From 9af23095e019eff59305e098e25faf161d4e0732 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 10:02:53 -0600 Subject: [PATCH 01/11] test(json): golden wire assertions for JSON-RPC envelopes before the v2 swap Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/handler/wire_golden_test.go | 137 +++++++++++++++++++++++++++ pkgs/service/jsondisp_golden_test.go | 65 +++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 pkgs/handler/wire_golden_test.go create mode 100644 pkgs/service/jsondisp_golden_test.go diff --git a/pkgs/handler/wire_golden_test.go b/pkgs/handler/wire_golden_test.go new file mode 100644 index 0000000000..d1ef2a89b7 --- /dev/null +++ b/pkgs/handler/wire_golden_test.go @@ -0,0 +1,137 @@ +package handler_test + +import ( + "encoding/json" + "net/http/httptest" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/handler" +) + +type goldenAttr struct { + S *string `json:"S,omitempty"` + N *string `json:"N,omitempty"` + B []byte `json:"B,omitempty"` + NULL *bool `json:"NULL,omitempty"` + M map[string]*goldenAttr `json:"M,omitempty"` + L []*goldenAttr `json:"L,omitempty"` +} + +type goldenScanOutput struct { + Items []map[string]*goldenAttr `json:"Items"` + LastEvaluatedKey map[string]*goldenAttr `json:"LastEvaluatedKey,omitempty"` + Count int32 `json:"Count"` + ScannedCount int32 `json:"ScannedCount"` +} + +type goldenSQSMessage struct { + Attributes map[string]string `json:"Attributes"` + MessageID string `json:"MessageId"` + Body string `json:"Body"` + MD5 string `json:"MD5OfBody"` +} + +type goldenSQSOutput struct { + Messages []goldenSQSMessage `json:"Messages"` +} + +type goldenMetricResult struct { + ID string `json:"Id"` + Label string `json:"Label"` + StatusCode string `json:"StatusCode"` + Timestamps []float64 `json:"Timestamps"` + Values []float64 `json:"Values"` + Messages []string `json:"Messages"` + Extra json.RawMessage `json:"Extra,omitempty"` +} + +type goldenMetricOutput struct { + NextToken *string `json:"NextToken,omitempty"` + Results []goldenMetricResult `json:"MetricDataResults"` +} + +func goldenStr(s string) *string { return &s } + +func TestWireGoldenJSONRPC(t *testing.T) { + t.Parallel() + + ts := time.Date(2025, 3, 4, 5, 6, 7, 123_000_000, time.UTC) + yes := true + + tests := []struct { + payload any + name string + body string + crc string + }{ + { + name: "dynamodb scan", + payload: goldenScanOutput{ + Items: []map[string]*goldenAttr{{ + "id": {S: goldenStr("a&c
\"q\"")}, + "n": {N: goldenStr("1.50")}, + "bin": {B: []byte{1, 2, 3}}, + "nul": {NULL: &yes}, + "m": {M: map[string]*goldenAttr{"z": {S: goldenStr("1")}, "a": {S: goldenStr("2")}}}, + "list": {L: []*goldenAttr{{S: goldenStr("x")}, {N: goldenStr("2")}}}, + }}, + Count: 1, + ScannedCount: 1, + }, + body: `{"Items":[{"bin":{"B":"AQID"},"id":{"S":"a\u003cb\u003e\u0026c\u2028\"q\""},"list":{"L":[{"S":"x"},{"N":"2"}]},"m":{"M":{"a":{"S":"2"},"z":{"S":"1"}}},"n":{"N":"1.50"},"nul":{"NULL":true}}],"Count":1,"ScannedCount":1}`, + crc: "2457307943", + }, + { + name: "dynamodb empty scan", + payload: goldenScanOutput{}, + body: `{"Items":null,"Count":0,"ScannedCount":0}`, + crc: "4196347728", + }, + { + name: "sqs receive", + payload: goldenSQSOutput{Messages: []goldenSQSMessage{{ + MessageID: "m-1", + Body: `{"k":""}`, + MD5: "abc", + }}}, + body: `{"Messages":[{"Attributes":null,"MessageId":"m-1","Body":"{\"k\":\"\u003cv\u003e\"}","MD5OfBody":"abc"}]}`, + crc: "2547812670", + }, + { + name: "sqs empty", + payload: goldenSQSOutput{}, + body: `{"Messages":null}`, + crc: "1433687114", + }, + { + name: "cloudwatch get metric data", + payload: goldenMetricOutput{Results: []goldenMetricResult{{ + ID: "q1", + Label: "CPU ", + StatusCode: "Complete", + Timestamps: []float64{awstime.Epoch(ts), awstime.Epoch(ts.Add(time.Minute))}, + Values: []float64{1.5, 2, 1e21, 0.000001, 1e-7, 100, 123456789012}, + Extra: json.RawMessage(` { "a" : [1, 2] } `), + }}}, + body: `{"MetricDataResults":[{"Id":"q1","Label":"CPU \u003cavg\u003e","StatusCode":"Complete","Timestamps":[1741064767.1230001,1741064827.1230001],"Values":[1.5,2,1e+21,0.000001,1e-7,100,123456789012],"Messages":null,"Extra":{"a":[1,2]}}]}`, + crc: "2076035819", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + rec := httptest.NewRecorder() + require.NoError(t, handler.WriteJSONWithChecksum(rec, 200, tt.payload)) + + assert.Equal(t, tt.body, rec.Body.String()) + assert.Equal(t, tt.crc, rec.Header().Get("X-Amz-Crc32")) + }) + } +} diff --git a/pkgs/service/jsondisp_golden_test.go b/pkgs/service/jsondisp_golden_test.go new file mode 100644 index 0000000000..708d19712d --- /dev/null +++ b/pkgs/service/jsondisp_golden_test.go @@ -0,0 +1,65 @@ +package service_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/service" +) + +type goldenSendInput struct { + QueueURL string `json:"QueueUrl"` + MessageBody string `json:"MessageBody"` + DelaySeconds *int32 `json:"DelaySeconds,omitempty"` + Attributes map[string]string `json:"MessageAttributes"` + Ignored string `json:"-"` +} + +func TestJSONErrorResponseGolden(t *testing.T) { + t.Parallel() + + b, err := service.JSONErrorResponse{Type: "com.amazonaws.sqs#QueueDoesNotExist", Message: "queue & y"}.MarshalJSON() + require.NoError(t, err) + + assert.Equal(t, `{"__type":"com.amazonaws.sqs#QueueDoesNotExist","message":"queue \u003cx\u003e \u0026 y","Message":"queue \u003cx\u003e \u0026 y"}`, string(b)) +} + +func TestHandleJSONGoldenDecode(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + body string + want goldenSendInput + wantErr string + }{ + {name: "basic", body: `{"QueueUrl":"u","MessageBody":"b","DelaySeconds":5,"MessageAttributes":{"a":"b"}}`, + want: goldenSendInput{QueueURL: "u", MessageBody: "b", DelaySeconds: new(int32(5)), Attributes: map[string]string{"a": "b"}}}, + {name: "case insensitive and unknown", body: `{"queueurl":"u","MESSAGEBODY":"b","extra":1}`, + want: goldenSendInput{QueueURL: "u", MessageBody: "b"}}, + {name: "null members", body: `{"QueueUrl":null,"MessageAttributes":null}`, want: goldenSendInput{}}, + {name: "empty body", body: ``, want: goldenSendInput{}}, + {name: "type mismatch", body: `{"QueueUrl":5}`, wantErr: "json: cannot unmarshal number into Go struct field goldenSendInput.QueueUrl of type string"}, + {name: "truncated", body: `{"QueueUrl":`, wantErr: "unexpected end of JSON input"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := service.HandleJSON(context.Background(), []byte(tt.body), + func(_ context.Context, in *goldenSendInput) (*goldenSendInput, error) { return in, nil }) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + + return + } + + require.NoError(t, err) + assert.Equal(t, &tt.want, got) + }) + } +} From 6d2b143d1a7bbec5e5058dbb71a74dd22b4194a5 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 10:30:23 -0600 Subject: [PATCH 02/11] refactor(json): move pkgs/ and internal/ to encoding/json/v2 with v1-equivalent options Adds pkgs/jsonx (V1 option set, Number, UseNumber) and cmd/jsonv2mod, the codemod that performs the swap mechanically. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- cmd/jsonv2mod/main.go | 99 +++ cmd/jsonv2mod/rewrite.go | 589 ++++++++++++++++++ cmd/jsonv2mod/rewrite_test.go | 96 +++ internal/app/adapters_cosmos.go | 8 +- .../app/adapters_cosmos_throughput_test.go | 7 +- internal/app/app_inspector_fanout_test.go | 5 +- internal/app/app_inspector_test.go | 7 +- internal/app/appsync_datasources_wiring.go | 7 +- .../app/appsync_datasources_wiring_test.go | 10 +- .../app/appsync_dynamodb_resolvers_test.go | 8 +- .../app/azureeventgrid_domains_sdk_test.go | 10 +- .../app/azureeventgrid_scopes_sdk_test.go | 6 +- internal/app/azureeventgrid_wiring_test.go | 5 +- internal/app/azuregraph_wiring_test.go | 5 +- internal/app/cli.go | 28 +- internal/app/cli_test.go | 60 +- internal/app/cloudcontrol_handlers.go | 11 +- .../app/cloudcontrol_handlers_security.go | 7 +- internal/app/cloudcontrol_handlers_test.go | 14 +- internal/app/cloudcontrol_provisioned_test.go | 5 +- internal/app/cloudcontrol_queue_url_test.go | 6 +- internal/app/cloudcontrol_wire_client.go | 11 +- .../cloudformation_cloudhsm_wiring_test.go | 6 +- ...loudformation_connectfamily_wiring_test.go | 8 +- .../app/cloudformation_directconnect_test.go | 6 +- .../app/cloudformation_networkmanager_test.go | 6 +- .../app/cloudformation_oam_wiring_test.go | 6 +- .../app/cloudformation_rum_wiring_test.go | 6 +- internal/app/codepipeline_actions_test.go | 6 +- internal/app/dev_endpoints_test.go | 12 +- internal/app/dms_engine_docker_test.go | 5 +- internal/app/ecs_runtime_test.go | 6 +- internal/app/error_wire_guards_test.go | 12 +- internal/app/extensions_test.go | 7 +- ...is_cloudwatch_stopcondition_wiring_test.go | 9 +- internal/app/gcpenforce_wiring_test.go | 5 +- .../app/gcpfunctions_events_wiring_test.go | 10 +- internal/app/gcpfunctions_wiring_test.go | 4 +- internal/app/globalaccelerator_wiring_test.go | 6 +- internal/app/http_targets_wiring.go | 5 +- internal/app/iam_policy_stream.go | 5 +- internal/app/iam_policy_stream_e2e_test.go | 6 +- internal/app/iam_policy_stream_test.go | 7 +- internal/app/init_stages.go | 7 +- internal/app/iot_rule_actions_test.go | 7 +- internal/app/iot_rule_http_test.go | 13 +- internal/app/iot_rule_lookups_test.go | 5 +- .../iotanalytics_lambda_iot_wiring_test.go | 7 +- internal/app/lifecycle_cmd_test.go | 8 +- internal/app/lifecycle_foreground_test.go | 12 +- internal/app/lifecycle_run.go | 21 +- internal/app/localstack_compat_test.go | 5 +- internal/app/logs_policy.go | 20 +- internal/app/mcp_wiring_test.go | 5 +- internal/app/persist_modes_test.go | 7 +- internal/app/pods_apply.go | 5 +- internal/app/pods_cmd.go | 12 +- internal/app/pods_localstack.go | 10 +- internal/app/region_wiring_test.go | 5 +- internal/app/regional_platform_wiring_test.go | 5 +- internal/app/registry_webhook_test.go | 5 +- internal/app/registry_wiring.go | 7 +- internal/app/replicate_cmd.go | 9 +- internal/app/replicate_test.go | 9 +- internal/app/requests_endpoint_test.go | 7 +- internal/app/s3_snapshot_options_test.go | 5 +- internal/app/s3_sns_subject_wiring_test.go | 5 +- internal/app/s3tables_s3_wiring_test.go | 6 +- .../app/scheduler_universal_targets_test.go | 8 +- internal/app/service_role_authz_test.go | 5 +- internal/app/ses_inbound_wiring_test.go | 5 +- internal/app/sesv2_sns_event_wiring_test.go | 8 +- internal/app/sfn_sdk_integration_test.go | 5 +- internal/app/sns_wiring_test.go | 5 +- internal/app/sso_test.go | 5 +- .../textract_rekognition_s3_wiring_test.go | 7 +- .../app/timestreaminfluxdb_wiring_test.go | 6 +- internal/app/verifiedpermissions_jwt_test.go | 8 +- internal/awstest/awstest.go | 8 +- internal/awswire/awswire.go | 11 +- internal/awswire/awswire_test.go | 7 +- internal/dockercompat/client/client.go | 8 +- .../client/client_runtime_test.go | 6 +- internal/mcpserver/backend.go | 8 +- internal/mcpserver/server.go | 6 +- internal/replicator/sqs.go | 5 +- pkgs/apptrace/middleware.go | 5 +- pkgs/awserr/respond.go | 6 +- pkgs/awserr/respond_test.go | 5 +- pkgs/awstime/awstime_test.go | 9 +- pkgs/chaos/handler.go | 14 +- pkgs/chaos/handler_test.go | 48 +- pkgs/chaos/localstack.go | 9 +- pkgs/container/credentials_resources_test.go | 5 +- pkgs/deltalog/deltalog.go | 38 +- pkgs/dmsengine/kinesis_target.go | 19 +- pkgs/dmsengine/mapping.go | 12 +- pkgs/dmsengine/s3_target.go | 6 +- pkgs/dmsengine/settings.go | 6 +- pkgs/dmsengine/targets_test.go | 9 +- pkgs/docker/pull.go | 14 +- pkgs/dynamoattr/attr.go | 5 +- pkgs/extensions/control.go | 11 +- pkgs/extensions/hooks.go | 7 +- pkgs/extensions/hooks_internal_test.go | 9 +- pkgs/extensions/main_internal_test.go | 5 +- pkgs/gcpdispatch/gcpdispatch.go | 6 +- pkgs/gcpdispatch/gcpdispatch_test.go | 5 +- pkgs/gcplro/store.go | 8 +- pkgs/gcprest/errors.go | 17 +- pkgs/gcpserve/logentry.go | 6 +- pkgs/handler/handler_test.go | 5 +- pkgs/handler/response.go | 7 +- pkgs/handler/wire_golden_test.go | 26 +- pkgs/httputils/httputils.go | 7 +- pkgs/iceberg/iceberg_test.go | 10 +- pkgs/iceberg/manifest.go | 10 +- pkgs/iceberg/metadata.go | 49 +- pkgs/iceberg/types.go | 37 +- pkgs/idempotency/idempotency.go | 5 +- pkgs/jsonx/jsonx.go | 147 +++++ pkgs/jsonx/jsonx_test.go | 109 ++++ pkgs/jsruntime/convert.go | 8 +- pkgs/ociregistry/client.go | 6 +- pkgs/ociregistry/describe.go | 8 +- pkgs/ociregistry/ocitest/ocitest.go | 14 +- pkgs/odatatable/batchwire.go | 6 +- pkgs/odatatable/codec.go | 43 +- pkgs/odatatable/models.go | 12 +- pkgs/persistence/manager_test.go | 5 +- pkgs/persistence/modes_test.go | 7 +- pkgs/persistence/snapshot.go | 7 +- .../persistence/snapshotversion_guard_test.go | 9 +- pkgs/persistence/store_test.go | 7 +- pkgs/pods/merge.go | 12 +- pkgs/pods/pods.go | 9 +- pkgs/regionpeers/regionpeers.go | 19 +- pkgs/regionpeers/regionpeers_test.go | 5 +- pkgs/registryauth/dockerconfig.go | 8 +- pkgs/registryauth/resolver.go | 5 +- pkgs/registryauth/resolver_test.go | 5 +- pkgs/restroute/restroute_test.go | 7 +- pkgs/restroute/serve.go | 5 +- pkgs/service/cbor.go | 7 +- pkgs/service/cbor_test.go | 15 +- pkgs/service/cloudtrail_capture.go | 5 +- pkgs/service/json_error_message.go | 11 +- pkgs/service/jsondisp.go | 9 +- pkgs/service/regions.go | 7 +- pkgs/service/restdispatch.go | 5 +- pkgs/service/rpcv2cbor_bridge.go | 13 +- pkgs/store/core.go | 17 +- pkgs/store/registry.go | 8 +- pkgs/store/store_test.go | 10 +- pkgs/tags/tags.go | 7 +- pkgs/tags/tags_test.go | 17 +- pkgs/wfinterp/value.go | 16 +- 157 files changed, 1898 insertions(+), 627 deletions(-) create mode 100644 cmd/jsonv2mod/main.go create mode 100644 cmd/jsonv2mod/rewrite.go create mode 100644 cmd/jsonv2mod/rewrite_test.go create mode 100644 pkgs/jsonx/jsonx.go create mode 100644 pkgs/jsonx/jsonx_test.go diff --git a/cmd/jsonv2mod/main.go b/cmd/jsonv2mod/main.go new file mode 100644 index 0000000000..64d50f328e --- /dev/null +++ b/cmd/jsonv2mod/main.go @@ -0,0 +1,99 @@ +// Command jsonv2mod rewrites encoding/json (v1) call sites to +// encoding/json/v2 plus jsontext, passing jsonx.V1() so behavior is unchanged. +// +// Usage: +// +// go run ./cmd/jsonv2mod [-n] [-skip dir,...] path... +// +// Each path is a Go file or a directory walked recursively. Files are +// rewritten in place (-n lists them instead). Constructs that cannot be +// rewritten safely are left untouched and printed as file:line: reason; the +// exit status is 1 when any are reported. See pkgs/jsonx for the mapping. +package main + +import ( + "flag" + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" +) + +func main() { + dry := flag.Bool("n", false, "list files that would change without writing") + skip := flag.String("skip", "", "comma-separated path fragments to skip") + flag.Parse() + + skips := strings.Split(*skip, ",") + changed, leftovers := 0, 0 + + for _, root := range flag.Args() { + err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() || !strings.HasSuffix(path, ".go") || skipped(path, skips) { + return nil + } + + res, err := processFile(path) + if err != nil { + return err + } + + for _, f := range res.findings { + fmt.Fprintf(os.Stderr, "%s:%d: %s\n", path, f.line, f.msg) + leftovers++ + } + + if res.out == nil { + return nil + } + + changed++ + fmt.Println(path) + + if *dry { + return nil + } + + return os.WriteFile(path, res.out, 0o644) + }) + if err != nil { + fmt.Fprintln(os.Stderr, "jsonv2mod:", err) + os.Exit(2) + } + } + + fmt.Fprintf(os.Stderr, "jsonv2mod: %d files changed, %d leftovers\n", changed, leftovers) + + if leftovers > 0 { + os.Exit(1) + } +} + +func skipped(path string, skips []string) bool { + slash := filepath.ToSlash(path) + if strings.Contains(slash, "pkgs/jsonx/") || strings.Contains(slash, "cmd/jsonv2mod/") { + return true + } + + for _, s := range skips { + if s != "" && strings.Contains(slash, s) { + return true + } + } + + return false +} + +func processFile(path string) (*result, error) { + src, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + return rewrite(path, src) +} diff --git a/cmd/jsonv2mod/rewrite.go b/cmd/jsonv2mod/rewrite.go new file mode 100644 index 0000000000..864b4a5d3b --- /dev/null +++ b/cmd/jsonv2mod/rewrite.go @@ -0,0 +1,589 @@ +package main + +import ( + "bytes" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "sort" + "strconv" + "strings" +) + +const ( + v1Path = "encoding/json" + v2Path = "encoding/json/v2" + jsontextPath = "encoding/json/jsontext" + jsonxPath = "github.com/blackbirdworks/gopherstack/pkgs/jsonx" + localPrefix = "github.com/blackbirdworks/gopherstack" + optV1 = "jsonx.V1()" +) + +type finding struct { + msg string + line int +} + +type result struct { + out []byte + findings []finding +} + +type edit struct { + text string + start, end int +} + +type stream struct { + call *ast.CallExpr + block *ast.BlockStmt + name string + opts []string + edits []edit + decoder bool + bad bool +} + +type rewriter struct { + fset *token.FileSet + file *ast.File + src []byte + jsonName string + consumed map[ast.Node]bool + streams map[string]*stream + edits []edit + findings []finding +} + +func (r *rewriter) off(p token.Pos) int { return r.fset.Position(p).Offset } + +func (r *rewriter) text(a, b ast.Node) string { return string(r.src[r.off(a.Pos()):r.off(b.End())]) } + +func (r *rewriter) add(start, end int, text string) { + r.edits = append(r.edits, edit{start: start, end: end, text: text}) +} + +func (r *rewriter) report(p token.Pos, format string, a ...any) { + r.findings = append(r.findings, finding{line: r.fset.Position(p).Line, msg: fmt.Sprintf(format, a...)}) +} + +func (r *rewriter) isJSON(e ast.Expr, name string) bool { + sel, ok := e.(*ast.SelectorExpr) + if !ok { + return false + } + + id, ok := sel.X.(*ast.Ident) + + return ok && id.Name == r.jsonName && (name == "" || sel.Sel.Name == name) +} + +func (r *rewriter) hasComment(start, end int) bool { + for _, cg := range r.file.Comments { + if r.off(cg.Pos()) < end && r.off(cg.End()) > start { + return true + } + } + + return false +} + +func rewrite(path string, src []byte) (*result, error) { + fset := token.NewFileSet() + + file, err := parser.ParseFile(fset, path, src, parser.ParseComments) + if err != nil { + return nil, err + } + + name, ok := jsonImportName(file) + if !ok { + return &result{}, nil + } + + r := &rewriter{fset: fset, file: file, src: src, jsonName: name, consumed: map[ast.Node]bool{}} + + for _, d := range file.Decls { + r.streams = map[string]*stream{} + r.collectStreams(d) + r.rewriteStreamUses(d) + r.rewriteCalls(d) + r.rewriteSelectors(d) + r.emitStreams() + } + + out, err := r.apply() + if err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + + out, err = fixImports(path, out, name) + if err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + + res := &result{findings: r.findings} + if !bytes.Equal(out, src) { + res.out = out + } + + return res, nil +} + +func jsonImportName(file *ast.File) (string, bool) { + for _, imp := range file.Imports { + if p, _ := strconv.Unquote(imp.Path.Value); p != v1Path { + continue + } + + if imp.Name == nil { + return "json", true + } + + if imp.Name.Name == "_" || imp.Name.Name == "." { + return "", false + } + + return imp.Name.Name, true + } + + return "", false +} + +func (r *rewriter) collectStreams(d ast.Decl) { + register := func(lhs ast.Expr, rhs ast.Expr, block *ast.BlockStmt) { + id, ok := lhs.(*ast.Ident) + call, isCall := rhs.(*ast.CallExpr) + + if !ok || !isCall || len(call.Args) != 1 { + return + } + + switch { + case r.isJSON(call.Fun, "NewDecoder"): + r.streams[id.Name] = &stream{name: id.Name, call: call, decoder: true, block: block} + case r.isJSON(call.Fun, "NewEncoder"): + r.streams[id.Name] = &stream{name: id.Name, call: call, block: block} + default: + return + } + + r.consumed[call.Fun] = true + } + + ast.Inspect(d, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.AssignStmt: + if len(x.Lhs) == 1 && len(x.Rhs) == 1 { + register(x.Lhs[0], x.Rhs[0], enclosing(d, x)) + } + case *ast.ValueSpec: + if len(x.Names) == 1 && len(x.Values) == 1 { + register(x.Names[0], x.Values[0], enclosing(d, x)) + } + } + + return true + }) +} + +// enclosing returns the innermost block statement of d containing n. +func enclosing(d ast.Decl, n ast.Node) *ast.BlockStmt { + var best *ast.BlockStmt + + ast.Inspect(d, func(c ast.Node) bool { + if b, ok := c.(*ast.BlockStmt); ok && b.Pos() <= n.Pos() && n.End() <= b.End() { + best = b + } + + return true + }) + + return best +} + +func (r *rewriter) rewriteStreamUses(d ast.Decl) { + if len(r.streams) == 0 { + return + } + + declIdents := map[*ast.Ident]bool{} + + for _, s := range r.streams { + ast.Inspect(d, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.AssignStmt: + for _, l := range x.Lhs { + if id, ok := l.(*ast.Ident); ok && id.Name == s.name { + declIdents[id] = true + } + } + case *ast.ValueSpec: + for _, id := range x.Names { + declIdents[id] = true + } + } + + return true + }) + } + + var stack []ast.Node + + ast.Inspect(d, func(n ast.Node) bool { + if n == nil { + stack = stack[:len(stack)-1] + + return true + } + + stack = append(stack, n) + + id, ok := n.(*ast.Ident) + if !ok || declIdents[id] || r.streams[id.Name] == nil { + return true + } + + r.streamUse(r.streams[id.Name], id, stack) + + return true + }) +} + +func (r *rewriter) streamUse(s *stream, id *ast.Ident, stack []ast.Node) { + n := len(stack) + if n < 3 { + s.bad = true + + return + } + + sel, ok := stack[n-2].(*ast.SelectorExpr) + call, isCall := stack[n-3].(*ast.CallExpr) + + if !ok || sel.X != id || !isCall || call.Fun != sel { + s.bad = true + r.report(id.Pos(), "%s escapes (not a plain method call); rewrite by hand", s.name) + + return + } + + var stmt *ast.ExprStmt + + if n >= 5 { + if es, ok := stack[n-4].(*ast.ExprStmt); ok && stack[n-5] == ast.Node(s.block) { + stmt = es + } + } + + method, argc := sel.Sel.Name, len(call.Args) + + switch { + case s.decoder && method == "Decode" && argc == 1: + s.add(r, r.off(call.Pos()), r.off(call.Args[0].Pos()), r.jsonName+".UnmarshalDecode("+s.name+", ") + s.add(r, r.off(call.Args[0].End()), r.off(call.End()), ", "+optV1+r.extra(s)+")") + case !s.decoder && method == "Encode" && argc == 1: + s.add(r, r.off(call.Pos()), r.off(call.Args[0].Pos()), r.jsonName+".MarshalEncode("+s.name+", ") + case s.decoder && method == "UseNumber" && argc == 0 && stmt != nil: + s.opts = append(s.opts, "jsonx.UseNumber()") + s.edits = append(s.edits, r.stmtEdit(stmt)) + case s.decoder && method == "DisallowUnknownFields" && argc == 0 && stmt != nil: + s.opts = append(s.opts, r.jsonName+".RejectUnknownMembers(true)") + s.edits = append(s.edits, r.stmtEdit(stmt)) + case !s.decoder && method == "SetEscapeHTML" && argc == 1 && stmt != nil: + s.opts = append(s.opts, "jsontext.EscapeForHTML("+r.text(call.Args[0], call.Args[0])+")") + s.edits = append(s.edits, r.stmtEdit(stmt)) + case !s.decoder && method == "SetIndent" && argc == 2 && stmt != nil: + s.opts = append(s.opts, r.indentOpts(call.Args[0], call.Args[1])...) + s.edits = append(s.edits, r.stmtEdit(stmt)) + default: + s.bad = true + r.report(call.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", s.name, method) + } +} + +func (r *rewriter) extra(s *stream) string { + if !s.decoder || len(s.opts) == 0 { + return "" + } + + return ", " + strings.Join(s.opts, ", ") +} + +func (r *rewriter) indentOpts(prefix, indent ast.Expr) []string { + opts := []string{"jsontext.Multiline(true)"} + + if lit, ok := prefix.(*ast.BasicLit); !ok || lit.Value != `""` { + opts = append(opts, "jsontext.WithIndentPrefix("+r.text(prefix, prefix)+")") + } + + if lit, ok := indent.(*ast.BasicLit); !ok || lit.Value != `""` { + opts = append(opts, "jsontext.WithIndent("+r.text(indent, indent)+")") + } + + return opts +} + +func (s *stream) add(r *rewriter, start, end int, text string) { + s.edits = append(s.edits, edit{start: start, end: end, text: text}) +} + +func (r *rewriter) stmtEdit(s *ast.ExprStmt) edit { + start, end := r.off(s.Pos()), r.off(s.End()) + + for start > 0 && (r.src[start-1] == ' ' || r.src[start-1] == '\t') { + start-- + } + + if end < len(r.src) && r.src[end] == '\n' { + end++ + } + + return edit{start: start, end: end} +} + +func (r *rewriter) emitStreams() { + for _, s := range r.streams { + if s.bad { + continue + } + + r.edits = append(r.edits, s.edits...) + + fun := s.call.Fun.(*ast.SelectorExpr) + if s.decoder { + r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewDecoder") + + continue + } + + r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewEncoder") + + opts := ", " + optV1 + if len(s.opts) > 0 { + opts += ", " + strings.Join(s.opts, ", ") + } + + r.add(r.off(s.call.Rparen), r.off(s.call.Rparen), opts) + } +} + +func (r *rewriter) rewriteCalls(d ast.Decl) { + ast.Inspect(d, func(n ast.Node) bool { + call, ok := n.(*ast.CallExpr) + if !ok { + return true + } + + r.callExpr(call) + + return true + }) +} + +func (r *rewriter) callExpr(call *ast.CallExpr) { + argc := len(call.Args) + + switch { + case r.isJSON(call.Fun, "Marshal") && argc == 1, r.isJSON(call.Fun, "Unmarshal") && argc == 2: + r.consumed[call.Fun] = true + r.add(r.off(call.Rparen), r.off(call.Rparen), ", "+optV1) + case r.isJSON(call.Fun, "MarshalIndent") && argc == 3: + r.marshalIndent(call) + case r.isJSON(call.Fun, "Valid") && argc == 1: + r.consumed[call.Fun] = true + r.add(r.off(call.Pos()), r.off(call.Args[0].Pos()), "jsontext.Value(") + r.add(r.off(call.Args[0].End()), r.off(call.End()), ").IsValid("+optV1+")") + default: + r.chain(call) + } +} + +func (r *rewriter) marshalIndent(call *ast.CallExpr) { + prefix, ok1 := call.Args[1].(*ast.BasicLit) + indent, ok2 := call.Args[2].(*ast.BasicLit) + + for _, lit := range []*ast.BasicLit{prefix, indent} { + if lit == nil { + continue + } + + if s, err := strconv.Unquote(lit.Value); err == nil && strings.Trim(s, " \t\r\n") != "" { + r.report(call.Pos(), "MarshalIndent with non-whitespace indent %s; v2 panics, rewrite by hand", lit.Value) + + return + } + } + + _, _ = ok1, ok2 + sel := call.Fun.(*ast.SelectorExpr) + r.consumed[call.Fun] = true + r.add(r.off(sel.Sel.Pos()), r.off(sel.Sel.End()), "Marshal") + + opts := append([]string{optV1}, r.indentOpts(call.Args[1], call.Args[2])...) + r.add(r.off(call.Args[0].End()), r.off(call.Rparen), ", "+strings.Join(opts, ", ")) +} + +func (r *rewriter) chain(call *ast.CallExpr) { + outer, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return + } + + inner, ok := outer.X.(*ast.CallExpr) + if !ok || len(inner.Args) != 1 || len(call.Args) != 1 { + return + } + + start, end := r.off(inner.Args[0].End()), r.off(call.Args[0].Pos()) + + switch { + case r.isJSON(inner.Fun, "NewDecoder") && outer.Sel.Name == "Decode": + if r.hasComment(r.off(call.Pos()), r.off(call.End())) { + r.report(call.Pos(), "comment inside NewDecoder(...).Decode chain; rewrite by hand") + + return + } + + r.consumed[inner.Fun] = true + r.add(r.off(call.Pos()), r.off(inner.Args[0].Pos()), r.jsonName+".UnmarshalDecode(jsontext.NewDecoder(") + r.add(start, end, "), ") + r.add(r.off(call.Args[0].End()), r.off(call.End()), ", "+optV1+")") + case r.isJSON(inner.Fun, "NewEncoder") && outer.Sel.Name == "Encode": + if r.hasComment(r.off(call.Pos()), r.off(call.End())) { + r.report(call.Pos(), "comment inside NewEncoder(...).Encode chain; rewrite by hand") + + return + } + + r.consumed[inner.Fun] = true + r.add(r.off(call.Pos()), r.off(inner.Args[0].Pos()), r.jsonName+".MarshalEncode(jsontext.NewEncoder(") + r.add(start, end, ", "+optV1+"), ") + r.add(r.off(call.Args[0].End()), r.off(call.End()), ")") + } +} + +func (r *rewriter) rewriteSelectors(d ast.Decl) { + ast.Inspect(d, func(n ast.Node) bool { + sel, ok := n.(*ast.SelectorExpr) + if !ok || r.consumed[sel] || !r.isJSON(sel, "") { + return true + } + + switch sel.Sel.Name { + case "RawMessage": + r.add(r.off(sel.Pos()), r.off(sel.End()), "jsontext.Value") + case "Number": + r.add(r.off(sel.Pos()), r.off(sel.End()), "jsonx.Number") + case "Marshaler", "Unmarshaler": + default: + r.report(sel.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", r.jsonName, sel.Sel.Name) + } + + return true + }) +} + +func (r *rewriter) apply() ([]byte, error) { + sort.SliceStable(r.edits, func(i, j int) bool { return r.edits[i].start > r.edits[j].start }) + + out := append([]byte(nil), r.src...) + prev := len(out) + 1 + + for _, e := range r.edits { + if e.end > prev { + return nil, fmt.Errorf("overlapping edits at offset %d", e.start) + } + + out = append(out[:e.start], append([]byte(e.text), out[e.end:]...)...) + prev = e.start + } + + return out, nil +} + +// fixImports swaps the v1 import for v2 (or drops it when unused after the +// rewrite) and adds jsontext / jsonx when referenced. +func fixImports(path string, src []byte, jsonName string) ([]byte, error) { + fset := token.NewFileSet() + + file, err := parser.ParseFile(fset, path, src, parser.ParseComments) + if err != nil { + return nil, fmt.Errorf("rewritten file does not parse: %w", err) + } + + used := map[string]bool{} + + ast.Inspect(file, func(n ast.Node) bool { + if sel, ok := n.(*ast.SelectorExpr); ok { + if id, ok := sel.X.(*ast.Ident); ok { + used[id.Name] = true + } + } + + return true + }) + + have := map[string]bool{} + + var v1Spec *ast.ImportSpec + + var firstLocal, last *ast.ImportSpec + + for _, imp := range file.Imports { + p, _ := strconv.Unquote(imp.Path.Value) + have[p] = true + last = imp + + if p == v1Path { + v1Spec = imp + } + + if firstLocal == nil && strings.HasPrefix(p, localPrefix) { + firstLocal = imp + } + } + + var edits []edit + + off := func(p token.Pos) int { return fset.Position(p).Offset } + + if used[jsonName] { + edits = append(edits, edit{start: off(v1Spec.Path.Pos()), end: off(v1Spec.Path.End()), text: strconv.Quote(v2Path)}) + } else { + start, end := off(v1Spec.Pos()), off(v1Spec.End()) + for start > 0 && (src[start-1] == ' ' || src[start-1] == '\t') { + start-- + } + + if end < len(src) && src[end] == '\n' { + end++ + } + + edits = append(edits, edit{start: start, end: end}) + } + + if used["jsontext"] && !have[jsontextPath] { + edits = append(edits, edit{start: off(v1Spec.End()), end: off(v1Spec.End()), text: "\n\t" + strconv.Quote(jsontextPath)}) + } + + if used["jsonx"] && !have[jsonxPath] { + switch { + case firstLocal != nil: + edits = append(edits, edit{start: off(firstLocal.Pos()), end: off(firstLocal.Pos()), text: strconv.Quote(jsonxPath) + "\n\t"}) + default: + edits = append(edits, edit{start: off(last.End()), end: off(last.End()), text: "\n\n\t" + strconv.Quote(jsonxPath)}) + } + } + + sort.SliceStable(edits, func(i, j int) bool { return edits[i].start > edits[j].start }) + + out := append([]byte(nil), src...) + for _, e := range edits { + out = append(out[:e.start], append([]byte(e.text), out[e.end:]...)...) + } + + return format.Source(out) +} diff --git a/cmd/jsonv2mod/rewrite_test.go b/cmd/jsonv2mod/rewrite_test.go new file mode 100644 index 0000000000..81db45a0fb --- /dev/null +++ b/cmd/jsonv2mod/rewrite_test.go @@ -0,0 +1,96 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const header = "package p\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/blackbirdworks/gopherstack/pkgs/arn\"\n)\n\nvar _ = http.StatusOK\nvar _ = arn.X\n\n" + +func TestRewrite(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + body string + want []string + wantFindings int + }{ + { + name: "marshal unmarshal", + body: "func f(b []byte) { _, _ = json.Marshal(b); _ = json.Unmarshal(b, &b) }\n", + want: []string{"json.Marshal(b, jsonx.V1())", "json.Unmarshal(b, &b, jsonx.V1())", "\"encoding/json/v2\"", "pkgs/jsonx\""}, + }, + { + name: "marshal indent", + body: "func f(v any) { _, _ = json.MarshalIndent(v, \"\", \" \") }\n", + want: []string{"json.Marshal(v, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(\" \"))", "encoding/json/jsontext"}, + }, + { + name: "decode chain", + body: "func f(r *http.Request, v any) error { return json.NewDecoder(r.Body).Decode(&v) }\n", + want: []string{"json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &v, jsonx.V1())"}, + }, + { + name: "encode chain", + body: "func f(w http.ResponseWriter, v any) { _ = json.NewEncoder(w).Encode(v) }\n", + want: []string{"json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), v)"}, + }, + { + name: "decoder var", + body: "func f(r *http.Request, v any) error {\n\tdec := json.NewDecoder(r.Body)\n\tdec.UseNumber()\n\tdec.DisallowUnknownFields()\n\n\treturn dec.Decode(&v)\n}\n", + want: []string{"dec := jsontext.NewDecoder(r.Body)", "json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber(), json.RejectUnknownMembers(true))"}, + }, + { + name: "encoder var", + body: "func f(w http.ResponseWriter, v any) error {\n\tenc := json.NewEncoder(w)\n\tenc.SetEscapeHTML(false)\n\tenc.SetIndent(\"\", \"\\t\")\n\n\treturn enc.Encode(v)\n}\n", + want: []string{"jsontext.NewEncoder(w, jsonx.V1(), jsontext.EscapeForHTML(false), jsontext.Multiline(true), jsontext.WithIndent(\"\\t\"))", "json.MarshalEncode(enc, v)"}, + }, + { + name: "types", + body: "type T struct {\n\tR json.RawMessage\n\tN json.Number\n}\n\nvar _ json.Marshaler\n\nfunc f(b []byte) bool { return json.Valid(b) }\n", + want: []string{"R jsontext.Value", "N jsonx.Number", "json.Marshaler", "jsontext.Value(b).IsValid(jsonx.V1())"}, + }, + { + name: "bad stream stays untouched", + body: "func f(r *http.Request, v any) {\n\tdec := json.NewDecoder(r.Body)\n\t_ = dec.Decode(&v)\n\t_ = dec.Buffered()\n}\n", + want: []string{"_ = dec.Decode(&v)", "json.NewDecoder(r.Body)"}, wantFindings: 1, + }, + { + name: "conditional setindent is not hoisted", + body: "func f(w http.ResponseWriter, v any, c bool) {\n\tenc := json.NewEncoder(w)\n\tif c {\n\t\tenc.SetIndent(\"\", \" \")\n\t}\n\t_ = enc.Encode(v)\n}\n", + want: []string{"enc.SetIndent"}, wantFindings: 1, + }, + { + name: "leftovers", + body: "func f(r *http.Request) { d := json.NewDecoder(r.Body); _ = d.More(); var e *json.SyntaxError; _ = e }\n", + want: []string{"json.NewDecoder(r.Body)"}, + wantFindings: 2, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + res, err := rewrite("x.go", []byte(header+tt.body)) + require.NoError(t, err) + assert.Len(t, res.findings, tt.wantFindings) + require.NotNil(t, res.out) + + for _, w := range tt.want { + assert.Contains(t, string(res.out), w) + } + }) + } +} + +func TestRewriteNoV1Import(t *testing.T) { + t.Parallel() + + res, err := rewrite("x.go", []byte("package p\n\nimport \"fmt\"\n\nvar _ = fmt.Sprint\n")) + require.NoError(t, err) + assert.Nil(t, res.out) +} diff --git a/internal/app/adapters_cosmos.go b/internal/app/adapters_cosmos.go index 97f06b39a7..3581308e24 100644 --- a/internal/app/adapters_cosmos.go +++ b/internal/app/adapters_cosmos.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -106,9 +106,9 @@ func (a *azureCosmosAdapter) DeleteDatabase(id string) error { func containerSpec(c azurearm.CosmosContainer) cosmosdb.ContainerSpec { return cosmosdb.ContainerSpec{ ID: c.ID, PartitionKeyPaths: c.PartitionKeyPaths, DefaultTTL: c.DefaultTTL, - IndexingPolicy: json.RawMessage(c.IndexingPolicy), - ConflictResolutionPolicy: json.RawMessage(c.ConflictResolutionPolicy), - UniqueKeyPolicy: json.RawMessage(c.UniqueKeyPolicy), + IndexingPolicy: jsontext.Value(c.IndexingPolicy), + ConflictResolutionPolicy: jsontext.Value(c.ConflictResolutionPolicy), + UniqueKeyPolicy: jsontext.Value(c.UniqueKeyPolicy), } } diff --git a/internal/app/adapters_cosmos_throughput_test.go b/internal/app/adapters_cosmos_throughput_test.go index 5b4d5abca2..bf3ad78dfb 100644 --- a/internal/app/adapters_cosmos_throughput_test.go +++ b/internal/app/adapters_cosmos_throughput_test.go @@ -2,7 +2,7 @@ package app import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -40,7 +41,7 @@ func armCosmosDo(t *testing.T, h http.Handler, method, path string, body any) (i if body != nil { var err error - raw, err = json.Marshal(body) + raw, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -53,7 +54,7 @@ func armCosmosDo(t *testing.T, h http.Handler, method, path string, body any) (i var out map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) } return rec.Code, out diff --git a/internal/app/app_inspector_fanout_test.go b/internal/app/app_inspector_fanout_test.go index 5256ff6622..365a519b36 100644 --- a/internal/app/app_inspector_fanout_test.go +++ b/internal/app/app_inspector_fanout_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/apptrace" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const fanoutQueueName = "fanout-queue" @@ -55,7 +56,7 @@ func (f *fanoutEnv) spans(t *testing.T, query string) []apptrace.Span { require.Equal(t, http.StatusOK, rec.Code) var res apptrace.ListResult - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &res)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &res, jsonx.V1())) return res.Items } diff --git a/internal/app/app_inspector_test.go b/internal/app/app_inspector_test.go index 508d8f6ee3..cbf8686132 100644 --- a/internal/app/app_inspector_test.go +++ b/internal/app/app_inspector_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/apptrace" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func inspectorServer(t *testing.T) (*echo.Echo, *apptrace.Tracer) { @@ -69,7 +70,7 @@ func TestAppInspectorEndpoints(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var res apptrace.ListResult - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &res)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &res, jsonx.V1())) assert.Equal(t, tc.total, res.Total) }) } @@ -93,7 +94,7 @@ func TestAppInspectorDetailTraceAndConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var detail appInspectorDetail - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detail)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detail, jsonx.V1())) require.NotNil(t, detail.Span.Detail) assert.NotContains(t, detail.Span.Detail.RequestBody, "hunter2") require.Len(t, detail.Trace, 2) diff --git a/internal/app/appsync_datasources_wiring.go b/internal/app/appsync_datasources_wiring.go index fc57744235..00919a74dc 100644 --- a/internal/app/appsync_datasources_wiring.go +++ b/internal/app/appsync_datasources_wiring.go @@ -3,7 +3,7 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -13,6 +13,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" appsyncbackend "github.com/blackbirdworks/gopherstack/services/appsync" eventbridgebackend "github.com/blackbirdworks/gopherstack/services/eventbridge" @@ -173,14 +174,14 @@ func (a appsyncRDSData) ExecuteRDSStatement( raw, err := json.Marshal(map[string]any{ "records": nonNil(records), "columnMetadata": nonNil(cols), "numberOfRecordsUpdated": updated, "generatedFields": nonNil(generated), - }) + }, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode result: %w", err) } var out map[string]any - return out, json.Unmarshal(raw, &out) + return out, json.Unmarshal(raw, &out, jsonx.V1()) } func nonNil[T any](s []T) []T { diff --git a/internal/app/appsync_datasources_wiring_test.go b/internal/app/appsync_datasources_wiring_test.go index fc773e9481..e3d012f116 100644 --- a/internal/app/appsync_datasources_wiring_test.go +++ b/internal/app/appsync_datasources_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -17,6 +17,8 @@ import ( sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -95,7 +97,7 @@ func (f *asDSFixture) query(t *testing.T, field string, vars map[string]any) any query = "query(" + strings.Join(decls, ", ") + ") { " + field + " }" } - body, err := json.Marshal(map[string]any{"query": query, "variables": vars}) + body, err := json.Marshal(map[string]any{"query": query, "variables": vars}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/v1/apis/"+f.apiID+"/graphql", strings.NewReader(string(body))) @@ -112,7 +114,7 @@ func (f *asDSFixture) query(t *testing.T, field string, vars map[string]any) any Message string `json:"message"` } `json:"errors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out), rec.Body.String()) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()), rec.Body.String()) require.Empty(t, out.Errors, rec.Body.String()) name, _, _ := strings.Cut(field, "(") @@ -129,7 +131,7 @@ func asJSONValue(t *testing.T, v any) any { } var out any - require.NoError(t, json.Unmarshal([]byte(s), &out), s) + require.NoError(t, json.Unmarshal([]byte(s), &out, jsonx.V1()), s) return out } diff --git a/internal/app/appsync_dynamodb_resolvers_test.go b/internal/app/appsync_dynamodb_resolvers_test.go index a7c70f051f..613ec4fc2e 100644 --- a/internal/app/appsync_dynamodb_resolvers_test.go +++ b/internal/app/appsync_dynamodb_resolvers_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,8 @@ import ( ddbsdktypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const asDDBSchema = ` @@ -256,7 +258,7 @@ type asGQLResponse struct { func (f *asDDBFixture) do(t *testing.T, query string) asGQLResponse { t.Helper() - body, err := json.Marshal(map[string]any{"query": query}) + body, err := json.Marshal(map[string]any{"query": query}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/v1/apis/"+f.apiID+"/graphql", strings.NewReader(string(body))) @@ -268,7 +270,7 @@ func (f *asDDBFixture) do(t *testing.T, query string) asGQLResponse { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out asGQLResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out), rec.Body.String()) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()), rec.Body.String()) return out } diff --git a/internal/app/azureeventgrid_domains_sdk_test.go b/internal/app/azureeventgrid_domains_sdk_test.go index f4f52fdfb2..a82377c15c 100644 --- a/internal/app/azureeventgrid_domains_sdk_test.go +++ b/internal/app/azureeventgrid_domains_sdk_test.go @@ -1,7 +1,8 @@ package app import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" "github.com/blackbirdworks/gopherstack/services/azureeventgrid" @@ -42,9 +44,9 @@ func newEGReceiver(t *testing.T) *egReceiver { if req.Header.Get("Aeg-Event-Type") == "SubscriptionValidation" { var evs []map[string]any - _ = json.Unmarshal(body, &evs) + _ = json.Unmarshal(body, &evs, jsonx.V1()) code, _ := evs[0]["data"].(map[string]any)["validationCode"].(string) - _ = json.NewEncoder(w).Encode(map[string]string{"validationResponse": code}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{"validationResponse": code}) return } @@ -70,7 +72,7 @@ func (r *egReceiver) events(t *testing.T) ([]map[string]any, int) { for _, b := range r.bodies { var arr []map[string]any - require.NoError(t, json.Unmarshal(b, &arr)) + require.NoError(t, json.Unmarshal(b, &arr, jsonx.V1())) out = append(out, arr...) } diff --git a/internal/app/azureeventgrid_scopes_sdk_test.go b/internal/app/azureeventgrid_scopes_sdk_test.go index 1d16bb84dc..c9f7aec17b 100644 --- a/internal/app/azureeventgrid_scopes_sdk_test.go +++ b/internal/app/azureeventgrid_scopes_sdk_test.go @@ -3,7 +3,7 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "reflect" "strings" @@ -14,6 +14,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventgrid/armeventgrid/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -25,7 +27,7 @@ const ( func (s *egDomainStack) armDo(t *testing.T, method, path string, body any) *http.Response { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), method, s.armSrv.URL+path+"?api-version=2021-04-01", diff --git a/internal/app/azureeventgrid_wiring_test.go b/internal/app/azureeventgrid_wiring_test.go index 6b456b3bb1..90bf09095d 100644 --- a/internal/app/azureeventgrid_wiring_test.go +++ b/internal/app/azureeventgrid_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "log/slog" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azureblob" @@ -129,7 +130,7 @@ func jsonField(t *testing.T, raw []byte, key string) string { var m map[string]any - require.NoError(t, json.Unmarshal(raw, &m)) + require.NoError(t, json.Unmarshal(raw, &m, jsonx.V1())) s, _ := m[key].(string) diff --git a/internal/app/azuregraph_wiring_test.go b/internal/app/azuregraph_wiring_test.go index 30ff349c3c..ea6b891ed1 100644 --- a/internal/app/azuregraph_wiring_test.go +++ b/internal/app/azuregraph_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" "github.com/blackbirdworks/gopherstack/services/azuregraph" @@ -86,7 +87,7 @@ func do( require.NoError(t, err) var out map[string]any - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) return resp.StatusCode, out } diff --git a/internal/app/cli.go b/internal/app/cli.go index acc58566b0..49a8b8004b 100644 --- a/internal/app/cli.go +++ b/internal/app/cli.go @@ -8,12 +8,14 @@ import ( sqssdk "github.com/blackbirdworks/gopherstack/internal/awswire/sqs" ssmsdk "github.com/blackbirdworks/gopherstack/internal/awswire/ssm" "github.com/blackbirdworks/gopherstack/internal/routegates" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/internal/cliconfig" "context" "crypto/tls" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "log/slog" @@ -1391,7 +1393,7 @@ func (c *CLI) SaveConfig() error { StepFunctions: c.StepFunctions, } - data, err := json.MarshalIndent(cfg, "", " ") + data, err := json.Marshal(cfg, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } @@ -1415,7 +1417,7 @@ func (c *CLI) LoadConfig() error { } var cfg cliconfig.PersistableConfig - if unmarshalErr := json.Unmarshal(data, &cfg); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &cfg, jsonx.V1()); unmarshalErr != nil { return fmt.Errorf("failed to unmarshal config: %w", unmarshalErr) } @@ -3287,7 +3289,7 @@ func buildResetHandler(services []service.Registerable) echo.HandlerFunc { // payload stays human-readable without an extra base64 layer. type snapshotBundle struct { // Services maps each registered service name to its raw JSON snapshot. - Services map[string]json.RawMessage `json:"services"` + Services map[string]jsontext.Value `json:"services"` // Format is a fixed version tag; currently "gopherstack-snapshot/v1". Format string `json:"format"` } @@ -3326,9 +3328,9 @@ func buildSnapshotHandler(m *persistence.Manager) echo.HandlerFunc { return func(c *echo.Context) error { raw := m.ExportAll() - services := make(map[string]json.RawMessage, len(raw)) + services := make(map[string]jsontext.Value, len(raw)) for name, data := range raw { - services[name] = json.RawMessage(data) + services[name] = jsontext.Value(data) } resp := snapshotResponse{ @@ -3352,7 +3354,7 @@ func buildLoadHandler(m *persistence.Manager) echo.HandlerFunc { return func(c *echo.Context) error { var bundle snapshotBundle - if err := json.NewDecoder(c.Request().Body).Decode(&bundle); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &bundle, jsonx.V1()); err != nil { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("invalid snapshot bundle: %s", err.Error())) } @@ -5969,7 +5971,7 @@ func buildECSRunInput( ) ecsbackend.RunTaskInput { var input map[string]any if len(payload) > 0 { - _ = json.Unmarshal(payload, &input) + _ = json.Unmarshal(payload, &input, jsonx.V1()) } runInput := ecsbackend.RunTaskInput{ @@ -6605,7 +6607,7 @@ func (a *cognitoLambdaTriggerAdapter) InvokeTrigger( functionARN string, event map[string]any, ) (map[string]any, error) { - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { return nil, err } @@ -6618,7 +6620,7 @@ func (a *cognitoLambdaTriggerAdapter) InvokeTrigger( } var resp map[string]any - if err = json.Unmarshal(result, &resp); err != nil { + if err = json.Unmarshal(result, &resp, jsonx.V1()); err != nil { return nil, err } @@ -14614,7 +14616,7 @@ func (a *iotAnalyticsThingShadowAdapter) GetThingShadow(thingName string) (map[s } var data map[string]any - if unmarshalErr := json.Unmarshal(doc, &data); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(doc, &data, jsonx.V1()); unmarshalErr != nil { return nil, fmt.Errorf("iotanalytics: unmarshal thing shadow document: %w", unmarshalErr) } @@ -14697,7 +14699,7 @@ func (a *ddbKinesisEmitterAdapter) EmitDynamoDBStreamRecord( ctx, streamName := kinesisRefContext(context.Background(), streamARN) partitionKey := tableName - if keys, err := json.Marshal(record.Keys); err == nil { + if keys, err := json.Marshal(record.Keys, jsonx.V1()); err == nil { partitionKey = string(keys) } @@ -14717,7 +14719,7 @@ func (a *ddbKinesisEmitterAdapter) EmitDynamoDBStreamRecord( ApproximateCreationDateTime: record.ApproximateCreationDateTime, SizeBytes: record.SizeBytes, }, - }) + }, jsonx.V1()) if err != nil { return } diff --git a/internal/app/cli_test.go b/internal/app/cli_test.go index c3403cb41f..8504ca29ba 100644 --- a/internal/app/cli_test.go +++ b/internal/app/cli_test.go @@ -3,7 +3,8 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -21,6 +22,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/dns/dnstest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/service" svctags "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -895,7 +897,7 @@ func TestWireResourceGroupsTagging_CrossServiceResources(t *testing.T) { wafBk := wafv2backend.NewInMemoryBackend(accountID, region) webACL, err := wafBk.CreateWebACL( context.Background(), "wiring-test-acl", "REGIONAL", "", - json.RawMessage(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + jsontext.Value(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, ) require.NoError(t, err) require.NoError(t, wafBk.TagResource( @@ -1527,7 +1529,7 @@ func TestWireResourceGroupsTagging_CrossServiceResources(t *testing.T) { "SubnetIds": []string{"subnet-1", "subnet-2"}, "SecurityGroupIds": []string{"sg-1"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPut, "/environments/wiring-test-env", bytes.NewReader(body)) @@ -2355,7 +2357,7 @@ func TestWireResourceGroupsTagging_TagResourcesRoundTrip(t *testing.T) { wafBk := wafv2backend.NewInMemoryBackend(accountID, region) webACL, err := wafBk.CreateWebACL( context.Background(), "roundtrip-acl", "REGIONAL", "", - json.RawMessage(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + jsontext.Value(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, ) require.NoError(t, err) @@ -3102,7 +3104,7 @@ func TestHealthEndpoint_GoroutineAndMemStats(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var body map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1())) // Verify the new observability fields are present. assert.Contains(t, body, "goroutines", "health response must include goroutines count") @@ -3208,7 +3210,7 @@ func TestLocalstackCompatibilityEndpoints(t *testing.T) { waitForEndpoint(t, fmt.Sprintf("http://localhost:%d/_localstack/init/ready", port), func(resp *http.Response) bool { var body map[string]any - return json.NewDecoder(resp.Body).Decode(&body) == nil && body["completed"] == true + return json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1()) == nil && body["completed"] == true }) for _, tt := range tests { @@ -3219,7 +3221,7 @@ func TestLocalstackCompatibilityEndpoints(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var body map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1())) tt.validate(t, body) }) } @@ -3384,7 +3386,7 @@ func TestBuildSnapshotHandler_EmptyManager(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp snapshotResponse - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, snapshotBundleFormat, resp.Format) assert.Equal(t, 0, resp.Exported) assert.Empty(t, resp.Services) @@ -3445,7 +3447,7 @@ func TestBuildSnapshotHandler(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp snapshotResponse - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, snapshotBundleFormat, resp.Format) assert.Equal(t, "ok", resp.Status) @@ -3469,14 +3471,14 @@ func TestBuildSnapshotHandler_ResponseIsValidJSON(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp snapshotResponse - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) // Service snapshot must be embedded as raw JSON, not base64. rawSvc, ok := resp.Services["svc"] require.True(t, ok, "svc key must be present") var parsed map[string]any - require.NoError(t, json.Unmarshal(rawSvc, &parsed)) + require.NoError(t, json.Unmarshal(rawSvc, &parsed, jsonx.V1())) assert.Equal(t, []any{float64(1), float64(2), float64(3)}, parsed["items"]) } @@ -3490,14 +3492,14 @@ func TestBuildLoadHandler_EmptyBundle(t *testing.T) { body, _ := json.Marshal(snapshotBundle{ Format: snapshotBundleFormat, - Services: map[string]json.RawMessage{}, - }) + Services: map[string]jsontext.Value{}, + }, jsonx.V1()) rec := postJSON(t, handler, body) assert.Equal(t, http.StatusOK, rec.Code) var resp loadResponse - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "ok", resp.Status) assert.Equal(t, 0, resp.Loaded) } @@ -3505,7 +3507,7 @@ func TestBuildLoadHandler_EmptyBundle(t *testing.T) { func TestBuildLoadHandler(t *testing.T) { t.Parallel() - snap := json.RawMessage(`{"restored":true}`) + snap := jsontext.Value(`{"restored":true}`) tests := []struct { setupErr error @@ -3518,7 +3520,7 @@ func TestBuildLoadHandler(t *testing.T) { name: "single_service_loaded", bundle: snapshotBundle{ Format: snapshotBundleFormat, - Services: map[string]json.RawMessage{"svc": snap}, + Services: map[string]jsontext.Value{"svc": snap}, }, wantStatusCode: http.StatusOK, wantLoaded: 1, @@ -3527,7 +3529,7 @@ func TestBuildLoadHandler(t *testing.T) { name: "unknown_service_skipped", bundle: snapshotBundle{ Format: snapshotBundleFormat, - Services: map[string]json.RawMessage{"unknown": snap}, + Services: map[string]jsontext.Value{"unknown": snap}, }, wantStatusCode: http.StatusOK, wantLoaded: 1, @@ -3537,7 +3539,7 @@ func TestBuildLoadHandler(t *testing.T) { setupErr: errRestoreFailure, bundle: snapshotBundle{ Format: snapshotBundleFormat, - Services: map[string]json.RawMessage{"svc": snap}, + Services: map[string]jsontext.Value{"svc": snap}, }, wantStatusCode: http.StatusInternalServerError, }, @@ -3555,7 +3557,7 @@ func TestBuildLoadHandler(t *testing.T) { e.HTTPErrorHandler = buildHTTPErrorHandler() e.POST("/", handler) - body, marshalErr := json.Marshal(tt.bundle) + body, marshalErr := json.Marshal(tt.bundle, jsonx.V1()) require.NoError(t, marshalErr) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -3567,7 +3569,7 @@ func TestBuildLoadHandler(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp loadResponse - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "ok", resp.Status) assert.Equal(t, tt.wantLoaded, resp.Loaded) } else { @@ -3649,7 +3651,7 @@ func TestSnapshotLoadRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, snapRec.Code) var snapResp snapshotResponse - require.NoError(t, json.NewDecoder(snapRec.Body).Decode(&snapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(snapRec.Body), &snapResp, jsonx.V1())) assert.Equal(t, len(tt.initial), snapResp.Exported) // Step 2: Reset all services. @@ -3662,7 +3664,7 @@ func TestSnapshotLoadRoundTrip(t *testing.T) { } // Step 3: POST /_gopherstack/load with the exported snapshot. - loadBody, err := json.Marshal(snapResp.snapshotBundle) + loadBody, err := json.Marshal(snapResp.snapshotBundle, jsonx.V1()) require.NoError(t, err) loadReq := httptest.NewRequest( @@ -3678,7 +3680,7 @@ func TestSnapshotLoadRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, loadRec.Code) var loadResp loadResponse - require.NoError(t, json.NewDecoder(loadRec.Body).Decode(&loadResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(loadRec.Body), &loadResp, jsonx.V1())) assert.Equal(t, "ok", loadResp.Status) assert.Equal(t, len(tt.initial), loadResp.Loaded) @@ -3711,10 +3713,10 @@ func TestSnapshotLoadRoundTrip_CrossManagerLoad(t *testing.T) { require.Equal(t, http.StatusOK, snapRec.Code) var snapResp snapshotResponse - require.NoError(t, json.NewDecoder(snapRec.Body).Decode(&snapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(snapRec.Body), &snapResp, jsonx.V1())) // Load into mgrB. - loadBody, err := json.Marshal(snapResp.snapshotBundle) + loadBody, err := json.Marshal(snapResp.snapshotBundle, jsonx.V1()) require.NoError(t, err) loadReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(loadBody)) @@ -3741,7 +3743,7 @@ func TestSnapshotLoadRoundTrip_EmptyServicesProduceEmptyBundle(t *testing.T) { require.Equal(t, http.StatusOK, snapRec.Code) var snapResp snapshotResponse - require.NoError(t, json.NewDecoder(snapRec.Body).Decode(&snapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(snapRec.Body), &snapResp, jsonx.V1())) assert.Equal(t, 0, snapResp.Exported, "nil-snapshot service must not be exported") assert.Empty(t, snapResp.Services) } @@ -3762,7 +3764,7 @@ func TestBuildEchoServer_SnapshotLoadRoutes(t *testing.T) { e.ServeHTTP(snapshotRec, snapshotReq) assert.NotEqual(t, http.StatusNotFound, snapshotRec.Code, "snapshot route must be registered") - loadBody, _ := json.Marshal(snapshotBundle{Format: snapshotBundleFormat, Services: nil}) + loadBody, _ := json.Marshal(snapshotBundle{Format: snapshotBundleFormat, Services: nil}, jsonx.V1()) loadReq := httptest.NewRequest(http.MethodPost, "/_gopherstack/load", bytes.NewReader(loadBody)) loadReq.Header.Set("Content-Type", "application/json") loadRec := httptest.NewRecorder() @@ -3791,7 +3793,7 @@ func TestBuildSnapshotHandler_MultipleServices_StatePreservedIndependently(t *te require.Equal(t, http.StatusOK, snapRec.Code) var snapResp snapshotResponse - require.NoError(t, json.NewDecoder(snapRec.Body).Decode(&snapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(snapRec.Body), &snapResp, jsonx.V1())) assert.Equal(t, 3, snapResp.Exported) // Reset. @@ -3800,7 +3802,7 @@ func TestBuildSnapshotHandler_MultipleServices_StatePreservedIndependently(t *te } // Load. - loadBody, err := json.Marshal(snapResp.snapshotBundle) + loadBody, err := json.Marshal(snapResp.snapshotBundle, jsonx.V1()) require.NoError(t, err) loadRec := httptest.NewRecorder() diff --git a/internal/app/cloudcontrol_handlers.go b/internal/app/cloudcontrol_handlers.go index 78b3e3bc6b..d46ebc30ad 100644 --- a/internal/app/cloudcontrol_handlers.go +++ b/internal/app/cloudcontrol_handlers.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -28,6 +28,7 @@ import ( "github.com/blackbirdworks/gopherstack/internal/awswire/cloudwatchlogs" "github.com/blackbirdworks/gopherstack/internal/awswire/sqs" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" cloudcontrolbackend "github.com/blackbirdworks/gopherstack/services/cloudcontrol" cfnbackend "github.com/blackbirdworks/gopherstack/services/cloudformation" @@ -82,12 +83,12 @@ func tagsProperty(m map[string]string) []map[string]string { func ccDecode[T any](raw any) (T, error) { var out T - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return out, fmt.Errorf("%w: %w", cloudcontrolbackend.ErrValidation, err) } - if err = json.Unmarshal(b, &out); err != nil { + if err = json.Unmarshal(b, &out, jsonx.V1()); err != nil { return out, fmt.Errorf("%w: %w", cloudcontrolbackend.ErrValidation, err) } @@ -147,13 +148,13 @@ func ccRejectUnsupportedChanges(current, desired map[string]any, allowed ...stri } func normalizeJSON(v any) any { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } var out any - if json.Unmarshal(b, &out) != nil { + if json.Unmarshal(b, &out, jsonx.V1()) != nil { return v } diff --git a/internal/app/cloudcontrol_handlers_security.go b/internal/app/cloudcontrol_handlers_security.go index dcdd987b3e..11524dd0c4 100644 --- a/internal/app/cloudcontrol_handlers_security.go +++ b/internal/app/cloudcontrol_handlers_security.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "math" "net/url" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/internal/awswire/kms" "github.com/blackbirdworks/gopherstack/internal/awswire/secretsmanager" "github.com/blackbirdworks/gopherstack/internal/awswire/ssm" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cloudcontrolbackend "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -78,7 +79,7 @@ func ccPolicyJSON(v any) (string, error) { return s, nil } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "", fmt.Errorf("%w: %w", cloudcontrolbackend.ErrValidation, err) } @@ -94,7 +95,7 @@ func ccPolicyObject(doc string, unescape bool) any { } var out any - if json.Unmarshal([]byte(doc), &out) != nil { + if json.Unmarshal([]byte(doc), &out, jsonx.V1()) != nil { return doc } diff --git a/internal/app/cloudcontrol_handlers_test.go b/internal/app/cloudcontrol_handlers_test.go index 3e43835ca7..ce6a8eafea 100644 --- a/internal/app/cloudcontrol_handlers_test.go +++ b/internal/app/cloudcontrol_handlers_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "net/netip" "slices" "strings" @@ -12,6 +12,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type ccDelegationCase struct { @@ -120,7 +122,7 @@ func ccAssertGet(t *testing.T, cc *cloudcontrol.Client, tt ccDelegationCase, id assert.Equal(t, id, aws.ToString(got.ResourceDescription.Identifier)) var props map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props, jsonx.V1())) for _, k := range tt.wantKeys { assert.Contains(t, props, k) @@ -206,7 +208,7 @@ func ccDeleteAndVerify(t *testing.T, cc *cloudcontrol.Client, fx *sfnFixture, tt } func jsonScalar(v any) string { - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return string(b) } @@ -215,9 +217,9 @@ func subsetJSON(t *testing.T, doc, key string) string { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(doc), &m)) + require.NoError(t, json.Unmarshal([]byte(doc), &m, jsonx.V1())) - b, err := json.Marshal(map[string]any{key: m[key]}) + b, err := json.Marshal(map[string]any{key: m[key]}, jsonx.V1()) require.NoError(t, err) return string(b) @@ -334,7 +336,7 @@ func TestCloudControlSubnetIPv6(t *testing.T) { require.NoError(t, err) var props map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props, jsonx.V1())) assert.Equal(t, []any{v6}, props["Ipv6CidrBlocks"]) assert.Equal(t, azID, props["AvailabilityZoneId"]) assert.Equal(t, true, props["AssignIpv6AddressOnCreation"]) diff --git a/internal/app/cloudcontrol_provisioned_test.go b/internal/app/cloudcontrol_provisioned_test.go index cf6101d017..caa2de93e5 100644 --- a/internal/app/cloudcontrol_provisioned_test.go +++ b/internal/app/cloudcontrol_provisioned_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cfnbackend "github.com/blackbirdworks/gopherstack/services/cloudformation" ) @@ -42,7 +43,7 @@ func TestCloudControlProvisionedType_Lifecycle(t *testing.T) { require.NoError(t, err) var props map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props, jsonx.V1())) assert.Equal(t, "cc-prov-user", props["UserName"]) listed, err := cc.ListResources(t.Context(), &cloudcontrol.ListResourcesInput{TypeName: aws.String(typeName)}) diff --git a/internal/app/cloudcontrol_queue_url_test.go b/internal/app/cloudcontrol_queue_url_test.go index bff2f402d8..323d48b0e6 100644 --- a/internal/app/cloudcontrol_queue_url_test.go +++ b/internal/app/cloudcontrol_queue_url_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -13,6 +13,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudControlQueueURLMatchesSQS(t *testing.T) { @@ -68,7 +70,7 @@ func TestCloudFormationQueueURLMatchesSQS(t *testing.T) { "Q": map[string]any{"Type": "AWS::SQS::Queue", "Properties": map[string]any{"QueueName": "cfn-url-q"}}, }, "Outputs": map[string]any{"Url": map[string]any{"Value": map[string]any{"Ref": "Q"}}}, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/cloudcontrol_wire_client.go b/internal/app/cloudcontrol_wire_client.go index 05210b39f2..b8d7f5862e 100644 --- a/internal/app/cloudcontrol_wire_client.go +++ b/internal/app/cloudcontrol_wire_client.go @@ -2,12 +2,13 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cloudcontrolbackend "github.com/blackbirdworks/gopherstack/services/cloudcontrol" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire" ) @@ -40,12 +41,12 @@ func wireCall[O any](ctx context.Context, c *ccWireClient, op string, in any) (* params := map[string]any{} if in != nil { - b, err := json.Marshal(in) + b, err := json.Marshal(in, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: %w", cloudcontrolbackend.ErrValidation, err) } - if err = json.Unmarshal(b, ¶ms); err != nil { + if err = json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", cloudcontrolbackend.ErrValidation, err) } } @@ -57,12 +58,12 @@ func wireCall[O any](ctx context.Context, c *ccWireClient, op string, in any) (* var out O - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, err } - if err = json.Unmarshal(b, &out); err != nil { + if err = json.Unmarshal(b, &out, jsonx.V1()); err != nil { return nil, fmt.Errorf("decode %s response: %w", op, err) } diff --git a/internal/app/cloudformation_cloudhsm_wiring_test.go b/internal/app/cloudformation_cloudhsm_wiring_test.go index 29e03794d2..b88ea086f8 100644 --- a/internal/app/cloudformation_cloudhsm_wiring_test.go +++ b/internal/app/cloudformation_cloudhsm_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsCloudHSMCluster(t *testing.T) { @@ -42,7 +44,7 @@ func TestCloudFormationProvisionsCloudHSMCluster(t *testing.T) { "Outputs": map[string]any{ "Id": map[string]any{"Value": map[string]any{"Ref": "Cluster"}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) _, err = cfn.CreateStack(t.Context(), &cloudformation.CreateStackInput{ diff --git a/internal/app/cloudformation_connectfamily_wiring_test.go b/internal/app/cloudformation_connectfamily_wiring_test.go index 04eeda4073..85f6b53067 100644 --- a/internal/app/cloudformation_connectfamily_wiring_test.go +++ b/internal/app/cloudformation_connectfamily_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -13,6 +13,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/connect" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsAppIntegrationsAndCodeGuru(t *testing.T) { @@ -44,7 +46,7 @@ func TestCloudFormationProvisionsAppIntegrationsAndCodeGuru(t *testing.T) { "EventArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Event", "EventIntegrationArn"}}}, "AssocArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Assoc", "AssociationArn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) @@ -122,7 +124,7 @@ func TestCloudFormationProvisionsConnect(t *testing.T) { "InstanceId": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Instance", "Id"}}}, "QueueArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Queue", "QueueArn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/cloudformation_directconnect_test.go b/internal/app/cloudformation_directconnect_test.go index 81540aecf5..51f8661272 100644 --- a/internal/app/cloudformation_directconnect_test.go +++ b/internal/app/cloudformation_directconnect_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/directconnect" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsDirectConnect(t *testing.T) { @@ -48,7 +50,7 @@ func TestCloudFormationProvisionsDirectConnect(t *testing.T) { "ConnArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Conn", "ConnectionArn"}}}, "VifArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Vif", "VirtualInterfaceArn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/cloudformation_networkmanager_test.go b/internal/app/cloudformation_networkmanager_test.go index 073b0cb4dc..c2c17ca7e8 100644 --- a/internal/app/cloudformation_networkmanager_test.go +++ b/internal/app/cloudformation_networkmanager_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/networkmanager" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsNetworkManager(t *testing.T) { @@ -55,7 +57,7 @@ func TestCloudFormationProvisionsNetworkManager(t *testing.T) { "SiteArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Site", "SiteArn"}}}, "GNArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"GN", "Arn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/cloudformation_oam_wiring_test.go b/internal/app/cloudformation_oam_wiring_test.go index 82e9605ee4..1e2e537653 100644 --- a/internal/app/cloudformation_oam_wiring_test.go +++ b/internal/app/cloudformation_oam_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/oam" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsOAMSink(t *testing.T) { @@ -25,7 +27,7 @@ func TestCloudFormationProvisionsOAMSink(t *testing.T) { "Outputs": map[string]any{ "Arn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Sink", "Arn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/cloudformation_rum_wiring_test.go b/internal/app/cloudformation_rum_wiring_test.go index b336061833..4c6d17b278 100644 --- a/internal/app/cloudformation_rum_wiring_test.go +++ b/internal/app/cloudformation_rum_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/rum" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCloudFormationProvisionsRUMAppMonitor(t *testing.T) { @@ -30,7 +32,7 @@ func TestCloudFormationProvisionsRUMAppMonitor(t *testing.T) { "Name": map[string]any{"Value": map[string]any{"Ref": "Mon"}}, "Id": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Mon", "Id"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/codepipeline_actions_test.go b/internal/app/codepipeline_actions_test.go index 14103e0709..f0a50e51e1 100644 --- a/internal/app/codepipeline_actions_test.go +++ b/internal/app/codepipeline_actions_test.go @@ -3,7 +3,7 @@ package app import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/v2" "io" "maps" "testing" @@ -21,6 +21,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const cfnPipelineTemplate = `{"Parameters":{"Env":{"Type":"String","Default":"dev"}},` + @@ -509,7 +511,7 @@ func TestCodePipelineECRSource(t *testing.T) { } var detail map[string]any - require.NoError(t, json.Unmarshal([]byte(env.object(t, "out/imageDetail.json")), &detail)) + require.NoError(t, json.Unmarshal([]byte(env.object(t, "out/imageDetail.json")), &detail, jsonx.V1())) imgs, err := ecrc.DescribeImages(ctx, &ecr.DescribeImagesInput{ RepositoryName: aws.String( diff --git a/internal/app/dev_endpoints_test.go b/internal/app/dev_endpoints_test.go index 522d97d25c..934aecdc01 100644 --- a/internal/app/dev_endpoints_test.go +++ b/internal/app/dev_endpoints_test.go @@ -2,7 +2,8 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "io" "net/http" @@ -24,6 +25,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -143,7 +145,7 @@ func TestSESRetrospectionEndpoint(t *testing.T) { var got struct { Messages []map[string]any `json:"messages"` } - require.NoError(t, json.Unmarshal(body, &got)) + require.NoError(t, json.Unmarshal(body, &got, jsonx.V1())) require.Len(t, got.Messages, tt.wantN) if tt.wantN == 0 { @@ -225,7 +227,7 @@ func TestSQSInspectEndpoint(t *testing.T) { Body string `json:"Body"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(body, &got)) + require.NoError(t, json.Unmarshal(body, &got, jsonx.V1())) require.Len(t, got.Messages, 1) assert.Equal(t, "payload", got.Messages[0].Body) assert.Equal(t, "0", got.Messages[0].Attributes["ApproximateReceiveCount"]) @@ -316,7 +318,7 @@ func TestCloudWatchRawMetricsEndpoint(t *testing.T) { var got struct { Metrics []map[string]any `json:"metrics"` } - require.NoError(t, json.Unmarshal(body, &got)) + require.NoError(t, json.Unmarshal(body, &got, jsonx.V1())) var found map[string]any @@ -419,7 +421,7 @@ func TestLambdaRuntimesEndpoint(t *testing.T) { Runtimes []string `json:"Runtimes"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Contains(t, out.Runtimes, tt.has) if tt.hasNot != "" { diff --git a/internal/app/dms_engine_docker_test.go b/internal/app/dms_engine_docker_test.go index 888f126beb..8bc7014c10 100644 --- a/internal/app/dms_engine_docker_test.go +++ b/internal/app/dms_engine_docker_test.go @@ -3,7 +3,7 @@ package app import ( "context" "database/sql" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net" @@ -30,6 +30,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -698,7 +699,7 @@ func TestDMSDockerMySQLToInProcessTargets(t *testing.T) { for _, r := range out.Records { var x dmsKinesisRec - require.NoError(t, json.Unmarshal(r.Data, &x)) + require.NoError(t, json.Unmarshal(r.Data, &x, jsonx.V1())) got = append(got, x) } diff --git a/internal/app/ecs_runtime_test.go b/internal/app/ecs_runtime_test.go index 75aead18e7..74c1a73544 100644 --- a/internal/app/ecs_runtime_test.go +++ b/internal/app/ecs_runtime_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -14,6 +14,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sts" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func newECSTaskFixture(t *testing.T, role string) (*sfnFixture, *ecs.Client, string) { @@ -87,7 +89,7 @@ func TestECSTaskStateEventsReachRuleTarget(t *testing.T) { for _, m := range out.Messages { var env map[string]any - uErr := json.Unmarshal([]byte(aws.ToString(m.Body)), &env) + uErr := json.Unmarshal([]byte(aws.ToString(m.Body)), &env, jsonx.V1()) if uErr != nil || env["detail-type"] != "ECS Task State Change" { continue } diff --git a/internal/app/error_wire_guards_test.go b/internal/app/error_wire_guards_test.go index 1f551b32b4..07a9689bc6 100644 --- a/internal/app/error_wire_guards_test.go +++ b/internal/app/error_wire_guards_test.go @@ -1,7 +1,8 @@ package app import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "fmt" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -41,7 +43,7 @@ func probeJSONBody() string { for _, k := range keys { m[k] = "gs-probe-missing" } - b, _ := json.Marshal(m) + b, _ := json.Marshal(m, jsonx.V1()) return string(b) } @@ -172,8 +174,8 @@ func parseErrorBody(p errorProbe) (parsedError, bool) { } func parseJSONError(p errorProbe, body string) (parsedError, bool) { - var m map[string]json.RawMessage - if json.Unmarshal([]byte(body), &m) != nil { + var m map[string]jsontext.Value + if json.Unmarshal([]byte(body), &m, jsonx.V1()) != nil { return parsedError{}, false } @@ -184,7 +186,7 @@ func parseJSONError(p errorProbe, body string) (parsedError, bool) { } var s string - _ = json.Unmarshal(raw, &s) + _ = json.Unmarshal(raw, &s, jsonx.V1()) return s, true } diff --git a/internal/app/extensions_test.go b/internal/app/extensions_test.go index 09700b9906..8695152bdc 100644 --- a/internal/app/extensions_test.go +++ b/internal/app/extensions_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/extensions" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -76,7 +77,7 @@ func TestExtensionRoutingAndHooks(t *testing.T) { "hooks": map[string]any{"request": []map[string]any{ {"services": []string{"Dash"}, "pre": "/hook/pre", "post": "/hook/post"}, }}, - }) + }, jsonx.V1()) require.NoError(t, err) require.NoError(t, os.WriteFile(regFile, reg, 0o600)) @@ -87,7 +88,7 @@ func TestExtensionRoutingAndHooks(t *testing.T) { cfgFile := filepath.Join(dir, "ext.json") cfg, err := json.Marshal(map[string]any{"extensions": []map[string]any{ {"name": "t", "command": []string{"sh", "-c", script}, "health_interval": "1h"}, - }}) + }}, jsonx.V1()) require.NoError(t, err) require.NoError(t, os.WriteFile(cfgFile, cfg, 0o600)) diff --git a/internal/app/fis_cloudwatch_stopcondition_wiring_test.go b/internal/app/fis_cloudwatch_stopcondition_wiring_test.go index af77938f0b..fc7d50adca 100644 --- a/internal/app/fis_cloudwatch_stopcondition_wiring_test.go +++ b/internal/app/fis_cloudwatch_stopcondition_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cwbackend "github.com/blackbirdworks/gopherstack/services/cloudwatch" fisbackend "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -25,7 +26,7 @@ func fisWiringRequest(t *testing.T, h *fisbackend.Handler, method, path string, var bodyBytes []byte if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyBytes = b } @@ -94,7 +95,7 @@ func TestWireFISStopConditions_AlarmStopsRealExperiment(t *testing.T) { ID string `json:"id"` } `json:"experimentTemplate"` } - require.NoError(t, json.Unmarshal(tplRec.Body.Bytes(), &tplResp)) + require.NoError(t, json.Unmarshal(tplRec.Body.Bytes(), &tplResp, jsonx.V1())) expRec := fisWiringRequest(t, fisH, http.MethodPost, "/experiments", map[string]any{ "experimentTemplateId": tplResp.ExperimentTemplate.ID, @@ -106,7 +107,7 @@ func TestWireFISStopConditions_AlarmStopsRealExperiment(t *testing.T) { ID string `json:"id"` } `json:"experiment"` } - require.NoError(t, json.Unmarshal(expRec.Body.Bytes(), &expResp)) + require.NoError(t, json.Unmarshal(expRec.Body.Bytes(), &expResp, jsonx.V1())) expID := expResp.Experiment.ID // Advance past the pending -> initiating -> running transition. This diff --git a/internal/app/gcpenforce_wiring_test.go b/internal/app/gcpenforce_wiring_test.go index 505d087570..9b97a00c42 100644 --- a/internal/app/gcpenforce_wiring_test.go +++ b/internal/app/gcpenforce_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "io" "log/slog" "net/http" @@ -21,6 +21,7 @@ import ( "google.golang.org/grpc/status" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -233,7 +234,7 @@ func getREST(t *testing.T, url string) (int, restEnvelope) { var env restEnvelope - _ = json.Unmarshal(body, &env) + _ = json.Unmarshal(body, &env, jsonx.V1()) return resp.StatusCode, env } diff --git a/internal/app/gcpfunctions_events_wiring_test.go b/internal/app/gcpfunctions_events_wiring_test.go index 15da9b5bff..c07cde1c51 100644 --- a/internal/app/gcpfunctions_events_wiring_test.go +++ b/internal/app/gcpfunctions_events_wiring_test.go @@ -4,7 +4,8 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net" @@ -21,6 +22,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" gcpfirestorebackend "github.com/blackbirdworks/gopherstack/services/gcpfirestore" gcpfunctionsbackend "github.com/blackbirdworks/gopherstack/services/gcpfunctions" @@ -130,9 +132,9 @@ func TestWireGCPFunctions_StorageFirestoreAndSecrets(t *testing.T) { "GCPFunctions": fns, "GCPStorage": gcs, "GCPFirestore": fs, "GCPSecretManager": sm, }) - _, err := gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": json.RawMessage(`"src"`)}) + _, err := gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": jsontext.Value(`"src"`)}) require.NoError(t, err) - _, err = gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": json.RawMessage(`"inbox"`)}) + _, err = gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": jsontext.Value(`"inbox"`)}) require.NoError(t, err) _, err = sm.Backend.CreateSecret(&secretmanagerpb.CreateSecretRequest{ @@ -204,7 +206,7 @@ func TestWireGCPFunctions_StorageFirestoreAndSecrets(t *testing.T) { var obj map[string]any - require.NoError(t, json.Unmarshal(ev.body, &obj)) + require.NoError(t, json.Unmarshal(ev.body, &obj, jsonx.V1())) assert.Equal(t, "inbox", obj["bucket"]) assert.Equal(t, "a.txt", obj["name"]) diff --git a/internal/app/gcpfunctions_wiring_test.go b/internal/app/gcpfunctions_wiring_test.go index 10d37f049b..931bef9003 100644 --- a/internal/app/gcpfunctions_wiring_test.go +++ b/internal/app/gcpfunctions_wiring_test.go @@ -3,7 +3,7 @@ package app import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/jsontext" "testing" "cloud.google.com/go/functions/apiv2/functionspb" @@ -56,7 +56,7 @@ func TestWireGCPFunctions(t *testing.T) { _, err := ps.Backend.CreateTopic(&pubsubpb.Topic{Name: topic}) require.NoError(t, err) - _, err = gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": json.RawMessage(`"src-bucket"`)}) + _, err = gcs.Backend.CreateBucket("p", gcpstoragebackend.Patch{"name": jsontext.Value(`"src-bucket"`)}) require.NoError(t, err) var buf bytes.Buffer diff --git a/internal/app/globalaccelerator_wiring_test.go b/internal/app/globalaccelerator_wiring_test.go index bcb0011217..835bca1ffa 100644 --- a/internal/app/globalaccelerator_wiring_test.go +++ b/internal/app/globalaccelerator_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -17,6 +17,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func waitStack(t *testing.T, cfn *cloudformation.Client, name string) cfntypes.Stack { @@ -80,7 +82,7 @@ func TestCloudFormationProvisionsGlobalAccelerator(t *testing.T) { "GrpArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Grp", "EndpointGroupArn"}}}, "AttArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Att", "AttachmentArn"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) fx := newSFNFixture(t) diff --git a/internal/app/http_targets_wiring.go b/internal/app/http_targets_wiring.go index c3c0100fe6..66ed7fa7f6 100644 --- a/internal/app/http_targets_wiring.go +++ b/internal/app/http_targets_wiring.go @@ -2,11 +2,12 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" apigwbackend "github.com/blackbirdworks/gopherstack/services/apigateway" ebbackend "github.com/blackbirdworks/gopherstack/services/eventbridge" @@ -115,7 +116,7 @@ func (a *schedUniversalAdapter) InvokeUniversalTarget( ctx context.Context, region, roleARN, svc, action string, input []byte, ) error { var params any - if err := json.Unmarshal(input, ¶ms); err != nil { + if err := json.Unmarshal(input, ¶ms, jsonx.V1()); err != nil { return fmt.Errorf("universal target input is not valid JSON: %w", err) } diff --git a/internal/app/iam_policy_stream.go b/internal/app/iam_policy_stream.go index fd798e3b8b..c948530803 100644 --- a/internal/app/iam_policy_stream.go +++ b/internal/app/iam_policy_stream.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/iampolicystream" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" iambackend "github.com/blackbirdworks/gopherstack/services/iam" organizationsbackend "github.com/blackbirdworks/gopherstack/services/organizations" @@ -116,7 +117,7 @@ func followIAMPolicyStream(c *echo.Context, rec *iampolicystream.Recorder, f iam _ = rc.Flush() send := func(ev iampolicystream.Event) error { - b, err := json.Marshal(ev) + b, err := json.Marshal(ev, jsonx.V1()) if err != nil { return err } diff --git a/internal/app/iam_policy_stream_e2e_test.go b/internal/app/iam_policy_stream_e2e_test.go index 8486a83441..7ae78dd1e7 100644 --- a/internal/app/iam_policy_stream_e2e_test.go +++ b/internal/app/iam_policy_stream_e2e_test.go @@ -1,7 +1,8 @@ package app import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http/httptest" "testing" @@ -15,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/chaos" "github.com/blackbirdworks/gopherstack/pkgs/iampolicystream" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -114,7 +116,7 @@ func TestIAMPolicyStreamEndToEnd(t *testing.T) { var body struct { Events []iampolicystream.Event `json:"events"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1())) require.Len(t, body.Events, 2) allow, deny := body.Events[0], body.Events[1] diff --git a/internal/app/iam_policy_stream_test.go b/internal/app/iam_policy_stream_test.go index 8ca5ac932d..1d8df3357a 100644 --- a/internal/app/iam_policy_stream_test.go +++ b/internal/app/iam_policy_stream_test.go @@ -3,7 +3,7 @@ package app import ( "bufio" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/iampolicystream" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -73,7 +74,7 @@ func TestIAMPolicyStreamList(t *testing.T) { var body struct { Events []iampolicystream.Event `json:"events"` } - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body.Events, tt.wantCount) }) } @@ -88,7 +89,7 @@ func TestIAMPolicySuggest(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var s iampolicystream.Suggestion - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &s, jsonx.V1())) require.Len(t, s.Policy.Statement, 1) assert.Equal(t, []string{"s3:GetObject"}, s.Policy.Statement[0].Action) } diff --git a/internal/app/init_stages.go b/internal/app/init_stages.go index f3fc3f24d3..c37f26767b 100644 --- a/internal/app/init_stages.go +++ b/internal/app/init_stages.go @@ -2,7 +2,8 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "log/slog" "net" @@ -13,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/inithooks" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -136,8 +138,7 @@ func buildInitRunHandler(st *localstackInitState) echo.HandlerFunc { } var req initRunRequest - if err := json.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, initRunMaxBody)). - Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, initRunMaxBody)), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyMessageField: "invalid request body"}) } diff --git a/internal/app/iot_rule_actions_test.go b/internal/app/iot_rule_actions_test.go index c6835607b1..994ded4ad3 100644 --- a/internal/app/iot_rule_actions_test.go +++ b/internal/app/iot_rule_actions_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "fmt" "io" "strings" @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" firehosebackend "github.com/blackbirdworks/gopherstack/services/firehose" iotbackend "github.com/blackbirdworks/gopherstack/services/iot" iotanalyticsbackend "github.com/blackbirdworks/gopherstack/services/iotanalytics" @@ -267,7 +268,7 @@ func iotCaseSNS(t *testing.T, f *iotRuleFixture, format, payload, want string) { Message string `json:"Message"` } - require.NoError(t, json.Unmarshal([]byte(f.bodies(t, url, 1)[0]), &env)) + require.NoError(t, json.Unmarshal([]byte(f.bodies(t, url, 1)[0]), &env, jsonx.V1())) assert.Contains(t, env.Message, want) } @@ -648,7 +649,7 @@ func iotCaseTemplateError(t *testing.T, f *iotRuleFixture) { f.publish(t, "tpl/topic", `{"present":1}`) var env map[string]string - require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env)) + require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env, jsonx.V1())) assert.Equal(t, "KinesisAction", env["failedAction"]) assert.Equal(t, "r", env["ruleName"]) assert.Empty(t, kinesisRecords(t, f.fx, "iot-tpl-stream")) diff --git a/internal/app/iot_rule_http_test.go b/internal/app/iot_rule_http_test.go index 2cf7c45a6e..d77943e8ae 100644 --- a/internal/app/iot_rule_http_test.go +++ b/internal/app/iot_rule_http_test.go @@ -2,7 +2,7 @@ package app import ( "cmp" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -109,7 +110,7 @@ func decodeConfirm(t *testing.T, hit iotHTTPHit) confirmBody { t.Helper() var b confirmBody - require.NoError(t, json.Unmarshal(hit.body, &b)) + require.NoError(t, json.Unmarshal(hit.body, &b, jsonx.V1())) return b } @@ -119,7 +120,7 @@ func (f *iotRuleFixture) confirmViaSDK(t *testing.T) func(hit iotHTTPHit) { return func(hit iotHTTPHit) { var b confirmBody - if json.Unmarshal(hit.body, &b) != nil { + if json.Unmarshal(hit.body, &b, jsonx.V1()) != nil { return } @@ -185,7 +186,7 @@ func TestIoTTopicRuleDestinationConfirmation(t *testing.T) { return func(hit iotHTTPHit) { var b confirmBody - if json.Unmarshal(hit.body, &b) != nil { + if json.Unmarshal(hit.body, &b, jsonx.V1()) != nil { return } @@ -427,7 +428,7 @@ func runIoTHTTPCase(t *testing.T, tt iotHTTPCase) { if tt.wantReason != "" { var env map[string]string - require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env)) + require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env, jsonx.V1())) assert.Equal(t, "HttpAction", env["failedAction"]) assert.Contains(t, env["failedActionReason"], tt.wantReason) } @@ -555,7 +556,7 @@ func TestIoTRuleHTTPActionSigV4Enforcement(t *testing.T) { if !tt.wantHit { var env map[string]string - require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env)) + require.NoError(t, json.Unmarshal([]byte(f.bodies(t, errURL, 1)[0]), &env, jsonx.V1())) assert.Equal(t, "HttpAction", env["failedAction"]) assert.Empty(t, ep.deliveries()) diff --git a/internal/app/iot_rule_lookups_test.go b/internal/app/iot_rule_lookups_test.go index 860d094f6f..8fea90a493 100644 --- a/internal/app/iot_rule_lookups_test.go +++ b/internal/app/iot_rule_lookups_test.go @@ -3,7 +3,7 @@ package app import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net" "strconv" "strings" @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" iotbackend "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -484,7 +485,7 @@ func TestIoTRuleConnectionFunctions(t *testing.T) { require.True(t, tok.WaitTimeout(authzDeadline)) var msg map[string]string - require.NoError(t, json.Unmarshal([]byte(f.bodies(t, url, 1)[0]), &msg)) + require.NoError(t, json.Unmarshal([]byte(f.bodies(t, url, 1)[0]), &msg, jsonx.V1())) assert.Equal(t, "device-7", msg["cid"]) assert.NotNil(t, net.ParseIP(msg["ip"])) diff --git a/internal/app/iotanalytics_lambda_iot_wiring_test.go b/internal/app/iotanalytics_lambda_iot_wiring_test.go index 50adaf0c81..01ad0894c3 100644 --- a/internal/app/iotanalytics_lambda_iot_wiring_test.go +++ b/internal/app/iotanalytics_lambda_iot_wiring_test.go @@ -2,8 +2,9 @@ package app import ( "github.com/blackbirdworks/gopherstack/internal/cliconfig" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http/httptest" "testing" @@ -116,7 +117,7 @@ func TestInitializeServices_IoTAnalyticsLambdaIoTWiring(t *testing.T) { require.Len(t, out.Payloads, 1) var decoded map[string]any - require.NoError(t, json.Unmarshal(out.Payloads[0], &decoded)) + require.NoError(t, json.Unmarshal(out.Payloads[0], &decoded, jsonx.V1())) registryData, isMap := decoded["registry"].(map[string]any) require.True(t, isMap, "registry attribute must be populated from the real IoT backend") @@ -155,7 +156,7 @@ func TestInitializeServices_IoTAnalyticsLambdaIoTWiring(t *testing.T) { require.Len(t, out.Payloads, 1) var decoded map[string]any - require.NoError(t, json.Unmarshal(out.Payloads[0], &decoded)) + require.NoError(t, json.Unmarshal(out.Payloads[0], &decoded, jsonx.V1())) shadowData, isMap := decoded["shadow"].(map[string]any) require.True(t, isMap, "shadow attribute must be populated from the real IoT backend") diff --git a/internal/app/lifecycle_cmd_test.go b/internal/app/lifecycle_cmd_test.go index a943b50c5a..a3781d22f4 100644 --- a/internal/app/lifecycle_cmd_test.go +++ b/internal/app/lifecycle_cmd_test.go @@ -3,7 +3,8 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -23,6 +24,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -104,7 +106,7 @@ func healthServer(t *testing.T, code int, h healthResponse) (*httptest.Server, s switch { case r.URL.Path == "/_gopherstack/health": w.WriteHeader(code) - _ = json.NewEncoder(w).Encode(h) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), h) case r.URL.Path == "/_gopherstack/reset" && r.Method == http.MethodPost: mu.Lock() posts = append(posts, r.URL.RawQuery) @@ -607,7 +609,7 @@ func TestLifecycleStatus(t *testing.T) { require.NoError(t, cmd.run(t.Context(), d)) var rep statusReport - require.NoError(t, json.Unmarshal(out.Bytes(), &rep)) + require.NoError(t, json.Unmarshal(out.Bytes(), &rep, jsonx.V1())) assert.True(t, rep.Running) assert.Equal(t, 4, rep.EnabledCount) assert.Equal(t, 1, rep.DisabledCount) diff --git a/internal/app/lifecycle_foreground_test.go b/internal/app/lifecycle_foreground_test.go index b9d30e8e1a..6cb480fac0 100644 --- a/internal/app/lifecycle_foreground_test.go +++ b/internal/app/lifecycle_foreground_test.go @@ -2,7 +2,8 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -17,6 +18,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errKillFake = errors.New("no console") @@ -79,7 +81,7 @@ func readyServer(t *testing.T, ready *atomic.Bool) string { return } - _ = json.NewEncoder(w).Encode(healthResponse{Status: "ok"}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), healthResponse{Status: "ok"}) })) t.Cleanup(srv.Close) @@ -315,12 +317,12 @@ func TestLifecycleStatusServiceHealth(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/_gopherstack/health": - _ = json.NewEncoder(w).Encode(healthResponse{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), healthResponse{ Status: "ok", Version: "v1", UptimeSecs: 5, Goroutines: 12, HeapAllocB: 3 << 20, Services: []string{"S3", "SQS"}, Disabled: []string{"SNS"}, }) case "/_localstack/health": - _ = json.NewEncoder(w).Encode(localstackHealthResponse{Services: map[string]string{"s3": "available"}}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), localstackHealthResponse{Services: map[string]string{"s3": "available"}}) default: http.NotFound(w, r) } @@ -335,7 +337,7 @@ func TestLifecycleStatusServiceHealth(t *testing.T) { require.NoError(t, cmd.run(t.Context(), d)) var rep statusReport - require.NoError(t, json.Unmarshal(out.Bytes(), &rep)) + require.NoError(t, json.Unmarshal(out.Bytes(), &rep, jsonx.V1())) got := map[string]serviceState{} for _, s := range rep.Clouds["aws"] { diff --git a/internal/app/lifecycle_run.go b/internal/app/lifecycle_run.go index 9ba2fe5363..45fe333e6a 100644 --- a/internal/app/lifecycle_run.go +++ b/internal/app/lifecycle_run.go @@ -3,7 +3,8 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -17,6 +18,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type lifecycleState struct { @@ -41,7 +43,7 @@ func (d *lifecycleDeps) loadState(t LifecycleTarget) (lifecycleState, bool) { } var st lifecycleState - if json.Unmarshal(b, &st) != nil { + if json.Unmarshal(b, &st, jsonx.V1()) != nil { return lifecycleState{}, false } @@ -49,7 +51,7 @@ func (d *lifecycleDeps) loadState(t LifecycleTarget) (lifecycleState, bool) { } func (d *lifecycleDeps) saveState(t LifecycleTarget, st lifecycleState) error { - b, err := json.Marshal(st) + b, err := json.Marshal(st, jsonx.V1()) if err != nil { return fmt.Errorf("encode state: %w", err) } @@ -92,7 +94,7 @@ func (d *lifecycleDeps) health(ctx context.Context, endpoint string) (healthResp return h, fmt.Errorf("%w: health status %d", errLifecycleRequest, code) } - if err = json.Unmarshal(body, &h); err != nil { + if err = json.Unmarshal(body, &h, jsonx.V1()); err != nil { return h, fmt.Errorf("decode health: %w", err) } @@ -485,7 +487,7 @@ func (d *lifecycleDeps) serviceHealth(ctx context.Context, endpoint string) map[ } var r localstackHealthResponse - if json.Unmarshal(body, &r) != nil { + if json.Unmarshal(body, &r, jsonx.V1()) != nil { return nil } @@ -566,7 +568,7 @@ func (c *StatusCmd) run(ctx context.Context, d *lifecycleDeps) error { h, err := d.health(ctx, endpoint) if err != nil { if c.JSON { - _ = json.NewEncoder(d.Out).Encode(statusReport{Endpoint: endpoint, Managed: managed}) + _ = json.MarshalEncode(jsontext.NewEncoder(d.Out, jsonx.V1()), statusReport{Endpoint: endpoint, Managed: managed}) } else { fmt.Fprintf(d.Out, "gopherstack is not running (%s)\n", endpoint) } @@ -576,10 +578,9 @@ func (c *StatusCmd) run(ctx context.Context, d *lifecycleDeps) error { rep := buildStatus(endpoint, h, managed, d.serviceHealth(ctx, endpoint)) if c.JSON { - enc := json.NewEncoder(d.Out) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(d.Out, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(rep) + return json.MarshalEncode(enc, rep) } rep.print(d.Out) @@ -652,7 +653,7 @@ func (c *ResetCmd) run(ctx context.Context, d *lifecycleDeps) error { Message string `json:"message"` } - _ = json.Unmarshal(body, &resp) + _ = json.Unmarshal(body, &resp, jsonx.V1()) fmt.Fprintln(d.Out, resp.Message) } diff --git a/internal/app/localstack_compat_test.go b/internal/app/localstack_compat_test.go index 1d0715c54b..4b186dd25d 100644 --- a/internal/app/localstack_compat_test.go +++ b/internal/app/localstack_compat_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/inithooks" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestLocalstackEnvPlan(t *testing.T) { @@ -355,7 +356,7 @@ func TestLocalstackInternalEndpoints(t *testing.T) { } var body map[string]any - require.NoError(t, json.Unmarshal(raw, &body)) + require.NoError(t, json.Unmarshal(raw, &body, jsonx.V1())) tt.check(t, body) }) } diff --git a/internal/app/logs_policy.go b/internal/app/logs_policy.go index b201342f5c..935fe01afd 100644 --- a/internal/app/logs_policy.go +++ b/internal/app/logs_policy.go @@ -2,9 +2,11 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cwlogsbackend "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -29,7 +31,7 @@ func (a *logsPolicyAdapter) GetResourcePolicy(_ context.Context, resourceARN str } var ( - statements []json.RawMessage + statements []jsontext.Value token string ) @@ -55,7 +57,7 @@ func (a *logsPolicyAdapter) GetResourcePolicy(_ context.Context, resourceARN str return "", nil } - doc, err := json.Marshal(map[string]any{"Version": "2012-10-17", "Statement": statements}) + doc, err := json.Marshal(map[string]any{"Version": "2012-10-17", "Statement": statements}, jsonx.V1()) if err != nil { return "", err } @@ -63,19 +65,19 @@ func (a *logsPolicyAdapter) GetResourcePolicy(_ context.Context, resourceARN str return string(doc), nil } -func policyStatements(doc string) []json.RawMessage { +func policyStatements(doc string) []jsontext.Value { var parsed struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if json.Unmarshal([]byte(doc), &parsed) != nil || len(parsed.Statement) == 0 { + if json.Unmarshal([]byte(doc), &parsed, jsonx.V1()) != nil || len(parsed.Statement) == 0 { return nil } - var list []json.RawMessage - if json.Unmarshal(parsed.Statement, &list) == nil { + var list []jsontext.Value + if json.Unmarshal(parsed.Statement, &list, jsonx.V1()) == nil { return list } - return []json.RawMessage{parsed.Statement} + return []jsontext.Value{parsed.Statement} } diff --git a/internal/app/mcp_wiring_test.go b/internal/app/mcp_wiring_test.go index 224befdc8e..76ac9713c3 100644 --- a/internal/app/mcp_wiring_test.go +++ b/internal/app/mcp_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "os" @@ -22,6 +22,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/chaos" "github.com/blackbirdworks/gopherstack/pkgs/iampolicystream" "github.com/blackbirdworks/gopherstack/pkgs/inithooks" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -127,7 +128,7 @@ func callTool(t *testing.T, cs *mcp.ClientSession, name string, args map[string] res, err := cs.CallTool(t.Context(), &mcp.CallToolParams{Name: name, Arguments: args}) require.NoError(t, err) - raw, err := json.Marshal(res) + raw, err := json.Marshal(res, jsonx.V1()) require.NoError(t, err) require.False(t, res.IsError, "tool %s: %s", name, raw) diff --git a/internal/app/persist_modes_test.go b/internal/app/persist_modes_test.go index a2dd217ea3..759a706677 100644 --- a/internal/app/persist_modes_test.go +++ b/internal/app/persist_modes_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -48,7 +49,7 @@ func (k *kvPersistSvc) Snapshot(context.Context) []byte { k.mu.Lock() defer k.mu.Unlock() - b, _ := json.Marshal(k.vals) + b, _ := json.Marshal(k.vals, jsonx.V1()) return b } @@ -57,7 +58,7 @@ func (k *kvPersistSvc) Restore(_ context.Context, data []byte) error { k.mu.Lock() defer k.mu.Unlock() - return json.Unmarshal(data, &k.vals) + return json.Unmarshal(data, &k.vals, jsonx.V1()) } func (k *kvPersistSvc) getA() string { diff --git a/internal/app/pods_apply.go b/internal/app/pods_apply.go index 2cd087d1af..da30e553c7 100644 --- a/internal/app/pods_apply.go +++ b/internal/app/pods_apply.go @@ -2,13 +2,14 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/pods" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -32,7 +33,7 @@ func podApplyHTTPError(err error) error { // validateSnaps rejects any section that is not well-formed JSON. func validateSnaps(snaps map[string][]byte) error { for n, d := range snaps { - if !json.Valid(d) { + if !jsontext.Value(d).IsValid(jsonx.V1()) { return podInvalidError{fmt.Errorf("%w: service %q section is not valid JSON", pods.ErrCorrupt, n)} } } diff --git a/internal/app/pods_cmd.go b/internal/app/pods_cmd.go index e43e23c55b..229e2745b3 100644 --- a/internal/app/pods_cmd.go +++ b/internal/app/pods_cmd.go @@ -3,7 +3,8 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const podCmdTimeout = 10 * time.Minute @@ -85,7 +87,7 @@ func (t PodTarget) call(method, path string, query url.Values, body any) error { var rdr io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) if err != nil { return fmt.Errorf("encode request: %w", err) } @@ -118,9 +120,9 @@ func (t PodTarget) call(method, path string, query url.Values, body any) error { return fmt.Errorf("%w: %d: %s", errPodServer, resp.StatusCode, strings.TrimSpace(string(out))) } - var pretty bytes.Buffer - if json.Indent(&pretty, out, "", " ") == nil { - out = pretty.Bytes() + pretty := jsontext.Value(bytes.Clone(out)) + if pretty.Indent(jsonx.V1(), jsontext.WithIndent(" ")) == nil { + out = pretty } fmt.Fprintln(os.Stdout, strings.TrimSpace(string(out))) diff --git a/internal/app/pods_localstack.go b/internal/app/pods_localstack.go index 6308cf8a2b..0239eadfa5 100644 --- a/internal/app/pods_localstack.go +++ b/internal/app/pods_localstack.go @@ -1,12 +1,14 @@ package app import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/pods" ) @@ -118,10 +120,10 @@ func (a *podAPI) lsDelete(c *echo.Context) error { func (a *podAPI) lsStateExport(c *echo.Context) error { raw := a.manager.ExportAll() - services := make(map[string]json.RawMessage, len(raw)) + services := make(map[string]jsontext.Value, len(raw)) for n, d := range raw { - services[n] = json.RawMessage(d) + services[n] = jsontext.Value(d) } return c.JSON(http.StatusOK, snapshotResponse{ @@ -131,7 +133,7 @@ func (a *podAPI) lsStateExport(c *echo.Context) error { func (a *podAPI) lsStateImport(c *echo.Context) error { var bundle snapshotBundle - if err := json.NewDecoder(c.Request().Body).Decode(&bundle); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &bundle, jsonx.V1()); err != nil { return echo.NewHTTPError(http.StatusBadRequest, "invalid snapshot bundle: "+err.Error()) } diff --git a/internal/app/region_wiring_test.go b/internal/app/region_wiring_test.go index f6cd071af2..7366bc5160 100644 --- a/internal/app/region_wiring_test.go +++ b/internal/app/region_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/pkgs/service" athenabackend "github.com/blackbirdworks/gopherstack/services/athena" @@ -59,7 +60,7 @@ func regionTargetCall( require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/internal/app/regional_platform_wiring_test.go b/internal/app/regional_platform_wiring_test.go index 22646b5770..dbc1b689a1 100644 --- a/internal/app/regional_platform_wiring_test.go +++ b/internal/app/regional_platform_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" awsconfigbackend "github.com/blackbirdworks/gopherstack/services/awsconfig" cfnbackend "github.com/blackbirdworks/gopherstack/services/cloudformation" codebuildbackend "github.com/blackbirdworks/gopherstack/services/codebuild" @@ -37,7 +38,7 @@ func regionRESTCall(t *testing.T, h echo.HandlerFunc, region, method, path, body out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out diff --git a/internal/app/registry_webhook_test.go b/internal/app/registry_webhook_test.go index f0c85c0922..c6ec715bdc 100644 --- a/internal/app/registry_webhook_test.go +++ b/internal/app/registry_webhook_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" ) @@ -31,7 +32,7 @@ func newHookSink(t *testing.T) *hookSink { raw, _ := io.ReadAll(r.Body) var m map[string]any - _ = json.Unmarshal(raw, &m) + _ = json.Unmarshal(raw, &m, jsonx.V1()) s.mu.Lock() s.got = append(s.got, m) diff --git a/internal/app/registry_wiring.go b/internal/app/registry_wiring.go index 4d7297309a..dd15fe638c 100644 --- a/internal/app/registry_wiring.go +++ b/internal/app/registry_wiring.go @@ -1,10 +1,11 @@ package app import ( - "encoding/json" + "encoding/json/v2" "errors" "path/filepath" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" acr "github.com/blackbirdworks/gopherstack/services/azurecontainerregistry" @@ -103,13 +104,13 @@ func (a *azureContainerRegistryAdapter) WebhookEvents(registry, name string) ([] out := make([]map[string]any, 0, len(events)) for _, ev := range events { - raw, marshalErr := json.Marshal(ev) + raw, marshalErr := json.Marshal(ev, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } var m map[string]any - if unmarshalErr := json.Unmarshal(raw, &m); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(raw, &m, jsonx.V1()); unmarshalErr != nil { return nil, unmarshalErr } diff --git a/internal/app/replicate_cmd.go b/internal/app/replicate_cmd.go index 8e65a403f7..a41b1c348a 100644 --- a/internal/app/replicate_cmd.go +++ b/internal/app/replicate_cmd.go @@ -2,7 +2,8 @@ package app import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -12,6 +13,7 @@ import ( "text/tabwriter" "github.com/blackbirdworks/gopherstack/internal/replicator" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -67,10 +69,9 @@ func (c *ReplicateCmd) run(ctx context.Context, out io.Writer, fn replicateFunc) } if c.JSON { - enc := json.NewEncoder(out) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(out, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if err = enc.Encode(rep); err != nil { + if err = json.MarshalEncode(enc, rep); err != nil { return fmt.Errorf("encode report: %w", err) } } else { diff --git a/internal/app/replicate_test.go b/internal/app/replicate_test.go index c67e62daa9..26fc865454 100644 --- a/internal/app/replicate_test.go +++ b/internal/app/replicate_test.go @@ -3,7 +3,7 @@ package app import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/internal/replicator" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func fakeReplicate(rep *replicator.Report, err error, seen *replicator.Config) replicateFunc { @@ -86,7 +87,7 @@ func TestReplicateAPIJobLifecycle(t *testing.T) { } var started map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) var job replicateJob @@ -94,7 +95,7 @@ func TestReplicateAPIJobLifecycle(t *testing.T) { r := replicateDo(e, http.MethodGet, replicateBasePath+"/"+started["id"], "") job = replicateJob{} - return r.Code == http.StatusOK && json.Unmarshal(r.Body.Bytes(), &job) == nil && + return r.Code == http.StatusOK && json.Unmarshal(r.Body.Bytes(), &job, jsonx.V1()) == nil && job.Status != replicateRunning }, 5*time.Second, 5*time.Millisecond) @@ -131,7 +132,7 @@ func TestReplicateAPIDoesNotEchoCredentials(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var started map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) got := replicateDo(e, http.MethodGet, replicateBasePath+"/"+started["id"], "") assert.NotContains(t, got.Body.String(), "topsecret") diff --git a/internal/app/requests_endpoint_test.go b/internal/app/requests_endpoint_test.go index d9626b1a6a..15c0bc8601 100644 --- a/internal/app/requests_endpoint_test.go +++ b/internal/app/requests_endpoint_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -64,14 +65,14 @@ func TestRequestsHandler(t *testing.T) { if tt.wantCode != http.StatusOK { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body["message"]) return } var got []logger.CapturedRequest - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) paths := make([]string, 0, len(got)) for _, r := range got { diff --git a/internal/app/s3_snapshot_options_test.go b/internal/app/s3_snapshot_options_test.go index 48d7885ac8..fd26aa31ad 100644 --- a/internal/app/s3_snapshot_options_test.go +++ b/internal/app/s3_snapshot_options_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -164,7 +165,7 @@ func TestPersistManualEndpoints(t *testing.T) { var out map[string]any - require.NoError(t, json.Unmarshal(load.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(load.Body.Bytes(), &out, jsonx.V1())) assert.InDelta(t, 1, out["loaded"], 0) assert.Equal(t, "7", h3.kvs[0].getA()) } diff --git a/internal/app/s3_sns_subject_wiring_test.go b/internal/app/s3_sns_subject_wiring_test.go index db4a12339e..853f7860c7 100644 --- a/internal/app/s3_sns_subject_wiring_test.go +++ b/internal/app/s3_sns_subject_wiring_test.go @@ -1,13 +1,14 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" s3backend "github.com/blackbirdworks/gopherstack/services/s3" snsbackend "github.com/blackbirdworks/gopherstack/services/sns" sqsbackend "github.com/blackbirdworks/gopherstack/services/sqs" @@ -83,7 +84,7 @@ func TestS3SNSPublisherAdapter_ForwardsSubject(t *testing.T) { var envelope struct { Subject string `json:"Subject"` } - require.NoError(t, json.Unmarshal([]byte(receivedBody), &envelope)) + require.NoError(t, json.Unmarshal([]byte(receivedBody), &envelope, jsonx.V1())) require.Equal(t, "S3Notification", envelope.Subject, "s3SNSPublisherAdapter must forward the S3 notification dispatcher's subject to SNS "+ "Publish instead of hardcoding an empty one") diff --git a/internal/app/s3tables_s3_wiring_test.go b/internal/app/s3tables_s3_wiring_test.go index dbdc75ccfa..bcd2b1d887 100644 --- a/internal/app/s3tables_s3_wiring_test.go +++ b/internal/app/s3tables_s3_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "io" "strings" "testing" @@ -12,6 +12,8 @@ import ( s3tablestypes "github.com/aws/aws-sdk-go-v2/service/s3tables/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestS3TablesInitialMetadataMaterialized(t *testing.T) { @@ -84,7 +86,7 @@ func TestS3TablesInitialMetadataMaterialized(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(raw, &doc)) + require.NoError(t, json.Unmarshal(raw, &doc, jsonx.V1())) assert.InDelta(t, 2, doc["format-version"], 0) assert.Equal(t, aws.ToString(loc.WarehouseLocation), doc["location"]) assert.InDelta(t, 2, doc["last-column-id"], 0) diff --git a/internal/app/scheduler_universal_targets_test.go b/internal/app/scheduler_universal_targets_test.go index 126c15b6c7..909b2065a0 100644 --- a/internal/app/scheduler_universal_targets_test.go +++ b/internal/app/scheduler_universal_targets_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/scheduler" schedtypes "github.com/aws/aws-sdk-go-v2/service/scheduler/types" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const universalPrefix = "arn:aws:scheduler:::aws-sdk:" @@ -46,7 +48,7 @@ func TestSchedulerUniversalTargets(t *testing.T) { t.Helper() url, _ := authzQueue(t, fx, "universal-q") - in, err := json.Marshal(map[string]string{"QueueUrl": url, "MessageBody": "hello"}) + in, err := json.Marshal(map[string]string{"QueueUrl": url, "MessageBody": "hello"}, jsonx.V1()) require.NoError(t, err) return string(in), url @@ -97,7 +99,7 @@ func TestSchedulerUniversalTargets(t *testing.T) { jd := setupBatchQueue(t, fx) in, err := json.Marshal(map[string]string{ "JobName": "universal-job", "JobQueue": "eb-queue", "JobDefinition": jd, - }) + }, jsonx.V1()) require.NoError(t, err) return string(in), "" diff --git a/internal/app/service_role_authz_test.go b/internal/app/service_role_authz_test.go index 6f2d10ceab..3508ce1c20 100644 --- a/internal/app/service_role_authz_test.go +++ b/internal/app/service_role_authz_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -182,7 +183,7 @@ func TestServiceRoleAuthzStepFunctionsLegacy(t *testing.T) { func jsonAtOptional(raw *string, path ...string) (string, bool) { var cur any - if raw == nil || json.Unmarshal([]byte(*raw), &cur) != nil { + if raw == nil || json.Unmarshal([]byte(*raw), &cur, jsonx.V1()) != nil { return "", false } diff --git a/internal/app/ses_inbound_wiring_test.go b/internal/app/ses_inbound_wiring_test.go index 1714c7a163..1a43609466 100644 --- a/internal/app/ses_inbound_wiring_test.go +++ b/internal/app/ses_inbound_wiring_test.go @@ -4,7 +4,7 @@ import ( "crypto/aes" "crypto/cipher" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/smtp" "testing" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" sesbackend "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -110,7 +111,7 @@ func TestSESInboundKMSAndAuthWiring(t *testing.T) { require.NoError(t, err) var matdesc map[string]string - require.NoError(t, json.Unmarshal([]byte(obj.Metadata["x-amz-matdesc"]), &matdesc)) + require.NoError(t, json.Unmarshal([]byte(obj.Metadata["x-amz-matdesc"]), &matdesc, jsonx.V1())) dec, err := kmsC.Decrypt(ctx, &kms.DecryptInput{CiphertextBlob: wrapped, EncryptionContext: matdesc}) require.NoError(t, err) diff --git a/internal/app/sesv2_sns_event_wiring_test.go b/internal/app/sesv2_sns_event_wiring_test.go index b4f0c02e8a..def710603b 100644 --- a/internal/app/sesv2_sns_event_wiring_test.go +++ b/internal/app/sesv2_sns_event_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -13,6 +13,8 @@ import ( sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSESv2SNSEventDestinationWiring(t *testing.T) { @@ -114,7 +116,7 @@ func TestSESv2SNSEventDestinationWiring(t *testing.T) { Message string `json:"Message"` } - if json.Unmarshal([]byte(aws.ToString(m.Body)), &env) != nil { + if json.Unmarshal([]byte(aws.ToString(m.Body)), &env, jsonx.V1()) != nil { continue } @@ -122,7 +124,7 @@ func TestSESv2SNSEventDestinationWiring(t *testing.T) { EventType string `json:"eventType"` } - if json.Unmarshal([]byte(env.Message), &ev) == nil { + if json.Unmarshal([]byte(env.Message), &ev, jsonx.V1()) == nil { got[ev.EventType] = true } } diff --git a/internal/app/sfn_sdk_integration_test.go b/internal/app/sfn_sdk_integration_test.go index 348dc98d78..55eb090404 100644 --- a/internal/app/sfn_sdk_integration_test.go +++ b/internal/app/sfn_sdk_integration_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net" "net/http" @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" sfnbackend "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -157,7 +158,7 @@ func jsonAt(t *testing.T, raw *string, path ...string) any { t.Helper() var cur any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(raw)), &cur)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(raw)), &cur, jsonx.V1())) for _, p := range path { m, ok := cur.(map[string]any) diff --git a/internal/app/sns_wiring_test.go b/internal/app/sns_wiring_test.go index b4b3d9cab8..2772233fe2 100644 --- a/internal/app/sns_wiring_test.go +++ b/internal/app/sns_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "context" - "encoding/json" + "encoding/json/v2" "io" "testing" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" firehosebackend "github.com/blackbirdworks/gopherstack/services/firehose" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" snsbackend "github.com/blackbirdworks/gopherstack/services/sns" @@ -124,7 +125,7 @@ func TestWireSNSToLambdaFirehose_EndToEndDelivery(t *testing.T) { require.NoError(t, err) dlqARN := arn.Build("sqs", config.DefaultRegion, config.DefaultAccountID, "lambda-dlq") - redrivePolicy, err := json.Marshal(map[string]string{"deadLetterTargetArn": dlqARN}) + redrivePolicy, err := json.Marshal(map[string]string{"deadLetterTargetArn": dlqARN}, jsonx.V1()) require.NoError(t, err) require.NoError(t, snsBk.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy))) diff --git a/internal/app/sso_test.go b/internal/app/sso_test.go index 3cc196dbd4..d422c28f06 100644 --- a/internal/app/sso_test.go +++ b/internal/app/sso_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" identitystorebackend "github.com/blackbirdworks/gopherstack/services/identitystore" @@ -194,7 +195,7 @@ func writeSSOTokenCache(t *testing.T, l ssoLogin, expiresAt time.Time) string { "accessToken": l.accessToken, "expiresAt": expiresAt.UTC().Format(time.RFC3339), "refreshToken": l.refreshToken, "clientId": l.clientID, "clientSecret": l.clientSecret, "region": "us-east-1", "startUrl": ssoStartURL, - }) + }, jsonx.V1()) require.NoError(t, err) require.NoError(t, os.WriteFile(path, data, 0o600)) diff --git a/internal/app/textract_rekognition_s3_wiring_test.go b/internal/app/textract_rekognition_s3_wiring_test.go index c58743b500..039acde657 100644 --- a/internal/app/textract_rekognition_s3_wiring_test.go +++ b/internal/app/textract_rekognition_s3_wiring_test.go @@ -2,7 +2,7 @@ package app import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/pkgs/service" rekognitionbackend "github.com/blackbirdworks/gopherstack/services/rekognition" @@ -31,7 +32,7 @@ func doJSONTargetRequest( ) (int, map[string]any) { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -44,7 +45,7 @@ func doJSONTargetRequest( require.NoError(t, h(c)) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return rec.Code, resp } diff --git a/internal/app/timestreaminfluxdb_wiring_test.go b/internal/app/timestreaminfluxdb_wiring_test.go index 0f83425e6d..7aa0526db0 100644 --- a/internal/app/timestreaminfluxdb_wiring_test.go +++ b/internal/app/timestreaminfluxdb_wiring_test.go @@ -1,7 +1,7 @@ package app import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/timestreaminfluxdb/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTimestreamInfluxDBAuthSecretWiring(t *testing.T) { @@ -55,7 +57,7 @@ func TestTimestreamInfluxDBAuthSecretWiring(t *testing.T) { require.NoError(t, err) var secret map[string]string - require.NoError(t, json.Unmarshal([]byte(aws.ToString(val.SecretString)), &secret)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(val.SecretString)), &secret, jsonx.V1())) assert.Equal(t, tt.wantUsername, secret["username"]) assert.Equal(t, "Passw0rdPassw0rd", secret["password"]) assert.Len(t, secret["token"], 64) diff --git a/internal/app/verifiedpermissions_jwt_test.go b/internal/app/verifiedpermissions_jwt_test.go index 681d4dc078..25497f9f1e 100644 --- a/internal/app/verifiedpermissions_jwt_test.go +++ b/internal/app/verifiedpermissions_jwt_test.go @@ -6,7 +6,8 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "log/slog" "math/big" @@ -28,6 +29,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/chaos" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" cognitoidpbackend "github.com/blackbirdworks/gopherstack/services/cognitoidp" verifiedpermissionsbackend "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" @@ -304,11 +306,11 @@ func newOIDCServer(t *testing.T) *oidcServer { t.Cleanup(o.srv.Close) mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, _ *http.Request) { - _ = json.NewEncoder(w).Encode(map[string]string{"issuer": o.srv.URL, "jwks_uri": o.srv.URL + "/keys"}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{"issuer": o.srv.URL, "jwks_uri": o.srv.URL + "/keys"}) }) mux.HandleFunc("/keys", func(w http.ResponseWriter, _ *http.Request) { o.jwksHits.Add(1) - _ = json.NewEncoder(w).Encode(map[string]any{"keys": []map[string]string{{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{"keys": []map[string]string{{ "kty": "RSA", "use": "sig", "alg": "RS256", "kid": "k1", "n": base64.RawURLEncoding.EncodeToString(key.N.Bytes()), "e": base64.RawURLEncoding.EncodeToString(big.NewInt(int64(key.E)).Bytes()), diff --git a/internal/awstest/awstest.go b/internal/awstest/awstest.go index 827c45e81f..6ef1be0d87 100644 --- a/internal/awstest/awstest.go +++ b/internal/awstest/awstest.go @@ -8,13 +8,15 @@ package awstest import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http/httptest" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // NewContext builds an echo context and response recorder for an httptest @@ -38,7 +40,7 @@ func NewJSONContext( var body io.Reader if payload != nil { - raw, err := json.Marshal(payload) + raw, err := json.Marshal(payload, jsonx.V1()) require.NoError(t, err) body = bytes.NewReader(raw) } @@ -53,5 +55,5 @@ func NewJSONContext( func DecodeJSON(t *testing.T, rec *httptest.ResponseRecorder, v any) { t.Helper() - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1())) } diff --git a/internal/awswire/awswire.go b/internal/awswire/awswire.go index f06527c661..e1a016f3a9 100644 --- a/internal/awswire/awswire.go +++ b/internal/awswire/awswire.go @@ -5,7 +5,7 @@ package awswire import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -17,6 +17,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/retry" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire" ) @@ -142,12 +143,12 @@ func Do[O any](ctx context.Context, c *Core, op string, in any) (*O, error) { params := map[string]any{} if in != nil { - b, err := json.Marshal(in) + b, err := json.Marshal(in, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode %s request: %w", op, err) } - if err = json.Unmarshal(b, ¶ms); err != nil { + if err = json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return nil, fmt.Errorf("encode %s request: %w", op, err) } } @@ -159,12 +160,12 @@ func Do[O any](ctx context.Context, c *Core, op string, in any) (*O, error) { var out O - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, err } - if err = json.Unmarshal(b, &out); err != nil { + if err = json.Unmarshal(b, &out, jsonx.V1()); err != nil { return nil, fmt.Errorf("decode %s response: %w", op, err) } diff --git a/internal/awswire/awswire_test.go b/internal/awswire/awswire_test.go index e6b05e068f..80dd480feb 100644 --- a/internal/awswire/awswire_test.go +++ b/internal/awswire/awswire_test.go @@ -2,7 +2,7 @@ package awswire_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -25,6 +25,7 @@ import ( "github.com/blackbirdworks/gopherstack/internal/awswire/kms" "github.com/blackbirdworks/gopherstack/internal/awswire/lambda" "github.com/blackbirdworks/gopherstack/internal/awswire/sqs" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func testConfig(base string) aws.Config { @@ -56,7 +57,7 @@ func TestClientSignsAndDecodes(t *testing.T) { auth, token = r.Header.Get("Authorization"), r.Header.Get("X-Amz-Security-Token") target = r.Header.Get("X-Amz-Target") raw, _ := io.ReadAll(r.Body) - _ = json.Unmarshal(raw, &body) + _ = json.Unmarshal(raw, &body, jsonx.V1()) w.Header().Set("Content-Type", "application/x-amz-json-1.1") _, _ = w.Write([]byte(`{"KeyMetadata":{"KeyId":"k-1","Arn":"arn:aws:kms:us-west-2:1:key/k-1","Enabled":true}}`)) })) @@ -166,7 +167,7 @@ func TestPaginator(t *testing.T) { raw, _ := io.ReadAll(r.Body) var in map[string]any - _ = json.Unmarshal(raw, &in) + _ = json.Unmarshal(raw, &in, jsonx.V1()) marker, _ := in["Marker"].(string) seen = append(seen, marker) diff --git a/internal/dockercompat/client/client.go b/internal/dockercompat/client/client.go index 7c6119f4ff..97ab333273 100644 --- a/internal/dockercompat/client/client.go +++ b/internal/dockercompat/client/client.go @@ -3,7 +3,8 @@ package client import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -19,6 +20,7 @@ import ( compatcontainer "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/container" compatimage "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/image" compatnetwork "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/network" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Opt aliases the Moby client option type. @@ -104,13 +106,13 @@ var errPushRejected = errors.New("image push failed") // pushAnonymousAuth is the base64 of "{}": the X-Registry-Auth header for a registry without credentials. const pushAnonymousAuth = "e30=" -func pushDigest(aux *json.RawMessage, statusLine, prev string) string { +func pushDigest(aux *jsontext.Value, statusLine, prev string) string { if aux != nil { var a struct { Digest string `json:"Digest"` } - if json.Unmarshal(*aux, &a) == nil && a.Digest != "" { + if json.Unmarshal(*aux, &a, jsonx.V1()) == nil && a.Digest != "" { return a.Digest } } diff --git a/internal/dockercompat/client/client_runtime_test.go b/internal/dockercompat/client/client_runtime_test.go index 4a2bf77a1d..39a75ae8d1 100644 --- a/internal/dockercompat/client/client_runtime_test.go +++ b/internal/dockercompat/client/client_runtime_test.go @@ -1,7 +1,8 @@ package client_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +14,7 @@ import ( compatcontainer "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/container" "github.com/blackbirdworks/gopherstack/internal/dockercompat/client" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type fakeDaemon struct { @@ -26,7 +28,7 @@ func (f *fakeDaemon) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch { case strings.HasSuffix(r.URL.Path, "/containers/create"): f.mu.Lock() - _ = json.NewDecoder(r.Body).Decode(&f.createBody) + _ = json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &f.createBody, jsonx.V1()) f.mu.Unlock() w.WriteHeader(http.StatusCreated) _, _ = w.Write([]byte(`{"Id":"abc","Warnings":[]}`)) diff --git a/internal/mcpserver/backend.go b/internal/mcpserver/backend.go index be0feaa9c2..bafc7b6b7f 100644 --- a/internal/mcpserver/backend.go +++ b/internal/mcpserver/backend.go @@ -4,13 +4,15 @@ package mcpserver import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -40,7 +42,7 @@ func (b *backend) call(ctx context.Context, method, path string, q url.Values, i var body io.Reader = http.NoBody if in != nil { - raw, err := json.Marshal(in) + raw, err := json.Marshal(in, jsonx.V1()) if err != nil { return fmt.Errorf("encode request: %w", err) } @@ -81,7 +83,7 @@ func (b *backend) call(ctx context.Context, method, path string, q url.Values, i return nil } - if err = json.Unmarshal(raw, out); err != nil { + if err = json.Unmarshal(raw, out, jsonx.V1()); err != nil { return fmt.Errorf("decode response: %w", err) } diff --git a/internal/mcpserver/server.go b/internal/mcpserver/server.go index 4a748d7aec..78e18adac3 100644 --- a/internal/mcpserver/server.go +++ b/internal/mcpserver/server.go @@ -2,10 +2,12 @@ package mcpserver import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/modelcontextprotocol/go-sdk/mcp" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -51,7 +53,7 @@ func (b *backend) infoResource(ctx context.Context, req *mcp.ReadResourceRequest return nil, err } - raw, err := json.Marshal(h) + raw, err := json.Marshal(h, jsonx.V1()) if err != nil { return nil, err } diff --git a/internal/replicator/sqs.go b/internal/replicator/sqs.go index 516303ed42..bca02c3b0d 100644 --- a/internal/replicator/sqs.go +++ b/internal/replicator/sqs.go @@ -2,7 +2,7 @@ package replicator import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "path" "slices" @@ -10,6 +10,7 @@ import ( sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types" "github.com/blackbirdworks/gopherstack/internal/awswire/sqs" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func sqsCreateAttrs() []sqstypes.QueueAttributeName { @@ -79,7 +80,7 @@ func dlqName(redrive string) string { Arn string `json:"deadLetterTargetArn"` } - if json.Unmarshal([]byte(redrive), &rp) != nil || rp.Arn == "" { + if json.Unmarshal([]byte(redrive), &rp, jsonx.V1()) != nil || rp.Arn == "" { return "" } diff --git a/pkgs/apptrace/middleware.go b/pkgs/apptrace/middleware.go index 84f503ed5d..8afaa1187d 100644 --- a/pkgs/apptrace/middleware.go +++ b/pkgs/apptrace/middleware.go @@ -2,7 +2,7 @@ package apptrace import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -317,7 +318,7 @@ func (r *redactor) errorCode(header string, body []byte) string { if b[0] == '{' { var env errEnvelope - if json.Unmarshal(b, &env) == nil { + if json.Unmarshal(b, &env, jsonx.V1()) == nil { return cleanCode(env.pick()) } diff --git a/pkgs/awserr/respond.go b/pkgs/awserr/respond.go index 9679259561..6fc0f5e0fb 100644 --- a/pkgs/awserr/respond.go +++ b/pkgs/awserr/respond.go @@ -1,7 +1,7 @@ package awserr import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "hash/crc32" @@ -9,6 +9,8 @@ import ( "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Protocol identifies the AWS wire protocol used to encode an error envelope. @@ -129,7 +131,7 @@ func Write(c *echo.Context, proto Protocol, e APIError) error { } func writeJSON(c *echo.Context, contentType string, e APIError) error { - body, _ := json.Marshal(jsonErrorEnvelope{Type: e.Code, Message: e.Message, MessageCap: e.Message}) + body, _ := json.Marshal(jsonErrorEnvelope{Type: e.Code, Message: e.Message, MessageCap: e.Message}, jsonx.V1()) checksum := crc32.ChecksumIEEE(body) c.Response().Header().Set("X-Amz-Crc32", strconv.FormatUint(uint64(checksum), 10)) c.Response().Header().Set("Content-Type", contentType) diff --git a/pkgs/awserr/respond_test.go b/pkgs/awserr/respond_test.go index 0fd7806b93..4c5caa2a0a 100644 --- a/pkgs/awserr/respond_test.go +++ b/pkgs/awserr/respond_test.go @@ -1,7 +1,7 @@ package awserr_test import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestClassifyMatchesWrappedSentinel(t *testing.T) { @@ -67,7 +68,7 @@ func TestWriteJSON10(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", env.Type) assert.Equal(t, "nope", env.Message) } diff --git a/pkgs/awstime/awstime_test.go b/pkgs/awstime/awstime_test.go index b7d24971ff..2e016c78ef 100644 --- a/pkgs/awstime/awstime_test.go +++ b/pkgs/awstime/awstime_test.go @@ -1,11 +1,12 @@ package awstime_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEpoch(t *testing.T) { @@ -61,7 +62,7 @@ func TestEpochTimeJSON(t *testing.T) { in := doc{At: awstime.NewEpochTime(time.Unix(1_700_000_000, 500_000_000).UTC())} - raw, err := json.Marshal(in) + raw, err := json.Marshal(in, jsonx.V1()) if err != nil { t.Fatal(err) } @@ -71,7 +72,7 @@ func TestEpochTimeJSON(t *testing.T) { } var out doc - if err = json.Unmarshal(raw, &out); err != nil { + if err = json.Unmarshal(raw, &out, jsonx.V1()); err != nil { t.Fatal(err) } @@ -79,7 +80,7 @@ func TestEpochTimeJSON(t *testing.T) { t.Fatalf("round trip lost data: %+v", out) } - if err = json.Unmarshal([]byte(`{"at":"2026-01-01"}`), &out); err == nil { + if err = json.Unmarshal([]byte(`{"at":"2026-01-01"}`), &out, jsonx.V1()); err == nil { t.Fatal("string timestamp must be rejected") } } diff --git a/pkgs/chaos/handler.go b/pkgs/chaos/handler.go index 2f15e1ada6..4ec74576c9 100644 --- a/pkgs/chaos/handler.go +++ b/pkgs/chaos/handler.go @@ -1,11 +1,13 @@ package chaos import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -83,7 +85,7 @@ func (h *apiHandler) getFaults(c *echo.Context) error { // postFaults replaces the entire fault configuration. func (h *apiHandler) postFaults(c *echo.Context) error { var rules []FaultRule - if err := json.NewDecoder(c.Request().Body).Decode(&rules); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &rules, jsonx.V1()); err != nil { return c.String(http.StatusBadRequest, "invalid JSON: "+err.Error()) } @@ -99,7 +101,7 @@ func (h *apiHandler) postFaults(c *echo.Context) error { // patchFaults appends rules to the existing fault configuration. func (h *apiHandler) patchFaults(c *echo.Context) error { var rules []FaultRule - if err := json.NewDecoder(c.Request().Body).Decode(&rules); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &rules, jsonx.V1()); err != nil { return c.String(http.StatusBadRequest, "invalid JSON: "+err.Error()) } @@ -115,7 +117,7 @@ func (h *apiHandler) patchFaults(c *echo.Context) error { // deleteFaults removes rules matching the provided list. func (h *apiHandler) deleteFaults(c *echo.Context) error { var rules []FaultRule - if err := json.NewDecoder(c.Request().Body).Decode(&rules); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &rules, jsonx.V1()); err != nil { return c.String(http.StatusBadRequest, "invalid JSON: "+err.Error()) } @@ -132,7 +134,7 @@ func (h *apiHandler) getEffects(c *echo.Context) error { // postEffects updates the network effect configuration. func (h *apiHandler) postEffects(c *echo.Context) error { var effects NetworkEffects - if err := json.NewDecoder(c.Request().Body).Decode(&effects); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &effects, jsonx.V1()); err != nil { return c.String(http.StatusBadRequest, "invalid JSON: "+err.Error()) } @@ -246,7 +248,7 @@ func (h *apiHandler) clearFaults(c *echo.Context) error { // deleteFaultByIndex removes the fault rule at the given index. func (h *apiHandler) deleteFaultByIndex(c *echo.Context) error { var req deleteByIndexRequest - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.String(http.StatusBadRequest, "invalid JSON: "+err.Error()) } diff --git a/pkgs/chaos/handler_test.go b/pkgs/chaos/handler_test.go index 44233f6838..c984319328 100644 --- a/pkgs/chaos/handler_test.go +++ b/pkgs/chaos/handler_test.go @@ -2,7 +2,8 @@ package chaos_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/chaos" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -77,7 +79,7 @@ func TestChaosHandler_Faults_GetEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var rules []chaos.FaultRule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules, jsonx.V1())) assert.Empty(t, rules) } @@ -138,14 +140,14 @@ func TestChaosHandler_Faults_PostReplacesRules(t *testing.T) { reg := service.NewRegistry() e := buildChaosAPI(t, store, reg) - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := callGroup(t, e, http.MethodPost, "/_gopherstack/chaos/faults", bodyBytes) assert.Equal(t, tt.wantStatus, rec.Code) var rules []chaos.FaultRule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules, jsonx.V1())) assert.Equal(t, tt.wantRules, rules) }) } @@ -188,14 +190,14 @@ func TestChaosHandler_Faults_PatchAppendsRules(t *testing.T) { reg := service.NewRegistry() e := buildChaosAPI(t, store, reg) - bodyBytes, err := json.Marshal(tt.patch) + bodyBytes, err := json.Marshal(tt.patch, jsonx.V1()) require.NoError(t, err) rec := callGroup(t, e, http.MethodPatch, "/_gopherstack/chaos/faults", bodyBytes) assert.Equal(t, tt.wantStatus, rec.Code) var rules []chaos.FaultRule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules, jsonx.V1())) assert.Len(t, rules, tt.wantCount) }) } @@ -242,14 +244,14 @@ func TestChaosHandler_Faults_DeleteRemovesRules(t *testing.T) { reg := service.NewRegistry() e := buildChaosAPI(t, store, reg) - bodyBytes, err := json.Marshal(tt.delete) + bodyBytes, err := json.Marshal(tt.delete, jsonx.V1()) require.NoError(t, err) rec := callGroup(t, e, http.MethodDelete, "/_gopherstack/chaos/faults", bodyBytes) assert.Equal(t, tt.wantStatus, rec.Code) var rules []chaos.FaultRule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rules, jsonx.V1())) assert.Len(t, rules, tt.wantCount) }) } @@ -301,7 +303,7 @@ func TestChaosHandler_Effects(t *testing.T) { e := buildChaosAPI(t, store, reg) if tt.postBody != nil { - bodyBytes, err := json.Marshal(tt.postBody) + bodyBytes, err := json.Marshal(tt.postBody, jsonx.V1()) require.NoError(t, err) postRec := callGroup(t, e, http.MethodPost, "/_gopherstack/chaos/effects", bodyBytes) @@ -312,7 +314,7 @@ func TestChaosHandler_Effects(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var effects chaos.NetworkEffects - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &effects)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &effects, jsonx.V1())) assert.Equal(t, tt.wantEffects, effects) }) } @@ -407,7 +409,7 @@ func TestChaosHandler_Targets(t *testing.T) { } var resp targetsResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := make([]string, 0, len(resp.Services)) for _, s := range resp.Services { @@ -503,7 +505,7 @@ func TestChaosHandler_TargetsMerge(t *testing.T) { } var resp targetsResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Find the entry for the expected service name. var found *targetEntry @@ -599,8 +601,8 @@ func TestChaosHandler_Activity_GetEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, "application/json", rec.Header().Get("Content-Type")) - var events []json.RawMessage - require.NoError(t, json.NewDecoder(rec.Body).Decode(&events)) + var events []jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &events, jsonx.V1())) assert.Empty(t, events) } @@ -655,7 +657,7 @@ func TestChaosHandler_Activity_GetWithEvents(t *testing.T) { var events []struct { Service string `json:"service"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&events)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &events, jsonx.V1())) require.Len(t, events, tt.wantCount) if tt.wantFirst != "" { @@ -676,11 +678,11 @@ func TestChaosHandler_Query_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Faults []json.RawMessage `json:"faults"` - Effects json.RawMessage `json:"effects"` - Activity []json.RawMessage `json:"activity"` + Faults []jsontext.Value `json:"faults"` + Effects jsontext.Value `json:"effects"` + Activity []jsontext.Value `json:"activity"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Empty(t, resp.Faults) assert.Empty(t, resp.Activity) } @@ -704,7 +706,7 @@ func TestChaosHandler_Query_WithData(t *testing.T) { Effects chaos.NetworkEffects `json:"effects"` Activity []chaos.ActivityEvent `json:"activity"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.Faults, 1) assert.Equal(t, "s3", resp.Faults[0].Service) require.NotNil(t, resp.Faults[0].Probability) @@ -730,7 +732,7 @@ func TestChaosHandler_ClearFaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var rules []chaos.FaultRule - require.NoError(t, json.NewDecoder(rec.Body).Decode(&rules)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &rules, jsonx.V1())) assert.Empty(t, rules) // Confirm store is empty. @@ -801,7 +803,7 @@ func TestChaosHandler_DeleteFaultByIndex(t *testing.T) { if tt.wantCode == http.StatusOK { var rules []chaos.FaultRule - require.NoError(t, json.NewDecoder(rec.Body).Decode(&rules)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &rules, jsonx.V1())) assert.Len(t, rules, tt.wantCount) } }) @@ -821,7 +823,7 @@ func TestChaosHandler_ResetEffects(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var effects chaos.NetworkEffects - require.NoError(t, json.NewDecoder(rec.Body).Decode(&effects)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &effects, jsonx.V1())) assert.Zero(t, effects.Latency) assert.Zero(t, effects.Jitter) diff --git a/pkgs/chaos/localstack.go b/pkgs/chaos/localstack.go index 07c601ce66..c11a411615 100644 --- a/pkgs/chaos/localstack.go +++ b/pkgs/chaos/localstack.go @@ -1,11 +1,14 @@ package chaos import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -41,7 +44,7 @@ func (h *lsHandler) rules() []FaultRule { return h.store.GetRules() } func decodeRules(c *echo.Context) ([]FaultRule, error) { var rules []FaultRule - if err := json.NewDecoder(c.Request().Body).Decode(&rules); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &rules, jsonx.V1()); err != nil { return nil, err } @@ -111,7 +114,7 @@ func (h *lsHandler) getEffects(c *echo.Context) error { func (h *lsHandler) postEffects(c *echo.Context) error { var in localstackEffects - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil || in.Latency < 0 { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil || in.Latency < 0 { return badRequest(c, errInvalidEffects) } diff --git a/pkgs/container/credentials_resources_test.go b/pkgs/container/credentials_resources_test.go index 6221e76a26..a1a20df73f 100644 --- a/pkgs/container/credentials_resources_test.go +++ b/pkgs/container/credentials_resources_test.go @@ -3,7 +3,7 @@ package container_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "strings" "testing" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/image" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type authRecordingAPI struct { @@ -54,7 +55,7 @@ func TestPullImageWithCredentials(t *testing.T) { var got map[string]string - require.NoError(t, json.Unmarshal(raw, &got)) + require.NoError(t, json.Unmarshal(raw, &got, jsonx.V1())) assert.Equal(t, "puller", got["username"]) assert.Equal(t, "s3cret", got["password"]) assert.Contains(t, got["serveraddress"], strings.TrimPrefix(tc.wantServer, "docker.io")) diff --git a/pkgs/deltalog/deltalog.go b/pkgs/deltalog/deltalog.go index c2f896ebf2..dbfe6c1381 100644 --- a/pkgs/deltalog/deltalog.go +++ b/pkgs/deltalog/deltalog.go @@ -7,7 +7,8 @@ import ( "bufio" "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/url" @@ -16,6 +17,7 @@ import ( "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -82,7 +84,7 @@ type action struct { type addAction struct { PartitionValues map[string]*string `json:"partitionValues"` Path string `json:"path"` - DeletionVector json.RawMessage `json:"deletionVector"` + DeletionVector jsontext.Value `json:"deletionVector"` Size int64 `json:"size"` } @@ -210,7 +212,7 @@ func (s *state) loadCheckpoint(ctx context.Context, st Storage, cps map[int64][] Version int64 `json:"version"` } - if json.Unmarshal(raw, &lc) == nil { + if json.Unmarshal(raw, &lc, jsonx.V1()) == nil { if _, ok := cps[lc.Version]; ok { best = lc.Version } @@ -260,13 +262,13 @@ func (s *state) applyCheckpoint(body []byte) error { continue } - raw, merr := json.Marshal(v) + raw, merr := json.Marshal(v, jsonx.V1()) if merr != nil { return merr } part := map[int]string{0: "add", 1: "metaData", 2: "protocol", 3: "remove"}[i] - if uerr := json.Unmarshal([]byte(`{"`+part+`":`+string(raw)+`}`), &a); uerr != nil { + if uerr := json.Unmarshal([]byte(`{"`+part+`":`+string(raw)+`}`), &a, jsonx.V1()); uerr != nil { return fmt.Errorf("%w: %w", ErrBadLog, uerr) } } @@ -291,7 +293,7 @@ func (s *state) applyCommit(body []byte) error { } var a action - if err := json.Unmarshal(line, &a); err != nil { + if err := json.Unmarshal(line, &a, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", ErrBadLog, err) } @@ -362,9 +364,9 @@ func (s *state) snapshot() (*Snapshot, error) { } type schemaField struct { - Metadata map[string]any `json:"metadata"` - Name string `json:"name"` - Type json.RawMessage `json:"type"` + Metadata map[string]any `json:"metadata"` + Name string `json:"name"` + Type jsontext.Value `json:"type"` } func parseSchema(s, mode string) ([]Column, error) { @@ -372,7 +374,7 @@ func parseSchema(s, mode string) ([]Column, error) { Fields []schemaField `json:"fields"` } - if err := json.Unmarshal([]byte(s), &st); err != nil { + if err := json.Unmarshal([]byte(s), &st, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: schemaString: %w", ErrBadLog, err) } @@ -402,21 +404,21 @@ func parseSchema(s, mode string) ([]Column, error) { return cols, nil } -func hiveType(raw json.RawMessage) (string, error) { +func hiveType(raw jsontext.Value) (string, error) { var prim string - if err := json.Unmarshal(raw, &prim); err == nil { + if err := json.Unmarshal(raw, &prim, jsonx.V1()); err == nil { return hivePrimitive(prim) } var n struct { - Type string `json:"type"` - ElementType json.RawMessage `json:"elementType"` - KeyType json.RawMessage `json:"keyType"` - ValueType json.RawMessage `json:"valueType"` - Fields []schemaField `json:"fields"` + Type string `json:"type"` + ElementType jsontext.Value `json:"elementType"` + KeyType jsontext.Value `json:"keyType"` + ValueType jsontext.Value `json:"valueType"` + Fields []schemaField `json:"fields"` } - if err := json.Unmarshal(raw, &n); err != nil { + if err := json.Unmarshal(raw, &n, jsonx.V1()); err != nil { return "", fmt.Errorf("%w: type %s", ErrBadLog, raw) } diff --git a/pkgs/dmsengine/kinesis_target.go b/pkgs/dmsengine/kinesis_target.go index 377ca82500..67e6a014a1 100644 --- a/pkgs/dmsengine/kinesis_target.go +++ b/pkgs/dmsengine/kinesis_target.go @@ -3,12 +3,15 @@ package dmsengine import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errNoStreamARN = errors.New("KinesisSettings.StreamArn is required") @@ -36,7 +39,7 @@ func newKinesisTarget(ep EndpointConfig, store StreamStore) (Target, error) { var o kinesisOptions if ep.KinesisSettings != "" { - if err := json.Unmarshal([]byte(ep.KinesisSettings), &o); err != nil { + if err := json.Unmarshal([]byte(ep.KinesisSettings), &o, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid KinesisSettings: %w", err) } } @@ -85,7 +88,7 @@ func (t *kinesisTarget) value(v any, k Kind) any { if isNumeric(k) { if _, err := strconv.ParseFloat(x, 64); err == nil { - return json.Number(x) + return jsonx.Number(x) } } @@ -163,14 +166,14 @@ type recordOut struct { func (t *kinesisTarget) encode(data, meta map[string]any) ([]byte, error) { var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) - + opts := []jsontext.Options{jsonx.V1(), jsontext.EscapeForHTML(false)} if !strings.EqualFold(t.opts.MessageFormat, "json-unformatted") { - enc.SetIndent("", " ") + opts = append(opts, jsontext.Multiline(true), jsontext.WithIndent(" ")) } - if err := enc.Encode(recordOut{Data: data, Metadata: meta}); err != nil { + enc := jsontext.NewEncoder(&buf, opts...) + + if err := json.MarshalEncode(enc, recordOut{Data: data, Metadata: meta}); err != nil { return nil, err } diff --git a/pkgs/dmsengine/mapping.go b/pkgs/dmsengine/mapping.go index ee83aa71d7..9abc2d3ba2 100644 --- a/pkgs/dmsengine/mapping.go +++ b/pkgs/dmsengine/mapping.go @@ -1,13 +1,15 @@ package dmsengine import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "regexp" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrMapping reports an invalid table-mappings document. @@ -30,15 +32,15 @@ const ( type flexString string func (f *flexString) UnmarshalJSON(b []byte) error { - var n json.Number - if err := json.Unmarshal(b, &n); err == nil { + var n jsonx.Number + if err := json.Unmarshal(b, &n, jsonx.V1()); err == nil { *f = flexString(n.String()) return nil } var s string - if err := json.Unmarshal(b, &s); err != nil { + if err := json.Unmarshal(b, &s, jsonx.V1()); err != nil { return err } @@ -75,7 +77,7 @@ func ParseMappings(doc string) (Mappings, error) { return m, nil } - if err := json.Unmarshal([]byte(doc), &m); err != nil { + if err := json.Unmarshal([]byte(doc), &m, jsonx.V1()); err != nil { return m, fmt.Errorf("%w: %w", ErrMapping, err) } diff --git a/pkgs/dmsengine/s3_target.go b/pkgs/dmsengine/s3_target.go index dd650cf20a..c6a2d373f0 100644 --- a/pkgs/dmsengine/s3_target.go +++ b/pkgs/dmsengine/s3_target.go @@ -4,12 +4,14 @@ import ( "bytes" "context" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" "sync" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -71,7 +73,7 @@ func newS3Target(ep EndpointConfig, store ObjectStore) (Target, error) { var o s3Options if ep.S3Settings != "" { - if err := json.Unmarshal([]byte(ep.S3Settings), &o); err != nil { + if err := json.Unmarshal([]byte(ep.S3Settings), &o, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid S3Settings: %w", err) } } diff --git a/pkgs/dmsengine/settings.go b/pkgs/dmsengine/settings.go index 62a678aa5b..be03f552b3 100644 --- a/pkgs/dmsengine/settings.go +++ b/pkgs/dmsengine/settings.go @@ -1,10 +1,12 @@ package dmsengine import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrInvalidSettings reports an unusable ReplicationTaskSettings document. @@ -34,7 +36,7 @@ func ParseTaskSettings(doc string) (TaskSettings, error) { } `json:"FullLoadSettings"` } - if err := json.Unmarshal([]byte(doc), &raw); err != nil { + if err := json.Unmarshal([]byte(doc), &raw, jsonx.V1()); err != nil { return ts, fmt.Errorf("%w: %w", ErrInvalidSettings, err) } diff --git a/pkgs/dmsengine/targets_test.go b/pkgs/dmsengine/targets_test.go index 0e17e83597..86e20204ec 100644 --- a/pkgs/dmsengine/targets_test.go +++ b/pkgs/dmsengine/targets_test.go @@ -2,7 +2,7 @@ package dmsengine_test import ( "context" - "encoding/json" + "encoding/json/v2" "sort" "strings" "sync" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/dmsengine" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -239,9 +240,9 @@ func TestKinesisTargetRecords(t *testing.T) { var first, second, del map[string]map[string]any - require.NoError(t, json.Unmarshal([]byte(store.recs[0]), &first)) - require.NoError(t, json.Unmarshal([]byte(store.recs[1]), &second)) - require.NoError(t, json.Unmarshal([]byte(store.recs[2]), &del)) + require.NoError(t, json.Unmarshal([]byte(store.recs[0]), &first, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(store.recs[1]), &second, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(store.recs[2]), &del, jsonx.V1())) assert.Equal(t, map[string]any{"id": float64(1), "name": "alpha"}, first["data"]) assert.Equal(t, map[string]any{"id": float64(2)}, second["data"], "nulls are omitted by default") diff --git a/pkgs/docker/pull.go b/pkgs/docker/pull.go index 11b6650f85..d52ac6ba48 100644 --- a/pkgs/docker/pull.go +++ b/pkgs/docker/pull.go @@ -1,10 +1,14 @@ package docker import ( - "encoding/json" + "bytes" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrImagePull wraps failures the daemon reports in an image pull stream. @@ -20,12 +24,12 @@ type pullMessage struct { // ConsumePullStream reads an ImagePull response to EOF (closing early cancels // the pull) and returns the first error the daemon reports in the stream. func ConsumePullStream(r io.Reader) error { - dec := json.NewDecoder(r) + dec := jsontext.NewDecoder(r) for { var msg pullMessage - err := dec.Decode(&msg) + err := json.UnmarshalDecode(dec, &msg, jsonx.V1()) if errors.Is(err, io.EOF) { return nil } @@ -37,13 +41,13 @@ func ConsumePullStream(r io.Reader) error { } if msg.ErrorDetail != nil && msg.ErrorDetail.Message != "" { - _, _ = io.Copy(io.Discard, io.MultiReader(dec.Buffered(), r)) + _, _ = io.Copy(io.Discard, io.MultiReader(bytes.NewReader(dec.UnreadBuffer()), r)) return fmt.Errorf("%w: %s", ErrImagePull, msg.ErrorDetail.Message) } if msg.Error != "" { - _, _ = io.Copy(io.Discard, io.MultiReader(dec.Buffered(), r)) + _, _ = io.Copy(io.Discard, io.MultiReader(bytes.NewReader(dec.UnreadBuffer()), r)) return fmt.Errorf("%w: %s", ErrImagePull, msg.Error) } diff --git a/pkgs/dynamoattr/attr.go b/pkgs/dynamoattr/attr.go index 39e782c0c1..d0e3b4d4cd 100644 --- a/pkgs/dynamoattr/attr.go +++ b/pkgs/dynamoattr/attr.go @@ -1,12 +1,13 @@ package dynamoattr import ( - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "strings" "github.com/blackbirdworks/gopherstack/pkgs/dynamonum" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // UnwrapAttributeValue converts a DynamoDB wire attribute map into a bare value when possible. @@ -163,7 +164,7 @@ func ToString(v any) string { case nil: return "" default: - b, err := json.Marshal(s) + b, err := json.Marshal(s, jsonx.V1()) if err != nil { return fmt.Sprintf("%v", s) } diff --git a/pkgs/extensions/control.go b/pkgs/extensions/control.go index 0036f52527..a4c4ee3d34 100644 --- a/pkgs/extensions/control.go +++ b/pkgs/extensions/control.go @@ -2,7 +2,8 @@ package extensions import ( "crypto/subtle" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net" @@ -11,6 +12,8 @@ import ( "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -115,8 +118,8 @@ func (m *Manager) ServeRegister(w http.ResponseWriter, r *http.Request) { var reg Registration - dec := json.NewDecoder(http.MaxBytesReader(w, r.Body, maxRegistrationBytes)) - if err := dec.Decode(®); err != nil { + dec := jsontext.NewDecoder(http.MaxBytesReader(w, r.Body, maxRegistrationBytes)) + if err := json.UnmarshalDecode(dec, ®, jsonx.V1()); err != nil { writeJSON(w, http.StatusBadRequest, map[string]string{keyMessage: "invalid JSON: " + err.Error()}) return @@ -287,5 +290,5 @@ func overlap(a, b []string) bool { func writeJSON(w http.ResponseWriter, code int, v any) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - _ = json.NewEncoder(w).Encode(v) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), v) } diff --git a/pkgs/extensions/hooks.go b/pkgs/extensions/hooks.go index 4490e254f7..d45ff90f5c 100644 --- a/pkgs/extensions/hooks.go +++ b/pkgs/extensions/hooks.go @@ -3,7 +3,7 @@ package extensions import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -11,6 +11,7 @@ import ( "net/url" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -320,12 +321,12 @@ func (h *HookSet) Post(r *http.Request, rec *Recorder) *HookResponse { func (h *HookSet) call(ctx context.Context, b boundHook, path string, req hookRequest, rep any) *HookResponse { req.Extension = b.name - payload, err := json.Marshal(req) + payload, err := json.Marshal(req, jsonx.V1()) if err == nil { var out []byte if out, err = h.m.post(ctx, b.ep, path, payload, b.timeout); err == nil && len(bytes.TrimSpace(out)) > 0 { - err = json.Unmarshal(out, rep) + err = json.Unmarshal(out, rep, jsonx.V1()) } } diff --git a/pkgs/extensions/hooks_internal_test.go b/pkgs/extensions/hooks_internal_test.go index d7be9176cb..cc12696239 100644 --- a/pkgs/extensions/hooks_internal_test.go +++ b/pkgs/extensions/hooks_internal_test.go @@ -1,7 +1,8 @@ package extensions import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -10,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func hookManager(t *testing.T, failOpen *bool, hook RequestHook, handler http.HandlerFunc) *Manager { @@ -129,7 +132,7 @@ func TestPreHookPayload(t *testing.T) { var got hookRequest m := hookManager(t, nil, RequestHook{Pre: "/pre"}, func(_ http.ResponseWriter, r *http.Request) { - _ = json.NewDecoder(r.Body).Decode(&got) + _ = json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &got, jsonx.V1()) }) req := httptest.NewRequest(http.MethodPut, "/bkt/key?x=1", strings.NewReader("data")) @@ -172,7 +175,7 @@ func TestPostHook(t *testing.T) { var seen hookRequest m := hookManager(t, nil, RequestHook{Post: "/post"}, func(w http.ResponseWriter, r *http.Request) { - _ = json.NewDecoder(r.Body).Decode(&seen) + _ = json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &seen, jsonx.V1()) _, _ = io.WriteString(w, tt.reply) }) diff --git a/pkgs/extensions/main_internal_test.go b/pkgs/extensions/main_internal_test.go index 6daa0cd011..93302615e3 100644 --- a/pkgs/extensions/main_internal_test.go +++ b/pkgs/extensions/main_internal_test.go @@ -2,7 +2,7 @@ package extensions import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net" "net/http" @@ -12,6 +12,7 @@ import ( "testing" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testleak" ) @@ -90,7 +91,7 @@ func runHelper() { } func mustJSON(v any) string { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { panic(err) } diff --git a/pkgs/gcpdispatch/gcpdispatch.go b/pkgs/gcpdispatch/gcpdispatch.go index 28f1c349db..acbf61761e 100644 --- a/pkgs/gcpdispatch/gcpdispatch.go +++ b/pkgs/gcpdispatch/gcpdispatch.go @@ -3,12 +3,14 @@ package gcpdispatch import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "math" "net/http" "time" "google.golang.org/genproto/googleapis/rpc/code" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -65,7 +67,7 @@ func Backoff(lo, hi time.Duration, doublings, failures int32) time.Duration { } func b64(v any) string { - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(raw) } diff --git a/pkgs/gcpdispatch/gcpdispatch_test.go b/pkgs/gcpdispatch/gcpdispatch_test.go index 6a5ac8b8aa..1be6edd4eb 100644 --- a/pkgs/gcpdispatch/gcpdispatch_test.go +++ b/pkgs/gcpdispatch/gcpdispatch_test.go @@ -2,7 +2,7 @@ package gcpdispatch_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -13,6 +13,7 @@ import ( "google.golang.org/genproto/googleapis/rpc/code" "github.com/blackbirdworks/gopherstack/pkgs/gcpdispatch" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHTTPToRPC(t *testing.T) { @@ -81,7 +82,7 @@ func TestTokens(t *testing.T) { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) assert.Equal(t, "https://x.test/y", claims["aud"]) assert.Equal(t, "sa@p.iam", claims["email"]) diff --git a/pkgs/gcplro/store.go b/pkgs/gcplro/store.go index 82353d6b47..508a2fe6ee 100644 --- a/pkgs/gcplro/store.go +++ b/pkgs/gcplro/store.go @@ -4,7 +4,7 @@ package gcplro import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "strings" @@ -103,11 +103,11 @@ func (s *Store) Reset() { } // Snapshot serialises every operation as protojson. -func (s *Store) Snapshot() map[string]json.RawMessage { +func (s *Store) Snapshot() map[string]jsontext.Value { s.mu.RLock("Snapshot") defer s.mu.RUnlock() - out := make(map[string]json.RawMessage, len(s.ops)) + out := make(map[string]jsontext.Value, len(s.ops)) for name, op := range s.ops { if raw, err := protojson.Marshal(op); err == nil { @@ -119,7 +119,7 @@ func (s *Store) Snapshot() map[string]json.RawMessage { } // Restore replaces the stored operations with a Snapshot result. -func (s *Store) Restore(snap map[string]json.RawMessage) error { +func (s *Store) Restore(snap map[string]jsontext.Value) error { ops := make(map[string]*longrunningpb.Operation, len(snap)) for name, raw := range snap { diff --git a/pkgs/gcprest/errors.go b/pkgs/gcprest/errors.go index 1a87408b98..1792922049 100644 --- a/pkgs/gcprest/errors.go +++ b/pkgs/gcprest/errors.go @@ -1,12 +1,15 @@ package gcprest import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/encoding/protojson" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type codeInfo struct { @@ -40,10 +43,10 @@ type errorBody struct { } type errorDetail struct { - Message string `json:"message"` - Status string `json:"status"` - Details []json.RawMessage `json:"details"` - Code int `json:"code"` + Message string `json:"message"` + Status string `json:"status"` + Details []jsontext.Value `json:"details"` + Code int `json:"code"` } // HTTPStatus maps a gRPC code to the HTTP status Google APIs use for it. @@ -63,7 +66,7 @@ func writeError(w http.ResponseWriter, err error) { info = codeInfo{"UNKNOWN", http.StatusInternalServerError} } - details := make([]json.RawMessage, 0, len(st.Proto().GetDetails())) + details := make([]jsontext.Value, 0, len(st.Proto().GetDetails())) for _, d := range st.Proto().GetDetails() { if b, mErr := protojson.Marshal(d); mErr == nil { @@ -77,7 +80,7 @@ func writeError(w http.ResponseWriter, err error) { } func writeJSON(w http.ResponseWriter, code int, v any) { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/pkgs/gcpserve/logentry.go b/pkgs/gcpserve/logentry.go index c3ba1b2a5c..986ad7c253 100644 --- a/pkgs/gcpserve/logentry.go +++ b/pkgs/gcpserve/logentry.go @@ -1,7 +1,7 @@ package gcpserve import ( - "encoding/json" + "encoding/json/v2" "maps" "strconv" "strings" @@ -9,6 +9,8 @@ import ( "cloud.google.com/go/logging/apiv2/loggingpb" ltype "google.golang.org/genproto/googleapis/logging/type" "google.golang.org/protobuf/types/known/structpb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Special JSON fields the structured-logging agent lifts out of jsonPayload. @@ -49,7 +51,7 @@ func jsonObject(line string) (map[string]any, bool) { } var obj map[string]any - if err := json.Unmarshal([]byte(s), &obj); err != nil || obj == nil { + if err := json.Unmarshal([]byte(s), &obj, jsonx.V1()); err != nil || obj == nil { return nil, false } diff --git a/pkgs/handler/handler_test.go b/pkgs/handler/handler_test.go index 7d59017efe..507292359b 100644 --- a/pkgs/handler/handler_test.go +++ b/pkgs/handler/handler_test.go @@ -2,7 +2,7 @@ package handler_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/handler" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- OperationContext --- @@ -158,7 +159,7 @@ func TestWriteJSON_SetsHeadersAndBody(t *testing.T) { assert.Equal(t, "application/json", rec.Header().Get("Content-Type")) var got map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "value", got["key"]) } diff --git a/pkgs/handler/response.go b/pkgs/handler/response.go index f91d696f21..1968af6d81 100644 --- a/pkgs/handler/response.go +++ b/pkgs/handler/response.go @@ -2,20 +2,21 @@ package handler import ( "context" - "encoding/json" + "encoding/json/v2" "hash/crc32" "net/http" "strconv" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) // WriteJSON marshals the payload to JSON, sets standard headers, and writes the response. // Sets Content-Type to "application/json" and Content-Length. func WriteJSON(w http.ResponseWriter, code int, payload any) error { - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) if err != nil { return err } @@ -33,7 +34,7 @@ func WriteJSON(w http.ResponseWriter, code int, payload any) error { // and writes the response. The checksum is required by the DynamoDB wire protocol. // Sets Content-Type to "application/x-amz-json-1.0" and X-Amz-Crc32. func WriteJSONWithChecksum(w http.ResponseWriter, code int, payload any) error { - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) if err != nil { return err } diff --git a/pkgs/handler/wire_golden_test.go b/pkgs/handler/wire_golden_test.go index d1ef2a89b7..b5e4478aab 100644 --- a/pkgs/handler/wire_golden_test.go +++ b/pkgs/handler/wire_golden_test.go @@ -1,7 +1,7 @@ package handler_test import ( - "encoding/json" + "encoding/json/jsontext" "net/http/httptest" "testing" "time" @@ -41,13 +41,13 @@ type goldenSQSOutput struct { } type goldenMetricResult struct { - ID string `json:"Id"` - Label string `json:"Label"` - StatusCode string `json:"StatusCode"` - Timestamps []float64 `json:"Timestamps"` - Values []float64 `json:"Values"` - Messages []string `json:"Messages"` - Extra json.RawMessage `json:"Extra,omitempty"` + ID string `json:"Id"` + Label string `json:"Label"` + StatusCode string `json:"StatusCode"` + Timestamps []float64 `json:"Timestamps"` + Values []float64 `json:"Values"` + Messages []string `json:"Messages"` + Extra jsontext.Value `json:"Extra,omitempty"` } type goldenMetricOutput struct { @@ -89,8 +89,8 @@ func TestWireGoldenJSONRPC(t *testing.T) { { name: "dynamodb empty scan", payload: goldenScanOutput{}, - body: `{"Items":null,"Count":0,"ScannedCount":0}`, - crc: "4196347728", + body: `{"Items":null,"Count":0,"ScannedCount":0}`, + crc: "4196347728", }, { name: "sqs receive", @@ -105,8 +105,8 @@ func TestWireGoldenJSONRPC(t *testing.T) { { name: "sqs empty", payload: goldenSQSOutput{}, - body: `{"Messages":null}`, - crc: "1433687114", + body: `{"Messages":null}`, + crc: "1433687114", }, { name: "cloudwatch get metric data", @@ -116,7 +116,7 @@ func TestWireGoldenJSONRPC(t *testing.T) { StatusCode: "Complete", Timestamps: []float64{awstime.Epoch(ts), awstime.Epoch(ts.Add(time.Minute))}, Values: []float64{1.5, 2, 1e21, 0.000001, 1e-7, 100, 123456789012}, - Extra: json.RawMessage(` { "a" : [1, 2] } `), + Extra: jsontext.Value(` { "a" : [1, 2] } `), }}}, body: `{"MetricDataResults":[{"Id":"q1","Label":"CPU \u003cavg\u003e","StatusCode":"Complete","Timestamps":[1741064767.1230001,1741064827.1230001],"Values":[1.5,2,1e+21,0.000001,1e-7,100,123456789012],"Messages":null,"Extra":{"a":[1,2]}}]}`, crc: "2076035819", diff --git a/pkgs/httputils/httputils.go b/pkgs/httputils/httputils.go index cd7f4741e8..c9144fcc5a 100644 --- a/pkgs/httputils/httputils.go +++ b/pkgs/httputils/httputils.go @@ -3,7 +3,7 @@ package httputils import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "hash/crc32" "io" @@ -18,6 +18,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -163,7 +164,7 @@ func ParseFormBody(r *http.Request) (url.Values, error) { func WriteJSON(ctx context.Context, w http.ResponseWriter, code int, payload any) { log := logger.Load(ctx) - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) if err != nil { log.ErrorContext(ctx, "failed to marshal JSON response", "error", err) http.Error(w, "internal server error", http.StatusInternalServerError) @@ -209,7 +210,7 @@ func WriteXML(ctx context.Context, w http.ResponseWriter, code int, payload any) func WriteDynamoDBResponse(ctx context.Context, w http.ResponseWriter, code int, payload any) { log := logger.Load(ctx) - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) if err != nil { log.ErrorContext(ctx, "failed to marshal DynamoDB response", "error", err) http.Error(w, diff --git a/pkgs/iceberg/iceberg_test.go b/pkgs/iceberg/iceberg_test.go index 92f85282af..08905f07e4 100644 --- a/pkgs/iceberg/iceberg_test.go +++ b/pkgs/iceberg/iceberg_test.go @@ -1,7 +1,8 @@ package iceberg_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "time" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/iceberg" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTransformSpecVectors(t *testing.T) { @@ -184,8 +186,8 @@ func TestMetadataPreservesUnknownFields(t *testing.T) { out, err := iceberg.EncodeMetadata(m) require.NoError(t, err) - var generic map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out, &generic)) + var generic map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out, &generic, jsonx.V1())) assert.Contains(t, generic, "statistics") _, err = iceberg.ParseMetadata([]byte(`{"format-version":9}`)) @@ -206,7 +208,7 @@ func TestHiveType(t *testing.T) { t.Run(tc.want, func(t *testing.T) { t.Parallel() - got, err := iceberg.HiveType(json.RawMessage(tc.in)) + got, err := iceberg.HiveType(jsontext.Value(tc.in)) require.NoError(t, err) assert.Equal(t, tc.want, got) }) diff --git a/pkgs/iceberg/manifest.go b/pkgs/iceberg/manifest.go index 867264f0aa..23224e48aa 100644 --- a/pkgs/iceberg/manifest.go +++ b/pkgs/iceberg/manifest.go @@ -2,13 +2,15 @@ package iceberg import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strconv" "github.com/iskorotkov/avro/v2" "github.com/iskorotkov/avro/v2/ocf" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Manifest entry statuses and content types from the table spec. @@ -399,7 +401,7 @@ func manifestSchema(meta *TableMetadata, spec PartitionSpec) (string, error) { }, } - b, err := json.Marshal(schema) + b, err := json.Marshal(schema, jsonx.V1()) return string(b), err } @@ -415,8 +417,8 @@ func EncodeManifest(meta *TableMetadata, spec PartitionSpec, content int, entrie return nil, fmt.Errorf("%w: %w", ErrInvalidManifest, err) } - cur, _ := json.Marshal(meta.CurrentSchema()) - specJSON, _ := json.Marshal(spec.Fields) + cur, _ := json.Marshal(meta.CurrentSchema(), jsonx.V1()) + specJSON, _ := json.Marshal(spec.Fields, jsonx.V1()) contentName := "data" if content != ContentData { diff --git a/pkgs/iceberg/metadata.go b/pkgs/iceberg/metadata.go index b977bf3ee4..8f0c3c74b8 100644 --- a/pkgs/iceberg/metadata.go +++ b/pkgs/iceberg/metadata.go @@ -3,7 +3,8 @@ package iceberg import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -12,6 +13,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -35,11 +38,11 @@ var ( // Field is one schema field; Type is a primitive name or a nested type object. type Field struct { - Name string `json:"name"` - Doc string `json:"doc,omitempty"` - Type json.RawMessage `json:"type"` - ID int `json:"id"` - Required bool `json:"required"` + Name string `json:"name"` + Doc string `json:"doc,omitempty"` + Type jsontext.Value `json:"type"` + ID int `json:"id"` + Required bool `json:"required"` } // Schema is an Iceberg struct schema. @@ -98,12 +101,12 @@ type Ref struct { type TableMetadata struct { Properties map[string]string `json:"properties"` Refs map[string]Ref `json:"refs,omitempty"` - extra map[string]json.RawMessage + extra map[string]jsontext.Value TableUUID string `json:"table-uuid"` Location string `json:"location"` Schemas []Schema `json:"schemas"` PartitionSpecs []PartitionSpec `json:"partition-specs"` - SortOrders []json.RawMessage `json:"sort-orders"` + SortOrders []jsontext.Value `json:"sort-orders"` Snapshots []Snapshot `json:"snapshots"` SnapshotLog []SnapshotLogEntry `json:"snapshot-log"` MetadataLog []MetadataLogEntry `json:"metadata-log"` @@ -140,11 +143,11 @@ func (m *TableMetadata) UnmarshalJSON(b []byte) error { a.CurrentSnapshotID = NoSnapshot - if err := json.Unmarshal(b, &a); err != nil { + if err := json.Unmarshal(b, &a, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", ErrInvalidMetadata, err) } - if err := json.Unmarshal(b, &v1); err != nil { + if err := json.Unmarshal(b, &v1, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", ErrInvalidMetadata, err) } @@ -157,8 +160,8 @@ func (m *TableMetadata) UnmarshalJSON(b []byte) error { a.PartitionSpecs = []PartitionSpec{{SpecID: 0, Fields: v1.PartitionSpecV1}} } - raw := map[string]json.RawMessage{} - _ = json.Unmarshal(b, &raw) + raw := map[string]jsontext.Value{} + _ = json.Unmarshal(b, &raw, jsonx.V1()) for _, k := range modeledKeys() { delete(raw, k) @@ -174,28 +177,28 @@ func (m *TableMetadata) UnmarshalJSON(b []byte) error { func (m *TableMetadata) MarshalJSON() ([]byte, error) { out := maps.Clone(m.extra) if out == nil { - out = map[string]json.RawMessage{} + out = map[string]jsontext.Value{} } - typed, err := json.Marshal(metadataAlias(*m)) + typed, err := json.Marshal(metadataAlias(*m), jsonx.V1()) if err != nil { return nil, err } - var fields map[string]json.RawMessage - if err = json.Unmarshal(typed, &fields); err != nil { + var fields map[string]jsontext.Value + if err = json.Unmarshal(typed, &fields, jsonx.V1()); err != nil { return nil, err } maps.Copy(out, fields) - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } // ParseMetadata decodes and validates a metadata.json document. func ParseMetadata(data []byte) (*TableMetadata, error) { var m TableMetadata - if err := json.Unmarshal(data, &m); err != nil { + if err := json.Unmarshal(data, &m, jsonx.V1()); err != nil { return nil, err } @@ -310,7 +313,7 @@ type NewParams struct { Now time.Time Properties map[string]string Location string - SortOrder json.RawMessage + SortOrder jsontext.Value Schema Schema Spec PartitionSpec } @@ -333,7 +336,7 @@ func NewTableMetadata(p NewParams) *TableMetadata { order := p.SortOrder if order == nil { - order = json.RawMessage(`{"order-id":0,"fields":[]}`) + order = jsontext.Value(`{"order-id":0,"fields":[]}`) } props := map[string]string{} @@ -349,7 +352,7 @@ func NewTableMetadata(p NewParams) *TableMetadata { DefaultSpecID: p.Spec.SpecID, PartitionSpecs: []PartitionSpec{p.Spec}, LastPartitionID: lastPart, - SortOrders: []json.RawMessage{order}, + SortOrders: []jsontext.Value{order}, Properties: props, CurrentSnapshotID: NoSnapshot, Snapshots: []Snapshot{}, @@ -359,12 +362,12 @@ func NewTableMetadata(p NewParams) *TableMetadata { } } -func sortOrderID(order json.RawMessage) int { +func sortOrderID(order jsontext.Value) int { var o struct { ID int `json:"order-id"` } - _ = json.Unmarshal(order, &o) + _ = json.Unmarshal(order, &o, jsonx.V1()) return o.ID } diff --git a/pkgs/iceberg/types.go b/pkgs/iceberg/types.go index 0cb5bdded9..8d5565a26a 100644 --- a/pkgs/iceberg/types.go +++ b/pkgs/iceberg/types.go @@ -1,39 +1,42 @@ package iceberg import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrUnsupportedType is returned for a type that cannot be converted or written. var ErrUnsupportedType = errors.New("unsupported iceberg type") type nestedType struct { - Element json.RawMessage `json:"element"` - Key json.RawMessage `json:"key"` - Value json.RawMessage `json:"value"` - Type string `json:"type"` - Fields []Field `json:"fields"` - ElementID int `json:"element-id"` - KeyID int `json:"key-id"` - ValueID int `json:"value-id"` - ElementNeeded bool `json:"element-required"` - ValueNeeded bool `json:"value-required"` + Element jsontext.Value `json:"element"` + Key jsontext.Value `json:"key"` + Value jsontext.Value `json:"value"` + Type string `json:"type"` + Fields []Field `json:"fields"` + ElementID int `json:"element-id"` + KeyID int `json:"key-id"` + ValueID int `json:"value-id"` + ElementNeeded bool `json:"element-required"` + ValueNeeded bool `json:"value-required"` } // HiveType renders an Iceberg type as the Athena/Hive type name used in the // Glue catalog (long -> bigint, list -> array<..>, struct -> struct). -func HiveType(raw json.RawMessage) (string, error) { +func HiveType(raw jsontext.Value) (string, error) { var prim string - if err := json.Unmarshal(raw, &prim); err == nil { + if err := json.Unmarshal(raw, &prim, jsonx.V1()); err == nil { return hivePrimitive(prim) } var n nestedType - if err := json.Unmarshal(raw, &n); err != nil { + if err := json.Unmarshal(raw, &n, jsonx.V1()); err != nil { return "", fmt.Errorf("%w: %s", ErrUnsupportedType, raw) } @@ -105,9 +108,9 @@ func hivePrimitive(p string) (string, error) { } // PrimitiveName returns the primitive type name of a field type ("" for nested types). -func PrimitiveName(raw json.RawMessage) string { +func PrimitiveName(raw jsontext.Value) string { var prim string - if err := json.Unmarshal(raw, &prim); err != nil { + if err := json.Unmarshal(raw, &prim, jsonx.V1()); err != nil { return "" } @@ -176,7 +179,7 @@ func SchemaFromColumns(cols []ColumnSpec) (Schema, error) { return Schema{}, err } - raw, _ := json.Marshal(t) + raw, _ := json.Marshal(t, jsonx.V1()) fields = append(fields, Field{ID: i + 1, Name: c.Name, Type: raw, Doc: c.Comment}) } diff --git a/pkgs/idempotency/idempotency.go b/pkgs/idempotency/idempotency.go index 97cc663498..9d755b4792 100644 --- a/pkgs/idempotency/idempotency.go +++ b/pkgs/idempotency/idempotency.go @@ -3,11 +3,12 @@ package idempotency import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -64,7 +65,7 @@ func New(name string, opts ...Option) *Memo { // Fingerprint renders request parameters for comparison across retries. func Fingerprint(v any) string { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Sprintf("%+v", v) } diff --git a/pkgs/jsonx/jsonx.go b/pkgs/jsonx/jsonx.go new file mode 100644 index 0000000000..b3a9e4024f --- /dev/null +++ b/pkgs/jsonx/jsonx.go @@ -0,0 +1,147 @@ +// Package jsonx holds the shared option sets for encoding/json/v2 and the few +// helpers that have no 1:1 v2 equivalent. +// +// Every call site uses encoding/json/v2 and encoding/json/jsontext directly; +// V1 is passed so a mechanical swap from encoding/json keeps byte-identical +// wire output and error text (nil slices and maps as null, HTML escaping, +// case-insensitive member matching, tolerated duplicate names and invalid +// UTF-8, v1 error messages). Drop V1 per call only where the v2 default is +// wanted and verified. +// +// This is the only package allowed to import the v1 encoding/json package: +// DefaultOptionsV1 and the legacy-semantics options are exported from there. +// +// v1 to v2 mapping: +// +// json.Marshal(v) json.Marshal(v, jsonx.V1()) +// json.Unmarshal(b, &v) json.Unmarshal(b, &v, jsonx.V1()) +// json.MarshalIndent(v, p, i) json.Marshal(v, jsonx.V1(), jsontext.Multiline(true), +// jsontext.WithIndentPrefix(p), jsontext.WithIndent(i)) +// json.NewDecoder(r).Decode(&v) json.UnmarshalDecode(jsontext.NewDecoder(r), &v, jsonx.V1()) +// json.NewEncoder(w).Encode(v) json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), v) +// enc.SetIndent / SetEscapeHTML jsontext.Multiline, WithIndent, EscapeForHTML on NewEncoder +// dec.DisallowUnknownFields() json.RejectUnknownMembers(true) +// dec.UseNumber(), json.Number jsonx.UseNumber(), jsonx.Number +// json.RawMessage jsontext.Value +// json.Valid(b) jsontext.Value(b).IsValid(jsonx.V1()) +// json.Compact / Indent jsontext.Value.Compact / Indent +// json.Marshaler, Unmarshaler same names in v2 (MarshalJSON / UnmarshalJSON still honored) +// *json.SyntaxError *jsontext.SyntacticError +// *json.UnmarshalTypeError *json.SemanticError +// +// Use UnmarshalRead instead of UnmarshalDecode only when trailing data after +// the first value must be an error; v1 Decoder.Decode ignored it. +package jsonx + +import ( + jsonv1 "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" + "fmt" + "strconv" +) + +// V1 is the full option set that reproduces encoding/json v1 behavior. +func V1() json.Options { + return jsonv1.DefaultOptionsV1() +} + +// Number is a JSON number kept in its textual form, the v2 stand-in for +// v1 json.Number. It is produced for untyped numbers when UseNumber is set. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { return strconv.ParseFloat(string(n), 64) } + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } + +// MarshalJSON emits the number literal; an empty Number is 0 like v1. +func (n Number) MarshalJSON() ([]byte, error) { + if n == "" { + return []byte("0"), nil + } + + if !jsontext.Value(n).IsValid() || jsontext.Value(n).Kind() != '0' { + return nil, fmt.Errorf("json: invalid number literal %q", string(n)) + } + + return []byte(n), nil +} + +// UnmarshalJSON accepts a JSON number, or a string holding a valid number as v1 did. +func (n *Number) UnmarshalJSON(b []byte) error { + v := jsontext.Value(b) + + switch v.Kind() { + case '0': + *n = Number(b) + case '"': + s, err := jsontext.AppendUnquote(nil, b) + if err != nil { + return err + } + + if lit := jsontext.Value(s); !lit.IsValid() || lit.Kind() != '0' { + return fmt.Errorf("json: invalid number literal %q", string(s)) + } + + *n = Number(s) + case 'n': + default: + return fmt.Errorf("json: cannot unmarshal %s into Go value of type jsonx.Number", v.Kind()) + } + + return nil +} + +// UseNumber makes every untyped (any) JSON number decode as Number instead of +// float64, replacing v1 Decoder.UseNumber. +func UseNumber() json.Options { + return json.WithUnmarshalers(json.UnmarshalFromFunc(unmarshalAnyNumber)) +} + +func unmarshalAnyNumber(dec *jsontext.Decoder, v *any) error { + switch dec.PeekKind() { + case '0': + val, err := dec.ReadValue() + if err != nil { + return err + } + + *v = Number(val) + case '{': + var m map[string]any + if err := json.UnmarshalDecode(dec, &m, V1(), UseNumber()); err != nil { + return err + } + + *v = m + case '[': + var s []any + if err := json.UnmarshalDecode(dec, &s, V1(), UseNumber()); err != nil { + return err + } + + *v = s + default: + tok, err := dec.ReadToken() + if err != nil { + return err + } + + switch tok.Kind() { + case 'n': + *v = nil + case 't', 'f': + *v = tok.Bool() + default: + *v = tok.String() + } + } + + return nil +} diff --git a/pkgs/jsonx/jsonx_test.go b/pkgs/jsonx/jsonx_test.go new file mode 100644 index 0000000000..34af9c09cc --- /dev/null +++ b/pkgs/jsonx/jsonx_test.go @@ -0,0 +1,109 @@ +package jsonx_test + +import ( + "encoding/json/jsontext" + "encoding/json/v2" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) + +func TestV1Semantics(t *testing.T) { + t.Parallel() + + type in struct { + S []int `json:"s"` + M map[string]int `json:"m"` + H string `json:"h"` + } + + b, err := json.Marshal(in{H: "<&>"}, jsonx.V1()) + require.NoError(t, err) + assert.JSONEq(t, `{"s":null,"m":null,"h":"<&>"}`, string(b)) + assert.Contains(t, string(b), "\\u003c") + + var out in + + require.NoError(t, json.Unmarshal([]byte(`{"S":[1],"H":"x","dup":1,"dup":2}`), &out, jsonx.V1())) + assert.Equal(t, []int{1}, out.S) + assert.Equal(t, "x", out.H) + + err = json.Unmarshal([]byte(`{"s":`), &out, jsonx.V1()) + require.EqualError(t, err, "unexpected end of JSON input") +} + +func TestUseNumber(t *testing.T) { + t.Parallel() + + var got any + + err := json.Unmarshal([]byte(`{"a":1.50,"b":[2,"x",true,null,{"c":3}],"d":"s"}`), &got, jsonx.V1(), jsonx.UseNumber()) + require.NoError(t, err) + + m, ok := got.(map[string]any) + require.True(t, ok) + assert.Equal(t, jsonx.Number("1.50"), m["a"]) + assert.Equal(t, "s", m["d"]) + assert.Equal(t, []any{jsonx.Number("2"), "x", true, nil, map[string]any{"c": jsonx.Number("3")}}, m["b"]) + + var typed struct{ N int } + + require.NoError(t, json.Unmarshal([]byte(`{"N":7}`), &typed, jsonx.V1(), jsonx.UseNumber())) + assert.Equal(t, 7, typed.N) +} + +func TestNumber(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + in string + want string + wantErr bool + }{ + {name: "number", in: `12.5`, want: "12.5"}, + {name: "quoted number", in: `"7"`, want: "7"}, + {name: "quoted junk", in: `"x"`, wantErr: true}, + {name: "bool", in: `true`, wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + var n jsonx.Number + + err := json.Unmarshal([]byte(tt.in), &n, jsonx.V1()) + if tt.wantErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + assert.Equal(t, tt.want, n.String()) + + out, err := json.Marshal(n, jsonx.V1()) + require.NoError(t, err) + assert.Equal(t, tt.want, string(out)) + }) + } + + out, err := json.Marshal(jsonx.Number(""), jsonx.V1()) + require.NoError(t, err) + assert.Equal(t, "0", string(out)) +} + +func TestDecoderStreamTolerantOfTrailingData(t *testing.T) { + t.Parallel() + + var v map[string]int + + dec := jsontext.NewDecoder(strings.NewReader(`{"a":1} trailing`)) + require.NoError(t, json.UnmarshalDecode(dec, &v, jsonx.V1())) + assert.Equal(t, map[string]int{"a": 1}, v) +} diff --git a/pkgs/jsruntime/convert.go b/pkgs/jsruntime/convert.go index 0fb0f7be5c..1ffb658642 100644 --- a/pkgs/jsruntime/convert.go +++ b/pkgs/jsruntime/convert.go @@ -1,11 +1,13 @@ package jsruntime import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "github.com/dop251/goja" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrNotJSON means a value could not be converted to or from JSON. @@ -13,7 +15,7 @@ var ErrNotJSON = errors.New("value is not JSON-serializable") // ToJS builds a fresh JS value from plain Go data via JSON.parse. func (s *Sandbox) ToJS(v any) (goja.Value, error) { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: %w", ErrNotJSON, err) } @@ -56,7 +58,7 @@ func (s *Sandbox) FromJS(v goja.Value) (any, error) { } var out any - if err = json.Unmarshal([]byte(str), &out); err != nil { + if err = json.Unmarshal([]byte(str), &out, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrNotJSON, err) } diff --git a/pkgs/ociregistry/client.go b/pkgs/ociregistry/client.go index 1acc9e8f7f..c2a15a2d2f 100644 --- a/pkgs/ociregistry/client.go +++ b/pkgs/ociregistry/client.go @@ -3,13 +3,15 @@ package ociregistry import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" "net/http" "net/url" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrNotFound is returned when a repository, manifest or blob does not exist. @@ -140,7 +142,7 @@ func (c Client) pages(ctx context.Context, base string, pick func(listResponse) } var lr listResponse - if err = json.Unmarshal(rec.body.Bytes(), &lr); err != nil { + if err = json.Unmarshal(rec.body.Bytes(), &lr, jsonx.V1()); err != nil { return nil, fmt.Errorf("ociregistry: decode list: %w", err) } diff --git a/pkgs/ociregistry/describe.go b/pkgs/ociregistry/describe.go index 34ef8ad382..4cfaeae79c 100644 --- a/pkgs/ociregistry/describe.go +++ b/pkgs/ociregistry/describe.go @@ -2,8 +2,10 @@ package ociregistry import ( "context" - "encoding/json" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxConfigBytes = 1 << 20 @@ -44,7 +46,7 @@ func (c Client) Describe(ctx context.Context, repo string, m Manifest) Info { info := Info{Digest: m.Digest, MediaType: m.MediaType} var doc manifestDoc - if json.Unmarshal(m.Body, &doc) != nil { + if json.Unmarshal(m.Body, &doc, jsonx.V1()) != nil { return info } @@ -85,7 +87,7 @@ func (c Client) platform(ctx context.Context, repo, configDigest string) (string OS string `json:"os"` } - if json.Unmarshal(raw, &cfg) != nil { + if json.Unmarshal(raw, &cfg, jsonx.V1()) != nil { return "", "" } diff --git a/pkgs/ociregistry/ocitest/ocitest.go b/pkgs/ociregistry/ocitest/ocitest.go index 48bdc3f699..e0a7df4eb1 100644 --- a/pkgs/ociregistry/ocitest/ocitest.go +++ b/pkgs/ociregistry/ocitest/ocitest.go @@ -6,7 +6,8 @@ import ( "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -20,6 +21,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -174,7 +176,7 @@ func (c Client) PushImage(repo, tag string) Image { cfg, err := json.Marshal(map[string]any{ "architecture": "amd64", "os": "linux", "rootfs": map[string]any{"type": "layers", "diff_ids": []string{layerDigest}}, - }) + }, jsonx.V1()) require.NoError(c.T, err) cfgDigest := c.PushBlob(repo, cfg, configChunks) @@ -188,7 +190,7 @@ func (c Client) PushImage(repo, tag string) Image { keyMediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": len(layer), "digest": layerDigest, }}, - }) + }, jsonx.V1()) require.NoError(c.T, err) put := c.Do( @@ -215,11 +217,11 @@ func (c Client) Names(path, field string, n int) []string { resp := c.Do(http.MethodGet, next, nil, nil) require.Equal(c.T, http.StatusOK, resp.Status, string(resp.Body)) - var doc map[string]json.RawMessage - require.NoError(c.T, json.Unmarshal(resp.Body, &doc)) + var doc map[string]jsontext.Value + require.NoError(c.T, json.Unmarshal(resp.Body, &doc, jsonx.V1())) var page []string - require.NoError(c.T, json.Unmarshal(doc[field], &page)) + require.NoError(c.T, json.Unmarshal(doc[field], &page, jsonx.V1())) all = append(all, page...) diff --git a/pkgs/odatatable/batchwire.go b/pkgs/odatatable/batchwire.go index 267c8e62a0..d0be53c09c 100644 --- a/pkgs/odatatable/batchwire.go +++ b/pkgs/odatatable/batchwire.go @@ -2,7 +2,7 @@ package odatatable import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -12,6 +12,8 @@ import ( "net/url" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -456,5 +458,5 @@ func FailureBody(index int, f BatchFailure, requestID, timestamp string) ([]byte env.Error.Message.Lang = "en-US" env.Error.Message.Value = fmt.Sprintf("%d:%s\nRequestId:%s\nTime:%s", index, f.Message, requestID, timestamp) - return json.Marshal(env) + return json.Marshal(env, jsonx.V1()) } diff --git a/pkgs/odatatable/codec.go b/pkgs/odatatable/codec.go index c5bd574d8d..93f5c15b67 100644 --- a/pkgs/odatatable/codec.go +++ b/pkgs/odatatable/codec.go @@ -2,12 +2,15 @@ package odatatable import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // OData metadata level names, negotiated by each caller from its own @@ -66,9 +69,9 @@ func ParseTop(raw string) (int, error) { // supplied value never overwrites it -- the server always wins). Any // "odata.*"/"@odata.type" metadata key is skipped. func DecodeEntityBody(body []byte) (string, string, bool, bool, map[string]EntityProperty, error) { - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value - if err := json.Unmarshal(body, &raw); err != nil { + if err := json.Unmarshal(body, &raw, jsonx.V1()); err != nil { return "", "", false, false, nil, fmt.Errorf("%w: %w", ErrInvalidEntityProperty, err) } @@ -92,14 +95,14 @@ func DecodeEntityBody(body []byte) (string, string, bool, bool, map[string]Entit // decodeSystemKeyProperty extracts the string-valued system property name // (PartitionKey or RowKey) from raw, if present. -func decodeSystemKeyProperty(raw map[string]json.RawMessage, name string) (string, bool, error) { +func decodeSystemKeyProperty(raw map[string]jsontext.Value, name string) (string, bool, error) { rawVal, ok := raw[name] if !ok { return "", false, nil } var s string - if err := json.Unmarshal(rawVal, &s); err != nil { + if err := json.Unmarshal(rawVal, &s, jsonx.V1()); err != nil { return "", false, fmt.Errorf("%w: %s must be a string", ErrInvalidEntityProperty, name) } @@ -125,7 +128,7 @@ func isSystemOrMetadataKey(key string) bool { // decodeCustomProperties decodes every user-defined (non-system, // non-metadata) property in raw into its typed EntityProperty. -func decodeCustomProperties(raw map[string]json.RawMessage) (map[string]EntityProperty, error) { +func decodeCustomProperties(raw map[string]jsontext.Value) (map[string]EntityProperty, error) { props := make(map[string]EntityProperty, len(raw)) for key, rawVal := range raw { @@ -136,7 +139,7 @@ func decodeCustomProperties(raw map[string]json.RawMessage) (map[string]EntityPr edmType := "" if annRaw, ok := raw[key+"@odata.type"]; ok { - if err := json.Unmarshal(annRaw, &edmType); err != nil { + if err := json.Unmarshal(annRaw, &edmType, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: malformed %s@odata.type", ErrInvalidEntityProperty, key) } } @@ -154,7 +157,7 @@ func decodeCustomProperties(raw map[string]json.RawMessage) (map[string]EntityPr // decodeProperty decodes raw into a typed EntityProperty per its (possibly // empty) "@odata.type" annotation value edmType. -func decodeProperty(edmType string, raw json.RawMessage) (EntityProperty, error) { +func decodeProperty(edmType string, raw jsontext.Value) (EntityProperty, error) { switch EdmType(edmType) { case EdmString, EdmInt32, EdmDouble, EdmBoolean: return decodeScalarProperty(EdmType(edmType), raw) @@ -169,32 +172,32 @@ func decodeProperty(edmType string, raw json.RawMessage) (EntityProperty, error) // decodeScalarProperty decodes the four EDM types whose wire representation // is a bare, natively-typed JSON value (string/number/number/bool). -func decodeScalarProperty(edmType EdmType, raw json.RawMessage) (EntityProperty, error) { +func decodeScalarProperty(edmType EdmType, raw jsontext.Value) (EntityProperty, error) { switch edmType { case EdmString: var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return EntityProperty{}, fmt.Errorf("%w: not a string", ErrInvalidEntityProperty) } return EntityProperty{Type: EdmString, Value: s}, nil case EdmInt32: var n int32 - if err := json.Unmarshal(raw, &n); err != nil { + if err := json.Unmarshal(raw, &n, jsonx.V1()); err != nil { return EntityProperty{}, fmt.Errorf("%w: not an Int32", ErrInvalidEntityProperty) } return EntityProperty{Type: EdmInt32, Value: n}, nil case EdmDouble: var f float64 - if err := json.Unmarshal(raw, &f); err != nil { + if err := json.Unmarshal(raw, &f, jsonx.V1()); err != nil { return EntityProperty{}, fmt.Errorf("%w: not a Double", ErrInvalidEntityProperty) } return EntityProperty{Type: EdmDouble, Value: f}, nil case EdmBoolean: var b bool - if err := json.Unmarshal(raw, &b); err != nil { + if err := json.Unmarshal(raw, &b, jsonx.V1()); err != nil { return EntityProperty{}, fmt.Errorf("%w: not a Boolean", ErrInvalidEntityProperty) } @@ -208,9 +211,9 @@ func decodeScalarProperty(edmType EdmType, raw json.RawMessage) (EntityProperty, // representation is always a JSON string carrying an encoded value (decimal // digits, an RFC3339 timestamp, a UUID, or base64), requiring the // "@odata.type" annotation to disambiguate from Edm.String. -func decodeStringEncodedProperty(edmType EdmType, raw json.RawMessage) (EntityProperty, error) { +func decodeStringEncodedProperty(edmType EdmType, raw jsontext.Value) (EntityProperty, error) { var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return EntityProperty{}, fmt.Errorf("%w: %s must be a string", ErrInvalidEntityProperty, edmType) } @@ -247,24 +250,24 @@ func decodeStringEncodedProperty(edmType EdmType, raw json.RawMessage) (EntityPr // mirroring aztables' own client-side inference exactly: try Int32 first // (so a decimal-point-free number becomes Edm.Int32), then fall back to the // JSON value's natural Go type. -func decodeUnannotatedProperty(raw json.RawMessage) (EntityProperty, error) { +func decodeUnannotatedProperty(raw jsontext.Value) (EntityProperty, error) { var i32 int32 - if err := json.Unmarshal(raw, &i32); err == nil { + if err := json.Unmarshal(raw, &i32, jsonx.V1()); err == nil { return EntityProperty{Type: EdmInt32, Value: i32}, nil } var f float64 - if err := json.Unmarshal(raw, &f); err == nil { + if err := json.Unmarshal(raw, &f, jsonx.V1()); err == nil { return EntityProperty{Type: EdmDouble, Value: f}, nil } var b bool - if err := json.Unmarshal(raw, &b); err == nil { + if err := json.Unmarshal(raw, &b, jsonx.V1()); err == nil { return EntityProperty{Type: EdmBoolean, Value: b}, nil } var s string - if err := json.Unmarshal(raw, &s); err == nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err == nil { return EntityProperty{Type: EdmString, Value: s}, nil } diff --git a/pkgs/odatatable/models.go b/pkgs/odatatable/models.go index 88040ae50d..99dfea3fd9 100644 --- a/pkgs/odatatable/models.go +++ b/pkgs/odatatable/models.go @@ -19,12 +19,14 @@ package odatatable import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "math" "strconv" "sync/atomic" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // System entity property names, shared across path-predicate parsing @@ -106,7 +108,7 @@ func (p EntityProperty) MarshalJSON() ([]byte, error) { return nil, err } - return json.Marshal(entityPropertyWire{Type: p.Type, Value: v}) + return json.Marshal(entityPropertyWire{Type: p.Type, Value: v}, jsonx.V1()) } // marshalValue dispatches to marshalScalarValue or marshalStringEncodedValue @@ -219,7 +221,7 @@ func (p EntityProperty) marshalStringEncodedValue() (any, error) { func (p *EntityProperty) UnmarshalJSON(data []byte) error { var wire entityPropertyWire - if err := json.Unmarshal(data, &wire); err != nil { + if err := json.Unmarshal(data, &wire, jsonx.V1()); err != nil { return err } @@ -428,7 +430,7 @@ const entityCompositeKeyElemCount = 2 // encoding can't reintroduce the same collision class the struct key itself // was introduced to close. func (k entityCompositeKey) MarshalText() ([]byte, error) { - return json.Marshal([entityCompositeKeyElemCount]string{k.PartitionKey, k.RowKey}) + return json.Marshal([entityCompositeKeyElemCount]string{k.PartitionKey, k.RowKey}, jsonx.V1()) } // UnmarshalText implements encoding.TextUnmarshaler, the inverse of @@ -442,7 +444,7 @@ func (k *entityCompositeKey) UnmarshalText(text []byte) error { // two elements". var pair []string - if err := json.Unmarshal(text, &pair); err != nil { + if err := json.Unmarshal(text, &pair, jsonx.V1()); err != nil { return fmt.Errorf("odatatable: malformed entity composite key %q: %w", text, err) } diff --git a/pkgs/persistence/manager_test.go b/pkgs/persistence/manager_test.go index 3506b97446..eca03bf1af 100644 --- a/pkgs/persistence/manager_test.go +++ b/pkgs/persistence/manager_test.go @@ -2,7 +2,7 @@ package persistence_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "sync" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -821,7 +822,7 @@ func (s *statefulPersistable) Restore(_ context.Context, data []byte) error { State string `json:"state"` } - if err := json.Unmarshal(data, &v); err != nil { + if err := json.Unmarshal(data, &v, jsonx.V1()); err != nil { return err } diff --git a/pkgs/persistence/modes_test.go b/pkgs/persistence/modes_test.go index 9d3c241e8e..4463e18cea 100644 --- a/pkgs/persistence/modes_test.go +++ b/pkgs/persistence/modes_test.go @@ -2,7 +2,7 @@ package persistence_test import ( "context" - "encoding/json" + "encoding/json/v2" "path/filepath" "sync" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -40,7 +41,7 @@ func (c *counterSvc) Snapshot(context.Context) []byte { c.mu.Lock() defer c.mu.Unlock() - b, _ := json.Marshal(c.vals) + b, _ := json.Marshal(c.vals, jsonx.V1()) return b } @@ -49,7 +50,7 @@ func (c *counterSvc) Restore(_ context.Context, data []byte) error { c.mu.Lock() defer c.mu.Unlock() - return json.Unmarshal(data, &c.vals) + return json.Unmarshal(data, &c.vals, jsonx.V1()) } func newMgr( diff --git a/pkgs/persistence/snapshot.go b/pkgs/persistence/snapshot.go index aa56ce56c9..968e7be6f9 100644 --- a/pkgs/persistence/snapshot.go +++ b/pkgs/persistence/snapshot.go @@ -2,8 +2,9 @@ package persistence import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -15,7 +16,7 @@ import ( // persistence Manager). Centralising this here keeps every backend's Snapshot // method consistent and gives the ctx parameter a purpose. func MarshalSnapshot(ctx context.Context, service string, v any) []byte { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "persistence: snapshot marshal failed", @@ -37,7 +38,7 @@ func MarshalSnapshot(ctx context.Context, service string, v any) []byte { // the decode error. Centralising this here keeps every backend's Restore method // consistent and gives the ctx parameter a purpose. func UnmarshalSnapshot(ctx context.Context, service string, data []byte, v any) error { - if err := json.Unmarshal(data, v); err != nil { + if err := json.Unmarshal(data, v, jsonx.V1()); err != nil { logger.Load(ctx).WarnContext(ctx, "persistence: snapshot unmarshal failed", "service", service, "error", err) diff --git a/pkgs/persistence/snapshotversion_guard_test.go b/pkgs/persistence/snapshotversion_guard_test.go index 16adc151e8..7997b7e934 100644 --- a/pkgs/persistence/snapshotversion_guard_test.go +++ b/pkgs/persistence/snapshotversion_guard_test.go @@ -2,7 +2,8 @@ package persistence_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "flag" "fmt" @@ -20,6 +21,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errNoVersionStruct = errors.New("no struct with an int-typed Version field") @@ -480,7 +483,7 @@ func loadGolden(t *testing.T) map[string]snapshotInfo { var golden map[string]snapshotInfo - require.NoError(t, json.Unmarshal(data, &golden)) + require.NoError(t, json.Unmarshal(data, &golden, jsonx.V1())) return golden } @@ -488,7 +491,7 @@ func loadGolden(t *testing.T) map[string]snapshotInfo { func writeGolden(t *testing.T, live map[string]snapshotInfo) { t.Helper() - data, err := json.MarshalIndent(live, "", " ") + data, err := json.Marshal(live, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) require.NoError(t, err) require.NoError(t, os.WriteFile(goldenFile, append(data, '\n'), 0o644)) diff --git a/pkgs/persistence/store_test.go b/pkgs/persistence/store_test.go index 0c3a091fc4..f3361ea76f 100644 --- a/pkgs/persistence/store_test.go +++ b/pkgs/persistence/store_test.go @@ -1,7 +1,7 @@ package persistence_test import ( - "encoding/json" + "encoding/json/v2" "os" "path/filepath" "sync" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -220,7 +221,7 @@ func TestFileStore_ConcurrentAccess(t *testing.T) { go func(i int) { defer wg.Done() - data, _ := json.Marshal(map[string]int{"i": i}) + data, _ := json.Marshal(map[string]int{"i": i}, jsonx.V1()) if err := s.Save("concurrent", "snap", data); err != nil { errs <- err } @@ -239,7 +240,7 @@ func TestFileStore_ConcurrentAccess(t *testing.T) { require.NoError(t, err) var out map[string]int - require.NoError(t, json.Unmarshal(data, &out)) + require.NoError(t, json.Unmarshal(data, &out, jsonx.V1())) assert.Contains(t, out, "i") } diff --git a/pkgs/pods/merge.go b/pkgs/pods/merge.go index 6cb37536c5..31417784a9 100644 --- a/pkgs/pods/merge.go +++ b/pkgs/pods/merge.go @@ -2,8 +2,11 @@ package pods import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type scopeKey struct{ account, region string } @@ -107,11 +110,10 @@ func mergeValue(cur, inc any, scopes map[scopeKey]bool) any { } func decodeJSON(raw []byte) (any, error) { - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fmt.Errorf("%w: %w", ErrCorrupt, err) } @@ -140,7 +142,7 @@ func MergeScoped(current, incoming []byte) ([]byte, bool, error) { return nil, false, err } - merged, err := json.Marshal(mergeValue(cur, inc, scopes)) + merged, err := json.Marshal(mergeValue(cur, inc, scopes), jsonx.V1()) if err != nil { return nil, false, fmt.Errorf("marshal merged snapshot: %w", err) } diff --git a/pkgs/pods/pods.go b/pkgs/pods/pods.go index 9fdcf4e60b..aed1579b57 100644 --- a/pkgs/pods/pods.go +++ b/pkgs/pods/pods.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -156,7 +157,7 @@ func (s *Service) Save(ctx context.Context, name, message string, snaps map[stri m.Size = int64(len(archive)) - meta, err := json.Marshal(m) + meta, err := json.Marshal(m, jsonx.V1()) if err != nil { return Manifest{}, fmt.Errorf("marshal manifest: %w", err) } @@ -179,7 +180,7 @@ func buildArchive(m *Manifest, snaps map[string][]byte) ([]byte, error) { zw := zip.NewWriter(&buf) - meta, err := json.Marshal(m) + meta, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal manifest: %w", err) } @@ -262,7 +263,7 @@ func (s *Service) readManifest(ctx context.Context, name string, v int) (Manifes } var m Manifest - if err = json.Unmarshal(raw, &m); err != nil { + if err = json.Unmarshal(raw, &m, jsonx.V1()); err != nil { return Manifest{}, fmt.Errorf("%w: manifest: %w", ErrCorrupt, err) } diff --git a/pkgs/regionpeers/regionpeers.go b/pkgs/regionpeers/regionpeers.go index 24bb98a5fd..aede357921 100644 --- a/pkgs/regionpeers/regionpeers.go +++ b/pkgs/regionpeers/regionpeers.go @@ -3,11 +3,14 @@ package regionpeers import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "regexp" "slices" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -113,7 +116,7 @@ func (s *Set[T]) Snapshot(base []byte, snap func(*T) []byte) []byte { } s.mu.Lock() - regions := make(map[string]json.RawMessage, len(s.peers)) + regions := make(map[string]jsontext.Value, len(s.peers)) for r, p := range s.peers { if data := snap(p); data != nil { @@ -126,19 +129,19 @@ func (s *Set[T]) Snapshot(base []byte, snap func(*T) []byte) []byte { return base } - doc := make(map[string]json.RawMessage) - if err := json.Unmarshal(base, &doc); err != nil { + doc := make(map[string]jsontext.Value) + if err := json.Unmarshal(base, &doc, jsonx.V1()); err != nil { return base } - enc, err := json.Marshal(regions) + enc, err := json.Marshal(regions, jsonx.V1()) if err != nil { return base } doc[snapshotKey] = enc - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return base } @@ -158,10 +161,10 @@ func (s *Set[T]) Restore(data []byte, restore func(*T, []byte) error, closeFn fu } var doc struct { - Regions map[string]json.RawMessage `json:"regions"` + Regions map[string]jsontext.Value `json:"regions"` } - if err := json.Unmarshal(data, &doc); err != nil { + if err := json.Unmarshal(data, &doc, jsonx.V1()); err != nil { return err } diff --git a/pkgs/regionpeers/regionpeers_test.go b/pkgs/regionpeers/regionpeers_test.go index a367068151..42b3567184 100644 --- a/pkgs/regionpeers/regionpeers_test.go +++ b/pkgs/regionpeers/regionpeers_test.go @@ -1,13 +1,14 @@ package regionpeers_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" ) @@ -57,7 +58,7 @@ func TestSet_SnapshotRestore(t *testing.T) { t.Parallel() snap := func(p *fake) []byte { return []byte(`"` + p.state + `"`) } - restore := func(p *fake, d []byte) error { return json.Unmarshal(d, &p.state) } + restore := func(p *fake, d []byte) error { return json.Unmarshal(d, &p.state, jsonx.V1()) } closeFn := func(*fake) {} tests := []struct { diff --git a/pkgs/registryauth/dockerconfig.go b/pkgs/registryauth/dockerconfig.go index 75d94f0d50..60c491cdcc 100644 --- a/pkgs/registryauth/dockerconfig.go +++ b/pkgs/registryauth/dockerconfig.go @@ -4,13 +4,15 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "os" "os/exec" "path/filepath" "regexp" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const helperTimeout = 15 * time.Second @@ -63,7 +65,7 @@ func loadDockerConfig() *dockerConfig { } var cfg dockerConfig - if json.Unmarshal(data, &cfg) != nil { + if json.Unmarshal(data, &cfg, jsonx.V1()) != nil { return nil } @@ -157,7 +159,7 @@ func runHelper(ctx context.Context, name, host string) (authConfig, bool) { } var rep helperReply - if json.Unmarshal(out.Bytes(), &rep) != nil || rep.Secret == "" { + if json.Unmarshal(out.Bytes(), &rep, jsonx.V1()) != nil || rep.Secret == "" { return authConfig{}, false } diff --git a/pkgs/registryauth/resolver.go b/pkgs/registryauth/resolver.go index d2922193e7..0e8a6cc3f8 100644 --- a/pkgs/registryauth/resolver.go +++ b/pkgs/registryauth/resolver.go @@ -3,10 +3,11 @@ package registryauth import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "log/slog" "sync" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -49,7 +50,7 @@ func (r *Resolver) RegisterEmulated(host, user, pass string) { } func encodeAuth(ac authConfig) string { - raw, err := json.Marshal(ac) //nolint:gosec // credentials are the payload of the X-Registry-Auth header + raw, err := json.Marshal(ac, jsonx.V1()) //nolint:gosec // credentials are the payload of the X-Registry-Auth header if err != nil { return "" } diff --git a/pkgs/registryauth/resolver_test.go b/pkgs/registryauth/resolver_test.go index 49ea6e39ba..dd5125eb2b 100644 --- a/pkgs/registryauth/resolver_test.go +++ b/pkgs/registryauth/resolver_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "log/slog" "os" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/registryauth" ) @@ -50,7 +51,7 @@ func decode(t *testing.T, enc string) map[string]string { require.NoError(t, err) m := map[string]string{} - require.NoError(t, json.Unmarshal(raw, &m)) + require.NoError(t, json.Unmarshal(raw, &m, jsonx.V1())) return m } diff --git a/pkgs/restroute/restroute_test.go b/pkgs/restroute/restroute_test.go index 64ebc486a2..a7d0bb18e4 100644 --- a/pkgs/restroute/restroute_test.go +++ b/pkgs/restroute/restroute_test.go @@ -2,7 +2,7 @@ package restroute_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -215,7 +216,7 @@ func TestServerDispatchAndErrors(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Header().Get("X-Amzn-Errortype")) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) if tt.wantCode != "" { assert.NotEmpty(t, body["message"]) @@ -242,7 +243,7 @@ func TestErrorMessageDropsRepeatedCode(t *testing.T) { ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "cell is busy", body["message"]) assert.Equal(t, "R", body["reason"]) } diff --git a/pkgs/restroute/serve.go b/pkgs/restroute/serve.go index 90530ecdde..910693fd37 100644 --- a/pkgs/restroute/serve.go +++ b/pkgs/restroute/serve.go @@ -2,7 +2,7 @@ package restroute import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Error is an AWS REST-JSON exception: HTTP status, error code, message and optional extra body members. @@ -61,7 +62,7 @@ func (r *Request) Decode(v any) error { return nil } - if err := json.Unmarshal(r.Body, v); err != nil { + if err := json.Unmarshal(r.Body, v, jsonx.V1()); err != nil { return Validation("request body is not valid JSON for this operation") } diff --git a/pkgs/service/cbor.go b/pkgs/service/cbor.go index 1726e3ec43..91e29e1b0f 100644 --- a/pkgs/service/cbor.go +++ b/pkgs/service/cbor.go @@ -2,7 +2,7 @@ package service import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "math" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/aws/smithy-go/encoding/cbor" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ContentTypeCBOR is the AWS CBOR wire protocol content type used by DynamoDB, Kinesis, and Timestream. @@ -39,7 +40,7 @@ func CBORToJSON(data []byte) ([]byte, error) { generic := cborToInterface(val) - out, err := json.Marshal(generic) + out, err := json.Marshal(generic, jsonx.V1()) if err != nil { return nil, fmt.Errorf("json marshal: %w", err) } @@ -58,7 +59,7 @@ func CBORToJSON(data []byte) ([]byte, error) { // produces a CBOR list of byte strings when "BS" is in binaryKeys. func JSONToCBOR(data []byte, binaryKeys map[string]bool) ([]byte, error) { var generic any - if err := json.Unmarshal(data, &generic); err != nil { + if err := json.Unmarshal(data, &generic, jsonx.V1()); err != nil { return nil, fmt.Errorf("json unmarshal: %w", err) } diff --git a/pkgs/service/cbor_test.go b/pkgs/service/cbor_test.go index 603e4bd699..6f9f9e9cee 100644 --- a/pkgs/service/cbor_test.go +++ b/pkgs/service/cbor_test.go @@ -2,7 +2,7 @@ package service_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/aws/smithy-go/encoding/cbor" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -109,7 +110,7 @@ func TestCBORToJSON(t *testing.T) { } var got map[string]any - if err := json.Unmarshal(jsonBytes, &got); err != nil { + if err := json.Unmarshal(jsonBytes, &got, jsonx.V1()); err != nil { t.Fatalf("unmarshal result: %v", err) } @@ -290,15 +291,15 @@ func TestCBORRoundTrip(t *testing.T) { } var orig, got map[string]any - if e := json.Unmarshal([]byte(tc.args.jsonInput), &orig); e != nil { + if e := json.Unmarshal([]byte(tc.args.jsonInput), &orig, jsonx.V1()); e != nil { t.Fatalf("unmarshal orig: %v", e) } - if e := json.Unmarshal(jsonOut, &got); e != nil { + if e := json.Unmarshal(jsonOut, &got, jsonx.V1()); e != nil { t.Fatalf("unmarshal got: %v", e) } - origJSON, _ := json.Marshal(orig) - gotJSON, _ := json.Marshal(got) + origJSON, _ := json.Marshal(orig, jsonx.V1()) + gotJSON, _ := json.Marshal(got, jsonx.V1()) if string(origJSON) != string(gotJSON) { t.Errorf("round-trip mismatch:\n orig: %s\n got: %s", origJSON, gotJSON) @@ -359,7 +360,7 @@ func TestCBORBinaryRoundTrip(t *testing.T) { } var jsonMap map[string]any - if err = json.Unmarshal(jsonBytes, &jsonMap); err != nil { + if err = json.Unmarshal(jsonBytes, &jsonMap, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } diff --git a/pkgs/service/cloudtrail_capture.go b/pkgs/service/cloudtrail_capture.go index adaacc7b3d..19973e0beb 100644 --- a/pkgs/service/cloudtrail_capture.go +++ b/pkgs/service/cloudtrail_capture.go @@ -2,7 +2,7 @@ package service import ( "bytes" - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // minCredentialParts is the minimum number of slash-delimited fields in an AWS @@ -275,7 +276,7 @@ func extractErrorInfo(status int, body []byte) (string, string) { func extractJSONErrorInfo(body []byte) (string, string) { var env jsonErrorEnvelope - if err := json.Unmarshal(body, &env); err != nil { + if err := json.Unmarshal(body, &env, jsonx.V1()); err != nil { return "", "" } diff --git a/pkgs/service/json_error_message.go b/pkgs/service/json_error_message.go index 72351eedfb..335affa963 100644 --- a/pkgs/service/json_error_message.go +++ b/pkgs/service/json_error_message.go @@ -2,7 +2,8 @@ package service import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "hash/crc32" "io" "net/http" @@ -10,6 +11,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSONErrorMessageMiddleware mirrors a lone "message" or "Message" key in JSON @@ -92,8 +95,8 @@ func (w *jsonErrorMirrorWriter) flush() { } func mirrorMessageKey(body []byte) []byte { - var obj map[string]json.RawMessage - if err := json.Unmarshal(body, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(body, &obj, jsonx.V1()); err != nil { return body } @@ -115,7 +118,7 @@ func mirrorMessageKey(body []byte) []byte { obj["message"] = upper } - out, err := json.Marshal(obj) + out, err := json.Marshal(obj, jsonx.V1()) if err != nil { return body } diff --git a/pkgs/service/jsondisp.go b/pkgs/service/jsondisp.go index 6dbb8916d1..e6b85b885a 100644 --- a/pkgs/service/jsondisp.go +++ b/pkgs/service/jsondisp.go @@ -2,7 +2,7 @@ package service import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSONErrorResponse is the standard JSON error envelope for AWS JSON-protocol services. @@ -34,7 +35,7 @@ func (r JSONErrorResponse) MarshalJSON() ([]byte, error) { Type string `json:"__type"` Message string `json:"message"` MessageCap string `json:"Message"` - }{r.Type, r.Message, r.Message}) + }{r.Type, r.Message, r.Message}, jsonx.V1()) } // DispatchFunc is the signature for service-specific action dispatch functions. @@ -57,7 +58,7 @@ func HandleJSON[In, Out any]( var input In if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } @@ -146,7 +147,7 @@ func HandleTarget( func writeDispatchError(c *echo.Context, contentType string, status int, errType, message string) error { c.Response().Header().Set("Content-Type", contentType) - payload, err := json.Marshal(JSONErrorResponse{Type: errType, Message: message}) + payload, err := json.Marshal(JSONErrorResponse{Type: errType, Message: message}, jsonx.V1()) if err != nil { return err } diff --git a/pkgs/service/regions.go b/pkgs/service/regions.go index a131bb1d8d..dcbe94d3cf 100644 --- a/pkgs/service/regions.go +++ b/pkgs/service/regions.go @@ -1,12 +1,13 @@ package service import ( - "encoding/json" + "encoding/json/v2" "sort" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" ) @@ -94,7 +95,7 @@ func SnapshotKnownRegions() []byte { return nil } - data, err := json.Marshal(regions) + data, err := json.Marshal(regions, jsonx.V1()) if err != nil { return nil } @@ -107,7 +108,7 @@ func SnapshotKnownRegions() []byte { // backfill, not a correctness-critical load. func RestoreKnownRegions(data []byte) { var regions []string - if err := json.Unmarshal(data, ®ions); err != nil { + if err := json.Unmarshal(data, ®ions, jsonx.V1()); err != nil { return } diff --git a/pkgs/service/restdispatch.go b/pkgs/service/restdispatch.go index 97fa5dcbc7..0ef6d606f3 100644 --- a/pkgs/service/restdispatch.go +++ b/pkgs/service/restdispatch.go @@ -2,12 +2,13 @@ package service import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -95,7 +96,7 @@ func (r RESTRouter) handleREST(c *echo.Context) error { return c.JSON(statusCode, struct{}{}) } - data, jsonErr := json.Marshal(result) + data, jsonErr := json.Marshal(result, jsonx.V1()) if jsonErr != nil { return c.JSON(http.StatusInternalServerError, r.InternalErrorBody()) } diff --git a/pkgs/service/rpcv2cbor_bridge.go b/pkgs/service/rpcv2cbor_bridge.go index 614b300ccc..03688baf14 100644 --- a/pkgs/service/rpcv2cbor_bridge.go +++ b/pkgs/service/rpcv2cbor_bridge.go @@ -3,7 +3,8 @@ package service import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "strconv" @@ -13,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -122,11 +124,10 @@ func (b RPCv2CBORBridge) jsonToRPCv2CBOR(body []byte) ([]byte, error) { return cbor.Encode(cbor.Map{}), nil } - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, err } @@ -159,14 +160,14 @@ func (b RPCv2CBORBridge) anyToCBOR(v any, key string) cbor.Value { return cbor.String(t) case bool: return cbor.Bool(t) - case json.Number: + case jsonx.Number: return jsonNumberToCBOR(t, b.TimeKeys[key]) default: return &cbor.Nil{} } } -func jsonNumberToCBOR(n json.Number, timestamp bool) cbor.Value { +func jsonNumberToCBOR(n jsonx.Number, timestamp bool) cbor.Value { if !timestamp && !strings.ContainsAny(string(n), ".eE") { if u, err := strconv.ParseUint(string(n), 10, 64); err == nil { return cbor.Uint(u) diff --git a/pkgs/store/core.go b/pkgs/store/core.go index 614b3a6151..0b2da7df83 100644 --- a/pkgs/store/core.go +++ b/pkgs/store/core.go @@ -2,11 +2,14 @@ package store import ( "cmp" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "reflect" "slices" "unsafe" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // tableCore is the non-generic engine behind every Table[V]. Values are held @@ -171,7 +174,7 @@ func (t *tableCore) insertFresh(v unsafe.Pointer) { // slice is built with reflect so no per-V code (and no *Table[V] interface // conversion, which would keep every Table method alive in the binary) is // needed. -func (t *tableCore) snapshotJSON() (json.RawMessage, error) { +func (t *tableCore) snapshotJSON() (jsontext.Value, error) { items := t.snapshot() sliceType := reflect.SliceOf(reflect.PointerTo(t.elem)) s := reflect.Zero(sliceType) // nil marshals as null, as the typed original did @@ -184,7 +187,7 @@ func (t *tableCore) snapshotJSON() (json.RawMessage, error) { s.Index(i).Set(reflect.NewAt(t.elem, p)) } - data, err := json.Marshal(s.Interface()) + data, err := json.Marshal(s.Interface(), jsonx.V1()) if err != nil { return nil, fmt.Errorf("store: marshal table snapshot: %w", err) } @@ -193,10 +196,10 @@ func (t *tableCore) snapshotJSON() (json.RawMessage, error) { } // restoreJSON loads data produced by snapshotJSON. -func (t *tableCore) restoreJSON(data json.RawMessage) error { +func (t *tableCore) restoreJSON(data jsontext.Value) error { sp := reflect.New(reflect.SliceOf(reflect.PointerTo(t.elem))) - if err := json.Unmarshal(data, sp.Interface()); err != nil { + if err := json.Unmarshal(data, sp.Interface(), jsonx.V1()); err != nil { return fmt.Errorf("store: unmarshal table snapshot: %w", err) } @@ -215,8 +218,8 @@ func (t *tableCore) restoreJSON(data json.RawMessage) error { // tableSnapshotter is the type-erased contract a [Registry] holds per table. type tableSnapshotter interface { reset() - snapshotJSON() (json.RawMessage, error) - restoreJSON(data json.RawMessage) error + snapshotJSON() (jsontext.Value, error) + restoreJSON(data jsontext.Value) error } // indexCore is the non-generic engine behind every Index[V]. diff --git a/pkgs/store/registry.go b/pkgs/store/registry.go index e2f7e1a18e..1f18bdbb1b 100644 --- a/pkgs/store/registry.go +++ b/pkgs/store/registry.go @@ -1,7 +1,7 @@ package store import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sync" @@ -78,9 +78,9 @@ func (r *Registry) ResetAll() { // deterministic (see [Table.Snapshot]); marshaling a Go map with string keys // additionally sorts those keys, so the overall result — and any JSON built // from it — is byte-for-byte stable across calls for the same backend state. -func (r *Registry) SnapshotAll() (map[string]json.RawMessage, error) { +func (r *Registry) SnapshotAll() (map[string]jsontext.Value, error) { tables := r.all() - out := make(map[string]json.RawMessage, len(tables)) + out := make(map[string]jsontext.Value, len(tables)) for name, t := range tables { data, err := t.snapshotJSON() @@ -99,7 +99,7 @@ func (r *Registry) SnapshotAll() (map[string]json.RawMessage, error) { // from data is reset to empty rather than left untouched, so RestoreAll always // produces the same backend state a fresh [NewRegistry] plus SnapshotAll's // input would — never a stale mix of old and new state. -func (r *Registry) RestoreAll(data map[string]json.RawMessage) error { +func (r *Registry) RestoreAll(data map[string]jsontext.Value) error { for name, t := range r.all() { raw, ok := data[name] if !ok { diff --git a/pkgs/store/store_test.go b/pkgs/store/store_test.go index a5649cd8d1..8cd719c504 100644 --- a/pkgs/store/store_test.go +++ b/pkgs/store/store_test.go @@ -1,7 +1,8 @@ package store_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sync" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -336,11 +338,11 @@ func Test_TableSnapshotJSONRoundTrip(t *testing.T) { src := newWidgetTable(&widget{ID: "a", Group: "g", Count: 1}) - data, err := json.Marshal(src.Snapshot()) + data, err := json.Marshal(src.Snapshot(), jsonx.V1()) require.NoError(t, err) var items []*widget - require.NoError(t, json.Unmarshal(data, &items)) + require.NoError(t, json.Unmarshal(data, &items, jsonx.V1())) dst := store.New(widgetKey) dst.Restore(items) @@ -590,7 +592,7 @@ func Test_RegistryRestoreAllResetsTablesMissingFromData(t *testing.T) { widgets.Put(&widget{ID: "stale"}) // data intentionally omits "widgets" entirely. - require.NoError(t, reg.RestoreAll(map[string]json.RawMessage{})) + require.NoError(t, reg.RestoreAll(map[string]jsontext.Value{})) assert.Equal(t, 0, widgets.Len()) } diff --git a/pkgs/tags/tags.go b/pkgs/tags/tags.go index ef4020664e..2faffd45f2 100644 --- a/pkgs/tags/tags.go +++ b/pkgs/tags/tags.go @@ -5,9 +5,10 @@ package tags import ( - "encoding/json" + "encoding/json/v2" "sort" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/safemap" ) @@ -153,7 +154,7 @@ func MapToKV(m map[string]string) []KV { // MarshalJSON implements [json.Marshaler]. // Tags serialises as a plain JSON object (e.g. {"env":"prod","team":"platform"}). func (t *Tags) MarshalJSON() ([]byte, error) { - return json.Marshal(t.Clone()) //nolint:wrapcheck // thin delegation + return json.Marshal(t.Clone(), jsonx.V1()) //nolint:wrapcheck // thin delegation } // UnmarshalJSON implements [json.Unmarshaler]. @@ -164,7 +165,7 @@ func (t *Tags) MarshalJSON() ([]byte, error) { // so the result matches the JSON payload exactly. func (t *Tags) UnmarshalJSON(data []byte) error { var m map[string]string - if err := json.Unmarshal(data, &m); err != nil { + if err := json.Unmarshal(data, &m, jsonx.V1()); err != nil { return err //nolint:wrapcheck // thin delegation } diff --git a/pkgs/tags/tags_test.go b/pkgs/tags/tags_test.go index bb49535e3b..cb16f248d9 100644 --- a/pkgs/tags/tags_test.go +++ b/pkgs/tags/tags_test.go @@ -1,11 +1,12 @@ package tags_test import ( - "encoding/json" + "encoding/json/v2" "sort" "sync" "testing" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/stretchr/testify/assert" @@ -332,7 +333,7 @@ func TestTags_MarshalJSON(t *testing.T) { tt.setup(tg) } - data, err := json.Marshal(tg) + data, err := json.Marshal(tg, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(data)) }) @@ -351,7 +352,7 @@ func TestTags_MarshalJSON_InStruct(t *testing.T) { tg.Set("team", "platform") r := resource{Name: "bucket", Tags: tg} - data, err := json.Marshal(r) + data, err := json.Marshal(r, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, `{"name":"bucket","tags":{"team":"platform"}}`, string(data)) } @@ -379,7 +380,7 @@ func TestTags_UnmarshalJSON(t *testing.T) { t.Parallel() tg := tags.New("test.unmarshal." + tt.name) - err := json.Unmarshal([]byte(tt.input), tg) + err := json.Unmarshal([]byte(tt.input), tg, jsonx.V1()) if tt.wantErr { require.Error(t, err) @@ -402,7 +403,7 @@ func TestTags_UnmarshalJSON_InStruct(t *testing.T) { } r := resource{Tags: tags.New("test.unmarshal.struct")} - err := json.Unmarshal([]byte(`{"name":"bucket","tags":{"env":"staging"}}`), &r) + err := json.Unmarshal([]byte(`{"name":"bucket","tags":{"env":"staging"}}`), &r, jsonx.V1()) require.NoError(t, err) assert.Equal(t, "bucket", r.Name) assert.Equal(t, map[string]string{"env": "staging"}, r.Tags.Clone()) @@ -415,11 +416,11 @@ func TestTags_RoundTrip(t *testing.T) { tg.Set("env", "prod") tg.Set("team", "platform") - data, err := json.Marshal(tg) + data, err := json.Marshal(tg, jsonx.V1()) require.NoError(t, err) tg2 := tags.New("test.roundtrip2") - require.NoError(t, json.Unmarshal(data, tg2)) + require.NoError(t, json.Unmarshal(data, tg2, jsonx.V1())) assert.Equal(t, tg.Clone(), tg2.Clone()) } @@ -431,7 +432,7 @@ func TestTags_UnmarshalJSON_ClearsStaleKeys(t *testing.T) { require.True(t, tg.HasTag("old-key")) // Second unmarshal with a different payload must not leave "old-key" behind. - require.NoError(t, json.Unmarshal([]byte(`{"new-key":"new-value"}`), tg)) + require.NoError(t, json.Unmarshal([]byte(`{"new-key":"new-value"}`), tg, jsonx.V1())) assert.False(t, tg.HasTag("old-key"), "stale key must be removed on unmarshal") v, ok := tg.Get("new-key") diff --git a/pkgs/wfinterp/value.go b/pkgs/wfinterp/value.go index fca2b3317c..7bb508b770 100644 --- a/pkgs/wfinterp/value.go +++ b/pkgs/wfinterp/value.go @@ -5,13 +5,16 @@ package wfinterp import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "math" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errTrailingJSON = errors.New("trailing data") @@ -165,15 +168,14 @@ func sortedKeys(m map[string]any) []string { // ParseJSON decodes JSON into workflow values: integers become int64, other numbers float64. func ParseJSON(raw []byte) (any, error) { - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fmt.Errorf("invalid JSON: %w", err) } - if dec.More() { + if dec.PeekKind() != 0 { return nil, fmt.Errorf("invalid JSON: %w", errTrailingJSON) } @@ -182,7 +184,7 @@ func ParseJSON(raw []byte) (any, error) { func normalizeJSON(v any) any { switch x := v.(type) { - case json.Number: + case jsonx.Number: if i, err := x.Int64(); err == nil && !strings.ContainsAny(string(x), ".eE") { return i } @@ -209,7 +211,7 @@ func normalizeJSON(v any) any { // ToJSON encodes a workflow value as JSON; bytes become base64 strings. func ToJSON(v any) ([]byte, error) { - raw, err := json.Marshal(jsonSafe(v)) + raw, err := json.Marshal(jsonSafe(v), jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode JSON: %w", err) } From b0d1113e19bcc66ec3f8ce2fd198fc3a294a0780 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 10:55:56 -0600 Subject: [PATCH 03/11] refactor(json): lint-clean jsonx and jsonv2mod; keep trailing commas and single-line imports intact Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- cmd/jsonv2mod/main.go | 108 +++++-- cmd/jsonv2mod/rewrite.go | 302 +++++++++++-------- cmd/jsonv2mod/rewrite_test.go | 129 ++++++-- internal/app/cli_test.go | 3 +- internal/app/cloudcontrol_handlers_test.go | 5 +- internal/app/init_stages.go | 6 +- internal/app/lifecycle_foreground_test.go | 5 +- internal/app/lifecycle_run.go | 5 +- internal/app/verifiedpermissions_jwt_test.go | 5 +- pkgs/chaos/localstack.go | 7 +- pkgs/handler/wire_golden_test.go | 30 +- pkgs/jsonx/jsonx.go | 12 +- pkgs/jsonx/jsonx_test.go | 7 +- pkgs/registryauth/resolver.go | 2 +- pkgs/service/jsondisp_golden_test.go | 25 +- 15 files changed, 447 insertions(+), 204 deletions(-) diff --git a/cmd/jsonv2mod/main.go b/cmd/jsonv2mod/main.go index 64d50f328e..2bfff044be 100644 --- a/cmd/jsonv2mod/main.go +++ b/cmd/jsonv2mod/main.go @@ -3,7 +3,7 @@ // // Usage: // -// go run ./cmd/jsonv2mod [-n] [-skip dir,...] path... +// go run ./cmd/jsonv2mod [-n] [-skip frag,...] path... // // Each path is a Go file or a directory walked recursively. Files are // rewritten in place (-n lists them instead). Constructs that cannot be @@ -14,64 +14,106 @@ package main import ( "flag" "fmt" + "io" "io/fs" "os" "path/filepath" "strings" ) +const ( + exitLeftovers = 1 + exitFailure = 2 + fileMode = 0o600 +) + +type options struct { + out, errOut io.Writer + skips []string + dry bool +} + func main() { dry := flag.Bool("n", false, "list files that would change without writing") skip := flag.String("skip", "", "comma-separated path fragments to skip") flag.Parse() - skips := strings.Split(*skip, ",") - changed, leftovers := 0, 0 + opts := options{out: os.Stdout, errOut: os.Stderr, skips: strings.Split(*skip, ","), dry: *dry} - for _, root := range flag.Args() { - err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - if d.IsDir() || !strings.HasSuffix(path, ".go") || skipped(path, skips) { - return nil - } + sum, err := opts.run(flag.Args()) + if err != nil { + fmt.Fprintln(os.Stderr, "jsonv2mod:", err) + os.Exit(exitFailure) + } - res, err := processFile(path) - if err != nil { - return err - } + fmt.Fprintf(os.Stderr, "jsonv2mod: %d files changed, %d leftovers\n", sum.changed, sum.leftovers) - for _, f := range res.findings { - fmt.Fprintf(os.Stderr, "%s:%d: %s\n", path, f.line, f.msg) - leftovers++ - } + if sum.leftovers > 0 { + os.Exit(exitLeftovers) + } +} - if res.out == nil { - return nil - } +type summary struct{ changed, leftovers int } - changed++ - fmt.Println(path) +func (o options) run(roots []string) (summary, error) { + var ( + files []string + sum summary + ) - if *dry { - return nil + for _, root := range roots { + walkErr := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if err == nil && !d.IsDir() && strings.HasSuffix(path, ".go") && !skipped(path, o.skips) { + files = append(files, path) } - return os.WriteFile(path, res.out, 0o644) + return err }) + if walkErr != nil { + return sum, walkErr + } + } + + for _, path := range files { + one, err := o.process(path) if err != nil { - fmt.Fprintln(os.Stderr, "jsonv2mod:", err) - os.Exit(2) + return sum, err } + + sum.changed += one.changed + sum.leftovers += one.leftovers + } + + return sum, nil +} + +func (o options) process(path string) (summary, error) { + var sum summary + + res, err := processFile(path) + if err != nil { + return sum, err } - fmt.Fprintf(os.Stderr, "jsonv2mod: %d files changed, %d leftovers\n", changed, leftovers) + for _, f := range res.findings { + fmt.Fprintf(o.errOut, "%s:%d: %s\n", path, f.line, f.msg) - if leftovers > 0 { - os.Exit(1) + sum.leftovers++ } + + if res.out == nil { + return sum, nil + } + + sum.changed++ + + fmt.Fprintln(o.out, path) + + if o.dry { + return sum, nil + } + + return sum, os.WriteFile(path, res.out, fileMode) } func skipped(path string, skips []string) bool { diff --git a/cmd/jsonv2mod/rewrite.go b/cmd/jsonv2mod/rewrite.go index 864b4a5d3b..80e77dc8ad 100644 --- a/cmd/jsonv2mod/rewrite.go +++ b/cmd/jsonv2mod/rewrite.go @@ -2,6 +2,7 @@ package main import ( "bytes" + "errors" "fmt" "go/ast" "go/format" @@ -21,6 +22,8 @@ const ( optV1 = "jsonx.V1()" ) +var errOverlap = errors.New("overlapping edits") + type finding struct { msg string line int @@ -42,6 +45,7 @@ type stream struct { name string opts []string edits []edit + decodes []*ast.CallExpr decoder bool bad bool } @@ -65,7 +69,7 @@ func (r *rewriter) add(start, end int, text string) { r.edits = append(r.edits, edit{start: start, end: end, text: text}) } -func (r *rewriter) report(p token.Pos, format string, a ...any) { +func (r *rewriter) reportf(p token.Pos, format string, a ...any) { r.findings = append(r.findings, finding{line: r.fset.Position(p).Line, msg: fmt.Sprintf(format, a...)}) } @@ -204,32 +208,36 @@ func enclosing(d ast.Decl, n ast.Node) *ast.BlockStmt { return best } -func (r *rewriter) rewriteStreamUses(d ast.Decl) { - if len(r.streams) == 0 { - return - } - - declIdents := map[*ast.Ident]bool{} +func (r *rewriter) declIdents(d ast.Decl) map[*ast.Ident]bool { + out := map[*ast.Ident]bool{} - for _, s := range r.streams { - ast.Inspect(d, func(n ast.Node) bool { - switch x := n.(type) { - case *ast.AssignStmt: - for _, l := range x.Lhs { - if id, ok := l.(*ast.Ident); ok && id.Name == s.name { - declIdents[id] = true - } - } - case *ast.ValueSpec: - for _, id := range x.Names { - declIdents[id] = true + ast.Inspect(d, func(n ast.Node) bool { + switch x := n.(type) { + case *ast.AssignStmt: + for _, l := range x.Lhs { + if id, ok := l.(*ast.Ident); ok && r.streams[id.Name] != nil { + out[id] = true } } + case *ast.ValueSpec: + for _, id := range x.Names { + out[id] = true + } + } - return true - }) + return true + }) + + return out +} + +func (r *rewriter) rewriteStreamUses(d ast.Decl) { + if len(r.streams) == 0 { + return } + decls := r.declIdents(d) + var stack []ast.Node ast.Inspect(d, func(n ast.Node) bool { @@ -241,75 +249,100 @@ func (r *rewriter) rewriteStreamUses(d ast.Decl) { stack = append(stack, n) - id, ok := n.(*ast.Ident) - if !ok || declIdents[id] || r.streams[id.Name] == nil { - return true + if id, ok := n.(*ast.Ident); ok && !decls[id] && r.streams[id.Name] != nil { + r.streamUse(r.streams[id.Name], id, stack) } - r.streamUse(r.streams[id.Name], id, stack) - return true }) } +// Stack offsets from the identifier at the top: selector, call, statement, block. +const ( + stackSel = 2 + stackCall = 3 + stackStmt = 4 + stackBlock = 5 +) + func (r *rewriter) streamUse(s *stream, id *ast.Ident, stack []ast.Node) { n := len(stack) - if n < 3 { + if n < stackCall { s.bad = true return } - sel, ok := stack[n-2].(*ast.SelectorExpr) - call, isCall := stack[n-3].(*ast.CallExpr) + sel, isSel := stack[n-stackSel].(*ast.SelectorExpr) + call, isCall := stack[n-stackCall].(*ast.CallExpr) - if !ok || sel.X != id || !isCall || call.Fun != sel { + if !isSel || sel.X != id || !isCall || call.Fun != sel { s.bad = true - r.report(id.Pos(), "%s escapes (not a plain method call); rewrite by hand", s.name) + + r.reportf(id.Pos(), "%s escapes (not a plain method call); rewrite by hand", s.name) return } var stmt *ast.ExprStmt - if n >= 5 { - if es, ok := stack[n-4].(*ast.ExprStmt); ok && stack[n-5] == ast.Node(s.block) { - stmt = es - } + if n >= stackBlock && stack[n-stackBlock] == ast.Node(s.block) { + stmt, _ = stack[n-stackStmt].(*ast.ExprStmt) + } + + var handled bool + if s.decoder { + handled = r.decoderMethod(s, call, sel.Sel.Name, stmt) + } else { + handled = r.encoderMethod(s, call, sel.Sel.Name, stmt) } - method, argc := sel.Sel.Name, len(call.Args) + if !handled { + s.bad = true + + r.reportf(call.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", s.name, sel.Sel.Name) + } +} + +func (r *rewriter) decoderMethod(s *stream, call *ast.CallExpr, method string, stmt *ast.ExprStmt) bool { + argc := len(call.Args) switch { - case s.decoder && method == "Decode" && argc == 1: - s.add(r, r.off(call.Pos()), r.off(call.Args[0].Pos()), r.jsonName+".UnmarshalDecode("+s.name+", ") - s.add(r, r.off(call.Args[0].End()), r.off(call.End()), ", "+optV1+r.extra(s)+")") - case !s.decoder && method == "Encode" && argc == 1: - s.add(r, r.off(call.Pos()), r.off(call.Args[0].Pos()), r.jsonName+".MarshalEncode("+s.name+", ") - case s.decoder && method == "UseNumber" && argc == 0 && stmt != nil: + case method == "Decode" && argc == 1: + s.decodes = append(s.decodes, call) + case method == "UseNumber" && argc == 0 && stmt != nil: s.opts = append(s.opts, "jsonx.UseNumber()") s.edits = append(s.edits, r.stmtEdit(stmt)) - case s.decoder && method == "DisallowUnknownFields" && argc == 0 && stmt != nil: + case method == "DisallowUnknownFields" && argc == 0 && stmt != nil: s.opts = append(s.opts, r.jsonName+".RejectUnknownMembers(true)") s.edits = append(s.edits, r.stmtEdit(stmt)) - case !s.decoder && method == "SetEscapeHTML" && argc == 1 && stmt != nil: + default: + return false + } + + return true +} + +func (r *rewriter) encoderMethod(s *stream, call *ast.CallExpr, method string, stmt *ast.ExprStmt) bool { + argc := len(call.Args) + + switch { + case method == "Encode" && argc == 1: + s.edits = append(s.edits, edit{ + start: r.off(call.Pos()), end: r.off(call.Args[0].Pos()), + text: r.jsonName + ".MarshalEncode(" + s.name + ", ", + }) + case method == "SetEscapeHTML" && argc == 1 && stmt != nil: s.opts = append(s.opts, "jsontext.EscapeForHTML("+r.text(call.Args[0], call.Args[0])+")") s.edits = append(s.edits, r.stmtEdit(stmt)) - case !s.decoder && method == "SetIndent" && argc == 2 && stmt != nil: + case method == "SetIndent" && argc == 2 && stmt != nil: s.opts = append(s.opts, r.indentOpts(call.Args[0], call.Args[1])...) s.edits = append(s.edits, r.stmtEdit(stmt)) default: - s.bad = true - r.report(call.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", s.name, method) - } -} - -func (r *rewriter) extra(s *stream) string { - if !s.decoder || len(s.opts) == 0 { - return "" + return false } - return ", " + strings.Join(s.opts, ", ") + return true } func (r *rewriter) indentOpts(prefix, indent ast.Expr) []string { @@ -326,10 +359,6 @@ func (r *rewriter) indentOpts(prefix, indent ast.Expr) []string { return opts } -func (s *stream) add(r *rewriter, start, end int, text string) { - s.edits = append(s.edits, edit{start: start, end: end, text: text}) -} - func (r *rewriter) stmtEdit(s *ast.ExprStmt) edit { start, end := r.off(s.Pos()), r.off(s.End()) @@ -346,27 +375,32 @@ func (r *rewriter) stmtEdit(s *ast.ExprStmt) edit { func (r *rewriter) emitStreams() { for _, s := range r.streams { - if s.bad { + fun, ok := s.call.Fun.(*ast.SelectorExpr) + if s.bad || !ok { continue } r.edits = append(r.edits, s.edits...) - fun := s.call.Fun.(*ast.SelectorExpr) - if s.decoder { - r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewDecoder") + opts := ", " + optV1 + if len(s.opts) > 0 { + opts += ", " + strings.Join(s.opts, ", ") + } + + if !s.decoder { + r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewEncoder") + end := r.off(s.call.Args[0].End()) + r.add(end, end, opts) continue } - r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewEncoder") + r.add(r.off(fun.Pos()), r.off(fun.End()), "jsontext.NewDecoder") - opts := ", " + optV1 - if len(s.opts) > 0 { - opts += ", " + strings.Join(s.opts, ", ") + for _, c := range s.decodes { + r.add(r.off(c.Pos()), r.off(c.Args[0].Pos()), r.jsonName+".UnmarshalDecode("+s.name+", ") + r.add(r.off(c.Args[0].End()), r.off(c.End()), opts+")") } - - r.add(r.off(s.call.Rparen), r.off(s.call.Rparen), opts) } } @@ -389,7 +423,8 @@ func (r *rewriter) callExpr(call *ast.CallExpr) { switch { case r.isJSON(call.Fun, "Marshal") && argc == 1, r.isJSON(call.Fun, "Unmarshal") && argc == 2: r.consumed[call.Fun] = true - r.add(r.off(call.Rparen), r.off(call.Rparen), ", "+optV1) + end := r.off(call.Args[len(call.Args)-1].End()) + r.add(end, end, ", "+optV1) case r.isJSON(call.Fun, "MarshalIndent") && argc == 3: r.marshalIndent(call) case r.isJSON(call.Fun, "Valid") && argc == 1: @@ -402,28 +437,29 @@ func (r *rewriter) callExpr(call *ast.CallExpr) { } func (r *rewriter) marshalIndent(call *ast.CallExpr) { - prefix, ok1 := call.Args[1].(*ast.BasicLit) - indent, ok2 := call.Args[2].(*ast.BasicLit) - - for _, lit := range []*ast.BasicLit{prefix, indent} { - if lit == nil { + for _, arg := range call.Args[1:] { + lit, isLit := arg.(*ast.BasicLit) + if !isLit { continue } if s, err := strconv.Unquote(lit.Value); err == nil && strings.Trim(s, " \t\r\n") != "" { - r.report(call.Pos(), "MarshalIndent with non-whitespace indent %s; v2 panics, rewrite by hand", lit.Value) + r.reportf(call.Pos(), "MarshalIndent with non-whitespace indent %s; v2 panics, rewrite by hand", lit.Value) return } } - _, _ = ok1, ok2 - sel := call.Fun.(*ast.SelectorExpr) + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return + } + r.consumed[call.Fun] = true r.add(r.off(sel.Sel.Pos()), r.off(sel.Sel.End()), "Marshal") opts := append([]string{optV1}, r.indentOpts(call.Args[1], call.Args[2])...) - r.add(r.off(call.Args[0].End()), r.off(call.Rparen), ", "+strings.Join(opts, ", ")) + r.add(r.off(call.Args[0].End()), r.off(call.Args[2].End()), ", "+strings.Join(opts, ", ")) } func (r *rewriter) chain(call *ast.CallExpr) { @@ -442,7 +478,7 @@ func (r *rewriter) chain(call *ast.CallExpr) { switch { case r.isJSON(inner.Fun, "NewDecoder") && outer.Sel.Name == "Decode": if r.hasComment(r.off(call.Pos()), r.off(call.End())) { - r.report(call.Pos(), "comment inside NewDecoder(...).Decode chain; rewrite by hand") + r.reportf(call.Pos(), "comment inside NewDecoder(...).Decode chain; rewrite by hand") return } @@ -453,7 +489,7 @@ func (r *rewriter) chain(call *ast.CallExpr) { r.add(r.off(call.Args[0].End()), r.off(call.End()), ", "+optV1+")") case r.isJSON(inner.Fun, "NewEncoder") && outer.Sel.Name == "Encode": if r.hasComment(r.off(call.Pos()), r.off(call.End())) { - r.report(call.Pos(), "comment inside NewEncoder(...).Encode chain; rewrite by hand") + r.reportf(call.Pos(), "comment inside NewEncoder(...).Encode chain; rewrite by hand") return } @@ -479,7 +515,7 @@ func (r *rewriter) rewriteSelectors(d ast.Decl) { r.add(r.off(sel.Pos()), r.off(sel.End()), "jsonx.Number") case "Marshaler", "Unmarshaler": default: - r.report(sel.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", r.jsonName, sel.Sel.Name) + r.reportf(sel.Pos(), "%s.%s has no mechanical v2 equivalent; rewrite by hand", r.jsonName, sel.Sel.Name) } return true @@ -494,7 +530,7 @@ func (r *rewriter) apply() ([]byte, error) { for _, e := range r.edits { if e.end > prev { - return nil, fmt.Errorf("overlapping edits at offset %d", e.start) + return nil, fmt.Errorf("%w at offset %d", errOverlap, e.start) } out = append(out[:e.start], append([]byte(e.text), out[e.end:]...)...) @@ -504,56 +540,71 @@ func (r *rewriter) apply() ([]byte, error) { return out, nil } -// fixImports swaps the v1 import for v2 (or drops it when unused after the -// rewrite) and adds jsontext / jsonx when referenced. -func fixImports(path string, src []byte, jsonName string) ([]byte, error) { - fset := token.NewFileSet() +type importInfo struct { + v1Spec *ast.ImportSpec + firstLocal *ast.ImportSpec + last *ast.ImportSpec + have map[string]bool + used map[string]bool +} - file, err := parser.ParseFile(fset, path, src, parser.ParseComments) - if err != nil { - return nil, fmt.Errorf("rewritten file does not parse: %w", err) - } +func scanImports(file *ast.File) importInfo { + info := importInfo{have: map[string]bool{}, used: map[string]bool{}} - used := map[string]bool{} + for _, imp := range file.Imports { + p, _ := strconv.Unquote(imp.Path.Value) + info.have[p] = true + info.last = imp + + if p == v1Path { + info.v1Spec = imp + } + + if info.firstLocal == nil && strings.HasPrefix(p, localPrefix) { + info.firstLocal = imp + } + } ast.Inspect(file, func(n ast.Node) bool { if sel, ok := n.(*ast.SelectorExpr); ok { - if id, ok := sel.X.(*ast.Ident); ok { - used[id.Name] = true + if id, isID := sel.X.(*ast.Ident); isID { + info.used[id.Name] = true } } return true }) - have := map[string]bool{} + return info +} - var v1Spec *ast.ImportSpec +// fixImports swaps the v1 import for v2 (or drops it when unused after the +// rewrite) and adds jsontext / jsonx when referenced. +func fixImports(path string, src []byte, jsonName string) ([]byte, error) { + fset := token.NewFileSet() - var firstLocal, last *ast.ImportSpec + file, err := parser.ParseFile(fset, path, src, parser.ParseComments) + if err != nil { + return nil, fmt.Errorf("rewritten file does not parse: %w", err) + } - for _, imp := range file.Imports { - p, _ := strconv.Unquote(imp.Path.Value) - have[p] = true - last = imp + info := scanImports(file) + off := func(p token.Pos) int { return fset.Position(p).Offset } + spec := info.v1Spec - if p == v1Path { - v1Spec = imp - } + if decl := importDecl(file, spec); !decl.Lparen.IsValid() { + block := "import (\n\t" + string(src[off(spec.Pos()):off(spec.End())]) + "\n)" + out := append(append(append([]byte(nil), src[:off(decl.Pos())]...), block...), src[off(decl.End()):]...) - if firstLocal == nil && strings.HasPrefix(p, localPrefix) { - firstLocal = imp - } + return fixImports(path, out, jsonName) } var edits []edit - off := func(p token.Pos) int { return fset.Position(p).Offset } - - if used[jsonName] { - edits = append(edits, edit{start: off(v1Spec.Path.Pos()), end: off(v1Spec.Path.End()), text: strconv.Quote(v2Path)}) + if info.used[jsonName] { + edits = append(edits, edit{start: off(spec.Path.Pos()), end: off(spec.Path.End()), text: strconv.Quote(v2Path)}) } else { - start, end := off(v1Spec.Pos()), off(v1Spec.End()) + start, end := off(spec.Pos()), off(spec.End()) for start > 0 && (src[start-1] == ' ' || src[start-1] == '\t') { start-- } @@ -565,17 +616,20 @@ func fixImports(path string, src []byte, jsonName string) ([]byte, error) { edits = append(edits, edit{start: start, end: end}) } - if used["jsontext"] && !have[jsontextPath] { - edits = append(edits, edit{start: off(v1Spec.End()), end: off(v1Spec.End()), text: "\n\t" + strconv.Quote(jsontextPath)}) + if info.used["jsontext"] && !info.have[jsontextPath] { + edits = append( + edits, + edit{start: off(spec.End()), end: off(spec.End()), text: "\n\t" + strconv.Quote(jsontextPath)}, + ) } - if used["jsonx"] && !have[jsonxPath] { - switch { - case firstLocal != nil: - edits = append(edits, edit{start: off(firstLocal.Pos()), end: off(firstLocal.Pos()), text: strconv.Quote(jsonxPath) + "\n\t"}) - default: - edits = append(edits, edit{start: off(last.End()), end: off(last.End()), text: "\n\n\t" + strconv.Quote(jsonxPath)}) + if info.used["jsonx"] && !info.have[jsonxPath] { + at, text := off(info.last.End()), "\n\n\t"+strconv.Quote(jsonxPath) + if info.firstLocal != nil { + at, text = off(info.firstLocal.Pos()), strconv.Quote(jsonxPath)+"\n\t" } + + edits = append(edits, edit{start: at, end: at, text: text}) } sort.SliceStable(edits, func(i, j int) bool { return edits[i].start > edits[j].start }) @@ -587,3 +641,13 @@ func fixImports(path string, src []byte, jsonName string) ([]byte, error) { return format.Source(out) } + +func importDecl(file *ast.File, spec *ast.ImportSpec) *ast.GenDecl { + for _, d := range file.Decls { + if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.IMPORT && g.Pos() <= spec.Pos() && spec.End() <= g.End() { + return g + } + } + + return nil +} diff --git a/cmd/jsonv2mod/rewrite_test.go b/cmd/jsonv2mod/rewrite_test.go index 81db45a0fb..3c8ad3ddd9 100644 --- a/cmd/jsonv2mod/rewrite_test.go +++ b/cmd/jsonv2mod/rewrite_test.go @@ -7,7 +7,19 @@ import ( "github.com/stretchr/testify/require" ) -const header = "package p\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\n\t\"github.com/blackbirdworks/gopherstack/pkgs/arn\"\n)\n\nvar _ = http.StatusOK\nvar _ = arn.X\n\n" +const header = `package p + +import ( + "encoding/json" + "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/arn" +) + +var _ = http.StatusOK +var _ = arn.X + +` func TestRewrite(t *testing.T) { t.Parallel() @@ -20,52 +32,118 @@ func TestRewrite(t *testing.T) { }{ { name: "marshal unmarshal", - body: "func f(b []byte) { _, _ = json.Marshal(b); _ = json.Unmarshal(b, &b) }\n", - want: []string{"json.Marshal(b, jsonx.V1())", "json.Unmarshal(b, &b, jsonx.V1())", "\"encoding/json/v2\"", "pkgs/jsonx\""}, + body: `func f(b []byte) { + _, _ = json.Marshal(b) + _ = json.Unmarshal(b, &b) +}`, + want: []string{ + "json.Marshal(b, jsonx.V1())", "json.Unmarshal(b, &b, jsonx.V1())", + `"encoding/json/v2"`, `pkgs/jsonx"`, + }, + }, + { + name: "multiline trailing comma", + body: `func f(b []byte) { + _, _ = json.Marshal( + b, + ) +}`, + want: []string{"b, jsonx.V1(),"}, }, { name: "marshal indent", - body: "func f(v any) { _, _ = json.MarshalIndent(v, \"\", \" \") }\n", - want: []string{"json.Marshal(v, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(\" \"))", "encoding/json/jsontext"}, + body: `func f(v any) { _, _ = json.MarshalIndent(v, "", " ") }`, + want: []string{ + `json.Marshal(v, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" "))`, + "encoding/json/jsontext", + }, }, { name: "decode chain", - body: "func f(r *http.Request, v any) error { return json.NewDecoder(r.Body).Decode(&v) }\n", + body: `func f(r *http.Request, v any) error { return json.NewDecoder(r.Body).Decode(&v) }`, want: []string{"json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &v, jsonx.V1())"}, }, { name: "encode chain", - body: "func f(w http.ResponseWriter, v any) { _ = json.NewEncoder(w).Encode(v) }\n", + body: `func f(w http.ResponseWriter, v any) { _ = json.NewEncoder(w).Encode(v) }`, want: []string{"json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), v)"}, }, { name: "decoder var", - body: "func f(r *http.Request, v any) error {\n\tdec := json.NewDecoder(r.Body)\n\tdec.UseNumber()\n\tdec.DisallowUnknownFields()\n\n\treturn dec.Decode(&v)\n}\n", - want: []string{"dec := jsontext.NewDecoder(r.Body)", "json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber(), json.RejectUnknownMembers(true))"}, + body: `func f(r *http.Request, v any) error { + dec := json.NewDecoder(r.Body) + dec.UseNumber() + dec.DisallowUnknownFields() + + return dec.Decode(&v) +}`, + want: []string{ + "dec := jsontext.NewDecoder(r.Body)", + "json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber(), json.RejectUnknownMembers(true))", + }, }, { name: "encoder var", - body: "func f(w http.ResponseWriter, v any) error {\n\tenc := json.NewEncoder(w)\n\tenc.SetEscapeHTML(false)\n\tenc.SetIndent(\"\", \"\\t\")\n\n\treturn enc.Encode(v)\n}\n", - want: []string{"jsontext.NewEncoder(w, jsonx.V1(), jsontext.EscapeForHTML(false), jsontext.Multiline(true), jsontext.WithIndent(\"\\t\"))", "json.MarshalEncode(enc, v)"}, + body: `func f(w http.ResponseWriter, v any) error { + enc := json.NewEncoder(w) + enc.SetEscapeHTML(false) + enc.SetIndent("", "\t") + + return enc.Encode(v) +}`, + want: []string{ + `jsontext.NewEncoder(w, jsonx.V1(), jsontext.EscapeForHTML(false), jsontext.Multiline(true), ` + + `jsontext.WithIndent("\t"))`, + "json.MarshalEncode(enc, v)", + }, }, { name: "types", - body: "type T struct {\n\tR json.RawMessage\n\tN json.Number\n}\n\nvar _ json.Marshaler\n\nfunc f(b []byte) bool { return json.Valid(b) }\n", - want: []string{"R jsontext.Value", "N jsonx.Number", "json.Marshaler", "jsontext.Value(b).IsValid(jsonx.V1())"}, + body: `type T struct { + R json.RawMessage + N json.Number +} + +var _ json.Marshaler + +func f(b []byte) bool { return json.Valid(b) }`, + want: []string{ + "R jsontext.Value", + "N jsonx.Number", + "json.Marshaler", + "jsontext.Value(b).IsValid(jsonx.V1())", + }, }, { name: "bad stream stays untouched", - body: "func f(r *http.Request, v any) {\n\tdec := json.NewDecoder(r.Body)\n\t_ = dec.Decode(&v)\n\t_ = dec.Buffered()\n}\n", - want: []string{"_ = dec.Decode(&v)", "json.NewDecoder(r.Body)"}, wantFindings: 1, + body: `func f(r *http.Request, v any) { + dec := json.NewDecoder(r.Body) + _ = dec.Decode(&v) + _ = dec.Buffered() +}`, + want: []string{"_ = dec.Decode(&v)", "json.NewDecoder(r.Body)"}, + wantFindings: 1, }, { name: "conditional setindent is not hoisted", - body: "func f(w http.ResponseWriter, v any, c bool) {\n\tenc := json.NewEncoder(w)\n\tif c {\n\t\tenc.SetIndent(\"\", \" \")\n\t}\n\t_ = enc.Encode(v)\n}\n", - want: []string{"enc.SetIndent"}, wantFindings: 1, + body: `func f(w http.ResponseWriter, v any, c bool) { + enc := json.NewEncoder(w) + if c { + enc.SetIndent("", " ") + } + _ = enc.Encode(v) +}`, + want: []string{"enc.SetIndent"}, + wantFindings: 1, }, { - name: "leftovers", - body: "func f(r *http.Request) { d := json.NewDecoder(r.Body); _ = d.More(); var e *json.SyntaxError; _ = e }\n", + name: "leftovers", + body: `func f(r *http.Request) { + d := json.NewDecoder(r.Body) + _ = d.More() + var e *json.SyntaxError + _ = e +}`, want: []string{"json.NewDecoder(r.Body)"}, wantFindings: 2, }, @@ -75,7 +153,7 @@ func TestRewrite(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - res, err := rewrite("x.go", []byte(header+tt.body)) + res, err := rewrite("x.go", []byte(header+tt.body+"\n")) require.NoError(t, err) assert.Len(t, res.findings, tt.wantFindings) require.NotNil(t, res.out) @@ -87,6 +165,17 @@ func TestRewrite(t *testing.T) { } } +func TestRewriteSingleLineImport(t *testing.T) { + t.Parallel() + + src := "package p\n\nimport \"encoding/json\"\n\nfunc f(b []byte) bool { return json.Valid(b) }\n" + res, err := rewrite("x.go", []byte(src)) + require.NoError(t, err) + require.NotNil(t, res.out) + assert.Contains(t, string(res.out), "jsontext.Value(b).IsValid(jsonx.V1())") + assert.Contains(t, string(res.out), "encoding/json/jsontext") +} + func TestRewriteNoV1Import(t *testing.T) { t.Parallel() diff --git a/internal/app/cli_test.go b/internal/app/cli_test.go index 8504ca29ba..59c5e09539 100644 --- a/internal/app/cli_test.go +++ b/internal/app/cli_test.go @@ -3210,7 +3210,8 @@ func TestLocalstackCompatibilityEndpoints(t *testing.T) { waitForEndpoint(t, fmt.Sprintf("http://localhost:%d/_localstack/init/ready", port), func(resp *http.Response) bool { var body map[string]any - return json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1()) == nil && body["completed"] == true + return json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1()) == nil && + body["completed"] == true }) for _, tt := range tests { diff --git a/internal/app/cloudcontrol_handlers_test.go b/internal/app/cloudcontrol_handlers_test.go index ce6a8eafea..fb235a2991 100644 --- a/internal/app/cloudcontrol_handlers_test.go +++ b/internal/app/cloudcontrol_handlers_test.go @@ -336,7 +336,10 @@ func TestCloudControlSubnetIPv6(t *testing.T) { require.NoError(t, err) var props map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props, jsonx.V1())) + require.NoError( + t, + json.Unmarshal([]byte(aws.ToString(got.ResourceDescription.Properties)), &props, jsonx.V1()), + ) assert.Equal(t, []any{v6}, props["Ipv6CidrBlocks"]) assert.Equal(t, azID, props["AvailabilityZoneId"]) assert.Equal(t, true, props["AssignIpv6AddressOnCreation"]) diff --git a/internal/app/init_stages.go b/internal/app/init_stages.go index c37f26767b..797370df5b 100644 --- a/internal/app/init_stages.go +++ b/internal/app/init_stages.go @@ -138,7 +138,11 @@ func buildInitRunHandler(st *localstackInitState) echo.HandlerFunc { } var req initRunRequest - if err := json.UnmarshalDecode(jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, initRunMaxBody)), &req, jsonx.V1()); err != nil { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, initRunMaxBody)), + &req, + jsonx.V1(), + ); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyMessageField: "invalid request body"}) } diff --git a/internal/app/lifecycle_foreground_test.go b/internal/app/lifecycle_foreground_test.go index 6cb480fac0..838aaa3c59 100644 --- a/internal/app/lifecycle_foreground_test.go +++ b/internal/app/lifecycle_foreground_test.go @@ -322,7 +322,10 @@ func TestLifecycleStatusServiceHealth(t *testing.T) { Services: []string{"S3", "SQS"}, Disabled: []string{"SNS"}, }) case "/_localstack/health": - _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), localstackHealthResponse{Services: map[string]string{"s3": "available"}}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + localstackHealthResponse{Services: map[string]string{"s3": "available"}}, + ) default: http.NotFound(w, r) } diff --git a/internal/app/lifecycle_run.go b/internal/app/lifecycle_run.go index 45fe333e6a..d520e5681e 100644 --- a/internal/app/lifecycle_run.go +++ b/internal/app/lifecycle_run.go @@ -568,7 +568,10 @@ func (c *StatusCmd) run(ctx context.Context, d *lifecycleDeps) error { h, err := d.health(ctx, endpoint) if err != nil { if c.JSON { - _ = json.MarshalEncode(jsontext.NewEncoder(d.Out, jsonx.V1()), statusReport{Endpoint: endpoint, Managed: managed}) + _ = json.MarshalEncode( + jsontext.NewEncoder(d.Out, jsonx.V1()), + statusReport{Endpoint: endpoint, Managed: managed}, + ) } else { fmt.Fprintf(d.Out, "gopherstack is not running (%s)\n", endpoint) } diff --git a/internal/app/verifiedpermissions_jwt_test.go b/internal/app/verifiedpermissions_jwt_test.go index 25497f9f1e..c2598cabe9 100644 --- a/internal/app/verifiedpermissions_jwt_test.go +++ b/internal/app/verifiedpermissions_jwt_test.go @@ -306,7 +306,10 @@ func newOIDCServer(t *testing.T) *oidcServer { t.Cleanup(o.srv.Close) mux.HandleFunc("/.well-known/openid-configuration", func(w http.ResponseWriter, _ *http.Request) { - _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{"issuer": o.srv.URL, "jwks_uri": o.srv.URL + "/keys"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"issuer": o.srv.URL, "jwks_uri": o.srv.URL + "/keys"}, + ) }) mux.HandleFunc("/keys", func(w http.ResponseWriter, _ *http.Request) { o.jwksHits.Add(1) diff --git a/pkgs/chaos/localstack.go b/pkgs/chaos/localstack.go index c11a411615..48c99f693c 100644 --- a/pkgs/chaos/localstack.go +++ b/pkgs/chaos/localstack.go @@ -114,7 +114,12 @@ func (h *lsHandler) getEffects(c *echo.Context) error { func (h *lsHandler) postEffects(c *echo.Context) error { var in localstackEffects - if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil || in.Latency < 0 { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &in, + jsonx.V1(), + ); err != nil || + in.Latency < 0 { return badRequest(c, errInvalidEffects) } diff --git a/pkgs/handler/wire_golden_test.go b/pkgs/handler/wire_golden_test.go index b5e4478aab..5264b79685 100644 --- a/pkgs/handler/wire_golden_test.go +++ b/pkgs/handler/wire_golden_test.go @@ -23,8 +23,8 @@ type goldenAttr struct { } type goldenScanOutput struct { - Items []map[string]*goldenAttr `json:"Items"` LastEvaluatedKey map[string]*goldenAttr `json:"LastEvaluatedKey,omitempty"` + Items []map[string]*goldenAttr `json:"Items"` Count int32 `json:"Count"` ScannedCount int32 `json:"ScannedCount"` } @@ -55,8 +55,6 @@ type goldenMetricOutput struct { Results []goldenMetricResult `json:"MetricDataResults"` } -func goldenStr(s string) *string { return &s } - func TestWireGoldenJSONRPC(t *testing.T) { t.Parallel() @@ -73,18 +71,20 @@ func TestWireGoldenJSONRPC(t *testing.T) { name: "dynamodb scan", payload: goldenScanOutput{ Items: []map[string]*goldenAttr{{ - "id": {S: goldenStr("a&c
\"q\"")}, - "n": {N: goldenStr("1.50")}, + "id": {S: new("a&c
\"q\"")}, + "n": {N: new("1.50")}, "bin": {B: []byte{1, 2, 3}}, "nul": {NULL: &yes}, - "m": {M: map[string]*goldenAttr{"z": {S: goldenStr("1")}, "a": {S: goldenStr("2")}}}, - "list": {L: []*goldenAttr{{S: goldenStr("x")}, {N: goldenStr("2")}}}, + "m": {M: map[string]*goldenAttr{"z": {S: new("1")}, "a": {S: new("2")}}}, + "list": {L: []*goldenAttr{{S: new("x")}, {N: new("2")}}}, }}, Count: 1, ScannedCount: 1, }, - body: `{"Items":[{"bin":{"B":"AQID"},"id":{"S":"a\u003cb\u003e\u0026c\u2028\"q\""},"list":{"L":[{"S":"x"},{"N":"2"}]},"m":{"M":{"a":{"S":"2"},"z":{"S":"1"}}},"n":{"N":"1.50"},"nul":{"NULL":true}}],"Count":1,"ScannedCount":1}`, - crc: "2457307943", + body: `{"Items":[{"bin":{"B":"AQID"},"id":{"S":"a\u003cb\u003e\u0026c\u2028\"q\""},` + + `"list":{"L":[{"S":"x"},{"N":"2"}]},"m":{"M":{"a":{"S":"2"},"z":{"S":"1"}}},` + + `"n":{"N":"1.50"},"nul":{"NULL":true}}],"Count":1,"ScannedCount":1}`, + crc: "2457307943", }, { name: "dynamodb empty scan", @@ -99,8 +99,9 @@ func TestWireGoldenJSONRPC(t *testing.T) { Body: `{"k":""}`, MD5: "abc", }}}, - body: `{"Messages":[{"Attributes":null,"MessageId":"m-1","Body":"{\"k\":\"\u003cv\u003e\"}","MD5OfBody":"abc"}]}`, - crc: "2547812670", + body: `{"Messages":[{"Attributes":null,"MessageId":"m-1",` + + `"Body":"{\"k\":\"\u003cv\u003e\"}","MD5OfBody":"abc"}]}`, + crc: "2547812670", }, { name: "sqs empty", @@ -118,8 +119,11 @@ func TestWireGoldenJSONRPC(t *testing.T) { Values: []float64{1.5, 2, 1e21, 0.000001, 1e-7, 100, 123456789012}, Extra: jsontext.Value(` { "a" : [1, 2] } `), }}}, - body: `{"MetricDataResults":[{"Id":"q1","Label":"CPU \u003cavg\u003e","StatusCode":"Complete","Timestamps":[1741064767.1230001,1741064827.1230001],"Values":[1.5,2,1e+21,0.000001,1e-7,100,123456789012],"Messages":null,"Extra":{"a":[1,2]}}]}`, - crc: "2076035819", + body: `{"MetricDataResults":[{"Id":"q1","Label":"CPU \u003cavg\u003e",` + + `"StatusCode":"Complete","Timestamps":[1741064767.1230001,1741064827.1230001],` + + `"Values":[1.5,2,1e+21,0.000001,1e-7,100,123456789012],"Messages":null,` + + `"Extra":{"a":[1,2]}}]}`, + crc: "2076035819", }, } diff --git a/pkgs/jsonx/jsonx.go b/pkgs/jsonx/jsonx.go index b3a9e4024f..f10627420f 100644 --- a/pkgs/jsonx/jsonx.go +++ b/pkgs/jsonx/jsonx.go @@ -37,10 +37,16 @@ import ( jsonv1 "encoding/json" "encoding/json/jsontext" "encoding/json/v2" + "errors" "fmt" "strconv" ) +var ( + errInvalidNumber = errors.New("json: invalid number literal") + errNotNumber = errors.New("json: cannot unmarshal into jsonx.Number") +) + // V1 is the full option set that reproduces encoding/json v1 behavior. func V1() json.Options { return jsonv1.DefaultOptionsV1() @@ -66,7 +72,7 @@ func (n Number) MarshalJSON() ([]byte, error) { } if !jsontext.Value(n).IsValid() || jsontext.Value(n).Kind() != '0' { - return nil, fmt.Errorf("json: invalid number literal %q", string(n)) + return nil, fmt.Errorf("%w %q", errInvalidNumber, string(n)) } return []byte(n), nil @@ -86,13 +92,13 @@ func (n *Number) UnmarshalJSON(b []byte) error { } if lit := jsontext.Value(s); !lit.IsValid() || lit.Kind() != '0' { - return fmt.Errorf("json: invalid number literal %q", string(s)) + return fmt.Errorf("%w %q", errInvalidNumber, string(s)) } *n = Number(s) case 'n': default: - return fmt.Errorf("json: cannot unmarshal %s into Go value of type jsonx.Number", v.Kind()) + return fmt.Errorf("%w: %s", errNotNumber, v.Kind()) } return nil diff --git a/pkgs/jsonx/jsonx_test.go b/pkgs/jsonx/jsonx_test.go index 34af9c09cc..64237b7e29 100644 --- a/pkgs/jsonx/jsonx_test.go +++ b/pkgs/jsonx/jsonx_test.go @@ -16,9 +16,9 @@ func TestV1Semantics(t *testing.T) { t.Parallel() type in struct { - S []int `json:"s"` - M map[string]int `json:"m"` H string `json:"h"` + M map[string]int `json:"m"` + S []int `json:"s"` } b, err := json.Marshal(in{H: "<&>"}, jsonx.V1()) @@ -41,7 +41,8 @@ func TestUseNumber(t *testing.T) { var got any - err := json.Unmarshal([]byte(`{"a":1.50,"b":[2,"x",true,null,{"c":3}],"d":"s"}`), &got, jsonx.V1(), jsonx.UseNumber()) + doc := `{"a":1.50,"b":[2,"x",true,null,{"c":3}],"d":"s"}` + err := json.Unmarshal([]byte(doc), &got, jsonx.V1(), jsonx.UseNumber()) require.NoError(t, err) m, ok := got.(map[string]any) diff --git a/pkgs/registryauth/resolver.go b/pkgs/registryauth/resolver.go index 0e8a6cc3f8..9ef72126c4 100644 --- a/pkgs/registryauth/resolver.go +++ b/pkgs/registryauth/resolver.go @@ -50,7 +50,7 @@ func (r *Resolver) RegisterEmulated(host, user, pass string) { } func encodeAuth(ac authConfig) string { - raw, err := json.Marshal(ac, jsonx.V1()) //nolint:gosec // credentials are the payload of the X-Registry-Auth header + raw, err := json.Marshal(ac, jsonx.V1()) if err != nil { return "" } diff --git a/pkgs/service/jsondisp_golden_test.go b/pkgs/service/jsondisp_golden_test.go index 708d19712d..6623e92abb 100644 --- a/pkgs/service/jsondisp_golden_test.go +++ b/pkgs/service/jsondisp_golden_test.go @@ -2,6 +2,7 @@ package service_test import ( "context" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -21,10 +22,14 @@ type goldenSendInput struct { func TestJSONErrorResponseGolden(t *testing.T) { t.Parallel() - b, err := service.JSONErrorResponse{Type: "com.amazonaws.sqs#QueueDoesNotExist", Message: "queue & y"}.MarshalJSON() + resp := service.JSONErrorResponse{Type: "com.amazonaws.sqs#QueueDoesNotExist", Message: "queue & y"} + b, err := resp.MarshalJSON() require.NoError(t, err) - assert.Equal(t, `{"__type":"com.amazonaws.sqs#QueueDoesNotExist","message":"queue \u003cx\u003e \u0026 y","Message":"queue \u003cx\u003e \u0026 y"}`, string(b)) + esc := strings.NewReplacer("<", "\\u003c", ">", "\\u003e", "&", "\\u0026").Replace("queue & y") + want := `{"__type":"com.amazonaws.sqs#QueueDoesNotExist","message":"` + esc + `","Message":"` + esc + `"}` + + assert.Equal(t, want, string(b)) } func TestHandleJSONGoldenDecode(t *testing.T) { @@ -36,13 +41,23 @@ func TestHandleJSONGoldenDecode(t *testing.T) { want goldenSendInput wantErr string }{ - {name: "basic", body: `{"QueueUrl":"u","MessageBody":"b","DelaySeconds":5,"MessageAttributes":{"a":"b"}}`, - want: goldenSendInput{QueueURL: "u", MessageBody: "b", DelaySeconds: new(int32(5)), Attributes: map[string]string{"a": "b"}}}, + { + name: "basic", + body: `{"QueueUrl":"u","MessageBody":"b","DelaySeconds":5,"MessageAttributes":{"a":"b"}}`, + want: goldenSendInput{ + QueueURL: "u", MessageBody: "b", DelaySeconds: new(int32(5)), + Attributes: map[string]string{"a": "b"}, + }, + }, {name: "case insensitive and unknown", body: `{"queueurl":"u","MESSAGEBODY":"b","extra":1}`, want: goldenSendInput{QueueURL: "u", MessageBody: "b"}}, {name: "null members", body: `{"QueueUrl":null,"MessageAttributes":null}`, want: goldenSendInput{}}, {name: "empty body", body: ``, want: goldenSendInput{}}, - {name: "type mismatch", body: `{"QueueUrl":5}`, wantErr: "json: cannot unmarshal number into Go struct field goldenSendInput.QueueUrl of type string"}, + { + name: "type mismatch", + body: `{"QueueUrl":5}`, + wantErr: "json: cannot unmarshal number into Go struct field goldenSendInput.QueueUrl of type string", + }, {name: "truncated", body: `{"QueueUrl":`, wantErr: "unexpected end of JSON input"}, } From c76368438fdfdc8c64c6f35186a51ff1f2a8c3d7 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 12:03:25 -0600 Subject: [PATCH 04/11] fix(wfinterp): buffer the cancellation test start signal; keep ParseJSON trailing-data check equal to Decoder.More TestCancellationInterruptsSleep dropped its only Progress signal when the run goroutine fired before the test reached the receive, then hung. ParseJSON used PeekKind()!=0, which accepts trailing garbage that v1 More() rejected. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/wfinterp/flow_test.go | 2 +- pkgs/wfinterp/parsejson_test.go | 41 +++++++++++++++++++++++++++++++++ pkgs/wfinterp/value.go | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 pkgs/wfinterp/parsejson_test.go diff --git a/pkgs/wfinterp/flow_test.go b/pkgs/wfinterp/flow_test.go index 12d635a658..a57f6ea78d 100644 --- a/pkgs/wfinterp/flow_test.go +++ b/pkgs/wfinterp/flow_test.go @@ -402,7 +402,7 @@ main: require.NoError(t, err) ctx, cancel := context.WithCancel(t.Context()) - started := make(chan struct{}) + started := make(chan struct{}, 1) host := &wfinterp.Host{ Clock: &blockingClock{}, Progress: func(f []wfinterp.Frame) { diff --git a/pkgs/wfinterp/parsejson_test.go b/pkgs/wfinterp/parsejson_test.go new file mode 100644 index 0000000000..946b9adacd --- /dev/null +++ b/pkgs/wfinterp/parsejson_test.go @@ -0,0 +1,41 @@ +package wfinterp_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/wfinterp" +) + +func TestParseJSONTrailingData(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + in string + wantErr bool + }{ + {name: "single", in: `{"a":1}`}, + {name: "trailing_space", in: "{\"a\":1} \n"}, + {name: "second_value", in: `{"a":1} {"b":2}`, wantErr: true}, + {name: "garbage", in: `{"a":1} x`, wantErr: true}, + {name: "invalid", in: `{"a":`, wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + _, err := wfinterp.ParseJSON([]byte(tt.in)) + if tt.wantErr { + require.Error(t, err) + + return + } + + assert.NoError(t, err) + }) + } +} diff --git a/pkgs/wfinterp/value.go b/pkgs/wfinterp/value.go index 7bb508b770..bfc661cff0 100644 --- a/pkgs/wfinterp/value.go +++ b/pkgs/wfinterp/value.go @@ -175,7 +175,7 @@ func ParseJSON(raw []byte) (any, error) { return nil, fmt.Errorf("invalid JSON: %w", err) } - if dec.PeekKind() != 0 { + if rest := bytes.TrimLeft(raw[dec.InputOffset():], " \t\r\n"); len(rest) > 0 && rest[0] != ']' && rest[0] != '}' { return nil, fmt.Errorf("invalid JSON: %w", errTrailingJSON) } From 36ed5241ba5821972b68bb4a637c5df2cd74dd31 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 12:23:49 -0600 Subject: [PATCH 05/11] refactor(json): move services a-l to encoding/json/v2 with v1-equivalent options Codemod plus hand fixes for streaming decoders, Indent/Compact and error classification. jsonx gains SyntaxError/TypeError (v2 with V1 options still returns the v1 error types) and SDKDecoder for SDK helpers taking *json.Decoder. Snapshot inventory golden updated for json.RawMessage -> jsontext.Value. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/jsonx/jsonx.go | 54 +- pkgs/jsonx/jsonx_test.go | 49 ++ .../testdata/snapshot_inventory.json | 534 +++++++++--------- services/accessanalyzer/access_previews.go | 4 +- .../accessanalyzer/analyzer_validation.go | 17 +- services/accessanalyzer/analyzers.go | 10 +- services/accessanalyzer/analyzers_test.go | 6 +- services/accessanalyzer/handler.go | 5 +- .../accessanalyzer/handler_access_previews.go | 13 +- .../handler_access_previews_test.go | 15 +- .../handler_analyzed_resources.go | 8 +- .../handler_analyzed_resources_test.go | 7 +- services/accessanalyzer/handler_analyzers.go | 17 +- .../accessanalyzer/handler_analyzers_test.go | 13 +- .../accessanalyzer/handler_archive_rules.go | 10 +- services/accessanalyzer/handler_findings.go | 12 +- .../accessanalyzer/handler_findings_test.go | 17 +- .../handler_generated_policies.go | 6 +- .../handler_generated_policies_test.go | 21 +- .../handler_policy_validation.go | 12 +- .../handler_policy_validation_test.go | 12 +- services/accessanalyzer/handler_tags.go | 6 +- services/accessanalyzer/handler_test.go | 5 +- services/accessanalyzer/interfaces.go | 10 +- services/accessanalyzer/models.go | 8 +- services/accessanalyzer/persistence.go | 6 +- services/accessanalyzer/persistence_test.go | 8 +- services/accessanalyzer/policy_analysis.go | 47 +- .../accessanalyzer/policy_analysis_test.go | 15 +- services/account/handler.go | 5 +- services/account/handler_account_info_test.go | 26 +- services/account/handler_contacts_test.go | 9 +- services/account/handler_regions_test.go | 16 +- services/account/handler_test.go | 6 +- services/account/persistence.go | 32 +- services/account/validation_test.go | 5 +- .../acm/acme_domain_validation_status_test.go | 14 +- ...ificate_detail_no_fabricated_keyid_test.go | 17 +- services/acm/certificate_validation_test.go | 18 +- services/acm/handler.go | 12 +- services/acm/handler_account.go | 6 +- services/acm/handler_acme_accounts.go | 10 +- .../acm/handler_acme_domain_validations.go | 13 +- services/acm/handler_acme_eab.go | 15 +- services/acm/handler_acme_endpoints.go | 13 +- .../acm/handler_certificate_lifecycle_test.go | 77 +-- .../handler_certificate_status_errors_test.go | 51 +- services/acm/handler_certificates.go | 28 +- .../acm/handler_certificates_list_test.go | 37 +- services/acm/handler_certificates_test.go | 88 +-- ...uest_certificate_invalid_parameter_test.go | 12 +- services/acm/handler_resource_tags.go | 9 +- services/acm/handler_search_certificates.go | 6 +- services/acm/handler_tags.go | 9 +- services/acm/handler_tags_test.go | 38 +- services/acm/handler_test.go | 113 ++-- services/acm/persistence.go | 14 +- services/acm/persistence_test.go | 15 +- .../acm/request_certificate_realism_test.go | 8 +- services/acm/wire_field_additions_test.go | 29 +- services/acmpca/handler.go | 14 +- services/acmpca/handler_audit_reports.go | 8 +- services/acmpca/handler_ca_policy.go | 10 +- .../acmpca/handler_certificate_authorities.go | 28 +- .../handler_certificate_authorities_test.go | 9 +- services/acmpca/handler_certificates.go | 10 +- services/acmpca/handler_certificates_test.go | 9 +- services/acmpca/handler_permissions.go | 10 +- services/acmpca/handler_tags.go | 9 +- services/acmpca/handler_test.go | 9 +- services/acmpca/persistence.go | 6 +- services/amp/dataplane_status_http.go | 5 +- services/amp/dataplane_test.go | 10 +- services/amp/persistence.go | 10 +- services/amp/rules_eval_test.go | 14 +- services/amp/series_json.go | 9 +- services/amp/validate.go | 5 +- services/amplify/handler_apps.go | 7 +- services/amplify/handler_apps_test.go | 13 +- services/amplify/handler_artifacts.go | 5 +- services/amplify/handler_artifacts_test.go | 6 +- services/amplify/handler_branches.go | 7 +- services/amplify/handler_branches_test.go | 9 +- services/amplify/handler_deployments.go | 7 +- services/amplify/handler_deployments_test.go | 8 +- services/amplify/handler_domains.go | 7 +- services/amplify/handler_domains_test.go | 10 +- services/amplify/handler_environments.go | 5 +- services/amplify/handler_environments_test.go | 8 +- services/amplify/handler_jobs.go | 5 +- services/amplify/handler_jobs_test.go | 17 +- services/amplify/handler_tags.go | 5 +- services/amplify/handler_test.go | 7 +- services/amplify/handler_webhooks.go | 7 +- services/amplify/handler_webhooks_test.go | 10 +- services/amplify/persistence.go | 10 +- services/amplify/sent_keys.go | 12 +- services/amplify/wire_shape_test.go | 7 +- services/apigateway/api_keys_test.go | 18 +- services/apigateway/authorizers_test.go | 5 +- .../apigateway/client_certificates_test.go | 9 +- services/apigateway/deployments_test.go | 24 +- services/apigateway/documentation_test.go | 8 +- services/apigateway/domain_names_test.go | 14 +- services/apigateway/error_envelope_test.go | 5 +- services/apigateway/export_test.go | 7 +- services/apigateway/gateway_responses_test.go | 11 +- services/apigateway/handler.go | 48 +- services/apigateway/handler_account.go | 6 +- services/apigateway/handler_api_keys.go | 14 +- services/apigateway/handler_authorizers.go | 16 +- .../apigateway/handler_base_path_mappings.go | 14 +- .../apigateway/handler_client_certificates.go | 14 +- services/apigateway/handler_deployments.go | 14 +- services/apigateway/handler_documentation.go | 24 +- services/apigateway/handler_domain_names.go | 24 +- services/apigateway/handler_export.go | 8 +- services/apigateway/handler_fixtures_test.go | 13 +- .../apigateway/handler_gateway_responses.go | 14 +- services/apigateway/handler_import_export.go | 9 +- .../apigateway/handler_import_export_test.go | 23 +- services/apigateway/handler_integrations.go | 20 +- services/apigateway/handler_methods.go | 26 +- .../apigateway/handler_request_validators.go | 14 +- services/apigateway/handler_resources.go | 14 +- services/apigateway/handler_rest_apis.go | 13 +- services/apigateway/handler_router_test.go | 11 +- services/apigateway/handler_schema_models.go | 16 +- services/apigateway/handler_sdk.go | 12 +- services/apigateway/handler_stages.go | 18 +- services/apigateway/handler_tags.go | 9 +- services/apigateway/handler_test.go | 61 +- services/apigateway/handler_usage.go | 8 +- services/apigateway/handler_usage_plans.go | 22 +- services/apigateway/handler_vpc_links.go | 14 +- services/apigateway/import.go | 52 +- services/apigateway/import_test.go | 8 +- services/apigateway/integrations_test.go | 16 +- services/apigateway/invoke_stage_test.go | 5 +- services/apigateway/methods_test.go | 7 +- services/apigateway/models.go | 9 +- services/apigateway/multi_region_test.go | 5 +- services/apigateway/patch.go | 119 ++-- services/apigateway/persistence.go | 4 +- services/apigateway/proxy.go | 11 +- services/apigateway/proxy_authorizer.go | 10 +- .../proxy_authorizer_cache_internal_test.go | 8 +- services/apigateway/proxy_authorizer_test.go | 21 +- services/apigateway/proxy_integrations.go | 32 +- services/apigateway/proxy_mapping_test.go | 9 +- services/apigateway/proxy_test.go | 33 +- services/apigateway/proxy_validation.go | 8 +- services/apigateway/proxy_validation_test.go | 7 +- .../apigateway/request_validators_test.go | 5 +- services/apigateway/resources_test.go | 12 +- .../apigateway/rest_api_policy_wire_test.go | 9 +- services/apigateway/rest_apis_test.go | 10 +- .../apigateway/route_matcher_proxy_test.go | 5 +- services/apigateway/schema_models.go | 15 +- services/apigateway/schema_models_test.go | 11 +- services/apigateway/sdk.go | 7 +- services/apigateway/sdk_test.go | 7 +- services/apigateway/stages_test.go | 10 +- services/apigateway/store_test.go | 5 +- services/apigateway/tags_test.go | 13 +- services/apigateway/test_invoke.go | 11 +- services/apigateway/test_invoke_test.go | 5 +- services/apigateway/usage_plans_test.go | 14 +- services/apigateway/usage_test.go | 13 +- services/apigateway/validation.go | 12 +- services/apigateway/vpc_links_test.go | 15 +- services/apigateway/vtl_values.go | 62 +- services/apigatewaymanagementapi/admin.go | 9 +- .../apigatewaymanagementapi/admin_test.go | 25 +- .../error_messages_test.go | 5 +- .../apigatewaymanagementapi/handler_test.go | 26 +- .../ringbuffer_test.go | 5 +- .../authorizer_cache_internal_test.go | 6 +- services/apigatewayv2/authorizer_context.go | 8 +- services/apigatewayv2/authorizers.go | 15 +- services/apigatewayv2/custom_domain_test.go | 7 +- services/apigatewayv2/custom_id_test.go | 5 +- services/apigatewayv2/handler.go | 10 +- .../apigatewayv2/handler_api_mappings_test.go | 13 +- .../apigatewayv2/handler_api_models_test.go | 23 +- services/apigatewayv2/handler_apis.go | 16 +- services/apigatewayv2/handler_apis_test.go | 49 +- .../apigatewayv2/handler_authorizers_test.go | 19 +- .../apigatewayv2/handler_deployments_test.go | 25 +- .../apigatewayv2/handler_domain_names_test.go | 18 +- .../handler_export_api_sdk_test.go | 7 +- .../handler_integration_responses_test.go | 25 +- .../apigatewayv2/handler_integrations_test.go | 17 +- services/apigatewayv2/handler_portals.go | 13 +- services/apigatewayv2/handler_portals_test.go | 51 +- .../handler_route_responses_test.go | 25 +- services/apigatewayv2/handler_routes_test.go | 35 +- services/apigatewayv2/handler_stages_test.go | 9 +- services/apigatewayv2/handler_tags.go | 6 +- services/apigatewayv2/handler_tags_test.go | 6 +- services/apigatewayv2/handler_test.go | 7 +- .../apigatewayv2/handler_vpc_links_test.go | 20 +- services/apigatewayv2/http_proxy.go | 7 +- .../apigatewayv2/http_proxy_flows_test.go | 13 +- services/apigatewayv2/http_proxy_test.go | 57 +- .../apigatewayv2/http_proxy_throttle_test.go | 5 +- services/apigatewayv2/lambda_response.go | 17 +- services/apigatewayv2/models.go | 8 +- services/apigatewayv2/multi_region_test.go | 5 +- services/apigatewayv2/persistence.go | 8 +- services/apigatewayv2/rse.go | 6 +- .../wire_field_fixes_respsweep_test.go | 17 +- .../apigatewayv2/wire_field_fixes_test.go | 9 +- services/apigatewayv2/ws_proxy.go | 15 +- services/apigatewayv2/ws_realclient_test.go | 7 +- .../appconfig/deletion_protection_test.go | 9 +- .../appconfig/errsweep_wire_shape_test.go | 5 +- services/appconfig/extension_actions.go | 10 +- services/appconfig/extension_actions_test.go | 5 +- services/appconfig/extension_events.go | 16 +- services/appconfig/extension_events_test.go | 11 +- services/appconfig/extension_sibling_test.go | 5 +- services/appconfig/feature_flags.go | 12 +- .../handler_account_settings_test.go | 13 +- .../appconfig/handler_applications_test.go | 31 +- .../handler_configuration_profiles_test.go | 49 +- .../appconfig/handler_configuration_test.go | 21 +- .../handler_deployment_strategies_test.go | 15 +- .../appconfig/handler_deployments_test.go | 65 +-- .../appconfig/handler_environments_test.go | 45 +- services/appconfig/handler_extensions_test.go | 57 +- ...dler_hosted_configuration_versions_test.go | 19 +- .../appconfig/handler_list_summary_test.go | 33 +- services/appconfig/handler_tags_test.go | 11 +- services/appconfig/handler_test.go | 19 +- services/appconfig/persistence.go | 4 +- services/appconfigdata/configuration.go | 6 +- services/appconfigdata/configuration_test.go | 13 +- services/appconfigdata/errors_test.go | 17 +- services/appconfigdata/handler.go | 6 +- .../handler_sdk_route_table_test.go | 6 +- services/appconfigdata/handler_test.go | 9 +- services/appconfigdata/persistence.go | 6 +- services/appconfigdata/sessions_test.go | 25 +- services/appconfigdata/store.go | 7 +- services/appintegrations/persistence.go | 10 +- .../applicationautoscaling/errors_test.go | 11 +- services/applicationautoscaling/handler.go | 13 +- .../handler_forecast_test.go | 6 +- .../handler_scalable_targets_describe_test.go | 32 +- .../handler_scalable_targets_test.go | 26 +- .../handler_scaling_policies_test.go | 30 +- .../handler_scheduled_actions_test.go | 28 +- .../handler_tags_test.go | 28 +- .../applicationautoscaling/handler_test.go | 9 +- .../multi_region_test.go | 5 +- .../applicationautoscaling/persistence.go | 10 +- .../persistence_test.go | 5 +- .../scaling_activities_test.go | 15 +- services/appmesh/handler.go | 8 +- services/appmesh/handler_meshes.go | 14 +- services/appmesh/handler_test.go | 7 +- services/appmesh/handler_virtual_gateways.go | 26 +- services/appmesh/handler_virtual_nodes.go | 14 +- services/appmesh/handler_virtual_routers.go | 26 +- services/appmesh/handler_virtual_services.go | 14 +- services/appmesh/interfaces.go | 44 +- services/appmesh/meshes.go | 6 +- services/appmesh/meshes_test.go | 4 +- services/appmesh/persistence.go | 4 +- services/appmesh/spec_schema.go | 8 +- services/appmesh/spec_schema_test.go | 6 +- services/appmesh/spec_validate.go | 16 +- services/appmesh/spec_validate_test.go | 14 +- services/appmesh/store.go | 6 +- services/appmesh/virtual_gateways.go | 10 +- services/appmesh/virtual_gateways_test.go | 6 +- services/appmesh/virtual_nodes.go | 10 +- services/appmesh/virtual_routers.go | 10 +- services/appmesh/virtual_routers_test.go | 6 +- services/appmesh/virtual_services.go | 6 +- services/appmesh/virtual_services_test.go | 4 +- services/apprunner/handler.go | 11 +- ...andler_auto_scaling_configurations_test.go | 36 +- .../apprunner/handler_connections_test.go | 18 +- .../apprunner/handler_custom_domains_test.go | 14 +- ...ndler_observability_configurations_test.go | 26 +- services/apprunner/handler_operations_test.go | 6 +- services/apprunner/handler_services_test.go | 85 +-- services/apprunner/handler_tags_test.go | 8 +- services/apprunner/handler_test.go | 7 +- .../apprunner/handler_vpc_connectors_test.go | 18 +- .../handler_vpc_ingress_connections_test.go | 22 +- services/apprunner/multi_region_test.go | 5 +- ...ability_configuration_summary_wire_test.go | 5 +- services/apprunner/persistence.go | 4 +- .../apprunner/vpc_ingress_service_arn_test.go | 6 +- .../wire_output_required_r80d_test.go | 7 +- services/appstream/app_blocks_test.go | 27 +- services/appstream/applications_test.go | 19 +- services/appstream/directory_configs_test.go | 13 +- services/appstream/entitlements_test.go | 13 +- services/appstream/fleets_test.go | 41 +- services/appstream/handler.go | 39 +- services/appstream/handler_appblock.go | 29 +- services/appstream/handler_application.go | 41 +- services/appstream/handler_image.go | 45 +- services/appstream/handler_test.go | 25 +- services/appstream/handler_user.go | 37 +- services/appstream/images_test.go | 35 +- services/appstream/persistence.go | 4 +- services/appstream/rpcv2cbor.go | 7 +- services/appstream/sessions_test.go | 15 +- services/appstream/stacks_test.go | 15 +- services/appstream/tags_test.go | 17 +- services/appstream/themes_test.go | 5 +- .../usage_report_subscriptions_test.go | 9 +- services/appstream/users_test.go | 27 +- services/appsync/api_keys_test.go | 7 +- services/appsync/auth.go | 7 +- services/appsync/auth_test.go | 7 +- services/appsync/caching_test.go | 5 +- services/appsync/data_sources_config_test.go | 7 +- services/appsync/ddb_ops.go | 10 +- services/appsync/ddb_resolver_flow_test.go | 7 +- services/appsync/ddb_transact.go | 8 +- services/appsync/domain_names_test.go | 5 +- services/appsync/ds_external.go | 10 +- services/appsync/ds_external_test.go | 18 +- services/appsync/ds_http.go | 5 +- services/appsync/ds_rds.go | 6 +- services/appsync/evaluation.go | 8 +- services/appsync/evaluation_logs_test.go | 6 +- services/appsync/export_test.go | 8 +- services/appsync/functions_test.go | 7 +- services/appsync/graphql.go | 22 +- services/appsync/graphql_apis_config_test.go | 7 +- services/appsync/handler_api_keys.go | 7 +- services/appsync/handler_api_keys_test.go | 14 +- services/appsync/handler_caching.go | 7 +- services/appsync/handler_caching_test.go | 10 +- .../appsync/handler_channel_namespaces.go | 7 +- .../handler_channel_namespaces_test.go | 12 +- services/appsync/handler_data_sources.go | 9 +- services/appsync/handler_data_sources_test.go | 14 +- services/appsync/handler_domain_names.go | 9 +- services/appsync/handler_domain_names_test.go | 12 +- services/appsync/handler_evaluation.go | 7 +- services/appsync/handler_events.go | 7 +- services/appsync/handler_events_test.go | 19 +- services/appsync/handler_functions.go | 7 +- services/appsync/handler_functions_test.go | 12 +- services/appsync/handler_graphql_apis.go | 9 +- services/appsync/handler_graphql_apis_test.go | 30 +- services/appsync/handler_resolvers.go | 7 +- services/appsync/handler_resolvers_test.go | 12 +- services/appsync/handler_routing_test.go | 16 +- services/appsync/handler_schema.go | 5 +- services/appsync/handler_schema_test.go | 14 +- services/appsync/handler_schema_types.go | 7 +- services/appsync/handler_schema_types_test.go | 14 +- .../handler_source_api_associations.go | 9 +- .../handler_source_api_associations_test.go | 20 +- services/appsync/handler_tags.go | 5 +- services/appsync/handler_tags_test.go | 8 +- services/appsync/helpers_test.go | 9 +- services/appsync/identity_test.go | 5 +- services/appsync/introspection.go | 6 +- services/appsync/introspection_test.go | 8 +- services/appsync/jseval_test.go | 6 +- services/appsync/lambda_batch.go | 8 +- services/appsync/lambda_batch_test.go | 10 +- services/appsync/models.go | 16 +- services/appsync/multi_region_test.go | 10 +- services/appsync/nested_resolver_test.go | 5 +- services/appsync/null_propagation_test.go | 5 +- services/appsync/persistence.go | 4 +- services/appsync/realtime.go | 17 +- services/appsync/realtime_test.go | 9 +- services/appsync/resolver_cache.go | 8 +- services/appsync/resolver_cache_test.go | 7 +- services/appsync/resolver_runtime_e2e_test.go | 5 +- services/appsync/resolvers_config_test.go | 7 +- services/appsync/schema_types_test.go | 7 +- services/appsync/subscription_filter.go | 8 +- services/appsync/subscription_filter_test.go | 7 +- services/appsync/util_ddb.go | 6 +- services/appsync/util_esdsl.go | 6 +- services/appsync/util_extra.go | 15 +- services/appsync/util_funcs.go | 10 +- services/appsync/util_rds.go | 8 +- services/appsync/vtl.go | 10 +- services/appsync/vtl_eval.go | 12 +- services/appsync/wire_field_fixes_test.go | 8 +- services/appsync/wire_shape.go | 10 +- services/appsync/wire_shape_test.go | 5 +- services/arczonalshift/handler_ops.go | 8 +- services/arczonalshift/managed_more.go | 5 +- .../arczonalshift/managed_resources_test.go | 10 +- services/arczonalshift/misc_test.go | 5 +- services/arczonalshift/persistence.go | 6 +- services/athena/audit_athena_test.go | 12 +- services/athena/client_token_test.go | 8 +- services/athena/ddl_test.go | 9 +- services/athena/engine_complex.go | 12 +- services/athena/engine_funcs_agg.go | 6 +- services/athena/engine_funcs_json.go | 12 +- services/athena/engine_iceberg_meta.go | 7 +- services/athena/engine_load.go | 14 +- services/athena/engine_parquet.go | 5 +- services/athena/engine_write_format.go | 8 +- services/athena/error_codes_test.go | 6 +- services/athena/handler.go | 9 +- services/athena/handler_calculations.go | 18 +- .../athena/handler_capacity_reservations.go | 22 +- .../handler_capacity_reservations_test.go | 13 +- services/athena/handler_data_catalogs.go | 16 +- services/athena/handler_data_catalogs_test.go | 21 +- services/athena/handler_databases.go | 14 +- services/athena/handler_named_queries.go | 16 +- services/athena/handler_named_queries_test.go | 23 +- services/athena/handler_notebooks.go | 22 +- services/athena/handler_notebooks_test.go | 13 +- .../athena/handler_prepared_statements.go | 16 +- .../handler_prepared_statements_test.go | 13 +- services/athena/handler_query_executions.go | 18 +- .../athena/handler_query_executions_test.go | 37 +- services/athena/handler_sessions.go | 28 +- services/athena/handler_sessions_test.go | 13 +- services/athena/handler_tags.go | 12 +- services/athena/handler_tags_test.go | 9 +- services/athena/handler_test.go | 11 +- services/athena/handler_work_groups.go | 16 +- services/athena/handler_work_groups_test.go | 23 +- services/athena/multi_region_test.go | 5 +- services/athena/pagination_opaque_test.go | 9 +- services/athena/persistence.go | 6 +- services/athena/prepared_exec_test.go | 5 +- services/athena/query_results_test.go | 15 +- services/athena/result_object.go | 6 +- services/autoscaling/persistence.go | 4 +- services/awsconfig/accounts.go | 18 +- .../awsconfig/conformance_pack_template.go | 17 +- services/awsconfig/delivery_status.go | 7 +- services/awsconfig/evaluation.go | 10 +- services/awsconfig/evaluation_test.go | 15 +- services/awsconfig/handler.go | 19 +- .../awsconfig/handler_config_rules_test.go | 16 +- .../handler_configuration_recorders.go | 9 +- .../handler_configuration_recorders_test.go | 32 +- .../handler_conformance_packs_test.go | 9 +- .../awsconfig/handler_delivery_channels.go | 7 +- .../handler_delivery_channels_test.go | 10 +- .../awsconfig/handler_remediation_test.go | 5 +- .../awsconfig/handler_stored_queries_test.go | 6 +- services/awsconfig/handler_test.go | 5 +- services/awsconfig/multi_region_test.go | 5 +- services/awsconfig/persistence.go | 8 +- services/awsconfig/select_query.go | 8 +- services/awsconfig/select_query_test.go | 7 +- services/awsconfig/tags_test.go | 6 +- services/azureappconfig/http_test.go | 6 +- services/azureappconfig/server.go | 8 +- services/azurearm/aci_wire.go | 18 +- services/azurearm/aci_wire_ext.go | 12 +- services/azurearm/aks_sdk_test.go | 5 +- services/azurearm/apim_asyncop_test.go | 6 +- services/azurearm/apim_gateway_test.go | 11 +- services/azurearm/apim_policy_test.go | 11 +- services/azurearm/apim_sources_test.go | 16 +- services/azurearm/directory_test.go | 5 +- services/azurearm/export_test.go | 28 +- services/azurearm/flexdb_mysql_test.go | 6 +- services/azurearm/flexdb_pg_test.go | 6 +- services/azurearm/flexdb_stack_test.go | 5 +- services/azurearm/handler.go | 6 +- services/azurearm/handler_test.go | 11 +- services/azurearm/rp_aks.go | 5 +- services/azurearm/rp_aks_persist.go | 10 +- services/azurearm/rp_apim_exec.go | 8 +- services/azurearm/rp_apim_gateway.go | 9 +- services/azurearm/rp_apim_import.go | 6 +- services/azurearm/rp_apim_persist.go | 20 +- services/azurearm/rp_authorization.go | 7 +- .../azurearm/rp_authorization_sdk_test.go | 5 +- services/azurearm/rp_compute_ext_test.go | 8 +- services/azurearm/rp_compute_sets_test.go | 9 +- services/azurearm/rp_containerapps_app.go | 5 +- services/azurearm/rp_containerapps_persist.go | 10 +- .../azurearm/rp_containerapps_revision.go | 4 +- services/azurearm/rp_containerapps_wire.go | 8 +- services/azurearm/rp_cosmos_sql.go | 8 +- services/azurearm/rp_cosmos_test.go | 9 +- services/azurearm/rp_identity_sdk_test.go | 7 +- services/azurearm/rp_keyvault_deleted_test.go | 7 +- services/azurearm/rp_monitor_test.go | 7 +- services/azurearm/rp_network_pe_sdk_test.go | 7 +- services/azurearm/rp_network_sdk_test.go | 6 +- services/azurearm/rp_redis_test.go | 7 +- services/azurearm/rp_sql_test.go | 7 +- .../azurecontainerregistry/acrapi_test.go | 5 +- .../azurecontainerregistry/helpers_test.go | 5 +- services/azurecontainerregistry/hooks.go | 5 +- services/azurecontainerregistry/serve.go | 8 +- services/azurecontainerregistry/webhooks.go | 5 +- .../azurecontainerregistry/webhooks_test.go | 7 +- services/azureeventgrid/armscope_test.go | 5 +- services/azureeventgrid/attributes.go | 10 +- services/azureeventgrid/batching_test.go | 11 +- services/azureeventgrid/deadletter.go | 8 +- services/azureeventgrid/delivery_test.go | 32 +- services/azureeventgrid/domains_test.go | 9 +- services/azureeventgrid/filter.go | 7 +- services/azureeventgrid/filter_test.go | 5 +- services/azureeventgrid/helpers_test.go | 5 +- services/azureeventgrid/http_routes.go | 11 +- services/azureeventgrid/model.go | 30 +- services/azureeventgrid/publish.go | 19 +- services/azureeventgrid/pull.go | 14 +- services/azureeventgrid/subscription.go | 16 +- services/azureeventgrid/webhook.go | 8 +- services/azureeventhubs/http_routes.go | 11 +- services/azurefile/ops_share.go | 12 +- services/azurefunctions/functions.go | 5 +- services/azurefunctions/keys.go | 8 +- services/azurefunctions/keys_test.go | 5 +- services/azurefunctions/kudu.go | 6 +- services/azurefunctions/kudu_test.go | 7 +- services/azurefunctions/webapp.go | 5 +- services/azurefunctions/zip.go | 6 +- services/azuregraph/apps.go | 6 +- services/azuregraph/assign.go | 8 +- services/azuregraph/collections.go | 19 +- services/azuregraph/groups.go | 6 +- services/azuregraph/helpers_test.go | 7 +- services/azuregraph/model.go | 36 +- services/azuregraph/patch.go | 28 +- services/azuregraph/relations.go | 11 +- services/azuregraph/routes.go | 13 +- services/azuregraph/routes_sub.go | 15 +- services/azuregraph/sps.go | 6 +- services/azuregraph/users.go | 8 +- services/azurekeyvault/backup.go | 8 +- services/azurekeyvault/handler.go | 5 +- services/azuremonitor/backend.go | 7 +- services/azuremonitor/handler.go | 13 +- services/azuremonitor/ingest.go | 8 +- services/azuremonitor/kql/funcs.go | 10 +- services/azuremonitor/kql/golden_test.go | 5 +- services/azuremonitor/kql/parser.go | 8 +- services/azuremonitor/kql/value.go | 10 +- services/azuremonitor/sdk_test.go | 7 +- services/azureservicebus/handler.go | 9 +- services/azureservicebus/handler_test.go | 5 +- services/azureservicebus/receive_handlers.go | 6 +- services/azureservicebus/receive_test.go | 5 +- services/azuretable/batch.go | 5 +- services/azuretable/entity_ops_test.go | 23 +- services/azuretable/handler.go | 7 +- services/azuretable/models_test.go | 11 +- services/azuretable/sdk_wire_test.go | 9 +- services/azuretable/table_ops.go | 5 +- services/azuretable/table_ops_test.go | 14 +- services/backup/async_jobs.go | 4 +- services/backup/backup_plans.go | 5 +- services/backup/copy_jobs.go | 4 +- services/backup/ddb_item_codec.go | 15 +- .../backup/handler_backup_access_points.go | 6 +- services/backup/handler_backup_jobs.go | 6 +- services/backup/handler_backup_jobs_test.go | 7 +- services/backup/handler_backup_plans.go | 12 +- services/backup/handler_backup_plans_test.go | 21 +- services/backup/handler_copy_jobs.go | 6 +- services/backup/handler_copy_jobs_test.go | 7 +- services/backup/handler_dispatch.go | 10 +- services/backup/handler_frameworks.go | 8 +- services/backup/handler_frameworks_test.go | 7 +- services/backup/handler_legal_holds.go | 6 +- services/backup/handler_recovery_points.go | 8 +- .../backup/handler_recovery_points_test.go | 5 +- services/backup/handler_report_plans.go | 10 +- services/backup/handler_report_plans_test.go | 11 +- services/backup/handler_restore_jobs.go | 8 +- services/backup/handler_restore_testing.go | 12 +- services/backup/handler_selections.go | 6 +- services/backup/handler_selections_test.go | 11 +- services/backup/handler_settings.go | 8 +- services/backup/handler_tags.go | 8 +- services/backup/handler_templates_test.go | 17 +- services/backup/handler_tiering.go | 8 +- services/backup/handler_vault_policies.go | 10 +- .../backup/handler_vault_policies_test.go | 5 +- services/backup/handler_vaults.go | 12 +- services/backup/handler_vaults_test.go | 11 +- services/backup/helpers_test.go | 7 +- services/backup/models.go | 4 +- services/backup/multi_region_test.go | 5 +- services/backup/persistence.go | 20 +- services/backup/protected_resources_test.go | 7 +- ...overy_point_by_vault_storage_class_test.go | 7 +- services/backup/recovery_points_test.go | 5 +- services/backup/report_delivery.go | 6 +- services/backup/resource_engines.go | 38 +- services/backup/resource_restore_test.go | 5 +- services/backup/settings_test.go | 5 +- services/backup/vault_policies.go | 6 +- services/batch/exec_test.go | 5 +- services/batch/handler.go | 5 +- .../handler_compute_environments_test.go | 10 +- .../batch/handler_job_definitions_test.go | 11 +- services/batch/handler_job_queues_test.go | 26 +- services/batch/handler_jobs_test.go | 20 +- services/batch/handler_tags.go | 6 +- services/batch/handler_tags_test.go | 7 +- services/batch/handler_test.go | 14 +- services/batch/job_overrides.go | 8 +- services/batch/models.go | 6 +- .../batch/node_range_property_json_test.go | 7 +- services/batch/persistence.go | 6 +- services/batch/validation.go | 5 +- services/bcmdataexports/errors.go | 5 +- services/bcmdataexports/executions.go | 5 +- services/bcmdataexports/handler.go | 5 +- services/bcmdataexports/persistence.go | 10 +- services/bcmdataexports/rows.go | 5 +- .../bedrock/automated_reasoning_policies.go | 8 +- services/bedrock/export_test.go | 6 +- services/bedrock/ghost_row_jkiu_test.go | 6 +- services/bedrock/handler.go | 7 +- .../handler_automated_reasoning_policies.go | 26 +- ...ndler_automated_reasoning_policies_test.go | 57 +- .../handler_custom_model_deployments_test.go | 15 +- .../bedrock/handler_custom_models_test.go | 13 +- .../bedrock/handler_evaluation_jobs_test.go | 32 +- ...andler_foundation_model_agreements_test.go | 5 +- .../bedrock/handler_foundation_models_test.go | 27 +- services/bedrock/handler_guardrails_test.go | 17 +- .../handler_inference_profiles_test.go | 17 +- ...andler_marketplace_model_endpoints_test.go | 15 +- .../bedrock/handler_model_copy_jobs_test.go | 5 +- .../handler_model_customization_jobs_test.go | 17 +- .../bedrock/handler_model_import_jobs_test.go | 25 +- .../handler_model_invocation_jobs_test.go | 21 +- .../handler_model_invocation_logging_test.go | 12 +- .../bedrock/handler_prompt_routers_test.go | 21 +- .../handler_provisioned_throughput_test.go | 5 +- services/bedrock/handler_test.go | 9 +- services/bedrock/list_summary_shapes_test.go | 11 +- services/bedrock/models.go | 26 +- services/bedrock/persistence.go | 4 +- services/bedrock/persistence_test.go | 4 +- services/bedrock/request_realism_test.go | 5 +- services/bedrock/test_helpers_test.go | 7 +- .../bedrockagent/delete_output_shape_test.go | 25 +- .../delete_version_in_use_test.go | 7 +- .../handler_agent_action_groups.go | 8 +- .../handler_agent_action_groups_test.go | 10 +- .../bedrockagent/handler_agent_aliases.go | 8 +- .../handler_agent_collaborators.go | 8 +- .../handler_agent_collaborators_test.go | 10 +- .../handler_agent_knowledge_bases.go | 8 +- .../handler_agent_knowledge_bases_test.go | 14 +- services/bedrockagent/handler_agents.go | 8 +- services/bedrockagent/handler_agents_test.go | 36 +- services/bedrockagent/handler_data_sources.go | 8 +- .../bedrockagent/handler_data_sources_test.go | 8 +- services/bedrockagent/handler_flows.go | 16 +- services/bedrockagent/handler_flows_test.go | 10 +- services/bedrockagent/handler_helpers.go | 10 +- .../bedrockagent/handler_ingestion_jobs.go | 8 +- .../handler_ingestion_jobs_test.go | 19 +- .../bedrockagent/handler_knowledge_bases.go | 14 +- .../handler_knowledge_bases_test.go | 25 +- services/bedrockagent/handler_prompts.go | 10 +- services/bedrockagent/handler_prompts_test.go | 10 +- .../bedrockagent/handler_resource_policy.go | 6 +- services/bedrockagent/handler_tags.go | 6 +- services/bedrockagent/handler_tags_test.go | 6 +- services/bedrockagent/handler_test.go | 5 +- .../handler_vpc_configurations.go | 6 +- services/bedrockagent/lifecycle_test.go | 5 +- services/bedrockagent/models.go | 6 +- services/bedrockagent/persistence.go | 4 +- .../bedrockagent/wire_field_fixes_test.go | 10 +- .../bedrockagent/wire_field_omissions_test.go | 14 +- services/bedrockagentcore/identity.go | 5 +- services/bedrockagentcore/identity_test.go | 11 +- services/bedrockagentcore/oauth.go | 12 +- services/bedrockagentcore/persistence.go | 6 +- .../bedrockagentcore/runtime_docker_test.go | 7 +- services/bedrockagentcore/wire.go | 7 +- services/bedrockagentcorecontrol/dataplane.go | 7 +- .../bedrockagentcorecontrol/dataplane_test.go | 5 +- services/bedrockagentcorecontrol/engine.go | 5 +- .../bedrockagentcorecontrol/hooks_data.go | 5 +- .../bedrockagentcorecontrol/hooks_policy.go | 5 +- .../bedrockagentcorecontrol/ops_special.go | 5 +- .../bedrockagentcorecontrol/persistence.go | 6 +- services/bedrockagentcorecontrol/spec.go | 5 +- .../bedrockruntime/converse_validation.go | 27 +- services/bedrockruntime/eventstream_test.go | 6 +- services/bedrockruntime/guardrail_lookup.go | 10 +- .../bedrockruntime/handler_async_invoke.go | 12 +- .../handler_async_invoke_test.go | 35 +- services/bedrockruntime/handler_converse.go | 21 +- .../bedrockruntime/handler_converse_test.go | 20 +- .../handler_count_tokens_test.go | 24 +- .../handler_guardrail_checks.go | 8 +- services/bedrockruntime/handler_guardrails.go | 8 +- .../bedrockruntime/handler_guardrails_test.go | 28 +- services/bedrockruntime/handler_invoke.go | 16 +- .../bedrockruntime/handler_invoke_test.go | 34 +- ...handler_list_async_invokes_filters_test.go | 12 +- .../handler_sdk_route_table_test.go | 6 +- services/bedrockruntime/handler_test.go | 5 +- .../bedrockruntime/janitor_interval_test.go | 7 +- .../bedrockruntime/ollama_backend_test.go | 18 +- services/bedrockruntime/ollama_client.go | 21 +- services/bedrockruntime/ollama_converse.go | 40 +- services/bedrockruntime/ollama_invoke.go | 50 +- services/bedrockruntime/persistence.go | 16 +- .../wire_field_fixes_y1zn_test.go | 6 +- services/budgets/budgets.go | 7 +- services/budgets/handler.go | 5 +- services/budgets/persistence.go | 10 +- services/budgets/wire.go | 9 +- services/ce/cost_usage_granularity_test.go | 9 +- services/ce/cost_usage_timeperiod_test.go | 7 +- services/ce/handler.go | 23 +- services/ce/handler_anomalies_test.go | 50 +- services/ce/handler_anomaly_detection_test.go | 22 +- ...ndler_commitment_purchase_analysis_test.go | 16 +- .../ce/handler_cost_allocation_tags_test.go | 20 +- services/ce/handler_cost_categories_test.go | 46 +- services/ce/handler_cost_usage_test.go | 48 +- services/ce/handler_filters_test.go | 42 +- services/ce/handler_reservations_test.go | 24 +- services/ce/handler_savings_plans_test.go | 28 +- services/ce/handler_tags_test.go | 20 +- services/ce/handler_test.go | 12 +- services/ce/persistence.go | 18 +- services/ce/persistence_version_test.go | 11 +- services/ce/store.go | 5 +- services/ce/usage_validation_test.go | 10 +- .../cleanrooms/analysis_templates_test.go | 10 +- services/cleanrooms/collaborations_test.go | 32 +- services/cleanrooms/configured_tables_test.go | 10 +- services/cleanrooms/handler.go | 5 +- .../handler_analysis_log_exports.go | 9 +- .../cleanrooms/handler_analysis_templates.go | 20 +- .../handler_analysis_templates_test.go | 10 +- services/cleanrooms/handler_collaborations.go | 24 +- .../cleanrooms/handler_collaborations_test.go | 6 +- ..._configured_audience_model_associations.go | 18 +- ...igured_audience_model_associations_test.go | 8 +- .../handler_configured_table_associations.go | 22 +- ...dler_configured_table_associations_test.go | 10 +- .../cleanrooms/handler_configured_tables.go | 20 +- .../handler_configured_tables_test.go | 6 +- .../cleanrooms/handler_id_mapping_tables.go | 16 +- .../handler_id_namespace_associations.go | 18 +- .../cleanrooms/handler_intermediate_tables.go | 28 +- services/cleanrooms/handler_memberships.go | 12 +- .../cleanrooms/handler_privacy_budgets.go | 24 +- services/cleanrooms/handler_protected_jobs.go | 12 +- .../cleanrooms/handler_protected_jobs_test.go | 8 +- .../cleanrooms/handler_protected_queries.go | 12 +- services/cleanrooms/handler_routing.go | 15 +- services/cleanrooms/handler_schemas.go | 14 +- services/cleanrooms/handler_schemas_test.go | 6 +- services/cleanrooms/handler_tags.go | 10 +- services/cleanrooms/handler_test.go | 24 +- services/cleanrooms/id_mapping_tables_test.go | 26 +- .../id_namespace_associations_test.go | 6 +- ...ured_table_associations_rule_types_test.go | 14 +- services/cleanrooms/memberships_test.go | 10 +- .../overwide_collaboration_list_test.go | 10 +- services/cleanrooms/persistence.go | 4 +- services/cleanrooms/privacy_budgets_test.go | 14 +- services/cleanrooms/protected_jobs_test.go | 6 +- services/cleanrooms/protected_queries_test.go | 8 +- .../protected_query_lifecycle_test.go | 7 +- .../cleanrooms/undeclared_members_test.go | 5 +- services/cloudcontrol/handler.go | 11 +- services/cloudcontrol/handler_test.go | 7 +- services/cloudcontrol/models.go | 8 +- services/cloudcontrol/models_test.go | 9 +- services/cloudcontrol/persistence.go | 4 +- services/cloudcontrol/provisioned.go | 6 +- .../cloudcontrol/resource_requests_test.go | 27 +- services/cloudcontrol/resources.go | 23 +- services/cloudcontrol/resources_test.go | 47 +- services/cloudcontrol/type_handlers.go | 11 +- services/cloudformation/cfn_attributes.go | 6 +- .../cloudformation/cfn_property_schemas.go | 6 +- services/cloudformation/changeset_diff.go | 9 +- .../cloudcontrol_provisioner.go | 5 +- .../cloudformation/deletion_policy_test.go | 5 +- services/cloudformation/drift_detection.go | 8 +- .../cloudformation/drift_detection_test.go | 5 +- services/cloudformation/dynamic_refs.go | 6 +- .../cloudformation/generated_templates.go | 5 +- .../cloudformation/handler_type_registry.go | 9 +- services/cloudformation/persistence.go | 4 +- .../resource_type_schemas_test.go | 8 +- .../cloudformation/resource_update_inplace.go | 5 +- services/cloudformation/resources.go | 4 +- .../cloudformation/resources_apigatewayv2.go | 7 +- services/cloudformation/resources_cfnrest.go | 7 +- .../resources_connect_content.go | 5 +- .../resources_connect_core_test.go | 5 +- .../resources_connect_people.go | 10 +- .../resources_connect_workspace.go | 8 +- .../resources_connectfamily_helpers_test.go | 5 +- services/cloudformation/resources_deep.go | 5 +- .../cloudformation/resources_extensibility.go | 24 +- ...nsibility_customresource_lifecycle_test.go | 15 +- ...urces_extensibility_customresource_test.go | 15 +- .../resources_extensibility_macro_test.go | 13 +- .../cloudformation/resources_iot_more_test.go | 9 +- .../resources_networkmanager.go | 5 +- services/cloudformation/resources_oam_test.go | 5 +- services/cloudformation/resources_rum_test.go | 5 +- .../cloudformation/resources_sagemaker.go | 6 +- .../resources_sagemaker_athena_wafv2_test.go | 4 +- services/cloudformation/resources_ssm.go | 5 +- services/cloudformation/resources_ssm_more.go | 5 +- services/cloudformation/resources_wafv2.go | 4 +- services/cloudformation/sam_api.go | 8 +- services/cloudformation/sam_events_test.go | 7 +- services/cloudformation/sam_misc.go | 8 +- .../sam_statemachine_events_test.go | 6 +- services/cloudformation/sam_transform.go | 13 +- services/cloudformation/stack_policy_eval.go | 10 +- services/cloudformation/template.go | 19 +- services/cloudformation/template_preflight.go | 13 +- .../cloudformation/template_strictness.go | 8 +- services/cloudfront/dataplane_edge.go | 8 +- services/cloudfront/dataplane_function.go | 6 +- services/cloudfront/dataplane_s3_policy.go | 13 +- services/cloudfront/dataplane_signing.go | 8 +- .../dataplane_signing_internal_test.go | 6 +- .../distributions_transition_test.go | 5 +- services/cloudfront/function_exec.go | 6 +- .../handler_distribution_tenants.go | 12 +- services/cloudfront/handler_functions.go | 6 +- .../handler_key_value_store_test.go | 5 +- services/cloudfront/kvs_import.go | 6 +- services/cloudfront/lambda_edge_test.go | 9 +- services/cloudfront/persistence.go | 12 +- services/cloudfrontkeyvaluestore/handler.go | 9 +- services/cloudhsmv2/backups.go | 5 +- services/cloudhsmv2/handler.go | 5 +- services/cloudhsmv2/persistence.go | 10 +- services/cloudhsmv2/policies.go | 9 +- services/cloudtrail/delivery.go | 9 +- services/cloudtrail/handler.go | 10 +- services/cloudtrail/handler_channels.go | 13 +- services/cloudtrail/handler_dashboards.go | 15 +- .../cloudtrail/handler_event_data_stores.go | 23 +- .../cloudtrail/handler_event_selectors.go | 19 +- services/cloudtrail/handler_events.go | 5 +- services/cloudtrail/handler_imports.go | 13 +- services/cloudtrail/handler_queries.go | 15 +- .../cloudtrail/handler_resource_policies.go | 10 +- services/cloudtrail/handler_tags.go | 10 +- services/cloudtrail/handler_test.go | 12 +- services/cloudtrail/handler_trails.go | 25 +- services/cloudtrail/insights_metrics.go | 6 +- services/cloudtrail/management_event.go | 5 +- .../management_event_render_whitebox_test.go | 6 +- services/cloudtrail/models.go | 7 +- services/cloudtrail/multi_region_test.go | 5 +- services/cloudtrail/persistence.go | 4 +- services/cloudtrail/query_exec.go | 8 +- services/cloudtrail/s3_delivery_test.go | 5 +- services/cloudwatch/alarm_actions.go | 5 +- services/cloudwatch/alarm_history.go | 7 +- services/cloudwatch/alarm_reason.go | 6 +- .../cloudwatch/alarm_validation_sdk_test.go | 11 +- services/cloudwatch/anomaly_detectors.go | 5 +- .../contributor_insights_sdk_test.go | 5 +- services/cloudwatch/dashboard_validation.go | 15 +- services/cloudwatch/firehose_interop_test.go | 5 +- services/cloudwatch/insight_rule_eval.go | 12 +- services/cloudwatch/insight_rule_spec.go | 6 +- .../cloudwatch/insight_rule_validation.go | 6 +- services/cloudwatch/json_target.go | 16 +- services/cloudwatch/json_target_test.go | 9 +- services/cloudwatch/metric_stream_delivery.go | 5 +- .../cloudwatch/metric_stream_delivery_test.go | 6 +- services/cloudwatch/metricdata.go | 10 +- services/cloudwatch/persistence.go | 10 +- services/cloudwatch/persistence_test.go | 7 +- services/cloudwatch/widget.go | 39 +- .../cloudwatchlogs/data_protection_mask.go | 6 +- .../cloudwatchlogs/filter_pattern_json.go | 8 +- services/cloudwatchlogs/golden_perf_test.go | 20 +- services/cloudwatchlogs/handler.go | 9 +- .../handler_anomaly_detectors.go | 18 +- .../handler_anomaly_detectors_test.go | 9 +- .../cloudwatchlogs/handler_data_protection.go | 16 +- .../handler_data_protection_test.go | 9 +- services/cloudwatchlogs/handler_deliveries.go | 36 +- .../cloudwatchlogs/handler_deliveries_test.go | 35 +- .../cloudwatchlogs/handler_destinations.go | 12 +- .../handler_destinations_test.go | 13 +- .../cloudwatchlogs/handler_export_tasks.go | 18 +- .../handler_export_tasks_test.go | 29 +- .../cloudwatchlogs/handler_index_policies.go | 10 +- .../handler_index_policies_test.go | 13 +- .../cloudwatchlogs/handler_integrations.go | 18 +- .../handler_integrations_test.go | 21 +- services/cloudwatchlogs/handler_log_events.go | 20 +- .../cloudwatchlogs/handler_log_events_test.go | 25 +- services/cloudwatchlogs/handler_log_groups.go | 26 +- .../cloudwatchlogs/handler_log_groups_test.go | 31 +- .../cloudwatchlogs/handler_log_streams.go | 10 +- .../handler_log_streams_test.go | 13 +- .../cloudwatchlogs/handler_lookup_tables.go | 14 +- .../cloudwatchlogs/handler_metric_filters.go | 12 +- services/cloudwatchlogs/handler_queries.go | 14 +- .../cloudwatchlogs/handler_queries_test.go | 39 +- .../handler_query_definitions.go | 10 +- .../handler_resource_policies.go | 10 +- .../handler_resource_policies_test.go | 9 +- .../handler_scheduled_queries.go | 16 +- .../handler_scheduled_queries_test.go | 19 +- .../handler_storage_tier_policy.go | 6 +- .../handler_subscription_filters.go | 10 +- .../handler_subscription_filters_test.go | 9 +- .../handler_syslog_configurations.go | 10 +- services/cloudwatchlogs/handler_tags.go | 15 +- services/cloudwatchlogs/handler_tags_test.go | 21 +- services/cloudwatchlogs/handler_test.go | 27 +- .../cloudwatchlogs/handler_transformers.go | 12 +- .../handler_transformers_test.go | 5 +- services/cloudwatchlogs/insights_parse.go | 8 +- services/cloudwatchlogs/log_events.go | 8 +- .../cloudwatchlogs/perf_sweep_bench_test.go | 7 +- services/cloudwatchlogs/persistence.go | 10 +- .../presence_validation_test.go | 11 +- .../cloudwatchlogs/subscription_filters.go | 5 +- services/cloudwatchlogs/transformers.go | 8 +- .../cloudwatchlogs/undeclared_members_test.go | 5 +- .../cloudwatchlogs/wire_field_fixes_test.go | 5 +- .../domain_owner_and_error_message_test.go | 5 +- services/codeartifact/handler.go | 10 +- services/codeartifact/handler_domains.go | 10 +- services/codeartifact/handler_domains_test.go | 31 +- .../handler_internal_error_test.go | 6 +- .../codeartifact/handler_list_summary_test.go | 8 +- .../codeartifact/handler_package_groups.go | 10 +- .../handler_package_groups_list_test.go | 41 +- .../handler_package_groups_test.go | 19 +- .../handler_package_version_rejection_test.go | 6 +- .../codeartifact/handler_package_versions.go | 12 +- .../handler_package_versions_assets_test.go | 21 +- .../handler_package_versions_test.go | 45 +- services/codeartifact/handler_packages.go | 6 +- .../codeartifact/handler_packages_test.go | 23 +- services/codeartifact/handler_repositories.go | 10 +- .../codeartifact/handler_repositories_test.go | 41 +- services/codeartifact/handler_tags.go | 8 +- services/codeartifact/handler_tags_test.go | 16 +- services/codeartifact/handler_test.go | 9 +- services/codeartifact/package_versions.go | 19 +- services/codeartifact/persistence.go | 6 +- services/codebuild/build_batches_test.go | 31 +- services/codebuild/builds_semantics_test.go | 21 +- services/codebuild/builds_test.go | 37 +- services/codebuild/command_executions_test.go | 22 +- .../codebuild/curated_environments_test.go | 7 +- services/codebuild/engine_env.go | 6 +- services/codebuild/fleets_test.go | 27 +- services/codebuild/handler.go | 11 +- services/codebuild/handler_test.go | 14 +- services/codebuild/multi_region_test.go | 5 +- services/codebuild/pagination_test.go | 18 +- services/codebuild/persistence.go | 14 +- .../codebuild/phase_duration_internal_test.go | 6 +- services/codebuild/projects_schema_test.go | 25 +- services/codebuild/projects_test.go | 25 +- services/codebuild/report_formats.go | 17 +- services/codebuild/reports_test.go | 34 +- services/codebuild/resource_policies_test.go | 11 +- services/codebuild/sandboxes_test.go | 18 +- services/codebuild/source_credentials_test.go | 13 +- services/codebuild/tagswire.go | 8 +- services/codebuild/webhooks_test.go | 21 +- services/codebuild/whitebox_test.go | 9 +- services/codecommit/actor_arn_test.go | 9 +- services/codecommit/handler.go | 15 +- ...handler_approval_rule_associations_test.go | 32 +- services/codecommit/handler_approval_rules.go | 30 +- .../codecommit/handler_approval_rules_test.go | 13 +- services/codecommit/handler_branches.go | 14 +- services/codecommit/handler_branches_test.go | 12 +- services/codecommit/handler_comments.go | 19 +- services/codecommit/handler_comments_test.go | 38 +- services/codecommit/handler_commits.go | 12 +- services/codecommit/handler_commits_test.go | 68 +-- services/codecommit/handler_files.go | 18 +- services/codecommit/handler_files_test.go | 52 +- services/codecommit/handler_merges.go | 23 +- services/codecommit/handler_merges_test.go | 57 +- .../handler_pull_request_approvals_test.go | 30 +- services/codecommit/handler_pull_requests.go | 33 +- .../codecommit/handler_pull_requests_test.go | 42 +- services/codecommit/handler_reactions.go | 7 +- services/codecommit/handler_reactions_test.go | 10 +- services/codecommit/handler_repositories.go | 20 +- .../codecommit/handler_repositories_test.go | 34 +- services/codecommit/handler_tags.go | 10 +- services/codecommit/handler_tags_test.go | 17 +- services/codecommit/handler_test.go | 13 +- services/codecommit/handler_triggers.go | 10 +- services/codecommit/handler_triggers_test.go | 16 +- services/codecommit/multi_region_test.go | 5 +- services/codecommit/persistence.go | 6 +- services/codeconnections/handler.go | 9 +- services/codeconnections/handler_test.go | 9 +- services/codeconnections/persistence.go | 12 +- .../codedeploy/application_revisions_test.go | 19 +- services/codedeploy/applications_test.go | 15 +- .../codedeploy/deployment_configs_test.go | 18 +- .../deployment_group_tag_filters_test.go | 8 +- services/codedeploy/deployment_groups_test.go | 21 +- .../codedeploy/deployment_instances_test.go | 27 +- services/codedeploy/deployments_test.go | 55 +- services/codedeploy/github_tokens_test.go | 12 +- services/codedeploy/handler.go | 14 +- .../codedeploy/handler_deployment_groups.go | 7 +- services/codedeploy/handler_test.go | 7 +- services/codedeploy/lifecycle_hooks_test.go | 10 +- .../codedeploy/lifecycle_validation_test.go | 6 +- services/codedeploy/multi_region_test.go | 5 +- .../codedeploy/on_premises_instances_test.go | 17 +- services/codedeploy/persistence.go | 14 +- services/codedeploy/store_setup.go | 5 +- services/codedeploy/tags_test.go | 12 +- services/codegurureviewer/persistence.go | 10 +- .../async_builtin_actions_test.go | 5 +- .../codepipeline/custom_action_types_test.go | 28 +- .../codepipeline/deploy_cloudformation.go | 19 +- services/codepipeline/deploy_ecs.go | 6 +- services/codepipeline/handler.go | 12 +- services/codepipeline/handler_test.go | 13 +- services/codepipeline/jobs_test.go | 13 +- services/codepipeline/persistence.go | 20 +- .../codepipeline/pipeline_declaration_test.go | 7 +- .../codepipeline/pipeline_executions_test.go | 18 +- services/codepipeline/pipeline_state_test.go | 11 +- .../codepipeline/pipeline_state_wire_test.go | 5 +- services/codepipeline/pipelines_test.go | 41 +- services/codepipeline/rules_test.go | 6 +- services/codepipeline/source_actions.go | 5 +- services/codepipeline/tags_test.go | 13 +- .../codepipeline/third_party_jobs_test.go | 9 +- services/codepipeline/webhooks_test.go | 18 +- services/codestarconnections/handler.go | 13 +- .../handler_connections_test.go | 15 +- .../codestarconnections/handler_hosts_test.go | 15 +- .../handler_repository_links_test.go | 9 +- .../handler_sync_blockers_test.go | 5 +- .../handler_sync_configurations_test.go | 13 +- .../handler_sync_statuses_test.go | 7 +- .../codestarconnections/handler_tags_test.go | 13 +- services/codestarconnections/handler_test.go | 11 +- services/codestarconnections/persistence.go | 12 +- services/cognitoidentity/handler.go | 11 +- .../handler_credentials_test.go | 38 +- .../handler_developer_identities_test.go | 36 +- .../handler_identities_test.go | 53 +- .../handler_identity_pool_roles_test.go | 37 +- .../handler_identity_pools_test.go | 75 +-- services/cognitoidentity/handler_tags_test.go | 18 +- services/cognitoidentity/handler_test.go | 19 +- services/cognitoidentity/login_tokens.go | 8 +- services/cognitoidentity/open_id_token.go | 8 +- .../cognitoidentity/open_id_token_test.go | 5 +- services/cognitoidentity/persistence.go | 12 +- services/cognitoidentity/persistence_test.go | 8 +- .../cognitoidentity/role_selection_test.go | 7 +- .../sdk_login_token_flow_test.go | 8 +- .../attribute_custom_message_test.go | 7 +- .../cognitoidp/attributes_management_test.go | 31 +- services/cognitoidp/attributes_test.go | 15 +- services/cognitoidp/auth_events_test.go | 8 +- services/cognitoidp/auth_tokens.go | 6 +- services/cognitoidp/auth_tokens_test.go | 39 +- services/cognitoidp/branding_test.go | 18 +- services/cognitoidp/delivery_test.go | 9 +- services/cognitoidp/devices_test.go | 21 +- services/cognitoidp/domains_test.go | 27 +- .../cognitoidp/federation_providers_test.go | 11 +- services/cognitoidp/groups_membership_test.go | 25 +- services/cognitoidp/groups_test.go | 25 +- services/cognitoidp/handler.go | 11 +- .../handler_auth_challenges_test.go | 29 +- .../cognitoidp/handler_auth_flows_test.go | 47 +- .../cognitoidp/handler_auth_tokens_test.go | 20 +- services/cognitoidp/handler_test.go | 15 +- .../handler_users_lifecycle_test.go | 49 +- services/cognitoidp/handler_users_test.go | 35 +- .../cognitoidp/identity_providers_test.go | 31 +- services/cognitoidp/input_validation.go | 6 +- services/cognitoidp/input_validation_test.go | 6 +- services/cognitoidp/mfa_test.go | 29 +- services/cognitoidp/multi_region_test.go | 5 +- .../cognitoidp/oauth_federation_backend.go | 9 +- .../oauth_federation_helpers_test.go | 10 +- services/cognitoidp/oauth_federation_idp.go | 10 +- services/cognitoidp/oauth_federation_test.go | 5 +- services/cognitoidp/oauth_helpers_test.go | 7 +- services/cognitoidp/oauth_token.go | 6 +- services/cognitoidp/persistence.go | 14 +- .../cognitoidp/persistence_internal_test.go | 15 +- services/cognitoidp/persistence_test.go | 13 +- ...ent_managed_login_and_provisioning_test.go | 5 +- services/cognitoidp/regions.go | 5 +- services/cognitoidp/resource_servers_test.go | 13 +- services/cognitoidp/saml_federation_test.go | 7 +- services/cognitoidp/saml_slo_test.go | 5 +- services/cognitoidp/security_config_test.go | 21 +- services/cognitoidp/tags_test.go | 8 +- services/cognitoidp/temp_password_sdk_test.go | 23 +- services/cognitoidp/terms_test.go | 22 +- services/cognitoidp/testhelpers_test.go | 19 +- services/cognitoidp/tokens.go | 8 +- services/cognitoidp/user_import_test.go | 25 +- .../user_pool_clients_handler_test.go | 53 +- services/cognitoidp/user_pool_clients_test.go | 25 +- services/cognitoidp/user_pools_config_test.go | 31 +- services/cognitoidp/user_pools_test.go | 27 +- services/cognitoidp/users_test.go | 5 +- services/cognitoidp/webauthn_test.go | 12 +- services/cognitoidp/wire_field_fixes_test.go | 6 +- services/comprehend/handler.go | 11 +- services/comprehend/handler_test.go | 13 +- services/comprehend/persistence.go | 4 +- services/comprehend/s3_output.go | 7 +- services/connect/contacts.go | 18 +- services/connect/datatables.go | 16 +- services/connect/evaluationforms.go | 64 ++- services/connect/flows.go | 11 +- services/connect/metrics.go | 10 +- services/connect/models.go | 32 +- services/connect/persistence.go | 10 +- services/connect/proficiencies.go | 34 +- services/connect/records.go | 16 +- services/connect/rules.go | 30 +- services/connect/search.go | 16 +- services/connect/searchengine.go | 10 +- services/connect/searches.go | 13 +- services/connect/security.go | 18 +- services/connect/securityextras.go | 41 +- services/connect/users.go | 12 +- services/connect/views.go | 8 +- services/connect/workspaces.go | 36 +- services/cosmosdb/account_ops_test.go | 6 +- services/cosmosdb/batch.go | 18 +- services/cosmosdb/changelog.go | 8 +- services/cosmosdb/computed_properties_test.go | 12 +- services/cosmosdb/computed_rules.go | 4 +- services/cosmosdb/conflicts.go | 17 +- services/cosmosdb/container_ops.go | 20 +- services/cosmosdb/container_policy.go | 53 +- services/cosmosdb/container_policy_test.go | 5 +- services/cosmosdb/database_ops.go | 5 +- services/cosmosdb/document_ops.go | 22 +- services/cosmosdb/fulltext.go | 11 +- services/cosmosdb/fulltext_analysis_test.go | 6 +- services/cosmosdb/handler.go | 7 +- services/cosmosdb/handler_test.go | 29 +- services/cosmosdb/helpers_test.go | 10 +- services/cosmosdb/indexing.go | 15 +- services/cosmosdb/live_server_test.go | 9 +- services/cosmosdb/models.go | 78 +-- services/cosmosdb/offer_ops.go | 7 +- services/cosmosdb/pagination_test.go | 8 +- services/cosmosdb/partition_epk.go | 12 +- services/cosmosdb/partitionkey.go | 11 +- services/cosmosdb/patch.go | 30 +- services/cosmosdb/permission_ops.go | 10 +- services/cosmosdb/persistence.go | 6 +- services/cosmosdb/persistence_test.go | 4 +- services/cosmosdb/query_resources.go | 15 +- services/cosmosdb/query_rows.go | 10 +- services/cosmosdb/region_http.go | 5 +- services/cosmosdb/regions_conflicts_test.go | 5 +- services/cosmosdb/script_engine.go | 12 +- services/cosmosdb/script_ops.go | 17 +- services/cosmosdb/scripts_test.go | 9 +- services/cosmosdb/sdk_test.go | 5 +- services/cosmosdb/search_funcs_test.go | 5 +- services/cosmosdb/search_sdk_test.go | 7 +- services/cosmosdb/spatial_index.go | 9 +- services/cosmosdb/sql_agg.go | 7 +- services/cosmosdb/sql_engine_test.go | 9 +- services/cosmosdb/sql_eval.go | 30 +- services/cosmosdb/sql_exec_test.go | 4 +- services/cosmosdb/sql_ext_test.go | 5 +- services/cosmosdb/sql_funcs.go | 19 +- services/cosmosdb/sql_funcs_ext.go | 18 +- services/cosmosdb/sql_funcs_more.go | 13 +- services/cosmosdb/sql_functions_doc_test.go | 7 +- services/cosmosdb/sql_parser.go | 9 +- services/cosmosdb/sql_spatial_doc_test.go | 12 +- services/cosmosdb/store_test.go | 4 +- services/cosmosdb/table_api.go | 9 +- services/cosmosdb/throughput_test.go | 5 +- services/cosmosdb/token.go | 8 +- services/cosmosdb/triggers.go | 6 +- services/cosmosdb/ttl_test.go | 4 +- services/cosmosdb/users.go | 10 +- services/cosmosdb/users_ops.go | 5 +- services/cosmosdb/users_test.go | 5 +- services/cosmosdb/vector.go | 11 +- services/cur/delivery.go | 9 +- services/cur/delivery_test.go | 6 +- services/cur/handler.go | 5 +- services/cur/persistence.go | 10 +- services/databrew/datasets_test.go | 11 +- services/databrew/handler.go | 34 +- services/databrew/handler_datasets.go | 22 +- services/databrew/handler_jobs.go | 44 +- services/databrew/handler_projects.go | 30 +- services/databrew/handler_recipes.go | 36 +- services/databrew/handler_rulesets.go | 22 +- services/databrew/handler_schedules.go | 22 +- services/databrew/handler_tags.go | 16 +- services/databrew/handler_test.go | 6 +- services/databrew/jobs_test.go | 23 +- services/databrew/paginate_helper.go | 6 +- services/databrew/persistence.go | 8 +- services/databrew/projects_test.go | 11 +- services/databrew/recipes_test.go | 19 +- services/databrew/rulesets_test.go | 13 +- services/databrew/schedules_test.go | 8 +- services/databrew/store_test.go | 10 +- services/databrew/tags_test.go | 7 +- services/datasync/handler.go | 11 +- services/datasync/handler_agents_test.go | 15 +- .../handler_locations_agentarns_test.go | 16 +- .../handler_locations_azureblob_test.go | 10 +- .../datasync/handler_locations_efs_test.go | 8 +- .../handler_locations_fsxlustre_test.go | 8 +- .../handler_locations_fsxontap_test.go | 10 +- .../handler_locations_fsxopenzfs_test.go | 8 +- .../handler_locations_fsxwindows_test.go | 10 +- .../datasync/handler_locations_hdfs_test.go | 10 +- .../datasync/handler_locations_nfs_test.go | 14 +- .../handler_locations_objectstorage_test.go | 14 +- .../handler_locations_secretconfig_test.go | 21 +- .../datasync/handler_locations_smb_test.go | 14 +- services/datasync/handler_locations_test.go | 15 +- services/datasync/handler_tags_test.go | 12 +- services/datasync/handler_tasks_test.go | 63 ++- services/datasync/handler_test.go | 13 +- services/datasync/persistence.go | 4 +- services/datasync/validation.go | 5 +- services/datasync/validation_test.go | 8 +- services/datasync/wire_field_fixes_test.go | 5 +- services/dax/handler_clusters.go | 17 +- services/dax/handler_clusters_test.go | 17 +- services/dax/handler_events.go | 21 +- services/dax/handler_events_test.go | 5 +- services/dax/handler_parameter_groups.go | 18 +- services/dax/handler_parameter_groups_test.go | 7 +- services/dax/handler_subnet_groups.go | 12 +- services/dax/handler_subnet_groups_test.go | 7 +- services/dax/handler_tags.go | 10 +- services/dax/handler_tags_test.go | 37 +- services/dax/handler_test.go | 12 +- services/dax/handler_wire_shape_test.go | 23 +- services/dax/multi_region_test.go | 5 +- services/dax/persistence.go | 10 +- services/detective/handler_administrator.go | 9 +- .../detective/handler_administrator_test.go | 12 +- .../detective/handler_datasource_packages.go | 11 +- .../handler_datasource_packages_test.go | 30 +- services/detective/handler_graphs.go | 9 +- services/detective/handler_graphs_test.go | 19 +- services/detective/handler_investigations.go | 13 +- .../detective/handler_investigations_test.go | 20 +- services/detective/handler_members.go | 19 +- services/detective/handler_members_test.go | 50 +- services/detective/handler_organization.go | 7 +- .../detective/handler_organization_test.go | 10 +- services/detective/handler_tags.go | 5 +- services/detective/handler_tags_test.go | 21 +- services/detective/handler_test.go | 9 +- services/detective/persistence.go | 4 +- services/detective/whitebox_test.go | 10 +- services/directconnect/cloudformation.go | 12 +- services/directconnect/connections.go | 5 +- services/directconnect/handler.go | 18 +- services/directconnect/persistence.go | 12 +- services/directoryservice/handler.go | 14 +- .../handler_ad_assessments.go | 11 +- .../handler_ad_assessments_test.go | 20 +- .../directoryservice/handler_certificates.go | 15 +- .../handler_certificates_test.go | 16 +- .../directoryservice/handler_client_auth.go | 9 +- .../handler_client_auth_test.go | 7 +- .../handler_conditional_forwarders.go | 9 +- .../handler_conditional_forwarders_test.go | 10 +- .../directoryservice/handler_directories.go | 19 +- .../handler_directories_extra_test.go | 7 +- .../handler_directories_test.go | 39 +- .../handler_domain_controllers.go | 7 +- .../handler_domain_controllers_test.go | 8 +- .../directoryservice/handler_event_topics.go | 5 +- .../handler_event_topics_test.go | 8 +- .../directoryservice/handler_hybrid_ad.go | 9 +- .../handler_hybrid_ad_test.go | 15 +- .../directoryservice/handler_ip_routes.go | 9 +- .../handler_ip_routes_test.go | 8 +- services/directoryservice/handler_ldaps.go | 9 +- .../directoryservice/handler_ldaps_test.go | 7 +- .../handler_log_subscriptions.go | 7 +- .../handler_log_subscriptions_test.go | 8 +- services/directoryservice/handler_radius.go | 9 +- services/directoryservice/handler_regions.go | 9 +- .../directoryservice/handler_regions_test.go | 10 +- .../handler_schema_extensions.go | 9 +- .../handler_schema_extensions_test.go | 8 +- services/directoryservice/handler_settings.go | 17 +- .../directoryservice/handler_settings_test.go | 16 +- .../handler_shared_directories.go | 13 +- .../handler_shared_directories_test.go | 14 +- .../directoryservice/handler_snapshots.go | 13 +- .../handler_snapshots_test.go | 27 +- services/directoryservice/handler_sso.go | 7 +- services/directoryservice/handler_sso_test.go | 5 +- services/directoryservice/handler_tags.go | 9 +- .../directoryservice/handler_tags_test.go | 13 +- services/directoryservice/handler_test.go | 11 +- services/directoryservice/handler_trusts.go | 13 +- .../directoryservice/handler_trusts_test.go | 15 +- services/directoryservice/id_format_test.go | 8 +- services/directoryservice/persistence.go | 10 +- services/dlm/handler.go | 9 +- .../dlm/handler_lifecycle_policies_test.go | 35 +- services/dlm/handler_tags_test.go | 17 +- services/dlm/handler_test.go | 27 +- services/dlm/persistence.go | 8 +- services/dlm/persistence_test.go | 12 +- services/dms/data_providers.go | 11 +- services/dms/endpoints.go | 11 +- services/dms/engine.go | 5 +- services/dms/handler.go | 7 +- services/dms/handler_assessment_runs_test.go | 9 +- services/dms/handler_data_providers.go | 50 +- services/dms/handler_data_providers_test.go | 5 +- services/dms/handler_endpoints.go | 66 +-- services/dms/handler_endpoints_test.go | 5 +- .../dms/handler_event_subscriptions_test.go | 5 +- services/dms/handler_replication_configs.go | 5 +- services/dms/handler_replication_tasks.go | 5 +- .../dms/handler_replication_tasks_test.go | 9 +- services/dms/handler_test.go | 13 +- services/dms/persistence.go | 8 +- services/dms/validation.go | 8 +- services/docdb/master_secret.go | 5 +- services/docdb/persistence.go | 6 +- services/dsql/handler_clusters.go | 8 +- services/dsql/handler_policy.go | 6 +- services/dsql/handler_streams.go | 6 +- services/dsql/handler_tags.go | 6 +- services/dsql/persistence.go | 6 +- services/dsql/validation.go | 5 +- services/dynamodb/backup_interface_test.go | 23 +- services/dynamodb/backup_ops.go | 15 +- services/dynamodb/backup_replica_test.go | 7 +- .../dynamodb/bench_extract_resource_test.go | 5 +- services/dynamodb/bench_hot_ops_test.go | 5 +- services/dynamodb/cbor_test.go | 5 +- .../dynamodb/condition_check_return_test.go | 5 +- services/dynamodb/expr/evaluator.go | 9 +- services/dynamodb/global_tables_test.go | 7 +- services/dynamodb/golden_perf_test.go | 16 +- services/dynamodb/handler.go | 27 +- services/dynamodb/handler_autoscaling.go | 5 +- services/dynamodb/handler_backups.go | 15 +- .../dynamodb/handler_contributor_insights.go | 9 +- services/dynamodb/handler_debug_test.go | 7 +- .../dynamodb/handler_execute_transaction.go | 5 +- services/dynamodb/handler_global_tables.go | 15 +- services/dynamodb/handler_import.go | 9 +- .../dynamodb/handler_kinesis_streaming.go | 11 +- services/dynamodb/handler_resource_policy.go | 10 +- services/dynamodb/handler_streams_test.go | 9 +- services/dynamodb/handler_test.go | 7 +- services/dynamodb/import_export_s3.go | 12 +- services/dynamodb/import_export_s3_test.go | 5 +- .../dynamodb/item_collection_metrics_test.go | 21 +- services/dynamodb/json_check_test.go | 5 +- services/dynamodb/kinesis_streaming_test.go | 9 +- services/dynamodb/partiql.go | 11 +- services/dynamodb/partiql_test.go | 19 +- services/dynamodb/perf_sweep_bench_test.go | 7 +- services/dynamodb/persistence.go | 18 +- services/dynamodb/realism_test.go | 11 +- services/dynamodb/resource_policy_test.go | 11 +- services/dynamodb/search_vectors_test.go | 7 +- services/dynamodb/test_utils_test.go | 9 +- services/dynamodb/transact_ops.go | 5 +- services/dynamodb/transact_validation.go | 5 +- services/dynamodb/wire_codec_internal_test.go | 29 +- services/dynamodb/wire_encode.go | 7 +- services/dynamodbstreams/handler.go | 21 +- .../dynamodbstreams/handler_errors_test.go | 9 +- .../dynamodbstreams/handler_lifecycle_test.go | 13 +- .../dynamodbstreams/handler_records_test.go | 47 +- .../dynamodbstreams/handler_streams_test.go | 21 +- services/dynamodbstreams/handler_test.go | 5 +- services/dynamodbstreams/handler_wire_test.go | 5 +- services/dynamodbstreams/isolation_test.go | 9 +- .../dynamodbstreams/request_errors_test.go | 5 +- services/ec2/cleanup_test.go | 8 +- services/ec2/client_vpn_auth_policy.go | 6 +- services/ec2/docker_ports_internal_test.go | 6 +- services/ec2/images_public_catalog_test.go | 5 +- services/ec2/imds_test.go | 9 +- services/ec2/imds_tree.go | 15 +- services/ec2/ipam_routing_policy.go | 7 +- services/ec2/mac_hosts.go | 6 +- services/ec2/persistence.go | 8 +- services/ec2/usage_metrics.go | 6 +- services/ecr/auth_token_test.go | 5 +- services/ecr/handler.go | 12 +- services/ecr/handler_images.go | 8 +- services/ecr/handler_test.go | 11 +- services/ecr/interfaces_test.go | 11 +- services/ecr/lifecycle.go | 6 +- services/ecr/lifecycle_policy_test.go | 5 +- services/ecr/manifest_meta.go | 9 +- services/ecr/multi_region_test.go | 5 +- services/ecr/persistence.go | 4 +- services/ecr/realism_validation_test.go | 6 +- services/ecr/repositories_test.go | 9 +- services/ecr/tags_test.go | 13 +- services/ecr/validation.go | 8 +- services/ecrpublic/digest.go | 6 +- services/ecrpublic/handler.go | 13 +- services/ecrpublic/images_and_layers_test.go | 6 +- services/ecrpublic/manifest_index_test.go | 6 +- services/ecrpublic/persistence.go | 4 +- services/ecrpublic/policy.go | 7 +- ...acity_provider_strategy_validation_test.go | 8 +- services/ecs/docker_inputs.go | 5 +- services/ecs/docker_inputs_internal_test.go | 6 +- .../docker_linklocal_live_internal_test.go | 9 +- services/ecs/docker_secrets.go | 11 +- services/ecs/docker_usage.go | 14 +- services/ecs/events.go | 5 +- services/ecs/events_internal_test.go | 5 +- services/ecs/handler.go | 13 +- services/ecs/handler_account_settings_test.go | 29 +- services/ecs/handler_agent_ops_test.go | 47 +- services/ecs/handler_attributes_test.go | 29 +- .../ecs/handler_capacity_providers_test.go | 43 +- services/ecs/handler_cluster_tags_test.go | 10 +- services/ecs/handler_clusters_test.go | 49 +- services/ecs/handler_container_instances.go | 5 +- .../ecs/handler_container_instances_test.go | 59 +- services/ecs/handler_daemon_test.go | 55 +- .../ecs/handler_describe_taskdef_tags_test.go | 5 +- services/ecs/handler_express_gateway_test.go | 29 +- services/ecs/handler_service_config_test.go | 28 +- .../ecs/handler_service_deployments_test.go | 21 +- ...handler_service_deployments_wiring_test.go | 10 +- services/ecs/handler_service_fields_test.go | 38 +- .../ecs/handler_services_deployments_test.go | 33 +- services/ecs/handler_services_test.go | 35 +- services/ecs/handler_tags_test.go | 23 +- .../handler_task_definition_fields_test.go | 60 +- services/ecs/handler_task_definitions_test.go | 61 +- services/ecs/handler_task_exec_test.go | 65 +-- services/ecs/handler_task_sets_test.go | 67 +-- services/ecs/handler_tasks_fields_test.go | 39 +- services/ecs/handler_tasks_test.go | 31 +- services/ecs/handler_test.go | 21 +- services/ecs/lambda_hooks.go | 8 +- services/ecs/models.go | 6 +- services/ecs/multi_region_test.go | 5 +- services/ecs/pagination_test.go | 55 +- services/ecs/persistence.go | 4 +- services/ecs/realism_validation_test.go | 6 +- services/ecs/reconciler_test.go | 6 +- services/ecs/run_task_count_test.go | 6 +- .../ecs/service_deployment_filters_test.go | 5 +- services/ecs/task_metadata.go | 8 +- services/ecs/task_metadata_test.go | 10 +- services/ecs/taskdef_validation.go | 5 +- services/ecs/undeclared_members_test.go | 6 +- services/efs/file_system_policy.go | 6 +- services/efs/handler.go | 10 +- services/efs/handler_access_points.go | 6 +- services/efs/handler_access_points_test.go | 11 +- services/efs/handler_account_preferences.go | 6 +- services/efs/handler_backup_policy.go | 6 +- services/efs/handler_backup_policy_test.go | 9 +- services/efs/handler_file_system_policy.go | 6 +- .../efs/handler_file_system_policy_test.go | 7 +- services/efs/handler_file_systems.go | 7 +- services/efs/handler_file_systems_test.go | 15 +- services/efs/handler_lifecycle_config.go | 6 +- services/efs/handler_lifecycle_config_test.go | 6 +- .../handler_mount_target_security_groups.go | 6 +- services/efs/handler_mount_targets.go | 6 +- services/efs/handler_mount_targets_test.go | 23 +- services/efs/handler_replication.go | 8 +- services/efs/handler_replication_test.go | 23 +- services/efs/handler_tags.go | 9 +- services/efs/helpers_test.go | 7 +- services/efs/persistence.go | 6 +- services/efs/wire_sdk_roundtrip_test.go | 5 +- services/eks/addons.go | 5 +- services/eks/capability_configuration.go | 14 +- services/eks/cluster_config_blocks.go | 41 +- services/eks/cluster_options_test.go | 5 +- services/eks/clusters.go | 4 +- services/eks/clusters_test.go | 9 +- services/eks/handler.go | 10 +- services/eks/handler_access_entries.go | 9 +- services/eks/handler_addons.go | 7 +- services/eks/handler_capabilities.go | 7 +- .../eks/handler_certificate_authorities.go | 9 +- services/eks/handler_clusters.go | 9 +- services/eks/handler_fargate_profiles.go | 5 +- services/eks/handler_identity_providers.go | 9 +- services/eks/handler_insights.go | 5 +- services/eks/handler_irsa.go | 6 +- services/eks/handler_node_groups.go | 9 +- services/eks/handler_pod_identity.go | 7 +- services/eks/handler_subscriptions.go | 7 +- services/eks/handler_tags.go | 6 +- services/eks/handler_test.go | 7 +- services/eks/handler_updates.go | 13 +- services/eks/idempotency.go | 26 +- services/eks/irsa.go | 8 +- services/eks/irsa_test.go | 7 +- services/eks/k8s_api.go | 10 +- services/eks/k8s_proxy.go | 6 +- services/eks/k8s_reconcile_internal_test.go | 6 +- services/eks/models.go | 44 +- services/eks/multi_region_test.go | 10 +- services/eks/node_groups_test.go | 7 +- services/eks/persistence.go | 8 +- services/eks/pod_identity_auth.go | 11 +- services/eks/updates.go | 8 +- services/eks/updates_test.go | 5 +- services/elasticache/persistence.go | 4 +- services/elasticache/persistence_test.go | 7 +- services/elasticbeanstalk/persistence.go | 6 +- services/elasticbeanstalk/store_test.go | 5 +- services/elasticsearch/handler.go | 5 +- .../handler_domain_advanced_options_test.go | 6 +- .../elasticsearch/handler_domain_config.go | 5 +- .../handler_domain_fields_test.go | 27 +- .../elasticsearch/handler_domain_lifecycle.go | 5 +- services/elasticsearch/handler_domains.go | 7 +- .../elasticsearch/handler_domains_test.go | 12 +- .../handler_outbound_connections.go | 5 +- services/elasticsearch/handler_packages.go | 5 +- services/elasticsearch/handler_tags.go | 7 +- services/elasticsearch/handler_tags_test.go | 13 +- services/elasticsearch/handler_test.go | 10 +- .../elasticsearch/handler_versions_test.go | 9 +- .../elasticsearch/handler_vpc_endpoints.go | 7 +- services/elasticsearch/persistence.go | 6 +- services/elasticsearch/persistence_test.go | 5 +- services/elb/persistence.go | 5 +- services/elb/persistence_test.go | 5 +- services/elbv2/dataplane.go | 7 +- services/elbv2/dataplane_lambda.go | 7 +- services/elbv2/dataplane_lambda_test.go | 6 +- services/elbv2/persistence.go | 4 +- services/elbv2/target_groups_test.go | 5 +- services/emr/handler.go | 7 +- services/emr/handler_cluster_settings_test.go | 16 +- services/emr/handler_clusters_test.go | 71 +-- services/emr/handler_instance_fleets_test.go | 23 +- services/emr/handler_instance_groups_test.go | 25 +- services/emr/handler_instances_test.go | 14 +- services/emr/handler_job_flows_test.go | 10 +- .../emr/handler_notebook_executions_test.go | 19 +- .../emr/handler_persistent_app_ui_test.go | 13 +- services/emr/handler_policies_test.go | 24 +- services/emr/handler_release_labels_test.go | 10 +- .../handler_security_configurations_test.go | 9 +- services/emr/handler_steps_test.go | 37 +- services/emr/handler_studios_test.go | 43 +- services/emr/handler_tags_test.go | 15 +- services/emr/handler_test.go | 9 +- services/emr/handler_wire_shape_test.go | 76 +-- services/emr/janitor_test.go | 5 +- services/emr/kerberos_secrets_test.go | 8 +- services/emr/models.go | 13 +- services/emr/persistence.go | 6 +- services/emr/request_validation_test.go | 8 +- services/emr/security_configurations.go | 5 +- services/emr/validation.go | 5 +- services/emr/wire_field_fixes_test.go | 15 +- services/emrserverless/handler.go | 11 +- .../handler_applications_test.go | 7 +- .../emrserverless/handler_job_runs_test.go | 9 +- .../handler_list_summary_test.go | 5 +- .../emrserverless/handler_sessions_test.go | 5 +- services/emrserverless/handler_test.go | 9 +- services/emrserverless/multi_region_test.go | 5 +- services/emrserverless/persistence.go | 8 +- services/emrserverless/persistence_test.go | 7 +- .../emrserverless/request_validation_test.go | 8 +- services/emrserverless/session_handler.go | 6 +- services/eventbridge/delivery.go | 15 +- .../eventbridge/delivery_api_destination.go | 9 +- .../delivery_api_destination_test.go | 5 +- services/eventbridge/delivery_ssm_appsync.go | 9 +- services/eventbridge/delivery_test.go | 7 +- services/eventbridge/delivery_transform.go | 12 +- services/eventbridge/envelope_map_test.go | 6 +- services/eventbridge/event_buses.go | 10 +- services/eventbridge/event_buses_test.go | 5 +- services/eventbridge/export_test.go | 6 +- .../eventbridge/handler_api_destinations.go | 14 +- services/eventbridge/handler_archives.go | 14 +- services/eventbridge/handler_connections.go | 16 +- services/eventbridge/handler_dispatch.go | 9 +- services/eventbridge/handler_endpoints.go | 14 +- .../eventbridge/handler_endpoints_test.go | 10 +- services/eventbridge/handler_event_buses.go | 21 +- .../eventbridge/handler_event_buses_test.go | 22 +- services/eventbridge/handler_event_sources.go | 12 +- .../eventbridge/handler_event_sources_test.go | 16 +- services/eventbridge/handler_events.go | 6 +- services/eventbridge/handler_events_test.go | 5 +- .../eventbridge/handler_partner_sources.go | 16 +- services/eventbridge/handler_registries.go | 14 +- services/eventbridge/handler_replays.go | 12 +- services/eventbridge/handler_replays_test.go | 16 +- services/eventbridge/handler_rules.go | 19 +- services/eventbridge/handler_rules_test.go | 21 +- services/eventbridge/handler_schemas.go | 32 +- services/eventbridge/handler_schemas_rest.go | 9 +- services/eventbridge/handler_schemas_test.go | 5 +- services/eventbridge/handler_tags.go | 9 +- services/eventbridge/handler_tags_test.go | 5 +- services/eventbridge/handler_targets.go | 10 +- services/eventbridge/handler_targets_test.go | 9 +- services/eventbridge/handler_test.go | 11 +- services/eventbridge/metrics.go | 5 +- services/eventbridge/pattern.go | 15 +- services/eventbridge/persistence.go | 12 +- services/eventbridge/persistence_test.go | 17 +- services/eventbridge/put_events.go | 5 +- services/eventbridge/put_events_test.go | 7 +- services/eventbridge/region_isolation_test.go | 20 +- services/eventbridge/rule_arn_format_test.go | 7 +- services/eventbridge/rules.go | 6 +- services/eventbridge/ssm_integration.go | 6 +- services/eventbridge/targets_test.go | 7 +- services/eventbridge/wire_field_fixes_test.go | 5 +- services/eventbridge/wire_time.go | 8 +- services/eventbridge/wire_time_test.go | 7 +- services/firehose/delivery_http.go | 19 +- services/firehose/delivery_opensearch.go | 5 +- .../firehose/delivery_realism_helpers_test.go | 7 +- services/firehose/delivery_realism_test.go | 15 +- services/firehose/delivery_splunk.go | 5 +- services/firehose/flush_test.go | 13 +- services/firehose/formats.go | 10 +- services/firehose/formats_infer_test.go | 14 +- services/firehose/formats_parquet.go | 15 +- services/firehose/handler.go | 11 +- services/firehose/handler_delivery_streams.go | 4 +- .../firehose/handler_delivery_streams_test.go | 25 +- .../firehose/handler_destination_updates.go | 4 +- .../handler_destination_updates_test.go | 9 +- services/firehose/handler_records_test.go | 17 +- services/firehose/handler_tags_test.go | 17 +- services/firehose/handler_test.go | 17 +- .../firehose/http_endpoint_secret_test.go | 6 +- services/firehose/isolation_test.go | 9 +- services/firehose/non_s3_delivery_test.go | 8 +- services/firehose/partitioning.go | 8 +- services/firehose/persistence.go | 14 +- services/firehose/persistence_test.go | 7 +- services/firehose/transform.go | 9 +- services/fis/actions_test.go | 9 +- services/fis/experiment_actions_mode_test.go | 20 +- services/fis/experiment_execution_test.go | 7 +- services/fis/experiment_reports_test.go | 12 +- services/fis/experiment_status_test.go | 36 +- services/fis/experiments_test.go | 5 +- services/fis/handler_experiment_templates.go | 8 +- services/fis/handler_experiments.go | 6 +- services/fis/handler_safety_levers.go | 6 +- services/fis/handler_tags.go | 6 +- .../handler_target_account_configurations.go | 7 +- services/fis/handler_test.go | 9 +- services/fis/persistence.go | 16 +- services/fis/safety_levers_test.go | 10 +- services/fis/target_resolution_test.go | 7 +- services/fis/wire_field_test.go | 12 +- services/forecast/handler.go | 28 +- .../forecast/handler_sdk_route_table_test.go | 5 +- services/forecast/handler_test.go | 7 +- services/forecast/persistence.go | 4 +- services/forecast/store.go | 7 +- services/fsx/client_request_token_test.go | 5 +- .../data_repository_and_cache_config_test.go | 12 +- services/fsx/file_cache_wire_test.go | 12 +- .../file_system_type_configuration_test.go | 22 +- services/fsx/file_systems.go | 5 +- services/fsx/handler.go | 7 +- services/fsx/handler_backups_test.go | 19 +- ...ndler_data_repository_associations_test.go | 11 +- .../fsx/handler_data_repository_tasks_test.go | 24 +- services/fsx/handler_file_caches_test.go | 15 +- services/fsx/handler_file_systems_test.go | 39 +- services/fsx/handler_s3_access_points_test.go | 10 +- .../handler_shared_vpc_configuration_test.go | 6 +- services/fsx/handler_snapshots_test.go | 17 +- .../handler_storage_virtual_machines_test.go | 11 +- services/fsx/handler_tags_test.go | 32 +- services/fsx/handler_test.go | 19 +- services/fsx/handler_volumes_test.go | 21 +- services/fsx/idempotency.go | 10 +- services/fsx/interfaces.go | 10 +- services/fsx/lustre_config.go | 93 +-- services/fsx/multi_region_test.go | 5 +- services/fsx/openzfs_volume_config_test.go | 7 +- services/fsx/page_token.go | 21 +- services/fsx/persistence.go | 4 +- services/fsx/persistence_test.go | 25 +- services/gcpapigateway/auth.go | 7 +- services/gcpapigateway/dataplane.go | 9 +- services/gcpapigateway/helpers_test.go | 8 +- services/gcpapigateway/persistence.go | 12 +- services/gcpapigateway/security_test.go | 9 +- services/gcpartifactregistry/filehttp.go | 8 +- services/gcpartifactregistry/files.go | 5 +- services/gcpartifactregistry/files_test.go | 5 +- services/gcpartifactregistry/helpers_test.go | 5 +- services/gcpartifactregistry/npm.go | 37 +- services/gcpartifactregistry/persistence.go | 24 +- services/gcpartifactregistry/pkgfmt.go | 5 +- services/gcpartifactregistry/pkgfmt_test.go | 7 +- services/gcpartifactregistry/python.go | 13 +- services/gcpartifactregistry/util.go | 6 +- services/gcpbatch/persistence.go | 6 +- services/gcpbigquery/autodetect.go | 11 +- services/gcpbigquery/bqsql/engine_test.go | 13 +- services/gcpbigquery/bqsql/sqlvalues.go | 16 +- services/gcpbigquery/bqsql/udf_array.go | 17 +- services/gcpbigquery/bqsql/udf_json.go | 11 +- services/gcpbigquery/bqsql/udf_regex.go | 6 +- services/gcpbigquery/bqsql/udf_str.go | 6 +- services/gcpbigquery/bqsql/udf_time.go | 6 +- services/gcpbigquery/bqsql/values.go | 17 +- services/gcpbigquery/handler.go | 14 +- services/gcpbigquery/jobs_extract.go | 18 +- services/gcpbigquery/jobs_query.go | 9 +- services/gcpbigquery/load_formats.go | 9 +- services/gcpbigquery/tables.go | 7 +- services/gcpbigtable/persistence.go | 40 +- services/gcpcloudbuild/bindings.go | 14 +- services/gcpcloudbuild/persistence.go | 28 +- services/gcpcloudbuild/publish.go | 5 +- services/gcpcloudbuild/pubsubtrigger.go | 5 +- services/gcpcloudtasks/helpers_test.go | 5 +- services/gcpcloudtasks/persistence.go | 32 +- services/gcpcompute/filter.go | 8 +- services/gcpcompute/handler.go | 7 +- services/gcpcompute/labels.go | 6 +- services/gcpcompute/lb_neg_test.go | 6 +- services/gcpcompute/meta.go | 12 +- services/gcpcompute/rest_test.go | 10 +- services/gcpcontainer/persistence.go | 44 +- services/gcpcontainer/rest_test.go | 7 +- services/gcpdatastore/persistence.go | 26 +- services/gcpdns/handler.go | 7 +- services/gcpdns/handler_test.go | 8 +- services/gcpdns/rrsets.go | 7 +- services/gcpdns/store.go | 15 +- services/gcpeventarc/delivery.go | 36 +- services/gcpeventarc/delivery_test.go | 8 +- services/gcpeventarc/persistence.go | 34 +- .../gcpeventarc/workflow_delivery_test.go | 10 +- services/gcpfirestore/persistence.go | 10 +- services/gcpfunctions/docker_test.go | 4 +- services/gcpfunctions/fake_runtime_test.go | 6 +- services/gcpfunctions/helpers_test.go | 5 +- services/gcpfunctions/ingress.go | 12 +- services/gcpfunctions/persistence.go | 20 +- services/gcpiam/keymat.go | 9 +- services/gcpiam/keys_test.go | 12 +- services/gcpiam/persistence.go | 22 +- services/gcpiam/sign.go | 16 +- services/gcpiam/sign_test.go | 10 +- services/gcpidentitytoolkit/handler.go | 7 +- services/gcpidentitytoolkit/helpers_test.go | 8 +- services/gcpidentitytoolkit/store.go | 15 +- services/gcpidentitytoolkit/tokens.go | 10 +- services/gcpidentitytoolkit/users.go | 5 +- services/gcpidentitytoolkit/wire.go | 10 +- services/gcpkms/persistence.go | 44 +- services/gcplogging/export_bq.go | 8 +- services/gcplogging/filter_eval.go | 8 +- services/gcplogging/persistence.go | 48 +- services/gcpmonitoring/alerts_test.go | 6 +- services/gcpmonitoring/helpers_test.go | 5 +- services/gcpmonitoring/notify.go | 5 +- services/gcpmonitoring/persistence.go | 46 +- services/gcpmonitoring/promql_http.go | 6 +- services/gcpmonitoring/promql_test.go | 11 +- services/gcppubsub/avro.go | 6 +- services/gcppubsub/persistence.go | 42 +- services/gcppubsub/push.go | 5 +- services/gcppubsub/schema.go | 19 +- services/gcppubsub/sdk_test.go | 6 +- services/gcpredis/persistence.go | 14 +- services/gcpredis/rest_test.go | 5 +- services/gcpresourcemanager/helpers_test.go | 6 +- services/gcpresourcemanager/persistence.go | 8 +- services/gcpresourcemanager/v1.go | 10 +- services/gcprun/persistence.go | 56 +- services/gcpscheduler/helpers_test.go | 5 +- services/gcpscheduler/persistence.go | 10 +- services/gcpsecretmanager/persistence.go | 20 +- services/gcpspanner/persistence.go | 18 +- services/gcpspanner/rest_test.go | 5 +- services/gcpsql/backups.go | 9 +- services/gcpsql/handler.go | 12 +- services/gcpsql/settingsdef.go | 6 +- services/gcpstorage/acl.go | 6 +- services/gcpstorage/events.go | 9 +- services/gcpstorage/events_test.go | 5 +- services/gcpstorage/handler_acl.go | 6 +- services/gcpstorage/handler_bucket.go | 5 +- services/gcpstorage/handler_object.go | 6 +- services/gcpstorage/handler_test.go | 11 +- services/gcpstorage/iam.go | 11 +- services/gcpstorage/iam_policy_test.go | 8 +- services/gcpstorage/models.go | 38 +- services/gcpstorage/patch.go | 17 +- services/gcpstorage/util.go | 9 +- services/gcpstorage/wire.go | 6 +- services/gcpworkflows/callbacks.go | 10 +- services/gcpworkflows/integration_test.go | 7 +- services/gcpworkflows/persistence.go | 18 +- services/glacier/handler_archives_test.go | 7 +- .../glacier/handler_data_retrieval_policy.go | 8 +- .../handler_data_retrieval_policy_test.go | 14 +- services/glacier/handler_job_output_test.go | 27 +- services/glacier/handler_jobs.go | 8 +- services/glacier/handler_jobs_test.go | 78 +-- .../glacier/handler_multipart_uploads_test.go | 64 ++- .../handler_provisioned_capacity_test.go | 17 +- services/glacier/handler_tags.go | 8 +- services/glacier/handler_tags_test.go | 12 +- services/glacier/handler_test.go | 14 +- .../glacier/handler_vault_access_policy.go | 6 +- .../handler_vault_access_policy_test.go | 6 +- services/glacier/handler_vault_lock.go | 6 +- services/glacier/handler_vault_lock_test.go | 25 +- .../glacier/handler_vault_notifications.go | 6 +- .../handler_vault_notifications_test.go | 10 +- services/glacier/handler_vaults_test.go | 38 +- services/glacier/inventory_retrieval_test.go | 11 +- services/glacier/oldshape_restore_test.go | 23 +- services/glacier/persistence.go | 4 +- services/glacier/persistence_test.go | 13 +- services/glacier/select_output.go | 5 +- services/glacier/select_output_test.go | 5 +- services/glacier/select_test.go | 20 +- services/glacier/vault_lock_policy_eval.go | 27 +- .../glacier/writesince_writesites_test.go | 5 +- services/globalaccelerator/handler.go | 5 +- services/globalaccelerator/handler_test.go | 9 +- services/globalaccelerator/persistence.go | 12 +- services/glue/blueprint_include_flags_test.go | 5 +- services/glue/crawl_run.go | 5 +- services/glue/crawler_lake.go | 7 +- services/glue/crawler_s3.go | 35 +- services/glue/get_partitions_index_test.go | 5 +- services/glue/get_partitions_segment_test.go | 8 +- services/glue/glossary_client_token_test.go | 8 +- services/glue/handler.go | 7 +- services/glue/handler_blueprints_test.go | 10 +- services/glue/handler_catalogs_test.go | 12 +- services/glue/handler_classifiers_test.go | 6 +- .../glue/handler_column_statistics_test.go | 13 +- .../glue/handler_connection_types_sdk_test.go | 9 +- .../glue/handler_connection_types_test.go | 6 +- services/glue/handler_connections_test.go | 23 +- services/glue/handler_crawlers_test.go | 23 +- .../glue/handler_custom_entity_types_test.go | 7 +- .../handler_data_quality_rulesets_test.go | 29 +- .../glue/handler_data_quality_stats_test.go | 35 +- services/glue/handler_databases_test.go | 5 +- services/glue/handler_dev_endpoints_test.go | 9 +- services/glue/handler_entities_test.go | 31 +- services/glue/handler_etl_test.go | 18 +- services/glue/handler_identity_center_test.go | 6 +- services/glue/handler_integrations_test.go | 26 +- services/glue/handler_jobs.go | 16 +- services/glue/handler_jobs_test.go | 29 +- .../glue/handler_materialized_views_test.go | 16 +- services/glue/handler_ml_test.go | 29 +- services/glue/handler_pagination_test.go | 10 +- .../glue/handler_partition_indexes_test.go | 5 +- services/glue/handler_partitions_test.go | 19 +- services/glue/handler_resource_limits_test.go | 7 +- .../glue/handler_resource_policies_test.go | 12 +- services/glue/handler_schemas.go | 8 +- services/glue/handler_schemas_test.go | 37 +- services/glue/handler_smoke_test.go | 5 +- .../glue/handler_table_optimizers_test.go | 6 +- services/glue/handler_tables_test.go | 15 +- services/glue/handler_test.go | 43 +- services/glue/handler_triggers_test.go | 13 +- services/glue/handler_unfiltered_test.go | 28 +- services/glue/handler_usage_profiles_test.go | 6 +- .../handler_user_defined_functions_test.go | 6 +- services/glue/handler_workflows_test.go | 43 +- services/glue/models.go | 23 +- services/glue/multi_region_test.go | 5 +- services/glue/persistence.go | 4 +- services/glue/persistence_test.go | 7 +- services/glue/policy_shares.go | 18 +- services/glue/schema_avro.go | 6 +- services/glue/schema_json.go | 6 +- services/glue/search_tables_sort_test.go | 6 +- services/glue/session_docker.go | 14 +- services/glue/timestamp_wire_shape_test.go | 12 +- services/glue/trigger_conditional_test.go | 5 +- services/glue/wire_arn_no_leak_test.go | 7 +- services/glue/wire_field_fixes_test.go | 7 +- services/glue/workflow_run_options_test.go | 12 +- services/grafana/handler.go | 5 +- services/grafana/handler_api_keys.go | 10 +- services/grafana/handler_authentication.go | 10 +- services/grafana/handler_configuration.go | 10 +- services/grafana/handler_license.go | 8 +- services/grafana/handler_permissions.go | 9 +- .../grafana/handler_service_account_tokens.go | 11 +- services/grafana/handler_service_accounts.go | 11 +- services/grafana/handler_tags.go | 12 +- services/grafana/handler_versions.go | 5 +- services/grafana/handler_workspaces.go | 17 +- services/grafana/persistence.go | 14 +- .../guardduty/coverage_statistics_test.go | 9 +- services/guardduty/cross_service_test.go | 5 +- services/guardduty/detectors_test.go | 27 +- services/guardduty/entity_sets_test.go | 23 +- services/guardduty/filters_test.go | 15 +- services/guardduty/finding_criteria.go | 12 +- services/guardduty/finding_criteria_test.go | 5 +- services/guardduty/finding_statistics_test.go | 10 +- services/guardduty/findings_test.go | 25 +- .../guardduty/handler_coverage_statistics.go | 8 +- services/guardduty/handler_detectors.go | 8 +- services/guardduty/handler_entity_sets.go | 11 +- services/guardduty/handler_filters.go | 7 +- services/guardduty/handler_findings.go | 18 +- services/guardduty/handler_investigations.go | 7 +- .../handler_ip_and_threatintel_sets.go | 12 +- .../handler_ip_and_threatintel_sets_test.go | 8 +- .../guardduty/handler_malware_protection.go | 17 +- services/guardduty/handler_members.go | 30 +- services/guardduty/handler_organization.go | 10 +- .../handler_publishing_destinations.go | 8 +- services/guardduty/handler_tags.go | 6 +- services/guardduty/handler_tagsync_test.go | 5 +- services/guardduty/handler_test.go | 7 +- services/guardduty/handler_usage.go | 8 +- services/guardduty/handler_wireshape_test.go | 36 +- services/guardduty/ip_sets_test.go | 27 +- .../malware_protection_plan_schema.go | 14 +- services/guardduty/malware_protection_test.go | 27 +- services/guardduty/members_test.go | 23 +- services/guardduty/multi_region_test.go | 5 +- services/guardduty/organization_test.go | 11 +- services/guardduty/persistence.go | 6 +- .../guardduty/publishing_destinations_test.go | 11 +- services/guardduty/tags_test.go | 17 +- services/guardduty/threat_intel_sets_test.go | 23 +- services/guardduty/usage_test.go | 14 +- services/guardduty/wire_field_fixes_test.go | 5 +- services/iam/accounts.go | 10 +- services/iam/aws_managed.go | 28 +- services/iam/aws_managed_test.go | 16 +- services/iam/conditions_test.go | 5 +- services/iam/enforcement_integration_test.go | 7 +- services/iam/evaluator.go | 5 +- services/iam/handler_inline_policies.go | 9 +- services/iam/middleware.go | 5 +- services/iam/persistence.go | 10 +- services/iam/policy_validation.go | 35 +- services/iam/request_scope.go | 7 +- services/iam/resource_arn.go | 5 +- services/iam/role_templates.go | 5 +- services/iam/roles.go | 26 +- services/identitystore/epoch_time_test.go | 12 +- services/identitystore/guard_sentinel_test.go | 5 +- services/identitystore/handler.go | 9 +- .../handler_group_memberships.go | 18 +- services/identitystore/handler_groups.go | 14 +- services/identitystore/handler_guard_test.go | 5 +- services/identitystore/handler_test.go | 9 +- services/identitystore/handler_users.go | 14 +- services/identitystore/models.go | 7 +- services/identitystore/persistence.go | 14 +- services/inspector2/handler.go | 5 +- services/inspector2/handler_cis_scans.go | 23 +- services/inspector2/handler_cis_scans_test.go | 41 +- services/inspector2/handler_code_security.go | 29 +- .../inspector2/handler_code_security_test.go | 43 +- services/inspector2/handler_connectors.go | 15 +- .../inspector2/handler_coverage_reporting.go | 5 +- .../handler_coverage_reporting_test.go | 15 +- .../inspector2/handler_ec2_configuration.go | 11 +- .../handler_ec2_configuration_test.go | 12 +- .../inspector2/handler_ecr_configuration.go | 5 +- .../handler_ecr_configuration_test.go | 6 +- services/inspector2/handler_enablement.go | 13 +- .../inspector2/handler_enablement_test.go | 21 +- services/inspector2/handler_encryption.go | 7 +- .../inspector2/handler_encryption_test.go | 6 +- services/inspector2/handler_filters.go | 11 +- services/inspector2/handler_filters_test.go | 19 +- services/inspector2/handler_findings.go | 17 +- .../inspector2/handler_findings_core_test.go | 7 +- .../handler_findings_reports_test.go | 17 +- services/inspector2/handler_members.go | 11 +- services/inspector2/handler_members_test.go | 10 +- services/inspector2/handler_organization.go | 9 +- .../inspector2/handler_organization_test.go | 12 +- services/inspector2/handler_sbom.go | 9 +- services/inspector2/handler_sbom_test.go | 8 +- services/inspector2/handler_tags.go | 5 +- services/inspector2/handler_tags_test.go | 9 +- services/inspector2/handler_test.go | 17 +- services/inspector2/handler_usage.go | 7 +- services/inspector2/handler_usage_test.go | 9 +- services/inspector2/paging.go | 5 +- services/inspector2/persistence.go | 10 +- .../required_output_members_test.go | 6 +- .../inspector2/wire_field_fixes_y1zn_test.go | 5 +- services/iot/authorizer_invoke.go | 20 +- services/iot/broker_auth.go | 5 +- services/iot/broker_commands.go | 8 +- services/iot/broker_custom_auth_test.go | 9 +- services/iot/broker_events.go | 6 +- services/iot/broker_events_test.go | 9 +- services/iot/broker_jobs.go | 19 +- services/iot/broker_jobs_test.go | 5 +- services/iot/command_executions_test.go | 9 +- services/iot/events.go | 6 +- services/iot/handler.go | 8 +- .../handler_audit_suppressions_list_test.go | 14 +- services/iot/handler_billing_groups.go | 7 +- services/iot/handler_billing_groups_test.go | 6 +- services/iot/handler_certificates.go | 14 +- services/iot/handler_certificates_test.go | 15 +- services/iot/handler_helpers.go | 12 +- services/iot/handler_helpers_test.go | 12 +- services/iot/handler_indexing.go | 12 +- services/iot/handler_jobs.go | 14 +- services/iot/handler_jobs_test.go | 9 +- services/iot/handler_packages.go | 7 +- services/iot/handler_policies.go | 14 +- services/iot/handler_policies_test.go | 20 +- services/iot/handler_routing_test.go | 9 +- services/iot/handler_tags_wire_test.go | 9 +- services/iot/handler_test.go | 34 +- services/iot/handler_thing_groups.go | 12 +- services/iot/handler_thing_types.go | 8 +- services/iot/handler_thing_types_test.go | 6 +- .../iot/handler_thingtype_searchable_test.go | 6 +- services/iot/handler_topic_rules.go | 16 +- services/iot/handler_topic_rules_test.go | 12 +- services/iot/jobs_data_plane_test.go | 8 +- services/iot/multi_region_test.go | 5 +- services/iot/names.go | 32 +- services/iot/ota_options.go | 8 +- services/iot/ota_updates.go | 5 +- services/iot/persistence.go | 12 +- services/iot/policy_evaluation.go | 10 +- services/iot/realism_test.go | 6 +- services/iot/rule_actions.go | 45 +- services/iot/rule_authz.go | 5 +- services/iot/rule_http.go | 7 +- services/iot/rule_http_destinations.go | 7 +- services/iot/rule_lookups.go | 7 +- services/iot/rule_republish.go | 4 +- services/iot/sql_value.go | 62 +- services/iot/things_test.go | 7 +- services/iot/topic_rules.go | 6 +- services/iot/types.go | 23 +- services/iotanalytics/handler_channels.go | 8 +- .../iotanalytics/handler_channels_test.go | 16 +- services/iotanalytics/handler_datasets.go | 10 +- .../iotanalytics/handler_datasets_test.go | 34 +- services/iotanalytics/handler_datastores.go | 8 +- .../iotanalytics/handler_datastores_test.go | 14 +- services/iotanalytics/handler_logging.go | 6 +- services/iotanalytics/handler_logging_test.go | 6 +- services/iotanalytics/handler_messages.go | 6 +- .../iotanalytics/handler_messages_test.go | 8 +- services/iotanalytics/handler_pipelines.go | 12 +- .../iotanalytics/handler_pipelines_test.go | 18 +- .../handler_sdk_route_table_test.go | 6 +- services/iotanalytics/handler_tags.go | 6 +- services/iotanalytics/handler_tags_test.go | 16 +- services/iotanalytics/handler_test.go | 15 +- services/iotanalytics/persistence.go | 4 +- services/iotanalytics/pipeline_expr_test.go | 5 +- .../iotanalytics/pipeline_lambda_iot_test.go | 17 +- services/iotanalytics/pipelines.go | 12 +- services/iotanalytics/pipelines_test.go | 5 +- .../wire_shape_sdk_roundtrip_test.go | 7 +- services/iotdataplane/connections_test.go | 25 +- services/iotdataplane/export_test.go | 10 +- services/iotdataplane/handler_publish.go | 10 +- .../handler_sdk_route_table_test.go | 6 +- services/iotdataplane/handler_test.go | 7 +- services/iotdataplane/models.go | 10 +- services/iotdataplane/persistence.go | 30 +- services/iotdataplane/persistence_test.go | 7 +- services/iotdataplane/publish.go | 6 +- .../iotdataplane/retained_messages_test.go | 25 +- services/iotdataplane/shadows.go | 88 +-- services/iotdataplane/shadows_merge_test.go | 38 +- .../iotdataplane/shadows_pagination_test.go | 29 +- services/iotdataplane/shadows_state_test.go | 35 +- services/iotdataplane/shadows_test.go | 25 +- .../iotdataplane/shadows_validation_test.go | 17 +- services/iotdataplane/value_semantics_test.go | 8 +- services/iotdataplane/whitebox_test.go | 6 +- .../iotdataplane/wire_sdk_roundtrip_test.go | 5 +- services/iotwireless/handler.go | 11 +- services/iotwireless/handler_certificates.go | 11 +- .../iotwireless/handler_certificates_test.go | 34 +- services/iotwireless/handler_destinations.go | 7 +- .../iotwireless/handler_destinations_test.go | 12 +- .../handler_event_configurations.go | 6 +- .../handler_event_configurations_test.go | 26 +- services/iotwireless/handler_fuota_tasks.go | 13 +- .../iotwireless/handler_fuota_tasks_test.go | 47 +- services/iotwireless/handler_log_levels.go | 8 +- .../iotwireless/handler_log_levels_test.go | 14 +- services/iotwireless/handler_metrics.go | 8 +- services/iotwireless/handler_metrics_test.go | 20 +- .../iotwireless/handler_multicast_groups.go | 16 +- .../handler_multicast_groups_test.go | 41 +- .../iotwireless/handler_network_analyzer.go | 7 +- .../handler_network_analyzer_test.go | 12 +- .../iotwireless/handler_partner_accounts.go | 5 +- .../handler_partner_accounts_test.go | 14 +- services/iotwireless/handler_positioning.go | 10 +- .../iotwireless/handler_positioning_test.go | 20 +- services/iotwireless/handler_profiles.go | 7 +- services/iotwireless/handler_profiles_test.go | 28 +- services/iotwireless/handler_tags.go | 5 +- services/iotwireless/handler_tags_test.go | 8 +- services/iotwireless/handler_test.go | 17 +- .../iotwireless/handler_wireless_devices.go | 11 +- .../handler_wireless_devices_filter_test.go | 5 +- .../handler_wireless_devices_test.go | 59 +- ...handler_wireless_devices_wireshape_test.go | 14 +- .../handler_wireless_gateway_tasks.go | 8 +- .../handler_wireless_gateway_tasks_test.go | 30 +- .../iotwireless/handler_wireless_gateways.go | 9 +- .../handler_wireless_gateways_test.go | 37 +- services/iotwireless/idempotency.go | 8 +- .../idempotency_persistence_test.go | 7 +- .../iotwireless/import_task_single_test.go | 10 +- services/iotwireless/multi_region_test.go | 8 +- services/iotwireless/multicast_bulk_test.go | 5 +- services/iotwireless/pagination_test.go | 6 +- services/iotwireless/persistence.go | 12 +- .../wireless_gateway_tasks_test.go | 5 +- services/kafka/handler.go | 9 +- services/kafka/handler_channels.go | 8 +- services/kafka/handler_channels_test.go | 7 +- .../kafka/handler_cluster_operations_test.go | 17 +- services/kafka/handler_cluster_policy.go | 6 +- services/kafka/handler_cluster_policy_test.go | 5 +- services/kafka/handler_cluster_updates.go | 18 +- .../kafka/handler_cluster_updates_test.go | 15 +- services/kafka/handler_clusters.go | 8 +- .../kafka/handler_clusters_fields_test.go | 13 +- .../kafka/handler_clusters_shapes_test.go | 23 +- services/kafka/handler_clusters_test.go | 45 +- services/kafka/handler_configurations.go | 8 +- services/kafka/handler_configurations_test.go | 19 +- services/kafka/handler_nodes_test.go | 5 +- services/kafka/handler_replicators.go | 8 +- services/kafka/handler_replicators_test.go | 17 +- services/kafka/handler_scram_secrets.go | 8 +- services/kafka/handler_scram_secrets_test.go | 28 +- services/kafka/handler_tags.go | 6 +- services/kafka/handler_tags_test.go | 12 +- services/kafka/handler_test.go | 9 +- services/kafka/handler_topics.go | 8 +- services/kafka/handler_topics_test.go | 18 +- services/kafka/handler_vpc_connections.go | 8 +- .../kafka/handler_vpc_connections_test.go | 25 +- services/kafka/iam_auth.go | 5 +- services/kafka/persistence.go | 16 +- services/kafka/routes_test.go | 13 +- services/kafka/scram_sync.go | 12 +- services/kafkaconnect/handler.go | 5 +- services/kafkaconnect/multi_region_test.go | 8 +- services/kafkaconnect/persistence.go | 6 +- services/kafkaconnect/worker_engine.go | 7 +- services/kinesis/account_settings_test.go | 13 +- services/kinesis/cbor_test.go | 19 +- services/kinesis/channel_delivery.go | 8 +- services/kinesis/consumer_wire_shape_test.go | 8 +- services/kinesis/consumers_test.go | 41 +- services/kinesis/errors_test.go | 6 +- services/kinesis/handler.go | 7 +- services/kinesis/handler_account_settings.go | 7 +- services/kinesis/handler_channels.go | 13 +- services/kinesis/handler_consumers.go | 15 +- services/kinesis/handler_monitoring.go | 8 +- services/kinesis/handler_records.go | 10 +- services/kinesis/handler_resharding.go | 10 +- services/kinesis/handler_resource_policy.go | 10 +- services/kinesis/handler_shard_iterators.go | 6 +- services/kinesis/handler_shards.go | 6 +- services/kinesis/handler_stream_encryption.go | 8 +- services/kinesis/handler_stream_modes.go | 8 +- services/kinesis/handler_stream_retention.go | 8 +- services/kinesis/handler_streams.go | 13 +- services/kinesis/handler_tags.go | 15 +- services/kinesis/handler_test.go | 11 +- services/kinesis/inspect_test.go | 5 +- services/kinesis/monitoring_test.go | 10 +- services/kinesis/page_token.go | 8 +- services/kinesis/persistence.go | 10 +- .../kinesis/persistence_roundtrip_test.go | 13 +- services/kinesis/persistence_test.go | 5 +- services/kinesis/records_get_test.go | 51 +- services/kinesis/records_test.go | 17 +- .../kinesis/resharding_shard_count_test.go | 11 +- services/kinesis/resharding_test.go | 29 +- services/kinesis/resource_policy_test.go | 7 +- services/kinesis/ring_buffer.go | 8 +- services/kinesis/shard_iterators.go | 8 +- services/kinesis/shard_iterators_test.go | 19 +- services/kinesis/shards_test.go | 19 +- services/kinesis/stream_encryption_test.go | 9 +- services/kinesis/stream_modes_test.go | 7 +- services/kinesis/stream_retention_test.go | 7 +- services/kinesis/streams_describe_test.go | 50 +- services/kinesis/streams_test.go | 27 +- services/kinesis/tags_test.go | 37 +- .../application_cloudwatch_test.go | 5 +- .../application_inputs_test.go | 5 +- .../application_outputs_test.go | 5 +- .../application_reference_data_test.go | 5 +- .../application_update_test.go | 11 +- .../applications_handler_test.go | 9 +- .../kinesisanalytics/applications_test.go | 7 +- services/kinesisanalytics/discover_schema.go | 20 +- .../kinesisanalytics/discover_schema_test.go | 5 +- services/kinesisanalytics/handler.go | 13 +- services/kinesisanalytics/handler_test.go | 7 +- services/kinesisanalytics/persistence.go | 16 +- services/kinesisanalytics/persistence_test.go | 13 +- services/kinesisanalytics/tags_test.go | 5 +- .../application_update_test.go | 5 +- .../kinesisanalyticsv2/flink_engine_test.go | 6 +- services/kinesisanalyticsv2/flink_rest.go | 8 +- services/kinesisanalyticsv2/flink_run.go | 5 +- services/kinesisanalyticsv2/handler.go | 5 +- .../handler_application_config.go | 26 +- .../handler_application_config_delete_test.go | 13 +- .../handler_application_config_test.go | 19 +- .../handler_application_presigned_url.go | 6 +- .../handler_application_presigned_url_test.go | 5 +- .../handler_application_snapshots.go | 18 +- .../handler_application_snapshots_test.go | 6 +- .../handler_application_update.go | 6 +- .../handler_application_update_test.go | 28 +- .../handler_application_versions.go | 13 +- .../handler_application_versions_test.go | 12 +- .../handler_applications.go | 25 +- .../handler_applications_test.go | 25 +- services/kinesisanalyticsv2/handler_tags.go | 10 +- .../kinesisanalyticsv2/handler_tags_test.go | 10 +- services/kinesisanalyticsv2/handler_test.go | 5 +- services/kinesisanalyticsv2/persistence.go | 4 +- .../wire_field_fixes_test.go | 8 +- services/kinesisvideo/handler.go | 5 +- services/kinesisvideo/handler_configs.go | 12 +- services/kinesisvideo/handler_edge.go | 12 +- services/kinesisvideo/handler_signaling.go | 14 +- services/kinesisvideo/handler_storage.go | 19 +- services/kinesisvideo/handler_streams.go | 17 +- services/kinesisvideo/handler_tags.go | 16 +- services/kinesisvideo/multi_region_test.go | 8 +- services/kinesisvideo/persistence.go | 6 +- services/kms/aliases_test.go | 5 +- services/kms/custom_key_stores_test.go | 25 +- .../kms/describe_key_grant_tokens_test.go | 5 +- services/kms/errtarget_findings_test.go | 13 +- services/kms/grant_authz.go | 12 +- services/kms/handler.go | 11 +- services/kms/handler_alias_rotation.go | 18 +- services/kms/handler_alias_rotation_test.go | 41 +- services/kms/handler_crypto.go | 20 +- services/kms/handler_crypto_test.go | 59 +- services/kms/handler_custom_key_stores.go | 16 +- .../kms/handler_custom_key_stores_test.go | 33 +- services/kms/handler_generate_and_mac.go | 14 +- services/kms/handler_generate_and_mac_test.go | 21 +- services/kms/handler_grants_policies.go | 18 +- services/kms/handler_grants_policies_test.go | 44 +- services/kms/handler_keys.go | 5 +- services/kms/handler_keys_test.go | 33 +- .../kms/handler_replication_maintenance.go | 20 +- .../handler_replication_maintenance_test.go | 49 +- services/kms/handler_tags.go | 9 +- services/kms/handler_tags_persistence_test.go | 5 +- services/kms/handler_tags_test.go | 41 +- services/kms/handler_test.go | 8 +- services/kms/helpers_test.go | 13 +- services/kms/import_error_wiring_test.go | 15 +- services/kms/incorrect_key_test.go | 7 +- services/kms/isolation_test.go | 29 +- services/kms/key_policies.go | 5 +- services/kms/mac_algorithm_wiring_test.go | 7 +- services/kms/persistence.go | 16 +- services/kms/realism_validation_test.go | 11 +- services/kms/replicate_key_policy_test.go | 11 +- services/kms/terraform_lifecycle_test.go | 21 +- services/kms/undeclared_members_test.go | 8 +- services/kms/validation.go | 6 +- services/kms/wire_error_types_test.go | 9 +- services/lakeformation/handler_credentials.go | 12 +- .../lakeformation/handler_credentials_test.go | 7 +- .../handler_data_cells_filter.go | 14 +- .../handler_data_lake_settings.go | 8 +- .../handler_data_lake_settings_test.go | 5 +- .../handler_lake_formation_identity_center.go | 12 +- ...ler_lake_formation_identity_center_test.go | 7 +- .../handler_lf_tag_expression.go | 14 +- services/lakeformation/handler_lf_tags.go | 24 +- .../lakeformation/handler_lf_tags_test.go | 19 +- services/lakeformation/handler_opt_ins.go | 10 +- services/lakeformation/handler_permissions.go | 16 +- .../lakeformation/handler_permissions_test.go | 11 +- services/lakeformation/handler_resources.go | 14 +- .../lakeformation/handler_resources_test.go | 9 +- .../lakeformation/handler_table_storage.go | 12 +- services/lakeformation/handler_test.go | 10 +- .../lakeformation/handler_transactions.go | 18 +- .../handler_transactions_test.go | 7 +- services/lakeformation/handler_work_units.go | 14 +- .../lakeformation/handler_work_units_test.go | 5 +- services/lakeformation/multi_region_test.go | 8 +- .../lakeformation/pagination_validation.go | 8 +- services/lakeformation/persistence.go | 10 +- services/lakeformation/persistence_test.go | 5 +- services/lambda/account_settings_test.go | 16 +- services/lambda/async_destinations.go | 22 +- services/lambda/capacity_providers_test.go | 20 +- services/lambda/code_signing_test.go | 26 +- services/lambda/concurrency_test.go | 18 +- services/lambda/ddb_esm_test.go | 5 +- .../lambda/delete_function_cleanup_test.go | 8 +- services/lambda/dispatch_test.go | 12 +- services/lambda/durable_execution_test.go | 29 +- services/lambda/esm_config_test.go | 68 +-- services/lambda/esm_failure.go | 5 +- services/lambda/esm_failure_internal_test.go | 19 +- services/lambda/esm_kafka_failure.go | 4 +- services/lambda/esm_logging.go | 5 +- services/lambda/esm_partial_batch_test.go | 5 +- services/lambda/esm_stream_retry.go | 12 +- services/lambda/esm_stream_window.go | 38 +- .../lambda/esm_stream_window_internal_test.go | 29 +- services/lambda/esm_test.go | 23 +- services/lambda/esm_tuning_validation_test.go | 6 +- services/lambda/event_filter.go | 77 +-- services/lambda/event_invoke_config_test.go | 22 +- services/lambda/event_source_poller.go | 18 +- services/lambda/event_source_poller_test.go | 5 +- services/lambda/extensions_api.go | 14 +- .../lambda/extensions_api_internal_test.go | 13 +- services/lambda/fis.go | 5 +- services/lambda/function_fields_test.go | 82 +-- services/lambda/function_settings_test.go | 22 +- .../lambda/function_tenancy_capacity_test.go | 8 +- services/lambda/function_url_host_test.go | 9 +- services/lambda/function_url_http.go | 11 +- services/lambda/function_urls_test.go | 24 +- services/lambda/functions_test.go | 62 +- .../lambda/get_function_qualifier_test.go | 9 +- services/lambda/handler_capacity_providers.go | 7 +- services/lambda/handler_code_signing.go | 9 +- services/lambda/handler_concurrency.go | 12 +- services/lambda/handler_durable_execution.go | 11 +- .../lambda/handler_event_invoke_config.go | 7 +- .../lambda/handler_event_source_mappings.go | 7 +- services/lambda/handler_function_settings.go | 9 +- services/lambda/handler_function_urls.go | 7 +- services/lambda/handler_function_urls_test.go | 7 +- services/lambda/handler_functions.go | 9 +- services/lambda/handler_invocation.go | 12 +- services/lambda/handler_layers.go | 7 +- services/lambda/handler_permissions.go | 5 +- services/lambda/handler_resource_policy.go | 5 +- services/lambda/handler_runtime_test.go | 5 +- services/lambda/handler_tags.go | 5 +- services/lambda/handler_tags_iam_test.go | 7 +- services/lambda/handler_test.go | 13 +- services/lambda/handler_versions_aliases.go | 9 +- .../lambda/handler_versions_aliases_test.go | 15 +- services/lambda/invocation_test.go | 7 +- services/lambda/kafka_event.go | 6 +- services/lambda/kafka_event_internal_test.go | 6 +- .../lambda/kafka_integration_internal_test.go | 6 +- services/lambda/kafka_msk_internal_test.go | 6 +- services/lambda/kafka_worker_internal_test.go | 6 +- services/lambda/layer_permissions_test.go | 14 +- services/lambda/layers.go | 7 +- services/lambda/layers_http_test.go | 20 +- services/lambda/layers_test.go | 5 +- .../list_functions_master_region_test.go | 9 +- services/lambda/mq_event.go | 8 +- services/lambda/mq_event_internal_test.go | 6 +- services/lambda/mq_worker.go | 5 +- services/lambda/mq_worker_internal_test.go | 6 +- services/lambda/multi_region_test.go | 14 +- services/lambda/permissions.go | 9 +- services/lambda/permissions_test.go | 34 +- services/lambda/persistence.go | 12 +- .../lambda/provisioned_concurrency_test.go | 26 +- .../lambda/publish_latest_published_test.go | 8 +- services/lambda/snapstart_extra_test.go | 8 +- services/lambda/store_test.go | 5 +- services/lambda/tags_test.go | 16 +- services/lambda/test_helpers_test.go | 5 +- services/lambda/versions_aliases_test.go | 54 +- services/lambda/zip_handler_test.go | 15 +- services/lightsail/error_envelope_test.go | 5 +- services/lightsail/handler.go | 18 +- services/lightsail/multi_region_test.go | 5 +- services/lightsail/persistence.go | 18 +- .../sdk_roundtrip_field_fixes_test.go | 18 +- 2460 files changed, 18923 insertions(+), 15106 deletions(-) diff --git a/pkgs/jsonx/jsonx.go b/pkgs/jsonx/jsonx.go index f10627420f..6efe2b820f 100644 --- a/pkgs/jsonx/jsonx.go +++ b/pkgs/jsonx/jsonx.go @@ -26,8 +26,8 @@ // json.Valid(b) jsontext.Value(b).IsValid(jsonx.V1()) // json.Compact / Indent jsontext.Value.Compact / Indent // json.Marshaler, Unmarshaler same names in v2 (MarshalJSON / UnmarshalJSON still honored) -// *json.SyntaxError *jsontext.SyntacticError -// *json.UnmarshalTypeError *json.SemanticError +// *json.SyntaxError jsonx.SyntaxError / IsSyntaxError +// *json.UnmarshalTypeError jsonx.TypeError / IsTypeError // // Use UnmarshalRead instead of UnmarshalDecode only when trailing data after // the first value must be an error; v1 Decoder.Decode ignored it. @@ -39,7 +39,9 @@ import ( "encoding/json/v2" "errors" "fmt" + "io" "strconv" + "strings" ) var ( @@ -52,6 +54,54 @@ func V1() json.Options { return jsonv1.DefaultOptionsV1() } +// SyntaxError reports whether err is a JSON syntax error and its byte offset. +// With V1 options the v2 engine returns the v1 error types, so both are accepted. +func SyntaxError(err error) (int64, bool) { + if se, ok := errors.AsType[*jsonv1.SyntaxError](err); ok { + return se.Offset, true + } + + if se, ok := errors.AsType[*jsontext.SyntacticError](err); ok { + return se.ByteOffset, true + } + + return 0, false +} + +// IsSyntaxError reports whether err is a JSON syntax error. +func IsSyntaxError(err error) bool { + _, ok := SyntaxError(err) + + return ok +} + +// TypeError reports whether err is a JSON value/type mismatch and the dotted +// path of the offending member (the v1 UnmarshalTypeError.Field form). +func TypeError(err error) (string, bool) { + if te, ok := errors.AsType[*jsonv1.UnmarshalTypeError](err); ok { + return te.Field, true + } + + if se, ok := errors.AsType[*json.SemanticError](err); ok { + return strings.ReplaceAll(strings.TrimPrefix(string(se.JSONPointer), "/"), "/", "."), true + } + + return "", false +} + +// IsTypeError reports whether err is a JSON value/type mismatch. +func IsTypeError(err error) bool { + _, ok := TypeError(err) + + return ok +} + +// SDKDecoder returns a v1 decoder for AWS SDK helpers that still take +// *encoding/json.Decoder (e.g. restjson.GetErrorInfo). +func SDKDecoder(r io.Reader) *jsonv1.Decoder { + return jsonv1.NewDecoder(r) +} + // Number is a JSON number kept in its textual form, the v2 stand-in for // v1 json.Number. It is produced for untyped numbers when UseNumber is set. type Number string diff --git a/pkgs/jsonx/jsonx_test.go b/pkgs/jsonx/jsonx_test.go index 64237b7e29..89f976a3cb 100644 --- a/pkgs/jsonx/jsonx_test.go +++ b/pkgs/jsonx/jsonx_test.go @@ -108,3 +108,52 @@ func TestDecoderStreamTolerantOfTrailingData(t *testing.T) { require.NoError(t, json.UnmarshalDecode(dec, &v, jsonx.V1())) assert.Equal(t, map[string]int{"a": 1}, v) } + +func TestErrorClassifiers(t *testing.T) { + t.Parallel() + + type doc struct { + A struct{ B int } `json:"a"` + } + + tests := []struct { + name string + body string + field string + wantSyn bool + wantType bool + wantNoErr bool + }{ + {name: "garbage", body: `not json`, wantSyn: true}, + {name: "truncated", body: `{"a":`, wantSyn: true}, + {name: "type_mismatch", body: `{"a":{"B":"x"}}`, wantType: true, field: "a.B"}, + {name: "ok", body: `{"a":{"B":1}}`, wantNoErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + var d doc + + err := json.Unmarshal([]byte(tt.body), &d, jsonx.V1()) + if tt.wantNoErr { + require.NoError(t, err) + + return + } + + require.Error(t, err) + assert.Equal(t, tt.wantSyn, jsonx.IsSyntaxError(err)) + assert.Equal(t, tt.wantType, jsonx.IsTypeError(err)) + + if tt.wantType { + field, _ := jsonx.TypeError(err) + assert.Equal(t, tt.field, field) + } + }) + } + + _, ok := jsonx.SyntaxError(json.Unmarshal([]byte(`{"a":1}x`), new(doc), jsonx.V1())) + assert.True(t, ok) +} diff --git a/pkgs/persistence/testdata/snapshot_inventory.json b/pkgs/persistence/testdata/snapshot_inventory.json index 298ca89f5d..f3514522f0 100644 --- a/pkgs/persistence/testdata/snapshot_inventory.json +++ b/pkgs/persistence/testdata/snapshot_inventory.json @@ -2,7 +2,7 @@ "accessanalyzer": { "fields": [ "AccessPreview.AnalyzerArn string", - "AccessPreview.Configurations map[string]json.RawMessage", + "AccessPreview.Configurations map[string]jsontext.Value", "AccessPreview.CreatedAt time.Time", "AccessPreview.ID string", "AccessPreview.Status AccessPreviewStatus", @@ -14,7 +14,7 @@ "AnalyzedResource.ResourceType string", "AnalyzedResource.UpdatedAt time.Time", "Analyzer.Arn string `json:\"arn\"`", - "Analyzer.Configuration json.RawMessage `json:\"configuration,omitempty\"`", + "Analyzer.Configuration jsontext.Value `json:\"configuration,omitempty\"`", "Analyzer.CreatedAt time.Time `json:\"createdAt\"`", "Analyzer.LastResourceAnalyzed string `json:\"lastResourceAnalyzed,omitempty\"`", "Analyzer.LastResourceAnalyzedAt *time.Time `json:\"lastResourceAnalyzedAt,omitempty\"`", @@ -69,7 +69,7 @@ "archiveRuleSnapshot.UpdatedAt time.Time `json:\"updatedAt\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 1 @@ -108,7 +108,7 @@ "backendSnapshot.PrimaryEmailUpdateStatus PrimaryEmailUpdateStatus `json:\"primaryEmailUpdateStatus,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.Regions []*Region `json:\"regions\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 2 }, @@ -228,7 +228,7 @@ "backendSnapshot.EndpointIdempotency map[string]map[string]acmeIdempotencyEntry `json:\"endpointIdempotency,omitempty\"`", "backendSnapshot.IdempotencyMap map[string]map[string]certIdempotencyEntry `json:\"idempotencyMap,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "certIdempotencyEntry.ARN string `json:\"arn\"`", "certIdempotencyEntry.CreatedAt time.Time `json:\"createdAt\"`", "certTagsEntry.ResourceID string", @@ -361,7 +361,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Policies map[string]map[string]string `json:\"policies\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "caDTO.ARN string `json:\"arn\"`", "caDTO.PrivKeyPEM string `json:\"privKeyPEM,omitempty\"`", "caDTO.Region string `json:\"region\"`", @@ -479,7 +479,7 @@ "WorkspaceConfig.RuleQueryOffsetSet bool `json:\"ruleQueryOffsetSet,omitempty\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -613,7 +613,7 @@ "Webhook.WebhookURL string `json:\"webhookUrl\"`", "backendSnapshot.AccountID string `json:\"accountId\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -871,7 +871,7 @@ "authorizerSnapshot.RestAPIID string `json:\"restApiId\"`", "authorizerSnapshot.Type string `json:\"type\"`", "backendSnapshot.Account *Account `json:\"account,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UsageOverrides map[string]map[string]int64 `json:\"usageOverrides,omitempty\"`", "deploymentSnapshot.APISummary map[string]map[string]MethodSnapshot `json:\"apiSummary,omitempty\"`", "deploymentSnapshot.Config *DeploymentConfig `json:\"config,omitempty\"`", @@ -1212,7 +1212,7 @@ "authorizerSnapshot.JwtConfiguration *JwtConfiguration `json:\"jwtConfiguration,omitempty\"`", "authorizerSnapshot.Name string `json:\"name\"`", "backendSnapshot.PortalProductSharingPolicies map[string]string `json:\"portalProductSharingPolicies,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "deploymentSnapshot.APIID string `json:\"apiId\"`", "deploymentSnapshot.AutoDeployed bool `json:\"autoDeployed\"`", "deploymentSnapshot.CreatedDate isoTime `json:\"createdDate\"`", @@ -1488,7 +1488,7 @@ "backendSnapshot.ExperimentRunEvents map[string][]ExperimentRunEvent `json:\"experimentRunEvents\"`", "backendSnapshot.FetchedConfigs map[string]*HostedConfigurationVersion `json:\"fetchedConfigs,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TagsByArn map[string]map[string]string `json:\"tagsByArn\"`", "backendSnapshot.VersionCounters map[string]map[string]int32 `json:\"versionCounters\"`" ], @@ -1526,7 +1526,7 @@ "Session.PreviousContentHash string `json:\"previousContentHash\"`", "Session.Token string `json:\"token\"`", "Session.TokenFamilyID string `json:\"tokenFamilyId\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "graceEntry.Content []byte", "graceEntry.ContentHash string", "graceEntry.ContentType string", @@ -1621,7 +1621,7 @@ "Subscription.Event string `json:\"Event\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -1674,7 +1674,7 @@ "SuspendedState.ScheduledScalingSuspended bool `json:\"scheduledScalingSuspended\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -1683,12 +1683,12 @@ "GatewayRoute.GatewayRouteName string", "GatewayRoute.MeshName string", "GatewayRoute.Meta ResourceMeta", - "GatewayRoute.Spec json.RawMessage", + "GatewayRoute.Spec jsontext.Value", "GatewayRoute.Status string", "GatewayRoute.VirtualGatewayName string", "Mesh.Meta ResourceMeta", "Mesh.Name string", - "Mesh.Spec json.RawMessage", + "Mesh.Spec jsontext.Value", "Mesh.Status string", "ResourceMeta.Arn string", "ResourceMeta.CreatedAt time.Time", @@ -1699,32 +1699,32 @@ "Route.MeshName string", "Route.Meta ResourceMeta", "Route.RouteName string", - "Route.Spec json.RawMessage", + "Route.Spec jsontext.Value", "Route.Status string", "Route.VirtualRouterName string", "VirtualGateway.MeshName string", "VirtualGateway.Meta ResourceMeta", - "VirtualGateway.Spec json.RawMessage", + "VirtualGateway.Spec jsontext.Value", "VirtualGateway.Status string", "VirtualGateway.VirtualGatewayName string", "VirtualNode.MeshName string", "VirtualNode.Meta ResourceMeta", - "VirtualNode.Spec json.RawMessage", + "VirtualNode.Spec jsontext.Value", "VirtualNode.Status string", "VirtualNode.VirtualNodeName string", "VirtualRouter.MeshName string", "VirtualRouter.Meta ResourceMeta", - "VirtualRouter.Spec json.RawMessage", + "VirtualRouter.Spec jsontext.Value", "VirtualRouter.Status string", "VirtualRouter.VirtualRouterName string", "VirtualService.MeshName string", "VirtualService.Meta ResourceMeta", - "VirtualService.Spec json.RawMessage", + "VirtualService.Spec jsontext.Value", "VirtualService.Status string", "VirtualService.VirtualServiceName string", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 1 @@ -1773,7 +1773,7 @@ "SourceConfig.ConnectionArn string `json:\"connectionArn,omitempty\"`", "SourceConfig.ImageRepository *ImageSource `json:\"imageRepository,omitempty\"`", "backendSnapshot.CustomDomains map[string][]*storedCustomDomain `json:\"customDomains\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "storedAutoScalingConfiguration.AutoScalingConfigurationArn string `json:\"arn\"`", "storedAutoScalingConfiguration.AutoScalingConfigurationName string `json:\"name\"`", @@ -1902,7 +1902,7 @@ "backendSnapshot.ExportTaskSeq int `json:\"exportTaskSeq\"`", "backendSnapshot.SessionSeq int `json:\"sessionSeq\"`", "backendSnapshot.SoftwareAssoc map[string]map[string]bool `json:\"softwareAssoc\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "backendSnapshot.UsageReport *storedUsageReportSubscription `json:\"usageReport\"`", "backendSnapshot.UserStackAssoc map[string]map[string]bool `json:\"userStackAssoc\"`", @@ -2316,7 +2316,7 @@ "UserPoolConfig.DefaultAction string `json:\"defaultAction\"`", "UserPoolConfig.UserPoolID string `json:\"userPoolId\"`", "backendSnapshot.APIKeys map[string]map[string]*APIKey `json:\"apiKeys,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 2 }, @@ -2343,7 +2343,7 @@ "Shift.Resource string `json:\"resource\"`", "Shift.StartTime time.Time `json:\"startTime\"`", "Shift.Type string `json:\"type\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -2539,7 +2539,7 @@ "backendSnapshot.QueryResults map[string]*sqlResultSnapshot `json:\"queryResults,omitempty\"`", "backendSnapshot.ResourceTags map[string]map[string]string `json:\"resourceTags,omitempty\"`", "backendSnapshot.TableData map[string][]map[string]any `json:\"tableData,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "databaseSnapshot.Catalog string `json:\"catalog\"`", "databaseSnapshot.Record Database `json:\"record\"`", "sqlColumnSnapshot.Name string `json:\"name\"`", @@ -2829,7 +2829,7 @@ "backendSnapshot.DeletedActivities []ScalingActivity `json:\"deletedActivities,omitempty\"`", "backendSnapshot.InstanceRefreshes map[string][]*InstanceRefresh `json:\"instanceRefreshes\"`", "backendSnapshot.NotificationConfigs map[string][]*NotificationConfiguration `json:\"notificationConfigs\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "pendingHookAction.DefaultResult string", "pendingHookAction.Disposition terminationDisposition", "pendingHookAction.GroupName string", @@ -3038,7 +3038,7 @@ "StoredQuery.QueryArn string `json:\"QueryArn,omitempty\"`", "StoredQuery.QueryID string `json:\"QueryId,omitempty\"`", "StoredQuery.QueryName string `json:\"QueryName\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "deliveryChannelStatusState.ChannelName string `json:\"channelName\"`", "deliveryChannelStatusState.Snapshot *exportDeliveryState `json:\"snapshot,omitempty\"`", "deliveryChannelStatusState.Stream *streamDeliveryState `json:\"stream,omitempty\"`", @@ -3122,7 +3122,7 @@ "aciContainerPropsWire.Command []string `json:\"command,omitempty\"`", "aciContainerPropsWire.EnvironmentVariables []aciEnvWire `json:\"environmentVariables,omitempty\"`", "aciContainerPropsWire.Image string `json:\"image\"`", - "aciContainerPropsWire.InstanceView json.RawMessage `json:\"instanceView,omitempty\"`", + "aciContainerPropsWire.InstanceView jsontext.Value `json:\"instanceView,omitempty\"`", "aciContainerPropsWire.LivenessProbe *aciProbeWire `json:\"livenessProbe,omitempty\"`", "aciContainerPropsWire.Ports []aciPortWire `json:\"ports,omitempty\"`", "aciContainerPropsWire.ReadinessProbe *aciProbeWire `json:\"readinessProbe,omitempty\"`", @@ -3158,7 +3158,7 @@ "aciInitPropsWire.Command []string `json:\"command,omitempty\"`", "aciInitPropsWire.EnvironmentVariables []aciEnvWire `json:\"environmentVariables,omitempty\"`", "aciInitPropsWire.Image string `json:\"image\"`", - "aciInitPropsWire.InstanceView json.RawMessage `json:\"instanceView,omitempty\"`", + "aciInitPropsWire.InstanceView jsontext.Value `json:\"instanceView,omitempty\"`", "aciInitPropsWire.VolumeMounts []aciMountWire `json:\"volumeMounts,omitempty\"`", "aciInitWire.Name string `json:\"name\"`", "aciInitWire.Properties aciInitPropsWire `json:\"properties\"`", @@ -3185,7 +3185,7 @@ "aciPropsWire.IPAddress *aciIPWire `json:\"ipAddress,omitempty\"`", "aciPropsWire.ImageRegistryCredentials []aciCredWire `json:\"imageRegistryCredentials,omitempty\"`", "aciPropsWire.InitContainers []aciInitWire `json:\"initContainers,omitempty\"`", - "aciPropsWire.InstanceView json.RawMessage `json:\"instanceView,omitempty\"`", + "aciPropsWire.InstanceView jsontext.Value `json:\"instanceView,omitempty\"`", "aciPropsWire.OSType string `json:\"osType,omitempty\"`", "aciPropsWire.Priority string `json:\"priority,omitempty\"`", "aciPropsWire.ProvisioningState string `json:\"provisioningState,omitempty\"`", @@ -3200,7 +3200,7 @@ "aciSubnetWire.ID string `json:\"id\"`", "aciSubnetWire.Name string `json:\"name,omitempty\"`", "aciVolumeWire.AzureFile *aciAzureFileWire `json:\"azureFile,omitempty\"`", - "aciVolumeWire.EmptyDir *json.RawMessage `json:\"emptyDir,omitempty\"`", + "aciVolumeWire.EmptyDir *jsontext.Value `json:\"emptyDir,omitempty\"`", "aciVolumeWire.GitRepo *aciGitRepoWire `json:\"gitRepo,omitempty\"`", "aciVolumeWire.Name string `json:\"name\"`", "aciVolumeWire.Secret map[string]string `json:\"secret,omitempty\"`", @@ -3216,8 +3216,8 @@ "acrRecord.ResourceGroup string `json:\"resourceGroup\"`", "acrRecord.SKU string `json:\"sku,omitempty\"`", "acrRecord.Tags map[string]string `json:\"tags,omitempty\"`", - "apimSnapshot.Operations json.RawMessage `json:\"operations,omitempty\"`", - "apimSnapshot.Services json.RawMessage `json:\"services,omitempty\"`", + "apimSnapshot.Operations jsontext.Value `json:\"operations,omitempty\"`", + "apimSnapshot.Services jsontext.Value `json:\"services,omitempty\"`", "appConfigDeletedRecord.DeletedAt time.Time `json:\"deletedAt\"`", "appConfigDeletedRecord.Location string `json:\"location\"`", "appConfigDeletedRecord.Name string `json:\"name\"`", @@ -3819,7 +3819,7 @@ "backendSnapshot.Topics map[string]*topic `json:\"topics\"`", "delivery.Attempts int `json:\"attempts\"`", "delivery.Due time.Time `json:\"due\"`", - "delivery.Event json.RawMessage `json:\"event\"`", + "delivery.Event jsontext.Value `json:\"event\"`", "delivery.ID string `json:\"id\"`", "delivery.InFlight bool `json:\"-\"`", "delivery.LastAttempt time.Time `json:\"lastAttempt\"`", @@ -3848,7 +3848,7 @@ "nsTopic.Subs map[string]*pullSub `json:\"subs\"`", "pullEvent.AvailableAt time.Time `json:\"availableAt\"`", "pullEvent.Count int `json:\"count\"`", - "pullEvent.Event json.RawMessage `json:\"event\"`", + "pullEvent.Event jsontext.Value `json:\"event\"`", "pullEvent.ExpiresAt time.Time `json:\"expiresAt\"`", "pullEvent.LockToken string `json:\"lockToken,omitempty\"`", "pullEvent.LockedUntil time.Time `json:\"lockedUntil\"`", @@ -4059,28 +4059,28 @@ "AppRoleAssignment.ResourceDisplayName string `json:\"resourceDisplayName\"`", "AppRoleAssignment.ResourceID string `json:\"resourceId\"`", "Application.API APIApplication `json:\"api\"`", - "Application.AddIns json.RawMessage `json:\"addIns,omitempty\"`", + "Application.AddIns jsontext.Value `json:\"addIns,omitempty\"`", "Application.AppID string `json:\"appId\"`", "Application.AppRoles []AppRole `json:\"appRoles\"`", "Application.ApplicationTemplateID string `json:\"applicationTemplateId,omitempty\"`", - "Application.AuthenticationBehaviors json.RawMessage `json:\"authenticationBehaviors,omitempty\"`", - "Application.Certification json.RawMessage `json:\"certification,omitempty\"`", + "Application.AuthenticationBehaviors jsontext.Value `json:\"authenticationBehaviors,omitempty\"`", + "Application.Certification jsontext.Value `json:\"certification,omitempty\"`", "Application.CreatedDateTime time.Time `json:\"createdDateTime\"`", "Application.DefaultRedirectURI string `json:\"defaultRedirectUri,omitempty\"`", "Application.Description string `json:\"description,omitempty\"`", - "Application.DisabledByMicrosoftStatus json.RawMessage `json:\"disabledByMicrosoftStatus,omitempty\"`", + "Application.DisabledByMicrosoftStatus jsontext.Value `json:\"disabledByMicrosoftStatus,omitempty\"`", "Application.DisplayName string `json:\"displayName\"`", "Application.GroupMembershipClaims string `json:\"groupMembershipClaims,omitempty\"`", "Application.ID string `json:\"id\"`", "Application.IdentifierURIs []string `json:\"identifierUris\"`", - "Application.Info json.RawMessage `json:\"info,omitempty\"`", + "Application.Info jsontext.Value `json:\"info,omitempty\"`", "Application.IsDeviceOnlyAuthSupported *bool `json:\"isDeviceOnlyAuthSupported\"`", "Application.IsFallbackPublicClient bool `json:\"isFallbackPublicClient\"`", "Application.KeyCredentials []KeyCredential `json:\"keyCredentials\"`", "Application.Notes string `json:\"notes,omitempty\"`", "Application.OAuth2RequirePostResponse bool `json:\"oauth2RequirePostResponse\"`", - "Application.OptionalClaims json.RawMessage `json:\"optionalClaims,omitempty\"`", - "Application.ParentalControlSettings json.RawMessage `json:\"parentalControlSettings,omitempty\"`", + "Application.OptionalClaims jsontext.Value `json:\"optionalClaims,omitempty\"`", + "Application.ParentalControlSettings jsontext.Value `json:\"parentalControlSettings,omitempty\"`", "Application.PasswordCredentials []PasswordCredential `json:\"passwordCredentials\"`", "Application.PublicClient RedirectFacet `json:\"publicClient\"`", "Application.PublisherDomain string `json:\"publisherDomain\"`", @@ -4092,7 +4092,7 @@ "Application.Tags []string `json:\"tags\"`", "Application.TokenEncryptionKeyID string `json:\"tokenEncryptionKeyId,omitempty\"`", "Application.UniqueName string `json:\"uniqueName,omitempty\"`", - "Application.VerifiedPublisher json.RawMessage `json:\"verifiedPublisher,omitempty\"`", + "Application.VerifiedPublisher jsontext.Value `json:\"verifiedPublisher,omitempty\"`", "Application.Web WebApplication `json:\"web\"`", "Group.Classification string `json:\"classification,omitempty\"`", "Group.CreatedDateTime time.Time `json:\"createdDateTime\"`", @@ -4153,7 +4153,7 @@ "ResourceAccess.ID string `json:\"id\"`", "ResourceAccess.Type string `json:\"type\"`", "ServicePrincipal.AccountEnabled bool `json:\"accountEnabled\"`", - "ServicePrincipal.AddIns json.RawMessage `json:\"addIns,omitempty\"`", + "ServicePrincipal.AddIns jsontext.Value `json:\"addIns,omitempty\"`", "ServicePrincipal.AlternativeNames []string `json:\"alternativeNames\"`", "ServicePrincipal.AppDescription string `json:\"appDescription,omitempty\"`", "ServicePrincipal.AppDisplayName string `json:\"appDisplayName\"`", @@ -4163,13 +4163,13 @@ "ServicePrincipal.AppRoles []AppRole `json:\"appRoles\"`", "ServicePrincipal.ApplicationTemplateID string `json:\"applicationTemplateId,omitempty\"`", "ServicePrincipal.CreatedDateTime time.Time `json:\"createdDateTime\"`", - "ServicePrincipal.CustomSecurityAttributes json.RawMessage `json:\"customSecurityAttributes,omitempty\"`", + "ServicePrincipal.CustomSecurityAttributes jsontext.Value `json:\"customSecurityAttributes,omitempty\"`", "ServicePrincipal.Description string `json:\"description,omitempty\"`", - "ServicePrincipal.DisabledByMicrosoftStatus json.RawMessage `json:\"disabledByMicrosoftStatus,omitempty\"`", + "ServicePrincipal.DisabledByMicrosoftStatus jsontext.Value `json:\"disabledByMicrosoftStatus,omitempty\"`", "ServicePrincipal.DisplayName string `json:\"displayName\"`", "ServicePrincipal.Homepage string `json:\"homepage,omitempty\"`", "ServicePrincipal.ID string `json:\"id\"`", - "ServicePrincipal.Info json.RawMessage `json:\"info,omitempty\"`", + "ServicePrincipal.Info jsontext.Value `json:\"info,omitempty\"`", "ServicePrincipal.KeyCredentials []KeyCredential `json:\"keyCredentials\"`", "ServicePrincipal.LoginURL string `json:\"loginUrl,omitempty\"`", "ServicePrincipal.LogoutURL string `json:\"logoutUrl,omitempty\"`", @@ -4177,20 +4177,20 @@ "ServicePrincipal.NotificationEmailAddresses []string `json:\"notificationEmailAddresses\"`", "ServicePrincipal.OAuth2PermissionScopes []PermissionScope `json:\"oauth2PermissionScopes\"`", "ServicePrincipal.PasswordCredentials []PasswordCredential `json:\"passwordCredentials\"`", - "ServicePrincipal.PasswordSSOSettings json.RawMessage `json:\"passwordSingleSignOnSettings,omitempty\"`", - "ServicePrincipal.PreferredKeyEndDateTime json.RawMessage `json:\"preferredTokenSigningKeyEndDateTime,omitempty\"`", + "ServicePrincipal.PasswordSSOSettings jsontext.Value `json:\"passwordSingleSignOnSettings,omitempty\"`", + "ServicePrincipal.PreferredKeyEndDateTime jsontext.Value `json:\"preferredTokenSigningKeyEndDateTime,omitempty\"`", "ServicePrincipal.PreferredSingleSignOnMode string `json:\"preferredSingleSignOnMode,omitempty\"`", "ServicePrincipal.PreferredTokenSigningKeyThumb string `json:\"preferredTokenSigningKeyThumbprint,omitempty\"`", "ServicePrincipal.ReplyURLs []string `json:\"replyUrls\"`", - "ServicePrincipal.ResourceSpecificPermissions json.RawMessage `json:\"resourceSpecificApplicationPermissions,omitempty\"`", + "ServicePrincipal.ResourceSpecificPermissions jsontext.Value `json:\"resourceSpecificApplicationPermissions,omitempty\"`", "ServicePrincipal.SAMLMetadataURL string `json:\"samlMetadataUrl,omitempty\"`", - "ServicePrincipal.SAMLSingleSignOnSettings json.RawMessage `json:\"samlSingleSignOnSettings,omitempty\"`", + "ServicePrincipal.SAMLSingleSignOnSettings jsontext.Value `json:\"samlSingleSignOnSettings,omitempty\"`", "ServicePrincipal.ServicePrincipalNames []string `json:\"servicePrincipalNames\"`", "ServicePrincipal.ServicePrincipalType string `json:\"servicePrincipalType\"`", "ServicePrincipal.SignInAudience string `json:\"signInAudience\"`", "ServicePrincipal.Tags []string `json:\"tags\"`", "ServicePrincipal.TokenEncryptionKeyID string `json:\"tokenEncryptionKeyId,omitempty\"`", - "ServicePrincipal.VerifiedPublisher json.RawMessage `json:\"verifiedPublisher,omitempty\"`", + "ServicePrincipal.VerifiedPublisher jsontext.Value `json:\"verifiedPublisher,omitempty\"`", "User.AccountEnabled bool `json:\"accountEnabled\"`", "User.BusinessPhones []string `json:\"businessPhones\"`", "User.City string `json:\"city,omitempty\"`", @@ -4633,7 +4633,7 @@ "RecoveryPoint.ResourceArn string `json:\"resourceArn,omitempty\"`", "RecoveryPoint.ResourceName string `json:\"resourceName,omitempty\"`", "RecoveryPoint.ResourceType string `json:\"resourceType,omitempty\"`", - "RecoveryPoint.Snapshot json.RawMessage `json:\"snapshot,omitempty\"`", + "RecoveryPoint.Snapshot jsontext.Value `json:\"snapshot,omitempty\"`", "RecoveryPoint.SourceBackupVaultArn string `json:\"sourceBackupVaultArn,omitempty\"`", "RecoveryPoint.Status string `json:\"status\"`", "RecoveryPoint.StorageClass string `json:\"storageClass,omitempty\"`", @@ -4809,11 +4809,11 @@ "backendSnapshot.RecoveryPointIndexStatus map[string]string `json:\"recoveryPointIndexStatus,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.RegionSettings *RegionSettings `json:\"regionSettings,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "ddbSnapshot.Attributes []ddbtypes.AttributeDefinition `json:\"attributes\"`", "ddbSnapshot.BillingMode ddbtypes.BillingMode `json:\"billingMode\"`", "ddbSnapshot.GSIs []ddbtypes.GlobalSecondaryIndex `json:\"gsis,omitempty\"`", - "ddbSnapshot.Items []map[string]json.RawMessage `json:\"items\"`", + "ddbSnapshot.Items []map[string]jsontext.Value `json:\"items\"`", "ddbSnapshot.KeySchema []ddbtypes.KeySchemaElement `json:\"keySchema\"`", "ddbSnapshot.LSIs []ddbtypes.LocalSecondaryIndex `json:\"lsis,omitempty\"`", "ddbSnapshot.Provisioned *ddbtypes.ProvisionedThroughput `json:\"provisioned,omitempty\"`", @@ -5237,7 +5237,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.JobDefRevisions map[string]map[string]int32 `json:\"jobDefRevisions\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "nodeRun.attempts []JobAttempt", "nodeRun.startedAt *int64", "nodeRun.status string", @@ -5279,7 +5279,7 @@ "Export.Tags map[string]string `json:\"tags\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -5313,7 +5313,7 @@ "AdvancedPromptOptimizationJob.OutputConfig AdvancedPromptOptimizationOutputConfig", "AdvancedPromptOptimizationJob.Tags []Tag", "AdvancedPromptOptimizationOutputConfig.S3URI string `json:\"s3Uri\"`", - "AutomatedEvaluationConfig.CustomMetricConfig json.RawMessage `json:\"customMetricConfig,omitempty\"`", + "AutomatedEvaluationConfig.CustomMetricConfig jsontext.Value `json:\"customMetricConfig,omitempty\"`", "AutomatedEvaluationConfig.DatasetMetricConfigs []EvaluationDatasetMetricConfig `json:\"datasetMetricConfigs,omitempty\"`", "AutomatedEvaluationConfig.EvaluatorModelConfig *EvaluatorModelConfig `json:\"evaluatorModelConfig,omitempty\"`", "AutomatedReasoningPolicy.CreatedAt time.Time `json:\"createdAt\"`", @@ -5322,7 +5322,7 @@ "AutomatedReasoningPolicy.KmsKeyArn string `json:\"kmsKeyArn,omitempty\"`", "AutomatedReasoningPolicy.Name string `json:\"name\"`", "AutomatedReasoningPolicy.PolicyArn string `json:\"policyArn\"`", - "AutomatedReasoningPolicy.PolicyDefinition json.RawMessage `json:\"policyDefinition,omitempty\"`", + "AutomatedReasoningPolicy.PolicyDefinition jsontext.Value `json:\"policyDefinition,omitempty\"`", "AutomatedReasoningPolicy.Status string `json:\"status\"`", "AutomatedReasoningPolicy.Tags []Tag `json:\"tags,omitempty\"`", "AutomatedReasoningPolicy.UpdatedAt time.Time `json:\"updatedAt\"`", @@ -5330,7 +5330,7 @@ "AutomatedReasoningPolicyBuildWorkflow.BuildWorkflowType string `json:\"buildWorkflowType,omitempty\"`", "AutomatedReasoningPolicyBuildWorkflow.CreatedAt time.Time `json:\"createdAt\"`", "AutomatedReasoningPolicyBuildWorkflow.PolicyArn string `json:\"policyArn\"`", - "AutomatedReasoningPolicyBuildWorkflow.SourceContent json.RawMessage `json:\"sourceContent,omitempty\"`", + "AutomatedReasoningPolicyBuildWorkflow.SourceContent jsontext.Value `json:\"sourceContent,omitempty\"`", "AutomatedReasoningPolicyBuildWorkflow.Status string `json:\"status\"`", "AutomatedReasoningPolicyBuildWorkflow.UpdatedAt time.Time `json:\"updatedAt\"`", "AutomatedReasoningPolicyTestCase.ConfidenceThreshold *float64 `json:\"confidenceThreshold,omitempty\"`", @@ -5584,8 +5584,8 @@ "ProvisionedModelThroughput.ProvisionedModelName string `json:\"provisionedModelName\"`", "ProvisionedModelThroughput.Status string `json:\"status\"`", "ProvisionedModelThroughput.Tags []Tag `json:\"tags,omitempty\"`", - "RAGConfig.KnowledgeBaseConfig json.RawMessage `json:\"knowledgeBaseConfig,omitempty\"`", - "RAGConfig.PrecomputedRagSourceConfig json.RawMessage `json:\"precomputedRagSourceConfig,omitempty\"`", + "RAGConfig.KnowledgeBaseConfig jsontext.Value `json:\"knowledgeBaseConfig,omitempty\"`", + "RAGConfig.PrecomputedRagSourceConfig jsontext.Value `json:\"precomputedRagSourceConfig,omitempty\"`", "ResourcePolicy.CreatedAt time.Time", "ResourcePolicy.PolicyDocument string", "ResourcePolicy.ResourceArn string", @@ -5639,7 +5639,7 @@ "backendSnapshot.ProvisionedCounter int `json:\"provisionedCounter\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourcePolicyRevisionCounter int `json:\"resourcePolicyRevisionCounter\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UseCaseFormData []byte `json:\"useCaseFormData,omitempty\"`" ], "version": 3 @@ -5879,7 +5879,7 @@ "backendSnapshot.PromptVersionCtrs map[string]int `json:\"promptVersionCtrs\"`", "backendSnapshot.PromptsByName map[string]string `json:\"promptsByName\"`", "backendSnapshot.ResourcePolicyCounter int `json:\"resourcePolicyCounter\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 3 @@ -5927,7 +5927,7 @@ "ToolSession.Token string `json:\"clientToken,omitempty\"`", "ToolSession.ToolID string `json:\"toolId\"`", "ToolSession.Updated time.Time `json:\"updated\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -5961,7 +5961,7 @@ "Version.Doc map[string]any `json:\"doc\"`", "Version.ID string `json:\"id\"`", "Version.Parents []string `json:\"parents,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -5987,7 +5987,7 @@ "backendSnapshot.AsyncInvokeCounter int `json:\"asyncInvokeCounter\"`", "backendSnapshot.Invocations []*Invocation `json:\"invocations\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TokenIndex map[string]string `json:\"tokenIndex\"`" ], "version": 1 @@ -6097,7 +6097,7 @@ "ValuesFilter.Values []string `json:\"Values,omitempty\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -6179,7 +6179,7 @@ "backendSnapshot.AnomalyTTL time.Duration `json:\"anomalyTTL\"`", "backendSnapshot.BackfillJobs []*BackfillJob `json:\"backfillJobs\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "ceCostCategoryValues.Key string `json:\"Key\"`", "ceCostCategoryValues.Values []string `json:\"Values\"`", "ceDimensionValues.Key string `json:\"Key\"`", @@ -6497,7 +6497,7 @@ "SchemaAnalysisRule.UpdateTime float64 `json:\"updateTime,omitempty\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TagsByArn map[string]map[string]string `json:\"tagsByArn\"`" ], "version": 1 @@ -6522,7 +6522,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.ClientTokens map[string]clientTokenEntry `json:\"clientTokens\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "clientTokenEntry.CreatedAt time.Time `json:\"createdAt,omitzero\"`", "clientTokenEntry.Fingerprint string `json:\"fingerprint\"`", "clientTokenEntry.RequestToken string `json:\"requestToken\"`", @@ -6771,7 +6771,7 @@ "backendSnapshot.StackPolicies map[string]string `json:\"stackPolicies\"`", "backendSnapshot.StackSetOpResults map[string]map[string][]StackSetOperationResult `json:\"stackSetOpResults\"`", "backendSnapshot.StackSetOperations map[string]map[string]*StackSetOperation `json:\"stackSetOperations\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TypeConfigs map[string]string `json:\"typeConfigs\"`", "backendSnapshot.TypeVersions map[string][]*RegisteredTypeVersion `json:\"typeVersions\"`", "pendingStackOp.DisableValidation bool `json:\"disableValidation,omitempty\"`", @@ -7106,7 +7106,7 @@ "backendSnapshot.MonitoringSubscriptions map[string]*MonitoringSubscription `json:\"monitoringSubscriptions,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourcePolicies map[string]*resourcePolicyEntry `json:\"resourcePolicies,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "invalidationSnapshot.CallerRef string `json:\"callerRef,omitempty\"`", "invalidationSnapshot.CreateTime time.Time `json:\"createTime\"`", "invalidationSnapshot.ID string `json:\"id\"`", @@ -7178,7 +7178,7 @@ "Hsm.Zone string `json:\"zone\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -7331,7 +7331,7 @@ "backendSnapshot.ImportCounter int `json:\"importCounter\"`", "backendSnapshot.QueryCounter int `json:\"queryCounter\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -7526,7 +7526,7 @@ "backendSnapshot.AlarmHistory map[string][]AlarmHistoryItem `json:\"alarmHistory\"`", "backendSnapshot.Metrics map[string]map[string]*metricRecord `json:\"metrics\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TotalMetrics int `json:\"totalMetrics\"`", "dashboardRecord.Body string `json:\"Body\"`", "dashboardRecord.LastModified time.Time `json:\"LastModified\"`", @@ -7802,7 +7802,7 @@ "Transformer.Processors []map[string]any `json:\"transformerConfig\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "cwlIntegrationSnapshot.CreatedAt time.Time `json:\"createdAt,omitzero\"`", "cwlIntegrationSnapshot.Name string `json:\"integrationName\"`", "cwlIntegrationSnapshot.OpenSearchResourceConfig *OpenSearchResourceConfig `json:\"openSearchResourceConfig,omitempty\"`", @@ -7938,7 +7938,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.ExternalConnections map[string]map[string][]ExternalConnection `json:\"externalConnections\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "domainPolicyDTO.DomainName string `json:\"domainName\"`", "domainPolicyDTO.Region string `json:\"region\"`", "domainPolicyDTO.Value *DomainPermissionsPolicy `json:\"value\"`", @@ -8303,7 +8303,7 @@ "backendSnapshot.BuildBatchNumbers map[string]int64 `json:\"buildBatchNumbers\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourcePolicies map[string]string `json:\"resourcePolicies\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "reportDetail.Coverages []CodeCoverage `json:\"coverages,omitempty\"`", "reportDetail.ReportArn string `json:\"reportArn\"`", "reportDetail.TestCases []TestCase `json:\"testCases,omitempty\"`" @@ -8419,7 +8419,7 @@ "backendSnapshot.PROverrides map[string]bool `json:\"prOverrides\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.RepoTemplateAssoc map[string]map[string]struct{} `json:\"repoTemplateAssoc\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Triggers map[string][]RepositoryTrigger `json:\"triggers\"`", "commentSnapshot.AfterCommitID string `json:\"afterCommitId,omitempty\"`", "commentSnapshot.AuthorARN string `json:\"authorArn\"`", @@ -8508,7 +8508,7 @@ "VpcConfiguration.VpcID string `json:\"vpcId\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -8658,7 +8658,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.GitHubTokens []string `json:\"githubTokens,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "deploymentGroupSnapshot.TagsMap map[string]string `json:\"tagsMap\"`", "onPremisesInstanceSnapshot.TagsMap map[string]string `json:\"tagsMap\"`" ], @@ -8709,7 +8709,7 @@ "associationRecord.Updated awstime.EpochTime `json:\"updated\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "feedbackRecord.CodeReviewARN string `json:\"codeReviewArn\"`", "feedbackRecord.Created awstime.EpochTime `json:\"created\"`", "feedbackRecord.Reactions []string `json:\"reactions\"`", @@ -8984,7 +8984,7 @@ "backendSnapshot.ConditionRuns []conditionRunEntry `json:\"conditionRuns,omitempty\"`", "backendSnapshot.Executions []executionEntry `json:\"executions\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "conditionRunEntry.PipelineName string `json:\"pipelineName\"`", "conditionRunEntry.Region string `json:\"region\"`", "conditionRunEntry.Runs []*ConditionRun `json:\"runs\"`", @@ -9067,7 +9067,7 @@ "VpcConfiguration.VpcID string `json:\"VpcId\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "repositorySyncStatusDTO.Branch string `json:\"branch\"`", "repositorySyncStatusDTO.Region string `json:\"region\"`", "repositorySyncStatusDTO.RepositoryLinkID string `json:\"repositoryLinkID\"`", @@ -9125,7 +9125,7 @@ "RulesConfiguration.Rules []MappingRule `json:\"rules\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "principalTagDTO.PoolID string `json:\"poolID\"`", "principalTagDTO.ProviderName string `json:\"providerName\"`", "principalTagDTO.Region string `json:\"region\"`", @@ -9387,7 +9387,7 @@ "backendSnapshot.ResourceTags map[string]map[string]string `json:\"resourceTags,omitempty\"`", "backendSnapshot.RevokedChains map[string]time.Time `json:\"revokedChains,omitempty\"`", "backendSnapshot.RiskConfigurations map[string]*RiskConfiguration `json:\"riskConfigurations,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables,omitempty\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables,omitempty\"`", "backendSnapshot.TokenRevokedBefore map[string]time.Time `json:\"tokenRevokedBefore,omitempty\"`", "backendSnapshot.TokenRevokedBeforeSeq map[string]int64 `json:\"tokenRevokedBeforeSeq,omitempty\"`", "backendSnapshot.TokenSeq int64 `json:\"tokenSeq,omitempty\"`", @@ -9503,7 +9503,7 @@ "backendSnapshot.PolicyModifiedAt map[string]time.Time `json:\"policyModifiedAt\"`", "backendSnapshot.PolicyRevisions map[string]string `json:\"policyRevisions\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 1 @@ -9570,7 +9570,7 @@ "StorageAssociation.ResourceType string `json:\"ResourceType\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "hierarchyStructureRec.InstanceID string `json:\"instanceId\"`", "hierarchyStructureRec.Structure HierarchyStructure `json:\"structure\"`", "instanceRec.Attributes map[string]string `json:\"attributes\"`", @@ -9606,7 +9606,7 @@ "ThroughputSpec.Manual int `json:\"Throughput,omitempty\"`", "backendSnapshot.Databases map[string]*storedDatabase `json:\"databases\"`", "backendSnapshot.Regions *AccountRegions `json:\"regions,omitempty\"`", - "backendSnapshot.TableAPI json.RawMessage `json:\"tableApi,omitempty\"`", + "backendSnapshot.TableAPI jsontext.Value `json:\"tableApi,omitempty\"`", "changeRecord.Current *storedDocument `json:\"Current,omitempty\"`", "changeRecord.ID string `json:\"ID\"`", "changeRecord.Op string `json:\"Op\"`", @@ -9652,15 +9652,15 @@ "storedContainer.ChangeFloor int64 `json:\"ChangeFloor,omitempty\"`", "storedContainer.ChangeLog []*changeRecord `json:\"ChangeLog,omitempty\"`", "storedContainer.ChangeSeq int64 `json:\"ChangeSeq,omitempty\"`", - "storedContainer.ComputedProperties json.RawMessage `json:\"ComputedProperties,omitempty\"`", - "storedContainer.ConflictResolutionPolicy json.RawMessage `json:\"ConflictResolutionPolicy,omitempty\"`", + "storedContainer.ComputedProperties jsontext.Value `json:\"ComputedProperties,omitempty\"`", + "storedContainer.ConflictResolutionPolicy jsontext.Value `json:\"ConflictResolutionPolicy,omitempty\"`", "storedContainer.Conflicts []*conflictRecord `json:\"Conflicts,omitempty\"`", "storedContainer.DefaultTTL *int `json:\"DefaultTTL,omitempty\"`", "storedContainer.Documents map[documentCompositeKey]*storedDocument", - "storedContainer.FullTextPolicy json.RawMessage `json:\"FullTextPolicy,omitempty\"`", - "storedContainer.GeospatialConfig json.RawMessage `json:\"GeospatialConfig,omitempty\"`", + "storedContainer.FullTextPolicy jsontext.Value `json:\"FullTextPolicy,omitempty\"`", + "storedContainer.GeospatialConfig jsontext.Value `json:\"GeospatialConfig,omitempty\"`", "storedContainer.ID string", - "storedContainer.IndexingPolicy json.RawMessage `json:\"IndexingPolicy,omitempty\"`", + "storedContainer.IndexingPolicy jsontext.Value `json:\"IndexingPolicy,omitempty\"`", "storedContainer.Modified time.Time `json:\"Modified\"`", "storedContainer.Offer *storedOffer `json:\"Offer,omitempty\"`", "storedContainer.PKLayout *pkLayout `json:\"PKLayout,omitempty\"`", @@ -9669,8 +9669,8 @@ "storedContainer.Sprocs map[string]*storedScript `json:\"Sprocs,omitempty\"`", "storedContainer.Triggers map[string]*storedScript `json:\"Triggers,omitempty\"`", "storedContainer.UDFs map[string]*storedScript `json:\"UDFs,omitempty\"`", - "storedContainer.UniqueKeyPolicy json.RawMessage `json:\"UniqueKeyPolicy,omitempty\"`", - "storedContainer.VectorEmbeddingPolicy json.RawMessage `json:\"VectorEmbeddingPolicy,omitempty\"`", + "storedContainer.UniqueKeyPolicy jsontext.Value `json:\"UniqueKeyPolicy,omitempty\"`", + "storedContainer.VectorEmbeddingPolicy jsontext.Value `json:\"VectorEmbeddingPolicy,omitempty\"`", "storedContainer.keep time.Duration", "storedContainer.repl *replState", "storedContainer.sorted atomic.Pointer[[]*storedDocument]", @@ -9694,7 +9694,7 @@ "storedPermission.Link string", "storedPermission.Mode string", "storedPermission.Modified time.Time `json:\"Modified\"`", - "storedPermission.PartitionKey json.RawMessage `json:\"PartitionKey,omitempty\"`", + "storedPermission.PartitionKey jsontext.Value `json:\"PartitionKey,omitempty\"`", "storedPermission.PartitionKeyJSON string `json:\"PartitionKeyJSON,omitempty\"`", "storedPermission.Resource string", "storedScript.Body string", @@ -9732,7 +9732,7 @@ "Report.TimeUnit string `json:\"timeUnit\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -9940,7 +9940,7 @@ "backendSnapshot.JobRuns map[string]map[string][]*JobRun `json:\"jobRuns\"`", "backendSnapshot.RecipeVersions map[string]map[string][]*Recipe `json:\"recipeVersions\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -9951,7 +9951,7 @@ "PrivateLinkConfig.VpcEndpointID string `json:\"vpcEndpointId,omitempty\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "storedAgent.AgentArn string `json:\"agentArn\"`", "storedAgent.CreationTime time.Time `json:\"creationTime\"`", @@ -10164,7 +10164,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Events []*Event `json:\"events\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 1 @@ -10175,7 +10175,7 @@ "backendSnapshot.Datasources map[string]map[string]string `json:\"datasources\"`", "backendSnapshot.OrgAdmins []*storedOrgAdmin `json:\"orgAdmins\"`", "backendSnapshot.OrgConfigs map[string]bool `json:\"orgConfigs\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "storedGraph.Arn string `json:\"arn\"`", "storedGraph.CreatedTime time.Time `json:\"createdTime\"`", @@ -10362,7 +10362,7 @@ "backendSnapshot.AccountID string `json:\"accountId\"`", "backendSnapshot.NextASN int64 `json:\"nextAmazonSideAsn\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -10386,7 +10386,7 @@ "backendSnapshot.DirSettings map[string]map[string][]*storedDirectorySetting `json:\"dirSettings\"`", "backendSnapshot.IPRoutes map[string]map[string][]storedIpRoute `json:\"ipRoutes\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UpdateInfoEntries map[string]map[string][]*storedUpdateInfo `json:\"updateInfoEntries\"`", "storedADAssessment.AssessType string `json:\"assessmentType\"`", "storedADAssessment.AssessmentID string `json:\"assessmentId\"`", @@ -10588,7 +10588,7 @@ "dlm": { "fields": [ "backendSnapshot.Counter int `json:\"counter\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "managedResource.ArchivedAt time.Time `json:\"archivedAt,omitzero\"`", "managedResource.CopyOf string `json:\"copyOf,omitempty\"`", "managedResource.CreatedAt time.Time `json:\"createdAt\"`", @@ -10883,7 +10883,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourceTags map[string]map[string]string `json:\"resourceTags,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -11041,7 +11041,7 @@ "backendSnapshot.EventsLog map[string][]Event `json:\"eventsLog\"`", "backendSnapshot.PendingMaintenanceActions map[string]map[string]PendingMaintenanceAction `json:\"pendingMaintenanceActions\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string][]Tag `json:\"tags\"`", "xmlAvailabilityZoneList.Members []string `xml:\"AvailabilityZone\"`", "xmlDBClusterSnapshot.AvailabilityZones xmlAvailabilityZoneList `xml:\"AvailabilityZones\"`", @@ -11095,7 +11095,7 @@ "Stream.Target *StreamTarget", "StreamTarget.RoleArn string", "StreamTarget.StreamArn string", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -13056,7 +13056,7 @@ "backendSnapshot.SpotFleetHistory map[string][]SpotFleetHistoryRecord `json:\"spotFleetHistory\"`", "backendSnapshot.SubnetCIDRAssociations map[string][]*SubnetCIDRAssociation `json:\"subnetCIDRAssociations\"`", "backendSnapshot.SubnetCIDRReservations map[string][]*SubnetCIDRReservation `json:\"subnetCIDRReservations\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags,omitempty\"`", "backendSnapshot.TgwRTPropagations map[string]map[string]*snapTGWRTProp `json:\"tgwRTPropagations,omitempty\"`", "backendSnapshot.UsageReportEntries map[string][]*UsageReportEntry `json:\"usageReportEntries,omitempty\"`", @@ -13234,7 +13234,7 @@ "backendSnapshot.ReplicationConfig *ReplicationConfig `json:\"replicationConfig,omitempty\"`", "backendSnapshot.RepoTags map[string]map[string]string `json:\"repoTags,omitempty\"`", "backendSnapshot.SigningConfig *SigningSettings `json:\"signingConfig,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UploadedLayers map[string]map[string]int64 `json:\"uploadedLayers,omitempty\"`", "lifecyclePolicyEntry.PolicyText string `json:\"policyText\"`", "lifecyclePolicyEntry.RepositoryName string `json:\"repositoryName\"`", @@ -13271,7 +13271,7 @@ "Repository.RepositoryURI string", "Repository.Tags map[string]string", "backendSnapshot.RegistryCatalogData RegistryCatalogData `json:\"registryCatalogData\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TagIndex map[string]map[string]tagBinding `json:\"tagIndex,omitempty\"`", "backendSnapshot.UploadedLayers map[string]map[string]int64 `json:\"uploadedLayers,omitempty\"`", "tagBinding.CreatedAt time.Time", @@ -13881,7 +13881,7 @@ "backendSnapshot.Attributes map[string]map[string]*Attribute `json:\"attributes\"`", "backendSnapshot.DaemonTaskDefinitions map[string][]*DaemonTaskDefinition `json:\"daemonTaskDefinitions\"`", "backendSnapshot.ResourceTags map[string][]Tag `json:\"resourceTags\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TaskDefinitions map[string][]*TaskDefinition `json:\"taskDefinitions\"`", "rollingPlan.currentLive int", "rollingPlan.runningTotal int", @@ -13974,7 +13974,7 @@ "backendSnapshot.FileSystemPolicies map[string]map[string]string `json:\"fileSystemPolicies\"`", "backendSnapshot.LifecyclePolicies map[string]map[string][]LifecyclePolicy `json:\"lifecyclePolicies\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -14079,7 +14079,7 @@ "Cluster.CertificateAuthority string `json:\"certificateAuthority,omitempty\"`", "Cluster.ClusterLogging []ClusterLogEntry `json:\"clusterLogging,omitempty\"`", "Cluster.ComputeConfig *ComputeConfig `json:\"computeConfig,omitempty\"`", - "Cluster.ConfigBlocks map[string]json.RawMessage `json:\"configBlocks,omitempty\"`", + "Cluster.ConfigBlocks map[string]jsontext.Value `json:\"configBlocks,omitempty\"`", "Cluster.ConnectorConfig *ConnectorConfig `json:\"connectorConfig,omitempty\"`", "Cluster.CreatedAt time.Time `json:\"createdAt\"`", "Cluster.CreatorARN string `json:\"creatorArn,omitempty\"`", @@ -14238,8 +14238,8 @@ "backendSnapshot.AccountID string `json:\"accountId\"`", "backendSnapshot.EncryptionConfigs map[string][]EncryptionConfig `json:\"encryptionConfigs,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", - "idempotencyRecord.Body json.RawMessage `json:\"body\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", + "idempotencyRecord.Body jsontext.Value `json:\"body\"`", "idempotencyRecord.CreatedAt time.Time `json:\"createdAt\"`", "idempotencyRecord.Fingerprint string `json:\"fingerprint\"`", "idempotencyRecord.Op string `json:\"op\"`", @@ -14528,7 +14528,7 @@ "backendSnapshot.ServerlessCaches map[string][]*ServerlessCache `json:\"serverlessCaches,omitempty\"`", "backendSnapshot.Snapshots map[string][]*CacheSnapshot `json:\"snapshots\"`", "backendSnapshot.SubnetGroups map[string][]*CacheSubnetGroup `json:\"subnetGroups\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UserGroups map[string][]*UserGroup `json:\"userGroups,omitempty\"`", "backendSnapshot.Users map[string][]*User `json:\"users,omitempty\"`", "clusterGroupState.AZMode string `json:\"azMode,omitempty\"`", @@ -14679,7 +14679,7 @@ "backendSnapshot.Events map[string][]*EventRecord `json:\"events,omitempty\"`", "backendSnapshot.ManagedActionHistory map[string]map[string][]*ManagedActionHistory `json:\"managedActionHistory,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -14822,7 +14822,7 @@ "backendSnapshot.PackageAssociations map[string]map[string][]string `json:\"packageAssociations\"`", "backendSnapshot.PackagesByName map[string]map[string]string `json:\"packagesByName\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.VpcAccess map[string]map[string][]string `json:\"vpcAccess\"`" ], "version": 1 @@ -15071,7 +15071,7 @@ "backendSnapshot.ResourcePolicies map[string]string `json:\"resourcePolicies\"`", "backendSnapshot.RevocationIDCounter int64 `json:\"revocationIdCounter\"`", "backendSnapshot.RuleCounter int `json:\"ruleCounter\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.TargetDrainingUntil map[string]map[string]time.Time `json:\"targetDrainingUntil\"`", "backendSnapshot.TargetReadyAt map[string]map[string]time.Time `json:\"targetReadyAt\"`" ], @@ -15325,7 +15325,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.ArnIndex map[string]map[string]string `json:\"arnIndex\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "blockPublicAccessMeta.CreatedByArn string `json:\"CreatedByArn,omitempty\"`", "blockPublicAccessMeta.CreationDateTime float64 `json:\"CreationDateTime\"`", "blockPublicAccessMeta.region string", @@ -15397,7 +15397,7 @@ "backendSnapshot.JobRunTokens map[string]map[string]string `json:\"jobRunTokens\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.SessionTokens map[string]map[string]string `json:\"sessionTokens\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -15431,7 +15431,7 @@ "backendSnapshot.BusPolicies map[string]map[string]*EventBusPolicy `json:\"busPolicies,omitempty\"`", "backendSnapshot.EventLog []EventLogEntry `json:\"eventLog\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "handlerSnapshot.Backend []byte `json:\"backend\"`", "handlerSnapshot.Tags map[string]map[string]string `json:\"tags,omitempty\"`" ], @@ -15718,7 +15718,7 @@ "VpcConfigurationDescription.VpcID string `json:\"VpcId\"`", "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "flushSnapshot.backupRecords [][]byte", "flushSnapshot.elasticsearchDest *ElasticsearchDestinationDescription", "flushSnapshot.httpDest *HTTPEndpointDestinationDescription", @@ -15864,7 +15864,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.SafetyLever *SafetyLever `json:\"safetyLever\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -15891,7 +15891,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Evaluations map[string][]MonitorEvaluation `json:\"evaluations\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 1 @@ -15948,7 +15948,7 @@ "backendSnapshot.Aliases map[string][]string `json:\"aliases\"`", "backendSnapshot.CreateFileSystemTokens map[string]fsCreateTokenEntry `json:\"createFileSystemTokens\"`", "backendSnapshot.SharedVpcEnabled string `json:\"sharedVpcEnabled\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "fsCreateTokenEntry.CreatedAt time.Time `json:\"createdAt,omitzero\"`", "fsCreateTokenEntry.FileSystemID string `json:\"fileSystemId\"`", @@ -16044,16 +16044,16 @@ "storedFileSystem.WeeklyMaintenanceStartTime string `json:\"weeklyMaintenanceStartTime,omitempty\"`", "storedLustreExtras.AutoImportPolicy string `json:\"autoImportPolicy,omitempty\"`", "storedLustreExtras.DataCompressionType string `json:\"dataCompression,omitempty\"`", - "storedLustreExtras.DataReadCacheConfiguration json.RawMessage `json:\"dataReadCache,omitempty\"`", + "storedLustreExtras.DataReadCacheConfiguration jsontext.Value `json:\"dataReadCache,omitempty\"`", "storedLustreExtras.DriveCacheType string `json:\"driveCache,omitempty\"`", "storedLustreExtras.EfaEnabled bool `json:\"efa,omitempty\"`", "storedLustreExtras.ExportPath string `json:\"exportPath,omitempty\"`", "storedLustreExtras.ImportPath string `json:\"importPath,omitempty\"`", "storedLustreExtras.ImportedFileChunkSize int32 `json:\"importedChunk,omitempty\"`", - "storedLustreExtras.LogConfiguration json.RawMessage `json:\"log,omitempty\"`", - "storedLustreExtras.MetadataConfiguration json.RawMessage `json:\"metadata,omitempty\"`", + "storedLustreExtras.LogConfiguration jsontext.Value `json:\"log,omitempty\"`", + "storedLustreExtras.MetadataConfiguration jsontext.Value `json:\"metadata,omitempty\"`", "storedLustreExtras.PerUnitStorageThroughput int32 `json:\"perUnitThroughput,omitempty\"`", - "storedLustreExtras.RootSquashConfiguration json.RawMessage `json:\"rootSquash,omitempty\"`", + "storedLustreExtras.RootSquashConfiguration jsontext.Value `json:\"rootSquash,omitempty\"`", "storedS3AccessPoint.Alias string `json:\"alias\"`", "storedS3AccessPoint.CreationTime time.Time `json:\"creationTime\"`", "storedS3AccessPoint.Lifecycle string `json:\"lifecycle\"`", @@ -16119,8 +16119,8 @@ "opRec.Target string `json:\"target\"`", "opRec.Verb string `json:\"verb\"`", "recSnap.Life life `json:\"life\"`", - "recSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", - "recSnap.Resource json.RawMessage `json:\"resource\"`" + "recSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", + "recSnap.Resource jsontext.Value `json:\"resource\"`" ], "version": 1 }, @@ -16131,20 +16131,20 @@ "backendSnapshot.GenericVers map[string]*resMeta `json:\"genericVersions,omitempty\"`", "backendSnapshot.Ledger ociregistry.Ledger `json:\"ledger\"`", "backendSnapshot.Meta map[string]*resMeta `json:\"meta,omitempty\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.PackageTags map[string]map[string]string `json:\"packageTags,omitempty\"`", "backendSnapshot.Repositories map[string]repoSnap `json:\"repositories\"`", - "backendSnapshot.Rules map[string]json.RawMessage `json:\"rules,omitempty\"`", - "backendSnapshot.Settings map[string]json.RawMessage `json:\"projectSettings,omitempty\"`", - "backendSnapshot.VPCSC map[string]json.RawMessage `json:\"vpcscConfigs,omitempty\"`", + "backendSnapshot.Rules map[string]jsontext.Value `json:\"rules,omitempty\"`", + "backendSnapshot.Settings map[string]jsontext.Value `json:\"projectSettings,omitempty\"`", + "backendSnapshot.VPCSC map[string]jsontext.Value `json:\"vpcscConfigs,omitempty\"`", "genFile.Annotations map[string]string `json:\"annotations,omitempty\"`", "genFile.Created time.Time `json:\"created\"`", "genFile.Data []byte `json:\"data\"`", "genFile.Doc []byte `json:\"doc,omitempty\"`", "genFile.Owner string `json:\"owner\"`", "genFile.Updated time.Time `json:\"updated\"`", - "repoSnap.IAM json.RawMessage `json:\"iam,omitempty\"`", - "repoSnap.Repository json.RawMessage `json:\"repository\"`", + "repoSnap.IAM jsontext.Value `json:\"iam,omitempty\"`", + "repoSnap.Repository jsontext.Value `json:\"repository\"`", "resMeta.Annotations map[string]string `json:\"annotations,omitempty\"`", "resMeta.Created time.Time `json:\"created\"`", "resMeta.Description string `json:\"description,omitempty\"`", @@ -16177,7 +16177,7 @@ "jobRec.TaskRun int64 `json:\"taskRun\"`", "jobRec.Tasks []*taskRec `json:\"tasks\"`", "jobRec.pb *batchpb.Job", - "jobSnap.Job json.RawMessage `json:\"job\"`", + "jobSnap.Job jsontext.Value `json:\"job\"`", "jobSnap.Rec *jobRec `json:\"rec\"`", "opRec.Created time.Time `json:\"created\"`", "opRec.EndAt time.Time `json:\"endAt\"`", @@ -16240,10 +16240,10 @@ "gcpbigtable": { "fields": [ "backendSnapshot.Instances map[string]instSnap `json:\"instances\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.Seq uint64 `json:\"seq\"`", - "backupSnap.Backup json.RawMessage `json:\"backup\"`", - "backupSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", + "backupSnap.Backup jsontext.Value `json:\"backup\"`", + "backupSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", "backupSnap.Table tableSnap `json:\"table\"`", "cellSnap.TS int64 `json:\"ts\"`", "cellSnap.Val []byte `json:\"val,omitempty\"`", @@ -16251,43 +16251,43 @@ "columnSnap.Family string `json:\"family\"`", "columnSnap.Qualifier []byte `json:\"qualifier,omitempty\"`", "instSnap.Backups map[string]backupSnap `json:\"backups,omitempty\"`", - "instSnap.Clusters map[string]json.RawMessage `json:\"clusters,omitempty\"`", - "instSnap.Instance json.RawMessage `json:\"instance\"`", - "instSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", - "instSnap.Profiles map[string]json.RawMessage `json:\"profiles,omitempty\"`", + "instSnap.Clusters map[string]jsontext.Value `json:\"clusters,omitempty\"`", + "instSnap.Instance jsontext.Value `json:\"instance\"`", + "instSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", + "instSnap.Profiles map[string]jsontext.Value `json:\"profiles,omitempty\"`", "instSnap.Tables map[string]tableSnap `json:\"tables,omitempty\"`", "rowSnap.Columns []columnSnap `json:\"columns\"`", "rowSnap.Key []byte `json:\"key\"`", - "tableSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", + "tableSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", "tableSnap.Rows []rowSnap `json:\"rows,omitempty\"`", "tableSnap.Splits [][]byte `json:\"splits,omitempty\"`", - "tableSnap.Table json.RawMessage `json:\"table\"`" + "tableSnap.Table jsontext.Value `json:\"table\"`" ], "version": 1 }, "gcpcloudbuild": { "fields": [ "backendSnapshot.Builds map[string]buildSnap `json:\"builds\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", - "backendSnapshot.Pools map[string]json.RawMessage `json:\"workerPools\"`", - "backendSnapshot.Triggers map[string]json.RawMessage `json:\"triggers\"`", - "buildSnap.Build json.RawMessage `json:\"build\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", + "backendSnapshot.Pools map[string]jsontext.Value `json:\"workerPools\"`", + "backendSnapshot.Triggers map[string]jsontext.Value `json:\"triggers\"`", + "buildSnap.Build jsontext.Value `json:\"build\"`", "buildSnap.OpName string `json:\"opName\"`", - "buildSnap.Orig json.RawMessage `json:\"orig\"`" + "buildSnap.Orig jsontext.Value `json:\"orig\"`" ], "version": 1 }, "gcpcloudtasks": { "fields": [ - "backendSnapshot.Cmek map[string]json.RawMessage `json:\"cmek\"`", + "backendSnapshot.Cmek map[string]jsontext.Value `json:\"cmek\"`", "backendSnapshot.EtagSeq uint64 `json:\"etagSeq\"`", - "backendSnapshot.Ops map[string]json.RawMessage `json:\"operations,omitempty\"`", - "backendSnapshot.Policies map[string]json.RawMessage `json:\"policies\"`", + "backendSnapshot.Ops map[string]jsontext.Value `json:\"operations,omitempty\"`", + "backendSnapshot.Policies map[string]jsontext.Value `json:\"policies\"`", "backendSnapshot.Queues map[string]queueSnap `json:\"queues\"`", "backendSnapshot.TaskSeq uint64 `json:\"taskSeq\"`", "backendSnapshot.Tombstones map[string]time.Time `json:\"tombstones\"`", - "queueSnap.Queue json.RawMessage `json:\"queue\"`", - "queueSnap.Tasks map[string]json.RawMessage `json:\"tasks,omitempty\"`" + "queueSnap.Queue jsontext.Value `json:\"queue\"`", + "queueSnap.Tasks map[string]jsontext.Value `json:\"tasks,omitempty\"`" ], "version": 1 }, @@ -16353,7 +16353,7 @@ "backendSnapshot.Clusters map[string]clusterSnap `json:\"clusters\"`", "backendSnapshot.Ops map[string]opSnap `json:\"operations\"`", "backendSnapshot.Seq uint64 `json:\"seq\"`", - "clusterSnap.Cluster json.RawMessage `json:\"cluster\"`", + "clusterSnap.Cluster jsontext.Value `json:\"cluster\"`", "clusterSnap.DeleteOp string `json:\"deleteOp\"`", "clusterSnap.Failure string `json:\"failure\"`", "clusterSnap.Pools []poolSnap `json:\"pools\"`", @@ -16366,11 +16366,11 @@ "opSnap.Kind opKind `json:\"kind\"`", "opSnap.Location string `json:\"location\"`", "opSnap.Manual bool `json:\"manual\"`", - "opSnap.Op json.RawMessage `json:\"op\"`", + "opSnap.Op jsontext.Value `json:\"op\"`", "opSnap.Pool string `json:\"pool\"`", "opSnap.Project string `json:\"project\"`", "poolSnap.DeleteOp string `json:\"deleteOp\"`", - "poolSnap.Pool json.RawMessage `json:\"pool\"`", + "poolSnap.Pool jsontext.Value `json:\"pool\"`", "poolSnap.PrevVersion string `json:\"prevVersion\"`", "poolSnap.Size int32 `json:\"size\"`", "rotationRec.Credentials bool", @@ -16381,13 +16381,13 @@ "gcpdatastore": { "fields": [ "backendSnapshot.Entities map[string]entitySnap `json:\"entities\"`", - "backendSnapshot.Indexes map[string]json.RawMessage `json:\"indexes\"`", + "backendSnapshot.Indexes map[string]jsontext.Value `json:\"indexes\"`", "backendSnapshot.LastCommit time.Time `json:\"lastCommit\"`", "backendSnapshot.NextIndex int64 `json:\"nextIndex\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.UsedIDs map[string][]int64 `json:\"usedIds\"`", "entitySnap.Created time.Time `json:\"created\"`", - "entitySnap.Entity json.RawMessage `json:\"entity\"`", + "entitySnap.Entity jsontext.Value `json:\"entity\"`", "entitySnap.Updated time.Time `json:\"updated\"`" ], "version": 1 @@ -16411,22 +16411,22 @@ "gcpeventarc": { "fields": [ "backendSnapshot.Channels map[string]channelSnap `json:\"channels\"`", - "backendSnapshot.Configs map[string]json.RawMessage `json:\"configs\"`", - "backendSnapshot.Connections map[string]json.RawMessage `json:\"connections\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Configs map[string]jsontext.Value `json:\"configs\"`", + "backendSnapshot.Connections map[string]jsontext.Value `json:\"connections\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.Seq uint64 `json:\"seq\"`", "backendSnapshot.Triggers map[string]triggerSnap `json:\"triggers\"`", - "channelSnap.Channel json.RawMessage `json:\"channel\"`", - "channelSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", + "channelSnap.Channel jsontext.Value `json:\"channel\"`", + "channelSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", "triggerSnap.OwnedTopic bool `json:\"ownedTopic,omitempty\"`", - "triggerSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", - "triggerSnap.Trigger json.RawMessage `json:\"trigger\"`" + "triggerSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", + "triggerSnap.Trigger jsontext.Value `json:\"trigger\"`" ], "version": 1 }, "gcpfirestore": { "fields": [ - "backendSnapshot.Docs map[string]json.RawMessage `json:\"docs\"`", + "backendSnapshot.Docs map[string]jsontext.Value `json:\"docs\"`", "backendSnapshot.LastCommit time.Time `json:\"lastCommit\"`" ], "version": 1 @@ -16434,10 +16434,10 @@ "gcpfunctions": { "fields": [ "backendSnapshot.Functions map[string]fnSnap `json:\"functions\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.Uploads map[string]uploadSnap `json:\"uploads\"`", "fnSnap.Failure string `json:\"failure\"`", - "fnSnap.Function json.RawMessage `json:\"function\"`", + "fnSnap.Function jsontext.Value `json:\"function\"`", "fnSnap.RevSeq int `json:\"revSeq\"`", "fnSnap.SubName string `json:\"subName\"`", "fnSnap.Zip []byte `json:\"zip\"`", @@ -16448,20 +16448,20 @@ }, "gcpiam": { "fields": [ - "accountSnap.Account json.RawMessage `json:\"account\"`", + "accountSnap.Account jsontext.Value `json:\"account\"`", "accountSnap.DeletedAt time.Time `json:\"deletedAt\"`", "accountSnap.Keys map[string]keySnap `json:\"keys,omitempty\"`", - "accountSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", + "accountSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", "accountSnap.System *keySnap `json:\"system,omitempty\"`", "backendSnapshot.Accounts map[string]accountSnap `json:\"accounts\"`", "backendSnapshot.EtagSeq uint64 `json:\"etagSeq\"`", "backendSnapshot.Roles map[string]roleSnap `json:\"roles\"`", "keySnap.Cert []byte `json:\"cert,omitempty\"`", - "keySnap.Key json.RawMessage `json:\"key\"`", + "keySnap.Key jsontext.Value `json:\"key\"`", "keySnap.Private []byte `json:\"private,omitempty\"`", "keySnap.Public []byte `json:\"public,omitempty\"`", "roleSnap.DeletedAt time.Time `json:\"deletedAt\"`", - "roleSnap.Role json.RawMessage `json:\"role\"`" + "roleSnap.Role jsontext.Value `json:\"role\"`" ], "version": 1 }, @@ -16529,13 +16529,13 @@ "backendSnapshot.EtagSeq uint64 `json:\"etagSeq\"`", "backendSnapshot.Jobs map[string]jobSnap `json:\"jobs\"`", "backendSnapshot.Keys map[string]keySnap `json:\"keys\"`", - "backendSnapshot.Ops map[string]json.RawMessage `json:\"operations,omitempty\"`", - "backendSnapshot.Policies map[string]json.RawMessage `json:\"policies\"`", - "backendSnapshot.Retired map[string]json.RawMessage `json:\"retired,omitempty\"`", - "backendSnapshot.Rings map[string]json.RawMessage `json:\"rings\"`", - "jobSnap.Job json.RawMessage `json:\"job\"`", + "backendSnapshot.Ops map[string]jsontext.Value `json:\"operations,omitempty\"`", + "backendSnapshot.Policies map[string]jsontext.Value `json:\"policies\"`", + "backendSnapshot.Retired map[string]jsontext.Value `json:\"retired,omitempty\"`", + "backendSnapshot.Rings map[string]jsontext.Value `json:\"rings\"`", + "jobSnap.Job jsontext.Value `json:\"job\"`", "jobSnap.Private []byte `json:\"private,omitempty\"`", - "keySnap.Key json.RawMessage `json:\"key\"`", + "keySnap.Key jsontext.Value `json:\"key\"`", "keySnap.Primary int64 `json:\"primary\"`", "keySnap.Versions []versionSnap `json:\"versions,omitempty\"`", "versionSnap.Deleted bool `json:\"deleted,omitempty\"`", @@ -16546,20 +16546,20 @@ "gcplogging": { "fields": [ "backendSnapshot.Buckets map[string]bucketSnap `json:\"buckets\"`", - "backendSnapshot.Cmek map[string]json.RawMessage `json:\"cmek\"`", - "backendSnapshot.Entries []json.RawMessage `json:\"entries\"`", - "backendSnapshot.Exclusions map[string]json.RawMessage `json:\"exclusions\"`", + "backendSnapshot.Cmek map[string]jsontext.Value `json:\"cmek\"`", + "backendSnapshot.Entries []jsontext.Value `json:\"entries\"`", + "backendSnapshot.Exclusions map[string]jsontext.Value `json:\"exclusions\"`", "backendSnapshot.Metrics map[string]metricSnap `json:\"metrics\"`", - "backendSnapshot.Ops map[string]json.RawMessage `json:\"ops\"`", + "backendSnapshot.Ops map[string]jsontext.Value `json:\"ops\"`", "backendSnapshot.Seeded []string `json:\"seeded\"`", "backendSnapshot.Seq uint64 `json:\"seq\"`", - "backendSnapshot.Settings map[string]json.RawMessage `json:\"settings\"`", - "backendSnapshot.Sinks map[string]json.RawMessage `json:\"sinks\"`", - "backendSnapshot.Views map[string]json.RawMessage `json:\"views\"`", - "bucketSnap.Bucket json.RawMessage `json:\"bucket\"`", + "backendSnapshot.Settings map[string]jsontext.Value `json:\"settings\"`", + "backendSnapshot.Sinks map[string]jsontext.Value `json:\"sinks\"`", + "backendSnapshot.Views map[string]jsontext.Value `json:\"views\"`", + "bucketSnap.Bucket jsontext.Value `json:\"bucket\"`", "bucketSnap.DeleteRequested time.Time `json:\"deleteRequested\"`", "bucketSnap.Entries []int `json:\"entries,omitempty\"`", - "metricSnap.Metric json.RawMessage `json:\"metric\"`", + "metricSnap.Metric jsontext.Value `json:\"metric\"`", "metricSnap.Series []seriesSnap `json:\"series,omitempty\"`", "seriesSnap.Buckets []int64 `json:\"buckets,omitempty\"`", "seriesSnap.Count int64 `json:\"count\"`", @@ -16589,23 +16589,23 @@ "Incident.State string `json:\"state\"`", "Incident.Threshold float64 `json:\"threshold\"`", "backendSnapshot.Channels map[string]channelSnap `json:\"channels\"`", - "backendSnapshot.Descriptors map[string]json.RawMessage `json:\"descriptors\"`", - "backendSnapshot.Groups map[string]json.RawMessage `json:\"groups\"`", + "backendSnapshot.Descriptors map[string]jsontext.Value `json:\"descriptors\"`", + "backendSnapshot.Groups map[string]jsontext.Value `json:\"groups\"`", "backendSnapshot.Incidents []Incident `json:\"incidents\"`", - "backendSnapshot.Policies map[string]json.RawMessage `json:\"policies\"`", - "backendSnapshot.SLOs map[string]json.RawMessage `json:\"slos,omitempty\"`", + "backendSnapshot.Policies map[string]jsontext.Value `json:\"policies\"`", + "backendSnapshot.SLOs map[string]jsontext.Value `json:\"slos,omitempty\"`", "backendSnapshot.Series []seriesSnap `json:\"series\"`", - "backendSnapshot.Services map[string]json.RawMessage `json:\"services,omitempty\"`", - "backendSnapshot.Snoozes map[string]json.RawMessage `json:\"snoozes,omitempty\"`", + "backendSnapshot.Services map[string]jsontext.Value `json:\"services,omitempty\"`", + "backendSnapshot.Snoozes map[string]jsontext.Value `json:\"snoozes,omitempty\"`", "backendSnapshot.Uptime map[string]uptimeSnap `json:\"uptime\"`", - "channelSnap.Channel json.RawMessage `json:\"channel\"`", + "channelSnap.Channel jsontext.Value `json:\"channel\"`", "channelSnap.Code string `json:\"code,omitempty\"`", "channelSnap.CodeAt time.Time `json:\"codeAt\"`", "channelSnap.Sensitive map[string]string `json:\"sensitive,omitempty\"`", "seriesSnap.Project string `json:\"project\"`", - "seriesSnap.Series json.RawMessage `json:\"series\"`", + "seriesSnap.Series jsontext.Value `json:\"series\"`", "seriesSnap.Unit string `json:\"unit,omitempty\"`", - "uptimeSnap.Config json.RawMessage `json:\"config\"`", + "uptimeSnap.Config jsontext.Value `json:\"config\"`", "uptimeSnap.LastRun time.Time `json:\"lastRun\"`" ], "version": 1 @@ -16614,7 +16614,7 @@ "fields": [ "backendSnapshot.EtagSeq uint64 `json:\"etagSeq,omitempty\"`", "backendSnapshot.LastMsg int64 `json:\"lastMsg\"`", - "backendSnapshot.Policies map[string]json.RawMessage `json:\"policies,omitempty\"`", + "backendSnapshot.Policies map[string]jsontext.Value `json:\"policies,omitempty\"`", "backendSnapshot.Schemas map[string]*schemaRec `json:\"schemas\"`", "backendSnapshot.Snapshots map[string]pbSnapSnap `json:\"snapshots\"`", "backendSnapshot.Subs map[string]subSnap `json:\"subs\"`", @@ -16625,7 +16625,7 @@ "message.OrderingKey string `json:\"orderingKey,omitempty\"`", "message.PublishTime time.Time `json:\"publishTime\"`", "pbSnapSnap.Created time.Time `json:\"created\"`", - "pbSnapSnap.Snapshot json.RawMessage `json:\"snapshot\"`", + "pbSnapSnap.Snapshot jsontext.Value `json:\"snapshot\"`", "pbSnapSnap.Unacked []string `json:\"unacked,omitempty\"`", "schemaRec.Name string `json:\"name\"`", "schemaRec.Revisions []schemaRevision `json:\"revisions\"`", @@ -16645,18 +16645,18 @@ "subMsg.owner string", "subSnap.LastActive time.Time `json:\"lastActive\"`", "subSnap.Msgs []*subMsg `json:\"msgs,omitempty\"`", - "subSnap.Sub json.RawMessage `json:\"sub\"`", + "subSnap.Sub jsontext.Value `json:\"sub\"`", "topicSnap.Retained []*message `json:\"retained,omitempty\"`", - "topicSnap.Topic json.RawMessage `json:\"topic\"`" + "topicSnap.Topic jsontext.Value `json:\"topic\"`" ], "version": 1 }, "gcpredis": { "fields": [ "backendSnapshot.Instances map[string]instSnap `json:\"instances\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "instSnap.AuthString string `json:\"authString,omitempty\"`", - "instSnap.Instance json.RawMessage `json:\"instance\"`", + "instSnap.Instance jsontext.Value `json:\"instance\"`", "instSnap.Keyspace []byte `json:\"keyspace,omitempty\"`" ], "version": 1 @@ -16666,8 +16666,8 @@ "backendSnapshot.Bindings map[string]*bindingRec `json:\"tagBindings\"`", "backendSnapshot.Enabled map[string]map[string]time.Time `json:\"enabledServices\"`", "backendSnapshot.Folders map[string]*folderRec `json:\"folders\"`", - "backendSnapshot.Ops map[string]json.RawMessage `json:\"operations\"`", - "backendSnapshot.Policies map[string]json.RawMessage `json:\"policies\"`", + "backendSnapshot.Ops map[string]jsontext.Value `json:\"operations\"`", + "backendSnapshot.Policies map[string]jsontext.Value `json:\"policies\"`", "backendSnapshot.PolicySeq uint64 `json:\"policySeq\"`", "backendSnapshot.Projects map[string]*projectRec `json:\"projects\"`", "backendSnapshot.Seed string `json:\"seed\"`", @@ -16702,25 +16702,25 @@ }, "gcprun": { "fields": [ - "backendSnapshot.DeletedExe map[string]json.RawMessage `json:\"deletedExecutions\"`", - "backendSnapshot.DeletedJob map[string]json.RawMessage `json:\"deletedJobs\"`", - "backendSnapshot.DeletedSvc map[string]json.RawMessage `json:\"deletedServices\"`", - "backendSnapshot.Executions map[string]json.RawMessage `json:\"executions\"`", - "backendSnapshot.IAM map[string]json.RawMessage `json:\"iamPolicies\"`", + "backendSnapshot.DeletedExe map[string]jsontext.Value `json:\"deletedExecutions\"`", + "backendSnapshot.DeletedJob map[string]jsontext.Value `json:\"deletedJobs\"`", + "backendSnapshot.DeletedSvc map[string]jsontext.Value `json:\"deletedServices\"`", + "backendSnapshot.Executions map[string]jsontext.Value `json:\"executions\"`", + "backendSnapshot.IAM map[string]jsontext.Value `json:\"iamPolicies\"`", "backendSnapshot.IAMSeq uint64 `json:\"iamSeq\"`", - "backendSnapshot.Jobs map[string]json.RawMessage `json:\"jobs\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Jobs map[string]jsontext.Value `json:\"jobs\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.Revisions map[string]revSnap `json:\"revisions\"`", "backendSnapshot.Services map[string]svcSnap `json:\"services\"`", "backendSnapshot.Tasks map[string]taskSnap `json:\"tasks\"`", - "revSnap.Revision json.RawMessage `json:\"revision\"`", + "revSnap.Revision jsontext.Value `json:\"revision\"`", "revSnap.Seq int `json:\"seq\"`", "revSnap.StartErr string `json:\"startErr\"`", "svcSnap.Failure string `json:\"failure\"`", "svcSnap.RevSeq int `json:\"revSeq\"`", - "svcSnap.Service json.RawMessage `json:\"service\"`", + "svcSnap.Service jsontext.Value `json:\"service\"`", "taskSnap.State string `json:\"state\"`", - "taskSnap.Task json.RawMessage `json:\"task\"`" + "taskSnap.Task jsontext.Value `json:\"task\"`" ], "version": 1 }, @@ -16730,7 +16730,7 @@ "backendSnapshot.Jobs map[string]jobSnap `json:\"jobs\"`", "jobSnap.ExecStart time.Time `json:\"execStart\"`", "jobSnap.Failures int32 `json:\"failures\"`", - "jobSnap.Job json.RawMessage `json:\"job\"`", + "jobSnap.Job jsontext.Value `json:\"job\"`", "jobSnap.RetryAt time.Time `json:\"retryAt\"`" ], "version": 1 @@ -16740,8 +16740,8 @@ "backendSnapshot.EtagSeq uint64 `json:\"etagSeq\"`", "backendSnapshot.Secrets map[string]secretSnap `json:\"secrets\"`", "secretSnap.NextVer int64 `json:\"nextVer\"`", - "secretSnap.Policy json.RawMessage `json:\"policy,omitempty\"`", - "secretSnap.Secret json.RawMessage `json:\"secret\"`", + "secretSnap.Policy jsontext.Value `json:\"policy,omitempty\"`", + "secretSnap.Secret jsontext.Value `json:\"secret\"`", "secretSnap.Versions []versionSnap `json:\"versions,omitempty\"`", "versionSnap.Data []byte `json:\"data,omitempty\"`", "versionSnap.Num int64 `json:\"num\"`" @@ -16752,12 +16752,12 @@ "fields": [ "backendSnapshot.EtagSeq uint64 `json:\"etagSeq\"`", "backendSnapshot.Instances map[string]instSnap `json:\"instances\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "dbSnap.DDL []string `json:\"ddl,omitempty\"`", - "dbSnap.Database json.RawMessage `json:\"database\"`", + "dbSnap.Database jsontext.Value `json:\"database\"`", "instSnap.Databases map[string]dbSnap `json:\"databases,omitempty\"`", - "instSnap.Instance json.RawMessage `json:\"instance\"`", - "instSnap.Policy json.RawMessage `json:\"policy,omitempty\"`" + "instSnap.Instance jsontext.Value `json:\"instance\"`", + "instSnap.Policy jsontext.Value `json:\"policy,omitempty\"`" ], "version": 1 }, @@ -16901,7 +16901,7 @@ "ACLEntry.Entity string `json:\"entity\"`", "ACLEntry.Role string `json:\"role\"`", "Bucket.ACL []ACLEntry `json:\"acl,omitempty\"`", - "Bucket.Config map[string]json.RawMessage `json:\"config,omitempty\"`", + "Bucket.Config map[string]jsontext.Value `json:\"config,omitempty\"`", "Bucket.Created time.Time `json:\"created\"`", "Bucket.DefaultEventBasedHold bool `json:\"defaultEventBasedHold,omitempty\"`", "Bucket.DefaultObjectACL []ACLEntry `json:\"defaultObjectAcl,omitempty\"`", @@ -16915,7 +16915,7 @@ "Bucket.StorageClass string `json:\"storageClass\"`", "Bucket.Updated time.Time `json:\"updated\"`", "Bucket.Versioning bool `json:\"versioning,omitempty\"`", - "IAMBinding.Condition json.RawMessage `json:\"condition,omitempty\"`", + "IAMBinding.Condition jsontext.Value `json:\"condition,omitempty\"`", "IAMBinding.Members []string `json:\"members\"`", "IAMBinding.Role string `json:\"role\"`", "IAMPolicy.Bindings []IAMBinding `json:\"bindings\"`", @@ -16949,10 +16949,10 @@ }, "gcpworkflows": { "fields": [ - "backendSnapshot.Executions map[string]json.RawMessage `json:\"executions\"`", - "backendSnapshot.Operations map[string]json.RawMessage `json:\"operations\"`", + "backendSnapshot.Executions map[string]jsontext.Value `json:\"executions\"`", + "backendSnapshot.Operations map[string]jsontext.Value `json:\"operations\"`", "backendSnapshot.Workflows map[string]workflowSnap `json:\"workflows\"`", - "workflowSnap.Revisions []json.RawMessage `json:\"revisions\"`" + "workflowSnap.Revisions []jsontext.Value `json:\"revisions\"`" ], "version": 1 }, @@ -17027,7 +17027,7 @@ "backendSnapshot.DataRetrievalPolicies map[string]string `json:\"dataRetrievalPolicies,omitempty\"`", "backendSnapshot.MultipartParts []multipartPartSnapshot `json:\"multipartParts\"`", "backendSnapshot.ProvisionedCapacity []provisionedCapacitySnapshot `json:\"provisionedCapacity\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "csvInputDTO.Comments string `json:\"Comments,omitempty\"`", "csvInputDTO.FieldDelimiter string `json:\"FieldDelimiter,omitempty\"`", "csvInputDTO.FileHeaderInfo string `json:\"FileHeaderInfo,omitempty\"`", @@ -17156,7 +17156,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.Seq int64 `json:\"seq\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -17551,7 +17551,7 @@ "JSONClassifier.JSONPath string `json:\"JsonPath\"`", "JSONClassifier.Name string `json:\"Name\"`", "Job.ARN string `json:\"Arn,omitempty\"`", - "Job.CodeGenConfigurationNodes map[string]json.RawMessage `json:\"CodeGenConfigurationNodes,omitempty\"`", + "Job.CodeGenConfigurationNodes map[string]jsontext.Value `json:\"CodeGenConfigurationNodes,omitempty\"`", "Job.Command JobCommand `json:\"Command,omitzero\"`", "Job.Connections ConnectionsList `json:\"Connections,omitzero\"`", "Job.CreatedOn float64 `json:\"CreatedOn,omitempty\"`", @@ -17924,7 +17924,7 @@ "backendSnapshot.SchemaVersions map[string][]*SchemaVersion `json:\"schemaVersions\"`", "backendSnapshot.SessionStatements map[string][]*Statement `json:\"sessionStatements\"`", "backendSnapshot.TableColumnStats map[string]*ColumnStatistics `json:\"tableColumnStats\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.WorkflowRuns map[string][]*WorkflowRun `json:\"workflowRuns\"`", "resourcePolicyEntry.CreateTime float64 `json:\"CreateTime,omitempty\"`", "resourcePolicyEntry.EnableHybrid string `json:\"EnableHybrid,omitempty\"`", @@ -18017,7 +18017,7 @@ "backendSnapshot.NextServiceAccountID uint64 `json:\"nextServiceAccountId\"`", "backendSnapshot.NextTokenID uint64 `json:\"nextTokenId\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -18201,7 +18201,7 @@ "backendSnapshot.AccountID string `json:\"accountId\"`", "backendSnapshot.MemberSeq int64 `json:\"memberSeq\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 2 @@ -18401,7 +18401,7 @@ "backendSnapshot.RoleByARN map[string]string `json:\"roleByARN,omitempty\"`", "backendSnapshot.RoleInlinePolicies map[string]map[string]string `json:\"roleInlinePolicies,omitempty\"`", "backendSnapshot.RolePolicies map[string][]string `json:\"rolePolicies,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.UserInlinePolicies map[string]map[string]string `json:\"userInlinePolicies,omitempty\"`", "backendSnapshot.UserPolicies map[string][]string `json:\"userPolicies,omitempty\"`", "comprehensiveSnapshot.AccessAdvisorJobs map[string]*accessAdvisorJob `json:\"accessAdvisorJobs,omitempty\"`", @@ -18409,8 +18409,8 @@ "comprehensiveSnapshot.OrgReportJobs map[string]time.Time `json:\"orgReportJobs,omitempty\"`", "comprehensiveSnapshot.SSHPublicKeys map[string]SSHPublicKey `json:\"sshPublicKeys,omitempty\"`", "comprehensiveSnapshot.ServiceLastAccessed map[string]map[string]ServiceLastAccessedDetail `json:\"serviceLastAccessed,omitempty\"`", - "handlerSnapshot.Accounts map[string]json.RawMessage `json:\"accounts,omitempty\"`", - "handlerSnapshot.Backend json.RawMessage `json:\"backend,omitempty\"`", + "handlerSnapshot.Accounts map[string]jsontext.Value `json:\"accounts,omitempty\"`", + "handlerSnapshot.Backend jsontext.Value `json:\"backend,omitempty\"`", "handlerSnapshot.Tags map[string]map[string]string `json:\"tags,omitempty\"`", "policyAttachmentRefs.groups map[string]struct{}", "policyAttachmentRefs.roles map[string]struct{}", @@ -18498,7 +18498,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.Counter int `json:\"counter\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -18762,7 +18762,7 @@ "backendSnapshot.OrgConfig OrgConfiguration `json:\"orgConfig\"`", "backendSnapshot.OrgEc2Config OrgEc2DeepInspectionConfig `json:\"orgEc2Config\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`", "codeSnippet.EndLine int32 `json:\"endLine,omitempty\"`", "codeSnippet.FindingArn string `json:\"findingArn\"`", @@ -19230,7 +19230,7 @@ "RoleAlias.RoleAliasARN string `json:\"roleAliasArn\"`", "RoleAlias.Tags map[string]string `json:\"tags,omitempty\"`", "RuleAction.Lambda *LambdaAction `json:\"lambda,omitempty\"`", - "RuleAction.Other map[string]json.RawMessage `json:\"-\"`", + "RuleAction.Other map[string]jsontext.Value `json:\"-\"`", "RuleAction.SNS *SNSAction `json:\"sns,omitempty\"`", "RuleAction.SQS *SQSAction `json:\"sqs,omitempty\"`", "RuleAction.{MarshalJSON}", @@ -19428,7 +19428,7 @@ "backendSnapshot.ResourceTags map[string]map[string]string `json:\"resourceTags\"`", "backendSnapshot.SbomValidationResults map[string][]*SbomValidationResult `json:\"sbomValidationResults\"`", "backendSnapshot.SecurityProfileTargets map[string][]string `json:\"securityProfileTargets\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.ThingBillingGroups map[string]string `json:\"thingBillingGroups\"`", "backendSnapshot.ThingConnectivity map[string]*ThingConnectivityData `json:\"thingConnectivity\"`", "backendSnapshot.ThingGroupIndexingConfiguration *ThingGroupIndexingConfiguration `json:\"thingGroupIndexingConfiguration\"`", @@ -19650,7 +19650,7 @@ "backendSnapshot.ChannelMessages map[string][]ChannelMessage `json:\"channelMessages\"`", "backendSnapshot.DatasetContents map[string][]*DatasetContent `json:\"datasetContents\"`", "backendSnapshot.LoggingOptions *LoggingOptions `json:\"loggingOptions\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.Tags map[string]map[string]string `json:\"tags\"`" ], "version": 2 @@ -19662,7 +19662,7 @@ "RetainedMessage.Qos int32", "RetainedMessage.Topic string", "RetainedMessage.UserProperties []byte", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "connectionEntry.clientID string", "connectionEntry.connectedAt time.Time", "connectionEntry.disconnectReason string", @@ -19674,19 +19674,19 @@ "connectionEntrySnap.DisconnectedAt time.Time `json:\"disconnectedAt,omitzero\"`", "connectionEntrySnap.SourceIP string `json:\"sourceIp,omitempty\"`", "shadowEntry.deleted bool", - "shadowEntry.desired map[string]json.RawMessage", + "shadowEntry.desired map[string]jsontext.Value", "shadowEntry.metaDesired map[string]int64", "shadowEntry.metaReported map[string]int64", - "shadowEntry.reported map[string]json.RawMessage", + "shadowEntry.reported map[string]jsontext.Value", "shadowEntry.shadowName string", "shadowEntry.thingName string", "shadowEntry.updatedAt time.Time", "shadowEntry.version int", "shadowEntrySnap.Deleted bool `json:\"deleted,omitempty\"`", - "shadowEntrySnap.Desired map[string]json.RawMessage `json:\"desired,omitempty\"`", + "shadowEntrySnap.Desired map[string]jsontext.Value `json:\"desired,omitempty\"`", "shadowEntrySnap.MetaDesired map[string]int64 `json:\"metaDesired,omitempty\"`", "shadowEntrySnap.MetaReported map[string]int64 `json:\"metaReported,omitempty\"`", - "shadowEntrySnap.Reported map[string]json.RawMessage `json:\"reported,omitempty\"`", + "shadowEntrySnap.Reported map[string]jsontext.Value `json:\"reported,omitempty\"`", "shadowEntrySnap.ShadowName string `json:\"shadowName\"`", "shadowEntrySnap.ThingName string `json:\"thingName\"`", "shadowEntrySnap.UpdatedAt time.Time `json:\"updatedAt\"`" @@ -19974,7 +19974,7 @@ "backendSnapshot.QueuedMessages map[string][]QueuedMessage `json:\"queuedMessages,omitempty\"`", "backendSnapshot.ResourceLogLevels map[string]string `json:\"resourceLogLevels,omitempty\"`", "backendSnapshot.ResourceTags map[string]map[string]string `json:\"resourceTags,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.WirelessDeviceThings map[string]string `json:\"wirelessDeviceThings,omitempty\"`", "backendSnapshot.WirelessGatewayCerts map[string]string `json:\"wirelessGatewayCerts,omitempty\"`", "backendSnapshot.WirelessGatewayThings map[string]string `json:\"wirelessGatewayThings,omitempty\"`", @@ -20273,7 +20273,7 @@ "backendSnapshot.PolicyVersions map[string]string `json:\"clusterPolicyVersions,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ScramSecrets map[string][]string `json:\"scramSecrets\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -20366,7 +20366,7 @@ "WorkerLogDelivery.CloudWatchLogs *CloudWatchLogsDelivery", "WorkerLogDelivery.Firehose *FirehoseDelivery", "WorkerLogDelivery.S3 *S3LogDelivery", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -20469,7 +20469,7 @@ "backendSnapshot.OnDemandStreamCountLimit int `json:\"onDemandStreamCountLimit,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourcePolicies map[string]map[string]string `json:\"resourcePolicies,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "channelBufferSnapshot.Failed []failedChannelRecordSnapshot `json:\"failed,omitempty\"`", "channelBufferSnapshot.Records [][]byte `json:\"records,omitempty\"`", "channelFlushSnapshot.channel *Channel", @@ -20565,7 +20565,7 @@ "backendSnapshot.AccountID string `json:\"accountID\"`", "backendSnapshot.NextID int64 `json:\"next_id\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -20717,7 +20717,7 @@ "ZeppelinMonitoringConfigDesc.LogLevel string `json:\"LogLevel\"`", "backendSnapshot.FlinkStopSaves map[string]persistedStopSave `json:\"flink_stop_saves,omitempty\"`", "backendSnapshot.NextID int64 `json:\"next_id\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "persistedApplication.ApplicationARN string `json:\"ApplicationARN\"`", "persistedApplication.ApplicationDescription string `json:\"ApplicationDescription,omitempty\"`", "persistedApplication.ApplicationMode string `json:\"ApplicationMode,omitempty\"`", @@ -20822,7 +20822,7 @@ "Stream.PendingUntil time.Time", "Stream.Status string", "Stream.Tags map[string]string", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`" + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`" ], "version": 1 }, @@ -20904,8 +20904,8 @@ "backendSnapshot.PendingMaterials map[string]map[string]serializedKeyMaterial `json:\"pending_key_materials,omitempty\"`", "backendSnapshot.Policies map[string]map[string]string `json:\"policies\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", - "handlerSnapshot.Backend json.RawMessage `json:\"backend,omitempty\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", + "handlerSnapshot.Backend jsontext.Value `json:\"backend,omitempty\"`", "handlerSnapshot.HandlerFormat int `json:\"handlerFormat\"`", "handlerSnapshot.Tags map[string]map[string]string `json:\"tags,omitempty\"`", "serializedKeyMaterial.PrivKeyDER []byte `json:\"priv_key_der,omitempty\"`", @@ -21028,7 +21028,7 @@ "backendSnapshot.Queries map[string]string `json:\"queries,omitempty\"`", "backendSnapshot.ResourceLFTags map[string][]LFTagPair `json:\"resourceLFTags\"`", "backendSnapshot.TableStorageOptimizers map[string][]StorageOptimizer `json:\"tableStorageOptimizers,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "transactionInfo.EndTime string `json:\"EndTime,omitempty\"`", "transactionInfo.ID string `json:\"-\"`", "transactionInfo.LastExtended string `json:\"LastExtended,omitempty\"`", @@ -21312,7 +21312,7 @@ "backendSnapshot.Layers map[string][]*LayerVersion `json:\"layers\"`", "backendSnapshot.Region string `json:\"region\"`", "backendSnapshot.ResourcePolicyOverrides map[string]*ResourcePolicyOverride `json:\"resourcePolicyOverrides,omitempty\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.VersionCounters map[string]int `json:\"versionCounters\"`", "backendSnapshot.Versions map[string][]*FunctionVersion `json:\"versions\"`", "functionConfigurationSnapshot.CreatedAt time.Time `json:\"createdAt,omitzero\"`", @@ -21794,7 +21794,7 @@ "backendSnapshot.NextAccessKeySeq int `json:\"nextAccessKeySeq\"`", "backendSnapshot.Partner *PartnerProfile `json:\"partner,omitempty\"`", "backendSnapshot.Region string `json:\"region\"`", - "backendSnapshot.Tables map[string]json.RawMessage `json:\"tables\"`", + "backendSnapshot.Tables map[string]jsontext.Value `json:\"tables\"`", "backendSnapshot.VpcPeered bool `json:\"vpcPeered\"`", "instanceHealth.Reason string", "instanceHealth.State string" diff --git a/services/accessanalyzer/access_previews.go b/services/accessanalyzer/access_previews.go index 14fda3f418..3994e3e724 100644 --- a/services/accessanalyzer/access_previews.go +++ b/services/accessanalyzer/access_previews.go @@ -1,7 +1,7 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" "maps" "sort" "time" @@ -13,7 +13,7 @@ import ( // required and must contain exactly one element (api_op_CreateAccessPreview.go:39-43). func (b *InMemoryBackend) CreateAccessPreview( analyzerArn string, - configurations map[string]json.RawMessage, + configurations map[string]jsontext.Value, ) (*AccessPreview, error) { if len(configurations) != 1 { return nil, ErrValidation diff --git a/services/accessanalyzer/analyzer_validation.go b/services/accessanalyzer/analyzer_validation.go index 9ba2831846..c483d383a0 100644 --- a/services/accessanalyzer/analyzer_validation.go +++ b/services/accessanalyzer/analyzer_validation.go @@ -1,11 +1,14 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -28,7 +31,7 @@ func isValidAnalyzerType(t AnalyzerType) bool { // validateCreateAnalyzer enforces the CreateAnalyzer name pattern (1-255, // [A-Za-z][A-Za-z0-9_.-]*), the Type enum, and that the configuration union // member matches the analyzer type. -func validateCreateAnalyzer(name string, t AnalyzerType, config json.RawMessage) error { +func validateCreateAnalyzer(name string, t AnalyzerType, config jsontext.Value) error { if len(name) > maxAnalyzerNameLen || !analyzerNameRe.MatchString(name) { return fmt.Errorf("%w: analyzerName must match [A-Za-z][A-Za-z0-9_.-]* (1-255 characters)", ErrValidation) } @@ -36,7 +39,7 @@ func validateCreateAnalyzer(name string, t AnalyzerType, config json.RawMessage) return validateAnalyzerTypeAndConfig(t, config) } -func validateAnalyzerTypeAndConfig(t AnalyzerType, config json.RawMessage) error { +func validateAnalyzerTypeAndConfig(t AnalyzerType, config jsontext.Value) error { if !isValidAnalyzerType(t) { return fmt.Errorf("%w: unsupported analyzer type %q", ErrValidation, t) } @@ -45,8 +48,8 @@ func validateAnalyzerTypeAndConfig(t AnalyzerType, config json.RawMessage) error return nil } - var members map[string]json.RawMessage - if err := json.Unmarshal(config, &members); err != nil { + var members map[string]jsontext.Value + if err := json.Unmarshal(config, &members, jsonx.V1()); err != nil { return fmt.Errorf("%w: malformed configuration", ErrValidation) } @@ -65,12 +68,12 @@ func validateAnalyzerTypeAndConfig(t AnalyzerType, config json.RawMessage) error return nil } -func validateUnusedAccessAge(raw json.RawMessage) error { +func validateUnusedAccessAge(raw jsontext.Value) error { var cfg struct { UnusedAccessAge *int `json:"unusedAccessAge"` } - if err := json.Unmarshal(raw, &cfg); err != nil { + if err := json.Unmarshal(raw, &cfg, jsonx.V1()); err != nil { return fmt.Errorf("%w: malformed unusedAccess configuration", ErrValidation) } diff --git a/services/accessanalyzer/analyzers.go b/services/accessanalyzer/analyzers.go index ddd6e88374..ff40b8b8b8 100644 --- a/services/accessanalyzer/analyzers.go +++ b/services/accessanalyzer/analyzers.go @@ -1,7 +1,7 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" "slices" "sort" "time" @@ -15,7 +15,7 @@ import ( // UpdateAnalyzer all accept the AnalyzerConfiguration union as an optional // parameter this way so existing call sites (which never set it) do not // need to change. -func firstConfiguration(cs []json.RawMessage) json.RawMessage { +func firstConfiguration(cs []jsontext.Value) jsontext.Value { if len(cs) == 0 { return nil } @@ -34,7 +34,7 @@ func (b *InMemoryBackend) CreateAnalyzer( name string, analyzerType AnalyzerType, tags map[string]string, - configuration ...json.RawMessage, + configuration ...jsontext.Value, ) (*Analyzer, error) { if name == "" { return nil, ErrValidation @@ -154,7 +154,7 @@ func (b *InMemoryBackend) DeleteAnalyzer(name string) error { // AnalyzerConfiguration union body (see Analyzer.Configuration). func (b *InMemoryBackend) CreateServiceLinkedAnalyzer( analyzerType AnalyzerType, - configuration ...json.RawMessage, + configuration ...jsontext.Value, ) (*Analyzer, error) { name := "_AccessAnalyzerForInternalUse-" + uuid.NewString()[:8] @@ -166,7 +166,7 @@ func (b *InMemoryBackend) CreateServiceLinkedAnalyzer( // AnalyzerConfiguration; otherwise the existing configuration is left // untouched and simply echoed back, matching UpdateAnalyzerOutput's // contract of always returning the analyzer's current configuration. -func (b *InMemoryBackend) UpdateAnalyzer(name string, configuration ...json.RawMessage) (*Analyzer, error) { +func (b *InMemoryBackend) UpdateAnalyzer(name string, configuration ...jsontext.Value) (*Analyzer, error) { b.mu.Lock("UpdateAnalyzer") defer b.mu.Unlock() diff --git a/services/accessanalyzer/analyzers_test.go b/services/accessanalyzer/analyzers_test.go index 978f0c7d70..04c29d49f5 100644 --- a/services/accessanalyzer/analyzers_test.go +++ b/services/accessanalyzer/analyzers_test.go @@ -1,7 +1,7 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -101,8 +101,8 @@ func TestDeleteAnalyzer_CascadesGhostRows(t *testing.T) { _, err = b.AddAnalyzedResource(a.Arn, "arn:aws:s3:::analyzed-bucket", "AWS::S3::Bucket", false) require.NoError(t, err) - preview, err := b.CreateAccessPreview(a.Arn, map[string]json.RawMessage{ - "arn:aws:s3:::analyzed-bucket": json.RawMessage(`{"s3Bucket":{"bucketPolicy":"{}"}}`), + preview, err := b.CreateAccessPreview(a.Arn, map[string]jsontext.Value{ + "arn:aws:s3:::analyzed-bucket": jsontext.Value(`{"s3Bucket":{"bucketPolicy":"{}"}}`), }) require.NoError(t, err) diff --git a/services/accessanalyzer/handler.go b/services/accessanalyzer/handler.go index dece6fc389..0d1b151376 100644 --- a/services/accessanalyzer/handler.go +++ b/services/accessanalyzer/handler.go @@ -2,7 +2,7 @@ package accessanalyzer import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -232,7 +233,7 @@ func (h *Handler) handleREST(c *echo.Context) error { return c.JSON(statusCode, struct{}{}) } - data, err := json.Marshal(result) + data, err := json.Marshal(result, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorBody("InternalFailure", "failed to serialize response")) diff --git a/services/accessanalyzer/handler_access_previews.go b/services/accessanalyzer/handler_access_previews.go index fd5d819293..53fc5c39f3 100644 --- a/services/accessanalyzer/handler_access_previews.go +++ b/services/accessanalyzer/handler_access_previews.go @@ -1,9 +1,12 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -54,11 +57,11 @@ func (h *Handler) dispatchAccessPreviewOps( // AccessPreview.Configurations godoc). func (h *Handler) handleCreateAccessPreview(body []byte) (any, int, error) { var req struct { - Configurations map[string]json.RawMessage `json:"configurations"` - AnalyzerArn string `json:"analyzerArn"` + Configurations map[string]jsontext.Value `json:"configurations"` + AnalyzerArn string `json:"analyzerArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -135,7 +138,7 @@ func (h *Handler) handleListAccessPreviewFindings(path string, body []byte) (any MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_access_previews_test.go b/services/accessanalyzer/handler_access_previews_test.go index 7726238344..31a8ce279b 100644 --- a/services/accessanalyzer/handler_access_previews_test.go +++ b/services/accessanalyzer/handler_access_previews_test.go @@ -1,13 +1,14 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -43,7 +44,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) previewID := created["id"] require.NotEmpty(t, previewID) @@ -51,7 +52,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got, jsonx.V1())) ap := got["accessPreview"].(map[string]any) assert.Equal(t, previewID, ap["id"]) assert.Equal(t, "COMPLETED", ap["status"]) @@ -107,7 +108,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) previews, ok := resp["accessPreviews"].([]any) require.True(t, ok) require.Len(t, previews, 1) @@ -134,7 +135,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { "configurations": singleS3BucketConfig("arn:aws:s3:::preview-findings-bucket"), }) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) previewID := created["id"] rec2 := doRequest(t, h, http.MethodPost, "/access-preview/"+previewID, map[string]any{ @@ -143,7 +144,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) findings := resp["findings"].([]any) require.Len(t, findings, 1) @@ -170,7 +171,7 @@ func TestAccessPreviewLifecycle(t *testing.T) { "configurations": singleS3BucketConfig("arn:aws:s3:::preview-findings-no-arn-bucket"), }) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) previewID := created["id"] // ListAccessPreviewFindingsInput requires analyzerArn. diff --git a/services/accessanalyzer/handler_analyzed_resources.go b/services/accessanalyzer/handler_analyzed_resources.go index 50740fbf2a..66827a3a03 100644 --- a/services/accessanalyzer/handler_analyzed_resources.go +++ b/services/accessanalyzer/handler_analyzed_resources.go @@ -1,9 +1,11 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -69,7 +71,7 @@ func (h *Handler) handleListAnalyzedResources(body []byte) (any, int, error) { MaxResults int `json:"maxResults"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) resources, nextToken, err := h.Backend.ListAnalyzedResources( req.AnalyzerArn, req.ResourceType, req.MaxResults, req.NextToken, @@ -106,7 +108,7 @@ func (h *Handler) handleStartResourceScan(body []byte) (int, error) { ResourceArn string `json:"resourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return 0, ErrValidation } diff --git a/services/accessanalyzer/handler_analyzed_resources_test.go b/services/accessanalyzer/handler_analyzed_resources_test.go index 29e97ee765..ec90b6d558 100644 --- a/services/accessanalyzer/handler_analyzed_resources_test.go +++ b/services/accessanalyzer/handler_analyzed_resources_test.go @@ -1,13 +1,14 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -34,7 +35,7 @@ func TestAnalyzedResourceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resource := resp["resource"].(map[string]any) assert.Equal(t, resourceArn, resource["resourceArn"]) // resourceOwnerAccount is a required AnalyzedResource member. @@ -70,7 +71,7 @@ func TestAnalyzedResourceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources := resp["analyzedResources"].([]any) assert.Len(t, resources, 2) diff --git a/services/accessanalyzer/handler_analyzers.go b/services/accessanalyzer/handler_analyzers.go index 0e4f65fea6..1b8aba9033 100644 --- a/services/accessanalyzer/handler_analyzers.go +++ b/services/accessanalyzer/handler_analyzers.go @@ -1,10 +1,13 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -63,13 +66,13 @@ func (h *Handler) dispatchAnalyzerOps(op, path, query string, body []byte) (any, func (h *Handler) handleCreateAnalyzer(body []byte) (any, int, error) { var req struct { Tags map[string]string `json:"tags"` - Configuration json.RawMessage `json:"configuration"` + Configuration jsontext.Value `json:"configuration"` AnalyzerName string `json:"analyzerName"` Type string `json:"type"` ArchiveRules []inlineArchiveRule `json:"archiveRules"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -186,10 +189,10 @@ func (h *Handler) handleUpdateAnalyzer(path string, body []byte) (any, int, erro name := extractAnalyzerName(path) var req struct { - Configuration json.RawMessage `json:"configuration"` + Configuration jsontext.Value `json:"configuration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -208,12 +211,12 @@ func (h *Handler) handleUpdateAnalyzer(path string, body []byte) (any, int, erro func (h *Handler) handleCreateServiceLinkedAnalyzer(body []byte) (any, int, error) { var req struct { - Configuration json.RawMessage `json:"configuration"` + Configuration jsontext.Value `json:"configuration"` Type string `json:"type"` ArchiveRules []inlineArchiveRule `json:"archiveRules"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_analyzers_test.go b/services/accessanalyzer/handler_analyzers_test.go index 8ceb0167b5..8cfdffd9f8 100644 --- a/services/accessanalyzer/handler_analyzers_test.go +++ b/services/accessanalyzer/handler_analyzers_test.go @@ -1,7 +1,7 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -30,7 +31,7 @@ func TestServiceLinkedAnalyzerLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.True(t, strings.HasPrefix(resp["arn"], "arn:aws:access-analyzer:")) }, }, @@ -112,7 +113,7 @@ func TestUpdateAnalyzer(t *testing.T) { // UpdateAnalyzerOutput carries only "configuration" -- unlike // CreateAnalyzer/CreateServiceLinkedAnalyzer, it has no "arn" member. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasArn := resp["arn"] assert.False(t, hasArn, `UpdateAnalyzerOutput has no "arn" member`) }) @@ -145,7 +146,7 @@ func TestAnalyzerConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) analyzer, ok := getResp["analyzer"].(map[string]any) require.True(t, ok) @@ -160,7 +161,7 @@ func TestAnalyzerConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) analyzers, ok := listResp["analyzers"].([]any) require.True(t, ok) require.Len(t, analyzers, 1) @@ -185,7 +186,7 @@ func TestAnalyzerConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfg, ok := resp["configuration"].(map[string]any) require.True(t, ok) unused, ok := cfg["unusedAccess"].(map[string]any) diff --git a/services/accessanalyzer/handler_archive_rules.go b/services/accessanalyzer/handler_archive_rules.go index bac1b102b0..ca00d58268 100644 --- a/services/accessanalyzer/handler_archive_rules.go +++ b/services/accessanalyzer/handler_archive_rules.go @@ -1,11 +1,13 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -78,7 +80,7 @@ func (h *Handler) handleCreateArchiveRule(path string, body []byte) (int, error) RuleName string `json:"ruleName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return 0, ErrValidation } @@ -154,7 +156,7 @@ func (h *Handler) handleUpdateArchiveRule(path string, body []byte) (int, error) Filter map[string]FilterCriterion `json:"filter"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return 0, ErrValidation } @@ -171,7 +173,7 @@ func (h *Handler) handleApplyArchiveRule(body []byte) (int, error) { RuleName string `json:"ruleName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return 0, ErrValidation } diff --git a/services/accessanalyzer/handler_findings.go b/services/accessanalyzer/handler_findings.go index 79d73d814d..c27f68df71 100644 --- a/services/accessanalyzer/handler_findings.go +++ b/services/accessanalyzer/handler_findings.go @@ -1,10 +1,12 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -108,7 +110,7 @@ func (h *Handler) handleListFindings(body []byte) (any, int, error) { MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -151,7 +153,7 @@ func (h *Handler) handleUpdateFindings(body []byte) (int, error) { IDs []string `json:"ids"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return 0, ErrValidation } @@ -212,7 +214,7 @@ func (h *Handler) handleListFindingsV2(body []byte) (any, int, error) { MaxResults int `json:"maxResults"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) findings, nextToken, err := h.Backend.ListFindingsV2( req.AnalyzerArn, req.Status, req.Filter, req.Sort, req.MaxResults, req.NextToken, @@ -273,7 +275,7 @@ func (h *Handler) handleGetFindingsStatistics(body []byte) (any, int, error) { AnalyzerArn string `json:"analyzerArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_findings_test.go b/services/accessanalyzer/handler_findings_test.go index 228bd4a7a2..f6acf3eb38 100644 --- a/services/accessanalyzer/handler_findings_test.go +++ b/services/accessanalyzer/handler_findings_test.go @@ -1,7 +1,7 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -59,7 +60,7 @@ func TestGetFinding(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) finding, ok := resp["finding"].(map[string]any) require.True(t, ok) @@ -105,7 +106,7 @@ func TestListFindings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, ok := resp["findings"].([]any) require.True(t, ok) @@ -223,7 +224,7 @@ func TestFindingV2Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, findingID, resp["id"]) // findingType and the ExternalAccessDetails union member of // findingDetails are required GetFindingV2Output members. @@ -253,7 +254,7 @@ func TestFindingV2Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings := resp["findings"].([]any) assert.Len(t, findings, 2) first, ok := findings[0].(map[string]any) @@ -331,7 +332,7 @@ func TestGetFindingsStatistics(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantActive > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stats := resp["findingsStatistics"].([]any) require.Len(t, stats, 1) @@ -368,7 +369,7 @@ func TestFindingRecommendationLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["recommendationType"]) }, }, @@ -436,7 +437,7 @@ func TestGetFindingRecommendation_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "UnusedPermissionRecommendation", resp["recommendationType"]) assert.Equal(t, "arn:aws:s3:::bucket", resp["resourceArn"]) diff --git a/services/accessanalyzer/handler_generated_policies.go b/services/accessanalyzer/handler_generated_policies.go index 451fa61629..0f5cae1b2d 100644 --- a/services/accessanalyzer/handler_generated_policies.go +++ b/services/accessanalyzer/handler_generated_policies.go @@ -1,11 +1,13 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // errPolicyGenerationJobNotModeled translates ErrPolicyGenerationNotFound for @@ -82,7 +84,7 @@ func (h *Handler) handleStartPolicyGeneration(body []byte) (any, int, error) { } `json:"policyGenerationDetails"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_generated_policies_test.go b/services/accessanalyzer/handler_generated_policies_test.go index 040d669870..99cfc5a4e8 100644 --- a/services/accessanalyzer/handler_generated_policies_test.go +++ b/services/accessanalyzer/handler_generated_policies_test.go @@ -1,7 +1,7 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -36,7 +37,7 @@ func TestPolicyGenerationLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["jobId"]) }, }, @@ -55,7 +56,7 @@ func TestPolicyGenerationLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["policyGenerations"]) }, }, @@ -102,7 +103,7 @@ func TestGetGeneratedPolicy(t *testing.T) { "policyGenerationDetails": map[string]any{"principalArn": "arn:aws:iam::000000000000:role/R"}, }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobID = resp["jobId"] } @@ -117,7 +118,7 @@ func TestGetGeneratedPolicy(t *testing.T) { // principalArn member -- that value only appears under // generatedPolicyResult.properties.principalArn for this operation. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobDetails, ok := resp["jobDetails"].(map[string]any) require.True(t, ok) _, hasPrincipalArn := jobDetails["principalArn"] @@ -163,7 +164,7 @@ func TestCancelPolicyGeneration(t *testing.T) { "policyGenerationDetails": map[string]any{"principalArn": "arn:aws:iam::000000000000:role/R"}, }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobID = resp["jobId"] } @@ -198,13 +199,13 @@ func TestStartPolicyGeneration_CloudTrailDetails(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) getRec := doRequest(t, h, http.MethodGet, "/policy/generation/"+startResp["jobId"], nil) require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) result, ok := resp["generatedPolicyResult"].(map[string]any) require.True(t, ok) @@ -249,7 +250,7 @@ func TestListPolicyGenerations_MaxResultsAndNextToken(t *testing.T) { require.Equal(t, http.StatusOK, firstRec.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstResp, jsonx.V1())) firstPage, ok := firstResp["policyGenerations"].([]any) require.True(t, ok) @@ -262,7 +263,7 @@ func TestListPolicyGenerations_MaxResultsAndNextToken(t *testing.T) { require.Equal(t, http.StatusOK, secondRec.Code) var secondResp map[string]any - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondResp, jsonx.V1())) secondPage, ok := secondResp["policyGenerations"].([]any) require.True(t, ok) diff --git a/services/accessanalyzer/handler_policy_validation.go b/services/accessanalyzer/handler_policy_validation.go index b04510809b..a5a96bdda2 100644 --- a/services/accessanalyzer/handler_policy_validation.go +++ b/services/accessanalyzer/handler_policy_validation.go @@ -1,9 +1,11 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -57,7 +59,7 @@ func (h *Handler) handleCheckAccessNotGranted(body []byte) (any, int, error) { Access []AccessSpec `json:"access"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -86,7 +88,7 @@ func (h *Handler) handleCheckNoNewAccess(body []byte) (any, int, error) { PolicyType string `json:"policyType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -114,7 +116,7 @@ func (h *Handler) handleCheckNoPublicAccess(body []byte) (any, int, error) { ResourceType string `json:"resourceType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -143,7 +145,7 @@ func (h *Handler) handleValidatePolicy(body []byte, query string) (any, int, err ResourceType string `json:"validatePolicyResourceType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_policy_validation_test.go b/services/accessanalyzer/handler_policy_validation_test.go index f92c6e5790..7ece7c3b07 100644 --- a/services/accessanalyzer/handler_policy_validation_test.go +++ b/services/accessanalyzer/handler_policy_validation_test.go @@ -1,12 +1,14 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCheckPolicyOps verifies Check* operations return PASS. @@ -55,7 +57,7 @@ func TestCheckPolicyOps(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PASS", resp["result"]) }) } @@ -165,7 +167,7 @@ func TestCheckPolicyOps_MalformedPolicyDocument(t *testing.T) { assert.Equal(t, http.StatusUnprocessableEntity, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "UnprocessableEntityException", resp["__type"]) }) } @@ -183,7 +185,7 @@ func TestValidatePolicy(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["findings"]) } @@ -204,7 +206,7 @@ func TestValidatePolicy_FindingDetailsPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, ok := resp["findings"].([]any) require.True(t, ok) require.NotEmpty(t, findings) diff --git a/services/accessanalyzer/handler_tags.go b/services/accessanalyzer/handler_tags.go index f987e957bb..c40ae3e40a 100644 --- a/services/accessanalyzer/handler_tags.go +++ b/services/accessanalyzer/handler_tags.go @@ -1,10 +1,12 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -36,7 +38,7 @@ func (h *Handler) handleTagResource(path string, body []byte) (any, int, error) Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/accessanalyzer/handler_test.go b/services/accessanalyzer/handler_test.go index e90700ea3d..b9027d8be4 100644 --- a/services/accessanalyzer/handler_test.go +++ b/services/accessanalyzer/handler_test.go @@ -2,7 +2,7 @@ package accessanalyzer_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -33,7 +34,7 @@ func doRequest(t *testing.T, h *accessanalyzer.Handler, method, path string, bod if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/accessanalyzer/interfaces.go b/services/accessanalyzer/interfaces.go index b901307c4a..de86ab5985 100644 --- a/services/accessanalyzer/interfaces.go +++ b/services/accessanalyzer/interfaces.go @@ -2,7 +2,7 @@ package accessanalyzer import ( "context" - "encoding/json" + "encoding/json/jsontext" ) // StorageBackend defines the interface for Access Analyzer backend implementations. @@ -11,13 +11,13 @@ type StorageBackend interface { // Analyzer operations. configuration is the optional raw // AnalyzerConfiguration union wire body -- see Analyzer.Configuration. CreateAnalyzer( - name string, analyzerType AnalyzerType, tags map[string]string, configuration ...json.RawMessage, + name string, analyzerType AnalyzerType, tags map[string]string, configuration ...jsontext.Value, ) (*Analyzer, error) GetAnalyzer(name string) (*Analyzer, error) ListAnalyzers(analyzerType string) ([]*Analyzer, error) DeleteAnalyzer(name string) error - UpdateAnalyzer(name string, configuration ...json.RawMessage) (*Analyzer, error) - CreateServiceLinkedAnalyzer(analyzerType AnalyzerType, configuration ...json.RawMessage) (*Analyzer, error) + UpdateAnalyzer(name string, configuration ...jsontext.Value) (*Analyzer, error) + CreateServiceLinkedAnalyzer(analyzerType AnalyzerType, configuration ...jsontext.Value) (*Analyzer, error) // Archive rule operations CreateArchiveRule(analyzerName, ruleName string, filter map[string]FilterCriterion) (*ArchiveRule, error) @@ -82,7 +82,7 @@ type StorageBackend interface { ListPolicyGenerations(principalArn string, maxResults int, nextToken string) ([]*PolicyGeneration, string, error) // Access previews - CreateAccessPreview(analyzerArn string, configurations map[string]json.RawMessage) (*AccessPreview, error) + CreateAccessPreview(analyzerArn string, configurations map[string]jsontext.Value) (*AccessPreview, error) GetAccessPreview(accessPreviewID string) (*AccessPreview, error) ListAccessPreviews(analyzerArn string) ([]*AccessPreview, error) ListAccessPreviewFindings( diff --git a/services/accessanalyzer/models.go b/services/accessanalyzer/models.go index 79b937f5be..32470f04da 100644 --- a/services/accessanalyzer/models.go +++ b/services/accessanalyzer/models.go @@ -1,7 +1,7 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" "maps" "time" ) @@ -72,7 +72,7 @@ type Analyzer struct { Name string `json:"name"` Type AnalyzerType `json:"type"` Status AnalyzerStatus `json:"status"` - Configuration json.RawMessage `json:"configuration,omitempty"` + Configuration jsontext.Value `json:"configuration,omitempty"` } // ArchiveRule represents an archive rule for an analyzer. @@ -169,7 +169,7 @@ const ( // echoed back opaquely as submitted instead of decoded into the full union. type AccessPreview struct { CreatedAt time.Time - Configurations map[string]json.RawMessage + Configurations map[string]jsontext.Value ID string AnalyzerArn string Status AccessPreviewStatus @@ -230,7 +230,7 @@ func cloneFilter(f map[string]FilterCriterion) map[string]FilterCriterion { func copyAnalyzer(a *Analyzer) *Analyzer { cp := *a cp.Tags = cloneTags(a.Tags) - cp.Configuration = append(json.RawMessage(nil), a.Configuration...) + cp.Configuration = append(jsontext.Value(nil), a.Configuration...) return &cp } diff --git a/services/accessanalyzer/persistence.go b/services/accessanalyzer/persistence.go index 7b3d95b0de..355a474a75 100644 --- a/services/accessanalyzer/persistence.go +++ b/services/accessanalyzer/persistence.go @@ -2,7 +2,7 @@ package accessanalyzer import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -96,7 +96,7 @@ func buildPersistenceDTORegistry() (*store.Registry, *store.Table[archiveRuleSna // identity of its own, so it is persisted here directly, matching its // pre-refactor shape exactly. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -194,7 +194,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // store_setup.go's registerAllTables doc) from tables via the ephemeral DTO // registry, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreArchiveRules(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreArchiveRules(tables map[string]jsontext.Value) error { dtoReg, archiveRuleDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("accessanalyzer: restore snapshot DTO tables: %w", err) diff --git a/services/accessanalyzer/persistence_test.go b/services/accessanalyzer/persistence_test.go index 4a31cd1d16..6e0add3b36 100644 --- a/services/accessanalyzer/persistence_test.go +++ b/services/accessanalyzer/persistence_test.go @@ -1,7 +1,7 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "time" @@ -88,7 +88,7 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { analyzer, err := original.CreateAnalyzer( "analyzer-1", accessanalyzer.AnalyzerTypeAccount, map[string]string{"env": "test"}, - json.RawMessage(`{"unusedAccess":{"unusedAccessAge":90}}`), + jsontext.Value(`{"unusedAccess":{"unusedAccessAge":90}}`), ) require.NoError(t, err) @@ -119,8 +119,8 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { ) require.NoError(t, err) - ap, err := original.CreateAccessPreview(analyzer.Arn, map[string]json.RawMessage{ - "arn:aws:s3:::bucket-2": json.RawMessage(`{"s3Bucket":{"bucketPolicy":"{}"}}`), + ap, err := original.CreateAccessPreview(analyzer.Arn, map[string]jsontext.Value{ + "arn:aws:s3:::bucket-2": jsontext.Value(`{"s3Bucket":{"bucketPolicy":"{}"}}`), }) require.NoError(t, err) diff --git a/services/accessanalyzer/policy_analysis.go b/services/accessanalyzer/policy_analysis.go index c09b552aee..63dfb228db 100644 --- a/services/accessanalyzer/policy_analysis.go +++ b/services/accessanalyzer/policy_analysis.go @@ -1,11 +1,14 @@ package accessanalyzer import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "path/filepath" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -52,14 +55,14 @@ type iamStringOrSlice []string func (s *iamStringOrSlice) UnmarshalJSON(data []byte) error { var str string - if err := json.Unmarshal(data, &str); err == nil { + if err := json.Unmarshal(data, &str, jsonx.V1()); err == nil { *s = []string{str} return nil } var slice []string - if err := json.Unmarshal(data, &slice); err != nil { + if err := json.Unmarshal(data, &slice, jsonx.V1()); err != nil { return err } @@ -78,27 +81,27 @@ type iamPrincipal struct { //nolint:govet // field order chosen for readability func (p *iamPrincipal) UnmarshalJSON(data []byte) error { var str string - if err := json.Unmarshal(data, &str); err == nil { + if err := json.Unmarshal(data, &str, jsonx.V1()); err == nil { p.IsWildcard = str == "*" return nil } - var m map[string]json.RawMessage - if err := json.Unmarshal(data, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(data, &m, jsonx.V1()); err != nil { return err } if v, ok := m["AWS"]; ok { - _ = json.Unmarshal(v, &p.AWS) + _ = json.Unmarshal(v, &p.AWS, jsonx.V1()) } if v, ok := m["Service"]; ok { - _ = json.Unmarshal(v, &p.Service) + _ = json.Unmarshal(v, &p.Service, jsonx.V1()) } if v, ok := m["Federated"]; ok { - _ = json.Unmarshal(v, &p.Federated) + _ = json.Unmarshal(v, &p.Federated, jsonx.V1()) } return nil @@ -116,7 +119,7 @@ func parsePolicy(doc string) (iamPolicy, error) { } var p iamPolicy - if err := json.Unmarshal([]byte(doc), &p); err != nil { + if err := json.Unmarshal([]byte(doc), &p, jsonx.V1()); err != nil { return iamPolicy{}, ErrMalformedPolicy } @@ -439,7 +442,7 @@ func stmtFieldLoc(stmtPath []any, field string) []map[string]any { } // validateVersion checks the Version field of a policy document. -func validateVersion(raw map[string]json.RawMessage, p iamPolicy) []ValidatePolicyFinding { +func validateVersion(raw map[string]jsontext.Value, p iamPolicy) []ValidatePolicyFinding { var findings []ValidatePolicyFinding if _, ok := raw["Version"]; !ok { @@ -546,8 +549,8 @@ func validateStatement(i int, stmt iamStatement, policyType string) []ValidatePo // ValidatePolicy checks a policy document for structural and semantic errors. func ValidatePolicy(policyDoc, policyType string) []ValidatePolicyFinding { - var raw map[string]json.RawMessage - if err := json.Unmarshal([]byte(policyDoc), &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal([]byte(policyDoc), &raw, jsonx.V1()); err != nil { findings := []ValidatePolicyFinding{errFinding("INVALID_POLICY_SYNTAX", rootLoc())} attachSpans(policyDoc, findings) @@ -582,7 +585,7 @@ func ValidatePolicy(policyDoc, policyType string) []ValidatePolicyFinding { // the finding) falls back one step at a time toward the document root, // which always resolves -- so span is never dropped. func attachSpans(doc string, findings []ValidatePolicyFinding) { - root := json.RawMessage(doc) + root := jsontext.Value(doc) for i := range findings { locs := findings[i].Locations @@ -595,7 +598,7 @@ func attachSpans(doc string, findings []ValidatePolicyFinding) { // attachSpan resolves loc's "span" in place. loc is a map (a reference // type), so mutating it here mutates the same map attachSpans's caller // holds -- no index expression needs to survive past this call. -func attachSpan(doc string, root json.RawMessage, loc map[string]any) { +func attachSpan(doc string, root jsontext.Value, loc map[string]any) { path, _ := loc[keyPath].([]any) for { @@ -619,7 +622,7 @@ func attachSpan(doc string, root json.RawMessage, loc map[string]any) { // map[string]any{keyValue: field} / map[string]any{keyIndex: i} shapes // rootLoc/fieldLoc/stmtLoc/stmtFieldLoc build (never JSON-decoded, so the // map values are concrete Go string/int, not float64/etc). -func resolveRawAt(node json.RawMessage, nodeStart int, path []any) (json.RawMessage, int, bool) { +func resolveRawAt(node jsontext.Value, nodeStart int, path []any) (jsontext.Value, int, bool) { if len(path) == 0 { return node, nodeStart, true } @@ -641,9 +644,9 @@ func resolveRawAt(node json.RawMessage, nodeStart int, path []any) (json.RawMess // resolveKeyStep resolves a map[string]any{keyValue: key} path step: the // PathElementMemberValue shape rootLoc/fieldLoc/stmtFieldLoc build for "the // value at this object key". -func resolveKeyStep(node json.RawMessage, nodeStart int, key string, rest []any) (json.RawMessage, int, bool) { - var m map[string]json.RawMessage - if err := json.Unmarshal(node, &m); err != nil { +func resolveKeyStep(node jsontext.Value, nodeStart int, key string, rest []any) (jsontext.Value, int, bool) { + var m map[string]jsontext.Value + if err := json.Unmarshal(node, &m, jsonx.V1()); err != nil { return nil, 0, false } @@ -666,9 +669,9 @@ func resolveKeyStep(node json.RawMessage, nodeStart int, key string, rest []any) // against the whole node) so an earlier element byte-identical to arr[idx] // can't steal the match -- each element narrows the search window past // itself. -func resolveIndexStep(node json.RawMessage, nodeStart, idx int, rest []any) (json.RawMessage, int, bool) { - var arr []json.RawMessage - if err := json.Unmarshal(node, &arr); err != nil { +func resolveIndexStep(node jsontext.Value, nodeStart, idx int, rest []any) (jsontext.Value, int, bool) { + var arr []jsontext.Value + if err := json.Unmarshal(node, &arr, jsonx.V1()); err != nil { return nil, 0, false } diff --git a/services/accessanalyzer/policy_analysis_test.go b/services/accessanalyzer/policy_analysis_test.go index 23800ce87d..1ea550a0c7 100644 --- a/services/accessanalyzer/policy_analysis_test.go +++ b/services/accessanalyzer/policy_analysis_test.go @@ -1,13 +1,14 @@ package accessanalyzer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/accessanalyzer" ) @@ -24,7 +25,7 @@ func policyAllow(action, resource string) string { }, } - b, _ := json.Marshal(p) + b, _ := json.Marshal(p, jsonx.V1()) return string(b) } @@ -48,7 +49,7 @@ func policyPublic() string { }, } - b, _ := json.Marshal(p) + b, _ := json.Marshal(p, jsonx.V1()) return string(b) } @@ -541,7 +542,7 @@ func TestCheckAccessNotGrantedHTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantResult, resp["result"]) }) } @@ -588,7 +589,7 @@ func TestCheckNoNewAccessHTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantResult, resp["result"]) }) } @@ -633,7 +634,7 @@ func TestCheckNoPublicAccessHTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantResult, resp["result"]) assert.NotNil(t, resp["reasons"]) }) @@ -689,7 +690,7 @@ func TestValidatePolicyHTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["findings"]) findings := resp["findings"].([]any) diff --git a/services/account/handler.go b/services/account/handler.go index 0fdd91ed74..2bc93ec586 100644 --- a/services/account/handler.go +++ b/services/account/handler.go @@ -1,7 +1,7 @@ package account import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -219,7 +220,7 @@ func decodeJSON(body []byte, v any) error { return nil } - return json.Unmarshal(body, v) + return json.Unmarshal(body, v, jsonx.V1()) } func (h *Handler) handleGetContactInformation(c *echo.Context, body []byte) error { diff --git a/services/account/handler_account_info_test.go b/services/account/handler_account_info_test.go index cd3e46d239..f522bb7fc5 100644 --- a/services/account/handler_account_info_test.go +++ b/services/account/handler_account_info_test.go @@ -1,13 +1,15 @@ package account_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/account" ) @@ -21,14 +23,14 @@ func TestHandler_GetAccountInformation(t *testing.T) { respBody := rec.Body.Bytes() var out account.Info - require.NoError(t, json.Unmarshal(respBody, &out)) + require.NoError(t, json.Unmarshal(respBody, &out, jsonx.V1())) assert.NotEmpty(t, out.AccountID) assert.NotEmpty(t, out.AccountCreatedDate) assert.Equal(t, account.StateActive, out.AccountState) // Response is a flat object, not wrapped like most other operations. var raw map[string]any - require.NoError(t, json.Unmarshal(respBody, &raw)) + require.NoError(t, json.Unmarshal(respBody, &raw, jsonx.V1())) assert.NotContains(t, raw, "Account") } @@ -63,7 +65,7 @@ func TestHandler_PutAccountName(t *testing.T) { require.Equal(t, http.StatusOK, infoRec.Code) var out account.Info - require.NoError(t, json.NewDecoder(infoRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(infoRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.accountName, out.AccountName) } }) @@ -78,7 +80,7 @@ func TestHandler_PrimaryEmail_GetDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["PrimaryEmail"]) } @@ -114,7 +116,7 @@ func TestHandler_PrimaryEmail_UpdateFlow(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) assert.Equal(t, "PENDING", startOut["Status"]) acceptRec := doRequest(t, h, "/acceptPrimaryEmailUpdate", map[string]any{ @@ -125,14 +127,14 @@ func TestHandler_PrimaryEmail_UpdateFlow(t *testing.T) { require.Equal(t, http.StatusOK, acceptRec.Code) var acceptOut map[string]any - require.NoError(t, json.NewDecoder(acceptRec.Body).Decode(&acceptOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(acceptRec.Body), &acceptOut, jsonx.V1())) assert.Equal(t, "ACCEPTED", acceptOut["Status"]) getRec := doRequest(t, h, "/getPrimaryEmail", map[string]any{"AccountId": "000000000000"}) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, tc.newEmail, getOut["PrimaryEmail"]) }) } @@ -206,7 +208,7 @@ func TestHandler_PrimaryEmail_StartConflictsOnCurrentEmail(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) currentEmail, ok := getOut["PrimaryEmail"].(string) require.True(t, ok) @@ -217,7 +219,7 @@ func TestHandler_PrimaryEmail_StartConflictsOnCurrentEmail(t *testing.T) { require.Equal(t, http.StatusConflict, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "ConflictException", out["__type"]) assert.Equal(t, "ConflictException", rec.Header().Get("X-Amzn-Errortype")) } @@ -262,7 +264,7 @@ func TestHandler_GetPrimaryEmailUpdateStatus(t *testing.T) { } var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantBody, out["Status"]) assert.NotZero(t, out["UpdatedAt"]) }) @@ -277,7 +279,7 @@ func TestHandler_GetGovCloudAccountInformation_NotLinked(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", out["__type"]) assert.Equal(t, "ResourceNotFoundException", rec.Header().Get("X-Amzn-Errortype")) } diff --git a/services/account/handler_contacts_test.go b/services/account/handler_contacts_test.go index 40445f54f7..886d5a6f9c 100644 --- a/services/account/handler_contacts_test.go +++ b/services/account/handler_contacts_test.go @@ -1,13 +1,16 @@ package account_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ContactInformation_PutGet(t *testing.T) { @@ -42,7 +45,7 @@ func TestHandler_ContactInformation_PutGet(t *testing.T) { var out struct { ContactInformation map[string]any `json:"ContactInformation"` } - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &out, jsonx.V1())) // Every field set on Put round-trips through Get exactly. for k, v := range full { @@ -137,7 +140,7 @@ func TestHandler_AlternateContact_PutGetDelete(t *testing.T) { var out struct { AlternateContact map[string]any `json:"AlternateContact"` } - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &out, jsonx.V1())) assert.Equal(t, "Test Contact", out.AlternateContact["Name"]) assert.Equal(t, tt.contactType, out.AlternateContact["AlternateContactType"]) diff --git a/services/account/handler_regions_test.go b/services/account/handler_regions_test.go index 5dfc1f9e5c..689669af96 100644 --- a/services/account/handler_regions_test.go +++ b/services/account/handler_regions_test.go @@ -1,7 +1,8 @@ package account_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/account" ) @@ -44,7 +46,7 @@ func TestHandler_ListRegions(t *testing.T) { var out struct { Regions []account.Region `json:"Regions"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Regions, tt.wantCount) }) } @@ -60,7 +62,7 @@ func TestHandler_ListRegions_RegionFieldsPresent(t *testing.T) { var out struct { Regions []map[string]any `json:"Regions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Regions) for _, r := range out.Regions { @@ -79,7 +81,7 @@ func TestHandler_ListRegions_Alphabetical(t *testing.T) { var out struct { Regions []account.Region `json:"Regions"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.Regions) for i := 1; i < len(out.Regions); i++ { @@ -129,7 +131,7 @@ func TestHandler_ListRegions_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Regions []map[string]any `json:"Regions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Regions), tc.maxResults) for _, r := range resp.Regions { @@ -231,7 +233,7 @@ func TestHandler_GetRegionOptStatus(t *testing.T) { if tc.wantStatus != "" { var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tc.regionName, out["RegionName"]) assert.Equal(t, tc.wantStatus, out["RegionOptStatus"]) } @@ -263,7 +265,7 @@ func TestHandler_EnableDisableRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) return out["RegionOptStatus"].(string) } diff --git a/services/account/handler_test.go b/services/account/handler_test.go index 397bccd3e7..89c0f8df87 100644 --- a/services/account/handler_test.go +++ b/services/account/handler_test.go @@ -1,7 +1,8 @@ package account_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/internal/awstest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/account" ) @@ -247,6 +249,6 @@ func TestHandler_ErrorEnvelope(t *testing.T) { assert.Equal(t, "ResourceNotFoundException", rec.Header().Get("X-Amzn-Errortype")) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", out["__type"]) } diff --git a/services/account/persistence.go b/services/account/persistence.go index 199c24f9a8..7ee64bd71b 100644 --- a/services/account/persistence.go +++ b/services/account/persistence.go @@ -2,7 +2,7 @@ package account import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -58,21 +58,21 @@ const accountSnapshotVersion = 2 // key on) and Regions is a plain (non-map) slice, so both stay raw; the // rest are scalars. type backendSnapshot struct { - AccountCreatedDate time.Time `json:"accountCreatedDate"` - Tables map[string]json.RawMessage `json:"tables"` - ContactInfo *ContactInformation `json:"contactInfo,omitempty"` - AccountID string `json:"accountID"` - Region string `json:"region"` - AccountName string `json:"accountName"` - PrimaryEmail string `json:"primaryEmail"` - PendingEmail string `json:"pendingEmail"` - PendingOTP string `json:"pendingOTP"` - PhoneVerifyNumber string `json:"phoneVerifyNumber,omitempty"` - PhoneVerifyOTP string `json:"phoneVerifyOTP,omitempty"` - PrimaryEmailUpdateStatus PrimaryEmailUpdateStatus `json:"primaryEmailUpdateStatus,omitempty"` - PrimaryEmailUpdateAt time.Time `json:"primaryEmailUpdateAt"` - Regions []*Region `json:"regions"` - Version int `json:"version"` + AccountCreatedDate time.Time `json:"accountCreatedDate"` + Tables map[string]jsontext.Value `json:"tables"` + ContactInfo *ContactInformation `json:"contactInfo,omitempty"` + AccountID string `json:"accountID"` + Region string `json:"region"` + AccountName string `json:"accountName"` + PrimaryEmail string `json:"primaryEmail"` + PendingEmail string `json:"pendingEmail"` + PendingOTP string `json:"pendingOTP"` + PhoneVerifyNumber string `json:"phoneVerifyNumber,omitempty"` + PhoneVerifyOTP string `json:"phoneVerifyOTP,omitempty"` + PrimaryEmailUpdateStatus PrimaryEmailUpdateStatus `json:"primaryEmailUpdateStatus,omitempty"` + PrimaryEmailUpdateAt time.Time `json:"primaryEmailUpdateAt"` + Regions []*Region `json:"regions"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. It implements diff --git a/services/account/validation_test.go b/services/account/validation_test.go index d64640f719..a00e5fdda5 100644 --- a/services/account/validation_test.go +++ b/services/account/validation_test.go @@ -1,7 +1,7 @@ package account_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/account" ) @@ -165,7 +166,7 @@ func TestHandler_Validation(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantCode, out.Type) assert.Contains(t, out.Message, tt.wantMsg) assert.False(t, strings.HasPrefix(out.Message, tt.wantCode), "message repeats the code: %q", out.Message) diff --git a/services/acm/acme_domain_validation_status_test.go b/services/acm/acme_domain_validation_status_test.go index badf2e9663..008b279bb1 100644 --- a/services/acm/acme_domain_validation_status_test.go +++ b/services/acm/acme_domain_validation_status_test.go @@ -1,7 +1,7 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAcmeDomainValidation_SettlesToValid(t *testing.T) { @@ -39,7 +41,7 @@ func TestAcmeDomainValidation_SettlesToValid(t *testing.T) { "PrevalidationOptions": map[string]any{ "DnsPrevalidation": map[string]any{"HostedZoneId": "Z123456"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) @@ -48,7 +50,7 @@ func TestAcmeDomainValidation_SettlesToValid(t *testing.T) { var out struct { Arn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) time.Sleep(tt.wait) @@ -58,13 +60,13 @@ func TestAcmeDomainValidation_SettlesToValid(t *testing.T) { "PrevalidationOptions": map[string]any{ "DnsPrevalidation": map[string]any{"HostedZoneId": "Z999999"}, }, - }) + }, jsonx.V1()) require.NoError(t, mErr) require.Equal(t, http.StatusOK, postACMJSON(t, h, "UpdateAcmeDomainValidation", string(upd)).Code) } - descBody, err := json.Marshal(map[string]string{"AcmeDomainValidationArn": out.Arn}) + descBody, err := json.Marshal(map[string]string{"AcmeDomainValidationArn": out.Arn}, jsonx.V1()) require.NoError(t, err) desc := postACMJSON(t, h, "DescribeAcmeDomainValidation", string(descBody)) @@ -75,7 +77,7 @@ func TestAcmeDomainValidation_SettlesToValid(t *testing.T) { Status string `json:"Status"` } `json:"AcmeDomainValidation"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantStatus, got.V.Status) }) }) diff --git a/services/acm/certificate_detail_no_fabricated_keyid_test.go b/services/acm/certificate_detail_no_fabricated_keyid_test.go index 4a7367fb43..82b87f85c5 100644 --- a/services/acm/certificate_detail_no_fabricated_keyid_test.go +++ b/services/acm/certificate_detail_no_fabricated_keyid_test.go @@ -1,11 +1,14 @@ package acm_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestACMHandler_DescribeCertificate_NoFabricatedKeyId locks in the removal @@ -30,19 +33,19 @@ func TestACMHandler_DescribeCertificate_NoFabricatedKeyId(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) - var certRaw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(raw["Certificate"], &certRaw)) + var certRaw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(raw["Certificate"], &certRaw, jsonx.V1())) _, hasKeyID := certRaw["KeyId"] require.False(t, hasKeyID, "DescribeCertificate must not emit a fabricated KeyId member on Certificate") diff --git a/services/acm/certificate_validation_test.go b/services/acm/certificate_validation_test.go index 2817885695..570abcf89e 100644 --- a/services/acm/certificate_validation_test.go +++ b/services/acm/certificate_validation_test.go @@ -1,12 +1,14 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestACMHandler_MalformedArn_ReturnsInvalidArnException verifies that a @@ -102,7 +104,7 @@ func TestACMHandler_RequestCertificate_TooManySANs_ReturnsLimitExceeded(t *testi body, err := json.Marshal(map[string]any{ "DomainName": "toomany.example.com", "SubjectAlternativeNames": sans, - }) + }, jsonx.V1()) require.NoError(t, err) h := newACMHandler() @@ -124,7 +126,7 @@ func TestACMHandler_TooManyTags_ReturnsTooManyTagsException(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) tags := make([]map[string]string, 0, 51) for i := range 51 { @@ -134,7 +136,7 @@ func TestACMHandler_TooManyTags_ReturnsTooManyTagsException(t *testing.T) { body, err := json.Marshal(map[string]any{ "CertificateArn": reqOut.CertificateArn, "Tags": tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "AddTagsToCertificate", string(body)) @@ -155,12 +157,12 @@ func TestACMHandler_ReservedTagPrefix_ReturnsInvalidTagException(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) body, err := json.Marshal(map[string]any{ "CertificateArn": reqOut.CertificateArn, "Tags": []map[string]string{{"Key": "aws:reserved", "Value": "v"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "AddTagsToCertificate", string(body)) @@ -187,9 +189,9 @@ func TestACMHandler_RequestCertificate_DomainValidationOptions_Applied(t *testin var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) diff --git a/services/acm/handler.go b/services/acm/handler.go index 24f82f24ac..17aadabceb 100644 --- a/services/acm/handler.go +++ b/services/acm/handler.go @@ -2,7 +2,8 @@ package acm import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "regexp" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -182,8 +184,8 @@ func (h *Handler) ExtractResource(c *echo.Context) string { if err != nil { return "" } - var m map[string]json.RawMessage - if unmarshalErr := json.Unmarshal(body, &m); unmarshalErr != nil { + var m map[string]jsontext.Value + if unmarshalErr := json.Unmarshal(body, &m, jsonx.V1()); unmarshalErr != nil { return "" } @@ -194,7 +196,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var arn string - if unmarshalErr := json.Unmarshal(raw, &arn); unmarshalErr == nil && arn != "" { + if unmarshalErr := json.Unmarshal(raw, &arn, jsonx.V1()); unmarshalErr == nil && arn != "" { return arn } } @@ -227,7 +229,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // handleError writes a standardized error response back to the client. diff --git a/services/acm/handler_account.go b/services/acm/handler_account.go index 0f955ba393..84ac957a24 100644 --- a/services/acm/handler_account.go +++ b/services/acm/handler_account.go @@ -2,7 +2,9 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type expiryEventsConfiguration struct { @@ -32,7 +34,7 @@ func (h *Handler) jsonGetAccountConfiguration(ctx context.Context, _ []byte) (an func (h *Handler) jsonPutAccountConfiguration(ctx context.Context, body []byte) (any, error) { var input putAccountConfigurationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_acme_accounts.go b/services/acm/handler_acme_accounts.go index c11d7ef1d3..86194a6410 100644 --- a/services/acm/handler_acme_accounts.go +++ b/services/acm/handler_acme_accounts.go @@ -2,7 +2,9 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type acmeAccountWire struct { @@ -36,7 +38,7 @@ type describeAcmeAccountOutput struct { func (h *Handler) jsonDescribeAcmeAccount(ctx context.Context, body []byte) (any, error) { var input describeAcmeAccountInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -63,7 +65,7 @@ type listAcmeAccountsOutput struct { func (h *Handler) jsonListAcmeAccounts(ctx context.Context, body []byte) (any, error) { var input listAcmeAccountsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -89,7 +91,7 @@ type revokeAcmeAccountOutput struct{} func (h *Handler) jsonRevokeAcmeAccount(ctx context.Context, body []byte) (any, error) { var input revokeAcmeAccountInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_acme_domain_validations.go b/services/acm/handler_acme_domain_validations.go index ba9be4f718..ab1e415633 100644 --- a/services/acm/handler_acme_domain_validations.go +++ b/services/acm/handler_acme_domain_validations.go @@ -2,9 +2,10 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -107,7 +108,7 @@ type createAcmeDomainValidationOutput struct { func (h *Handler) jsonCreateAcmeDomainValidation(ctx context.Context, body []byte) (any, error) { var input createAcmeDomainValidationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -146,7 +147,7 @@ type describeAcmeDomainValidationOutput struct { func (h *Handler) jsonDescribeAcmeDomainValidation(ctx context.Context, body []byte) (any, error) { var input describeAcmeDomainValidationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -176,7 +177,7 @@ type deleteAcmeDomainValidationOutput struct{} func (h *Handler) jsonDeleteAcmeDomainValidation(ctx context.Context, body []byte) (any, error) { var input deleteAcmeDomainValidationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -206,7 +207,7 @@ type listAcmeDomainValidationsOutput struct { func (h *Handler) jsonListAcmeDomainValidations(ctx context.Context, body []byte) (any, error) { var input listAcmeDomainValidationsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -240,7 +241,7 @@ type updateAcmeDomainValidationOutput struct{} func (h *Handler) jsonUpdateAcmeDomainValidation(ctx context.Context, body []byte) (any, error) { var input updateAcmeDomainValidationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_acme_eab.go b/services/acm/handler_acme_eab.go index d7e527d11c..a214d5d3be 100644 --- a/services/acm/handler_acme_eab.go +++ b/services/acm/handler_acme_eab.go @@ -2,9 +2,10 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -64,7 +65,7 @@ type createAcmeEABOutput struct { func (h *Handler) jsonCreateAcmeExternalAccountBinding(ctx context.Context, body []byte) (any, error) { var input createAcmeEABInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -110,7 +111,7 @@ type describeAcmeEABOutput struct { func (h *Handler) jsonDescribeAcmeExternalAccountBinding(ctx context.Context, body []byte) (any, error) { var input describeAcmeEABInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -140,7 +141,7 @@ type deleteAcmeEABOutput struct{} func (h *Handler) jsonDeleteAcmeExternalAccountBinding(ctx context.Context, body []byte) (any, error) { var input deleteAcmeEABInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -170,7 +171,7 @@ type listAcmeEABsOutput struct { func (h *Handler) jsonListAcmeExternalAccountBindings(ctx context.Context, body []byte) (any, error) { var input listAcmeEABsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -208,7 +209,7 @@ type getAcmeEABCredentialsOutput struct { func (h *Handler) jsonGetAcmeExternalAccountBindingCredentials(ctx context.Context, body []byte) (any, error) { var input getAcmeEABCredentialsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -236,7 +237,7 @@ type revokeAcmeEABOutput struct{} func (h *Handler) jsonRevokeAcmeExternalAccountBinding(ctx context.Context, body []byte) (any, error) { var input revokeAcmeEABInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_acme_endpoints.go b/services/acm/handler_acme_endpoints.go index a1d47d8233..015f62e8b1 100644 --- a/services/acm/handler_acme_endpoints.go +++ b/services/acm/handler_acme_endpoints.go @@ -2,9 +2,10 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -65,7 +66,7 @@ type createAcmeEndpointOutput struct { func (h *Handler) jsonCreateAcmeEndpoint(ctx context.Context, body []byte) (any, error) { var input createAcmeEndpointInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -111,7 +112,7 @@ type describeAcmeEndpointOutput struct { func (h *Handler) jsonDescribeAcmeEndpoint(ctx context.Context, body []byte) (any, error) { var input describeAcmeEndpointInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -141,7 +142,7 @@ type deleteAcmeEndpointOutput struct{} func (h *Handler) jsonDeleteAcmeEndpoint(ctx context.Context, body []byte) (any, error) { var input deleteAcmeEndpointInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -170,7 +171,7 @@ type listAcmeEndpointsOutput struct { func (h *Handler) jsonListAcmeEndpoints(ctx context.Context, body []byte) (any, error) { var input listAcmeEndpointsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -198,7 +199,7 @@ type updateAcmeEndpointOutput struct{} func (h *Handler) jsonUpdateAcmeEndpoint(ctx context.Context, body []byte) (any, error) { var input updateAcmeEndpointInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_certificate_lifecycle_test.go b/services/acm/handler_certificate_lifecycle_test.go index a3a67fee04..79a183e88c 100644 --- a/services/acm/handler_certificate_lifecycle_test.go +++ b/services/acm/handler_certificate_lifecycle_test.go @@ -2,7 +2,7 @@ package acm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -29,11 +30,11 @@ func TestACMHandler_DNSValidationWorkflow(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) require.NotEmpty(t, reqOut.CertificateArn) // Describe should show PENDING_VALIDATION with CNAME records - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -48,7 +49,7 @@ func TestACMHandler_DNSValidationWorkflow(t *testing.T) { } `json:"DomainValidationOptions"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Equal(t, "PENDING_VALIDATION", descOut.Certificate.Status) require.NotEmpty(t, descOut.Certificate.DomainValidationOptions) assert.NotNil(t, descOut.Certificate.DomainValidationOptions[0].ResourceRecord) @@ -64,7 +65,7 @@ func TestACMHandler_DNSValidationWorkflow(t *testing.T) { Status string `json:"Status"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ISSUED", out.Certificate.Status, "cert should transition to ISSUED") }) } @@ -89,7 +90,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -98,7 +99,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { "CertificateArn": certARN, "Domain": "email-resend.example.com", "ValidationDomain": "email-resend.example.com", - }) + }, jsonx.V1()) return string(b) }, @@ -114,7 +115,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { "CertificateArn": certARN, "Domain": "example.com", "ValidationDomain": "example.com", - }) + }, jsonx.V1()) return string(b) }, @@ -131,7 +132,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -140,7 +141,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { "CertificateArn": certARN, "Domain": "issued.example.com", "ValidationDomain": "issued.example.com", - }) + }, jsonx.V1()) return string(b) }, @@ -157,7 +158,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -166,7 +167,7 @@ func TestACMHandler_ResendValidationEmail(t *testing.T) { "CertificateArn": certARN, "Domain": "dns.example.com", "ValidationDomain": "dns.example.com", - }) + }, jsonx.V1()) return string(b) }, @@ -222,7 +223,7 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -230,7 +231,7 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { b, _ := json.Marshal(map[string]string{ "CertificateArn": certARN, "RevocationReason": "UNSPECIFIED", - }) + }, jsonx.V1()) return string(b) }, @@ -245,7 +246,7 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -253,7 +254,7 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { b, _ := json.Marshal(map[string]string{ "CertificateArn": certARN, "RevocationReason": "KEY_COMPROMISE", - }) + }, jsonx.V1()) return string(b) }, @@ -286,12 +287,12 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Revoke once b, _ := json.Marshal(map[string]string{ "CertificateArn": out.CertificateArn, "RevocationReason": "UNSPECIFIED", - }) + }, jsonx.V1()) postACMJSON(t, h, "RevokeCertificate", string(b)) return out.CertificateArn @@ -300,7 +301,7 @@ func TestACMHandler_RevokeCertificate(t *testing.T) { b, _ := json.Marshal(map[string]string{ "CertificateArn": certARN, "RevocationReason": "UNSPECIFIED", - }) + }, jsonx.V1()) return string(b) }, @@ -349,18 +350,18 @@ func TestACMHandler_RevokeCertificate_DescribeShowsRevoked(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) // Revoke it revokeBody, _ := json.Marshal(map[string]string{ "CertificateArn": reqOut.CertificateArn, "RevocationReason": "KEY_COMPROMISE", - }) + }, jsonx.V1()) revokeRec := postACMJSON(t, h, "RevokeCertificate", string(revokeBody)) require.Equal(t, http.StatusOK, revokeRec.Code) // Describe should show REVOKED with RevocationReason - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -371,7 +372,7 @@ func TestACMHandler_RevokeCertificate_DescribeShowsRevoked(t *testing.T) { RevocationReason string `json:"RevocationReason"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "REVOKED", descOut.Certificate.Status) assert.Equal(t, "KEY_COMPROMISE", descOut.Certificate.RevocationReason) assert.NotNil(t, descOut.Certificate.RevokedAt) @@ -396,7 +397,7 @@ func TestACMHandler_UpdateCertificateOptions(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -406,7 +407,7 @@ func TestACMHandler_UpdateCertificateOptions(t *testing.T) { "Options": map[string]string{ "CertificateTransparencyLoggingPreference": "ENABLED", }, - }) + }, jsonx.V1()) return string(b) }, @@ -421,7 +422,7 @@ func TestACMHandler_UpdateCertificateOptions(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.CertificateArn }, @@ -431,7 +432,7 @@ func TestACMHandler_UpdateCertificateOptions(t *testing.T) { "Options": map[string]string{ "CertificateTransparencyLoggingPreference": "DISABLED", }, - }) + }, jsonx.V1()) return string(b) }, @@ -447,7 +448,7 @@ func TestACMHandler_UpdateCertificateOptions(t *testing.T) { "Options": map[string]string{ "CertificateTransparencyLoggingPreference": "ENABLED", }, - }) + }, jsonx.V1()) return string(b) }, @@ -506,7 +507,7 @@ func TestACMHandler_UpdateCertificateOptions_DescribeShowsOptions(t *testing.T) var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) // Update options optsBody, _ := json.Marshal(map[string]any{ @@ -514,12 +515,12 @@ func TestACMHandler_UpdateCertificateOptions_DescribeShowsOptions(t *testing.T) "Options": map[string]string{ "CertificateTransparencyLoggingPreference": "DISABLED", }, - }) + }, jsonx.V1()) optsRec := postACMJSON(t, h, "UpdateCertificateOptions", string(optsBody)) require.Equal(t, http.StatusOK, optsRec.Code) // Describe should reflect options - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -530,7 +531,7 @@ func TestACMHandler_UpdateCertificateOptions_DescribeShowsOptions(t *testing.T) } `json:"Options"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.Certificate.Options) assert.Equal(t, "DISABLED", descOut.Certificate.Options.CertificateTransparencyLoggingPreference) } @@ -559,9 +560,9 @@ func TestACMHandler_RevokeCertificate_PendingValidationRejected(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(body)) require.Equal(t, http.StatusOK, descRec.Code) @@ -570,14 +571,14 @@ func TestACMHandler_RevokeCertificate_PendingValidationRejected(t *testing.T) { Status string `json:"Status"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Equal(t, "PENDING_VALIDATION", descOut.Certificate.Status) // Try to revoke PENDING cert revokeBody, _ := json.Marshal(map[string]string{ "CertificateArn": reqOut.CertificateArn, "RevocationReason": "UNSPECIFIED", - }) + }, jsonx.V1()) revokeRec := postACMJSON(t, h, "RevokeCertificate", string(revokeBody)) assert.Equal(t, http.StatusBadRequest, revokeRec.Code) assert.Contains(t, revokeRec.Body.String(), "ConflictException") @@ -708,7 +709,7 @@ func TestACMHandler_StatusLifecycle_DescribeReflectsNewStatus(t *testing.T) { certARN := tt.setupCert(t, b) tt.transition(t, b, certARN) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": certARN}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": certARN}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -718,7 +719,7 @@ func TestACMHandler_StatusLifecycle_DescribeReflectsNewStatus(t *testing.T) { FailureReason string `json:"FailureReason,omitempty"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, tt.wantStatus, descOut.Certificate.Status) }) } diff --git a/services/acm/handler_certificate_status_errors_test.go b/services/acm/handler_certificate_status_errors_test.go index cce0dcd514..63e0ad1735 100644 --- a/services/acm/handler_certificate_status_errors_test.go +++ b/services/acm/handler_certificate_status_errors_test.go @@ -2,7 +2,7 @@ package acm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -49,7 +50,7 @@ func TestACMHandler_ExportCertificate_AmazonIssued(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) return reqOut.CertificateArn }, @@ -85,7 +86,7 @@ func TestACMHandler_ExportCertificate_AmazonIssued(t *testing.T) { body, _ := json.Marshal(map[string]string{ "CertificateArn": certARN, "Passphrase": "dGVzdA==", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "ExportCertificate", string(body)) if tt.wantErrType == "" { @@ -96,7 +97,7 @@ func TestACMHandler_ExportCertificate_AmazonIssued(t *testing.T) { CertificateChain string `json:"CertificateChain"` PrivateKey string `json:"PrivateKey"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out.Certificate, "BEGIN CERTIFICATE") assert.NotEmpty(t, out.PrivateKey) @@ -112,7 +113,7 @@ func TestACMHandler_ExportCertificate_AmazonIssued(t *testing.T) { Exported bool `json:"Exported"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) var found bool for _, s := range listOut.CertificateSummaryList { @@ -132,7 +133,7 @@ func TestACMHandler_ExportCertificate_AmazonIssued(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) }) } @@ -148,7 +149,7 @@ func requestAndAwaitIssued(t *testing.T, h *acm.Handler, domainName, exportOptio reqBody["Options"] = map[string]string{"Export": exportOption} } - reqJSON, err := json.Marshal(reqBody) + reqJSON, err := json.Marshal(reqBody, jsonx.V1()) require.NoError(t, err) reqRec := postACMJSON(t, h, "RequestCertificate", string(reqJSON)) @@ -157,7 +158,7 @@ func requestAndAwaitIssued(t *testing.T, h *acm.Handler, domainName, exportOptio var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) descRec := postACMJSON(t, h, "DescribeCertificate", `{"CertificateArn":"`+reqOut.CertificateArn+`"}`) @@ -166,7 +167,7 @@ func requestAndAwaitIssued(t *testing.T, h *acm.Handler, domainName, exportOptio Status string `json:"Status"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) require.Equal(t, "ISSUED", out.Certificate.Status) return reqOut.CertificateArn @@ -204,14 +205,14 @@ func TestACMHandler_RenewCertificate_Imported_Returns_RequestInProgressException require.NoError(t, err) h := acm.NewHandler(b) - body, _ := json.Marshal(map[string]string{"CertificateArn": imported.ARN}) + body, _ := json.Marshal(map[string]string{"CertificateArn": imported.ARN}, jsonx.V1()) rec := postACMJSON(t, h, "RenewCertificate", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "RequestInProgressException", errResp.Type, "RenewCertificate on IMPORTED cert must return RequestInProgressException, not RequestError") }) @@ -298,14 +299,14 @@ func TestACMHandler_GetCertificate_NonIssuedStates_Returns_RequestInProgressExce certARN := tt.setup(t, b) h := acm.NewHandler(b) - body, _ := json.Marshal(map[string]string{"CertificateArn": certARN}) + body, _ := json.Marshal(map[string]string{"CertificateArn": certARN}, jsonx.V1()) rec := postACMJSON(t, h, "GetCertificate", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal( t, "RequestInProgressException", @@ -348,16 +349,16 @@ func TestACMHandler_RevokeCertificate_PendingValidation_Returns_ConflictExceptio body, _ := json.Marshal(map[string]string{ "DomainName": "revoke-pending.example.com", "ValidationMethod": method, - }) + }, jsonx.V1()) reqRec := postACMJSON(t, h, "RequestCertificate", string(body)) require.Equal(t, http.StatusOK, reqRec.Code) var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -366,20 +367,20 @@ func TestACMHandler_RevokeCertificate_PendingValidation_Returns_ConflictExceptio Status string `json:"Status"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Equal(t, "PENDING_VALIDATION", descOut.Certificate.Status) revokeBody, _ := json.Marshal(map[string]string{ "CertificateArn": reqOut.CertificateArn, "RevocationReason": "UNSPECIFIED", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "RevokeCertificate", string(revokeBody)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal( t, "ConflictException", @@ -459,14 +460,14 @@ func TestACMHandler_UpdateCertificateOptions_NonIssued_Returns_InvalidStateExcep "Options": map[string]string{ "CertificateTransparencyLoggingPreference": "ENABLED", }, - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "UpdateCertificateOptions", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal( t, "InvalidStateException", @@ -499,7 +500,7 @@ func TestACMHandler_GetCertificate_Issued_Succeeds(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) // No ValidationMethod is set, so the cert issues synchronously. descRec := postACMJSON(t, h, "DescribeCertificate", @@ -509,17 +510,17 @@ func TestACMHandler_GetCertificate_Issued_Succeeds(t *testing.T) { Status string `json:"Status"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Equal(t, "ISSUED", descOut.Certificate.Status) - body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) rec := postACMJSON(t, h, "GetCertificate", string(body)) assert.Equal(t, http.StatusOK, rec.Code) var out struct { Certificate string `json:"Certificate"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out.Certificate, "BEGIN CERTIFICATE") }) } diff --git a/services/acm/handler_certificates.go b/services/acm/handler_certificates.go index f25f4054a2..f61894decf 100644 --- a/services/acm/handler_certificates.go +++ b/services/acm/handler_certificates.go @@ -3,9 +3,11 @@ package acm import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type requestCertificateInput struct { @@ -257,7 +259,7 @@ type updateCertificateOptionsOutput struct{} func (h *Handler) jsonRequestCertificate(ctx context.Context, body []byte) (any, error) { var input requestCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrRequestCertInvalidParameter } certType := "" @@ -400,7 +402,7 @@ func buildRenewalSummaryDetail(rs *RenewalSummary) *renewalSummaryDetail { func (h *Handler) jsonDescribeCertificate(ctx context.Context, body []byte) (any, error) { var input describeCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } if err := validateCertArn(input.CertificateArn); err != nil { @@ -459,7 +461,7 @@ func (h *Handler) jsonDescribeCertificate(ctx context.Context, body []byte) (any // jsonListCertificates handles the ListCertificates operation. func (h *Handler) jsonListCertificates(ctx context.Context, body []byte) (any, error) { var input listCertificatesInput - _ = json.Unmarshal(body, &input) + _ = json.Unmarshal(body, &input, jsonx.V1()) if input.MaxItems < 0 || input.MaxItems > maxListItems { return nil, fmt.Errorf("%w: MaxItems must be between 1 and %d", ErrInvalidArgs, maxListItems) @@ -639,7 +641,7 @@ type listCertificateDomainValidationsOutput struct { // jsonListCertificateDomainValidations handles the ListCertificateDomainValidations operation. func (h *Handler) jsonListCertificateDomainValidations(ctx context.Context, body []byte) (any, error) { var input listCertificateDomainValidationsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -668,7 +670,7 @@ func (h *Handler) jsonListCertificateDomainValidations(ctx context.Context, body func (h *Handler) jsonDeleteCertificate(ctx context.Context, body []byte) (any, error) { var input deleteCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } if err := validateCertArn(input.CertificateArn); err != nil { @@ -684,7 +686,7 @@ func (h *Handler) jsonDeleteCertificate(ctx context.Context, body []byte) (any, func (h *Handler) jsonImportCertificate(ctx context.Context, body []byte) (any, error) { var input importCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } if err := validateCertArn(input.CertificateArn); err != nil { @@ -719,7 +721,7 @@ func (h *Handler) jsonImportCertificate(ctx context.Context, body []byte) (any, func (h *Handler) jsonRenewCertificate(ctx context.Context, body []byte) (any, error) { var input renewCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } if err := validateCertArn(input.CertificateArn); err != nil { @@ -734,7 +736,7 @@ func (h *Handler) jsonRenewCertificate(ctx context.Context, body []byte) (any, e func (h *Handler) jsonExportCertificate(ctx context.Context, body []byte) (any, error) { var input exportCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -769,7 +771,7 @@ func (h *Handler) jsonExportCertificate(ctx context.Context, body []byte) (any, func (h *Handler) jsonGetCertificate(ctx context.Context, body []byte) (any, error) { var input getCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } if err := validateCertArn(input.CertificateArn); err != nil { @@ -788,7 +790,7 @@ func (h *Handler) jsonGetCertificate(ctx context.Context, body []byte) (any, err func (h *Handler) jsonResendValidationEmail(ctx context.Context, body []byte) (any, error) { var input resendValidationEmailInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -806,7 +808,7 @@ func (h *Handler) jsonResendValidationEmail(ctx context.Context, body []byte) (a func (h *Handler) jsonRevokeCertificate(ctx context.Context, body []byte) (any, error) { var input revokeCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -823,7 +825,7 @@ func (h *Handler) jsonRevokeCertificate(ctx context.Context, body []byte) (any, func (h *Handler) jsonUpdateCertificateOptions(ctx context.Context, body []byte) (any, error) { var input updateCertificateOptionsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_certificates_list_test.go b/services/acm/handler_certificates_list_test.go index f95d69acdb..fe6d322a0a 100644 --- a/services/acm/handler_certificates_list_test.go +++ b/services/acm/handler_certificates_list_test.go @@ -3,7 +3,7 @@ package acm_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -46,7 +47,7 @@ func TestACMHandler_ListCertificates_StatusFilter(t *testing.T) { Status string `json:"Status"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(filterRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(filterRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.CertificateSummaryList, 1, "only the immediately-issued cert should match") for _, s := range out.CertificateSummaryList { @@ -75,7 +76,7 @@ func TestACMHandler_ListCertificates_EnrichedSummary(t *testing.T) { DomainName string `json:"DomainName"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.CertificateSummaryList) summary := out.CertificateSummaryList[0] @@ -91,7 +92,7 @@ func TestACMHandler_ListCertificates_SortByCreatedAt(t *testing.T) { // Create three certs in sequence for _, domain := range []string{"sort-a.example.com", "sort-b.example.com", "sort-c.example.com"} { - body, _ := json.Marshal(map[string]string{"DomainName": domain}) + body, _ := json.Marshal(map[string]string{"DomainName": domain}, jsonx.V1()) rec := postACMJSON(t, h, "RequestCertificate", string(body)) require.Equal(t, http.StatusOK, rec.Code) } @@ -106,7 +107,7 @@ func TestACMHandler_ListCertificates_SortByCreatedAt(t *testing.T) { DomainName string `json:"DomainName"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.CertificateSummaryList, 3) // Descending means newest first: sort-c, sort-b, sort-a @@ -133,7 +134,7 @@ func TestACMHandler_ListCertificates_KeyTypesFilter(t *testing.T) { DomainName string `json:"DomainName"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(matchRec.Body.Bytes(), &matchOut)) + require.NoError(t, json.Unmarshal(matchRec.Body.Bytes(), &matchOut, jsonx.V1())) require.NotEmpty(t, matchOut.CertificateSummaryList, "EC_prime256v1 filter should return results") // Filter that does not match @@ -144,7 +145,7 @@ func TestACMHandler_ListCertificates_KeyTypesFilter(t *testing.T) { var noMatchOut struct { CertificateSummaryList []struct{} `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(noMatchRec.Body.Bytes(), &noMatchOut)) + require.NoError(t, json.Unmarshal(noMatchRec.Body.Bytes(), &noMatchOut, jsonx.V1())) assert.Empty(t, noMatchOut.CertificateSummaryList, "RSA_2048 filter should return no results") } @@ -167,7 +168,7 @@ func TestACMHandler_ListCertificates_SubjectAlternativeNameSummaries(t *testing. SubjectAlternativeNameSummaries []string `json:"SubjectAlternativeNameSummaries"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.CertificateSummaryList) assert.Contains(t, out.CertificateSummaryList[0].SubjectAlternativeNameSummaries, "www.san.example.com") assert.Contains(t, out.CertificateSummaryList[0].SubjectAlternativeNameSummaries, "api.san.example.com") @@ -231,7 +232,7 @@ func TestACMHandler_ListCertificates_IncludesFilters(t *testing.T) { var out struct { CertificateSummaryList []struct{} `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) if tt.wantNonEmpty { assert.NotEmpty(t, out.CertificateSummaryList) } else { @@ -357,7 +358,7 @@ func TestACMHandler_ListCertificates_StatusFilter_AllStatuses(t *testing.T) { filterBody, _ := json.Marshal(map[string][]string{ "CertificateStatuses": {tt.filterStatus}, - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "ListCertificates", string(filterBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -366,7 +367,7 @@ func TestACMHandler_ListCertificates_StatusFilter_AllStatuses(t *testing.T) { Status string `json:"Status"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.CertificateSummaryList, tt.wantCount) if tt.wantCount > 0 { @@ -398,7 +399,7 @@ func TestACMHandler_ListCertificates_SubjectAlternativeNameSummaries_IncludesPri SubjectAlternativeNameSummaries []string `json:"SubjectAlternativeNameSummaries"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.CertificateSummaryList) summaries := listOut.CertificateSummaryList[0].SubjectAlternativeNameSummaries @@ -480,13 +481,13 @@ func TestACMHandler_SearchCertificates(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out, jsonx.V1())) body, _ := json.Marshal(map[string]any{ "FilterStatement": map[string]any{ "Filter": map[string]any{"CertificateArn": out.CertificateArn}, }, - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "SearchCertificates", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "search-arn-1.example.com") @@ -566,7 +567,7 @@ func TestACMHandler_SearchCertificates(t *testing.T) { } `json:"X509Attributes"` } `json:"Results"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Results, 1) assert.Equal(t, "commonname.example.com", out.Results[0].X509Attributes.Subject.CommonName) }, @@ -587,7 +588,7 @@ func TestACMHandler_SearchCertificates(t *testing.T) { importBody, marshalErr := json.Marshal(map[string]any{ "Certificate": base64.StdEncoding.EncodeToString([]byte(certPEM)), "PrivateKey": base64.StdEncoding.EncodeToString([]byte(keyPEM)), - }) + }, jsonx.V1()) require.NoError(t, marshalErr) importRec := postACMJSON(t, h, "ImportCertificate", string(importBody)) @@ -604,7 +605,7 @@ func TestACMHandler_SearchCertificates(t *testing.T) { CertificateArn string `json:"CertificateArn"` } `json:"Results"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Results, 1) }, }, @@ -631,7 +632,7 @@ func TestACMHandler_SearchCertificates(t *testing.T) { } `json:"CertificateMetadata"` } `json:"Results"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Results, 2) assert.GreaterOrEqual(t, out.Results[0].CertificateMetadata.AcmCertificateMetadata.CreatedAt, diff --git a/services/acm/handler_certificates_test.go b/services/acm/handler_certificates_test.go index 68f843c970..3bf4b8aab8 100644 --- a/services/acm/handler_certificates_test.go +++ b/services/acm/handler_certificates_test.go @@ -3,7 +3,8 @@ package acm_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -42,7 +44,7 @@ func TestACMHandler_ImportCertificate(t *testing.T) { in, _ := json.Marshal(map[string]string{ "Certificate": b64(certPEM), "PrivateKey": b64(keyPEM), - }) + }, jsonx.V1()) return string(in) }(), @@ -57,7 +59,7 @@ func TestACMHandler_ImportCertificate(t *testing.T) { { name: "missing_key", body: func() string { - in, _ := json.Marshal(map[string]string{"Certificate": b64(certPEM)}) + in, _ := json.Marshal(map[string]string{"Certificate": b64(certPEM)}, jsonx.V1()) return string(in) }(), @@ -147,7 +149,7 @@ func TestACMHandler_ExportCertificate(t *testing.T) { body, _ := json.Marshal(map[string]string{ "CertificateArn": tt.certARN, "Passphrase": "dGVzdA==", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "ExportCertificate", string(body)) assert.Equal(t, tt.wantCode, rec.Code) for _, s := range tt.wantContains { @@ -183,9 +185,9 @@ func TestACMHandler_GetCertificate(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + body, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) rec := postACMJSON(t, h, "GetCertificate", string(body)) assert.Equal(t, tt.wantCode, rec.Code) for _, s := range tt.wantContains { @@ -208,9 +210,9 @@ func TestACMHandler_DescribeCertificate_RealistFields(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -224,7 +226,7 @@ func TestACMHandler_DescribeCertificate_RealistFields(t *testing.T) { SignatureAlgorithm string `json:"SignatureAlgorithm"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.NotEmpty(t, descOut.Certificate.Serial, "Serial should be set") assert.Contains(t, descOut.Certificate.Subject, "realism.example.com", "Subject should contain domain") assert.Contains(t, descOut.Certificate.Issuer, "realism.example.com", "Issuer should contain domain (self-signed)") @@ -247,16 +249,16 @@ func TestACMHandler_ImportCertificate_RealistFields(t *testing.T) { body, _ := json.Marshal(map[string]string{ "Certificate": b64(src.CertificateBody), "PrivateKey": b64(src.PrivateKey), - }) + }, jsonx.V1()) importRec := postACMJSON(t, h, "ImportCertificate", string(body)) require.Equal(t, http.StatusOK, importRec.Code) var importOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut, jsonx.V1())) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": importOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": importOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -266,7 +268,7 @@ func TestACMHandler_ImportCertificate_RealistFields(t *testing.T) { Type string `json:"Type"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "IMPORTED", descOut.Certificate.Type) assert.NotNil(t, descOut.Certificate.ImportedAt, "ImportedAt should be set for imported cert") } @@ -288,14 +290,14 @@ func TestACMHandler_ImportCertificate_ReImport(t *testing.T) { body1, _ := json.Marshal(map[string]string{ "Certificate": b64(src1.CertificateBody), "PrivateKey": b64(src1.PrivateKey), - }) + }, jsonx.V1()) importRec := postACMJSON(t, h, "ImportCertificate", string(body1)) require.Equal(t, http.StatusOK, importRec.Code) var importOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut, jsonx.V1())) originalARN := importOut.CertificateArn // Re-import using the same ARN with new cert material @@ -303,7 +305,7 @@ func TestACMHandler_ImportCertificate_ReImport(t *testing.T) { "CertificateArn": originalARN, "Certificate": b64(src2.CertificateBody), "PrivateKey": b64(src2.PrivateKey), - }) + }, jsonx.V1()) reImportRec := postACMJSON(t, h, "ImportCertificate", string(body2)) require.Equal(t, http.StatusOK, reImportRec.Code) @@ -311,7 +313,7 @@ func TestACMHandler_ImportCertificate_ReImport(t *testing.T) { var reImportOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reImportRec.Body.Bytes(), &reImportOut)) + require.NoError(t, json.Unmarshal(reImportRec.Body.Bytes(), &reImportOut, jsonx.V1())) assert.Equal(t, originalARN, reImportOut.CertificateArn, "re-import should return same ARN") } @@ -330,7 +332,7 @@ func TestACMHandler_RequestCertificate_IdempotencyToken(t *testing.T) { var out1 struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) // Second call with same token should return same ARN rec2 := postACMJSON(t, h, "RequestCertificate", body) @@ -339,7 +341,7 @@ func TestACMHandler_RequestCertificate_IdempotencyToken(t *testing.T) { var out2 struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1.CertificateArn, out2.CertificateArn, "repeated RequestCertificate with same IdempotencyToken must return same ARN") @@ -376,7 +378,7 @@ func TestACMHandler_RequestCertificate_DomainValidation(t *testing.T) { t.Parallel() h := newACMHandler() - body, _ := json.Marshal(map[string]string{"DomainName": tt.domain}) + body, _ := json.Marshal(map[string]string{"DomainName": tt.domain}, jsonx.V1()) rec := postACMJSON(t, h, "RequestCertificate", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) }) @@ -395,9 +397,9 @@ func TestACMHandler_DescribeCertificate_KeyUsageAndInUseBy(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -408,7 +410,7 @@ func TestACMHandler_DescribeCertificate_KeyUsageAndInUseBy(t *testing.T) { InUseBy []string `json:"InUseBy"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.NotEmpty(t, descOut.Certificate.KeyUsage, "KeyUsage should be set") assert.Equal(t, "DIGITAL_SIGNATURE", descOut.Certificate.KeyUsage[0]["Name"]) @@ -430,9 +432,9 @@ func TestACMHandler_RequestCertificate_EMAIL_ValidationEmails(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -444,7 +446,7 @@ func TestACMHandler_RequestCertificate_EMAIL_ValidationEmails(t *testing.T) { } `json:"DomainValidationOptions"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.NotEmpty(t, descOut.Certificate.DomainValidationOptions) dvo := descOut.Certificate.DomainValidationOptions[0] @@ -483,7 +485,7 @@ func TestACMHandler_ExportCertificate_PassphraseRequired(t *testing.T) { { name: "missing_passphrase_rejected", body: func() string { - b2, _ := json.Marshal(map[string]string{"CertificateArn": importedCert.ARN}) + b2, _ := json.Marshal(map[string]string{"CertificateArn": importedCert.ARN}, jsonx.V1()) return string(b2) }(), @@ -496,7 +498,7 @@ func TestACMHandler_ExportCertificate_PassphraseRequired(t *testing.T) { b2, _ := json.Marshal(map[string]string{ "CertificateArn": importedCert.ARN, "Passphrase": "dGVzdC1wYXNz", // base64("test-pass") - }) + }, jsonx.V1()) return string(b2) }(), @@ -509,7 +511,7 @@ func TestACMHandler_ExportCertificate_PassphraseRequired(t *testing.T) { b2, _ := json.Marshal(map[string]string{ "CertificateArn": importedCert.ARN, "Passphrase": "not-valid-base64!!!", - }) + }, jsonx.V1()) return string(b2) }(), @@ -548,7 +550,7 @@ func TestACMHandler_ExportCertificate_CertificateChainAlwaysPresent(t *testing.T exportBody, _ := json.Marshal(map[string]string{ "CertificateArn": imported.ARN, "Passphrase": "dGVzdA==", // base64("test") - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "ExportCertificate", string(exportBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -557,7 +559,7 @@ func TestACMHandler_ExportCertificate_CertificateChainAlwaysPresent(t *testing.T Certificate string `json:"Certificate"` PrivateKey string `json:"PrivateKey"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.CertificateChain, "CertificateChain should always be present on export") assert.NotEmpty(t, out.Certificate) assert.NotEmpty(t, out.PrivateKey) @@ -565,7 +567,7 @@ func TestACMHandler_ExportCertificate_CertificateChainAlwaysPresent(t *testing.T func mustMarshal(t *testing.T, v any) string { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) @@ -623,7 +625,7 @@ func TestACMHandler_SubjectAlternativeNames_IncludesPrimaryDomain(t *testing.T) var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) descBody := mustMarshal(t, map[string]string{"CertificateArn": reqOut.CertificateArn}) descRec := postACMJSON(t, h, "DescribeCertificate", descBody) @@ -634,7 +636,7 @@ func TestACMHandler_SubjectAlternativeNames_IncludesPrimaryDomain(t *testing.T) SubjectAlternativeNames []string `json:"SubjectAlternativeNames"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) sans := descOut.Certificate.SubjectAlternativeNames require.NotEmpty(t, sans, "SubjectAlternativeNames must not be empty") @@ -676,21 +678,21 @@ func TestACMHandler_DescribeCertificate_InUseByIsAlwaysArray(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) descBody := mustMarshal(t, map[string]string{"CertificateArn": reqOut.CertificateArn}) descRec := postACMJSON(t, h, "DescribeCertificate", descBody) require.Equal(t, http.StatusOK, descRec.Code) // Use raw JSON to verify InUseBy is an array, not null or missing. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) certRaw, ok := raw["Certificate"] require.True(t, ok, "response must have Certificate field") - var certMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(certRaw, &certMap)) + var certMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(certRaw, &certMap, jsonx.V1())) inUseByRaw, present := certMap["InUseBy"] require.True(t, present, @@ -716,7 +718,7 @@ func TestACMHandler_Serial_ColonSeparatedHexFormat(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) descBody := mustMarshal(t, map[string]string{"CertificateArn": reqOut.CertificateArn}) descRec := postACMJSON(t, h, "DescribeCertificate", descBody) @@ -727,7 +729,7 @@ func TestACMHandler_Serial_ColonSeparatedHexFormat(t *testing.T) { Serial string `json:"Serial"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) serial := descOut.Certificate.Serial require.NotEmpty(t, serial, "Serial must be set for an issued certificate") @@ -769,7 +771,7 @@ func TestACMHandler_ImportedCertificate_SerialColonFormat(t *testing.T) { var importOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut, jsonx.V1())) descBody := mustMarshal(t, map[string]string{"CertificateArn": importOut.CertificateArn}) descRec := postACMJSON(t, h, "DescribeCertificate", descBody) @@ -780,7 +782,7 @@ func TestACMHandler_ImportedCertificate_SerialColonFormat(t *testing.T) { Serial string `json:"Serial"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) serial := descOut.Certificate.Serial require.NotEmpty(t, serial, "imported cert Serial must be set") diff --git a/services/acm/handler_request_certificate_invalid_parameter_test.go b/services/acm/handler_request_certificate_invalid_parameter_test.go index 66d90c7a26..a77ec39916 100644 --- a/services/acm/handler_request_certificate_invalid_parameter_test.go +++ b/services/acm/handler_request_certificate_invalid_parameter_test.go @@ -1,13 +1,15 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestACMHandler_RequestCertificate_InvalidParameterException verifies that RequestCertificate's @@ -40,7 +42,7 @@ func TestACMHandler_RequestCertificate_InvalidParameterException(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) }) } @@ -65,7 +67,7 @@ func TestACMHandler_RequestCertificate_IdempotencyMismatch_InvalidParameterExcep var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) } @@ -83,7 +85,7 @@ func TestACMHandler_CreateAcmeDomainValidation_InvalidDomainName_StillValidation "AcmeEndpointArn": epARN, "DomainName": "foo..bad.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) @@ -92,7 +94,7 @@ func TestACMHandler_CreateAcmeDomainValidation_InvalidDomainName_StillValidation var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp.Type) } diff --git a/services/acm/handler_resource_tags.go b/services/acm/handler_resource_tags.go index 5b5ed84748..a243436e71 100644 --- a/services/acm/handler_resource_tags.go +++ b/services/acm/handler_resource_tags.go @@ -2,9 +2,10 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -66,7 +67,7 @@ type listTagsForResourceOutput struct { func (h *Handler) jsonListTagsForResource(ctx context.Context, body []byte) (any, error) { var input listTagsForResourceInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -86,7 +87,7 @@ type tagResourceOutput struct{} func (h *Handler) jsonTagResource(ctx context.Context, body []byte) (any, error) { var input tagResourceInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -119,7 +120,7 @@ type untagResourceOutput struct{} func (h *Handler) jsonUntagResource(ctx context.Context, body []byte) (any, error) { var input untagResourceInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_search_certificates.go b/services/acm/handler_search_certificates.go index 0c5967d71c..a184b848c9 100644 --- a/services/acm/handler_search_certificates.go +++ b/services/acm/handler_search_certificates.go @@ -2,8 +2,10 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type dnsNameFilterWire struct { @@ -291,7 +293,7 @@ type searchCertificatesOutput struct { func (h *Handler) jsonSearchCertificates(ctx context.Context, body []byte) (any, error) { var input searchCertificatesInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_tags.go b/services/acm/handler_tags.go index 837431c39e..9c9e0daa49 100644 --- a/services/acm/handler_tags.go +++ b/services/acm/handler_tags.go @@ -2,10 +2,11 @@ package acm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -146,7 +147,7 @@ func (h *Handler) getTags(resourceID string) []map[string]string { func (h *Handler) jsonListTagsForCertificate(ctx context.Context, body []byte) (any, error) { var input listTagsForCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -163,7 +164,7 @@ func (h *Handler) jsonListTagsForCertificate(ctx context.Context, body []byte) ( func (h *Handler) jsonAddTagsToCertificate(ctx context.Context, body []byte) (any, error) { var input addTagsToCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } @@ -188,7 +189,7 @@ func (h *Handler) jsonAddTagsToCertificate(ctx context.Context, body []byte) (an func (h *Handler) jsonRemoveTagsFromCertificate(ctx context.Context, body []byte) (any, error) { var input removeTagsFromCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidParameter } diff --git a/services/acm/handler_tags_test.go b/services/acm/handler_tags_test.go index b58a87004e..51bd2dc160 100644 --- a/services/acm/handler_tags_test.go +++ b/services/acm/handler_tags_test.go @@ -1,7 +1,7 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -66,17 +67,17 @@ func TestACMHandler_RequestCertificate_Tags(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Verify tags are stored - listBody, _ := json.Marshal(map[string]string{"CertificateArn": out.CertificateArn}) + listBody, _ := json.Marshal(map[string]string{"CertificateArn": out.CertificateArn}, jsonx.V1()) listRec := postACMJSON(t, h, "ListTagsForCertificate", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var tagsOut struct { Tags []map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) tagMap := make(map[string]string) for _, t2 := range tagsOut.Tags { @@ -113,18 +114,18 @@ func TestACMHandler_GenericResourceTags_RouteByArnType(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) // Tag via the certificate-specific op... addBody, _ := json.Marshal(map[string]any{ "CertificateArn": reqOut.CertificateArn, "Tags": []map[string]string{{"Key": "via", "Value": "AddTagsToCertificate"}}, - }) + }, jsonx.V1()) addRec := postACMJSON(t, h, "AddTagsToCertificate", string(addBody)) require.Equal(t, http.StatusOK, addRec.Code) // ...and read it back via the generic op. - listBody, _ := json.Marshal(map[string]string{"ResourceArn": reqOut.CertificateArn}) + listBody, _ := json.Marshal(map[string]string{"ResourceArn": reqOut.CertificateArn}, jsonx.V1()) listRec := postACMJSON(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) assert.Contains(t, listRec.Body.String(), "AddTagsToCertificate") @@ -133,12 +134,12 @@ func TestACMHandler_GenericResourceTags_RouteByArnType(t *testing.T) { tagBody, _ := json.Marshal(map[string]any{ "ResourceArn": reqOut.CertificateArn, "Tags": []map[string]string{{"Key": "via", "Value": "TagResource"}}, - }) + }, jsonx.V1()) tagRec := postACMJSON(t, h, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, tagRec.Code, tagRec.Body.String()) // ...and read it back via the certificate-specific op. - certListBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + certListBody, _ := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) certListRec := postACMJSON(t, h, "ListTagsForCertificate", string(certListBody)) require.Equal(t, http.StatusOK, certListRec.Code) assert.Contains(t, certListRec.Body.String(), "TagResource") @@ -154,16 +155,19 @@ func TestACMHandler_GenericResourceTags_RouteByArnType(t *testing.T) { tagBody, _ := json.Marshal(map[string]any{ "ResourceArn": epARN, "Tags": []map[string]string{{"Key": "env", "Value": "prod"}}, - }) + }, jsonx.V1()) tagRec := postACMJSON(t, h, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, tagRec.Code, tagRec.Body.String()) - listBody, _ := json.Marshal(map[string]string{"ResourceArn": epARN}) + listBody, _ := json.Marshal(map[string]string{"ResourceArn": epARN}, jsonx.V1()) listRec := postACMJSON(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) assert.Contains(t, listRec.Body.String(), "prod") - untagBody, _ := json.Marshal(map[string]any{"ResourceArn": epARN, "TagKeys": []string{"env"}}) + untagBody, _ := json.Marshal( + map[string]any{"ResourceArn": epARN, "TagKeys": []string{"env"}}, + jsonx.V1(), + ) untagRec := postACMJSON(t, h, "UntagResource", string(untagBody)) require.Equal(t, http.StatusOK, untagRec.Code) @@ -250,7 +254,7 @@ func TestACMHandler_NewStyleTagValidation_UsesValidationAndServiceQuota(t *testi "AuthorizationBehavior": "PRE_APPROVED", "CertificateAuthority": map[string]any{"PublicCertificateAuthority": map[string]any{}}, "Tags": tooManyTags(), - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "CreateAcmeEndpoint", string(body)) @@ -268,7 +272,7 @@ func TestACMHandler_NewStyleTagValidation_UsesValidationAndServiceQuota(t *testi body, err := json.Marshal(map[string]any{ "ResourceArn": epARN, "Tags": []map[string]string{{"Key": "aws:reserved", "Value": "v"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "TagResource", string(body)) @@ -276,7 +280,7 @@ func TestACMHandler_NewStyleTagValidation_UsesValidationAndServiceQuota(t *testi assert.Contains(t, rec.Body.String(), "ValidationException") assert.NotContains(t, rec.Body.String(), "InvalidTagException") - listBody, _ := json.Marshal(map[string]string{"ResourceArn": epARN}) + listBody, _ := json.Marshal(map[string]string{"ResourceArn": epARN}, jsonx.V1()) listRec := postACMJSON(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) assert.JSONEq(t, `{"Tags":[]}`, listRec.Body.String(), "rejected tag must not be stored") @@ -289,7 +293,7 @@ func TestACMHandler_NewStyleTagValidation_UsesValidationAndServiceQuota(t *testi epARN := createTestAcmeEndpoint(t, h) - body, err := json.Marshal(map[string]any{"ResourceArn": epARN, "Tags": tooManyTags()}) + body, err := json.Marshal(map[string]any{"ResourceArn": epARN, "Tags": tooManyTags()}, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "TagResource", string(body)) @@ -336,7 +340,7 @@ func TestACMHandler_LegacyTagOps_KeyOrValueTooLong_InvalidTagException(t *testin body, err := json.Marshal(map[string]any{ "DomainName": "toolong.example.com", "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := postACMJSON(t, h, "RequestCertificate", string(body)) diff --git a/services/acm/handler_test.go b/services/acm/handler_test.go index d33ca07179..07f0e83625 100644 --- a/services/acm/handler_test.go +++ b/services/acm/handler_test.go @@ -1,7 +1,7 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -205,10 +206,13 @@ func TestACMHandler(t *testing.T) { CertificateArn string `json:"CertificateArn"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.NotEmpty(t, listResp.CertificateSummaryList) b, _ := json.Marshal( - map[string]string{"CertificateArn": listResp.CertificateSummaryList[0].CertificateArn}, + map[string]string{ + "CertificateArn": listResp.CertificateSummaryList[0].CertificateArn, + }, + jsonx.V1(), ) body = string(b) } @@ -235,7 +239,7 @@ func createTestAcmeEndpoint(t *testing.T, h *acm.Handler) string { var out struct { AcmeEndpointArn string `json:"AcmeEndpointArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.AcmeEndpointArn) return out.AcmeEndpointArn @@ -291,7 +295,7 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { t.Helper() epARN := createTestAcmeEndpoint(t, h) - body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) rec := postACMJSON(t, h, "DescribeAcmeEndpoint", string(body)) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) assert.Contains(t, rec.Body.String(), `"Status":"ACTIVE"`) @@ -338,11 +342,14 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { t.Helper() epARN := createTestAcmeEndpoint(t, h) - updBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN, "Contact": "REQUIRED"}) + updBody, _ := json.Marshal( + map[string]string{"AcmeEndpointArn": epARN, "Contact": "REQUIRED"}, + jsonx.V1(), + ) updRec := postACMJSON(t, h, "UpdateAcmeEndpoint", string(updBody)) require.Equal(t, http.StatusOK, updRec.Code, updRec.Body.String()) - descBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + descBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeAcmeEndpoint", string(descBody)) assert.Contains(t, descRec.Body.String(), `"Contact":"REQUIRED"`) }, @@ -353,7 +360,7 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { t.Helper() epARN := createTestAcmeEndpoint(t, h) - delBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + delBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) delRec := postACMJSON(t, h, "DeleteAcmeEndpoint", string(delBody)) require.Equal(t, http.StatusOK, delRec.Code) @@ -377,7 +384,7 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { assert.Contains(t, delRec.Body.String(), "ValidationException") assert.NotContains(t, delRec.Body.String(), "ResourceNotFoundException") - descBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + descBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeAcmeEndpoint", string(descBody)) assert.Equal(t, http.StatusOK, descRec.Code, "unrelated endpoint must be untouched") }, @@ -395,7 +402,7 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { eabBody, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) eabRec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(eabBody)) require.Equal(t, http.StatusOK, eabRec.Code, eabRec.Body.String()) @@ -404,7 +411,7 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { AcmeExternalAccountBindingArn string `json:"AcmeExternalAccountBindingArn"` } `json:"ExternalAccountBinding"` } - require.NoError(t, json.Unmarshal(eabRec.Body.Bytes(), &eabOut)) + require.NoError(t, json.Unmarshal(eabRec.Body.Bytes(), &eabOut, jsonx.V1())) eabARN := eabOut.ExternalAccountBinding.AcmeExternalAccountBindingArn require.NotEmpty(t, eabARN) @@ -412,26 +419,26 @@ func TestACMHandler_AcmeEndpoints(t *testing.T) { "AcmeEndpointArn": epARN, "DomainName": "cascade.example.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) dvRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(dvBody)) require.Equal(t, http.StatusOK, dvRec.Code, dvRec.Body.String()) var dvOut struct { AcmeDomainValidationArn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(dvRec.Body.Bytes(), &dvOut)) + require.NoError(t, json.Unmarshal(dvRec.Body.Bytes(), &dvOut, jsonx.V1())) require.NotEmpty(t, dvOut.AcmeDomainValidationArn) - delBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + delBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) delRec := postACMJSON(t, h, "DeleteAcmeEndpoint", string(delBody)) require.Equal(t, http.StatusOK, delRec.Code) - descEABBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}) + descEABBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}, jsonx.V1()) descEABRec := postACMJSON(t, h, "DescribeAcmeExternalAccountBinding", string(descEABBody)) assert.Equal(t, http.StatusBadRequest, descEABRec.Code, "EAB must be cascade-deleted with its endpoint") descDVBody, _ := json.Marshal( - map[string]string{"AcmeDomainValidationArn": dvOut.AcmeDomainValidationArn}, + map[string]string{"AcmeDomainValidationArn": dvOut.AcmeDomainValidationArn}, jsonx.V1(), ) descDVRec := postACMJSON(t, h, "DescribeAcmeDomainValidation", string(descDVBody)) assert.Equal(t, http.StatusBadRequest, descDVRec.Code, @@ -473,7 +480,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", "Expiration": map[string]any{"Type": "DAYS", "Value": 7}, - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(body)) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) assert.Contains(t, rec.Body.String(), "acme-external-account-binding/") @@ -486,7 +493,10 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { t.Helper() epARN := createTestAcmeEndpoint(t, h) - body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN, "RoleArn": "not-a-role-arn"}) + body, _ := json.Marshal( + map[string]string{"AcmeEndpointArn": epARN, "RoleArn": "not-a-role-arn"}, + jsonx.V1(), + ) rec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) assert.Contains(t, rec.Body.String(), "ValidationException") @@ -500,7 +510,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { body, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": "arn:aws:acm:us-east-1:000000000000:acme-endpoint/nope", "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) assert.Contains(t, rec.Body.String(), "ResourceNotFoundException") @@ -515,7 +525,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { createBody, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(createBody)) require.Equal(t, http.StatusOK, createRec.Code) @@ -524,10 +534,10 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { AcmeExternalAccountBindingArn string `json:"AcmeExternalAccountBindingArn"` } `json:"ExternalAccountBinding"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) eabARN := createOut.ExternalAccountBinding.AcmeExternalAccountBindingArn - credBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}) + credBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}, jsonx.V1()) credRec := postACMJSON(t, h, "GetAcmeExternalAccountBindingCredentials", string(credBody)) require.Equal(t, http.StatusOK, credRec.Code) @@ -535,7 +545,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { KeyID string `json:"KeyId"` MacKey string `json:"MacKey"` } - require.NoError(t, json.Unmarshal(credRec.Body.Bytes(), &credOut)) + require.NoError(t, json.Unmarshal(credRec.Body.Bytes(), &credOut, jsonx.V1())) assert.NotEmpty(t, credOut.KeyID) assert.NotEmpty(t, credOut.MacKey) @@ -578,11 +588,11 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { createBody, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(createBody)) require.Equal(t, http.StatusOK, createRec.Code) - listBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + listBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) listRec := postACMJSON(t, h, "ListAcmeExternalAccountBindings", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) assert.Contains(t, listRec.Body.String(), "acme-external-account-binding/") @@ -597,7 +607,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { createBody, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(createBody)) require.Equal(t, http.StatusOK, createRec.Code) @@ -606,11 +616,11 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { AcmeExternalAccountBindingArn string `json:"AcmeExternalAccountBindingArn"` } `json:"ExternalAccountBinding"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) delBody, _ := json.Marshal(map[string]string{ "AcmeExternalAccountBindingArn": createOut.ExternalAccountBinding.AcmeExternalAccountBindingArn, - }) + }, jsonx.V1()) delRec := postACMJSON(t, h, "DeleteAcmeExternalAccountBinding", string(delBody)) assert.Equal(t, http.StatusOK, delRec.Code) }, @@ -627,7 +637,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { createBody, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "RoleArn": "arn:aws:iam::000000000000:role/acme-role", - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeExternalAccountBinding", string(createBody)) require.Equal(t, http.StatusOK, createRec.Code) @@ -636,7 +646,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { AcmeExternalAccountBindingArn string `json:"AcmeExternalAccountBindingArn"` } `json:"ExternalAccountBinding"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) eabARN := createOut.ExternalAccountBinding.AcmeExternalAccountBindingArn delBody := `{"AcmeExternalAccountBindingArn":"` + epARN + @@ -646,7 +656,7 @@ func TestACMHandler_AcmeExternalAccountBindings(t *testing.T) { assert.Contains(t, delRec.Body.String(), "ValidationException") assert.NotContains(t, delRec.Body.String(), "ResourceNotFoundException") - descBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}) + descBody, _ := json.Marshal(map[string]string{"AcmeExternalAccountBindingArn": eabARN}, jsonx.V1()) descRec := postACMJSON(t, h, "DescribeAcmeExternalAccountBinding", string(descBody)) assert.Equal(t, http.StatusOK, descRec.Code, "unrelated EAB must be untouched") }, @@ -688,17 +698,17 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { "PrevalidationOptions": map[string]any{ "DnsPrevalidation": map[string]any{"HostedZoneId": "Z123456"}, }, - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createOut struct { AcmeDomainValidationArn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) descBody, _ := json.Marshal( - map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, + map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, jsonx.V1(), ) descRec := postACMJSON(t, h, "DescribeAcmeDomainValidation", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) @@ -714,7 +724,10 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { t.Helper() epARN := createTestAcmeEndpoint(t, h) - body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN, "DomainName": "dv2.example.com"}) + body, _ := json.Marshal( + map[string]string{"AcmeEndpointArn": epARN, "DomainName": "dv2.example.com"}, + jsonx.V1(), + ) rec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) assert.Contains(t, rec.Body.String(), "ValidationException") @@ -730,11 +743,11 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { "AcmeEndpointArn": epARN, "DomainName": "dv3.example.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) require.Equal(t, http.StatusOK, createRec.Code) - listBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + listBody, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) listRec := postACMJSON(t, h, "ListAcmeDomainValidations", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) assert.Contains(t, listRec.Body.String(), "dv3.example.com") @@ -750,26 +763,26 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { "AcmeEndpointArn": epARN, "DomainName": "dv4.example.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) require.Equal(t, http.StatusOK, createRec.Code) var createOut struct { AcmeDomainValidationArn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) updBody, _ := json.Marshal(map[string]any{ "AcmeDomainValidationArn": createOut.AcmeDomainValidationArn, "PrevalidationOptions": map[string]any{ "DnsPrevalidation": map[string]any{"HostedZoneId": "Znew"}, }, - }) + }, jsonx.V1()) updRec := postACMJSON(t, h, "UpdateAcmeDomainValidation", string(updBody)) require.Equal(t, http.StatusOK, updRec.Code, updRec.Body.String()) descBody, _ := json.Marshal( - map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, + map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, jsonx.V1(), ) descRec := postACMJSON(t, h, "DescribeAcmeDomainValidation", string(descBody)) assert.Contains(t, descRec.Body.String(), `"HostedZoneId":"Znew"`) @@ -785,17 +798,17 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { "AcmeEndpointArn": epARN, "DomainName": "dv5.example.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) require.Equal(t, http.StatusOK, createRec.Code) var createOut struct { AcmeDomainValidationArn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) delBody, _ := json.Marshal( - map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, + map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, jsonx.V1(), ) delRec := postACMJSON(t, h, "DeleteAcmeDomainValidation", string(delBody)) assert.Equal(t, http.StatusOK, delRec.Code) @@ -814,14 +827,14 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { "AcmeEndpointArn": epARN, "DomainName": "dv6.example.com", "PrevalidationOptions": map[string]any{"DnsPrevalidation": map[string]any{}}, - }) + }, jsonx.V1()) createRec := postACMJSON(t, h, "CreateAcmeDomainValidation", string(body)) require.Equal(t, http.StatusOK, createRec.Code) var createOut struct { AcmeDomainValidationArn string `json:"AcmeDomainValidationArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) delBody := `{"AcmeDomainValidationArn":"` + epARN + `/acme-domain-validation/nope"}` delRec := postACMJSON(t, h, "DeleteAcmeDomainValidation", delBody) @@ -830,7 +843,7 @@ func TestACMHandler_AcmeDomainValidations(t *testing.T) { assert.NotContains(t, delRec.Body.String(), "ResourceNotFoundException") descBody, _ := json.Marshal( - map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, + map[string]string{"AcmeDomainValidationArn": createOut.AcmeDomainValidationArn}, jsonx.V1(), ) descRec := postACMJSON(t, h, "DescribeAcmeDomainValidation", string(descBody)) assert.Equal(t, http.StatusOK, descRec.Code, "unrelated domain validation must be untouched") @@ -869,7 +882,7 @@ func TestACMHandler_AcmeAccounts_HonestlyEmpty(t *testing.T) { body, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "AccountUrl": "https://example/acct/1", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "DescribeAcmeAccount", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) assert.Contains(t, rec.Body.String(), "ResourceNotFoundException") @@ -880,7 +893,7 @@ func TestACMHandler_AcmeAccounts_HonestlyEmpty(t *testing.T) { run: func(t *testing.T, h *acm.Handler, epARN string) { t.Helper() - body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}) + body, _ := json.Marshal(map[string]string{"AcmeEndpointArn": epARN}, jsonx.V1()) rec := postACMJSON(t, h, "ListAcmeAccounts", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), `"AcmeAccounts":[]`) @@ -893,7 +906,7 @@ func TestACMHandler_AcmeAccounts_HonestlyEmpty(t *testing.T) { body, _ := json.Marshal(map[string]string{ "AcmeEndpointArn": epARN, "AccountUrl": "https://example/acct/1", - }) + }, jsonx.V1()) rec := postACMJSON(t, h, "RevokeAcmeAccount", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) assert.Contains(t, rec.Body.String(), "ResourceNotFoundException") diff --git a/services/acm/persistence.go b/services/acm/persistence.go index 7befa5450b..c892e21063 100644 --- a/services/acm/persistence.go +++ b/services/acm/persistence.go @@ -2,11 +2,13 @@ package acm import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -60,7 +62,7 @@ func buildPersistenceDTORegistry() (*store.Registry, *store.Table[regionalDTO[Ce // directly, as before. Timers are runtime-only and were never persisted; // Restore rebuilds them from certificate state (see below). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` IdempotencyMap map[string]map[string]certIdempotencyEntry `json:"idempotencyMap,omitempty"` AccountIdempotency map[string]map[string]accountIdempotencyEntry `json:"accountIdempotency,omitempty"` AccountConfig map[string]AccountConfig `json:"accountConfig"` @@ -246,7 +248,7 @@ func (b *InMemoryBackend) applyRestoredMaps(snap *backendSnapshot) { // restoreCerts rebuilds the "dirty" certs store.Table from snap's DTO table, // factored out of Restore to keep Restore's own cognitive complexity low. // Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreCerts(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreCerts(tables map[string]jsontext.Value) error { dtoReg, certDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("acm: restore snapshot cert table: %w", err) @@ -279,7 +281,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { snap := handlerSnapshot{ Tags: tagsMap, } - if err := json.Unmarshal(h.Backend.Snapshot(ctx), &snap.Backend); err != nil { + if err := json.Unmarshal(h.Backend.Snapshot(ctx), &snap.Backend, jsonx.V1()); err != nil { return nil } @@ -291,12 +293,12 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { func (h *Handler) Restore(ctx context.Context, data []byte) error { var snap handlerSnapshot - if err := json.Unmarshal(data, &snap); err != nil { + if err := json.Unmarshal(data, &snap, jsonx.V1()); err != nil { // Fall back to backend-only snapshot for backward compatibility. return h.Backend.Restore(ctx, data) } - backendData, err := json.Marshal(snap.Backend) + backendData, err := json.Marshal(snap.Backend, jsonx.V1()) if err != nil { return err } diff --git a/services/acm/persistence_test.go b/services/acm/persistence_test.go index a55eabd99f..7bb9816a2a 100644 --- a/services/acm/persistence_test.go +++ b/services/acm/persistence_test.go @@ -2,7 +2,7 @@ package acm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -271,10 +272,10 @@ func TestInMemoryBackend_RestoreVersionMismatch(t *testing.T) { require.NoError(t, err) var snapMap map[string]any - require.NoError(t, json.Unmarshal(donor.Snapshot(t.Context()), &snapMap)) + require.NoError(t, json.Unmarshal(donor.Snapshot(t.Context()), &snapMap, jsonx.V1())) tt.mutate(snapMap) - mutatedSnap, err := json.Marshal(snapMap) + mutatedSnap, err := json.Marshal(snapMap, jsonx.V1()) require.NoError(t, err) // The restore target starts with its own, different state so we @@ -337,12 +338,12 @@ func TestACMHandler_Persistence_Tags(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) addBody, err := json.Marshal(map[string]any{ "CertificateArn": reqOut.CertificateArn, "Tags": []map[string]string{{"Key": "team", "Value": "platform"}}, - }) + }, jsonx.V1()) require.NoError(t, err) addRec := postACMJSON(t, h, "AddTagsToCertificate", string(addBody)) @@ -354,7 +355,7 @@ func TestACMHandler_Persistence_Tags(t *testing.T) { freshH := newACMHandler() require.NoError(t, freshH.Restore(t.Context(), snap)) - listBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + listBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) listRec := postACMJSON(t, freshH, "ListTagsForCertificate", string(listBody)) @@ -363,7 +364,7 @@ func TestACMHandler_Persistence_Tags(t *testing.T) { var tagsOut struct { Tags []map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) tagMap := make(map[string]string, len(tagsOut.Tags)) for _, kv := range tagsOut.Tags { diff --git a/services/acm/request_certificate_realism_test.go b/services/acm/request_certificate_realism_test.go index 68a9693901..7c453196ce 100644 --- a/services/acm/request_certificate_realism_test.go +++ b/services/acm/request_certificate_realism_test.go @@ -1,13 +1,15 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestACMHandler_RequestCertificate_InputRealism(t *testing.T) { @@ -66,7 +68,7 @@ func TestACMHandler_RequestCertificate_InputRealism(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp.Type) assert.NotContains(t, errResp.Message, "Exception") }) @@ -83,7 +85,7 @@ func TestACMHandler_WildcardValidationRecordAndNotFound(t *testing.T) { var created struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec = postACMJSON(t, h, "DescribeCertificate", `{"CertificateArn":"`+created.CertificateArn+`"}`) require.Equal(t, http.StatusOK, rec.Code) diff --git a/services/acm/wire_field_additions_test.go b/services/acm/wire_field_additions_test.go index 8b8745cf98..dc92b8b760 100644 --- a/services/acm/wire_field_additions_test.go +++ b/services/acm/wire_field_additions_test.go @@ -1,7 +1,7 @@ package acm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/acm" ) @@ -258,7 +259,7 @@ func TestACMHandler_ListCertificates_SummaryHasCreatedAtAndInUse(t *testing.T) { InUse *bool `json:"InUse"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.CertificateSummaryList) summary := out.CertificateSummaryList[0] @@ -296,7 +297,7 @@ func TestACMHandler_ListCertificates_SummaryKeyUsages(t *testing.T) { ExtendedKeyUsages []string `json:"ExtendedKeyUsages"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.CertificateSummaryList) summary := out.CertificateSummaryList[0] @@ -320,9 +321,9 @@ func TestACMHandler_RenewCertificate_RenewalSummaryHasUpdatedAt(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - renewBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + renewBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) renewRec := postACMJSON(t, h, "RenewCertificate", string(renewBody)) @@ -341,7 +342,7 @@ func TestACMHandler_RenewCertificate_RenewalSummaryHasUpdatedAt(t *testing.T) { RenewalSummary renewalSummary `json:"RenewalSummary"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.NotEmpty(t, descOut.Certificate.RenewalSummary.RenewalStatus) assert.Positive(t, descOut.Certificate.RenewalSummary.UpdatedAt, "RenewalSummary.UpdatedAt must always be present on the wire") @@ -362,9 +363,9 @@ func TestACMHandler_RequestCertificate_ExportOption_RoundTrips(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) @@ -377,7 +378,7 @@ func TestACMHandler_RequestCertificate_ExportOption_RoundTrips(t *testing.T) { } `json:"Options"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "ENABLED", descOut.Certificate.Options.Export) } @@ -429,7 +430,7 @@ func TestACMHandler_RequestCertificate_ManagedBy(t *testing.T) { body, err := json.Marshal(map[string]string{ "DomainName": tt.domain, "ManagedBy": tt.managedBy, - }) + }, jsonx.V1()) require.NoError(t, err) reqRec := postACMJSON(t, h, "RequestCertificate", string(body)) @@ -442,9 +443,9 @@ func TestACMHandler_RequestCertificate_ManagedBy(t *testing.T) { var reqOut struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut)) + require.NoError(t, json.Unmarshal(reqRec.Body.Bytes(), &reqOut, jsonx.V1())) - descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}) + descBody, err := json.Marshal(map[string]string{"CertificateArn": reqOut.CertificateArn}, jsonx.V1()) require.NoError(t, err) descRec := postACMJSON(t, h, "DescribeCertificate", string(descBody)) @@ -455,7 +456,7 @@ func TestACMHandler_RequestCertificate_ManagedBy(t *testing.T) { ManagedBy string `json:"ManagedBy"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, tt.wantManagedBy, descOut.Certificate.ManagedBy) listRec := postACMJSON(t, h, "ListCertificates", `{}`) @@ -466,7 +467,7 @@ func TestACMHandler_RequestCertificate_ManagedBy(t *testing.T) { ManagedBy string `json:"ManagedBy"` } `json:"CertificateSummaryList"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.CertificateSummaryList, 1) assert.Equal(t, tt.wantManagedBy, listOut.CertificateSummaryList[0].ManagedBy) }) diff --git a/services/acmpca/handler.go b/services/acmpca/handler.go index 17aef1f156..e51f0d611f 100644 --- a/services/acmpca/handler.go +++ b/services/acmpca/handler.go @@ -3,7 +3,8 @@ package acmpca import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -118,8 +120,8 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } - var m map[string]json.RawMessage - if unmarshalErr := json.Unmarshal(body, &m); unmarshalErr != nil { + var m map[string]jsontext.Value + if unmarshalErr := json.Unmarshal(body, &m, jsonx.V1()); unmarshalErr != nil { return "" } @@ -151,7 +153,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // handleError writes a standardized error response back to the client. @@ -308,11 +310,11 @@ func decodeBase64Field(encoded, fieldName string, sentinel error) (string, error } // extractFirstResourceByKeys returns the first string resource found for the provided JSON field names. -func extractFirstResourceByKeys(body map[string]json.RawMessage, keys ...string) string { +func extractFirstResourceByKeys(body map[string]jsontext.Value, keys ...string) string { for _, key := range keys { if raw, ok := body[key]; ok { var resourceID string - if err := json.Unmarshal(raw, &resourceID); err == nil { + if err := json.Unmarshal(raw, &resourceID, jsonx.V1()); err == nil { return resourceID } } diff --git a/services/acmpca/handler_audit_reports.go b/services/acmpca/handler_audit_reports.go index ea3a1f9696..aad7957c78 100644 --- a/services/acmpca/handler_audit_reports.go +++ b/services/acmpca/handler_audit_reports.go @@ -2,7 +2,9 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createCertificateAuthorityAuditReportInput struct { @@ -30,7 +32,7 @@ type describeCertificateAuthorityAuditReportOutput struct { func (h *Handler) jsonCreateAuditReport(ctx context.Context, body []byte) (any, error) { var input createCertificateAuthorityAuditReportInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArgs } @@ -52,7 +54,7 @@ func (h *Handler) jsonCreateAuditReport(ctx context.Context, body []byte) (any, func (h *Handler) jsonDescribeAuditReport(ctx context.Context, body []byte) (any, error) { var input describeCertificateAuthorityAuditReportInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArgs } diff --git a/services/acmpca/handler_ca_policy.go b/services/acmpca/handler_ca_policy.go index b9497bcded..484b83aaa1 100644 --- a/services/acmpca/handler_ca_policy.go +++ b/services/acmpca/handler_ca_policy.go @@ -2,7 +2,9 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getPolicyInput struct { @@ -28,7 +30,7 @@ type deletePolicyOutput struct{} func (h *Handler) jsonGetPolicy(ctx context.Context, body []byte) (any, error) { var input getPolicyInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -42,7 +44,7 @@ func (h *Handler) jsonGetPolicy(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonPutPolicy(ctx context.Context, body []byte) (any, error) { var input putPolicyInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -55,7 +57,7 @@ func (h *Handler) jsonPutPolicy(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonDeletePolicy(ctx context.Context, body []byte) (any, error) { var input deletePolicyInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } diff --git a/services/acmpca/handler_certificate_authorities.go b/services/acmpca/handler_certificate_authorities.go index 3de412ebe4..43d13e2ace 100644 --- a/services/acmpca/handler_certificate_authorities.go +++ b/services/acmpca/handler_certificate_authorities.go @@ -2,8 +2,10 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -211,14 +213,14 @@ func (in *updateCertificateAuthorityInput) UnmarshalJSON(data []byte) error { type alias updateCertificateAuthorityInput var a alias - if err := json.Unmarshal(data, &a); err != nil { + if err := json.Unmarshal(data, &a, jsonx.V1()); err != nil { return err } *in = updateCertificateAuthorityInput(a) - var raw map[string]json.RawMessage - if err := json.Unmarshal(data, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return err } @@ -262,7 +264,7 @@ type restoreCertificateAuthorityOutput struct{} func (h *Handler) jsonCreateCA(ctx context.Context, body []byte) (any, error) { var input createCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArgs } @@ -302,7 +304,7 @@ func (h *Handler) jsonCreateCA(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonDescribeCA(ctx context.Context, body []byte) (any, error) { var input describeCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -316,7 +318,7 @@ func (h *Handler) jsonDescribeCA(ctx context.Context, body []byte) (any, error) func (h *Handler) jsonListCAs(ctx context.Context, body []byte) (any, error) { var input listCertificateAuthoritiesInput - _ = json.Unmarshal(body, &input) + _ = json.Unmarshal(body, &input, jsonx.V1()) p, err := h.Backend.ListCertificateAuthorities(ctx, input.NextToken, input.MaxResults, input.ResourceOwner) if err != nil { @@ -337,7 +339,7 @@ func (h *Handler) jsonListCAs(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonDeleteCA(ctx context.Context, body []byte) (any, error) { var input deleteCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -356,7 +358,7 @@ func (h *Handler) jsonDeleteCA(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonUpdateCA(ctx context.Context, body []byte) (any, error) { var input updateCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -376,7 +378,7 @@ func (h *Handler) jsonUpdateCA(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonGetCsr(ctx context.Context, body []byte) (any, error) { var input getCertificateAuthorityCsrInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -390,7 +392,7 @@ func (h *Handler) jsonGetCsr(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonImportCACert(ctx context.Context, body []byte) (any, error) { var input importCertificateAuthorityCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -418,7 +420,7 @@ func (h *Handler) jsonImportCACert(ctx context.Context, body []byte) (any, error func (h *Handler) jsonGetCACert(ctx context.Context, body []byte) (any, error) { var input getCertificateAuthorityCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -432,7 +434,7 @@ func (h *Handler) jsonGetCACert(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonRestoreCA(ctx context.Context, body []byte) (any, error) { var input restoreCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } diff --git a/services/acmpca/handler_certificate_authorities_test.go b/services/acmpca/handler_certificate_authorities_test.go index 6e5bd34dbc..614c43001a 100644 --- a/services/acmpca/handler_certificate_authorities_test.go +++ b/services/acmpca/handler_certificate_authorities_test.go @@ -2,7 +2,7 @@ package acmpca_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acmpca" ) @@ -568,7 +569,7 @@ func TestACMPCA_DescribeCertificateAuthority_OwnerAccount(t *testing.T) { var createOut struct { CertificateAuthorityArn string `json:"CertificateAuthorityArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) descRec := doACMPCARequest(t, h, "DescribeCertificateAuthority", map[string]any{ "CertificateAuthorityArn": createOut.CertificateAuthorityArn, @@ -580,7 +581,7 @@ func TestACMPCA_DescribeCertificateAuthority_OwnerAccount(t *testing.T) { OwnerAccount string `json:"OwnerAccount"` } `json:"CertificateAuthority"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, testAccountID, descOut.CertificateAuthority.OwnerAccount, "OwnerAccount must match the backend account ID") @@ -666,7 +667,7 @@ func TestACMPCA_DescribeCertificateAuthority_Serial_AfterActivation(t *testing.T Status string `json:"Status"` } `json:"CertificateAuthority"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Equal(t, "ACTIVE", descOut.CertificateAuthority.Status) assert.NotEmpty(t, descOut.CertificateAuthority.Serial, diff --git a/services/acmpca/handler_certificates.go b/services/acmpca/handler_certificates.go index e323d2b781..cb770c01a7 100644 --- a/services/acmpca/handler_certificates.go +++ b/services/acmpca/handler_certificates.go @@ -2,11 +2,13 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -169,7 +171,7 @@ type revokeCertificateOutput struct{} func (h *Handler) jsonIssueCert(ctx context.Context, body []byte) (any, error) { var input issueCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArgs } @@ -486,7 +488,7 @@ func decodeGeneralName(gn generalNameWire) (APIPassthroughSAN, error) { func (h *Handler) jsonGetCert(ctx context.Context, body []byte) (any, error) { var input getCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -511,7 +513,7 @@ func (h *Handler) jsonGetCert(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonRevokeCert(ctx context.Context, body []byte) (any, error) { var input revokeCertificateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } diff --git a/services/acmpca/handler_certificates_test.go b/services/acmpca/handler_certificates_test.go index 0938770db9..5cc64d4969 100644 --- a/services/acmpca/handler_certificates_test.go +++ b/services/acmpca/handler_certificates_test.go @@ -2,7 +2,7 @@ package acmpca_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acmpca" ) @@ -265,7 +266,7 @@ func TestACMPCA_IssueCertificate_EndDateValidity(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.CertificateArn, "IssueCertificate with END_DATE must return a CertificateArn") } @@ -325,7 +326,7 @@ func TestACMPCA_IssueCertificate_ValidityTypeAliases(t *testing.T) { var out struct { CertificateArn string `json:"CertificateArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.CertificateArn, "validity type %q must return CertificateArn", tt.validityType) }) @@ -433,7 +434,7 @@ func TestACMPCA_GetCertificate_ChainIncludesCAChain(t *testing.T) { Certificate string `json:"Certificate"` CertificateChain string `json:"CertificateChain"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.Certificate, "Certificate must be present") if tt.wantChain { diff --git a/services/acmpca/handler_permissions.go b/services/acmpca/handler_permissions.go index e4896ed35b..5065acee0d 100644 --- a/services/acmpca/handler_permissions.go +++ b/services/acmpca/handler_permissions.go @@ -2,7 +2,9 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listPermissionsInput struct { @@ -44,7 +46,7 @@ type deletePermissionOutput struct{} func (h *Handler) jsonListPermissions(ctx context.Context, body []byte) (any, error) { var input listPermissionsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -76,7 +78,7 @@ func (h *Handler) jsonListPermissions(ctx context.Context, body []byte) (any, er func (h *Handler) jsonCreatePermission(ctx context.Context, body []byte) (any, error) { var input createPermissionInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -95,7 +97,7 @@ func (h *Handler) jsonCreatePermission(ctx context.Context, body []byte) (any, e func (h *Handler) jsonDeletePermission(ctx context.Context, body []byte) (any, error) { var input deletePermissionInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } diff --git a/services/acmpca/handler_tags.go b/services/acmpca/handler_tags.go index de14c7829d..6ee0a8a95b 100644 --- a/services/acmpca/handler_tags.go +++ b/services/acmpca/handler_tags.go @@ -2,11 +2,12 @@ package acmpca import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -126,7 +127,7 @@ func (h *Handler) GetTagsForTest(resourceID string) []map[string]string { func (h *Handler) jsonTagCA(ctx context.Context, body []byte) (any, error) { var input tagCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -151,7 +152,7 @@ func (h *Handler) jsonTagCA(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonUntagCA(ctx context.Context, body []byte) (any, error) { var input untagCertificateAuthorityInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } @@ -171,7 +172,7 @@ func (h *Handler) jsonUntagCA(ctx context.Context, body []byte) (any, error) { func (h *Handler) jsonListTags(ctx context.Context, body []byte) (any, error) { var input listTagsInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, ErrInvalidArn } diff --git a/services/acmpca/handler_test.go b/services/acmpca/handler_test.go index 0f909722a7..e45fe59cc0 100644 --- a/services/acmpca/handler_test.go +++ b/services/acmpca/handler_test.go @@ -5,7 +5,7 @@ import ( "context" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/acmpca" ) @@ -49,7 +50,7 @@ func doACMPCARequest(t *testing.T, h *acmpca.Handler, op string, body map[string var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -71,7 +72,7 @@ func parseACMPCAResponse(t *testing.T, rec *httptest.ResponseRecorder) map[strin t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } @@ -135,7 +136,7 @@ func TestACMPCAHandler_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) diff --git a/services/acmpca/persistence.go b/services/acmpca/persistence.go index 1932972c45..6e608385e7 100644 --- a/services/acmpca/persistence.go +++ b/services/acmpca/persistence.go @@ -4,7 +4,7 @@ import ( "context" "crypto/ecdsa" "crypto/x509" - "encoding/json" + "encoding/json/jsontext" "encoding/pem" "errors" "fmt" @@ -108,7 +108,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Policies map[string]map[string]string `json:"policies"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -282,7 +282,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/amp/dataplane_status_http.go b/services/amp/dataplane_status_http.go index 8fce8f7509..3749cff544 100644 --- a/services/amp/dataplane_status_http.go +++ b/services/amp/dataplane_status_http.go @@ -2,7 +2,7 @@ package amp import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -173,7 +174,7 @@ func (h *Handler) postAlerts(c *echo.Context, wsID string) error { } var in []postableAlert - if jerr := json.Unmarshal(body, &in); jerr != nil || len(in) > maxPostedAlerts { + if jerr := json.Unmarshal(body, &in, jsonx.V1()); jerr != nil || len(in) > maxPostedAlerts { return promError(c, http.StatusBadRequest, "bad_data", "body must be a JSON array of alerts") } diff --git a/services/amp/dataplane_test.go b/services/amp/dataplane_test.go index 583ac4104c..b9d1e09350 100644 --- a/services/amp/dataplane_test.go +++ b/services/amp/dataplane_test.go @@ -1,7 +1,8 @@ package amp_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "math" "net/http" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amp" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -69,8 +71,8 @@ type promResult struct { Status string `json:"status"` ErrorType string `json:"errorType"` Data struct { - ResultType string `json:"resultType"` - Result json.RawMessage `json:"result"` + ResultType string `json:"resultType"` + Result jsontext.Value `json:"result"` } `json:"data"` } @@ -80,7 +82,7 @@ func (f *fixture) query(t *testing.T, ws, path string, vals url.Values) (httpRes r := f.do(t, http.MethodGet, "/workspaces/"+ws+"/api/v1/"+path+"?"+vals.Encode(), nil, nil) var pr promResult - _ = json.Unmarshal(r.body, &pr) + _ = json.Unmarshal(r.body, &pr, jsonx.V1()) return r, pr } diff --git a/services/amp/persistence.go b/services/amp/persistence.go index 4eb7e69389..b6084f54ad 100644 --- a/services/amp/persistence.go +++ b/services/amp/persistence.go @@ -2,7 +2,7 @@ package amp import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state, samples included. diff --git a/services/amp/rules_eval_test.go b/services/amp/rules_eval_test.go index 677bdc0350..f87148d87a 100644 --- a/services/amp/rules_eval_test.go +++ b/services/amp/rules_eval_test.go @@ -2,7 +2,8 @@ package amp_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "strconv" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amp" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -86,7 +88,7 @@ func (f *fixture) vector(t *testing.T, ws, q string) []vecSample { require.Equal(t, http.StatusOK, r.status, string(r.body)) var out []vecSample - require.NoError(t, json.Unmarshal(pr.Data.Result, &out)) + require.NoError(t, json.Unmarshal(pr.Data.Result, &out, jsonx.V1())) return out } @@ -98,11 +100,11 @@ func (f *fixture) apiData(t *testing.T, ws, path string, into any) { require.Equal(t, http.StatusOK, r.status, string(r.body)) var env struct { - Data json.RawMessage `json:"data"` + Data jsontext.Value `json:"data"` } - require.NoError(t, json.Unmarshal(r.body, &env)) - require.NoError(t, json.Unmarshal(env.Data, into)) + require.NoError(t, json.Unmarshal(r.body, &env, jsonx.V1())) + require.NoError(t, json.Unmarshal(env.Data, into, jsonx.V1())) } func TestRecordingRule(t *testing.T) { @@ -416,7 +418,7 @@ inhibit_rules: func (f *fixture) postAlerts(t *testing.T, ws string, alerts []map[string]any) { t.Helper() - body, err := json.Marshal(alerts) + body, err := json.Marshal(alerts, jsonx.V1()) require.NoError(t, err) path := "/workspaces/" + ws + "/alertmanager/api/v2/alerts" diff --git a/services/amp/series_json.go b/services/amp/series_json.go index 3e08c20655..e3bcc9f3c5 100644 --- a/services/amp/series_json.go +++ b/services/amp/series_json.go @@ -1,9 +1,10 @@ package amp import ( - "encoding/json" + "encoding/json/v2" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -20,7 +21,7 @@ type seriesWithStale struct { // MarshalJSON writes stale markers as timestamps because JSON cannot carry NaN; other series are unchanged. func (r SeriesRecord) MarshalJSON() ([]byte, error) { if !slices.ContainsFunc(r.Samples, func(s promql.Sample) bool { return promql.IsStale(s.V) }) { - return json.Marshal(seriesPlain(r)) + return json.Marshal(seriesPlain(r), jsonx.V1()) } out := seriesWithStale{seriesPlain: seriesPlain(r)} @@ -33,13 +34,13 @@ func (r SeriesRecord) MarshalJSON() ([]byte, error) { } } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } // UnmarshalJSON restores stale markers in time order. func (r *SeriesRecord) UnmarshalJSON(data []byte) error { var in seriesWithStale - if err := json.Unmarshal(data, &in); err != nil { + if err := json.Unmarshal(data, &in, jsonx.V1()); err != nil { return err } diff --git a/services/amp/validate.go b/services/amp/validate.go index 46bac8264f..5880a02314 100644 --- a/services/amp/validate.go +++ b/services/amp/validate.go @@ -1,12 +1,13 @@ package amp import ( - "encoding/json" + "encoding/json/v2" "regexp" "strings" "gopkg.in/yaml.v3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -300,7 +301,7 @@ func validatePolicy(doc string) error { Statement any `json:"Statement"` } - if err := json.Unmarshal([]byte(doc), &p); err != nil || p.Statement == nil { + if err := json.Unmarshal([]byte(doc), &p, jsonx.V1()); err != nil || p.Statement == nil { return cannotParse("policyDocument must be a JSON policy with a Statement") } diff --git a/services/amplify/handler_apps.go b/services/amplify/handler_apps.go index 5de9a74782..a3900c5ad2 100644 --- a/services/amplify/handler_apps.go +++ b/services/amplify/handler_apps.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -112,7 +113,7 @@ func (h *Handler) createApp(ctx context.Context, c *echo.Context) error { var input createAppRequest - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } @@ -181,7 +182,7 @@ func (h *Handler) updateApp(ctx context.Context, c *echo.Context, appID string) var input createAppRequest - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_apps_test.go b/services/amplify/handler_apps_test.go index 9dde2c51e8..2c869cda0d 100644 --- a/services/amplify/handler_apps_test.go +++ b/services/amplify/handler_apps_test.go @@ -1,13 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amplify" ) @@ -50,7 +51,7 @@ func TestHandler_CreateApp(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) app := resp["app"].(map[string]any) assert.Equal(t, tt.wantName, app["name"]) } @@ -143,7 +144,7 @@ func TestHandler_ListApps(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps := resp["apps"].([]any) assert.Len(t, apps, tt.wantCount) }) @@ -197,7 +198,7 @@ func TestHandler_ListAppsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps := resp["apps"].([]any) assert.Len(t, apps, tt.wantCount) @@ -248,7 +249,7 @@ func TestHandler_DeleteApp(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) app, ok := resp["app"].(map[string]any) require.True(t, ok, "expected an \"app\" key wrapping the deleted App, got body %s", rec.Body.String()) assert.Equal(t, appID, app["appId"]) @@ -313,7 +314,7 @@ func TestHandler_UpdateApp(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) app := resp["app"].(map[string]any) assert.Equal(t, tt.wantName, app["name"]) } diff --git a/services/amplify/handler_artifacts.go b/services/amplify/handler_artifacts.go index 71aa71e384..cf61aeb074 100644 --- a/services/amplify/handler_artifacts.go +++ b/services/amplify/handler_artifacts.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // generateAccessLogs handles POST /apps/{appId}/accesslogs. @@ -27,7 +28,7 @@ func (h *Handler) generateAccessLogs(ctx context.Context, c *echo.Context, appID EndTime string `json:"endTime"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_artifacts_test.go b/services/amplify/handler_artifacts_test.go index fddfdb0913..e4f165d0c3 100644 --- a/services/amplify/handler_artifacts_test.go +++ b/services/amplify/handler_artifacts_test.go @@ -1,12 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_GenerateAccessLogs verifies POST /apps/{appId}/accesslogs returns a log URL. @@ -32,7 +34,7 @@ func TestHandler_GenerateAccessLogs(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["logUrl"]) }) } diff --git a/services/amplify/handler_branches.go b/services/amplify/handler_branches.go index 1680b89d97..348403ed41 100644 --- a/services/amplify/handler_branches.go +++ b/services/amplify/handler_branches.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -110,7 +111,7 @@ func (h *Handler) createBranch(ctx context.Context, c *echo.Context, appID strin var input createBranchRequest - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } @@ -184,7 +185,7 @@ func (h *Handler) updateBranch(ctx context.Context, c *echo.Context, appID, bran var input createBranchRequest - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_branches_test.go b/services/amplify/handler_branches_test.go index bc7e33debf..4bf1388b54 100644 --- a/services/amplify/handler_branches_test.go +++ b/services/amplify/handler_branches_test.go @@ -1,13 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amplify" ) @@ -223,7 +224,7 @@ func TestHandler_ListBranchesPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) branches := resp["branches"].([]any) assert.Len(t, branches, tt.wantCount) @@ -277,7 +278,7 @@ func TestHandler_DeleteBranch(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) branch, ok := resp["branch"].(map[string]any) require.True( t, ok, "expected a \"branch\" key wrapping the deleted Branch, got body %s", rec.Body.String(), @@ -347,7 +348,7 @@ func TestHandler_UpdateBranch(t *testing.T) { if tt.wantDesc != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) br := resp["branch"].(map[string]any) assert.Equal(t, tt.wantDesc, br["description"]) } diff --git a/services/amplify/handler_deployments.go b/services/amplify/handler_deployments.go index 48671a8dd3..4b9bae020e 100644 --- a/services/amplify/handler_deployments.go +++ b/services/amplify/handler_deployments.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createDeployment handles POST /apps/{appId}/branches/{branchName}/deployments. @@ -26,7 +27,7 @@ func (h *Handler) createDeployment(ctx context.Context, c *echo.Context, appID, } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } } @@ -60,7 +61,7 @@ func (h *Handler) startDeployment(ctx context.Context, c *echo.Context, appID, b SourceURLType string `json:"sourceUrlType"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_deployments_test.go b/services/amplify/handler_deployments_test.go index 81263254bf..d06eb1872c 100644 --- a/services/amplify/handler_deployments_test.go +++ b/services/amplify/handler_deployments_test.go @@ -1,12 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_DeploymentOps verifies CreateDeployment and StartDeployment via the HTTP handler. @@ -34,7 +36,7 @@ func TestHandler_DeploymentOps(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp["jobId"].(string) assert.NotEmpty(t, jobID) assert.NotNil(t, createResp["fileUploadUrls"]) @@ -45,7 +47,7 @@ func TestHandler_DeploymentOps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.NotNil(t, startResp["jobSummary"]) }) } diff --git a/services/amplify/handler_domains.go b/services/amplify/handler_domains.go index 9809103d60..984fdda9fb 100644 --- a/services/amplify/handler_domains.go +++ b/services/amplify/handler_domains.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSON response key used by the domain association handlers. @@ -79,7 +80,7 @@ func (h *Handler) createDomainAssociation(ctx context.Context, c *echo.Context, EnableAutoSubDomain bool `json:"enableAutoSubDomain"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } @@ -163,7 +164,7 @@ func (h *Handler) updateDomainAssociation( AutoSubDomainCreationPatterns []string `json:"autoSubDomainCreationPatterns"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_domains_test.go b/services/amplify/handler_domains_test.go index b5954ad67f..33f90a1c85 100644 --- a/services/amplify/handler_domains_test.go +++ b/services/amplify/handler_domains_test.go @@ -1,12 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_DomainAssociationCRUD verifies domain association lifecycle via the HTTP handler. @@ -34,7 +36,7 @@ func TestHandler_DomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) da := createResp["domainAssociation"].(map[string]any) assert.Equal(t, "example.com", da["domainName"]) @@ -47,7 +49,7 @@ func TestHandler_DomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["domainAssociations"].([]any), 1) // Update. @@ -56,7 +58,7 @@ func TestHandler_DomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) updated := updateResp["domainAssociation"].(map[string]any) assert.Equal(t, true, updated["enableAutoSubDomain"]) diff --git a/services/amplify/handler_environments.go b/services/amplify/handler_environments.go index 02550e8546..3336085415 100644 --- a/services/amplify/handler_environments.go +++ b/services/amplify/handler_environments.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSON response key used by the backend environment handlers. @@ -54,7 +55,7 @@ func (h *Handler) createBackendEnvironment(ctx context.Context, c *echo.Context, DeploymentArtifacts string `json:"deploymentArtifacts"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_environments_test.go b/services/amplify/handler_environments_test.go index f48278b017..ddbc497f22 100644 --- a/services/amplify/handler_environments_test.go +++ b/services/amplify/handler_environments_test.go @@ -1,12 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_BackendEnvironmentCRUD verifies backend environment lifecycle via the HTTP handler. @@ -32,7 +34,7 @@ func TestHandler_BackendEnvironmentCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) be := createResp["backendEnvironment"].(map[string]any) assert.Equal(t, "prod", be["environmentName"]) @@ -45,7 +47,7 @@ func TestHandler_BackendEnvironmentCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["backendEnvironments"].([]any), 1) // Delete. diff --git a/services/amplify/handler_jobs.go b/services/amplify/handler_jobs.go index 51f64b1ec1..21971ec33d 100644 --- a/services/amplify/handler_jobs.go +++ b/services/amplify/handler_jobs.go @@ -2,13 +2,14 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSON response key used by the job handlers (and by handler_deployments.go, @@ -58,7 +59,7 @@ func (h *Handler) startJob(ctx context.Context, c *echo.Context, appID, branchNa CommitTime float64 `json:"commitTime"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_jobs_test.go b/services/amplify/handler_jobs_test.go index 2052c0bf6a..73d8c7a247 100644 --- a/services/amplify/handler_jobs_test.go +++ b/services/amplify/handler_jobs_test.go @@ -1,7 +1,7 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amplify" ) @@ -38,7 +39,7 @@ func TestHandler_JobLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) summary := startResp["jobSummary"].(map[string]any) jobID := summary["jobId"].(string) assert.NotEmpty(t, jobID) @@ -48,7 +49,7 @@ func TestHandler_JobLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["jobSummaries"].([]any), 1) // Get job. @@ -56,7 +57,7 @@ func TestHandler_JobLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) job := getResp["job"].(map[string]any) assert.NotNil(t, job["summary"]) assert.NotNil(t, job["steps"]) @@ -109,7 +110,7 @@ func TestHandler_ListJobs_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["jobSummaries"].([]any), tt.wantCount) if tt.wantNextToken { @@ -149,7 +150,7 @@ func TestHandler_StartJob_ResponseShape(t *testing.T) { } `json:"jobSummary"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload, jsonx.V1())) assert.NotEmpty(t, payload.JobSummary.JobID) assert.NotEmpty(t, payload.JobSummary.JobARN) assert.Contains(t, payload.JobSummary.JobARN, "arn:aws:amplify:") @@ -174,7 +175,7 @@ func TestHandler_GetJob_Steps(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["jobSummary"].(map[string]any)["jobId"].(string) type step struct { @@ -195,7 +196,7 @@ func TestHandler_GetJob_Steps(t *testing.T) { Steps []step `json:"steps"` } `json:"job"` } - require.NoError(t, json.Unmarshal(stepsRec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(stepsRec.Body.Bytes(), &payload, jsonx.V1())) return payload.Job.Steps } diff --git a/services/amplify/handler_tags.go b/services/amplify/handler_tags.go index c1a7c4fba5..466eb7f546 100644 --- a/services/amplify/handler_tags.go +++ b/services/amplify/handler_tags.go @@ -2,7 +2,7 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleTags dispatches GET/POST/DELETE /tags/{resourceArn}. @@ -49,7 +50,7 @@ func (h *Handler) tagResource(ctx context.Context, c *echo.Context, resourceARN Tags map[string]string `json:"tags"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_test.go b/services/amplify/handler_test.go index cc3b3510ca..ff5faa9539 100644 --- a/services/amplify/handler_test.go +++ b/services/amplify/handler_test.go @@ -2,7 +2,7 @@ package amplify_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amplify" ) @@ -34,7 +35,7 @@ func doRequest( var buf *bytes.Buffer if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) buf = bytes.NewBuffer(b) } else { @@ -422,7 +423,7 @@ func TestHandler_ErrorResponseShape(t *testing.T) { var payload map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload, jsonx.V1())) assert.Equal(t, tt.wantType, payload["__type"]) assert.NotEmpty(t, payload["message"]) }) diff --git a/services/amplify/handler_webhooks.go b/services/amplify/handler_webhooks.go index cce179fef6..3cbbf7557a 100644 --- a/services/amplify/handler_webhooks.go +++ b/services/amplify/handler_webhooks.go @@ -2,12 +2,13 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // JSON response key used by the webhook handlers. @@ -51,7 +52,7 @@ func (h *Handler) createWebhook(ctx context.Context, c *echo.Context, appID stri Description string `json:"description"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } @@ -106,7 +107,7 @@ func (h *Handler) updateWebhook(ctx context.Context, c *echo.Context, webhookID BranchName string `json:"branchName"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return amplifyErrorJSON(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/amplify/handler_webhooks_test.go b/services/amplify/handler_webhooks_test.go index 738494a93a..33f0400f1c 100644 --- a/services/amplify/handler_webhooks_test.go +++ b/services/amplify/handler_webhooks_test.go @@ -1,12 +1,14 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_WebhookCRUD verifies create/get/list/update/delete webhook lifecycle. @@ -34,7 +36,7 @@ func TestHandler_WebhookCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) wh := createResp["webhook"].(map[string]any) webhookID := wh["webhookId"].(string) assert.NotEmpty(t, webhookID) @@ -48,7 +50,7 @@ func TestHandler_WebhookCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["webhooks"].([]any), 1) // Update. @@ -57,7 +59,7 @@ func TestHandler_WebhookCRUD(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) updated := updateResp["webhook"].(map[string]any) assert.Equal(t, "updated", updated["description"]) diff --git a/services/amplify/persistence.go b/services/amplify/persistence.go index 9d717ba583..46b4e1cb0a 100644 --- a/services/amplify/persistence.go +++ b/services/amplify/persistence.go @@ -2,7 +2,7 @@ package amplify import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -34,10 +34,10 @@ const amplifySnapshotVersion = 1 // store.Table.Restore from the webhooks table's AppID field. So Tables is // the entirety of the persisted state besides AccountID/Region. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. It implements diff --git a/services/amplify/sent_keys.go b/services/amplify/sent_keys.go index 2a9f6c6eec..993e4d36b3 100644 --- a/services/amplify/sent_keys.go +++ b/services/amplify/sent_keys.go @@ -1,12 +1,18 @@ package amplify -import "encoding/json" +import ( + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // sentKeys reports which top-level JSON members a request body carried, so an // update can tell an explicit empty value or false from an omitted member. func sentKeys(body []byte) map[string]bool { - var raw map[string]json.RawMessage - if err := json.Unmarshal(body, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(body, &raw, jsonx.V1()); err != nil { return nil } diff --git a/services/amplify/wire_shape_test.go b/services/amplify/wire_shape_test.go index 8eb49b055d..506f0774a9 100644 --- a/services/amplify/wire_shape_test.go +++ b/services/amplify/wire_shape_test.go @@ -1,7 +1,7 @@ package amplify_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amplify" ) @@ -163,7 +164,7 @@ func TestGetBackendEnvironment_NoFabricatedAppID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) be, ok := resp["backendEnvironment"].(map[string]any) require.True(t, ok) @@ -205,7 +206,7 @@ func TestGetDomainAssociation_NoFabricatedAppID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) da, ok := resp["domainAssociation"].(map[string]any) require.True(t, ok) diff --git a/services/apigateway/api_keys_test.go b/services/apigateway/api_keys_test.go index a6b6faa7b4..7b385bcd52 100644 --- a/services/apigateway/api_keys_test.go +++ b/services/apigateway/api_keys_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -23,7 +25,7 @@ func TestAPIGW_APIKeys(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "expected 2xx for CreateAPIKey") var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) keyID, _ := createResp["id"].(string) require.NotEmpty(t, keyID) @@ -91,7 +93,7 @@ func TestGetApiKey_ValueHiddenByDefault(t *testing.T) { require.True(t, createRec.Code >= 200 && createRec.Code < 300) var createResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) keyID, _ := createResp["id"].(string) require.NotEmpty(t, keyID) @@ -99,7 +101,7 @@ func TestGetApiKey_ValueHiddenByDefault(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) if tt.wantValue { assert.NotEmpty(t, resp["value"], "value must be present when includeValue=true") @@ -154,7 +156,7 @@ func TestGetApiKeys_ValueHiddenByDefault(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, ok := resp["item"].([]any) require.True(t, ok && len(items) > 0, "expected at least one key in response") @@ -207,7 +209,7 @@ func TestPatchOps_UpdateApiKey(t *testing.T) { require.True(t, createRec.Code >= 200 && createRec.Code < 300) var createResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) keyID, _ := createResp["id"].(string) require.NotEmpty(t, keyID) @@ -239,7 +241,7 @@ func TestApiKey_CustomerID(t *testing.T) { require.True(t, createRec.Code >= 200 && createRec.Code < 300) var createResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) keyID, _ := createResp["id"].(string) require.NotEmpty(t, keyID) assert.Equal(t, "mp-cust-123", createResp["customerId"], @@ -308,7 +310,7 @@ func TestUpdateApiKey(t *testing.T) { createRec := postWithHandler(t, handler, e, "CreateApiKey", `{"name":"orig-key","enabled":true}`) require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) keyID := createResp["id"].(string) lookupID := keyID diff --git a/services/apigateway/authorizers_test.go b/services/apigateway/authorizers_test.go index be539dd5b2..247eb73553 100644 --- a/services/apigateway/authorizers_test.go +++ b/services/apigateway/authorizers_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -76,7 +77,7 @@ func TestTestInvokeAuthorizer(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "user-1", resp["principalId"]) } }) diff --git a/services/apigateway/client_certificates_test.go b/services/apigateway/client_certificates_test.go index a7bef08235..9be47848f0 100644 --- a/services/apigateway/client_certificates_test.go +++ b/services/apigateway/client_certificates_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -26,7 +27,7 @@ func TestAPIGateway_UpdateClientCertificate_RESTRoute(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "updated desc", resp["description"]) } @@ -81,7 +82,7 @@ func TestClientCertificates(t *testing.T) { assert.Equal(t, tt.wantCreateCode, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["clientCertificateId"].(string) // Get @@ -98,7 +99,7 @@ func TestClientCertificates(t *testing.T) { listRec := postWithHandler(t, handler, e, "GetClientCertificates", `{}`) assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.GreaterOrEqual(t, len(listResp["item"].([]any)), tt.wantListMinLen) } diff --git a/services/apigateway/deployments_test.go b/services/apigateway/deployments_test.go index 40c7e7f0ea..229139fe43 100644 --- a/services/apigateway/deployments_test.go +++ b/services/apigateway/deployments_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -29,7 +31,7 @@ func TestDeleteDeployment_StageProtection(t *testing.T) { "create deployment: %d %s", rec.Code, rec.Body.String()) var depl map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &depl)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &depl, jsonx.V1())) deplID, _ := depl["id"].(string) require.NotEmpty(t, deplID) @@ -58,7 +60,7 @@ func TestDeleteDeployment_Unreferenced(t *testing.T) { "create deployment: %d %s", rec.Code, rec.Body.String()) var depl map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &depl)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &depl, jsonx.V1())) deplID, _ := depl["id"].(string) require.NotEmpty(t, deplID) @@ -104,7 +106,7 @@ func TestCreateDeployment_StageDescription(t *testing.T) { require.True(t, createAPIRec.Code >= 200 && createAPIRec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(createAPIRec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createAPIRec.Body), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -117,7 +119,7 @@ func TestCreateDeployment_StageDescription(t *testing.T) { require.True(t, stageRec.Code >= 200 && stageRec.Code < 300) var stage map[string]any - require.NoError(t, json.NewDecoder(stageRec.Body).Decode(&stage)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stageRec.Body), &stage, jsonx.V1())) // JSON omitempty means empty description is absent (nil), not "". got, _ := stage["description"].(string) assert.Equal(t, tt.wantDescription, got) @@ -163,13 +165,13 @@ func TestCreateDeployment_StageVariables(t *testing.T) { require.True(t, createAPIRec.Code >= 200 && createAPIRec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(createAPIRec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createAPIRec.Body), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) var deplBody string if tt.variables != nil { - varsJSON, _ := json.Marshal(tt.variables) + varsJSON, _ := json.Marshal(tt.variables, jsonx.V1()) deplBody = `{"stageName":"prod","variables":` + string(varsJSON) + `}` } else { deplBody = `{"stageName":"prod"}` @@ -181,7 +183,7 @@ func TestCreateDeployment_StageVariables(t *testing.T) { require.True(t, stageRec.Code >= 200 && stageRec.Code < 300) var stage map[string]any - require.NoError(t, json.NewDecoder(stageRec.Body).Decode(&stage)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stageRec.Body), &stage, jsonx.V1())) vars, _ := stage["variables"].(map[string]any) assert.Len(t, vars, tt.wantVarsLen) @@ -235,7 +237,7 @@ func TestUpdateDeployment(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.description, resp["description"]) } }) @@ -272,13 +274,13 @@ func TestHandler_GetAndDeleteDeployment(t *testing.T) { createRec := postWithHandler(t, h, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) deplRec := postWithHandler(t, h, e, "CreateDeployment", fmt.Sprintf(`{"restApiId":%q,"stageName":"prod","description":""}`, apiID)) var depl map[string]any - require.NoError(t, json.Unmarshal(deplRec.Body.Bytes(), &depl)) + require.NoError(t, json.Unmarshal(deplRec.Body.Bytes(), &depl, jsonx.V1())) deplID := depl["id"].(string) if tt.action == "DeleteDeployment" { diff --git a/services/apigateway/documentation_test.go b/services/apigateway/documentation_test.go index 0eb635f8e1..defacc04a5 100644 --- a/services/apigateway/documentation_test.go +++ b/services/apigateway/documentation_test.go @@ -1,13 +1,15 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDocumentationPart_CRUD tests GetDocumentationPart, GetDocumentationParts, DeleteDocumentationPart. @@ -61,7 +63,7 @@ func TestDocumentationPart_CRUD(t *testing.T) { fmt.Sprintf(`{"restApiId":%q}`, apiID)) assert.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["item"].([]any), tt.listWantLen) } @@ -130,7 +132,7 @@ func TestDocumentationVersion_CRUD(t *testing.T) { fmt.Sprintf(`{"restApiId":%q}`, apiID)) assert.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["item"].([]any), tt.listWantLen) } diff --git a/services/apigateway/domain_names_test.go b/services/apigateway/domain_names_test.go index b67aeb170f..5446fb5cd6 100644 --- a/services/apigateway/domain_names_test.go +++ b/services/apigateway/domain_names_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -26,7 +28,7 @@ func TestAPIGW_DomainNames(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "expected 2xx") var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -77,7 +79,7 @@ func TestAPIGateway_DomainNameAccessAssociation_RESTLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) arn, _ := created["domainNameAccessAssociationArn"].(string) require.NotEmpty(t, arn, "create must return a real association ARN") @@ -85,7 +87,7 @@ func TestAPIGateway_DomainNameAccessAssociation_RESTLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var list map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list, jsonx.V1())) items, _ := list["item"].([]any) require.Len(t, items, 1, "list must reflect the created association, not a hardcoded empty list") @@ -94,7 +96,7 @@ func TestAPIGateway_DomainNameAccessAssociation_RESTLifecycle(t *testing.T) { listAfterDeleteRec := restCall(t, h, http.MethodGet, "/domainnameaccessassociations", "", "") var listAfter map[string]any - require.NoError(t, json.Unmarshal(listAfterDeleteRec.Body.Bytes(), &listAfter)) + require.NoError(t, json.Unmarshal(listAfterDeleteRec.Body.Bytes(), &listAfter, jsonx.V1())) itemsAfter, _ := listAfter["item"].([]any) assert.Empty(t, itemsAfter) @@ -234,7 +236,7 @@ func TestHandlerDomainName_SecurityPolicy_RoundTrip(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "TLS_1_2", resp["securityPolicy"]) assert.NotEmpty(t, resp["regionalDomainName"]) assert.NotEmpty(t, resp["distributionDomainName"]) diff --git a/services/apigateway/error_envelope_test.go b/services/apigateway/error_envelope_test.go index 6c3ef72fe2..7343a120e1 100644 --- a/services/apigateway/error_envelope_test.go +++ b/services/apigateway/error_envelope_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/apigateway" @@ -86,7 +87,7 @@ func TestErrorEnvelope_GetRestApiNotFoundDecodesToTypedError(t *testing.T) { require.NoError(t, err) var envelope map[string]any - require.NoError(t, json.Unmarshal(raw, &envelope)) + require.NoError(t, json.Unmarshal(raw, &envelope, jsonx.V1())) require.Equal(t, "NotFoundException", envelope["__type"], "raw body must carry __type key restjson.GetErrorInfo's fallback reads: %s", raw) diff --git a/services/apigateway/export_test.go b/services/apigateway/export_test.go index 0df8b60323..ef349f3e89 100644 --- a/services/apigateway/export_test.go +++ b/services/apigateway/export_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -28,7 +29,7 @@ func TestAPIGateway_GetExport_RESTRoute(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var doc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1())) assert.Equal(t, "3.0.1", doc["openapi"]) } @@ -74,7 +75,7 @@ func TestAPIGateway_GetExport_HeadersNotBody_RealClient(t *testing.T) { require.NotEmpty(t, out.Body, "Body must round-trip as raw bytes, not a base64 JSON field") var doc map[string]any - require.NoError(t, json.Unmarshal(out.Body, &doc)) + require.NoError(t, json.Unmarshal(out.Body, &doc, jsonx.V1())) assert.Equal(t, "3.0.1", doc["openapi"]) } diff --git a/services/apigateway/gateway_responses_test.go b/services/apigateway/gateway_responses_test.go index 1a27a49987..1dbe7d18b2 100644 --- a/services/apigateway/gateway_responses_test.go +++ b/services/apigateway/gateway_responses_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -33,7 +34,7 @@ func TestAPIGateway_UpdateGatewayResponse_RESTRoute(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "404", resp["statusCode"]) } @@ -111,7 +112,7 @@ func TestGatewayResponses(t *testing.T) { if tt.wantDefaultResp { var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["defaultResponse"]) } } @@ -132,7 +133,7 @@ func TestGatewayResponses(t *testing.T) { fmt.Sprintf(`{"restApiId":%q,"responseType":%q}`, apiID, tt.responseType)) assert.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) // After delete, should revert to default assert.Equal(t, true, resp["defaultResponse"]) } @@ -166,7 +167,7 @@ func TestDeleteRestAPI_ClearsGatewayResponses(t *testing.T) { } `json:"gatewayResponses"` } `json:"tables"` } - require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded)) + require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded, jsonx.V1())) for _, gr := range decoded.Tables.GatewayResponses { assert.NotEqual(t, api.ID, gr.RestAPIID, "a deleted REST API's gateway responses must not survive in the persisted snapshot") diff --git a/services/apigateway/handler.go b/services/apigateway/handler.go index 9fee815216..5ca824ccc5 100644 --- a/services/apigateway/handler.go +++ b/services/apigateway/handler.go @@ -3,7 +3,8 @@ package apigateway import ( "context" "crypto/rsa" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -23,6 +24,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/executeapi" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -446,7 +448,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -515,7 +517,7 @@ func (h *Handler) Handler() echo.HandlerFunc { func writeJSONProtocolDispatchError(c *echo.Context, status int, errType, message string) error { c.Response().Header().Set(headerContentType, "application/x-amz-json-1.1") - payload, err := json.Marshal(ErrorResponse{Type: errType, Message: message}) + payload, err := json.Marshal(ErrorResponse{Type: errType, Message: message}, jsonx.V1()) if err != nil { return err } @@ -715,7 +717,7 @@ func detectImportRESTAPI( Body: body, FailOnWarnings: query.Get("failonwarnings") == litTrue, } - encoded, err := json.Marshal(in) + encoded, err := json.Marshal(in, jsonx.V1()) if err != nil { return "", nil, false } @@ -728,7 +730,7 @@ func detectImportRESTAPI( Body: body, Format: query.Get("format"), } - encoded, err := json.Marshal(in) + encoded, err := json.Marshal(in, jsonx.V1()) if err != nil { return "", nil, false } @@ -741,7 +743,7 @@ func detectImportRESTAPI( FailOnWarnings: query.Get("failonwarnings") == litTrue, Body: body, } - encoded, err := json.Marshal(in) + encoded, err := json.Marshal(in, jsonx.V1()) if err != nil { return "", nil, false } @@ -759,28 +761,28 @@ func detectImportRESTAPI( // must be injected as a bare JSON number, not a quoted string, or a real // client's Limit always 500s on json.Unmarshal. func injectJSONFieldAPIGW(body []byte, key, value string) []byte { - var m map[string]json.RawMessage + var m map[string]jsontext.Value if len(body) > 0 { - if err := json.Unmarshal(body, &m); err != nil { - m = make(map[string]json.RawMessage) + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { + m = make(map[string]jsontext.Value) } } else { - m = make(map[string]json.RawMessage) + m = make(map[string]jsontext.Value) } if key == keyLimit { if n, err := strconv.Atoi(value); err == nil { - m[key] = json.RawMessage(strconv.Itoa(n)) - result, _ := json.Marshal(m) + m[key] = jsontext.Value(strconv.Itoa(n)) + result, _ := json.Marshal(m, jsonx.V1()) return result } } - quoted, _ := json.Marshal(value) - m[key] = json.RawMessage(quoted) + quoted, _ := json.Marshal(value, jsonx.V1()) + m[key] = jsontext.Value(quoted) - result, _ := json.Marshal(m) + result, _ := json.Marshal(m, jsonx.V1()) return result } @@ -790,19 +792,19 @@ func injectJSONFieldAPIGW(body []byte, key, value string) []byte { // (encoder.AddQuery in a loop) rather than a single scalar -- e.g. tagKeys // (UntagResource, serializers.go:9284). func injectJSONArrayFieldAPIGW(body []byte, key string, values []string) []byte { - var m map[string]json.RawMessage + var m map[string]jsontext.Value if len(body) > 0 { - if err := json.Unmarshal(body, &m); err != nil { - m = make(map[string]json.RawMessage) + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { + m = make(map[string]jsontext.Value) } } else { - m = make(map[string]json.RawMessage) + m = make(map[string]jsontext.Value) } - encoded, _ := json.Marshal(values) + encoded, _ := json.Marshal(values, jsonx.V1()) m[key] = encoded - result, _ := json.Marshal(m) + result, _ := json.Marshal(m, jsonx.V1()) return result } @@ -984,7 +986,7 @@ func (h *Handler) dispatch( return statusCode, nil, raw, nil } - encoded, err := json.Marshal(response) + encoded, err := json.Marshal(response, jsonx.V1()) if err != nil { return 0, nil, nil, err } @@ -1047,7 +1049,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin Message: strings.TrimPrefix(reqErr.Error(), errType+": "), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/apigateway/handler_account.go b/services/apigateway/handler_account.go index e637447b6f..c43d1867fb 100644 --- a/services/apigateway/handler_account.go +++ b/services/apigateway/handler_account.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseAPIGWAccountPath handles /account paths. @@ -32,7 +34,7 @@ func (h *Handler) accountActions() map[string]actionFn { }, opUpdateAccount: func(b []byte) (int, any, error) { var input UpdateAccountInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateAccount(input) diff --git a/services/apigateway/handler_api_keys.go b/services/apigateway/handler_api_keys.go index eddb564e28..0eac95800d 100644 --- a/services/apigateway/handler_api_keys.go +++ b/services/apigateway/handler_api_keys.go @@ -1,10 +1,12 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getAPIKeyInput struct { @@ -56,7 +58,7 @@ func parseAPIGWAPIKeysPath(method string, segs []string, n int, query url.Values func (h *Handler) getAPIKeyAction(b []byte) (int, any, error) { var input getAPIKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } key, err := h.Backend.GetAPIKey(input.APIKeyID) @@ -72,7 +74,7 @@ func (h *Handler) getAPIKeyAction(b []byte) (int, any, error) { func (h *Handler) getAPIKeysAction(b []byte) (int, any, error) { var input getAPIKeysPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } keys, position, err := h.fetchAPIKeys(input) @@ -135,7 +137,7 @@ func filterAPIKeys(keys []APIKey, customerID, nameQuery string) []APIKey { func (h *Handler) deleteAPIKeyAction(b []byte) (int, any, error) { var input deleteAPIKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteAPIKey(input.APIKeyID); err != nil { @@ -150,7 +152,7 @@ func (h *Handler) apiKeyActions() map[string]actionFn { return map[string]actionFn{ opCreateAPIKey: func(b []byte) (int, any, error) { var input CreateAPIKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -166,7 +168,7 @@ func (h *Handler) apiKeyActions() map[string]actionFn { opDeleteAPIKey: h.deleteAPIKeyAction, opUpdateAPIKey: func(b []byte) (int, any, error) { var input updateAPIKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } key, err := h.Backend.UpdateAPIKey(input.APIKeyID, input.UpdateAPIKeyInput) diff --git a/services/apigateway/handler_authorizers.go b/services/apigateway/handler_authorizers.go index fcafe0c71b..222e02a6d1 100644 --- a/services/apigateway/handler_authorizers.go +++ b/services/apigateway/handler_authorizers.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createAuthorizerInput struct { @@ -67,7 +69,7 @@ func (h *Handler) authorizerActions() map[string]actionFn { func (h *Handler) createAuthorizerAction(b []byte) (int, any, error) { var input createAuthorizerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ttl := defaultAuthorizerTTLSeconds @@ -94,7 +96,7 @@ func (h *Handler) createAuthorizerAction(b []byte) (int, any, error) { func (h *Handler) getAuthorizerAction(b []byte) (int, any, error) { var input getAuthorizerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } auth, err := h.Backend.GetAuthorizer(input.RestAPIID, input.AuthorizerID) @@ -107,7 +109,7 @@ func (h *Handler) getAuthorizerAction(b []byte) (int, any, error) { func (h *Handler) getAuthorizersAction(b []byte) (int, any, error) { var input getAuthorizersInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } auths, err := h.Backend.GetAuthorizers(input.RestAPIID) @@ -127,7 +129,7 @@ func (h *Handler) getAuthorizersAction(b []byte) (int, any, error) { func (h *Handler) updateAuthorizerAction(b []byte) (int, any, error) { var input updateAuthorizerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } auth, err := h.Backend.UpdateAuthorizer(input.RestAPIID, input.AuthorizerID, UpdateAuthorizerInput{ @@ -150,7 +152,7 @@ func (h *Handler) updateAuthorizerAction(b []byte) (int, any, error) { func (h *Handler) deleteAuthorizerAction(b []byte) (int, any, error) { var input deleteAuthorizerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteAuthorizer(input.RestAPIID, input.AuthorizerID); err != nil { @@ -162,7 +164,7 @@ func (h *Handler) deleteAuthorizerAction(b []byte) (int, any, error) { func (h *Handler) testInvokeAuthorizerAction(b []byte) (int, any, error) { var input TestInvokeAuthorizerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } auth, err := h.Backend.GetAuthorizer(input.RestAPIID, input.AuthorizerID) diff --git a/services/apigateway/handler_base_path_mappings.go b/services/apigateway/handler_base_path_mappings.go index 7fd37a2132..8568bee45b 100644 --- a/services/apigateway/handler_base_path_mappings.go +++ b/services/apigateway/handler_base_path_mappings.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getBasePathMappingInput struct { @@ -50,7 +52,7 @@ func (h *Handler) basePathMappingActions() map[string]actionFn { func (h *Handler) createBasePathMappingAction(b []byte) (int, any, error) { var input CreateBasePathMappingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -64,7 +66,7 @@ func (h *Handler) createBasePathMappingAction(b []byte) (int, any, error) { func (h *Handler) getBasePathMappingAction(b []byte) (int, any, error) { var input getBasePathMappingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } bpm, err := h.Backend.GetBasePathMapping(input.DomainName, input.BasePath) @@ -77,7 +79,7 @@ func (h *Handler) getBasePathMappingAction(b []byte) (int, any, error) { func (h *Handler) getBasePathMappingsAction(b []byte) (int, any, error) { var input getBasePathMappingsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } bpms, err := h.Backend.GetBasePathMappings(input.DomainName) @@ -98,7 +100,7 @@ func (h *Handler) getBasePathMappingsAction(b []byte) (int, any, error) { func (h *Handler) deleteBasePathMappingAction(b []byte) (int, any, error) { var input deleteBasePathMappingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteBasePathMapping(input.DomainName, input.BasePath); err != nil { @@ -110,7 +112,7 @@ func (h *Handler) deleteBasePathMappingAction(b []byte) (int, any, error) { func (h *Handler) updateBasePathMappingAction(b []byte) (int, any, error) { var input UpdateBasePathMappingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateBasePathMapping(input) diff --git a/services/apigateway/handler_client_certificates.go b/services/apigateway/handler_client_certificates.go index 13ad70dea6..6d9081e9ec 100644 --- a/services/apigateway/handler_client_certificates.go +++ b/services/apigateway/handler_client_certificates.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const opUpdateClientCertificate = "UpdateClientCertificate" @@ -48,7 +50,7 @@ func (h *Handler) clientCertificateActions() map[string]actionFn { func (h *Handler) generateClientCertificateAction(b []byte) (int, any, error) { var input GenerateClientCertificateInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GenerateClientCertificate(input) @@ -63,7 +65,7 @@ func (h *Handler) getClientCertificateAction(b []byte) (int, any, error) { var params struct { ClientCertificateID string `json:"clientCertificateId"` } - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetClientCertificate(params.ClientCertificateID) @@ -76,7 +78,7 @@ func (h *Handler) getClientCertificateAction(b []byte) (int, any, error) { func (h *Handler) getClientCertificatesAction(b []byte) (int, any, error) { var input getClientCertificatesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetClientCertificates() @@ -99,7 +101,7 @@ func (h *Handler) deleteClientCertificateAction(b []byte) (int, any, error) { var params struct { ClientCertificateID string `json:"clientCertificateId"` } - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteClientCertificate(params.ClientCertificateID); err != nil { @@ -111,7 +113,7 @@ func (h *Handler) deleteClientCertificateAction(b []byte) (int, any, error) { func (h *Handler) updateClientCertificateAction(b []byte) (int, any, error) { var input UpdateClientCertificateInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } diff --git a/services/apigateway/handler_deployments.go b/services/apigateway/handler_deployments.go index aee02b0ec8..b124bf768f 100644 --- a/services/apigateway/handler_deployments.go +++ b/services/apigateway/handler_deployments.go @@ -1,9 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createDeploymentInput struct { @@ -53,7 +55,7 @@ func (h *Handler) deploymentActions() map[string]actionFn { // createDeploymentAction handles CreateDeployment incl. inline stage update. func (h *Handler) createDeploymentAction(b []byte) (int, any, error) { var input createDeploymentInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } depl, err := h.Backend.CreateDeploymentWithCanary( @@ -104,7 +106,7 @@ func (h *Handler) deploymentCRUDActions() map[string]actionFn { func (h *Handler) getDeploymentAction(b []byte) (int, any, error) { var input getDeploymentInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } depl, err := h.Backend.GetDeployment(input.RestAPIID, input.DeploymentID) @@ -121,7 +123,7 @@ func (h *Handler) getDeploymentAction(b []byte) (int, any, error) { func (h *Handler) getDeploymentsAction(b []byte) (int, any, error) { var input getDeploymentsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } depls, err := h.Backend.GetDeployments(input.RestAPIID) @@ -146,7 +148,7 @@ func (h *Handler) getDeploymentsAction(b []byte) (int, any, error) { func (h *Handler) deleteDeploymentAction(b []byte) (int, any, error) { var input deleteDeploymentInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteDeployment(input.RestAPIID, input.DeploymentID); err != nil { @@ -163,7 +165,7 @@ func (h *Handler) deleteDeploymentAction(b []byte) (int, any, error) { func (h *Handler) updateDeploymentAction(b []byte) (int, any, error) { var input updateDeploymentHandlerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } depl, err := h.Backend.UpdateDeployment(input.RestAPIID, input.DeploymentID, input.UpdateDeploymentInput) diff --git a/services/apigateway/handler_documentation.go b/services/apigateway/handler_documentation.go index dbadca69bf..dd9e095431 100644 --- a/services/apigateway/handler_documentation.go +++ b/services/apigateway/handler_documentation.go @@ -1,9 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getDocumentationPartInput struct { @@ -120,7 +122,7 @@ func (h *Handler) documentationActions() map[string]actionFn { func (h *Handler) createDocumentationPartAction(b []byte) (int, any, error) { var input CreateDocumentationPartInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -134,7 +136,7 @@ func (h *Handler) createDocumentationPartAction(b []byte) (int, any, error) { func (h *Handler) createDocumentationVersionAction(b []byte) (int, any, error) { var input CreateDocumentationVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -148,7 +150,7 @@ func (h *Handler) createDocumentationVersionAction(b []byte) (int, any, error) { func (h *Handler) getDocumentationPartAction(b []byte) (int, any, error) { var input getDocumentationPartInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } p, err := h.Backend.GetDocumentationPart(input.RestAPIID, input.DocPartID) @@ -161,7 +163,7 @@ func (h *Handler) getDocumentationPartAction(b []byte) (int, any, error) { func (h *Handler) getDocumentationPartsAction(b []byte) (int, any, error) { var input getDocumentationPartsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ps, err := h.Backend.GetDocumentationParts(input.RestAPIID) @@ -231,7 +233,7 @@ func filterDocumentationPartsByStatus(parts []DocumentationPart, status string) func (h *Handler) updateDocumentationPartAction(b []byte) (int, any, error) { var input UpdateDocumentationPartInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateDocumentationPart(input) @@ -244,7 +246,7 @@ func (h *Handler) updateDocumentationPartAction(b []byte) (int, any, error) { func (h *Handler) updateDocumentationVersionAction(b []byte) (int, any, error) { var input UpdateDocumentationVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateDocumentationVersion(input) @@ -257,7 +259,7 @@ func (h *Handler) updateDocumentationVersionAction(b []byte) (int, any, error) { func (h *Handler) deleteDocumentationPartAction(b []byte) (int, any, error) { var input deleteDocumentationPartInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteDocumentationPart(input.RestAPIID, input.DocPartID); err != nil { @@ -269,7 +271,7 @@ func (h *Handler) deleteDocumentationPartAction(b []byte) (int, any, error) { func (h *Handler) getDocumentationVersionAction(b []byte) (int, any, error) { var input getDocumentationVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } v, err := h.Backend.GetDocumentationVersion(input.RestAPIID, input.DocVersion) @@ -282,7 +284,7 @@ func (h *Handler) getDocumentationVersionAction(b []byte) (int, any, error) { func (h *Handler) getDocumentationVersionsAction(b []byte) (int, any, error) { var input getDocumentationVersionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } vs, err := h.Backend.GetDocumentationVersions(input.RestAPIID) @@ -303,7 +305,7 @@ func (h *Handler) getDocumentationVersionsAction(b []byte) (int, any, error) { func (h *Handler) deleteDocumentationVersionAction(b []byte) (int, any, error) { var input deleteDocumentationVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteDocumentationVersion(input.RestAPIID, input.DocVersion); err != nil { diff --git a/services/apigateway/handler_domain_names.go b/services/apigateway/handler_domain_names.go index 661762e685..b1b04aa243 100644 --- a/services/apigateway/handler_domain_names.go +++ b/services/apigateway/handler_domain_names.go @@ -1,9 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -107,7 +109,7 @@ func (h *Handler) domainNameActions() map[string]actionFn { func (h *Handler) createDomainNameAction(b []byte) (int, any, error) { var input CreateDomainNameInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -121,7 +123,7 @@ func (h *Handler) createDomainNameAction(b []byte) (int, any, error) { func (h *Handler) getDomainNameAction(b []byte) (int, any, error) { var input getDomainNameInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } dn, err := h.Backend.GetDomainName(input.DomainName) @@ -134,7 +136,7 @@ func (h *Handler) getDomainNameAction(b []byte) (int, any, error) { func (h *Handler) getDomainNamesAction(b []byte) (int, any, error) { var input getDomainNamesPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if input.ResourceOwner == resourceOwnerOther { @@ -158,7 +160,7 @@ func (h *Handler) getDomainNamesAction(b []byte) (int, any, error) { func (h *Handler) deleteDomainNameAction(b []byte) (int, any, error) { var input deleteDomainNameInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteDomainName(input.DomainName); err != nil { @@ -170,7 +172,7 @@ func (h *Handler) deleteDomainNameAction(b []byte) (int, any, error) { func (h *Handler) updateDomainNameAction(b []byte) (int, any, error) { var input UpdateDomainNameInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateDomainName(input) @@ -187,7 +189,7 @@ func (h *Handler) domainNameAccessAssociationActions() map[string]actionFn { return map[string]actionFn{ opCreateDomainNameAccessAssociation: func(b []byte) (int, any, error) { var input CreateDomainNameAccessAssociationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -204,7 +206,7 @@ func (h *Handler) domainNameAccessAssociationActions() map[string]actionFn { Position string `json:"position,omitempty"` Limit int `json:"limit,omitempty"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -224,7 +226,7 @@ func (h *Handler) domainNameAccessAssociationActions() map[string]actionFn { var input struct { Arn string `json:"domainNameAccessAssociationArn"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -239,7 +241,7 @@ func (h *Handler) domainNameAccessAssociationActions() map[string]actionFn { Arn string `json:"domainNameAccessAssociationArn"` DomainNameArn string `json:"domainNameArn"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -265,7 +267,7 @@ func (h *Handler) withDomainNameID(fn actionFn) actionFn { DomainName string `json:"domainName"` DomainNameID string `json:"domainNameId"` } - if err := json.Unmarshal(b, &ref); err != nil { + if err := json.Unmarshal(b, &ref, jsonx.V1()); err != nil { return 0, nil, err } diff --git a/services/apigateway/handler_export.go b/services/apigateway/handler_export.go index a381cd3600..daf1382945 100644 --- a/services/apigateway/handler_export.go +++ b/services/apigateway/handler_export.go @@ -1,12 +1,14 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" "gopkg.in/yaml.v3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const opGetExport = "GetExport" @@ -39,7 +41,7 @@ func (h *Handler) exportActions() map[string]actionFn { return map[string]actionFn{ opGetExport: func(b []byte) (int, any, error) { var input getExportInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -82,5 +84,5 @@ func encodeExport(export map[string]any, contentType string) ([]byte, error) { return yaml.Marshal(export) } - return json.Marshal(export) + return json.Marshal(export, jsonx.V1()) } diff --git a/services/apigateway/handler_fixtures_test.go b/services/apigateway/handler_fixtures_test.go index b45dd31e63..c4f29b5c3f 100644 --- a/services/apigateway/handler_fixtures_test.go +++ b/services/apigateway/handler_fixtures_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -27,7 +28,7 @@ func boostAPI(t *testing.T, handler *apigateway.Handler, e *echo.Echo) string { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"boost-api"}`) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -38,7 +39,7 @@ func boostRootResource(t *testing.T, handler *apigateway.Handler, e *echo.Echo, rec := postWithHandler(t, handler, e, "GetResources", fmt.Sprintf(`{"restApiId":%q}`, apiID)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["item"].([]any) require.NotEmpty(t, items) @@ -52,7 +53,7 @@ func boostDeployment(t *testing.T, handler *apigateway.Handler, e *echo.Echo, ap fmt.Sprintf(`{"restApiId":%q,"stageName":%q}`, apiID, stageName)) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -72,7 +73,7 @@ func boostAuthorizer(t *testing.T, handler *apigateway.Handler, e *echo.Echo, ap ) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -84,7 +85,7 @@ func boostDocPart(t *testing.T, handler *apigateway.Handler, e *echo.Echo, apiID fmt.Sprintf(`{"restApiId":%q,"location":{"type":"API"},"properties":"{}"}`, apiID)) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } diff --git a/services/apigateway/handler_gateway_responses.go b/services/apigateway/handler_gateway_responses.go index c82b2bc0cb..738b0ea781 100644 --- a/services/apigateway/handler_gateway_responses.go +++ b/services/apigateway/handler_gateway_responses.go @@ -1,9 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const opUpdateGatewayResponse = "UpdateGatewayResponse" @@ -32,7 +34,7 @@ func (h *Handler) gatewayResponseActions() map[string]actionFn { func (h *Handler) getGatewayResponseAction(b []byte) (int, any, error) { var params getGatewayResponseInput - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetGatewayResponse(params.RestAPIID, params.ResponseType) @@ -45,7 +47,7 @@ func (h *Handler) getGatewayResponseAction(b []byte) (int, any, error) { func (h *Handler) getGatewayResponsesAction(b []byte) (int, any, error) { var params getGatewayResponsesInput - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetGatewayResponses(params.RestAPIID) @@ -67,7 +69,7 @@ func (h *Handler) getGatewayResponsesAction(b []byte) (int, any, error) { func (h *Handler) putGatewayResponseAction(b []byte) (int, any, error) { var input PutGatewayResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.PutGatewayResponse(input) @@ -80,7 +82,7 @@ func (h *Handler) putGatewayResponseAction(b []byte) (int, any, error) { func (h *Handler) updateGatewayResponseAction(b []byte) (int, any, error) { var input PutGatewayResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -94,7 +96,7 @@ func (h *Handler) updateGatewayResponseAction(b []byte) (int, any, error) { func (h *Handler) deleteGatewayResponseAction(b []byte) (int, any, error) { var params getGatewayResponseInput - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteGatewayResponse(params.RestAPIID, params.ResponseType); err != nil { diff --git a/services/apigateway/handler_import_export.go b/services/apigateway/handler_import_export.go index d1ae083393..9ed7d142c7 100644 --- a/services/apigateway/handler_import_export.go +++ b/services/apigateway/handler_import_export.go @@ -15,13 +15,14 @@ package apigateway // payload, optionally with "restApiId"/"mode" as extra sibling fields. import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -59,7 +60,7 @@ type restAPISpecEnvelope struct { // for the two payload shapes this handles. func decodeRestAPISpecPayload(b []byte) ([]byte, restAPISpecEnvelope) { var env restAPISpecEnvelope - if err := json.Unmarshal(b, &env); err == nil && env.Body != "" { + if err := json.Unmarshal(b, &env, jsonx.V1()); err == nil && env.Body != "" { if raw, decErr := base64.StdEncoding.DecodeString(env.Body); decErr == nil { return raw, env } @@ -75,7 +76,7 @@ func decodeRestAPISpecPayload(b []byte) ([]byte, restAPISpecEnvelope) { Format string `json:"format,omitempty"` } - _ = json.Unmarshal(b, &fallback) + _ = json.Unmarshal(b, &fallback, jsonx.V1()) return b, restAPISpecEnvelope{ RestAPIID: fallback.RestAPIID, @@ -206,7 +207,7 @@ func (h *Handler) dispatchRestAPISpec( env.Parameters[k] = v[0] } - envelope, err := json.Marshal(env) + envelope, err := json.Marshal(env, jsonx.V1()) if err != nil { return writeJSONProtocolDispatchError(c, http.StatusInternalServerError, "InternalFailure", "internal server error") diff --git a/services/apigateway/handler_import_export_test.go b/services/apigateway/handler_import_export_test.go index 72f3526c8f..cb1a6e8b46 100644 --- a/services/apigateway/handler_import_export_test.go +++ b/services/apigateway/handler_import_export_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -48,7 +49,7 @@ func TestAPIGateway_ImportRestApi_DirectDispatch(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, "Pet Store", api["name"]) assert.Equal(t, "A sample API", api["description"]) @@ -63,7 +64,7 @@ func TestAPIGateway_ImportRestApi_YAML(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, "YAML API", api["name"]) assert.Equal(t, "from yaml", api["description"]) } @@ -79,7 +80,7 @@ func TestAPIGateway_ImportRestApi_CreatesResourcesFromPaths(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) apiID, _ := api["id"].(string) require.NotEmpty(t, apiID) @@ -143,7 +144,7 @@ func TestAPIGateway_PutRestApi_DirectDispatch_Merge(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, "merged", api["name"]) resources, _, err := backend.GetResources(created.ID, "", 0) @@ -184,7 +185,7 @@ func TestAPIGateway_ImportRestApi_RESTRoute(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, "Pet Store", api["name"]) // A plain POST /restapis (no mode=import) must still route to CreateRestApi @@ -197,7 +198,7 @@ func TestAPIGateway_ImportRestApi_RESTRoute(t *testing.T) { require.Equal(t, http.StatusCreated, rec2.Code) var api2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &api2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &api2, jsonx.V1())) assert.Equal(t, "plain-create", api2["name"]) } @@ -228,7 +229,7 @@ func TestAPIGateway_PutRestApi_RESTRoute_Overwrite(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var api map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, "Pet Store", api["name"]) resources, _, err := backend.GetResources(created.ID, "", 0) @@ -300,7 +301,7 @@ func TestAPIGateway_ImportApiKeys_RESTRoute(t *testing.T) { if tt.wantCount > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, _ := resp["ids"].([]any) require.Len(t, ids, tt.wantCount) } @@ -329,7 +330,7 @@ func TestAPIGateway_ImportApiKeys_DuplicateWarns(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, _ := resp["ids"].([]any) warnings, _ := resp["warnings"].([]any) assert.Len(t, ids, 1, "only the non-duplicate row is imported") @@ -364,7 +365,7 @@ func TestAPIGateway_ImportDocumentationParts_RESTRoute(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, _ := resp["ids"].([]any) require.Len(t, ids, 2) diff --git a/services/apigateway/handler_integrations.go b/services/apigateway/handler_integrations.go index 9827335a17..d975d78fea 100644 --- a/services/apigateway/handler_integrations.go +++ b/services/apigateway/handler_integrations.go @@ -1,9 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putIntegrationInput struct { @@ -103,7 +105,7 @@ func (h *Handler) integrationResponseActions() map[string]actionFn { return map[string]actionFn{ opPutIntegrationResponse: func(b []byte) (int, any, error) { var input putIntegrationResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ir, err := h.Backend.PutIntegrationResponse( @@ -121,7 +123,7 @@ func (h *Handler) integrationResponseActions() map[string]actionFn { }, opGetIntegrationResponse: func(b []byte) (int, any, error) { var input getIntegrationResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ir, err := h.Backend.GetIntegrationResponse( @@ -138,7 +140,7 @@ func (h *Handler) integrationResponseActions() map[string]actionFn { }, opDeleteIntegrationResponse: func(b []byte) (int, any, error) { var input deleteIntegrationResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteIntegrationResponse( @@ -154,7 +156,7 @@ func (h *Handler) integrationResponseActions() map[string]actionFn { }, opUpdateIntegrationResponse: func(b []byte) (int, any, error) { var input UpdateIntegrationResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateIntegrationResponse(input) @@ -171,7 +173,7 @@ func (h *Handler) integrationActions() map[string]actionFn { return map[string]actionFn{ opPutIntegration: func(b []byte) (int, any, error) { var input putIntegrationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } switch input.Type { @@ -197,7 +199,7 @@ func (h *Handler) integrationActions() map[string]actionFn { }, opGetIntegration: func(b []byte) (int, any, error) { var input getIntegrationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } integ, err := h.Backend.GetIntegration(input.RestAPIID, input.ResourceID, input.HTTPMethod) @@ -209,7 +211,7 @@ func (h *Handler) integrationActions() map[string]actionFn { }, opDeleteIntegration: func(b []byte) (int, any, error) { var input deleteIntegrationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteIntegration(input.RestAPIID, input.ResourceID, input.HTTPMethod); err != nil { @@ -220,7 +222,7 @@ func (h *Handler) integrationActions() map[string]actionFn { }, opUpdateIntegration: func(b []byte) (int, any, error) { var input UpdateIntegrationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateIntegration(input) diff --git a/services/apigateway/handler_methods.go b/services/apigateway/handler_methods.go index 9e0304f5d8..424bd0037b 100644 --- a/services/apigateway/handler_methods.go +++ b/services/apigateway/handler_methods.go @@ -2,10 +2,12 @@ package apigateway import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type testInvokeMethodHandlerInput struct { @@ -295,7 +297,7 @@ func (h *Handler) invokeLambdaTestMethod( event.StageVariables = input.StageVariables - payload, _ := json.Marshal(event) + payload, _ := json.Marshal(event, jsonx.V1()) lambdaFn := ExtractLambdaFunctionName(interpolateStageVars(integration.URI, input.StageVariables)) respBytes, _, invokeErr := h.lambda.InvokeFunction(context.Background(), lambdaFn, "RequestResponse", payload) @@ -321,7 +323,7 @@ func lambdaTestOutput(respBytes []byte, invokeErr error) *TestInvokeMethodOutput } var lambdaResp LambdaProxyResponse - if json.Unmarshal(respBytes, &lambdaResp) == nil { + if json.Unmarshal(respBytes, &lambdaResp, jsonx.V1()) == nil { sc := lambdaResp.StatusCode if sc == 0 { sc = http.StatusOK @@ -366,7 +368,7 @@ func (h *Handler) methodActions() map[string]actionFn { func (h *Handler) putMethodAction(b []byte) (int, any, error) { var input putMethodInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } switch input.AuthorizationType { @@ -394,7 +396,7 @@ func (h *Handler) putMethodAction(b []byte) (int, any, error) { func (h *Handler) getMethodAction(b []byte) (int, any, error) { var input getMethodInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } m, err := h.Backend.GetMethod(input.RestAPIID, input.ResourceID, input.HTTPMethod) @@ -407,7 +409,7 @@ func (h *Handler) getMethodAction(b []byte) (int, any, error) { func (h *Handler) deleteMethodAction(b []byte) (int, any, error) { var input deleteMethodInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteMethod(input.RestAPIID, input.ResourceID, input.HTTPMethod); err != nil { @@ -419,7 +421,7 @@ func (h *Handler) deleteMethodAction(b []byte) (int, any, error) { func (h *Handler) updateMethodAction(b []byte) (int, any, error) { var input UpdateMethodInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateMethod(input) @@ -432,7 +434,7 @@ func (h *Handler) updateMethodAction(b []byte) (int, any, error) { func (h *Handler) testInvokeMethodAction(b []byte) (int, any, error) { var input testInvokeMethodHandlerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.testInvokeMethod(input.TestInvokeMethodInput) @@ -448,7 +450,7 @@ func (h *Handler) methodResponseActions() map[string]actionFn { return map[string]actionFn{ opPutMethodResponse: func(b []byte) (int, any, error) { var input putMethodResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } mr, err := h.Backend.PutMethodResponse( @@ -466,7 +468,7 @@ func (h *Handler) methodResponseActions() map[string]actionFn { }, opGetMethodResponse: func(b []byte) (int, any, error) { var input getMethodResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } mr, err := h.Backend.GetMethodResponse( @@ -483,7 +485,7 @@ func (h *Handler) methodResponseActions() map[string]actionFn { }, opDeleteMethodResponse: func(b []byte) (int, any, error) { var input deleteMethodResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteMethodResponse( @@ -499,7 +501,7 @@ func (h *Handler) methodResponseActions() map[string]actionFn { }, opUpdateMethodResponse: func(b []byte) (int, any, error) { var input UpdateMethodResponseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateMethodResponse(input) diff --git a/services/apigateway/handler_request_validators.go b/services/apigateway/handler_request_validators.go index fc161140c3..1535211901 100644 --- a/services/apigateway/handler_request_validators.go +++ b/services/apigateway/handler_request_validators.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createRequestValidatorInput struct { @@ -47,7 +49,7 @@ func (h *Handler) requestValidatorActions() map[string]actionFn { func (h *Handler) createRequestValidatorAction(b []byte) (int, any, error) { var input createRequestValidatorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } rv, err := h.Backend.CreateRequestValidator(input.RestAPIID, CreateRequestValidatorInput{ @@ -64,7 +66,7 @@ func (h *Handler) createRequestValidatorAction(b []byte) (int, any, error) { func (h *Handler) getRequestValidatorAction(b []byte) (int, any, error) { var input getRequestValidatorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } rv, err := h.Backend.GetRequestValidator(input.RestAPIID, input.ValidatorID) @@ -77,7 +79,7 @@ func (h *Handler) getRequestValidatorAction(b []byte) (int, any, error) { func (h *Handler) getRequestValidatorsAction(b []byte) (int, any, error) { var input getRequestValidatorsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } rvs, err := h.Backend.GetRequestValidators(input.RestAPIID) @@ -98,7 +100,7 @@ func (h *Handler) getRequestValidatorsAction(b []byte) (int, any, error) { func (h *Handler) updateRequestValidatorAction(b []byte) (int, any, error) { var input updateRequestValidatorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } rv, err := h.Backend.UpdateRequestValidator( @@ -115,7 +117,7 @@ func (h *Handler) updateRequestValidatorAction(b []byte) (int, any, error) { func (h *Handler) deleteRequestValidatorAction(b []byte) (int, any, error) { var input deleteRequestValidatorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteRequestValidator(input.RestAPIID, input.ValidatorID); err != nil { diff --git a/services/apigateway/handler_resources.go b/services/apigateway/handler_resources.go index 460cc7f35c..b3f92333c7 100644 --- a/services/apigateway/handler_resources.go +++ b/services/apigateway/handler_resources.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getResourcesInput struct { @@ -47,7 +49,7 @@ func (h *Handler) resourceActions() map[string]actionFn { func (h *Handler) getResourcesAction(b []byte) (int, any, error) { var input getResourcesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } resources, position, err := h.Backend.GetResources(input.RestAPIID, input.Position, input.Limit) @@ -64,7 +66,7 @@ func (h *Handler) getResourcesAction(b []byte) (int, any, error) { func (h *Handler) getResourceAction(b []byte) (int, any, error) { var input getResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } r, err := h.Backend.GetResource(input.RestAPIID, input.ResourceID) @@ -77,7 +79,7 @@ func (h *Handler) getResourceAction(b []byte) (int, any, error) { func (h *Handler) createResourceAction(b []byte) (int, any, error) { var input createResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } r, err := h.Backend.CreateResource(input.RestAPIID, input.ParentID, input.PathPart) @@ -90,7 +92,7 @@ func (h *Handler) createResourceAction(b []byte) (int, any, error) { func (h *Handler) deleteResourceAction(b []byte) (int, any, error) { var input deleteResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteResource(input.RestAPIID, input.ResourceID); err != nil { @@ -102,7 +104,7 @@ func (h *Handler) deleteResourceAction(b []byte) (int, any, error) { func (h *Handler) updateResourceAction(b []byte) (int, any, error) { var input updateResourceHandlerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } res, err := h.Backend.UpdateResource(input.RestAPIID, input.ResourceID, input.UpdateResourceInput) diff --git a/services/apigateway/handler_rest_apis.go b/services/apigateway/handler_rest_apis.go index 013f062980..9fcfdb2ecf 100644 --- a/services/apigateway/handler_rest_apis.go +++ b/services/apigateway/handler_rest_apis.go @@ -1,9 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -39,7 +40,7 @@ func (h *Handler) restAPIActions() map[string]actionFn { func (h *Handler) createRestAPIAction(b []byte) (int, any, error) { var input createRestAPIInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if input.Tags != nil { @@ -61,7 +62,7 @@ func (h *Handler) createRestAPIAction(b []byte) (int, any, error) { func (h *Handler) deleteRestAPIAction(b []byte) (int, any, error) { var input deleteRestAPIInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } // Deployment IDs are freshly random and never reused, so the trie cache @@ -85,7 +86,7 @@ func (h *Handler) deleteRestAPIAction(b []byte) (int, any, error) { func (h *Handler) getRestAPIAction(b []byte) (int, any, error) { var input getRestAPIInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } api, err := h.Backend.GetRestAPI(input.RestAPIID) @@ -98,7 +99,7 @@ func (h *Handler) getRestAPIAction(b []byte) (int, any, error) { func (h *Handler) getRestAPIsAction(b []byte) (int, any, error) { var input getRestApisInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } apis, position, err := h.Backend.GetRestAPIs(input.Limit, input.Position) @@ -116,7 +117,7 @@ func (h *Handler) getRestAPIsAction(b []byte) (int, any, error) { func (h *Handler) updateRestAPIAction(b []byte) (int, any, error) { var input updateRestAPIHandlerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } api, err := h.Backend.UpdateRestAPI(input.RestAPIID, input.UpdateRestAPIInput) diff --git a/services/apigateway/handler_router_test.go b/services/apigateway/handler_router_test.go index c7a4afd8d8..d4ba5ecc14 100644 --- a/services/apigateway/handler_router_test.go +++ b/services/apigateway/handler_router_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "log/slog" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -31,7 +32,7 @@ func createParityAPI(t *testing.T, h *apigateway.Handler, name string) string { require.Equal(t, http.StatusCreated, rec.Code, "create api: %s", rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) id, _ := out["id"].(string) require.NotEmpty(t, id) @@ -49,7 +50,7 @@ func getRootResourceID(t *testing.T, h *apigateway.Handler, apiID string) string var out struct { Items []map[string]any `json:"item"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) for _, r := range out.Items { if r["path"] == "/" { @@ -575,7 +576,7 @@ func TestHandler_APIGateway_FullWorkflow(t *testing.T) { // parseJSON is a helper to decode JSON from a response recorder. func parseJSON(rec *httptest.ResponseRecorder, v any) error { - return json.Unmarshal(rec.Body.Bytes(), v) + return json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1()) } // errNoopNotImplemented is returned by noopBackend for methods that are not expected @@ -1357,7 +1358,7 @@ func TestHandler_GetSupportedOperations(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.Contains(t, ops, "CreateRestApi") }) } diff --git a/services/apigateway/handler_schema_models.go b/services/apigateway/handler_schema_models.go index 9dbce8598e..de70de7318 100644 --- a/services/apigateway/handler_schema_models.go +++ b/services/apigateway/handler_schema_models.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getModelInput struct { @@ -47,7 +49,7 @@ func (h *Handler) schemaModelActions() map[string]actionFn { func (h *Handler) createModelAction(b []byte) (int, any, error) { var input CreateModelInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -61,7 +63,7 @@ func (h *Handler) createModelAction(b []byte) (int, any, error) { func (h *Handler) getModelAction(b []byte) (int, any, error) { var input getModelInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } m, err := h.Backend.GetModel(input.RestAPIID, input.ModelName, input.Flatten == litTrue) @@ -74,7 +76,7 @@ func (h *Handler) getModelAction(b []byte) (int, any, error) { func (h *Handler) getModelsAction(b []byte) (int, any, error) { var input getModelsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ms, err := h.Backend.GetModels(input.RestAPIID) @@ -94,7 +96,7 @@ func (h *Handler) getModelsAction(b []byte) (int, any, error) { func (h *Handler) deleteModelAction(b []byte) (int, any, error) { var input deleteModelInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteModel(input.RestAPIID, input.ModelName); err != nil { @@ -106,7 +108,7 @@ func (h *Handler) deleteModelAction(b []byte) (int, any, error) { func (h *Handler) updateModelAction(b []byte) (int, any, error) { var input updateModelInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } m, err := h.Backend.UpdateModel(input.RestAPIID, input.ModelName, input.UpdateModelInput) @@ -122,7 +124,7 @@ func (h *Handler) getModelTemplateAction(b []byte) (int, any, error) { RestAPIID string `json:"restApiId"` ModelName string `json:"modelName"` } - if err := json.Unmarshal(b, ¶ms); err != nil { + if err := json.Unmarshal(b, ¶ms, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetModelTemplate(params.RestAPIID, params.ModelName) diff --git a/services/apigateway/handler_sdk.go b/services/apigateway/handler_sdk.go index 6b10462fbd..ef757aa424 100644 --- a/services/apigateway/handler_sdk.go +++ b/services/apigateway/handler_sdk.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -48,12 +50,12 @@ func (h *Handler) sdkActions() map[string]actionFn { StageName string `json:"stageName"` SdkType string `json:"sdkType"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } var raw map[string]any - _ = json.Unmarshal(b, &raw) + _ = json.Unmarshal(b, &raw, jsonx.V1()) params := make(map[string]string) @@ -78,7 +80,7 @@ func (h *Handler) sdkActions() map[string]actionFn { var input struct { ID string `json:"id"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -93,7 +95,7 @@ func (h *Handler) sdkActions() map[string]actionFn { var input struct { Limit int `json:"limit,omitempty"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } diff --git a/services/apigateway/handler_stages.go b/services/apigateway/handler_stages.go index a74973de92..b72e7e810a 100644 --- a/services/apigateway/handler_stages.go +++ b/services/apigateway/handler_stages.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getStagesInput struct { @@ -46,7 +48,7 @@ func (h *Handler) stageActions() map[string]actionFn { func (h *Handler) createStageAction(b []byte) (int, any, error) { var input CreateStageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -60,7 +62,7 @@ func (h *Handler) createStageAction(b []byte) (int, any, error) { func (h *Handler) updateStageAction(b []byte) (int, any, error) { var input updateStageHandlerInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } stage, err := h.Backend.UpdateStage(input.RestAPIID, input.StageName, input.UpdateStageInput) @@ -77,7 +79,7 @@ func (h *Handler) updateStageAction(b []byte) (int, any, error) { func (h *Handler) flushStageCacheAction(b []byte) (int, any, error) { var input flushStageCacheInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if _, err := h.Backend.GetStage(input.RestAPIID, input.StageName); err != nil { @@ -91,7 +93,7 @@ func (h *Handler) flushStageCacheAction(b []byte) (int, any, error) { func (h *Handler) flushStageAuthorizersCacheAction(b []byte) (int, any, error) { var input flushStageCacheInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } h.authCache.flush() @@ -101,7 +103,7 @@ func (h *Handler) flushStageAuthorizersCacheAction(b []byte) (int, any, error) { func (h *Handler) getStagesAction(b []byte) (int, any, error) { var input getStagesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } stages, err := h.Backend.GetStages(input.RestAPIID) @@ -123,7 +125,7 @@ func (h *Handler) getStagesAction(b []byte) (int, any, error) { func (h *Handler) getStageAction(b []byte) (int, any, error) { var input getStageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } stage, err := h.Backend.GetStage(input.RestAPIID, input.StageName) @@ -136,7 +138,7 @@ func (h *Handler) getStageAction(b []byte) (int, any, error) { func (h *Handler) deleteStageAction(b []byte) (int, any, error) { var input deleteStageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteStage(input.RestAPIID, input.StageName); err != nil { diff --git a/services/apigateway/handler_tags.go b/services/apigateway/handler_tags.go index 58c12fbf38..53c4c78fbf 100644 --- a/services/apigateway/handler_tags.go +++ b/services/apigateway/handler_tags.go @@ -1,11 +1,12 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -51,7 +52,7 @@ func (h *Handler) tagActions() map[string]actionFn { return map[string]actionFn{ opGetTags: func(b []byte) (int, any, error) { var input getTagsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } t, err := h.Backend.GetResourceTags(input.ResourceARN) @@ -63,7 +64,7 @@ func (h *Handler) tagActions() map[string]actionFn { }, opTagResource: func(b []byte) (int, any, error) { var input tagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } for key := range input.Tags { @@ -83,7 +84,7 @@ func (h *Handler) tagActions() map[string]actionFn { }, opUntagResource: func(b []byte) (int, any, error) { var input untagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.UntagResource(input.ResourceARN, input.TagKeys); err != nil { diff --git a/services/apigateway/handler_test.go b/services/apigateway/handler_test.go index 2012383682..54e22b3d4c 100644 --- a/services/apigateway/handler_test.go +++ b/services/apigateway/handler_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -129,7 +130,7 @@ func TestHandler_RestAPI(t *testing.T) { assert.Equal(t, tt.wantCreateCode, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.NotEmpty(t, created["id"]) assert.Equal(t, tt.primaryAPIName, created["name"]) @@ -144,7 +145,7 @@ func TestHandler_RestAPI(t *testing.T) { assert.Equal(t, tt.wantGetCode, rec2.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, apiID, got["id"]) assert.Equal(t, tt.primaryAPIName, got["name"]) } @@ -154,7 +155,7 @@ func TestHandler_RestAPI(t *testing.T) { assert.Equal(t, http.StatusOK, rec3.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["item"].([]any), tt.wantListCount) } @@ -207,14 +208,14 @@ func TestHandler_Resources(t *testing.T) { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) rec2 := postWithHandler(t, handler, e, "GetResources", fmt.Sprintf(`{"restApiId":%q}`, apiID)) assert.Equal(t, http.StatusOK, rec2.Code) var res map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res, jsonx.V1())) items := res["item"].([]any) if tt.wantResourceCount > 0 { @@ -231,7 +232,7 @@ func TestHandler_Resources(t *testing.T) { assert.Equal(t, http.StatusCreated, rec3.Code) var child map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &child)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &child, jsonx.V1())) if tt.wantChildPath != "" { assert.Equal(t, tt.wantChildPath, child["path"]) @@ -284,12 +285,12 @@ func TestHandler_Method(t *testing.T) { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) rec2 := postWithHandler(t, handler, e, "GetResources", fmt.Sprintf(`{"restApiId":%q}`, apiID)) var res map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res, jsonx.V1())) rootID := res["item"].([]any)[0].(map[string]any)["id"].(string) rec3 := postWithHandler(t, handler, e, "PutMethod", @@ -298,7 +299,7 @@ func TestHandler_Method(t *testing.T) { assert.Equal(t, tt.wantPutCode, rec3.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &m, jsonx.V1())) assert.Equal(t, tt.httpMethod, m["httpMethod"]) rec4 := postWithHandler(t, handler, e, "GetMethod", @@ -347,12 +348,12 @@ func TestHandler_Integration(t *testing.T) { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) rec2 := postWithHandler(t, handler, e, "GetResources", fmt.Sprintf(`{"restApiId":%q}`, apiID)) var res map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &res, jsonx.V1())) rootID := res["item"].([]any)[0].(map[string]any)["id"].(string) postWithHandler(t, handler, e, "PutMethod", @@ -365,7 +366,7 @@ func TestHandler_Integration(t *testing.T) { assert.Equal(t, tt.wantPutCode, rec3.Code) var integ map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &integ, jsonx.V1())) assert.Equal(t, tt.integrationType, integ["type"]) rec4 := postWithHandler(t, handler, e, "GetIntegration", @@ -410,7 +411,7 @@ func TestHandler_Deployment(t *testing.T) { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) rec2 := postWithHandler(t, handler, e, "CreateDeployment", @@ -419,14 +420,14 @@ func TestHandler_Deployment(t *testing.T) { assert.Equal(t, tt.wantCreateCode, rec2.Code) var depl map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &depl)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &depl, jsonx.V1())) assert.NotEmpty(t, depl["id"]) rec3 := postWithHandler(t, handler, e, "GetDeployments", fmt.Sprintf(`{"restApiId":%q}`, apiID)) assert.Equal(t, http.StatusOK, rec3.Code) var depls map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &depls)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &depls, jsonx.V1())) assert.Len(t, depls["item"].([]any), tt.wantListCount) }) } @@ -463,7 +464,7 @@ func TestHandler_Stages(t *testing.T) { rec := postWithHandler(t, handler, e, "CreateRestApi", `{"name":"api"}`) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) postWithHandler(t, handler, e, "CreateDeployment", @@ -473,7 +474,7 @@ func TestHandler_Stages(t *testing.T) { assert.Equal(t, tt.wantListCode, rec2.Code) var stages map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &stages)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &stages, jsonx.V1())) assert.Len(t, stages["item"].([]any), tt.wantListCount) rec3 := postWithHandler(t, handler, e, "GetStage", @@ -540,7 +541,7 @@ func TestHandler_Errors(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -716,7 +717,7 @@ func TestHandler_CreateAPIKey(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["name"]) // value must be non-empty (either provided or auto-generated) assert.NotEmpty(t, resp["value"]) @@ -784,7 +785,7 @@ func TestHandler_CreateDocumentationPart(t *testing.T) { require.Equal(t, http.StatusCreated, apiRec.Code) var apiResp map[string]any - require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp)) + require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -833,7 +834,7 @@ func TestHandler_CreateDocumentationVersion(t *testing.T) { require.Equal(t, http.StatusCreated, apiRec.Code) var apiResp map[string]any - require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp)) + require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -979,7 +980,7 @@ func TestHandler_CreateModel(t *testing.T) { require.Equal(t, http.StatusCreated, apiRec.Code) var apiResp map[string]any - require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp)) + require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -1043,7 +1044,7 @@ func TestHandler_CreateStageStandalone(t *testing.T) { require.Equal(t, http.StatusCreated, apiRec.Code) var apiResp map[string]any - require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp)) + require.NoError(t, json.Unmarshal(apiRec.Body.Bytes(), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -1051,7 +1052,7 @@ func TestHandler_CreateStageStandalone(t *testing.T) { require.Equal(t, http.StatusCreated, deplRec.Code) var deplResp map[string]any - require.NoError(t, json.Unmarshal(deplRec.Body.Bytes(), &deplResp)) + require.NoError(t, json.Unmarshal(deplRec.Body.Bytes(), &deplResp, jsonx.V1())) deplID, _ := deplResp["id"].(string) require.NotEmpty(t, deplID) @@ -1170,7 +1171,7 @@ func TestHandler_CreateUsagePlan(t *testing.T) { if tt.checkResp != nil && rec.Code == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.checkResp(t, resp) } }) @@ -1187,7 +1188,7 @@ func TestHandler_CreateUsagePlanKey(t *testing.T) { require.Equal(t, http.StatusCreated, keyRec.Code) var keyResp map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &keyResp)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &keyResp, jsonx.V1())) keyID, _ := keyResp["id"].(string) require.NotEmpty(t, keyID) @@ -1195,7 +1196,7 @@ func TestHandler_CreateUsagePlanKey(t *testing.T) { require.Equal(t, http.StatusCreated, planRec.Code) var planResp map[string]any - require.NoError(t, json.Unmarshal(planRec.Body.Bytes(), &planResp)) + require.NoError(t, json.Unmarshal(planRec.Body.Bytes(), &planResp, jsonx.V1())) planID, _ := planResp["id"].(string) require.NotEmpty(t, planID) @@ -1204,7 +1205,7 @@ func TestHandler_CreateUsagePlanKey(t *testing.T) { require.Equal(t, http.StatusCreated, dupKeyRec.Code) var dupKeyResp map[string]any - require.NoError(t, json.Unmarshal(dupKeyRec.Body.Bytes(), &dupKeyResp)) + require.NoError(t, json.Unmarshal(dupKeyRec.Body.Bytes(), &dupKeyResp, jsonx.V1())) dupKeyID, _ := dupKeyResp["id"].(string) require.NotEmpty(t, dupKeyID) @@ -1260,7 +1261,7 @@ func TestHandler_CreateUsagePlanKey(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["type"]) } }) diff --git a/services/apigateway/handler_usage.go b/services/apigateway/handler_usage.go index 011b8e7ad8..8c01381843 100644 --- a/services/apigateway/handler_usage.go +++ b/services/apigateway/handler_usage.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const opUpdateUsage = "UpdateUsage" @@ -13,7 +15,7 @@ func (h *Handler) usageActions() map[string]actionFn { return map[string]actionFn{ opGetUsage: func(b []byte) (int, any, error) { var input GetUsageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.GetUsage(input) @@ -25,7 +27,7 @@ func (h *Handler) usageActions() map[string]actionFn { }, opUpdateUsage: func(b []byte) (int, any, error) { var raw map[string]string - if err := json.Unmarshal(b, &raw); err != nil { + if err := json.Unmarshal(b, &raw, jsonx.V1()); err != nil { return 0, nil, err } diff --git a/services/apigateway/handler_usage_plans.go b/services/apigateway/handler_usage_plans.go index 7c7726cd83..a1c090b864 100644 --- a/services/apigateway/handler_usage_plans.go +++ b/services/apigateway/handler_usage_plans.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getUsagePlansPageInput struct { @@ -139,7 +141,7 @@ func (h *Handler) usagePlanActions() map[string]actionFn { func (h *Handler) createUsagePlanAction(b []byte) (int, any, error) { var input CreateUsagePlanInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -153,7 +155,7 @@ func (h *Handler) createUsagePlanAction(b []byte) (int, any, error) { func (h *Handler) createUsagePlanKeyAction(b []byte) (int, any, error) { var input CreateUsagePlanKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -167,7 +169,7 @@ func (h *Handler) createUsagePlanKeyAction(b []byte) (int, any, error) { func (h *Handler) getUsagePlanAction(b []byte) (int, any, error) { var input getUsagePlanInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } p, err := h.Backend.GetUsagePlan(input.UsagePlanID) @@ -180,7 +182,7 @@ func (h *Handler) getUsagePlanAction(b []byte) (int, any, error) { func (h *Handler) getUsagePlansAction(b []byte) (int, any, error) { var input getUsagePlansPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -215,7 +217,7 @@ func (h *Handler) getUsagePlansAction(b []byte) (int, any, error) { func (h *Handler) updateUsagePlanAction(b []byte) (int, any, error) { var input UpdateUsagePlanInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } out, err := h.Backend.UpdateUsagePlan(input) @@ -228,7 +230,7 @@ func (h *Handler) updateUsagePlanAction(b []byte) (int, any, error) { func (h *Handler) deleteUsagePlanAction(b []byte) (int, any, error) { var input deleteUsagePlanInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteUsagePlan(input.UsagePlanID); err != nil { @@ -240,7 +242,7 @@ func (h *Handler) deleteUsagePlanAction(b []byte) (int, any, error) { func (h *Handler) getUsagePlanKeyAction(b []byte) (int, any, error) { var input getUsagePlanKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } k, err := h.Backend.GetUsagePlanKey(input.UsagePlanID, input.KeyID) @@ -253,7 +255,7 @@ func (h *Handler) getUsagePlanKeyAction(b []byte) (int, any, error) { func (h *Handler) getUsagePlanKeysAction(b []byte) (int, any, error) { var input getUsagePlanKeysInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } ks, err := h.Backend.GetUsagePlanKeys(input.UsagePlanID) @@ -282,7 +284,7 @@ func (h *Handler) getUsagePlanKeysAction(b []byte) (int, any, error) { func (h *Handler) deleteUsagePlanKeyAction(b []byte) (int, any, error) { var input deleteUsagePlanKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } if err := h.Backend.DeleteUsagePlanKey(input.UsagePlanID, input.KeyID); err != nil { diff --git a/services/apigateway/handler_vpc_links.go b/services/apigateway/handler_vpc_links.go index 762127269b..24d7d62f7c 100644 --- a/services/apigateway/handler_vpc_links.go +++ b/services/apigateway/handler_vpc_links.go @@ -1,8 +1,10 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -64,7 +66,7 @@ func (h *Handler) vpcLinkActions() map[string]actionFn { func (h *Handler) createVpcLinkAction(b []byte) (int, any, error) { var input CreateVpcLinkInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -78,7 +80,7 @@ func (h *Handler) createVpcLinkAction(b []byte) (int, any, error) { func (h *Handler) deleteVpcLinkAction(b []byte) (int, any, error) { var input deleteVpcLinkInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -91,7 +93,7 @@ func (h *Handler) deleteVpcLinkAction(b []byte) (int, any, error) { func (h *Handler) getVpcLinkAction(b []byte) (int, any, error) { var input getVpcLinkInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } @@ -105,7 +107,7 @@ func (h *Handler) getVpcLinkAction(b []byte) (int, any, error) { func (h *Handler) getVpcLinksAction(b []byte) (int, any, error) { var input getVpcLinksInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } links, err := h.Backend.GetVpcLinks() @@ -126,7 +128,7 @@ func (h *Handler) getVpcLinksAction(b []byte) (int, any, error) { func (h *Handler) updateVpcLinkAction(b []byte) (int, any, error) { var input UpdateVpcLinkInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return 0, nil, err } diff --git a/services/apigateway/import.go b/services/apigateway/import.go index 75d44d1a54..815ea95009 100644 --- a/services/apigateway/import.go +++ b/services/apigateway/import.go @@ -10,7 +10,8 @@ package apigateway import ( "bytes" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "strings" @@ -19,6 +20,7 @@ import ( "gopkg.in/yaml.v3" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -43,15 +45,15 @@ type PutRestAPIInput struct { // openAPIDoc is the subset of an OpenAPI/Swagger document we interpret. type openAPIDoc struct { - Info openAPIInfo `json:"info"` - Paths map[string]map[string]json.RawMessage `json:"paths"` - Definitions map[string]json.RawMessage `json:"definitions"` - Components *openAPIComponents `json:"components"` - SecurityDefinitions map[string]openAPISecurityScheme `json:"securityDefinitions"` - Swagger string `json:"swagger"` - OpenAPI string `json:"openapi"` - APIKeySourceExt string `json:"x-amazon-apigateway-api-key-source"` - BinaryMediaTypes []string `json:"x-amazon-apigateway-binary-media-types"` + Info openAPIInfo `json:"info"` + Paths map[string]map[string]jsontext.Value `json:"paths"` + Definitions map[string]jsontext.Value `json:"definitions"` + Components *openAPIComponents `json:"components"` + SecurityDefinitions map[string]openAPISecurityScheme `json:"securityDefinitions"` + Swagger string `json:"swagger"` + OpenAPI string `json:"openapi"` + APIKeySourceExt string `json:"x-amazon-apigateway-api-key-source"` + BinaryMediaTypes []string `json:"x-amazon-apigateway-binary-media-types"` } type openAPIInfo struct { @@ -61,7 +63,7 @@ type openAPIInfo struct { } type openAPIComponents struct { - Schemas map[string]json.RawMessage `json:"schemas"` + Schemas map[string]jsontext.Value `json:"schemas"` SecuritySchemes map[string]openAPISecurityScheme `json:"securitySchemes"` } @@ -76,20 +78,20 @@ type openAPIOperation struct { } type openAPIParameter struct { - Name string `json:"name"` - In string `json:"in"` - Schema json.RawMessage `json:"schema"` - Required bool `json:"required"` + Name string `json:"name"` + In string `json:"in"` + Schema jsontext.Value `json:"schema"` + Required bool `json:"required"` } type openAPIResponse struct { Content map[string]openAPIMediaTyp `json:"content"` Description string `json:"description"` - Schema json.RawMessage `json:"schema"` + Schema jsontext.Value `json:"schema"` } type openAPIMediaTyp struct { - Schema json.RawMessage `json:"schema"` + Schema jsontext.Value `json:"schema"` } type openAPIRequestBody struct { @@ -141,13 +143,13 @@ func parseOpenAPI(body []byte) (*openAPIDoc, error) { ) } - normalized, err := json.Marshal(raw) + normalized, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: invalid OpenAPI document: %w", ErrInvalidParameter, err) } var doc openAPIDoc - if jsonErr := json.Unmarshal(normalized, &doc); jsonErr != nil { + if jsonErr := json.Unmarshal(normalized, &doc, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: invalid OpenAPI document: %w", ErrInvalidParameter, jsonErr) } if doc.Swagger == "" && doc.OpenAPI == "" { @@ -244,7 +246,7 @@ func openAPIOperationWarnings(raw map[string]any, knownOperationExtensions map[s } // schemaDefinitions returns the named schemas regardless of spec version. -func (d *openAPIDoc) schemaDefinitions() map[string]json.RawMessage { +func (d *openAPIDoc) schemaDefinitions() map[string]jsontext.Value { if len(d.Definitions) > 0 { return d.Definitions } @@ -446,7 +448,7 @@ func importPaths(b *InMemoryBackend, api *RestAPI, doc *openAPIDoc) { continue } var op openAPIOperation - if err := json.Unmarshal(raw, &op); err != nil { + if err := json.Unmarshal(raw, &op, jsonx.V1()); err != nil { continue } importMethod(res, httpMethod, &op, auths) @@ -665,14 +667,14 @@ func applyImportedSecurity(method *Method, op *openAPIOperation) { // schemaRefName extracts the model name from a JSON schema reference such as // {"$ref":"#/definitions/Foo"} or {"$ref":"#/components/schemas/Foo"}. -func schemaRefName(raw json.RawMessage) string { +func schemaRefName(raw jsontext.Value) string { if len(raw) == 0 { return "" } var s struct { Ref string `json:"$ref"` } - if err := json.Unmarshal(raw, &s); err != nil || s.Ref == "" { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil || s.Ref == "" { return "" } idx := strings.LastIndex(s.Ref, "/") @@ -811,7 +813,7 @@ func (b *InMemoryBackend) ImportAPIKeys(body []byte, format string, failOnWarnin // "x-amazon-apigateway-documentation" documentationParts array. type importDocumentationPartEntry struct { Location DocumentationLocation `json:"location"` - Properties json.RawMessage `json:"properties"` + Properties jsontext.Value `json:"properties"` } // importDocumentationPartsPayload is the expected JSON shape for @@ -831,7 +833,7 @@ func (b *InMemoryBackend) ImportDocumentationParts( restAPIID string, body []byte, mode string, failOnWarnings bool, ) ([]string, []string, error) { var payload importDocumentationPartsPayload - if err := json.Unmarshal(body, &payload); err != nil { + if err := json.Unmarshal(body, &payload, jsonx.V1()); err != nil { return nil, nil, fmt.Errorf("%w: failed to parse documentation parts payload: %w", ErrInvalidParameter, err) } diff --git a/services/apigateway/import_test.go b/services/apigateway/import_test.go index 316aa698be..9377b50113 100644 --- a/services/apigateway/import_test.go +++ b/services/apigateway/import_test.go @@ -1,13 +1,15 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -282,7 +284,7 @@ func TestImportRestAPI_RESTRouting(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "PetStore", resp["name"]) apiID, _ := resp["id"].(string) require.NotEmpty(t, apiID) @@ -302,7 +304,7 @@ func TestImportRestAPI_RESTRouting(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "plain", resp["name"]) }) diff --git a/services/apigateway/integrations_test.go b/services/apigateway/integrations_test.go index ccfa55db32..81a815c872 100644 --- a/services/apigateway/integrations_test.go +++ b/services/apigateway/integrations_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -47,7 +49,7 @@ func TestPutIntegration_DefaultTimeout(t *testing.T) { require.True(t, createRec.Code >= 200 && createRec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -55,7 +57,7 @@ func TestPutIntegration_DefaultTimeout(t *testing.T) { require.True(t, resRec.Code >= 200 && resRec.Code < 300) var resResp map[string]any - require.NoError(t, json.NewDecoder(resRec.Body).Decode(&resResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resRec.Body), &resResp, jsonx.V1())) items := resResp["item"].([]any) rootID := items[0].(map[string]any)["id"].(string) @@ -70,7 +72,7 @@ func TestPutIntegration_DefaultTimeout(t *testing.T) { require.True(t, intRec.Code >= 200 && intRec.Code < 300) var intResp map[string]any - require.NoError(t, json.NewDecoder(intRec.Body).Decode(&intResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(intRec.Body), &intResp, jsonx.V1())) got, ok := intResp["timeoutInMillis"].(float64) require.True(t, ok, "timeoutInMillis must be present in PutIntegration response") @@ -318,14 +320,14 @@ func TestHandlerIntegration_ConnectionType_RoundTrip(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) rec = restRequest(t, h, http.MethodGet, "/restapis/"+apiID+"/resources", "") require.True(t, rec.Code >= 200 && rec.Code < 300) var resResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resResp, jsonx.V1())) items := resResp["item"].([]any) rootID := items[0].(map[string]any)["id"].(string) @@ -340,7 +342,7 @@ func TestHandlerIntegration_ConnectionType_RoundTrip(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var integResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&integResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &integResp, jsonx.V1())) assert.Equal(t, "INTERNET", integResp["connectionType"]) } diff --git a/services/apigateway/invoke_stage_test.go b/services/apigateway/invoke_stage_test.go index 5df23eb915..58ff716f74 100644 --- a/services/apigateway/invoke_stage_test.go +++ b/services/apigateway/invoke_stage_test.go @@ -1,13 +1,14 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -64,7 +65,7 @@ func TestInvokeStage(t *testing.T) { var ev apigateway.LambdaProxyEvent - require.NoError(t, json.Unmarshal(captured, &ev)) + require.NoError(t, json.Unmarshal(captured, &ev, jsonx.V1())) assert.Equal(t, "/items", ev.Resource) assert.Equal(t, `{"a":1}`, ev.Body) assert.Equal(t, "v", ev.QueryStringParameters["q"]) diff --git a/services/apigateway/methods_test.go b/services/apigateway/methods_test.go index 6e9ce9e89f..8b3371e777 100644 --- a/services/apigateway/methods_test.go +++ b/services/apigateway/methods_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -129,7 +130,7 @@ func TestPutMethod_RequestParametersRoundtrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, "body: %s", rec.Body.String()) var method map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &method)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &method, jsonx.V1())) params, _ := method["requestParameters"].(map[string]any) require.NotNil(t, params, "requestParameters must be present in response") @@ -234,7 +235,7 @@ func TestTestInvokeMethod(t *testing.T) { if tt.wantStatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.EqualValues(t, http.StatusOK, resp["status"]) } }) diff --git a/services/apigateway/models.go b/services/apigateway/models.go index f379b7ecb2..4d72f22fe5 100644 --- a/services/apigateway/models.go +++ b/services/apigateway/models.go @@ -1,10 +1,11 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -32,12 +33,12 @@ type unixEpochTime struct { } func (t unixEpochTime) MarshalJSON() ([]byte, error) { - return json.Marshal(t.Unix()) + return json.Marshal(t.Unix(), jsonx.V1()) } func (t *unixEpochTime) UnmarshalJSON(b []byte) error { var epoch int64 - if err := json.Unmarshal(b, &epoch); err != nil { + if err := json.Unmarshal(b, &epoch, jsonx.V1()); err != nil { return err } @@ -105,7 +106,7 @@ func wirePolicyString(plain string) *string { return nil } - quoted, err := json.Marshal(plain) + quoted, err := json.Marshal(plain, jsonx.V1()) if err != nil || len(quoted) < 2 { return nil } diff --git a/services/apigateway/multi_region_test.go b/services/apigateway/multi_region_test.go index 6d509428cc..5f533a7793 100644 --- a/services/apigateway/multi_region_test.go +++ b/services/apigateway/multi_region_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -50,7 +51,7 @@ func apiNames(t *testing.T, h *apigateway.Handler, region string) []string { } `json:"item"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) names := make([]string, 0, len(out.Item)) for _, i := range out.Item { diff --git a/services/apigateway/patch.go b/services/apigateway/patch.go index ed2f5f59d0..10b384088b 100644 --- a/services/apigateway/patch.go +++ b/services/apigateway/patch.go @@ -1,12 +1,15 @@ package apigateway import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // patch.go implements AWS API Gateway's PATCH-operation semantics beyond what @@ -90,10 +93,10 @@ const ( // op used e.g. to promote a canary deployment, // {"op":"copy","from":"/canarySettings/deploymentId","path":"/deploymentId"}. type patchOp struct { - Op string `json:"op"` - Path string `json:"path"` - From string `json:"from,omitempty"` - Value json.RawMessage `json:"value"` + Op string `json:"op"` + Path string `json:"path"` + From string `json:"from,omitempty"` + Value jsontext.Value `json:"value"` } // parsePatchDocument detects and parses a PATCH request body: either a bare @@ -101,7 +104,7 @@ type patchOp struct { // wrapper (the real AWS wire shape), which may carry sibling fields alongside // "patchOperations" (rest). ok is false when body is neither shape, in which // case the caller should treat body as an already-flat field object. -func parsePatchDocument(body []byte) ([]patchOp, map[string]json.RawMessage, bool) { +func parsePatchDocument(body []byte) ([]patchOp, map[string]jsontext.Value, bool) { if len(body) == 0 { return nil, nil, false } @@ -109,7 +112,7 @@ func parsePatchDocument(body []byte) ([]patchOp, map[string]json.RawMessage, boo switch body[0] { case '[': var arr []patchOp - if err := json.Unmarshal(body, &arr); err != nil || len(arr) == 0 || arr[0].Op == "" { + if err := json.Unmarshal(body, &arr, jsonx.V1()); err != nil || len(arr) == 0 || arr[0].Op == "" { return nil, nil, false } @@ -118,13 +121,13 @@ func parsePatchDocument(body []byte) ([]patchOp, map[string]json.RawMessage, boo var wrapper struct { PatchOperations []patchOp `json:"patchOperations"` } - if err := json.Unmarshal(body, &wrapper); err != nil || len(wrapper.PatchOperations) == 0 { + if err := json.Unmarshal(body, &wrapper, jsonx.V1()); err != nil || len(wrapper.PatchOperations) == 0 { return nil, nil, false } - var siblings map[string]json.RawMessage + var siblings map[string]jsontext.Value - _ = json.Unmarshal(body, &siblings) + _ = json.Unmarshal(body, &siblings, jsonx.V1()) delete(siblings, "patchOperations") return wrapper.PatchOperations, siblings, true @@ -180,7 +183,7 @@ var removableTopLevelScalar = map[string]map[string]bool{ // top level. Fields absent from patchFieldKind are assumed to be strings (the // common case, and already correctly a JSON string on the wire) and passed // through unchanged. -func coerceTopLevelPatchValue(field string, raw json.RawMessage) json.RawMessage { +func coerceTopLevelPatchValue(field string, raw jsontext.Value) jsontext.Value { kind, known := patchFieldKind[field] if !known { return raw @@ -194,13 +197,13 @@ func coerceTopLevelPatchValue(field string, raw json.RawMessage) json.RawMessage switch kind { case patchKindBool: if b, parseErr := strconv.ParseBool(s); parseErr == nil { - if encoded, marshalErr := json.Marshal(b); marshalErr == nil { + if encoded, marshalErr := json.Marshal(b, jsonx.V1()); marshalErr == nil { return encoded } } case patchKindInt: if n, parseErr := strconv.Atoi(s); parseErr == nil { - if encoded, marshalErr := json.Marshal(n); marshalErr == nil { + if encoded, marshalErr := json.Marshal(n, jsonx.V1()); marshalErr == nil { return encoded } } @@ -228,13 +231,13 @@ func patchIgnorableErr(err error) bool { // numeric targets (see the package doc above), so every call site that needs // the underlying scalar goes through this and then parses it with strconv. // ok is false when Value is empty/absent or not a JSON string. -func patchValueString(raw json.RawMessage) (string, bool) { +func patchValueString(raw jsontext.Value) (string, bool) { if len(raw) == 0 { return "", false } var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return "", false } @@ -264,8 +267,8 @@ func patchPathSegments(path string) []string { // setJSONValue marshals value and stores it under field in out. Errors are // swallowed (defensive only): every call site below passes a well-formed // built-in Go value that always marshals successfully. -func setJSONValue(out map[string]json.RawMessage, field string, value any) { - raw, err := json.Marshal(value) +func setJSONValue(out map[string]jsontext.Value, field string, value any) { + raw, err := json.Marshal(value, jsonx.V1()) if err != nil { return } @@ -284,7 +287,7 @@ func setJSONValue(out map[string]json.RawMessage, field string, value any) { // discarding whatever an earlier op in the SAME request had already staged // there. ok is false when field isn't staged yet or fails to decode, in // which case the caller must fall back to reading current backend state. -func stagedValue[T any](out map[string]json.RawMessage, field string) (T, bool) { +func stagedValue[T any](out map[string]jsontext.Value, field string) (T, bool) { var v T raw, present := out[field] @@ -292,7 +295,7 @@ func stagedValue[T any](out map[string]json.RawMessage, field string) (T, bool) return v, false } - if err := json.Unmarshal(raw, &v); err != nil { + if err := json.Unmarshal(raw, &v, jsonx.V1()); err != nil { return v, false } @@ -334,7 +337,7 @@ func (h *Handler) applyStructuredPatch(action string, pathParams map[string]stri return body, nil } - out := make(map[string]json.RawMessage, len(rest)+len(ops)) + out := make(map[string]jsontext.Value, len(rest)+len(ops)) maps.Copy(out, rest) for _, op := range ops { @@ -350,7 +353,7 @@ func (h *Handler) applyStructuredPatch(action string, pathParams map[string]stri applyTopLevelPatchOp(action, op, out) } - raw, err := json.Marshal(out) + raw, err := json.Marshal(out, jsonx.V1()) if patchIgnorableErr(err) { return body, nil } @@ -385,7 +388,7 @@ func unmodeledPatchPath(action, path string) error { // "not provided" from "reset to zero value" — a much larger refactor across // every resource's Update backend method than this pass's PATCH-semantics // fix covers in full. Tracked as a follow-up (see PARITY.md gaps). -func applyTopLevelPatchOp(action string, op patchOp, out map[string]json.RawMessage) { +func applyTopLevelPatchOp(action string, op patchOp, out map[string]jsontext.Value) { field := strings.TrimPrefix(op.Path, "/") if field == "" || strings.Contains(field, "/") { return @@ -396,7 +399,7 @@ func applyTopLevelPatchOp(action string, op patchOp, out map[string]json.RawMess out[field] = coerceTopLevelPatchValue(field, op.Value) case patchOpRemove: if removableTopLevelScalar[action][field] { - out[field] = json.RawMessage(`""`) + out[field] = jsontext.Value(`""`) } } } @@ -408,7 +411,7 @@ func applyTopLevelPatchOp(action string, op patchOp, out map[string]json.RawMess // is one this action must reject, or (false, nil) to fall through to the // generic top-level fallback. type resourcePatchResolver func( - h *Handler, pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + h *Handler, pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) // resourcePatchResolvers maps each action with map/struct/list/rejectable @@ -440,7 +443,7 @@ var resourcePatchResolvers = map[string]resourcePatchResolver{ // single-field replace cannot express. See resourcePatchResolver's doc // comment for the return-value contract. func (h *Handler) applyResourcePatchOp( - action string, pathParams map[string]string, op patchOp, out map[string]json.RawMessage, + action string, pathParams map[string]string, op patchOp, out map[string]jsontext.Value, ) (bool, error) { segs := patchPathSegments(op.Path) if len(segs) == 0 { @@ -460,7 +463,7 @@ func (h *Handler) applyResourcePatchOp( // stage-variable edits, single canarySettings/accessLogSettings sub-fields, // and per-route method settings. func (h *Handler) applyStagePatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if op.Op == patchOpCopy && op.Path == "/deploymentId" && op.From == "/canarySettings/deploymentId" { stage, err := h.Backend.GetStage(pathParams[keyRestAPIID], pathParams[keyStageName]) @@ -499,7 +502,7 @@ func (h *Handler) applyStagePatchOp( // with whatever an earlier op in the SAME request already staged into // out["variables"] (see stagedValue's doc comment). func (h *Handler) applyStageVariablePatch( - pathParams map[string]string, op patchOp, rawName string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, rawName string, out map[string]jsontext.Value, ) bool { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return false @@ -534,7 +537,7 @@ func (h *Handler) applyStageVariablePatch( // with the stage's existing canary settings and whatever an earlier op in the // SAME request already staged into out["canarySettings"]. func (h *Handler) applyStageCanaryPatch( - pathParams map[string]string, op patchOp, prop string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, prop string, out map[string]jsontext.Value, ) bool { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return false @@ -595,7 +598,7 @@ func applyStageCanaryProp(cur *CanarySettings, prop, val string, remove bool) bo // contents are themselves a JSON-encoded {name: value} object. if !remove { var overrides map[string]string - if json.Unmarshal([]byte(val), &overrides) == nil { + if json.Unmarshal([]byte(val), &overrides, jsonx.V1()) == nil { cur.StageVariableOverrides = overrides } } @@ -611,7 +614,7 @@ func applyStageCanaryProp(cur *CanarySettings, prop, val string, remove bool) bo // existing access log settings and whatever an earlier op in the SAME // request already staged into out["accessLogSettings"]. func (h *Handler) applyStageAccessLogPatch( - pathParams map[string]string, op patchOp, prop string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, prop string, out map[string]jsontext.Value, ) bool { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return false @@ -737,7 +740,7 @@ func parseBoolLenient(v string) bool { // (e.g. "/~1pets/GET/throttling/burstLimit" or "/*/*/logging/loglevel") — // merged with the stage's existing per-route overrides. func (h *Handler) applyStageMethodSettingPatch( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) bool { apply, known := stageMethodSettingProperty[strings.Join(segs[2:], "/")] if !known || (op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove) { @@ -773,7 +776,7 @@ func (h *Handler) applyStageMethodSettingPatch( // silently drop every other configured type) and whatever an earlier op in // the SAME request already staged into out["binaryMediaTypes"]. func (h *Handler) applyRestAPIPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != patchPathSegs2 || segs[0] != "binaryMediaTypes" { return false, nil @@ -823,7 +826,7 @@ const accountFeatureUsagePlans = "UsagePlans" // membership. "/cloudwatchRoleArn" is a plain top-level string field and is // handled by the generic fallback (applyTopLevelPatchOp). func (h *Handler) applyAccountPatchOp( - _ map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + _ map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) == 1 && segs[0] == "features" { return h.applyAccountFeaturesPatch(op, out) @@ -892,7 +895,7 @@ func applyAccountThrottleProp(cur *ThrottleSettings, prop, val string, remove bo // removing accountFeatureUsagePlans, matching patch-operations.html's // documented exception, and any op other than add/remove (replace is "Not // supported"). -func (h *Handler) applyAccountFeaturesPatch(op patchOp, out map[string]json.RawMessage) (bool, error) { +func (h *Handler) applyAccountFeaturesPatch(op patchOp, out map[string]jsontext.Value) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpRemove { return true, unsupportedPatchOp("/features", op.Op) } @@ -941,7 +944,7 @@ func (h *Handler) applyAccountFeaturesPatch(op patchOp, out map[string]json.RawM // earlier op in this request has touched apiStages yet. ok is false only // when the plan itself can't be resolved. func (h *Handler) currentUsagePlanAPIStages( - pathParams map[string]string, out map[string]json.RawMessage, + pathParams map[string]string, out map[string]jsontext.Value, ) ([]APIStageAssociation, bool) { if staged, ok := stagedValue[[]APIStageAssociation](out, "apiStages"); ok { return staged, true @@ -962,7 +965,7 @@ func (h *Handler) currentUsagePlanAPIStages( // applyUsagePlanThrottlePatch) — see the AWS "UpdateUsagePlan" patch-operations // reference. func (h *Handler) applyUsagePlanPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) == 1 && segs[0] == "apiStages" { return h.applyUsagePlanAPIStageMembershipPatch(pathParams, op, out), nil @@ -978,7 +981,7 @@ func (h *Handler) applyUsagePlanPatchOp( // applyUsagePlanAPIStageMembershipPatch handles the whole-apiStage add/remove // case ("/apiStages", Value "{restApiId}:{stage}"). func (h *Handler) applyUsagePlanAPIStageMembershipPatch( - pathParams map[string]string, op patchOp, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, out map[string]jsontext.Value, ) bool { if op.Op != patchOpAdd && op.Op != patchOpRemove { return false @@ -1038,7 +1041,7 @@ const usagePlanThrottlePathMinSegs = 5 // APIStageAssociation.Throttle elsewhere in this service (see usage.go's // effectiveThrottle and CreateUsagePlan's test fixtures). func (h *Handler) applyUsagePlanThrottlePatch( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) bool { if len(segs) < usagePlanThrottlePathMinSegs || len(segs) > usagePlanThrottlePathMinSegs+1 { return false @@ -1139,7 +1142,7 @@ func (h *Handler) mergeUsagePlanThrottleEntry( // default response when none has been customized yet) and whatever an // earlier op in the SAME request already staged into out[segs[0]]. func (h *Handler) applyGatewayResponsePatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != patchPathSegs2 || (segs[0] != fieldResponseParameters && segs[0] != "responseTemplates") { return false, nil @@ -1185,7 +1188,7 @@ func (h *Handler) applyGatewayResponsePatchOp( // StageKeys (a wholesale replace would otherwise silently drop every other // associated stage). func (h *Handler) applyAPIKeyPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != 1 || segs[0] != "stages" { return false, nil @@ -1236,7 +1239,7 @@ func (h *Handler) applyAPIKeyPatchOp( // had no case for opUpdateDomainName at all, so every nested DomainName PATCH // path silently no-opped via applyTopLevelPatchOp's path-contains-"/" guard. func (h *Handler) applyDomainNamePatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != patchPathSegs2 { return false, nil @@ -1258,7 +1261,7 @@ func (h *Handler) applyDomainNamePatchOp( // and whatever an earlier op in the SAME request already staged into // out["endpointConfiguration"]. func (h *Handler) applyDomainNameEndpointConfigPatch( - pathParams map[string]string, op patchOp, prop string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, prop string, out map[string]jsontext.Value, ) bool { cur, ok := stagedValue[EndpointConfiguration](out, "endpointConfiguration") if !ok { @@ -1310,7 +1313,7 @@ func (h *Handler) applyDomainNameEndpointConfigPatch( // with the domain name's existing mTLS configuration and whatever an earlier // op in the SAME request already staged into out["mutualTlsAuthentication"]. func (h *Handler) applyDomainNameMTLSPatch( - pathParams map[string]string, op patchOp, prop string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, prop string, out map[string]jsontext.Value, ) bool { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return false @@ -1354,7 +1357,7 @@ func (h *Handler) applyDomainNameMTLSPatch( // patch-operations.html's UpdateResource table documents both paths as // replace-only. func (h *Handler) applyResourceEntityPatchOp( - _ map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + _ map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != 1 || segs[0] != "parentId" { return false, nil @@ -1398,7 +1401,7 @@ func (h *Handler) applyResourceEntityPatchOp( // decision). "/restApiId" and "/stage" are spelled identically in every AWS // source and already work via the generic fallback (applyTopLevelPatchOp). func (h *Handler) applyBasePathMappingPatchOp( - _ map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + _ map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != 1 { return false, nil @@ -1431,7 +1434,7 @@ func (h *Handler) applyBasePathMappingPatchOp( // json.Unmarshal then failed the WHOLE PATCH request with a 500 (same bug // class as UpdateIntegration's /cacheKeyParameters). func (h *Handler) applyAuthorizerPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != 1 || segs[0] != "providerARNs" { return false, nil @@ -1484,7 +1487,7 @@ func (h *Handler) applyAuthorizerPatchOp( // requestValidatorId) are plain replace-only fields left to the generic // fallback. func (h *Handler) applyMethodPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) == 1 && segs[0] == "authorizationScopes" { return true, unmodeledPatchPath(opUpdateMethod, op.Path) @@ -1510,7 +1513,7 @@ func (h *Handler) applyMethodPatchOp( // silently drop every other parameter) and whatever an earlier op in the SAME // request already staged into out["requestParameters"]. func (h *Handler) applyMethodRequestParameterPatch( - pathParams map[string]string, op patchOp, rawName string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, rawName string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/requestParameters", op.Op) @@ -1546,7 +1549,7 @@ func (h *Handler) applyMethodRequestParameterPatch( // existing RequestModels and whatever an earlier op in the SAME request // already staged into out["requestModels"]. func (h *Handler) applyMethodRequestModelPatch( - pathParams map[string]string, op patchOp, rawContentType string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, rawContentType string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/requestModels", op.Op) @@ -1587,7 +1590,7 @@ func (h *Handler) applyMethodRequestModelPatch( // connectionId, connectionType, contentHandling, httpMethod, passthroughBehavior, // uri, timeoutInMillis) are plain replace-only fields left to the generic fallback. func (h *Handler) applyIntegrationPatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) == 1 { return h.applyIntegrationTopLevelPatchOp(pathParams, op, segs[0], out) @@ -1613,7 +1616,7 @@ func (h *Handler) applyIntegrationPatchOp( // PATCH paths that need explicit rejection or list-membership merging rather // than the generic scalar fallback. func (h *Handler) applyIntegrationTopLevelPatchOp( - pathParams map[string]string, op patchOp, field string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, field string, out map[string]jsontext.Value, ) (bool, error) { switch field { case "type": @@ -1636,7 +1639,7 @@ func (h *Handler) applyIntegrationTopLevelPatchOp( // matching this file's other single-segment list-membership paths // (UpdateApiKey's "/stages", UpdateRestApi's "/binaryMediaTypes"). func (h *Handler) applyIntegrationCacheKeyParametersPatch( - pathParams map[string]string, op patchOp, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/cacheKeyParameters", op.Op) @@ -1681,7 +1684,7 @@ func (h *Handler) applyIntegrationCacheKeyParametersPatch( // with the integration's existing map and whatever an earlier op in the SAME // request already staged into out[field]. func (h *Handler) applyIntegrationMapPatch( - pathParams map[string]string, op patchOp, field, rawKey string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, field, rawKey string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/"+field, op.Op) @@ -1722,7 +1725,7 @@ func (h *Handler) applyIntegrationMapPatch( // edits. "/contentHandling" and "/selectionPattern" are plain top-level // replace-only fields left to the generic fallback. func (h *Handler) applyIntegrationResponsePatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != patchPathSegs2 { return false, nil @@ -1743,7 +1746,7 @@ func (h *Handler) applyIntegrationResponsePatchOp( // merging with the integration response's existing map and whatever an // earlier op in the SAME request already staged into out[field]. func (h *Handler) applyIntegrationResponseMapPatch( - pathParams map[string]string, op patchOp, field, rawKey string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, field, rawKey string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/"+field, op.Op) @@ -1782,7 +1785,7 @@ func (h *Handler) applyIntegrationResponseMapPatch( // applyMethodResponsePatchOp handles UpdateMethodResponse's per-key // "/responseModels/{content-type}" and "/responseParameters/{name}" map edits. func (h *Handler) applyMethodResponsePatchOp( - pathParams map[string]string, op patchOp, segs []string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, segs []string, out map[string]jsontext.Value, ) (bool, error) { if len(segs) != patchPathSegs2 { return false, nil @@ -1803,7 +1806,7 @@ func (h *Handler) applyMethodResponsePatchOp( // method response's existing ResponseModels and whatever an earlier op in the // SAME request already staged into out["responseModels"]. func (h *Handler) applyMethodResponseModelPatch( - pathParams map[string]string, op patchOp, rawContentType string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, rawContentType string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/responseModels", op.Op) @@ -1840,7 +1843,7 @@ func (h *Handler) applyMethodResponseModelPatch( // method response's existing ResponseParameters and whatever an earlier op in // the SAME request already staged into out["responseParameters"]. func (h *Handler) applyMethodResponseParameterPatch( - pathParams map[string]string, op patchOp, rawName string, out map[string]json.RawMessage, + pathParams map[string]string, op patchOp, rawName string, out map[string]jsontext.Value, ) (bool, error) { if op.Op != patchOpAdd && op.Op != patchOpReplace && op.Op != patchOpRemove { return true, unsupportedPatchOp("/responseParameters", op.Op) diff --git a/services/apigateway/persistence.go b/services/apigateway/persistence.go index 638d739a53..bd9e89b343 100644 --- a/services/apigateway/persistence.go +++ b/services/apigateway/persistence.go @@ -2,7 +2,7 @@ package apigateway import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -414,7 +414,7 @@ var dirtyTableNames = struct { // registerAllTables doc for the clean/dirty split), merged into one map so a // single Tables blob round-trips the whole backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Account *Account `json:"account,omitempty"` UsageOverrides map[string]map[string]int64 `json:"usageOverrides,omitempty"` Version int `json:"version"` diff --git a/services/apigateway/proxy.go b/services/apigateway/proxy.go index bcce84fde1..bb7210f8ed 100644 --- a/services/apigateway/proxy.go +++ b/services/apigateway/proxy.go @@ -3,7 +3,8 @@ package apigateway import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "github.com/golang-jwt/jwt/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -410,7 +412,7 @@ func writeThrottleResponse(w http.ResponseWriter, errorType, message string) { w.Header().Set(headerContentType, "application/json") w.Header().Set("X-Amzn-Errortype", errorType) w.WriteHeader(http.StatusTooManyRequests) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: message}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{jsonMessageKey: message}) } // writeMissingAuthenticationTokenResponse writes AWS API Gateway's real response for a @@ -423,7 +425,10 @@ func writeMissingAuthenticationTokenResponse(w http.ResponseWriter) { w.Header().Set(headerContentType, "application/json") w.Header().Set("X-Amzn-Errortype", "MissingAuthenticationTokenException") w.WriteHeader(http.StatusForbidden) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: "Missing Authentication Token"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{jsonMessageKey: "Missing Authentication Token"}, + ) } // dispatchIntegration routes the request to the appropriate integration handler. diff --git a/services/apigateway/proxy_authorizer.go b/services/apigateway/proxy_authorizer.go index 0c96694f72..28470245db 100644 --- a/services/apigateway/proxy_authorizer.go +++ b/services/apigateway/proxy_authorizer.go @@ -3,7 +3,8 @@ package apigateway import ( "container/list" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -162,7 +164,7 @@ func authorizerTTL(auth *Authorizer) time.Duration { func writeAuthorizerError(w http.ResponseWriter, status int, message string) { w.Header().Set(headerContentType, "application/json") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: message}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{jsonMessageKey: message}) } // runAuthorizer enforces the method's authorizer and returns true if the request @@ -219,7 +221,7 @@ func (h *Handler) runAuthorizer( event := h.buildAuthorizerEvent(ctx, r, auth, apiID, stageName) event.MethodArn = methodArn - payload, _ := json.Marshal(event) + payload, _ := json.Marshal(event, jsonx.V1()) funcName := ExtractLambdaFunctionName(auth.AuthorizerURI) respBytes, _, invokeErr := h.lambda.InvokeFunction(ctx, funcName, "RequestResponse", payload) @@ -232,7 +234,7 @@ func (h *Handler) runAuthorizer( } var authResp AuthorizerResponse - if parseErr := json.Unmarshal(respBytes, &authResp); parseErr != nil { + if parseErr := json.Unmarshal(respBytes, &authResp, jsonx.V1()); parseErr != nil { logger.Load(ctx).WarnContext(ctx, "APIGateway proxy: failed to parse authorizer response", "error", parseErr) writeAuthorizerError(w, http.StatusUnauthorized, msgUnauthorized) diff --git a/services/apigateway/proxy_authorizer_cache_internal_test.go b/services/apigateway/proxy_authorizer_cache_internal_test.go index b793aa2be4..0b5deb1697 100644 --- a/services/apigateway/proxy_authorizer_cache_internal_test.go +++ b/services/apigateway/proxy_authorizer_cache_internal_test.go @@ -2,7 +2,7 @@ package apigateway import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "sync/atomic" @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // policyInvoker allows only callers whose "auth" header (or token) is in allowed, for allowedARN. @@ -25,7 +27,7 @@ func (p *policyInvoker) InvokeFunction(_ context.Context, _, _ string, payload [ p.calls.Add(1) var ev AuthorizerEvent - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, http.StatusInternalServerError, err } @@ -49,7 +51,7 @@ func (p *policyInvoker) InvokeFunction(_ context.Context, _, _ string, payload [ PolicyDocument: &PolicyDocument{Statement: []PolicyStatement{ {Effect: effect, Action: "execute-api:Invoke", Resource: res}, }}, - }) + }, jsonx.V1()) return body, http.StatusOK, nil } diff --git a/services/apigateway/proxy_authorizer_test.go b/services/apigateway/proxy_authorizer_test.go index 0a90c96f6f..b47bd5fa19 100644 --- a/services/apigateway/proxy_authorizer_test.go +++ b/services/apigateway/proxy_authorizer_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -53,13 +54,13 @@ func setupAuthorizerAPI( require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) // Get root resource. listRec := postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rootID := listResp["item"].([]any)[0].(map[string]any)["id"].(string) // Create /secure resource. @@ -68,7 +69,7 @@ func setupAuthorizerAPI( require.Equal(t, http.StatusCreated, childRec.Code) var childResp map[string]any - require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp)) + require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) // Create authorizer. @@ -83,7 +84,7 @@ func setupAuthorizerAPI( require.Equal(t, http.StatusCreated, authRec.Code) var authResp map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) authID := authResp["id"].(string) // PutMethod with authorizerId. @@ -280,7 +281,7 @@ func TestRunAuthorizer_MethodArn_ResourcePath(t *testing.T) { // Verify the methodArn in the captured event uses the stripped resource path ("/secure"), // not the full proxy path ("/restapis/.../prod/_user_request_/secure"). var event map[string]any - require.NoError(t, json.Unmarshal(capturedPayload, &event)) + require.NoError(t, json.Unmarshal(capturedPayload, &event, jsonx.V1())) methodArn, _ := event["methodArn"].(string) assert.Contains(t, methodArn, "/secure", "methodArn should contain the stripped path") assert.NotContains(t, methodArn, "_user_request_", "methodArn must not contain internal proxy prefix") @@ -856,12 +857,12 @@ func TestRunCognitoAuthorizer_ValidToken(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) listRec := postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rootID := listResp["item"].([]any)[0].(map[string]any)["id"].(string) childRec := postWithHandler(t, h, e, "CreateResource", @@ -869,7 +870,7 @@ func TestRunCognitoAuthorizer_ValidToken(t *testing.T) { require.Equal(t, http.StatusCreated, childRec.Code) var childResp map[string]any - require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp)) + require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) authBody := `{ @@ -882,7 +883,7 @@ func TestRunCognitoAuthorizer_ValidToken(t *testing.T) { require.Equal(t, http.StatusCreated, authRec.Code) var authResp map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) authID := authResp["id"].(string) putMethodBody := `{"restApiId":"` + apiID + `","resourceId":"` + childID + diff --git a/services/apigateway/proxy_integrations.go b/services/apigateway/proxy_integrations.go index 9ccf56b2c7..6883f14023 100644 --- a/services/apigateway/proxy_integrations.go +++ b/services/apigateway/proxy_integrations.go @@ -4,7 +4,8 @@ import ( "container/list" "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "mime" @@ -16,6 +17,7 @@ import ( "sync" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -43,7 +45,7 @@ func (h *Handler) handleAWSProxy( return } - payload, _ := json.Marshal(event) + payload, _ := json.Marshal(event, jsonx.V1()) respBytes, _, invokeErr := h.lambda.InvokeFunction( ctx, @@ -315,7 +317,10 @@ func writeAWSIntegrationReadError(ctx context.Context, w http.ResponseWriter, re w.Header().Set(headerContentType, contentTypeJSON) w.Header().Set("X-Amzn-Errortype", "UnsupportedMediaTypeException") w.WriteHeader(http.StatusUnsupportedMediaType) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: "Unsupported Media Type"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{jsonMessageKey: "Unsupported Media Type"}, + ) return } @@ -983,7 +988,10 @@ func writeInternalServerError(w http.ResponseWriter, status int) { w.Header().Set(headerContentType, "application/json") w.Header().Set("X-Amzn-Errortype", "InternalServerErrorException") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: "Internal server error"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{jsonMessageKey: "Internal server error"}, + ) } var errMalformedProxyResponse = errors.New("malformed Lambda proxy response") @@ -997,8 +1005,8 @@ const ( // way execute-api does: a JSON object with an integer statusCode, and // string-valued headers and body. func parseLambdaProxyResponse(raw []byte) (*LambdaProxyResponse, error) { - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil || obj == nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil || obj == nil { return nil, errMalformedProxyResponse } @@ -1009,14 +1017,14 @@ func parseLambdaProxyResponse(raw []byte) (*LambdaProxyResponse, error) { return nil, errMalformedProxyResponse } - var n json.Number - if err := json.Unmarshal(code, &n); err != nil { + var n jsonx.Number + if err := json.Unmarshal(code, &n, jsonx.V1()); err != nil { var str string - if json.Unmarshal(code, &str) != nil { + if json.Unmarshal(code, &str, jsonx.V1()) != nil { return nil, errMalformedProxyResponse } - n = json.Number(str) + n = jsonx.Number(str) } status, err := strconv.Atoi(n.String()) @@ -1045,13 +1053,13 @@ func parseLambdaProxyResponse(raw []byte) (*LambdaProxyResponse, error) { return &resp, nil } -func decodeProxyField(obj map[string]json.RawMessage, key string, dst any) error { +func decodeProxyField(obj map[string]jsontext.Value, key string, dst any) error { raw, ok := obj[key] if !ok || string(raw) == jsonNull { return nil } - if err := json.Unmarshal(raw, dst); err != nil { + if err := json.Unmarshal(raw, dst, jsonx.V1()); err != nil { return errMalformedProxyResponse } diff --git a/services/apigateway/proxy_mapping_test.go b/services/apigateway/proxy_mapping_test.go index 419b1564d6..ede2c06342 100644 --- a/services/apigateway/proxy_mapping_test.go +++ b/services/apigateway/proxy_mapping_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -45,14 +46,14 @@ func setupMappingAPI( rec := postWithHandler(t, h, e, "CreateRestApi", `{"name":"map-api"}`) require.Equal(t, http.StatusCreated, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) apiID := created["id"].(string) rec = postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) var list map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &list, jsonx.V1())) rootID := list["item"].([]any)[0].(map[string]any)["id"].(string) rec = postWithHandler(t, h, e, "CreateResource", @@ -61,7 +62,7 @@ func setupMappingAPI( var child map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &child)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &child, jsonx.V1())) resID := child["id"].(string) base := `"restApiId":"` + apiID + `","resourceId":"` + resID + `","httpMethod":"POST"` diff --git a/services/apigateway/proxy_test.go b/services/apigateway/proxy_test.go index 86d2a91b89..c6bdf3755f 100644 --- a/services/apigateway/proxy_test.go +++ b/services/apigateway/proxy_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -70,7 +71,7 @@ func setupProxyAPIViaHandler( require.Equal(tb, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(tb, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(tb, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) // Get root resource. @@ -78,7 +79,7 @@ func setupProxyAPIViaHandler( require.Equal(tb, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(tb, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(tb, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rootID := listResp["item"].([]any)[0].(map[string]any)["id"].(string) // Create child resource. @@ -87,7 +88,7 @@ func setupProxyAPIViaHandler( require.Equal(tb, http.StatusCreated, childRec.Code) var childResp map[string]any - require.NoError(tb, json.Unmarshal(childRec.Body.Bytes(), &childResp)) + require.NoError(tb, json.Unmarshal(childRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) // PutMethod. @@ -270,18 +271,18 @@ func setupVTLAPI(t *testing.T) (*apigateway.Handler, *echo.Echo, string) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) listRec := postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rootID := listResp["item"].([]any)[0].(map[string]any)["id"].(string) childRec := postWithHandler(t, h, e, "CreateResource", `{"restApiId":"`+apiID+`","parentId":"`+rootID+`","pathPart":"transform"}`) var childResp map[string]any - require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp)) + require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) postWithHandler(t, h, e, "PutMethod", @@ -332,7 +333,7 @@ func TestHandleAWSIntegration(t *testing.T) { checkCapture: func(t *testing.T, captured []byte) { t.Helper() var got map[string]any - require.NoError(t, json.Unmarshal(captured, &got)) + require.NoError(t, json.Unmarshal(captured, &got, jsonx.V1())) assert.Equal(t, "alice", got["name"]) }, }, @@ -484,14 +485,14 @@ func setupProxyAPIWithResource( createRec := postWithHandler(t, h, e, "CreateRestApi", `{"name":"path-api","description":"test"}`) require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) // Get root resource ID by finding the resource with path "/". listRec := postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["item"].([]any) var parentID string @@ -519,7 +520,7 @@ func setupProxyAPIWithResource( `{"restApiId":"`+apiID+`","parentId":"`+parentID+`","pathPart":"`+part+`"}`) require.Equal(t, http.StatusCreated, r.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1())) parentID = resp["id"].(string) } } @@ -635,7 +636,7 @@ func TestPathVariableMatching(t *testing.T) { checkEvent: func(t *testing.T, payload []byte) { t.Helper() var event map[string]any - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) params, _ := event["pathParameters"].(map[string]any) assert.Equal(t, "42", params["id"]) }, @@ -648,7 +649,7 @@ func TestPathVariableMatching(t *testing.T) { checkEvent: func(t *testing.T, payload []byte) { t.Helper() var event map[string]any - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) params, _ := event["pathParameters"].(map[string]any) assert.Equal(t, "/a/b/c", params["proxy"]) }, @@ -891,20 +892,20 @@ func TestHandleProxyRequest_RequiresDeployedStage(t *testing.T) { createRec := postWithHandler(t, h, e, "CreateRestApi", `{"name":"gate-api"}`) require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiID := createResp["id"].(string) listRec := postWithHandler(t, h, e, "GetResources", `{"restApiId":"`+apiID+`"}`) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rootID := listResp["item"].([]any)[0].(map[string]any)["id"].(string) childRec := postWithHandler(t, h, e, "CreateResource", `{"restApiId":"`+apiID+`","parentId":"`+rootID+`","pathPart":"items"}`) require.Equal(t, http.StatusCreated, childRec.Code) var childResp map[string]any - require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp)) + require.NoError(t, json.Unmarshal(childRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) methodRec := postWithHandler(t, h, e, "PutMethod", diff --git a/services/apigateway/proxy_validation.go b/services/apigateway/proxy_validation.go index a1040aaaf9..900d019f8d 100644 --- a/services/apigateway/proxy_validation.go +++ b/services/apigateway/proxy_validation.go @@ -2,13 +2,15 @@ package apigateway import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/url" "sort" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -72,7 +74,7 @@ func (h *Handler) validateRequestBody( // Replace body so downstream handlers can still read it. r.Body = io.NopCloser(strings.NewReader(string(bodyBytes))) - if len(bodyBytes) == 0 || !json.Valid(bodyBytes) { + if len(bodyBytes) == 0 || !jsontext.Value(bodyBytes).IsValid(jsonx.V1()) { writeValidationError(w, "Invalid request body") return true @@ -130,7 +132,7 @@ func writeValidationError(w http.ResponseWriter, message string) { w.Header().Set(headerContentType, "application/json") w.Header().Set("X-Amzn-Errortype", "BadRequestException") w.WriteHeader(http.StatusBadRequest) - _ = json.NewEncoder(w).Encode(map[string]string{jsonMessageKey: message}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{jsonMessageKey: message}) } // missingRequiredParameters returns the names of required request parameters (as diff --git a/services/apigateway/proxy_validation_test.go b/services/apigateway/proxy_validation_test.go index 7e548fb38a..c6427c69af 100644 --- a/services/apigateway/proxy_validation_test.go +++ b/services/apigateway/proxy_validation_test.go @@ -4,7 +4,7 @@ import ( "compress/gzip" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -616,7 +617,7 @@ func TestProxy_StageVariables_InterpolatedInURI(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) // The invoker receives the payload; check the captured function name via the event. var event map[string]any - require.NoError(t, json.Unmarshal(capturedPayload, &event)) + require.NoError(t, json.Unmarshal(capturedPayload, &event, jsonx.V1())) // Response comes from captureInvoker which echoes the payload back, so status is 200. // The important check is that the handler resolved the stage variable without panicking. } @@ -902,7 +903,7 @@ func TestProxy_AuthorizerCacheKey_IdentityValidationExpression(t *testing.T) { authRec := postWithHandler(t, h, e, "CreateAuthorizer", authBody) require.Equal(t, http.StatusCreated, authRec.Code) var auth map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &auth)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &auth, jsonx.V1())) authID := auth["id"].(string) _, _ = backend.PutMethod(apigateway.PutMethodInput{ diff --git a/services/apigateway/request_validators_test.go b/services/apigateway/request_validators_test.go index 1eac7c110d..2f750b2761 100644 --- a/services/apigateway/request_validators_test.go +++ b/services/apigateway/request_validators_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -46,7 +47,7 @@ func TestUpdateRequestValidator(t *testing.T) { fmt.Sprintf(`{"restApiId":%q,"name":"orig-validator"}`, apiID)) require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) validatorID := createResp["id"].(string) lookupID := validatorID diff --git a/services/apigateway/resources_test.go b/services/apigateway/resources_test.go index 269a48cbe4..20e5cd6053 100644 --- a/services/apigateway/resources_test.go +++ b/services/apigateway/resources_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -46,7 +48,7 @@ func TestGetResources_NoPositionOnLastPage(t *testing.T) { require.True(t, apiRec.Code >= 200 && apiRec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(apiRec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(apiRec.Body), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -55,7 +57,7 @@ func TestGetResources_NoPositionOnLastPage(t *testing.T) { require.True(t, resRec.Code >= 200 && resRec.Code < 300) var resResp map[string]any - require.NoError(t, json.NewDecoder(resRec.Body).Decode(&resResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resRec.Body), &resResp, jsonx.V1())) items := resResp["item"].([]any) rootID := items[0].(map[string]any)["id"].(string) @@ -69,7 +71,7 @@ func TestGetResources_NoPositionOnLastPage(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) _, hasPosition := resp["position"] assert.False(t, hasPosition, @@ -162,7 +164,7 @@ func TestUpdateResource(t *testing.T) { fmt.Sprintf(`{"restApiId":%q,"parentId":%q,"pathPart":"original"}`, apiID, rootID)) require.Equal(t, http.StatusCreated, createRec.Code) var childResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &childResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &childResp, jsonx.V1())) childID := childResp["id"].(string) lookupID := childID diff --git a/services/apigateway/rest_api_policy_wire_test.go b/services/apigateway/rest_api_policy_wire_test.go index 421b35a722..d2b2ea92be 100644 --- a/services/apigateway/rest_api_policy_wire_test.go +++ b/services/apigateway/rest_api_policy_wire_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -55,9 +56,9 @@ func TestRestAPIPolicy_WireReEscaping(t *testing.T) { var created struct { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) - patchValue, err := json.Marshal(tt.plainPolicy) + patchValue, err := json.Marshal(tt.plainPolicy, jsonx.V1()) require.NoError(t, err) patchBody := `{"patchOperations":[{"op":"replace","path":"/policy","value":` + string(patchValue) + `}]}` @@ -68,7 +69,7 @@ func TestRestAPIPolicy_WireReEscaping(t *testing.T) { var resp struct { Policy string `json:"policy"` } - require.NoError(t, json.Unmarshal(patchRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(patchRec.Body.Bytes(), &resp, jsonx.V1())) // Mirror terraform-provider-aws's flattenAPIPolicy: wrap in // literal quotes, then unquote -- must recover the plain policy. diff --git a/services/apigateway/rest_apis_test.go b/services/apigateway/rest_apis_test.go index 497a16a2a8..40e666f7c1 100644 --- a/services/apigateway/rest_apis_test.go +++ b/services/apigateway/rest_apis_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -54,7 +56,7 @@ func TestGetRestApis_NoPositionOnLastPage(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) _, hasPosition := resp["position"] assert.False(t, hasPosition, @@ -212,7 +214,7 @@ func TestUpdateRestAPI(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.newName, resp["name"]) } }) @@ -365,7 +367,7 @@ func TestGetRestAPIs_RESTPath_WithLimit(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["item"]) }) } diff --git a/services/apigateway/route_matcher_proxy_test.go b/services/apigateway/route_matcher_proxy_test.go index a140686e48..5d305df476 100644 --- a/services/apigateway/route_matcher_proxy_test.go +++ b/services/apigateway/route_matcher_proxy_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/apigateway" "github.com/blackbirdworks/gopherstack/services/s3" @@ -66,7 +67,7 @@ func jsonAction(t *testing.T, client *http.Client, baseURL, action, body string, require.NoError(t, err) if out != nil && len(respBody) > 0 { - require.NoError(t, json.Unmarshal(respBody, out)) + require.NoError(t, json.Unmarshal(respBody, out, jsonx.V1())) } return resp.StatusCode diff --git a/services/apigateway/schema_models.go b/services/apigateway/schema_models.go index fdd130f49b..993dcda0ff 100644 --- a/services/apigateway/schema_models.go +++ b/services/apigateway/schema_models.go @@ -1,10 +1,13 @@ package apigateway import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // CreateModel creates a data model for a REST API. @@ -25,7 +28,7 @@ func (b *InMemoryBackend) CreateModel(input CreateModelInput) (*Model, error) { return nil, fmt.Errorf("%w: Model name must be alphanumeric", ErrInvalidParameter) } - if input.Schema != "" && !json.Valid([]byte(input.Schema)) { + if input.Schema != "" && !jsontext.Value([]byte(input.Schema)).IsValid(jsonx.V1()) { return nil, fmt.Errorf("%w: Invalid model specified: schema is not valid JSON", ErrInvalidParameter) } @@ -95,13 +98,13 @@ func (b *InMemoryBackend) GetModel(restAPIID, modelName string, flatten bool) (* // JSON, or a $ref naming no model in this REST API, is left untouched. func flattenModelSchema(b *InMemoryBackend, restAPIID, schema string, visiting map[string]bool) string { var node any - if err := json.Unmarshal([]byte(schema), &node); err != nil { + if err := json.Unmarshal([]byte(schema), &node, jsonx.V1()); err != nil { return schema } resolved := resolveModelRefNode(b, restAPIID, node, visiting) - out, err := json.Marshal(resolved) + out, err := json.Marshal(resolved, jsonx.V1()) if err != nil { return schema } @@ -150,7 +153,7 @@ func resolveModelRefNode(b *InMemoryBackend, restAPIID string, node any, visitin func resolveModelRef(b *InMemoryBackend, restAPIID, ref string, visiting map[string]bool) (any, bool) { refJSON, err := json.Marshal(struct { Ref string `json:"$ref"` - }{Ref: ref}) + }{Ref: ref}, jsonx.V1()) if err != nil { return nil, false } @@ -172,7 +175,7 @@ func resolveModelRef(b *InMemoryBackend, restAPIID, ref string, visiting map[str nested[name] = true var decoded any - if unmarshalErr := json.Unmarshal([]byte(m.Schema), &decoded); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal([]byte(m.Schema), &decoded, jsonx.V1()); unmarshalErr != nil { return nil, false } diff --git a/services/apigateway/schema_models_test.go b/services/apigateway/schema_models_test.go index 723371ee1a..924161cbf8 100644 --- a/services/apigateway/schema_models_test.go +++ b/services/apigateway/schema_models_test.go @@ -1,13 +1,16 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAPIGW_Models covers GetModel, GetModels, CreateModel, DeleteModel. @@ -21,7 +24,7 @@ func TestAPIGW_Models(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "expected 2xx") var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &apiResp, jsonx.V1())) apiID, _ := apiResp["id"].(string) require.NotEmpty(t, apiID) @@ -90,7 +93,7 @@ func TestGetModel_Flatten(t *testing.T) { var got struct { Schema string `json:"schema"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &got, jsonx.V1())) assert.JSONEq(t, tt.wantSchema, got.Schema) }) } @@ -117,7 +120,7 @@ func TestGetModel_FlattenSelfCycle(t *testing.T) { var got struct { Schema string `json:"schema"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &got, jsonx.V1())) assert.JSONEq(t, `{"$ref":"https://apigateway.amazonaws.com/restapis/{restApiId}/models/Node"}`, got.Schema) } diff --git a/services/apigateway/sdk.go b/services/apigateway/sdk.go index 7b531c0fab..57fa5491d5 100644 --- a/services/apigateway/sdk.go +++ b/services/apigateway/sdk.go @@ -3,8 +3,11 @@ package apigateway import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // SdkType describes a code-generation target supported by GetSdk. AWS @@ -87,7 +90,7 @@ func (b *InMemoryBackend) GetSdk( ctx := exportContext{b: b, restAPIID: restAPIID, apiName: api.Name, opts: ExportOptions{Integrations: true}} spec := buildOAS30Export(ctx, stageName) - specJSON, err := json.MarshalIndent(spec, "", " ") + specJSON, err := json.Marshal(spec, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return nil, fmt.Errorf("failed to marshal OpenAPI spec: %w", err) } diff --git a/services/apigateway/sdk_test.go b/services/apigateway/sdk_test.go index 5109f261b5..f2422791b4 100644 --- a/services/apigateway/sdk_test.go +++ b/services/apigateway/sdk_test.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -28,7 +29,7 @@ func TestAPIGateway_GetSdkTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["item"].([]any) require.NotEmpty(t, items) @@ -52,7 +53,7 @@ func TestAPIGateway_GetSdkType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "java", resp["id"]) assert.Equal(t, "Java", resp["friendlyName"]) diff --git a/services/apigateway/stages_test.go b/services/apigateway/stages_test.go index bbab176182..1cc70e1e04 100644 --- a/services/apigateway/stages_test.go +++ b/services/apigateway/stages_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -164,7 +166,7 @@ func TestHandlerStage_ClientCertificateId(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var certResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&certResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &certResp, jsonx.V1())) certID := certResp["clientCertificateId"].(string) require.NotEmpty(t, certID) @@ -172,7 +174,7 @@ func TestHandlerStage_ClientCertificateId(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) rec = restRequest(t, h, http.MethodPost, "/restapis/"+apiID+"/deployments", @@ -184,7 +186,7 @@ func TestHandlerStage_ClientCertificateId(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var stageResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&stageResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &stageResp, jsonx.V1())) assert.Equal(t, certID, stageResp["clientCertificateId"]) } diff --git a/services/apigateway/store_test.go b/services/apigateway/store_test.go index 0bacbed38d..e280294d2b 100644 --- a/services/apigateway/store_test.go +++ b/services/apigateway/store_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -112,7 +113,7 @@ func TestPaginatedListing(t *testing.T) { rec2 := postWithHandler(t, handler, e, tt.action, `{}`) assert.Equal(t, tt.wantCode, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["item"].([]any) assert.GreaterOrEqual(t, len(items), tt.wantMinItems) }) diff --git a/services/apigateway/tags_test.go b/services/apigateway/tags_test.go index 417ad888b8..b206c57baa 100644 --- a/services/apigateway/tags_test.go +++ b/services/apigateway/tags_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -45,7 +46,7 @@ func TestGetTags_DomainNameAccessAssociation(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tagsResp, jsonx.V1())) gotTags, _ := tagsResp["tags"].(map[string]any) assert.Empty(t, gotTags) } @@ -91,13 +92,13 @@ func TestResourceTags(t *testing.T) { fmt.Sprintf(`{"name":"tagged-api","tags":%s}`, tt.initialTags)) require.Equal(t, http.StatusCreated, rec.Code) var apiResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) arn := fmt.Sprintf("arn:aws:apigateway:us-east-1::/restapis/%s", apiID) // TagResource - tagsJSON, err := json.Marshal(tt.addTags) + tagsJSON, err := json.Marshal(tt.addTags, jsonx.V1()) require.NoError(t, err) tagRec := postWithHandler(t, handler, e, "TagResource", fmt.Sprintf(`{"resourceArn":%q,"tags":%s}`, arn, tagsJSON)) @@ -105,7 +106,7 @@ func TestResourceTags(t *testing.T) { // UntagResource (if applicable) if len(tt.removeTags) > 0 { - keysJSON, err2 := json.Marshal(tt.removeTags) + keysJSON, err2 := json.Marshal(tt.removeTags, jsonx.V1()) require.NoError(t, err2) untagRec := postWithHandler(t, handler, e, "UntagResource", fmt.Sprintf(`{"resourceArn":%q,"tagKeys":%s}`, arn, keysJSON)) @@ -117,7 +118,7 @@ func TestResourceTags(t *testing.T) { fmt.Sprintf(`{"resourceArn":%q}`, arn)) assert.Equal(t, http.StatusOK, getRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tagsResp, jsonx.V1())) tagsMap, _ := tagsResp["tags"].(map[string]any) for k, v := range tt.wantTagsAfter { assert.Equal(t, v, tagsMap[k]) diff --git a/services/apigateway/test_invoke.go b/services/apigateway/test_invoke.go index c3f976490d..43722e72e4 100644 --- a/services/apigateway/test_invoke.go +++ b/services/apigateway/test_invoke.go @@ -2,7 +2,7 @@ package apigateway import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const testInvokeStage = "test-invoke-stage" @@ -100,7 +101,7 @@ func claimString(v any) string { return s } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Sprint(v) } @@ -131,7 +132,7 @@ func (h *Handler) testInvokeLambdaAuthorizer( methodArn := authorizerMethodArn(ctx, r, apiID, testInvokeStage, r.URL.Path) event.MethodArn = methodArn - payload, _ := json.Marshal(event) + payload, _ := json.Marshal(event, jsonx.V1()) funcName := ExtractLambdaFunctionName(auth.AuthorizerURI) resp, failure := h.invokeAuthorizerFunction(ctx, funcName, payload) @@ -139,7 +140,7 @@ func (h *Handler) testInvokeLambdaAuthorizer( return &TestInvokeAuthorizerOutput{ClientStatus: http.StatusUnauthorized, Log: failure}, nil } - policy, _ := json.Marshal(resp.PolicyDocument) + policy, _ := json.Marshal(resp.PolicyDocument, jsonx.V1()) out := &TestInvokeAuthorizerOutput{ PrincipalID: resp.PrincipalID, PolicyDocument: string(policy), @@ -213,7 +214,7 @@ func (h *Handler) invokeAuthorizerFunction( return resp, "Authorizer function invocation failed: " + invokeErr.Error() } - if err := json.Unmarshal(respBytes, &resp); err != nil { + if err := json.Unmarshal(respBytes, &resp, jsonx.V1()); err != nil { return resp, "Authorizer function returned an unparseable response: " + err.Error() } diff --git a/services/apigateway/test_invoke_test.go b/services/apigateway/test_invoke_test.go index 2cb66c1ab7..a5b51edc2f 100644 --- a/services/apigateway/test_invoke_test.go +++ b/services/apigateway/test_invoke_test.go @@ -2,7 +2,7 @@ package apigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -188,7 +189,7 @@ func TestTestInvokeMethod_StageVariablesAndPathParameters(t *testing.T) { assert.Equal(t, "real-fn", inv.fn, "stage variable substituted into the integration URI") var event map[string]any - require.NoError(t, json.Unmarshal(inv.payload, &event)) + require.NoError(t, json.Unmarshal(inv.payload, &event, jsonx.V1())) assert.Equal(t, map[string]any{"id": "42"}, event["pathParameters"]) assert.Equal(t, map[string]any{"fn": "real-fn"}, event["stageVariables"]) } diff --git a/services/apigateway/usage_plans_test.go b/services/apigateway/usage_plans_test.go index 93cb6febd4..d440e6e0cb 100644 --- a/services/apigateway/usage_plans_test.go +++ b/services/apigateway/usage_plans_test.go @@ -1,7 +1,8 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -27,7 +29,7 @@ func TestAPIGW_UsagePlans(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "expected 2xx") var keyResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&keyResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &keyResp, jsonx.V1())) keyID, _ := keyResp["id"].(string) require.NotEmpty(t, keyID) @@ -42,7 +44,7 @@ func TestAPIGW_UsagePlans(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "expected 2xx") var planResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&planResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &planResp, jsonx.V1())) planID, _ := planResp["id"].(string) require.NotEmpty(t, planID) @@ -262,7 +264,7 @@ func TestHandlerUsagePlan_ApiStages(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &apiResp, jsonx.V1())) apiID := apiResp["id"].(string) rec = restRequest(t, h, http.MethodPost, "/restapis/"+apiID+"/deployments", @@ -276,7 +278,7 @@ func TestHandlerUsagePlan_ApiStages(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var planResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&planResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &planResp, jsonx.V1())) apiStages, ok := planResp["apiStages"].([]any) require.True(t, ok) require.Len(t, apiStages, 1) @@ -317,7 +319,7 @@ func TestUpdateUsagePlan(t *testing.T) { createRec := postWithHandler(t, handler, e, "CreateUsagePlan", `{"name":"orig-plan"}`) require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) planID := createResp["id"].(string) lookupID := planID diff --git a/services/apigateway/usage_test.go b/services/apigateway/usage_test.go index bf32857e27..a67cf25b6b 100644 --- a/services/apigateway/usage_test.go +++ b/services/apigateway/usage_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -41,7 +42,7 @@ func TestUpdateUsage_ValidatesKeyExists(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300, "create plan: %s", rec.Body.String()) var plan map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &plan)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &plan, jsonx.V1())) planID, _ := plan["id"].(string) require.NotEmpty(t, planID) @@ -81,7 +82,7 @@ func TestAPIGateway_UpdateUsage_RESTRoute(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) values, _ := resp["values"].(map[string]any) require.Contains(t, values, key.ID, "real wire key is \"values\", not \"items\"") @@ -174,7 +175,7 @@ func TestGetUsage(t *testing.T) { planRec := postWithHandler(t, handler, e, "CreateUsagePlan", `{"name":"my-plan"}`) require.Equal(t, http.StatusCreated, planRec.Code) var planResp map[string]any - require.NoError(t, json.Unmarshal(planRec.Body.Bytes(), &planResp)) + require.NoError(t, json.Unmarshal(planRec.Body.Bytes(), &planResp, jsonx.V1())) planID := planResp["id"].(string) lookupID := planID @@ -250,7 +251,7 @@ func TestDeleteUsagePlan_ClearsUsageOverrides(t *testing.T) { var decoded struct { UsageOverrides map[string]map[string]int64 `json:"usageOverrides"` } - require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded)) + require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded, jsonx.V1())) assert.NotContains(t, decoded.UsageOverrides, plan.ID, "a deleted usage plan's override entry must not survive in the persisted snapshot") } @@ -278,7 +279,7 @@ func TestDeleteAPIKey_ClearsUsageOverrides(t *testing.T) { var decoded struct { UsageOverrides map[string]map[string]int64 `json:"usageOverrides"` } - require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded)) + require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &decoded, jsonx.V1())) assert.NotContains(t, decoded.UsageOverrides[plan.ID], key.ID, "a deleted API key's usage override must not survive in the persisted snapshot") } diff --git a/services/apigateway/validation.go b/services/apigateway/validation.go index 1cf6b79cbb..0a95677c16 100644 --- a/services/apigateway/validation.go +++ b/services/apigateway/validation.go @@ -1,11 +1,13 @@ package apigateway import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "math" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // errSchemaViolation is the sentinel returned when a request body fails JSON Schema @@ -31,7 +33,7 @@ func validateJSONAgainstSchema(body []byte, schema string) error { } var doc any - if err := json.Unmarshal(body, &doc); err != nil { + if err := json.Unmarshal(body, &doc, jsonx.V1()); err != nil { return errSchemaViolation } @@ -44,7 +46,7 @@ func validateJSONAgainstSchema(body []byte, schema string) error { // when the schema is not a parseable JSON object. func parseSchemaObject(schema string) (map[string]any, bool) { var root map[string]any - if err := json.Unmarshal([]byte(schema), &root); err != nil { + if err := json.Unmarshal([]byte(schema), &root, jsonx.V1()); err != nil { return nil, false } @@ -316,11 +318,11 @@ func toFloat(raw any) (float64, bool) { // jsonValuesEqual compares two decoded JSON values for equality (used by enum checks). func jsonValuesEqual(a, b any) bool { - ab, err := json.Marshal(a) + ab, err := json.Marshal(a, jsonx.V1()) if err != nil { return false } - bb, err := json.Marshal(b) + bb, err := json.Marshal(b, jsonx.V1()) if err != nil { return false } diff --git a/services/apigateway/vpc_links_test.go b/services/apigateway/vpc_links_test.go index eb9d2606cc..4e773dff51 100644 --- a/services/apigateway/vpc_links_test.go +++ b/services/apigateway/vpc_links_test.go @@ -1,7 +1,7 @@ package apigateway_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigateway" ) @@ -29,7 +30,7 @@ func TestAPIGateway_VpcLink_RESTLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) id, _ := created["id"].(string) require.NotEmpty(t, id) assert.Equal(t, "my-link", created["name"]) @@ -41,7 +42,7 @@ func TestAPIGateway_VpcLink_RESTLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var list map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list, jsonx.V1())) items, _ := list["item"].([]any) assert.Len(t, items, 1) @@ -50,7 +51,7 @@ func TestAPIGateway_VpcLink_RESTLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, patchRec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(patchRec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(patchRec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "renamed-link", updated["name"]) deleteRec := restCall(t, h, http.MethodDelete, "/vpclinks/"+id, "", "") @@ -117,7 +118,7 @@ func TestVpcLinks(t *testing.T) { if tt.wantCreateCode == http.StatusCreated { var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) linkID = createResp["id"].(string) // Get @@ -133,7 +134,7 @@ func TestVpcLinks(t *testing.T) { listRec := postWithHandler(t, handler, e, "GetVpcLinks", `{}`) assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.GreaterOrEqual(t, len(listResp["item"].([]any)), 1) // Update @@ -142,7 +143,7 @@ func TestVpcLinks(t *testing.T) { fmt.Sprintf(`{"vpcLinkId":%q,"name":%q}`, linkID, tt.updateName)) assert.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, tt.updateName, updateResp["name"]) } diff --git a/services/apigateway/vtl_values.go b/services/apigateway/vtl_values.go index 54ace57f14..dc04046e48 100644 --- a/services/apigateway/vtl_values.go +++ b/services/apigateway/vtl_values.go @@ -2,7 +2,8 @@ package apigateway import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -10,6 +11,8 @@ import ( "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // vtlMap is an insertion-ordered map, matching the LinkedHashMap API Gateway @@ -67,55 +70,59 @@ var errVTLJSON = errors.New("invalid JSON") // parseOrderedJSON decodes JSON into vtl values (ordered maps, lists, int64/float64, string, bool, nil). func parseOrderedJSON(s string) (any, error) { - dec := json.NewDecoder(strings.NewReader(s)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(s), jsonx.V1()) v, err := decodeVTLValue(dec) if err != nil { return nil, err } - if _, err = dec.Token(); !errors.Is(err, io.EOF) { + if _, err = dec.ReadToken(); !errors.Is(err, io.EOF) { return nil, errVTLJSON } return v, nil } -func decodeVTLValue(dec *json.Decoder) (any, error) { - tok, err := dec.Token() +func decodeVTLValue(dec *jsontext.Decoder) (any, error) { + tok, err := dec.ReadToken() if err != nil { return nil, err } - switch t := tok.(type) { - case json.Delim: - if t == '{' { - return decodeVTLObject(dec) - } - + switch tok.Kind() { + case '{': + return decodeVTLObject(dec) + case '[': return decodeVTLArray(dec) - case json.Number: - return numberFromJSON(t), nil + case '0': + return numberFromJSON(jsonx.Number(tok.String())), nil + case '"': + return tok.String(), nil + case 't', 'f': + return tok.Bool(), nil default: - return t, nil + var null any + + return null, nil } } -func decodeVTLObject(dec *json.Decoder) (any, error) { +func decodeVTLObject(dec *jsontext.Decoder) (any, error) { m := newVTLMap() - for dec.More() { - keyTok, err := dec.Token() + for dec.PeekKind() != '}' { + keyTok, err := dec.ReadToken() if err != nil { return nil, err } - key, ok := keyTok.(string) - if !ok { + if keyTok.Kind() != '"' { return nil, errVTLJSON } + key := keyTok.String() + v, err := decodeVTLValue(dec) if err != nil { return nil, err @@ -124,17 +131,17 @@ func decodeVTLObject(dec *json.Decoder) (any, error) { m.put(key, v) } - if _, err := dec.Token(); err != nil { + if _, err := dec.ReadToken(); err != nil { return nil, err } return m, nil } -func decodeVTLArray(dec *json.Decoder) (any, error) { +func decodeVTLArray(dec *jsontext.Decoder) (any, error) { l := &vtlList{items: []any{}} - for dec.More() { + for dec.PeekKind() != ']' { v, err := decodeVTLValue(dec) if err != nil { return nil, err @@ -143,14 +150,14 @@ func decodeVTLArray(dec *json.Decoder) (any, error) { l.items = append(l.items, v) } - if _, err := dec.Token(); err != nil { + if _, err := dec.ReadToken(); err != nil { return nil, err } return l, nil } -func numberFromJSON(n json.Number) any { +func numberFromJSON(n jsonx.Number) any { if i, err := strconv.ParseInt(n.String(), 10, 64); err == nil { return i } @@ -213,9 +220,8 @@ func writeVTLJSON(buf *bytes.Buffer, v any) { func writeJSONString(buf *bytes.Buffer, s string) { var tmp bytes.Buffer - enc := json.NewEncoder(&tmp) - enc.SetEscapeHTML(false) - _ = enc.Encode(s) + enc := jsontext.NewEncoder(&tmp, jsonx.V1(), jsontext.EscapeForHTML(false)) + _ = json.MarshalEncode(enc, s) buf.Write(bytes.TrimRight(tmp.Bytes(), "\n")) } diff --git a/services/apigatewaymanagementapi/admin.go b/services/apigatewaymanagementapi/admin.go index 470bc720b1..9c28498dd5 100644 --- a/services/apigatewaymanagementapi/admin.go +++ b/services/apigatewaymanagementapi/admin.go @@ -1,7 +1,8 @@ package apigatewaymanagementapi import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -244,10 +246,9 @@ func (h *Handler) connectionExists(connectionID string) bool { } func decodeJSON(r io.Reader, dst any) error { - dec := json.NewDecoder(r) - dec.DisallowUnknownFields() + dec := jsontext.NewDecoder(r) - if err := dec.Decode(dst); err != nil { + if err := json.UnmarshalDecode(dec, dst, jsonx.V1(), json.RejectUnknownMembers(true)); err != nil { return err } diff --git a/services/apigatewaymanagementapi/admin_test.go b/services/apigatewaymanagementapi/admin_test.go index 28d243a496..f62d2b51a6 100644 --- a/services/apigatewaymanagementapi/admin_test.go +++ b/services/apigatewaymanagementapi/admin_test.go @@ -2,7 +2,7 @@ package apigatewaymanagementapi_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewaymanagementapi" ) @@ -34,7 +35,7 @@ func TestAdmin_ListConnections(t *testing.T) { Connections []apigatewaymanagementapi.Connection `json:"connections"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Connections, 2) } @@ -56,7 +57,7 @@ func TestAdmin_ListConnections_QueryFilter(t *testing.T) { Connections []apigatewaymanagementapi.Connection `json:"connections"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Connections, 1) assert.Equal(t, "beta-2", resp.Connections[0].ConnectionID) } @@ -70,7 +71,7 @@ func TestAdmin_SimulateConnection(t *testing.T) { "connectionId": "sim-1", "sourceIp": "1.2.3.4", "userAgent": "ua", - }) + }, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/_gopherstack/apigwmgmt/connections", body) assert.Equal(t, http.StatusCreated, rec.Code) @@ -88,7 +89,7 @@ func TestAdmin_SimulateDuplicate(t *testing.T) { _, err := h.Backend.CreateConnection("dupe", "1.1.1.1", "ua", nil) require.NoError(t, err) - body, _ := json.Marshal(map[string]string{"connectionId": "dupe"}) + body, _ := json.Marshal(map[string]string{"connectionId": "dupe"}, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/_gopherstack/apigwmgmt/connections", body) assert.Equal(t, http.StatusConflict, rec.Code) } @@ -98,7 +99,7 @@ func TestAdmin_SimulateEmptyConnectionID(t *testing.T) { h := newTestHandler(t) - body, _ := json.Marshal(map[string]string{"connectionId": ""}) + body, _ := json.Marshal(map[string]string{"connectionId": ""}, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/_gopherstack/apigwmgmt/connections", body) assert.Equal(t, http.StatusBadRequest, rec.Code) } @@ -123,7 +124,7 @@ func TestAdmin_GetMessages(t *testing.T) { } `json:"messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Messages, 2) assert.Equal(t, "hello", resp.Messages[0].Data) assert.Equal(t, 5, resp.Messages[0].Bytes) @@ -170,7 +171,7 @@ func TestAdmin_GetTimeline(t *testing.T) { Events []apigatewaymanagementapi.LifecycleEvent `json:"events"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Events, 3) assert.Equal(t, apigatewaymanagementapi.EventConnected, resp.Events[0].Type) assert.Equal(t, apigatewaymanagementapi.EventMessage, resp.Events[1].Type) @@ -208,7 +209,7 @@ func TestAdmin_Broadcast(t *testing.T) { require.NoError(t, err) } - body, _ := json.Marshal(map[string]string{"data": "broadcast-payload"}) + body, _ := json.Marshal(map[string]string{"data": "broadcast-payload"}, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/_gopherstack/apigwmgmt/broadcast", body) assert.Equal(t, http.StatusOK, rec.Code) @@ -217,7 +218,7 @@ func TestAdmin_Broadcast(t *testing.T) { Delivered int `json:"delivered"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 3, resp.Delivered) for _, id := range []string{"a", "b", "c"} { @@ -236,7 +237,7 @@ func TestAdmin_BroadcastTooLarge(t *testing.T) { require.NoError(t, err) big := bytes.Repeat([]byte("x"), 130*1024) - body, _ := json.Marshal(map[string]string{"data": string(big)}) + body, _ := json.Marshal(map[string]string{"data": string(big)}, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/_gopherstack/apigwmgmt/broadcast", body) assert.Equal(t, http.StatusRequestEntityTooLarge, rec.Code) @@ -255,7 +256,7 @@ func TestAdmin_Stats(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var stats apigatewaymanagementapi.Stats - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stats)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stats, jsonx.V1())) assert.Equal(t, 1, stats.ActiveConnections) assert.Equal(t, int64(1), stats.TotalConnections) assert.Equal(t, int64(1), stats.TotalMessages) diff --git a/services/apigatewaymanagementapi/error_messages_test.go b/services/apigatewaymanagementapi/error_messages_test.go index 2ac98e8888..fb2beda9d0 100644 --- a/services/apigatewaymanagementapi/error_messages_test.go +++ b/services/apigatewaymanagementapi/error_messages_test.go @@ -1,7 +1,7 @@ package apigatewaymanagementapi_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewaymanagementapi" ) @@ -53,7 +54,7 @@ func TestModeledErrorBodies(t *testing.T) { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantMsg, body["message"]) assert.NotContains(t, body, "connectionId") }) diff --git a/services/apigatewaymanagementapi/handler_test.go b/services/apigatewaymanagementapi/handler_test.go index 2b1fec35ff..1001144ea5 100644 --- a/services/apigatewaymanagementapi/handler_test.go +++ b/services/apigatewaymanagementapi/handler_test.go @@ -2,7 +2,8 @@ package apigatewaymanagementapi_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "log/slog" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/apigatewaymanagementapi" ) @@ -325,8 +327,8 @@ func TestHandler_GetConnection(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) if tt.wantStatus == http.StatusOK { - var body map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + var body map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Contains(t, body, "connectedAt") assert.Contains(t, body, "identity") assert.Contains(t, body, "lastActiveAt") @@ -362,8 +364,8 @@ func TestHandler_GetConnection_NoConnectionIDField(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/@connections/"+tt.connectionID, nil) require.Equal(t, http.StatusOK, rec.Code) - var body map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + var body map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotContains(t, body, "connectionId", "GetConnectionOutput has no ConnectionId member on the real API") }) @@ -398,15 +400,15 @@ func TestHandler_GetConnection_IdentityShape(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/@connections/conn-identity", nil) require.Equal(t, http.StatusOK, rec.Code) - var body map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + var body map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) // AWS shape: identity must be a nested object. identityRaw, ok := body["identity"] require.True(t, ok, "response must include 'identity' field") var identity map[string]string - require.NoError(t, json.Unmarshal(identityRaw, &identity)) + require.NoError(t, json.Unmarshal(identityRaw, &identity, jsonx.V1())) assert.Equal(t, tt.sourceIP, identity["sourceIp"], "identity.sourceIp must match") assert.Equal(t, tt.userAgent, identity["userAgent"], "identity.userAgent must match") @@ -440,7 +442,7 @@ func TestHandler_GetConnection_TimestampFields(t *testing.T) { ConnectedAt string `json:"connectedAt"` LastActiveAt string `json:"lastActiveAt"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body.ConnectedAt, "connectedAt must be non-empty") assert.NotEmpty(t, body.LastActiveAt, "lastActiveAt must be non-empty") } @@ -533,7 +535,7 @@ func TestHandler_GoneExceptionWireShape(t *testing.T) { assert.Equal(t, "GoneException", rec.Header().Get("X-Amzn-Errortype")) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "GoneException", body["__type"]) assert.NotEqual(t, "GoneException", body["message"], "message must be a human-readable string, not the error type") @@ -563,7 +565,7 @@ func TestHandler_PostToConnection_LimitExceeded(t *testing.T) { assert.Equal(t, "LimitExceededException", rec.Header().Get("X-Amzn-Errortype")) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "LimitExceededException", body["__type"]) assert.NotEmpty(t, body["message"]) @@ -588,7 +590,7 @@ func TestHandler_PostToConnection_PayloadTooLarge_WireShape(t *testing.T) { assert.Equal(t, "PayloadTooLargeException", rec.Header().Get("X-Amzn-Errortype")) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "PayloadTooLargeException", body["__type"]) assert.NotEmpty(t, body["message"]) } diff --git a/services/apigatewaymanagementapi/ringbuffer_test.go b/services/apigatewaymanagementapi/ringbuffer_test.go index 60c2514745..b9958eb638 100644 --- a/services/apigatewaymanagementapi/ringbuffer_test.go +++ b/services/apigatewaymanagementapi/ringbuffer_test.go @@ -1,13 +1,14 @@ package apigatewaymanagementapi_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewaymanagementapi" ) @@ -211,7 +212,7 @@ func TestBackend_SnapshotPreservesEverything(t *testing.T) { // Verify well-formed JSON var raw map[string]any - require.NoError(t, json.Unmarshal(data, &raw)) + require.NoError(t, json.Unmarshal(data, &raw, jsonx.V1())) fresh := apigatewaymanagementapi.NewInMemoryBackend() require.NoError(t, fresh.Restore(t.Context(), data)) diff --git a/services/apigatewayv2/authorizer_cache_internal_test.go b/services/apigatewayv2/authorizer_cache_internal_test.go index 53d5f2390d..17330fbde6 100644 --- a/services/apigatewayv2/authorizer_cache_internal_test.go +++ b/services/apigatewayv2/authorizer_cache_internal_test.go @@ -3,7 +3,7 @@ package apigatewayv2 import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -15,6 +15,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // doInternalRequest performs an HTTP request against h and returns the @@ -27,7 +29,7 @@ func doInternalRequest(t *testing.T, h *Handler, method, path string, body any) var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) } else { diff --git a/services/apigatewayv2/authorizer_context.go b/services/apigatewayv2/authorizer_context.go index c2bbed876d..86cec940fe 100644 --- a/services/apigatewayv2/authorizer_context.go +++ b/services/apigatewayv2/authorizer_context.go @@ -1,13 +1,15 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/v2" "slices" "strconv" "strings" "github.com/golang-jwt/jwt/v5" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const authorizerCtxKey = "apigwv2.authorizer" @@ -51,7 +53,7 @@ func stringifyClaim(v any) string { return "[" + strings.Join(parts, " ") + "]" default: - b, _ := json.Marshal(t) + b, _ := json.Marshal(t, jsonx.V1()) return string(b) } @@ -97,7 +99,7 @@ func lambdaAuthorizerContext(respBytes []byte) map[string]any { var resp struct { Context map[string]any `json:"context"` } - if err := json.Unmarshal(respBytes, &resp); err != nil || len(resp.Context) == 0 { + if err := json.Unmarshal(respBytes, &resp, jsonx.V1()); err != nil || len(resp.Context) == 0 { return nil } diff --git a/services/apigatewayv2/authorizers.go b/services/apigatewayv2/authorizers.go index 3bec274b22..39395e14ae 100644 --- a/services/apigatewayv2/authorizers.go +++ b/services/apigatewayv2/authorizers.go @@ -1,7 +1,7 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "sort" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -211,7 +212,7 @@ func (f *flexibleStrings) UnmarshalJSON(data []byte) error { if strings.HasPrefix(trimmed, "[") { var arr []string - if err := json.Unmarshal(data, &arr); err != nil { + if err := json.Unmarshal(data, &arr, jsonx.V1()); err != nil { return err } @@ -221,7 +222,7 @@ func (f *flexibleStrings) UnmarshalJSON(data []byte) error { } var s string - if err := json.Unmarshal(data, &s); err != nil { + if err := json.Unmarshal(data, &s, jsonx.V1()); err != nil { return err } @@ -375,7 +376,7 @@ func buildAuthorizerPayload( }, } - return json.Marshal(event) + return json.Marshal(event, jsonx.V1()) } event := requestAuthorizerEventV2{ @@ -403,7 +404,7 @@ func buildAuthorizerPayload( }, } - return json.Marshal(event) + return json.Marshal(event, jsonx.V1()) } // authorizerUsesV1Payload reports whether the authorizer expects the 1.0 event @@ -418,7 +419,7 @@ func evaluateAuthorizerResponse(respBytes []byte, auth *Authorizer, routeArn str // Simple response: only valid with payload 2.0 + EnableSimpleResponses. if auth.EnableSimpleResponses && !authorizerUsesV1Payload(auth) { var simple simpleAuthorizerResponse - if err := json.Unmarshal(respBytes, &simple); err == nil { + if err := json.Unmarshal(respBytes, &simple, jsonx.V1()); err == nil { return simple.IsAuthorized, false } @@ -427,7 +428,7 @@ func evaluateAuthorizerResponse(respBytes []byte, auth *Authorizer, routeArn str // IAM policy response. var policy iamPolicyResponse - if err := json.Unmarshal(respBytes, &policy); err != nil { + if err := json.Unmarshal(respBytes, &policy, jsonx.V1()); err != nil { return false, false } diff --git a/services/apigatewayv2/custom_domain_test.go b/services/apigatewayv2/custom_domain_test.go index 888908c79c..a9ab330f1a 100644 --- a/services/apigatewayv2/custom_domain_test.go +++ b/services/apigatewayv2/custom_domain_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -32,11 +33,11 @@ func TestCustomDomainRouting(t *testing.T) { } `json:"requestContext"` RawPath string `json:"rawPath"` } - _ = json.Unmarshal(payload, &ev) + _ = json.Unmarshal(payload, &ev, jsonx.V1()) b, _ := json.Marshal(map[string]any{ "statusCode": 200, "body": name + "|" + ev.RequestContext.Stage + "|" + ev.RawPath, - }) + }, jsonx.V1()) return b, 200, nil }, diff --git a/services/apigatewayv2/custom_id_test.go b/services/apigatewayv2/custom_id_test.go index 53b1711682..5bc7bf6d7e 100644 --- a/services/apigatewayv2/custom_id_test.go +++ b/services/apigatewayv2/custom_id_test.go @@ -1,13 +1,14 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -54,7 +55,7 @@ func TestCreateAPICustomIDTag(t *testing.T) { } var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, tt.wantID, api.APIID) assert.NotContains(t, api.Tags, "_custom_id_") assert.NotContains(t, api.Tags, "gopherstack:id") diff --git a/services/apigatewayv2/handler.go b/services/apigatewayv2/handler.go index 24d6f15c5f..874ebcde7a 100644 --- a/services/apigatewayv2/handler.go +++ b/services/apigatewayv2/handler.go @@ -3,7 +3,8 @@ package apigatewayv2 import ( "context" "crypto/rsa" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "slices" @@ -19,6 +20,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" "github.com/blackbirdworks/gopherstack/pkgs/executeapi" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -643,7 +645,7 @@ func handleCreateMulti[I, O any]( log := logger.Load(c.Request().Context()) var input I - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -682,7 +684,7 @@ func handleUpdate[I, O any]( log := logger.Load(c.Request().Context()) var input I - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -785,7 +787,7 @@ func handleCreateNoParent[I, O any]( log := logger.Load(c.Request().Context()) var input I - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } diff --git a/services/apigatewayv2/handler_api_mappings_test.go b/services/apigatewayv2/handler_api_mappings_test.go index 63223f459a..ed27246ff4 100644 --- a/services/apigatewayv2/handler_api_mappings_test.go +++ b/services/apigatewayv2/handler_api_mappings_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -119,7 +120,7 @@ func TestHandler_CreateApiMapping(t *testing.T) { if tt.wantAPIIDSet { var mapping apigatewayv2.APIMapping - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping, jsonx.V1())) assert.Equal(t, apiID, mapping.APIID) assert.NotEmpty(t, mapping.APIMappingID) } @@ -174,7 +175,7 @@ func TestHandler_GetAPIMappings(t *testing.T) { var out struct { Items []apigatewayv2.APIMapping `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.mappingsCnt) } }) @@ -230,7 +231,7 @@ func TestHandler_GetAPIMapping(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var mapping apigatewayv2.APIMapping - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping, jsonx.V1())) domainName := "example.com" mappingID := mapping.APIMappingID @@ -299,7 +300,7 @@ func TestHandler_DeleteAPIMapping(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var mapping apigatewayv2.APIMapping - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &mapping, jsonx.V1())) domainName := "example.com" mappingID := mapping.APIMappingID @@ -340,7 +341,7 @@ func TestHandler_UpdateAPIMapping(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) var m apigatewayv2.APIMapping - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m, jsonx.V1())) return "api.example.com", m.APIMappingID }, diff --git a/services/apigatewayv2/handler_api_models_test.go b/services/apigatewayv2/handler_api_models_test.go index 5fe44c52a2..8e2dd18c52 100644 --- a/services/apigatewayv2/handler_api_models_test.go +++ b/services/apigatewayv2/handler_api_models_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -73,7 +74,7 @@ func TestHandler_CreateModel(t *testing.T) { if tt.wantName != "" { var model apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model, jsonx.V1())) assert.Equal(t, tt.wantName, model.Name) assert.NotEmpty(t, model.ModelID) } @@ -121,7 +122,7 @@ func TestHandler_GetModelTemplate(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var model apigatewayv2.Model - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &model)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &model, jsonx.V1())) rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/v2/apis/%s/models/%s/template", apiID, model.ModelID), nil) @@ -130,7 +131,7 @@ func TestHandler_GetModelTemplate(t *testing.T) { var out struct { Value string `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantValue, out.Value) }) } @@ -224,7 +225,7 @@ func TestHandler_GetModels(t *testing.T) { var out struct { Items []apigatewayv2.Model `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.modelCnt) } }) @@ -265,7 +266,7 @@ func TestHandler_GetModel(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var model apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model, jsonx.V1())) modelID := model.ModelID if tt.useWrongID { @@ -277,7 +278,7 @@ func TestHandler_GetModel(t *testing.T) { if tt.wantStatus == http.StatusOK { var got apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "MyModel", got.Name) } }) @@ -318,7 +319,7 @@ func TestHandler_DeleteModel(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var model apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &model, jsonx.V1())) modelID := model.ModelID if tt.useWrongID { @@ -350,7 +351,7 @@ func TestHandler_UpdateModel(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) var m apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m, jsonx.V1())) return apiID, m.ModelID }, @@ -390,7 +391,7 @@ func TestHandler_UpdateModel(t *testing.T) { if tt.wantName != "" { var m apigatewayv2.Model - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &m, jsonx.V1())) assert.Equal(t, tt.wantName, m.Name) } }) @@ -432,7 +433,7 @@ func TestGetModels_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), 2) for _, m := range resp.Items { diff --git a/services/apigatewayv2/handler_apis.go b/services/apigatewayv2/handler_apis.go index 40c08e7fd9..d27ee0af22 100644 --- a/services/apigatewayv2/handler_apis.go +++ b/services/apigatewayv2/handler_apis.go @@ -1,7 +1,8 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "gopkg.in/yaml.v3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -103,7 +105,7 @@ func (h *Handler) handleCreateAPI(c *echo.Context) error { log := logger.Load(c.Request().Context()) var input CreateAPIInput - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -196,7 +198,7 @@ func (h *Handler) handleUpdateAPI(c *echo.Context, apiID string) error { log := logger.Load(c.Request().Context()) var input UpdateAPIInput - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -364,7 +366,7 @@ func parseOpenAPISpec(body string) (*openAPISpec, error) { return &spec, nil } - if err := json.Unmarshal([]byte(body), &spec); err != nil { + if err := json.Unmarshal([]byte(body), &spec, jsonx.V1()); err != nil { return nil, err } @@ -466,7 +468,7 @@ func (h *Handler) handleImportAPI(c *echo.Context) error { var input struct { Body string `json:"body"` } - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -510,7 +512,7 @@ func (h *Handler) handleReimportAPI(c *echo.Context, apiID string) error { var input struct { Body string `json:"body"` } - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -677,7 +679,7 @@ func (h *Handler) handleExportAPI(c *echo.Context, apiID, specification string) return c.Blob(http.StatusOK, "application/x-yaml", blob) } - blob, mErr := json.Marshal(spec) + blob, mErr := json.Marshal(spec, jsonx.V1()) if mErr != nil { return writeErr(c, http.StatusInternalServerError, mErr.Error()) } diff --git a/services/apigatewayv2/handler_apis_test.go b/services/apigatewayv2/handler_apis_test.go index c9644fef71..fd1aa6e5ac 100644 --- a/services/apigatewayv2/handler_apis_test.go +++ b/services/apigatewayv2/handler_apis_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -59,7 +60,7 @@ func TestHandler_CreateAPI(t *testing.T) { if tt.wantName != "" { var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, tt.wantName, api.Name) assert.NotEmpty(t, api.APIID) } @@ -106,7 +107,7 @@ func TestHandler_GetAPI(t *testing.T) { if tt.wantStatus == http.StatusOK { var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, apiID, api.APIID) } }) @@ -151,7 +152,7 @@ func TestHandler_GetAPIs(t *testing.T) { } var resp listResp - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, tt.apiCount) }) } @@ -238,7 +239,7 @@ func TestHandler_UpdateAPI(t *testing.T) { if tt.wantName != "" { var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) assert.Equal(t, tt.wantName, api.Name) } }) @@ -301,7 +302,7 @@ func TestExportAPI_ReturnsRawSpec(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var spec map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec, jsonx.V1())) // Raw OpenAPI doc — not the old {"body":...,"specification":...} wrapper. assert.Equal(t, "3.0.1", spec["openapi"]) @@ -355,7 +356,7 @@ func TestExportAPI_OutputType(t *testing.T) { var asJSON map[string]any require.Error( t, - json.Unmarshal(rr.Body.Bytes(), &asJSON), + json.Unmarshal(rr.Body.Bytes(), &asJSON, jsonx.V1()), "YAML output must not also be valid strict JSON object syntax expected by this assertion", ) assert.Contains(t, rr.Body.String(), "openapi:") @@ -364,7 +365,7 @@ func TestExportAPI_OutputType(t *testing.T) { } var spec map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec, jsonx.V1())) assert.Equal(t, "3.0.1", spec["openapi"]) }) } @@ -400,7 +401,7 @@ func TestExportAPI_JWTSecurityScheme(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var auth apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+apiID+"/routes", map[string]any{ "routeKey": "GET /jwt", @@ -413,7 +414,7 @@ func TestExportAPI_JWTSecurityScheme(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var spec map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &spec, jsonx.V1())) components, ok := spec["components"].(map[string]any) require.True(t, ok, "expected components block") @@ -494,7 +495,7 @@ func TestGetAPIs_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.API `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), tc.maxResults, "page must not exceed maxResults") for _, api := range resp.Items { @@ -540,7 +541,7 @@ func TestGetAPIs_NoMaxResults_ReturnsAll(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.API `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, 5) assert.Empty(t, resp.NextToken) } @@ -563,7 +564,7 @@ func TestGetAPIs_EmptyLastPage(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.API `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, 2) assert.Empty(t, resp.NextToken, "no nextToken when all items fit") } @@ -583,7 +584,7 @@ func TestCreateAPI_HTTP_DefaultAPIKeySelectionExpression(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "$request.header.x-api-key", resp["apiKeySelectionExpression"]) } @@ -602,7 +603,7 @@ func TestCreateAPI_WebSocket_DefaultAPIKeySelectionExpression(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "$context.authorizer.usageIdentifierKey", resp["apiKeySelectionExpression"]) } @@ -623,7 +624,7 @@ func TestCreateAPI_ExplicitAPIKeySelectionExpressionPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, custom, resp["apiKeySelectionExpression"]) } @@ -675,7 +676,7 @@ func TestImportAPI_Basepath_Prepend(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodGet, "/v2/apis/"+api.APIID+"/routes", nil) require.Equal(t, http.StatusOK, rr.Code) @@ -683,7 +684,7 @@ func TestImportAPI_Basepath_Prepend(t *testing.T) { var routes struct { Items []apigatewayv2.Route `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes, jsonx.V1())) require.Len(t, routes.Items, 1) assert.Equal(t, "GET /v1/items", routes.Items[0].RouteKey) } @@ -707,7 +708,7 @@ func TestImportAPI_Basepath_DefaultIgnoresSpecBasePath(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodGet, "/v2/apis/"+api.APIID+"/routes", nil) require.Equal(t, http.StatusOK, rr.Code) @@ -715,7 +716,7 @@ func TestImportAPI_Basepath_DefaultIgnoresSpecBasePath(t *testing.T) { var routes struct { Items []apigatewayv2.Route `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes, jsonx.V1())) require.Len(t, routes.Items, 1) assert.Equal(t, "GET /items", routes.Items[0].RouteKey) } @@ -791,7 +792,7 @@ func TestImportAPI_Basepath_RouteKeyTransforms(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodGet, "/v2/apis/"+api.APIID+"/routes", nil) require.Equal(t, http.StatusOK, rr.Code) @@ -799,7 +800,7 @@ func TestImportAPI_Basepath_RouteKeyTransforms(t *testing.T) { var routes struct { Items []apigatewayv2.Route `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes, jsonx.V1())) require.Len(t, routes.Items, 1) assert.Equal(t, tt.wantRouteKey, routes.Items[0].RouteKey) }) @@ -846,7 +847,7 @@ func TestReimportAPI_Basepath_RouteKeyTransforms(t *testing.T) { var routes struct { Items []apigatewayv2.Route `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &routes, jsonx.V1())) require.Len(t, routes.Items, 1) assert.Equal(t, tt.wantRouteKey, routes.Items[0].RouteKey) }) @@ -899,7 +900,7 @@ func TestImportAPI_FailOnWarnings(t *testing.T) { var apis struct { Items []apigatewayv2.API `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &apis)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &apis, jsonx.V1())) assert.Len(t, apis.Items, tt.wantAPIs) }) } diff --git a/services/apigatewayv2/handler_authorizers_test.go b/services/apigatewayv2/handler_authorizers_test.go index 94a9d92240..a5197582d7 100644 --- a/services/apigatewayv2/handler_authorizers_test.go +++ b/services/apigatewayv2/handler_authorizers_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -48,7 +49,7 @@ func TestHandler_Authorizers(t *testing.T) { require.Equal(t, tt.wantCreateCode, rr.Code) var auth apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth, jsonx.V1())) assert.Equal(t, tt.authorizerName, auth.Name) // GetAuthorizers @@ -245,7 +246,7 @@ func TestGetAuthorizers_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), tc.maxResults) for _, a := range resp.Items { @@ -311,7 +312,7 @@ func setupRequestAuthAPI( authCalls := &atomic.Int64{} integrationCalls := &atomic.Int64{} - respBytes, _ := json.Marshal(sc.authResponse) + respBytes, _ := json.Marshal(sc.authResponse, jsonx.V1()) h.SetLambdaInvoker(&mockLambdaInvoker{ fn: func(_ context.Context, name, _ string, _ []byte) ([]byte, int, error) { @@ -324,7 +325,7 @@ func setupRequestAuthAPI( // Integration backend function. integrationCalls.Add(1) - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, @@ -341,7 +342,7 @@ func setupRequestAuthAPI( require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) // Authorizer. identity := sc.identitySource @@ -365,7 +366,7 @@ func setupRequestAuthAPI( require.Equal(t, http.StatusCreated, rr.Code) var auth apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &auth, jsonx.V1())) authorizerID := auth.AuthorizerID if sc.authorizerMissing { @@ -619,7 +620,7 @@ func TestRouteAuth_AWSIAM(t *testing.T) { fn: func(_ context.Context, _, _ string, _ []byte) ([]byte, int, error) { integrationCalls.Add(1) - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, @@ -635,7 +636,7 @@ func TestRouteAuth_AWSIAM(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+apiID+"/routes", map[string]any{ "routeKey": "GET /iam", diff --git a/services/apigatewayv2/handler_deployments_test.go b/services/apigatewayv2/handler_deployments_test.go index 1ff59a659c..a28a4016e5 100644 --- a/services/apigatewayv2/handler_deployments_test.go +++ b/services/apigatewayv2/handler_deployments_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -54,7 +55,7 @@ func TestHandler_CreateDeployment(t *testing.T) { if tt.wantStatus == http.StatusCreated { var deployment apigatewayv2.Deployment - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment, jsonx.V1())) assert.NotEmpty(t, deployment.DeploymentID) assert.Equal(t, "DEPLOYED", deployment.DeploymentStatus) } @@ -95,7 +96,7 @@ func TestHandler_GetDeployment(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var deployment apigatewayv2.Deployment - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment, jsonx.V1())) deploymentID = deployment.DeploymentID } @@ -138,7 +139,7 @@ func TestHandler_DeleteDeployment(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var deployment apigatewayv2.Deployment - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &deployment, jsonx.V1())) deploymentID = deployment.DeploymentID } @@ -213,7 +214,7 @@ func TestHandler_GetDeployments(t *testing.T) { } var resp listResp - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, tt.deployCount) } }) @@ -239,7 +240,7 @@ func TestHandler_UpdateDeployment(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) var dep apigatewayv2.Deployment - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep, jsonx.V1())) return apiID, dep.DeploymentID }, @@ -279,7 +280,7 @@ func TestHandler_UpdateDeployment(t *testing.T) { if tt.wantDesc != "" { var dep apigatewayv2.Deployment - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, tt.wantDesc, dep.Description) } }) @@ -304,7 +305,7 @@ func getStage(t *testing.T, h *apigatewayv2.Handler, apiID, stageName string) ap require.Equal(t, http.StatusOK, rr.Code) var s apigatewayv2.Stage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &s, jsonx.V1())) return s } @@ -320,7 +321,7 @@ func createIntegrationHelper(t *testing.T, h *apigatewayv2.Handler, apiID string require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) return integ.IntegrationID } @@ -369,7 +370,7 @@ func TestAutoDeploy_RouteAndIntegrationChangesDeploy(t *testing.T) { var out struct { Items []apigatewayv2.Deployment `json:"items"` } - require.NoError(t, json.Unmarshal(drr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(drr.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Items) var foundAuto bool @@ -423,7 +424,7 @@ func TestGetDeployments_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), 2) for _, d := range resp.Items { @@ -484,6 +485,6 @@ func TestCreateDeployment_ValidStageName201(t *testing.T) { assert.Equal(t, http.StatusCreated, rr.Code) var dep map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, "DEPLOYED", dep["deploymentStatus"]) } diff --git a/services/apigatewayv2/handler_domain_names_test.go b/services/apigatewayv2/handler_domain_names_test.go index de26e60fda..799717c9ea 100644 --- a/services/apigatewayv2/handler_domain_names_test.go +++ b/services/apigatewayv2/handler_domain_names_test.go @@ -1,7 +1,8 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -59,7 +61,7 @@ func TestHandler_CreateDomainName(t *testing.T) { if tt.wantDomain != "" { var dn apigatewayv2.DomainName - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn, jsonx.V1())) assert.Equal(t, tt.wantDomain, dn.DomainNameValue) } }) @@ -138,7 +140,7 @@ func TestHandler_GetDomainNames(t *testing.T) { var out struct { Items []apigatewayv2.DomainName `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.domainCnt) } }) @@ -181,7 +183,7 @@ func TestHandler_GetDomainName(t *testing.T) { if tt.wantStatus == http.StatusOK { var dn apigatewayv2.DomainName - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn, jsonx.V1())) assert.Equal(t, "example.com", dn.DomainNameValue) } }) @@ -310,7 +312,7 @@ func TestHandler_CreateDomainName_WithConfigurations(t *testing.T) { if tt.wantConfig { var dn apigatewayv2.DomainName - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn, jsonx.V1())) require.Len(t, dn.DomainNameConfigurations, 1) assert.Equal(t, "AVAILABLE", dn.DomainNameConfigurations[0].DomainNameStatus) assert.Equal(t, "REGIONAL", dn.DomainNameConfigurations[0].EndpointType) @@ -358,14 +360,14 @@ func TestDomainNameConfigurationsNullBug(t *testing.T) { rr := doRequest(t, h, http.MethodPost, "/v2/domainnames", tt.body) require.Equal(t, http.StatusCreated, rr.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw, jsonx.V1())) _, hasKey := raw["domainNameConfigurations"] assert.True(t, hasKey, "domainNameConfigurations key must always be present in DomainName response") var dn apigatewayv2.DomainName - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &dn, jsonx.V1())) if tt.wantConfigsEmpty { assert.Empty(t, dn.DomainNameConfigurations, diff --git a/services/apigatewayv2/handler_export_api_sdk_test.go b/services/apigatewayv2/handler_export_api_sdk_test.go index 932743ff66..bb51b58d42 100644 --- a/services/apigatewayv2/handler_export_api_sdk_test.go +++ b/services/apigatewayv2/handler_export_api_sdk_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -36,7 +37,7 @@ func TestExportApi_OutputType_RoundTrip(t *testing.T) { require.NoError(t, err) var asJSON map[string]any - require.NoError(t, json.Unmarshal(jsonOut.Body, &asJSON), "OutputType=JSON must return valid JSON") + require.NoError(t, json.Unmarshal(jsonOut.Body, &asJSON, jsonx.V1()), "OutputType=JSON must return valid JSON") assert.Equal(t, "3.0.1", asJSON["openapi"]) yamlOut, err := client.ExportApi(t.Context(), &apigatewayv2sdk.ExportApiInput{ @@ -47,7 +48,7 @@ func TestExportApi_OutputType_RoundTrip(t *testing.T) { require.NoError(t, err) require.Error( - t, json.Unmarshal(yamlOut.Body, &asJSON), + t, json.Unmarshal(yamlOut.Body, &asJSON, jsonx.V1()), "OutputType=YAML must not return the same JSON syntax as OutputType=JSON", ) assert.Contains(t, string(yamlOut.Body), "openapi:") diff --git a/services/apigatewayv2/handler_integration_responses_test.go b/services/apigatewayv2/handler_integration_responses_test.go index 2e9987ff49..0f5aa058e9 100644 --- a/services/apigatewayv2/handler_integration_responses_test.go +++ b/services/apigatewayv2/handler_integration_responses_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -69,7 +70,7 @@ func TestHandler_CreateIntegrationResponse(t *testing.T) { require.Equal(t, http.StatusCreated, integrationRR.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(integrationRR.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(integrationRR.Body.Bytes(), &integ, jsonx.V1())) integrationID = integ.IntegrationID } @@ -91,7 +92,7 @@ func TestHandler_CreateIntegrationResponse(t *testing.T) { if tt.wantRespKey != "" { var ir apigatewayv2.IntegrationResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir, jsonx.V1())) assert.Equal(t, tt.wantRespKey, ir.IntegrationResponseKey) assert.NotEmpty(t, ir.IntegrationResponseID) } @@ -125,7 +126,7 @@ func TestHandler_DuplicateIntegrationResponseKey(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/integrations/%s/integrationresponses", apiID, integration.IntegrationID) @@ -195,7 +196,7 @@ func TestHandler_GetIntegrationResponses(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) integrationID = integration.IntegrationID } @@ -215,7 +216,7 @@ func TestHandler_GetIntegrationResponses(t *testing.T) { var out struct { Items []apigatewayv2.IntegrationResponse `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.responseCnt) } }) @@ -255,7 +256,7 @@ func TestHandler_GetIntegrationResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/integrations/%s/integrationresponses", apiID, integration.IntegrationID) rr = doRequest(t, h, http.MethodPost, path, map[string]any{ @@ -264,7 +265,7 @@ func TestHandler_GetIntegrationResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var ir apigatewayv2.IntegrationResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir, jsonx.V1())) responseID := ir.IntegrationResponseID if tt.useWrongID { @@ -312,7 +313,7 @@ func TestHandler_DeleteIntegrationResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/integrations/%s/integrationresponses", apiID, integration.IntegrationID) rr = doRequest(t, h, http.MethodPost, path, map[string]any{ @@ -321,7 +322,7 @@ func TestHandler_DeleteIntegrationResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var ir apigatewayv2.IntegrationResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir, jsonx.V1())) responseID := ir.IntegrationResponseID if tt.useWrongID { @@ -354,14 +355,14 @@ func TestHandler_UpdateIntegrationResponse(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) var i apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &i)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &i, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, fmt.Sprintf("/v2/apis/%s/integrations/%s/integrationresponses", apiID, i.IntegrationID), map[string]any{"integrationResponseKey": "200"}) require.Equal(t, http.StatusCreated, rr.Code) var ir apigatewayv2.IntegrationResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ir, jsonx.V1())) return apiID, i.IntegrationID, ir.IntegrationResponseID }, diff --git a/services/apigatewayv2/handler_integrations_test.go b/services/apigatewayv2/handler_integrations_test.go index 7a5e9ca429..5f1fcceda9 100644 --- a/services/apigatewayv2/handler_integrations_test.go +++ b/services/apigatewayv2/handler_integrations_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -54,7 +55,7 @@ func TestHandler_CreateIntegration(t *testing.T) { if tt.wantStatus == http.StatusCreated { var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) assert.Equal(t, tt.integrationType, integration.IntegrationType) assert.NotEmpty(t, integration.IntegrationID) } @@ -123,7 +124,7 @@ func TestHandler_GetIntegrations(t *testing.T) { } var resp listResp - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, len(tt.integrations)) } }) @@ -165,7 +166,7 @@ func TestHandler_GetIntegration(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) integrationID = integration.IntegrationID } @@ -210,7 +211,7 @@ func TestHandler_DeleteIntegration(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) integrationID = integration.IntegrationID } @@ -261,7 +262,7 @@ func TestHandler_UpdateIntegration(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integration apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integration, jsonx.V1())) integrationID = integration.IntegrationID } @@ -350,7 +351,7 @@ func TestHandler_CreateIntegration_InvalidType(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, fmt.Sprintf("/v2/apis/%s/integrations", api.APIID), tt.body) assert.Equal(t, tt.wantStatus, rr.Code) @@ -405,7 +406,7 @@ func TestGetIntegrations_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), tc.maxResults) for _, s := range resp.Items { diff --git a/services/apigatewayv2/handler_portals.go b/services/apigatewayv2/handler_portals.go index 9f90fa6f98..a7a250367d 100644 --- a/services/apigatewayv2/handler_portals.go +++ b/services/apigatewayv2/handler_portals.go @@ -1,7 +1,8 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -9,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -449,7 +451,12 @@ func (h *Handler) handleUpdatePortal(c *echo.Context, portalID string) error { func (h *Handler) handlePublishPortal(c *echo.Context, portalID string) error { var input PublishPortalInput - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil && !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &input, + jsonx.V1(), + ); err != nil && + !errors.Is(err, io.EOF) { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } @@ -521,7 +528,7 @@ func (h *Handler) handleGetPortalProductSharingPolicy(c *echo.Context, portalPro func (h *Handler) handlePutPortalProductSharingPolicy(c *echo.Context, portalProductID string) error { var input PortalProductSharingPolicy - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } diff --git a/services/apigatewayv2/handler_portals_test.go b/services/apigatewayv2/handler_portals_test.go index 397f1886db..e53bbcf98e 100644 --- a/services/apigatewayv2/handler_portals_test.go +++ b/services/apigatewayv2/handler_portals_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -123,7 +124,7 @@ func TestHandler_CreatePortal(t *testing.T) { if tt.wantPortal { var portal apigatewayv2.Portal - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &portal)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &portal, jsonx.V1())) assert.NotEmpty(t, portal.PortalID) assert.Empty(t, portal.PublishStatus) require.NotNil(t, portal.LastModified) @@ -184,7 +185,7 @@ func TestHandler_CreatePortalProduct(t *testing.T) { if tt.wantName != "" { var product apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product, jsonx.V1())) assert.Equal(t, tt.wantName, product.DisplayName) assert.NotEmpty(t, product.PortalProductID) } @@ -234,7 +235,7 @@ func TestHandler_CreateProductPage(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var product apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product, jsonx.V1())) portalProductID = product.PortalProductID } @@ -252,7 +253,7 @@ func TestHandler_CreateProductPage(t *testing.T) { if tt.wantPage { var page apigatewayv2.ProductPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page, jsonx.V1())) assert.NotEmpty(t, page.ProductPageID) } }) @@ -333,7 +334,7 @@ func TestHandler_CreateProductRestEndpointPage(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var product apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product, jsonx.V1())) portalProductID = product.PortalProductID } @@ -351,7 +352,7 @@ func TestHandler_CreateProductRestEndpointPage(t *testing.T) { if tt.wantPage { var page apigatewayv2.ProductRestEndpointPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page, jsonx.V1())) assert.NotEmpty(t, page.ProductRestEndpointPageID) require.NotNil(t, page.RestEndpointIdentifier) require.NotNil(t, page.RestEndpointIdentifier.IdentifierParts) @@ -399,7 +400,7 @@ func TestHandler_ListPortals(t *testing.T) { var out struct { Items []apigatewayv2.Portal `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.portalCnt) }) } @@ -434,7 +435,7 @@ func TestHandler_GetPortal(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var portal apigatewayv2.Portal - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &portal)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &portal, jsonx.V1())) portalID := portal.PortalID if tt.useWrongID { @@ -486,7 +487,7 @@ func TestHandler_ListPortalProducts(t *testing.T) { var out struct { Items []apigatewayv2.PortalProduct `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.productCnt) }) } @@ -523,7 +524,7 @@ func TestHandler_GetPortalProduct(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var pp apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp, jsonx.V1())) ppID := pp.PortalProductID if tt.useWrongID { @@ -578,7 +579,7 @@ func TestHandler_ListProductPages(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var pp apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp, jsonx.V1())) ppID = pp.PortalProductID } @@ -596,7 +597,7 @@ func TestHandler_ListProductPages(t *testing.T) { var out struct { Items []apigatewayv2.ProductPage `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.pageCnt) } }) @@ -645,7 +646,7 @@ func TestHandler_ListProductRestEndpointPages(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var pp apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp, jsonx.V1())) ppID = pp.PortalProductID } @@ -671,7 +672,7 @@ func TestHandler_ListProductRestEndpointPages(t *testing.T) { var out struct { Items []apigatewayv2.ProductRestEndpointPage `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.pageCnt) } }) @@ -683,7 +684,7 @@ func createPortal(t *testing.T, h *apigatewayv2.Handler) string { rr := doRequest(t, h, http.MethodPost, "/v2/portals", validCreatePortalBody()) require.Equal(t, http.StatusCreated, rr.Code) var p apigatewayv2.Portal - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p, jsonx.V1())) return p.PortalID } @@ -695,7 +696,7 @@ func createPortalProduct(t *testing.T, h *apigatewayv2.Handler) string { }) require.Equal(t, http.StatusCreated, rr.Code) var pp apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &pp, jsonx.V1())) return pp.PortalProductID } @@ -879,7 +880,7 @@ func TestHandler_GetProductPage(t *testing.T) { fmt.Sprintf("/v2/portalproducts/%s/productpages", ppID), map[string]any{}) require.Equal(t, http.StatusCreated, rr.Code) var p apigatewayv2.ProductPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p, jsonx.V1())) return ppID, p.ProductPageID }, @@ -932,7 +933,7 @@ func TestHandler_DeleteProductPage(t *testing.T) { fmt.Sprintf("/v2/portalproducts/%s/productpages", ppID), map[string]any{}) require.Equal(t, http.StatusCreated, rr.Code) var p apigatewayv2.ProductPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p, jsonx.V1())) return ppID, p.ProductPageID }, @@ -986,7 +987,7 @@ func TestHandler_GetProductRestEndpointPage(t *testing.T) { ) require.Equal(t, http.StatusCreated, rr.Code) var p apigatewayv2.ProductRestEndpointPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p, jsonx.V1())) return ppID, p.ProductRestEndpointPageID }, @@ -1040,7 +1041,7 @@ func TestHandler_DeleteProductRestEndpointPage(t *testing.T) { ) require.Equal(t, http.StatusCreated, rr.Code) var p apigatewayv2.ProductRestEndpointPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &p, jsonx.V1())) return ppID, p.ProductRestEndpointPageID }, @@ -1094,7 +1095,7 @@ func TestHandler_ListPortals_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.Portal `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Items, 1, "maxResults=1 must limit the page to 1 item") require.NotEmpty(t, page1.NextToken, "a partial page must return a nextToken") @@ -1106,7 +1107,7 @@ func TestHandler_ListPortals_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.Portal `json:"items"` } - require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.Items, portalCount-1, "second page must return the remainder") } @@ -1130,7 +1131,7 @@ func TestHandler_ListPortalProducts_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.PortalProduct `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Items, 1, "maxResults=1 must limit the page to 1 item") require.NotEmpty(t, page1.NextToken, "a partial page must return a nextToken") @@ -1142,6 +1143,6 @@ func TestHandler_ListPortalProducts_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.PortalProduct `json:"items"` } - require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.Items, productCount-1, "second page must return the remainder") } diff --git a/services/apigatewayv2/handler_route_responses_test.go b/services/apigatewayv2/handler_route_responses_test.go index e99cd4209e..3c276fb51a 100644 --- a/services/apigatewayv2/handler_route_responses_test.go +++ b/services/apigatewayv2/handler_route_responses_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -69,7 +70,7 @@ func TestHandler_CreateRouteResponse(t *testing.T) { require.Equal(t, http.StatusCreated, routeRR.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &route, jsonx.V1())) routeID = route.RouteID } @@ -91,7 +92,7 @@ func TestHandler_CreateRouteResponse(t *testing.T) { if tt.wantRespKey != "" { var rresp apigatewayv2.RouteResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rresp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rresp, jsonx.V1())) assert.Equal(t, tt.wantRespKey, rresp.RouteResponseKey) assert.NotEmpty(t, rresp.RouteResponseID) } @@ -125,7 +126,7 @@ func TestHandler_DuplicateRouteResponseKey(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/routes/%s/routeresponses", apiID, route.RouteID) @@ -187,7 +188,7 @@ func TestHandler_GetRouteResponses(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) routeID = route.RouteID } @@ -199,7 +200,7 @@ func TestHandler_GetRouteResponses(t *testing.T) { var out struct { Items []apigatewayv2.RouteResponse `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Items, tt.responseCnt) } }) @@ -238,7 +239,7 @@ func TestHandler_GetRouteResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/routes/%s/routeresponses", apiID, route.RouteID) rr = doRequest(t, h, http.MethodPost, path, map[string]any{ @@ -247,7 +248,7 @@ func TestHandler_GetRouteResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var rr2 apigatewayv2.RouteResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2, jsonx.V1())) responseID := rr2.RouteResponseID if tt.useWrongID { @@ -293,7 +294,7 @@ func TestHandler_DeleteRouteResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) path := fmt.Sprintf("/v2/apis/%s/routes/%s/routeresponses", apiID, route.RouteID) rr = doRequest(t, h, http.MethodPost, path, map[string]any{ @@ -302,7 +303,7 @@ func TestHandler_DeleteRouteResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var rr2 apigatewayv2.RouteResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2, jsonx.V1())) responseID := rr2.RouteResponseID if tt.useWrongID { @@ -334,14 +335,14 @@ func TestHandler_UpdateRouteResponse(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) var r apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &r, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, fmt.Sprintf("/v2/apis/%s/routes/%s/routeresponses", apiID, r.RouteID), map[string]any{"routeResponseKey": "$default"}) require.Equal(t, http.StatusCreated, rr.Code) var rr2 apigatewayv2.RouteResponse - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &rr2, jsonx.V1())) return apiID, r.RouteID, rr2.RouteResponseID }, diff --git a/services/apigatewayv2/handler_routes_test.go b/services/apigatewayv2/handler_routes_test.go index 6d535e431e..88edf4b4fc 100644 --- a/services/apigatewayv2/handler_routes_test.go +++ b/services/apigatewayv2/handler_routes_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -54,7 +55,7 @@ func TestHandler_CreateRoute(t *testing.T) { if tt.wantStatus == http.StatusCreated { var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) assert.Equal(t, tt.routeKey, route.RouteKey) assert.NotEmpty(t, route.RouteID) } @@ -117,7 +118,7 @@ func TestHandler_GetRoutes(t *testing.T) { } var resp listResp - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, len(tt.routes)) } }) @@ -159,7 +160,7 @@ func TestHandler_GetRoute(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) routeID = route.RouteID } @@ -204,7 +205,7 @@ func TestHandler_DeleteRoute(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) routeID = route.RouteID } @@ -249,7 +250,7 @@ func TestHandler_UpdateRoute(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var route apigatewayv2.Route - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &route, jsonx.V1())) routeID = route.RouteID } @@ -355,7 +356,7 @@ func TestUpdateRouteClearsAuthorizerIDOnNone(t *testing.T) { require.Equal(t, http.StatusCreated, authRR.Code) var authResult map[string]any - require.NoError(t, json.Unmarshal(authRR.Body.Bytes(), &authResult)) + require.NoError(t, json.Unmarshal(authRR.Body.Bytes(), &authResult, jsonx.V1())) authID := authResult["authorizerId"].(string) // Create a route with JWT authorization. @@ -367,7 +368,7 @@ func TestUpdateRouteClearsAuthorizerIDOnNone(t *testing.T) { require.Equal(t, http.StatusCreated, routeRR.Code) var routeResult map[string]any - require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &routeResult)) + require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &routeResult, jsonx.V1())) routeID := routeResult["routeId"].(string) // Patch the route with the test body. @@ -381,7 +382,7 @@ func TestUpdateRouteClearsAuthorizerIDOnNone(t *testing.T) { require.Equal(t, http.StatusOK, patchRR.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(patchRR.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(patchRR.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, tt.wantAuthType, updated["authorizationType"]) @@ -417,7 +418,7 @@ func TestUpdateRouteClearsAuthorizerIDRoundtrip(t *testing.T) { require.Equal(t, http.StatusCreated, authRR.Code) var authResult map[string]any - require.NoError(t, json.Unmarshal(authRR.Body.Bytes(), &authResult)) + require.NoError(t, json.Unmarshal(authRR.Body.Bytes(), &authResult, jsonx.V1())) authID := authResult["authorizerId"].(string) // Create route with JWT auth. @@ -429,7 +430,7 @@ func TestUpdateRouteClearsAuthorizerIDRoundtrip(t *testing.T) { require.Equal(t, http.StatusCreated, routeRR.Code) var routeResult map[string]any - require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &routeResult)) + require.NoError(t, json.Unmarshal(routeRR.Body.Bytes(), &routeResult, jsonx.V1())) routeID := routeResult["routeId"].(string) // Verify initial state: JWT auth with authorizer ID set. @@ -446,7 +447,7 @@ func TestUpdateRouteClearsAuthorizerIDRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, getRR.Code) var getResult map[string]any - require.NoError(t, json.Unmarshal(getRR.Body.Bytes(), &getResult)) + require.NoError(t, json.Unmarshal(getRR.Body.Bytes(), &getResult, jsonx.V1())) assert.Equal(t, "NONE", getResult["authorizationType"]) assert.Empty(t, getResult["authorizerId"], "authorizerId should be empty after UpdateRoute to NONE") @@ -498,7 +499,7 @@ func TestGetRoutes_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []apigatewayv2.Route `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), tc.maxResults) for _, r := range resp.Items { @@ -540,7 +541,7 @@ func TestCreateRoute_APIKeyRequiredPresentAndFalse(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) v, hasKey := resp["apiKeyRequired"] assert.True(t, hasKey, "apiKeyRequired should be present in response") @@ -562,7 +563,7 @@ func TestCreateRoute_AuthorizationScopesIsEmptyArray(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) raw, hasKey := resp["authorizationScopes"] assert.True(t, hasKey, "authorizationScopes should be present in response") @@ -586,7 +587,7 @@ func TestGetRoute_AuthorizationScopesIsEmptyArray(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created, jsonx.V1())) routeID, _ := created["routeId"].(string) require.NotEmpty(t, routeID) @@ -595,7 +596,7 @@ func TestGetRoute_AuthorizationScopesIsEmptyArray(t *testing.T) { require.Equal(t, http.StatusOK, rr2.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rr2.Body.Bytes(), &got, jsonx.V1())) raw, hasKey := got["authorizationScopes"] assert.True(t, hasKey, "authorizationScopes should be present in GetRoute response") diff --git a/services/apigatewayv2/handler_stages_test.go b/services/apigatewayv2/handler_stages_test.go index 9759e2bbce..dac4678ee6 100644 --- a/services/apigatewayv2/handler_stages_test.go +++ b/services/apigatewayv2/handler_stages_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -54,7 +55,7 @@ func TestHandler_CreateStage(t *testing.T) { if tt.wantStatus == http.StatusCreated { var stage apigatewayv2.Stage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &stage)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &stage, jsonx.V1())) assert.Equal(t, tt.stageName, stage.StageName) } }) @@ -116,7 +117,7 @@ func TestHandler_GetStages(t *testing.T) { } var resp listResp - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, len(tt.stages)) } }) @@ -306,7 +307,7 @@ func TestGetStages_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.LessOrEqual(t, len(resp.Items), tc.maxResults) for _, s := range resp.Items { diff --git a/services/apigatewayv2/handler_tags.go b/services/apigatewayv2/handler_tags.go index cb84fee7c4..8e2ee0a080 100644 --- a/services/apigatewayv2/handler_tags.go +++ b/services/apigatewayv2/handler_tags.go @@ -1,7 +1,8 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -75,7 +77,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string) error { log := logger.Load(c.Request().Context()) var input tagResourceInput - if err := json.NewDecoder(c.Request().Body).Decode(&input); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &input, jsonx.V1()); err != nil { return writeErr(c, http.StatusBadRequest, msgInvalidBody) } diff --git a/services/apigatewayv2/handler_tags_test.go b/services/apigatewayv2/handler_tags_test.go index d8ba9fd64f..6e44eea8d3 100644 --- a/services/apigatewayv2/handler_tags_test.go +++ b/services/apigatewayv2/handler_tags_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Tags(t *testing.T) { @@ -75,7 +77,7 @@ func TestHandler_Tags(t *testing.T) { var out struct { Tags map[string]string `json:"tags"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantTags, out.Tags) } }) diff --git a/services/apigatewayv2/handler_test.go b/services/apigatewayv2/handler_test.go index eb896410a1..ec86211a08 100644 --- a/services/apigatewayv2/handler_test.go +++ b/services/apigatewayv2/handler_test.go @@ -3,7 +3,7 @@ package apigatewayv2_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *apigatewayv2.Handler, method, path string, body var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) } else { @@ -77,7 +78,7 @@ func createAPI(t *testing.T, h *apigatewayv2.Handler, name string) string { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) return api.APIID } diff --git a/services/apigatewayv2/handler_vpc_links_test.go b/services/apigatewayv2/handler_vpc_links_test.go index 43e9895a18..41cd5fffa5 100644 --- a/services/apigatewayv2/handler_vpc_links_test.go +++ b/services/apigatewayv2/handler_vpc_links_test.go @@ -1,13 +1,15 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -46,14 +48,14 @@ func TestVpcLinkSecurityGroupIDsNullBug(t *testing.T) { rr := doRequest(t, h, http.MethodPost, "/v2/vpclinks", tt.body) require.Equal(t, http.StatusCreated, rr.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw, jsonx.V1())) _, ok := raw["securityGroupIds"] assert.True(t, ok, "securityGroupIds key must always be present in VpcLink response") var link apigatewayv2.VpcLink - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &link)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &link, jsonx.V1())) assert.Equal(t, tt.wantSecGroups, link.SecurityGroupIDs) }) } @@ -71,8 +73,8 @@ func TestVpcLinkSubnetIDsNullBug(t *testing.T) { }) require.Equal(t, http.StatusCreated, rr.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &raw, jsonx.V1())) _, ok := raw["subnetIds"] assert.True(t, ok, "subnetIds key must always be present in VpcLink response") @@ -92,13 +94,13 @@ func TestVpcLinkGetReturnsArrayFields(t *testing.T) { require.Equal(t, http.StatusCreated, createRR.Code) var created apigatewayv2.VpcLink - require.NoError(t, json.Unmarshal(createRR.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRR.Body.Bytes(), &created, jsonx.V1())) getRR := doRequest(t, h, http.MethodGet, "/v2/vpclinks/"+created.VpcLinkID, nil) require.Equal(t, http.StatusOK, getRR.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(getRR.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(getRR.Body.Bytes(), &raw, jsonx.V1())) _, hasSec := raw["securityGroupIds"] assert.True(t, hasSec, "securityGroupIds key must be present in GetVpcLink response") diff --git a/services/apigatewayv2/http_proxy.go b/services/apigatewayv2/http_proxy.go index bcf614317b..5a81bbbae4 100644 --- a/services/apigatewayv2/http_proxy.go +++ b/services/apigatewayv2/http_proxy.go @@ -2,7 +2,7 @@ package apigatewayv2 import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -19,6 +19,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -373,7 +374,7 @@ func buildV1Payload( }, } - p, _ := json.Marshal(event) + p, _ := json.Marshal(event, jsonx.V1()) return p } @@ -451,7 +452,7 @@ func buildV2Payload( }, } - p, _ := json.Marshal(event) + p, _ := json.Marshal(event, jsonx.V1()) return p } diff --git a/services/apigatewayv2/http_proxy_flows_test.go b/services/apigatewayv2/http_proxy_flows_test.go index c29cee4d90..05d211089c 100644 --- a/services/apigatewayv2/http_proxy_flows_test.go +++ b/services/apigatewayv2/http_proxy_flows_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "maps" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -39,7 +40,7 @@ func newFlowAPI(t *testing.T, cors map[string]any) *flowAPI { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) return &flowAPI{h: h, apiID: api.APIID} } @@ -51,7 +52,7 @@ func (f *flowAPI) integration(t *testing.T, body map[string]any) string { require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String()) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) return integ.IntegrationID } @@ -95,7 +96,7 @@ func (r *recordedEvents) last(t *testing.T) map[string]any { func recordingInvoker(rec *recordedEvents, response string) *mockLambdaInvoker { return &mockLambdaInvoker{fn: func(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { var ev map[string]any - if err := json.Unmarshal(payload, &ev); err == nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err == nil { rec.mu.Lock() rec.events = append(rec.events, ev) rec.mu.Unlock() @@ -359,7 +360,7 @@ func TestHTTPAPIProxy_JWTAuthorizerCognitoFlow(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var authz apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authz)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authz, jsonx.V1())) extra := map[string]any{"authorizationType": "JWT", "authorizerId": authz.AuthorizerID} if tt.scopes != nil { @@ -418,7 +419,7 @@ func TestHTTPAPIProxy_LambdaAuthorizerContext(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var authz apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authz)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authz, jsonx.V1())) f.lambdaRoute(t, "GET /secure", "2.0", map[string]any{"authorizationType": "CUSTOM", "authorizerId": authz.AuthorizerID}) diff --git a/services/apigatewayv2/http_proxy_test.go b/services/apigatewayv2/http_proxy_test.go index b4dd6947d7..3f32f6f887 100644 --- a/services/apigatewayv2/http_proxy_test.go +++ b/services/apigatewayv2/http_proxy_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -36,7 +37,7 @@ func (m *mockLambdaInvoker) InvokeFunction( } resp := map[string]any{"statusCode": 200, "body": "ok"} - b, _ := json.Marshal(resp) + b, _ := json.Marshal(resp, jsonx.V1()) return b, 200, nil } @@ -119,7 +120,7 @@ func buildHTTPAPIWithLambda( require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) theAPIID := api.APIID @@ -132,7 +133,7 @@ func buildHTTPAPIWithLambda( require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) theIntegrationID := integ.IntegrationID @@ -222,12 +223,12 @@ func TestHTTPAPIProxy_RouteMatching(t *testing.T) { lambda := &mockLambdaInvoker{ fn: func(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { var ev map[string]any - if err := json.Unmarshal(payload, &ev); err == nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err == nil { capturedRouteKey, _ = ev["routeKey"].(string) } resp := map[string]any{"statusCode": 200, "body": "routed"} - b, _ := json.Marshal(resp) + b, _ := json.Marshal(resp, jsonx.V1()) return b, 200, nil }, @@ -247,7 +248,7 @@ func TestHTTPAPIProxy_RouteMatching(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+apiID+"/routes", map[string]any{ "routeKey": rk, @@ -337,10 +338,10 @@ func TestHTTPAPIProxy_PayloadFormat(t *testing.T) { var capturedPayload map[string]any lambda := &mockLambdaInvoker{ fn: func(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { - _ = json.Unmarshal(payload, &capturedPayload) + _ = json.Unmarshal(payload, &capturedPayload, jsonx.V1()) resp := map[string]any{"statusCode": 200, "body": "ok"} - b, _ := json.Marshal(resp) + b, _ := json.Marshal(resp, jsonx.V1()) return b, 200, nil }, @@ -354,7 +355,7 @@ func TestHTTPAPIProxy_PayloadFormat(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/integrations", map[string]any{ "integrationType": "AWS_PROXY", @@ -364,7 +365,7 @@ func TestHTTPAPIProxy_PayloadFormat(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/routes", map[string]any{ "routeKey": "GET /test", @@ -414,7 +415,7 @@ func TestHTTPAPIProxy_CORSPreflight(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) // Create a route (even though OPTIONS won't use it). rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/integrations", map[string]any{ @@ -424,7 +425,7 @@ func TestHTTPAPIProxy_CORSPreflight(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/routes", map[string]any{ "routeKey": "GET /items", @@ -459,7 +460,7 @@ func TestHTTPAPIProxy_JWTAuthorizer(t *testing.T) { fn: func(_ context.Context, _, _ string, _ []byte) ([]byte, int, error) { integrationCalls.Add(1) - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, @@ -472,7 +473,7 @@ func TestHTTPAPIProxy_JWTAuthorizer(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) // Create JWT authorizer. rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/authorizers", map[string]any{ @@ -487,7 +488,7 @@ func TestHTTPAPIProxy_JWTAuthorizer(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var authorizer apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authorizer)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authorizer, jsonx.V1())) // Create integration + route with JWT auth. rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/integrations", map[string]any{ @@ -497,7 +498,7 @@ func TestHTTPAPIProxy_JWTAuthorizer(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/routes", map[string]any{ "routeKey": "GET /secure", @@ -535,7 +536,7 @@ func TestHTTPAPIProxy_JWTAuthorizerMissing_DoesNotInvokeIntegration(t *testing.T fn: func(_ context.Context, _, _ string, _ []byte) ([]byte, int, error) { integrationCalls.Add(1) - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, @@ -547,7 +548,7 @@ func TestHTTPAPIProxy_JWTAuthorizerMissing_DoesNotInvokeIntegration(t *testing.T require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/integrations", map[string]any{ "integrationType": "AWS_PROXY", @@ -556,7 +557,7 @@ func TestHTTPAPIProxy_JWTAuthorizerMissing_DoesNotInvokeIntegration(t *testing.T require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) // authorizerId names an authorizer that was never created. rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/routes", map[string]any{ @@ -612,7 +613,7 @@ func TestHTTPAPIProxy_JWTAuthorizer_ValidCognitoToken(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var api apigatewayv2.API - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &api, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/authorizers", map[string]any{ "name": "cognito-jwt", @@ -626,7 +627,7 @@ func TestHTTPAPIProxy_JWTAuthorizer_ValidCognitoToken(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var authorizer apigatewayv2.Authorizer - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authorizer)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &authorizer, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/integrations", map[string]any{ "integrationType": "AWS_PROXY", @@ -635,7 +636,7 @@ func TestHTTPAPIProxy_JWTAuthorizer_ValidCognitoToken(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+api.APIID+"/routes", map[string]any{ "routeKey": "GET /secure", @@ -707,7 +708,7 @@ func TestHTTPAPIProxy_LambdaResponse(t *testing.T) { lambda := &mockLambdaInvoker{ fn: func(_ context.Context, _, _ string, _ []byte) ([]byte, int, error) { - b, _ := json.Marshal(tt.lambdaBody) + b, _ := json.Marshal(tt.lambdaBody, jsonx.V1()) return b, 200, nil }, @@ -744,13 +745,13 @@ func TestHTTPAPIProxy_PathParameters(t *testing.T) { h.SetLambdaInvoker(&mockLambdaInvoker{ fn: func(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { var ev map[string]any - if err := json.Unmarshal(payload, &ev); err == nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err == nil { if pp, ok := ev["pathParameters"].(map[string]any); ok { capturedPathParams = pp } } - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, @@ -795,7 +796,7 @@ func TestHTTPAPIProxy_DeploymentSnapshot(t *testing.T) { body = "from-b" } - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": body}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": body}, jsonx.V1()) return b, 200, nil }, @@ -812,7 +813,7 @@ func TestHTTPAPIProxy_DeploymentSnapshot(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var integ apigatewayv2.Integration - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &integ, jsonx.V1())) rr = doRequest(t, h, http.MethodPost, "/v2/apis/"+apiID+"/routes", map[string]any{ "routeKey": "GET /a", diff --git a/services/apigatewayv2/http_proxy_throttle_test.go b/services/apigatewayv2/http_proxy_throttle_test.go index ec9b1a26dd..4ec7a6a633 100644 --- a/services/apigatewayv2/http_proxy_throttle_test.go +++ b/services/apigatewayv2/http_proxy_throttle_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "sync/atomic" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -38,7 +39,7 @@ func TestHTTPAPIProxy_RouteThrottle_TooManyRequests(t *testing.T) { fn: func(_ context.Context, _, _ string, _ []byte) ([]byte, int, error) { integrationCalls.Add(1) - b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}) + b, _ := json.Marshal(map[string]any{"statusCode": 200, "body": "ok"}, jsonx.V1()) return b, 200, nil }, diff --git a/services/apigatewayv2/lambda_response.go b/services/apigatewayv2/lambda_response.go index 6d560285f1..f7a547293d 100644 --- a/services/apigatewayv2/lambda_response.go +++ b/services/apigatewayv2/lambda_response.go @@ -3,11 +3,14 @@ package apigatewayv2 import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -22,16 +25,16 @@ const ( func writeHTTPAPILambdaResponse(c *echo.Context, respBytes []byte, payloadVersion string) error { trimmed := bytes.TrimSpace(respBytes) - var envelope map[string]json.RawMessage + var envelope map[string]jsontext.Value - isObject := json.Unmarshal(trimmed, &envelope) == nil && envelope != nil + isObject := json.Unmarshal(trimmed, &envelope, jsonx.V1()) == nil && envelope != nil if isObject && isFunctionErrorEnvelope(envelope) { return writeJSONMessage(c, http.StatusInternalServerError, msgInternalError) } _, hasStatus := envelope["statusCode"] if !isObject || !hasStatus { - if payloadVersion == payloadFormatV1 || len(trimmed) == 0 || !json.Valid(trimmed) { + if payloadVersion == payloadFormatV1 || len(trimmed) == 0 || !jsontext.Value(trimmed).IsValid(jsonx.V1()) { return writeJSONMessage(c, http.StatusInternalServerError, msgInternalError) } @@ -43,14 +46,14 @@ func writeHTTPAPILambdaResponse(c *echo.Context, respBytes []byte, payloadVersio } var lambdaResp httpAPILambdaResponse - if err := json.Unmarshal(trimmed, &lambdaResp); err != nil { + if err := json.Unmarshal(trimmed, &lambdaResp, jsonx.V1()); err != nil { return writeJSONMessage(c, http.StatusInternalServerError, msgInternalError) } return writeLambdaEnvelope(c, &lambdaResp) } -func isFunctionErrorEnvelope(envelope map[string]json.RawMessage) bool { +func isFunctionErrorEnvelope(envelope map[string]jsontext.Value) bool { _, hasMsg := envelope["errorMessage"] _, hasType := envelope["errorType"] _, hasStatus := envelope["statusCode"] @@ -111,7 +114,7 @@ func writeJSONMessage(c *echo.Context, status int, body string) error { // httpAPIMessage renders the `{"message":"..."}` body execute-api returns for gateway errors. func httpAPIMessage(msg string) string { - b, _ := json.Marshal(map[string]string{jsonKeyMessage: msg}) + b, _ := json.Marshal(map[string]string{jsonKeyMessage: msg}, jsonx.V1()) return strings.TrimSpace(string(b)) } diff --git a/services/apigatewayv2/models.go b/services/apigatewayv2/models.go index 9bfc20e50c..45f18033b7 100644 --- a/services/apigatewayv2/models.go +++ b/services/apigatewayv2/models.go @@ -1,8 +1,10 @@ package apigatewayv2 import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // isoTime wraps [time.Time] and marshals to/from a JSON string in RFC3339 format, @@ -12,12 +14,12 @@ type isoTime struct { } func (t isoTime) MarshalJSON() ([]byte, error) { - return json.Marshal(t.UTC().Format(time.RFC3339)) + return json.Marshal(t.UTC().Format(time.RFC3339), jsonx.V1()) } func (t *isoTime) UnmarshalJSON(b []byte) error { var s string - if err := json.Unmarshal(b, &s); err != nil { + if err := json.Unmarshal(b, &s, jsonx.V1()); err != nil { return err } diff --git a/services/apigatewayv2/multi_region_test.go b/services/apigatewayv2/multi_region_test.go index c6ed1738dc..87abad8c80 100644 --- a/services/apigatewayv2/multi_region_test.go +++ b/services/apigatewayv2/multi_region_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -37,7 +38,7 @@ func regionCall(t *testing.T, h *apigatewayv2.Handler, region, method, path, bod require.Less(t, rec.Code, http.StatusMultipleChoices, rec.Body.String()) out := map[string]any{} - if rec.Body.Len() > 0 && json.Unmarshal(rec.Body.Bytes(), &out) != nil { + if rec.Body.Len() > 0 && json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) != nil { out["raw"] = rec.Body.String() } diff --git a/services/apigatewayv2/persistence.go b/services/apigatewayv2/persistence.go index 80c00f5490..24a5ec5aca 100644 --- a/services/apigatewayv2/persistence.go +++ b/services/apigatewayv2/persistence.go @@ -2,7 +2,7 @@ package apigatewayv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -619,9 +619,9 @@ var dirtyTableNames = struct { // registerAllTables doc for the clean/dirty split), merged into one map so a // single Tables blob round-trips the whole backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - PortalProductSharingPolicies map[string]string `json:"portalProductSharingPolicies,omitempty"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + PortalProductSharingPolicies map[string]string `json:"portalProductSharingPolicies,omitempty"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/apigatewayv2/rse.go b/services/apigatewayv2/rse.go index 56b1fdbecb..1a9c190373 100644 --- a/services/apigatewayv2/rse.go +++ b/services/apigatewayv2/rse.go @@ -2,11 +2,13 @@ package apigatewayv2 import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // EvalRouteSelectionExpression evaluates an AWS API Gateway v2 route-selection @@ -95,7 +97,7 @@ func parseJSONBody(r *http.Request) map[string]any { } var obj map[string]any - if jsonErr := json.Unmarshal(raw, &obj); jsonErr != nil { + if jsonErr := json.Unmarshal(raw, &obj, jsonx.V1()); jsonErr != nil { return nil } diff --git a/services/apigatewayv2/wire_field_fixes_respsweep_test.go b/services/apigatewayv2/wire_field_fixes_respsweep_test.go index 5b4ad9a947..b14aceede6 100644 --- a/services/apigatewayv2/wire_field_fixes_respsweep_test.go +++ b/services/apigatewayv2/wire_field_fixes_respsweep_test.go @@ -1,13 +1,14 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -74,7 +75,7 @@ func testPortalIncludedPortalProductArnsPresent(t *testing.T, h *apigatewayv2.Ha require.Equal(t, http.StatusCreated, rr.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created, jsonx.V1())) arns, ok := created["includedPortalProductArns"] assert.True(t, ok, "includedPortalProductArns key must be present on Create") assert.Equal(t, []any{}, arns) @@ -85,7 +86,7 @@ func testPortalIncludedPortalProductArnsPresent(t *testing.T, h *apigatewayv2.Ha var listed struct { Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed, jsonx.V1())) require.Len(t, listed.Items, 1) arns, ok = listed.Items[0]["includedPortalProductArns"] @@ -100,7 +101,7 @@ func testPortalProductDescriptionPresent(t *testing.T, h *apigatewayv2.Handler) require.Equal(t, http.StatusCreated, rr.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created, jsonx.V1())) desc, ok := created["description"] assert.True(t, ok, "description key must be present on Create") assert.Empty(t, desc) @@ -111,7 +112,7 @@ func testPortalProductDescriptionPresent(t *testing.T, h *apigatewayv2.Handler) var listed struct { Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed, jsonx.V1())) require.Len(t, listed.Items, 1) desc, ok = listed.Items[0]["description"] @@ -126,7 +127,7 @@ func testProductPageArnAndTitlePresent(t *testing.T, h *apigatewayv2.Handler) { require.Equal(t, http.StatusCreated, rr.Code) var product map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product, jsonx.V1())) portalProductID, _ := product["portalProductId"].(string) require.NotEmpty(t, portalProductID) @@ -137,7 +138,7 @@ func testProductPageArnAndTitlePresent(t *testing.T, h *apigatewayv2.Handler) { require.Equal(t, http.StatusCreated, rr.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created, jsonx.V1())) assert.NotEmpty(t, created["productPageArn"]) assert.Equal(t, "My Page", created["pageTitle"]) @@ -147,7 +148,7 @@ func testProductPageArnAndTitlePresent(t *testing.T, h *apigatewayv2.Handler) { var listed struct { Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &listed, jsonx.V1())) require.Len(t, listed.Items, 1) assert.NotEmpty(t, listed.Items[0]["productPageArn"]) assert.Equal(t, "My Page", listed.Items[0]["pageTitle"]) diff --git a/services/apigatewayv2/wire_field_fixes_test.go b/services/apigatewayv2/wire_field_fixes_test.go index 4a91cb8575..3b2e674e22 100644 --- a/services/apigatewayv2/wire_field_fixes_test.go +++ b/services/apigatewayv2/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package apigatewayv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -550,7 +551,7 @@ func TestCreateProductRestEndpointPage_DisplayContent(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var product apigatewayv2.PortalProduct - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &product, jsonx.V1())) body := map[string]any{ "restEndpointIdentifier": map[string]any{ @@ -571,7 +572,7 @@ func TestCreateProductRestEndpointPage_DisplayContent(t *testing.T) { require.Equal(t, http.StatusCreated, rr.Code) var created apigatewayv2.ProductRestEndpointPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, wantEndpoint, created.DisplayContent["endpoint"]) assert.Equal(t, "custom docs", created.DisplayContent["body"]) assert.Equal(t, wantEndpoint, created.Endpoint) @@ -584,7 +585,7 @@ func TestCreateProductRestEndpointPage_DisplayContent(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var got apigatewayv2.ProductRestEndpointPage - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, wantEndpoint, got.DisplayContent["endpoint"]) assert.Equal(t, "custom docs", got.DisplayContent["body"]) assert.Equal(t, wantEndpoint, got.Endpoint) diff --git a/services/apigatewayv2/ws_proxy.go b/services/apigatewayv2/ws_proxy.go index c3d1455490..485e9318ff 100644 --- a/services/apigatewayv2/ws_proxy.go +++ b/services/apigatewayv2/ws_proxy.go @@ -3,7 +3,7 @@ package apigatewayv2 import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -19,6 +19,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -164,7 +165,7 @@ func (s *wsSession) sendForbidden() { jsonKeyMessage: wsForbiddenMessage, "connectionId": s.connID, "requestId": uuid.NewString(), - }) + }, jsonx.V1()) s.send(b) } @@ -223,7 +224,7 @@ func (s *wsSession) invoke( return nil, fmt.Errorf("%w: %s", ErrInvalidLambdaArn, integration.IntegrationURI) } - payload, marshalErr := json.Marshal(event) + payload, marshalErr := json.Marshal(event, jsonx.V1()) if marshalErr != nil { return nil, fmt.Errorf("failed to marshal WebSocket event: %w", marshalErr) } @@ -364,7 +365,7 @@ func proxyResponseStatus(out []byte) int { var resp struct { StatusCode *int `json:"statusCode"` } - if json.Unmarshal(out, &resp) != nil || resp.StatusCode == nil { + if json.Unmarshal(out, &resp, jsonx.V1()) != nil || resp.StatusCode == nil { return 0 } @@ -441,7 +442,7 @@ func (h *Handler) enforceWSRequestAuthorizer(c *echo.Context, s *wsSession, auth "multiValueQueryStringParameters": s.query, "stageVariables": map[string]string{}, evKeyRequestContext: s.requestContext(routeKeyConnect, wsEventConnect), - }) + }, jsonx.V1()) if err != nil { return errRouteAuthConfigInvalid } @@ -458,7 +459,7 @@ func (h *Handler) enforceWSRequestAuthorizer(c *echo.Context, s *wsSession, auth var policy iamPolicyResponse allow, explicit := false, false - if json.Unmarshal(out, &policy) == nil { + if json.Unmarshal(out, &policy, jsonx.V1()) == nil { allow, explicit = evaluateIAMPolicy(policy.PolicyDocument.Statement, methodArn) } @@ -497,7 +498,7 @@ func evalRouteSelection(expr string, body []byte) string { expr = strings.ReplaceAll(expr, `\$`, escaped) var doc any - _ = json.Unmarshal(body, &doc) + _ = json.Unmarshal(body, &doc, jsonx.V1()) failed := false out := wsBodyVarRE.ReplaceAllStringFunc(expr, func(m string) string { diff --git a/services/apigatewayv2/ws_realclient_test.go b/services/apigatewayv2/ws_realclient_test.go index 9f8cf81ee3..d1b9013f1a 100644 --- a/services/apigatewayv2/ws_realclient_test.go +++ b/services/apigatewayv2/ws_realclient_test.go @@ -2,7 +2,7 @@ package apigatewayv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/apigatewaymanagementapi" "github.com/blackbirdworks/gopherstack/services/apigatewayv2" @@ -40,7 +41,7 @@ type wsLambda struct { func (l *wsLambda) InvokeFunction(_ context.Context, fn, _ string, payload []byte) ([]byte, int, error) { var ev map[string]any - _ = json.Unmarshal(payload, &ev) + _ = json.Unmarshal(payload, &ev, jsonx.V1()) l.calls <- wsLambdaCall{fn: fn, event: ev} if h := l.handlers[fn]; h != nil { @@ -459,7 +460,7 @@ func TestWebSocket_NoMatchingRouteSendsForbidden(t *testing.T) { require.NoError(t, conn.WriteMessage(websocket.TextMessage, []byte(`{"action":"x"}`))) var frame map[string]string - require.NoError(t, json.Unmarshal([]byte(readText(t, conn)), &frame)) + require.NoError(t, json.Unmarshal([]byte(readText(t, conn)), &frame, jsonx.V1())) assert.Equal(t, "Forbidden", frame["message"]) assert.NotEmpty(t, frame["connectionId"]) } diff --git a/services/appconfig/deletion_protection_test.go b/services/appconfig/deletion_protection_test.go index 4f61628b16..9c0389ffed 100644 --- a/services/appconfig/deletion_protection_test.go +++ b/services/appconfig/deletion_protection_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/appconfig" "github.com/blackbirdworks/gopherstack/services/appconfigdata" @@ -58,20 +59,20 @@ func newDeletionProtectionFixture(t *testing.T) *deletionProtectionFixture { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"name":"dp-env"}`)) require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"name":"dp-profile","locationUri":"hosted","type":"AWS.Freeform"}`)) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) return &deletionProtectionFixture{h: h, acd: acd, appID: app.ID, envID: env.ID, profileID: profile.ID} } diff --git a/services/appconfig/errsweep_wire_shape_test.go b/services/appconfig/errsweep_wire_shape_test.go index adea34d7dc..4a2d4e01ee 100644 --- a/services/appconfig/errsweep_wire_shape_test.go +++ b/services/appconfig/errsweep_wire_shape_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/appconfig" @@ -55,6 +56,6 @@ func TestHandler_UnmatchedRouteCarriesTypedErrorCode(t *testing.T) { require.NoError(t, err) var decoded map[string]any - require.NoError(t, json.Unmarshal(raw, &decoded)) + require.NoError(t, json.Unmarshal(raw, &decoded, jsonx.V1())) require.NotEmpty(t, decoded["message"]) } diff --git a/services/appconfig/extension_actions.go b/services/appconfig/extension_actions.go index dee040d9ba..102a32ee18 100644 --- a/services/appconfig/extension_actions.go +++ b/services/appconfig/extension_actions.go @@ -5,7 +5,8 @@ import ( "crypto/rand" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +14,7 @@ import ( "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -185,7 +187,7 @@ func (b *InMemoryBackend) runPreActions( ev["Parameters"] = params ev["Content"] = base64.StdEncoding.EncodeToString(content) - payload, err := json.Marshal(ev) + payload, err := json.Marshal(ev, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: encoding extension event: %w", ErrBadRequest, err) } @@ -209,12 +211,12 @@ func applyActionResponse(uri string, raw, content []byte) ([]byte, error) { return content, nil } - if !json.Valid(raw) { + if !jsontext.Value(raw).IsValid(jsonx.V1()) { return content, nil } var resp actionResponse - if err := json.Unmarshal(raw, &resp); err != nil { + if err := json.Unmarshal(raw, &resp, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: extension action %s returned an unreadable response: %w", ErrBadRequest, uri, err) } diff --git a/services/appconfig/extension_actions_test.go b/services/appconfig/extension_actions_test.go index c246ad0033..5e350f3b29 100644 --- a/services/appconfig/extension_actions_test.go +++ b/services/appconfig/extension_actions_test.go @@ -3,7 +3,7 @@ package appconfig_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "sync" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -50,7 +51,7 @@ func (r *recordingInvoker) lastEvent(t *testing.T) map[string]any { require.NotEmpty(t, r.payloads) var ev map[string]any - require.NoError(t, json.Unmarshal(r.payloads[len(r.payloads)-1], &ev)) + require.NoError(t, json.Unmarshal(r.payloads[len(r.payloads)-1], &ev, jsonx.V1())) return ev } diff --git a/services/appconfig/extension_events.go b/services/appconfig/extension_events.go index f8e69e7ba6..45a1db3f6a 100644 --- a/services/appconfig/extension_events.go +++ b/services/appconfig/extension_events.go @@ -2,7 +2,8 @@ package appconfig import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "regexp" @@ -11,6 +12,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ebbackend "github.com/blackbirdworks/gopherstack/services/eventbridge" @@ -276,7 +278,7 @@ func (b *InMemoryBackend) deliverAction(act preAction, event map[string]any) ([] return nil, nil } - payload, err := json.Marshal(ev) + payload, err := json.Marshal(ev, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: encoding extension event: %w", ErrBadRequest, err) } @@ -303,7 +305,7 @@ func stringifyDeploymentNumber(ev map[string]any) map[string]any { } func (b *InMemoryBackend) deliverSNS(act preAction, ev map[string]any) error { - msg, err := json.Marshal(stringifyDeploymentNumber(ev)) + msg, err := json.Marshal(stringifyDeploymentNumber(ev), jsonx.V1()) if err != nil { return err } @@ -315,7 +317,7 @@ func (b *InMemoryBackend) deliverSNS(act preAction, ev map[string]any) error { } func (b *InMemoryBackend) deliverSQS(act preAction, ev map[string]any) error { - body, err := json.Marshal(stringifyDeploymentNumber(ev)) + body, err := json.Marshal(stringifyDeploymentNumber(ev), jsonx.V1()) if err != nil { return err } @@ -324,7 +326,7 @@ func (b *InMemoryBackend) deliverSQS(act preAction, ev map[string]any) error { } func (b *InMemoryBackend) deliverEvents(act preAction, ev map[string]any) error { - detail, err := json.Marshal(ev) + detail, err := json.Marshal(ev, jsonx.V1()) if err != nil { return err } @@ -404,12 +406,12 @@ func (b *InMemoryBackend) tickRollbackReason(job tickJob) string { return fmt.Sprintf("Extension action %s failed: %v", act.uri, err) } - if len(raw) == 0 || !json.Valid(raw) { + if len(raw) == 0 || !jsontext.Value(raw).IsValid(jsonx.V1()) { continue } var resp actionResponse - if json.Unmarshal(raw, &resp) != nil { + if json.Unmarshal(raw, &resp, jsonx.V1()) != nil { continue } diff --git a/services/appconfig/extension_events_test.go b/services/appconfig/extension_events_test.go index 6086b0c6cc..c1aa7bf588 100644 --- a/services/appconfig/extension_events_test.go +++ b/services/appconfig/extension_events_test.go @@ -2,7 +2,7 @@ package appconfig_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "slices" "sync" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -104,7 +105,7 @@ type lifecycleInvoker struct { func (l *lifecycleInvoker) Invoke(_ context.Context, _ string, payload []byte) ([]byte, error) { var ev map[string]any - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, err } @@ -270,7 +271,7 @@ func TestExtensionActions_OnDeploymentTargets(t *testing.T) { assert.Equal(t, "OnDeploymentComplete", snsMsgs[1].attrs["MessageType"]) var m map[string]any - require.NoError(t, json.Unmarshal([]byte(snsMsgs[0].message), &m)) + require.NoError(t, json.Unmarshal([]byte(snsMsgs[0].message), &m, jsonx.V1())) assert.Equal(t, "1", m["DeploymentNumber"]) assert.Equal(t, "1", m["ConfigurationVersion"]) assert.Equal(t, "my deploy", m["Description"]) @@ -282,7 +283,7 @@ func TestExtensionActions_OnDeploymentTargets(t *testing.T) { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(sqsMsgs[1]), &m)) + require.NoError(t, json.Unmarshal([]byte(sqsMsgs[1]), &m, jsonx.V1())) assert.Equal(t, "OnDeploymentComplete", m["Type"]) assert.Equal(t, "1", m["DeploymentNumber"]) }}, @@ -297,7 +298,7 @@ func TestExtensionActions_OnDeploymentTargets(t *testing.T) { assert.Contains(t, busMsgs[0].resources[0], ":extensionassociation/") var m map[string]any - require.NoError(t, json.Unmarshal([]byte(busMsgs[0].detail), &m)) + require.NoError(t, json.Unmarshal([]byte(busMsgs[0].detail), &m, jsonx.V1())) assert.InDelta(t, 1, m["DeploymentNumber"], 0) }}, } diff --git a/services/appconfig/extension_sibling_test.go b/services/appconfig/extension_sibling_test.go index b4e068bd7d..92a8de639b 100644 --- a/services/appconfig/extension_sibling_test.go +++ b/services/appconfig/extension_sibling_test.go @@ -1,12 +1,13 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" sqsbackend "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -61,7 +62,7 @@ func TestExtensionActions_SiblingSQSDelivery(t *testing.T) { } var m map[string]any - require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &m)) + require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &m, jsonx.V1())) return m["Type"] == "OnDeploymentComplete" }, eventuallyWait, eventuallyTick) diff --git a/services/appconfig/feature_flags.go b/services/appconfig/feature_flags.go index 49bd0dbcdf..9b78e86cd3 100644 --- a/services/appconfig/feature_flags.go +++ b/services/appconfig/feature_flags.go @@ -1,6 +1,12 @@ package appconfig -import "encoding/json" +import ( + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // featureFlagDocument mirrors the parts of the real AWS.AppConfig.FeatureFlags // JSON schema this backend needs in order to validate CreateExperimentDefinition's @@ -19,7 +25,7 @@ import "encoding/json" // feature flags), so it is documented and field-diffed against AWS's public // user-guide schema page directly rather than SDK-generated code. type featureFlagDocument struct { - Flags map[string]json.RawMessage `json:"flags"` + Flags map[string]jsontext.Value `json:"flags"` } // parseFeatureFlagKeys attempts to parse content as a real @@ -39,7 +45,7 @@ func parseFeatureFlagKeys(content []byte) (map[string]struct{}, bool) { } var doc featureFlagDocument - if err := json.Unmarshal(content, &doc); err != nil || doc.Flags == nil { + if err := json.Unmarshal(content, &doc, jsonx.V1()); err != nil || doc.Flags == nil { return nil, false } diff --git a/services/appconfig/handler_account_settings_test.go b/services/appconfig/handler_account_settings_test.go index 532d856f18..efeb4fc6a6 100644 --- a/services/appconfig/handler_account_settings_test.go +++ b/services/appconfig/handler_account_settings_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -47,7 +48,7 @@ func TestHandler_GetAccountSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var settings appconfig.AccountSettings - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings, jsonx.V1())) } // TestHandler_UpdateAccountSettings_DeletionProtectionFieldsSurviveIndependentUpdates @@ -73,7 +74,7 @@ func TestHandler_UpdateAccountSettings_DeletionProtectionFieldsSurviveIndependen require.Equal(t, http.StatusOK, rec.Code) var settings appconfig.AccountSettings - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings, jsonx.V1())) require.NotNil(t, settings.DeletionProtection) require.NotNil(t, settings.DeletionProtection.Enabled) assert.False(t, *settings.DeletionProtection.Enabled, "B's own field must apply") @@ -84,7 +85,7 @@ func TestHandler_UpdateAccountSettings_DeletionProtectionFieldsSurviveIndependen // GetAccountSettings must reflect the same merged state. rec = doRequest(t, h, http.MethodGet, "/settings", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings, jsonx.V1())) require.NotNil(t, settings.DeletionProtection.ProtectionPeriodInMinutes) assert.EqualValues(t, 120, *settings.DeletionProtection.ProtectionPeriodInMinutes) } @@ -100,7 +101,7 @@ func TestHandler_UpdateAccountSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var settings appconfig.AccountSettings - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings, jsonx.V1())) require.NotNil(t, settings.DeletionProtection) require.NotNil(t, settings.DeletionProtection.Enabled) assert.True(t, *settings.DeletionProtection.Enabled) @@ -109,7 +110,7 @@ func TestHandler_UpdateAccountSettings(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/settings", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settings, jsonx.V1())) require.NotNil(t, settings.DeletionProtection) assert.True(t, *settings.DeletionProtection.Enabled) } diff --git a/services/appconfig/handler_applications_test.go b/services/appconfig/handler_applications_test.go index 9f0ce0c5df..c4db0720e1 100644 --- a/services/appconfig/handler_applications_test.go +++ b/services/appconfig/handler_applications_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -51,7 +52,7 @@ func TestHandler_Application_CRUD(t *testing.T) { if tt.wantName != "" { var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) assert.Equal(t, tt.wantName, app.Name) } }) @@ -76,7 +77,7 @@ func TestHandler_DeleteApplication(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Delete it. rec = doRequest(t, h, http.MethodDelete, "/applications/"+app.ID, nil) @@ -96,7 +97,7 @@ func TestHandler_UpdateApplication(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest( t, @@ -108,7 +109,7 @@ func TestHandler_UpdateApplication(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "updated", updated.Name) assert.Equal(t, "new desc", updated.Description) } @@ -128,7 +129,7 @@ func TestHandler_UpdateApplication_OmittedDescriptionPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Update only Name; Description is omitted from the request body. rec = doRequest(t, h, http.MethodPatch, "/applications/"+app.ID, @@ -136,7 +137,7 @@ func TestHandler_UpdateApplication_OmittedDescriptionPreserved(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "renamed", updated.Name) assert.Equal(t, "keep-me", updated.Description, "omitted Description must not clobber the existing value") @@ -182,7 +183,7 @@ func TestHandler_ListApplicationsPagination(t *testing.T) { NextToken string `json:"NextToken"` Items []any `json:"Items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, 4) assert.Empty(t, resp.NextToken) }) @@ -200,7 +201,7 @@ func TestHandler_ListApplicationsPagination(t *testing.T) { NextToken string `json:"NextToken"` Items []any `json:"Items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, 2) assert.NotEmpty(t, resp.NextToken) }) @@ -219,7 +220,7 @@ func TestHandler_ListApplicationsPagination(t *testing.T) { NextToken string `json:"NextToken"` Items []any `json:"Items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first, jsonx.V1())) require.NotEmpty(t, first.NextToken) rec2 := doRequest( @@ -234,7 +235,7 @@ func TestHandler_ListApplicationsPagination(t *testing.T) { NextToken string `json:"NextToken"` Items []any `json:"Items"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Items, 2) assert.Empty(t, resp.NextToken) }) @@ -260,7 +261,7 @@ func TestHandler_ListApplicationsPagination(t *testing.T) { NextToken string `json:"NextToken"` Items []any `json:"Items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.Items) assert.Empty(t, resp.NextToken) }) @@ -297,14 +298,14 @@ func TestHandler_CreateApplication_TagsAppliedInline(t *testing.T) { body, err := json.Marshal(map[string]any{ "Name": "tagged-app-" + tt.name, "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/applications", body) require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID tagsRec := doRequest(t, h, http.MethodGet, "/tags/"+resourceArn, nil) @@ -313,7 +314,7 @@ func TestHandler_CreateApplication_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) diff --git a/services/appconfig/handler_configuration_profiles_test.go b/services/appconfig/handler_configuration_profiles_test.go index acd049a8b5..0b580a8601 100644 --- a/services/appconfig/handler_configuration_profiles_test.go +++ b/services/appconfig/handler_configuration_profiles_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -23,7 +24,7 @@ func TestHandler_ConfigurationProfile_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Create profile. profileBody := []byte(`{"name":"my-config","locationUri":"hosted","type":"AWS.Freeform"}`) @@ -37,7 +38,7 @@ func TestHandler_ConfigurationProfile_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) assert.Equal(t, "my-config", profile.Name) // Get profile. @@ -70,7 +71,7 @@ func TestHandler_ListConfigurationProfiles_HTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Create two profiles. for _, name := range []string{"prof-1", "prof-2"} { @@ -99,7 +100,7 @@ func TestHandler_UpdateConfigurationProfile_HTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) profileBody := []byte(`{"name":"old-name","locationUri":"hosted","type":"AWS.Freeform"}`) rec = doRequest( @@ -112,7 +113,7 @@ func TestHandler_UpdateConfigurationProfile_HTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) // Update. rec = doRequest( @@ -125,7 +126,7 @@ func TestHandler_UpdateConfigurationProfile_HTTP(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "new-name", updated.Name) } @@ -143,7 +144,7 @@ func TestHandler_UpdateConfigurationProfile_RetrievalRoleArnAndValidators(t *tes require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) profileBody := []byte( `{"Name":"old-name","Description":"keep-me","LocationUri":"hosted","Type":"AWS.Freeform"}`, @@ -152,7 +153,7 @@ func TestHandler_UpdateConfigurationProfile_RetrievalRoleArnAndValidators(t *tes require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) rec = doRequest(t, h, http.MethodPatch, "/applications/"+app.ID+"/configurationprofiles/"+profile.ID, @@ -161,7 +162,7 @@ func TestHandler_UpdateConfigurationProfile_RetrievalRoleArnAndValidators(t *tes assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "arn:aws:iam::123456789012:role/retrieval", updated.RetrievalRoleArn, "RetrievalRoleArn must be applied, not silently dropped") require.Len(t, updated.Validators, 1, "Validators must be applied, not silently dropped") @@ -245,21 +246,21 @@ func TestHandler_CreateConfigurationProfile_TagsAppliedInline(t *testing.T) { require.Equal(t, http.StatusCreated, appRec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) body, err := json.Marshal(map[string]any{ "Name": "tagged-prof-" + tt.name, "LocationUri": "hosted", "Type": "AWS.Freeform", "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", body) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID + "/configurationprofile/" + profile.ID @@ -269,7 +270,7 @@ func TestHandler_CreateConfigurationProfile_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) @@ -334,7 +335,7 @@ func seedExperimentDefinitionHTTP(t *testing.T, h *appconfig.Handler) (string, s var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"exp-http-env"}`)) @@ -343,7 +344,7 @@ func seedExperimentDefinitionHTTP(t *testing.T, h *appconfig.Handler) (string, s var env struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"exp-http-profile","LocationUri":"hosted","Type":"AWS.AppConfig.FeatureFlags"}`)) @@ -352,7 +353,7 @@ func seedExperimentDefinitionHTTP(t *testing.T, h *appconfig.Handler) (string, s var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) return app.ID, env.ID, prof.ID } @@ -382,7 +383,7 @@ func TestHandler_ExperimentDefinition_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created appconfig.ExperimentDefinition - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) assert.NotEmpty(t, created.ID) assert.Equal(t, appID, created.ApplicationID) assert.Equal(t, envID, created.EnvironmentID) @@ -396,7 +397,7 @@ func TestHandler_ExperimentDefinition_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got appconfig.ExperimentDefinition - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, created.ID, got.ID) listRec := doRequest(t, h, http.MethodGet, "/experimentdefinitions?application_identifier="+appID, nil) @@ -405,7 +406,7 @@ func TestHandler_ExperimentDefinition_CRUD(t *testing.T) { var listResp struct { Items []appconfig.ExperimentDefinition `json:"Items"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Items, 1) assert.Equal(t, created.ID, listResp.Items[0].ID) @@ -414,7 +415,7 @@ func TestHandler_ExperimentDefinition_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updated appconfig.ExperimentDefinition - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "country == 'US'", updated.AudienceRule) deleteRec := doRequest(t, h, http.MethodDelete, "/applications/"+appID+"/experimentdefinitions/"+created.ID, nil) @@ -424,7 +425,7 @@ func TestHandler_ExperimentDefinition_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, afterDeleteRec.Code, "default delete_type archives rather than destroying") var afterDelete appconfig.ExperimentDefinition - require.NoError(t, json.Unmarshal(afterDeleteRec.Body.Bytes(), &afterDelete)) + require.NoError(t, json.Unmarshal(afterDeleteRec.Body.Bytes(), &afterDelete, jsonx.V1())) assert.Equal(t, "ARCHIVED", afterDelete.Status) // FlagKey is validated against the profile's actual feature flag @@ -551,14 +552,14 @@ func TestHandler_DeleteConfigurationProfile_DeletionProtectionCheck(t *testing.T require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"name":"dpc-profile","locationUri":"hosted","type":"AWS.Freeform"}`)) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) path := "/applications/" + app.ID + "/configurationprofiles/" + profile.ID diff --git a/services/appconfig/handler_configuration_test.go b/services/appconfig/handler_configuration_test.go index 9bc3377ceb..7eb2ade566 100644 --- a/services/appconfig/handler_configuration_test.go +++ b/services/appconfig/handler_configuration_test.go @@ -2,7 +2,7 @@ package appconfig_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -26,7 +27,7 @@ func TestHandler_GetConfiguration(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest( t, @@ -38,14 +39,14 @@ func TestHandler_GetConfiguration(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"conf-profile","LocationUri":"hosted","Type":"AWS.Freeform"}`)) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) tests := []struct { name string @@ -94,7 +95,7 @@ func TestHandler_GetConfiguration_WithContent(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest( t, @@ -106,14 +107,14 @@ func TestHandler_GetConfiguration_WithContent(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"content-profile","LocationUri":"hosted","Type":"AWS.Freeform"}`)) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) // Create a hosted configuration version. e := echo.New() @@ -143,7 +144,7 @@ func TestHandler_GetConfiguration_WithContent(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var strat appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat, jsonx.V1())) depBody := []byte( `{"ConfigurationProfileId":"` + profile.ID + @@ -171,14 +172,14 @@ func TestHandler_ValidateConfiguration(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"validate-profile","LocationUri":"hosted","Type":"AWS.Freeform"}`)) require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) validatorBase := "/applications/" + app.ID + "/configurationprofiles/" + profile.ID + "/validators" diff --git a/services/appconfig/handler_deployment_strategies_test.go b/services/appconfig/handler_deployment_strategies_test.go index b35c1d47b1..42c505b07f 100644 --- a/services/appconfig/handler_deployment_strategies_test.go +++ b/services/appconfig/handler_deployment_strategies_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -24,7 +25,7 @@ func TestHandler_DeploymentStrategy_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var strategy appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strategy)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strategy, jsonx.V1())) assert.Equal(t, "my-strategy", strategy.Name) // Get. @@ -88,14 +89,14 @@ func TestHandler_UpdateDeploymentStrategy_OmittedDescriptionPreserved(t *testing require.Equal(t, http.StatusCreated, rec.Code) var strat appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat, jsonx.V1())) rec = doRequest(t, h, http.MethodPatch, "/deploymentstrategies/"+strat.ID, []byte(`{"GrowthFactor":50}`)) assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.InDelta(t, float32(50), updated.GrowthFactor, 0.001) assert.Equal(t, "keep-me", updated.Description, "omitted Description must be preserved") } @@ -137,14 +138,14 @@ func TestHandler_CreateDeploymentStrategy_TagsAppliedInline(t *testing.T) { "GrowthType": "LINEAR", "ReplicateTo": "NONE", "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/deploymentstrategies", body) require.Equal(t, http.StatusCreated, rec.Code) var strategy appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strategy)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strategy, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:deploymentstrategy/" + strategy.ID tagsRec := doRequest(t, h, http.MethodGet, "/tags/"+resourceArn, nil) @@ -153,7 +154,7 @@ func TestHandler_CreateDeploymentStrategy_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) diff --git a/services/appconfig/handler_deployments_test.go b/services/appconfig/handler_deployments_test.go index 8933058c53..0457f67a0c 100644 --- a/services/appconfig/handler_deployments_test.go +++ b/services/appconfig/handler_deployments_test.go @@ -2,7 +2,7 @@ package appconfig_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -138,7 +139,7 @@ func seedExperimentRunHTTP(t *testing.T, h *appconfig.Handler) (string, appconfi var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"run-http-env"}`)) @@ -147,7 +148,7 @@ func seedExperimentRunHTTP(t *testing.T, h *appconfig.Handler) (string, appconfi var env struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"run-http-profile","LocationUri":"hosted","Type":"AWS.AppConfig.FeatureFlags"}`)) @@ -156,7 +157,7 @@ func seedExperimentRunHTTP(t *testing.T, h *appconfig.Handler) (string, appconfi var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) defBody := `{ "Name": "run-http-def", @@ -171,7 +172,7 @@ func seedExperimentRunHTTP(t *testing.T, h *appconfig.Handler) (string, appconfi require.Equal(t, http.StatusCreated, defRec.Code) var def appconfig.ExperimentDefinition - require.NoError(t, json.Unmarshal(defRec.Body.Bytes(), &def)) + require.NoError(t, json.Unmarshal(defRec.Body.Bytes(), &def, jsonx.V1())) return app.ID, def } @@ -194,7 +195,7 @@ func TestHandler_ExperimentRun_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var run appconfig.ExperimentRun - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &run, jsonx.V1())) assert.Equal(t, int32(1), run.Run) assert.Equal(t, "RUNNING", run.Status) assert.InDelta(t, float32(10), run.ExposurePercentage, 0.001) @@ -208,14 +209,14 @@ func TestHandler_ExperimentRun_Lifecycle(t *testing.T) { var listResp struct { Items []appconfig.ExperimentRun `json:"Items"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Items, 1) updateRec := doRequest(t, h, http.MethodPatch, base+"/1/update", []byte(`{"ExposurePercentage":25}`)) require.Equal(t, http.StatusOK, updateRec.Code) var updated appconfig.ExperimentRun - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated, jsonx.V1())) assert.InDelta(t, float32(25), updated.ExposurePercentage, 0.001) stopRec := doRequest(t, h, http.MethodPatch, base+"/1/stop", @@ -223,7 +224,7 @@ func TestHandler_ExperimentRun_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopped appconfig.ExperimentRun - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopped)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopped, jsonx.V1())) assert.Equal(t, "DONE", stopped.Status) require.NotNil(t, stopped.Result) assert.Equal(t, "treatment won", stopped.Result.ExecutiveSummary) @@ -234,7 +235,7 @@ func TestHandler_ExperimentRun_Lifecycle(t *testing.T) { var eventsResp struct { Items []appconfig.ExperimentRunEvent `json:"Items"` } - require.NoError(t, json.Unmarshal(eventsRec.Body.Bytes(), &eventsResp)) + require.NoError(t, json.Unmarshal(eventsRec.Body.Bytes(), &eventsResp, jsonx.V1())) require.Len(t, eventsResp.Items, 3, "RUN_STARTED, EXPOSURE_UPDATED, RUN_STOPPED") assert.Equal(t, "RUN_STOPPED", eventsResp.Items[0].EventType, "most-recent-first ordering") } @@ -295,7 +296,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Create env. rec = doRequest( @@ -308,7 +309,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) // Create configuration profile (required by StartDeployment validation). profBody := []byte(`{"name":"my-profile","locationUri":"hosted"}`) @@ -322,7 +323,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var prof appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &prof, jsonx.V1())) // Create a hosted configuration version (required for StartDeployment // to validate ConfigurationVersion against, for a "hosted" profile). @@ -343,7 +344,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var strat appconfig.DeploymentStrategy - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &strat, jsonx.V1())) // Start deployment. depBodyStr := `{"configurationProfileId":"` + prof.ID + @@ -358,7 +359,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var dep appconfig.Deployment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, int32(1), dep.DeploymentNumber) assert.Equal(t, "DEPLOYING", dep.State, "a non-zero-duration strategy must not complete synchronously") assert.NotEmpty(t, dep.EventLog, "StartDeployment must record a DEPLOYMENT_STARTED event") @@ -377,7 +378,7 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var final appconfig.Deployment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &final)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &final, jsonx.V1())) assert.Equal(t, "COMPLETE", final.State) assert.InDelta(t, float32(100.0), final.PercentageComplete, 0.001) @@ -412,13 +413,13 @@ func TestHandler_Deployment_Lifecycle(t *testing.T) { "Allow-Revert", "true", nil, ) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, "REVERTED", dep.State, "StopDeploymentOutput itself must reflect the new state") rec = doRequest(t, h, http.MethodGet, "/applications/"+app.ID+"/environments/"+env.ID+"/deployments/1", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, "REVERTED", dep.State) }) } @@ -493,7 +494,7 @@ func TestHandler_ListDeployments_HTTP(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appOut)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appOut, jsonx.V1())) envRec := doRequest( t, h, http.MethodPost, @@ -506,7 +507,7 @@ func TestHandler_ListDeployments_HTTP(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &envOut)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &envOut, jsonx.V1())) listRec := doRequest( t, h, http.MethodGet, @@ -531,7 +532,7 @@ func TestHandler_DeploymentFieldsPresent(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"dep-env"}`)) @@ -541,7 +542,7 @@ func TestHandler_DeploymentFieldsPresent(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", @@ -552,7 +553,7 @@ func TestHandler_DeploymentFieldsPresent(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) hcvRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles/"+prof.ID+"/hostedconfigurationversions", @@ -567,13 +568,13 @@ func TestHandler_DeploymentFieldsPresent(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat, jsonx.V1())) depBody, _ := json.Marshal(map[string]string{ "ConfigurationProfileId": prof.ID, "DeploymentStrategyId": strat.ID, "ConfigurationVersion": "1", - }) + }, jsonx.V1()) depRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments/"+env.ID+"/deployments", depBody) require.Equal(t, http.StatusCreated, depRec.Code) @@ -587,7 +588,7 @@ func TestHandler_DeploymentFieldsPresent(t *testing.T) { PercentageComplete float32 `json:"PercentageComplete"` DeploymentNumber int32 `json:"DeploymentNumber"` } - require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, app.ID, dep.ApplicationID) assert.Equal(t, env.ID, dep.EnvironmentID) @@ -612,7 +613,7 @@ func TestHandler_DeploymentNumberIncrements(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"seq-env"}`)) @@ -622,7 +623,7 @@ func TestHandler_DeploymentNumberIncrements(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", @@ -633,7 +634,7 @@ func TestHandler_DeploymentNumberIncrements(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) hcvRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles/"+prof.ID+"/hostedconfigurationversions", @@ -648,13 +649,13 @@ func TestHandler_DeploymentNumberIncrements(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat, jsonx.V1())) depBody, _ := json.Marshal(map[string]string{ "ConfigurationProfileId": prof.ID, "DeploymentStrategyId": strat.ID, "ConfigurationVersion": "1", - }) + }, jsonx.V1()) for wantNum := int32(1); wantNum <= 3; wantNum++ { rec := doRequest(t, h, http.MethodPost, @@ -664,7 +665,7 @@ func TestHandler_DeploymentNumberIncrements(t *testing.T) { var dep struct { DeploymentNumber int32 `json:"DeploymentNumber"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dep, jsonx.V1())) assert.Equal(t, wantNum, dep.DeploymentNumber, "deployment must have sequential DeploymentNumber") } diff --git a/services/appconfig/handler_environments_test.go b/services/appconfig/handler_environments_test.go index dfbde232ac..65ec83ed68 100644 --- a/services/appconfig/handler_environments_test.go +++ b/services/appconfig/handler_environments_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -22,7 +23,7 @@ func TestHandler_Environment_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // Create env. rec = doRequest( @@ -35,7 +36,7 @@ func TestHandler_Environment_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) assert.Equal(t, "production", env.Name) assert.Equal(t, app.ID, env.ApplicationID) @@ -62,7 +63,7 @@ func TestHandler_UpdateEnvironment_HTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest( t, @@ -74,7 +75,7 @@ func TestHandler_UpdateEnvironment_HTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) // Update env. rec = doRequest( @@ -87,7 +88,7 @@ func TestHandler_UpdateEnvironment_HTTP(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "production", updated.Name) } @@ -104,14 +105,14 @@ func TestHandler_UpdateEnvironment_OmittedFieldsPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"staging","Description":"keep-me","Monitors":[{"AlarmArn":"arn:aws:cloudwatch:alarm1"}]}`)) require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) require.Len(t, env.Monitors, 1) // Update only Name; Description and Monitors are omitted. @@ -120,7 +121,7 @@ func TestHandler_UpdateEnvironment_OmittedFieldsPreserved(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "production", updated.Name) assert.Equal(t, "keep-me", updated.Description, "omitted Description must be preserved") require.Len(t, updated.Monitors, 1, "omitted Monitors must be preserved") @@ -132,7 +133,7 @@ func TestHandler_UpdateEnvironment_OmittedFieldsPreserved(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var cleared appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cleared)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cleared, jsonx.V1())) assert.Empty(t, cleared.Monitors, "an explicit empty Monitors list must replace the existing one") } @@ -209,19 +210,19 @@ func TestHandler_CreateEnvironment_TagsAppliedInline(t *testing.T) { require.Equal(t, http.StatusCreated, appRec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) body, err := json.Marshal(map[string]any{ "Name": "tagged-env-" + tt.name, "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", body) require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID + "/environment/" + env.ID @@ -231,7 +232,7 @@ func TestHandler_CreateEnvironment_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) @@ -255,7 +256,7 @@ func TestHandler_EnvironmentStateIsReadyForDeployment(t *testing.T) { var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) tests := []struct { name string @@ -285,7 +286,7 @@ func TestHandler_EnvironmentStateIsReadyForDeployment(t *testing.T) { var env struct { State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) assert.Equal(t, tt.want, env.State, "environment State must be READY_FOR_DEPLOYMENT (SCREAMING_SNAKE_CASE)") }) @@ -305,7 +306,7 @@ func TestHandler_EnvironmentStateRoundTrip(t *testing.T) { var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"staging"}`)) @@ -315,7 +316,7 @@ func TestHandler_EnvironmentStateRoundTrip(t *testing.T) { ID string `json:"Id"` State string `json:"State"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) assert.Equal(t, "READY_FOR_DEPLOYMENT", env.State) require.NotEmpty(t, env.ID) @@ -327,7 +328,7 @@ func TestHandler_EnvironmentStateRoundTrip(t *testing.T) { var getEnv struct { State string `json:"State"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getEnv)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getEnv, jsonx.V1())) assert.Equal(t, "READY_FOR_DEPLOYMENT", getEnv.State, "GetEnvironment must also return READY_FOR_DEPLOYMENT") // ListEnvironments must also return correct state. @@ -339,7 +340,7 @@ func TestHandler_EnvironmentStateRoundTrip(t *testing.T) { State string `json:"State"` } `json:"Items"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Items, 1) assert.Equal(t, "READY_FOR_DEPLOYMENT", listResp.Items[0].State, "ListEnvironments must also return READY_FOR_DEPLOYMENT") @@ -381,14 +382,14 @@ func TestHandler_DeleteEnvironment_DeletionProtectionCheck(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"name":"dpc-env"}`)) require.Equal(t, http.StatusCreated, rec.Code) var env appconfig.Environment - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &env, jsonx.V1())) path := "/applications/" + app.ID + "/environments/" + env.ID diff --git a/services/appconfig/handler_extensions_test.go b/services/appconfig/handler_extensions_test.go index 99c10de476..40e9e7ecf5 100644 --- a/services/appconfig/handler_extensions_test.go +++ b/services/appconfig/handler_extensions_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -86,7 +87,7 @@ func TestHandler_Extension_CRUD(t *testing.T) { if tt.wantField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantValue, resp[tt.wantField]) } }) @@ -103,7 +104,7 @@ func TestHandler_Extension_GetDeleteByID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) assert.NotEmpty(t, ext.ID) assert.Equal(t, "ext-to-delete", ext.Name) @@ -163,7 +164,7 @@ func TestHandler_Extension_ListPaginated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Items"].([]any) require.True(t, ok) assert.Len(t, items, 2) @@ -180,14 +181,14 @@ func TestHandler_ExtensionAssociation_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) // Create an application to use as resource. rec = doRequest(t, h, http.MethodPost, "/applications", []byte(`{"name":"assoc-app"}`)) require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) // List associations empty. rec = doRequest(t, h, http.MethodGet, "/extensionassociations", nil) @@ -202,7 +203,7 @@ func TestHandler_ExtensionAssociation_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var assoc appconfig.ExtensionAssociation - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc, jsonx.V1())) assert.NotEmpty(t, assoc.ID) assert.Equal(t, ext.Arn, assoc.ExtensionArn) @@ -215,7 +216,7 @@ func TestHandler_ExtensionAssociation_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items, ok := listResp["Items"].([]any) require.True(t, ok) assert.Len(t, items, 1) @@ -285,7 +286,7 @@ func TestHandler_UpdateExtension(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) assert.Equal(t, int32(1), ext.VersionNumber) // Update extension. @@ -294,7 +295,7 @@ func TestHandler_UpdateExtension(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "updated", updated.Description) assert.Equal(t, int32(2), updated.VersionNumber) } @@ -313,7 +314,7 @@ func TestHandler_UpdateExtension_OmittedDescriptionPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) // Update Actions only; Description is omitted. rec = doRequest(t, h, http.MethodPatch, "/extensions/"+ext.ID, @@ -321,7 +322,7 @@ func TestHandler_UpdateExtension_OmittedDescriptionPreserved(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "keep-me", updated.Description, "omitted Description must not be cleared") } @@ -344,7 +345,7 @@ func TestHandler_UpdateExtensionAssociation(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) resourceID := "arn:aws:appconfig:us-east-1:123456789012:application/abc" assocBody := []byte( @@ -354,7 +355,7 @@ func TestHandler_UpdateExtensionAssociation(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var assoc appconfig.ExtensionAssociation - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc, jsonx.V1())) // Update the association parameters. rec = doRequest(t, h, http.MethodPatch, "/extensionassociations/"+assoc.ID, @@ -362,7 +363,7 @@ func TestHandler_UpdateExtensionAssociation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated appconfig.ExtensionAssociation - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "value", updated.Parameters["key"]) } @@ -474,7 +475,7 @@ func TestHandler_Extension_VersionQueryParams(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var v1 appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &v1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &v1, jsonx.V1())) rec = doRequest(t, h, http.MethodPatch, "/extensions/"+v1.ID, []byte(`{"Description":"v2"}`)) @@ -485,7 +486,7 @@ func TestHandler_Extension_VersionQueryParams(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gotV1 appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gotV1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gotV1, jsonx.V1())) assert.Equal(t, "v1", gotV1.Description) assert.Equal(t, int32(1), gotV1.VersionNumber) @@ -494,7 +495,7 @@ func TestHandler_Extension_VersionQueryParams(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gotLatest appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gotLatest)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gotLatest, jsonx.V1())) assert.Equal(t, int32(2), gotLatest.VersionNumber) // Delete version 1 explicitly via the "version" query param; version 2 @@ -525,7 +526,7 @@ func TestHandler_DeleteExtension_ConflictWhenAssociated(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) assocBody := []byte( `{"ExtensionIdentifier":"` + ext.ID + @@ -555,7 +556,7 @@ func TestHandler_ListExtensions_NameFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Items"].([]any) require.True(t, ok) assert.Len(t, items, 1) @@ -564,7 +565,7 @@ func TestHandler_ListExtensions_NameFilter(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/extensions?name=nonexistent", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok = resp["Items"].([]any) require.True(t, ok) assert.Empty(t, items) @@ -601,14 +602,14 @@ func TestHandler_CreateExtension_TagsAppliedInline(t *testing.T) { body, err := json.Marshal(map[string]any{ "Name": "tagged-ext-" + tt.name, "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/extensions", body) require.Equal(t, http.StatusCreated, rec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ext, jsonx.V1())) require.NotEmpty(t, ext.Arn) tagsRec := doRequest(t, h, http.MethodGet, "/tags/"+ext.Arn, nil) @@ -617,7 +618,7 @@ func TestHandler_CreateExtension_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) @@ -662,21 +663,21 @@ func TestHandler_CreateExtensionAssociation_TagsAppliedInline(t *testing.T) { require.Equal(t, http.StatusCreated, extRec.Code) var ext appconfig.Extension - require.NoError(t, json.Unmarshal(extRec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(extRec.Body.Bytes(), &ext, jsonx.V1())) resourceID := "arn:aws:appconfig:us-east-1:123456789012:application/tagged-assoc-" + tt.name body, err := json.Marshal(map[string]any{ "ExtensionIdentifier": ext.ID, "ResourceIdentifier": resourceID, "Tags": tt.tags, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/extensionassociations", body) require.Equal(t, http.StatusCreated, rec.Code) var assoc appconfig.ExtensionAssociation - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assoc, jsonx.V1())) require.NotEmpty(t, assoc.Arn) tagsRec := doRequest(t, h, http.MethodGet, "/tags/"+assoc.Arn, nil) @@ -685,7 +686,7 @@ func TestHandler_CreateExtensionAssociation_TagsAppliedInline(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) if len(tt.tags) == 0 { assert.Empty(t, tagsResp.Tags) diff --git a/services/appconfig/handler_hosted_configuration_versions_test.go b/services/appconfig/handler_hosted_configuration_versions_test.go index b5387357e0..caead87390 100644 --- a/services/appconfig/handler_hosted_configuration_versions_test.go +++ b/services/appconfig/handler_hosted_configuration_versions_test.go @@ -2,7 +2,7 @@ package appconfig_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -27,7 +28,7 @@ func TestHandler_HostedConfigurationVersion_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) profileBody := []byte(`{"name":"hcv-profile","locationUri":"hosted","type":"AWS.Freeform"}`) rec = doRequest( @@ -40,7 +41,7 @@ func TestHandler_HostedConfigurationVersion_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var profile appconfig.ConfigurationProfile - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) // Create hosted configuration version with raw body. e := echo.New() @@ -146,7 +147,7 @@ func TestHandler_HostedConfigVersion_HTTP_ListEmpty(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appOut)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appOut, jsonx.V1())) profRec := doRequest( t, h, http.MethodPost, @@ -159,7 +160,7 @@ func TestHandler_HostedConfigVersion_HTTP_ListEmpty(t *testing.T) { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &profOut)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &profOut, jsonx.V1())) listRec := doRequest( t, @@ -193,7 +194,7 @@ func TestHandler_HostedConfigVersionResponseHeaders(t *testing.T) { var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", @@ -203,7 +204,7 @@ func TestHandler_HostedConfigVersionResponseHeaders(t *testing.T) { var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) base := "/applications/" + app.ID + "/configurationprofiles/" + prof.ID + "/hostedconfigurationversions" @@ -254,7 +255,7 @@ func TestHandler_CreateHostedConfigurationVersion_LatestVersionNumberConflict(t var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", @@ -264,7 +265,7 @@ func TestHandler_CreateHostedConfigurationVersion_LatestVersionNumberConflict(t var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) base := "/applications/" + app.ID + "/configurationprofiles/" + prof.ID + "/hostedconfigurationversions" diff --git a/services/appconfig/handler_list_summary_test.go b/services/appconfig/handler_list_summary_test.go index cc39e49353..bef7ac6677 100644 --- a/services/appconfig/handler_list_summary_test.go +++ b/services/appconfig/handler_list_summary_test.go @@ -1,7 +1,7 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -154,7 +155,7 @@ func listSingleItem(t *testing.T, h *appconfig.Handler, path string) map[string] require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Items"].([]any) require.True(t, ok, "response missing Items list, got keys: %v", mapKeys(resp)) @@ -175,7 +176,7 @@ func setupConfigurationProfileListLeak(t *testing.T, h *appconfig.Handler) map[s var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) profBody := []byte(`{ "Name": "cp-list-leak-profile", @@ -200,7 +201,7 @@ func setupDeploymentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"dep-list-leak-env"}`)) @@ -209,7 +210,7 @@ func setupDeploymentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var env struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"dep-list-leak-profile","LocationUri":"hosted"}`)) @@ -218,7 +219,7 @@ func setupDeploymentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) hcvRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles/"+prof.ID+"/hostedconfigurationversions", @@ -234,7 +235,7 @@ func setupDeploymentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var strat struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat, jsonx.V1())) depBody := []byte(`{ "ConfigurationProfileId": "` + prof.ID + `", @@ -249,7 +250,7 @@ func setupDeploymentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var dep struct { State string `json:"State"` } - require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &dep)) + require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &dep, jsonx.V1())) require.Equal(t, "COMPLETE", dep.State, "a zero-duration strategy must complete synchronously") return listSingleItem(t, h, "/applications/"+app.ID+"/environments/"+env.ID+"/deployments") @@ -315,7 +316,7 @@ func setupExtensionAssociationListLeak(t *testing.T, h *appconfig.Handler) map[s var ext struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(extRec.Body.Bytes(), &ext)) + require.NoError(t, json.Unmarshal(extRec.Body.Bytes(), &ext, jsonx.V1())) appRec := doRequest(t, h, http.MethodPost, "/applications", []byte(`{"Name":"ext-assoc-list-leak-app"}`)) require.Equal(t, http.StatusCreated, appRec.Code) @@ -323,7 +324,7 @@ func setupExtensionAssociationListLeak(t *testing.T, h *appconfig.Handler) map[s var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) resourceID := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID assocBody := []byte(`{ @@ -346,7 +347,7 @@ func setupHostedConfigurationVersionListLeak(t *testing.T, h *appconfig.Handler) var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) profRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles", []byte(`{"Name":"hcv-list-leak-profile","LocationUri":"hosted"}`)) @@ -355,7 +356,7 @@ func setupHostedConfigurationVersionListLeak(t *testing.T, h *appconfig.Handler) var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) hcvRec := doRequestWithHeader(t, h, http.MethodPost, "/applications/"+app.ID+"/configurationprofiles/"+prof.ID+"/hostedconfigurationversions", @@ -386,7 +387,7 @@ func setupEnvironmentListLeak(t *testing.T, h *appconfig.Handler) map[string]any var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"env-list-leak-env"}`)) @@ -422,7 +423,7 @@ func TestHandler_GetOps_NoCreatedAtUpdatedAt(t *testing.T) { require.Equal(t, http.StatusCreated, appRec.Code) var createdApp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &createdApp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &createdApp, jsonx.V1())) assert.NotContains(t, createdApp, "CreatedAt") assert.NotContains(t, createdApp, "UpdatedAt") @@ -433,7 +434,7 @@ func TestHandler_GetOps_NoCreatedAtUpdatedAt(t *testing.T) { require.Equal(t, http.StatusOK, getAppRec.Code) var gotApp map[string]any - require.NoError(t, json.Unmarshal(getAppRec.Body.Bytes(), &gotApp)) + require.NoError(t, json.Unmarshal(getAppRec.Body.Bytes(), &gotApp, jsonx.V1())) assert.NotContains(t, gotApp, "CreatedAt") assert.NotContains(t, gotApp, "UpdatedAt") @@ -443,7 +444,7 @@ func TestHandler_GetOps_NoCreatedAtUpdatedAt(t *testing.T) { require.Equal(t, http.StatusCreated, stratRec.Code) var createdStrat map[string]any - require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &createdStrat)) + require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &createdStrat, jsonx.V1())) assert.NotContains(t, createdStrat, "CreatedAt") assert.NotContains(t, createdStrat, "UpdatedAt") } diff --git a/services/appconfig/handler_tags_test.go b/services/appconfig/handler_tags_test.go index 885aca1866..b611e42e1e 100644 --- a/services/appconfig/handler_tags_test.go +++ b/services/appconfig/handler_tags_test.go @@ -1,13 +1,14 @@ package appconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -21,7 +22,7 @@ func TestHandler_TagResource(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &app, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID @@ -52,7 +53,7 @@ func TestHandler_TagResource_VerifyTags(t *testing.T) { require.Equal(t, http.StatusCreated, created.Code) var app appconfig.Application - require.NoError(t, json.Unmarshal(created.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(created.Body.Bytes(), &app, jsonx.V1())) resourceArn := "arn:aws:appconfig:us-east-1:123456789012:application/" + app.ID @@ -66,7 +67,7 @@ func TestHandler_TagResource_VerifyTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "prod", resp["Tags"]["env"]) assert.Equal(t, "1.0", resp["Tags"]["version"]) @@ -78,7 +79,7 @@ func TestHandler_TagResource_VerifyTags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/tags/"+resourceArn, nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Tags"], 1) assert.Equal(t, "1.0", resp["Tags"]["version"]) } diff --git a/services/appconfig/handler_test.go b/services/appconfig/handler_test.go index 6b859a5b23..b09c2a92af 100644 --- a/services/appconfig/handler_test.go +++ b/services/appconfig/handler_test.go @@ -2,7 +2,7 @@ package appconfig_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/appconfig" ) @@ -394,7 +395,7 @@ func TestHandler_ResourceIDsPresentAcrossResources(t *testing.T) { var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) require.NotEmpty(t, app.ID, "Application must have a non-empty Id") // Create environment. @@ -406,7 +407,7 @@ func TestHandler_ResourceIDsPresentAcrossResources(t *testing.T) { ID string `json:"Id"` ApplicationID string `json:"ApplicationId"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) require.NotEmpty(t, env.ID, "Environment must have a non-empty Id") assert.Equal(t, app.ID, env.ApplicationID, "Environment.ApplicationId must match the parent application") @@ -422,7 +423,7 @@ func TestHandler_ResourceIDsPresentAcrossResources(t *testing.T) { ApplicationID string `json:"ApplicationId"` LocationURI string `json:"LocationUri"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) require.NotEmpty(t, prof.ID, "ConfigurationProfile must have a non-empty Id") assert.Equal(t, app.ID, prof.ApplicationID) assert.Equal(t, "hosted", prof.LocationURI) @@ -436,7 +437,7 @@ func TestHandler_ResourceIDsPresentAcrossResources(t *testing.T) { ID string `json:"Id"` Name string `json:"Name"` } - require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat)) + require.NoError(t, json.Unmarshal(stratRec.Body.Bytes(), &strat, jsonx.V1())) require.NotEmpty(t, strat.ID, "DeploymentStrategy must have a non-empty Id") assert.Equal(t, "id-strat", strat.Name) } @@ -456,7 +457,7 @@ func TestHandler_ListResponsesUseItemsKey(t *testing.T) { var app struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &app, jsonx.V1())) envRec := doRequest(t, h, http.MethodPost, "/applications/"+app.ID+"/environments", []byte(`{"Name":"items-env"}`)) @@ -470,7 +471,7 @@ func TestHandler_ListResponsesUseItemsKey(t *testing.T) { var prof struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof)) + require.NoError(t, json.Unmarshal(profRec.Body.Bytes(), &prof, jsonx.V1())) stratRec := doRequest(t, h, http.MethodPost, "/deploymentstrategies", []byte(`{"Name":"items-strat","DeploymentDurationInMinutes":0,"GrowthFactor":100,"ReplicateTo":"NONE"}`)) @@ -479,7 +480,7 @@ func TestHandler_ListResponsesUseItemsKey(t *testing.T) { var env struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env)) + require.NoError(t, json.Unmarshal(envRec.Body.Bytes(), &env, jsonx.V1())) listPaths := []struct { name string @@ -506,7 +507,7 @@ func TestHandler_ListResponsesUseItemsKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "path: %s", tt.path) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["Items"] assert.True(t, ok, "%s: response must have 'Items' key, got keys: %v", tt.name, mapKeys(resp)) diff --git a/services/appconfig/persistence.go b/services/appconfig/persistence.go index 488fdddf54..d6d19609bd 100644 --- a/services/appconfig/persistence.go +++ b/services/appconfig/persistence.go @@ -2,7 +2,7 @@ package appconfig import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -54,7 +54,7 @@ const appconfigSnapshotVersion = 1 // deploymentTimers is deliberately NOT part of this snapshot -- see its doc // comment on InMemoryBackend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TagsByArn map[string]map[string]string `json:"tagsByArn"` VersionCounters map[string]map[string]int32 `json:"versionCounters"` DeploymentCounters map[string]map[string]int32 `json:"deploymentCounters"` diff --git a/services/appconfigdata/configuration.go b/services/appconfigdata/configuration.go index b711d04445..4d40980005 100644 --- a/services/appconfigdata/configuration.go +++ b/services/appconfigdata/configuration.go @@ -1,9 +1,11 @@ package appconfigdata import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // SetConfiguration stores or updates configuration content for a profile, @@ -33,7 +35,7 @@ func (b *InMemoryBackend) setConfiguration(app, env, profile, content, contentTy if isJSONContentType(contentType) { var v any - if err := json.Unmarshal([]byte(content), &v); err != nil { + if err := json.Unmarshal([]byte(content), &v, jsonx.V1()); err != nil { return ErrContentTypeMismatch } } diff --git a/services/appconfigdata/configuration_test.go b/services/appconfigdata/configuration_test.go index 2d1cfafed8..1f33af6fd2 100644 --- a/services/appconfigdata/configuration_test.go +++ b/services/appconfigdata/configuration_test.go @@ -1,7 +1,7 @@ package appconfigdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfigdata" ) @@ -361,14 +362,14 @@ func TestHandler_RetryAfterHeader(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": tt.pollInterval, - }) + }, jsonx.V1()) require.NoError(t, err) sessionRec := doRequest(t, h, http.MethodPost, "/configurationsessions", sessionBody) require.Equal(t, http.StatusCreated, sessionRec.Code) var sessionResp map[string]string - require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &sessionResp)) + require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &sessionResp, jsonx.V1())) tok := sessionResp["InitialConfigurationToken"] // First poll — gets content. @@ -635,13 +636,13 @@ func TestHandler_PollRateLimitEnforced(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": tt.pollInterval, - }) + }, jsonx.V1()) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", sessionBody) require.Equal(t, http.StatusCreated, rec.Code) var sessionResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sessionResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sessionResp, jsonx.V1())) tok := sessionResp["InitialConfigurationToken"] // First poll — succeeds. @@ -657,7 +658,7 @@ func TestHandler_PollRateLimitEnforced(t *testing.T) { assert.Equal(t, tt.wantRetry, rec2.Header().Get("Retry-After")) var body map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "BadRequestException", body["__type"]) assert.Equal(t, "InvalidParameters", body["Reason"]) diff --git a/services/appconfigdata/errors_test.go b/services/appconfigdata/errors_test.go index 75fc391fdb..b0a085d30c 100644 --- a/services/appconfigdata/errors_test.go +++ b/services/appconfigdata/errors_test.go @@ -1,13 +1,14 @@ package appconfigdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfigdata" ) @@ -134,7 +135,7 @@ func TestHandler_BadRequestException_Details(t *testing.T) { assert.Equal(t, "BadRequestException", rec.Header().Get("X-Amzn-Errortype")) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "BadRequestException", body["__type"]) assert.Equal(t, "InvalidParameters", body["Reason"]) @@ -158,14 +159,14 @@ func TestHandler_BadRequestException_Details(t *testing.T) { "EnvironmentIdentifier": "e", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": 60, - }) + }, jsonx.V1()) require.NoError(t, err) sessionRec := doRequest(t, h2, http.MethodPost, "/configurationsessions", sessionBody) require.Equal(t, http.StatusCreated, sessionRec.Code) var sessionResp map[string]string - require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &sessionResp)) + require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &sessionResp, jsonx.V1())) tok := sessionResp["InitialConfigurationToken"] // First poll succeeds. @@ -180,7 +181,7 @@ func TestHandler_BadRequestException_Details(t *testing.T) { assert.Equal(t, "BadRequestException", rec2.Header().Get("X-Amzn-Errortype")) var body map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "BadRequestException", body["__type"]) assert.Equal(t, "InvalidParameters", body["Reason"]) @@ -216,7 +217,7 @@ func TestHandler_ResourceNotFoundException_Structure(t *testing.T) { assert.Equal(t, "ResourceNotFoundException", rec.Header().Get("X-Amzn-Errortype")) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) assert.Equal(t, "Deployment", resp["ResourceType"]) @@ -245,7 +246,7 @@ func TestHandler_ResourceNotFoundException_Structure(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) }) } @@ -377,7 +378,7 @@ func TestHandler_ErrorResponseShape(t *testing.T) { "X-Amzn-ErrorType header must match exception type") var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantErrorType, body["__type"], "response body __type field must match exception type") assert.NotEmpty(t, body["message"], "error body must have a message field") diff --git a/services/appconfigdata/handler.go b/services/appconfigdata/handler.go index a12548cc2e..149f71ca57 100644 --- a/services/appconfigdata/handler.go +++ b/services/appconfigdata/handler.go @@ -2,7 +2,8 @@ package appconfigdata import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -191,7 +193,7 @@ func (h *Handler) handleStartConfigurationSession(c *echo.Context) error { log := logger.Load(c.Request().Context()) var req startSessionRequest - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { log.Error("appconfigdata: failed to decode StartConfigurationSession request", "error", err) return writeAWSError(c, http.StatusBadRequest, exceptionBadRequest, "invalid request body") diff --git a/services/appconfigdata/handler_sdk_route_table_test.go b/services/appconfigdata/handler_sdk_route_table_test.go index cf6fc091b4..8b25b1c79a 100644 --- a/services/appconfigdata/handler_sdk_route_table_test.go +++ b/services/appconfigdata/handler_sdk_route_table_test.go @@ -2,7 +2,7 @@ package appconfigdata_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sdkRouteCases is the authoritative method+path for every real AppConfigData @@ -95,7 +97,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var decoded struct { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded, jsonx.V1())) assert.NotEqual(t, "not found", decoded.Message, "method=%s path=%s op=%s: dispatched to the unmatched-route default", tc.method, tc.path, tc.op) } diff --git a/services/appconfigdata/handler_test.go b/services/appconfigdata/handler_test.go index 7038514d52..e27bd7519c 100644 --- a/services/appconfigdata/handler_test.go +++ b/services/appconfigdata/handler_test.go @@ -2,7 +2,7 @@ package appconfigdata_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/appconfigdata" ) @@ -20,7 +21,7 @@ import ( func nowUTC() time.Time { return time.Now().UTC() } func mustMarshalJSON(v any) []byte { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { panic(err) } @@ -81,7 +82,7 @@ func startSession(t *testing.T, h *appconfigdata.Handler, app, env, profile stri require.Equal(t, http.StatusCreated, rec.Code, "startSession failed: %s", rec.Body.String()) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) token := resp["InitialConfigurationToken"] require.NotEmpty(t, token) @@ -93,7 +94,7 @@ func decodeErrorBody(t *testing.T, body string) (string, string) { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &m), "error body must be valid JSON") + require.NoError(t, json.Unmarshal([]byte(body), &m, jsonx.V1()), "error body must be valid JSON") errType, _ := m["__type"].(string) errMsg, _ := m["message"].(string) diff --git a/services/appconfigdata/persistence.go b/services/appconfigdata/persistence.go index 08a3c3a1a4..b8d4b362b1 100644 --- a/services/appconfigdata/persistence.go +++ b/services/appconfigdata/persistence.go @@ -2,7 +2,7 @@ package appconfigdata import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -44,8 +44,8 @@ const appconfigdataSnapshotVersion = 1 // material to disk was judged not worth the added attack surface for a // session-token integrity check. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. It implements diff --git a/services/appconfigdata/sessions_test.go b/services/appconfigdata/sessions_test.go index 4f8d00acaa..f85adb8e97 100644 --- a/services/appconfigdata/sessions_test.go +++ b/services/appconfigdata/sessions_test.go @@ -1,7 +1,7 @@ package appconfigdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfigdata" ) @@ -122,7 +123,7 @@ func TestHandler_StartConfigurationSession(t *testing.T) { if tt.wantToken { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["InitialConfigurationToken"]) } }) @@ -169,7 +170,7 @@ func TestHandler_PollIntervalValidation(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": tt.interval, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", bodyJSON) @@ -221,14 +222,14 @@ func TestHandler_PollIntervalHonored(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "profile", "RequiredMinimumPollIntervalInSeconds": tt.interval, - }) + }, jsonx.V1()) require.NoError(t, err) sessionRec := doRequest(t, h, http.MethodPost, "/configurationsessions", sessionBody) require.Equal(t, http.StatusCreated, sessionRec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sessionRec.Body.Bytes(), &resp, jsonx.V1())) token := resp["InitialConfigurationToken"] cfgRec := doRequest(t, h, http.MethodGet, "/configuration?configuration_token="+token, nil) @@ -257,7 +258,7 @@ func TestHandler_StartSession_IdentifierLength(t *testing.T) { "ApplicationIdentifier": longID, "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", - }) + }, jsonx.V1()) return b }(), @@ -269,7 +270,7 @@ func TestHandler_StartSession_IdentifierLength(t *testing.T) { "ApplicationIdentifier": "app", "EnvironmentIdentifier": longID, "ConfigurationProfileIdentifier": "p", - }) + }, jsonx.V1()) return b }(), @@ -281,7 +282,7 @@ func TestHandler_StartSession_IdentifierLength(t *testing.T) { "ApplicationIdentifier": "app", "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": longID, - }) + }, jsonx.V1()) return b }(), @@ -329,7 +330,7 @@ func TestHandler_StartSession_MaxPollInterval(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": tt.interval, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", bodyJSON) @@ -405,7 +406,7 @@ func TestHandler_StartSession_ExactMaxIdentifierLength(t *testing.T) { "ApplicationIdentifier": validID, "EnvironmentIdentifier": validID, "ConfigurationProfileIdentifier": validID, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", bodyJSON) @@ -419,7 +420,7 @@ func TestHandler_StartSession_ExactMaxIdentifierLength(t *testing.T) { "ApplicationIdentifier": invalidID, "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", bodyJSON) @@ -462,7 +463,7 @@ func TestHandler_StartSession_PollInterval_Boundary(t *testing.T) { "EnvironmentIdentifier": "env", "ConfigurationProfileIdentifier": "p", "RequiredMinimumPollIntervalInSeconds": tt.interval, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/configurationsessions", bodyJSON) diff --git a/services/appconfigdata/store.go b/services/appconfigdata/store.go index ce3d2ed916..071c622d47 100644 --- a/services/appconfigdata/store.go +++ b/services/appconfigdata/store.go @@ -6,12 +6,13 @@ import ( "crypto/rand" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "sync/atomic" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -64,8 +65,8 @@ func profileKey(app, env, profile string) string { func normalizedContentHash(content, contentType string) string { if isJSONContentType(contentType) { var v any - if err := json.Unmarshal([]byte(content), &v); err == nil { - if normalized, marshalErr := json.Marshal(v); marshalErr == nil { + if err := json.Unmarshal([]byte(content), &v, jsonx.V1()); err == nil { + if normalized, marshalErr := json.Marshal(v, jsonx.V1()); marshalErr == nil { sum := sha256.Sum256(normalized) return hex.EncodeToString(sum[:]) diff --git a/services/appintegrations/persistence.go b/services/appintegrations/persistence.go index c242097b1e..9457ecceb6 100644 --- a/services/appintegrations/persistence.go +++ b/services/appintegrations/persistence.go @@ -2,7 +2,7 @@ package appintegrations import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/applicationautoscaling/errors_test.go b/services/applicationautoscaling/errors_test.go index 5409bedd73..078c805037 100644 --- a/services/applicationautoscaling/errors_test.go +++ b/services/applicationautoscaling/errors_test.go @@ -9,7 +9,7 @@ package applicationautoscaling_test // InvalidNextTokenException. import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/applicationautoscaling" ) @@ -40,7 +41,7 @@ func TestHandler_PutScalingPolicy_RequiresRegisteredTarget(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ObjectNotFoundException", errBody["__type"]) } @@ -62,7 +63,7 @@ func TestHandler_PutScheduledAction_RequiresRegisteredTarget(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ObjectNotFoundException", errBody["__type"]) } @@ -84,7 +85,7 @@ func TestHandler_ObjectNotFoundException_Is400Not404(t *testing.T) { require.NotEqual(t, http.StatusNotFound, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ObjectNotFoundException", errBody["__type"]) } @@ -218,7 +219,7 @@ func TestHandler_DescribeOps_InvalidNextToken(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "InvalidNextTokenException", errBody["__type"]) }) } diff --git a/services/applicationautoscaling/handler.go b/services/applicationautoscaling/handler.go index dfe8db7295..a43b97bae2 100644 --- a/services/applicationautoscaling/handler.go +++ b/services/applicationautoscaling/handler.go @@ -2,7 +2,7 @@ package applicationautoscaling import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -177,13 +178,13 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // marshalError serialises a JSONErrorResponse into bytes. // Marshaling a struct with only string fields cannot fail; error is intentionally ignored. func marshalError(errType, message string) []byte { - payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}) + payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}, jsonx.V1()) return payload } @@ -206,7 +207,7 @@ func marshalResourceError(errType, message, resourceName string) []byte { Type string `json:"__type"` Message string `json:"message"` ResourceName string `json:"ResourceName,omitempty"` - }{Type: errType, Message: message, ResourceName: resourceName}) + }{Type: errType, Message: message, ResourceName: resourceName}, jsonx.V1()) return payload } @@ -234,8 +235,6 @@ func clientMessage(err error) string { } func (h *Handler) writeAPIError(_ context.Context, c *echo.Context, _ string, err error, msg string) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError resourceName := "" if rn, ok := errors.AsType[resourceNamer](err); ok { @@ -270,7 +269,7 @@ func (h *Handler) writeAPIError(_ context.Context, c *echo.Context, _ string, er case errors.Is(err, ErrValidation): return c.JSONBlob(http.StatusBadRequest, marshalError("ValidationException", msg)) case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSONBlob(http.StatusBadRequest, marshalError("ValidationException", msg)) // Server faults (HTTP 500). case errors.Is(err, ErrConcurrentUpdate): diff --git a/services/applicationautoscaling/handler_forecast_test.go b/services/applicationautoscaling/handler_forecast_test.go index 713da3de7b..5964d44712 100644 --- a/services/applicationautoscaling/handler_forecast_test.go +++ b/services/applicationautoscaling/handler_forecast_test.go @@ -1,12 +1,14 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetPredictiveScalingForecast(t *testing.T) { @@ -146,7 +148,7 @@ func TestHandler_GetPredictiveScalingForecast_HonestlyEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cf, ok := resp["CapacityForecast"].(map[string]any) require.True(t, ok, "expected CapacityForecast in response") diff --git a/services/applicationautoscaling/handler_scalable_targets_describe_test.go b/services/applicationautoscaling/handler_scalable_targets_describe_test.go index 3c40ab560d..c6b9327ac2 100644 --- a/services/applicationautoscaling/handler_scalable_targets_describe_test.go +++ b/services/applicationautoscaling/handler_scalable_targets_describe_test.go @@ -1,13 +1,15 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DeregisterScalableTarget(t *testing.T) { @@ -131,7 +133,7 @@ func TestHandler_DeregisterScalableTarget_CascadeDelete(t *testing.T) { "ServiceNamespace": "ecs", }) var targetsResp map[string]any - require.NoError(t, json.Unmarshal(targetsRec.Body.Bytes(), &targetsResp)) + require.NoError(t, json.Unmarshal(targetsRec.Body.Bytes(), &targetsResp, jsonx.V1())) targets, _ := targetsResp["ScalableTargets"].([]any) assert.Empty(t, targets, "scalable targets should be empty after deregister") @@ -140,7 +142,7 @@ func TestHandler_DeregisterScalableTarget_CascadeDelete(t *testing.T) { "ServiceNamespace": "ecs", }) var policiesResp map[string]any - require.NoError(t, json.Unmarshal(policiesRec.Body.Bytes(), &policiesResp)) + require.NoError(t, json.Unmarshal(policiesRec.Body.Bytes(), &policiesResp, jsonx.V1())) policies, _ := policiesResp["ScalingPolicies"].([]any) assert.Empty(t, policies, "scaling policies should be cascade-deleted") @@ -149,7 +151,7 @@ func TestHandler_DeregisterScalableTarget_CascadeDelete(t *testing.T) { "ServiceNamespace": "ecs", }) var actionsResp map[string]any - require.NoError(t, json.Unmarshal(actionsRec.Body.Bytes(), &actionsResp)) + require.NoError(t, json.Unmarshal(actionsRec.Body.Bytes(), &actionsResp, jsonx.V1())) actions, _ := actionsResp["ScheduledActions"].([]any) assert.Empty(t, actions, "scheduled actions should be cascade-deleted") } @@ -191,14 +193,14 @@ func TestDeregisterScalableTarget_Cascades(t *testing.T) { "ServiceNamespace": ns, }) var polOut map[string]any - require.NoError(t, json.Unmarshal(polRec.Body.Bytes(), &polOut)) + require.NoError(t, json.Unmarshal(polRec.Body.Bytes(), &polOut, jsonx.V1())) assert.Empty(t, polOut["ScalingPolicies"], "policies must be deleted when target is deregistered") actRec := doRequest(t, h, "DescribeScheduledActions", map[string]any{ "ServiceNamespace": ns, }) var actOut map[string]any - require.NoError(t, json.Unmarshal(actRec.Body.Bytes(), &actOut)) + require.NoError(t, json.Unmarshal(actRec.Body.Bytes(), &actOut, jsonx.V1())) assert.Empty(t, actOut["ScheduledActions"], "scheduled actions must be deleted when target is deregistered") } @@ -240,7 +242,7 @@ func TestHandler_DescribeScalableTargets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["ScalableTargets"].([]any) require.True(t, ok) assert.Len(t, targets, tt.wantCount) @@ -264,7 +266,7 @@ func TestHandler_DescribeScalableTargets_HasTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets := resp["ScalableTargets"].([]any) require.Len(t, targets, 1) @@ -287,7 +289,7 @@ func TestHandler_DescribeScalableTargets_OmitsTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var registerResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®isterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®isterResp, jsonx.V1())) doRequest(t, h, "TagResource", map[string]any{ "ResourceARN": registerResp["ScalableTargetARN"], @@ -298,7 +300,7 @@ func TestHandler_DescribeScalableTargets_OmitsTags(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) targets := resp["ScalableTargets"].([]any) require.Len(t, targets, 1) @@ -332,7 +334,7 @@ func TestHandler_DescribeScalableTargets_ResourceIdsFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["ScalableTargets"].([]any) require.True(t, ok) assert.Len(t, targets, 2, "expected exactly 2 targets when filtering by ResourceIds") @@ -390,7 +392,7 @@ func TestHandler_DescribeScalableTargets_ScalableDimensionFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["ScalableTargets"].([]any) require.True(t, ok) assert.Len(t, targets, tt.wantCount) @@ -431,7 +433,7 @@ func TestHandler_DescribeScalableTargets_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) targets := out["ScalableTargets"].([]any) assert.Len(t, targets, tc.wantCount) if tc.wantNext { @@ -481,7 +483,7 @@ func TestHandler_MaxResults_DescribeScalableTargets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["ScalableTargets"].([]any) require.True(t, ok) assert.Len(t, targets, tt.wantLen) @@ -512,7 +514,7 @@ func TestHandler_ApplyMaxResults_CapAt50(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, _ := resp["ScalableTargets"].([]any) assert.Len(t, targets, 50, "MaxResults=200 should be capped at 50") } diff --git a/services/applicationautoscaling/handler_scalable_targets_test.go b/services/applicationautoscaling/handler_scalable_targets_test.go index 8296e49099..878b5b8c04 100644 --- a/services/applicationautoscaling/handler_scalable_targets_test.go +++ b/services/applicationautoscaling/handler_scalable_targets_test.go @@ -1,13 +1,15 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_RegisterScalableTarget(t *testing.T) { @@ -42,7 +44,7 @@ func TestHandler_RegisterScalableTarget(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) assert.Contains(t, resp[tt.wantKey].(string), "arn:aws:application-autoscaling:") }) @@ -65,7 +67,7 @@ func TestHandler_RegisterScalableTarget_Upsert(t *testing.T) { rec1 := doRequest(t, h, "RegisterScalableTarget", body) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) // Update (upsert) - should update, not error body["MaxCapacity"] = int32(20) @@ -76,7 +78,7 @@ func TestHandler_RegisterScalableTarget_Upsert(t *testing.T) { descRec := doRequest(t, h, "DescribeScalableTargets", map[string]any{"ServiceNamespace": "ecs"}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) targets := descResp["ScalableTargets"].([]any) require.Len(t, targets, 1) target := targets[0].(map[string]any) @@ -171,7 +173,7 @@ func TestHandler_RegisterScalableTarget_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) targetARN, _ := regResp["ScalableTargetARN"].(string) require.NotEmpty(t, targetARN) @@ -180,7 +182,7 @@ func TestHandler_RegisterScalableTarget_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, tagRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp, jsonx.V1())) tags, ok := tagResp["Tags"].(map[string]any) require.True(t, ok, "expected Tags in response") assert.Equal(t, "prod", tags["env"]) @@ -207,7 +209,7 @@ func TestHandler_RegisterScalableTarget_WithRoleARN(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) targets, ok := descResp["ScalableTargets"].([]any) require.True(t, ok) require.Len(t, targets, 1) @@ -239,7 +241,7 @@ func TestHandler_RegisterScalableTarget_WithSuspendedState(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["ScalableTargets"].([]any) require.True(t, ok) require.Len(t, targets, 1) @@ -283,7 +285,7 @@ func TestHandler_RegisterScalableTarget_UpdateSuspendedState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, _ := resp["ScalableTargets"].([]any) require.Len(t, targets, 1) @@ -435,7 +437,7 @@ func TestRegisterDeregisterLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) targets := descOut["ScalableTargets"].([]any) require.Len(t, targets, 1) t0 := targets[0].(map[string]any) @@ -454,7 +456,7 @@ func TestRegisterDeregisterLifecycle(t *testing.T) { "ServiceNamespace": ns, }) var afterOut map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut, jsonx.V1())) assert.Empty(t, afterOut["ScalableTargets"]) } @@ -493,7 +495,7 @@ func TestHandler_RegisterScalableTarget_UpdateOmittedCapacityPreserved(t *testin require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) targets, _ := resp["ScalableTargets"].([]any) require.Len(t, targets, 1) target := targets[0].(map[string]any) diff --git a/services/applicationautoscaling/handler_scaling_policies_test.go b/services/applicationautoscaling/handler_scaling_policies_test.go index e396562d3c..88fc0e3027 100644 --- a/services/applicationautoscaling/handler_scaling_policies_test.go +++ b/services/applicationautoscaling/handler_scaling_policies_test.go @@ -1,7 +1,7 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutScalingPolicy(t *testing.T) { @@ -26,7 +28,7 @@ func TestHandler_PutScalingPolicy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policyARN, _ := resp["PolicyARN"].(string) assert.Contains(t, policyARN, "arn:aws:autoscaling:") assert.Contains(t, policyARN, "scalingPolicy:") @@ -125,7 +127,7 @@ func TestHandler_PutScalingPolicy_DefaultPolicyType(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ScalingPolicies"].([]any) require.True(t, ok) require.Len(t, policies, 1) @@ -161,7 +163,7 @@ func TestHandler_PutScalingPolicy_PreservesTypeOnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, _ := resp["ScalingPolicies"].([]any) require.Len(t, policies, 1) policy := policies[0].(map[string]any) @@ -284,7 +286,7 @@ func TestHandler_DescribeScalingPolicies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ScalingPolicies"].([]any) require.True(t, ok) assert.Len(t, policies, tt.wantCount) @@ -348,7 +350,7 @@ func TestHandler_DescribeScalingPolicies_RicherFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ScalingPolicies"].([]any) require.True(t, ok) assert.Len(t, policies, tt.wantCount) @@ -380,7 +382,7 @@ func TestHandler_DescribeScalingPolicies_IncludesConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, _ := resp["ScalingPolicies"].([]any) require.Len(t, policies, 1) policy := policies[0].(map[string]any) @@ -411,7 +413,7 @@ func TestHandler_MaxResults_DescribeScalingPolicies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ScalingPolicies"].([]any) require.True(t, ok) assert.Len(t, policies, 2) @@ -442,7 +444,7 @@ func TestScalingPolicyCRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, putRec.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) policyARN := putOut["PolicyARN"].(string) assert.NotEmpty(t, policyARN) @@ -450,7 +452,7 @@ func TestScalingPolicyCRUD(t *testing.T) { "ServiceNamespace": ns, }) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) policies := descOut["ScalingPolicies"].([]any) require.Len(t, policies, 1) p0 := policies[0].(map[string]any) @@ -471,7 +473,7 @@ func TestScalingPolicyCRUD(t *testing.T) { "ServiceNamespace": ns, }) var afterOut map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut, jsonx.V1())) assert.Empty(t, afterOut["ScalingPolicies"]) } @@ -538,7 +540,7 @@ func TestHandler_PutScalingPolicy_Alarms(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut, jsonx.V1())) _, putHasAlarms := putOut["Alarms"] assert.False(t, putHasAlarms, "PutScalingPolicy response Alarms should be omitted") @@ -549,7 +551,7 @@ func TestHandler_PutScalingPolicy_Alarms(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) policies := descOut["ScalingPolicies"].([]any) require.Len(t, policies, 1) _, descHasAlarms := policies[0].(map[string]any)["Alarms"] @@ -589,7 +591,7 @@ func TestHandler_PutScalingPolicy_PredictiveScalingConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) policies := descOut["ScalingPolicies"].([]any) require.Len(t, policies, 1) p0 := policies[0].(map[string]any) diff --git a/services/applicationautoscaling/handler_scheduled_actions_test.go b/services/applicationautoscaling/handler_scheduled_actions_test.go index af98f94cb8..03700a7e99 100644 --- a/services/applicationautoscaling/handler_scheduled_actions_test.go +++ b/services/applicationautoscaling/handler_scheduled_actions_test.go @@ -1,13 +1,15 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutScheduledAction(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_PutScheduledAction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ScheduledActionARN"], "arn:aws:autoscaling:") assert.Contains(t, resp["ScheduledActionARN"], "scheduledAction:") } @@ -54,7 +56,7 @@ func TestHandler_PutScheduledAction_Upsert(t *testing.T) { descRec := doRequest(t, h, "DescribeScheduledActions", map[string]any{"ServiceNamespace": "ecs"}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) actions := descResp["ScheduledActions"].([]any) assert.Len(t, actions, 1) } @@ -141,7 +143,7 @@ func TestHandler_PutScheduledAction_WithScalableTargetAction(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) require.Len(t, actions, 1) @@ -176,7 +178,7 @@ func TestHandler_PutScheduledAction_StartEndTimeTimezone(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) require.Len(t, actions, 1) @@ -318,7 +320,7 @@ func TestHandler_DescribeScheduledActions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) assert.Len(t, actions, tt.wantCount) @@ -377,7 +379,7 @@ func TestHandler_DescribeScheduledActions_RicherFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) assert.Len(t, actions, tt.wantCount) @@ -407,7 +409,7 @@ func TestHandler_MaxResults_DescribeScheduledActions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) assert.Len(t, actions, 2) @@ -439,7 +441,7 @@ func TestScheduledActionCRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, putRec.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) actionARN := putOut["ScheduledActionARN"].(string) assert.NotEmpty(t, actionARN) @@ -447,7 +449,7 @@ func TestScheduledActionCRUD(t *testing.T) { "ServiceNamespace": ns, }) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) actions := descOut["ScheduledActions"].([]any) require.Len(t, actions, 1) a0 := actions[0].(map[string]any) @@ -467,7 +469,7 @@ func TestScheduledActionCRUD(t *testing.T) { "ServiceNamespace": ns, }) var afterOut map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut, jsonx.V1())) assert.Empty(t, afterOut["ScheduledActions"]) } @@ -507,7 +509,7 @@ func TestHandler_PutScheduledAction_UpdateClearsOmittedStartEndTime(t *testing.T require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) require.Len(t, actions, 1) @@ -554,7 +556,7 @@ func TestHandler_PutScheduledAction_UpdateWithoutScheduleKeepsOld(t *testing.T) require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) actions, ok := resp["ScheduledActions"].([]any) require.True(t, ok) require.Len(t, actions, 1) diff --git a/services/applicationautoscaling/handler_tags_test.go b/services/applicationautoscaling/handler_tags_test.go index b54f97f773..5bf03e39d7 100644 --- a/services/applicationautoscaling/handler_tags_test.go +++ b/services/applicationautoscaling/handler_tags_test.go @@ -1,13 +1,15 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagResource(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_TagResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) resourceARN := createResp["ScalableTargetARN"] tagRec := doRequest(t, h, "TagResource", map[string]any{ @@ -84,7 +86,7 @@ func TestHandler_TagResource_ExceedsLimit(t *testing.T) { require.Equal(t, http.StatusOK, regRec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Resp, jsonx.V1())) targetARN, _ := regResp["ScalableTargetARN"].(string) require.NotEmpty(t, targetARN) @@ -110,7 +112,7 @@ func TestHandler_TagResource_ExceedsLimit(t *testing.T) { assert.Equal(t, http.StatusBadRequest, overRec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(overRec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(overRec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "TooManyTagsException", errBody["__type"]) assert.Equal(t, targetARN, errBody["ResourceName"]) } @@ -141,7 +143,7 @@ func TestHandler_RegisterScalableTarget_ExceedsTagLimit(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "LimitExceededException", errBody["__type"]) } @@ -187,7 +189,7 @@ func TestHandler_TagOps_NotFound_ResourceNotFoundException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errBody["__type"]) assert.Equal(t, missingARN, errBody["ResourceName"]) }) @@ -208,7 +210,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) resourceARN := createResp["ScalableTargetARN"] doRequest(t, h, "TagResource", map[string]any{ @@ -220,7 +222,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -234,7 +236,7 @@ func TestHandler_ListTagsForResource_EmptyARN(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errBody["__type"], "ListTagsForResource's own deserializeOpError switch types only ResourceNotFoundException") } @@ -253,7 +255,7 @@ func TestHandler_UntagResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) resourceARN := createResp["ScalableTargetARN"] doRequest(t, h, "TagResource", map[string]any{ @@ -269,7 +271,7 @@ func TestHandler_UntagResource(t *testing.T) { listRec := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": resourceARN}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) _, hasEnv := tags["env"] @@ -305,7 +307,7 @@ func TestHandler_TagResource_RoundTrip(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -320,7 +322,7 @@ func TestHandler_TagResource_RoundTrip(t *testing.T) { "ResourceARN": arn, }) var afterOut map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut, jsonx.V1())) afterTags := afterOut["Tags"].(map[string]any) assert.NotContains(t, afterTags, "env") assert.Equal(t, "platform", afterTags["team"]) diff --git a/services/applicationautoscaling/handler_test.go b/services/applicationautoscaling/handler_test.go index d49fe37375..66659d7861 100644 --- a/services/applicationautoscaling/handler_test.go +++ b/services/applicationautoscaling/handler_test.go @@ -2,7 +2,7 @@ package applicationautoscaling_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "log/slog" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/applicationautoscaling" ) @@ -35,7 +36,7 @@ func doRequest(t *testing.T, h *applicationautoscaling.Handler, action string, b var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -101,7 +102,7 @@ func seedTargetNS( require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ScalableTargetARN"].(string) } @@ -433,7 +434,7 @@ func TestApplicationAutoScaling_Handler_Reset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) targets, _ := out["ScalableTargets"].([]any) assert.Len(t, targets, tt.wantAfter) diff --git a/services/applicationautoscaling/multi_region_test.go b/services/applicationautoscaling/multi_region_test.go index 7720c4b5a6..a3b62f4a86 100644 --- a/services/applicationautoscaling/multi_region_test.go +++ b/services/applicationautoscaling/multi_region_test.go @@ -2,7 +2,7 @@ package applicationautoscaling_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/applicationautoscaling" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/applicationautoscaling/persistence.go b/services/applicationautoscaling/persistence.go index 0d0985e1f7..eab6e67a92 100644 --- a/services/applicationautoscaling/persistence.go +++ b/services/applicationautoscaling/persistence.go @@ -2,7 +2,7 @@ package applicationautoscaling import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -35,10 +35,10 @@ const applicationautoscalingSnapshotVersion = 1 // it too), so it remains ephemeral, reset to empty by both Reset and a // version-mismatch Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/applicationautoscaling/persistence_test.go b/services/applicationautoscaling/persistence_test.go index 94abafa699..7309609c79 100644 --- a/services/applicationautoscaling/persistence_test.go +++ b/services/applicationautoscaling/persistence_test.go @@ -1,13 +1,14 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/applicationautoscaling" ) @@ -368,7 +369,7 @@ func TestPersistence_SnapshotRestore(t *testing.T) { rec := doRequest(t, h2, "DescribeScalableTargets", map[string]any{"ServiceNamespace": "ecs"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets := resp["ScalableTargets"].([]any) assert.Len(t, targets, 1) } diff --git a/services/applicationautoscaling/scaling_activities_test.go b/services/applicationautoscaling/scaling_activities_test.go index 3bf19ffd8e..e675c1592d 100644 --- a/services/applicationautoscaling/scaling_activities_test.go +++ b/services/applicationautoscaling/scaling_activities_test.go @@ -1,13 +1,14 @@ package applicationautoscaling_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/applicationautoscaling" ) @@ -126,7 +127,7 @@ func TestHandler_DescribeScalingActivities(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) activities, ok := resp["ScalingActivities"].([]any) require.True(t, ok) assert.Empty(t, activities) @@ -154,7 +155,7 @@ func TestHandler_DescribeScalingActivities_AfterRegister(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) activities, ok := resp["ScalingActivities"].([]any) require.True(t, ok) require.Len(t, activities, 1) @@ -188,7 +189,7 @@ func TestHandler_DescribeScalingActivities_WithInput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) acts, ok := resp["ScalingActivities"].([]any) require.True(t, ok, "ScalingActivities should be an array") assert.Empty(t, acts, "expected empty array not null") @@ -213,7 +214,7 @@ func TestHandler_DescribeScalingActivities_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1 := out1["ScalingActivities"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["NextToken"].(string) @@ -226,7 +227,7 @@ func TestHandler_DescribeScalingActivities_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2 := out2["ScalingActivities"].([]any) assert.Len(t, page2, 2) } @@ -243,7 +244,7 @@ func TestHandler_DescribeScalingActivities_TypedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) activities := out["ScalingActivities"].([]any) require.Len(t, activities, 1) diff --git a/services/appmesh/handler.go b/services/appmesh/handler.go index 160bf2c1aa..8853733455 100644 --- a/services/appmesh/handler.go +++ b/services/appmesh/handler.go @@ -2,7 +2,8 @@ package appmesh import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -211,12 +213,12 @@ func metaToWire(m ResourceMeta) map[string]any { } // specOrEmpty returns a JSON object, ensuring we never return null. -func specOrEmpty(spec json.RawMessage) any { +func specOrEmpty(spec jsontext.Value) any { if len(spec) == 0 { return map[string]any{} } var v any - if err := json.Unmarshal(spec, &v); err != nil { + if err := json.Unmarshal(spec, &v, jsonx.V1()); err != nil { return map[string]any{} } diff --git a/services/appmesh/handler_meshes.go b/services/appmesh/handler_meshes.go index 5583569248..803cb0c54b 100644 --- a/services/appmesh/handler_meshes.go +++ b/services/appmesh/handler_meshes.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "github.com/labstack/echo/v5" @@ -71,10 +71,10 @@ func (h *Handler) handleMeshes(c *echo.Context, segs []string) error { func (h *Handler) handleCreateMesh(c *echo.Context) error { var body struct { - MeshName string `json:"meshName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + MeshName string `json:"meshName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.MeshName) { return c.JSON( @@ -104,8 +104,8 @@ func (h *Handler) handleDescribeMesh(c *echo.Context, meshName string) error { func (h *Handler) handleUpdateMesh(c *echo.Context, meshName string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) diff --git a/services/appmesh/handler_test.go b/services/appmesh/handler_test.go index 3141a2b0d2..3ff79ffc11 100644 --- a/services/appmesh/handler_test.go +++ b/services/appmesh/handler_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appmesh" ) @@ -26,7 +27,7 @@ func doRequest(t *testing.T, h *appmesh.Handler, method, path string, body any) t.Helper() var bodyStr string if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyStr = string(b) } @@ -45,7 +46,7 @@ func doRequest(t *testing.T, h *appmesh.Handler, method, path string, body any) func getBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/appmesh/handler_virtual_gateways.go b/services/appmesh/handler_virtual_gateways.go index 5bc6c92aa6..ca9e2443f8 100644 --- a/services/appmesh/handler_virtual_gateways.go +++ b/services/appmesh/handler_virtual_gateways.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "github.com/labstack/echo/v5" @@ -47,10 +47,10 @@ func (h *Handler) handleVirtualGateways(c *echo.Context, segs []string, meshName func (h *Handler) handleCreateVirtualGateway(c *echo.Context, meshName string) error { var body struct { - VirtualGatewayName string `json:"virtualGatewayName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + VirtualGatewayName string `json:"virtualGatewayName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.VirtualGatewayName) { return c.JSON( @@ -77,8 +77,8 @@ func (h *Handler) handleDescribeVirtualGateway(c *echo.Context, meshName, name s func (h *Handler) handleUpdateVirtualGateway(c *echo.Context, meshName, name string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) @@ -190,10 +190,10 @@ func (h *Handler) handleGatewayRoutes(c *echo.Context, segs []string, meshName s func (h *Handler) handleCreateGatewayRoute(c *echo.Context, meshName, vgName string) error { var body struct { - GatewayRouteName string `json:"gatewayRouteName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + GatewayRouteName string `json:"gatewayRouteName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.GatewayRouteName) { return c.JSON( @@ -220,8 +220,8 @@ func (h *Handler) handleDescribeGatewayRoute(c *echo.Context, meshName, vgName, func (h *Handler) handleUpdateGatewayRoute(c *echo.Context, meshName, vgName, routeName string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) diff --git a/services/appmesh/handler_virtual_nodes.go b/services/appmesh/handler_virtual_nodes.go index 4bc1dcce0e..0db9ddb14c 100644 --- a/services/appmesh/handler_virtual_nodes.go +++ b/services/appmesh/handler_virtual_nodes.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "github.com/labstack/echo/v5" @@ -47,10 +47,10 @@ func (h *Handler) handleVirtualNodes(c *echo.Context, segs []string, meshName st func (h *Handler) handleCreateVirtualNode(c *echo.Context, meshName string) error { var body struct { - VirtualNodeName string `json:"virtualNodeName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + VirtualNodeName string `json:"virtualNodeName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.VirtualNodeName) { return c.JSON( @@ -77,8 +77,8 @@ func (h *Handler) handleDescribeVirtualNode(c *echo.Context, meshName, name stri func (h *Handler) handleUpdateVirtualNode(c *echo.Context, meshName, name string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) diff --git a/services/appmesh/handler_virtual_routers.go b/services/appmesh/handler_virtual_routers.go index 140c21ddc8..7c288fa9c6 100644 --- a/services/appmesh/handler_virtual_routers.go +++ b/services/appmesh/handler_virtual_routers.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "github.com/labstack/echo/v5" @@ -47,10 +47,10 @@ func (h *Handler) handleVirtualRouters(c *echo.Context, segs []string, meshName func (h *Handler) handleCreateVirtualRouter(c *echo.Context, meshName string) error { var body struct { - VirtualRouterName string `json:"virtualRouterName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + VirtualRouterName string `json:"virtualRouterName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.VirtualRouterName) { return c.JSON( @@ -77,8 +77,8 @@ func (h *Handler) handleDescribeVirtualRouter(c *echo.Context, meshName, name st func (h *Handler) handleUpdateVirtualRouter(c *echo.Context, meshName, name string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) @@ -190,10 +190,10 @@ func (h *Handler) handleRoutes(c *echo.Context, segs []string, meshName string) func (h *Handler) handleCreateRoute(c *echo.Context, meshName, vrName string) error { var body struct { - RouteName string `json:"routeName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + RouteName string `json:"routeName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.RouteName) { return c.JSON( @@ -220,8 +220,8 @@ func (h *Handler) handleDescribeRoute(c *echo.Context, meshName, vrName, routeNa func (h *Handler) handleUpdateRoute(c *echo.Context, meshName, vrName, routeName string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) diff --git a/services/appmesh/handler_virtual_services.go b/services/appmesh/handler_virtual_services.go index e6bee819a8..2cd89ae43c 100644 --- a/services/appmesh/handler_virtual_services.go +++ b/services/appmesh/handler_virtual_services.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "github.com/labstack/echo/v5" @@ -47,10 +47,10 @@ func (h *Handler) handleVirtualServices(c *echo.Context, segs []string, meshName func (h *Handler) handleCreateVirtualService(c *echo.Context, meshName string) error { var body struct { - VirtualServiceName string `json:"virtualServiceName"` - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` - Tags []tagInput `json:"tags"` + VirtualServiceName string `json:"virtualServiceName"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` + Tags []tagInput `json:"tags"` } if err := c.Bind(&body); err != nil || !isValidResourceName(body.VirtualServiceName) { return c.JSON( @@ -77,8 +77,8 @@ func (h *Handler) handleDescribeVirtualService(c *echo.Context, meshName, name s func (h *Handler) handleUpdateVirtualService(c *echo.Context, meshName, name string) error { var body struct { - ClientToken string `json:"clientToken"` - Spec json.RawMessage `json:"spec"` + ClientToken string `json:"clientToken"` + Spec jsontext.Value `json:"spec"` } if err := c.Bind(&body); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) diff --git a/services/appmesh/interfaces.go b/services/appmesh/interfaces.go index 37e588e3d3..e061a17256 100644 --- a/services/appmesh/interfaces.go +++ b/services/appmesh/interfaces.go @@ -2,7 +2,7 @@ package appmesh import ( "context" - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -15,59 +15,59 @@ type StorageBackend interface { Restore(ctx context.Context, data []byte) error // Mesh operations - CreateMesh(name string, spec json.RawMessage, tags map[string]string) (*Mesh, error) + CreateMesh(name string, spec jsontext.Value, tags map[string]string) (*Mesh, error) DescribeMesh(name string) (*Mesh, error) - UpdateMesh(name string, spec json.RawMessage) (*Mesh, error) + UpdateMesh(name string, spec jsontext.Value) (*Mesh, error) DeleteMesh(name string) (*Mesh, error) ListMeshes(maxResults int32, nextToken string) ([]*MeshSummary, string, error) // VirtualNode operations - CreateVirtualNode(meshName, name string, spec json.RawMessage, tags map[string]string) (*VirtualNode, error) + CreateVirtualNode(meshName, name string, spec jsontext.Value, tags map[string]string) (*VirtualNode, error) DescribeVirtualNode(meshName, name string) (*VirtualNode, error) - UpdateVirtualNode(meshName, name string, spec json.RawMessage) (*VirtualNode, error) + UpdateVirtualNode(meshName, name string, spec jsontext.Value) (*VirtualNode, error) DeleteVirtualNode(meshName, name string) (*VirtualNode, error) ListVirtualNodes(meshName string, maxResults int32, nextToken string) ([]*VirtualNodeSummary, string, error) // VirtualRouter operations - CreateVirtualRouter(meshName, name string, spec json.RawMessage, tags map[string]string) (*VirtualRouter, error) + CreateVirtualRouter(meshName, name string, spec jsontext.Value, tags map[string]string) (*VirtualRouter, error) DescribeVirtualRouter(meshName, name string) (*VirtualRouter, error) - UpdateVirtualRouter(meshName, name string, spec json.RawMessage) (*VirtualRouter, error) + UpdateVirtualRouter(meshName, name string, spec jsontext.Value) (*VirtualRouter, error) DeleteVirtualRouter(meshName, name string) (*VirtualRouter, error) ListVirtualRouters(meshName string, maxResults int32, nextToken string) ([]*VirtualRouterSummary, string, error) // Route operations (nested under virtual router) CreateRoute( meshName, virtualRouterName, routeName string, - spec json.RawMessage, + spec jsontext.Value, tags map[string]string, ) (*Route, error) DescribeRoute(meshName, virtualRouterName, routeName string) (*Route, error) - UpdateRoute(meshName, virtualRouterName, routeName string, spec json.RawMessage) (*Route, error) + UpdateRoute(meshName, virtualRouterName, routeName string, spec jsontext.Value) (*Route, error) DeleteRoute(meshName, virtualRouterName, routeName string) (*Route, error) ListRoutes(meshName, virtualRouterName string, maxResults int32, nextToken string) ([]*RouteSummary, string, error) // VirtualService operations - CreateVirtualService(meshName, name string, spec json.RawMessage, tags map[string]string) (*VirtualService, error) + CreateVirtualService(meshName, name string, spec jsontext.Value, tags map[string]string) (*VirtualService, error) DescribeVirtualService(meshName, name string) (*VirtualService, error) - UpdateVirtualService(meshName, name string, spec json.RawMessage) (*VirtualService, error) + UpdateVirtualService(meshName, name string, spec jsontext.Value) (*VirtualService, error) DeleteVirtualService(meshName, name string) (*VirtualService, error) ListVirtualServices(meshName string, maxResults int32, nextToken string) ([]*VirtualServiceSummary, string, error) // VirtualGateway operations - CreateVirtualGateway(meshName, name string, spec json.RawMessage, tags map[string]string) (*VirtualGateway, error) + CreateVirtualGateway(meshName, name string, spec jsontext.Value, tags map[string]string) (*VirtualGateway, error) DescribeVirtualGateway(meshName, name string) (*VirtualGateway, error) - UpdateVirtualGateway(meshName, name string, spec json.RawMessage) (*VirtualGateway, error) + UpdateVirtualGateway(meshName, name string, spec jsontext.Value) (*VirtualGateway, error) DeleteVirtualGateway(meshName, name string) (*VirtualGateway, error) ListVirtualGateways(meshName string, maxResults int32, nextToken string) ([]*VirtualGatewaySummary, string, error) // GatewayRoute operations (nested under virtual gateway) CreateGatewayRoute( meshName, virtualGatewayName, routeName string, - spec json.RawMessage, + spec jsontext.Value, tags map[string]string, ) (*GatewayRoute, error) DescribeGatewayRoute(meshName, virtualGatewayName, routeName string) (*GatewayRoute, error) - UpdateGatewayRoute(meshName, virtualGatewayName, routeName string, spec json.RawMessage) (*GatewayRoute, error) + UpdateGatewayRoute(meshName, virtualGatewayName, routeName string, spec jsontext.Value) (*GatewayRoute, error) DeleteGatewayRoute(meshName, virtualGatewayName, routeName string) (*GatewayRoute, error) ListGatewayRoutes( meshName, virtualGatewayName string, @@ -102,7 +102,7 @@ type Mesh struct { Name string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // MeshSummary is a mesh entry in a list response. @@ -122,7 +122,7 @@ type VirtualNode struct { VirtualNodeName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // VirtualNodeSummary is a virtual node entry in a list response. @@ -143,7 +143,7 @@ type VirtualRouter struct { VirtualRouterName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // VirtualRouterSummary is a virtual router entry in a list response. @@ -165,7 +165,7 @@ type Route struct { RouteName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // RouteSummary is a route entry in a list response. @@ -187,7 +187,7 @@ type VirtualService struct { VirtualServiceName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // VirtualServiceSummary is a virtual service entry in a list response. @@ -208,7 +208,7 @@ type VirtualGateway struct { VirtualGatewayName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // VirtualGatewaySummary is a virtual gateway entry in a list response. @@ -230,7 +230,7 @@ type GatewayRoute struct { GatewayRouteName string Status string Meta ResourceMeta - Spec json.RawMessage + Spec jsontext.Value } // GatewayRouteSummary is a gateway route entry in a list response. diff --git a/services/appmesh/meshes.go b/services/appmesh/meshes.go index 19f93ffdf0..b54ac252c8 100644 --- a/services/appmesh/meshes.go +++ b/services/appmesh/meshes.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -12,7 +12,7 @@ func (b *InMemoryBackend) meshARN(meshName string) string { return arn.Build("appmesh", b.region, b.accountID, fmt.Sprintf("mesh/%s", meshName)) } -func (b *InMemoryBackend) CreateMesh(name string, spec json.RawMessage, tags map[string]string) (*Mesh, error) { +func (b *InMemoryBackend) CreateMesh(name string, spec jsontext.Value, tags map[string]string) (*Mesh, error) { b.mu.Lock("CreateMesh") defer b.mu.Unlock() if err := validateMeshSpec(spec); err != nil { @@ -47,7 +47,7 @@ func (b *InMemoryBackend) DescribeMesh(name string) (*Mesh, error) { return m, nil } -func (b *InMemoryBackend) UpdateMesh(name string, spec json.RawMessage) (*Mesh, error) { +func (b *InMemoryBackend) UpdateMesh(name string, spec jsontext.Value) (*Mesh, error) { b.mu.Lock("UpdateMesh") defer b.mu.Unlock() if err := validateMeshSpec(spec); err != nil { diff --git a/services/appmesh/meshes_test.go b/services/appmesh/meshes_test.go index f016fb4d6e..0511bae77b 100644 --- a/services/appmesh/meshes_test.go +++ b/services/appmesh/meshes_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/http" "strings" @@ -232,7 +232,7 @@ func TestBackend_SpecRoundTrip(t *testing.T) { t.Parallel() b := appmesh.NewInMemoryBackend("000000000000", "us-east-1") - _, err := b.CreateMesh("m1", json.RawMessage(`{"key":"val"}`), nil) + _, err := b.CreateMesh("m1", jsontext.Value(`{"key":"val"}`), nil) require.NoError(t, err) m, err := b.DescribeMesh("m1") diff --git a/services/appmesh/persistence.go b/services/appmesh/persistence.go index c58e2f41c1..0c94fd83a9 100644 --- a/services/appmesh/persistence.go +++ b/services/appmesh/persistence.go @@ -2,7 +2,7 @@ package appmesh import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -36,7 +36,7 @@ const appmeshSnapshotVersion = 1 // an incompatible (older or newer) build of this backend as though it were // the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/appmesh/spec_schema.go b/services/appmesh/spec_schema.go index 3d3b285d15..bf98c5ce97 100644 --- a/services/appmesh/spec_schema.go +++ b/services/appmesh/spec_schema.go @@ -2,7 +2,8 @@ package appmesh import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -12,6 +13,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errSpecDSL = errors.New("appmesh spec dsl") @@ -459,13 +461,13 @@ func mustSpecSchemas() *specSchemas { return s } -func (s *specSchemas) validate(shape string, spec json.RawMessage) error { +func (s *specSchemas) validate(shape string, spec jsontext.Value) error { if len(bytes.TrimSpace(spec)) == 0 { return nil } var v any - if err := json.Unmarshal(spec, &v); err != nil { + if err := json.Unmarshal(spec, &v, jsonx.V1()); err != nil { return awserr.Newf("spec: %s", awserr.ErrInvalidParameter, err) } diff --git a/services/appmesh/spec_schema_test.go b/services/appmesh/spec_schema_test.go index 502ea0adf5..765caa7c6e 100644 --- a/services/appmesh/spec_schema_test.go +++ b/services/appmesh/spec_schema_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -105,10 +105,10 @@ func TestBackend_DeepSpecValidation(t *testing.T) { require.NoError(t, err) _, err = b.CreateVirtualRouter("m", "r", nil, nil) require.NoError(t, err) - _, err = b.CreateVirtualGateway("m", "g", json.RawMessage(`{"listeners":[`+httpPortMapping+`]}`), nil) + _, err = b.CreateVirtualGateway("m", "g", jsontext.Value(`{"listeners":[`+httpPortMapping+`]}`), nil) require.NoError(t, err) - spec := json.RawMessage(tt.spec) + spec := jsontext.Value(tt.spec) switch tt.kind { case "node": diff --git a/services/appmesh/spec_validate.go b/services/appmesh/spec_validate.go index 9ca254f0e1..64d1a41503 100644 --- a/services/appmesh/spec_validate.go +++ b/services/appmesh/spec_validate.go @@ -1,9 +1,11 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Structural validation for the shallow spec shapes (MeshSpec, VirtualRouterSpec, @@ -36,7 +38,7 @@ func isValidPortProtocol(p string) bool { } // validateMeshSpec structurally validates a MeshSpec body (types.MeshSpec). -func validateMeshSpec(spec json.RawMessage) error { +func validateMeshSpec(spec jsontext.Value) error { if len(spec) == 0 { return nil } @@ -48,7 +50,7 @@ func validateMeshSpec(spec json.RawMessage) error { IPPreference string `json:"ipPreference"` } `json:"serviceDiscovery"` } - if err := json.Unmarshal(spec, &body); err != nil { + if err := json.Unmarshal(spec, &body, jsonx.V1()); err != nil { return awserr.Newf("spec: %s", awserr.ErrInvalidParameter, err) } if body.EgressFilter != nil && !isValidEgressFilterType(body.EgressFilter.Type) { @@ -89,7 +91,7 @@ func validatePortMapping(pm *portMappingBody) error { // validateVirtualRouterSpec structurally validates a VirtualRouterSpec body // (types.VirtualRouterSpec). -func validateVirtualRouterSpec(spec json.RawMessage) error { +func validateVirtualRouterSpec(spec jsontext.Value) error { if len(spec) == 0 { return nil } @@ -98,7 +100,7 @@ func validateVirtualRouterSpec(spec json.RawMessage) error { PortMapping *portMappingBody `json:"portMapping"` } `json:"listeners"` } - if err := json.Unmarshal(spec, &body); err != nil { + if err := json.Unmarshal(spec, &body, jsonx.V1()); err != nil { return awserr.Newf("spec: %s", awserr.ErrInvalidParameter, err) } for _, l := range body.Listeners { @@ -122,14 +124,14 @@ type virtualServiceProviderBody struct { // validateVirtualServiceSpec structurally validates a VirtualServiceSpec body // (types.VirtualServiceSpec). provider is a smithy union: exactly one of // virtualNode/virtualRouter may be set. -func validateVirtualServiceSpec(spec json.RawMessage) error { +func validateVirtualServiceSpec(spec jsontext.Value) error { if len(spec) == 0 { return nil } var body struct { Provider *virtualServiceProviderBody `json:"provider"` } - if err := json.Unmarshal(spec, &body); err != nil { + if err := json.Unmarshal(spec, &body, jsonx.V1()); err != nil { return awserr.Newf("spec: %s", awserr.ErrInvalidParameter, err) } if body.Provider == nil { diff --git a/services/appmesh/spec_validate_test.go b/services/appmesh/spec_validate_test.go index 5d5a43056d..909c27ea09 100644 --- a/services/appmesh/spec_validate_test.go +++ b/services/appmesh/spec_validate_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -37,9 +37,9 @@ func TestBackend_MeshSpecValidation(t *testing.T) { t.Parallel() b := appmesh.NewInMemoryBackend("000000000000", "us-east-1") - var raw json.RawMessage + var raw jsontext.Value if tt.spec != "" { - raw = json.RawMessage(tt.spec) + raw = jsontext.Value(tt.spec) } _, err := b.CreateMesh("m1", raw, nil) if tt.wantErr { @@ -102,9 +102,9 @@ func TestBackend_VirtualRouterSpecValidation(t *testing.T) { _, err := b.CreateMesh("m1", nil, nil) require.NoError(t, err) - var raw json.RawMessage + var raw jsontext.Value if tt.spec != "" { - raw = json.RawMessage(tt.spec) + raw = jsontext.Value(tt.spec) } _, err = b.CreateVirtualRouter("m1", "vr1", raw, nil) if tt.wantErr { @@ -168,9 +168,9 @@ func TestBackend_VirtualServiceSpecValidation(t *testing.T) { _, err := b.CreateMesh("m1", nil, nil) require.NoError(t, err) - var raw json.RawMessage + var raw jsontext.Value if tt.spec != "" { - raw = json.RawMessage(tt.spec) + raw = jsontext.Value(tt.spec) } _, err = b.CreateVirtualService("m1", "vs1", raw, nil) if tt.wantErr { diff --git a/services/appmesh/store.go b/services/appmesh/store.go index e0c1a2aa61..554cc46954 100644 --- a/services/appmesh/store.go +++ b/services/appmesh/store.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "maps" @@ -108,9 +108,9 @@ const statusActive = "ACTIVE" const statusDeleted = "DELETED" // normalizeSpec returns a non-nil JSON object if spec is nil or empty. -func normalizeSpec(spec json.RawMessage) json.RawMessage { +func normalizeSpec(spec jsontext.Value) jsontext.Value { if len(spec) == 0 { - return json.RawMessage(`{}`) + return jsontext.Value(`{}`) } return spec diff --git a/services/appmesh/virtual_gateways.go b/services/appmesh/virtual_gateways.go index e52765036a..7dc36f62c1 100644 --- a/services/appmesh/virtual_gateways.go +++ b/services/appmesh/virtual_gateways.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "time" @@ -23,7 +23,7 @@ func (b *InMemoryBackend) gatewayRouteARN(meshName, vgName, routeName string) st // ─── VirtualGateway ─── func (b *InMemoryBackend) CreateVirtualGateway( - meshName, name string, spec json.RawMessage, tags map[string]string, + meshName, name string, spec jsontext.Value, tags map[string]string, ) (*VirtualGateway, error) { b.mu.Lock("CreateVirtualGateway") defer b.mu.Unlock() @@ -67,7 +67,7 @@ func (b *InMemoryBackend) DescribeVirtualGateway(meshName, name string) (*Virtua return vg, nil } -func (b *InMemoryBackend) UpdateVirtualGateway(meshName, name string, spec json.RawMessage) (*VirtualGateway, error) { +func (b *InMemoryBackend) UpdateVirtualGateway(meshName, name string, spec jsontext.Value) (*VirtualGateway, error) { if err := b.schemas.validate("virtualGatewaySpec", spec); err != nil { return nil, err } @@ -145,7 +145,7 @@ func (b *InMemoryBackend) ListVirtualGateways( // ─── GatewayRoute ─── func (b *InMemoryBackend) CreateGatewayRoute( - meshName, virtualGatewayName, routeName string, spec json.RawMessage, tags map[string]string, + meshName, virtualGatewayName, routeName string, spec jsontext.Value, tags map[string]string, ) (*GatewayRoute, error) { if err := b.schemas.validate("gatewayRouteSpec", spec); err != nil { return nil, err @@ -197,7 +197,7 @@ func (b *InMemoryBackend) DescribeGatewayRoute(meshName, virtualGatewayName, rou } func (b *InMemoryBackend) UpdateGatewayRoute( - meshName, virtualGatewayName, routeName string, spec json.RawMessage, + meshName, virtualGatewayName, routeName string, spec jsontext.Value, ) (*GatewayRoute, error) { if err := b.schemas.validate("gatewayRouteSpec", spec); err != nil { return nil, err diff --git a/services/appmesh/virtual_gateways_test.go b/services/appmesh/virtual_gateways_test.go index 565f0ca038..d15c513717 100644 --- a/services/appmesh/virtual_gateways_test.go +++ b/services/appmesh/virtual_gateways_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/http" "testing" @@ -232,7 +232,7 @@ func TestBackend_UpdateVirtualGateway(t *testing.T) { tt.setup(b) vg, err := b.UpdateVirtualGateway( tt.meshName, tt.vgName, - json.RawMessage(`{"listeners":[{"portMapping":{"port":8080,"protocol":"http"}}]}`), + jsontext.Value(`{"listeners":[{"portMapping":{"port":8080,"protocol":"http"}}]}`), ) if tt.wantErr != nil { require.Error(t, err) @@ -306,7 +306,7 @@ func TestBackend_UpdateGatewayRoute(t *testing.T) { tt.meshName, tt.vgName, tt.routeName, - json.RawMessage(`{}`), + jsontext.Value(`{}`), ) if tt.wantErr != nil { require.Error(t, err) diff --git a/services/appmesh/virtual_nodes.go b/services/appmesh/virtual_nodes.go index 526d0a9e76..0e2c236dc2 100644 --- a/services/appmesh/virtual_nodes.go +++ b/services/appmesh/virtual_nodes.go @@ -1,12 +1,14 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (b *InMemoryBackend) virtualNodeARN(meshName, name string) string { @@ -14,7 +16,7 @@ func (b *InMemoryBackend) virtualNodeARN(meshName, name string) string { } func (b *InMemoryBackend) CreateVirtualNode( - meshName, name string, spec json.RawMessage, tags map[string]string, + meshName, name string, spec jsontext.Value, tags map[string]string, ) (*VirtualNode, error) { if err := b.schemas.validate("virtualNodeSpec", spec); err != nil { return nil, err @@ -58,7 +60,7 @@ func (b *InMemoryBackend) DescribeVirtualNode(meshName, name string) (*VirtualNo return vn, nil } -func (b *InMemoryBackend) UpdateVirtualNode(meshName, name string, spec json.RawMessage) (*VirtualNode, error) { +func (b *InMemoryBackend) UpdateVirtualNode(meshName, name string, spec jsontext.Value) (*VirtualNode, error) { if err := b.schemas.validate("virtualNodeSpec", spec); err != nil { return nil, err } @@ -87,7 +89,7 @@ func (b *InMemoryBackend) virtualNodeIsServiceProvider(meshName, name string) bo var body struct { Provider *virtualServiceProviderBody `json:"provider"` } - if err := json.Unmarshal(vs.Spec, &body); err != nil { + if err := json.Unmarshal(vs.Spec, &body, jsonx.V1()); err != nil { continue } if body.Provider != nil && body.Provider.VirtualNode != nil && diff --git a/services/appmesh/virtual_routers.go b/services/appmesh/virtual_routers.go index 3ecf3e9e59..fc0364f56a 100644 --- a/services/appmesh/virtual_routers.go +++ b/services/appmesh/virtual_routers.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "time" @@ -24,7 +24,7 @@ func (b *InMemoryBackend) routeARN(meshName, vrName, routeName string) string { //nolint:dupl // create pattern (incl. spec validation call) is structurally identical across resource types func (b *InMemoryBackend) CreateVirtualRouter( - meshName, name string, spec json.RawMessage, tags map[string]string, + meshName, name string, spec jsontext.Value, tags map[string]string, ) (*VirtualRouter, error) { b.mu.Lock("CreateVirtualRouter") defer b.mu.Unlock() @@ -68,7 +68,7 @@ func (b *InMemoryBackend) DescribeVirtualRouter(meshName, name string) (*Virtual return vr, nil } -func (b *InMemoryBackend) UpdateVirtualRouter(meshName, name string, spec json.RawMessage) (*VirtualRouter, error) { +func (b *InMemoryBackend) UpdateVirtualRouter(meshName, name string, spec jsontext.Value) (*VirtualRouter, error) { b.mu.Lock("UpdateVirtualRouter") defer b.mu.Unlock() if err := validateVirtualRouterSpec(spec); err != nil { @@ -146,7 +146,7 @@ func (b *InMemoryBackend) ListVirtualRouters( // ─── Route ─── func (b *InMemoryBackend) CreateRoute( - meshName, virtualRouterName, routeName string, spec json.RawMessage, tags map[string]string, + meshName, virtualRouterName, routeName string, spec jsontext.Value, tags map[string]string, ) (*Route, error) { if err := b.schemas.validate("routeSpec", spec); err != nil { return nil, err @@ -199,7 +199,7 @@ func (b *InMemoryBackend) DescribeRoute(meshName, virtualRouterName, routeName s func (b *InMemoryBackend) UpdateRoute( meshName, virtualRouterName, routeName string, - spec json.RawMessage, + spec jsontext.Value, ) (*Route, error) { if err := b.schemas.validate("routeSpec", spec); err != nil { return nil, err diff --git a/services/appmesh/virtual_routers_test.go b/services/appmesh/virtual_routers_test.go index 315941b6ff..2f14f1e1c8 100644 --- a/services/appmesh/virtual_routers_test.go +++ b/services/appmesh/virtual_routers_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/http" "testing" @@ -291,7 +291,7 @@ func TestBackend_UpdateVirtualRouter(t *testing.T) { t.Parallel() b := appmesh.NewInMemoryBackend("000000000000", "us-east-1") tt.setup(b) - vr, err := b.UpdateVirtualRouter(tt.meshName, tt.vrName, json.RawMessage(`{}`)) + vr, err := b.UpdateVirtualRouter(tt.meshName, tt.vrName, jsontext.Value(`{}`)) if tt.wantErr != nil { require.Error(t, err) assert.True(t, appmesh.ErrIs(err, tt.wantErr)) @@ -360,7 +360,7 @@ func TestBackend_UpdateRoute(t *testing.T) { t.Parallel() b := appmesh.NewInMemoryBackend("000000000000", "us-east-1") tt.setup(b) - r, err := b.UpdateRoute(tt.meshName, tt.vrName, tt.routeName, json.RawMessage(`{}`)) + r, err := b.UpdateRoute(tt.meshName, tt.vrName, tt.routeName, jsontext.Value(`{}`)) if tt.wantErr != nil { require.Error(t, err) assert.True(t, appmesh.ErrIs(err, tt.wantErr)) diff --git a/services/appmesh/virtual_services.go b/services/appmesh/virtual_services.go index 09fcdb6464..df8329e0cf 100644 --- a/services/appmesh/virtual_services.go +++ b/services/appmesh/virtual_services.go @@ -1,7 +1,7 @@ package appmesh import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "time" @@ -15,7 +15,7 @@ func (b *InMemoryBackend) virtualServiceARN(meshName, name string) string { //nolint:dupl // create pattern (incl. spec validation call) is structurally identical across resource types func (b *InMemoryBackend) CreateVirtualService( - meshName, name string, spec json.RawMessage, tags map[string]string, + meshName, name string, spec jsontext.Value, tags map[string]string, ) (*VirtualService, error) { b.mu.Lock("CreateVirtualService") defer b.mu.Unlock() @@ -59,7 +59,7 @@ func (b *InMemoryBackend) DescribeVirtualService(meshName, name string) (*Virtua return vs, nil } -func (b *InMemoryBackend) UpdateVirtualService(meshName, name string, spec json.RawMessage) (*VirtualService, error) { +func (b *InMemoryBackend) UpdateVirtualService(meshName, name string, spec jsontext.Value) (*VirtualService, error) { b.mu.Lock("UpdateVirtualService") defer b.mu.Unlock() if err := validateVirtualServiceSpec(spec); err != nil { diff --git a/services/appmesh/virtual_services_test.go b/services/appmesh/virtual_services_test.go index 3e33e7e5a3..0cbce486fd 100644 --- a/services/appmesh/virtual_services_test.go +++ b/services/appmesh/virtual_services_test.go @@ -1,7 +1,7 @@ package appmesh_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/http" "testing" @@ -126,7 +126,7 @@ func TestBackend_UpdateVirtualService(t *testing.T) { t.Parallel() b := appmesh.NewInMemoryBackend("000000000000", "us-east-1") tt.setup(b) - vs, err := b.UpdateVirtualService(tt.meshName, tt.vsName, json.RawMessage(`{}`)) + vs, err := b.UpdateVirtualService(tt.meshName, tt.vsName, jsontext.Value(`{}`)) if tt.wantErr != nil { require.Error(t, err) assert.True(t, appmesh.ErrIs(err, tt.wantErr)) diff --git a/services/apprunner/handler.go b/services/apprunner/handler.go index 6a7ef3fc06..b029f1de20 100644 --- a/services/apprunner/handler.go +++ b/services/apprunner/handler.go @@ -2,7 +2,7 @@ package apprunner import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -192,12 +193,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError switch { case errors.Is(err, awserr.ErrNotFound): @@ -218,8 +217,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyType: invalidRequestType, keyMessage: errMessage(err), diff --git a/services/apprunner/handler_auto_scaling_configurations_test.go b/services/apprunner/handler_auto_scaling_configurations_test.go index 354b147eb1..09ed22698a 100644 --- a/services/apprunner/handler_auto_scaling_configurations_test.go +++ b/services/apprunner/handler_auto_scaling_configurations_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAutoScalingConfigurationCRUD(t *testing.T) { //nolint:paralleltest // existing issue. @@ -27,7 +29,7 @@ func TestAutoScalingConfigurationCRUD(t *testing.T) { //nolint:paralleltest // e check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["AutoScalingConfiguration"].(map[string]any) assert.Contains(t, cfg["AutoScalingConfigurationArn"], "autoscalingconfiguration/my-asg/1/") assert.Equal(t, "ACTIVE", cfg["Status"]) @@ -67,7 +69,7 @@ func TestAutoScalingConfigurationDescribeDeleteList(t *testing.T) { //nolint:par }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) asgArn := createResp["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationArn"].(string) tests := []struct { @@ -85,7 +87,7 @@ func TestAutoScalingConfigurationDescribeDeleteList(t *testing.T) { //nolint:par check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["AutoScalingConfiguration"].(map[string]any) assert.Equal(t, "cfg1", cfg["AutoScalingConfigurationName"]) assert.InDelta(t, float64(50), cfg["MaxConcurrency"], 0.0001) @@ -113,7 +115,7 @@ func TestAutoScalingConfigurationDescribeDeleteList(t *testing.T) { //nolint:par check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["AutoScalingConfigurationSummaryList"].([]any) // cfg1 plus the account's always-present DefaultConfiguration // (see ensureDefaultAutoScalingConfiguration). @@ -128,7 +130,7 @@ func TestAutoScalingConfigurationDescribeDeleteList(t *testing.T) { //nolint:par check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["AutoScalingConfiguration"].(map[string]any) assert.Equal(t, "cfg1", cfg["AutoScalingConfigurationName"]) }, @@ -152,13 +154,13 @@ func TestAutoScalingConfigurationRevisions(t *testing.T) { //nolint:paralleltest rec := doRequest(t, h, "CreateAutoScalingConfiguration", map[string]any{"AutoScalingConfigurationName": "my-asg"}) require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) asgArn1 := r1["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationArn"].(string) rec = doRequest(t, h, "CreateAutoScalingConfiguration", map[string]any{"AutoScalingConfigurationName": "my-asg"}) require.Equal(t, http.StatusOK, rec.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2, jsonx.V1())) rev2 := r2["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationRevision"].(float64) assert.InDelta(t, float64(2), rev2, 0.0001) @@ -169,21 +171,21 @@ func TestAutoScalingConfigurationRevisions(t *testing.T) { //nolint:paralleltest rec = doRequest(t, h, "ListAutoScalingConfigurations", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list := listResp["AutoScalingConfigurationSummaryList"].([]any) // my-asg's latest revision plus DefaultConfiguration. assert.Len(t, list, 2) rec = doRequest(t, h, "ListAutoScalingConfigurations", map[string]any{"LatestOnly": true}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list = listResp["AutoScalingConfigurationSummaryList"].([]any) // my-asg's latest revision plus DefaultConfiguration. assert.Len(t, list, 2) rec = doRequest(t, h, "ListAutoScalingConfigurations", map[string]any{"LatestOnly": false}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list = listResp["AutoScalingConfigurationSummaryList"].([]any) // my-asg's 2 revisions plus the account's always-present // DefaultConfiguration (see ensureDefaultAutoScalingConfiguration). @@ -194,7 +196,7 @@ func TestAutoScalingConfigurationRevisions(t *testing.T) { //nolint:paralleltest }) require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) cfg := updateResp["AutoScalingConfiguration"].(map[string]any) assert.Equal(t, true, cfg["IsDefault"]) } @@ -205,7 +207,7 @@ func TestListServicesForAutoScalingConfiguration(t *testing.T) { //nolint:parall rec := doRequest(t, h, "CreateAutoScalingConfiguration", map[string]any{"AutoScalingConfigurationName": "my-asg"}) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) asgArn := createResp["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationArn"].(string) tests := []struct { @@ -221,7 +223,7 @@ func TestListServicesForAutoScalingConfiguration(t *testing.T) { //nolint:parall check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["ServiceArnList"].([]any) assert.Empty(t, list) }, @@ -264,7 +266,7 @@ func TestDeleteAutoScalingConfiguration_RejectsDefaultAndInUse(t *testing.T) { / rec := doRequest(t, h, "ListAutoScalingConfigurations", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list := listResp["AutoScalingConfigurationSummaryList"].([]any) require.Len(t, list, 1, "only the seeded default configuration should exist yet") defaultArn := list[0].(map[string]any)["AutoScalingConfigurationArn"].(string) @@ -281,7 +283,7 @@ func TestDeleteAutoScalingConfiguration_RejectsDefaultAndInUse(t *testing.T) { / ) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) asgArn := createResp["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -293,7 +295,7 @@ func TestDeleteAutoScalingConfiguration_RejectsDefaultAndInUse(t *testing.T) { / }) require.Equal(t, http.StatusOK, rec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp, jsonx.V1())) svcArn := svcResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DeleteAutoScalingConfiguration", map[string]any{"AutoScalingConfigurationArn": asgArn}) diff --git a/services/apprunner/handler_connections_test.go b/services/apprunner/handler_connections_test.go index 8d19891c2c..b5520453b6 100644 --- a/services/apprunner/handler_connections_test.go +++ b/services/apprunner/handler_connections_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConnectionCRUD(t *testing.T) { //nolint:paralleltest // existing issue. @@ -27,7 +29,7 @@ func TestConnectionCRUD(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) conn := resp["Connection"].(map[string]any) assert.Contains(t, conn["ConnectionArn"], "connection/my-conn/") assert.Equal(t, "AVAILABLE", conn["Status"]) @@ -65,7 +67,7 @@ func TestConnectionDeleteList(t *testing.T) { //nolint:paralleltest // existing rec := doRequest(t, h, "CreateConnection", map[string]any{"ConnectionName": "conn1", "ProviderType": "GITHUB"}) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) connArn := createResp["Connection"].(map[string]any)["ConnectionArn"].(string) doRequest(t, h, "CreateConnection", map[string]any{"ConnectionName": "conn2", "ProviderType": "BITBUCKET"}) @@ -85,7 +87,7 @@ func TestConnectionDeleteList(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["ConnectionSummaryList"].([]any) assert.Len(t, list, 2) }, @@ -98,7 +100,7 @@ func TestConnectionDeleteList(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["ConnectionSummaryList"].([]any) assert.Len(t, list, 1) }, @@ -111,7 +113,7 @@ func TestConnectionDeleteList(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) conn := resp["Connection"].(map[string]any) assert.Equal(t, "conn1", conn["ConnectionName"]) }, @@ -157,7 +159,7 @@ func TestDeleteConnection_RejectsWhenServiceUsesIt(t *testing.T) { rec := doRequest(t, h, "CreateConnection", map[string]any{"ConnectionName": "gh-conn", "ProviderType": "GITHUB"}) require.Equal(t, http.StatusOK, rec.Code) var connResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &connResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &connResp, jsonx.V1())) connArn := connResp["Connection"].(map[string]any)["ConnectionArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -172,7 +174,7 @@ func TestDeleteConnection_RejectsWhenServiceUsesIt(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp, jsonx.V1())) svcArn := svcResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DeleteConnection", map[string]any{"ConnectionArn": connArn}) diff --git a/services/apprunner/handler_custom_domains_test.go b/services/apprunner/handler_custom_domains_test.go index 454337099e..bb00067f58 100644 --- a/services/apprunner/handler_custom_domains_test.go +++ b/services/apprunner/handler_custom_domains_test.go @@ -1,13 +1,15 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCustomDomainAssociateDescribeDisassociate(t *testing.T) { //nolint:paralleltest // existing issue. @@ -32,7 +34,7 @@ func TestCustomDomainAssociateDescribeDisassociate(t *testing.T) { //nolint:para check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cd := resp["CustomDomain"].(map[string]any) assert.Equal(t, "example.com", cd["DomainName"]) assert.Equal(t, "PENDING_CERTIFICATE_DNS_VALIDATION", cd["Status"]) @@ -107,7 +109,7 @@ func TestCustomDomainDescribeAndDisassociate(t *testing.T) { //nolint:parallelte check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) domains := resp["CustomDomains"].([]any) assert.Len(t, domains, 2) assert.NotEmpty(t, resp["ServiceArn"]) @@ -134,7 +136,7 @@ func TestCustomDomainDescribeAndDisassociate(t *testing.T) { //nolint:parallelte check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cd := resp["CustomDomain"].(map[string]any) assert.Equal(t, "example.com", cd["DomainName"]) }, @@ -180,7 +182,7 @@ func TestAssociateCustomDomainDNSTargetIsServiceURL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dnsTarget, ok := resp["DNSTarget"].(string) require.True(t, ok, "AssociateCustomDomain response must include DNSTarget string") @@ -211,7 +213,7 @@ func TestDisassociateCustomDomainDNSTargetIsServiceURL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dnsTarget, ok := resp["DNSTarget"].(string) require.True(t, ok, "DisassociateCustomDomain response must include DNSTarget string") diff --git a/services/apprunner/handler_observability_configurations_test.go b/services/apprunner/handler_observability_configurations_test.go index 23efe7d65c..4341ee4a6d 100644 --- a/services/apprunner/handler_observability_configurations_test.go +++ b/services/apprunner/handler_observability_configurations_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestObservabilityConfigurationCRUD(t *testing.T) { //nolint:paralleltest // existing issue. @@ -30,7 +32,7 @@ func TestObservabilityConfigurationCRUD(t *testing.T) { //nolint:paralleltest // check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["ObservabilityConfiguration"].(map[string]any) assert.Contains(t, cfg["ObservabilityConfigurationArn"], "observabilityconfiguration/my-obs/1/") assert.Equal(t, "ACTIVE", cfg["Status"]) @@ -65,7 +67,7 @@ func TestObservabilityConfigurationDescribeDeleteList(t *testing.T) { //nolint:p }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) obsArn := createResp["ObservabilityConfiguration"].(map[string]any)["ObservabilityConfigurationArn"].(string) tests := []struct { @@ -83,7 +85,7 @@ func TestObservabilityConfigurationDescribeDeleteList(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["ObservabilityConfiguration"].(map[string]any) assert.Equal(t, "obs1", cfg["ObservabilityConfigurationName"]) }, @@ -110,7 +112,7 @@ func TestObservabilityConfigurationDescribeDeleteList(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["ObservabilityConfigurationSummaryList"].([]any) assert.Len(t, list, 1) }, @@ -123,7 +125,7 @@ func TestObservabilityConfigurationDescribeDeleteList(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfg := resp["ObservabilityConfiguration"].(map[string]any) assert.Equal(t, "obs1", cfg["ObservabilityConfigurationName"]) }, @@ -156,7 +158,7 @@ func TestDeleteObservabilityConfiguration_RejectsWhenServiceUsesIt(t *testing.T) }) require.Equal(t, http.StatusOK, rec.Code) var obsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &obsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &obsResp, jsonx.V1())) obsArn := obsResp["ObservabilityConfiguration"].(map[string]any)["ObservabilityConfigurationArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -171,7 +173,7 @@ func TestDeleteObservabilityConfiguration_RejectsWhenServiceUsesIt(t *testing.T) }) require.Equal(t, http.StatusOK, rec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp, jsonx.V1())) svcArn := svcResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DeleteObservabilityConfiguration", map[string]any{"ObservabilityConfigurationArn": obsArn}) @@ -201,26 +203,26 @@ func TestObservabilityConfigurationRevisionsLatestOnlyDefault(t *testing.T) { // ) require.Equal(t, http.StatusOK, rec.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2, jsonx.V1())) rev2 := r2["ObservabilityConfiguration"].(map[string]any)["ObservabilityConfigurationRevision"].(float64) assert.InDelta(t, float64(2), rev2, 0.0001) rec = doRequest(t, h, "ListObservabilityConfigurations", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list := listResp["ObservabilityConfigurationSummaryList"].([]any) assert.Len(t, list, 1) rec = doRequest(t, h, "ListObservabilityConfigurations", map[string]any{"LatestOnly": true}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list = listResp["ObservabilityConfigurationSummaryList"].([]any) assert.Len(t, list, 1) rec = doRequest(t, h, "ListObservabilityConfigurations", map[string]any{"LatestOnly": false}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list = listResp["ObservabilityConfigurationSummaryList"].([]any) assert.Len(t, list, 2) } diff --git a/services/apprunner/handler_operations_test.go b/services/apprunner/handler_operations_test.go index 423c035fff..360b9a45ac 100644 --- a/services/apprunner/handler_operations_test.go +++ b/services/apprunner/handler_operations_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListOperations(t *testing.T) { @@ -22,7 +24,7 @@ func TestListOperations(t *testing.T) { rec := doRequest(t, h, "ListOperations", map[string]any{"ServiceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ops, ok := resp["OperationSummaryList"].([]any) require.True(t, ok) // CREATE + PAUSE + RESUME = 3 operations diff --git a/services/apprunner/handler_services_test.go b/services/apprunner/handler_services_test.go index 92eb4e3bca..cda5d87b7f 100644 --- a/services/apprunner/handler_services_test.go +++ b/services/apprunner/handler_services_test.go @@ -1,13 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apprunner" ) @@ -35,7 +36,7 @@ func TestCreateService_ReturnsServiceArn(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) svc, ok := resp["Service"].(map[string]any) require.True(t, ok) assert.Contains(t, svc["ServiceArn"], "arn:aws:apprunner:us-east-1:000000000000:service/") @@ -77,7 +78,7 @@ func TestServiceCRUD(t *testing.T) { rec := doRequest(t, h, "DescribeService", map[string]any{"ServiceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) svc := descResp["Service"].(map[string]any) assert.Equal(t, "test-service", svc["ServiceName"]) assert.Equal(t, "RUNNING", svc["Status"]) @@ -86,7 +87,7 @@ func TestServiceCRUD(t *testing.T) { rec = doRequest(t, h, "ListServices", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["ServiceSummaryList"], 1) // Delete @@ -109,7 +110,7 @@ func TestPauseResume(t *testing.T) { rec := doRequest(t, h, "PauseService", map[string]any{"ServiceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var pauseResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pauseResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pauseResp, jsonx.V1())) svc := pauseResp["Service"].(map[string]any) assert.Equal(t, "PAUSED", svc["Status"]) @@ -117,7 +118,7 @@ func TestPauseResume(t *testing.T) { rec = doRequest(t, h, "ResumeService", map[string]any{"ServiceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var resumeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resumeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resumeResp, jsonx.V1())) svc = resumeResp["Service"].(map[string]any) assert.Equal(t, "RUNNING", svc["Status"]) } @@ -131,7 +132,7 @@ func TestStartDeployment(t *testing.T) { rec := doRequest(t, h, "StartDeployment", map[string]any{"ServiceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["OperationId"]) } @@ -150,7 +151,7 @@ func TestUpdateService(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["OperationId"]) } @@ -161,7 +162,7 @@ func TestListServices_Empty(t *testing.T) { rec := doRequest(t, h, "ListServices", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["ServiceSummaryList"].([]any) require.True(t, ok) assert.Empty(t, services) @@ -201,7 +202,7 @@ func TestPauseService_StateGuard(t *testing.T) { //nolint:paralleltest // existi assert.Equal(t, tc.wantCode, rec.Code) if tc.wantType != "" { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tc.wantType, body["__type"]) } }) @@ -242,7 +243,7 @@ func TestResumeService_StateGuard(t *testing.T) { //nolint:paralleltest // exist assert.Equal(t, tc.wantCode, rec.Code) if tc.wantType != "" { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tc.wantType, body["__type"]) } }) @@ -286,7 +287,7 @@ func TestUpdateService_StateGuard(t *testing.T) { //nolint:paralleltest // exist assert.Equal(t, tc.wantCode, rec.Code) if tc.wantType != "" { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tc.wantType, body["__type"]) } }) @@ -333,7 +334,7 @@ func TestStartDeployment_StateGuard(t *testing.T) { //nolint:paralleltest // exi assert.Equal(t, tc.wantCode, rec.Code) if tc.wantType != "" { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tc.wantType, body["__type"]) } }) @@ -363,14 +364,14 @@ func TestServiceOutputInstanceConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) svcArn := createResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DescribeService", map[string]any{"ServiceArn": svcArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) svc := descResp["Service"].(map[string]any) ic, ok := svc["InstanceConfiguration"].(map[string]any) @@ -398,14 +399,14 @@ func TestServiceOutputSourceConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) svcArn := createResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DescribeService", map[string]any{"ServiceArn": svcArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) svc := descResp["Service"].(map[string]any) sc, ok := svc["SourceConfiguration"].(map[string]any) @@ -436,14 +437,14 @@ func TestDefaultInstanceConfigurationPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) svcArn := createResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DescribeService", map[string]any{"ServiceArn": svcArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) svc := descResp["Service"].(map[string]any) ic, ok := svc["InstanceConfiguration"].(map[string]any) @@ -474,7 +475,7 @@ func TestCreateService_InstanceRoleArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ic := resp["Service"].(map[string]any)["InstanceConfiguration"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/my-role", ic["InstanceRoleArn"]) } @@ -499,7 +500,7 @@ func TestCreateService_EncryptionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) enc, ok := resp["Service"].(map[string]any)["EncryptionConfiguration"].(map[string]any) require.True(t, ok, "EncryptionConfiguration must be present when a KmsKey was provided") assert.Equal(t, "arn:aws:kms:us-east-1:000000000000:key/abc", enc["KmsKey"]) @@ -515,7 +516,7 @@ func TestCreateService_EncryptionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, present := resp["Service"].(map[string]any)["EncryptionConfiguration"] assert.False(t, present, "EncryptionConfiguration must be absent when no KmsKey was provided") }) @@ -537,7 +538,7 @@ func TestCreateService_AutoScalingConfigurationAssociation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var asgResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &asgResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &asgResp, jsonx.V1())) asgArn := asgResp["AutoScalingConfiguration"].(map[string]any)["AutoScalingConfigurationArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -550,7 +551,7 @@ func TestCreateService_AutoScalingConfigurationAssociation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) svc := createResp["Service"].(map[string]any) svcArn := svc["ServiceArn"].(string) summary := svc["AutoScalingConfigurationSummary"].(map[string]any) @@ -563,7 +564,7 @@ func TestCreateService_AutoScalingConfigurationAssociation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) arns := listResp["ServiceArnList"].([]any) require.Len(t, arns, 1) assert.Equal(t, svcArn, arns[0]) @@ -575,7 +576,7 @@ func TestCreateService_AutoScalingConfigurationAssociation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) cfg := descResp["AutoScalingConfiguration"].(map[string]any) assert.Equal(t, false, cfg["HasAssociatedService"]) @@ -583,7 +584,7 @@ func TestCreateService_AutoScalingConfigurationAssociation(t *testing.T) { "AutoScalingConfigurationArn": asgArn, }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp["ServiceArnList"]) } @@ -600,7 +601,7 @@ func TestCreateService_DefaultAutoScalingConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary := resp["Service"].(map[string]any)["AutoScalingConfigurationSummary"].(map[string]any) assert.Equal(t, "DefaultConfiguration", summary["AutoScalingConfigurationName"]) assert.Equal(t, true, summary["IsDefault"]) @@ -625,7 +626,7 @@ func TestCreateService_UnknownAutoScalingConfigurationArn(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidRequestException", body["__type"]) } @@ -685,7 +686,7 @@ func TestCreateService_NetworkConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nc := resp["Service"].(map[string]any)["NetworkConfiguration"].(map[string]any) assert.Equal(t, "IPV4", nc["IpAddressType"]) assert.Equal(t, "DEFAULT", nc["EgressConfiguration"].(map[string]any)["EgressType"]) @@ -704,7 +705,7 @@ func TestCreateService_NetworkConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var vcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vcResp, jsonx.V1())) vcArn := vcResp["VpcConnector"].(map[string]any)["VpcConnectorArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -720,7 +721,7 @@ func TestCreateService_NetworkConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) nc := createResp["Service"].(map[string]any)["NetworkConfiguration"].(map[string]any) assert.Equal(t, "VPC", nc["EgressConfiguration"].(map[string]any)["EgressType"]) assert.Equal(t, vcArn, nc["EgressConfiguration"].(map[string]any)["VpcConnectorArn"]) @@ -764,7 +765,7 @@ func TestCreateService_HealthCheckConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hc := resp["Service"].(map[string]any)["HealthCheckConfiguration"].(map[string]any) assert.Equal(t, "TCP", hc["Protocol"]) assert.Equal(t, "/", hc["Path"]) @@ -796,7 +797,7 @@ func TestCreateService_HealthCheckConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) hc := createResp["Service"].(map[string]any)["HealthCheckConfiguration"].(map[string]any) assert.Equal(t, "HTTP", hc["Protocol"]) assert.Equal(t, "/healthz", hc["Path"]) @@ -822,7 +823,7 @@ func TestCreateService_ObservabilityConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var obsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &obsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &obsResp, jsonx.V1())) obsArn := obsResp["ObservabilityConfiguration"].(map[string]any)["ObservabilityConfigurationArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -838,7 +839,7 @@ func TestCreateService_ObservabilityConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) oc := createResp["Service"].(map[string]any)["ObservabilityConfiguration"].(map[string]any) assert.Equal(t, true, oc["ObservabilityEnabled"]) assert.Equal(t, obsArn, oc["ObservabilityConfigurationArn"]) @@ -884,7 +885,7 @@ func TestCreateService_CodeRepository(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var connResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &connResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &connResp, jsonx.V1())) connArn := connResp["Connection"].(map[string]any)["ConnectionArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -908,7 +909,7 @@ func TestCreateService_CodeRepository(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) sc := createResp["Service"].(map[string]any)["SourceConfiguration"].(map[string]any) cr := sc["CodeRepository"].(map[string]any) assert.Equal(t, "https://github.com/example/repo", cr["RepositoryUrl"]) @@ -962,7 +963,7 @@ func TestUpdateService_CannotSwitchSourceType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidRequestException", body["__type"]) } @@ -978,7 +979,7 @@ func TestListOperations_UpdatedAtPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ops := resp["OperationSummaryList"].([]any) require.NotEmpty(t, ops) @@ -1008,7 +1009,7 @@ func TestDeleteService_RejectsWhenActiveVpcIngressConnectionExists(t *testing.T) }) require.Equal(t, http.StatusOK, rec.Code) var vicResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vicResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vicResp, jsonx.V1())) vicArn := vicResp["VpcIngressConnection"].(map[string]any)["VpcIngressConnectionArn"].(string) rec = doRequest(t, h, "DeleteService", map[string]any{"ServiceArn": svcArn}) @@ -1017,7 +1018,7 @@ func TestDeleteService_RejectsWhenActiveVpcIngressConnectionExists(t *testing.T) ) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidStateException", body["__type"]) rec = doRequest(t, h, "DeleteVpcIngressConnection", map[string]any{"VpcIngressConnectionArn": vicArn}) diff --git a/services/apprunner/handler_tags_test.go b/services/apprunner/handler_tags_test.go index 34ebfbdce8..05f82d5259 100644 --- a/services/apprunner/handler_tags_test.go +++ b/services/apprunner/handler_tags_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags(t *testing.T) { @@ -29,7 +31,7 @@ func TestTags(t *testing.T) { rec = doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": svcArn}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 2) @@ -43,7 +45,7 @@ func TestTags(t *testing.T) { // Verify untag rec = doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": svcArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags = listResp["Tags"].([]any) assert.Len(t, tags, 1) } diff --git a/services/apprunner/handler_test.go b/services/apprunner/handler_test.go index 94e6e97b69..d1b1c2b789 100644 --- a/services/apprunner/handler_test.go +++ b/services/apprunner/handler_test.go @@ -2,7 +2,7 @@ package apprunner_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apprunner" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *apprunner.Handler, action string, body any) *htt if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -60,7 +61,7 @@ func createTestService(t *testing.T, h *apprunner.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc, ok := resp["Service"].(map[string]any) require.True(t, ok) diff --git a/services/apprunner/handler_vpc_connectors_test.go b/services/apprunner/handler_vpc_connectors_test.go index cb57c7adba..a69461850a 100644 --- a/services/apprunner/handler_vpc_connectors_test.go +++ b/services/apprunner/handler_vpc_connectors_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestVpcConnectorCRUD(t *testing.T) { //nolint:paralleltest // existing issue. @@ -31,7 +33,7 @@ func TestVpcConnectorCRUD(t *testing.T) { //nolint:paralleltest // existing issu check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vc := resp["VpcConnector"].(map[string]any) assert.Contains(t, vc["VpcConnectorArn"], "vpcconnector/my-vpc/1/") assert.Equal(t, "ACTIVE", vc["Status"]) @@ -74,7 +76,7 @@ func TestVpcConnectorDescribeDeleteList(t *testing.T) { //nolint:paralleltest // }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) vcArn := createResp["VpcConnector"].(map[string]any)["VpcConnectorArn"].(string) tests := []struct { @@ -92,7 +94,7 @@ func TestVpcConnectorDescribeDeleteList(t *testing.T) { //nolint:paralleltest // check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vc := resp["VpcConnector"].(map[string]any) assert.Equal(t, "vc1", vc["VpcConnectorName"]) }, @@ -119,7 +121,7 @@ func TestVpcConnectorDescribeDeleteList(t *testing.T) { //nolint:paralleltest // check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["VpcConnectors"].([]any) assert.Len(t, list, 1) }, @@ -132,7 +134,7 @@ func TestVpcConnectorDescribeDeleteList(t *testing.T) { //nolint:paralleltest // check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vc := resp["VpcConnector"].(map[string]any) assert.Equal(t, "vc1", vc["VpcConnectorName"]) }, @@ -180,7 +182,7 @@ func TestDeleteVpcConnector_RejectsWhenServiceUsesIt(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var vcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vcResp, jsonx.V1())) vcArn := vcResp["VpcConnector"].(map[string]any)["VpcConnectorArn"].(string) rec = doRequest(t, h, "CreateService", map[string]any{ @@ -194,7 +196,7 @@ func TestDeleteVpcConnector_RejectsWhenServiceUsesIt(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &svcResp, jsonx.V1())) svcArn := svcResp["Service"].(map[string]any)["ServiceArn"].(string) rec = doRequest(t, h, "DeleteVpcConnector", map[string]any{"VpcConnectorArn": vcArn}) diff --git a/services/apprunner/handler_vpc_ingress_connections_test.go b/services/apprunner/handler_vpc_ingress_connections_test.go index f6d1a80aa2..3dd396a596 100644 --- a/services/apprunner/handler_vpc_ingress_connections_test.go +++ b/services/apprunner/handler_vpc_ingress_connections_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestVpcIngressConnectionCRUD(t *testing.T) { //nolint:paralleltest // existing issue. @@ -35,7 +37,7 @@ func TestVpcIngressConnectionCRUD(t *testing.T) { //nolint:paralleltest // exist check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vic := resp["VpcIngressConnection"].(map[string]any) assert.Contains(t, vic["VpcIngressConnectionArn"], "vpcingressconnection/my-vic/") assert.Equal(t, "AVAILABLE", vic["Status"]) @@ -80,7 +82,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p }) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) vicArn := createResp["VpcIngressConnection"].(map[string]any)["VpcIngressConnectionArn"].(string) tests := []struct { @@ -98,7 +100,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vic := resp["VpcIngressConnection"].(map[string]any) assert.Equal(t, "vic1", vic["VpcIngressConnectionName"]) }, @@ -125,7 +127,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["VpcIngressConnectionSummaryList"].([]any) assert.Len(t, list, 1) }, @@ -138,7 +140,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["VpcIngressConnectionSummaryList"].([]any) assert.Len(t, list, 1) }, @@ -155,7 +157,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["VpcIngressConnectionSummaryList"].([]any) assert.Len(t, list, 1) }, @@ -168,7 +170,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) list := resp["VpcIngressConnectionSummaryList"].([]any) assert.Empty(t, list) }, @@ -187,7 +189,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vic := resp["VpcIngressConnection"].(map[string]any) ivc := vic["IngressVpcConfiguration"].(map[string]any) assert.Equal(t, "vpc-new", ivc["VpcId"]) @@ -207,7 +209,7 @@ func TestVpcIngressConnectionDescribeDeleteListUpdate(t *testing.T) { //nolint:p check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) vic := resp["VpcIngressConnection"].(map[string]any) assert.Equal(t, "vic1", vic["VpcIngressConnectionName"]) }, diff --git a/services/apprunner/multi_region_test.go b/services/apprunner/multi_region_test.go index eab901d70a..fd82d8d173 100644 --- a/services/apprunner/multi_region_test.go +++ b/services/apprunner/multi_region_test.go @@ -2,7 +2,7 @@ package apprunner_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apprunner" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/apprunner/observability_configuration_summary_wire_test.go b/services/apprunner/observability_configuration_summary_wire_test.go index 438c70b171..3676d98a5e 100644 --- a/services/apprunner/observability_configuration_summary_wire_test.go +++ b/services/apprunner/observability_configuration_summary_wire_test.go @@ -1,7 +1,7 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apprunner" ) @@ -36,7 +37,7 @@ func TestListObservabilityConfigurations_SummaryHasNoFabricatedFields(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["ObservabilityConfigurationSummaryList"].([]any) require.True(t, ok) diff --git a/services/apprunner/persistence.go b/services/apprunner/persistence.go index 610a54ea40..cac2ba732e 100644 --- a/services/apprunner/persistence.go +++ b/services/apprunner/persistence.go @@ -2,7 +2,7 @@ package apprunner import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -37,7 +37,7 @@ const apprunnerSnapshotVersion = 1 // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` CustomDomains map[string][]*storedCustomDomain `json:"customDomains"` Tags map[string]map[string]string `json:"tags"` Version int `json:"version"` diff --git a/services/apprunner/vpc_ingress_service_arn_test.go b/services/apprunner/vpc_ingress_service_arn_test.go index 15ea8eb15e..d806d16a06 100644 --- a/services/apprunner/vpc_ingress_service_arn_test.go +++ b/services/apprunner/vpc_ingress_service_arn_test.go @@ -1,12 +1,14 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateVpcIngressConnection_ServiceMustExist(t *testing.T) { @@ -42,7 +44,7 @@ func TestCreateVpcIngressConnection_ServiceMustExist(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["__type"], tt.wantType) } }) diff --git a/services/apprunner/wire_output_required_r80d_test.go b/services/apprunner/wire_output_required_r80d_test.go index f19589e0d3..a612ab6096 100644 --- a/services/apprunner/wire_output_required_r80d_test.go +++ b/services/apprunner/wire_output_required_r80d_test.go @@ -1,7 +1,7 @@ package apprunner_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/apprunner" ) @@ -77,7 +78,7 @@ func Test_CodeRepository_SourceCodeVersion_Required(t *testing.T) { ServiceArn string `json:"ServiceArn"` } `json:"Service"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) rec = doRequest(t, h, "DescribeService", map[string]any{ "ServiceArn": createOut.Service.ServiceArn, @@ -95,7 +96,7 @@ func Test_CodeRepository_SourceCodeVersion_Required(t *testing.T) { } `json:"SourceConfiguration"` } `json:"Service"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.Service.SourceConfiguration.CodeRepository.SourceCodeVersion) assert.Equal(t, "main", descOut.Service.SourceConfiguration.CodeRepository.SourceCodeVersion.Value) } diff --git a/services/appstream/app_blocks_test.go b/services/appstream/app_blocks_test.go index f28280c40c..75956703ec 100644 --- a/services/appstream/app_blocks_test.go +++ b/services/appstream/app_blocks_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -37,7 +38,7 @@ func TestAppStream_AppBlocks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ab := resp["AppBlock"].(map[string]any) assert.Equal(t, "my-block", ab["Name"]) assert.Contains(t, ab["Arn"], ":app-block/my-block") @@ -73,7 +74,7 @@ func TestAppStream_AppBlocks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) blocks := resp["AppBlocks"].([]any) assert.Len(t, blocks, 2) }, @@ -136,7 +137,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bb := resp["AppBlockBuilder"].(map[string]any) assert.Equal(t, "my-builder", bb["Name"]) assert.Equal(t, "STOPPED", bb["State"]) @@ -162,7 +163,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bb := resp["AppBlockBuilder"].(map[string]any) assert.Equal(t, "RUNNING", bb["State"]) }, @@ -180,7 +181,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bb := resp["AppBlockBuilder"].(map[string]any) assert.Equal(t, "STOPPED", bb["State"]) }, @@ -196,7 +197,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bb := resp["AppBlockBuilder"].(map[string]any) assert.Equal(t, "STOPPED", bb["State"]) }, @@ -212,7 +213,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bb := resp["AppBlockBuilder"].(map[string]any) assert.Equal(t, "updated", bb["Description"]) }, @@ -228,7 +229,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.NotEmpty(t, resp["StreamingURL"]) assert.NotEmpty(t, resp["Expires"]) }, @@ -263,7 +264,7 @@ func TestAppStream_AppBlockBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assocs := resp["AppBlockBuilderAppBlockAssociations"].([]any) assert.Len(t, assocs, 1) }, @@ -307,7 +308,7 @@ func TestAppStream_AppBlockARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ab := resp["AppBlock"].(map[string]any) assert.Contains(t, ab["Arn"], "arn:aws:appstream:") assert.Contains(t, ab["Arn"], "app-block/arn-appblock") @@ -330,7 +331,7 @@ func TestAppStream_AppBlockBuilderStreamingURL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["StreamingURL"]) assert.NotEmpty(t, resp["Expires"]) } @@ -355,7 +356,7 @@ func TestAppStream_DeleteAppBlock_InUseByApplication(t *testing.T) { require.Equal(t, http.StatusOK, abRec.Code) var abResp map[string]any - require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp)) + require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp, jsonx.V1())) ab := abResp["AppBlock"].(map[string]any) appRec := doRequest(t, h, "CreateApplication", map[string]any{ diff --git a/services/appstream/applications_test.go b/services/appstream/applications_test.go index 09f9a394e4..42b5d65afa 100644 --- a/services/appstream/applications_test.go +++ b/services/appstream/applications_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -40,7 +41,7 @@ func TestAppStream_Applications(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) app := resp["Application"].(map[string]any) assert.Equal(t, "my-app", app["Name"]) assert.Contains(t, app["Arn"], ":application/my-app") @@ -75,7 +76,7 @@ func TestAppStream_Applications(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) apps := resp["Applications"].([]any) assert.Len(t, apps, 2) }, @@ -91,7 +92,7 @@ func TestAppStream_Applications(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) app := resp["Application"].(map[string]any) assert.Equal(t, "Updated App", app["DisplayName"]) }, @@ -113,7 +114,7 @@ func TestAppStream_Applications(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) usages, ok := resp["AppLicenseUsages"] require.True(t, ok, "response must carry AppLicenseUsages") assert.Empty(t, usages) @@ -167,7 +168,7 @@ func TestAppStream_Applications(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assocs := resp["ApplicationFleetAssociations"].([]any) assert.Len(t, assocs, 1) }, @@ -262,7 +263,7 @@ func TestAppStream_CreateApplication_RequiredMembersRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) app := createOut["Application"].(map[string]any) icon, ok := app["IconS3Location"].(map[string]any) @@ -275,7 +276,7 @@ func TestAppStream_CreateApplication_RequiredMembersRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) apps := descOut["Applications"].([]any) require.Len(t, apps, 1) got := apps[0].(map[string]any) @@ -304,7 +305,7 @@ func TestAppStream_ApplicationARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) app := resp["Application"].(map[string]any) assert.Contains(t, app["Arn"], "arn:aws:appstream:") assert.Contains(t, app["Arn"], "application/arn-app") diff --git a/services/appstream/directory_configs_test.go b/services/appstream/directory_configs_test.go index 7d27954a04..81ae0fd6b7 100644 --- a/services/appstream/directory_configs_test.go +++ b/services/appstream/directory_configs_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -34,7 +35,7 @@ func TestAppStream_DirectoryConfigs(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) dc := resp["DirectoryConfig"].(map[string]any) assert.Equal(t, "corp.example.com", dc["DirectoryName"]) }, @@ -51,7 +52,7 @@ func TestAppStream_DirectoryConfigs(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) dcs := resp["DirectoryConfigs"].([]any) assert.Len(t, dcs, 1) }, @@ -122,7 +123,7 @@ func TestAppStream_DirectoryConfigRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp, jsonx.V1())) configs := resp["DirectoryConfigs"].([]any) require.Len(t, configs, 1) dc := configs[0].(map[string]any) @@ -154,7 +155,7 @@ func TestAppStream_DirectoryConfigServiceAccountCredentials(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) dc := createResp["DirectoryConfig"].(map[string]any) cred := dc["ServiceAccountCredentials"].(map[string]any) @@ -174,7 +175,7 @@ func TestAppStream_DirectoryConfigServiceAccountCredentials(t *testing.T) { require.Equal(t, http.StatusOK, recUpd.Code) var updResp map[string]any - require.NoError(t, json.Unmarshal(recUpd.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(recUpd.Body.Bytes(), &updResp, jsonx.V1())) updDC := updResp["DirectoryConfig"].(map[string]any) updCred := updDC["ServiceAccountCredentials"].(map[string]any) assert.Equal(t, "svc-account-2", updCred["AccountName"]) diff --git a/services/appstream/entitlements_test.go b/services/appstream/entitlements_test.go index 8b88b2a9ae..4b884009fa 100644 --- a/services/appstream/entitlements_test.go +++ b/services/appstream/entitlements_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -38,7 +39,7 @@ func TestAppStream_Entitlements(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ent := resp["Entitlement"].(map[string]any) assert.Equal(t, "my-ent", ent["Name"]) assert.Equal(t, "ALL", ent["AppVisibility"]) @@ -63,7 +64,7 @@ func TestAppStream_Entitlements(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ents := resp["Entitlements"].([]any) assert.Len(t, ents, 1) }, @@ -84,7 +85,7 @@ func TestAppStream_Entitlements(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ent := resp["Entitlement"].(map[string]any) assert.Equal(t, "updated", ent["Description"]) }, @@ -137,7 +138,7 @@ func TestAppStream_Entitlements(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) apps := resp["EntitledApplications"].([]any) assert.Len(t, apps, 1) }, @@ -206,7 +207,7 @@ func TestAppStream_EntitlementRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp, jsonx.V1())) entitlements := resp["Entitlements"].([]any) require.Len(t, entitlements, 1) ent := entitlements[0].(map[string]any) diff --git a/services/appstream/fleets_test.go b/services/appstream/fleets_test.go index ed9920fbf2..6a057d8649 100644 --- a/services/appstream/fleets_test.go +++ b/services/appstream/fleets_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -34,7 +35,7 @@ func TestAppStream_Fleets(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, "my-fleet", fleet["Name"]) assert.Equal(t, "STOPPED", fleet["State"]) @@ -64,7 +65,7 @@ func TestAppStream_Fleets(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) fleets := resp["Fleets"].([]any) assert.Len(t, fleets, 1) }, @@ -124,7 +125,7 @@ func TestAppStream_Fleets(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, "stream.compute.large", fleet["InstanceType"]) }, @@ -190,7 +191,7 @@ func TestAppStream_Associations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) names := resp["Names"].([]any) assert.Len(t, names, 1) assert.Equal(t, "fleet-2", names[0]) @@ -209,7 +210,7 @@ func TestAppStream_Associations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) names := resp["Names"].([]any) assert.Len(t, names, 1) assert.Equal(t, "stack-3", names[0]) @@ -377,7 +378,7 @@ func TestAppStream_FleetErrorCodes(t *testing.T) { if tc.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"], "wrong __type in error response") } }) @@ -400,7 +401,7 @@ func TestAppStream_FleetComputeCapacityStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) ccs, ok := fleet["ComputeCapacityStatus"].(map[string]any) @@ -426,7 +427,7 @@ func TestAppStream_FleetComputeCapacityStatus(t *testing.T) { require.Equal(t, http.StatusOK, recD.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(recD.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(recD.Body.Bytes(), &dr, jsonx.V1())) fleets := dr["Fleets"].([]any) require.Len(t, fleets, 1) f := fleets[0].(map[string]any) @@ -449,7 +450,7 @@ func TestAppStream_FleetComputeCapacityStatusDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) ccs, ok := fleet["ComputeCapacityStatus"].(map[string]any) @@ -473,7 +474,7 @@ func TestAppStream_FleetImageNameRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, "AppStream-WinServer2019-05-01-2023", fleet["ImageName"]) } @@ -493,7 +494,7 @@ func TestAppStream_FleetImageArnRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, imageArn, fleet["ImageArn"]) } @@ -512,7 +513,7 @@ func TestAppStream_FleetIdleDisconnectTimeout(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.EqualValues(t, 600, fleet["IdleDisconnectTimeoutInSeconds"]) } @@ -531,7 +532,7 @@ func TestAppStream_FleetEnableDefaultInternetAccess(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, true, fleet["EnableDefaultInternetAccess"]) } @@ -554,7 +555,7 @@ func TestAppStream_FleetUpdateImageName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, "new-image", fleet["ImageName"]) } @@ -578,7 +579,7 @@ func TestAppStream_FleetUpdateComputeCapacity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) ccs := fleet["ComputeCapacityStatus"].(map[string]any) assert.EqualValues(t, 5, ccs["Desired"]) @@ -597,7 +598,7 @@ func TestAppStream_FleetARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Regexp(t, `^arn:aws:appstream:[a-z0-9-]+:\d+:fleet/arn-fleet$`, fleet["Arn"]) } @@ -617,7 +618,7 @@ func TestAppStream_FleetDefaultsMatchAWS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleet"].(map[string]any) assert.Equal(t, "ON_DEMAND", fleet["FleetType"]) assert.EqualValues(t, 57600, fleet["MaxUserDurationInSeconds"]) @@ -639,7 +640,7 @@ func TestAppStream_FleetStartedStateRunning(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fleet := resp["Fleets"].([]any)[0].(map[string]any) assert.Equal(t, "RUNNING", fleet["State"]) } @@ -669,6 +670,6 @@ func TestAppStream_DeleteFleet_ClearsAssociations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Names"], "re-created fleet must not inherit the deleted fleet's stack associations") } diff --git a/services/appstream/handler.go b/services/appstream/handler.go index feb4e93923..a5608ebbaf 100644 --- a/services/appstream/handler.go +++ b/services/appstream/handler.go @@ -2,7 +2,7 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -155,7 +156,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // errorCodeStatus maps a backend error to the AWS exception name and HTTP @@ -657,7 +658,7 @@ type createStackInput struct { func (h *Handler) opCreateStack(_ context.Context, body []byte) (any, error) { var req createStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -701,7 +702,7 @@ type describeStacksInput struct { func (h *Handler) opDescribeStacks(_ context.Context, body []byte) (any, error) { var req describeStacksInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -744,7 +745,7 @@ type updateStackInput struct { func (h *Handler) opUpdateStack(_ context.Context, body []byte) (any, error) { var req updateStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -781,7 +782,7 @@ type deleteStackInput struct { func (h *Handler) opDeleteStack(_ context.Context, body []byte) (any, error) { var req deleteStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -879,7 +880,7 @@ type createFleetInput struct { func (h *Handler) opCreateFleet(_ context.Context, body []byte) (any, error) { var req createFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -928,7 +929,7 @@ type describeFleetsInput struct { func (h *Handler) opDescribeFleets(_ context.Context, body []byte) (any, error) { var req describeFleetsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -980,7 +981,7 @@ type updateFleetInput struct { func (h *Handler) opUpdateFleet(_ context.Context, body []byte) (any, error) { var req updateFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1030,7 +1031,7 @@ type deleteFleetInput struct { func (h *Handler) opDeleteFleet(_ context.Context, body []byte) (any, error) { var req deleteFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1047,7 +1048,7 @@ type fleetNameInput struct { func (h *Handler) opStartFleet(_ context.Context, body []byte) (any, error) { var req fleetNameInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1060,7 +1061,7 @@ func (h *Handler) opStartFleet(_ context.Context, body []byte) (any, error) { func (h *Handler) opStopFleet(_ context.Context, body []byte) (any, error) { var req fleetNameInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1080,7 +1081,7 @@ type associateFleetInput struct { func (h *Handler) opAssociateFleet(_ context.Context, body []byte) (any, error) { var req associateFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1093,7 +1094,7 @@ func (h *Handler) opAssociateFleet(_ context.Context, body []byte) (any, error) func (h *Handler) opDisassociateFleet(_ context.Context, body []byte) (any, error) { var req associateFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1111,7 +1112,7 @@ type listAssociatedFleetsInput struct { func (h *Handler) opListAssociatedFleets(_ context.Context, body []byte) (any, error) { var req listAssociatedFleetsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1135,7 +1136,7 @@ type listAssociatedStacksInput struct { func (h *Handler) opListAssociatedStacks(_ context.Context, body []byte) (any, error) { var req listAssociatedStacksInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1161,7 +1162,7 @@ type tagResourceInput struct { func (h *Handler) opTagResource(_ context.Context, body []byte) (any, error) { var req tagResourceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1180,7 +1181,7 @@ type untagResourceInput struct { func (h *Handler) opUntagResource(_ context.Context, body []byte) (any, error) { var req untagResourceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -1197,7 +1198,7 @@ type listTagsForResourceInput struct { func (h *Handler) opListTagsForResource(_ context.Context, body []byte) (any, error) { var req listTagsForResourceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } diff --git a/services/appstream/handler_appblock.go b/services/appstream/handler_appblock.go index d813f591af..3ef409d084 100644 --- a/services/appstream/handler_appblock.go +++ b/services/appstream/handler_appblock.go @@ -2,11 +2,12 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- AppBlock handlers --- @@ -54,7 +55,7 @@ type createAppBlockInput struct { func (h *Handler) opCreateAppBlock(_ context.Context, body []byte) (any, error) { var req createAppBlockInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -79,7 +80,7 @@ type deleteAppBlockInput struct { func (h *Handler) opDeleteAppBlock(_ context.Context, body []byte) (any, error) { var req deleteAppBlockInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -98,7 +99,7 @@ type describeAppBlocksInput struct { func (h *Handler) opDescribeAppBlocks(_ context.Context, body []byte) (any, error) { var req describeAppBlocksInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -144,7 +145,7 @@ type createAppBlockBuilderInput struct { func (h *Handler) opCreateAppBlockBuilder(_ context.Context, body []byte) (any, error) { var req createAppBlockBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -177,7 +178,7 @@ type deleteAppBlockBuilderInput struct { func (h *Handler) opDeleteAppBlockBuilder(_ context.Context, body []byte) (any, error) { var req deleteAppBlockBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -196,7 +197,7 @@ type describeAppBlockBuildersInput struct { func (h *Handler) opDescribeAppBlockBuilders(_ context.Context, body []byte) (any, error) { var req describeAppBlockBuildersInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -225,7 +226,7 @@ type appBlockBuilderNameInput struct { func (h *Handler) opStartAppBlockBuilder(_ context.Context, body []byte) (any, error) { var req appBlockBuilderNameInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -243,7 +244,7 @@ func (h *Handler) opStartAppBlockBuilder(_ context.Context, body []byte) (any, e func (h *Handler) opStopAppBlockBuilder(_ context.Context, body []byte) (any, error) { var req appBlockBuilderNameInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -275,7 +276,7 @@ type updateAppBlockBuilderInput struct { func (h *Handler) opUpdateAppBlockBuilder(_ context.Context, body []byte) (any, error) { var req updateAppBlockBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -317,7 +318,7 @@ type createAppBlockBuilderStreamingURLInput struct { func (h *Handler) opCreateAppBlockBuilderStreamingURL(_ context.Context, body []byte) (any, error) { var req createAppBlockBuilderStreamingURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -341,7 +342,7 @@ type appBlockBuilderAppBlockInput struct { func (h *Handler) opAssociateAppBlockBuilderAppBlock(_ context.Context, body []byte) (any, error) { var req appBlockBuilderAppBlockInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -358,7 +359,7 @@ func (h *Handler) opAssociateAppBlockBuilderAppBlock(_ context.Context, body []b func (h *Handler) opDisassociateAppBlockBuilderAppBlock(_ context.Context, body []byte) (any, error) { var req appBlockBuilderAppBlockInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -378,7 +379,7 @@ type describeAppBlockBuilderAppBlockAssociationsInput struct { func (h *Handler) opDescribeAppBlockBuilderAppBlockAssociations(_ context.Context, body []byte) (any, error) { var req describeAppBlockBuilderAppBlockAssociationsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } diff --git a/services/appstream/handler_application.go b/services/appstream/handler_application.go index cbccb591ec..bcecf9a833 100644 --- a/services/appstream/handler_application.go +++ b/services/appstream/handler_application.go @@ -2,11 +2,12 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Application handlers --- @@ -46,7 +47,7 @@ type createApplicationInput struct { func (h *Handler) opCreateApplication(_ context.Context, body []byte) (any, error) { var req createApplicationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -68,7 +69,7 @@ type deleteApplicationInput struct { func (h *Handler) opDeleteApplication(_ context.Context, body []byte) (any, error) { var req deleteApplicationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -87,7 +88,7 @@ type describeApplicationsInput struct { func (h *Handler) opDescribeApplications(_ context.Context, body []byte) (any, error) { var req describeApplicationsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -124,7 +125,7 @@ type updateApplicationInput struct { func (h *Handler) opUpdateApplication(_ context.Context, body []byte) (any, error) { var req updateApplicationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -153,7 +154,7 @@ func (h *Handler) opUpdateApplication(_ context.Context, body []byte) (any, erro func (h *Handler) opDescribeAppLicenseUsage(_ context.Context, body []byte) (any, error) { var req pageReq if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -186,7 +187,7 @@ type applicationFleetInput struct { func (h *Handler) opAssociateApplicationFleet(_ context.Context, body []byte) (any, error) { var req applicationFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -203,7 +204,7 @@ func (h *Handler) opAssociateApplicationFleet(_ context.Context, body []byte) (a func (h *Handler) opDisassociateApplicationFleet(_ context.Context, body []byte) (any, error) { var req applicationFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -223,7 +224,7 @@ type describeApplicationFleetAssociationsInput struct { func (h *Handler) opDescribeApplicationFleetAssociations(_ context.Context, body []byte) (any, error) { var req describeApplicationFleetAssociationsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -273,7 +274,7 @@ func toEntitlementAttributes(attrs []entitlementAttributeJSON) []EntitlementAttr func (h *Handler) opCreateEntitlement(_ context.Context, body []byte) (any, error) { var req createEntitlementInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -295,7 +296,7 @@ type deleteEntitlementInput struct { func (h *Handler) opDeleteEntitlement(_ context.Context, body []byte) (any, error) { var req deleteEntitlementInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -315,7 +316,7 @@ type describeEntitlementsInput struct { func (h *Handler) opDescribeEntitlements(_ context.Context, body []byte) (any, error) { var req describeEntitlementsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -353,7 +354,7 @@ type updateEntitlementInput struct { func (h *Handler) opUpdateEntitlement(_ context.Context, body []byte) (any, error) { var req updateEntitlementInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -376,7 +377,7 @@ type associateApplicationToEntitlementInput struct { func (h *Handler) opAssociateApplicationToEntitlement(_ context.Context, body []byte) (any, error) { var req associateApplicationToEntitlementInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -397,7 +398,7 @@ type disassociateApplicationFromEntitlementInput struct { func (h *Handler) opDisassociateApplicationFromEntitlement(_ context.Context, body []byte) (any, error) { var req disassociateApplicationFromEntitlementInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -418,7 +419,7 @@ type listEntitledApplicationsInput struct { func (h *Handler) opListEntitledApplications(_ context.Context, body []byte) (any, error) { var req listEntitledApplicationsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -486,7 +487,7 @@ type createDirectoryConfigInput struct { func (h *Handler) opCreateDirectoryConfig(_ context.Context, body []byte) (any, error) { var req createDirectoryConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -507,7 +508,7 @@ type deleteDirectoryConfigInput struct { func (h *Handler) opDeleteDirectoryConfig(_ context.Context, body []byte) (any, error) { var req deleteDirectoryConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -526,7 +527,7 @@ type describeDirectoryConfigsInput struct { func (h *Handler) opDescribeDirectoryConfigs(_ context.Context, body []byte) (any, error) { var req describeDirectoryConfigsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -563,7 +564,7 @@ type updateDirectoryConfigInput struct { func (h *Handler) opUpdateDirectoryConfig(_ context.Context, body []byte) (any, error) { var req updateDirectoryConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } diff --git a/services/appstream/handler_image.go b/services/appstream/handler_image.go index 67548ac94a..86243005c7 100644 --- a/services/appstream/handler_image.go +++ b/services/appstream/handler_image.go @@ -2,11 +2,12 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Image handlers --- @@ -20,7 +21,7 @@ type copyImageInput struct { func (h *Handler) opCopyImage(_ context.Context, body []byte) (any, error) { var req copyImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -46,7 +47,7 @@ type createImportedImageInput struct { func (h *Handler) opCreateImportedImage(_ context.Context, body []byte) (any, error) { var req createImportedImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -84,7 +85,7 @@ type createUpdatedImageInput struct { func (h *Handler) opCreateUpdatedImage(_ context.Context, body []byte) (any, error) { var req createUpdatedImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -112,7 +113,7 @@ type deleteImageInput struct { func (h *Handler) opDeleteImage(_ context.Context, body []byte) (any, error) { var req deleteImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -134,7 +135,7 @@ type describeImagesInput struct { func (h *Handler) opDescribeImages(_ context.Context, body []byte) (any, error) { var req describeImagesInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -173,7 +174,7 @@ type imagePermissionsInput struct { func (h *Handler) opUpdateImagePermissions(_ context.Context, body []byte) (any, error) { var req imagePermissionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -197,7 +198,7 @@ type deleteImagePermissionsInput struct { func (h *Handler) opDeleteImagePermissions(_ context.Context, body []byte) (any, error) { var req deleteImagePermissionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -216,7 +217,7 @@ type describeImagePermissionsInput struct { func (h *Handler) opDescribeImagePermissions(_ context.Context, body []byte) (any, error) { var req describeImagePermissionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -280,7 +281,7 @@ type createImageBuilderInput struct { func (h *Handler) opCreateImageBuilder(_ context.Context, body []byte) (any, error) { var req createImageBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -315,7 +316,7 @@ type deleteImageBuilderInput struct { func (h *Handler) opDeleteImageBuilder(_ context.Context, body []byte) (any, error) { var req deleteImageBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -335,7 +336,7 @@ type describeImageBuildersInput struct { func (h *Handler) opDescribeImageBuilders(_ context.Context, body []byte) (any, error) { var req describeImageBuildersInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -368,7 +369,7 @@ type startImageBuilderInput struct { // this handler invented one, which real SDK clients would never receive. func (h *Handler) opStartImageBuilder(_ context.Context, body []byte) (any, error) { var req startImageBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -392,7 +393,7 @@ type stopImageBuilderInput struct { func (h *Handler) opStopImageBuilder(_ context.Context, body []byte) (any, error) { var req stopImageBuilderInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -411,7 +412,7 @@ type createImageBuilderStreamingURLInput struct { func (h *Handler) opCreateImageBuilderStreamingURL(_ context.Context, body []byte) (any, error) { var req createImageBuilderStreamingURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -435,7 +436,7 @@ type associateSoftwareInput struct { func (h *Handler) opAssociateSoftwareToImageBuilder(_ context.Context, body []byte) (any, error) { var req associateSoftwareInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -448,7 +449,7 @@ func (h *Handler) opAssociateSoftwareToImageBuilder(_ context.Context, body []by func (h *Handler) opDisassociateSoftwareFromImageBuilder(_ context.Context, body []byte) (any, error) { var req associateSoftwareInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -466,7 +467,7 @@ type describeSoftwareAssociationsInput struct { func (h *Handler) opDescribeSoftwareAssociations(_ context.Context, body []byte) (any, error) { var req describeSoftwareAssociationsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -505,7 +506,7 @@ type startSoftwareDeploymentInput struct { func (h *Handler) opStartSoftwareDeploymentToImageBuilder(_ context.Context, body []byte) (any, error) { var req startSoftwareDeploymentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -533,7 +534,7 @@ type createExportImageTaskInput struct { func (h *Handler) opCreateExportImageTask(_ context.Context, body []byte) (any, error) { var req createExportImageTaskInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -553,7 +554,7 @@ type getExportImageTaskInput struct { func (h *Handler) opGetExportImageTask(_ context.Context, body []byte) (any, error) { var req getExportImageTaskInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -594,7 +595,7 @@ func stateFilterValues(filters []filterInput) []string { func (h *Handler) opListExportImageTasks(_ context.Context, body []byte) (any, error) { var req listExportImageTasksInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } diff --git a/services/appstream/handler_test.go b/services/appstream/handler_test.go index 7b97b91695..a501bb4792 100644 --- a/services/appstream/handler_test.go +++ b/services/appstream/handler_test.go @@ -2,7 +2,7 @@ package appstream_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -62,7 +63,7 @@ func doRequest(t *testing.T, h *appstream.Handler, action string, body any) *htt var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -174,7 +175,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { require.Equal(t, http.StatusOK, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appArn := appResp["Application"].(map[string]any)["Arn"].(string) require.NotEmpty(t, appArn) @@ -185,7 +186,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { require.Equal(t, http.StatusOK, abRec.Code) var abResp map[string]any - require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp)) + require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp, jsonx.V1())) appBlockArn := abResp["AppBlock"].(map[string]any)["Arn"].(string) require.NotEmpty(t, appBlockArn) @@ -193,7 +194,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { require.Equal(t, http.StatusOK, imgRec.Code) var imgResp map[string]any - require.NoError(t, json.Unmarshal(imgRec.Body.Bytes(), &imgResp)) + require.NoError(t, json.Unmarshal(imgRec.Body.Bytes(), &imgResp, jsonx.V1())) imageArn := imgResp["Image"].(map[string]any)["Arn"].(string) require.NotEmpty(t, imageArn) @@ -204,7 +205,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps := resp["Applications"].([]any) require.Len(t, apps, 1) assert.Equal(t, "arn-app", apps[0].(map[string]any)["Name"]) @@ -217,7 +218,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) blocks := resp["AppBlocks"].([]any) require.Len(t, blocks, 1) assert.Equal(t, "arn-appblock", blocks[0].(map[string]any)["Name"]) @@ -230,7 +231,7 @@ func TestAppStream_DescribeByARN(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) images := resp["Images"].([]any) require.Len(t, images, 1) assert.Equal(t, "arn-image", images[0].(map[string]any)["Name"]) @@ -260,7 +261,7 @@ func TestAppStream_AssociationsAcceptARNIdentifiers(t *testing.T) { require.Equal(t, http.StatusOK, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appArn := appResp["Application"].(map[string]any)["Arn"].(string) require.NotEmpty(t, appArn) @@ -275,7 +276,7 @@ func TestAppStream_AssociationsAcceptARNIdentifiers(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assocs := descResp["ApplicationFleetAssociations"].([]any) require.Len(t, assocs, 1) assert.Equal(t, "assoc-arn-fleet", assocs[0].(map[string]any)["FleetName"]) @@ -294,7 +295,7 @@ func TestAppStream_AssociationsAcceptARNIdentifiers(t *testing.T) { require.Equal(t, http.StatusOK, abRec.Code) var abResp map[string]any - require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp)) + require.NoError(t, json.Unmarshal(abRec.Body.Bytes(), &abResp, jsonx.V1())) appBlockArn := abResp["AppBlock"].(map[string]any)["Arn"].(string) require.NotEmpty(t, appBlockArn) @@ -309,7 +310,7 @@ func TestAppStream_AssociationsAcceptARNIdentifiers(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assocs := descResp["AppBlockBuilderAppBlockAssociations"].([]any) require.Len(t, assocs, 1) assert.Equal(t, appBlockArn, assocs[0].(map[string]any)["AppBlockArn"]) diff --git a/services/appstream/handler_user.go b/services/appstream/handler_user.go index 2cd48732d8..6ea21d28c9 100644 --- a/services/appstream/handler_user.go +++ b/services/appstream/handler_user.go @@ -2,11 +2,12 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- User handlers --- @@ -21,7 +22,7 @@ type createUserInput struct { func (h *Handler) opCreateUser(_ context.Context, body []byte) (any, error) { var req createUserInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -57,7 +58,7 @@ type deleteUserInput struct { func (h *Handler) opDeleteUser(_ context.Context, body []byte) (any, error) { var req deleteUserInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -76,7 +77,7 @@ type describeUsersInput struct { func (h *Handler) opDescribeUsers(_ context.Context, body []byte) (any, error) { var req describeUsersInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -111,7 +112,7 @@ type userAuthInput struct { func (h *Handler) opDisableUser(_ context.Context, body []byte) (any, error) { var req userAuthInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -124,7 +125,7 @@ func (h *Handler) opDisableUser(_ context.Context, body []byte) (any, error) { func (h *Handler) opEnableUser(_ context.Context, body []byte) (any, error) { var req userAuthInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -157,7 +158,7 @@ func (h *Handler) opBatchAssociateUserStack( //nolint:dupl // existing issue. body []byte, ) (any, error) { var req batchAssociateUserStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -197,7 +198,7 @@ func (h *Handler) opBatchDisassociateUserStack( //nolint:dupl // existing issue. body []byte, ) (any, error) { var req batchAssociateUserStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -242,7 +243,7 @@ type describeUserStackAssociationsInput struct { func (h *Handler) opDescribeUserStackAssociations(_ context.Context, body []byte) (any, error) { var req describeUserStackAssociationsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -286,7 +287,7 @@ type describeSessionsInput struct { func (h *Handler) opDescribeSessions(_ context.Context, body []byte) (any, error) { var req describeSessionsInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -321,7 +322,7 @@ type sessionIDInput struct { func (h *Handler) opDrainSessionInstance(_ context.Context, body []byte) (any, error) { var req sessionIDInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -334,7 +335,7 @@ func (h *Handler) opDrainSessionInstance(_ context.Context, body []byte) (any, e func (h *Handler) opExpireSession(_ context.Context, body []byte) (any, error) { var req sessionIDInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -354,7 +355,7 @@ type createStreamingURLInput struct { func (h *Handler) opCreateStreamingURL(_ context.Context, body []byte) (any, error) { var req createStreamingURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -394,7 +395,7 @@ func (h *Handler) opDeleteUsageReportSubscription(_ context.Context, _ []byte) ( func (h *Handler) opDescribeUsageReportSubscriptions(_ context.Context, body []byte) (any, error) { var req pageReq if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } } @@ -450,7 +451,7 @@ type createThemeForStackInput struct { func (h *Handler) opCreateThemeForStack(_ context.Context, body []byte) (any, error) { var req createThemeForStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -473,7 +474,7 @@ func (h *Handler) opCreateThemeForStack(_ context.Context, body []byte) (any, er func (h *Handler) opDeleteThemeForStack(_ context.Context, body []byte) (any, error) { var req themeStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -486,7 +487,7 @@ func (h *Handler) opDeleteThemeForStack(_ context.Context, body []byte) (any, er func (h *Handler) opDescribeThemeForStack(_ context.Context, body []byte) (any, error) { var req themeStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } @@ -514,7 +515,7 @@ type updateThemeForStackInput struct { func (h *Handler) opUpdateThemeForStack(_ context.Context, body []byte) (any, error) { var req updateThemeForStackInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, awserr.New(errInvalidParameter, awserr.ErrInvalidParameter) } diff --git a/services/appstream/images_test.go b/services/appstream/images_test.go index d3f9f6ac83..619d39db3f 100644 --- a/services/appstream/images_test.go +++ b/services/appstream/images_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -31,7 +32,7 @@ func TestAppStream_Images(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) img := resp["Image"].(map[string]any) assert.Equal(t, "my-img", img["Name"]) assert.Equal(t, "AVAILABLE", img["State"]) @@ -49,7 +50,7 @@ func TestAppStream_Images(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) imgs := resp["Images"].([]any) assert.Len(t, imgs, 2) }, @@ -69,7 +70,7 @@ func TestAppStream_Images(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Equal(t, "dst-img", resp["DestinationImageName"]) }, }, @@ -125,7 +126,7 @@ func TestAppStream_Images(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) perms := resp["SharedImagePermissionsList"].([]any) assert.Len(t, perms, 1) }, @@ -185,7 +186,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ib := resp["ImageBuilder"].(map[string]any) // Real CreateImageBuilder launches the build instance // immediately -- terraform-provider-aws's resource waits @@ -208,7 +209,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ib := resp["ImageBuilder"].(map[string]any) assert.Equal(t, "RUNNING", ib["State"]) // Real StartImageBuilderOutput carries only ImageBuilder -- @@ -229,7 +230,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ib := resp["ImageBuilder"].(map[string]any) assert.Equal(t, "STOPPED", ib["State"]) }, @@ -245,7 +246,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) ib := resp["ImageBuilder"].(map[string]any) assert.Equal(t, "STOPPED", ib["State"]) }, @@ -261,7 +262,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.NotEmpty(t, resp["StreamingURL"]) assert.NotEmpty(t, resp["Expires"]) }, @@ -294,7 +295,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Equal(t, "list-sw-ib", resp["AssociatedResource"]) assocs := resp["SoftwareAssociations"].([]any) assert.Len(t, assocs, 1) @@ -311,7 +312,7 @@ func TestAppStream_ImageBuilders(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Equal(t, "sw-assoc-image", resp["AssociatedResource"]) assocs := resp["SoftwareAssociations"].([]any) assert.Empty(t, assocs) @@ -397,7 +398,7 @@ func TestAppStream_ExportImageTasks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) task := resp["ExportImageTask"].(map[string]any) assert.NotEmpty(t, task["TaskId"]) assert.Equal(t, "exported-ami", task["AmiName"]) @@ -423,7 +424,7 @@ func TestAppStream_ExportImageTasks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) tasks := resp["ExportImageTasks"].([]any) assert.Len(t, tasks, 1) }, @@ -459,7 +460,7 @@ func TestAppStream_GetExportImageTask(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) task := createResp["ExportImageTask"].(map[string]any) taskID := task["TaskId"].(string) @@ -467,7 +468,7 @@ func TestAppStream_GetExportImageTask(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) gotTask := getResp["ExportImageTask"].(map[string]any) assert.Equal(t, taskID, gotTask["TaskId"]) } @@ -484,7 +485,7 @@ func TestAppStream_ImageBuilderARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) builder := resp["ImageBuilder"].(map[string]any) assert.Regexp(t, `^arn:aws:appstream:[a-z0-9-]+:\d+:image-builder/arn-builder$`, builder["Arn"]) } diff --git a/services/appstream/persistence.go b/services/appstream/persistence.go index 8f789989b5..e3b24c5bcc 100644 --- a/services/appstream/persistence.go +++ b/services/appstream/persistence.go @@ -2,7 +2,7 @@ package appstream import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -38,7 +38,7 @@ const appstreamSnapshotVersion = 2 // subscription exists at a time), so it is also persisted directly rather // than through a table. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Associations map[string]map[string]bool `json:"associations"` Tags map[string]map[string]string `json:"tags"` AppBlockBuilderAssoc map[string]map[string]bool `json:"appBlockBuilderAssoc"` diff --git a/services/appstream/rpcv2cbor.go b/services/appstream/rpcv2cbor.go index 3c544e88cd..d43edeb433 100644 --- a/services/appstream/rpcv2cbor.go +++ b/services/appstream/rpcv2cbor.go @@ -2,7 +2,7 @@ package appstream import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -12,6 +12,7 @@ import ( "github.com/aws/smithy-go/encoding/cbor" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -157,7 +158,7 @@ func cborBodyToJSON(body []byte) ([]byte, error) { return nil, fmt.Errorf("%w: got %T", errExpectedCBORMap, v) } - return json.Marshal(cborToGo(m)) + return json.Marshal(cborToGo(m), jsonx.V1()) } // cborToGo converts a decoded CBOR value tree into the generic Go value @@ -221,7 +222,7 @@ func awstimeSeconds(sec int64, nsec int) float64 { // a CBOR value tree suitable for the wire. func jsonToCBOR(body []byte) (cbor.Value, error) { var v any - if err := json.Unmarshal(body, &v); err != nil { + if err := json.Unmarshal(body, &v, jsonx.V1()); err != nil { return nil, err } diff --git a/services/appstream/sessions_test.go b/services/appstream/sessions_test.go index a9615472d7..9f89e3c699 100644 --- a/services/appstream/sessions_test.go +++ b/services/appstream/sessions_test.go @@ -1,7 +1,7 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -40,7 +41,7 @@ func TestAppStream_Sessions(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.NotEmpty(t, resp["StreamingURL"]) assert.NotEmpty(t, resp["Expires"]) }, @@ -66,7 +67,7 @@ func TestAppStream_Sessions(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) sessions := resp["Sessions"].([]any) assert.Len(t, sessions, 1) }, @@ -112,7 +113,7 @@ func TestAppStream_SessionLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) sessions := descResp["Sessions"].([]any) require.Len(t, sessions, 1) sessionID := sessions[0].(map[string]any)["Id"].(string) @@ -142,7 +143,7 @@ func TestAppStream_DrainSessionInstance(t *testing.T) { "StackName": "drain-stk", "FleetName": "drain-fleet", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) sessions := descResp["Sessions"].([]any) require.Len(t, sessions, 1) sessionID := sessions[0].(map[string]any)["Id"].(string) @@ -178,7 +179,7 @@ func TestAppStream_SessionStreamingURL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["StreamingURL"]) expires, ok := resp["Expires"].(float64) @@ -220,7 +221,7 @@ func TestAppStream_DescribeSessionsFilterByStack(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sessions, ok := resp["Sessions"].([]any) require.True(t, ok) assert.Len(t, sessions, 2) diff --git a/services/appstream/stacks_test.go b/services/appstream/stacks_test.go index 58bcca5525..95a254fd71 100644 --- a/services/appstream/stacks_test.go +++ b/services/appstream/stacks_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -30,7 +31,7 @@ func TestAppStream_Stacks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) stack, ok := resp["Stack"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-stack", stack["Name"]) @@ -58,7 +59,7 @@ func TestAppStream_Stacks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) stacks, ok := resp["Stacks"].([]any) require.True(t, ok) assert.Len(t, stacks, 1) @@ -76,7 +77,7 @@ func TestAppStream_Stacks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) stacks := resp["Stacks"].([]any) assert.Len(t, stacks, 1) s := stacks[0].(map[string]any) @@ -100,7 +101,7 @@ func TestAppStream_Stacks(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) stack := resp["Stack"].(map[string]any) assert.Equal(t, "Updated", stack["DisplayName"]) }, @@ -224,7 +225,7 @@ func TestAppStream_StackErrorCodes(t *testing.T) { if tc.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"], "wrong __type in error response") } }) @@ -241,7 +242,7 @@ func TestAppStream_StackARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stack := resp["Stack"].(map[string]any) assert.Regexp(t, `^arn:aws:appstream:[a-z0-9-]+:\d+:stack/arn-stack$`, stack["Arn"]) } diff --git a/services/appstream/tags_test.go b/services/appstream/tags_test.go index 98ee5d1d7e..531a832c71 100644 --- a/services/appstream/tags_test.go +++ b/services/appstream/tags_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -29,7 +30,7 @@ func TestAppStream_Tags(t *testing.T) { createStack(t, h, "tag-stack") rec := doRequest(t, h, "DescribeStacks", map[string]any{"Names": []string{"tag-stack"}}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Stacks"].([]any)[0].(map[string]any)["Arn"].(string) }, @@ -45,7 +46,7 @@ func TestAppStream_Tags(t *testing.T) { createStack(t, h, "listtag-stack") rec := doRequest(t, h, "DescribeStacks", map[string]any{"Names": []string{"listtag-stack"}}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["Stacks"].([]any)[0].(map[string]any)["Arn"].(string) doRequest( t, @@ -63,7 +64,7 @@ func TestAppStream_Tags(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) tags, ok := resp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "staging", tags["env"]) @@ -76,7 +77,7 @@ func TestAppStream_Tags(t *testing.T) { createStack(t, h, "untag-stack") rec := doRequest(t, h, "DescribeStacks", map[string]any{"Names": []string{"untag-stack"}}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["Stacks"].([]any)[0].(map[string]any)["Arn"].(string) doRequest(t, h, "TagResource", map[string]any{"ResourceArn": arn, "Tags": map[string]string{"k": "v"}}) @@ -124,14 +125,14 @@ func TestAppStream_TagLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) stackArn := createResp["Stack"].(map[string]any)["Arn"].(string) recList := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": stackArn}) require.Equal(t, http.StatusOK, recList.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -143,7 +144,7 @@ func TestAppStream_TagLifecycle(t *testing.T) { recList2 := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": stackArn}) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listResp2, jsonx.V1())) tags2 := listResp2["Tags"].(map[string]any) assert.NotContains(t, tags2, "env") assert.Equal(t, "platform", tags2["team"]) diff --git a/services/appstream/themes_test.go b/services/appstream/themes_test.go index 7761f8ab7e..a6e4d89084 100644 --- a/services/appstream/themes_test.go +++ b/services/appstream/themes_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -56,7 +57,7 @@ func TestAppStream_Themes(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) th := resp["Theme"].(map[string]any) assert.Equal(t, "theme-stk", th["StackName"]) assert.Equal(t, "ENABLED", th["State"]) diff --git a/services/appstream/usage_report_subscriptions_test.go b/services/appstream/usage_report_subscriptions_test.go index e39c850dc3..caebb1dc49 100644 --- a/services/appstream/usage_report_subscriptions_test.go +++ b/services/appstream/usage_report_subscriptions_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -31,7 +32,7 @@ func TestAppStream_UsageReports(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Equal(t, "DAILY", resp["Schedule"]) assert.NotEmpty(t, resp["S3BucketName"]) }, @@ -48,7 +49,7 @@ func TestAppStream_UsageReports(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) subs := resp["UsageReportSubscriptions"].([]any) assert.Len(t, subs, 1) }, @@ -103,7 +104,7 @@ func TestAppStream_UsageReportSubscriptionRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp, jsonx.V1())) subs := resp["UsageReportSubscriptions"].([]any) require.Len(t, subs, 1) sub := subs[0].(map[string]any) diff --git a/services/appstream/users_test.go b/services/appstream/users_test.go index ba12217f8a..e33409b676 100644 --- a/services/appstream/users_test.go +++ b/services/appstream/users_test.go @@ -1,13 +1,14 @@ package appstream_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appstream" ) @@ -56,7 +57,7 @@ func TestAppStream_Users(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) users := resp["Users"].([]any) assert.Len(t, users, 2) }, @@ -136,7 +137,7 @@ func TestAppStream_UserARNPartition(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) users := resp["Users"].([]any) require.Len(t, users, 1) assert.Equal( @@ -161,7 +162,7 @@ func TestAppStream_UserARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp, jsonx.V1())) users := resp["Users"].([]any) require.Len(t, users, 1) user := users[0].(map[string]any) @@ -187,7 +188,7 @@ func TestAppStream_UserStatusEnabled(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) users := resp["Users"].([]any) require.Len(t, users, 1) user := users[0].(map[string]any) @@ -226,7 +227,7 @@ func TestAppStream_UserStackAssociations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) errs := resp["errors"].([]any) assert.Empty(t, errs) }, @@ -247,7 +248,7 @@ func TestAppStream_UserStackAssociations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) errs := resp["errors"].([]any) assert.Len(t, errs, 1) }, @@ -274,7 +275,7 @@ func TestAppStream_UserStackAssociations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assocs := resp["UserStackAssociations"].([]any) assert.Len(t, assocs, 1) }, @@ -344,7 +345,7 @@ func TestAppStream_BatchAssociateUserStackErrors(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // errors field may be empty or present depending on implementation // but response must be 200 with valid JSON assert.NotNil(t, resp) @@ -374,7 +375,7 @@ func TestAppStream_BatchAssociateUserStack_StackNotFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) errs := resp["errors"].([]any) require.Len(t, errs, 1) assert.Equal(t, "STACK_NOT_FOUND", errs[0].(map[string]any)["ErrorCode"]) @@ -383,7 +384,7 @@ func TestAppStream_BatchAssociateUserStack_StackNotFound(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Empty(t, descResp["UserStackAssociations"]) } @@ -416,7 +417,7 @@ func TestAppStream_DescribeUserStackAssociations(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &resp, jsonx.V1())) assocs := resp["UserStackAssociations"].([]any) assert.Len(t, assocs, 1) assoc := assocs[0].(map[string]any) @@ -446,7 +447,7 @@ func TestAppStream_BatchDisassociateUserStack_StackNotFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) errs := resp["errors"].([]any) require.Len(t, errs, 1) assert.Equal(t, "STACK_NOT_FOUND", errs[0].(map[string]any)["ErrorCode"]) diff --git a/services/appsync/api_keys_test.go b/services/appsync/api_keys_test.go index 135b7bf81b..0a86dfe1be 100644 --- a/services/appsync/api_keys_test.go +++ b/services/appsync/api_keys_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -367,7 +368,7 @@ func TestListAPIKeys_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var apiOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut, jsonx.V1())) apiID := apiOut["graphqlApi"].(map[string]any)["apiId"].(string) for range 4 { @@ -407,7 +408,7 @@ func TestListAPIKeys_Pagination(t *testing.T) { NextToken string `json:"nextToken"` APIKeys []map[string]any `json:"apiKeys"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.APIKeys, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/auth.go b/services/appsync/auth.go index 90d53f5551..1feba9f624 100644 --- a/services/appsync/auth.go +++ b/services/appsync/auth.go @@ -2,7 +2,7 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // errUnexpectedJWTSigningMethod mirrors the sentinel @@ -255,7 +256,7 @@ func (b *InMemoryBackend) checkLambdaAuth( }, } - payload, marshalErr := json.Marshal(event) + payload, marshalErr := json.Marshal(event, jsonx.V1()) if marshalErr != nil { return nil, false } @@ -267,7 +268,7 @@ func (b *InMemoryBackend) checkLambdaAuth( } var resp lambdaAuthorizerResponse - if jsonErr := json.Unmarshal(result, &resp); jsonErr != nil { + if jsonErr := json.Unmarshal(result, &resp, jsonx.V1()); jsonErr != nil { return nil, false } diff --git a/services/appsync/auth_test.go b/services/appsync/auth_test.go index bba2be11d9..c608f2362c 100644 --- a/services/appsync/auth_test.go +++ b/services/appsync/auth_test.go @@ -4,7 +4,7 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -136,7 +137,7 @@ func TestHandleGraphQL_APIKeyAuth_HTTPShape(t *testing.T) { require.Equal(t, http.StatusUnauthorized, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Real AppSync's transport-level auth failure body is exactly // {"message":"Unauthorized"} -- no "code"/"__type" field, unlike this // package's control-plane errorResponse() convention. @@ -182,7 +183,7 @@ func TestExecuteGraphQL_LambdaAuth(t *testing.T) { } `json:"requestContext"` AuthorizationToken string `json:"authorizationToken"` } - require.NoError(t, json.Unmarshal(mock.calls[0].payload, &event)) + require.NoError(t, json.Unmarshal(mock.calls[0].payload, &event, jsonx.V1())) assert.Equal(t, "secret-tok", event.AuthorizationToken) assert.Equal(t, api.APIID, event.RequestContext.APIID) assert.Contains(t, event.RequestContext.QueryString, "hello") diff --git a/services/appsync/caching_test.go b/services/appsync/caching_test.go index a722481b73..185981f779 100644 --- a/services/appsync/caching_test.go +++ b/services/appsync/caching_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -291,7 +292,7 @@ func TestAPICache_UnmarshalJSON_HealthMetricsConfig(t *testing.T) { t.Parallel() var got appsync.APICache - err := json.Unmarshal([]byte(tt.body), &got) + err := json.Unmarshal([]byte(tt.body), &got, jsonx.V1()) if tt.wantErr { require.Error(t, err) diff --git a/services/appsync/data_sources_config_test.go b/services/appsync/data_sources_config_test.go index 90ebeb1237..40bf9b72ba 100644 --- a/services/appsync/data_sources_config_test.go +++ b/services/appsync/data_sources_config_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -661,7 +662,7 @@ func TestListDataSources_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var apiOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut, jsonx.V1())) apiID := apiOut["graphqlApi"].(map[string]any)["apiId"].(string) for i := range 4 { @@ -702,7 +703,7 @@ func TestListDataSources_Pagination(t *testing.T) { NextToken string `json:"nextToken"` DataSources []map[string]any `json:"dataSources"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.DataSources, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/ddb_ops.go b/services/appsync/ddb_ops.go index b37902df42..6c11e62198 100644 --- a/services/appsync/ddb_ops.go +++ b/services/appsync/ddb_ops.go @@ -3,11 +3,13 @@ package appsync import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" "reflect" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -234,7 +236,7 @@ func intOf(v any) int { return int(n) case int: return n - case json.Number: + case jsonx.Number: i, _ := n.Int64() return int(i) @@ -305,7 +307,7 @@ func ddbQueryScan( } func encodeNextToken(key map[string]any) string { - b, _ := json.Marshal(key) + b, _ := json.Marshal(key, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(b) } @@ -317,7 +319,7 @@ func decodeNextToken(tok string) (map[string]any, error) { } var key map[string]any - if err = json.Unmarshal(raw, &key); err != nil || len(key) == 0 { + if err = json.Unmarshal(raw, &key, jsonx.V1()); err != nil || len(key) == 0 { return nil, fmt.Errorf("%w: invalid nextToken", ErrValidation) } diff --git a/services/appsync/ddb_resolver_flow_test.go b/services/appsync/ddb_resolver_flow_test.go index dfb0541b65..76aeaf6b36 100644 --- a/services/appsync/ddb_resolver_flow_test.go +++ b/services/appsync/ddb_resolver_flow_test.go @@ -2,13 +2,14 @@ package appsync_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -123,7 +124,7 @@ type Mutation { putTodo(id: ID!, title: String): Todo }`) require.Len(t, out, 1) for _, v := range out { - got, mErr := json.Marshal(v) + got, mErr := json.Marshal(v, jsonx.V1()) require.NoError(t, mErr) assert.JSONEq(t, tt.want, string(got)) } @@ -182,7 +183,7 @@ type Query { todo: Todo todos: [Todo] }`) out, err := b.ExecuteGraphQL(t.Context(), api.APIID, tt.query, "", nil, appsync.GraphQLAuth{APIKey: key.ID}) require.NoError(t, err) - got, mErr := json.Marshal(out) + got, mErr := json.Marshal(out, jsonx.V1()) require.NoError(t, mErr) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/appsync/ddb_transact.go b/services/appsync/ddb_transact.go index 3f209704b5..b07b1a70e6 100644 --- a/services/appsync/ddb_transact.go +++ b/services/appsync/ddb_transact.go @@ -3,10 +3,12 @@ package appsync import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -190,7 +192,7 @@ func ddbSync(ctx context.Context, ddb DynamoDBBackend, cfg *DynamoDBDataSourceCo raw, err := base64.RawURLEncoding.DecodeString(tok) var st syncToken - if err != nil || json.Unmarshal(raw, &st) != nil || len(st.Key) == 0 { + if err != nil || json.Unmarshal(raw, &st, jsonx.V1()) != nil || len(st.Key) == 0 { return nil, fmt.Errorf("%w: invalid nextToken", ErrValidation) } @@ -210,7 +212,7 @@ func ddbSync(ctx context.Context, ddb DynamoDBBackend, cfg *DynamoDBDataSourceCo var next any if len(page.LastKey) > 0 { - b, _ := json.Marshal(syncToken{Key: page.LastKey, StartedAt: startedAt}) + b, _ := json.Marshal(syncToken{Key: page.LastKey, StartedAt: startedAt}, jsonx.V1()) next = base64.RawURLEncoding.EncodeToString(b) } diff --git a/services/appsync/domain_names_test.go b/services/appsync/domain_names_test.go index dafcd64472..9fec038a01 100644 --- a/services/appsync/domain_names_test.go +++ b/services/appsync/domain_names_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -352,7 +353,7 @@ func TestListDomainNames_Pagination(t *testing.T) { NextToken string `json:"nextToken"` DomainNameConfigs []map[string]any `json:"domainNameConfigs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.DomainNameConfigs, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/ds_external.go b/services/appsync/ds_external.go index e352511b62..0719aafb70 100644 --- a/services/appsync/ds_external.go +++ b/services/appsync/ds_external.go @@ -2,13 +2,15 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" "net/url" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -194,7 +196,7 @@ func eventBridgeEntry(m map[string]any, busARN string) (EventBridgeEntry, error) e.Detail = d case nil: default: - raw, err := json.Marshal(d) + raw, err := json.Marshal(d, jsonx.V1()) if err != nil { return e, fmt.Errorf("%w: event detail is not JSON-serializable", ErrValidation) } @@ -275,7 +277,7 @@ func parseSearchBody(body []byte) any { } var v any - if err := json.Unmarshal(body, &v); err != nil { + if err := json.Unmarshal(body, &v, jsonx.V1()); err != nil { return string(body) } @@ -313,7 +315,7 @@ func openSearchRequest(endpoint string, m map[string]any) (OpenSearchRequest, er case string: req.Body = []byte(body) default: - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) if err != nil { return req, fmt.Errorf("%w: request body is not JSON-serializable", ErrValidation) } diff --git a/services/appsync/ds_external_test.go b/services/appsync/ds_external_test.go index 00b24d8e50..b25e448896 100644 --- a/services/appsync/ds_external_test.go +++ b/services/appsync/ds_external_test.go @@ -2,7 +2,8 @@ package appsync_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -142,7 +144,7 @@ func TestEventBridgeDataSource_Request(t *testing.T) { assert.JSONEq(t, `{"k":"v"}`, eb.entries[0].Detail) assert.Equal(t, []string{"r1"}, eb.entries[0].Resources) - raw, _ := json.Marshal(out["run"]) + raw, _ := json.Marshal(out["run"], jsonx.V1()) assert.JSONEq(t, `{"Entries":[{"EventId":"ev-1"}],"FailedEntryCount":0}`, string(raw)) } @@ -165,7 +167,7 @@ func TestRDSHelpers(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - ctxJSON, _ := json.Marshal(map[string]any{"result": result}) + ctxJSON, _ := json.Marshal(map[string]any{"result": result}, jsonx.V1()) out, err := b.EvaluateMappingTemplate(tt.template, string(ctxJSON)) require.NoError(t, err) assert.JSONEq(t, tt.want, out) @@ -218,16 +220,16 @@ export function response(ctx) { return ctx.result; }` t.Run(tt.kind, func(t *testing.T) { t.Parallel() - ctxJSON, _ := json.Marshal(map[string]any{"arguments": map[string]any{"kind": tt.kind}}) + ctxJSON, _ := json.Marshal(map[string]any{"arguments": map[string]any{"kind": tt.kind}}, jsonx.V1()) out, err := b.EvaluateCode(code, string(ctxJSON), "request", "APPSYNC_JS") require.NoError(t, err) var got struct { - Version string `json:"version"` - Statements json.RawMessage `json:"statements"` - VariableMap json.RawMessage `json:"variableMap"` + Version string `json:"version"` + Statements jsontext.Value `json:"statements"` + VariableMap jsontext.Value `json:"variableMap"` } - require.NoError(t, json.Unmarshal([]byte(out), &got)) + require.NoError(t, json.Unmarshal([]byte(out), &got, jsonx.V1())) assert.JSONEq(t, tt.wantStmts, string(got.Statements)) assert.JSONEq(t, tt.wantVars, string(got.VariableMap)) assert.Equal(t, "2018-05-29", got.Version) diff --git a/services/appsync/ds_http.go b/services/appsync/ds_http.go index d47732aafa..dd6b0113a5 100644 --- a/services/appsync/ds_http.go +++ b/services/appsync/ds_http.go @@ -5,7 +5,7 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -17,6 +17,7 @@ import ( v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -147,7 +148,7 @@ func buildHTTPRequest(ctx context.Context, endpoint string, req map[string]any) case string: payload = strings.NewReader(b) default: - raw, mErr := json.Marshal(b) + raw, mErr := json.Marshal(b, jsonx.V1()) if mErr != nil { return nil, fmt.Errorf("%w: request body is not JSON-serializable", ErrValidation) } diff --git a/services/appsync/ds_rds.go b/services/appsync/ds_rds.go index 4a0d475284..e02fd9545a 100644 --- a/services/appsync/ds_rds.go +++ b/services/appsync/ds_rds.go @@ -2,8 +2,10 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // invokeRDSDataSource runs the mapped statements through the RDS Data API and @@ -51,7 +53,7 @@ func invokeRDSDataSource( results = append(results, out) } - raw, err := json.Marshal(map[string]any{"sqlStatementResults": results}) + raw, err := json.Marshal(map[string]any{"sqlStatementResults": results}, jsonx.V1()) if err != nil { return nil, fmt.Errorf("rds result is not JSON-serializable: %w", err) } diff --git a/services/appsync/evaluation.go b/services/appsync/evaluation.go index 1e53352f50..0587453825 100644 --- a/services/appsync/evaluation.go +++ b/services/appsync/evaluation.go @@ -1,9 +1,11 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // evalContext decodes an EvaluateMappingTemplate/EvaluateCode context JSON @@ -12,7 +14,7 @@ func evalContext(contextJSON string) (map[string]any, error) { ctx := map[string]any{} if strings.TrimSpace(contextJSON) != "" { - if err := json.Unmarshal([]byte(contextJSON), &ctx); err != nil { + if err := json.Unmarshal([]byte(contextJSON), &ctx, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid context JSON", ErrValidation) } } @@ -116,7 +118,7 @@ func (b *InMemoryBackend) EvaluateCodeLogs(code, contextJSON, function, runtime return "", out.Logs, err } - raw, err := json.Marshal(out.Value) + raw, err := json.Marshal(out.Value, jsonx.V1()) if err != nil { return "", out.Logs, fmt.Errorf("%w: result is not JSON-serializable", ErrValidation) } diff --git a/services/appsync/evaluation_logs_test.go b/services/appsync/evaluation_logs_test.go index 0179c20ce8..5c6348b63e 100644 --- a/services/appsync/evaluation_logs_test.go +++ b/services/appsync/evaluation_logs_test.go @@ -1,12 +1,14 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AppSync developer guide, "Logging utilities": $util.log.info/error output is @@ -49,7 +51,7 @@ func TestEvaluateMappingTemplate_Logs(t *testing.T) { Result string `json:"evaluationResult"` Logs []string `json:"logs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantLogs, out.Logs) assert.Equal(t, tt.wantErr, out.Error != nil) }) diff --git a/services/appsync/export_test.go b/services/appsync/export_test.go index 9948b998af..104750e588 100644 --- a/services/appsync/export_test.go +++ b/services/appsync/export_test.go @@ -2,7 +2,9 @@ // These exports exist solely for testing and must not be called from production code. package appsync -import "encoding/json" +import ( + "encoding/json/jsontext" +) // RenderVTL is the exported test hook for the VTL template renderer. // It is only exposed for package-level tests and should not be used in production code. @@ -22,13 +24,13 @@ func ToDynamoDBJSON(val any) string { // the explicit apiKeys handling, version guard, and Tags-close housekeeping // that the production persistence.go's Snapshot/Restore layer adds on top -- // without needing an unexported field accessor. -func (b *InMemoryBackend) SnapshotRegistry() (map[string]json.RawMessage, error) { +func (b *InMemoryBackend) SnapshotRegistry() (map[string]jsontext.Value, error) { return b.registry.SnapshotAll() } // RestoreRegistry is the exported test hook for the backend's internal // store.Registry.RestoreAll. See SnapshotRegistry. -func (b *InMemoryBackend) RestoreRegistry(data map[string]json.RawMessage) error { +func (b *InMemoryBackend) RestoreRegistry(data map[string]jsontext.Value) error { return b.registry.RestoreAll(data) } diff --git a/services/appsync/functions_test.go b/services/appsync/functions_test.go index ef896ef7b7..2169b7da32 100644 --- a/services/appsync/functions_test.go +++ b/services/appsync/functions_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -513,7 +514,7 @@ func TestListFunctions_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var apiOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut, jsonx.V1())) apiID := apiOut["graphqlApi"].(map[string]any)["apiId"].(string) rec = doRequest(t, h, http.MethodPost, fmt.Sprintf("/v1/apis/%s/datasources", apiID), map[string]any{ @@ -561,7 +562,7 @@ func TestListFunctions_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Functions []map[string]any `json:"functions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Functions, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/graphql.go b/services/appsync/graphql.go index 2754f28a40..4cf0f01344 100644 --- a/services/appsync/graphql.go +++ b/services/appsync/graphql.go @@ -3,7 +3,8 @@ package appsync import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "slices" @@ -12,6 +13,8 @@ import ( "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/validator/rules" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -380,12 +383,12 @@ func resolveValue(val *ast.Value, variables map[string]any) any { return val.Raw == "true" case ast.IntValue: var i float64 - _ = json.Unmarshal([]byte(val.Raw), &i) + _ = json.Unmarshal([]byte(val.Raw), &i, jsonx.V1()) return i case ast.FloatValue: var f float64 - _ = json.Unmarshal([]byte(val.Raw), &f) + _ = json.Unmarshal([]byte(val.Raw), &f, jsonx.V1()) return f case ast.StringValue, ast.BlockValue, ast.EnumValue: @@ -461,7 +464,7 @@ func functionMappingUnit(f *Function, source any) mappingUnit { // object -- callers that require one check the decoded type themselves). func unmarshalOrRaw(s string) any { var v any - if err := json.Unmarshal([]byte(s), &v); err == nil { + if err := json.Unmarshal([]byte(s), &v, jsonx.V1()); err == nil { return v } @@ -634,7 +637,7 @@ func invokeLambdaDataSource( var lambdaResult any - if jsonErr := json.Unmarshal(result, &lambdaResult); jsonErr != nil { + if jsonErr := json.Unmarshal(result, &lambdaResult, jsonx.V1()); jsonErr != nil { lambdaResult = string(result) } @@ -660,10 +663,10 @@ func buildLambdaEvent(mu mappingUnit, args map[string]any, prevResult any) ([]by } } - return json.Marshal(value) + return json.Marshal(value, jsonx.V1()) } - return json.Marshal(defaultLambdaEvent(mu, args)) + return json.Marshal(defaultLambdaEvent(mu, args), jsonx.V1()) } func defaultLambdaEvent(mu mappingUnit, args map[string]any) map[string]any { @@ -747,10 +750,9 @@ func invokeNoneDataSource(mu mappingUnit, args map[string]any, prevResult any) ( // parseGraphQLRequest parses the GraphQL request body. func parseGraphQLRequest(body []byte) (*graphqlRequest, error) { var req graphqlRequest - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) - if err := dec.Decode(&req); err != nil { + if err := json.UnmarshalDecode(dec, &req, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fmt.Errorf("invalid GraphQL request: %w", err) } diff --git a/services/appsync/graphql_apis_config_test.go b/services/appsync/graphql_apis_config_test.go index 7effb0871b..fe3ab95b67 100644 --- a/services/appsync/graphql_apis_config_test.go +++ b/services/appsync/graphql_apis_config_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -659,7 +660,7 @@ func TestListGraphqlAPIs_Pagination(t *testing.T) { NextToken string `json:"nextToken"` GraphqlAPIs []map[string]any `json:"graphqlApis"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.GraphqlAPIs, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) @@ -703,7 +704,7 @@ func TestListGraphqlAPIs_FullPagination(t *testing.T) { NextToken string `json:"nextToken"` GraphqlAPIs []map[string]any `json:"graphqlApis"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.LessOrEqual(t, len(out.GraphqlAPIs), 2) for _, api := range out.GraphqlAPIs { diff --git a/services/appsync/handler_api_keys.go b/services/appsync/handler_api_keys.go index 8d1ee3dddc..24fa7f547b 100644 --- a/services/appsync/handler_api_keys.go +++ b/services/appsync/handler_api_keys.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleAPIKeys handles /v1/apis/{apiId}/apikeys[/{keyId}]. @@ -52,7 +53,7 @@ func (h *Handler) createAPIKey(ctx context.Context, c *echo.Context, apiID strin Expires int64 `json:"expires"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -105,7 +106,7 @@ func (h *Handler) updateAPIKey(ctx context.Context, c *echo.Context, apiID, keyI Expires int64 `json:"expires"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_api_keys_test.go b/services/appsync/handler_api_keys_test.go index 2dedfe77d7..aea0516b81 100644 --- a/services/appsync/handler_api_keys_test.go +++ b/services/appsync/handler_api_keys_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -56,7 +58,7 @@ func TestHandler_CreateApiKey(t *testing.T) { if tt.wantKeyID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) key, ok := resp["apiKey"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, key["id"]) @@ -75,7 +77,7 @@ func TestHandler_CreateAPIKey_Da2Prefix(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) gqlAPI := resp["graphqlApi"].(map[string]any) apiID := gqlAPI["apiId"].(string) @@ -84,7 +86,7 @@ func TestHandler_CreateAPIKey_Da2Prefix(t *testing.T) { require.Equal(t, http.StatusCreated, rec2.Code) var keyResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&keyResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &keyResp, jsonx.V1())) apiKey := keyResp["apiKey"].(map[string]any) keyID := apiKey["id"].(string) require.GreaterOrEqual(t, len(keyID), 4, "key ID must be at least 4 characters") @@ -107,7 +109,7 @@ func TestHandler_ListApiKeys(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) keys := resp["apiKeys"].([]any) assert.Len(t, keys, 2) } @@ -146,7 +148,7 @@ func TestHandler_UpdateApiKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apiKey := resp["apiKey"].(map[string]any) assert.Equal(t, "updated", apiKey["description"]) } diff --git a/services/appsync/handler_caching.go b/services/appsync/handler_caching.go index 848204b6d0..69be67d11f 100644 --- a/services/appsync/handler_caching.go +++ b/services/appsync/handler_caching.go @@ -2,12 +2,13 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleAPICaches handles /v1/apis/{apiId}/ApiCaches[/entries]. @@ -56,7 +57,7 @@ func (h *Handler) createAPICache(ctx context.Context, c *echo.Context, apiID str } var cache APICache - if jsonErr := json.Unmarshal(body, &cache); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &cache, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -95,7 +96,7 @@ func (h *Handler) updateAPICache(ctx context.Context, c *echo.Context, apiID str } var cache APICache - if jsonErr := json.Unmarshal(body, &cache); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &cache, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_caching_test.go b/services/appsync/handler_caching_test.go index de845829bc..b24c8548a2 100644 --- a/services/appsync/handler_caching_test.go +++ b/services/appsync/handler_caching_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -102,7 +104,7 @@ func TestHandler_CreateAPICache_Validation(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) gqlAPI := resp["graphqlApi"].(map[string]any) apiID := gqlAPI["apiId"].(string) @@ -130,7 +132,7 @@ func TestHandler_GetApiCache(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotNil(t, resp["apiCache"]) } @@ -174,7 +176,7 @@ func TestHandler_UpdateApiCache(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) cache := resp["apiCache"].(map[string]any) assert.Equal(t, "LARGE", cache["type"]) } diff --git a/services/appsync/handler_channel_namespaces.go b/services/appsync/handler_channel_namespaces.go index 13aaf86f9d..86182e4ab6 100644 --- a/services/appsync/handler_channel_namespaces.go +++ b/services/appsync/handler_channel_namespaces.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleChannelNamespacesCollection(ctx context.Context, c *echo.Context, apiID string) error { @@ -50,7 +51,7 @@ func (h *Handler) createChannelNamespace(ctx context.Context, c *echo.Context, a SubscribeAuthModes []AuthMode `json:"subscribeAuthModes"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -116,7 +117,7 @@ func (h *Handler) updateChannelNamespace(ctx context.Context, c *echo.Context, a SubscribeAuthModes []AuthMode `json:"subscribeAuthModes"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_channel_namespaces_test.go b/services/appsync/handler_channel_namespaces_test.go index 2a4a1c8ade..83e98cef87 100644 --- a/services/appsync/handler_channel_namespaces_test.go +++ b/services/appsync/handler_channel_namespaces_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -64,7 +66,7 @@ func TestHandler_CreateChannelNamespace(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ns, ok := resp["channelNamespace"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, ns["name"]) @@ -83,7 +85,7 @@ func TestHandler_ChannelNamespace_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &apiResp, jsonx.V1())) apiID := apiResp["api"].(map[string]any)["apiId"].(string) // Create namespace. @@ -96,7 +98,7 @@ func TestHandler_ChannelNamespace_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec3.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec3.Body), &listResp, jsonx.V1())) items := listResp["channelNamespaces"].([]any) assert.Len(t, items, 1) @@ -105,7 +107,7 @@ func TestHandler_ChannelNamespace_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec4.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec4.Body), &getResp, jsonx.V1())) ns := getResp["channelNamespace"].(map[string]any) assert.Equal(t, "ns1", ns["name"]) diff --git a/services/appsync/handler_data_sources.go b/services/appsync/handler_data_sources.go index d890c75824..6347308e2e 100644 --- a/services/appsync/handler_data_sources.go +++ b/services/appsync/handler_data_sources.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDataSources handles /v1/apis/{apiId}/datasources[/{name}]. @@ -50,7 +51,7 @@ func (h *Handler) createDataSource(ctx context.Context, c *echo.Context, apiID s } var ds DataSource - if jsonErr := json.Unmarshal(body, &ds); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &ds, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -109,7 +110,7 @@ func (h *Handler) updateDataSource(ctx context.Context, c *echo.Context, apiID, } var ds DataSource - if jsonErr := json.Unmarshal(body, &ds); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &ds, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -180,7 +181,7 @@ func (h *Handler) startDataSourceIntrospection(ctx context.Context, c *echo.Cont RDSDataAPIConfig *RDSDataAPIConfig `json:"rdsDataApiConfig"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_data_sources_test.go b/services/appsync/handler_data_sources_test.go index 0ff16444cc..11f27bad32 100644 --- a/services/appsync/handler_data_sources_test.go +++ b/services/appsync/handler_data_sources_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -143,7 +145,7 @@ func TestHandler_DataSourceIntrospection_StartThenGet(t *testing.T) { IntrospectionID string `json:"introspectionId"` IntrospectionStatus string `json:"introspectionStatus"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut.IntrospectionID) assert.Equal(t, "SUCCESS", startOut.IntrospectionStatus) @@ -157,7 +159,7 @@ func TestHandler_DataSourceIntrospection_StartThenGet(t *testing.T) { Models []any `json:"models"` } `json:"introspectionResult"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, startOut.IntrospectionID, getOut.IntrospectionID) assert.Equal(t, "SUCCESS", getOut.IntrospectionStatus) assert.Empty(t, getOut.IntrospectionResult.Models) @@ -202,7 +204,7 @@ func TestHandler_CreateAndGetDataSource(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ds, ok := resp["dataSource"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, ds["name"]) @@ -233,7 +235,7 @@ func TestHandler_ListDataSources(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) dss, ok := resp["dataSources"].([]any) require.True(t, ok) assert.Len(t, dss, 1) @@ -275,7 +277,7 @@ func TestHandler_UpdateDataSource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ds := resp["dataSource"].(map[string]any) assert.Equal(t, "updated", ds["description"]) diff --git a/services/appsync/handler_domain_names.go b/services/appsync/handler_domain_names.go index fdf8cdbd7e..77a4e4a21d 100644 --- a/services/appsync/handler_domain_names.go +++ b/services/appsync/handler_domain_names.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDomainNames handles /v1/domainnames[/{domainName}[/apiassociation]]. @@ -81,7 +82,7 @@ func (h *Handler) createDomainName(ctx context.Context, c *echo.Context) error { Description string `json:"description"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -112,7 +113,7 @@ func (h *Handler) associateAPI(ctx context.Context, c *echo.Context, domainName APIID string `json:"apiId"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -189,7 +190,7 @@ func (h *Handler) updateDomainName(ctx context.Context, c *echo.Context, domainN CertificateARN string `json:"certificateArn"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_domain_names_test.go b/services/appsync/handler_domain_names_test.go index 8246a2a0ee..fcd7659d1c 100644 --- a/services/appsync/handler_domain_names_test.go +++ b/services/appsync/handler_domain_names_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -53,7 +55,7 @@ func TestHandler_CreateDomainName(t *testing.T) { if tt.wantDomainName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) cfg, ok := resp["domainNameConfig"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantDomainName, cfg["domainName"]) @@ -147,7 +149,7 @@ func TestHandler_DomainNameCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &listResp, jsonx.V1())) dns := listResp["domainNameConfigs"].([]any) assert.Len(t, dns, 1) @@ -198,7 +200,7 @@ func TestHandler_DisassociateAPI(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var apiResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&apiResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &apiResp, jsonx.V1())) apiID := apiResp["graphqlApi"].(map[string]any)["apiId"].(string) doRequest(t, h, http.MethodPost, "/v1/domainnames/api.example.com/apiassociation", @@ -228,7 +230,7 @@ func TestHandler_UpdateDomainName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) dn := resp["domainNameConfig"].(map[string]any) assert.Equal(t, "updated description", dn["description"]) } diff --git a/services/appsync/handler_evaluation.go b/services/appsync/handler_evaluation.go index 645759d8ec..919358e7cb 100644 --- a/services/appsync/handler_evaluation.go +++ b/services/appsync/handler_evaluation.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDataplaneEvaluations handles /v1/dataplane-evaluations/{template|code}. @@ -43,7 +44,7 @@ func (h *Handler) evaluateMappingTemplate(ctx context.Context, c *echo.Context) Context string `json:"context"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -75,7 +76,7 @@ func (h *Handler) evaluateCode(ctx context.Context, c *echo.Context) error { } `json:"runtime"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_events.go b/services/appsync/handler_events.go index 7b2b186f02..12e324b94d 100644 --- a/services/appsync/handler_events.go +++ b/services/appsync/handler_events.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleV2APIs handles /v2/apis[/{apiId}[/channelNamespaces[/{name}]]]. @@ -69,7 +70,7 @@ func (h *Handler) createAPI(ctx context.Context, c *echo.Context) error { OwnerContact string `json:"ownerContact"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -138,7 +139,7 @@ func (h *Handler) updateAPI(ctx context.Context, c *echo.Context, apiID string) OwnerContact string `json:"ownerContact"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_events_test.go b/services/appsync/handler_events_test.go index 909c7d0c20..d082ea7119 100644 --- a/services/appsync/handler_events_test.go +++ b/services/appsync/handler_events_test.go @@ -1,12 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateApi(t *testing.T) { @@ -44,7 +47,7 @@ func TestHandler_CreateApi(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) api, ok := resp["api"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, api["name"]) @@ -64,7 +67,7 @@ func TestHandler_EventAPI_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) apiID := createResp["api"].(map[string]any)["apiId"].(string) // List APIs. @@ -72,7 +75,7 @@ func TestHandler_EventAPI_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &listResp, jsonx.V1())) items := listResp["apis"].([]any) assert.Len(t, items, 1) @@ -81,7 +84,7 @@ func TestHandler_EventAPI_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec3.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec3.Body), &getResp, jsonx.V1())) assert.Equal(t, "MyEventAPI", getResp["api"].(map[string]any)["name"]) // Delete API. @@ -97,7 +100,7 @@ func TestHandler_EventAPI_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec6.Code) var listResp2 map[string]any - require.NoError(t, json.NewDecoder(rec6.Body).Decode(&listResp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec6.Body), &listResp2, jsonx.V1())) assert.Empty(t, listResp2["apis"]) } @@ -129,7 +132,7 @@ func TestHandler_UpdateAPI(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &createResp, jsonx.V1())) apiID := createResp["api"].(map[string]any)["apiId"].(string) rec2 := doRequest(t, h, http.MethodPut, "/v2/apis/"+apiID, @@ -137,7 +140,7 @@ func TestHandler_UpdateAPI(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp, jsonx.V1())) api := resp["api"].(map[string]any) assert.Equal(t, "UpdatedAPI", api["name"]) assert.Equal(t, "ops@example.com", api["ownerContact"]) diff --git a/services/appsync/handler_functions.go b/services/appsync/handler_functions.go index 34674bbd09..e9833ee2c9 100644 --- a/services/appsync/handler_functions.go +++ b/services/appsync/handler_functions.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleFunctions handles /v1/apis/{apiId}/functions[/{functionId}[/resolvers]]. @@ -61,7 +62,7 @@ func (h *Handler) createFunction(ctx context.Context, c *echo.Context, apiID str } var f Function - if jsonErr := json.Unmarshal(body, &f); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &f, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -124,7 +125,7 @@ func (h *Handler) updateFunction(ctx context.Context, c *echo.Context, apiID, fu } var f Function - if jsonErr := json.Unmarshal(body, &f); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &f, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_functions_test.go b/services/appsync/handler_functions_test.go index 8cf15cf639..18ad8666cc 100644 --- a/services/appsync/handler_functions_test.go +++ b/services/appsync/handler_functions_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -78,7 +80,7 @@ func TestHandler_CreateFunction(t *testing.T) { if tt.wantFuncName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) fn, ok := resp["functionConfiguration"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantFuncName, fn["name"]) @@ -102,7 +104,7 @@ func TestHandler_ListFunctions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) fns := resp["functions"].([]any) assert.Len(t, fns, 1) } @@ -121,7 +123,7 @@ func TestHandler_GetFunction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotNil(t, resp["functionConfiguration"]) } @@ -158,7 +160,7 @@ func TestHandler_UpdateFunction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) fnConfig := resp["functionConfiguration"].(map[string]any) assert.Equal(t, "updated fn", fnConfig["description"]) } diff --git a/services/appsync/handler_graphql_apis.go b/services/appsync/handler_graphql_apis.go index 8b914b8b4c..7721458136 100644 --- a/services/appsync/handler_graphql_apis.go +++ b/services/appsync/handler_graphql_apis.go @@ -2,7 +2,7 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strconv" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createGraphqlAPI handles POST /v1/apis. @@ -39,7 +40,7 @@ func (h *Handler) createGraphqlAPI(ctx context.Context, c *echo.Context) error { XrayEnabled bool `json:"xrayEnabled"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -202,7 +203,7 @@ func (h *Handler) updateGraphqlAPI(ctx context.Context, c *echo.Context, apiID s ResolverCountLimit int32 `json:"resolverCountLimit"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -255,7 +256,7 @@ func (h *Handler) handleEnvironmentVariables(ctx context.Context, c *echo.Contex EnvironmentVariables map[string]string `json:"environmentVariables"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_graphql_apis_test.go b/services/appsync/handler_graphql_apis_test.go index c4065cbf7e..a6f3a8c63a 100644 --- a/services/appsync/handler_graphql_apis_test.go +++ b/services/appsync/handler_graphql_apis_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -61,7 +63,7 @@ func TestHandler_CreateAndGetGraphqlAPI(t *testing.T) { if tt.wantAPIName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) api, ok := resp["graphqlApi"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantAPIName, api["name"]) @@ -162,7 +164,7 @@ func TestHandler_GraphQLExecution(t *testing.T) { if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) if _, hasErrors := resp["errors"]; !hasErrors { data, ok := resp["data"].(map[string]any) @@ -208,7 +210,7 @@ func TestHandler_ListGraphqlAPIs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apis, ok := resp["graphqlApis"].([]any) require.True(t, ok) assert.Len(t, apis, tt.wantCount) @@ -348,7 +350,7 @@ func TestHandler_UpdateGraphqlAPI(t *testing.T) { if tt.wantName != "" && tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) gqlAPI := resp["graphqlApi"].(map[string]any) assert.Equal(t, tt.wantName, gqlAPI["name"]) } @@ -366,7 +368,7 @@ func TestHandler_CreateAndUpdateGraphqlAPI_OwnerContact(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) createdAPI := createResp["graphqlApi"].(map[string]any) assert.Equal(t, "team-a@example.com", createdAPI["ownerContact"]) apiID := createdAPI["apiId"].(string) @@ -375,7 +377,7 @@ func TestHandler_CreateAndUpdateGraphqlAPI_OwnerContact(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getResp, jsonx.V1())) assert.Equal(t, "team-a@example.com", getResp["graphqlApi"].(map[string]any)["ownerContact"]) updateRec := doRequest(t, h, http.MethodPatch, "/v1/apis/"+apiID, @@ -383,7 +385,7 @@ func TestHandler_CreateAndUpdateGraphqlAPI_OwnerContact(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &updateResp, jsonx.V1())) assert.Equal(t, "team-b@example.com", updateResp["graphqlApi"].(map[string]any)["ownerContact"]) } @@ -399,7 +401,7 @@ func TestHandler_EnvironmentVariables(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &getResp, jsonx.V1())) assert.Empty(t, getResp["environmentVariables"]) // Put env vars. @@ -408,7 +410,7 @@ func TestHandler_EnvironmentVariables(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var putResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&putResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &putResp, jsonx.V1())) envVars := putResp["environmentVariables"].(map[string]any) assert.Equal(t, "value1", envVars["KEY1"]) assert.Equal(t, "value2", envVars["KEY2"]) @@ -418,7 +420,7 @@ func TestHandler_EnvironmentVariables(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var getResp2 map[string]any - require.NoError(t, json.NewDecoder(rec3.Body).Decode(&getResp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec3.Body), &getResp2, jsonx.V1())) envVars2 := getResp2["environmentVariables"].(map[string]any) assert.Equal(t, "value1", envVars2["KEY1"]) } @@ -480,7 +482,7 @@ func TestHandler_CreateGraphqlAPI_XrayEnabled(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apiObj := resp["graphqlApi"].(map[string]any) assert.NotEmpty(t, apiObj["apiId"]) @@ -540,7 +542,7 @@ func TestHandler_UpdateGraphqlAPI_XrayEnabled(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apiObj := resp["graphqlApi"].(map[string]any) // xrayEnabled omits false in JSON (omitempty), so nil == false. gotXray, _ := apiObj["xrayEnabled"].(bool) @@ -560,7 +562,7 @@ func TestHandler_ListGraphqlAPIs_ApiTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apis := resp["graphqlApis"].([]any) assert.Len(t, apis, 1) } diff --git a/services/appsync/handler_resolvers.go b/services/appsync/handler_resolvers.go index bdd749bae2..f3d60a21f4 100644 --- a/services/appsync/handler_resolvers.go +++ b/services/appsync/handler_resolvers.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleTypeResolvers handles /v1/apis/{apiId}/types/{typeName}/resolvers[/{fieldName}]. @@ -54,7 +55,7 @@ func (h *Handler) createResolver(ctx context.Context, c *echo.Context, apiID, ty } var r Resolver - if jsonErr := json.Unmarshal(body, &r); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &r, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -113,7 +114,7 @@ func (h *Handler) updateResolver(ctx context.Context, c *echo.Context, apiID, ty } var r Resolver - if jsonErr := json.Unmarshal(body, &r); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &r, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_resolvers_test.go b/services/appsync/handler_resolvers_test.go index 66982b80fe..f2767c4929 100644 --- a/services/appsync/handler_resolvers_test.go +++ b/services/appsync/handler_resolvers_test.go @@ -1,13 +1,15 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -57,7 +59,7 @@ func TestHandler_CreateAndGetResolver(t *testing.T) { if tt.wantFieldName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) r, ok := resp["resolver"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantFieldName, r["fieldName"]) @@ -88,7 +90,7 @@ func TestHandler_ListResolvers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) res, ok := resp["resolvers"].([]any) require.True(t, ok) assert.Len(t, res, 1) @@ -123,7 +125,7 @@ func TestHandler_UpdateResolver(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) resolver := resp["resolver"].(map[string]any) assert.Equal(t, "$util.toJson($context.args)", resolver["requestMappingTemplate"]) } @@ -149,7 +151,7 @@ func TestHandler_ListResolversByFunction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) resolvers := resp["resolvers"].([]any) assert.Len(t, resolvers, 1) assert.Equal(t, "getItem", resolvers[0].(map[string]any)["fieldName"]) diff --git a/services/appsync/handler_routing_test.go b/services/appsync/handler_routing_test.go index 3519460c42..94f8ba41ed 100644 --- a/services/appsync/handler_routing_test.go +++ b/services/appsync/handler_routing_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -924,7 +926,7 @@ func Test_TagResource_RealPath(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &listResp, jsonx.V1())) tagMap, ok := listResp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tagMap["env"]) @@ -934,7 +936,7 @@ func Test_TagResource_RealPath(t *testing.T) { require.Equal(t, http.StatusNoContent, rec3.Code) rec4 := doRequest(t, h, http.MethodGet, tagPath, nil) - require.NoError(t, json.NewDecoder(rec4.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec4.Body), &listResp, jsonx.V1())) assert.Empty(t, listResp["tags"]) } @@ -956,7 +958,7 @@ func Test_TagResource_RealPath_EventAPI(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp, jsonx.V1())) tagMap, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "core", tagMap["team"]) @@ -994,7 +996,7 @@ func Test_ApiCache_RealPaths(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) cache := resp["apiCache"].(map[string]any) assert.Equal(t, "LARGE", cache["type"]) @@ -1043,7 +1045,7 @@ func Test_ListSourceApiAssociations_ByAPIID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) // The real AWS SDK's ListSourceApiAssociationsOutput wraps the list under // "sourceApiAssociationSummaries", not "sourceApiAssociations" (the latter is only // the URL path segment name). @@ -1066,7 +1068,7 @@ func Test_ListApis_ResponseKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) apis, ok := resp["apis"].([]any) require.True(t, ok, "response must wrap the list under \"apis\", got keys %v", resp) assert.Len(t, apis, 1) diff --git a/services/appsync/handler_schema.go b/services/appsync/handler_schema.go index a6d2bbfaeb..bdbbc0c0e4 100644 --- a/services/appsync/handler_schema.go +++ b/services/appsync/handler_schema.go @@ -3,12 +3,13 @@ package appsync import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleSchemaCreation handles /v1/apis/{apiId}/schemacreation. @@ -34,7 +35,7 @@ func (h *Handler) startSchemaCreation(ctx context.Context, c *echo.Context, apiI Definition string `json:"definition"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_schema_test.go b/services/appsync/handler_schema_test.go index 683d4e9658..53d4e75fa6 100644 --- a/services/appsync/handler_schema_test.go +++ b/services/appsync/handler_schema_test.go @@ -2,13 +2,15 @@ package appsync_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -61,7 +63,7 @@ func TestHandler_StartSchemaCreation(t *testing.T) { if tt.wantStatus2 != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, tt.wantStatus2, resp["status"]) } }) @@ -79,7 +81,7 @@ func TestHandler_GetSchemaCreationStatus(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, string(appsync.SchemaStatusActive), resp["status"]) } @@ -149,10 +151,10 @@ func TestHandler_GetIntrospectionSchema_Format(t *testing.T) { checkBody: func(t *testing.T, body string) { t.Helper() - require.True(t, json.Valid([]byte(body))) + require.True(t, jsontext.Value([]byte(body)).IsValid(jsonx.V1())) var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &doc)) + require.NoError(t, json.Unmarshal([]byte(body), &doc, jsonx.V1())) data, ok := doc["data"].(map[string]any) require.True(t, ok) @@ -207,7 +209,7 @@ func TestHandler_GetIntrospectionSchema_InvalidSchema_JSON(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "GraphQLSchemaException", resp["code"]) } diff --git a/services/appsync/handler_schema_types.go b/services/appsync/handler_schema_types.go index e73944cfab..7ffa23678f 100644 --- a/services/appsync/handler_schema_types.go +++ b/services/appsync/handler_schema_types.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleTypes handles /v1/apis/{apiId}/types[/{typeName}[/resolvers[/{fieldName}]]]. @@ -68,7 +69,7 @@ func (h *Handler) createTypeHandler(ctx context.Context, c *echo.Context, apiID Format string `json:"format"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -149,7 +150,7 @@ func (h *Handler) updateType(ctx context.Context, c *echo.Context, apiID, typeNa Format string `json:"format"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_schema_types_test.go b/services/appsync/handler_schema_types_test.go index 50fec249b2..d8ad2e54a0 100644 --- a/services/appsync/handler_schema_types_test.go +++ b/services/appsync/handler_schema_types_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -139,7 +141,7 @@ func TestHandler_CreateType(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) typ, ok := resp["type"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, typ["name"]) @@ -158,7 +160,7 @@ func TestHandler_CreateType_DuplicateRejected(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) gqlAPI := resp["graphqlApi"].(map[string]any) apiID := gqlAPI["apiId"].(string) @@ -187,7 +189,7 @@ func TestHandler_ListTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) types := resp["types"].([]any) assert.Len(t, types, 1) } @@ -206,7 +208,7 @@ func TestHandler_GetType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotNil(t, resp["type"]) } @@ -243,7 +245,7 @@ func TestHandler_UpdateType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) typeDef := resp["type"].(map[string]any) assert.Contains(t, typeDef["definition"], "name") } diff --git a/services/appsync/handler_source_api_associations.go b/services/appsync/handler_source_api_associations.go index 893f64aeeb..9f99b9f0a9 100644 --- a/services/appsync/handler_source_api_associations.go +++ b/services/appsync/handler_source_api_associations.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleSourceAPIs handles /v1/sourceApis/{sourceApiIdentifier}/mergedApiAssociations[/{assocId}]. @@ -86,7 +87,7 @@ func (h *Handler) associateMergedGraphqlAPI(ctx context.Context, c *echo.Context } var input associateAPIInput - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -173,7 +174,7 @@ func (h *Handler) associateSourceGraphqlAPI(ctx context.Context, c *echo.Context } var input associateAPIInput - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -237,7 +238,7 @@ func (h *Handler) updateSourceAPIAssociation( Description string `json:"description"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_source_api_associations_test.go b/services/appsync/handler_source_api_associations_test.go index 9d5a9a80f2..d1cb7ecf57 100644 --- a/services/appsync/handler_source_api_associations_test.go +++ b/services/appsync/handler_source_api_associations_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -95,7 +97,7 @@ func TestHandler_AssociateMergedGraphqlApi(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assoc, ok := resp["sourceApiAssociation"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, assoc["associationId"]) @@ -138,7 +140,7 @@ func TestHandler_AssociateSourceGraphqlApi(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assoc, ok := resp["sourceApiAssociation"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, assoc["associationId"]) @@ -178,7 +180,7 @@ func TestHandler_SourceAPIAssociations_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &createResp, jsonx.V1())) assocID := createResp["sourceApiAssociation"].(map[string]any)["associationId"].(string) // List source API associations. @@ -186,7 +188,7 @@ func TestHandler_SourceAPIAssociations_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &listResp, jsonx.V1())) assocs := listResp["sourceApiAssociationSummaries"].([]any) assert.Len(t, assocs, 1) @@ -195,7 +197,7 @@ func TestHandler_SourceAPIAssociations_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec3.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec3.Body), &getResp, jsonx.V1())) assoc := getResp["sourceApiAssociation"].(map[string]any) assert.Equal(t, mrgAPI.APIID, assoc["mergedApiId"]) @@ -225,7 +227,7 @@ func TestHandler_DisassociateMergedGraphqlApi(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &createResp, jsonx.V1())) assocID := createResp["sourceApiAssociation"].(map[string]any)["associationId"].(string) // Disassociate. @@ -246,7 +248,7 @@ func TestHandler_ListSourceApiAssociations_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Empty(t, resp["sourceApiAssociationSummaries"]) } @@ -318,7 +320,7 @@ func TestHandler_StartSchemaMerge(t *testing.T) { } var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, appsync.SourceAPIAssociationStatusMergeSuccess, resp["sourceApiAssociationStatus"]) }) } diff --git a/services/appsync/handler_tags.go b/services/appsync/handler_tags.go index 50f47ce91e..f3dae2c8f7 100644 --- a/services/appsync/handler_tags.go +++ b/services/appsync/handler_tags.go @@ -2,13 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleTagsByARN handles /v1/tags/{resourceArn} — the real AWS SDK path for @@ -91,7 +92,7 @@ func (h *Handler) tagResource(ctx context.Context, c *echo.Context, apiID string Tags map[string]string `json:"tags"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/appsync/handler_tags_test.go b/services/appsync/handler_tags_test.go index f77d361f6d..1ef66c8559 100644 --- a/services/appsync/handler_tags_test.go +++ b/services/appsync/handler_tags_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -30,7 +32,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp, jsonx.V1())) tags := resp["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -54,7 +56,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var resp4 map[string]any - require.NoError(t, json.NewDecoder(rec4.Body).Decode(&resp4)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec4.Body), &resp4, jsonx.V1())) tags4 := resp4["tags"].(map[string]any) assert.NotContains(t, tags4, "env") assert.Equal(t, "platform", tags4["team"]) diff --git a/services/appsync/helpers_test.go b/services/appsync/helpers_test.go index a2ff9a5565..55f3622442 100644 --- a/services/appsync/helpers_test.go +++ b/services/appsync/helpers_test.go @@ -7,7 +7,7 @@ package appsync_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -36,7 +37,7 @@ func doRequest(t *testing.T, handler *appsync.Handler, method, path string, body var buf *bytes.Buffer if body != nil { - b, _ := json.Marshal(body) + b, _ := json.Marshal(body, jsonx.V1()) buf = bytes.NewBuffer(b) } else { buf = bytes.NewBuffer(nil) @@ -65,7 +66,7 @@ func doRequestWithHeaders( var buf *bytes.Buffer if body != nil { - b, _ := json.Marshal(body) + b, _ := json.Marshal(body, jsonx.V1()) buf = bytes.NewBuffer(b) } else { buf = bytes.NewBuffer(nil) @@ -94,7 +95,7 @@ func doV2Request(t *testing.T, handler *appsync.Handler, method, path string, bo var buf *bytes.Buffer if body != nil { - b, _ := json.Marshal(body) + b, _ := json.Marshal(body, jsonx.V1()) buf = bytes.NewBuffer(b) } else { buf = bytes.NewBuffer(nil) diff --git a/services/appsync/identity_test.go b/services/appsync/identity_test.go index 3855759181..01a307d564 100644 --- a/services/appsync/identity_test.go +++ b/services/appsync/identity_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -199,7 +200,7 @@ func whoMap(t *testing.T, v any) map[string]any { require.True(t, ok, "unexpected who: %#v", v) var m map[string]any - require.NoError(t, json.Unmarshal([]byte(s), &m)) + require.NoError(t, json.Unmarshal([]byte(s), &m, jsonx.V1())) return m } diff --git a/services/appsync/introspection.go b/services/appsync/introspection.go index 9e1f0c46d5..6d9fdeb586 100644 --- a/services/appsync/introspection.go +++ b/services/appsync/introspection.go @@ -1,10 +1,12 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "slices" "github.com/vektah/gqlparser/v2/ast" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // The types below mirror the GraphQL specification's introspection system @@ -110,7 +112,7 @@ func marshalIntrospectionSchema(schema *ast.Schema, includeDirectives bool) ([]b }, } - return json.Marshal(doc) + return json.Marshal(doc, jsonx.V1()) } func buildRootRef(def *ast.Definition) *rootTypeRef { diff --git a/services/appsync/introspection_test.go b/services/appsync/introspection_test.go index db8049167a..610d0e410d 100644 --- a/services/appsync/introspection_test.go +++ b/services/appsync/introspection_test.go @@ -1,12 +1,14 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -109,10 +111,10 @@ func fieldByName(fields []testField, name string) *testField { func decodeIntrospection(t *testing.T, raw []byte) testIntrospectionResponse { t.Helper() - require.True(t, json.Valid(raw)) + require.True(t, jsontext.Value(raw).IsValid(jsonx.V1())) var doc testIntrospectionResponse - require.NoError(t, json.Unmarshal(raw, &doc)) + require.NoError(t, json.Unmarshal(raw, &doc, jsonx.V1())) return doc } diff --git a/services/appsync/jseval_test.go b/services/appsync/jseval_test.go index 50c791cb6a..6dc9fd0af3 100644 --- a/services/appsync/jseval_test.go +++ b/services/appsync/jseval_test.go @@ -1,11 +1,13 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // twoHandlerCode defines both request and response handlers, used to exercise @@ -168,6 +170,6 @@ func TestInMemoryBackend_EvaluateCode_ResultIsValidJSON(t *testing.T) { require.NoError(t, err) var decoded map[string]any - require.NoError(t, json.Unmarshal([]byte(out), &decoded)) + require.NoError(t, json.Unmarshal([]byte(out), &decoded, jsonx.V1())) assert.Equal(t, "Scan", decoded["operation"]) } diff --git a/services/appsync/lambda_batch.go b/services/appsync/lambda_batch.go index 0f5a66c18d..9269df0451 100644 --- a/services/appsync/lambda_batch.go +++ b/services/appsync/lambda_batch.go @@ -2,12 +2,14 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "strings" "github.com/vektah/gqlparser/v2/ast" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -197,7 +199,7 @@ func (e *execEnv) invokeBatch( payloads[i] = ent.payload } - body, err := json.Marshal(payloads) + body, err := json.Marshal(payloads, jsonx.V1()) if err != nil { fail(err) @@ -217,7 +219,7 @@ func (e *execEnv) invokeBatch( if invType == lambdaInvokeEvent { results = make([]any, len(chunk)) - } else if err = json.Unmarshal(raw, &results); err != nil || len(results) != len(chunk) { + } else if err = json.Unmarshal(raw, &results, jsonx.V1()); err != nil || len(results) != len(chunk) { fail(fmt.Errorf("%w: BatchInvoke response must be a list of %d items", ErrValidation, len(chunk))) return diff --git a/services/appsync/lambda_batch_test.go b/services/appsync/lambda_batch_test.go index 067bc6939c..6b22d07d82 100644 --- a/services/appsync/lambda_batch_test.go +++ b/services/appsync/lambda_batch_test.go @@ -2,7 +2,7 @@ package appsync_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" @@ -11,6 +11,8 @@ import ( appsynctypes "github.com/aws/aws-sdk-go-v2/service/appsync/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type batchInvoker struct { @@ -27,7 +29,7 @@ func (b *batchInvoker) InvokeFunction(_ context.Context, name, _ string, payload } var items []any - if err := json.Unmarshal(payload, &items); err != nil { + if err := json.Unmarshal(payload, &items, jsonx.V1()); err != nil { return nil, 0, err } @@ -35,7 +37,7 @@ func (b *batchInvoker) InvokeFunction(_ context.Context, name, _ string, payload b.sizes = append(b.sizes, len(items)) b.mu.Unlock() - out, err := json.Marshal(b.respond(items)) + out, err := json.Marshal(b.respond(items), jsonx.V1()) return out, 200, err } @@ -166,7 +168,7 @@ type Query { posts: [Post] }`) Data map[string]any `json:"data"` Errors []any `json:"errors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &reply), rec.Body.String()) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &reply, jsonx.V1()), rec.Body.String()) assert.Equal(t, tt.wantSizes, inv.sizes) assert.Len(t, reply.Errors, max(tt.wantErrs, boolInt(tt.wantData == nil))) diff --git a/services/appsync/models.go b/services/appsync/models.go index c71d1f43b9..1df7ccd832 100644 --- a/services/appsync/models.go +++ b/services/appsync/models.go @@ -2,11 +2,13 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/vektah/gqlparser/v2/ast" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -227,7 +229,7 @@ func (r Resolver) MarshalJSON() ([]byte, error) { return json.Marshal(struct { PipelineConfig *pipelineConfigWire `json:"pipelineConfig,omitempty"` alias - }{alias: alias(r), PipelineConfig: pc}) + }{alias: alias(r), PipelineConfig: pc}, jsonx.V1()) } // UnmarshalJSON is the inverse of [Resolver.MarshalJSON], needed so a @@ -241,7 +243,7 @@ func (r *Resolver) UnmarshalJSON(data []byte) error { PipelineConfig *pipelineConfigWire `json:"pipelineConfig,omitempty"` }{alias: (*alias)(r)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -456,10 +458,10 @@ func (a *APICache) UnmarshalJSON(data []byte) error { aux := struct { *alias - HealthMetricsConfig json.RawMessage `json:"healthMetricsConfig,omitempty"` + HealthMetricsConfig jsontext.Value `json:"healthMetricsConfig,omitempty"` }{alias: (*alias)(a)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -468,12 +470,12 @@ func (a *APICache) UnmarshalJSON(data []byte) error { } // A real string (or null, a no-op unmarshal target) decodes here directly. - if err := json.Unmarshal(aux.HealthMetricsConfig, &a.HealthMetricsConfig); err == nil { + if err := json.Unmarshal(aux.HealthMetricsConfig, &a.HealthMetricsConfig, jsonx.V1()); err == nil { return nil } var legacy bool - if err := json.Unmarshal(aux.HealthMetricsConfig, &legacy); err != nil { + if err := json.Unmarshal(aux.HealthMetricsConfig, &legacy, jsonx.V1()); err != nil { return fmt.Errorf("APICache: invalid healthMetricsConfig %s: %w", aux.HealthMetricsConfig, err) } diff --git a/services/appsync/multi_region_test.go b/services/appsync/multi_region_test.go index 59ab92a007..e4bd963cea 100644 --- a/services/appsync/multi_region_test.go +++ b/services/appsync/multi_region_test.go @@ -2,7 +2,8 @@ package appsync_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -39,7 +41,7 @@ func regionDo(t *testing.T, h *appsync.Handler, region, method, path, body strin out := map[string]any{} if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) } return rec.Code, out @@ -158,9 +160,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/appsync/nested_resolver_test.go b/services/appsync/nested_resolver_test.go index 6d3bd2c5bf..dac026fe6f 100644 --- a/services/appsync/nested_resolver_test.go +++ b/services/appsync/nested_resolver_test.go @@ -1,12 +1,13 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -95,7 +96,7 @@ type Query { post: Post posts: [Post] }`) ) require.NoError(t, err) - got, mErr := json.Marshal(out) + got, mErr := json.Marshal(out, jsonx.V1()) require.NoError(t, mErr) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/appsync/null_propagation_test.go b/services/appsync/null_propagation_test.go index 0d3aac9e37..ac898dac66 100644 --- a/services/appsync/null_propagation_test.go +++ b/services/appsync/null_propagation_test.go @@ -1,13 +1,14 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -105,7 +106,7 @@ func TestNullPropagation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var got gqlReply - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantData, got.Data) require.Len(t, got.Errors, 1, rec.Body.String()) assert.Equal(t, tt.wantMsg, got.Errors[0].Message) diff --git a/services/appsync/persistence.go b/services/appsync/persistence.go index 2eb26b3f7e..66b080411a 100644 --- a/services/appsync/persistence.go +++ b/services/appsync/persistence.go @@ -10,7 +10,7 @@ package appsync // every "clean" table directly, same as here). import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -48,7 +48,7 @@ const appsyncSnapshotVersion = 2 // func(*APIKey) string that could reproduce the "#" composite // key from the value alone). It is persisted explicitly here instead. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` APIKeys map[string]map[string]*APIKey `json:"apiKeys,omitempty"` Version int `json:"version"` } diff --git a/services/appsync/realtime.go b/services/appsync/realtime.go index 678b29009f..890d9f02f7 100644 --- a/services/appsync/realtime.go +++ b/services/appsync/realtime.go @@ -3,7 +3,8 @@ package appsync import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +17,8 @@ import ( "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/validator/rules" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -59,9 +62,9 @@ type rtSub struct { } type rtMessage struct { - ID string `json:"id,omitempty"` - Type string `json:"type"` - Payload json.RawMessage `json:"payload,omitempty"` + ID string `json:"id,omitempty"` + Type string `json:"type"` + Payload jsontext.Value `json:"payload,omitempty"` } type rtStartPayload struct { @@ -95,7 +98,7 @@ func realtimeAuthFromQuery(r *http.Request) map[string]string { } } - _ = json.Unmarshal(dec, &out) + _ = json.Unmarshal(dec, &out, jsonx.V1()) return out } @@ -153,14 +156,14 @@ func (b *InMemoryBackend) startSubscription( ctx context.Context, apiID string, conn *rtConn, msg rtMessage, defaultAuth map[string]string, r *http.Request, ) { var payload rtStartPayload - if err := json.Unmarshal(msg.Payload, &payload); err != nil { + if err := json.Unmarshal(msg.Payload, &payload, jsonx.V1()); err != nil { _ = conn.send(rtError(msg.ID, rtErrBadRequest, "invalid start payload")) return } var req graphqlRequest - if err := json.Unmarshal([]byte(payload.Data), &req); err != nil { + if err := json.Unmarshal([]byte(payload.Data), &req, jsonx.V1()); err != nil { _ = conn.send(rtError(msg.ID, rtErrBadRequest, "payload.data must be a JSON string")) return diff --git a/services/appsync/realtime_test.go b/services/appsync/realtime_test.go index b2d86d7496..8e757c3282 100644 --- a/services/appsync/realtime_test.go +++ b/services/appsync/realtime_test.go @@ -2,7 +2,7 @@ package appsync_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -74,7 +75,7 @@ func newRealtimeFixture(t *testing.T) *rtFixture { func (f *rtFixture) dial(t *testing.T, apiKey string) *websocket.Conn { t.Helper() - hdr, err := json.Marshal(map[string]string{"x-api-key": apiKey}) + hdr, err := json.Marshal(map[string]string{"x-api-key": apiKey}, jsonx.V1()) require.NoError(t, err) d := websocket.Dialer{Subprotocols: []string{"graphql-ws"}} @@ -99,7 +100,7 @@ func readMsg(t *testing.T, conn *websocket.Conn) map[string]any { func startMsg(t *testing.T, id, query, apiKey string) map[string]any { t.Helper() - data, err := json.Marshal(map[string]any{"query": query}) + data, err := json.Marshal(map[string]any{"query": query}, jsonx.V1()) require.NoError(t, err) return map[string]any{ @@ -164,7 +165,7 @@ func TestRealtime_SubscriptionDelivery(t *testing.T) { assert.Equal(t, "data", msg["type"]) assert.Equal(t, "sub1", msg["id"]) - payload, mErr := json.Marshal(msg["payload"]) + payload, mErr := json.Marshal(msg["payload"], jsonx.V1()) require.NoError(t, mErr) assert.JSONEq(t, `{"data":`+tt.want+`}`, string(payload)) diff --git a/services/appsync/resolver_cache.go b/services/appsync/resolver_cache.go index ceb51e4fca..78664c5294 100644 --- a/services/appsync/resolver_cache.go +++ b/services/appsync/resolver_cache.go @@ -1,11 +1,13 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "strings" "time" "github.com/vektah/gqlparser/v2/ast" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -122,7 +124,7 @@ func (p cachePolicy) keyParts(ctxMap map[string]any) map[string]any { } func encodeKey(typeName, fieldName string, parts map[string]any) string { - raw, _ := json.Marshal(parts) + raw, _ := json.Marshal(parts, jsonx.V1()) return typeName + "." + fieldName + "|" + string(raw) } @@ -246,7 +248,7 @@ func (b *InMemoryBackend) evictMatching(apiID, prefix string, want map[string]an } var have map[string]any - if json.Unmarshal([]byte(rest), &have) != nil { + if json.Unmarshal([]byte(rest), &have, jsonx.V1()) != nil { continue } diff --git a/services/appsync/resolver_cache_test.go b/services/appsync/resolver_cache_test.go index 6714696bf4..95baac12c6 100644 --- a/services/appsync/resolver_cache_test.go +++ b/services/appsync/resolver_cache_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -92,10 +93,10 @@ func (f *cacheFixture) query(t *testing.T, q string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out gqlReply - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Empty(t, out.Errors, rec.Body.String()) - raw, err := json.Marshal(out.Data) + raw, err := json.Marshal(out.Data, jsonx.V1()) require.NoError(t, err) return string(raw) diff --git a/services/appsync/resolver_runtime_e2e_test.go b/services/appsync/resolver_runtime_e2e_test.go index ccb2e27ea5..6170f08461 100644 --- a/services/appsync/resolver_runtime_e2e_test.go +++ b/services/appsync/resolver_runtime_e2e_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "sync" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -216,7 +217,7 @@ func (e *runtimeEnv) exec(t *testing.T, query string) gqlReply { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out gqlReply - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out), rec.Body.String()) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()), rec.Body.String()) return out } diff --git a/services/appsync/resolvers_config_test.go b/services/appsync/resolvers_config_test.go index 27e52e78dc..8d53918c36 100644 --- a/services/appsync/resolvers_config_test.go +++ b/services/appsync/resolvers_config_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -503,7 +504,7 @@ func TestListResolvers_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var apiOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut, jsonx.V1())) apiID := apiOut["graphqlApi"].(map[string]any)["apiId"].(string) rec = doRequest(t, h, http.MethodPost, fmt.Sprintf("/v1/apis/%s/datasources", apiID), map[string]any{ @@ -557,7 +558,7 @@ func TestListResolvers_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Resolvers []map[string]any `json:"resolvers"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Resolvers, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/schema_types_test.go b/services/appsync/schema_types_test.go index f1593ecb8a..80b400b107 100644 --- a/services/appsync/schema_types_test.go +++ b/services/appsync/schema_types_test.go @@ -1,7 +1,7 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -266,7 +267,7 @@ func TestListTypes_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var apiOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &apiOut, jsonx.V1())) apiID := apiOut["graphqlApi"].(map[string]any)["apiId"].(string) for i := range 4 { @@ -307,7 +308,7 @@ func TestListTypes_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Types []map[string]any `json:"types"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Types, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) diff --git a/services/appsync/subscription_filter.go b/services/appsync/subscription_filter.go index 9f704f3b9b..7872181764 100644 --- a/services/appsync/subscription_filter.go +++ b/services/appsync/subscription_filter.go @@ -2,7 +2,7 @@ package appsync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "reflect" @@ -10,6 +10,8 @@ import ( "strings" "github.com/vektah/gqlparser/v2/ast" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -30,14 +32,14 @@ type subFilterSet [][]subFilter // plainJSON converts a VTL/JS value into plain JSON-shaped Go values. func plainJSON(v any) (any, error) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, err } var out any - err = json.Unmarshal(raw, &out) + err = json.Unmarshal(raw, &out, jsonx.V1()) return out, err } diff --git a/services/appsync/subscription_filter_test.go b/services/appsync/subscription_filter_test.go index 61ce89079d..5978c89311 100644 --- a/services/appsync/subscription_filter_test.go +++ b/services/appsync/subscription_filter_test.go @@ -1,12 +1,13 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -102,7 +103,7 @@ func TestSubscriptionFilter_AppliedToPublishedEvents(t *testing.T) { msg := next() require.Equal(t, "data", msg["type"], msg) - raw, err := json.Marshal(msg["payload"]) + raw, err := json.Marshal(msg["payload"], jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, `{"data":{"onPut":{"id":"2","title":"`+tt.want+`"}}}`, string(raw), "the filtered-out mutation must not be delivered before the matching one") @@ -207,7 +208,7 @@ export function response(ctx) { f.put(t, "1", "sell") f.put(t, "2", "buy") - raw, err := json.Marshal(next()["payload"]) + raw, err := json.Marshal(next()["payload"], jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, `{"data":{"onPut":{"id":"2","title":"buy"}}}`, string(raw)) } diff --git a/services/appsync/util_ddb.go b/services/appsync/util_ddb.go index 174712b7c1..4ea90d21cc 100644 --- a/services/appsync/util_ddb.go +++ b/services/appsync/util_ddb.go @@ -1,10 +1,12 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func ddbTyped(v any) any { @@ -118,7 +120,7 @@ func utilDynamo() map[string]utilFn { return nil, err } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) return string(b), err } diff --git a/services/appsync/util_esdsl.go b/services/appsync/util_esdsl.go index 8dbe37573c..78ce3da062 100644 --- a/services/appsync/util_esdsl.go +++ b/services/appsync/util_esdsl.go @@ -1,8 +1,10 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -24,7 +26,7 @@ func toQueryDSL(_ *utilEnv, a []any) (any, error) { return nil, err } - b, err := json.Marshal(q) + b, err := json.Marshal(q, jsonx.V1()) return string(b), err } diff --git a/services/appsync/util_extra.go b/services/appsync/util_extra.go index b7ac8f7349..236956226e 100644 --- a/services/appsync/util_extra.go +++ b/services/appsync/util_extra.go @@ -2,7 +2,8 @@ package appsync import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -12,6 +13,7 @@ import ( "golang.org/x/text/unicode/norm" "github.com/blackbirdworks/gopherstack/pkgs/ctxval" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -88,7 +90,7 @@ func s3Object(a []any) (any, error) { ref.Version = argStr(a, s3ObjectArgs) } - b, err := json.Marshal(map[string]any{"s3": ref}) + b, err := json.Marshal(map[string]any{"s3": ref}, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode s3 object: %w", err) } @@ -102,7 +104,7 @@ func s3ObjectJSON(_ *utilEnv, a []any) (any, error) { return nil, err } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) return string(b), err } @@ -112,7 +114,7 @@ func fromS3ObjectJSON(doc string) (any, error) { S3 *s3Ref `json:"s3"` } - if err := json.Unmarshal([]byte(doc), &wrapper); err != nil || wrapper.S3 == nil { + if err := json.Unmarshal([]byte(doc), &wrapper, jsonx.V1()); err != nil || wrapper.S3 == nil { return nil, fmt.Errorf("%w: not a DynamoDB S3 object", ErrValidation) } @@ -234,10 +236,9 @@ func xmlToJSONString(u *utilEnv, a []any) (any, error) { var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) + enc := jsontext.NewEncoder(&buf, jsonx.V1(), jsontext.EscapeForHTML(false)) - if err = enc.Encode(m); err != nil { + if err = json.MarshalEncode(enc, m); err != nil { return nil, fmt.Errorf("encode xml: %w", err) } diff --git a/services/appsync/util_funcs.go b/services/appsync/util_funcs.go index 4d69793682..30e0a48141 100644 --- a/services/appsync/util_funcs.go +++ b/services/appsync/util_funcs.go @@ -3,7 +3,7 @@ package appsync import ( "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "math/big" @@ -14,6 +14,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resolverError is an error raised from a mapping template or handler @@ -168,13 +170,13 @@ func utilCore() map[string]utilFn { return newKSUID(), nil }, "toJson": func(_ *utilEnv, a []any) (any, error) { - b, err := json.Marshal(argAt(a, 0)) + b, err := json.Marshal(argAt(a, 0), jsonx.V1()) return string(b), err }, "parseJson": func(_ *utilEnv, a []any) (any, error) { var v any - if err := json.Unmarshal([]byte(argStr(a, 0)), &v); err != nil { + if err := json.Unmarshal([]byte(argStr(a, 0)), &v, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON", ErrValidation) } @@ -405,7 +407,7 @@ func fmtNum(v any) string { return strconv.Itoa(t) case float64: return strconv.FormatFloat(t, 'f', -1, 64) - case json.Number: + case jsonx.Number: return t.String() } diff --git a/services/appsync/util_rds.go b/services/appsync/util_rds.go index cbbf19a5a3..b17c94b005 100644 --- a/services/appsync/util_rds.go +++ b/services/appsync/util_rds.go @@ -1,8 +1,10 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const rdsLongValue = "longValue" @@ -21,7 +23,7 @@ func utilRDS() map[string]utilFn { return nil, err } - raw, err := json.Marshal(objs) + raw, err := json.Marshal(objs, jsonx.V1()) return string(raw), err }, @@ -52,7 +54,7 @@ func rdsResultRoot(v any) (map[string]any, error) { return t, nil case string: var m map[string]any - if err := json.Unmarshal([]byte(t), &m); err != nil { + if err := json.Unmarshal([]byte(t), &m, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid RDS result JSON", ErrValidation) } diff --git a/services/appsync/vtl.go b/services/appsync/vtl.go index b7385fe9b1..38a4d9efbc 100644 --- a/services/appsync/vtl.go +++ b/services/appsync/vtl.go @@ -1,15 +1,17 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // renderVTL renders tmpl with the given arguments and result as the context. func renderVTL(tmpl string, args map[string]any, result any) (string, error) { if tmpl == "" { if result != nil { - b, err := json.Marshal(result) + b, err := json.Marshal(result, jsonx.V1()) return string(b), err } @@ -39,7 +41,7 @@ func returnedString(v any) string { return s } - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return string(b) } @@ -59,7 +61,7 @@ func vtlOutputValue(out vtlOutcome) any { } func toDynamoDBJSON(val any) string { - b, _ := json.Marshal(ddbTyped(val)) + b, _ := json.Marshal(ddbTyped(val), jsonx.V1()) return string(b) } diff --git a/services/appsync/vtl_eval.go b/services/appsync/vtl_eval.go index c44bc5044b..28ef040e88 100644 --- a/services/appsync/vtl_eval.go +++ b/services/appsync/vtl_eval.go @@ -1,12 +1,14 @@ package appsync import ( - "encoding/json" + "encoding/json/v2" "fmt" "math" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -23,7 +25,7 @@ func (l *vlist) MarshalJSON() ([]byte, error) { return []byte("[]"), nil } - return json.Marshal(l.items) + return json.Marshal(l.items, jsonx.V1()) } // vns is a utility namespace reference ($util, $util.time, ...). @@ -763,7 +765,7 @@ func toNum(v any) (float64, bool, bool) { return float64(t), true, true case float64: return t, false, true - case json.Number: + case jsonx.Number: if i, err := t.Int64(); err == nil { return float64(i), true, true } @@ -805,7 +807,7 @@ func vrender(v any) string { return strconv.Itoa(t) case float64: return renderFloat(t) - case json.Number: + case jsonx.Number: return t.String() case *vlist: parts := make([]string, len(t.items)) @@ -867,7 +869,7 @@ func vnorm(v any) any { } return t - case json.Number: + case jsonx.Number: if i, err := t.Int64(); err == nil { return i } diff --git a/services/appsync/wire_field_fixes_test.go b/services/appsync/wire_field_fixes_test.go index f77ce59de4..1010828c22 100644 --- a/services/appsync/wire_field_fixes_test.go +++ b/services/appsync/wire_field_fixes_test.go @@ -1,7 +1,8 @@ package appsync_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -126,7 +128,7 @@ func TestGraphqlApi_EnvironmentVariablesNotLeaked(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) graphqlAPI, ok := resp["graphqlApi"].(map[string]any) require.True(t, ok) @@ -138,7 +140,7 @@ func TestGraphqlApi_EnvironmentVariablesNotLeaked(t *testing.T) { require.Equal(t, 200, envRec.Code) var envResp map[string]any - require.NoError(t, json.NewDecoder(envRec.Body).Decode(&envResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(envRec.Body), &envResp, jsonx.V1())) envVars, ok := envResp["environmentVariables"].(map[string]any) require.True(t, ok) assert.Equal(t, "super-secret-value", envVars["DB_PASSWORD"]) diff --git a/services/appsync/wire_shape.go b/services/appsync/wire_shape.go index 331babb185..1074ad6c59 100644 --- a/services/appsync/wire_shape.go +++ b/services/appsync/wire_shape.go @@ -1,17 +1,21 @@ package appsync -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // wireShape re-encodes v without the internal-only keys drop from its top-level // object (or from each element when v is a slice). func wireShape(v any, drop ...string) any { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } var decoded any - if json.Unmarshal(raw, &decoded) != nil { + if json.Unmarshal(raw, &decoded, jsonx.V1()) != nil { return v } diff --git a/services/appsync/wire_shape_test.go b/services/appsync/wire_shape_test.go index 6117d2f026..906404383d 100644 --- a/services/appsync/wire_shape_test.go +++ b/services/appsync/wire_shape_test.go @@ -1,13 +1,14 @@ package appsync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appsync" ) @@ -62,7 +63,7 @@ func TestWire_NoInternalAPIID(t *testing.T) { require.Equal(t, http.StatusOK, list.Code) var out map[string][]map[string]any - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out[tt.listKey]) for _, item := range out[tt.listKey] { diff --git a/services/arczonalshift/handler_ops.go b/services/arczonalshift/handler_ops.go index 4cafe0a6e1..23283a1804 100644 --- a/services/arczonalshift/handler_ops.go +++ b/services/arczonalshift/handler_ops.go @@ -2,9 +2,11 @@ package arczonalshift import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -121,9 +123,9 @@ func (h *Handler) updatePractice(_ context.Context, req *restroute.Request) (any return nil, 0, err } - var present map[string]json.RawMessage + var present map[string]jsontext.Value if len(req.Body) > 0 { - _ = json.Unmarshal(req.Body, &present) + _ = json.Unmarshal(req.Body, &present, jsonx.V1()) } set := map[string]bool{} diff --git a/services/arczonalshift/managed_more.go b/services/arczonalshift/managed_more.go index 189b10f9d9..c9c34717b7 100644 --- a/services/arczonalshift/managed_more.go +++ b/services/arczonalshift/managed_more.go @@ -1,12 +1,13 @@ package arczonalshift import ( - "encoding/json" + "encoding/json/v2" "slices" "strings" awsarn "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" "github.com/blackbirdworks/gopherstack/pkgs/service" asgbackend "github.com/blackbirdworks/gopherstack/services/autoscaling" @@ -162,7 +163,7 @@ func clusterZonalShiftEnabled(c *eksbackend.Cluster) bool { Enabled bool `json:"enabled"` } - return json.Unmarshal(raw, &cfg) == nil && cfg.Enabled + return json.Unmarshal(raw, &cfg, jsonx.V1()) == nil && cfg.Enabled } func (b *InMemoryBackend) managedCluster(arn string, p awsarn.ARN) (managedResource, error) { diff --git a/services/arczonalshift/managed_resources_test.go b/services/arczonalshift/managed_resources_test.go index 4c4027f9c3..0c13b9a4af 100644 --- a/services/arczonalshift/managed_resources_test.go +++ b/services/arczonalshift/managed_resources_test.go @@ -2,7 +2,7 @@ package arczonalshift_test import ( "context" - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -67,7 +67,7 @@ func (w *managedWorld) group(t *testing.T, name string, enabled bool) string { return g.AutoScalingGroupARN } -func (w *managedWorld) cluster(t *testing.T, name string, zonalShift json.RawMessage) string { +func (w *managedWorld) cluster(t *testing.T, name string, zonalShift jsontext.Value) string { t.Helper() vpc, err := w.ec2.CreateVpc("10.0.0.0/16", "") @@ -84,7 +84,7 @@ func (w *managedWorld) cluster(t *testing.T, name string, zonalShift json.RawMes opts := eksbk.ClusterOptionalConfig{} if zonalShift != nil { - opts.ConfigBlocks = map[string]json.RawMessage{"zonalShiftConfig": zonalShift} + opts.ConfigBlocks = map[string]jsontext.Value{"zonalShiftConfig": zonalShift} } c, err := w.eks.CreateCluster(name, "1.31", "arn:aws:iam::"+testAccount+":role/eks", @@ -127,7 +127,7 @@ func TestManagedResourcesAutoScalingAndEKS(t *testing.T) { create: func(t *testing.T, w *managedWorld) string { t.Helper() - return w.cluster(t, "k8s", json.RawMessage(`{"enabled":true}`)) + return w.cluster(t, "k8s", jsontext.Value(`{"enabled":true}`)) }, }, { @@ -135,7 +135,7 @@ func TestManagedResourcesAutoScalingAndEKS(t *testing.T) { create: func(t *testing.T, w *managedWorld) string { t.Helper() - return w.cluster(t, "k8s", json.RawMessage(`{"enabled":false}`)) + return w.cluster(t, "k8s", jsontext.Value(`{"enabled":false}`)) }, }, { diff --git a/services/arczonalshift/misc_test.go b/services/arczonalshift/misc_test.go index 067f3017e1..dccd0539d5 100644 --- a/services/arczonalshift/misc_test.go +++ b/services/arczonalshift/misc_test.go @@ -1,7 +1,7 @@ package arczonalshift_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdkcheck" zs "github.com/blackbirdworks/gopherstack/services/arczonalshift" ) @@ -158,7 +159,7 @@ func TestErrorBodyShape(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Header().Get("X-Amzn-Errortype")) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body["message"]) assert.Equal(t, body["message"], body["Message"]) assert.False(t, strings.HasPrefix(body["message"].(string), tt.wantCode)) diff --git a/services/arczonalshift/persistence.go b/services/arczonalshift/persistence.go index 4e237a5ddc..6251681699 100644 --- a/services/arczonalshift/persistence.go +++ b/services/arczonalshift/persistence.go @@ -2,7 +2,7 @@ package arczonalshift import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -13,8 +13,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. It implements persistence.Persistable. diff --git a/services/athena/audit_athena_test.go b/services/athena/audit_athena_test.go index 4d1b1e16bf..c9fbfb1d91 100644 --- a/services/athena/audit_athena_test.go +++ b/services/athena/audit_athena_test.go @@ -1,13 +1,15 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAuditAthena_ResultReuseConfiguration_StoredAndReturned verifies that @@ -254,7 +256,7 @@ func TestAuditAthena_EnforceWorkGroupConfiguration_OverridesOutputLocation(t *te wgCfgJSON, _ := json.Marshal(map[string]any{ "EnforceWorkGroupConfiguration": tc.enforceWGConfig, "ResultConfiguration": map[string]any{"OutputLocation": tc.wgOutputLocation}, - }) + }, jsonx.V1()) rec := a1Do(t, h, "CreateWorkGroup", fmt.Sprintf(`{"Name":"enforce-wg","Configuration":%s}`, string(wgCfgJSON))) require.Equal(t, http.StatusOK, rec.Code) @@ -266,7 +268,7 @@ func TestAuditAthena_EnforceWorkGroupConfiguration_OverridesOutputLocation(t *te "ResultConfiguration": map[string]any{ "OutputLocation": tc.perQueryLocation, }, - }) + }, jsonx.V1()) rec2 := a1Do(t, h, "StartQueryExecution", string(startBody)) require.Equal(t, http.StatusOK, rec2.Code) @@ -400,7 +402,7 @@ func TestAuditAthena_BatchGetQueryExecution_Shape(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - idsJSON, _ := json.Marshal(tc.ids) + idsJSON, _ := json.Marshal(tc.ids, jsonx.V1()) batchRec := a1Do(t, h, "BatchGetQueryExecution", fmt.Sprintf(`{"QueryExecutionIds":%s}`, string(idsJSON))) require.Equal(t, http.StatusOK, batchRec.Code) @@ -471,7 +473,7 @@ func TestAuditAthena_WorkGroup_EnforceEncryption(t *testing.T) { "EncryptionOption": "SSE_S3", }, }, - }) + }, jsonx.V1()) rec := a1Do(t, h, "CreateWorkGroup", fmt.Sprintf(`{"Name":"enc-wg","Configuration":%s}`, string(wgCfg))) diff --git a/services/athena/client_token_test.go b/services/athena/client_token_test.go index 711a9dbc09..09ed31c8fb 100644 --- a/services/athena/client_token_test.go +++ b/services/athena/client_token_test.go @@ -1,12 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ClientRequestTokenReplay(t *testing.T) { @@ -153,7 +155,7 @@ func TestHandler_StartSessionTags(t *testing.T) { require.Equal(t, http.StatusOK, tagged.Code, tagged.Body.String()) var out tagList - require.NoError(t, json.Unmarshal(tagged.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(tagged.Body.Bytes(), &out, jsonx.V1())) got := map[string]string{} for _, tg := range out.Tags { @@ -182,7 +184,7 @@ func TestHandler_StartSessionCopyWorkGroupTags(t *testing.T) { require.Equal(t, http.StatusOK, tagged.Code, tagged.Body.String()) var out tagList - require.NoError(t, json.Unmarshal(tagged.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(tagged.Body.Bytes(), &out, jsonx.V1())) got := map[string]string{} for _, tg := range out.Tags { diff --git a/services/athena/ddl_test.go b/services/athena/ddl_test.go index 00f0bb7b0a..ab89b2c897 100644 --- a/services/athena/ddl_test.go +++ b/services/athena/ddl_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -278,7 +279,7 @@ func startQueryBody(query string) string { "Catalog": testCatalog, "Database": testDatabase, }, - }) + }, jsonx.V1()) return string(body) } @@ -306,7 +307,7 @@ func TestExecuteStatement_InsertThenSelect(t *testing.T) { insExec := doRequest(t, h, "GetQueryExecution", `{"QueryExecutionId":"`+insID+`"}`) var insResp map[string]any - require.NoError(t, json.Unmarshal(insExec.Body.Bytes(), &insResp)) + require.NoError(t, json.Unmarshal(insExec.Body.Bytes(), &insResp, jsonx.V1())) status := insResp["QueryExecution"].(map[string]any)["Status"].(map[string]any) assert.Equal(t, "SUCCEEDED", status["State"]) @@ -316,7 +317,7 @@ func TestExecuteStatement_InsertThenSelect(t *testing.T) { require.Equal(t, http.StatusOK, results.Code) var resResp map[string]any - require.NoError(t, json.Unmarshal(results.Body.Bytes(), &resResp)) + require.NoError(t, json.Unmarshal(results.Body.Bytes(), &resResp, jsonx.V1())) rs := resResp["ResultSet"].(map[string]any) rows := rs["Rows"].([]any) diff --git a/services/athena/engine_complex.go b/services/athena/engine_complex.go index e32bb1b14a..4f1663d821 100644 --- a/services/athena/engine_complex.go +++ b/services/athena/engine_complex.go @@ -3,7 +3,8 @@ package athena import ( "bytes" "database/sql/driver" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "sort" @@ -11,6 +12,8 @@ import ( "strings" sqlitedriver "modernc.org/sqlite" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // containerMark prefixes the JSON text of an ARRAY/MAP value so results render @@ -54,11 +57,10 @@ func complexTypeOf(glueType string) (string, bool) { } func decodeComplex(s string) (any, bool) { - dec := json.NewDecoder(strings.NewReader(strings.TrimPrefix(s, containerMark))) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(strings.TrimPrefix(s, containerMark))) var out any - if err := dec.Decode(&out); err != nil { + if err := json.UnmarshalDecode(dec, &out, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, false } @@ -79,7 +81,7 @@ func trinoString(v any) string { return t case bool: return strconv.FormatBool(t) - case json.Number: + case jsonx.Number: return t.String() case []any: parts := make([]string, len(t)) diff --git a/services/athena/engine_funcs_agg.go b/services/athena/engine_funcs_agg.go index 36849420a5..54c58c1e0b 100644 --- a/services/athena/engine_funcs_agg.go +++ b/services/athena/engine_funcs_agg.go @@ -2,13 +2,15 @@ package athena import ( "database/sql/driver" - "encoding/json" + "encoding/json/v2" "errors" "math" "sort" "strings" sqlitedriver "modernc.org/sqlite" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aggState is one running aggregate; step ignores NULL inputs unless nullsToo. @@ -152,7 +154,7 @@ func jsonElem(v driver.Value) any { if s, ok := v.(string); ok { var parsed any if t := strings.TrimPrefix(s, containerMark); len(t) > 0 && (t[0] == '[' || t[0] == '{') && - json.Unmarshal([]byte(t), &parsed) == nil { + json.Unmarshal([]byte(t), &parsed, jsonx.V1()) == nil { return parsed } } diff --git a/services/athena/engine_funcs_json.go b/services/athena/engine_funcs_json.go index f30a414645..1d81363033 100644 --- a/services/athena/engine_funcs_json.go +++ b/services/athena/engine_funcs_json.go @@ -2,13 +2,15 @@ package athena import ( "database/sql/driver" - "encoding/json" + "encoding/json/v2" "fmt" "math" "slices" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // arrays and maps live in SQLite as JSON text. @@ -20,7 +22,7 @@ func parseJSONArg(v driver.Value) (any, bool) { } var out any - if err := json.Unmarshal([]byte(strings.TrimPrefix(s, containerMark)), &out); err != nil { + if err := json.Unmarshal([]byte(strings.TrimPrefix(s, containerMark)), &out, jsonx.V1()); err != nil { return nil, false } @@ -29,7 +31,7 @@ func parseJSONArg(v driver.Value) (any, bool) { // jsonText encodes an ARRAY/MAP value; containerMark tags it so results render Trino-style. func jsonText(v any) driver.Value { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return sqlNull() } @@ -39,7 +41,7 @@ func jsonText(v any) driver.Value { // jsonPlain encodes a JSON-typed value, which renders as raw JSON text. func jsonPlain(v any) driver.Value { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return sqlNull() } @@ -385,7 +387,7 @@ func udfArrayDistinct(_ *fnCtx, args []driver.Value) (driver.Value, error) { out := make([]any, 0, len(a)) for _, e := range a { - k, _ := json.Marshal(e) + k, _ := json.Marshal(e, jsonx.V1()) if !seen[string(k)] { seen[string(k)] = true out = append(out, e) diff --git a/services/athena/engine_iceberg_meta.go b/services/athena/engine_iceberg_meta.go index 8b03e9da91..1de0a75ce3 100644 --- a/services/athena/engine_iceberg_meta.go +++ b/services/athena/engine_iceberg_meta.go @@ -3,12 +3,13 @@ package athena import ( "context" "database/sql" - "encoding/json" + "encoding/json/v2" "sort" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/iceberg" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // icebergMetaSuffix splits "tbl$snapshots" into the table and metadata table names. @@ -32,7 +33,7 @@ const colSnapshotID = "snapshot_id" func tsText(ms int64) string { return time.UnixMilli(ms).UTC().Format(tsMillisLayout) } func mapJSON(m map[string]string) string { - b, _ := json.Marshal(m) + b, _ := json.Marshal(m, jsonx.V1()) return string(b) } @@ -221,7 +222,7 @@ func (l *tableLoader) filesTable(ctx context.Context, snap iceberg.Snapshot, has for _, f := range append(files.data, files.deletes...) { df := f.entry.DataFile - part, _ := json.Marshal(df.Partition) + part, _ := json.Marshal(df.Partition, jsonx.V1()) rows = append(rows, []any{ int64(df.Content), df.Path, df.Format, int64(f.spec), string(part), df.RecordCount, df.FileSize, }) diff --git a/services/athena/engine_load.go b/services/athena/engine_load.go index 6cf53bc662..799b94a4d6 100644 --- a/services/athena/engine_load.go +++ b/services/athena/engine_load.go @@ -7,7 +7,8 @@ import ( "context" "database/sql" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -17,6 +18,8 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type dataFormat int @@ -454,12 +457,12 @@ func jsonRaw(v any) string { return "" case string: return t - case json.Number: + case jsonx.Number: return t.String() case bool: return strconv.FormatBool(t) default: - b, _ := json.Marshal(t) + b, _ := json.Marshal(t, jsonx.V1()) return string(b) } @@ -475,12 +478,11 @@ func (l *tableLoader) decodeJSON(ctx context.Context, rd io.Reader, f tableForma continue } - dec := json.NewDecoder(bytes.NewReader(line)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(line)) var obj map[string]any - if err := dec.Decode(&obj); err != nil { + if err := json.UnmarshalDecode(dec, &obj, jsonx.V1(), jsonx.UseNumber()); err != nil { if f.ignoreBad { continue } diff --git a/services/athena/engine_parquet.go b/services/athena/engine_parquet.go index 6b0c57108a..6c6ff513c7 100644 --- a/services/athena/engine_parquet.go +++ b/services/athena/engine_parquet.go @@ -3,13 +3,14 @@ package athena import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -124,7 +125,7 @@ func parquetCell(v any) string { case bool: return strconv.FormatBool(t) default: - b, err := json.Marshal(t) + b, err := json.Marshal(t, jsonx.V1()) if err != nil { return fmt.Sprint(t) } diff --git a/services/athena/engine_write_format.go b/services/athena/engine_write_format.go index 61de56b966..78b83648ec 100644 --- a/services/athena/engine_write_format.go +++ b/services/athena/engine_write_format.go @@ -3,10 +3,12 @@ package athena import ( "bytes" "encoding/csv" - "encoding/json" + "encoding/json/v2" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func encodeTextRows(res *sqlResult, rows []int, cols []outCol, delim string) []byte { @@ -63,7 +65,7 @@ func encodeJSONLines(res *sqlResult, rows []int, cols []outCol) []byte { buf.WriteByte(',') } - key, _ := json.Marshal(c.name) + key, _ := json.Marshal(c.name, jsonx.V1()) buf.Write(key) buf.WriteByte(':') @@ -99,7 +101,7 @@ func jsonLiteral(v string, null bool, typ string) string { case kindString, kindText: } - b, _ := json.Marshal(strings.ToValidUTF8(v, "�")) + b, _ := json.Marshal(strings.ToValidUTF8(v, "�"), jsonx.V1()) return string(b) } diff --git a/services/athena/error_codes_test.go b/services/athena/error_codes_test.go index 2df0489093..6106a6af88 100644 --- a/services/athena/error_codes_test.go +++ b/services/athena/error_codes_test.go @@ -1,12 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_DistinctErrorCodes verifies that Athena operations surface the @@ -110,7 +112,7 @@ func TestHandler_DistinctErrorCodes(t *testing.T) { "Athena client errors are HTTP 400") var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"], "error __type must be AWS-accurate for %s", tt.action) diff --git a/services/athena/handler.go b/services/athena/handler.go index 7d1742534f..01967675aa 100644 --- a/services/athena/handler.go +++ b/services/athena/handler.go @@ -2,7 +2,7 @@ package athena import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -266,7 +267,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var env resourceNameEnvelope - if uerr := json.Unmarshal(body, &env); uerr != nil { + if uerr := json.Unmarshal(body, &env, jsonx.V1()); uerr != nil { return "" } @@ -336,7 +337,7 @@ func (h *Handler) doDispatch(_ context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a standardized error response back to the client. @@ -387,7 +388,7 @@ func (h *Handler) handleError( Message: stripExceptionPrefix(reqErr.Error()), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/athena/handler_calculations.go b/services/athena/handler_calculations.go index 369c5ec406..ec285e8322 100644 --- a/services/athena/handler_calculations.go +++ b/services/athena/handler_calculations.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type startCalculationInput struct { SessionID string `json:"SessionId"` @@ -24,7 +28,7 @@ func (h *Handler) calcCoreOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "StartCalculationExecution": func(b []byte) (any, error) { var input startCalculationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -52,7 +56,7 @@ func (h *Handler) calcCoreOps() map[string]athenaActionFn { }, "GetCalculationExecution": func(b []byte) (any, error) { var input calculationIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -73,7 +77,7 @@ func (h *Handler) calcCoreOps() map[string]athenaActionFn { }, "GetCalculationExecutionStatus": func(b []byte) (any, error) { var input calculationIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -86,7 +90,7 @@ func (h *Handler) calcCoreOps() map[string]athenaActionFn { }, "GetCalculationExecutionCode": func(b []byte) (any, error) { var input calculationIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -104,7 +108,7 @@ func (h *Handler) calcControlOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "StopCalculationExecution": func(b []byte) (any, error) { var input calculationIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -117,7 +121,7 @@ func (h *Handler) calcControlOps() map[string]athenaActionFn { }, "ListCalculationExecutions": func(b []byte) (any, error) { var input listCalculationsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_capacity_reservations.go b/services/athena/handler_capacity_reservations.go index cc3b71622c..7eb649ce0f 100644 --- a/services/athena/handler_capacity_reservations.go +++ b/services/athena/handler_capacity_reservations.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type cancelCapacityReservationInput struct { Name string `json:"Name"` @@ -38,7 +42,7 @@ func (h *Handler) capacityReservationOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreateCapacityReservation": func(b []byte) (any, error) { var input createCapacityReservationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -48,7 +52,7 @@ func (h *Handler) capacityReservationOps() map[string]athenaActionFn { }, "CancelCapacityReservation": func(b []byte) (any, error) { var input cancelCapacityReservationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -56,7 +60,7 @@ func (h *Handler) capacityReservationOps() map[string]athenaActionFn { }, "DeleteCapacityReservation": func(b []byte) (any, error) { var input deleteCapacityReservationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -69,7 +73,7 @@ func (h *Handler) capacityExtraOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "GetCapacityReservation": func(b []byte) (any, error) { var input capacityReservationNameInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -82,7 +86,7 @@ func (h *Handler) capacityExtraOps() map[string]athenaActionFn { }, "ListCapacityReservations": func(b []byte) (any, error) { var input listPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -106,7 +110,7 @@ func (h *Handler) capacityExtraOps() map[string]athenaActionFn { }, "UpdateCapacityReservation": func(b []byte) (any, error) { var input updateCapacityReservationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -114,7 +118,7 @@ func (h *Handler) capacityExtraOps() map[string]athenaActionFn { }, "PutCapacityAssignmentConfiguration": func(b []byte) (any, error) { var input putCapacityAssignmentInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -124,7 +128,7 @@ func (h *Handler) capacityExtraOps() map[string]athenaActionFn { }, "GetCapacityAssignmentConfiguration": func(b []byte) (any, error) { var input getCapacityAssignmentInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_capacity_reservations_test.go b/services/athena/handler_capacity_reservations_test.go index e7cf59bddf..72d2851bb5 100644 --- a/services/athena/handler_capacity_reservations_test.go +++ b/services/athena/handler_capacity_reservations_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -51,7 +52,7 @@ func TestHandler_CreateCapacityReservation(t *testing.T) { if tt.wantErr { var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"]) } }) @@ -239,7 +240,7 @@ func TestHandler_CapacityReservation_LastAllocationStruct(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cr := resp["CapacityReservation"].(map[string]any) assert.Equal(t, "ACTIVE", cr["Status"]) @@ -263,7 +264,7 @@ func TestHandler_CapacityReservation_UpdateLastAllocation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cr := resp["CapacityReservation"].(map[string]any) assert.InDelta(t, float64(30), cr["TargetDpus"], 0.001) @@ -330,7 +331,7 @@ func TestHandler_GetCapacityReservation_NoInventedTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasTags := resp["CapacityReservation"]["Tags"] assert.False(t, hasTags, "CapacityReservation response must not carry an invented Tags field") @@ -339,7 +340,7 @@ func TestHandler_GetCapacityReservation_NoInventedTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string][]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) require.Len(t, tagsResp["Tags"], 1, "the tag set at creation must still be visible via ListTagsForResource") assert.Equal(t, "owner", tagsResp["Tags"][0]["Key"]) } diff --git a/services/athena/handler_data_catalogs.go b/services/athena/handler_data_catalogs.go index cbae21ed03..7fd7e37500 100644 --- a/services/athena/handler_data_catalogs.go +++ b/services/athena/handler_data_catalogs.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // dataCatalogRespKey is the JSON response key CreateDataCatalog, // GetDataCatalog, and DeleteDataCatalog all wrap their DataCatalog payload @@ -40,7 +44,7 @@ func (h *Handler) dataCatalogOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreateDataCatalog": func(b []byte) (any, error) { var input createDataCatalogInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -59,7 +63,7 @@ func (h *Handler) dataCatalogOps() map[string]athenaActionFn { }, "GetDataCatalog": func(b []byte) (any, error) { var input getDataCatalogInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -72,7 +76,7 @@ func (h *Handler) dataCatalogOps() map[string]athenaActionFn { }, "ListDataCatalogs": func(b []byte) (any, error) { var input listDataCatalogsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -90,7 +94,7 @@ func (h *Handler) dataCatalogOps() map[string]athenaActionFn { }, "UpdateDataCatalog": func(b []byte) (any, error) { var input updateDataCatalogInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -100,7 +104,7 @@ func (h *Handler) dataCatalogOps() map[string]athenaActionFn { }, "DeleteDataCatalog": func(b []byte) (any, error) { var input deleteDataCatalogInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_data_catalogs_test.go b/services/athena/handler_data_catalogs_test.go index e92165fa74..1aa73a4f20 100644 --- a/services/athena/handler_data_catalogs_test.go +++ b/services/athena/handler_data_catalogs_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -86,7 +87,7 @@ func TestHandler_GetDataCatalog(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dc, _ := resp["DataCatalog"].(map[string]any) require.NotNil(t, dc) assert.Equal(t, tt.wantType, dc["Type"]) @@ -110,7 +111,7 @@ func TestHandler_CreateDataCatalog_ReturnsDataCatalog(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dc, ok := resp["DataCatalog"].(map[string]any) require.True(t, ok, "CreateDataCatalogOutput must carry a DataCatalog object") assert.Equal(t, "created-cat", dc["Name"]) @@ -145,7 +146,7 @@ func TestHandler_ListDataCatalogs(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, _ := resp["DataCatalogsSummary"].([]any) assert.GreaterOrEqual(t, len(list), 1) }) @@ -239,7 +240,7 @@ func TestHandler_DeleteDataCatalog_ReturnsDataCatalog(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dc, ok := resp["DataCatalog"].(map[string]any) require.True(t, ok, "DeleteDataCatalogOutput must carry the deleted DataCatalog object") assert.Equal(t, "del-cat2", dc["Name"]) @@ -300,7 +301,7 @@ func TestHandler_DeleteDataCatalog_FederatedReportsDeleteComplete(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dc, ok := resp["DataCatalog"].(map[string]any) require.True(t, ok) assert.Equal(t, "DELETE_COMPLETE", dc["Status"]) @@ -386,7 +387,7 @@ func TestHandler_DataCatalog_FederatedStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dc := resp["DataCatalog"].(map[string]any) assert.Equal(t, tt.wantStatus, dc["Status"]) @@ -408,7 +409,7 @@ func TestHandler_DataCatalog_ListIncludesStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["DataCatalogsSummary"].([]any) require.True(t, ok) @@ -505,7 +506,7 @@ func TestListDataCatalogs_NextTokenOmittedWhenEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasNextToken := resp["NextToken"] assert.False(t, hasNextToken, @@ -627,7 +628,7 @@ func TestAwsDataCatalog_BuiltIn(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) diff --git a/services/athena/handler_databases.go b/services/athena/handler_databases.go index af22e51b24..b1d85b9519 100644 --- a/services/athena/handler_databases.go +++ b/services/athena/handler_databases.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type getDatabaseInput struct { CatalogName string `json:"CatalogName"` @@ -31,7 +35,7 @@ func (h *Handler) databaseOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "GetDatabase": func(b []byte) (any, error) { var input getDatabaseInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -44,7 +48,7 @@ func (h *Handler) databaseOps() map[string]athenaActionFn { }, "ListDatabases": func(b []byte) (any, error) { var input listDatabasesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -68,7 +72,7 @@ func (h *Handler) databaseOps() map[string]athenaActionFn { }, "GetTableMetadata": func(b []byte) (any, error) { var input getTableMetadataInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -81,7 +85,7 @@ func (h *Handler) databaseOps() map[string]athenaActionFn { }, "ListTableMetadata": func(b []byte) (any, error) { var input listTableMetadataInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_named_queries.go b/services/athena/handler_named_queries.go index c458c88472..97d0c416e4 100644 --- a/services/athena/handler_named_queries.go +++ b/services/athena/handler_named_queries.go @@ -1,8 +1,10 @@ package athena import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createNamedQueryInput struct { @@ -44,7 +46,7 @@ func (h *Handler) namedQueryOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreateNamedQuery": func(b []byte) (any, error) { var input createNamedQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -65,7 +67,7 @@ func (h *Handler) namedQueryOps() map[string]athenaActionFn { }, "GetNamedQuery": func(b []byte) (any, error) { var input getNamedQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -78,7 +80,7 @@ func (h *Handler) namedQueryOps() map[string]athenaActionFn { }, "ListNamedQueries": func(b []byte) (any, error) { var input listNamedQueriesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -100,7 +102,7 @@ func (h *Handler) namedQueryOps() map[string]athenaActionFn { }, "BatchGetNamedQuery": func(b []byte) (any, error) { var input batchGetNamedQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -121,7 +123,7 @@ func (h *Handler) namedQueryOps() map[string]athenaActionFn { }, "DeleteNamedQuery": func(b []byte) (any, error) { var input deleteNamedQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -136,7 +138,7 @@ func (h *Handler) namedQueryUpdateOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "UpdateNamedQuery": func(b []byte) (any, error) { var input updateNamedQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_named_queries_test.go b/services/athena/handler_named_queries_test.go index dc103000fc..c712851e37 100644 --- a/services/athena/handler_named_queries_test.go +++ b/services/athena/handler_named_queries_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -39,7 +40,7 @@ func TestHandler_CreateNamedQuery(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["NamedQueryId"]) } }) @@ -80,7 +81,7 @@ func TestHandler_GetNamedQuery(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) queryID = created["NamedQueryId"] } @@ -89,7 +90,7 @@ func TestHandler_GetNamedQuery(t *testing.T) { if tt.wantQuery { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nq, _ := resp["NamedQuery"].(map[string]any) require.NotNil(t, nq) assert.Equal(t, "q", nq["Name"]) @@ -127,7 +128,7 @@ func TestHandler_ListNamedQueries(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string][]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["NamedQueryIds"], tt.wantCount) }) } @@ -157,7 +158,7 @@ func TestHandler_BatchGetNamedQuery(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) id := created["NamedQueryId"] rec := doRequest(t, h, "BatchGetNamedQuery", @@ -165,7 +166,7 @@ func TestHandler_BatchGetNamedQuery(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found, _ := resp["NamedQueries"].([]any) assert.Len(t, found, 1) unprocessed, _ := resp["UnprocessedNamedQueryIds"].([]any) @@ -203,7 +204,7 @@ func TestHandler_DeleteNamedQuery(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) rec := doRequest(t, h, "DeleteNamedQuery", `{"NamedQueryId":"`+cr["NamedQueryId"]+`"}`) assert.Equal(t, tt.wantStatus, rec.Code) @@ -430,14 +431,14 @@ func TestBatchGetNamedQuery_UnprocessedShape(t *testing.T) { } } - body, err := json.Marshal(map[string]any{"NamedQueryIds": tt.ids}) + body, err := json.Marshal(map[string]any{"NamedQueryIds": tt.ids}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, "BatchGetNamedQuery", string(body)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found, _ := resp["NamedQueries"].([]any) assert.Len(t, found, tt.wantFound) @@ -492,7 +493,7 @@ func TestCreateNamedQuery_WorkgroupValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "InvalidRequestException") } }) diff --git a/services/athena/handler_notebooks.go b/services/athena/handler_notebooks.go index b709648519..e891982adf 100644 --- a/services/athena/handler_notebooks.go +++ b/services/athena/handler_notebooks.go @@ -1,8 +1,10 @@ package athena import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createNotebookInput has no Tags: the real CreateNotebookInput carries only Name/WorkGroup/ClientRequestToken. @@ -88,7 +90,7 @@ func (h *Handler) notebookOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreateNotebook": func(b []byte) (any, error) { var input createNotebookInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -105,7 +107,7 @@ func (h *Handler) notebookOps() map[string]athenaActionFn { }, "CreatePresignedNotebookUrl": func(b []byte) (any, error) { var input createPresignedNotebookURLInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -129,7 +131,7 @@ func (h *Handler) notebookOps() map[string]athenaActionFn { }, "DeleteNotebook": func(b []byte) (any, error) { var input deleteNotebookInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -137,7 +139,7 @@ func (h *Handler) notebookOps() map[string]athenaActionFn { }, "ExportNotebook": func(b []byte) (any, error) { var input exportNotebookInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -158,7 +160,7 @@ func (h *Handler) notebookExtraOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "GetNotebookMetadata": func(b []byte) (any, error) { var input notebookIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -171,7 +173,7 @@ func (h *Handler) notebookExtraOps() map[string]athenaActionFn { }, "ListNotebookMetadata": func(b []byte) (any, error) { var input listNotebookMetadataInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -195,7 +197,7 @@ func (h *Handler) notebookExtraOps() map[string]athenaActionFn { }, "ImportNotebook": func(b []byte) (any, error) { var input importNotebookInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -218,7 +220,7 @@ func (h *Handler) notebookExtraOps() map[string]athenaActionFn { }, "UpdateNotebook": func(b []byte) (any, error) { var input updateNotebookInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -226,7 +228,7 @@ func (h *Handler) notebookExtraOps() map[string]athenaActionFn { }, "UpdateNotebookMetadata": func(b []byte) (any, error) { var input updateNotebookMetadataInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_notebooks_test.go b/services/athena/handler_notebooks_test.go index 2b46915723..dcec04c9ea 100644 --- a/services/athena/handler_notebooks_test.go +++ b/services/athena/handler_notebooks_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -38,7 +39,7 @@ func TestHandler_CreateNotebook(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["NotebookId"]) } }) @@ -74,7 +75,7 @@ func TestHandler_CreatePresignedNotebookUrl(t *testing.T) { if tt.wantURL { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["NotebookUrl"], tt.sessionID) assert.NotEmpty(t, resp["AuthToken"]) assert.Positive(t, resp["AuthTokenExpirationTime"]) @@ -98,7 +99,7 @@ func TestHandler_DeleteNotebook(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) return cr["NotebookId"] }, @@ -142,7 +143,7 @@ func TestHandler_ExportNotebook(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) return cr["NotebookId"] }, @@ -170,7 +171,7 @@ func TestHandler_ExportNotebook(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta, _ := resp["NotebookMetadata"].(map[string]any) require.NotNil(t, meta, "NotebookMetadata should be present") assert.Equal(t, tt.wantName, meta["Name"]) diff --git a/services/athena/handler_prepared_statements.go b/services/athena/handler_prepared_statements.go index 96ef54cb51..0f0487c292 100644 --- a/services/athena/handler_prepared_statements.go +++ b/services/athena/handler_prepared_statements.go @@ -1,8 +1,10 @@ package athena import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // batchGetPreparedStatementInput's StatementNames field is tagged @@ -49,7 +51,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreatePreparedStatement": func(b []byte) (any, error) { var input createPreparedStatementInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -59,7 +61,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { }, "BatchGetPreparedStatement": func(b []byte) (any, error) { var input batchGetPreparedStatementInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -83,7 +85,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { }, "DeletePreparedStatement": func(b []byte) (any, error) { var input deletePreparedStatementInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -94,7 +96,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { }, "GetPreparedStatement": func(b []byte) (any, error) { var input getPreparedStatementInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -107,7 +109,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { }, "ListPreparedStatements": func(b []byte) (any, error) { var input listPreparedStatementsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -129,7 +131,7 @@ func (h *Handler) preparedStatementOps() map[string]athenaActionFn { }, "UpdatePreparedStatement": func(b []byte) (any, error) { var input updatePreparedStatementInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_prepared_statements_test.go b/services/athena/handler_prepared_statements_test.go index a6ba564dc1..2466f86f98 100644 --- a/services/athena/handler_prepared_statements_test.go +++ b/services/athena/handler_prepared_statements_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -52,7 +53,7 @@ func TestHandler_CreatePreparedStatement(t *testing.T) { if tt.wantErr { var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"]) } }) @@ -97,7 +98,7 @@ func TestHandler_BatchGetPreparedStatement(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found, _ := resp["PreparedStatements"].([]any) assert.Len(t, found, tt.wantFound) unprocessed, _ := resp["UnprocessedPreparedStatementNames"].([]any) @@ -225,7 +226,7 @@ func TestHandler_GetPreparedStatement(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ps, _ := resp["PreparedStatement"].(map[string]any) require.NotNil(t, ps, "PreparedStatement must be present") assert.Equal(t, tt.wantName, ps["StatementName"]) @@ -277,7 +278,7 @@ func TestHandler_ListPreparedStatements(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string][]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["PreparedStatements"], tt.wantCount) }) } @@ -294,7 +295,7 @@ func TestHandler_ListPreparedStatements_ReturnsSummary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string][]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp["PreparedStatements"], 1) sum := resp["PreparedStatements"][0] diff --git a/services/athena/handler_query_executions.go b/services/athena/handler_query_executions.go index 0f7db22af4..335c2cbcff 100644 --- a/services/athena/handler_query_executions.go +++ b/services/athena/handler_query_executions.go @@ -1,8 +1,10 @@ package athena import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type startQueryExecutionInput struct { @@ -46,7 +48,7 @@ func (h *Handler) queryExecutionOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "StartQueryExecution": func(b []byte) (any, error) { var input startQueryExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -76,7 +78,7 @@ func (h *Handler) queryExecutionOps() map[string]athenaActionFn { }, "StopQueryExecution": func(b []byte) (any, error) { var input stopQueryExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -84,7 +86,7 @@ func (h *Handler) queryExecutionOps() map[string]athenaActionFn { }, "GetQueryExecution": func(b []byte) (any, error) { var input getQueryExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -98,7 +100,7 @@ func (h *Handler) queryExecutionOps() map[string]athenaActionFn { "ListQueryExecutions": h.handleListQueryExecutions, "BatchGetQueryExecution": func(b []byte) (any, error) { var input batchGetQueryExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -120,7 +122,7 @@ func (h *Handler) queryExecutionOps() map[string]athenaActionFn { "GetQueryResults": h.handleGetQueryResults, "GetQueryRuntimeStatistics": func(b []byte) (any, error) { var input getQueryRuntimeStatsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -142,7 +144,7 @@ const athenaMaxQueryResultsPageSize = 1000 // opaque-token pagination. func (h *Handler) handleListQueryExecutions(b []byte) (any, error) { var input listQueryExecutionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -176,7 +178,7 @@ type getQueryResultsInput struct { // Real rows are returned for SELECT queries against registered in-memory tables. func (h *Handler) handleGetQueryResults(b []byte) (any, error) { var input getQueryResultsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrValidation, err) } diff --git a/services/athena/handler_query_executions_test.go b/services/athena/handler_query_executions_test.go index 96c54cf59f..54eb8396cb 100644 --- a/services/athena/handler_query_executions_test.go +++ b/services/athena/handler_query_executions_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -41,7 +42,7 @@ func TestHandler_StartQueryExecution(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["QueryExecutionId"]) } }) @@ -81,7 +82,7 @@ func TestHandler_GetQueryExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) execID = created["QueryExecutionId"] } @@ -90,7 +91,7 @@ func TestHandler_GetQueryExecution(t *testing.T) { if tt.wantState != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) qe, ok := resp["QueryExecution"].(map[string]any) require.True(t, ok) status, ok := qe["Status"].(map[string]any) @@ -118,7 +119,7 @@ func TestHandler_StopQueryExecution(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr, jsonx.V1())) execID := cr["QueryExecutionId"] // Override state to RUNNING so it can be stopped. @@ -142,7 +143,7 @@ func TestHandler_StopQueryExecution(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr, jsonx.V1())) return cr["QueryExecutionId"] // default state is SUCCEEDED }, @@ -191,7 +192,7 @@ func TestHandler_ListQueryExecutions(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, _ := resp["QueryExecutionIds"].([]any) assert.Len(t, ids, tt.wantCount) }) @@ -221,7 +222,7 @@ func TestHandler_BatchGetQueryExecution(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &cr, jsonx.V1())) id := cr["QueryExecutionId"] rec := doRequest(t, h, "BatchGetQueryExecution", @@ -229,7 +230,7 @@ func TestHandler_BatchGetQueryExecution(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found, _ := resp["QueryExecutions"].([]any) assert.Len(t, found, 1) unprocessed, _ := resp["UnprocessedQueryExecutionIds"].([]any) @@ -272,7 +273,7 @@ func TestHandler_QueryExecution_EngineVersionAndStatementType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) qe := resp["QueryExecution"].(map[string]any) assert.Equal(t, tt.wantStatementType, qe["StatementType"]) @@ -302,7 +303,7 @@ func TestHandler_QueryExecution_ExecutionParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) qe := resp["QueryExecution"].(map[string]any) params, ok := qe["ExecutionParameters"].([]any) @@ -334,7 +335,7 @@ func TestHandler_ResultConfiguration_AclAndOwner(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) qe := resp["QueryExecution"].(map[string]any) rc := qe["ResultConfiguration"].(map[string]any) @@ -522,7 +523,7 @@ func TestStartQueryExecution_EmptyQueryStringRejected(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "InvalidRequestException", "empty QueryString must return InvalidRequestException") } @@ -560,7 +561,7 @@ func TestListQueryExecutions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.QueryExecutionIDs), 2, "page exceeds MaxResults") for _, id := range resp.QueryExecutionIDs { @@ -595,7 +596,7 @@ func TestListQueryExecutions_NextTokenOmittedOnLastPage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasToken := resp["NextToken"] assert.False(t, hasToken, "NextToken must be omitted on the last page") } @@ -760,14 +761,14 @@ func TestBatchGetQueryExecution_UnprocessedShape(t *testing.T) { } } - body, err := json.Marshal(map[string]any{"QueryExecutionIds": tt.ids}) + body, err := json.Marshal(map[string]any{"QueryExecutionIds": tt.ids}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, "BatchGetQueryExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found, _ := resp["QueryExecutions"].([]any) assert.Len(t, found, tt.wantFound) @@ -822,7 +823,7 @@ func TestStartQueryExecution_WorkgroupValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "InvalidRequestException") } }) diff --git a/services/athena/handler_sessions.go b/services/athena/handler_sessions.go index 926628ff9d..39df596131 100644 --- a/services/athena/handler_sessions.go +++ b/services/athena/handler_sessions.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) const ( keySessionID = "SessionId" @@ -72,7 +76,7 @@ type getResourceDashboardInput struct { func (h *Handler) handleStartSession(b []byte) (any, error) { var input startSessionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -123,7 +127,7 @@ func (h *Handler) sessionCoreOps() map[string]athenaActionFn { "StartSession": h.handleStartSession, "GetSession": func(b []byte) (any, error) { var input sessionIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -147,7 +151,7 @@ func (h *Handler) sessionCoreOps() map[string]athenaActionFn { }, "GetSessionStatus": func(b []byte) (any, error) { var input sessionIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -160,7 +164,7 @@ func (h *Handler) sessionCoreOps() map[string]athenaActionFn { }, "GetSessionEndpoint": func(b []byte) (any, error) { var input sessionIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -177,7 +181,7 @@ func (h *Handler) sessionCoreOps() map[string]athenaActionFn { }, "TerminateSession": func(b []byte) (any, error) { var input sessionIDInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -195,7 +199,7 @@ func (h *Handler) sessionListOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "ListSessions": func(b []byte) (any, error) { var input listSessionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -219,7 +223,7 @@ func (h *Handler) sessionListOps() map[string]athenaActionFn { }, "ListNotebookSessions": func(b []byte) (any, error) { var input listNotebookSessionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -250,7 +254,7 @@ func (h *Handler) sessionInfoOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "ListExecutors": func(b []byte) (any, error) { var input listExecutorsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -274,7 +278,7 @@ func (h *Handler) sessionInfoOps() map[string]athenaActionFn { }, "ListEngineVersions": func(b []byte) (any, error) { var input listPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -293,7 +297,7 @@ func (h *Handler) sessionInfoOps() map[string]athenaActionFn { }, "ListApplicationDPUSizes": func(b []byte) (any, error) { var input listPageInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -309,7 +313,7 @@ func (h *Handler) sessionInfoOps() map[string]athenaActionFn { }, "GetResourceDashboard": func(b []byte) (any, error) { var input getResourceDashboardInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_sessions_test.go b/services/athena/handler_sessions_test.go index 4d684ae137..737d6e6cd4 100644 --- a/services/athena/handler_sessions_test.go +++ b/services/athena/handler_sessions_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -17,7 +18,7 @@ func jsonNested(t *testing.T, body []byte, keys ...string) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1())) cur := m for _, k := range keys { @@ -296,7 +297,7 @@ func TestHandler_ListSessions(t *testing.T) { if tt.wantNonEmpty { var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) assert.NotEmpty(t, m["Sessions"]) } }) @@ -409,7 +410,7 @@ func TestHandler_ListNotebookSessions(t *testing.T) { var body struct { NotebookSessionsList []map[string]any `json:"NotebookSessionsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body.NotebookSessionsList, 1, "expected the started session to be linked to its notebook") } }) @@ -458,7 +459,7 @@ func TestHandler_ListEngineVersions_NoInventedAuthEngineVersionField(t *testing. require.Equal(t, http.StatusOK, rec.Code) var resp map[string][]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp["EngineVersions"]) for _, ev := range resp["EngineVersions"] { @@ -744,7 +745,7 @@ func TestGetSessionEndpoint_UsesConfiguredRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) url, _ := resp["EndpointUrl"].(string) assert.Contains(t, url, tt.wantPrefix, diff --git a/services/athena/handler_tags.go b/services/athena/handler_tags.go index 09e77c5e77..27c78fb264 100644 --- a/services/athena/handler_tags.go +++ b/services/athena/handler_tags.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type tagResourceInput struct { ResourceARN string `json:"ResourceARN"` @@ -22,7 +26,7 @@ func (h *Handler) tagOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "TagResource": func(b []byte) (any, error) { var input tagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -30,7 +34,7 @@ func (h *Handler) tagOps() map[string]athenaActionFn { }, "UntagResource": func(b []byte) (any, error) { var input untagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -38,7 +42,7 @@ func (h *Handler) tagOps() map[string]athenaActionFn { }, "ListTagsForResource": func(b []byte) (any, error) { var input listTagsForResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_tags_test.go b/services/athena/handler_tags_test.go index 50c7ae6180..dc35997bfc 100644 --- a/services/athena/handler_tags_test.go +++ b/services/athena/handler_tags_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -98,7 +99,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string][]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Tags"], tt.wantCount) assert.Equal(t, "team", resp["Tags"][0]["Key"]) assert.Equal(t, "platform", resp["Tags"][0]["Value"]) @@ -126,7 +127,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) tags1, _ := page1["Tags"].([]any) require.Len(t, tags1, 2) nextToken, ok := page1["NextToken"].(string) @@ -138,7 +139,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) tags2, _ := page2["Tags"].([]any) require.Len(t, tags2, 1) _, hasNextToken := page2["NextToken"] diff --git a/services/athena/handler_test.go b/services/athena/handler_test.go index b695e90060..f7784b160e 100644 --- a/services/athena/handler_test.go +++ b/services/athena/handler_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -51,7 +52,7 @@ func jsonField(t *testing.T, body []byte, key string) string { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1())) v, ok := m[key] require.True(t, ok, "key %q missing", key) @@ -75,7 +76,7 @@ func athenaDoPass5(t *testing.T, h *athena.Handler, action, body string) *httpte func athenaUnmarshalPass5(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -104,7 +105,7 @@ func a1Unmarshal(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -136,7 +137,7 @@ func TestHandler_UnknownOperation(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"]) }) } diff --git a/services/athena/handler_work_groups.go b/services/athena/handler_work_groups.go index 9835e00e5f..88eb4eddb7 100644 --- a/services/athena/handler_work_groups.go +++ b/services/athena/handler_work_groups.go @@ -1,6 +1,10 @@ package athena -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type listWorkGroupsInput struct { NextToken string `json:"NextToken"` @@ -37,7 +41,7 @@ func (h *Handler) workGroupOps() map[string]athenaActionFn { return map[string]athenaActionFn{ "CreateWorkGroup": func(b []byte) (any, error) { var input createWorkGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -51,7 +55,7 @@ func (h *Handler) workGroupOps() map[string]athenaActionFn { }, "GetWorkGroup": func(b []byte) (any, error) { var input getWorkGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -64,7 +68,7 @@ func (h *Handler) workGroupOps() map[string]athenaActionFn { }, "ListWorkGroups": func(b []byte) (any, error) { var input listWorkGroupsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } list, nextToken, err := h.Backend.ListWorkGroups(input.NextToken, input.MaxResults) @@ -80,7 +84,7 @@ func (h *Handler) workGroupOps() map[string]athenaActionFn { }, "UpdateWorkGroup": func(b []byte) (any, error) { var input updateWorkGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -90,7 +94,7 @@ func (h *Handler) workGroupOps() map[string]athenaActionFn { }, "DeleteWorkGroup": func(b []byte) (any, error) { var input deleteWorkGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/athena/handler_work_groups_test.go b/services/athena/handler_work_groups_test.go index 89a98c38a5..990a069216 100644 --- a/services/athena/handler_work_groups_test.go +++ b/services/athena/handler_work_groups_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -65,7 +66,7 @@ func TestHandler_CreateWorkGroup(t *testing.T) { if tt.wantErr { var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"]) } }) @@ -106,7 +107,7 @@ func TestHandler_GetWorkGroup(t *testing.T) { if tt.wantName != "" { var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["WorkGroup"]["Name"]) } }) @@ -122,7 +123,7 @@ func TestHandler_ListWorkGroups(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string][]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.GreaterOrEqual(t, len(resp["WorkGroups"]), 1) found := false @@ -267,7 +268,7 @@ func TestHandler_GetWorkGroup_NoInventedTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasTags := resp["WorkGroup"]["Tags"] assert.False(t, hasTags, "WorkGroup response must not carry an invented Tags field") @@ -276,7 +277,7 @@ func TestHandler_GetWorkGroup_NoInventedTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string][]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) require.Len(t, tagsResp["Tags"], 1, "the tag set at creation must still be visible via ListTagsForResource") assert.Equal(t, "env", tagsResp["Tags"][0]["Key"]) } @@ -329,7 +330,7 @@ func TestHandler_WorkGroupConfiguration_EnforceAndExtras(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wg := resp["WorkGroup"].(map[string]any) cfg := wg["Configuration"].(map[string]any) @@ -358,7 +359,7 @@ func TestHandler_WorkGroupSummary_IncludesFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string][]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) var found map[string]any for _, wg := range resp["WorkGroups"] { @@ -537,7 +538,7 @@ func TestWorkGroup_StateValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "InvalidRequestException", "invalid State must return InvalidRequestException") } @@ -563,7 +564,7 @@ func TestCreateWorkGroup_AlwaysEnabled_NoStateMember(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wg, ok := resp["WorkGroup"].(map[string]any) require.True(t, ok) assert.Equal(t, "ENABLED", wg["State"], "CreateWorkGroupInput has no State member; must always be ENABLED") @@ -821,7 +822,7 @@ func TestHandler_UpdateWorkGroup_PreservesUnmentionedConfiguration(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wg, ok := resp["WorkGroup"].(map[string]any) require.True(t, ok) cfg, ok := wg["Configuration"].(map[string]any) diff --git a/services/athena/multi_region_test.go b/services/athena/multi_region_test.go index 5181d71bf5..47a77fc6dd 100644 --- a/services/athena/multi_region_test.go +++ b/services/athena/multi_region_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "slices" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -40,7 +41,7 @@ func regionCall(t *testing.T, h *athena.Handler, region, op, body string) map[st require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/athena/pagination_opaque_test.go b/services/athena/pagination_opaque_test.go index e2ad72f24f..4a365fbc2b 100644 --- a/services/athena/pagination_opaque_test.go +++ b/services/athena/pagination_opaque_test.go @@ -1,13 +1,14 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -24,7 +25,7 @@ func listPage(t *testing.T, h *athena.Handler, maxResults int, token string) ([] NextToken string `json:"NextToken"` QueryExecutionIDs []string `json:"QueryExecutionIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp.QueryExecutionIDs, resp.NextToken } @@ -53,7 +54,7 @@ func itoa(n int) string { } func jsonString(s string) string { - b, _ := json.Marshal(s) + b, _ := json.Marshal(s, jsonx.V1()) return string(b) } @@ -142,7 +143,7 @@ func TestPagination_ForgedTokenRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errResp["__type"]) }) } diff --git a/services/athena/persistence.go b/services/athena/persistence.go index 9ab6e55d55..396586a58c 100644 --- a/services/athena/persistence.go +++ b/services/athena/persistence.go @@ -29,7 +29,7 @@ package athena // mirroring services/appsync's apiKeys field. import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -189,7 +189,7 @@ func restoreQueryResults(m map[string]*sqlResultSnapshot) map[string]*sqlResult // - ResourceTags (resourceTags map[string]map[string]string): values are // map[string]string, not *T; already JSON-friendly as-is. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` QueryResults map[string]*sqlResultSnapshot `json:"queryResults,omitempty"` TableData map[string][]map[string]any `json:"tableData,omitempty"` ResourceTags map[string]map[string]string `json:"resourceTags,omitempty"` @@ -310,7 +310,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreDirtyTablesLocked restores the "dirty" tables (databases, tables) // from tables via the ephemeral DTO registry, converting each DTO back to // its live type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, dbDTOs, tblDTOs := newDirtyTableRegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/athena/prepared_exec_test.go b/services/athena/prepared_exec_test.go index 7ec335e2ab..1ed3459dd7 100644 --- a/services/athena/prepared_exec_test.go +++ b/services/athena/prepared_exec_test.go @@ -1,12 +1,13 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -125,7 +126,7 @@ func fetchResultRows(t *testing.T, h *athena.Handler, id string) [][]string { rec := doRequest(t, h, "GetQueryResults", `{"QueryExecutionId":"`+id+`"}`) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rs, _ := resp["ResultSet"].(map[string]any) require.NotNil(t, rs) diff --git a/services/athena/query_results_test.go b/services/athena/query_results_test.go index 03ffbad80c..f1656ce9a3 100644 --- a/services/athena/query_results_test.go +++ b/services/athena/query_results_test.go @@ -1,7 +1,7 @@ package athena_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/athena" ) @@ -107,7 +108,7 @@ func TestGetQueryResults_SQLExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rs, _ := resp["ResultSet"].(map[string]any) require.NotNil(t, rs) @@ -182,7 +183,7 @@ func TestGetQueryResults_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) nextToken, _ := resp1["NextToken"].(string) assert.NotEmpty(t, nextToken, "page 1 must have NextToken") @@ -199,7 +200,7 @@ func TestGetQueryResults_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Empty(t, resp2["NextToken"], "last page must have no NextToken") rs2 := resp2["ResultSet"].(map[string]any) @@ -235,7 +236,7 @@ func TestGetQueryResults_CatalogQualifiedTable(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rs := resp["ResultSet"].(map[string]any) allRows := rs["Rows"].([]any) @@ -311,7 +312,7 @@ func TestHandler_GetQueryResults(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rs, _ := resp["ResultSet"].(map[string]any) require.NotNil(t, rs, "ResultSet should be present") rows, _ := rs["Rows"].([]any) @@ -448,7 +449,7 @@ func TestGetQueryResults_NonSucceededQueryRejected(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "InvalidRequestException", "GetQueryResults on a non-SUCCEEDED query must return InvalidRequestException") msg, _ := errResp["message"].(string) diff --git a/services/athena/result_object.go b/services/athena/result_object.go index 9d33002272..965cdd6e1f 100644 --- a/services/athena/result_object.go +++ b/services/athena/result_object.go @@ -3,12 +3,14 @@ package athena import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "strings" "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" sdk_s3_types "github.com/aws/aws-sdk-go-v2/service/s3/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -80,7 +82,7 @@ func resultMetadata(result *sqlResult) []byte { cols[i] = col{Name: c.name, Type: c.typ} } - out, _ := json.Marshal(map[string]any{"columns": cols}) + out, _ := json.Marshal(map[string]any{"columns": cols}, jsonx.V1()) return out } diff --git a/services/autoscaling/persistence.go b/services/autoscaling/persistence.go index 11c000ed3a..5e68d1c130 100644 --- a/services/autoscaling/persistence.go +++ b/services/autoscaling/persistence.go @@ -2,7 +2,7 @@ package autoscaling import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -35,7 +35,7 @@ const autoscalingSnapshotVersion = 1 // map[string][]T/[]*T fields -- see store_setup.go's registerAllTables doc // for why those three are not store.Table-backed. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Activities map[string][]ScalingActivity `json:"activities"` InstanceRefreshes map[string][]*InstanceRefresh `json:"instanceRefreshes"` NotificationConfigs map[string][]*NotificationConfiguration `json:"notificationConfigs"` diff --git a/services/awsconfig/accounts.go b/services/awsconfig/accounts.go index 96c030130f..002786c91a 100644 --- a/services/awsconfig/accounts.go +++ b/services/awsconfig/accounts.go @@ -1,11 +1,13 @@ package awsconfig import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "regexp" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -98,7 +100,7 @@ func (s *accountSet) snapshot(base []byte, snap func(*Handler) []byte) []byte { } s.mu.RLock("snapshot") - accounts := make(map[string]json.RawMessage, len(s.peers)) + accounts := make(map[string]jsontext.Value, len(s.peers)) for a, p := range s.peers { if data := snap(p); data != nil { @@ -111,19 +113,19 @@ func (s *accountSet) snapshot(base []byte, snap func(*Handler) []byte) []byte { return base } - doc := make(map[string]json.RawMessage) - if err := json.Unmarshal(base, &doc); err != nil { + doc := make(map[string]jsontext.Value) + if err := json.Unmarshal(base, &doc, jsonx.V1()); err != nil { return base } - enc, err := json.Marshal(accounts) + enc, err := json.Marshal(accounts, jsonx.V1()) if err != nil { return base } doc[accountsSnapshotKey] = enc - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return base } @@ -142,10 +144,10 @@ func (s *accountSet) restore(data []byte, restore func(*Handler, []byte) error) } var doc struct { - Accounts map[string]json.RawMessage `json:"accounts"` + Accounts map[string]jsontext.Value `json:"accounts"` } - if err := json.Unmarshal(data, &doc); err != nil { + if err := json.Unmarshal(data, &doc, jsonx.V1()); err != nil { return err } diff --git a/services/awsconfig/conformance_pack_template.go b/services/awsconfig/conformance_pack_template.go index df28b10f3d..80a1720823 100644 --- a/services/awsconfig/conformance_pack_template.go +++ b/services/awsconfig/conformance_pack_template.go @@ -1,10 +1,13 @@ package awsconfig import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "sort" "gopkg.in/yaml.v3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resourceTypeConfigRule is the CloudFormation resource type a conformance @@ -32,7 +35,7 @@ type conformancePackConfigRuleResourceProperties struct { ConfigRuleName string `json:"ConfigRuleName,omitempty"` Description string `json:"Description,omitempty"` MaximumExecutionFrequency string `json:"MaximumExecutionFrequency,omitempty"` - InputParameters json.RawMessage `json:"InputParameters,omitempty"` + InputParameters jsontext.Value `json:"InputParameters,omitempty"` } // conformancePackTemplate is the minimal top-level shape parsed out of a @@ -57,24 +60,24 @@ func parseConformancePackConfigRules( jsonBody := []byte(templateBody) var doc map[string]any - if err := json.Unmarshal(jsonBody, &doc); err != nil { + if err := json.Unmarshal(jsonBody, &doc, jsonx.V1()); err != nil { converted, yamlErr := yamlToJSON(jsonBody) if yamlErr != nil { return nil } - if jsonErr := json.Unmarshal(converted, &doc); jsonErr != nil { + if jsonErr := json.Unmarshal(converted, &doc, jsonx.V1()); jsonErr != nil { return nil } } - resolved, err := json.Marshal(resolveTemplateRefs(doc, templateParamValues(doc, params))) + resolved, err := json.Marshal(resolveTemplateRefs(doc, templateParamValues(doc, params)), jsonx.V1()) if err != nil { return nil } var tmpl conformancePackTemplate - if err = json.Unmarshal(resolved, &tmpl); err != nil { + if err = json.Unmarshal(resolved, &tmpl, jsonx.V1()); err != nil { return nil } @@ -193,7 +196,7 @@ func yamlToJSON(body []byte) ([]byte, error) { return nil, err } - return json.Marshal(v) + return json.Marshal(v, jsonx.V1()) } // rewriteRefTags turns the YAML short form "!Ref Name" into the long form diff --git a/services/awsconfig/delivery_status.go b/services/awsconfig/delivery_status.go index a5a802fe24..462152426b 100644 --- a/services/awsconfig/delivery_status.go +++ b/services/awsconfig/delivery_status.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" s3pkg "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -384,7 +385,7 @@ func buildConfigSnapshotBody(snapshotID string, items []*ResourceConfigItem) ([] envelope.ConfigurationItems = append(envelope.ConfigurationItems, *item) } - encoded, err := json.Marshal(envelope) + encoded, err := json.Marshal(envelope, jsonx.V1()) if err != nil { return nil, err } @@ -461,7 +462,7 @@ func buildSnapshotSNSMessage(snapshotID, bucket, key string, t time.Time) string RecordVersion: configSnapshotNotificationRecordVersion, } - encoded, err := json.Marshal(msg) + encoded, err := json.Marshal(msg, jsonx.V1()) if err != nil { return "" } diff --git a/services/awsconfig/evaluation.go b/services/awsconfig/evaluation.go index bba427a0e3..37c72636cd 100644 --- a/services/awsconfig/evaluation.go +++ b/services/awsconfig/evaluation.go @@ -1,11 +1,13 @@ package awsconfig import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Compliance type constants used by the evaluation engine. @@ -109,7 +111,7 @@ func parseConfiguration(configuration string) map[string]any { } var m map[string]any - if err := json.Unmarshal([]byte(configuration), &m); err != nil { + if err := json.Unmarshal([]byte(configuration), &m, jsonx.V1()); err != nil { return map[string]any{} } @@ -125,7 +127,7 @@ func parseInputParameters(input string) map[string]string { } var raw map[string]any - if err := json.Unmarshal([]byte(input), &raw); err != nil { + if err := json.Unmarshal([]byte(input), &raw, jsonx.V1()); err != nil { return out } @@ -134,7 +136,7 @@ func parseInputParameters(input string) map[string]string { case string: out[k] = tv default: - b, _ := json.Marshal(tv) + b, _ := json.Marshal(tv, jsonx.V1()) out[k] = string(b) } } diff --git a/services/awsconfig/evaluation_test.go b/services/awsconfig/evaluation_test.go index e45be7f172..7f68e1eea2 100644 --- a/services/awsconfig/evaluation_test.go +++ b/services/awsconfig/evaluation_test.go @@ -1,7 +1,7 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -399,7 +400,7 @@ func TestHandler_DescribeConfigRulesPagination(t *testing.T) { NextToken string `json:"NextToken"` ConfigRules []awsconfig.ConfigRule `json:"ConfigRules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.ConfigRules, 100) require.NotEmpty(t, page1.NextToken) @@ -410,7 +411,7 @@ func TestHandler_DescribeConfigRulesPagination(t *testing.T) { NextToken string `json:"NextToken"` ConfigRules []awsconfig.ConfigRule `json:"ConfigRules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.ConfigRules, 50) assert.Empty(t, page2.NextToken) @@ -446,7 +447,7 @@ func TestHandler_GetComplianceDetailsByConfigRule_RealResults(t *testing.T) { var out struct { EvaluationResults []awsconfig.DetailedEvaluationResult `json:"EvaluationResults"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.EvaluationResults, 2) got := complianceByResource(out.EvaluationResults) @@ -475,7 +476,7 @@ func TestHandler_StartResourceEvaluationAndSummary(t *testing.T) { var started struct { ResourceEvaluationID string `json:"ResourceEvaluationId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) require.NotEmpty(t, started.ResourceEvaluationID) assert.NotEqual(t, "eval-stub", started.ResourceEvaluationID) @@ -514,7 +515,7 @@ func TestHandler_GetResourceConfigHistoryPagination(t *testing.T) { NextToken string `json:"nextToken"` ConfigurationItems []awsconfig.ResourceConfigItem `json:"configurationItems"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConfigurationItems, 1) assert.Equal(t, `{"v":2}`, out.ConfigurationItems[0].Configuration) require.NotEmpty(t, out.NextToken) @@ -531,7 +532,7 @@ func TestHandler_GetResourceConfigHistoryPagination(t *testing.T) { NextToken string `json:"nextToken"` ConfigurationItems []awsconfig.ResourceConfigItem `json:"configurationItems"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2, jsonx.V1())) require.Len(t, out2.ConfigurationItems, 1) assert.Equal(t, `{"v":1}`, out2.ConfigurationItems[0].Configuration) assert.Empty(t, out2.NextToken) diff --git a/services/awsconfig/handler.go b/services/awsconfig/handler.go index 5889902770..cb98e61f41 100644 --- a/services/awsconfig/handler.go +++ b/services/awsconfig/handler.go @@ -2,7 +2,8 @@ package awsconfig import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -202,8 +204,8 @@ type configNameBody struct { // extractNamedField extracts a top-level string field by key from a JSON body. func extractNamedField(body []byte, key string) string { - var m map[string]json.RawMessage - if err := json.Unmarshal(body, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { return "" } @@ -213,7 +215,7 @@ func extractNamedField(body []byte, key string) string { } var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return "" } @@ -279,13 +281,13 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // marshalError serialises a typed AWS error response into bytes. // Marshaling a struct with only string fields cannot fail; error is intentionally ignored. func marshalError(errType, message string) []byte { - payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}) + payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}, jsonx.V1()) return payload } @@ -350,15 +352,12 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err } } - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - // configservice@v1.68.4 has no single code that fits every operation here: // ValidationException is modeled on only 38 of its ~102 operations, the rest // use InvalidParameterValueException or model no bad-request-class error at // all (e.g. DeleteConfigurationAggregator declares only // NoSuchConfigurationAggregatorException). Left untyped rather than guessing. - if errors.Is(err, errUnknownAction) || errors.As(err, &syntaxErr) || errors.As(err, &typeErr) { + if errors.Is(err, errUnknownAction) || jsonx.IsSyntaxError(err) || jsonx.IsTypeError(err) { return c.JSON(http.StatusBadRequest, map[string]string{"message": err.Error()}) } diff --git a/services/awsconfig/handler_config_rules_test.go b/services/awsconfig/handler_config_rules_test.go index 61c03acbab..82ce0a4259 100644 --- a/services/awsconfig/handler_config_rules_test.go +++ b/services/awsconfig/handler_config_rules_test.go @@ -1,7 +1,8 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -61,7 +63,7 @@ func TestDescribeConfigRulesAcceptsFilters(t *testing.T) { ConfigRuleName string `json:"ConfigRuleName"` } `json:"ConfigRules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConfigRules, 1) assert.Equal(t, "rule-detective", out.ConfigRules[0].ConfigRuleName) } @@ -125,7 +127,7 @@ func TestConfigRuleScopeRoundtrip(t *testing.T) { } `json:"Scope"` } `json:"ConfigRules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConfigRules, 1) require.NotNil(t, out.ConfigRules[0].Scope) assert.Contains(t, out.ConfigRules[0].Scope.ComplianceResourceTypes, "AWS::S3::Bucket") @@ -251,7 +253,7 @@ func TestAWSConfigHandler_DescribeConfigRulesAndCompliance(t *testing.T) { } var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out[tt.wantField]) }) } @@ -394,11 +396,11 @@ func TestAWSConfigHandler_DescribeConfigRules_BackedByStorage(t *testing.T) { rec := doAWSConfigRequest(t, h, "DescribeConfigRules", tt.body) assert.Equal(t, tt.wantCode, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var rules []any - require.NoError(t, json.Unmarshal(out["ConfigRules"], &rules)) + require.NoError(t, json.Unmarshal(out["ConfigRules"], &rules, jsonx.V1())) assert.Len(t, rules, tt.wantCount) }) } diff --git a/services/awsconfig/handler_configuration_recorders.go b/services/awsconfig/handler_configuration_recorders.go index 4b2e534e3d..1484972f48 100644 --- a/services/awsconfig/handler_configuration_recorders.go +++ b/services/awsconfig/handler_configuration_recorders.go @@ -2,11 +2,12 @@ package awsconfig import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -50,7 +51,7 @@ type extractConfigRecorderNameInput struct { func extractConfigRecorderName(body []byte) string { var req extractConfigRecorderNameInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -59,7 +60,7 @@ func extractConfigRecorderName(body []byte) string { func extractTopLevelRecorderName(body []byte) string { var req configurationRecorderNameInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -72,7 +73,7 @@ type extractFirstRecorderNameInput struct { func extractFirstRecorderName(body []byte) string { var req extractFirstRecorderNameInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } if len(req.ConfigurationRecorderNames) > 0 { diff --git a/services/awsconfig/handler_configuration_recorders_test.go b/services/awsconfig/handler_configuration_recorders_test.go index 333f288072..60326b84ba 100644 --- a/services/awsconfig/handler_configuration_recorders_test.go +++ b/services/awsconfig/handler_configuration_recorders_test.go @@ -1,13 +1,15 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -84,7 +86,7 @@ func TestRecorderRecordingGroupRoundtrip(t *testing.T) { } `json:"recordingGroup"` } `json:"ConfigurationRecorders"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConfigurationRecorders, 1) require.NotNil(t, out.ConfigurationRecorders[0].RecordingGroup) assert.True(t, out.ConfigurationRecorders[0].RecordingGroup.AllSupported) @@ -130,7 +132,7 @@ func TestListConfigurationRecordersSummaries(t *testing.T) { RecordingScope string `json:"recordingScope"` } `json:"ConfigurationRecorderSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConfigurationRecorderSummaries, 1) assert.Equal(t, "default", out.ConfigurationRecorderSummaries[0].Name) assert.Contains(t, out.ConfigurationRecorderSummaries[0].Arn, "arn:aws:config:") @@ -330,7 +332,7 @@ func TestAWSConfigHandler_DescribeConfigurationRecorderStatus(t *testing.T) { } `json:"ConfigurationRecordersStatus"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.ConfigurationRecordersStatus, tt.wantRecordingLen) if tt.wantRecordingLen > 0 { @@ -529,11 +531,11 @@ func TestAWSConfigHandler_DescribeConfigurationRecorders_NameFilter(t *testing.T return } - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var recorders []any - require.NoError(t, json.Unmarshal(out["ConfigurationRecorders"], &recorders)) + require.NoError(t, json.Unmarshal(out["ConfigurationRecorders"], &recorders, jsonx.V1())) assert.Len(t, recorders, tt.wantCount) }) } @@ -565,7 +567,7 @@ func TestAWSConfigHandler_ServiceLinkedConfigurationRecorder(t *testing.T) { Arn string `json:"Arn"` Name string `json:"Name"` } - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) assert.Equal(t, "AWSConfigurationRecorderForGuardduty", putOut.Name) assert.NotEmpty(t, putOut.Arn) @@ -578,7 +580,7 @@ func TestAWSConfigHandler_ServiceLinkedConfigurationRecorder(t *testing.T) { Arn string `json:"Arn"` Name string `json:"Name"` } - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delOut)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delOut, jsonx.V1())) assert.Equal(t, putOut.Name, delOut.Name) // A second delete now 404s (NoSuchConfigurationRecorderException). @@ -682,7 +684,7 @@ func TestAWSConfigHandler_ConnectorsRoundtrip(t *testing.T) { var putOut struct { Arn string `json:"Arn"` } - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) require.NotEmpty(t, putOut.Arn) getRec := doAWSConfigRequest(t, h, "GetConnector", map[string]any{"Arn": putOut.Arn}) @@ -698,7 +700,7 @@ func TestAWSConfigHandler_ConnectorsRoundtrip(t *testing.T) { } `json:"connectorConfiguration"` } `json:"Connector"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, putOut.Arn, getOut.Connector.Arn) assert.Equal(t, "client-1", getOut.Connector.ConnectorConfiguration.Azure.ClientIdentifier) @@ -711,7 +713,7 @@ func TestAWSConfigHandler_ConnectorsRoundtrip(t *testing.T) { Provider string `json:"provider"` } `json:"ConnectorSummaries"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.ConnectorSummaries, 1) assert.Equal(t, putOut.Arn, listOut.ConnectorSummaries[0].Arn) assert.Equal(t, "AZURE", listOut.ConnectorSummaries[0].Provider) @@ -735,7 +737,7 @@ func TestAWSConfigHandler_PutThirdPartyServiceLinkedConfigurationRecorder(t *tes var connOut struct { Arn string `json:"Arn"` } - require.NoError(t, json.Unmarshal(putConnRec.Body.Bytes(), &connOut)) + require.NoError(t, json.Unmarshal(putConnRec.Body.Bytes(), &connOut, jsonx.V1())) body := map[string]any{ "ServicePrincipal": "thirdparty.amazonaws.com", @@ -753,7 +755,7 @@ func TestAWSConfigHandler_PutThirdPartyServiceLinkedConfigurationRecorder(t *tes Arn string `json:"Arn"` Name string `json:"Name"` } - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) assert.NotEmpty(t, putOut.Name) assert.NotEmpty(t, putOut.Arn) @@ -773,7 +775,7 @@ func TestAWSConfigHandler_PutThirdPartyServiceLinkedConfigurationRecorder(t *tes var connOut2 struct { Arn string `json:"Arn"` } - require.NoError(t, json.Unmarshal(putConnRec2.Body.Bytes(), &connOut2)) + require.NoError(t, json.Unmarshal(putConnRec2.Body.Bytes(), &connOut2, jsonx.V1())) conflictBody := map[string]any{ "ServicePrincipal": "thirdparty.amazonaws.com", diff --git a/services/awsconfig/handler_conformance_packs_test.go b/services/awsconfig/handler_conformance_packs_test.go index 66691da435..2027f96109 100644 --- a/services/awsconfig/handler_conformance_packs_test.go +++ b/services/awsconfig/handler_conformance_packs_test.go @@ -1,7 +1,7 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -66,7 +67,7 @@ func TestConformancePackARN(t *testing.T) { DeliveryS3Bucket string `json:"DeliveryS3Bucket"` } `json:"ConformancePackDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConformancePackDetails, 1) assert.Contains(t, out.ConformancePackDetails[0].ConformancePackArn, "arn:aws:config:") assert.NotEmpty(t, out.ConformancePackDetails[0].ConformancePackID) @@ -195,7 +196,7 @@ func TestAWSConfigHandler_PutConformancePack_TemplateBodyDeploysRules(t *testing ComplianceType string `json:"ComplianceType"` } `json:"ConformancePackRuleComplianceList"` } - require.NoError(t, json.Unmarshal(complianceRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(complianceRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConformancePackRuleComplianceList, 1) assert.Equal(t, "rule-a", out.ConformancePackRuleComplianceList[0].ConfigRuleName) assert.Equal(t, "INSUFFICIENT_DATA", out.ConformancePackRuleComplianceList[0].ComplianceType) @@ -233,7 +234,7 @@ func TestAWSConfigHandler_ListConformancePackComplianceScores(t *testing.T) { Score string `json:"Score"` } `json:"ConformancePackComplianceScores"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ConformancePackComplianceScores, 1) assert.Equal(t, "pack1", out.ConformancePackComplianceScores[0].ConformancePackName) assert.Equal(t, "INSUFFICIENT_DATA", out.ConformancePackComplianceScores[0].Score) diff --git a/services/awsconfig/handler_delivery_channels.go b/services/awsconfig/handler_delivery_channels.go index 546375f06a..5a4037a5c7 100644 --- a/services/awsconfig/handler_delivery_channels.go +++ b/services/awsconfig/handler_delivery_channels.go @@ -2,8 +2,9 @@ package awsconfig import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -33,7 +34,7 @@ type extractDeliveryChannelNameInput struct { func extractDeliveryChannelName(body []byte) string { var req extractDeliveryChannelNameInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -46,7 +47,7 @@ type extractFirstDeliveryChannelNameInput struct { func extractFirstDeliveryChannelName(body []byte) string { var req extractFirstDeliveryChannelNameInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } if len(req.DeliveryChannelNames) > 0 { diff --git a/services/awsconfig/handler_delivery_channels_test.go b/services/awsconfig/handler_delivery_channels_test.go index a326843aa1..296889c987 100644 --- a/services/awsconfig/handler_delivery_channels_test.go +++ b/services/awsconfig/handler_delivery_channels_test.go @@ -1,13 +1,15 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -252,11 +254,11 @@ func TestAWSConfigHandler_DescribeDeliveryChannels_NameFilter(t *testing.T) { return } - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var channels []any - require.NoError(t, json.Unmarshal(out["DeliveryChannels"], &channels)) + require.NoError(t, json.Unmarshal(out["DeliveryChannels"], &channels, jsonx.V1())) assert.Len(t, channels, tt.wantCount) }) } diff --git a/services/awsconfig/handler_remediation_test.go b/services/awsconfig/handler_remediation_test.go index 3518b0fc36..a54f9381c9 100644 --- a/services/awsconfig/handler_remediation_test.go +++ b/services/awsconfig/handler_remediation_test.go @@ -1,13 +1,14 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -43,7 +44,7 @@ func TestAWSConfigHandler_StartAndDescribeRemediationExecution(t *testing.T) { State string `json:"State"` } `json:"RemediationExecutionStatuses"` } - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.RemediationExecutionStatuses, 1) assert.Equal(t, "SUCCEEDED", out.RemediationExecutionStatuses[0].State) } diff --git a/services/awsconfig/handler_stored_queries_test.go b/services/awsconfig/handler_stored_queries_test.go index 28da729d77..6095781f5a 100644 --- a/services/awsconfig/handler_stored_queries_test.go +++ b/services/awsconfig/handler_stored_queries_test.go @@ -1,12 +1,14 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListStoredQueriesMetadata verifies ListStoredQueries returns StoredQueryMetadata. @@ -27,7 +29,7 @@ func TestListStoredQueriesMetadata(t *testing.T) { QueryName string `json:"QueryName"` } `json:"StoredQueryMetadata"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.StoredQueryMetadata, 1) assert.Equal(t, "my-query", out.StoredQueryMetadata[0].QueryName) assert.Contains(t, out.StoredQueryMetadata[0].QueryArn, "arn:aws:config:") diff --git a/services/awsconfig/handler_test.go b/services/awsconfig/handler_test.go index 8aa9f3df51..33b44e967d 100644 --- a/services/awsconfig/handler_test.go +++ b/services/awsconfig/handler_test.go @@ -2,7 +2,7 @@ package awsconfig_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -29,7 +30,7 @@ func doAWSConfigRequest(t *testing.T, h *awsconfig.Handler, action string, body var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") diff --git a/services/awsconfig/multi_region_test.go b/services/awsconfig/multi_region_test.go index d8c40df6eb..5a57667fc9 100644 --- a/services/awsconfig/multi_region_test.go +++ b/services/awsconfig/multi_region_test.go @@ -2,7 +2,7 @@ package awsconfig_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/awsconfig/persistence.go b/services/awsconfig/persistence.go index 003a287047..6100adc5f4 100644 --- a/services/awsconfig/persistence.go +++ b/services/awsconfig/persistence.go @@ -2,7 +2,7 @@ package awsconfig import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -126,8 +126,8 @@ func fromRemediationExecutionSnapshot(v *remediationExecutionSnapshot) *Remediat // rather than closing it, per the mechanical-conversion (not parity-fix) // scope of that rollout. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -222,7 +222,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // its "remediationExecutions" DTO entry in tables (gopherstack-ltj0d; // b.remediationExecutions is not on b.registry, see store_setup.go's package // doc and remediationExecutionSnapshot above). -func (b *InMemoryBackend) restoreRemediationExecutionsFromDTO(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreRemediationExecutionsFromDTO(tables map[string]jsontext.Value) error { remDTOReg := store.NewRegistry() remDTOs := store.Register(remDTOReg, "remediationExecutions", store.New(remediationExecutionSnapshotKey)) diff --git a/services/awsconfig/select_query.go b/services/awsconfig/select_query.go index 3efd7ef1df..8caf636af4 100644 --- a/services/awsconfig/select_query.go +++ b/services/awsconfig/select_query.go @@ -1,11 +1,13 @@ package awsconfig import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // select_query.go implements a minimal evaluator for the SQL-like query @@ -170,7 +172,7 @@ func evaluateSelectQuery(items []*ResourceConfigItem, expression string) ([]stri for _, item := range sorted { var config map[string]any - _ = json.Unmarshal([]byte(item.Configuration), &config) + _ = json.Unmarshal([]byte(item.Configuration), &config, jsonx.V1()) if config == nil { config = map[string]any{} @@ -207,7 +209,7 @@ func marshalSelectedFields(item *ResourceConfigItem, config map[string]any, fiel } } - encoded, err := json.Marshal(row) + encoded, err := json.Marshal(row, jsonx.V1()) if err != nil { return "", false } diff --git a/services/awsconfig/select_query_test.go b/services/awsconfig/select_query_test.go index 12c9ed08db..c56fde5c28 100644 --- a/services/awsconfig/select_query_test.go +++ b/services/awsconfig/select_query_test.go @@ -1,12 +1,13 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/v2" "sort" "testing" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -80,7 +81,7 @@ func TestSelectResourceConfig_SelectsRequestedFields(t *testing.T) { } var row map[string]any - if unmarshalErr := json.Unmarshal([]byte(results[0]), &row); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal([]byte(results[0]), &row, jsonx.V1()); unmarshalErr != nil { t.Fatalf("unmarshal row: %v", unmarshalErr) } @@ -116,7 +117,7 @@ func extractResourceIDs(t *testing.T, results []string) []string { for _, r := range results { var row map[string]any - if err := json.Unmarshal([]byte(r), &row); err != nil { + if err := json.Unmarshal([]byte(r), &row, jsonx.V1()); err != nil { t.Fatalf("unmarshal row: %v", err) } diff --git a/services/awsconfig/tags_test.go b/services/awsconfig/tags_test.go index fdd7773579..e6aae1b14d 100644 --- a/services/awsconfig/tags_test.go +++ b/services/awsconfig/tags_test.go @@ -1,12 +1,14 @@ package awsconfig_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/awsconfig" ) @@ -122,7 +124,7 @@ func TestCreationTags_Decoded(t *testing.T) { var out struct { Arn string `json:"Arn"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) return out.Arn }, diff --git a/services/azureappconfig/http_test.go b/services/azureappconfig/http_test.go index c5283516d3..1b1acd452b 100644 --- a/services/azureappconfig/http_test.go +++ b/services/azureappconfig/http_test.go @@ -1,7 +1,7 @@ package azureappconfig_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const av = "api-version=2023-11-01" @@ -22,7 +24,7 @@ func readJSON(t *testing.T, resp *http.Response) map[string]any { var out map[string]any - require.NoError(t, json.Unmarshal(raw, &out), string(raw)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1()), string(raw)) return out } diff --git a/services/azureappconfig/server.go b/services/azureappconfig/server.go index f095c1eb74..2273f31114 100644 --- a/services/azureappconfig/server.go +++ b/services/azureappconfig/server.go @@ -2,7 +2,7 @@ package azureappconfig import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net" "net/http" @@ -11,6 +11,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var apiVersions = map[string]bool{ //nolint:gochecknoglobals // supported api-version set, read-only @@ -156,7 +158,7 @@ func (h *Handler) fail(req *request, err error) error { } func mustJSON(v any) []byte { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return []byte("{}") } @@ -270,7 +272,7 @@ func decodeBody(body []byte, out any) error { return nil } - if err := json.Unmarshal(body, out); err != nil { + if err := json.Unmarshal(body, out, jsonx.V1()); err != nil { return ErrInvalidArgument } diff --git a/services/azurearm/aci_wire.go b/services/azurearm/aci_wire.go index bc98abdeca..b172f1ed8a 100644 --- a/services/azurearm/aci_wire.go +++ b/services/azurearm/aci_wire.go @@ -3,11 +3,14 @@ package azurearm import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -67,7 +70,7 @@ type aciContainerPropsWire struct { VolumeMounts []aciMountWire `json:"volumeMounts,omitempty"` LivenessProbe *aciProbeWire `json:"livenessProbe,omitempty"` ReadinessProbe *aciProbeWire `json:"readinessProbe,omitempty"` - InstanceView json.RawMessage `json:"instanceView,omitempty"` + InstanceView jsontext.Value `json:"instanceView,omitempty"` } type aciContainerWire struct { @@ -97,7 +100,7 @@ type aciAzureFileWire struct { } type aciVolumeWire struct { - EmptyDir *json.RawMessage `json:"emptyDir,omitempty"` + EmptyDir *jsontext.Value `json:"emptyDir,omitempty"` Secret map[string]string `json:"secret,omitempty"` AzureFile *aciAzureFileWire `json:"azureFile,omitempty"` GitRepo *aciGitRepoWire `json:"gitRepo,omitempty"` @@ -114,7 +117,7 @@ type aciPropsWire struct { Priority string `json:"priority,omitempty"` ProvisioningState string `json:"provisioningState,omitempty"` OSType string `json:"osType,omitempty"` - InstanceView json.RawMessage `json:"instanceView,omitempty"` + InstanceView jsontext.Value `json:"instanceView,omitempty"` Volumes []aciVolumeWire `json:"volumes,omitempty"` InitContainers []aciInitWire `json:"initContainers,omitempty"` SubnetIDs []aciSubnetWire `json:"subnetIds,omitempty"` @@ -134,15 +137,14 @@ func aciBad(format string, args ...any) error { func parseACIProps(raw any) (aciPropsWire, error) { var p aciPropsWire - buf, err := json.Marshal(raw) + buf, err := json.Marshal(raw, jsonx.V1()) if err != nil { return p, aciBad("properties: %v", err) } - dec := json.NewDecoder(bytes.NewReader(buf)) - dec.DisallowUnknownFields() + dec := jsontext.NewDecoder(bytes.NewReader(buf)) - if err = dec.Decode(&p); err != nil { + if err = json.UnmarshalDecode(dec, &p, jsonx.V1(), json.RejectUnknownMembers(true)); err != nil { if name, ok := strings.CutPrefix(err.Error(), "json: unknown field "); ok { return p, aciUnsupported("property " + name) } diff --git a/services/azurearm/aci_wire_ext.go b/services/azurearm/aci_wire_ext.go index 2eb689bb17..c8bcf00f09 100644 --- a/services/azurearm/aci_wire_ext.go +++ b/services/azurearm/aci_wire_ext.go @@ -1,7 +1,7 @@ package azurearm import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/netip" "strings" @@ -47,11 +47,11 @@ type aciProbeWire struct { } type aciInitPropsWire struct { - Image string `json:"image"` - Command []string `json:"command,omitempty"` - EnvironmentVariables []aciEnvWire `json:"environmentVariables,omitempty"` - VolumeMounts []aciMountWire `json:"volumeMounts,omitempty"` - InstanceView json.RawMessage `json:"instanceView,omitempty"` + Image string `json:"image"` + Command []string `json:"command,omitempty"` + EnvironmentVariables []aciEnvWire `json:"environmentVariables,omitempty"` + VolumeMounts []aciMountWire `json:"volumeMounts,omitempty"` + InstanceView jsontext.Value `json:"instanceView,omitempty"` } type aciInitWire struct { diff --git a/services/azurearm/aks_sdk_test.go b/services/azurearm/aks_sdk_test.go index d3b7dd46e2..62880fd3e4 100644 --- a/services/azurearm/aks_sdk_test.go +++ b/services/azurearm/aks_sdk_test.go @@ -3,7 +3,7 @@ package azurearm_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -1089,7 +1090,7 @@ func TestAKSSubnetReferences(t *testing.T) { func mustJSON(t *testing.T, v any) string { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/azurearm/apim_asyncop_test.go b/services/azurearm/apim_asyncop_test.go index e6f5f544a9..13967299b2 100644 --- a/services/azurearm/apim_asyncop_test.go +++ b/services/azurearm/apim_asyncop_test.go @@ -1,7 +1,7 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" @@ -16,6 +16,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const apimSvcBody = `{"location":"westus","sku":{"name":"Developer","capacity":1},` + @@ -53,7 +55,7 @@ func statusDoc(t *testing.T, body string) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &m)) + require.NoError(t, json.Unmarshal([]byte(body), &m, jsonx.V1())) return m } diff --git a/services/azurearm/apim_gateway_test.go b/services/azurearm/apim_gateway_test.go index c4e8c90cf2..668cecc2d0 100644 --- a/services/azurearm/apim_gateway_test.go +++ b/services/azurearm/apim_gateway_test.go @@ -2,7 +2,8 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net" "net/http" @@ -15,6 +16,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type echoReply struct { @@ -33,7 +36,7 @@ func newEchoBackend(t *testing.T) *httptest.Server { b, _ := io.ReadAll(r.Body) w.Header().Set("X-Backend", "yes") w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(echoReply{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), echoReply{ Method: r.Method, Path: r.URL.Path, Query: r.URL.RawQuery, @@ -101,7 +104,7 @@ func (e *gwEnv) call(t *testing.T, method, path, body string, extra map[string]s func (e *gwEnv) policy(t *testing.T, scope, doc string, wantStatus int) string { t.Helper() - b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": doc}}) + b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": doc}}, jsonx.V1()) require.NoError(t, err) status, body, _ := e.raw(t, http.MethodPut, e.armPath(scope+"/policies/policy"), string(b), nil) @@ -129,7 +132,7 @@ func decodeEcho(t *testing.T, body string) echoReply { var r echoReply - require.NoError(t, json.Unmarshal([]byte(body), &r), body) + require.NoError(t, json.Unmarshal([]byte(body), &r, jsonx.V1()), body) return r } diff --git a/services/azurearm/apim_policy_test.go b/services/azurearm/apim_policy_test.go index 7f63067614..c8ed9736ef 100644 --- a/services/azurearm/apim_policy_test.go +++ b/services/azurearm/apim_policy_test.go @@ -1,7 +1,7 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAPIMPolicy_Validation(t *testing.T) { @@ -142,7 +144,10 @@ func TestAPIMPolicy_Validation(t *testing.T) { format = "xml" } - b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": format, "value": tc.doc}}) + b, err := json.Marshal( + map[string]any{"properties": map[string]any{"format": format, "value": tc.doc}}, + jsonx.V1(), + ) require.NoError(t, err) status, body, _ := s.raw(t, http.MethodPut, s.armPath("/apis/echo/policies/policy"), string(b), nil) @@ -713,7 +718,7 @@ func TestAPIMGateway_PolicyInheritance(t *testing.T) { e := newGWEnv(t) svcDoc := policyDoc(`s`, "", "") - b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": svcDoc}}) + b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": svcDoc}}, jsonx.V1()) require.NoError(t, err) status, body, _ := e.raw(t, http.MethodPut, e.armPath("/policies/policy"), string(b), nil) diff --git a/services/azurearm/apim_sources_test.go b/services/azurearm/apim_sources_test.go index 94ad5cfbe7..df8da8ad04 100644 --- a/services/azurearm/apim_sources_test.go +++ b/services/azurearm/apim_sources_test.go @@ -1,7 +1,7 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -12,6 +12,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/apimanagement/armapimanagement/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func serviceBody(sku string, capacity int) string { @@ -26,7 +28,7 @@ func decodeProps(t *testing.T, body string) map[string]any { Properties map[string]any `json:"properties"` } - require.NoError(t, json.Unmarshal([]byte(body), &out), body) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1()), body) return out.Properties } @@ -122,7 +124,10 @@ func TestAPIMLimits_PolicySize(t *testing.T) { s.putAPI(t, "echo", "echo", "") doc := "" + strings.Repeat("", tc.bases) + "" - b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": doc}}) + b, err := json.Marshal( + map[string]any{"properties": map[string]any{"format": "xml", "value": doc}}, + jsonx.V1(), + ) require.NoError(t, err) status, body, _ := s.raw(t, http.MethodPut, s.armPath("/apis/echo/policies/policy"), string(b), nil) @@ -581,7 +586,10 @@ func TestAPIMPolicy_ReferenceRules(t *testing.T) { s.devService(t) s.putAPI(t, "echo", "echo", "") - b, err := json.Marshal(map[string]any{"properties": map[string]any{"format": "xml", "value": tc.doc}}) + b, err := json.Marshal( + map[string]any{"properties": map[string]any{"format": "xml", "value": tc.doc}}, + jsonx.V1(), + ) require.NoError(t, err) status, body, _ := s.raw(t, http.MethodPut, s.armPath(tc.scope+"/policies/policy"), string(b), nil) diff --git a/services/azurearm/directory_test.go b/services/azurearm/directory_test.go index 5ac05623bb..225dee39c3 100644 --- a/services/azurearm/directory_test.go +++ b/services/azurearm/directory_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -108,7 +109,7 @@ func TestTokenEndpointClientAuthentication(t *testing.T) { require.Equal(t, tt.status, rec.Code, rec.Body.String()) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) if tt.wantCode != 0 { assert.Equal(t, "invalid_client", body["error"]) diff --git a/services/azurearm/export_test.go b/services/azurearm/export_test.go index fa18fb2638..3f29d2430a 100644 --- a/services/azurearm/export_test.go +++ b/services/azurearm/export_test.go @@ -1,11 +1,13 @@ package azurearm import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // This file exposes internals needed by the blackbox (azurearm_test) test @@ -52,7 +54,7 @@ func NewTestHandlerWithCosmos(dataPlane CosmosResources, settings Settings) *Han // EventHubSnapshotJSON marshals the provider's ARM-side snapshot. func EventHubSnapshotJSON(p *EventHubProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -63,7 +65,7 @@ func EventHubRestoreJSON(t *testing.T, p *EventHubProvider, data []byte) { var s eventHubSnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } @@ -78,7 +80,7 @@ func NewTestHandlerWithEventGrid(dataPlane EventGrid, settings Settings) *Handle // EventGridSnapshotJSON marshals the provider's ARM-side snapshot. func EventGridSnapshotJSON(p *EventGridProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -89,7 +91,7 @@ func EventGridRestoreJSON(t *testing.T, p *EventGridProvider, data []byte) { var s eventGridSnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } @@ -104,7 +106,7 @@ func NewTestHandlerWithAppConfig(dataPlane AppConfig, settings Settings) *Handle // AppConfigSnapshotJSON marshals the provider's ARM-side snapshot. func AppConfigSnapshotJSON(p *AppConfigProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -115,7 +117,7 @@ func AppConfigRestoreJSON(t *testing.T, p *AppConfigProvider, data []byte) { var s appConfigSnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } @@ -144,7 +146,7 @@ func NewTestHandlerWithContainerRegistry(dataPlane ContainerRegistries, settings // ContainerRegistrySnapshotJSON marshals the provider's ARM-side snapshot. func ContainerRegistrySnapshotJSON(p *ContainerRegistryProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -155,7 +157,7 @@ func ContainerRegistryRestoreJSON(t *testing.T, p *ContainerRegistryProvider, da var s containerRegistrySnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } @@ -172,7 +174,7 @@ func NewTestHandlerWithRedis(dataPlane Redis, now func() time.Time) (*Handler, * // RedisSnapshotJSON marshals the provider's ARM-side snapshot. func RedisSnapshotJSON(p *RedisProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -183,7 +185,7 @@ func RedisRestoreJSON(t *testing.T, p *RedisProvider, data []byte) { var s redisSnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } @@ -199,7 +201,7 @@ func NewTestHandlerWithSQL(dataPlane SQL) (*Handler, *SQLProvider) { // SQLSnapshotJSON marshals the provider's ARM-side snapshot. func SQLSnapshotJSON(p *SQLProvider) []byte { - b, _ := json.Marshal(p.snapshot()) + b, _ := json.Marshal(p.snapshot(), jsonx.V1()) return b } @@ -210,6 +212,6 @@ func SQLRestoreJSON(t *testing.T, p *SQLProvider, data []byte) { var s sqlSnapshot - require.NoError(t, json.Unmarshal(data, &s)) + require.NoError(t, json.Unmarshal(data, &s, jsonx.V1())) p.restore(&s) } diff --git a/services/azurearm/flexdb_mysql_test.go b/services/azurearm/flexdb_mysql_test.go index 53a43f1307..d515bb0920 100644 --- a/services/azurearm/flexdb_mysql_test.go +++ b/services/azurearm/flexdb_mysql_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/mysql/armmysqlflexibleservers/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const myNS = "Microsoft.DBforMySQL" @@ -87,7 +89,7 @@ func TestMySQLFlexServerCRUD(t *testing.T) { status, raw := s.raw(t, http.MethodGet, flexServerPath(myNS, "my-crud"), "", flexAPIMy) require.Equal(t, http.StatusOK, status) - enc, err := json.Marshal(raw) + enc, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(enc), flexPassword) assert.NotContains(t, string(enc), "administratorLoginPassword") diff --git a/services/azurearm/flexdb_pg_test.go b/services/azurearm/flexdb_pg_test.go index df044fc44a..2667172c40 100644 --- a/services/azurearm/flexdb_pg_test.go +++ b/services/azurearm/flexdb_pg_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -12,6 +12,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const pgNS = "Microsoft.DBforPostgreSQL" @@ -71,7 +73,7 @@ func TestPGFlexServerCRUD(t *testing.T) { status, raw := s.raw(t, http.MethodGet, flexServerPath(pgNS, "pg-crud"), "", flexAPIPG) require.Equal(t, http.StatusOK, status) - enc, err := json.Marshal(raw) + enc, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(enc), flexPassword) assert.NotContains(t, string(enc), "administratorLoginPassword") diff --git a/services/azurearm/flexdb_stack_test.go b/services/azurearm/flexdb_stack_test.go index 9c9baf19de..731dd95453 100644 --- a/services/azurearm/flexdb_stack_test.go +++ b/services/azurearm/flexdb_stack_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -18,6 +18,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -130,7 +131,7 @@ func (s *flexStack) raw(t *testing.T, method, path, body, apiVersion string) (in var out map[string]any if len(data) > 0 { - _ = json.Unmarshal(data, &out) + _ = json.Unmarshal(data, &out, jsonx.V1()) } return resp.StatusCode, out diff --git a/services/azurearm/handler.go b/services/azurearm/handler.go index c6e8a5854e..e74892e425 100644 --- a/services/azurearm/handler.go +++ b/services/azurearm/handler.go @@ -3,7 +3,8 @@ package azurearm import ( "context" "crypto/tls" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net" @@ -18,6 +19,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/aadauth" "github.com/blackbirdworks/gopherstack/pkgs/devtls" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -568,7 +570,7 @@ func decodeJSONBody(r *http.Request) (map[string]any, error) { } var body map[string]any - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &body, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrInvalidRequestBody, err) } diff --git a/services/azurearm/handler_test.go b/services/azurearm/handler_test.go index c7fe8c3862..07e5b3c490 100644 --- a/services/azurearm/handler_test.go +++ b/services/azurearm/handler_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "crypto/tls" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "net" @@ -23,6 +23,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/aadauth" "github.com/blackbirdworks/gopherstack/pkgs/devtls" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -74,7 +75,7 @@ func doRequest(t *testing.T, h *azurearm.Handler, method, path string, body []by var decoded map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &decoded) + _ = json.Unmarshal(rec.Body.Bytes(), &decoded, jsonx.V1()) } return rec.Code, decoded @@ -96,7 +97,7 @@ func TestHandler_MetadataEndpoints(t *testing.T) { var doc map[string]any - require.NoError(t, json.Unmarshal(body, &doc)) + require.NoError(t, json.Unmarshal(body, &doc, jsonx.V1())) assert.Equal(t, "gopherstack", doc["name"]) } @@ -150,7 +151,7 @@ func TestHandler_TokenEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Bearer", resp["token_type"]) assert.NotEmpty(t, resp["access_token"]) }) @@ -512,7 +513,7 @@ func TestHandler_MetadataEndpoints_HonorsRequestHostPort(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var doc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1())) assert.Equal(t, "https://localhost:18006/", doc["resourceManagerEndpoint"]) } diff --git a/services/azurearm/rp_aks.go b/services/azurearm/rp_aks.go index 232f689c2f..22b772d06b 100644 --- a/services/azurearm/rp_aks.go +++ b/services/azurearm/rp_aks.go @@ -4,12 +4,13 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "sync" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -122,7 +123,7 @@ func aksResourceID(sub, rg string, types, names []string) ResourceID { func aksEtag(t time.Time) string { return acaEtag(t) } func aksJSON(v any) string { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "" } diff --git a/services/azurearm/rp_aks_persist.go b/services/azurearm/rp_aks_persist.go index 5fdf1bbc2d..f3c28ce45e 100644 --- a/services/azurearm/rp_aks_persist.go +++ b/services/azurearm/rp_aks_persist.go @@ -1,6 +1,10 @@ package azurearm -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type containerServiceSnapshot struct { Clusters map[string]*storedAKSCluster `json:"clusters"` @@ -10,13 +14,13 @@ func (p *ContainerServiceProvider) snapshot() *containerServiceSnapshot { p.mu.RLock("snapshot") defer p.mu.RUnlock() - buf, err := json.Marshal(&containerServiceSnapshot{Clusters: p.clusters}) + buf, err := json.Marshal(&containerServiceSnapshot{Clusters: p.clusters}, jsonx.V1()) if err != nil { return &containerServiceSnapshot{} } var out containerServiceSnapshot - if err = json.Unmarshal(buf, &out); err != nil { + if err = json.Unmarshal(buf, &out, jsonx.V1()); err != nil { return &containerServiceSnapshot{} } diff --git a/services/azurearm/rp_apim_exec.go b/services/azurearm/rp_apim_exec.go index 80b9abf393..79b6282606 100644 --- a/services/azurearm/rp_apim_exec.go +++ b/services/azurearm/rp_apim_exec.go @@ -3,7 +3,7 @@ package azurearm import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,8 @@ import ( "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // gwState carries one gateway request through the policy pipeline. @@ -125,7 +127,7 @@ func (g *gwState) subAll(in []string) []string { } func (g *gwState) fail(status int, msg string) { - body, _ := json.Marshal(map[string]any{apimCStatusCode: status, fieldMessage: msg}) + body, _ := json.Marshal(map[string]any{apimCStatusCode: status, fieldMessage: msg}, jsonx.V1()) g.setResponse(status, http.Header{apimCContentType: {"application/json"}}, body) g.short = true } @@ -373,7 +375,7 @@ func firstExample(examples map[string]any) ([]byte, bool) { return []byte(s), true } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) return b, err == nil } diff --git a/services/azurearm/rp_apim_gateway.go b/services/azurearm/rp_apim_gateway.go index 0b0854217b..78042df730 100644 --- a/services/azurearm/rp_apim_gateway.go +++ b/services/azurearm/rp_apim_gateway.go @@ -1,7 +1,8 @@ package azurearm import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net" "net/http" @@ -10,6 +11,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -160,7 +162,10 @@ func gatewayTarget(r *http.Request) (string, string, bool) { func writeGW(w http.ResponseWriter, status int, msg string) { w.Header().Set(apimCContentType, "application/json") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(map[string]any{apimCStatusCode: status, fieldMessage: msg}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]any{apimCStatusCode: status, fieldMessage: msg}, + ) } // ServeGateway answers a request addressed to a service's gateway (Host .azure-api.net, or the path prefix diff --git a/services/azurearm/rp_apim_import.go b/services/azurearm/rp_apim_import.go index 0009fc36df..53a9762ccc 100644 --- a/services/azurearm/rp_apim_import.go +++ b/services/azurearm/rp_apim_import.go @@ -1,11 +1,13 @@ package azurearm import ( - "encoding/json" + "encoding/json/v2" "regexp" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -56,7 +58,7 @@ func parseAPISpec(format, value string) (*apimAPISpec, error) { } var doc map[string]any - if err := json.Unmarshal([]byte(value), &doc); err != nil { + if err := json.Unmarshal([]byte(value), &doc, jsonx.V1()); err != nil { return nil, apimInvalid("The API definition is not valid JSON (YAML is not supported): %v", err) } diff --git a/services/azurearm/rp_apim_persist.go b/services/azurearm/rp_apim_persist.go index d8266bc774..9072b9d9eb 100644 --- a/services/azurearm/rp_apim_persist.go +++ b/services/azurearm/rp_apim_persist.go @@ -1,24 +1,30 @@ package azurearm -import "encoding/json" +import ( + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // apimSnapshot is the persisted state of the API Management provider, subscription keys, secret named values and // backend credentials included (as with the other azurearm credentials). type apimSnapshot struct { - Services json.RawMessage `json:"services,omitempty"` - Operations json.RawMessage `json:"operations,omitempty"` + Services jsontext.Value `json:"services,omitempty"` + Operations jsontext.Value `json:"operations,omitempty"` } func (p *APIMProvider) snapshot() *apimSnapshot { p.mu.RLock(apimCSnapshot) defer p.mu.RUnlock() - raw, err := json.Marshal(p.svcs) + raw, err := json.Marshal(p.svcs, jsonx.V1()) if err != nil { return &apimSnapshot{} } - ops, err := json.Marshal(p.ops) + ops, err := json.Marshal(p.ops, jsonx.V1()) if err != nil { return &apimSnapshot{Services: raw} } @@ -39,7 +45,7 @@ func (p *APIMProvider) restore(snap *apimSnapshot) { } var ops map[string]*apimOp - if err := json.Unmarshal(snap.Operations, &ops); err == nil { + if err := json.Unmarshal(snap.Operations, &ops, jsonx.V1()); err == nil { for id, o := range ops { if o != nil { p.ops[id] = o @@ -48,7 +54,7 @@ func (p *APIMProvider) restore(snap *apimSnapshot) { } var svcs map[string]*apimService - if err := json.Unmarshal(snap.Services, &svcs); err != nil { + if err := json.Unmarshal(snap.Services, &svcs, jsonx.V1()); err != nil { return } diff --git a/services/azurearm/rp_authorization.go b/services/azurearm/rp_authorization.go index 0d0daaf1be..532609235c 100644 --- a/services/azurearm/rp_authorization.go +++ b/services/azurearm/rp_authorization.go @@ -3,7 +3,7 @@ package azurearm import ( "context" _ "embed" // role and policy catalogs - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "regexp" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -187,14 +188,14 @@ func NewAuthorizationProvider(tenantID string, msi *ManagedIdentityProvider) *Au p.resetMaps() var roles []*builtinRole - if err := json.Unmarshal(authRolesJSON, &roles); err == nil { + if err := json.Unmarshal(authRolesJSON, &roles, jsonx.V1()); err == nil { for _, r := range roles { p.builtinRoles[strings.ToLower(r.Name)] = r } } var cat builtinPolicyCatalog - if err := json.Unmarshal(authPoliciesJSON, &cat); err == nil { + if err := json.Unmarshal(authPoliciesJSON, &cat, jsonx.V1()); err == nil { for i := range cat.Definitions { p.builtinPols[strings.ToLower(cat.Definitions[i].Name)] = &cat.Definitions[i] } diff --git a/services/azurearm/rp_authorization_sdk_test.go b/services/azurearm/rp_authorization_sdk_test.go index fb5658daf7..375756d0a5 100644 --- a/services/azurearm/rp_authorization_sdk_test.go +++ b/services/azurearm/rp_authorization_sdk_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -126,7 +127,7 @@ func (s *authStack) raw(t *testing.T, method, path, body string) (int, map[strin require.NoError(t, err) var out map[string]any - _ = json.Unmarshal(data, &out) + _ = json.Unmarshal(data, &out, jsonx.V1()) return resp.StatusCode, out } diff --git a/services/azurearm/rp_compute_ext_test.go b/services/azurearm/rp_compute_ext_test.go index 039f814761..5c814e69f0 100644 --- a/services/azurearm/rp_compute_ext_test.go +++ b/services/azurearm/rp_compute_ext_test.go @@ -1,13 +1,15 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v9" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const extSecret = "s3cr3t-protected-value" @@ -169,7 +171,7 @@ func TestComputeSDK_ExtensionSecretsNotPersisted(t *testing.T) { require.NoError(t, err) snap := src.handler.Snapshot(t.Context()) - raw, err := json.Marshal(snap) + raw, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(raw), extSecret) @@ -374,7 +376,7 @@ func TestComputeSDK_ManagedRunCommands(t *testing.T) { assert.Equal(t, "Succeeded", *got.Properties.ProvisioningState) assert.Equal(t, "Unknown", string(*got.Properties.InstanceView.ExecutionState)) - raw, err := json.Marshal(s.handler.Snapshot(t.Context())) + raw, err := json.Marshal(s.handler.Snapshot(t.Context()), jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(raw), extSecret) diff --git a/services/azurearm/rp_compute_sets_test.go b/services/azurearm/rp_compute_sets_test.go index dcaddafe07..f1b392c5e9 100644 --- a/services/azurearm/rp_compute_sets_test.go +++ b/services/azurearm/rp_compute_sets_test.go @@ -1,7 +1,8 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "strings" @@ -10,6 +11,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v9" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestComputeSDK_AvailabilitySets(t *testing.T) { @@ -462,7 +465,7 @@ func TestComputeSDK_ListPagingAndPatch(t *testing.T) { } var page listPage - require.NoError(t, json.NewDecoder(resp.Body).Decode(&page)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &page, jsonx.V1())) assert.Len(t, page.Value, 2) require.NotEmpty(t, page.NextLink) @@ -470,7 +473,7 @@ func TestComputeSDK_ListPagingAndPatch(t *testing.T) { resp = s.rawDo(t, http.MethodGet, next, "") var last listPage - require.NoError(t, json.NewDecoder(resp.Body).Decode(&last)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &last, jsonx.V1())) assert.Len(t, last.Value, 1) assert.Empty(t, last.NextLink) diff --git a/services/azurearm/rp_containerapps_app.go b/services/azurearm/rp_containerapps_app.go index cfa66f75a4..4ab10ed62b 100644 --- a/services/azurearm/rp_containerapps_app.go +++ b/services/azurearm/rp_containerapps_app.go @@ -2,7 +2,7 @@ package azurearm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -10,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -88,7 +89,7 @@ func acaTemplateKey(t map[string]any) string { c := acaClone(t) delete(c, fieldRevSuffix) - b, _ := json.Marshal(c) + b, _ := json.Marshal(c, jsonx.V1()) return string(b) } diff --git a/services/azurearm/rp_containerapps_persist.go b/services/azurearm/rp_containerapps_persist.go index 1d44920f27..7ee0979aa4 100644 --- a/services/azurearm/rp_containerapps_persist.go +++ b/services/azurearm/rp_containerapps_persist.go @@ -1,6 +1,10 @@ package azurearm -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) type containerAppsSnapshot struct { Envs map[string]*storedACAEnv `json:"envs"` @@ -23,13 +27,13 @@ func (p *ContainerAppsProvider) snapshot() *containerAppsSnapshot { snap := &containerAppsSnapshot{Envs: p.envs, Apps: p.apps, Jobs: p.jobs} - buf, err := json.Marshal(snap) + buf, err := json.Marshal(snap, jsonx.V1()) if err != nil { return &containerAppsSnapshot{} } var out containerAppsSnapshot - if err = json.Unmarshal(buf, &out); err != nil { + if err = json.Unmarshal(buf, &out, jsonx.V1()); err != nil { return &containerAppsSnapshot{} } diff --git a/services/azurearm/rp_containerapps_revision.go b/services/azurearm/rp_containerapps_revision.go index b830e53e7b..b1b5b8c814 100644 --- a/services/azurearm/rp_containerapps_revision.go +++ b/services/azurearm/rp_containerapps_revision.go @@ -3,7 +3,7 @@ package azurearm import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "net/http" @@ -91,7 +91,7 @@ func acaVolumeWires(t map[string]any, env *storedACAEnv, secrets map[string]stri switch strings.ToLower(strOf(v, "storageType")) { case "", "emptydir": - raw := json.RawMessage("{}") + raw := jsontext.Value("{}") w.EmptyDir = &raw case "secret": w.Secret = acaSecretVolume(acaList(v[fieldSecrets]), secrets) diff --git a/services/azurearm/rp_containerapps_wire.go b/services/azurearm/rp_containerapps_wire.go index 651889833a..31c0ee8273 100644 --- a/services/azurearm/rp_containerapps_wire.go +++ b/services/azurearm/rp_containerapps_wire.go @@ -1,13 +1,15 @@ package azurearm import ( - "encoding/json" + "encoding/json/v2" "math" "net/http" "net/url" "regexp" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -111,13 +113,13 @@ func acaClone(m map[string]any) map[string]any { return nil } - buf, err := json.Marshal(m) + buf, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil } var out map[string]any - if err = json.Unmarshal(buf, &out); err != nil { + if err = json.Unmarshal(buf, &out, jsonx.V1()); err != nil { return nil } diff --git a/services/azurearm/rp_cosmos_sql.go b/services/azurearm/rp_cosmos_sql.go index 75b2c96684..d6f50f9251 100644 --- a/services/azurearm/rp_cosmos_sql.go +++ b/services/azurearm/rp_cosmos_sql.go @@ -1,12 +1,14 @@ package azurearm import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type cosmosChildKind int @@ -608,7 +610,7 @@ func rawJSON(v any) []byte { return nil } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil } @@ -618,7 +620,7 @@ func rawJSON(v any) []byte { func jsonOr(raw []byte, def map[string]any) map[string]any { var m map[string]any - if len(raw) > 0 && json.Unmarshal(raw, &m) == nil && m != nil { + if len(raw) > 0 && json.Unmarshal(raw, &m, jsonx.V1()) == nil && m != nil { return m } diff --git a/services/azurearm/rp_cosmos_test.go b/services/azurearm/rp_cosmos_test.go index e5d150eaf7..0e264e1c53 100644 --- a/services/azurearm/rp_cosmos_test.go +++ b/services/azurearm/rp_cosmos_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "sort" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -234,7 +235,7 @@ func cosmosDo(t *testing.T, h *azurearm.Handler, method, path string, body any) if body != nil { var err error - raw, err = json.Marshal(body) + raw, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -734,9 +735,9 @@ func TestCosmos_LegacyThroughputSnapshotMigrates(t *testing.T) { putCosmosAccount(t, h, map[string]any{}) var env map[string]any - require.NoError(t, json.Unmarshal(h.Snapshot(context.Background()), &env)) + require.NoError(t, json.Unmarshal(h.Snapshot(context.Background()), &env, jsonx.V1())) inject(t, env, map[string]any{"acct1/db1": map[string]any{"autoscaleMax": 4000}}) - raw, err := json.Marshal(env) + raw, err := json.Marshal(env, jsonx.V1()) require.NoError(t, err) h2, fake2 := newCosmosHandler() diff --git a/services/azurearm/rp_identity_sdk_test.go b/services/azurearm/rp_identity_sdk_test.go index 0c4c2a28ef..94e2ecc94e 100644 --- a/services/azurearm/rp_identity_sdk_test.go +++ b/services/azurearm/rp_identity_sdk_test.go @@ -1,7 +1,7 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -387,7 +388,7 @@ func TestIdentitySDK_WebSiteLegacySnapshot(t *testing.T) { require.NoError(t, err) var snap map[string]any - require.NoError(t, json.Unmarshal(s.handler.Snapshot(t.Context()), &snap)) + require.NoError(t, json.Unmarshal(s.handler.Snapshot(t.Context()), &snap, jsonx.V1())) sites, _ := snap["web"].(map[string]any)["sites"].(map[string]any) require.Len(t, sites, 1) @@ -398,7 +399,7 @@ func TestIdentitySDK_WebSiteLegacySnapshot(t *testing.T) { m["identity"] = map[string]any{"type": "SystemAssigned"} } - legacy, err := json.Marshal(snap) + legacy, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) dst := newCmpStack(t) diff --git a/services/azurearm/rp_keyvault_deleted_test.go b/services/azurearm/rp_keyvault_deleted_test.go index 1ed3f290b6..c4ddb037a6 100644 --- a/services/azurearm/rp_keyvault_deleted_test.go +++ b/services/azurearm/rp_keyvault_deleted_test.go @@ -1,7 +1,7 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -24,7 +25,7 @@ func newKVHandler() (*azurearm.Handler, *fakeKeyVaults) { func putVault(t *testing.T, h *azurearm.Handler, name string, props map[string]any) int { t.Helper() - raw, err := json.Marshal(map[string]any{"location": "westus", "properties": props}) + raw, err := json.Marshal(map[string]any{"location": "westus", "properties": props}, jsonx.V1()) require.NoError(t, err) status, _ := doRequest(t, h, "PUT", @@ -177,7 +178,7 @@ func TestKeyVault_CheckNameAvailability(t *testing.T) { require.Less(t, putVault(t, h, "gone1", map[string]any{}), 300) deleteVault(t, h, "gone1") - raw, err := json.Marshal(map[string]any{"name": tt.check, "type": "Microsoft.KeyVault/vaults"}) + raw, err := json.Marshal(map[string]any{"name": tt.check, "type": "Microsoft.KeyVault/vaults"}, jsonx.V1()) require.NoError(t, err) st, body := doRequest(t, h, "POST", diff --git a/services/azurearm/rp_monitor_test.go b/services/azurearm/rp_monitor_test.go index aaae7e257b..b85a8f5e4f 100644 --- a/services/azurearm/rp_monitor_test.go +++ b/services/azurearm/rp_monitor_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -97,7 +98,7 @@ func newMonitorHandler(t *testing.T, dp azurearm.MonitorLogs) *azurearm.Handler func monitorDo(t *testing.T, h *azurearm.Handler, method, path string, body any) (int, map[string]any) { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(method, path, bytes.NewReader(raw)) @@ -106,7 +107,7 @@ func monitorDo(t *testing.T, h *azurearm.Handler, method, path string, body any) newEchoServer(h).ServeHTTP(rec, req) var out map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) return rec.Code, out } diff --git a/services/azurearm/rp_network_pe_sdk_test.go b/services/azurearm/rp_network_pe_sdk_test.go index f19c896062..dfe3d23222 100644 --- a/services/azurearm/rp_network_pe_sdk_test.go +++ b/services/azurearm/rp_network_pe_sdk_test.go @@ -1,7 +1,8 @@ package azurearm_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (s *netStack) rawJSON(t *testing.T, method, path, body string) (int, map[string]any) { @@ -18,7 +21,7 @@ func (s *netStack) rawJSON(t *testing.T, method, path, body string) (int, map[st var out map[string]any - _ = json.NewDecoder(resp.Body).Decode(&out) + _ = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1()) return resp.StatusCode, out } diff --git a/services/azurearm/rp_network_sdk_test.go b/services/azurearm/rp_network_sdk_test.go index 0268e3dee3..0880e598c3 100644 --- a/services/azurearm/rp_network_sdk_test.go +++ b/services/azurearm/rp_network_sdk_test.go @@ -2,7 +2,8 @@ package azurearm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "maps" "net/http" @@ -22,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -1126,5 +1128,5 @@ func TestNetworkSDK_Protocol(t *testing.T) { } func jsonDecode(resp *http.Response, v any) error { - return json.NewDecoder(resp.Body).Decode(v) + return json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), v, jsonx.V1()) } diff --git a/services/azurearm/rp_redis_test.go b/services/azurearm/rp_redis_test.go index 3d5a954c10..fe5a9e2f2f 100644 --- a/services/azurearm/rp_redis_test.go +++ b/services/azurearm/rp_redis_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -176,7 +177,7 @@ func (e *redisEnv) do(t *testing.T, method, path string, body any) (int, map[str var rdr *bytes.Reader if body != nil { - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rdr = bytes.NewReader(raw) @@ -191,7 +192,7 @@ func (e *redisEnv) do(t *testing.T, method, path string, body any) (int, map[str var out map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) } return rec.Code, out, rec.Header() diff --git a/services/azurearm/rp_sql_test.go b/services/azurearm/rp_sql_test.go index cb68687df8..0f9fc1023e 100644 --- a/services/azurearm/rp_sql_test.go +++ b/services/azurearm/rp_sql_test.go @@ -2,7 +2,7 @@ package azurearm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -116,7 +117,7 @@ func newSQLEnv() *sqlEnv { func (e *sqlEnv) do(t *testing.T, method, path string, body any) (int, map[string]any, http.Header) { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) if body == nil { @@ -130,7 +131,7 @@ func (e *sqlEnv) do(t *testing.T, method, path string, body any) (int, map[strin var out map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) } return rec.Code, out, rec.Header() diff --git a/services/azurecontainerregistry/acrapi_test.go b/services/azurecontainerregistry/acrapi_test.go index cfa88f52f8..55ea379f1c 100644 --- a/services/azurecontainerregistry/acrapi_test.go +++ b/services/azurecontainerregistry/acrapi_test.go @@ -1,13 +1,14 @@ package azurecontainerregistry_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" ) @@ -179,7 +180,7 @@ func TestACRTagsAndManifests(t *testing.T) { } func patch(enabledKey string, value bool) []byte { - raw, _ := json.Marshal(map[string]any{"value": map[string]any{enabledKey: value}}) + raw, _ := json.Marshal(map[string]any{"value": map[string]any{enabledKey: value}}, jsonx.V1()) return raw } diff --git a/services/azurecontainerregistry/helpers_test.go b/services/azurecontainerregistry/helpers_test.go index 62ba571299..514c4f85e6 100644 --- a/services/azurecontainerregistry/helpers_test.go +++ b/services/azurecontainerregistry/helpers_test.go @@ -2,13 +2,14 @@ package azurecontainerregistry_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" acr "github.com/blackbirdworks/gopherstack/services/azurecontainerregistry" ) @@ -72,7 +73,7 @@ func decode(t *testing.T, body []byte) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out } diff --git a/services/azurecontainerregistry/hooks.go b/services/azurecontainerregistry/hooks.go index a41c04f1e6..a2955ea7ea 100644 --- a/services/azurecontainerregistry/hooks.go +++ b/services/azurecontainerregistry/hooks.go @@ -1,11 +1,12 @@ package azurecontainerregistry import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry" ) @@ -36,7 +37,7 @@ func loadChange(app http.Handler, r *http.Request, repo, ref string) (ManifestCh } var doc manifestDoc - if json.Unmarshal(m.Body, &doc) == nil { + if json.Unmarshal(m.Body, &doc, jsonx.V1()) == nil { c.ConfigType = doc.Config.MediaType if doc.MediaType != "" { diff --git a/services/azurecontainerregistry/serve.go b/services/azurecontainerregistry/serve.go index 3ff0dae425..6c9f848730 100644 --- a/services/azurecontainerregistry/serve.go +++ b/services/azurecontainerregistry/serve.go @@ -2,13 +2,15 @@ package azurecontainerregistry import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/url" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry" ) @@ -48,7 +50,7 @@ type errorEntry struct { } func writeJSON(w http.ResponseWriter, status int, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { status, raw = http.StatusInternalServerError, []byte(`{"errors":[{"code":"UNKNOWN","message":"encode"}]}`) } @@ -303,7 +305,7 @@ func parseForm(w http.ResponseWriter, r *http.Request) (url.Values, bool) { func decodeBody(w http.ResponseWriter, r *http.Request, out any) bool { r.Body = http.MaxBytesReader(w, r.Body, maxFormBytes) - if err := json.NewDecoder(r.Body).Decode(out); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(r.Body), out, jsonx.V1()); err != nil { writeRegistryError(w, http.StatusBadRequest, "INVALID_REQUEST", "The request body is not valid JSON.") return false diff --git a/services/azurecontainerregistry/webhooks.go b/services/azurecontainerregistry/webhooks.go index 804818e3d8..b46c47d12f 100644 --- a/services/azurecontainerregistry/webhooks.go +++ b/services/azurecontainerregistry/webhooks.go @@ -3,7 +3,7 @@ package azurecontainerregistry import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "maps" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -292,7 +293,7 @@ func (b *InMemoryBackend) deliver(reg string, w Webhook, content EventContent) { } func (b *InMemoryBackend) send(ctx context.Context, reg string, w Webhook, content EventContent) { - body, err := json.Marshal(content) + body, err := json.Marshal(content, jsonx.V1()) if err != nil { return } diff --git a/services/azurecontainerregistry/webhooks_test.go b/services/azurecontainerregistry/webhooks_test.go index 080e0acff4..6e151c3b8a 100644 --- a/services/azurecontainerregistry/webhooks_test.go +++ b/services/azurecontainerregistry/webhooks_test.go @@ -1,7 +1,7 @@ package azurecontainerregistry_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" acr "github.com/blackbirdworks/gopherstack/services/azurecontainerregistry" ) @@ -44,7 +45,7 @@ func newReceiver(t *testing.T) *receiver { var d delivery d.header = req.Header.Clone() - _ = json.Unmarshal(raw, &d.content) + _ = json.Unmarshal(raw, &d.content, jsonx.V1()) r.mu.Lock() r.got = append(r.got, d) @@ -88,7 +89,7 @@ func pushHelmChart(t *testing.T, c ocitest.Client, repo, tag string) ocitest.Ima "mediaType": "application/vnd.cncf.helm.chart.content.v1.tar+gzip", "size": len(layer), "digest": layerDigest, }}, - }) + }, jsonx.V1()) require.NoError(t, err) put := c.Do(http.MethodPut, "/v2/"+repo+"/manifests/"+tag, body, diff --git a/services/azureeventgrid/armscope_test.go b/services/azureeventgrid/armscope_test.go index 72d244398e..74b05e8fd6 100644 --- a/services/azureeventgrid/armscope_test.go +++ b/services/azureeventgrid/armscope_test.go @@ -1,13 +1,14 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/v2" "maps" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -138,7 +139,7 @@ func TestPublishResourceEvent(t *testing.T) { for _, g := range got { var ev map[string]any - require.NoError(t, json.Unmarshal([]byte(g.text), &ev)) + require.NoError(t, json.Unmarshal([]byte(g.text), &ev, jsonx.V1())) assert.Equal(t, tt.wantTopics[g.queue], ev["topic"]) assert.Equal(t, tt.ev.ResourceURI, ev["subject"]) assert.Equal(t, tt.ev.EventType, ev["eventType"]) diff --git a/services/azureeventgrid/attributes.go b/services/azureeventgrid/attributes.go index 3d06009b66..84e68a58eb 100644 --- a/services/azureeventgrid/attributes.go +++ b/services/azureeventgrid/attributes.go @@ -1,10 +1,12 @@ package azureeventgrid import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -36,13 +38,13 @@ func (d Destination) mappings() ([]attrMapping, error) { return nil, nil } - data, err := json.Marshal(raw) + data, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, invalidSpec("deliveryAttributeMappings is not valid JSON") } var out []attrMapping - if err = json.Unmarshal(data, &out); err != nil { + if err = json.Unmarshal(data, &out, jsonx.V1()); err != nil { return nil, invalidSpec("deliveryAttributeMappings is malformed: %v", err) } @@ -133,7 +135,7 @@ func headerValue(v any) string { return s } - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) return string(raw) } diff --git a/services/azureeventgrid/batching_test.go b/services/azureeventgrid/batching_test.go index 78a6bd692d..cfa2d56c58 100644 --- a/services/azureeventgrid/batching_test.go +++ b/services/azureeventgrid/batching_test.go @@ -1,7 +1,7 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/v2" "io" "maps" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -68,7 +69,7 @@ func TestWebhookBatching(t *testing.T) { for i := range tt.events { ev := egEvent("e"+string(rune('a'+i)), "/s") ev.Fields["data"] = map[string]any{"pad": strings.Repeat("x", tt.padding)} - raw, _ := json.Marshal(ev.Fields) + raw, _ := json.Marshal(ev.Fields, jsonx.V1()) ev.Raw = raw events = append(events, ev) } @@ -85,7 +86,7 @@ func TestWebhookBatching(t *testing.T) { for _, body := range h.bodies { var arr []map[string]any - require.NoError(t, json.Unmarshal(body, &arr)) + require.NoError(t, json.Unmarshal(body, &arr, jsonx.V1())) sizes = append(sizes, len(arr)) total += len(arr) } @@ -127,7 +128,7 @@ func TestWebhookBatchFailureRetriesWholeBatch(t *testing.T) { var arr []map[string]any - require.NoError(t, json.Unmarshal(h.bodies[1], &arr)) + require.NoError(t, json.Unmarshal(h.bodies[1], &arr, jsonx.V1())) assert.Len(t, arr, 2) assert.Equal(t, "1", h.requests[1].Header.Get("Aeg-Delivery-Count")) } @@ -297,6 +298,6 @@ func TestCloudEventsBatchedDelivery(t *testing.T) { var arr []map[string]any - require.NoError(t, json.Unmarshal(body, &arr)) + require.NoError(t, json.Unmarshal(body, &arr, jsonx.V1())) assert.Len(t, arr, 2) } diff --git a/services/azureeventgrid/deadletter.go b/services/azureeventgrid/deadletter.go index abbd794d90..f3b1f889d4 100644 --- a/services/azureeventgrid/deadletter.go +++ b/services/azureeventgrid/deadletter.go @@ -1,14 +1,16 @@ package azureeventgrid import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func decodeFields(raw []byte) map[string]any { var m map[string]any - _ = json.Unmarshal(raw, &m) + _ = json.Unmarshal(raw, &m, jsonx.V1()) return m } @@ -25,7 +27,7 @@ func deadLetterPayload(item deadItem) ([]byte, error) { m["publishTime"] = item.d.Published.UTC().Format(time.RFC3339Nano) m["lastDeliveryAttemptTime"] = item.d.LastAttempt.UTC().Format(time.RFC3339Nano) - return json.Marshal(m) + return json.Marshal(m, jsonx.V1()) } func blobName(item deadItem, at time.Time) string { diff --git a/services/azureeventgrid/delivery_test.go b/services/azureeventgrid/delivery_test.go index 8447c877f0..5937f49057 100644 --- a/services/azureeventgrid/delivery_test.go +++ b/services/azureeventgrid/delivery_test.go @@ -1,7 +1,8 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -43,9 +45,12 @@ func newHook(t *testing.T, code func(n int) int) *hook { if !h.manual { var ev []map[string]any - _ = json.Unmarshal(body, &ev) + _ = json.Unmarshal(body, &ev, jsonx.V1()) code, _ := ev[0]["data"].(map[string]any)["validationCode"].(string) - _ = json.NewEncoder(w).Encode(map[string]string{"validationResponse": code}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"validationResponse": code}, + ) } return @@ -83,7 +88,10 @@ func TestWebhookHandshake(t *testing.T) { schema: azureeventgrid.SchemaEventGrid, wantState: azureeventgrid.StateSucceeded, respond: func(w http.ResponseWriter, _ *http.Request, code string) { - _ = json.NewEncoder(w).Encode(map[string]string{"validationResponse": code}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"validationResponse": code}, + ) }, }, { @@ -139,7 +147,7 @@ func TestWebhookHandshake(t *testing.T) { seen.mu.Lock() seen.headers, seen.method = r.Header.Clone(), r.Method - _ = json.Unmarshal(body, &seen.event) + _ = json.Unmarshal(body, &seen.event, jsonx.V1()) seen.mu.Unlock() code := "" @@ -192,7 +200,7 @@ func TestManualValidationUnlocksDelivery(t *testing.T) { var ev []map[string]any - require.NoError(t, json.Unmarshal(h.shakeBody, &ev)) + require.NoError(t, json.Unmarshal(h.shakeBody, &ev, jsonx.V1())) validationURL, _ = ev[0]["data"].(map[string]any)["validationUrl"].(string) h.mu.Unlock() @@ -236,7 +244,7 @@ func TestWebhookDeliveryShape(t *testing.T) { var got []map[string]any - require.NoError(t, json.Unmarshal(h.bodies[0], &got)) + require.NoError(t, json.Unmarshal(h.bodies[0], &got, jsonx.V1())) require.Len(t, got, 1) assert.Equal(t, "e1", got[0]["id"]) assert.Equal(t, topicRID, got[0]["topic"]) @@ -323,7 +331,7 @@ func TestRetryAndDeadLetter(t *testing.T) { var out map[string]any - require.NoError(t, json.Unmarshal(blobs[0].body, &out)) + require.NoError(t, json.Unmarshal(blobs[0].body, &out, jsonx.V1())) assert.Equal(t, tt.wantReason, out["deadLetterReason"]) assert.EqualValues(t, tt.wantCalls, out["deliveryAttempts"]) assert.Equal(t, "e1", out["id"]) @@ -400,7 +408,7 @@ func TestTargetDelivery(t *testing.T) { var arr []map[string]any - require.NoError(t, json.Unmarshal(got.body, &arr)) + require.NoError(t, json.Unmarshal(got.body, &arr, jsonx.V1())) assert.Equal(t, "e1", arr[0]["id"]) }, }, @@ -437,12 +445,12 @@ func TestTargetDelivery(t *testing.T) { } } -func mustField(t *testing.T, raw []byte, key string) json.RawMessage { +func mustField(t *testing.T, raw []byte, key string) jsontext.Value { t.Helper() - var m map[string]json.RawMessage + var m map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw, &m)) + require.NoError(t, json.Unmarshal(raw, &m, jsonx.V1())) return m[key] } diff --git a/services/azureeventgrid/domains_test.go b/services/azureeventgrid/domains_test.go index 11814db2d6..cebcb04fa2 100644 --- a/services/azureeventgrid/domains_test.go +++ b/services/azureeventgrid/domains_test.go @@ -1,7 +1,7 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" eg "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -123,7 +124,7 @@ func TestDomainPublishRouting(t *testing.T) { for _, s := range e.rec.all() { var got map[string]any - require.NoError(t, json.Unmarshal([]byte(s.text), &got)) + require.NoError(t, json.Unmarshal([]byte(s.text), &got, jsonx.V1())) assert.True(t, strings.HasPrefix(got["topic"].(string), domainRID+"/topics/"), "%v", got["topic"]) assert.Equal(t, "1", got["metadataVersion"]) } @@ -334,7 +335,7 @@ func TestDomainSubscriptionWebhookBatchingAndHeaders(t *testing.T) { var events []eg.Event for _, id := range []string{"a", "b", "c"} { - raw, _ := json.Marshal(domainEvent("orders", id, "/s")) + raw, _ := json.Marshal(domainEvent("orders", id, "/s"), jsonx.V1()) parsed, perr := eg.ParseEvents(raw, eg.SchemaEventGrid) require.NoError(t, perr) @@ -350,7 +351,7 @@ func TestDomainSubscriptionWebhookBatchingAndHeaders(t *testing.T) { var arr []map[string]any - require.NoError(t, json.Unmarshal(h.bodies[0], &arr)) + require.NoError(t, json.Unmarshal(h.bodies[0], &arr, jsonx.V1())) assert.Len(t, arr, 3) assert.Equal(t, "v", h.requests[0].Header.Get("X-Secret")) assert.Equal(t, domainRID+"/topics/orders", arr[0]["topic"]) diff --git a/services/azureeventgrid/filter.go b/services/azureeventgrid/filter.go index d45f80eaa9..35f6bb162b 100644 --- a/services/azureeventgrid/filter.go +++ b/services/azureeventgrid/filter.go @@ -1,8 +1,9 @@ package azureeventgrid import ( - "encoding/json" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var attrAliases = map[string]string{ //nolint:gochecknoglobals // static alias table @@ -162,7 +163,7 @@ func (a AdvancedFilter) matchScalar(v any) bool { return a.matchString(x) case float64: return a.matchNumber(x) - case json.Number: + case jsonx.Number: f, err := x.Float64() return err == nil && a.matchNumber(f) @@ -230,7 +231,7 @@ func toFloat(v any) (float64, bool) { return x, true case int: return float64(x), true - case json.Number: + case jsonx.Number: f, err := x.Float64() return f, err == nil diff --git a/services/azureeventgrid/filter_test.go b/services/azureeventgrid/filter_test.go index 2d45601683..c61b552a41 100644 --- a/services/azureeventgrid/filter_test.go +++ b/services/azureeventgrid/filter_test.go @@ -1,12 +1,13 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" eg "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -21,7 +22,7 @@ func decode(t *testing.T, raw string) map[string]any { var m map[string]any - require.NoError(t, json.Unmarshal([]byte(raw), &m)) + require.NoError(t, json.Unmarshal([]byte(raw), &m, jsonx.V1())) return m } diff --git a/services/azureeventgrid/helpers_test.go b/services/azureeventgrid/helpers_test.go index d0ba346b29..dbc5d9dffd 100644 --- a/services/azureeventgrid/helpers_test.go +++ b/services/azureeventgrid/helpers_test.go @@ -1,7 +1,7 @@ package azureeventgrid_test import ( - "encoding/json" + "encoding/json/v2" "maps" "sync" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureeventgrid" ) @@ -105,7 +106,7 @@ func egEvent(id, subject string) azureeventgrid.Event { raw, _ := json.Marshal(map[string]any{ "id": id, "subject": subject, "eventType": "App.Thing", "eventTime": "2026-10-20T12:00:00Z", "dataVersion": "1", "data": map[string]any{"n": 1}, - }) + }, jsonx.V1()) events, err := azureeventgrid.ParseEvents(raw, azureeventgrid.SchemaEventGrid) if err != nil { diff --git a/services/azureeventgrid/http_routes.go b/services/azureeventgrid/http_routes.go index 12d2061d38..339d9e595c 100644 --- a/services/azureeventgrid/http_routes.go +++ b/services/azureeventgrid/http_routes.go @@ -1,7 +1,7 @@ package azureeventgrid import ( - "encoding/json" + "encoding/json/v2" "errors" "io" "net" @@ -11,6 +11,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -283,7 +285,12 @@ func (h *Handler) handlePull(c *echo.Context, rt route) error { LockTokens []string `json:"lockTokens"` } - if err = json.Unmarshal(body, &in); err != nil || len(in.LockTokens) == 0 || len(in.LockTokens) > maxLockTokens { + if err = json.Unmarshal( + body, + &in, + jsonx.V1(), + ); err != nil || len(in.LockTokens) == 0 || + len(in.LockTokens) > maxLockTokens { return writeError(c, http.StatusBadRequest, outcomeBadRequest, "lockTokens must hold 1 to 100 tokens.") } diff --git a/services/azureeventgrid/model.go b/services/azureeventgrid/model.go index 7a14e3086d..1f435665d2 100644 --- a/services/azureeventgrid/model.go +++ b/services/azureeventgrid/model.go @@ -1,7 +1,7 @@ package azureeventgrid import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -69,14 +69,14 @@ type Spec struct { } type delivery struct { - Due time.Time `json:"due"` - Published time.Time `json:"published"` - LastAttempt time.Time `json:"lastAttempt"` - ID string `json:"id"` - LastOutcome string `json:"lastOutcome,omitempty"` - Event json.RawMessage `json:"event"` - Attempts int `json:"attempts"` - InFlight bool `json:"-"` + Due time.Time `json:"due"` + Published time.Time `json:"published"` + LastAttempt time.Time `json:"lastAttempt"` + ID string `json:"id"` + LastOutcome string `json:"lastOutcome,omitempty"` + Event jsontext.Value `json:"event"` + Attempts int `json:"attempts"` + InFlight bool `json:"-"` } type subscription struct { @@ -99,12 +99,12 @@ type topic struct { } type pullEvent struct { - AvailableAt time.Time `json:"availableAt"` - LockedUntil time.Time `json:"lockedUntil"` - ExpiresAt time.Time `json:"expiresAt"` - LockToken string `json:"lockToken,omitempty"` - Event json.RawMessage `json:"event"` - Count int `json:"count"` + AvailableAt time.Time `json:"availableAt"` + LockedUntil time.Time `json:"lockedUntil"` + ExpiresAt time.Time `json:"expiresAt"` + LockToken string `json:"lockToken,omitempty"` + Event jsontext.Value `json:"event"` + Count int `json:"count"` } type pullSub struct { diff --git a/services/azureeventgrid/publish.go b/services/azureeventgrid/publish.go index 808e5f755e..fb3000cfaa 100644 --- a/services/azureeventgrid/publish.go +++ b/services/azureeventgrid/publish.go @@ -2,9 +2,12 @@ package azureeventgrid import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -18,7 +21,7 @@ const ( type Event struct { Fields map[string]any ID string - Raw json.RawMessage + Raw jsontext.Value } func invalidEvent(format string, args ...any) error { @@ -33,14 +36,14 @@ func ParseEvents(body []byte, schema string) ([]Event, error) { return nil, invalidEvent("the request body is empty") } - var raws []json.RawMessage + var raws []jsontext.Value if trimmed[0] == '[' { - if err := json.Unmarshal(trimmed, &raws); err != nil { + if err := json.Unmarshal(trimmed, &raws, jsonx.V1()); err != nil { return nil, invalidEvent("the request body is not valid JSON") } } else { - raws = []json.RawMessage{trimmed} + raws = []jsontext.Value{trimmed} } if len(raws) == 0 { @@ -65,9 +68,9 @@ func ParseEvents(body []byte, schema string) ([]Event, error) { return out, nil } -func parseEvent(raw json.RawMessage, schema string) (Event, error) { +func parseEvent(raw jsontext.Value, schema string) (Event, error) { var fields map[string]any - if err := json.Unmarshal(raw, &fields); err != nil || fields == nil { + if err := json.Unmarshal(raw, &fields, jsonx.V1()); err != nil || fields == nil { return Event{}, invalidEvent("the event is not a JSON object") } @@ -99,7 +102,7 @@ func (e *Event) stamp(topicRID, schema string) error { e.Fields["topic"], e.Fields["metadataVersion"] = topicRID, "1" } - raw, err := json.Marshal(e.Fields) + raw, err := json.Marshal(e.Fields, jsonx.V1()) if err != nil { return invalidEvent("the event cannot be encoded") } diff --git a/services/azureeventgrid/pull.go b/services/azureeventgrid/pull.go index 94a130a9bd..c4107177d9 100644 --- a/services/azureeventgrid/pull.go +++ b/services/azureeventgrid/pull.go @@ -2,12 +2,14 @@ package azureeventgrid import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/iso8601" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -46,7 +48,7 @@ type pullProps struct { // Received is one event handed out by a receive call. type Received struct { LockToken string - Event json.RawMessage + Event jsontext.Value DeliveryCount int } @@ -84,19 +86,19 @@ func (s *pullSub) props() map[string]any { }, } - raw, _ := json.Marshal(p) + raw, _ := json.Marshal(p, jsonx.V1()) out := map[string]any{} - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) out[propProvisioning] = StateSucceeded return out } func parsePullProps(props map[string]any) (pullProps, error) { - raw, _ := json.Marshal(props) + raw, _ := json.Marshal(props, jsonx.V1()) var p pullProps - if err := json.Unmarshal(raw, &p); err != nil { + if err := json.Unmarshal(raw, &p, jsonx.V1()); err != nil { return p, invalidSpec("properties are malformed: %v", err) } diff --git a/services/azureeventgrid/subscription.go b/services/azureeventgrid/subscription.go index b67e24727e..ff79d3081f 100644 --- a/services/azureeventgrid/subscription.go +++ b/services/azureeventgrid/subscription.go @@ -2,12 +2,14 @@ package azureeventgrid import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/url" "sort" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -16,13 +18,13 @@ const ( ) func parseSpec(props map[string]any, inputSchema string) (Spec, error) { - raw, err := json.Marshal(props) + raw, err := json.Marshal(props, jsonx.V1()) if err != nil { return Spec{}, invalidSpec("properties are not valid JSON") } var spec Spec - if err = json.Unmarshal(raw, &spec); err != nil { + if err = json.Unmarshal(raw, &spec, jsonx.V1()); err != nil { return Spec{}, invalidSpec("properties are malformed: %v", err) } @@ -70,9 +72,9 @@ func normalizeSpec(spec *Spec, inputSchema string) error { // specProps renders the ARM properties of a subscription. Webhook secrets in the // query string are withheld (see FullURL). func specProps(spec Spec, state, topicRID string) map[string]any { - raw, _ := json.Marshal(spec) + raw, _ := json.Marshal(spec, jsonx.V1()) out := map[string]any{} - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) if dest, ok := out["destination"].(map[string]any); ok && spec.Destination.EndpointType == EndpointWebHook { dest["properties"] = webhookProps(spec.Destination) @@ -199,13 +201,13 @@ func mergeSpecPatch(cur Spec, patch map[string]any) (map[string]any, error) { } } - raw, err := json.Marshal(cur) + raw, err := json.Marshal(cur, jsonx.V1()) if err != nil { return nil, invalidSpec("current spec is not valid JSON") } merged := map[string]any{} - if err = json.Unmarshal(raw, &merged); err != nil { + if err = json.Unmarshal(raw, &merged, jsonx.V1()); err != nil { return nil, invalidSpec("current spec is not valid JSON") } diff --git a/services/azureeventgrid/webhook.go b/services/azureeventgrid/webhook.go index 0073ddb324..a2e9be97ee 100644 --- a/services/azureeventgrid/webhook.go +++ b/services/azureeventgrid/webhook.go @@ -3,7 +3,7 @@ package azureeventgrid import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -11,6 +11,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -96,7 +98,7 @@ func validationEvent(topicRID, code, validationURL string) ([]byte, error) { "id": uuid.NewString(), "topic": topicRID, fieldSubject: "", fieldEventType: validationEventType, fieldEventTime: time.Now().UTC().Format(time.RFC3339Nano), "metadataVersion": "1", fieldDataVersion: "2", "data": map[string]any{"validationCode": code, "validationUrl": validationURL}, - }}) + }}, jsonx.V1()) } // postHandshake sends the SubscriptionValidationEvent; echoed reports whether the @@ -138,7 +140,7 @@ func (b *InMemoryBackend) postHandshake( } data, _ := io.ReadAll(io.LimitReader(resp.Body, maxResponseBytes)) - _ = json.Unmarshal(data, &out) + _ = json.Unmarshal(data, &out, jsonx.V1()) return out.ValidationResponse == code, nil } diff --git a/services/azureeventhubs/http_routes.go b/services/azureeventhubs/http_routes.go index c4aedbec97..8ffe0d8260 100644 --- a/services/azureeventhubs/http_routes.go +++ b/services/azureeventhubs/http_routes.go @@ -1,7 +1,7 @@ package azureeventhubs import ( - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/amqp1" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -151,7 +152,7 @@ func (h *Handler) authorized(r *http.Request, right string) bool { } func writeError(c *echo.Context, status int, msg string) error { - body, err := json.Marshal(map[string]string{"Code": http.StatusText(status), "Message": msg}) + body, err := json.Marshal(map[string]string{"Code": http.StatusText(status), "Message": msg}, jsonx.V1()) if err != nil { return c.String(http.StatusInternalServerError, "internal error") } @@ -219,7 +220,7 @@ func restEvents(r *http.Request, body []byte) ([]NewEvent, error) { if bp := r.Header.Get("Brokerproperties"); bp != "" { var props brokerProperties - if err := json.Unmarshal([]byte(bp), &props); err != nil { + if err := json.Unmarshal([]byte(bp), &props, jsonx.V1()); err != nil { return nil, err } @@ -233,9 +234,9 @@ func restEvents(r *http.Request, body []byte) ([]NewEvent, error) { func batchEvents(body []byte) ([]NewEvent, error) { var items []jsonEvent - if err := json.Unmarshal(body, &items); err != nil { + if err := json.Unmarshal(body, &items, jsonx.V1()); err != nil { var one jsonEvent - if err2 := json.Unmarshal(body, &one); err2 != nil { + if err2 := json.Unmarshal(body, &one, jsonx.V1()); err2 != nil { return nil, err } diff --git a/services/azurefile/ops_share.go b/services/azurefile/ops_share.go index 014a657a86..032a236cc2 100644 --- a/services/azurefile/ops_share.go +++ b/services/azurefile/ops_share.go @@ -1,7 +1,7 @@ package azurefile import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "math" "net/http" @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -751,7 +752,12 @@ func (h *Handler) createPermission(rc *reqCtx) (*resp, *apiError) { } var in permissionJSON - if err := json.Unmarshal(data, &in); err != nil || in.Permission == "" || len(in.Permission) > maxSDDLLen { + if err := json.Unmarshal( + data, + &in, + jsonx.V1(), + ); err != nil || in.Permission == "" || + len(in.Permission) > maxSDDLLen { return nil, errInvalidHeader("x-ms-file-permission") } @@ -792,7 +798,7 @@ func (h *Handler) getPermission(rc *reqCtx) (*resp, *apiError) { return nil, errInvalidHeader("x-ms-file-permission-key") } - body, err := json.Marshal(permissionJSON{Permission: sddl, Format: "Sddl"}) + body, err := json.Marshal(permissionJSON{Permission: sddl, Format: "Sddl"}, jsonx.V1()) if err != nil { return nil, newErr(http.StatusInternalServerError, "InternalError", "Failed to marshal response.") } diff --git a/services/azurefunctions/functions.go b/services/azurefunctions/functions.go index 7ebac1bc80..6c64a3e601 100644 --- a/services/azurefunctions/functions.go +++ b/services/azurefunctions/functions.go @@ -2,7 +2,7 @@ package azurefunctions import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -13,6 +13,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -107,7 +108,7 @@ func (b *InMemoryBackend) adminFunctions(ctx context.Context, name string) ([]ad } var fns []adminFunction - if err = json.Unmarshal(body, &fns); err != nil { + if err = json.Unmarshal(body, &fns, jsonx.V1()); err != nil { return nil, fmt.Errorf("decode host functions: %w", err) } diff --git a/services/azurefunctions/keys.go b/services/azurefunctions/keys.go index d7047a58a2..be8684c3f3 100644 --- a/services/azurefunctions/keys.go +++ b/services/azurefunctions/keys.go @@ -3,12 +3,14 @@ package azurefunctions import ( "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "os" "path/filepath" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -105,7 +107,7 @@ func writeSecrets(dir string, st *appState) error { Source: "runtime", } - raw, err := json.Marshal(host) + raw, err := json.Marshal(host, jsonx.V1()) if err != nil { return fmt.Errorf("encode host secrets: %w", err) } @@ -117,7 +119,7 @@ func writeSecrets(dir string, st *appState) error { want := map[string]bool{"host.json": true} for fn, keys := range st.FunctionKeys { - raw, err = json.Marshal(functionSecretsFile{Source: "runtime", Keys: sortedKeys(keys)}) + raw, err = json.Marshal(functionSecretsFile{Source: "runtime", Keys: sortedKeys(keys)}, jsonx.V1()) if err != nil { return fmt.Errorf("encode function secrets: %w", err) } diff --git a/services/azurefunctions/keys_test.go b/services/azurefunctions/keys_test.go index ae12992030..648dbb4efa 100644 --- a/services/azurefunctions/keys_test.go +++ b/services/azurefunctions/keys_test.go @@ -1,7 +1,7 @@ package azurefunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "path/filepath" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurefunctions" ) @@ -33,7 +34,7 @@ func loadSecrets(t *testing.T, dir, file string) secretsFile { require.NoError(t, err) var s secretsFile - require.NoError(t, json.Unmarshal([]byte(raw), &s)) + require.NoError(t, json.Unmarshal([]byte(raw), &s, jsonx.V1())) return s } diff --git a/services/azurefunctions/kudu.go b/services/azurefunctions/kudu.go index ff4fbdcfc7..097a9a3514 100644 --- a/services/azurefunctions/kudu.go +++ b/services/azurefunctions/kudu.go @@ -2,13 +2,15 @@ package azurefunctions import ( "crypto/subtle" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -74,7 +76,7 @@ func toDeploymentJSON(r *http.Request, name string, d Deployment, active bool) d } func writeJSON(w http.ResponseWriter, status int, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/services/azurefunctions/kudu_test.go b/services/azurefunctions/kudu_test.go index 924827ba6d..93b17a6c65 100644 --- a/services/azurefunctions/kudu_test.go +++ b/services/azurefunctions/kudu_test.go @@ -1,13 +1,14 @@ package azurefunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azurefunctions" ) @@ -133,7 +134,7 @@ func TestKudu_DeploymentsAndDownload(t *testing.T) { _, body = e.do(t, http.MethodPost, scm, "/api/zipdeploy", pkg, auth) var first map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &first)) + require.NoError(t, json.Unmarshal([]byte(body), &first, jsonx.V1())) assert.InDelta(t, 4, first["status"], 0) assert.Equal(t, true, first["complete"]) assert.Equal(t, "ZipDeploy", first["deployer"]) @@ -143,7 +144,7 @@ func TestKudu_DeploymentsAndDownload(t *testing.T) { _, body = e.do(t, http.MethodGet, scm, "/api/deployments", nil, auth) var list []map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &list)) + require.NoError(t, json.Unmarshal([]byte(body), &list, jsonx.V1())) require.Len(t, list, 2) assert.Equal(t, "OneDeploy", list[0]["deployer"], "newest first") assert.Equal(t, true, list[0]["active"]) diff --git a/services/azurefunctions/webapp.go b/services/azurefunctions/webapp.go index 1ecd3d2eff..1d30d423b4 100644 --- a/services/azurefunctions/webapp.go +++ b/services/azurefunctions/webapp.go @@ -2,7 +2,7 @@ package azurefunctions import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "os" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -193,7 +194,7 @@ func hasStartScript(dir string) bool { Scripts map[string]string `json:"scripts"` } - return json.Unmarshal(raw, &pkg) == nil && pkg.Scripts["start"] != "" + return json.Unmarshal(raw, &pkg, jsonx.V1()) == nil && pkg.Scripts["start"] != "" } func dotnetEntry(dir string) string { diff --git a/services/azurefunctions/zip.go b/services/azurefunctions/zip.go index 2ce0fed56a..dd194f858b 100644 --- a/services/azurefunctions/zip.go +++ b/services/azurefunctions/zip.go @@ -3,7 +3,7 @@ package azurefunctions import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "io" "os" @@ -12,6 +12,8 @@ import ( "regexp" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -143,7 +145,7 @@ func scanFunctions(data []byte) []FunctionDef { _ = rc.Close() var cfg map[string]any - if readErr != nil || json.Unmarshal(bytes.TrimPrefix(raw, []byte("\xef\xbb\xbf")), &cfg) != nil { + if readErr != nil || json.Unmarshal(bytes.TrimPrefix(raw, []byte("\xef\xbb\xbf")), &cfg, jsonx.V1()) != nil { continue } diff --git a/services/azuregraph/apps.go b/services/azuregraph/apps.go index 2e4d9e980f..35106ba886 100644 --- a/services/azuregraph/apps.go +++ b/services/azuregraph/apps.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "net/url" "slices" "strings" @@ -107,7 +107,7 @@ func validateAppRoles(roles []AppRole, scopes []PermissionScope) error { } // CreateApplication registers an application. -func (b *Backend) CreateApplication(body map[string]json.RawMessage) (Application, error) { +func (b *Backend) CreateApplication(body map[string]jsontext.Value) (Application, error) { b.mu.Lock("CreateApplication") defer b.mu.Unlock() @@ -159,7 +159,7 @@ func (b *Backend) ListApplications() []Application { } // UpdateApplication applies a PATCH body. -func (b *Backend) UpdateApplication(r Ref, body map[string]json.RawMessage) error { +func (b *Backend) UpdateApplication(r Ref, body map[string]jsontext.Value) error { b.mu.Lock("UpdateApplication") defer b.mu.Unlock() diff --git a/services/azuregraph/assign.go b/services/azuregraph/assign.go index 34d148f992..5efc42c6af 100644 --- a/services/azuregraph/assign.go +++ b/services/azuregraph/assign.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "slices" "strings" ) @@ -24,7 +24,7 @@ func principalType(kind string) string { // CreateAppRoleAssignment grants an app role. ownerID is the path service principal, user or group; // asResource selects appRoleAssignedTo (owner is the resource) over appRoleAssignments (owner is the principal). func (b *Backend) CreateAppRoleAssignment( - ownerID string, asResource bool, body map[string]json.RawMessage, + ownerID string, asResource bool, body map[string]jsontext.Value, ) (AppRoleAssignment, error) { if err := requireProps("AppRoleAssignment", body, "principalId", "resourceId", "appRoleId"); err != nil { return AppRoleAssignment{}, err @@ -135,7 +135,7 @@ func (b *Backend) DeleteAppRoleAssignment(id, assignmentID string, asResource bo } // CreateGrant records a delegated permission grant. -func (b *Backend) CreateGrant(body map[string]json.RawMessage) (OAuth2PermissionGrant, error) { +func (b *Backend) CreateGrant(body map[string]jsontext.Value) (OAuth2PermissionGrant, error) { if err := requireProps("OAuth2PermissionGrant", body, "clientId", "consentType", "resourceId"); err != nil { return OAuth2PermissionGrant{}, err } @@ -181,7 +181,7 @@ func (b *Backend) ListGrants() []OAuth2PermissionGrant { } // UpdateGrant changes the scope of a grant. -func (b *Backend) UpdateGrant(id string, body map[string]json.RawMessage) error { +func (b *Backend) UpdateGrant(id string, body map[string]jsontext.Value) error { b.mu.Lock("UpdateGrant") defer b.mu.Unlock() diff --git a/services/azuregraph/collections.go b/services/azuregraph/collections.go index c85233dfae..d54f58ad7f 100644 --- a/services/azuregraph/collections.go +++ b/services/azuregraph/collections.go @@ -1,10 +1,13 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "reflect" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // collection adapts one directory object type to the generic CRUD routes. @@ -12,8 +15,8 @@ type collection struct { fields map[string]bool list func(*Backend) []map[string]any get func(*Backend, Ref) (map[string]any, error) - create func(*Backend, map[string]json.RawMessage) (map[string]any, error) - patch func(*Backend, Ref, map[string]json.RawMessage) error + create func(*Backend, map[string]jsontext.Value) (map[string]any, error) + patch func(*Backend, Ref, map[string]jsontext.Value) error del func(*Backend, Ref) error name string resource string @@ -33,13 +36,13 @@ func splitKey(seg string) (string, Ref) { // toMap renders an entity as its generic JSON object. func toMap(v any) map[string]any { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return map[string]any{} } out := map[string]any{} - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) if t := reflect.TypeOf(v); t.Kind() == reflect.Struct { for name := range jsonFields(t) { @@ -84,15 +87,15 @@ func newCollection[T any]( name, resource, kind string, list func(*Backend) []T, get func(*Backend, Ref) (T, error), - create func(*Backend, map[string]json.RawMessage) (T, error), - patch func(*Backend, Ref, map[string]json.RawMessage) error, + create func(*Backend, map[string]jsontext.Value) (T, error), + patch func(*Backend, Ref, map[string]jsontext.Value) error, del func(*Backend, Ref) error, ) *collection { return &collection{ name: name, resource: resource, kind: kind, fields: fieldsOf[T](), patch: patch, del: del, list: func(b *Backend) []map[string]any { return mapAll(list(b)) }, get: func(b *Backend, r Ref) (map[string]any, error) { return one(get(b, r)) }, - create: func(b *Backend, m map[string]json.RawMessage) (map[string]any, error) { return one(create(b, m)) }, + create: func(b *Backend, m map[string]jsontext.Value) (map[string]any, error) { return one(create(b, m)) }, } } diff --git a/services/azuregraph/groups.go b/services/azuregraph/groups.go index a6dbc59768..e08edb32bc 100644 --- a/services/azuregraph/groups.go +++ b/services/azuregraph/groups.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "slices" "strings" ) @@ -55,7 +55,7 @@ func validateGroup(g *Group) error { } // CreateGroup creates a group; members@odata.bind and owners@odata.bind add references atomically. -func (b *Backend) CreateGroup(body map[string]json.RawMessage) (Group, error) { +func (b *Backend) CreateGroup(body map[string]jsontext.Value) (Group, error) { if err := requireProps("Group", body, "displayName", "mailEnabled", "mailNickname", "securityEnabled"); err != nil { return Group{}, err } @@ -119,7 +119,7 @@ func (b *Backend) ListGroups() []Group { } // UpdateGroup applies a PATCH body. isAssignableToRole can only be set at creation. -func (b *Backend) UpdateGroup(r Ref, body map[string]json.RawMessage) error { +func (b *Backend) UpdateGroup(r Ref, body map[string]jsontext.Value) error { b.mu.Lock("UpdateGroup") defer b.mu.Unlock() diff --git a/services/azuregraph/helpers_test.go b/services/azuregraph/helpers_test.go index 502485101b..0ffaf5be0d 100644 --- a/services/azuregraph/helpers_test.go +++ b/services/azuregraph/helpers_test.go @@ -2,7 +2,7 @@ package azuregraph_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/aadauth" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuregraph" ) @@ -98,7 +99,7 @@ func (e *env) req(t *testing.T, method, path string, body any, hdr ...string) re case string: rdr = strings.NewReader(b) default: - raw, err := json.Marshal(b) + raw, err := json.Marshal(b, jsonx.V1()) require.NoError(t, err) rdr = bytes.NewReader(raw) @@ -126,7 +127,7 @@ func (e *env) req(t *testing.T, method, path string, body any, hdr ...string) re require.NoError(t, err) out := resp{status: res.StatusCode, header: res.Header, raw: string(raw)} - _ = json.Unmarshal(raw, &out.body) + _ = json.Unmarshal(raw, &out.body, jsonx.V1()) return out } diff --git a/services/azuregraph/model.go b/services/azuregraph/model.go index bacadfe11b..c757302e8f 100644 --- a/services/azuregraph/model.go +++ b/services/azuregraph/model.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -124,15 +124,15 @@ type Application struct { DisplayName string `json:"displayName"` Description string `json:"description,omitempty"` API APIApplication `json:"api"` - Certification json.RawMessage `json:"certification,omitempty"` - VerifiedPublisher json.RawMessage `json:"verifiedPublisher,omitempty"` + Certification jsontext.Value `json:"certification,omitempty"` + VerifiedPublisher jsontext.Value `json:"verifiedPublisher,omitempty"` SPA RedirectFacet `json:"spa"` - DisabledByMicrosoftStatus json.RawMessage `json:"disabledByMicrosoftStatus,omitempty"` - AddIns json.RawMessage `json:"addIns,omitempty"` - ParentalControlSettings json.RawMessage `json:"parentalControlSettings,omitempty"` - Info json.RawMessage `json:"info,omitempty"` - OptionalClaims json.RawMessage `json:"optionalClaims,omitempty"` - AuthenticationBehaviors json.RawMessage `json:"authenticationBehaviors,omitempty"` + DisabledByMicrosoftStatus jsontext.Value `json:"disabledByMicrosoftStatus,omitempty"` + AddIns jsontext.Value `json:"addIns,omitempty"` + ParentalControlSettings jsontext.Value `json:"parentalControlSettings,omitempty"` + Info jsontext.Value `json:"info,omitempty"` + OptionalClaims jsontext.Value `json:"optionalClaims,omitempty"` + AuthenticationBehaviors jsontext.Value `json:"authenticationBehaviors,omitempty"` PublicClient RedirectFacet `json:"publicClient"` IdentifierURIs []string `json:"identifierUris"` Tags []string `json:"tags"` @@ -147,18 +147,18 @@ type Application struct { // ServicePrincipal is the local instance of an application in the tenant. type ServicePrincipal struct { - AddIns json.RawMessage `json:"addIns,omitempty"` - DisabledByMicrosoftStatus json.RawMessage `json:"disabledByMicrosoftStatus,omitempty"` - ResourceSpecificPermissions json.RawMessage `json:"resourceSpecificApplicationPermissions,omitempty"` - PasswordSSOSettings json.RawMessage `json:"passwordSingleSignOnSettings,omitempty"` - PreferredKeyEndDateTime json.RawMessage `json:"preferredTokenSigningKeyEndDateTime,omitempty"` - CustomSecurityAttributes json.RawMessage `json:"customSecurityAttributes,omitempty"` + AddIns jsontext.Value `json:"addIns,omitempty"` + DisabledByMicrosoftStatus jsontext.Value `json:"disabledByMicrosoftStatus,omitempty"` + ResourceSpecificPermissions jsontext.Value `json:"resourceSpecificApplicationPermissions,omitempty"` + PasswordSSOSettings jsontext.Value `json:"passwordSingleSignOnSettings,omitempty"` + PreferredKeyEndDateTime jsontext.Value `json:"preferredTokenSigningKeyEndDateTime,omitempty"` + CustomSecurityAttributes jsontext.Value `json:"customSecurityAttributes,omitempty"` SAMLMetadataURL string `json:"samlMetadataUrl,omitempty"` ApplicationTemplateID string `json:"applicationTemplateId,omitempty"` CreatedDateTime time.Time `json:"createdDateTime"` - Info json.RawMessage `json:"info,omitempty"` - VerifiedPublisher json.RawMessage `json:"verifiedPublisher,omitempty"` - SAMLSingleSignOnSettings json.RawMessage `json:"samlSingleSignOnSettings,omitempty"` + Info jsontext.Value `json:"info,omitempty"` + VerifiedPublisher jsontext.Value `json:"verifiedPublisher,omitempty"` + SAMLSingleSignOnSettings jsontext.Value `json:"samlSingleSignOnSettings,omitempty"` ID string `json:"id"` AppID string `json:"appId"` DisplayName string `json:"displayName"` diff --git a/services/azuregraph/patch.go b/services/azuregraph/patch.go index 7feb1372fb..14c47ec55b 100644 --- a/services/azuregraph/patch.go +++ b/services/azuregraph/patch.go @@ -2,10 +2,13 @@ package azuregraph import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "reflect" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type normalizer[T any] interface { @@ -28,7 +31,7 @@ func jsonFields(t reflect.Type) map[string]bool { } // mergeJSON overlays patch onto base: objects merge recursively, null deletes, anything else replaces. -func mergeJSON(base, patch map[string]json.RawMessage) { +func mergeJSON(base, patch map[string]jsontext.Value) { for k, v := range patch { if bytes.Equal(bytes.TrimSpace(v), []byte(jsonNull)) { delete(base, k) @@ -36,11 +39,12 @@ func mergeJSON(base, patch map[string]json.RawMessage) { continue } - var pm, bm map[string]json.RawMessage - if json.Unmarshal(v, &pm) == nil && pm != nil && json.Unmarshal(base[k], &bm) == nil && bm != nil { + var pm, bm map[string]jsontext.Value + if json.Unmarshal(v, &pm, jsonx.V1()) == nil && pm != nil && json.Unmarshal(base[k], &bm, jsonx.V1()) == nil && + bm != nil { mergeJSON(bm, pm) - if merged, err := json.Marshal(bm); err == nil { + if merged, err := json.Marshal(bm, jsonx.V1()); err == nil { base[k] = merged continue @@ -53,9 +57,9 @@ func mergeJSON(base, patch map[string]json.RawMessage) { // applyBody merges a create or PATCH body onto cur and returns the resulting object. // Unknown or read-only properties are rejected the way Graph does. -func applyBody[T any, P normalizer[T]](cur *T, body map[string]json.RawMessage, readOnly ...string) (*T, error) { +func applyBody[T any, P normalizer[T]](cur *T, body map[string]jsontext.Value, readOnly ...string) (*T, error) { known := jsonFields(reflect.TypeFor[T]()) - patch := make(map[string]json.RawMessage, len(body)) + patch := make(map[string]jsontext.Value, len(body)) for k, v := range body { if strings.Contains(k, "@") { @@ -73,25 +77,25 @@ func applyBody[T any, P normalizer[T]](cur *T, body map[string]json.RawMessage, patch[k] = v } - raw, err := json.Marshal(cur) + raw, err := json.Marshal(cur, jsonx.V1()) if err != nil { return nil, err //nolint:wrapcheck // marshal of an owned struct cannot fail on input } - base := map[string]json.RawMessage{} - if err = json.Unmarshal(raw, &base); err != nil { + base := map[string]jsontext.Value{} + if err = json.Unmarshal(raw, &base, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // as above } mergeJSON(base, patch) - merged, err := json.Marshal(base) + merged, err := json.Marshal(base, jsonx.V1()) if err != nil { return nil, err //nolint:wrapcheck // as above } out := new(T) - if err = json.Unmarshal(merged, out); err != nil { + if err = json.Unmarshal(merged, out, jsonx.V1()); err != nil { return nil, badRequest( "Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.", ) diff --git a/services/azuregraph/relations.go b/services/azuregraph/relations.go index 21d446c79d..5b56da07ec 100644 --- a/services/azuregraph/relations.go +++ b/services/azuregraph/relations.go @@ -1,9 +1,12 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Object is a directory object of any kind with its entity (Application, ServicePrincipal, User or Group). @@ -55,13 +58,13 @@ func idFromRef(s string) string { } // bindTargets resolves a list of @odata.bind references, failing if any target does not exist. -func (b *Backend) bindTargets(raw json.RawMessage) ([]string, error) { +func (b *Backend) bindTargets(raw jsontext.Value) ([]string, error) { if len(raw) == 0 { return []string{}, nil } var refs []string - if err := json.Unmarshal(raw, &refs); err != nil { + if err := json.Unmarshal(raw, &refs, jsonx.V1()); err != nil { return nil, badRequest("Invalid value specified for an @odata.bind property.") } @@ -82,7 +85,7 @@ func (b *Backend) bindTargets(raw json.RawMessage) ([]string, error) { } // ownerBinds resolves owners@odata.bind; owners must be users or service principals. -func (b *Backend) ownerBinds(body map[string]json.RawMessage) ([]string, error) { +func (b *Backend) ownerBinds(body map[string]jsontext.Value) ([]string, error) { ids, err := b.bindTargets(body["owners@odata.bind"]) if err != nil { return nil, err diff --git a/services/azuregraph/routes.go b/services/azuregraph/routes.go index d03b1e07b5..7ad43b2a2b 100644 --- a/services/azuregraph/routes.go +++ b/services/azuregraph/routes.go @@ -1,7 +1,8 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "maps" "net/http" @@ -10,6 +11,8 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxGetByIDs = 1000 @@ -27,11 +30,11 @@ func odataBase(r *http.Request) string { return "https://" + r.Host + "/" + version } -func readJSON(c *echo.Context) (map[string]json.RawMessage, error) { +func readJSON(c *echo.Context) (map[string]jsontext.Value, error) { data, err := io.ReadAll(http.MaxBytesReader(c.Response(), c.Request().Body, maxBodyBytes)) - out := map[string]json.RawMessage{} + out := map[string]jsontext.Value{} - if err != nil || json.Unmarshal(data, &out) != nil || out == nil { + if err != nil || json.Unmarshal(data, &out, jsonx.V1()) != nil || out == nil { return nil, badRequest( "Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.", ) @@ -314,7 +317,7 @@ func (h *Handler) getByIDs(c *echo.Context) error { } data, _ := io.ReadAll(http.MaxBytesReader(c.Response(), r.Body, maxBodyBytes)) - if err := json.Unmarshal(data, &in); err != nil || len(in.IDs) == 0 || len(in.IDs) > maxGetByIDs { + if err := json.Unmarshal(data, &in, jsonx.V1()); err != nil || len(in.IDs) == 0 || len(in.IDs) > maxGetByIDs { return h.writeErr( c, badRequest("The 'ids' collection must contain between 1 and %d object identifiers.", maxGetByIDs), diff --git a/services/azuregraph/routes_sub.go b/services/azuregraph/routes_sub.go index 553cd9f49c..eb4f8fe26d 100644 --- a/services/azuregraph/routes_sub.go +++ b/services/azuregraph/routes_sub.go @@ -1,12 +1,15 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func supports(kind string, allowed ...string) bool { return slices.Contains(allowed, kind) } @@ -113,7 +116,7 @@ func (h *Handler) addPassword(c *echo.Context, id string) error { var in PasswordCredential if raw := body["passwordCredential"]; len(raw) > 0 && string(raw) != jsonNull { - if err = json.Unmarshal(raw, &in); err != nil { + if err = json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return h.writeErr(c, badRequest("Invalid value specified for property 'passwordCredential'.")) } } @@ -143,7 +146,7 @@ func (h *Handler) addKey(c *echo.Context, id string) error { } var in KeyCredential - if err = json.Unmarshal(body["keyCredential"], &in); err != nil { + if err = json.Unmarshal(body["keyCredential"], &in, jsonx.V1()); err != nil { return h.writeErr(c, badRequest("A value is required for property 'keyCredential' of resource 'Application'.")) } @@ -166,7 +169,7 @@ func (h *Handler) removeCred(c *echo.Context, id string, remove func(id, keyID s } var keyID string - if json.Unmarshal(body["keyId"], &keyID) != nil || keyID == "" { + if json.Unmarshal(body["keyId"], &keyID, jsonx.V1()) != nil || keyID == "" { return h.writeErr(c, badRequest("A value is required for property 'keyId'.")) } @@ -190,9 +193,9 @@ func (h *Handler) relation(c *echo.Context, load func() ([]Object, error)) error return h.list(c, "directoryObjects", "DirectoryObject", nil, typedObjects(objs)) } -func odataRefTarget(body map[string]json.RawMessage) (string, bool) { +func odataRefTarget(body map[string]jsontext.Value) (string, bool) { var ref string - if json.Unmarshal(body["@odata.id"], &ref) != nil || ref == "" { + if json.Unmarshal(body["@odata.id"], &ref, jsonx.V1()) != nil || ref == "" { return "", false } diff --git a/services/azuregraph/sps.go b/services/azuregraph/sps.go index 95a65d0d8e..ec14f0e1e6 100644 --- a/services/azuregraph/sps.go +++ b/services/azuregraph/sps.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "strings" ) @@ -31,7 +31,7 @@ func (b *Backend) findSP(r Ref) (*ServicePrincipal, error) { } // CreateServicePrincipal instantiates an application in the tenant; body.appId must name a registered application. -func (b *Backend) CreateServicePrincipal(body map[string]json.RawMessage) (ServicePrincipal, error) { +func (b *Backend) CreateServicePrincipal(body map[string]jsontext.Value) (ServicePrincipal, error) { b.mu.Lock("CreateServicePrincipal") defer b.mu.Unlock() @@ -111,7 +111,7 @@ func (b *Backend) ListServicePrincipals() []ServicePrincipal { } // UpdateServicePrincipal applies a PATCH body. -func (b *Backend) UpdateServicePrincipal(r Ref, body map[string]json.RawMessage) error { +func (b *Backend) UpdateServicePrincipal(r Ref, body map[string]jsontext.Value) error { b.mu.Lock("UpdateServicePrincipal") defer b.mu.Unlock() diff --git a/services/azuregraph/users.go b/services/azuregraph/users.go index a2b2bc4aae..b2f4328730 100644 --- a/services/azuregraph/users.go +++ b/services/azuregraph/users.go @@ -1,7 +1,7 @@ package azuregraph import ( - "encoding/json" + "encoding/json/jsontext" "strings" "unicode" ) @@ -80,7 +80,7 @@ func (b *Backend) validateUser(u *User, self string) error { return nil } -func requireProps(kind string, body map[string]json.RawMessage, props ...string) error { +func requireProps(kind string, body map[string]jsontext.Value, props ...string) error { for _, p := range props { if v, ok := body[p]; !ok || string(v) == jsonNull { return badRequest("A value is required for property '%s' of resource '%s'.", p, kind) @@ -91,7 +91,7 @@ func requireProps(kind string, body map[string]json.RawMessage, props ...string) } // CreateUser creates a user. passwordProfile is validated and discarded. -func (b *Backend) CreateUser(body map[string]json.RawMessage) (User, error) { +func (b *Backend) CreateUser(body map[string]jsontext.Value) (User, error) { if err := requireProps(typeUser, body, "accountEnabled", "displayName", "mailNickname", "passwordProfile", "userPrincipalName"); err != nil { return User{}, err @@ -147,7 +147,7 @@ func (b *Backend) ListUsers() []User { } // UpdateUser applies a PATCH body. -func (b *Backend) UpdateUser(r Ref, body map[string]json.RawMessage) error { +func (b *Backend) UpdateUser(r Ref, body map[string]jsontext.Value) error { b.mu.Lock("UpdateUser") defer b.mu.Unlock() diff --git a/services/azurekeyvault/backup.go b/services/azurekeyvault/backup.go index 92cc8a5f8a..9dabc0f03f 100644 --- a/services/azurekeyvault/backup.go +++ b/services/azurekeyvault/backup.go @@ -1,8 +1,10 @@ package azurekeyvault import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const backupPrefix = "gopherstack-keyvault-backup:" @@ -25,7 +27,7 @@ type RestoreRequest struct { } func encodeBackup(bl *backupBlob) (BackupResult, error) { - raw, err := json.Marshal(bl) + raw, err := json.Marshal(bl, jsonx.V1()) if err != nil { return BackupResult{}, err } @@ -40,7 +42,7 @@ func decodeBackup(value, kind string) (*backupBlob, error) { } var bl backupBlob - if err = json.Unmarshal(raw[len(backupPrefix):], &bl); err != nil || bl.Kind != kind { + if err = json.Unmarshal(raw[len(backupPrefix):], &bl, jsonx.V1()); err != nil || bl.Kind != kind { return nil, errBadParameter("The backup blob is not a %s backup.", lowerKind(kind)) } diff --git a/services/azurekeyvault/handler.go b/services/azurekeyvault/handler.go index 4bd729ff1d..11055dc85a 100644 --- a/services/azurekeyvault/handler.go +++ b/services/azurekeyvault/handler.go @@ -3,7 +3,7 @@ package azurekeyvault import ( "context" "crypto/tls" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -18,6 +18,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/devtls" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -270,7 +271,7 @@ func decodeBody[T any](rc *reqCtx) (*T, error) { return &in, nil } - if err := json.Unmarshal(rc.body, &in); err != nil { + if err := json.Unmarshal(rc.body, &in, jsonx.V1()); err != nil { return nil, errBadParameter("The request body is not valid JSON: %s", err.Error()) } diff --git a/services/azuremonitor/backend.go b/services/azuremonitor/backend.go index a0d16cb026..a5a2a4bb59 100644 --- a/services/azuremonitor/backend.go +++ b/services/azuremonitor/backend.go @@ -3,13 +3,14 @@ package azuremonitor import ( "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "regexp" "slices" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -97,14 +98,14 @@ func cloneJSON(m map[string]any) map[string]any { return nil } - raw, err := json.Marshal(m) + raw, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil } var out map[string]any - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) return out } diff --git a/services/azuremonitor/handler.go b/services/azuremonitor/handler.go index 394d49671e..e3c2b5a669 100644 --- a/services/azuremonitor/handler.go +++ b/services/azuremonitor/handler.go @@ -5,7 +5,8 @@ import ( "compress/gzip" "context" "crypto/tls" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -22,6 +23,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/aadauth" "github.com/blackbirdworks/gopherstack/pkgs/devtls" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -347,11 +349,10 @@ func decodeContent(encoding string, data []byte) ([]byte, *apiError) { } func parseRecords(data []byte) ([]map[string]any, *apiError) { - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(data)) var records []map[string]any - if err := dec.Decode(&records); err != nil { + if err := json.UnmarshalDecode(dec, &records, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, newErr(http.StatusBadRequest, "InvalidPayload", "The request body must be a JSON array of objects: %v", err) } @@ -398,7 +399,7 @@ func parseQueryRequest(r *http.Request) (QueryRequest, bool, *apiError) { return req, false, newErr(http.StatusBadRequest, "BadArgumentError", "The request body could not be read.") } - if err = json.Unmarshal(data, &req); err != nil { + if err = json.Unmarshal(data, &req, jsonx.V1()); err != nil { return req, false, newErr(http.StatusBadRequest, "BadArgumentError", "The request body is not valid JSON: %v", err) } @@ -440,7 +441,7 @@ func (h *Handler) handleBatch(c *echo.Context) error { } var req batchRequest - if err = json.Unmarshal(data, &req); err != nil || len(req.Requests) == 0 { + if err = json.Unmarshal(data, &req, jsonx.V1()); err != nil || len(req.Requests) == 0 { return writeAPIError(c, newErr(http.StatusBadRequest, "BadArgumentError", "The batch must contain a non-empty 'requests' array.")) } diff --git a/services/azuremonitor/ingest.go b/services/azuremonitor/ingest.go index 44ba843586..66fe9b78c1 100644 --- a/services/azuremonitor/ingest.go +++ b/services/azuremonitor/ingest.go @@ -1,7 +1,6 @@ package azuremonitor import ( - "encoding/json" "errors" "fmt" "math" @@ -9,6 +8,7 @@ import ( "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuremonitor/kql" ) @@ -69,7 +69,7 @@ func convertDatetime(v any) (any, bool) { func numberToInt(v any) (int64, bool) { switch x := v.(type) { - case json.Number: + case jsonx.Number: n, err := x.Int64() return n, err == nil @@ -86,7 +86,7 @@ func numberToInt(v any) (int64, bool) { func numberToFloat(v any) (float64, bool) { switch x := v.(type) { - case json.Number: + case jsonx.Number: f, err := x.Float64() return f, err == nil @@ -103,7 +103,7 @@ func normalizeDynamic(v any) any { switch x := v.(type) { case float64: return kql.NormalizeJSON(x) - case json.Number: + case jsonx.Number: if n, err := x.Int64(); err == nil { return n } diff --git a/services/azuremonitor/kql/funcs.go b/services/azuremonitor/kql/funcs.go index 02edf9a6a3..ac26cf2176 100644 --- a/services/azuremonitor/kql/funcs.go +++ b/services/azuremonitor/kql/funcs.go @@ -2,7 +2,8 @@ package kql import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "math" "net/url" @@ -11,6 +12,8 @@ import ( "strings" "time" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -45,10 +48,9 @@ func sameAsFirst(a []Type) (Type, error) { return a[0], nil } func parseJSONValue(s string) (any, error) { var v any - dec := json.NewDecoder(strings.NewReader(s)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(s)) - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, err } diff --git a/services/azuremonitor/kql/golden_test.go b/services/azuremonitor/kql/golden_test.go index 532e10044b..f6a7fe4dc9 100644 --- a/services/azuremonitor/kql/golden_test.go +++ b/services/azuremonitor/kql/golden_test.go @@ -1,7 +1,7 @@ package kql_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuremonitor/kql" ) @@ -78,7 +79,7 @@ func render(rel *kql.Rel) (string, string) { } } - raw, _ := json.Marshal(rows) + raw, _ := json.Marshal(rows, jsonx.V1()) return cols, string(raw) } diff --git a/services/azuremonitor/kql/parser.go b/services/azuremonitor/kql/parser.go index 15a6d826b1..5d31f2aea4 100644 --- a/services/azuremonitor/kql/parser.go +++ b/services/azuremonitor/kql/parser.go @@ -1,11 +1,13 @@ package kql import ( - "encoding/json" + "encoding/json/v2" "math" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type parser struct { @@ -1385,9 +1387,9 @@ func dynamicLiteral(raw string) (node, error) { var v any - if err := json.Unmarshal([]byte(raw), &v); err != nil { + if err := json.Unmarshal([]byte(raw), &v, jsonx.V1()); err != nil { alt := strings.ReplaceAll(raw, "'", `"`) - if err2 := json.Unmarshal([]byte(alt), &v); err2 != nil { + if err2 := json.Unmarshal([]byte(alt), &v, jsonx.V1()); err2 != nil { return nil, syntaxErr("invalid dynamic literal") } } diff --git a/services/azuremonitor/kql/value.go b/services/azuremonitor/kql/value.go index e7d13fe3c7..59d914d551 100644 --- a/services/azuremonitor/kql/value.go +++ b/services/azuremonitor/kql/value.go @@ -3,11 +3,13 @@ package kql import ( - "encoding/json" + "encoding/json/v2" "math" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Type is a KQL column type name as it appears in query results. @@ -183,7 +185,7 @@ func groupKey(v any) string { return "d" + strconv.FormatInt(int64(x), 10) } - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) return "j" + string(raw) } @@ -273,7 +275,7 @@ func formatReal(f float64) string { } func jsonString(v any) string { - raw, err := json.Marshal(jsonable(v)) + raw, err := json.Marshal(jsonable(v), jsonx.V1()) if err != nil { return "" } @@ -342,7 +344,7 @@ func NormalizeJSON(v any) any { } return x - case json.Number: + case jsonx.Number: if i, err := x.Int64(); err == nil { return i } diff --git a/services/azuremonitor/sdk_test.go b/services/azuremonitor/sdk_test.go index e5c06fce97..5971a914c5 100644 --- a/services/azuremonitor/sdk_test.go +++ b/services/azuremonitor/sdk_test.go @@ -3,7 +3,7 @@ package azuremonitor_test import ( "bytes" "compress/gzip" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuremonitor" ) @@ -111,7 +112,7 @@ func TestIngestThenQuery(t *testing.T) { assert.Equal(t, tt.wantCols, cols) - raw, err := json.Marshal(res.Tables[0].Rows) + raw, err := json.Marshal(res.Tables[0].Rows, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.wantRows, string(raw)) }) @@ -461,7 +462,7 @@ func TestSnapshotRestoreKeepsRows(t *testing.T) { require.NoError(t, e2.handler.Restore(t.Context(), snap)) res := e2.run(t, s, "AppEvents_CL | order by Count asc | project Count, Value, Ok, Extra") - raw, err := json.Marshal(res.Tables[0].Rows) + raw, err := json.Marshal(res.Tables[0].Rows, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, `[[1,1.5,true,"{\"a\":1}"],[2,4,false,"[1,2]"],[3,2.5,true,null]]`, string(raw)) assert.Equal(t, queryazlogs.ColumnTypeLong, *res.Tables[0].Columns[0].Type) diff --git a/services/azureservicebus/handler.go b/services/azureservicebus/handler.go index ff633d251d..dfdcc682e6 100644 --- a/services/azureservicebus/handler.go +++ b/services/azureservicebus/handler.go @@ -4,7 +4,7 @@ import ( "context" "crypto/rand" "crypto/tls" - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -17,6 +17,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -849,7 +850,7 @@ func brokerPropertiesFromHeader(r *http.Request) brokerProperties { var bp brokerProperties - _ = json.Unmarshal([]byte(raw), &bp) + _ = json.Unmarshal([]byte(raw), &bp, jsonx.V1()) return bp } @@ -979,7 +980,7 @@ func (h *Handler) writeLockedMessage(c *echo.Context, req parsedRequest, info Me bp.LockToken = info.LockToken bp.LockedUntilUtc = info.LockedUntil.UTC().Format(http.TimeFormat) - bpJSON, err := json.Marshal(bp) + bpJSON, err := json.Marshal(bp, jsonx.V1()) if err != nil { return h.writeError(c, http.StatusInternalServerError, "InternalError", "Failed to marshal BrokerProperties.") } @@ -1199,7 +1200,7 @@ func (h *Handler) writeBodyReadError(c *echo.Context, err error) error { } func (h *Handler) writeError(c *echo.Context, status int, code, message string) error { - body, err := json.Marshal(azureError{Code: code, Message: message}) + body, err := json.Marshal(azureError{Code: code, Message: message}, jsonx.V1()) if err != nil { return c.String(http.StatusInternalServerError, "internal error") } diff --git a/services/azureservicebus/handler_test.go b/services/azureservicebus/handler_test.go index ba8728e9ef..97c3fa1e57 100644 --- a/services/azureservicebus/handler_test.go +++ b/services/azureservicebus/handler_test.go @@ -2,7 +2,7 @@ package azureservicebus_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureservicebus" ) @@ -146,7 +147,7 @@ func TestHandler_MessageLifecycle_Queue(t *testing.T) { var bp map[string]any - require.NoError(t, json.Unmarshal([]byte(bpHeader), &bp)) + require.NoError(t, json.Unmarshal([]byte(bpHeader), &bp, jsonx.V1())) messageID, _ := bp["MessageId"].(string) lockToken, _ := bp["LockToken"].(string) require.NotEmpty(t, messageID) diff --git a/services/azureservicebus/receive_handlers.go b/services/azureservicebus/receive_handlers.go index 894cb4d081..2435d7731c 100644 --- a/services/azureservicebus/receive_handlers.go +++ b/services/azureservicebus/receive_handlers.go @@ -1,7 +1,7 @@ package azureservicebus import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/textproto" @@ -9,6 +9,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Auto dead-letter reasons real Service Bus stamps on system dead-lettering. @@ -124,7 +126,7 @@ func (h *Handler) handleReceiveAndDelete(c *echo.Context, req parsedRequest) err } func (h *Handler) writeReceivedMessage(c *echo.Context, info MessageInfo) error { - bpJSON, err := json.Marshal(brokerPropertiesFor(info)) + bpJSON, err := json.Marshal(brokerPropertiesFor(info), jsonx.V1()) if err != nil { return h.writeError(c, http.StatusInternalServerError, "InternalError", "Failed to marshal BrokerProperties.") } diff --git a/services/azureservicebus/receive_test.go b/services/azureservicebus/receive_test.go index 3a46b51012..07c3701339 100644 --- a/services/azureservicebus/receive_test.go +++ b/services/azureservicebus/receive_test.go @@ -1,7 +1,7 @@ package azureservicebus_test import ( - "encoding/json" + "encoding/json/v2" "math" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azureservicebus" ) @@ -42,7 +43,7 @@ func peek(t *testing.T, h *azureservicebus.Handler, path string) []peekResp { require.Equal(t, http.StatusOK, rec.Code) var out []peekResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/azuretable/batch.go b/services/azuretable/batch.go index 0a9dd6b331..02988f5f0f 100644 --- a/services/azuretable/batch.go +++ b/services/azuretable/batch.go @@ -1,13 +1,14 @@ package azuretable import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/odatatable" ) @@ -102,7 +103,7 @@ func (h *Handler) batchSuccessPart( level := odataLevelFromAccept(o.Headers.Get("Accept")) - payload, err := json.Marshal(h.encodeEntity(info, o.Table, level, "")) + payload, err := json.Marshal(h.encodeEntity(info, o.Table, level, ""), jsonx.V1()) if err != nil { return part, err } diff --git a/services/azuretable/entity_ops_test.go b/services/azuretable/entity_ops_test.go index 1d8fcc5005..b04a6dc106 100644 --- a/services/azuretable/entity_ops_test.go +++ b/services/azuretable/entity_ops_test.go @@ -2,7 +2,7 @@ package azuretable_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuretable" ) @@ -31,7 +32,7 @@ func TestInsertEntity(t *testing.T) { assert.NotEmpty(t, rec.Header().Get("ETag")) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "p", got["PartitionKey"]) assert.Equal(t, "r", got["RowKey"]) assert.Equal(t, "hi", got["Name"]) @@ -173,7 +174,7 @@ func TestEntity_EDMTypeRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantValue, got["Prop"], tt.name) if tt.annPresent { @@ -221,7 +222,7 @@ func TestGetEntity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "x", got["A"]) assert.NotContains(t, got, "B") assert.Contains(t, got, "PartitionKey") @@ -255,7 +256,7 @@ func TestQueryEntities(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Value, 2) assert.Equal(t, "p1", body.Value[0]["PartitionKey"]) assert.Equal(t, "p2", body.Value[1]["PartitionKey"]) @@ -272,7 +273,7 @@ func TestQueryEntities(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Value, 1) assert.Equal(t, "p2", body.Value[0]["PartitionKey"]) }) @@ -297,7 +298,7 @@ func TestQueryEntities(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body.Value, 1) }) @@ -385,7 +386,7 @@ func TestReplaceEntity(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/"+testAccount+"/mytable(PartitionKey='p',RowKey='r')", nil) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "z", got["A"]) assert.NotContains(t, got, "B") }) @@ -412,7 +413,7 @@ func TestMergeEntity(t *testing.T) { rec2 := doRequest(t, h, http.MethodGet, "/"+testAccount+"/mytable(PartitionKey='p',RowKey='r')", nil) var got map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "z", got["A"]) assert.Equal(t, "y", got["B"]) }) @@ -469,7 +470,7 @@ func TestMergeEntity(t *testing.T) { // Merge semantics, not replace: B must survive. rec2 := doRequest(t, h, http.MethodGet, "/"+testAccount+"/mytable(PartitionKey='p',RowKey='r')", nil) var got map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "z", got["A"]) assert.Equal(t, "y", got["B"]) @@ -496,7 +497,7 @@ func TestMergeEntity(t *testing.T) { rec2 := doRequest(t, h, http.MethodGet, "/"+testAccount+"/mytable(PartitionKey='p',RowKey='r')", nil) var got map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "z", got["A"]) assert.Equal(t, "y", got["B"], "merge semantics must apply, not PUT's own replace semantics") }) diff --git a/services/azuretable/handler.go b/services/azuretable/handler.go index ecaa01c3ee..1ebca943db 100644 --- a/services/azuretable/handler.go +++ b/services/azuretable/handler.go @@ -3,7 +3,7 @@ package azuretable import ( "context" "crypto/rand" - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/azureauth" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/odatatable" @@ -626,7 +627,7 @@ func odataLevelFromAccept(accept string) string { func (h *Handler) writeJSON(c *echo.Context, status int, v any) error { level := odataLevelFromAccept(c.Request().Header.Get("Accept")) - body, err := json.Marshal(v) + body, err := json.Marshal(v, jsonx.V1()) if err != nil { return h.writeErrorNoRecurse(c, http.StatusInternalServerError, "InternalError", "Failed to marshal response.") } @@ -670,7 +671,7 @@ func (h *Handler) writeErrorNoRecurse(c *echo.Context, status int, code, message c.Response().Header().Set("X-Ms-Error-Code", code) body, _ := json.Marshal(odataErrorEnvelope{ Error: odataErrorDetail{Code: code, Message: odataErrorMessage{Lang: "en-US", Value: message}}, - }) + }, jsonx.V1()) return c.Blob(status, "application/json;odata=minimalmetadata;streaming=true;charset=utf-8", body) } diff --git a/services/azuretable/models_test.go b/services/azuretable/models_test.go index 4e89b9fdca..fc1c55cdde 100644 --- a/services/azuretable/models_test.go +++ b/services/azuretable/models_test.go @@ -1,7 +1,7 @@ package azuretable_test import ( - "encoding/json" + "encoding/json/v2" "math" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuretable" ) @@ -60,11 +61,11 @@ func TestEntityProperty_JSONRoundTrip(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - data, err := json.Marshal(tt.prop) + data, err := json.Marshal(tt.prop, jsonx.V1()) require.NoError(t, err, tt.name) var got azuretable.EntityProperty - require.NoError(t, json.Unmarshal(data, &got), tt.name) + require.NoError(t, json.Unmarshal(data, &got, jsonx.V1()), tt.name) assert.Equal(t, tt.prop.Type, got.Type, tt.name) @@ -113,7 +114,7 @@ func TestEntityProperty_MarshalJSON_TypeMismatchErrors(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - _, err := json.Marshal(tt.prop) + _, err := json.Marshal(tt.prop, jsonx.V1()) require.Error(t, err, tt.name) }) } @@ -147,7 +148,7 @@ func TestEntityProperty_UnmarshalJSON_MalformedValueErrors(t *testing.T) { t.Parallel() var p azuretable.EntityProperty - err := json.Unmarshal([]byte(tt.json), &p) + err := json.Unmarshal([]byte(tt.json), &p, jsonx.V1()) require.Error(t, err, tt.name) }) } diff --git a/services/azuretable/sdk_wire_test.go b/services/azuretable/sdk_wire_test.go index a8e2a8dc77..dae611b2ca 100644 --- a/services/azuretable/sdk_wire_test.go +++ b/services/azuretable/sdk_wire_test.go @@ -1,7 +1,7 @@ package azuretable_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuretable" ) @@ -42,7 +43,7 @@ func sdkEntity(t *testing.T, pk, rk string, extra map[string]any) []byte { m := map[string]any{"PartitionKey": pk, "RowKey": rk} maps.Copy(m, extra) - b, err := json.Marshal(m) + b, err := json.Marshal(m, jsonx.V1()) require.NoError(t, err) return b @@ -224,7 +225,7 @@ func TestEdmDoubleRoundTripSDK(t *testing.T) { PartitionKey: "p", RowKey: "r", Properties: map[string]any{"D": 5.0}, } - raw, err := json.Marshal(ent) + raw, err := json.Marshal(ent, jsonx.V1()) require.NoError(t, err) _, err = client.AddEntity(ctx, raw, nil) require.NoError(t, err) @@ -233,7 +234,7 @@ func TestEdmDoubleRoundTripSDK(t *testing.T) { require.NoError(t, err) var back aztables.EDMEntity - require.NoError(t, json.Unmarshal(got.Value, &back)) + require.NoError(t, json.Unmarshal(got.Value, &back, jsonx.V1())) assert.InDelta(t, 5.0, back.Properties["D"], 0) } diff --git a/services/azuretable/table_ops.go b/services/azuretable/table_ops.go index 59a6074641..c9e930d37d 100644 --- a/services/azuretable/table_ops.go +++ b/services/azuretable/table_ops.go @@ -1,13 +1,14 @@ package azuretable import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/odatatable" ) @@ -32,7 +33,7 @@ func (h *Handler) createTable(c *echo.Context) error { } var req createTableBody - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInput", "The input is not valid.") } diff --git a/services/azuretable/table_ops_test.go b/services/azuretable/table_ops_test.go index 283f1b6464..0a97e5c938 100644 --- a/services/azuretable/table_ops_test.go +++ b/services/azuretable/table_ops_test.go @@ -1,7 +1,7 @@ package azuretable_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateTable(t *testing.T) { @@ -24,7 +26,7 @@ func TestCreateTable(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "mytable", body["TableName"]) assert.Contains(t, body, "odata.metadata") }) @@ -94,7 +96,7 @@ func TestListTables(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Value, 2) assert.Equal(t, "tablea", body.Value[0]["TableName"]) assert.Equal(t, "tableb", body.Value[1]["TableName"]) @@ -117,7 +119,7 @@ func TestListTables_NoMetadataLevel(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Value, 1) assert.NotContains(t, body.Value[0], "odata.metadata") assert.Contains(t, rec.Header().Get("Content-Type"), "odata=nometadata") @@ -140,7 +142,7 @@ func TestListTables_FullMetadataLevel(t *testing.T) { var body struct { Value []map[string]any `json:"value"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Value, 1) assert.Contains(t, body.Value[0], "odata.type") assert.Contains(t, body.Value[0], "odata.id") @@ -200,7 +202,7 @@ func TestGetTable(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "m8table", body["TableName"]) }) diff --git a/services/backup/async_jobs.go b/services/backup/async_jobs.go index 0022da64d2..371e3ae2e2 100644 --- a/services/backup/async_jobs.go +++ b/services/backup/async_jobs.go @@ -2,7 +2,7 @@ package backup import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" "time" @@ -97,7 +97,7 @@ func (b *InMemoryBackend) restoreResourceLocked(job *RestoreJob) (string, error) } // captureSnapshotLocked snapshots the backed-up resource when an engine is wired for its type. -func (b *InMemoryBackend) captureSnapshotLocked(job *Job) (json.RawMessage, error) { +func (b *InMemoryBackend) captureSnapshotLocked(job *Job) (jsontext.Value, error) { engine := b.engines[job.ResourceType] if engine == nil { return nil, nil diff --git a/services/backup/backup_plans.go b/services/backup/backup_plans.go index aa9013be8d..745a3d63b3 100644 --- a/services/backup/backup_plans.go +++ b/services/backup/backup_plans.go @@ -1,7 +1,7 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -211,7 +212,7 @@ func (b *InMemoryBackend) ExportBackupPlanTemplate(planID string) (string, error doc.AdvancedBackupSettings = advancedSettingsToJSON(plan.AdvancedBackupSettings) } - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return "", err } diff --git a/services/backup/copy_jobs.go b/services/backup/copy_jobs.go index 434401061b..598704cf85 100644 --- a/services/backup/copy_jobs.go +++ b/services/backup/copy_jobs.go @@ -1,7 +1,7 @@ package backup import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "strings" @@ -192,7 +192,7 @@ func (b *InMemoryBackend) settleCopyJobLocked(job *CopyJob, now time.Time) { return } - var snapshot json.RawMessage + var snapshot jsontext.Value if srcName, ok := b.vaultARNIndex[job.SourceBackupVaultArn]; ok { if srcRP, rpFound := b.recoveryPoints.Get(recoveryPointKey(srcName, job.SourceRecoveryPointArn)); rpFound { snapshot = srcRP.Snapshot diff --git a/services/backup/ddb_item_codec.go b/services/backup/ddb_item_codec.go index 88efbdd7ee..cfd6bda358 100644 --- a/services/backup/ddb_item_codec.go +++ b/services/backup/ddb_item_codec.go @@ -2,20 +2,23 @@ package backup import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" ddbtypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) -func encodeDDBItem(item map[string]ddbtypes.AttributeValue) (map[string]json.RawMessage, error) { - out := make(map[string]json.RawMessage, len(item)) +func encodeDDBItem(item map[string]ddbtypes.AttributeValue) (map[string]jsontext.Value, error) { + out := make(map[string]jsontext.Value, len(item)) for k, v := range item { w, err := ddbAttrToWire(v) if err != nil { return nil, err } - raw, err := json.Marshal(w) + raw, err := json.Marshal(w, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode attribute %s: %w", k, err) } @@ -25,11 +28,11 @@ func encodeDDBItem(item map[string]ddbtypes.AttributeValue) (map[string]json.Raw return out, nil } -func decodeDDBItem(raw map[string]json.RawMessage) (map[string]ddbtypes.AttributeValue, error) { +func decodeDDBItem(raw map[string]jsontext.Value) (map[string]ddbtypes.AttributeValue, error) { out := make(map[string]ddbtypes.AttributeValue, len(raw)) for k, r := range raw { var w map[string]any - if err := json.Unmarshal(r, &w); err != nil { + if err := json.Unmarshal(r, &w, jsonx.V1()); err != nil { return nil, fmt.Errorf("decode attribute %s: %w", k, err) } av, err := ddbWireToAttr(w) diff --git a/services/backup/handler_backup_access_points.go b/services/backup/handler_backup_access_points.go index f530564315..c823829225 100644 --- a/services/backup/handler_backup_access_points.go +++ b/services/backup/handler_backup_access_points.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createBackupAccessPointBody struct { @@ -18,7 +20,7 @@ type createBackupAccessPointBody struct { func (h *Handler) handleCreateBackupAccessPoint(c *echo.Context, body []byte) error { var in createBackupAccessPointBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_backup_jobs.go b/services/backup/handler_backup_jobs.go index 99a76d29ad..e20b9e21b2 100644 --- a/services/backup/handler_backup_jobs.go +++ b/services/backup/handler_backup_jobs.go @@ -1,11 +1,13 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type startBackupJobBody struct { @@ -22,7 +24,7 @@ type startBackupJobBody struct { func (h *Handler) handleStartBackupJob(c *echo.Context, body []byte) error { var in startBackupJobBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_backup_jobs_test.go b/services/backup/handler_backup_jobs_test.go index 3e4cd86d2d..0fc3189eae 100644 --- a/services/backup/handler_backup_jobs_test.go +++ b/services/backup/handler_backup_jobs_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -51,14 +52,14 @@ func TestDescribeBackupJobProgressFields(t *testing.T) { require.Equal(t, http.StatusOK, startResp.Code) var startData map[string]any - require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startData)) + require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startData, jsonx.V1())) jobID := startData["BackupJobId"].(string) descResp := doRequest(t, h, http.MethodGet, "/backup-jobs/"+jobID, "") require.Equal(t, http.StatusOK, descResp.Code) var descData map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descData)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descData, jsonx.V1())) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/services/backup/handler_backup_plans.go b/services/backup/handler_backup_plans.go index deb1ec9700..3177a22427 100644 --- a/services/backup/handler_backup_plans.go +++ b/services/backup/handler_backup_plans.go @@ -1,12 +1,14 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createBackupPlanBody struct { @@ -16,7 +18,7 @@ type createBackupPlanBody struct { func (h *Handler) handleCreateBackupPlan(c *echo.Context, body []byte) error { var in createBackupPlanBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -146,7 +148,7 @@ type updateBackupPlanBody struct { func (h *Handler) handleUpdateBackupPlan(c *echo.Context, id string, body []byte) error { var in updateBackupPlanBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -305,7 +307,7 @@ func (h *Handler) dispatchPlanTemplateCatalogOps( var reqBody struct { BackupPlanTemplateJSON string `json:"BackupPlanTemplateJson"` } - if err := json.Unmarshal(body, &reqBody); err != nil { + if err := json.Unmarshal(body, &reqBody, jsonx.V1()); err != nil { return true, c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -313,7 +315,7 @@ func (h *Handler) dispatchPlanTemplateCatalogOps( } var doc backupPlanBodyDoc - if err := json.Unmarshal([]byte(reqBody.BackupPlanTemplateJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(reqBody.BackupPlanTemplateJSON), &doc, jsonx.V1()); err != nil { return true, c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid BackupPlanTemplateJson"), diff --git a/services/backup/handler_backup_plans_test.go b/services/backup/handler_backup_plans_test.go index b9253064df..81c79c52a1 100644 --- a/services/backup/handler_backup_plans_test.go +++ b/services/backup/handler_backup_plans_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -33,7 +34,7 @@ func TestUpdateBackupPlanUpdateDate(t *testing.T) { }`) require.Equal(t, http.StatusOK, createResp.Code) var createData map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createData)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createData, jsonx.V1())) planID := createData["BackupPlanId"].(string) updateResp := doRequest(t, h, http.MethodPost, "/backup/plans/"+planID, `{ @@ -45,7 +46,7 @@ func TestUpdateBackupPlanUpdateDate(t *testing.T) { require.Equal(t, http.StatusOK, updateResp.Code) var updateData map[string]any - require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &updateData)) + require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &updateData, jsonx.V1())) assert.NotContains(t, updateData, "UpdateDate", "UpdateBackupPlanOutput has no UpdateDate member") @@ -105,7 +106,7 @@ func TestCreateBackupPlanAdvancedBackupSettings(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) if tc.wantInResponse { settings, ok := data["AdvancedBackupSettings"].([]any) @@ -255,14 +256,14 @@ func TestRuleLifecycle(t *testing.T) { "BackupPlanName": "test-plan", "Rules": tt.rules, }, - }) + }, jsonx.V1()) require.NoError(t, err) resp := doRequest(t, h, http.MethodPut, "/backup/plans", string(body)) require.Equal(t, http.StatusOK, resp.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createResp, jsonx.V1())) planID := createResp["BackupPlanId"].(string) // Retrieve and verify. @@ -271,7 +272,7 @@ func TestRuleLifecycle(t *testing.T) { _ = b var getPlan map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getPlan)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getPlan, jsonx.V1())) backupPlan := getPlan["BackupPlan"].(map[string]any) rules := backupPlan["Rules"].([]any) tt.wantInRules(t, rules) @@ -335,21 +336,21 @@ func TestAdvancedBackupSettings(t *testing.T) { planBody["BackupPlan"].(map[string]any)["AdvancedBackupSettings"] = tt.advancedSettings } - body, err := json.Marshal(planBody) + body, err := json.Marshal(planBody, jsonx.V1()) require.NoError(t, err) resp := doRequest(t, h, http.MethodPut, "/backup/plans", string(body)) require.Equal(t, http.StatusOK, resp.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createResp, jsonx.V1())) planID := createResp["BackupPlanId"].(string) getResp := doRequest(t, h, http.MethodGet, "/backup/plans/"+planID, "") require.Equal(t, http.StatusOK, getResp.Code) var getPlan map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getPlan)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getPlan, jsonx.V1())) backupPlan := getPlan["BackupPlan"].(map[string]any) if tt.advancedSettings != nil { diff --git a/services/backup/handler_copy_jobs.go b/services/backup/handler_copy_jobs.go index d27fb51889..8ac655223d 100644 --- a/services/backup/handler_copy_jobs.go +++ b/services/backup/handler_copy_jobs.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListCopyJobs(c *echo.Context) error { @@ -100,7 +102,7 @@ func (h *Handler) dispatchCopyJobExtraOps(c *echo.Context, route backupRoute, bo DestinationBackupVaultArn string `json:"DestinationBackupVaultArn"` IamRoleArn string `json:"IamRoleArn"` } - if err := json.Unmarshal(body, ©JobReq); err != nil { + if err := json.Unmarshal(body, ©JobReq, jsonx.V1()); err != nil { return true, c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_copy_jobs_test.go b/services/backup/handler_copy_jobs_test.go index 49e8367626..e3ee7958c8 100644 --- a/services/backup/handler_copy_jobs_test.go +++ b/services/backup/handler_copy_jobs_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -35,7 +36,7 @@ func TestStartCopyJobCreationDateEpoch(t *testing.T) { }`) require.Equal(t, http.StatusOK, resp.Code) var startData map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &startData)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &startData, jsonx.V1())) jobID := startData["BackupJobId"].(string) rpArn := "arn:aws:backup:us-east-1:000000000000:recovery-point:rp-copy-1" @@ -49,7 +50,7 @@ func TestStartCopyJobCreationDateEpoch(t *testing.T) { _ = jobID var copyData map[string]any - require.NoError(t, json.Unmarshal(copyResp.Body.Bytes(), ©Data)) + require.NoError(t, json.Unmarshal(copyResp.Body.Bytes(), ©Data, jsonx.V1())) assert.NotEmpty(t, copyData["CopyJobId"], "CopyJobId must be present") creationDate, exists := copyData["CreationDate"] diff --git a/services/backup/handler_dispatch.go b/services/backup/handler_dispatch.go index 68b3b18eec..88fd9f0295 100644 --- a/services/backup/handler_dispatch.go +++ b/services/backup/handler_dispatch.go @@ -2,7 +2,8 @@ package backup import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "regexp" @@ -14,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -184,9 +186,9 @@ func (h *Handler) Handler() echo.HandlerFunc { var body []byte if c.Request().Body != nil { - decoder := json.NewDecoder(c.Request().Body) - var raw json.RawMessage - if err := decoder.Decode(&raw); err == nil { + decoder := jsontext.NewDecoder(c.Request().Body) + var raw jsontext.Value + if err := json.UnmarshalDecode(decoder, &raw, jsonx.V1()); err == nil { body = raw } } diff --git a/services/backup/handler_frameworks.go b/services/backup/handler_frameworks.go index 8f0ed1a884..8e2d996d77 100644 --- a/services/backup/handler_frameworks.go +++ b/services/backup/handler_frameworks.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // controlInputParameterJSON is ControlInputParameter's wire shape: a single @@ -98,7 +100,7 @@ type createFrameworkBody struct { func (h *Handler) handleCreateFramework(c *echo.Context, body []byte) error { var in createFrameworkBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -193,7 +195,7 @@ func (h *Handler) handleUpdateFramework(c *echo.Context, name string, body []byt var in updateFrameworkBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_frameworks_test.go b/services/backup/handler_frameworks_test.go index e6c251356c..2f2d567dad 100644 --- a/services/backup/handler_frameworks_test.go +++ b/services/backup/handler_frameworks_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -70,7 +71,7 @@ func TestFrameworkControls(t *testing.T) { require.Equal(t, tt.wantStatus, resp.Code) var createData map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createData)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createData, jsonx.V1())) fwName := createData["FrameworkName"].(string) // Describe and verify controls. @@ -78,7 +79,7 @@ func TestFrameworkControls(t *testing.T) { require.Equal(t, http.StatusOK, getResp.Code) var fwData map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &fwData)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &fwData, jsonx.V1())) assert.Equal(t, tt.wantStatus2, fwData["FrameworkStatus"]) assert.Equal(t, "COMPLETED", fwData["DeploymentStatus"]) if tt.wantControlLen > 0 { diff --git a/services/backup/handler_legal_holds.go b/services/backup/handler_legal_holds.go index 0622fddc5d..9d370a66dd 100644 --- a/services/backup/handler_legal_holds.go +++ b/services/backup/handler_legal_holds.go @@ -1,11 +1,13 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCancelLegalHold(c *echo.Context, legalHoldID string) error { @@ -70,7 +72,7 @@ type createLegalHoldBody struct { func (h *Handler) handleCreateLegalHold(c *echo.Context, body []byte) error { var in createLegalHoldBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_recovery_points.go b/services/backup/handler_recovery_points.go index ef7d8fef80..82a839df16 100644 --- a/services/backup/handler_recovery_points.go +++ b/services/backup/handler_recovery_points.go @@ -1,12 +1,14 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // splitVaultRP splits a "vaultName|recoveryPointArn" resource string. @@ -362,7 +364,7 @@ func (h *Handler) handleUpdateRecoveryPointIndexSettings( var reqBody struct { Index string `json:"Index"` } - _ = json.Unmarshal(body, &reqBody) + _ = json.Unmarshal(body, &reqBody, jsonx.V1()) if err := h.Backend.UpdateRecoveryPointIndexSettings(vaultName, rpArn, reqBody.Index); err != nil { return h.handleError(c, err) @@ -388,7 +390,7 @@ func (h *Handler) handleUpdateRecoveryPointLifecycle( DeleteAfterDays int64 `json:"DeleteAfterDays"` } `json:"Lifecycle"` } - _ = json.Unmarshal(body, &reqBody) + _ = json.Unmarshal(body, &reqBody, jsonx.V1()) if err := h.Backend.UpdateRecoveryPointLifecycle(vaultName, rpArn, reqBody.Lifecycle.MoveToColdStorageAfterDays, reqBody.Lifecycle.DeleteAfterDays); err != nil { diff --git a/services/backup/handler_recovery_points_test.go b/services/backup/handler_recovery_points_test.go index d1a2bc7969..c5e2c6102e 100644 --- a/services/backup/handler_recovery_points_test.go +++ b/services/backup/handler_recovery_points_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -111,7 +112,7 @@ func TestRecoveryPointNewFields(t *testing.T) { require.Equal(t, http.StatusOK, descResp.Code) var respData map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &respData)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &respData, jsonx.V1())) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/services/backup/handler_report_plans.go b/services/backup/handler_report_plans.go index 62e76ee4c9..6df6e35630 100644 --- a/services/backup/handler_report_plans.go +++ b/services/backup/handler_report_plans.go @@ -1,12 +1,14 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ScanJobsFilterFromQuery builds a ListScanJobsFilter from ListScanJobs @@ -140,7 +142,7 @@ type createReportPlanBody struct { func (h *Handler) handleCreateReportPlan(c *echo.Context, body []byte) error { var in createReportPlanBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -239,7 +241,7 @@ func (h *Handler) handleUpdateReportPlan(c *echo.Context, name string, body []by var in updateReportPlanBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -413,7 +415,7 @@ func (h *Handler) handleStartScanJob(c *echo.Context, body []byte) error { IdempotencyToken string `json:"IdempotencyToken"` ScanBaseRecoveryPointArn string `json:"ScanBaseRecoveryPointArn"` } - if err := json.Unmarshal(body, &reqBody); err != nil { + if err := json.Unmarshal(body, &reqBody, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_report_plans_test.go b/services/backup/handler_report_plans_test.go index 532823e84f..c1c12cf050 100644 --- a/services/backup/handler_report_plans_test.go +++ b/services/backup/handler_report_plans_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -76,7 +77,7 @@ func TestReportPlanSubFields(t *testing.T) { require.Equal(t, tt.wantStatus, resp.Code) var createData map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createData)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &createData, jsonx.V1())) rpName := createData["ReportPlanName"].(string) // Describe and verify sub-fields. @@ -84,7 +85,7 @@ func TestReportPlanSubFields(t *testing.T) { require.Equal(t, http.StatusOK, getResp.Code) var getData map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData, jsonx.V1())) rpDoc := getData["ReportPlan"].(map[string]any) if tt.wantDelivery { @@ -142,7 +143,7 @@ func TestReportPlanFullShape(t *testing.T) { getResp := doRequest(t, h, http.MethodGet, "/audit/report-plans/rp-full-shape", "") require.Equal(t, http.StatusOK, getResp.Code) var getData map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData, jsonx.V1())) rpDoc := getData["ReportPlan"].(map[string]any) ch := rpDoc["ReportDeliveryChannel"].(map[string]any) @@ -169,7 +170,7 @@ func TestReportPlanFullShape(t *testing.T) { getResp2 := doRequest(t, h, http.MethodGet, "/audit/report-plans/rp-full-shape", "") var getData2 map[string]any - require.NoError(t, json.Unmarshal(getResp2.Body.Bytes(), &getData2)) + require.NoError(t, json.Unmarshal(getResp2.Body.Bytes(), &getData2, jsonx.V1())) rpDoc2 := getData2["ReportPlan"].(map[string]any) assert.Equal(t, "updated", rpDoc2["ReportPlanDescription"]) ch2 := rpDoc2["ReportDeliveryChannel"].(map[string]any) diff --git a/services/backup/handler_restore_jobs.go b/services/backup/handler_restore_jobs.go index 2f8287ebb5..40a1042b13 100644 --- a/services/backup/handler_restore_jobs.go +++ b/services/backup/handler_restore_jobs.go @@ -1,11 +1,13 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // RestoreJobsFilterFromQuery builds a ListRestoreJobsFilter from ListRestoreJobs @@ -92,7 +94,7 @@ func (h *Handler) handleStartRestoreJob(c *echo.Context, defaultRecoveryPointArn ResourceType string `json:"ResourceType"` IdempotencyToken string `json:"IdempotencyToken"` } - if err := json.Unmarshal(body, &reqBody); err != nil { + if err := json.Unmarshal(body, &reqBody, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } if reqBody.RecoveryPointArn == "" { @@ -126,7 +128,7 @@ func (h *Handler) handlePutRestoreValidationResult(c *echo.Context, restoreJobID ValidationStatus string `json:"ValidationStatus"` ValidationStatusMessage string `json:"ValidationStatusMessage"` } - if err := json.Unmarshal(body, &reqBody); err != nil { + if err := json.Unmarshal(body, &reqBody, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_restore_testing.go b/services/backup/handler_restore_testing.go index 3c44f6069b..745b62bf26 100644 --- a/services/backup/handler_restore_testing.go +++ b/services/backup/handler_restore_testing.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // restoreTestingRecoveryPointSelectionJSON is the wire shape of @@ -71,7 +73,7 @@ type createRestoreTestingPlanBody struct { func (h *Handler) handleCreateRestoreTestingPlan(c *echo.Context, body []byte) error { var in createRestoreTestingPlanBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -229,7 +231,7 @@ func (h *Handler) handleCreateRestoreTestingSelection( } var in createRestoreTestingSelectionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -331,7 +333,7 @@ func (h *Handler) handleUpdateRestoreTestingPlan( var in updateRestoreTestingPlanBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -445,7 +447,7 @@ func (h *Handler) handleUpdateRestoreTestingSelection( var in updateRestoreTestingSelectionBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_selections.go b/services/backup/handler_selections.go index d30b133e5d..99fa684980 100644 --- a/services/backup/handler_selections.go +++ b/services/backup/handler_selections.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type backupSelectionDoc struct { @@ -30,7 +32,7 @@ func (h *Handler) handleCreateBackupSelection(c *echo.Context, planID string, bo } var in createBackupSelectionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_selections_test.go b/services/backup/handler_selections_test.go index 670fa1a696..61d1b49470 100644 --- a/services/backup/handler_selections_test.go +++ b/services/backup/handler_selections_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -109,18 +110,18 @@ func TestBackupSelectionResourceFields(t *testing.T) { `{"BackupPlan":{"BackupPlanName":"p","Rules":[{"RuleName":"r","TargetBackupVaultName":"v"}]}}`) require.Equal(t, http.StatusOK, planResp.Code) var planData map[string]any - require.NoError(t, json.Unmarshal(planResp.Body.Bytes(), &planData)) + require.NoError(t, json.Unmarshal(planResp.Body.Bytes(), &planData, jsonx.V1())) planID := planData["BackupPlanId"].(string) // Create selection. - body, err := json.Marshal(map[string]any{"BackupSelection": tt.selection}) + body, err := json.Marshal(map[string]any{"BackupSelection": tt.selection}, jsonx.V1()) require.NoError(t, err) selResp := doRequest(t, h, http.MethodPut, "/backup/plans/"+planID+"/selections", string(body)) require.Equal(t, http.StatusOK, selResp.Code) var selData map[string]any - require.NoError(t, json.Unmarshal(selResp.Body.Bytes(), &selData)) + require.NoError(t, json.Unmarshal(selResp.Body.Bytes(), &selData, jsonx.V1())) selID := selData["SelectionId"].(string) // Get selection and verify fields. @@ -129,7 +130,7 @@ func TestBackupSelectionResourceFields(t *testing.T) { require.Equal(t, http.StatusOK, getResp.Code) var getData map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getData, jsonx.V1())) selDoc := getData["BackupSelection"].(map[string]any) tt.wantSel(t, selDoc) }) diff --git a/services/backup/handler_settings.go b/services/backup/handler_settings.go index f74adb5b5f..ff43bc0227 100644 --- a/services/backup/handler_settings.go +++ b/services/backup/handler_settings.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchSettingsOps handles the account-level global/region settings and @@ -26,7 +28,7 @@ func (h *Handler) dispatchSettingsOps( var reqGSBody struct { GlobalSettings map[string]string `json:"GlobalSettings"` } - if err := json.Unmarshal(body, &reqGSBody); err == nil && + if err := json.Unmarshal(body, &reqGSBody, jsonx.V1()); err == nil && reqGSBody.GlobalSettings != nil { h.Backend.UpdateGlobalSettings(reqGSBody.GlobalSettings) } @@ -44,7 +46,7 @@ func (h *Handler) dispatchSettingsOps( ResourceTypeManagementPreference map[string]bool `json:"ResourceTypeManagementPreference"` ResourceTypeOptInPreference map[string]bool `json:"ResourceTypeOptInPreference"` } - if err := json.Unmarshal(body, &reqRSBody); err == nil { + if err := json.Unmarshal(body, &reqRSBody, jsonx.V1()); err == nil { h.Backend.UpdateRegionSettings( reqRSBody.ResourceTypeManagementPreference, reqRSBody.ResourceTypeOptInPreference, diff --git a/services/backup/handler_tags.go b/services/backup/handler_tags.go index 667411460b..451d0dbd07 100644 --- a/services/backup/handler_tags.go +++ b/services/backup/handler_tags.go @@ -1,12 +1,14 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "slices" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceBody struct { @@ -15,7 +17,7 @@ type tagResourceBody struct { func (h *Handler) handleTagResource(c *echo.Context, resourceArn string, body []byte) error { var in tagResourceBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -61,7 +63,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, resourceArn string, body var in untagResourceBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_templates_test.go b/services/backup/handler_templates_test.go index 139c14a672..b3beee0685 100644 --- a/services/backup/handler_templates_test.go +++ b/services/backup/handler_templates_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -41,19 +42,19 @@ func TestExportBackupPlanTemplate_RealRules(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) planID := created["BackupPlanId"].(string) resp := doRequest(t, h, http.MethodGet, "/backup/plans/"+planID+"/toTemplate", "") require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) tmplJSON, ok := out["BackupPlanTemplateJson"].(string) require.True(t, ok) var tmpl map[string]any - require.NoError(t, json.Unmarshal([]byte(tmplJSON), &tmpl)) + require.NoError(t, json.Unmarshal([]byte(tmplJSON), &tmpl, jsonx.V1())) assert.Equal(t, "export-plan", tmpl["BackupPlanName"]) rules, ok := tmpl["Rules"].([]any) require.True(t, ok) @@ -75,7 +76,7 @@ func TestGetBackupPlanFromJSON_BuildsFromParsedBody(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) plan, ok := out["BackupPlan"].(map[string]any) require.True(t, ok) assert.Equal(t, "json-plan", plan["BackupPlanName"]) @@ -107,7 +108,7 @@ func TestGetBackupPlanFromTemplate_ResolvesBuiltinTemplate(t *testing.T) { require.Equal(t, http.StatusOK, listResp.Code) var list map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &list, jsonx.V1())) tmpls, ok := list["BackupPlanTemplatesList"].([]any) require.True(t, ok) require.NotEmpty(t, tmpls) @@ -120,7 +121,7 @@ func TestGetBackupPlanFromTemplate_ResolvesBuiltinTemplate(t *testing.T) { require.Equal(t, http.StatusOK, getResp.Code) var doc map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &doc, jsonx.V1())) planDoc, ok := doc["BackupPlanDocument"].(map[string]any) require.True(t, ok) assert.Equal(t, tmplName, planDoc["BackupPlanName"]) @@ -148,7 +149,7 @@ func TestListBackupPlanTemplates_ReturnsBuiltinCatalog(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) items, ok := out["BackupPlanTemplatesList"].([]any) require.True(t, ok) require.NotEmpty(t, items) diff --git a/services/backup/handler_tiering.go b/services/backup/handler_tiering.go index 7e450eecc4..b63ec786e4 100644 --- a/services/backup/handler_tiering.go +++ b/services/backup/handler_tiering.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -103,7 +105,7 @@ func (h *Handler) dispatchTieringOps( func (h *Handler) handleCreateTieringConfiguration(c *echo.Context, body []byte) error { var in createTieringConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } @@ -167,7 +169,7 @@ func (h *Handler) handleListTieringConfigurations(c *echo.Context) error { func (h *Handler) handleUpdateTieringConfiguration(c *echo.Context, name string, body []byte) error { var in updateTieringConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_vault_policies.go b/services/backup/handler_vault_policies.go index 39a10bf864..f92566be31 100644 --- a/services/backup/handler_vault_policies.go +++ b/services/backup/handler_vault_policies.go @@ -1,10 +1,12 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putVaultAccessPolicyBody struct { @@ -25,7 +27,7 @@ func (h *Handler) handlePutBackupVaultAccessPolicy( var in putVaultAccessPolicyBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -100,7 +102,7 @@ func (h *Handler) handlePutBackupVaultLockConfiguration( var in putVaultLockConfigBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -158,7 +160,7 @@ func (h *Handler) handlePutBackupVaultNotifications( var in putVaultNotificationsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), diff --git a/services/backup/handler_vault_policies_test.go b/services/backup/handler_vault_policies_test.go index 81874b9396..8c72d331d3 100644 --- a/services/backup/handler_vault_policies_test.go +++ b/services/backup/handler_vault_policies_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -59,7 +60,7 @@ func TestDescribeBackupVaultLockedField(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) locked, exists := data["Locked"] require.True(t, exists, "Locked must be present in DescribeBackupVault response") diff --git a/services/backup/handler_vaults.go b/services/backup/handler_vaults.go index 0f0236a652..5eefb43655 100644 --- a/services/backup/handler_vaults.go +++ b/services/backup/handler_vaults.go @@ -1,11 +1,13 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createBackupVaultBody struct { @@ -24,7 +26,7 @@ func (h *Handler) handleCreateBackupVault(c *echo.Context, name string, body []b var in createBackupVaultBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -192,7 +194,7 @@ func (h *Handler) handleAssociateBackupVaultMpaApprovalTeam( var in associateMpaApprovalTeamBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -230,7 +232,7 @@ func (h *Handler) handleCreateLogicallyAirGappedBackupVault( var in createLogicallyAirGappedBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body"), @@ -264,7 +266,7 @@ type createRestoreAccessVaultBody struct { func (h *Handler) handleCreateRestoreAccessBackupVault(c *echo.Context, body []byte) error { var in createRestoreAccessVaultBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterValueException", "invalid request body")) } diff --git a/services/backup/handler_vaults_test.go b/services/backup/handler_vaults_test.go index fba8592d38..1da6aea43d 100644 --- a/services/backup/handler_vaults_test.go +++ b/services/backup/handler_vaults_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -33,7 +34,7 @@ func TestDescribeBackupVaultVaultState(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) state, exists := data["VaultState"] require.True(t, exists, "VaultState must be present in DescribeBackupVault response") @@ -67,7 +68,7 @@ func TestListBackupVaultsVaultState(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) list, ok := data["BackupVaultList"].([]any) require.True(t, ok, "BackupVaultList must be present") @@ -184,14 +185,14 @@ func TestCreateVaultCreatorRequestIdIdempotency(t *testing.T) { r1 := doRequest(t, h, http.MethodPut, "/backup-vaults/idem-vault", tt.firstRequest) require.Equal(t, http.StatusOK, r1.Code) var d1 map[string]any - require.NoError(t, json.Unmarshal(r1.Body.Bytes(), &d1)) + require.NoError(t, json.Unmarshal(r1.Body.Bytes(), &d1, jsonx.V1())) arn1 := d1["BackupVaultArn"].(string) r2 := doRequest(t, h, http.MethodPut, "/backup-vaults/idem-vault", tt.secondRequest) assert.Equal(t, tt.wantSecondCode, r2.Code) if tt.wantSameArn { var d2 map[string]any - require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &d2)) + require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &d2, jsonx.V1())) assert.Equal(t, arn1, d2["BackupVaultArn"].(string)) } }) diff --git a/services/backup/helpers_test.go b/services/backup/helpers_test.go index 19c61685f9..cd53f98ad0 100644 --- a/services/backup/helpers_test.go +++ b/services/backup/helpers_test.go @@ -2,7 +2,7 @@ package backup_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -131,7 +132,7 @@ func doREST( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -151,7 +152,7 @@ func parseResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/backup/models.go b/services/backup/models.go index bc78d665c9..ad7e7906dd 100644 --- a/services/backup/models.go +++ b/services/backup/models.go @@ -1,7 +1,7 @@ package backup import ( - "encoding/json" + "encoding/json/jsontext" "time" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -401,7 +401,7 @@ type RecoveryPoint struct { SourceBackupVaultArn string `json:"sourceBackupVaultArn,omitempty"` ParentRecoveryPointArn string `json:"parentRecoveryPointArn,omitempty"` CompositeMemberIdentifier string `json:"compositeMemberIdentifier,omitempty"` - Snapshot json.RawMessage `json:"snapshot,omitempty"` + Snapshot jsontext.Value `json:"snapshot,omitempty"` BackupSizeInBytes int64 `json:"backupSizeInBytes,omitempty"` IsEncrypted bool `json:"isEncrypted,omitempty"` } diff --git a/services/backup/multi_region_test.go b/services/backup/multi_region_test.go index 79b3fe3527..288465938a 100644 --- a/services/backup/multi_region_test.go +++ b/services/backup/multi_region_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -38,7 +39,7 @@ func regionCall(t *testing.T, h *backup.Handler, region, method, path, body stri require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/backup/persistence.go b/services/backup/persistence.go index da564feeeb..467e6710fe 100644 --- a/services/backup/persistence.go +++ b/services/backup/persistence.go @@ -2,7 +2,7 @@ package backup import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -33,15 +33,15 @@ const backupSnapshotVersion = 1 // indexes (vaultARNIndex etc.) are NOT included here; they are rebuilt from // the restored tables by rebuildARNIndexes instead of persisted. type backendSnapshot struct { - GlobalSettingsLastUpdate time.Time `json:"globalSettingsLastUpdate,omitzero"` - Tables map[string]json.RawMessage `json:"tables"` - MpaApprovals map[string]string `json:"mpaApprovals,omitempty"` - GlobalSettings map[string]string `json:"globalSettings,omitempty"` - RecoveryPointIndexStatus map[string]string `json:"recoveryPointIndexStatus,omitempty"` - RegionSettings *RegionSettings `json:"regionSettings,omitempty"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + GlobalSettingsLastUpdate time.Time `json:"globalSettingsLastUpdate,omitzero"` + Tables map[string]jsontext.Value `json:"tables"` + MpaApprovals map[string]string `json:"mpaApprovals,omitempty"` + GlobalSettings map[string]string `json:"globalSettings,omitempty"` + RecoveryPointIndexStatus map[string]string `json:"recoveryPointIndexStatus,omitempty"` + RegionSettings *RegionSettings `json:"regionSettings,omitempty"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/backup/protected_resources_test.go b/services/backup/protected_resources_test.go index 08d1c466dd..e2d5c85813 100644 --- a/services/backup/protected_resources_test.go +++ b/services/backup/protected_resources_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -46,7 +47,7 @@ func TestProtectedResourceLastBackupTimeEpoch(t *testing.T) { "IamRoleArn": "arn:aws:iam::000000000000:role/backup-role" }`) var startData map[string]any - require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startData)) + require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startData, jsonx.V1())) // Real AWS Backup jobs complete asynchronously; the emulator // models that via the janitor. Complete it synchronously here // so the resource is recorded as protected. @@ -66,7 +67,7 @@ func TestProtectedResourceLastBackupTimeEpoch(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) lastBackup, exists := data["LastBackupTime"] require.True(t, exists, "LastBackupTime must be present") diff --git a/services/backup/recovery_point_by_vault_storage_class_test.go b/services/backup/recovery_point_by_vault_storage_class_test.go index 02ed5e6e58..0c4e407a21 100644 --- a/services/backup/recovery_point_by_vault_storage_class_test.go +++ b/services/backup/recovery_point_by_vault_storage_class_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -42,7 +43,7 @@ func TestListRecoveryPointsByBackupVault_NoStorageClassLeak(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, ok := listResp["RecoveryPoints"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -58,6 +59,6 @@ func TestListRecoveryPointsByBackupVault_NoStorageClassLeak(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "WARM", descResp["StorageClass"], "DescribeRecoveryPoint genuinely has StorageClass") } diff --git a/services/backup/recovery_points_test.go b/services/backup/recovery_points_test.go index 00ca5aae3c..db140880d9 100644 --- a/services/backup/recovery_points_test.go +++ b/services/backup/recovery_points_test.go @@ -1,7 +1,7 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -246,7 +247,7 @@ func TestDeleteRecoveryPointVaultLock(t *testing.T) { var probe struct { RecoveryPointIndexStatus map[string]string `json:"recoveryPointIndexStatus"` } - require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &probe)) + require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &probe, jsonx.V1())) assert.NotContains(t, probe.RecoveryPointIndexStatus, "idx-vault:arn:aws:backup:::rp/1") }) } diff --git a/services/backup/report_delivery.go b/services/backup/report_delivery.go index ac27853e3d..3dd82e1c82 100644 --- a/services/backup/report_delivery.go +++ b/services/backup/report_delivery.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/csv" - "encoding/json" + "encoding/json/v2" "fmt" "path" "sort" @@ -14,6 +14,8 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -89,7 +91,7 @@ func renderReport(format string, t reportTable) ([]byte, string, error) { recs = append(recs, rec) } - body, err := json.Marshal(recs) + body, err := json.Marshal(recs, jsonx.V1()) if err != nil { return nil, "", fmt.Errorf("encode JSON report: %w", err) } diff --git a/services/backup/resource_engines.go b/services/backup/resource_engines.go index 2a1650fbf7..4617893f99 100644 --- a/services/backup/resource_engines.go +++ b/services/backup/resource_engines.go @@ -3,7 +3,8 @@ package backup import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" @@ -13,6 +14,7 @@ import ( sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -24,8 +26,8 @@ const ( // resourceEngine snapshots a live resource at backup time and recreates it from that snapshot on restore. type resourceEngine interface { // capture returns nil data when the resource does not exist. - capture(ctx context.Context, resourceArn string) (json.RawMessage, error) - restore(ctx context.Context, data json.RawMessage, metadata map[string]string) (string, error) + capture(ctx context.Context, resourceArn string) (jsontext.Value, error) + restore(ctx context.Context, data jsontext.Value, metadata map[string]string) (string, error) } // DynamoDBBackend is the DynamoDB surface used to snapshot and restore tables. @@ -94,10 +96,10 @@ type ddbSnapshot struct { Attributes []ddbtypes.AttributeDefinition `json:"attributes"` GSIs []ddbtypes.GlobalSecondaryIndex `json:"gsis,omitempty"` LSIs []ddbtypes.LocalSecondaryIndex `json:"lsis,omitempty"` - Items []map[string]json.RawMessage `json:"items"` + Items []map[string]jsontext.Value `json:"items"` } -func (e *ddbEngine) capture(ctx context.Context, resourceArn string) (json.RawMessage, error) { +func (e *ddbEngine) capture(ctx context.Context, resourceArn string) (jsontext.Value, error) { name := resourceNameFromARN(resourceArn) desc, err := e.ddb.DescribeTable(ctx, &dynamodb.DescribeTableInput{TableName: aws.String(name)}) @@ -139,12 +141,12 @@ func (e *ddbEngine) capture(ctx context.Context, resourceArn string) (json.RawMe return nil, err } - return json.Marshal(snap) + return json.Marshal(snap, jsonx.V1()) } -func (e *ddbEngine) scanAll(ctx context.Context, table string) ([]map[string]json.RawMessage, error) { +func (e *ddbEngine) scanAll(ctx context.Context, table string) ([]map[string]jsontext.Value, error) { var ( - items []map[string]json.RawMessage + items []map[string]jsontext.Value start map[string]ddbtypes.AttributeValue ) @@ -169,9 +171,9 @@ func (e *ddbEngine) scanAll(ctx context.Context, table string) ([]map[string]jso } } -func (e *ddbEngine) restore(ctx context.Context, data json.RawMessage, md map[string]string) (string, error) { +func (e *ddbEngine) restore(ctx context.Context, data jsontext.Value, md map[string]string) (string, error) { var snap ddbSnapshot - if err := json.Unmarshal(data, &snap); err != nil { + if err := json.Unmarshal(data, &snap, jsonx.V1()); err != nil { return "", fmt.Errorf("decode DynamoDB snapshot: %w", err) } @@ -215,7 +217,7 @@ type s3SnapObject struct { Body []byte `json:"body"` } -func (e *s3Engine) capture(ctx context.Context, resourceArn string) (json.RawMessage, error) { +func (e *s3Engine) capture(ctx context.Context, resourceArn string) (jsontext.Value, error) { bucket, ok := s3BucketFromARN(resourceArn) if !ok { return nil, nil @@ -249,7 +251,7 @@ func (e *s3Engine) capture(ctx context.Context, resourceArn string) (json.RawMes token = page.NextContinuationToken } - return json.Marshal(snap) + return json.Marshal(snap, jsonx.V1()) } func (e *s3Engine) readObject(ctx context.Context, bucket, key string) (s3SnapObject, error) { @@ -267,9 +269,9 @@ func (e *s3Engine) readObject(ctx context.Context, bucket, key string) (s3SnapOb return s3SnapObject{Key: key, ContentType: aws.ToString(out.ContentType), Body: body}, nil } -func (e *s3Engine) restore(ctx context.Context, data json.RawMessage, md map[string]string) (string, error) { +func (e *s3Engine) restore(ctx context.Context, data jsontext.Value, md map[string]string) (string, error) { var snap s3Snapshot - if err := json.Unmarshal(data, &snap); err != nil { + if err := json.Unmarshal(data, &snap, jsonx.V1()); err != nil { return "", fmt.Errorf("decode S3 snapshot: %w", err) } @@ -303,18 +305,18 @@ type ebsEngine struct { accountID string } -func (e *ebsEngine) capture(_ context.Context, resourceArn string) (json.RawMessage, error) { +func (e *ebsEngine) capture(_ context.Context, resourceArn string) (jsontext.Value, error) { info, ok := e.vols.DescribeVolume(resourceNameFromARN(resourceArn)) if !ok { return nil, nil } - return json.Marshal(info) + return json.Marshal(info, jsonx.V1()) } -func (e *ebsEngine) restore(_ context.Context, data json.RawMessage, md map[string]string) (string, error) { +func (e *ebsEngine) restore(_ context.Context, data jsontext.Value, md map[string]string) (string, error) { var info VolumeInfo - if err := json.Unmarshal(data, &info); err != nil { + if err := json.Unmarshal(data, &info, jsonx.V1()); err != nil { return "", fmt.Errorf("decode EBS snapshot: %w", err) } if v := md["availabilityZone"]; v != "" { diff --git a/services/backup/resource_restore_test.go b/services/backup/resource_restore_test.go index b9768aeee0..893fa51e8b 100644 --- a/services/backup/resource_restore_test.go +++ b/services/backup/resource_restore_test.go @@ -3,7 +3,7 @@ package backup_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "sort" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -359,7 +360,7 @@ func TestReportJob_JSONContent(t *testing.T) { require.Len(t, got.ReportDestination.S3Keys, 1) var rows []map[string]string - require.NoError(t, json.Unmarshal(store.objects["rep/"+got.ReportDestination.S3Keys[0]], &rows)) + require.NoError(t, json.Unmarshal(store.objects["rep/"+got.ReportDestination.S3Keys[0]], &rows, jsonx.V1())) require.Len(t, rows, 1) assert.Equal(t, testVolumeArn, rows[0]["Resource ARN"]) assert.Equal(t, "COMPLETED", rows[0]["Job Status"]) diff --git a/services/backup/settings_test.go b/services/backup/settings_test.go index dbbab38d19..66a63872f0 100644 --- a/services/backup/settings_test.go +++ b/services/backup/settings_test.go @@ -1,13 +1,14 @@ package backup_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/backup" ) @@ -44,7 +45,7 @@ func TestGlobalSettingsLastUpdateTimeEpoch(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var data map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &data, jsonx.V1())) lastUpdate, exists := data["LastUpdateTime"] require.True(t, exists, "LastUpdateTime must be present") diff --git a/services/backup/vault_policies.go b/services/backup/vault_policies.go index 1f1ee7e792..87adb6f98b 100644 --- a/services/backup/vault_policies.go +++ b/services/backup/vault_policies.go @@ -1,11 +1,13 @@ package backup import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" sdktypes "github.com/aws/aws-sdk-go-v2/service/backup/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // isValidVaultEvent derives its answer from types.BackupVaultEvent.Values() @@ -35,7 +37,7 @@ func (b *InMemoryBackend) PutBackupVaultAccessPolicy(vaultName, policy string) e if policy != "" { var doc map[string]any - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return fmt.Errorf( "%w: Policy must be a valid JSON document: %s", ErrValidation, diff --git a/services/batch/exec_test.go b/services/batch/exec_test.go index b38992a268..24e6395db5 100644 --- a/services/batch/exec_test.go +++ b/services/batch/exec_test.go @@ -2,7 +2,7 @@ package batch_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "log/slog" "strings" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -300,7 +301,7 @@ func TestExecJobStateAndExitCode(t *testing.T) { assert.Equal(t, done.Container.LogStreamName, done.Attempts[0].Container.LogStreamName) assert.NotNil(t, done.Attempts[0].StoppedAt) - raw, err := json.Marshal(done.Attempts[0].Container) + raw, err := json.Marshal(done.Attempts[0].Container, jsonx.V1()) require.NoError(t, err) assert.Contains(t, string(raw), `"exitCode"`) diff --git a/services/batch/handler.go b/services/batch/handler.go index 26acb3482f..917ad42c2b 100644 --- a/services/batch/handler.go +++ b/services/batch/handler.go @@ -2,7 +2,7 @@ package batch import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "log/slog" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -331,7 +332,7 @@ func (h *Handler) Handler() echo.HandlerFunc { return h.writeError(c, opErr) } - out, marshalErr := json.Marshal(result) + out, marshalErr := json.Marshal(result, jsonx.V1()) if marshalErr != nil { log.ErrorContext(ctx, "batch: failed to marshal response", "error", marshalErr) diff --git a/services/batch/handler_compute_environments_test.go b/services/batch/handler_compute_environments_test.go index 31c4878362..101423e7aa 100644 --- a/services/batch/handler_compute_environments_test.go +++ b/services/batch/handler_compute_environments_test.go @@ -1,13 +1,15 @@ package batch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -293,7 +295,7 @@ func TestDescribeComputeEnvironments_TagsPresentNoTags(t *testing.T) { items := out["computeEnvironments"].([]any) require.Len(t, items, 1) - itemBytes, err := json.Marshal(items[0]) + itemBytes, err := json.Marshal(items[0], jsonx.V1()) require.NoError(t, err) assertTagsPresent(t, itemBytes) } @@ -307,8 +309,8 @@ func TestDescribeComputeEnvironments_EmptyList(t *testing.T) { rec := post(t, h, "/v1/describecomputeenvironments", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap, jsonx.V1())) raw, ok := rawMap["computeEnvironments"] require.True(t, ok, "computeEnvironments key must be present") assert.Equal(t, "[]", string(raw), "computeEnvironments must be [] not null when empty") diff --git a/services/batch/handler_job_definitions_test.go b/services/batch/handler_job_definitions_test.go index a5a640529e..8b96b2337f 100644 --- a/services/batch/handler_job_definitions_test.go +++ b/services/batch/handler_job_definitions_test.go @@ -1,12 +1,15 @@ package batch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_JobDefinition_CRUD(t *testing.T) { @@ -194,7 +197,7 @@ func TestDescribeJobDefinitions_TagsPresentNoTags(t *testing.T) { items := out["jobDefinitions"].([]any) require.Len(t, items, 1) - itemBytes, err := json.Marshal(items[0]) + itemBytes, err := json.Marshal(items[0], jsonx.V1()) require.NoError(t, err) assertTagsPresent(t, itemBytes) } @@ -208,8 +211,8 @@ func TestDescribeJobDefinitions_EmptyList(t *testing.T) { rec := post(t, h, "/v1/describejobdefinitions", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap, jsonx.V1())) raw, ok := rawMap["jobDefinitions"] require.True(t, ok, "jobDefinitions key must be present") assert.Equal(t, "[]", string(raw), "jobDefinitions must be [] not null when empty") diff --git a/services/batch/handler_job_queues_test.go b/services/batch/handler_job_queues_test.go index c4e5996240..3f33061bbb 100644 --- a/services/batch/handler_job_queues_test.go +++ b/services/batch/handler_job_queues_test.go @@ -1,13 +1,15 @@ package batch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -378,7 +380,7 @@ func TestHandler_DeleteJobQueue_TerminatesJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var submitResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitResp, jsonx.V1())) jobID := submitResp["jobId"].(string) // Delete the queue — associated jobs must be terminated (FAILED), not @@ -402,7 +404,7 @@ func TestHandler_DeleteJobQueue_TerminatesJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) jobs := descResp["jobs"].([]any) require.Len(t, jobs, 1, "job history must survive job queue deletion") job, _ := jobs[0].(map[string]any) @@ -524,21 +526,21 @@ func TestHandler_GetJobQueueSnapshot_WireShape(t *testing.T) { rec = post(t, h, "/v1/getjobqueuesnapshot", map[string]any{"jobQueue": "q-snap-wire"}) require.Equal(t, http.StatusOK, rec.Code) - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap, jsonx.V1())) - var frontOfQueue map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rawMap["frontOfQueue"], &frontOfQueue)) + var frontOfQueue map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rawMap["frontOfQueue"], &frontOfQueue, jsonx.V1())) _, hasTimestamp := frontOfQueue["timestamp"] assert.False(t, hasTimestamp, "wire shape must not have a legacy \"timestamp\" field") var lastUpdatedAt int64 - require.NoError(t, json.Unmarshal(frontOfQueue["lastUpdatedAt"], &lastUpdatedAt)) + require.NoError(t, json.Unmarshal(frontOfQueue["lastUpdatedAt"], &lastUpdatedAt, jsonx.V1())) assert.Positive(t, lastUpdatedAt, "lastUpdatedAt should be a positive epoch-millisecond value") var jobs []map[string]any - require.NoError(t, json.Unmarshal(frontOfQueue["jobs"], &jobs)) + require.NoError(t, json.Unmarshal(frontOfQueue["jobs"], &jobs, jsonx.V1())) require.Len(t, jobs, 1) assert.Contains(t, jobs[0]["jobArn"], "job/") @@ -583,7 +585,7 @@ func TestDescribeJobQueues_TagsPresentNoTags(t *testing.T) { items := out["jobQueues"].([]any) require.Len(t, items, 1) - itemBytes, err := json.Marshal(items[0]) + itemBytes, err := json.Marshal(items[0], jsonx.V1()) require.NoError(t, err) assertTagsPresent(t, itemBytes) } @@ -597,8 +599,8 @@ func TestDescribeJobQueues_EmptyList(t *testing.T) { rec := post(t, h, "/v1/describejobqueues", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap, jsonx.V1())) raw, ok := rawMap["jobQueues"] require.True(t, ok, "jobQueues key must be present") assert.Equal(t, "[]", string(raw), "jobQueues must be [] not null when empty") diff --git a/services/batch/handler_jobs_test.go b/services/batch/handler_jobs_test.go index 45284792ff..6c64ac9464 100644 --- a/services/batch/handler_jobs_test.go +++ b/services/batch/handler_jobs_test.go @@ -1,7 +1,8 @@ package batch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -198,7 +200,7 @@ func TestHandler_SubmitJob_JobARNPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var submitResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitResp, jsonx.V1())) jobID := submitResp["jobId"].(string) assert.NotEmpty(t, submitResp["jobArn"], "SubmitJob response should include jobArn") @@ -209,7 +211,7 @@ func TestHandler_SubmitJob_JobARNPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) jobs := descResp["jobs"].([]any) require.Len(t, jobs, 1) @@ -621,7 +623,7 @@ func TestDescribeJobs_TagsPresentNoTags(t *testing.T) { jobs := out["jobs"].([]any) require.Len(t, jobs, 1) - itemBytes, err := json.Marshal(jobs[0]) + itemBytes, err := json.Marshal(jobs[0], jsonx.V1()) require.NoError(t, err) assertTagsPresent(t, itemBytes) } @@ -668,8 +670,8 @@ func TestDescribeJobs_EmptyList(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rawMap, jsonx.V1())) raw, ok := rawMap["jobs"] require.True(t, ok, "jobs key must be present") assert.Equal(t, "[]", string(raw), "jobs must be [] not null when no matching jobs found") @@ -695,7 +697,7 @@ func TestListJobs_SummaryIncludesJobArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, _ := out["jobSummaryList"].([]any) require.Len(t, summaries, 1) @@ -720,7 +722,7 @@ func TestListJobs_SummaryIncludesTimestamps(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var submitOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &submitOut, jsonx.V1())) jobID := submitOut["jobId"] rec = post(t, h, "/v1/terminatejob", map[string]any{ @@ -736,7 +738,7 @@ func TestListJobs_SummaryIncludesTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, _ := out["jobSummaryList"].([]any) require.Len(t, summaries, 1) diff --git a/services/batch/handler_tags.go b/services/batch/handler_tags.go index f0b1dbe2d8..f163134652 100644 --- a/services/batch/handler_tags.go +++ b/services/batch/handler_tags.go @@ -2,11 +2,13 @@ package batch import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Tags handlers --- @@ -35,7 +37,7 @@ type tagResourceInput struct { func (h *Handler) handleTagResource(ctx context.Context, c *echo.Context, resourceARN string, body []byte) error { var in tagResourceInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid request body")) } } diff --git a/services/batch/handler_tags_test.go b/services/batch/handler_tags_test.go index dea1e9abc7..e02d46e958 100644 --- a/services/batch/handler_tags_test.go +++ b/services/batch/handler_tags_test.go @@ -2,7 +2,7 @@ package batch_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -259,7 +260,7 @@ func TestBatch_TagsOnNewResourceTypes(t *testing.T) { e := echo.New() tagPath := "/v1/tags/" + crARN tagBody := map[string]any{"tags": map[string]string{"env": "prod"}} - tagBytes, err := json.Marshal(tagBody) + tagBytes, err := json.Marshal(tagBody, jsonx.V1()) require.NoError(t, err) tagReq := httptest.NewRequest(http.MethodPost, tagPath, bytes.NewReader(tagBytes)) @@ -277,7 +278,7 @@ func TestBatch_TagsOnNewResourceTypes(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var tagsOut map[string]map[string]string - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) assert.Equal(t, "prod", tagsOut["tags"]["env"]) } diff --git a/services/batch/handler_test.go b/services/batch/handler_test.go index 7da8a819dd..58b97d1abe 100644 --- a/services/batch/handler_test.go +++ b/services/batch/handler_test.go @@ -2,7 +2,8 @@ package batch_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -33,7 +35,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -58,7 +60,7 @@ func post(t *testing.T, h *batch.Handler, path string, body any) *httptest.Respo func mustUnmarshal(t *testing.T, rec *httptest.ResponseRecorder, v any) { t.Helper() - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1())) } // --- Handler metadata tests --- @@ -418,15 +420,15 @@ func TestBatch_RequiredFieldValidation(t *testing.T) { func assertTagsPresent(t *testing.T, raw []byte) { t.Helper() - var rawMap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(raw, &rawMap)) + var rawMap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(raw, &rawMap, jsonx.V1())) tagBytes, hasTags := rawMap["tags"] assert.True(t, hasTags, "tags key must be present in describe response") if hasTags { var tags map[string]string - require.NoError(t, json.Unmarshal(tagBytes, &tags), "tags must be a JSON object, not null") + require.NoError(t, json.Unmarshal(tagBytes, &tags, jsonx.V1()), "tags must be a JSON object, not null") assert.NotNil(t, tags, "tags must be {} not null") } } diff --git a/services/batch/job_overrides.go b/services/batch/job_overrides.go index f7d5cf3f51..f09538a781 100644 --- a/services/batch/job_overrides.go +++ b/services/batch/job_overrides.go @@ -1,11 +1,13 @@ package batch import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const reservedEnvPrefix = "AWS_BATCH" @@ -51,12 +53,12 @@ type EksPropertiesOverride struct { func deepCopy[T any](v T) T { var out T - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } - if err = json.Unmarshal(raw, &out); err != nil { + if err = json.Unmarshal(raw, &out, jsonx.V1()); err != nil { return v } diff --git a/services/batch/models.go b/services/batch/models.go index dcd8309ffb..3e06cd167a 100644 --- a/services/batch/models.go +++ b/services/batch/models.go @@ -1,8 +1,10 @@ package batch import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- ComputeResources sub-types --- @@ -320,7 +322,7 @@ func (n *NodeRangeProperty) UnmarshalJSON(data []byte) error { Legacy *ContainerProperties `json:"containerProperties"` }{plain: (*plain)(n)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/batch/node_range_property_json_test.go b/services/batch/node_range_property_json_test.go index 30c2522330..20a8a292fa 100644 --- a/services/batch/node_range_property_json_test.go +++ b/services/batch/node_range_property_json_test.go @@ -1,12 +1,13 @@ package batch_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/batch" ) @@ -26,11 +27,11 @@ func TestNodeRangeProperty_JSONKeys(t *testing.T) { t.Parallel() var r batch.NodeRangeProperty - require.NoError(t, json.Unmarshal([]byte(tt.in), &r)) + require.NoError(t, json.Unmarshal([]byte(tt.in), &r, jsonx.V1())) require.NotNil(t, r.ContainerProperties) assert.Equal(t, "busybox", r.ContainerProperties.Image) - out, err := json.Marshal(r) + out, err := json.Marshal(r, jsonx.V1()) require.NoError(t, err) assert.Contains(t, string(out), `"container":`) assert.NotContains(t, string(out), `"containerProperties"`) diff --git a/services/batch/persistence.go b/services/batch/persistence.go index 1e7c5f8101..948a9b37b0 100644 --- a/services/batch/persistence.go +++ b/services/batch/persistence.go @@ -2,7 +2,7 @@ package batch import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/google/uuid" @@ -55,7 +55,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` JobDefRevisions map[string]map[string]int32 `json:"jobDefRevisions"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -271,7 +271,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // table (byRegion, byARN, byQueue, byName -- see store_setup.go), so unlike // the pre-refactor Restore this needs no separate index-rebuild step. // Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/batch/validation.go b/services/batch/validation.go index ae3cbb0539..862cc5aa14 100644 --- a/services/batch/validation.go +++ b/services/batch/validation.go @@ -1,10 +1,11 @@ package batch import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -40,7 +41,7 @@ func checkNextToken(body []byte) error { NextToken *string `json:"nextToken"` } - if json.Unmarshal(body, &in) == nil && in.NextToken != nil && *in.NextToken != "" && + if json.Unmarshal(body, &in, jsonx.V1()) == nil && in.NextToken != nil && *in.NextToken != "" && page.DecodeHMACToken(*in.NextToken, paginationSecret) <= 0 { return fmt.Errorf("%w: invalid nextToken", ErrValidation) } diff --git a/services/bcmdataexports/errors.go b/services/bcmdataexports/errors.go index 3dee148399..c70937e422 100644 --- a/services/bcmdataexports/errors.go +++ b/services/bcmdataexports/errors.go @@ -1,7 +1,7 @@ package bcmdataexports import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "hash/crc32" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Sentinels, one per exception in the pinned SDK's error set. @@ -120,7 +121,7 @@ func writeErrorBody(c *echo.Context, e awserr.APIError, d detail) error { body, _ := json.Marshal(errorBody{ Type: e.Code, Message: e.Message, ResourceID: d.resourceID, ResourceType: d.resourceType, Reason: d.reason, Fields: d.fields, - }) + }, jsonx.V1()) c.Response().Header().Set("X-Amz-Crc32", strconv.FormatUint(uint64(crc32.ChecksumIEEE(body)), 10)) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.1") diff --git a/services/bcmdataexports/executions.go b/services/bcmdataexports/executions.go index 9578f127df..152f13cbfb 100644 --- a/services/bcmdataexports/executions.go +++ b/services/bcmdataexports/executions.go @@ -2,13 +2,14 @@ package bcmdataexports import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "path" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/billingexport" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -239,7 +240,7 @@ func writeResult( man.DataFileKeys = []string{dataKey} - mb, err := json.Marshal(&man) + mb, err := json.Marshal(&man, jsonx.V1()) if err != nil { return fmt.Errorf("encode manifest: %w", err) } diff --git a/services/bcmdataexports/handler.go b/services/bcmdataexports/handler.go index 2400b09779..7bf17bd94b 100644 --- a/services/bcmdataexports/handler.go +++ b/services/bcmdataexports/handler.go @@ -2,7 +2,7 @@ package bcmdataexports import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/worker" @@ -39,7 +40,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, failReason(reasonCannotParse, "malformed request body: %v", err) } } diff --git a/services/bcmdataexports/persistence.go b/services/bcmdataexports/persistence.go index c924c24a85..aa1f2efcd5 100644 --- a/services/bcmdataexports/persistence.go +++ b/services/bcmdataexports/persistence.go @@ -2,7 +2,7 @@ package bcmdataexports import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/bcmdataexports/rows.go b/services/bcmdataexports/rows.go index 8dcd6663e1..2576e2faad 100644 --- a/services/bcmdataexports/rows.go +++ b/services/bcmdataexports/rows.go @@ -2,12 +2,13 @@ package bcmdataexports import ( "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "hash/fnv" "time" "github.com/blackbirdworks/gopherstack/pkgs/billingexport" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -35,7 +36,7 @@ func jsonMap(kv ...string) string { m[kv[i]] = kv[i+1] } - b, _ := json.Marshal(m) + b, _ := json.Marshal(m, jsonx.V1()) return string(b) } diff --git a/services/bedrock/automated_reasoning_policies.go b/services/bedrock/automated_reasoning_policies.go index 76c3ee6825..1af2f3c2fe 100644 --- a/services/bedrock/automated_reasoning_policies.go +++ b/services/bedrock/automated_reasoning_policies.go @@ -1,7 +1,7 @@ package bedrock import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "sort" @@ -56,7 +56,7 @@ func (b *InMemoryBackend) CreateAutomatedReasoningPolicy( // ARPCreateOptions carries CreateAutomatedReasoningPolicy's optional policyDefinition and kmsKeyId. type ARPCreateOptions struct { KmsKeyID string - PolicyDefinition json.RawMessage + PolicyDefinition jsontext.Value } // CreateAutomatedReasoningPolicyWithOptions is CreateAutomatedReasoningPolicy with ARPCreateOptions. @@ -317,7 +317,7 @@ func (b *InMemoryBackend) arpVersionSummariesLocked(policyARN string) []*Automat // would orphan that index instead of leaving the name unchanged. func (b *InMemoryBackend) UpdateAutomatedReasoningPolicy( policyARN, name, description string, - policyDefinition json.RawMessage, + policyDefinition jsontext.Value, ) (*AutomatedReasoningPolicy, error) { if len(policyDefinition) == 0 { return nil, fmt.Errorf("%w: policyDefinition is required", ErrValidation) @@ -451,7 +451,7 @@ func (b *InMemoryBackend) DeleteAutomatedReasoningPolicy(policyARN string, force // request body (serializers.go:8008-8058). func (b *InMemoryBackend) StartAutomatedReasoningPolicyBuildWorkflow( policyARN, buildWorkflowType string, - sourceContent json.RawMessage, + sourceContent jsontext.Value, ) (*AutomatedReasoningPolicyBuildWorkflow, error) { if buildWorkflowType == "" { return nil, fmt.Errorf("%w: buildWorkflowType is required", ErrValidation) diff --git a/services/bedrock/export_test.go b/services/bedrock/export_test.go index 3b39030b18..95752a90c3 100644 --- a/services/bedrock/export_test.go +++ b/services/bedrock/export_test.go @@ -1,7 +1,7 @@ package bedrock import ( - "encoding/json" + "encoding/json/jsontext" "strconv" ) @@ -112,7 +112,7 @@ func (b *InMemoryBackend) AddBuildWorkflowForTest(policyARN string) *AutomatedRe // conversion's registry mechanics directly, independent of the production // Snapshot/Restore pair added in persistence.go (see persistence_test.go for // black-box tests of that production path). -func (b *InMemoryBackend) SnapshotTablesForTest() (map[string]json.RawMessage, error) { +func (b *InMemoryBackend) SnapshotTablesForTest() (map[string]jsontext.Value, error) { b.mu.RLock("SnapshotTablesForTest") defer b.mu.RUnlock() @@ -121,7 +121,7 @@ func (b *InMemoryBackend) SnapshotTablesForTest() (map[string]json.RawMessage, e // RestoreTablesForTest replaces every store.Table registered on b.registry // with the contents of data, as produced by SnapshotTablesForTest. -func (b *InMemoryBackend) RestoreTablesForTest(data map[string]json.RawMessage) error { +func (b *InMemoryBackend) RestoreTablesForTest(data map[string]jsontext.Value) error { b.mu.Lock("RestoreTablesForTest") defer b.mu.Unlock() diff --git a/services/bedrock/ghost_row_jkiu_test.go b/services/bedrock/ghost_row_jkiu_test.go index 8a3d83869e..79f567e7f4 100644 --- a/services/bedrock/ghost_row_jkiu_test.go +++ b/services/bedrock/ghost_row_jkiu_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -24,7 +24,7 @@ func TestDeleteAutomatedReasoningPolicy_PrunesVersionCounterAndAnnotations(t *te wf, err := b.StartAutomatedReasoningPolicyBuildWorkflow( policy.PolicyArn, "INGEST_CONTENT", - json.RawMessage(`{}`), + jsontext.Value(`{}`), ) require.NoError(t, err) @@ -68,7 +68,7 @@ func TestDeleteAutomatedReasoningPolicyBuildWorkflow_PrunesAnnotations(t *testin wf, err := b.StartAutomatedReasoningPolicyBuildWorkflow( policy.PolicyArn, "INGEST_CONTENT", - json.RawMessage(`{}`), + jsontext.Value(`{}`), ) require.NoError(t, err) diff --git a/services/bedrock/handler.go b/services/bedrock/handler.go index 5a129d7615..f559a0b97d 100644 --- a/services/bedrock/handler.go +++ b/services/bedrock/handler.go @@ -2,7 +2,7 @@ package bedrock import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -140,7 +141,7 @@ type isoTime struct { } func (t isoTime) MarshalJSON() ([]byte, error) { - return json.Marshal(t.Time.Format(time.RFC3339)) + return json.Marshal(t.Time.Format(time.RFC3339), jsonx.V1()) } // Handler is the Echo HTTP handler for Amazon Bedrock operations. @@ -704,7 +705,7 @@ func parseBody[T any](body []byte) (*T, error) { return &v, nil } - if err := json.Unmarshal(body, &v); err != nil { + if err := json.Unmarshal(body, &v, jsonx.V1()); err != nil { return nil, err } diff --git a/services/bedrock/handler_automated_reasoning_policies.go b/services/bedrock/handler_automated_reasoning_policies.go index 2938662c1c..0973ab25ce 100644 --- a/services/bedrock/handler_automated_reasoning_policies.go +++ b/services/bedrock/handler_automated_reasoning_policies.go @@ -1,12 +1,14 @@ package bedrock import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "strconv" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractARPOperation mirrors routeARP's dispatch order exactly (same @@ -347,12 +349,12 @@ func (h *Handler) routeARPSingleItem( } type createAutomatedReasoningPolicyInput struct { - Name string `json:"name"` - Description string `json:"description,omitempty"` - KmsKeyID string `json:"kmsKeyId,omitempty"` - ClientRequestToken string `json:"clientRequestToken,omitempty"` - PolicyDefinition json.RawMessage `json:"policyDefinition,omitempty"` - Tags []Tag `json:"tags,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + KmsKeyID string `json:"kmsKeyId,omitempty"` + ClientRequestToken string `json:"clientRequestToken,omitempty"` + PolicyDefinition jsontext.Value `json:"policyDefinition,omitempty"` + Tags []Tag `json:"tags,omitempty"` } type createAutomatedReasoningPolicyOutput struct { @@ -809,9 +811,9 @@ func (h *Handler) handleListAutomatedReasoningPolicies(c *echo.Context) error { } type updateARPInput struct { - Description string `json:"description,omitempty"` - Name string `json:"name,omitempty"` - PolicyDefinition json.RawMessage `json:"policyDefinition"` + Description string `json:"description,omitempty"` + Name string `json:"name,omitempty"` + PolicyDefinition jsontext.Value `json:"policyDefinition"` } func (h *Handler) handleUpdateAutomatedReasoningPolicy(c *echo.Context, policyARN string, body []byte) error { @@ -858,7 +860,7 @@ func (h *Handler) handleDeleteAutomatedReasoningPolicy(c *echo.Context, policyAR func (h *Handler) handleStartARPBuildWorkflow(c *echo.Context, path string, body []byte) error { policyARN, buildWorkflowType := extractARPBuildWorkflowStart(path) - if !json.Valid(body) { + if !jsontext.Value(body).IsValid(jsonx.V1()) { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid request body")) } @@ -873,7 +875,7 @@ func (h *Handler) handleStartARPBuildWorkflow(c *echo.Context, path string, body return h.Backend.StartAutomatedReasoningPolicyBuildWorkflow( policyARN, buildWorkflowType, - json.RawMessage(body), + jsontext.Value(body), ) }, ) diff --git a/services/bedrock/handler_automated_reasoning_policies_test.go b/services/bedrock/handler_automated_reasoning_policies_test.go index d93cdbe4ad..4abfd0af58 100644 --- a/services/bedrock/handler_automated_reasoning_policies_test.go +++ b/services/bedrock/handler_automated_reasoning_policies_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -362,7 +363,7 @@ func TestAccuracy_ARPVersion_ViaHTTP(t *testing.T) { "/automated-reasoning-policies/"+url.PathEscape(policy.PolicyArn)+"/versions", map[string]any{"notes": fmt.Sprintf("version %d", i+1)}) require.Equal(t, http.StatusCreated, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lastVersion)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lastVersion, jsonx.V1())) } assert.Equal(t, tt.wantLastVersion, lastVersion["version"]) @@ -384,14 +385,14 @@ func TestAccuracy_ARP_DescriptionPreservedOnCreate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/automated-reasoning-policies/"+policyARN, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, desc, getOut["description"]) assert.Equal(t, "finance-arp", getOut["name"]) } @@ -406,7 +407,7 @@ func TestAccuracy_ARP_UpdateDescriptionReflected(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) // Update description (real AWS: UpdateAutomatedReasoningPolicy uses PATCH) @@ -424,7 +425,7 @@ func TestAccuracy_ARP_UpdateDescriptionReflected(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "updated description", getOut["description"]) } @@ -456,7 +457,7 @@ func TestAccuracy_ARP_VersionNumberingIsolatedPerPolicy(t *testing.T) { // Verify second version for policy0 has version "2" var verOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verOut, jsonx.V1())) // policy1's first version is "1" (isolated counter) assert.Equal(t, "1", verOut["version"], "policy1 version counter starts from 1 independent of policy0") @@ -475,7 +476,7 @@ func TestAccuracy_ARP_BuildWorkflowStatusTransitions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) // Add a build workflow via test helper @@ -488,7 +489,7 @@ func TestAccuracy_ARP_BuildWorkflowStatusTransitions(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "BUILDING", getOut["status"]) } @@ -504,7 +505,7 @@ func TestAccuracy_ARP_TestCaseRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) // Create test case (needs URL-encoded ARN in path) @@ -516,7 +517,7 @@ func TestAccuracy_ARP_TestCaseRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, tcRec.Code) var tcOut map[string]any - require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tcOut)) + require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tcOut, jsonx.V1())) tcID := tcOut["testCaseId"].(string) assert.NotEmpty(t, tcID) @@ -526,7 +527,7 @@ func TestAccuracy_ARP_TestCaseRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getTestRec.Code) var getTestOut map[string]any - require.NoError(t, json.Unmarshal(getTestRec.Body.Bytes(), &getTestOut)) + require.NoError(t, json.Unmarshal(getTestRec.Body.Bytes(), &getTestOut, jsonx.V1())) assert.Equal(t, policyARN, getTestOut["policyArn"]) testCase, ok := getTestOut["testCase"].(map[string]any) require.True(t, ok, "response must wrap the test case under the required testCase key") @@ -545,7 +546,7 @@ func TestAccuracy_ARP_AnnotationsGetAfterUpdate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) wf := h.Backend.AddBuildWorkflowForTest(policyARN) @@ -560,7 +561,7 @@ func TestAccuracy_ARP_AnnotationsGetAfterUpdate(t *testing.T) { require.Equal(t, http.StatusOK, preRec.Code) var preOut map[string]any - require.NoError(t, json.Unmarshal(preRec.Body.Bytes(), &preOut)) + require.NoError(t, json.Unmarshal(preRec.Body.Bytes(), &preOut, jsonx.V1())) hash, ok := preOut["annotationSetHash"].(string) require.True(t, ok) require.NotEmpty(t, hash) @@ -578,7 +579,7 @@ func TestAccuracy_ARP_AnnotationsGetAfterUpdate(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) assert.Equal(t, policyARN, updateOut["policyArn"]) assert.Equal(t, wf.BuildWorkflowID, updateOut["buildWorkflowId"]) assert.NotEmpty(t, updateOut["annotationSetHash"]) @@ -589,7 +590,7 @@ func TestAccuracy_ARP_AnnotationsGetAfterUpdate(t *testing.T) { require.Equal(t, http.StatusOK, getAnnRec.Code) var annOut map[string]any - require.NoError(t, json.Unmarshal(getAnnRec.Body.Bytes(), &annOut)) + require.NoError(t, json.Unmarshal(getAnnRec.Body.Bytes(), &annOut, jsonx.V1())) anns, ok := annOut["annotations"].([]any) require.True(t, ok) require.Len(t, anns, 1) @@ -1021,7 +1022,7 @@ func TestAccuracy_ARP_UpdateOpsRejectOldPUTMethod(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policyARN := out["policyArn"].(string) tcRec := doRequest(t, h, http.MethodPost, @@ -1029,7 +1030,7 @@ func TestAccuracy_ARP_UpdateOpsRejectOldPUTMethod(t *testing.T) { require.Equal(t, http.StatusCreated, tcRec.Code) var tcOut map[string]any - require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tcOut)) + require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tcOut, jsonx.V1())) tcID := tcOut["testCaseId"].(string) wf := h.Backend.AddBuildWorkflowForTest(policyARN) @@ -1131,7 +1132,7 @@ func TestAccuracy_ARP_BuildWorkflowScopedSubResources(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) policyARN := created["policyArn"].(string) wf := h.Backend.AddBuildWorkflowForTest(policyARN) @@ -1141,7 +1142,7 @@ func TestAccuracy_ARP_BuildWorkflowScopedSubResources(t *testing.T) { require.Equal(t, http.StatusCreated, tcRec.Code) var tc map[string]any - require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tc)) + require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tc, jsonx.V1())) tcID := tc["testCaseId"].(string) path := "/automated-reasoning-policies/" + url.PathEscape(policyARN) + @@ -1165,14 +1166,14 @@ func TestAccuracy_ARP_BuildWorkflowSubResourcesRejectWrongPolicy(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &p1, jsonx.V1())) policy1ARN := p1["policyArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/automated-reasoning-policies", map[string]any{"name": "wrong-policy-2"}) require.Equal(t, http.StatusCreated, rec2.Code) var p2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &p2, jsonx.V1())) policy2ARN := p2["policyArn"].(string) wf := h.Backend.AddBuildWorkflowForTest(policy1ARN) @@ -1214,7 +1215,7 @@ func TestAccuracy_ARP_ExportVersion(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) policyARN := created["policyArn"].(string) verRec := doRequest(t, h, http.MethodPost, @@ -1223,7 +1224,7 @@ func TestAccuracy_ARP_ExportVersion(t *testing.T) { require.Equal(t, http.StatusCreated, verRec.Code) var ver map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &ver)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &ver, jsonx.V1())) versionedARN := ver["policyArn"].(string) exportRec := doRequest(t, h, http.MethodGet, @@ -1231,7 +1232,7 @@ func TestAccuracy_ARP_ExportVersion(t *testing.T) { require.Equal(t, http.StatusOK, exportRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(exportRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(exportRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "hash-export", out["definitionHash"]) } @@ -1249,7 +1250,7 @@ func TestAccuracy_ARP_OldInventedSubResourcePathsGone(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) policyARN := created["policyArn"].(string) tcRec := doRequest(t, h, http.MethodPost, @@ -1257,7 +1258,7 @@ func TestAccuracy_ARP_OldInventedSubResourcePathsGone(t *testing.T) { require.Equal(t, http.StatusCreated, tcRec.Code) var tc map[string]any - require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tc)) + require.NoError(t, json.Unmarshal(tcRec.Body.Bytes(), &tc, jsonx.V1())) tcID := tc["testCaseId"].(string) verRec := doRequest(t, h, http.MethodPost, @@ -1266,7 +1267,7 @@ func TestAccuracy_ARP_OldInventedSubResourcePathsGone(t *testing.T) { require.Equal(t, http.StatusCreated, verRec.Code) var ver map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &ver)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &ver, jsonx.V1())) version := ver["version"].(string) base := "/automated-reasoning-policies/" + url.PathEscape(policyARN) diff --git a/services/bedrock/handler_custom_model_deployments_test.go b/services/bedrock/handler_custom_model_deployments_test.go index c2e70dc8b6..6f7a6be407 100644 --- a/services/bedrock/handler_custom_model_deployments_test.go +++ b/services/bedrock/handler_custom_model_deployments_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -129,7 +130,7 @@ func TestAccuracy_CustomModelDeployment_StatusIsActive(t *testing.T) { require.Equal(t, http.StatusCreated, modelRec.Code, modelRec.Body.String()) var modelOut map[string]any - require.NoError(t, json.Unmarshal(modelRec.Body.Bytes(), &modelOut)) + require.NoError(t, json.Unmarshal(modelRec.Body.Bytes(), &modelOut, jsonx.V1())) modelARN := modelOut["modelArn"].(string) // Create deployment for the model @@ -140,7 +141,7 @@ func TestAccuracy_CustomModelDeployment_StatusIsActive(t *testing.T) { require.Equal(t, http.StatusCreated, depRec.Code) var depOut map[string]any - require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &depOut)) + require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &depOut, jsonx.V1())) depARN := depOut["customModelDeploymentArn"].(string) assert.NotEmpty(t, depARN) @@ -148,7 +149,7 @@ func TestAccuracy_CustomModelDeployment_StatusIsActive(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "my-deployment", getOut["modelDeploymentName"]) // Creating is right immediately after create, but this test's own name // promises "StatusIsActive" -- an assertion that only checks the first @@ -162,7 +163,7 @@ func TestAccuracy_CustomModelDeployment_StatusIsActive(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var getOut2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2, jsonx.V1())) assert.Equal(t, "Active", getOut2["status"]) } @@ -184,7 +185,7 @@ func TestAccuracy_CustomModelDeployment_ListAfterMultipleCreates(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) deployments := listOut["modelDeploymentSummaries"].([]any) assert.GreaterOrEqual(t, len(deployments), 3) } @@ -203,7 +204,7 @@ func TestAccuracy_CustomModelDeployment_DeleteRemovesFromList(t *testing.T) { require.Equal(t, http.StatusCreated, depRec.Code) var depOut map[string]any - require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &depOut)) + require.NoError(t, json.Unmarshal(depRec.Body.Bytes(), &depOut, jsonx.V1())) depARN := depOut["customModelDeploymentArn"].(string) // Delete it diff --git a/services/bedrock/handler_custom_models_test.go b/services/bedrock/handler_custom_models_test.go index 49a8cdabcc..cfb2862f1f 100644 --- a/services/bedrock/handler_custom_models_test.go +++ b/services/bedrock/handler_custom_models_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -111,7 +112,7 @@ func TestAccuracy_CustomModel_GetViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, m.ModelArn, out["modelArn"]) assert.Equal(t, tt.modelName, out["modelName"]) assert.NotEmpty(t, out["creationTime"]) @@ -156,7 +157,7 @@ func TestAccuracy_CustomModel_ListViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) models := out["modelSummaries"].([]any) assert.Len(t, models, tt.wantLen) }) @@ -200,7 +201,7 @@ func TestAccuracy_CustomModel_ListFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) models := out["modelSummaries"].([]any) gotNames := make([]string, 0, len(models)) @@ -266,7 +267,7 @@ func TestHandler_CustomModelLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) modelARN := createOut["modelArn"].(string) // List custom models. @@ -274,7 +275,7 @@ func TestHandler_CustomModelLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut, jsonx.V1())) assert.NotEmpty(t, listOut["modelSummaries"]) // Get custom model by ARN. diff --git a/services/bedrock/handler_evaluation_jobs_test.go b/services/bedrock/handler_evaluation_jobs_test.go index 7cbe675512..a9655f3638 100644 --- a/services/bedrock/handler_evaluation_jobs_test.go +++ b/services/bedrock/handler_evaluation_jobs_test.go @@ -1,7 +1,8 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "strconv" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -290,7 +292,7 @@ func TestBatch1_EvaluationJob_RAGConfig_RoundTrip(t *testing.T) { }, InferenceConfig: &bedrock.EvaluationInferenceConfig{ RagConfigs: []bedrock.RAGConfig{ - {KnowledgeBaseConfig: json.RawMessage(`{"retrieveConfig":{"knowledgeBaseId":"kb-0001"}}`)}, + {KnowledgeBaseConfig: jsontext.Value(`{"retrieveConfig":{"knowledgeBaseId":"kb-0001"}}`)}, }, }, } @@ -508,7 +510,7 @@ func TestAccuracy_EvaluationJob_StopTransitionsStatus(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "Stopping", out["status"]) }) } @@ -542,7 +544,7 @@ func TestAccuracy_EvaluationJob_ListResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["jobSummaries"].([]any) assert.Len(t, summaries, tt.wantLen) @@ -595,14 +597,14 @@ func TestAccuracy_EvaluationJob_EvaluatorModelConfigPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/evaluation-jobs/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) automated := getOut["evaluationConfig"].(map[string]any)["automated"].(map[string]any) evaluatorModelConfig := automated["evaluatorModelConfig"].(map[string]any) @@ -631,14 +633,14 @@ func TestAccuracy_EvaluationJob_InferenceModelsPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/evaluation-jobs/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) inferCfg := getOut["inferenceConfig"].(map[string]any) models := inferCfg["models"].([]any) @@ -663,14 +665,14 @@ func TestAccuracy_EvaluationJob_RAGConfigPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/evaluation-jobs/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) inferCfg := getOut["inferenceConfig"].(map[string]any) ragConfigs := inferCfg["ragConfigs"].([]any) @@ -707,14 +709,14 @@ func TestAccuracy_EvaluationJob_EvalTaskConfigPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/evaluation-jobs/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) automated := getOut["evaluationConfig"].(map[string]any)["automated"].(map[string]any) datasetMetricConfigs := automated["datasetMetricConfigs"].([]any) @@ -738,14 +740,14 @@ func TestAccuracy_EvaluationJob_JobDescriptionPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/evaluation-jobs/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, desc, getOut["jobDescription"]) } @@ -983,7 +985,7 @@ func TestBatch2Ops_StopEvaluationJob_AlreadyStopped_Rejected(t *testing.T) { "stop of already-stopped job should return 400 ValidationException") var errBody map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ValidationException", errBody["__type"], "error type must be ValidationException") }) diff --git a/services/bedrock/handler_foundation_model_agreements_test.go b/services/bedrock/handler_foundation_model_agreements_test.go index 92e4e92e3d..08b2583576 100644 --- a/services/bedrock/handler_foundation_model_agreements_test.go +++ b/services/bedrock/handler_foundation_model_agreements_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -71,7 +72,7 @@ func TestAccuracy_FoundationModelAgreementOffers_ListRequiresModelID(t *testing. require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "amazon.titan-text-express-v1", out["modelId"]) offers, _ := out["offers"].([]any) diff --git a/services/bedrock/handler_foundation_models_test.go b/services/bedrock/handler_foundation_models_test.go index f5a2415973..bf9031b687 100644 --- a/services/bedrock/handler_foundation_models_test.go +++ b/services/bedrock/handler_foundation_models_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -216,14 +217,14 @@ func TestBatch1_FoundationModel_ResponseStreamingSupported_Bool(t *testing.T) { var out map[string]any mustUnmarshal(t, rec, &out) details := out["modelDetails"].(map[string]any) - rawBytes, err := json.Marshal(details) + rawBytes, err := json.Marshal(details, jsonx.V1()) require.NoError(t, err) var typed struct { InferenceTypesSupported []string `json:"inferenceTypesSupported"` ResponseStreamingSupported bool `json:"responseStreamingSupported"` } - require.NoError(t, json.Unmarshal(rawBytes, &typed)) + require.NoError(t, json.Unmarshal(rawBytes, &typed, jsonx.V1())) assert.True(t, typed.ResponseStreamingSupported) assert.NotEmpty(t, typed.InferenceTypesSupported) @@ -234,13 +235,13 @@ func TestBatch1_FoundationModel_ResponseStreamingSupported_Bool(t *testing.T) { var out2 map[string]any mustUnmarshal(t, rec2, &out2) details2 := out2["modelDetails"].(map[string]any) - rawBytes2, err := json.Marshal(details2) + rawBytes2, err := json.Marshal(details2, jsonx.V1()) require.NoError(t, err) var typed2 struct { ResponseStreamingSupported bool `json:"responseStreamingSupported"` } - require.NoError(t, json.Unmarshal(rawBytes2, &typed2)) + require.NoError(t, json.Unmarshal(rawBytes2, &typed2, jsonx.V1())) assert.False(t, typed2.ResponseStreamingSupported) } @@ -270,7 +271,7 @@ func TestAccuracy_FoundationModel_ListIsNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["modelSummaries"].([]any) assert.NotEmpty(t, summaries, "foundation models must be seeded on init") }) @@ -294,7 +295,7 @@ func TestAccuracy_FoundationModel_FieldsPresentOnList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["modelSummaries"].([]any) require.NotEmpty(t, summaries) @@ -336,7 +337,7 @@ func TestParity_FoundationModel_ARNIncludesRegion(t *testing.T) { ModelID string `json:"modelId"` } `json:"modelDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp.ModelDetails.ModelArn assert.True(t, strings.HasPrefix(arn, "arn:aws:bedrock:us-east-1::foundation-model/"), @@ -363,7 +364,7 @@ func TestParity_ListFoundationModels_ARNFormat(t *testing.T) { ModelArn string `json:"modelArn"` } `json:"modelSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.ModelSummaries, "ListFoundationModels must return at least one model") for _, m := range resp.ModelSummaries { @@ -402,7 +403,7 @@ func TestParity_FoundationModel_ModelLifecyclePresent(t *testing.T) { } `json:"modelLifecycle"` } `json:"modelDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACTIVE", resp.ModelDetails.ModelLifecycle.Status, "modelLifecycle.status must be ACTIVE for available models") @@ -427,7 +428,7 @@ func TestParity_ListFoundationModels_ModelLifecyclePresent(t *testing.T) { ModelID string `json:"modelId"` } `json:"modelSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.ModelSummaries) for _, m := range resp.ModelSummaries { @@ -470,7 +471,7 @@ func TestParity_GetFoundationModel_ByARN(t *testing.T) { ModelArn string `json:"modelArn"` } `json:"modelDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.modelID, resp.ModelDetails.ModelID, "GetFoundationModel by ARN must return the correct model") assert.Equal(t, expectedARN, resp.ModelDetails.ModelArn, @@ -501,7 +502,7 @@ func TestParity_GetFoundationModel_NotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) errType, _ := resp["__type"].(string) assert.Contains(t, errType, "ResourceNotFoundException") }) diff --git a/services/bedrock/handler_guardrails_test.go b/services/bedrock/handler_guardrails_test.go index c38a5e3c6b..89be258aa9 100644 --- a/services/bedrock/handler_guardrails_test.go +++ b/services/bedrock/handler_guardrails_test.go @@ -2,7 +2,7 @@ package bedrock_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -1081,7 +1082,7 @@ func TestAccuracy_GuardrailVersion_HTTPCreate(t *testing.T) { "/guardrails/"+g.GuardrailID, map[string]any{"description": fmt.Sprintf("v%d", i+1)}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lastOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lastOut, jsonx.V1())) } assert.Equal(t, tt.wantVersion, lastOut["version"]) @@ -1137,7 +1138,7 @@ func TestAccuracy_Guardrail_UpdatePreservesAllFields(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.newName, out["name"]) assert.Equal(t, tt.newDesc, out["description"]) }) @@ -1178,7 +1179,7 @@ func TestAccuracy_Tags_OnGuardrailViaListTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) returnedTags := out["tags"].([]any) assert.Len(t, returnedTags, tt.tagCount) }) @@ -1220,7 +1221,7 @@ func TestAccuracy_Tags_TagGuardrailAfterCreate(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) returnedTags := out["tags"].([]any) assert.Len(t, returnedTags, 1) assert.Equal(t, tt.key, returnedTags[0].(map[string]any)["key"]) @@ -1246,7 +1247,7 @@ func TestAccuracy_GuardrailVersion_PoliciesPreservedInVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) guardrailID := out["guardrailId"].(string) // Create a version @@ -1255,7 +1256,7 @@ func TestAccuracy_GuardrailVersion_PoliciesPreservedInVersion(t *testing.T) { require.Equal(t, http.StatusOK, versionRec.Code) var verOut map[string]any - require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &verOut)) + require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &verOut, jsonx.V1())) version := verOut["version"].(string) assert.NotEqual(t, "DRAFT", version) @@ -1264,6 +1265,6 @@ func TestAccuracy_GuardrailVersion_PoliciesPreservedInVersion(t *testing.T) { require.Equal(t, http.StatusOK, getVerRec.Code) var verDetailOut map[string]any - require.NoError(t, json.Unmarshal(getVerRec.Body.Bytes(), &verDetailOut)) + require.NoError(t, json.Unmarshal(getVerRec.Body.Bytes(), &verDetailOut, jsonx.V1())) assert.NotNil(t, verDetailOut["contentPolicy"], "version should preserve policies") } diff --git a/services/bedrock/handler_inference_profiles_test.go b/services/bedrock/handler_inference_profiles_test.go index 394293d713..0a17521cf9 100644 --- a/services/bedrock/handler_inference_profiles_test.go +++ b/services/bedrock/handler_inference_profiles_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -49,7 +50,7 @@ func TestAccuracy_InferenceProfile_CreateResponseShape(t *testing.T) { if tt.wantARN { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["inferenceProfileArn"]) assert.Equal(t, tt.wantProfileStatus, out["status"]) } @@ -141,7 +142,7 @@ func TestAccuracy_InferenceProfile_GetReturnsAllFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, p.InferenceProfileArn, out["inferenceProfileArn"]) assert.Equal(t, p.InferenceProfileID, out["inferenceProfileId"]) @@ -198,7 +199,7 @@ func TestAccuracy_InferenceProfile_ListContainsCreated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["inferenceProfileSummaries"].([]any) assert.Len(t, summaries, len(tt.profileNames)) @@ -246,7 +247,7 @@ func TestAccuracy_InferenceProfile_ListTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["inferenceProfileSummaries"].([]any) assert.Len(t, summaries, tt.wantLen) }) @@ -270,7 +271,7 @@ func TestAccuracy_InferenceProfile_DeleteRemovesFromList(t *testing.T) { recList := doRequest(t, h, http.MethodGet, "/inference-profiles", nil) require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut["inferenceProfileSummaries"].([]any)) } @@ -344,7 +345,7 @@ func TestHandler_InferenceProfileLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) profileARN := createOut["inferenceProfileArn"].(string) // List profiles. @@ -352,7 +353,7 @@ func TestHandler_InferenceProfileLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut, jsonx.V1())) assert.NotEmpty(t, listOut["inferenceProfileSummaries"]) // Get profile. diff --git a/services/bedrock/handler_marketplace_model_endpoints_test.go b/services/bedrock/handler_marketplace_model_endpoints_test.go index 68ade9382b..de7f1d52e5 100644 --- a/services/bedrock/handler_marketplace_model_endpoints_test.go +++ b/services/bedrock/handler_marketplace_model_endpoints_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -50,7 +51,7 @@ func TestAccuracy_MarketplaceEndpoint_CreateStartsAsCreating(t *testing.T) { if tt.wantStatus == http.StatusCreated { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ep := out["marketplaceModelEndpoint"].(map[string]any) assert.Equal(t, "REGISTERED", ep["status"]) assert.Equal(t, "Creating", ep["endpointStatus"]) @@ -185,7 +186,7 @@ func TestAccuracy_MarketplaceEndpoint_ListResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) endpoints := out["marketplaceModelEndpoints"].([]any) assert.Len(t, endpoints, 3) @@ -243,7 +244,7 @@ func TestAccuracy_MarketplaceEndpoint_ListModelSourceFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) endpoints := out["marketplaceModelEndpoints"].([]any) gotSources := make([]string, 0, len(endpoints)) @@ -277,7 +278,7 @@ func TestAccuracy_MarketplaceEndpoint_DeleteRemovesFromList(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["marketplaceModelEndpoints"].([]any)) } @@ -299,7 +300,7 @@ func TestAccuracy_MarketplaceEndpoint_UpdateReturnsEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) updated := out["marketplaceModelEndpoint"].(map[string]any) assert.Equal(t, ep.EndpointArn, updated["endpointArn"]) assert.NotEmpty(t, updated["updatedAt"]) @@ -428,7 +429,7 @@ func TestHandler_MarketplaceModelEndpointLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) endpointARN := createOut["marketplaceModelEndpoint"].(map[string]any)["endpointArn"].(string) // List endpoints. diff --git a/services/bedrock/handler_model_copy_jobs_test.go b/services/bedrock/handler_model_copy_jobs_test.go index a736c78647..44e84b7242 100644 --- a/services/bedrock/handler_model_copy_jobs_test.go +++ b/services/bedrock/handler_model_copy_jobs_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -156,7 +157,7 @@ func TestParity_ValidModelCopyJob_Returns201(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "jobArn", "successful response must include jobArn") } diff --git a/services/bedrock/handler_model_customization_jobs_test.go b/services/bedrock/handler_model_customization_jobs_test.go index 7d2cf485fa..d3b78e175f 100644 --- a/services/bedrock/handler_model_customization_jobs_test.go +++ b/services/bedrock/handler_model_customization_jobs_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -239,7 +240,7 @@ func TestAccuracy_CustomizationJob_StopTransitionsStatus(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "Stopping", out["status"]) }) } @@ -284,7 +285,7 @@ func TestAccuracy_CustomizationJob_ListViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["modelCustomizationJobSummaries"].([]any) assert.Len(t, summaries, tt.wantLen) @@ -347,7 +348,7 @@ func TestAccuracy_CustomizationJob_ListFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["modelCustomizationJobSummaries"].([]any) gotNames := make([]string, 0, len(summaries)) @@ -447,7 +448,7 @@ func TestAccuracy_CustomizationJob_CustomizationTypePreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) jobARN := createOut["jobArn"].(string) recGet := doRequest( @@ -460,7 +461,7 @@ func TestAccuracy_CustomizationJob_CustomizationTypePreserved(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.customizationType, out["customizationType"]) }) } @@ -481,7 +482,7 @@ func TestHandler_ModelCustomizationJobLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) jobARN := createOut["jobArn"].(string) assert.NotEmpty(t, jobARN) @@ -490,7 +491,7 @@ func TestHandler_ModelCustomizationJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut, jsonx.V1())) assert.NotEmpty(t, listOut["modelCustomizationJobSummaries"]) // Get job. diff --git a/services/bedrock/handler_model_import_jobs_test.go b/services/bedrock/handler_model_import_jobs_test.go index cf2cb88982..8fe2907434 100644 --- a/services/bedrock/handler_model_import_jobs_test.go +++ b/services/bedrock/handler_model_import_jobs_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -185,7 +186,7 @@ func TestAccuracy_ImportedModel_VisibleAfterImportJob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) models := out["modelSummaries"].([]any) assert.Len(t, models, 1) @@ -195,7 +196,7 @@ func TestAccuracy_ImportedModel_VisibleAfterImportJob(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var modelOut map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &modelOut)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &modelOut, jsonx.V1())) assert.Equal(t, job.ImportedModelArn, modelOut["modelArn"]) assert.Equal(t, tt.jobName+"-model", modelOut["modelName"]) assert.Equal(t, job.JobArn, modelOut["jobArn"]) @@ -223,7 +224,7 @@ func TestAccuracy_ImportedModel_DeleteRemovesFromList(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["modelSummaries"].([]any)) } @@ -240,7 +241,7 @@ func TestAccuracy_ModelImportJob_EndTimeAbsentWhileInProgress(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "InProgress", out["status"]) _, hasEndTime := out["endTime"] assert.False(t, hasEndTime, "endTime must not be present while InProgress") @@ -282,14 +283,14 @@ func TestAccuracy_ModelImportJob_ImportedModelStatus(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobARN := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/model-import-jobs/"+jobARN, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) // Status should be one of the valid statuses assert.Contains(t, []any{"InProgress", "Completed", "Failed"}, getOut["status"]) @@ -307,14 +308,14 @@ func TestAccuracy_ModelImportJob_TagsPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobARN := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/model-import-jobs/"+jobARN, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "tagged-import", getOut["jobName"]) } @@ -330,7 +331,7 @@ func TestAccuracy_ImportedModel_AvailableAfterJobComplete(t *testing.T) { require.Equal(t, http.StatusCreated, importRec.Code) var importOut map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut, jsonx.V1())) jobARN := importOut["jobArn"].(string) // Advance job status to complete (zero duration = immediate) @@ -341,7 +342,7 @@ func TestAccuracy_ImportedModel_AvailableAfterJobComplete(t *testing.T) { require.Equal(t, http.StatusOK, getJobRec.Code) var jobOut map[string]any - require.NoError(t, json.Unmarshal(getJobRec.Body.Bytes(), &jobOut)) + require.NoError(t, json.Unmarshal(getJobRec.Body.Bytes(), &jobOut, jsonx.V1())) importedModelARN := jobOut["importedModelArn"].(string) assert.NotEmpty(t, importedModelARN) @@ -350,7 +351,7 @@ func TestAccuracy_ImportedModel_AvailableAfterJobComplete(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) models := listOut["modelSummaries"].([]any) assert.NotEmpty(t, models) } diff --git a/services/bedrock/handler_model_invocation_jobs_test.go b/services/bedrock/handler_model_invocation_jobs_test.go index 123bae51e7..96dd0ea179 100644 --- a/services/bedrock/handler_model_invocation_jobs_test.go +++ b/services/bedrock/handler_model_invocation_jobs_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -43,7 +44,7 @@ func TestAccuracy_ModelInvocationJob_StopTransitionsStatus(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "Stopping", out["status"]) }) } @@ -77,7 +78,7 @@ func TestAccuracy_ModelInvocationJob_ListViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["invocationJobSummaries"].([]any) assert.Len(t, summaries, tt.wantLen) }) @@ -99,14 +100,14 @@ func TestAccuracy_ModelInvocationJob_JobNamePreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/model-invocation-job/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, jobName, getOut["jobName"]) }) } @@ -121,14 +122,14 @@ func TestAccuracy_ModelInvocationJob_StatusProgression(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/model-invocation-job/"+jobArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Contains(t, []any{"Submitted", "InProgress", "Completed", "Failed", "Stopped"}, getOut["status"], "status should be a valid model invocation job status") } @@ -142,7 +143,7 @@ func TestAccuracy_ModelInvocationJob_StopChangesStatus(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobArn := out["jobArn"].(string) stopRec := doRequest(t, h, http.MethodPost, "/model-invocation-job/"+jobArn+"/stop", nil) @@ -152,7 +153,7 @@ func TestAccuracy_ModelInvocationJob_StopChangesStatus(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "Stopping", getOut["status"]) } @@ -248,7 +249,7 @@ func TestBatch2Ops_StopModelInvocationJob_AlreadyStopped_Rejected(t *testing.T) "stop of already-stopped invocation job should return 400 ValidationException") var errBody map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ValidationException", errBody["__type"]) }) } diff --git a/services/bedrock/handler_model_invocation_logging_test.go b/services/bedrock/handler_model_invocation_logging_test.go index 141120b756..e77b2a6f95 100644 --- a/services/bedrock/handler_model_invocation_logging_test.go +++ b/services/bedrock/handler_model_invocation_logging_test.go @@ -1,12 +1,14 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAccuracy_LoggingConfig_RoundTrip proves the real @@ -36,7 +38,7 @@ func TestAccuracy_LoggingConfig_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) cfg, ok := out["loggingConfig"].(map[string]any) require.True(t, ok, "loggingConfig must be present after Put") @@ -73,7 +75,7 @@ func TestAccuracy_LoggingConfig_CloudWatchConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) cfg, ok := out["loggingConfig"].(map[string]any) require.True(t, ok) @@ -109,7 +111,7 @@ func TestAccuracy_LoggingConfig_DeleteClearsConfig(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Nil(t, out["loggingConfig"], "Delete must clear the config back to absent, not an empty object") } @@ -125,6 +127,6 @@ func TestAccuracy_LoggingConfig_GetBeforePutOmitsLoggingConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Nil(t, out["loggingConfig"]) } diff --git a/services/bedrock/handler_prompt_routers_test.go b/services/bedrock/handler_prompt_routers_test.go index 759e9301ad..c943fb865a 100644 --- a/services/bedrock/handler_prompt_routers_test.go +++ b/services/bedrock/handler_prompt_routers_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -78,7 +79,7 @@ func TestAccuracy_PromptRouter_CreateResponseShape(t *testing.T) { if tt.wantRouterID { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["promptRouterArn"]) } }) @@ -155,7 +156,7 @@ func TestAccuracy_PromptRouter_GetAndListAccuracy(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) routers := listOut["promptRouterSummaries"].([]any) assert.Len(t, routers, tt.wantLen) @@ -165,7 +166,7 @@ func TestAccuracy_PromptRouter_GetAndListAccuracy(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, lastARN, getOut["promptRouterArn"]) assert.Equal(t, "AVAILABLE", getOut["status"]) assert.Equal(t, "custom", getOut["type"]) @@ -232,7 +233,7 @@ func TestAccuracy_PromptRouter_NamePreservedInGetAndList(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) routerARN := out["promptRouterArn"].(string) assert.NotEmpty(t, routerARN) @@ -240,7 +241,7 @@ func TestAccuracy_PromptRouter_NamePreservedInGetAndList(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, tt.routerName, getOut["promptRouterName"]) assert.Equal(t, "AVAILABLE", getOut["status"]) }) @@ -260,7 +261,7 @@ func TestAccuracy_PromptRouter_TagsPreserved(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) routerARN := out["promptRouterArn"].(string) getRec := doRequest(t, h, http.MethodGet, "/prompt-routers/"+routerARN, nil) @@ -268,7 +269,7 @@ func TestAccuracy_PromptRouter_TagsPreserved(t *testing.T) { // Router ARN is returned and non-empty var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "AVAILABLE", getOut["status"]) } @@ -297,7 +298,7 @@ func TestAccuracy_PromptRouter_ListAfterDelete(t *testing.T) { require.Equal(t, http.StatusCreated, delRec.Code) var delOut map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delOut)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delOut, jsonx.V1())) delARN := delOut["promptRouterArn"].(string) // Delete it @@ -309,7 +310,7 @@ func TestAccuracy_PromptRouter_ListAfterDelete(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) routers := listOut["promptRouterSummaries"].([]any) for _, r := range routers { diff --git a/services/bedrock/handler_provisioned_throughput_test.go b/services/bedrock/handler_provisioned_throughput_test.go index 26dd18df1a..2775344e6b 100644 --- a/services/bedrock/handler_provisioned_throughput_test.go +++ b/services/bedrock/handler_provisioned_throughput_test.go @@ -2,7 +2,7 @@ package bedrock_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -533,7 +534,7 @@ func TestParity_ListProvisionedModelThroughputs_NameContainsFilter(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["provisionedModelSummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 1) diff --git a/services/bedrock/handler_test.go b/services/bedrock/handler_test.go index 55fecb2ea1..dd16f77b34 100644 --- a/services/bedrock/handler_test.go +++ b/services/bedrock/handler_test.go @@ -2,7 +2,7 @@ package bedrock_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -571,7 +572,7 @@ func TestHandler_RealSDKWireShapeRouteMatcher(t *testing.T) { //nolint:parallelt require.NoError(t, h.Handler()(c2)) var out map[string]string - _ = json.Unmarshal(rec2.Body.Bytes(), &out) + _ = json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1()) assert.NotEqual( t, "UnknownOperationException", out["__type"], "path/method must be dispatched to a real handler, not fall through as unrouted", @@ -714,7 +715,7 @@ func TestParity_ValidationException_Returns400(t *testing.T) { "ValidationException must return 400, not 500") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) errType, _ := resp["__type"].(string) assert.Contains(t, errType, "ValidationException", @@ -772,7 +773,7 @@ func TestParity_ValidationException_ErrorShape(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasType := resp["__type"] assert.True(t, hasType, "error response must have '__type' field") diff --git a/services/bedrock/list_summary_shapes_test.go b/services/bedrock/list_summary_shapes_test.go index c7be7b2e56..6ac44223c6 100644 --- a/services/bedrock/list_summary_shapes_test.go +++ b/services/bedrock/list_summary_shapes_test.go @@ -1,12 +1,15 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // listItems unmarshals a List response body and returns the array found @@ -14,14 +17,14 @@ import ( func listItems(t *testing.T, body []byte, key string) []map[string]any { t.Helper() - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(body, &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) raw, ok := resp[key] require.True(t, ok, "response missing key %q", key) var items []map[string]any - require.NoError(t, json.Unmarshal(raw, &items)) + require.NoError(t, json.Unmarshal(raw, &items, jsonx.V1())) return items } diff --git a/services/bedrock/models.go b/services/bedrock/models.go index 49ed6f555d..8ab9d95063 100644 --- a/services/bedrock/models.go +++ b/services/bedrock/models.go @@ -1,7 +1,7 @@ package bedrock import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -252,7 +252,7 @@ type EvaluationDatasetMetricConfig struct { type AutomatedEvaluationConfig struct { EvaluatorModelConfig *EvaluatorModelConfig `json:"evaluatorModelConfig,omitempty"` DatasetMetricConfigs []EvaluationDatasetMetricConfig `json:"datasetMetricConfigs,omitempty"` - CustomMetricConfig json.RawMessage `json:"customMetricConfig,omitempty"` + CustomMetricConfig jsontext.Value `json:"customMetricConfig,omitempty"` } // HumanEvaluationCustomMetric mirrors types.HumanEvaluationCustomMetric @@ -366,8 +366,8 @@ func (c *EvaluationConfig) EvaluatorModelIdentifiers() []string { // than partially modeled, same rationale as AutomatedEvaluationConfig. // CustomMetricConfig above. type RAGConfig struct { - KnowledgeBaseConfig json.RawMessage `json:"knowledgeBaseConfig,omitempty"` - PrecomputedRagSourceConfig json.RawMessage `json:"precomputedRagSourceConfig,omitempty"` + KnowledgeBaseConfig jsontext.Value `json:"knowledgeBaseConfig,omitempty"` + PrecomputedRagSourceConfig jsontext.Value `json:"precomputedRagSourceConfig,omitempty"` } // EvaluationInferenceConfig models bedrock's inferenceConfig union @@ -408,13 +408,13 @@ type AutomatedReasoningPolicy struct { // api_op_UpdateAutomatedReasoningPolicy.go:37-63). Kept as raw JSON rather // than the real nested rules/types/variables union -- inert, never // interpreted, but genuinely the caller's own content, not fabricated. - PolicyDefinition json.RawMessage `json:"policyDefinition,omitempty"` - Description string `json:"description,omitempty"` - Status string `json:"status"` - DefinitionHash string `json:"definitionHash,omitempty"` - Version string `json:"version,omitempty"` - KmsKeyArn string `json:"kmsKeyArn,omitempty"` - Tags []Tag `json:"tags,omitempty"` + PolicyDefinition jsontext.Value `json:"policyDefinition,omitempty"` + Description string `json:"description,omitempty"` + Status string `json:"status"` + DefinitionHash string `json:"definitionHash,omitempty"` + Version string `json:"version,omitempty"` + KmsKeyArn string `json:"kmsKeyArn,omitempty"` + Tags []Tag `json:"tags,omitempty"` } // AutomatedReasoningPolicyBuildWorkflow represents a build workflow for a policy. @@ -430,8 +430,8 @@ type AutomatedReasoningPolicyBuildWorkflow struct { // label, sourceContent is the entire JSON payload). SourceContent is // stored verbatim and never interpreted -- same rationale as // AutomatedReasoningPolicy.PolicyDefinition above. - BuildWorkflowType string `json:"buildWorkflowType,omitempty"` - SourceContent json.RawMessage `json:"sourceContent,omitempty"` + BuildWorkflowType string `json:"buildWorkflowType,omitempty"` + SourceContent jsontext.Value `json:"sourceContent,omitempty"` } // AutomatedReasoningPolicyTestCase represents a test case for a policy. diff --git a/services/bedrock/persistence.go b/services/bedrock/persistence.go index 82dd1eb414..d24caa025a 100644 --- a/services/bedrock/persistence.go +++ b/services/bedrock/persistence.go @@ -7,7 +7,7 @@ package bedrock // [github.com/blackbirdworks/gopherstack/pkgs/persistence.Persistable]. import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -75,7 +75,7 @@ const bedrockSnapshotVersion = 3 // CreateGuardrailVersion call reissues -- a real data-corruption risk, not // just a cosmetic gap. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` LoggingConfig *ModelInvocationLoggingConfiguration `json:"loggingConfig,omitempty"` GuardrailsByName map[string]string `json:"guardrailsByName"` GuardrailsByARN map[string]string `json:"guardrailsByARN"` diff --git a/services/bedrock/persistence_test.go b/services/bedrock/persistence_test.go index 17c7ada266..2fcc73f0a1 100644 --- a/services/bedrock/persistence_test.go +++ b/services/bedrock/persistence_test.go @@ -2,7 +2,7 @@ package bedrock_test import ( "context" - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -200,7 +200,7 @@ func seedJobResources( require.NoError(t, err) wf, err := b.StartAutomatedReasoningPolicyBuildWorkflow( - arp.PolicyArn, "INGEST_CONTENT", json.RawMessage(`{}`), + arp.PolicyArn, "INGEST_CONTENT", jsontext.Value(`{}`), ) require.NoError(t, err) diff --git a/services/bedrock/request_realism_test.go b/services/bedrock/request_realism_test.go index dea9697560..2a1113fa33 100644 --- a/services/bedrock/request_realism_test.go +++ b/services/bedrock/request_realism_test.go @@ -1,7 +1,7 @@ package bedrock_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -33,7 +34,7 @@ func TestRequestRealism_ErrorMessageHasNoCodePrefix(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", out["__type"]) assert.NotContains(t, out["message"], "ResourceNotFoundException") }) diff --git a/services/bedrock/test_helpers_test.go b/services/bedrock/test_helpers_test.go index 413b211749..9a5b843e1d 100644 --- a/services/bedrock/test_helpers_test.go +++ b/services/bedrock/test_helpers_test.go @@ -2,13 +2,14 @@ package bedrock_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http/httptest" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -72,7 +73,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -91,7 +92,7 @@ func doRequest( func mustUnmarshal(t *testing.T, rec *httptest.ResponseRecorder, v any) { t.Helper() - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1())) } func typesAsStrings(raw []any) []string { diff --git a/services/bedrockagent/delete_output_shape_test.go b/services/bedrockagent/delete_output_shape_test.go index cf47f1fb17..4ac4b9d403 100644 --- a/services/bedrockagent/delete_output_shape_test.go +++ b/services/bedrockagent/delete_output_shape_test.go @@ -1,7 +1,7 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "sort" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -86,7 +87,7 @@ func TestDeleteOps_ExactWireKeySet(t *testing.T) { require.Equal(t, http.StatusOK, agRec.Code, agRec.Body.String()) var agOut map[string]map[string]any - require.NoError(t, json.Unmarshal(agRec.Body.Bytes(), &agOut)) + require.NoError(t, json.Unmarshal(agRec.Body.Bytes(), &agOut, jsonx.V1())) groupID, _ := agOut["agentActionGroup"]["actionGroupId"].(string) require.NotEmpty(t, groupID) @@ -121,7 +122,7 @@ func TestDeleteOps_ExactWireKeySet(t *testing.T) { require.Equal(t, http.StatusCreated, verRec.Code, verRec.Body.String()) var verBody map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verBody)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verBody, jsonx.V1())) version, _ := verBody["version"].(string) require.NotEmpty(t, version) @@ -143,7 +144,7 @@ func TestDeleteOps_ExactWireKeySet(t *testing.T) { require.Equal(t, http.StatusCreated, aliasRec.Code, aliasRec.Body.String()) var aliasBody map[string]any - require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &aliasBody)) + require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &aliasBody, jsonx.V1())) aliasID, _ := aliasBody["id"].(string) require.NotEmpty(t, aliasID) @@ -242,7 +243,7 @@ func TestDeleteOps_ExactWireKeySet(t *testing.T) { require.Equal(t, http.StatusCreated, verRec.Code, verRec.Body.String()) var verBody map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verBody)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verBody, jsonx.V1())) version, _ := verBody["version"].(string) require.NotEmpty(t, version) @@ -269,7 +270,7 @@ func TestDeleteOps_ExactWireKeySet(t *testing.T) { } var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) gotKeys := make([]string, 0, len(out)) for k := range out { @@ -296,7 +297,7 @@ func createTestAgentForDeleteSweep(t *testing.T, h *bedrockagent.Handler, e *ech require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) agentID, _ := out["agent"]["agentId"].(string) require.NotEmpty(t, agentID) @@ -318,7 +319,7 @@ func createTestAgentAliasForDeleteSweep( require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) aliasID, _ := out["agentAlias"]["agentAliasId"].(string) require.NotEmpty(t, aliasID) @@ -342,7 +343,7 @@ func createTestFlowForDeleteSweep(t *testing.T, h *bedrockagent.Handler, e *echo require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) flowID, _ := out["id"].(string) require.NotEmpty(t, flowID) @@ -361,7 +362,7 @@ func createTestKBForDeleteSweep(t *testing.T, h *bedrockagent.Handler, e *echo.E require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) kbID, _ := out["knowledgeBase"]["knowledgeBaseId"].(string) require.NotEmpty(t, kbID) @@ -378,7 +379,7 @@ func createTestDSForDeleteSweep(t *testing.T, h *bedrockagent.Handler, e *echo.E require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) dsID, _ := out["dataSource"]["dataSourceId"].(string) require.NotEmpty(t, dsID) @@ -398,7 +399,7 @@ func createTestPromptForDeleteSweep(t *testing.T, h *bedrockagent.Handler, e *ec require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) promptID, _ := out["id"].(string) require.NotEmpty(t, promptID) diff --git a/services/bedrockagent/delete_version_in_use_test.go b/services/bedrockagent/delete_version_in_use_test.go index 681b23de3c..3eb7b34528 100644 --- a/services/bedrockagent/delete_version_in_use_test.go +++ b/services/bedrockagent/delete_version_in_use_test.go @@ -2,7 +2,7 @@ package bedrockagent_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -150,7 +151,7 @@ func TestHandleDeleteAgentVersion_ConflictOverHTTP(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) agentWrap, _ := created["agent"].(map[string]any) agentID, _ := agentWrap["agentId"].(string) require.NotEmpty(t, agentID) @@ -161,7 +162,7 @@ func TestHandleDeleteAgentVersion_ConflictOverHTTP(t *testing.T) { require.Equal(t, http.StatusOK, aliasRec.Code, aliasRec.Body.String()) var aliasBody map[string]any - require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &aliasBody)) + require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &aliasBody, jsonx.V1())) aliasWrap, _ := aliasBody["agentAlias"].(map[string]any) routing, _ := aliasWrap["routingConfiguration"].([]any) require.NotEmpty(t, routing) diff --git a/services/bedrockagent/handler_agent_action_groups.go b/services/bedrockagent/handler_agent_action_groups.go index e25a1810b2..0603556b9d 100644 --- a/services/bedrockagent/handler_agent_action_groups.go +++ b/services/bedrockagent/handler_agent_action_groups.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -27,7 +29,7 @@ func (h *Handler) handleCreateAgentActionGroup( ParentActionGroupSignature string `json:"parentActionGroupSignature"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -76,7 +78,7 @@ func (h *Handler) handleUpdateAgentActionGroup( ParentActionGroupSignature string `json:"parentActionGroupSignature"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_agent_action_groups_test.go b/services/bedrockagent/handler_agent_action_groups_test.go index 0e38088d97..0ca51f2e3f 100644 --- a/services/bedrockagent/handler_agent_action_groups_test.go +++ b/services/bedrockagent/handler_agent_action_groups_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateAgentActionGroupVersion locks in real AWS's constraint on the @@ -31,7 +33,7 @@ func TestCreateAgentActionGroupVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) rec := doRequest(t, h, e, http.MethodPut, @@ -44,7 +46,7 @@ func TestCreateAgentActionGroupVersion(t *testing.T) { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -69,7 +71,7 @@ func TestCreateAgentActionGroupVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) rec := doRequest(t, h, e, http.MethodPut, diff --git a/services/bedrockagent/handler_agent_aliases.go b/services/bedrockagent/handler_agent_aliases.go index b8ab5fcb57..a45b20e99a 100644 --- a/services/bedrockagent/handler_agent_aliases.go +++ b/services/bedrockagent/handler_agent_aliases.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -24,7 +26,7 @@ func (h *Handler) handleCreateAgentAlias( RoutingConfiguration []AliasRouting `json:"routingConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -66,7 +68,7 @@ func (h *Handler) handleUpdateAgentAlias( RoutingConfiguration []AliasRouting `json:"routingConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_agent_collaborators.go b/services/bedrockagent/handler_agent_collaborators.go index 515e2969f7..27cd5076d1 100644 --- a/services/bedrockagent/handler_agent_collaborators.go +++ b/services/bedrockagent/handler_agent_collaborators.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -23,7 +25,7 @@ func (h *Handler) handleAssociateCollaborator( ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -62,7 +64,7 @@ func (h *Handler) handleUpdateCollaborator( RelayConversationHistory string `json:"relayConversationHistory"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_agent_collaborators_test.go b/services/bedrockagent/handler_agent_collaborators_test.go index 28479cf24e..2d7e97e9d3 100644 --- a/services/bedrockagent/handler_agent_collaborators_test.go +++ b/services/bedrockagent/handler_agent_collaborators_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAssociateAgentCollaboratorVersion locks in real AWS's constraint on @@ -38,7 +40,7 @@ func TestAssociateAgentCollaboratorVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) rec := doRequest(t, h, e, http.MethodPut, @@ -55,7 +57,7 @@ func TestAssociateAgentCollaboratorVersion(t *testing.T) { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -80,7 +82,7 @@ func TestAssociateAgentCollaboratorVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) rec := doRequest(t, h, e, http.MethodPut, diff --git a/services/bedrockagent/handler_agent_knowledge_bases.go b/services/bedrockagent/handler_agent_knowledge_bases.go index 0b3f10bcf7..4c3e0bd5a3 100644 --- a/services/bedrockagent/handler_agent_knowledge_bases.go +++ b/services/bedrockagent/handler_agent_knowledge_bases.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -21,7 +23,7 @@ func (h *Handler) handleAssociateAgentKB( KnowledgeBaseState string `json:"knowledgeBaseState"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -54,7 +56,7 @@ func (h *Handler) handleUpdateAgentKB( KnowledgeBaseState string `json:"knowledgeBaseState"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_agent_knowledge_bases_test.go b/services/bedrockagent/handler_agent_knowledge_bases_test.go index b77461b59a..cab336c911 100644 --- a/services/bedrockagent/handler_agent_knowledge_bases_test.go +++ b/services/bedrockagent/handler_agent_knowledge_bases_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAssociateAgentKnowledgeBaseVersion locks in real AWS's constraint on @@ -29,7 +31,7 @@ func TestAssociateAgentKnowledgeBaseVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) kbRec := doRequest(t, h, e, http.MethodPut, "/knowledgebases", map[string]any{ @@ -44,7 +46,7 @@ func TestAssociateAgentKnowledgeBaseVersion(t *testing.T) { var kbResp map[string]map[string]any - _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp) + _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp, jsonx.V1()) kbID, _ := kbResp["knowledgeBase"]["knowledgeBaseId"].(string) rec := doRequest(t, h, e, http.MethodPut, @@ -58,7 +60,7 @@ func TestAssociateAgentKnowledgeBaseVersion(t *testing.T) { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -83,7 +85,7 @@ func TestAssociateAgentKnowledgeBaseVersion(t *testing.T) { var agentResp map[string]map[string]any - _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp) + _ = json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1()) agentID, _ := agentResp["agent"]["agentId"].(string) kbRec := doRequest(t, h, e, http.MethodPut, "/knowledgebases", map[string]any{ @@ -98,7 +100,7 @@ func TestAssociateAgentKnowledgeBaseVersion(t *testing.T) { var kbResp map[string]map[string]any - _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp) + _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp, jsonx.V1()) kbID, _ := kbResp["knowledgeBase"]["knowledgeBaseId"].(string) rec := doRequest(t, h, e, http.MethodPut, diff --git a/services/bedrockagent/handler_agents.go b/services/bedrockagent/handler_agents.go index 292e681366..cf9d85d1ed 100644 --- a/services/bedrockagent/handler_agents.go +++ b/services/bedrockagent/handler_agents.go @@ -2,12 +2,14 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -33,7 +35,7 @@ func (h *Handler) handleCreateAgent(ctx context.Context, c *echo.Context, body [ IdleSessionTTLInSeconds int `json:"idleSessionTTLInSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -92,7 +94,7 @@ func (h *Handler) handleUpdateAgent( IdleSessionTTLInSeconds int `json:"idleSessionTTLInSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_agents_test.go b/services/bedrockagent/handler_agents_test.go index 89b26a4e26..ae9d82b70e 100644 --- a/services/bedrockagent/handler_agents_test.go +++ b/services/bedrockagent/handler_agents_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerAgentCRUD(t *testing.T) { @@ -31,7 +33,7 @@ func TestHandlerAgentCRUD(t *testing.T) { } var createResp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &createResp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal create response: %v", err) } @@ -74,7 +76,7 @@ func TestHandlerAgentCRUD(t *testing.T) { } var sr map[string]map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &sr) + _ = json.Unmarshal(r.Body.Bytes(), &sr, jsonx.V1()) aid := sr["agent"]["agentId"].(string) path := tc.path @@ -122,7 +124,7 @@ func TestHandlerAgentVersions(t *testing.T) { rec := doRequest(t, h, e, http.MethodPut, "/agents", createBody) var createResp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &createResp) + _ = json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()) agentID := createResp["agent"]["agentId"].(string) // Prepare first so we can create a version @@ -138,7 +140,7 @@ func TestHandlerAgentVersions(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPut, "/agents", createBody) var resp map[string]map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) aid := resp["agent"]["agentId"].(string) doRequest(t, h2, e2, http.MethodPost, "/agents/"+aid+"/prepare", nil) @@ -148,7 +150,7 @@ func TestHandlerAgentVersions(t *testing.T) { } var listResp map[string]any - _ = json.Unmarshal(rec2.Body.Bytes(), &listResp) + _ = json.Unmarshal(rec2.Body.Bytes(), &listResp, jsonx.V1()) if _, ok := listResp["agentVersionSummaries"]; !ok { t.Errorf("response missing agentVersionSummaries: %s", rec2.Body.String()) @@ -181,7 +183,7 @@ func TestCreateAgent_DefaultIdleSessionTTL(t *testing.T) { } var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -208,7 +210,7 @@ func TestCreateAgent_CustomIdleSessionTTL(t *testing.T) { } var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -230,7 +232,7 @@ func TestUpdateAgent_IdleSessionTTL(t *testing.T) { }) var createResp map[string]map[string]any - if err := json.Unmarshal(createRec.Body.Bytes(), &createResp); err != nil { + if err := json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -248,7 +250,7 @@ func TestUpdateAgent_IdleSessionTTL(t *testing.T) { } var updateResp map[string]map[string]any - if err := json.Unmarshal(updateRec.Body.Bytes(), &updateResp); err != nil { + if err := json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -277,7 +279,7 @@ func TestAgentVersionsPOST_IsListNotCreate(t *testing.T) { }) var createResp map[string]map[string]any - if err := json.Unmarshal(createRec.Body.Bytes(), &createResp); err != nil { + if err := json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -290,7 +292,7 @@ func TestAgentVersionsPOST_IsListNotCreate(t *testing.T) { } var resp map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -315,7 +317,7 @@ func TestCreateAgentAlias_NoRoutingConfig_AutoCreatesVersion(t *testing.T) { }) var createResp map[string]map[string]any - if err := json.Unmarshal(createRec.Body.Bytes(), &createResp); err != nil { + if err := json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -330,7 +332,7 @@ func TestCreateAgentAlias_NoRoutingConfig_AutoCreatesVersion(t *testing.T) { } var aliasResp map[string]map[string]any - if err := json.Unmarshal(aliasRec.Body.Bytes(), &aliasResp); err != nil { + if err := json.Unmarshal(aliasRec.Body.Bytes(), &aliasResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -342,7 +344,7 @@ func TestCreateAgentAlias_NoRoutingConfig_AutoCreatesVersion(t *testing.T) { listRec := doRequest(t, h, e, http.MethodGet, "/agents/"+agentID+"/agentversions", nil) var listResp map[string]any - if err := json.Unmarshal(listRec.Body.Bytes(), &listResp); err != nil { + if err := json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -364,7 +366,7 @@ func TestPrepareAgent_ResponseIncludesPreparedAt(t *testing.T) { }) var createResp map[string]map[string]any - if err := json.Unmarshal(createRec.Body.Bytes(), &createResp); err != nil { + if err := json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -377,7 +379,7 @@ func TestPrepareAgent_ResponseIncludesPreparedAt(t *testing.T) { } var resp map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } diff --git a/services/bedrockagent/handler_data_sources.go b/services/bedrockagent/handler_data_sources.go index fffef1344d..5d1979f2f7 100644 --- a/services/bedrockagent/handler_data_sources.go +++ b/services/bedrockagent/handler_data_sources.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -23,7 +25,7 @@ func (h *Handler) handleCreateDS(ctx context.Context, c *echo.Context, kbID stri DataDeletionPolicy string `json:"dataDeletionPolicy"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -66,7 +68,7 @@ func (h *Handler) handleUpdateDS( DataDeletionPolicy string `json:"dataDeletionPolicy"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_data_sources_test.go b/services/bedrockagent/handler_data_sources_test.go index bfacfbd9c4..70931ba468 100644 --- a/services/bedrockagent/handler_data_sources_test.go +++ b/services/bedrockagent/handler_data_sources_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerDataSourceAndIngestion(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandlerDataSourceAndIngestion(t *testing.T) { } var kbResp map[string]map[string]any - _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp) + _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp, jsonx.V1()) kbID := kbResp["knowledgeBase"]["knowledgeBaseId"].(string) dsBody := map[string]any{ @@ -38,7 +40,7 @@ func TestHandlerDataSourceAndIngestion(t *testing.T) { } var dsResp map[string]map[string]any - _ = json.Unmarshal(dsRec.Body.Bytes(), &dsResp) + _ = json.Unmarshal(dsRec.Body.Bytes(), &dsResp, jsonx.V1()) dsID := dsResp["dataSource"]["dataSourceId"].(string) t.Run("start ingestion job", func(t *testing.T) { diff --git a/services/bedrockagent/handler_flows.go b/services/bedrockagent/handler_flows.go index 2ca5a42d1b..066de3a2eb 100644 --- a/services/bedrockagent/handler_flows.go +++ b/services/bedrockagent/handler_flows.go @@ -2,12 +2,14 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -25,7 +27,7 @@ func (h *Handler) handleCreateFlow(ctx context.Context, c *echo.Context, body [] CustomerEncryptionKeyArn string `json:"customerEncryptionKeyArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -77,7 +79,7 @@ func (h *Handler) handleUpdateFlow( CustomerEncryptionKeyArn string `json:"customerEncryptionKeyArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -133,7 +135,7 @@ func (h *Handler) handleValidateFlowDef(ctx context.Context, c *echo.Context, bo Definition map[string]any `json:"definition"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) errs, err := h.Backend.ValidateFlowDefinition(ctx, req.Definition) if err != nil { @@ -155,7 +157,7 @@ func (h *Handler) handleCreateFlowVersion( ClientToken string `json:"clientToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) fv, err := h.Backend.CreateFlowVersion(ctx, flowID, VersionConfig{ Description: req.Description, ClientToken: req.ClientToken, @@ -228,7 +230,7 @@ func (h *Handler) handleCreateFlowAlias( RoutingConfiguration []FlowAliasRouting `json:"routingConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -270,7 +272,7 @@ func (h *Handler) handleUpdateFlowAlias( RoutingConfiguration []FlowAliasRouting `json:"routingConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_flows_test.go b/services/bedrockagent/handler_flows_test.go index 4f426c2b66..7d1c411357 100644 --- a/services/bedrockagent/handler_flows_test.go +++ b/services/bedrockagent/handler_flows_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerFlowCRUD(t *testing.T) { @@ -26,7 +28,7 @@ func TestHandlerFlowCRUD(t *testing.T) { } var createResp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &createResp) + _ = json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()) flowID, _ := createResp["id"].(string) if flowID == "" { @@ -40,7 +42,7 @@ func TestHandlerFlowCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPost, "/flows", createBody) var resp map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["id"].(string) rec2 := doRequest(t, h2, e2, http.MethodGet, "/flows/"+id, nil) @@ -65,7 +67,7 @@ func TestHandlerFlowCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPost, "/flows", createBody) var resp map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["id"].(string) // Real PrepareFlow POSTs to "/flows/{flowIdentifier}/" -- no diff --git a/services/bedrockagent/handler_helpers.go b/services/bedrockagent/handler_helpers.go index c74b8b50dc..71775bc35e 100644 --- a/services/bedrockagent/handler_helpers.go +++ b/services/bedrockagent/handler_helpers.go @@ -2,7 +2,7 @@ package bedrockagent import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,12 +15,12 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var wireCodePrefix = regexp.MustCompile(`^(?:[A-Za-z]+Exception: )+`) func handleErr(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError var code string var status int @@ -35,7 +35,7 @@ func handleErr(c *echo.Context, err error) error { case errors.Is(err, awserr.ErrInvalidParameter): status = http.StatusBadRequest code = "ValidationException" - case errors.As(err, &syntaxErr): + case jsonx.IsSyntaxError(err): status = http.StatusBadRequest code = "ValidationException" default: @@ -76,7 +76,7 @@ func bodyPageParams(body []byte) (int, string) { } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } maxResults := maxPageDefault @@ -199,7 +199,7 @@ func validatePageRequest(query url.Values, body []byte) error { } var fromBody pageFields - if len(body) > 0 && json.Unmarshal(body, &fromBody) == nil { + if len(body) > 0 && json.Unmarshal(body, &fromBody, jsonx.V1()) == nil { req.overlay(fromBody) } diff --git a/services/bedrockagent/handler_ingestion_jobs.go b/services/bedrockagent/handler_ingestion_jobs.go index 50fd2583d2..475859b58e 100644 --- a/services/bedrockagent/handler_ingestion_jobs.go +++ b/services/bedrockagent/handler_ingestion_jobs.go @@ -2,10 +2,12 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -20,7 +22,7 @@ func (h *Handler) handleStartIngestionJob( ClientToken string `json:"clientToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) job, err := h.Backend.StartIngestionJob(ctx, kbID, dsID, req.Description, req.ClientToken) if err != nil { @@ -70,7 +72,7 @@ func (h *Handler) handleListIngestionJobs( } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } } diff --git a/services/bedrockagent/handler_ingestion_jobs_test.go b/services/bedrockagent/handler_ingestion_jobs_test.go index c102d923c3..d50629d2fc 100644 --- a/services/bedrockagent/handler_ingestion_jobs_test.go +++ b/services/bedrockagent/handler_ingestion_jobs_test.go @@ -1,12 +1,13 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -39,7 +40,7 @@ func newIngestionFixture(t *testing.T) ingestionFixture { var kbResp map[string]map[string]any - _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp) + _ = json.Unmarshal(kbRec.Body.Bytes(), &kbResp, jsonx.V1()) kbID, _ := kbResp["knowledgeBase"]["knowledgeBaseId"].(string) dsBody := map[string]any{ @@ -54,7 +55,7 @@ func newIngestionFixture(t *testing.T) ingestionFixture { var dsResp map[string]map[string]any - _ = json.Unmarshal(dsRec.Body.Bytes(), &dsResp) + _ = json.Unmarshal(dsRec.Body.Bytes(), &dsResp, jsonx.V1()) dsID, _ := dsResp["dataSource"]["dataSourceId"].(string) return ingestionFixture{h: h, e: e, kbID: kbID, dsID: dsID} @@ -95,7 +96,7 @@ func (f ingestionFixture) startJob(t *testing.T) map[string]any { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -199,7 +200,7 @@ func checkGetIngestionJobReturnsPersistedStats(t *testing.T) { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -232,7 +233,7 @@ func checkListIngestionJobsSummariesIncludeStats(t *testing.T) { IngestionJobSummaries []map[string]any `json:"ingestionJobSummaries"` } - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -284,7 +285,7 @@ func TestKBDocumentsRealWireRouting(t *testing.T) { var ingestResp map[string]any - if err := json.Unmarshal(putRec.Body.Bytes(), &ingestResp); err != nil { + if err := json.Unmarshal(putRec.Body.Bytes(), &ingestResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal PUT response: %v", err) } @@ -308,7 +309,7 @@ func TestKBDocumentsRealWireRouting(t *testing.T) { DocumentDetails []map[string]any `json:"documentDetails"` } - if err := json.Unmarshal(postRec.Body.Bytes(), &listResp); err != nil { + if err := json.Unmarshal(postRec.Body.Bytes(), &listResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal POST response: %v", err) } @@ -335,7 +336,7 @@ func TestStopIngestionJob(t *testing.T) { var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } diff --git a/services/bedrockagent/handler_knowledge_bases.go b/services/bedrockagent/handler_knowledge_bases.go index ee3abe4aa4..facc16f3c2 100644 --- a/services/bedrockagent/handler_knowledge_bases.go +++ b/services/bedrockagent/handler_knowledge_bases.go @@ -2,11 +2,13 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -24,7 +26,7 @@ func (h *Handler) handleCreateKB(ctx context.Context, c *echo.Context, body []by ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -63,7 +65,7 @@ func (h *Handler) handleUpdateKB(ctx context.Context, c *echo.Context, kbID stri RoleARN string `json:"roleArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -167,7 +169,7 @@ func (h *Handler) handleIngestKBDocs( } `json:"documents"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -195,7 +197,7 @@ func (h *Handler) handleGetKBDocs( DocumentIdentifiers []KBDocumentIdentifier `json:"documentIdentifiers"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -215,7 +217,7 @@ func (h *Handler) handleDeleteKBDocs( DocumentIdentifiers []KBDocumentIdentifier `json:"documentIdentifiers"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_knowledge_bases_test.go b/services/bedrockagent/handler_knowledge_bases_test.go index 7a9ad76ee8..e5e227f4c8 100644 --- a/services/bedrockagent/handler_knowledge_bases_test.go +++ b/services/bedrockagent/handler_knowledge_bases_test.go @@ -1,7 +1,7 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -35,7 +36,7 @@ func TestHandlerKnowledgeBaseCRUD(t *testing.T) { } var createResp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &createResp) + _ = json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()) kbID := createResp["knowledgeBase"]["knowledgeBaseId"].(string) t.Run("get kb", func(t *testing.T) { @@ -45,7 +46,7 @@ func TestHandlerKnowledgeBaseCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPut, "/knowledgebases", createBody) var resp map[string]map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["knowledgeBase"]["knowledgeBaseId"].(string) rec2 := doRequest(t, h2, e2, http.MethodGet, "/knowledgebases/"+id, nil) @@ -70,7 +71,7 @@ func TestHandlerKnowledgeBaseCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPut, "/knowledgebases", createBody) var resp map[string]map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["knowledgeBase"]["knowledgeBaseId"].(string) rec2 := doRequest(t, h2, e2, http.MethodDelete, "/knowledgebases/"+id, nil) @@ -98,7 +99,7 @@ func createKBForResourcePolicyTest(t *testing.T, h *bedrockagent.Handler, e *ech } var resp map[string]map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal create kb response: %v", err) } @@ -123,7 +124,7 @@ func putKBResourcePolicy( } var resp map[string]string - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal put resource policy response: %v", err) } @@ -215,7 +216,7 @@ func TestHandlerResourcePolicyPut(t *testing.T) { t.Helper() var resp map[string]string - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -369,7 +370,7 @@ func TestHandlerResourcePolicyGet(t *testing.T) { t.Helper() var resp map[string]string - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -420,7 +421,7 @@ func TestHandlerResourcePolicyDelete(t *testing.T) { t.Helper() var resp map[string]string - if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -528,7 +529,7 @@ func listKBDocsForIdentifierTest(t *testing.T, f ingestionFixture) []map[string] var resp struct { DocumentDetails []map[string]any `json:"documentDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp.DocumentDetails } @@ -554,7 +555,7 @@ func TestHandlerGetKBDocuments_RealWireIdentifier(t *testing.T) { var resp struct { DocumentDetails []map[string]any `json:"documentDetails"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.DocumentDetails, 1) assert.Equal(t, "INDEXED", resp.DocumentDetails[0]["status"]) @@ -588,7 +589,7 @@ func TestHandlerDeleteKBDocuments_RealWireIdentifier(t *testing.T) { var deleteResp struct { DocumentDetails []map[string]any `json:"documentDetails"` } - require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp, jsonx.V1())) require.Len(t, deleteResp.DocumentDetails, 1) assert.Equal(t, "DELETING", deleteResp.DocumentDetails[0]["status"]) diff --git a/services/bedrockagent/handler_prompts.go b/services/bedrockagent/handler_prompts.go index 5d873337c0..d59cfc9b3c 100644 --- a/services/bedrockagent/handler_prompts.go +++ b/services/bedrockagent/handler_prompts.go @@ -2,11 +2,13 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -24,7 +26,7 @@ func (h *Handler) handleCreatePrompt(ctx context.Context, c *echo.Context, body Variants []map[string]any `json:"variants"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -89,7 +91,7 @@ func (h *Handler) handleUpdatePrompt( Variants []map[string]any `json:"variants"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } @@ -150,7 +152,7 @@ func (h *Handler) handleCreatePromptVersion( ClientToken string `json:"clientToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) pv, err := h.Backend.CreatePromptVersion(ctx, promptID, VersionConfig{ Description: req.Description, ClientToken: req.ClientToken, Tags: req.Tags, diff --git a/services/bedrockagent/handler_prompts_test.go b/services/bedrockagent/handler_prompts_test.go index f343619833..f5d20a86d4 100644 --- a/services/bedrockagent/handler_prompts_test.go +++ b/services/bedrockagent/handler_prompts_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerPromptCRUD(t *testing.T) { @@ -28,7 +30,7 @@ func TestHandlerPromptCRUD(t *testing.T) { } var createResp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &createResp) + _ = json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()) promptID, _ := createResp["id"].(string) if promptID == "" { @@ -42,7 +44,7 @@ func TestHandlerPromptCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPost, "/prompts", createBody) var resp map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["id"].(string) rec2 := doRequest(t, h2, e2, http.MethodGet, "/prompts/"+id, nil) @@ -67,7 +69,7 @@ func TestHandlerPromptCRUD(t *testing.T) { r := doRequest(t, h2, e2, http.MethodPost, "/prompts", createBody) var resp map[string]any - _ = json.Unmarshal(r.Body.Bytes(), &resp) + _ = json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1()) id := resp["id"].(string) rec2 := doRequest(t, h2, e2, http.MethodPost, "/prompts/"+id+"/versions", map[string]any{ diff --git a/services/bedrockagent/handler_resource_policy.go b/services/bedrockagent/handler_resource_policy.go index b57796caa2..d282b4a377 100644 --- a/services/bedrockagent/handler_resource_policy.go +++ b/services/bedrockagent/handler_resource_policy.go @@ -2,11 +2,13 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resourcePolicyBase is bedrock-agent's real PutResourcePolicy/ @@ -85,7 +87,7 @@ func (h *Handler) handlePutResourcePolicy( ctx context.Context, c *echo.Context, resourceArn string, body []byte, ) error { var req putResourcePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_tags.go b/services/bedrockagent/handler_tags.go index d6d39d0af0..0cb99faee0 100644 --- a/services/bedrockagent/handler_tags.go +++ b/services/bedrockagent/handler_tags.go @@ -2,11 +2,13 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -31,7 +33,7 @@ func (h *Handler) handleTagResource( Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/handler_tags_test.go b/services/bedrockagent/handler_tags_test.go index 1a5aee225d..2c939ee0aa 100644 --- a/services/bedrockagent/handler_tags_test.go +++ b/services/bedrockagent/handler_tags_test.go @@ -1,9 +1,11 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerTagging(t *testing.T) { @@ -20,7 +22,7 @@ func TestHandlerTagging(t *testing.T) { rec := doRequest(t, h, e, http.MethodPut, "/agents", createBody) var createResp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &createResp) + _ = json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1()) arn := createResp["agent"]["agentArn"].(string) t.Run("tag resource", func(t *testing.T) { diff --git a/services/bedrockagent/handler_test.go b/services/bedrockagent/handler_test.go index 050d1be4d3..24111b9d90 100644 --- a/services/bedrockagent/handler_test.go +++ b/services/bedrockagent/handler_test.go @@ -3,13 +3,14 @@ package bedrockagent_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -36,7 +37,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) if err != nil { t.Fatalf("marshal body: %v", err) } diff --git a/services/bedrockagent/handler_vpc_configurations.go b/services/bedrockagent/handler_vpc_configurations.go index 480051047a..39a9c8daf6 100644 --- a/services/bedrockagent/handler_vpc_configurations.go +++ b/services/bedrockagent/handler_vpc_configurations.go @@ -2,13 +2,15 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -77,7 +79,7 @@ func (h *Handler) handleCreateVpcConfiguration( Port int32 `json:"port"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return handleErr(c, err) } diff --git a/services/bedrockagent/lifecycle_test.go b/services/bedrockagent/lifecycle_test.go index 9cf8297221..613cfb6ace 100644 --- a/services/bedrockagent/lifecycle_test.go +++ b/services/bedrockagent/lifecycle_test.go @@ -1,7 +1,7 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagent" ) @@ -117,7 +118,7 @@ func TestRequestRealism_ErrorsAndPaging(t *testing.T) { assert.Equal(t, tt.wantType, rec.Header().Get("X-Amzn-Errortype")) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out["message"], "Exception") }) } diff --git a/services/bedrockagent/models.go b/services/bedrockagent/models.go index 137a1c909e..be25ec1c1b 100644 --- a/services/bedrockagent/models.go +++ b/services/bedrockagent/models.go @@ -1,8 +1,10 @@ package bedrockagent import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // defaultIdleSessionTTLSeconds is the default agent idle session TTL (10 minutes), @@ -493,7 +495,7 @@ func (d *DataSource) UnmarshalJSON(data []byte) error { *dataSourceAlias }{dataSourceAlias: (*dataSourceAlias)(d)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/bedrockagent/persistence.go b/services/bedrockagent/persistence.go index a178925312..b203b4b90f 100644 --- a/services/bedrockagent/persistence.go +++ b/services/bedrockagent/persistence.go @@ -2,7 +2,7 @@ package bedrockagent import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -63,7 +63,7 @@ const bedrockagentSnapshotVersion = 3 // too, or a restored backend would start minting IDs that collide with // pre-restore ones. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` AgentsByName map[string]string `json:"agentsByName"` KBsByName map[string]string `json:"kbsByName"` FlowsByName map[string]string `json:"flowsByName"` diff --git a/services/bedrockagent/wire_field_fixes_test.go b/services/bedrockagent/wire_field_fixes_test.go index 0aacb27ac4..b730bea210 100644 --- a/services/bedrockagent/wire_field_fixes_test.go +++ b/services/bedrockagent/wire_field_fixes_test.go @@ -1,12 +1,14 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDeleteFlow_NoInventedStatusKey_RealClient guards against @@ -28,7 +30,7 @@ func TestDeleteFlow_NoInventedStatusKey_RealClient(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code, createRec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) flowID, _ := created["id"].(string) require.NotEmpty(t, flowID) @@ -58,7 +60,7 @@ func TestDeleteFlowVersion_NoInventedStatusKey_RealClient(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code, createRec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) flowID, _ := created["id"].(string) require.NotEmpty(t, flowID) @@ -66,7 +68,7 @@ func TestDeleteFlowVersion_NoInventedStatusKey_RealClient(t *testing.T) { require.Equal(t, http.StatusCreated, versionRec.Code, versionRec.Body.String()) var versionBody map[string]any - require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &versionBody)) + require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &versionBody, jsonx.V1())) version, _ := versionBody["version"].(string) require.NotEmpty(t, version) diff --git a/services/bedrockagent/wire_field_omissions_test.go b/services/bedrockagent/wire_field_omissions_test.go index c13b6215bc..72c8be6071 100644 --- a/services/bedrockagent/wire_field_omissions_test.go +++ b/services/bedrockagent/wire_field_omissions_test.go @@ -1,11 +1,13 @@ package bedrockagent_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestBedrockAgentLists_OmitGetOnlyFields asserts the raw decoded response @@ -30,7 +32,7 @@ func TestBedrockAgentLists_OmitGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, agentRec.Code, agentRec.Body.String()) var agentResp map[string]map[string]any - require.NoError(t, json.Unmarshal(agentRec.Body.Bytes(), &agentResp)) + require.NoError(t, json.Unmarshal(agentRec.Body.Bytes(), &agentResp, jsonx.V1())) agentID, _ := agentResp["agent"]["agentId"].(string) require.NotEmpty(t, agentID) @@ -43,7 +45,7 @@ func TestBedrockAgentLists_OmitGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, kbRec.Code, kbRec.Body.String()) var kbResp map[string]map[string]any - require.NoError(t, json.Unmarshal(kbRec.Body.Bytes(), &kbResp)) + require.NoError(t, json.Unmarshal(kbRec.Body.Bytes(), &kbResp, jsonx.V1())) kbID, _ := kbResp["knowledgeBase"]["knowledgeBaseId"].(string) require.NotEmpty(t, kbID) @@ -59,7 +61,7 @@ func TestBedrockAgentLists_OmitGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) summaries, ok := raw["agentKnowledgeBaseSummaries"].([]any) require.True(t, ok) @@ -91,7 +93,7 @@ func TestBedrockAgentLists_OmitGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) flowID, _ := createResp["id"].(string) require.NotEmpty(t, flowID) @@ -103,7 +105,7 @@ func TestBedrockAgentLists_OmitGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) summaries, ok := raw["flowVersionSummaries"].([]any) require.True(t, ok) diff --git a/services/bedrockagentcore/identity.go b/services/bedrockagentcore/identity.go index e3f68dadf6..e99853f220 100644 --- a/services/bedrockagentcore/identity.go +++ b/services/bedrockagentcore/identity.go @@ -3,11 +3,12 @@ package bedrockagentcore import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -96,7 +97,7 @@ func userFromJWT(in doc) (string, error) { Sub string `json:"sub"` } - if err = json.Unmarshal(raw, &claims); err != nil || claims.Sub == "" { + if err = json.Unmarshal(raw, &claims, jsonx.V1()); err != nil || claims.Sub == "" { return "", invalid("userToken must carry a sub claim") } diff --git a/services/bedrockagentcore/identity_test.go b/services/bedrockagentcore/identity_test.go index 99ca6afd5a..ac81cc5e42 100644 --- a/services/bedrockagentcore/identity_test.go +++ b/services/bedrockagentcore/identity_test.go @@ -2,7 +2,8 @@ package bedrockagentcore_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagentcore" ) @@ -32,7 +34,10 @@ func tokenServer(t *testing.T) *httptest.Server { return } - _ = json.NewEncoder(w).Encode(map[string]string{"access_token": "tok-for-" + r.FormValue("scope")}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"access_token": "tok-for-" + r.FormValue("scope")}, + ) })) t.Cleanup(srv.Close) @@ -81,7 +86,7 @@ func TestIdentity_WorkloadTokens(t *testing.T) { require.NoError(t, err) assert.NotEmpty(t, *plain.WorkloadAccessToken) - payload, _ := json.Marshal(map[string]string{"sub": "user-9"}) + payload, _ := json.Marshal(map[string]string{"sub": "user-9"}, jsonx.V1()) jwt := "e30." + base64.RawURLEncoding.EncodeToString(payload) + ".sig" viaJWT, err := f.client.GetWorkloadAccessTokenForJWT(t.Context(), &sdk.GetWorkloadAccessTokenForJWTInput{ diff --git a/services/bedrockagentcore/oauth.go b/services/bedrockagentcore/oauth.go index 00447788ea..e17cc0f6b8 100644 --- a/services/bedrockagentcore/oauth.go +++ b/services/bedrockagentcore/oauth.go @@ -2,12 +2,14 @@ package bedrockagentcore import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/url" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -101,7 +103,7 @@ func (b *InMemoryBackend) exchange(hreq *http.Request) (string, error) { AccessToken string `json:"access_token"` } - if err = json.Unmarshal(body, &out); err != nil || out.AccessToken == "" { + if err = json.Unmarshal(body, &out, jsonx.V1()); err != nil || out.AccessToken == "" { return "", invalid("the token endpoint did not return an access_token") } @@ -136,7 +138,11 @@ func (b *InMemoryBackend) tokenEndpoint(ctx context.Context, p ProviderInfo) (st TokenEndpoint string `json:"token_endpoint"` } - if err = json.NewDecoder(io.LimitReader(resp.Body, maxTokenResponse)).Decode(&meta); err != nil || + if err = json.UnmarshalDecode( + jsontext.NewDecoder(io.LimitReader(resp.Body, maxTokenResponse)), + &meta, + jsonx.V1(), + ); err != nil || meta.TokenEndpoint == "" { return "", invalid("the discovery document of provider %q has no token_endpoint", p.Name) } diff --git a/services/bedrockagentcore/persistence.go b/services/bedrockagentcore/persistence.go index 32b162b4d1..be7f0ae517 100644 --- a/services/bedrockagentcore/persistence.go +++ b/services/bedrockagentcore/persistence.go @@ -2,7 +2,7 @@ package bedrockagentcore import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. Containers and sandboxes are not part of it. diff --git a/services/bedrockagentcore/runtime_docker_test.go b/services/bedrockagentcore/runtime_docker_test.go index a52cad22a8..2af6cab527 100644 --- a/services/bedrockagentcore/runtime_docker_test.go +++ b/services/bedrockagentcore/runtime_docker_test.go @@ -2,7 +2,7 @@ package bedrockagentcore_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "os" "os/exec" @@ -18,6 +18,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockagentcore" ) @@ -160,7 +161,7 @@ func invokeRuntime( ) (map[string]any, *sdk.InvokeAgentRuntimeOutput) { t.Helper() - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) require.NoError(t, err) out, err := f.client.InvokeAgentRuntime(t.Context(), &sdk.InvokeAgentRuntimeInput{ @@ -179,7 +180,7 @@ func invokeRuntime( require.NoError(t, err) var got map[string]any - if json.Unmarshal(raw, &got) != nil { + if json.Unmarshal(raw, &got, jsonx.V1()) != nil { got = map[string]any{"raw": string(raw)} } diff --git a/services/bedrockagentcore/wire.go b/services/bedrockagentcore/wire.go index ba58c28172..47c7359f85 100644 --- a/services/bedrockagentcore/wire.go +++ b/services/bedrockagentcore/wire.go @@ -2,7 +2,7 @@ package bedrockagentcore import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -127,7 +128,7 @@ func sortedKeys[V any](m map[string]V) []string { } func mustJSON(v any) []byte { - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return b } @@ -147,7 +148,7 @@ func readJSONBody(r *http.Request) (doc, error) { return d, nil } - if err = json.Unmarshal(body, &d); err != nil { + if err = json.Unmarshal(body, &d, jsonx.V1()); err != nil { return nil, invalid("request body is not valid JSON") } diff --git a/services/bedrockagentcorecontrol/dataplane.go b/services/bedrockagentcorecontrol/dataplane.go index 0f69f344aa..d00aeb6c19 100644 --- a/services/bedrockagentcorecontrol/dataplane.go +++ b/services/bedrockagentcorecontrol/dataplane.go @@ -1,8 +1,9 @@ package bedrockagentcorecontrol import ( - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" dataplane "github.com/blackbirdworks/gopherstack/services/bedrockagentcore" ) @@ -178,7 +179,7 @@ func (d dataSeam) SecretValue(arn, jsonKey string) (string, bool) { } var fields map[string]any - if err := json.Unmarshal([]byte(raw), &fields); err != nil { + if err := json.Unmarshal([]byte(raw), &fields, jsonx.V1()); err != nil { return raw, true } @@ -193,7 +194,7 @@ func (d dataSeam) SecretValue(arn, jsonKey string) (string, bool) { } func mustMarshal(v any) []byte { - out, _ := json.Marshal(v) + out, _ := json.Marshal(v, jsonx.V1()) return out } diff --git a/services/bedrockagentcorecontrol/dataplane_test.go b/services/bedrockagentcorecontrol/dataplane_test.go index 3dfb588665..1cc556d4b1 100644 --- a/services/bedrockagentcorecontrol/dataplane_test.go +++ b/services/bedrockagentcorecontrol/dataplane_test.go @@ -1,7 +1,7 @@ package bedrockagentcorecontrol_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" dataplane "github.com/blackbirdworks/gopherstack/services/bedrockagentcore" ) @@ -98,7 +99,7 @@ func TestCredentialProviders_StoreRealSecrets(t *testing.T) { assert.Contains(t, arn, ":secret:bedrock-agentcore-identity-default/apikey/vendor/apiKey") var payload map[string]string - require.NoError(t, json.Unmarshal([]byte(store.values[arn]), &payload)) + require.NoError(t, json.Unmarshal([]byte(store.values[arn]), &payload, jsonx.V1())) assert.Equal(t, "sk-1", payload["apiKey"], "the key is stored, not discarded") info, ok := seam.Provider(dpScope(), dataplane.ProviderAPIKey, "vendor") diff --git a/services/bedrockagentcorecontrol/engine.go b/services/bedrockagentcorecontrol/engine.go index f9894ffb4c..7d7604a858 100644 --- a/services/bedrockagentcorecontrol/engine.go +++ b/services/bedrockagentcorecontrol/engine.go @@ -2,7 +2,7 @@ package bedrockagentcorecontrol import ( "cmp" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "slices" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -511,7 +512,7 @@ func (b *InMemoryBackend) matches(r *Resource, sp *opSpec, in args) bool { return false } case "targetResourceScope": - raw, _ := json.Marshal(r.Doc["definition"]) + raw, _ := json.Marshal(r.Doc["definition"], jsonx.V1()) if !strings.Contains(string(raw), want) { return false } diff --git a/services/bedrockagentcorecontrol/hooks_data.go b/services/bedrockagentcorecontrol/hooks_data.go index 8b435d6b24..5f340f4857 100644 --- a/services/bedrockagentcorecontrol/hooks_data.go +++ b/services/bedrockagentcorecontrol/hooks_data.go @@ -3,7 +3,7 @@ package bedrockagentcorecontrol import ( "bufio" "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -11,6 +11,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -122,7 +123,7 @@ func (b *InMemoryBackend) loadExamples(source map[string]any) ([]any, string) { } var m any - if err := json.Unmarshal([]byte(line), &m); err != nil { + if err := json.Unmarshal([]byte(line), &m, jsonx.V1()); err != nil { return nil, fmt.Sprintf("line %d of the S3 object is not valid JSON", len(out)+1) } diff --git a/services/bedrockagentcorecontrol/hooks_policy.go b/services/bedrockagentcorecontrol/hooks_policy.go index 8e378dd0bb..bbf6f3daa4 100644 --- a/services/bedrockagentcorecontrol/hooks_policy.go +++ b/services/bedrockagentcorecontrol/hooks_policy.go @@ -1,7 +1,7 @@ package bedrockagentcorecontrol import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -310,7 +311,7 @@ func (b *InMemoryBackend) managedSecret(sc scope, kind, name, member string, val return b.managedSecretARN(sc, kind, name, member) } - payload, _ := json.Marshal(map[string]string{member: text}) + payload, _ := json.Marshal(map[string]string{member: text}, jsonx.V1()) secretName := fmt.Sprintf("%s%s/%s/%s", managedSecretName, kind, name, member) if secretARN, err := st.PutSecret(sc.account, sc.region, secretName, string(payload)); err == nil { diff --git a/services/bedrockagentcorecontrol/ops_special.go b/services/bedrockagentcorecontrol/ops_special.go index 2a60d73592..719f58f645 100644 --- a/services/bedrockagentcorecontrol/ops_special.go +++ b/services/bedrockagentcorecontrol/ops_special.go @@ -1,12 +1,13 @@ package bedrockagentcorecontrol import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "slices" "strconv" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -469,7 +470,7 @@ func (b *InMemoryBackend) putResourcePolicy(sc scope, in args) (*reply, error) { var parsed struct { Statement any `json:"Statement"` } - if err := json.Unmarshal([]byte(doc), &parsed); err != nil || parsed.Statement == nil { + if err := json.Unmarshal([]byte(doc), &parsed, jsonx.V1()); err != nil || parsed.Statement == nil { return nil, invalid("policy must be a JSON policy document with a Statement") } diff --git a/services/bedrockagentcorecontrol/persistence.go b/services/bedrockagentcorecontrol/persistence.go index d447b04922..da12c5b5a9 100644 --- a/services/bedrockagentcorecontrol/persistence.go +++ b/services/bedrockagentcorecontrol/persistence.go @@ -2,7 +2,7 @@ package bedrockagentcorecontrol import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/bedrockagentcorecontrol/spec.go b/services/bedrockagentcorecontrol/spec.go index 4f8ba89c7c..6a38841680 100644 --- a/services/bedrockagentcorecontrol/spec.go +++ b/services/bedrockagentcorecontrol/spec.go @@ -2,12 +2,13 @@ package bedrockagentcorecontrol import ( _ "embed" // opsJSON - "encoding/json" + "encoding/json/v2" "slices" "sort" "strings" "sync" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -41,7 +42,7 @@ type specFile struct { var specs = sync.OnceValue(func() map[string]*opSpec { //nolint:gochecknoglobals // immutable embedded spec var f specFile - if err := json.Unmarshal(opsJSON, &f); err != nil { + if err := json.Unmarshal(opsJSON, &f, jsonx.V1()); err != nil { panic("bedrockagentcorecontrol: corrupt ops.json: " + err.Error()) } diff --git a/services/bedrockruntime/converse_validation.go b/services/bedrockruntime/converse_validation.go index f73659e973..69e7b5db0c 100644 --- a/services/bedrockruntime/converse_validation.go +++ b/services/bedrockruntime/converse_validation.go @@ -1,11 +1,14 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxRequestMetadataEntries = 16 @@ -47,13 +50,13 @@ func validateRequestMetadata(md map[string]string) string { // validateGuardrailConfig applies the patterns in API_runtime_GuardrailConfiguration.html and // API_runtime_GuardrailStreamConfiguration.html. -func validateGuardrailConfig(raw json.RawMessage) string { +func validateGuardrailConfig(raw jsontext.Value) string { if len(raw) == 0 { return "" } var gc guardrailConfigBody - if json.Unmarshal(raw, &gc) != nil { + if json.Unmarshal(raw, &gc, jsonx.V1()) != nil { return "" } @@ -135,13 +138,13 @@ type inferenceConfigBody struct { } // validateInferenceConfig applies the InferenceConfiguration bounds. -func validateInferenceConfig(raw json.RawMessage) string { +func validateInferenceConfig(raw jsontext.Value) string { if len(raw) == 0 { return "" } var ic inferenceConfigBody - if json.Unmarshal(raw, &ic) != nil { + if json.Unmarshal(raw, &ic, jsonx.V1()) != nil { return "" } @@ -162,11 +165,11 @@ func validateInferenceConfig(raw json.RawMessage) string { } type toolConfigBody struct { - ToolChoice map[string]json.RawMessage `json:"toolChoice"` + ToolChoice map[string]jsontext.Value `json:"toolChoice"` Tools []struct { ToolSpec *struct { - Name string `json:"name"` - InputSchema json.RawMessage `json:"inputSchema"` + Name string `json:"name"` + InputSchema jsontext.Value `json:"inputSchema"` } `json:"toolSpec"` } `json:"tools"` } @@ -177,13 +180,13 @@ type specificToolChoice struct { // validateToolConfig applies the ToolConfiguration shape: at least one tool, valid tool names, // a single-member toolChoice union, and a specific choice that names a declared tool. -func validateToolConfig(raw json.RawMessage) string { +func validateToolConfig(raw jsontext.Value) string { if len(raw) == 0 { return "" } var tc toolConfigBody - if json.Unmarshal(raw, &tc) != nil { + if json.Unmarshal(raw, &tc, jsonx.V1()) != nil { return "" } @@ -212,7 +215,7 @@ func validateToolConfig(raw json.RawMessage) string { return validateToolChoice(tc.ToolChoice, names) } -func validateToolChoice(choice map[string]json.RawMessage, declared map[string]bool) string { +func validateToolChoice(choice map[string]jsontext.Value, declared map[string]bool) string { if len(choice) == 0 { return "" } @@ -223,7 +226,7 @@ func validateToolChoice(choice map[string]json.RawMessage, declared map[string]b if raw, ok := choice["tool"]; ok { var st specificToolChoice - if json.Unmarshal(raw, &st) == nil && !declared[st.Name] { + if json.Unmarshal(raw, &st, jsonx.V1()) == nil && !declared[st.Name] { return "toolConfig.toolChoice.tool.name " + st.Name + " does not match a declared tool" } diff --git a/services/bedrockruntime/eventstream_test.go b/services/bedrockruntime/eventstream_test.go index 97963a5f27..891db74db0 100644 --- a/services/bedrockruntime/eventstream_test.go +++ b/services/bedrockruntime/eventstream_test.go @@ -2,12 +2,14 @@ package bedrockruntime_test import ( "encoding/binary" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseEventStreamFrames splits a raw binary event stream body into decoded @@ -41,7 +43,7 @@ func parseEventStreamFrames(data []byte) []map[string]any { if len(payload) > 0 { var m map[string]any - if err := json.Unmarshal(payload, &m); err == nil { + if err := json.Unmarshal(payload, &m, jsonx.V1()); err == nil { frames = append(frames, m) } } diff --git a/services/bedrockruntime/guardrail_lookup.go b/services/bedrockruntime/guardrail_lookup.go index ef4fd80fbf..c15692b1be 100644 --- a/services/bedrockruntime/guardrail_lookup.go +++ b/services/bedrockruntime/guardrail_lookup.go @@ -1,12 +1,14 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/bedrock" ) @@ -94,7 +96,7 @@ func (b *InMemoryBackend) inheritGuardrailLookup(home *InMemoryBackend) { // converseGuardrailMissing writes ResourceNotFoundException when the request's guardrailConfig // references a guardrail that is not registered; the bool reports whether a response was written. -func (h *Handler) converseGuardrailMissing(c *echo.Context, raw json.RawMessage) (bool, error) { +func (h *Handler) converseGuardrailMissing(c *echo.Context, raw jsontext.Value) (bool, error) { if len(raw) == 0 { return false, nil } @@ -123,8 +125,8 @@ func (h *Handler) invokeGuardrailMissing(c *echo.Context) (bool, error) { return true, writeGuardrailNotFound(c, id, version) } -func parseGuardrailConfig(raw json.RawMessage) (guardrailConfigBody, bool) { +func parseGuardrailConfig(raw jsontext.Value) (guardrailConfigBody, bool) { var gc guardrailConfigBody - return gc, json.Unmarshal(raw, &gc) == nil + return gc, json.Unmarshal(raw, &gc, jsonx.V1()) == nil } diff --git a/services/bedrockruntime/handler_async_invoke.go b/services/bedrockruntime/handler_async_invoke.go index be87d60795..5132b16c15 100644 --- a/services/bedrockruntime/handler_async_invoke.go +++ b/services/bedrockruntime/handler_async_invoke.go @@ -1,7 +1,8 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strconv" @@ -12,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // startAsyncInvokeInput is the parsed request body for StartAsyncInvoke. @@ -28,16 +30,16 @@ type startAsyncInvokeInput struct { S3URI string `json:"s3Uri"` } `json:"s3OutputDataConfig"` } `json:"outputDataConfig"` - ModelID string `json:"modelId"` - ClientRequestToken string `json:"clientRequestToken"` - ModelInput json.RawMessage `json:"modelInput"` + ModelID string `json:"modelId"` + ClientRequestToken string `json:"clientRequestToken"` + ModelInput jsontext.Value `json:"modelInput"` } // handleStartAsyncInvoke handles POST /async-invoke. func (h *Handler) handleStartAsyncInvoke(c *echo.Context, body []byte) error { var req startAsyncInvokeInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid request body")) } diff --git a/services/bedrockruntime/handler_async_invoke_test.go b/services/bedrockruntime/handler_async_invoke_test.go index 7aa907fdc8..22d1cb298f 100644 --- a/services/bedrockruntime/handler_async_invoke_test.go +++ b/services/bedrockruntime/handler_async_invoke_test.go @@ -2,7 +2,7 @@ package bedrockruntime_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockruntime" ) @@ -76,7 +77,7 @@ func TestHandler_StartAsyncInvoke(t *testing.T) { assert.Equal(t, http.StatusAccepted, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "invocationArn") assert.NotEmpty(t, out["invocationArn"]) }) @@ -101,7 +102,7 @@ func TestHandler_StartAsyncInvoke_MissingS3URI(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "__type") } @@ -123,7 +124,7 @@ func TestHandler_StartAsyncInvoke_WithTags(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut, jsonx.V1())) invocationArn := startOut["invocationArn"].(string) getPath := "/async-invoke/" + url.PathEscape(invocationArn) @@ -131,7 +132,7 @@ func TestHandler_StartAsyncInvoke_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.NotContains( t, getOut, "tags", "neither GetAsyncInvokeOutput nor AsyncInvokeSummary has a tags member; "+ @@ -230,7 +231,7 @@ func TestStartAsyncInvoke_ModelIDAsInferenceProfileARN(t *testing.T) { assert.Equal(t, http.StatusAccepted, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["invocationArn"]) } @@ -318,7 +319,7 @@ func TestHandler_GetAsyncInvoke(t *testing.T) { require.Equal(t, http.StatusAccepted, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) invocationArn := startOut["invocationArn"].(string) getPath := "/async-invoke/" + url.PathEscape(invocationArn) @@ -327,7 +328,7 @@ func TestHandler_GetAsyncInvoke(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, invocationArn, out["invocationArn"]) assert.Contains(t, out, "modelArn") assert.Contains(t, out, "status") @@ -362,7 +363,7 @@ func TestHandler_GetAsyncInvoke_FullFields(t *testing.T) { require.Equal(t, http.StatusAccepted, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) invocationArn := startOut["invocationArn"].(string) getPath := "/async-invoke/" + url.PathEscape(invocationArn) @@ -371,7 +372,7 @@ func TestHandler_GetAsyncInvoke_FullFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "clientRequestToken") assert.Equal(t, "my-idempotency-token", out["clientRequestToken"]) assert.NotContains( @@ -423,14 +424,14 @@ func TestAsyncInvoke_GetResponseShape(t *testing.T) { require.Equal(t, http.StatusAccepted, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) arn := createOut["invocationArn"].(string) recGet := doRequest(t, h, http.MethodGet, "/async-invoke/"+arn, nil) require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, arn, out["invocationArn"]) assert.Contains(t, out["modelArn"].(string), tt.modelID) assert.Equal(t, "InProgress", out["status"]) @@ -501,7 +502,7 @@ func TestHandler_ListAsyncInvokes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "asyncInvokeSummaries") summaries, ok := out["asyncInvokeSummaries"].([]any) @@ -568,7 +569,7 @@ func TestHandler_ListAsyncInvokes_StatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["asyncInvokeSummaries"].([]any) require.True(t, ok) @@ -595,7 +596,7 @@ func TestHandler_ListAsyncInvokes_WithClientToken(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["asyncInvokeSummaries"].([]any) require.True(t, ok) @@ -613,7 +614,7 @@ func TestListAsyncInvokes_EmptyList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) invokes, ok := out["asyncInvokeSummaries"].([]any) require.True(t, ok) assert.Empty(t, invokes) @@ -664,7 +665,7 @@ func TestListAsyncInvokes_AfterCreate(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) invokes := out["asyncInvokeSummaries"].([]any) assert.Len(t, invokes, tt.wantLen) diff --git a/services/bedrockruntime/handler_converse.go b/services/bedrockruntime/handler_converse.go index 8cdd4c9fa8..148a997961 100644 --- a/services/bedrockruntime/handler_converse.go +++ b/services/bedrockruntime/handler_converse.go @@ -1,10 +1,13 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // converseMessage represents a single message in a Converse request. @@ -25,9 +28,9 @@ type converseRequest struct { PerformanceConfig *performanceConfigBody `json:"performanceConfig,omitempty"` Messages []converseMessage `json:"messages"` System []converseContent `json:"system,omitempty"` - ToolConfig json.RawMessage `json:"toolConfig,omitempty"` - GuardrailConfig json.RawMessage `json:"guardrailConfig,omitempty"` - InferenceConfig json.RawMessage `json:"inferenceConfig,omitempty"` + ToolConfig jsontext.Value `json:"toolConfig,omitempty"` + GuardrailConfig jsontext.Value `json:"guardrailConfig,omitempty"` + InferenceConfig jsontext.Value `json:"inferenceConfig,omitempty"` } type serviceTierBody struct { @@ -133,7 +136,7 @@ func (h *Handler) handleConverse( ) error { var req converseRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if msg := validateConverseConfig(&req); msg != "" { @@ -151,7 +154,7 @@ func (h *Handler) handleConverse( resp := buildConverseResponse(&req) echoConverseConfig(resp, &req) - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -173,7 +176,7 @@ func (h *Handler) handleConverseStream( ) error { var req converseRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if msg := validateConverseConfig(&req); msg != "" { @@ -191,7 +194,7 @@ func (h *Handler) handleConverseStream( inputTokens := estimateTokensFromMessages(req.Messages, req.System) respSummary := buildConverseResponse(&req) - out, err := json.Marshal(respSummary) + out, err := json.Marshal(respSummary, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -202,7 +205,7 @@ func (h *Handler) handleConverseStream( c.Response().WriteHeader(http.StatusOK) writeStreamEvent := func(eventType string, payload any) { - data, merr := json.Marshal(payload) + data, merr := json.Marshal(payload, jsonx.V1()) if merr != nil { return } diff --git a/services/bedrockruntime/handler_converse_test.go b/services/bedrockruntime/handler_converse_test.go index d2455a7554..b2d64cef13 100644 --- a/services/bedrockruntime/handler_converse_test.go +++ b/services/bedrockruntime/handler_converse_test.go @@ -2,7 +2,7 @@ package bedrockruntime_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Converse tests --- @@ -52,7 +54,7 @@ func TestHandler_Converse(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "output") assert.Contains(t, out, "stopReason") @@ -87,7 +89,7 @@ func TestConverse_ReflectsInputTokens(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) usage, ok := out["usage"].(map[string]any) require.True(t, ok) @@ -118,7 +120,7 @@ func TestConverse_WithSystem(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "output") assert.Contains(t, out, "stopReason") assert.Contains(t, out, "usage") @@ -158,7 +160,7 @@ func TestConverse_ResponseFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, tt.wantKey) assert.Contains(t, out, "usage") assert.Contains(t, out, "stopReason") @@ -201,7 +203,7 @@ func TestConverse_WithSystemMessages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "output") }) } @@ -222,7 +224,7 @@ func TestConverse_StopReasonEndTurn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "end_turn", out["stopReason"]) } @@ -252,7 +254,7 @@ func TestConverse_WithToolConfig_ReturnsEndTurn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "end_turn", out["stopReason"]) assert.Contains(t, out, "output") assert.Contains(t, out, "usage") @@ -284,7 +286,7 @@ func TestConverse_MultiTurnMessages_AccumulatesTokens(t *testing.T) { extractInputTokens := func(body []byte) float64 { var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) usage := out["usage"].(map[string]any) return usage["inputTokens"].(float64) diff --git a/services/bedrockruntime/handler_count_tokens_test.go b/services/bedrockruntime/handler_count_tokens_test.go index 04f62b2c86..a0bd829f5f 100644 --- a/services/bedrockruntime/handler_count_tokens_test.go +++ b/services/bedrockruntime/handler_count_tokens_test.go @@ -1,13 +1,15 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // countTokensInvokeModelBody builds a real CountTokens request body wrapping @@ -68,7 +70,7 @@ func TestHandler_CountTokens(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "inputTokens") invocations := h.Backend.ListInvocations() @@ -121,7 +123,7 @@ func TestHandler_CountTokens_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.InDelta(t, tt.wantTokens, out["inputTokens"], 0) }) } @@ -149,8 +151,8 @@ func TestCountTokens_ReflectsInputLength(t *testing.T) { require.Equal(t, http.StatusOK, recLong.Code) var shortOut, longOut map[string]any - require.NoError(t, json.Unmarshal(recShort.Body.Bytes(), &shortOut)) - require.NoError(t, json.Unmarshal(recLong.Body.Bytes(), &longOut)) + require.NoError(t, json.Unmarshal(recShort.Body.Bytes(), &shortOut, jsonx.V1())) + require.NoError(t, json.Unmarshal(recLong.Body.Bytes(), &longOut, jsonx.V1())) shortTokens := shortOut["inputTokens"].(float64) longTokens := longOut["inputTokens"].(float64) @@ -175,8 +177,8 @@ func TestCountTokens_TitanUsesLargerDivisor(t *testing.T) { require.Equal(t, http.StatusOK, recTitan.Code) var claudeOut, titanOut map[string]any - require.NoError(t, json.Unmarshal(recClaude.Body.Bytes(), &claudeOut)) - require.NoError(t, json.Unmarshal(recTitan.Body.Bytes(), &titanOut)) + require.NoError(t, json.Unmarshal(recClaude.Body.Bytes(), &claudeOut, jsonx.V1())) + require.NoError(t, json.Unmarshal(recTitan.Body.Bytes(), &titanOut, jsonx.V1())) claudeTokens := claudeOut["inputTokens"].(float64) titanTokens := titanOut["inputTokens"].(float64) @@ -221,7 +223,7 @@ func TestCountTokens_MultipleModelFamilies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) count, ok := out["inputTokens"].(float64) require.True(t, ok, "inputTokens should be a number") assert.GreaterOrEqual(t, int(count), tt.minCount) @@ -245,8 +247,8 @@ func TestCountTokens_TitanUsesHigherDivisor(t *testing.T) { require.Equal(t, http.StatusOK, recTitan.Code) var claudeOut, titanOut map[string]any - require.NoError(t, json.Unmarshal(recClaude.Body.Bytes(), &claudeOut)) - require.NoError(t, json.Unmarshal(recTitan.Body.Bytes(), &titanOut)) + require.NoError(t, json.Unmarshal(recClaude.Body.Bytes(), &claudeOut, jsonx.V1())) + require.NoError(t, json.Unmarshal(recTitan.Body.Bytes(), &titanOut, jsonx.V1())) claudeTokens := claudeOut["inputTokens"].(float64) titanTokens := titanOut["inputTokens"].(float64) @@ -289,7 +291,7 @@ func TestCountTokens_MultiMessageBody(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) count := out["inputTokens"].(float64) assert.GreaterOrEqual(t, int(count), tt.minCount) }) diff --git a/services/bedrockruntime/handler_guardrail_checks.go b/services/bedrockruntime/handler_guardrail_checks.go index 2dadced9a4..8f1a6f790f 100644 --- a/services/bedrockruntime/handler_guardrail_checks.go +++ b/services/bedrockruntime/handler_guardrail_checks.go @@ -1,7 +1,7 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "strconv" @@ -9,6 +9,8 @@ import ( "unicode/utf8" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- InvokeGuardrailChecks (POST /guardrail-checks/invoke) --- @@ -162,7 +164,7 @@ type guardrailChecksTextUnitsResponse struct { func (h *Handler) handleInvokeGuardrailChecks(c *echo.Context, body []byte) error { var req invokeGuardrailChecksRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid request body")) } } @@ -204,7 +206,7 @@ func (h *Handler) handleInvokeGuardrailChecks(c *echo.Context, body []byte) erro "usage": usage, } - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } diff --git a/services/bedrockruntime/handler_guardrails.go b/services/bedrockruntime/handler_guardrails.go index 098b783e69..936e301114 100644 --- a/services/bedrockruntime/handler_guardrails.go +++ b/services/bedrockruntime/handler_guardrails.go @@ -1,11 +1,13 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // applyGuardrailRequest represents the parsed ApplyGuardrail request body. @@ -158,7 +160,7 @@ func (h *Handler) handleApplyGuardrail( var req applyGuardrailRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if msg := validateApplyGuardrail(&req); msg != "" { @@ -185,7 +187,7 @@ func (h *Handler) handleApplyGuardrail( }, } - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } diff --git a/services/bedrockruntime/handler_guardrails_test.go b/services/bedrockruntime/handler_guardrails_test.go index be49d951e1..8838c9d15a 100644 --- a/services/bedrockruntime/handler_guardrails_test.go +++ b/services/bedrockruntime/handler_guardrails_test.go @@ -1,12 +1,14 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- ApplyGuardrail tests --- @@ -51,7 +53,7 @@ func TestHandler_ApplyGuardrail(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "action") assert.Contains(t, out, "assessments") assert.Contains(t, out, "outputs") @@ -124,7 +126,7 @@ func TestApplyGuardrail_NoneForSafeContent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "NONE", out["action"]) } @@ -143,7 +145,7 @@ func TestApplyGuardrail_BlockedForHarmfulContent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "GUARDRAIL_INTERVENED", out["action"]) } @@ -162,7 +164,7 @@ func TestApplyGuardrail_BlockedForToxicContent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "GUARDRAIL_INTERVENED", out["action"]) } @@ -182,7 +184,7 @@ func TestApplyGuardrail_OutputsReflectsInput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) outputs, ok := out["outputs"].([]any) require.True(t, ok) @@ -231,7 +233,7 @@ func TestApplyGuardrail_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantAction, out["action"]) assert.Contains(t, out, "outputs") assert.Contains(t, out, "usage") @@ -269,7 +271,7 @@ func TestApplyGuardrail_OutputsMirrorInput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) outputs := out["outputs"].([]any) assert.Len(t, outputs, tt.wantLen) @@ -296,7 +298,7 @@ func TestApplyGuardrail_AssessmentsReflectBlockedMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Equal(t, "GUARDRAIL_INTERVENED", out["action"]) assessments, ok := out["assessments"].([]any) @@ -335,7 +337,7 @@ func TestApplyGuardrail_AssessmentsEmptyForNoneAction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Equal(t, "NONE", out["action"]) assessments, ok := out["assessments"].([]any) @@ -453,7 +455,7 @@ func TestHandler_InvokeGuardrailChecks(t *testing.T) { } var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "results") assert.Contains(t, out, "usage") }) @@ -486,7 +488,7 @@ func TestInvokeGuardrailChecks_ContentFilterNeverFabricatesSeverityScore(t *test require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) results, ok := out["results"].(map[string]any) require.True(t, ok) @@ -557,7 +559,7 @@ func TestInvokeGuardrailChecks_SensitiveInformation_RealRegexDetection(t *testin require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) results := out["results"].(map[string]any) sensitive := results["sensitiveInformation"].(map[string]any) diff --git a/services/bedrockruntime/handler_invoke.go b/services/bedrockruntime/handler_invoke.go index 3570170162..0b65c44c3b 100644 --- a/services/bedrockruntime/handler_invoke.go +++ b/services/bedrockruntime/handler_invoke.go @@ -2,12 +2,14 @@ package bedrockruntime import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Request/response header names used by the InvokeModel family (see @@ -147,7 +149,7 @@ func modelResponsePayloadPart(out []byte) []byte { part := map[string]string{"bytes": base64.StdEncoding.EncodeToString(out)} // Marshaling a map[string]string with one entry never fails. - b, _ := json.Marshal(part) + b, _ := json.Marshal(part, jsonx.V1()) return b } @@ -177,7 +179,7 @@ func (h *Handler) handleInvokeModel( resp := mockInvokeModelResponse(modelID) - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -234,7 +236,7 @@ func (h *Handler) handleInvokeModelWithResponseStream( resp := mockInvokeModelResponse(modelID) - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -271,7 +273,7 @@ func (h *Handler) handleInvokeModelWithBidirectionalStream( ) error { resp := mockInvokeModelResponse(modelID) - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -341,7 +343,7 @@ func estimateTokenCount(body []byte, modelID string) int { } var req countTokensRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return max(1, len(body)/charsPerToken) } @@ -392,7 +394,7 @@ func (h *Handler) handleCountTokens( keyInputTokens: inputTokens, } - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } diff --git a/services/bedrockruntime/handler_invoke_test.go b/services/bedrockruntime/handler_invoke_test.go index 7a59e9d61c..ef972f0fbf 100644 --- a/services/bedrockruntime/handler_invoke_test.go +++ b/services/bedrockruntime/handler_invoke_test.go @@ -3,7 +3,7 @@ package bedrockruntime_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- InvokeModel tests --- @@ -60,7 +62,7 @@ func TestHandler_InvokeModel(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, tt.wantKey) invocations := h.Backend.ListInvocations() @@ -107,7 +109,7 @@ func TestHandler_InvokeModel_ModelFamilies(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, tt.wantKey) }) } @@ -160,7 +162,7 @@ func TestInvokeModel_AcceptHeader_JSON(t *testing.T) { t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -180,7 +182,7 @@ func TestInvokeModel_AcceptHeader_Wildcard(t *testing.T) { t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -342,7 +344,7 @@ func TestInvocationTruncation(t *testing.T) { largePrompt[i] = 'x' } - body, _ := json.Marshal(map[string]any{"prompt": string(largePrompt)}) + body, _ := json.Marshal(map[string]any{"prompt": string(largePrompt)}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -391,7 +393,7 @@ func TestInvokeModel_Claude3_MessagesAPIFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Messages API format fields (not Claude 2 `completion` field) assert.Contains(t, out, "id", "Claude 3 response must include 'id' field") @@ -439,7 +441,7 @@ func TestInvokeModel_Claude2_LegacyCompletionFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Legacy completion format assert.Contains(t, out, "completion", "Claude 2 response must use legacy 'completion' field") @@ -478,7 +480,7 @@ func TestInvokeModel_ARNModelIDWithEmbeddedSlash(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Claude 3 Messages API format fields (not the legacy `completion` field // that the truncated-ARN bug would have produced). @@ -579,7 +581,7 @@ func TestInvokeModelWithResponseStream_ChunkPayloadIsBase64WrappedBytes(t *testi require.NoError(t, err) var modelResp map[string]any - require.NoError(t, json.Unmarshal(decoded, &modelResp)) + require.NoError(t, json.Unmarshal(decoded, &modelResp, jsonx.V1())) assert.Equal(t, "end_turn", modelResp["stop_reason"]) assert.Equal(t, "This is a mock response from Gopherstack.", modelResp["completion"]) } @@ -614,7 +616,7 @@ func TestInvokeModel_GuardrailIdentifierWithoutVersion_Returns400(t *testing.T) t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -629,7 +631,7 @@ func TestInvokeModel_GuardrailIdentifierWithoutVersion_Returns400(t *testing.T) assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ValidationException", out["__type"]) } @@ -637,7 +639,7 @@ func TestInvokeModel_GuardrailIdentifierWithVersion_Succeeds(t *testing.T) { t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -657,7 +659,7 @@ func TestInvokeModelWithResponseStream_GuardrailIdentifierWithoutVersion_Returns t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest( @@ -680,7 +682,7 @@ func TestInvokeModel_PerformanceConfigLatency_EchoedInResponse(t *testing.T) { t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/model/anthropic.claude-v2/invoke", bytes.NewReader(body)) @@ -711,7 +713,7 @@ func TestInvokeModelWithResponseStream_PerformanceConfigLatency_EchoedInResponse t.Parallel() h := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"prompt": "Hello"}) + body, _ := json.Marshal(map[string]any{"prompt": "Hello"}, jsonx.V1()) e := echo.New() req := httptest.NewRequest( diff --git a/services/bedrockruntime/handler_list_async_invokes_filters_test.go b/services/bedrockruntime/handler_list_async_invokes_filters_test.go index 7a426a43ff..cf64a4537c 100644 --- a/services/bedrockruntime/handler_list_async_invokes_filters_test.go +++ b/services/bedrockruntime/handler_list_async_invokes_filters_test.go @@ -1,7 +1,7 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func startAsyncInvokeBody(i int) map[string]any { @@ -71,7 +73,7 @@ func TestHandler_ListAsyncInvokes_SubmitTimeFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["asyncInvokeSummaries"].([]any) require.True(t, ok) @@ -93,7 +95,7 @@ func TestHandler_ListAsyncInvokes_SortOrder(t *testing.T) { require.Equal(t, http.StatusAccepted, rec1.Code) var firstBody map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &firstBody)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &firstBody, jsonx.V1())) firstARN, ok := firstBody["invocationArn"].(string) require.True(t, ok) @@ -103,7 +105,7 @@ func TestHandler_ListAsyncInvokes_SortOrder(t *testing.T) { require.Equal(t, http.StatusAccepted, rec2.Code) var secondBody map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &secondBody)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &secondBody, jsonx.V1())) secondARN, ok := secondBody["invocationArn"].(string) require.True(t, ok) @@ -111,7 +113,7 @@ func TestHandler_ListAsyncInvokes_SortOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["asyncInvokeSummaries"].([]any) require.True(t, ok) diff --git a/services/bedrockruntime/handler_sdk_route_table_test.go b/services/bedrockruntime/handler_sdk_route_table_test.go index c419ca717e..e371c8e2ae 100644 --- a/services/bedrockruntime/handler_sdk_route_table_test.go +++ b/services/bedrockruntime/handler_sdk_route_table_test.go @@ -1,7 +1,7 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sdkRouteCases is the authoritative method+path for every real Bedrock @@ -97,7 +99,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var decoded struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded, jsonx.V1())) assert.NotEqual(t, "UnknownOperationException", decoded.Type, "method=%s path=%s op=%s: dispatched to the unmatched-route default", tc.method, tc.path, tc.op) } diff --git a/services/bedrockruntime/handler_test.go b/services/bedrockruntime/handler_test.go index afca33582c..d5d9c0c61b 100644 --- a/services/bedrockruntime/handler_test.go +++ b/services/bedrockruntime/handler_test.go @@ -2,7 +2,7 @@ package bedrockruntime_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/bedrockruntime" ) @@ -34,7 +35,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/bedrockruntime/janitor_interval_test.go b/services/bedrockruntime/janitor_interval_test.go index 68f10b209c..ee17b67cf0 100644 --- a/services/bedrockruntime/janitor_interval_test.go +++ b/services/bedrockruntime/janitor_interval_test.go @@ -2,7 +2,7 @@ package bedrockruntime_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/bedrockruntime" ) @@ -44,7 +45,7 @@ func TestStartWorker_AdvancesAsyncInvoke_NearCompletionDelay(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var started map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) arn, ok := started["invocationArn"].(string) require.True(t, ok) @@ -57,7 +58,7 @@ func TestStartWorker_AdvancesAsyncInvoke_NearCompletionDelay(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, bedrockruntime.AsyncInvokeStatusCompleted, got["status"]) }) diff --git a/services/bedrockruntime/ollama_backend_test.go b/services/bedrockruntime/ollama_backend_test.go index 7f9416e617..3680e2d514 100644 --- a/services/bedrockruntime/ollama_backend_test.go +++ b/services/bedrockruntime/ollama_backend_test.go @@ -1,7 +1,8 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "maps" @@ -22,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/bedrockruntime" @@ -93,7 +95,7 @@ func newFakeOllama(t *testing.T, reply func(path string, req map[string]any) fak srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { raw, _ := io.ReadAll(r.Body) var req map[string]any - _ = json.Unmarshal(raw, &req) + _ = json.Unmarshal(raw, &req, jsonx.V1()) rec.mu.Lock() rec.reqs = append(rec.reqs, req) rec.path = append(rec.path, r.URL.Path) @@ -102,20 +104,20 @@ func newFakeOllama(t *testing.T, reply func(path string, req map[string]any) fak rp := reply(r.URL.Path, req) if rp.status != 0 { w.WriteHeader(rp.status) - _ = json.NewEncoder(w).Encode(map[string]string{"error": rp.errMsg}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{"error": rp.errMsg}) return } w.Header().Set("Content-Type", "application/x-ndjson") - enc := json.NewEncoder(w) + enc := jsontext.NewEncoder(w, jsonx.V1()) if stream, _ := req["stream"].(bool); !stream { - _ = enc.Encode(collapse(rp.lines)) + _ = json.MarshalEncode(enc, collapse(rp.lines)) return } for _, l := range rp.lines { - _ = enc.Encode(l) + _ = json.MarshalEncode(enc, l) if f, ok := w.(http.Flusher); ok { f.Flush() } @@ -734,7 +736,7 @@ func TestOllamaBackend_InvokeModel(t *testing.T) { assert.Equal(t, tc.wantPath, path) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body, &out)) + require.NoError(t, json.Unmarshal(resp.Body, &out, jsonx.V1())) tc.check(t, req, out) }) } @@ -849,7 +851,7 @@ func TestOllamaBackend_InvokeModelStream(t *testing.T) { part, ok := ev.(*types.ResponseStreamMemberChunk) require.True(t, ok, "unexpected event %T", ev) var m map[string]any - require.NoError(t, json.Unmarshal(part.Value.Bytes, &m)) + require.NoError(t, json.Unmarshal(part.Value.Bytes, &m, jsonx.V1())) chunks = append(chunks, m) } require.NoError(t, stream.Err()) diff --git a/services/bedrockruntime/ollama_client.go b/services/bedrockruntime/ollama_client.go index c4c5f3367f..c4043853a4 100644 --- a/services/bedrockruntime/ollama_client.go +++ b/services/bedrockruntime/ollama_client.go @@ -3,12 +3,15 @@ package bedrockruntime import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxOllamaErrBody = 4096 @@ -22,10 +25,10 @@ type ollamaOptions struct { } type ollamaToolFunc struct { - Name string `json:"name"` - Description string `json:"description,omitempty"` - Arguments json.RawMessage `json:"arguments,omitempty"` - Parameters json.RawMessage `json:"parameters,omitempty"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Arguments jsontext.Value `json:"arguments,omitempty"` + Parameters jsontext.Value `json:"parameters,omitempty"` } type ollamaToolCall struct { @@ -135,7 +138,7 @@ func (e *ollamaStatusError) Error() string { func (o *ollamaBackend) post(ctx context.Context, call *ollamaCall) (*http.Response, error) { endpoint, payload := call.endpoint() - raw, err := json.Marshal(payload) + raw, err := json.Marshal(payload, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal ollama request: %w", err) } @@ -159,7 +162,7 @@ func (o *ollamaBackend) post(ctx context.Context, call *ollamaCall) (*http.Respo msg := strings.TrimSpace(string(b)) var e ollamaChunk - if json.Unmarshal(b, &e) == nil && e.Error != "" { + if json.Unmarshal(b, &e, jsonx.V1()) == nil && e.Error != "" { msg = e.Error } @@ -185,12 +188,12 @@ func (o *ollamaBackend) run( defer resp.Body.Close() res := &ollamaResult{} - dec := json.NewDecoder(resp.Body) + dec := jsontext.NewDecoder(resp.Body) for { var ch ollamaChunk - if derr := dec.Decode(&ch); derr != nil { + if derr := json.UnmarshalDecode(dec, &ch, jsonx.V1()); derr != nil { return nil, fmt.Errorf("%w: reading ollama response: %w", errOllamaUnreachable, derr) } diff --git a/services/bedrockruntime/ollama_converse.go b/services/bedrockruntime/ollama_converse.go index 69f9b52c7d..46a25ee42d 100644 --- a/services/bedrockruntime/ollama_converse.go +++ b/services/bedrockruntime/ollama_converse.go @@ -3,7 +3,8 @@ package bedrockruntime import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -50,16 +52,16 @@ type cvDocument struct { } type cvToolUse struct { - ToolUseID string `json:"toolUseId"` - Name string `json:"name"` - Input json.RawMessage `json:"input"` + ToolUseID string `json:"toolUseId"` + Name string `json:"name"` + Input jsontext.Value `json:"input"` } type cvToolResult struct { ToolUseID string `json:"toolUseId"` Content []struct { - Text *string `json:"text"` - JSON json.RawMessage `json:"json"` + Text *string `json:"text"` + JSON jsontext.Value `json:"json"` } `json:"content"` } @@ -73,8 +75,8 @@ type cvSystemBlock struct { } type cvRequest struct { - InferenceConfig json.RawMessage `json:"inferenceConfig"` - ToolConfig json.RawMessage `json:"toolConfig"` + InferenceConfig jsontext.Value `json:"inferenceConfig"` + ToolConfig jsontext.Value `json:"toolConfig"` Messages []cvMessage `json:"messages"` System []cvSystemBlock `json:"system"` } @@ -185,15 +187,15 @@ func ollamaMessages(req *cvRequest) ([]ollamaMessage, error) { return out, nil } -func objectOrEmpty(raw json.RawMessage) json.RawMessage { +func objectOrEmpty(raw jsontext.Value) jsontext.Value { if len(raw) == 0 || string(raw) == "null" { - return json.RawMessage("{}") + return jsontext.Value("{}") } return raw } -func ollamaTools(raw json.RawMessage) []ollamaTool { +func ollamaTools(raw jsontext.Value) []ollamaTool { if len(raw) == 0 { return nil } @@ -204,12 +206,12 @@ func ollamaTools(raw json.RawMessage) []ollamaTool { Name string `json:"name"` Description string `json:"description"` InputSchema struct { - JSON json.RawMessage `json:"json"` + JSON jsontext.Value `json:"json"` } `json:"inputSchema"` } `json:"toolSpec"` } `json:"tools"` } - if json.Unmarshal(raw, &tc) != nil { + if json.Unmarshal(raw, &tc, jsonx.V1()) != nil { return nil } @@ -228,13 +230,13 @@ func ollamaTools(raw json.RawMessage) []ollamaTool { return out } -func ollamaOptionsFromInference(raw json.RawMessage) *ollamaOptions { +func ollamaOptionsFromInference(raw jsontext.Value) *ollamaOptions { if len(raw) == 0 { return nil } var ic inferenceConfigBody - if json.Unmarshal(raw, &ic) != nil { + if json.Unmarshal(raw, &ic, jsonx.V1()) != nil { return nil } @@ -248,7 +250,7 @@ func (o *ollamaBackend) converseCall(modelID string, body []byte) (*ollamaCall, } var req cvRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errUnsupportedContent, err) } @@ -335,7 +337,7 @@ func (h *Handler) handleOllamaConverse( resp := buildOllamaConverseResponse(res, time.Since(start)) echoConverseConfig(resp, req) - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -421,7 +423,7 @@ func (s *converseStreamer) finish(res *ollamaResult, meta map[string]any) { func frameWriter(c *echo.Context) (func(string, any), func(string, string)) { write := func(headers [][2]string, payload any) { - data, err := json.Marshal(payload) + data, err := json.Marshal(payload, jsonx.V1()) if err != nil { return } @@ -486,7 +488,7 @@ func (h *Handler) handleOllamaConverseStream( } func mustJSON(v any) []byte { - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return b } diff --git a/services/bedrockruntime/ollama_invoke.go b/services/bedrockruntime/ollama_invoke.go index 4bc547f5a9..6c7d0a3999 100644 --- a/services/bedrockruntime/ollama_invoke.go +++ b/services/bedrockruntime/ollama_invoke.go @@ -1,7 +1,8 @@ package bedrockruntime import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -82,7 +84,7 @@ func familyFor(id string) familyBuilder { } func parseBody(body []byte, v any) error { - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return malformed(err) } @@ -108,13 +110,13 @@ type anthropicBlock struct { Source *struct { Data string `json:"data"` } `json:"source"` - Type string `json:"type"` - Text string `json:"text"` - ID string `json:"id"` - Name string `json:"name"` - ToolUseID string `json:"tool_use_id"` - Input json.RawMessage `json:"input"` - Content json.RawMessage `json:"content"` + Type string `json:"type"` + Text string `json:"text"` + ID string `json:"id"` + Name string `json:"name"` + ToolUseID string `json:"tool_use_id"` + Input jsontext.Value `json:"input"` + Content jsontext.Value `json:"content"` } type anthropicRequest struct { @@ -125,36 +127,36 @@ type anthropicRequest struct { TopK *int `json:"top_k"` Prompt string `json:"prompt"` Messages []struct { - Role string `json:"role"` - Content json.RawMessage `json:"content"` + Role string `json:"role"` + Content jsontext.Value `json:"content"` } `json:"messages"` - System json.RawMessage `json:"system"` + System jsontext.Value `json:"system"` Tools []anthropicTool `json:"tools"` StopSequences []string `json:"stop_sequences"` } type anthropicTool struct { - Name string `json:"name"` - Description string `json:"description"` - InputSchema json.RawMessage `json:"input_schema"` + Name string `json:"name"` + Description string `json:"description"` + InputSchema jsontext.Value `json:"input_schema"` } // anthropicBlocks reads a content value that is either a string or an array of blocks. -func anthropicBlocks(raw json.RawMessage) ([]anthropicBlock, error) { +func anthropicBlocks(raw jsontext.Value) ([]anthropicBlock, error) { var s string - if json.Unmarshal(raw, &s) == nil { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil { return []anthropicBlock{{Type: typeText, Text: s}}, nil } var blocks []anthropicBlock - if err := json.Unmarshal(raw, &blocks); err != nil { + if err := json.Unmarshal(raw, &blocks, jsonx.V1()); err != nil { return nil, malformed(err) } return blocks, nil } -func anthropicToCv(role string, raw json.RawMessage) (cvMessage, error) { +func anthropicToCv(role string, raw jsontext.Value) (cvMessage, error) { blocks, err := anthropicBlocks(raw) if err != nil { return cvMessage{}, err @@ -188,8 +190,8 @@ func anthropicToCv(role string, raw json.RawMessage) (cvMessage, error) { for _, ib := range inner { t := ib.Text res.Content = append(res.Content, struct { - Text *string `json:"text"` - JSON json.RawMessage `json:"json"` + Text *string `json:"text"` + JSON jsontext.Value `json:"json"` }{Text: &t}) } @@ -202,7 +204,7 @@ func anthropicToCv(role string, raw json.RawMessage) (cvMessage, error) { return m, nil } -func anthropicSystem(raw json.RawMessage) ([]cvSystemBlock, error) { +func anthropicSystem(raw jsontext.Value) ([]cvSystemBlock, error) { if len(raw) == 0 { return nil, nil } @@ -907,7 +909,7 @@ func (h *Handler) handleOllamaInvoke(c *echo.Context, o *ollamaBackend, modelID return writeInvokeError(c, err) } - out, err := json.Marshal(plan.render(res)) + out, err := json.Marshal(plan.render(res), jsonx.V1()) if err != nil { return c.JSON(http.StatusInternalServerError, errorResponse("InternalServerException", "internal server error")) } @@ -952,7 +954,7 @@ func (h *Handler) handleOllamaInvokeStream(c *echo.Context, o *ollamaBackend, mo } for _, ch := range chunks { - emit("chunk", json.RawMessage(modelResponsePayloadPart(mustJSON(ch)))) + emit("chunk", jsontext.Value(modelResponsePayloadPart(mustJSON(ch)))) } } diff --git a/services/bedrockruntime/persistence.go b/services/bedrockruntime/persistence.go index fe2f73ed61..1bcb0ecb35 100644 --- a/services/bedrockruntime/persistence.go +++ b/services/bedrockruntime/persistence.go @@ -2,7 +2,7 @@ package bedrockruntime import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -45,13 +45,13 @@ const bedrockruntimeSnapshotVersion = 1 // freshly restored backend never reissues an ARN already handed out // before the snapshot. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - TokenIndex map[string]string `json:"tokenIndex"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Invocations []*Invocation `json:"invocations"` - AsyncInvokeCounter int `json:"asyncInvokeCounter"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + TokenIndex map[string]string `json:"tokenIndex"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Invocations []*Invocation `json:"invocations"` + AsyncInvokeCounter int `json:"asyncInvokeCounter"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. It implements diff --git a/services/bedrockruntime/wire_field_fixes_y1zn_test.go b/services/bedrockruntime/wire_field_fixes_y1zn_test.go index b090888ebb..a7436123ba 100644 --- a/services/bedrockruntime/wire_field_fixes_y1zn_test.go +++ b/services/bedrockruntime/wire_field_fixes_y1zn_test.go @@ -1,7 +1,7 @@ package bedrockruntime_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( brtypes "github.com/aws/aws-sdk-go-v2/service/bedrockruntime/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetAsyncInvoke_NoInventedTagsKey_RealClient covers gopherstack-y1zn. @@ -38,7 +40,7 @@ func TestGetAsyncInvoke_NoInventedTagsKey_RealClient(t *testing.T) { "neither GetAsyncInvokeOutput nor AsyncInvokeSummary has a tags member") var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) _, hasTags := out["tags"] assert.False(t, hasTags) } diff --git a/services/budgets/budgets.go b/services/budgets/budgets.go index fd160e7631..5a6e8292ed 100644 --- a/services/budgets/budgets.go +++ b/services/budgets/budgets.go @@ -3,19 +3,20 @@ package budgets import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) func deepCopy[T any](v *T) *T { - data, _ := json.Marshal(v) + data, _ := json.Marshal(v, jsonx.V1()) var out T - _ = json.Unmarshal(data, &out) + _ = json.Unmarshal(data, &out, jsonx.V1()) return &out } diff --git a/services/budgets/handler.go b/services/budgets/handler.go index 8fcbcd5ecb..586e5d6e3c 100644 --- a/services/budgets/handler.go +++ b/services/budgets/handler.go @@ -2,7 +2,7 @@ package budgets import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -37,7 +38,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrInvalidParameter, "malformed request body: %v", err) } } diff --git a/services/budgets/persistence.go b/services/budgets/persistence.go index 73edc0e1e0..79dffffc92 100644 --- a/services/budgets/persistence.go +++ b/services/budgets/persistence.go @@ -2,7 +2,7 @@ package budgets import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/budgets/wire.go b/services/budgets/wire.go index 595592bc5b..572f8284ed 100644 --- a/services/budgets/wire.go +++ b/services/budgets/wire.go @@ -1,10 +1,11 @@ package budgets import ( - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Wire shapes follow the pinned aws-sdk-go-v2/service/budgets v1.53.1 awsjson1.1 schemas; @@ -14,12 +15,14 @@ import ( type Timestamp struct{ time.Time } // MarshalJSON renders the epoch-seconds number the SDK expects. -func (t Timestamp) MarshalJSON() ([]byte, error) { return json.Marshal(awstime.Epoch(t.Time)) } +func (t Timestamp) MarshalJSON() ([]byte, error) { + return json.Marshal(awstime.Epoch(t.Time), jsonx.V1()) +} // UnmarshalJSON reads an epoch-seconds number. func (t *Timestamp) UnmarshalJSON(data []byte) error { var f float64 - if err := json.Unmarshal(data, &f); err != nil { + if err := json.Unmarshal(data, &f, jsonx.V1()); err != nil { return err } diff --git a/services/ce/cost_usage_granularity_test.go b/services/ce/cost_usage_granularity_test.go index d4863146b6..d1c5189010 100644 --- a/services/ce/cost_usage_granularity_test.go +++ b/services/ce/cost_usage_granularity_test.go @@ -1,12 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // wireError decodes the AWS JSON-protocol error envelope (__type/message). @@ -45,7 +48,7 @@ func TestGetCostAndUsage_InvalidGranularityRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var wireErr wireError - require.NoError(t, json.NewDecoder(rec.Body).Decode(&wireErr)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &wireErr, jsonx.V1())) assert.Equal(t, "ValidationError", wireErr.Type) }) } @@ -74,7 +77,7 @@ func TestGetCostAndUsage_HourlyGranularityBucketsHourly(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.ResultsByTime, 24, "one bucket per hour across a single day") assert.Equal(t, "2024-01-01T00:00:00Z", out.ResultsByTime[0].TimePeriod["Start"]) diff --git a/services/ce/cost_usage_timeperiod_test.go b/services/ce/cost_usage_timeperiod_test.go index af5286da01..e9944d984d 100644 --- a/services/ce/cost_usage_timeperiod_test.go +++ b/services/ce/cost_usage_timeperiod_test.go @@ -1,12 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetCostAndUsage_UnparseableTimePeriodRejected verifies that a @@ -43,7 +46,7 @@ func TestGetCostAndUsage_UnparseableTimePeriodRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var wireErr wireError - require.NoError(t, json.NewDecoder(rec.Body).Decode(&wireErr)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &wireErr, jsonx.V1())) assert.Equal(t, "ValidationError", wireErr.Type) }) } diff --git a/services/ce/handler.go b/services/ce/handler.go index fa4666a143..1cde01e271 100644 --- a/services/ce/handler.go +++ b/services/ce/handler.go @@ -2,7 +2,7 @@ package ce import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -196,19 +197,17 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError switch { case errors.Is(err, ErrUnknownMonitor): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "UnknownMonitorException", Message: err.Error(), - }) + }, jsonx.V1()) // Real AWS CE returns HTTP 400 for every modeled client-fault exception (verified // against API_DeleteAnomalyMonitor/API_UpdateAnomalyMonitor/API_GetAnomalyMonitors), @@ -218,21 +217,21 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "InvalidNextTokenException", Message: err.Error(), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrUnknownSubscription): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "UnknownSubscriptionException", Message: err.Error(), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrNotFound): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ResourceNotFoundException", Message: err.Error(), - }) + }, jsonx.V1()) // See API_DescribeCostCategoryDefinition: ResourceNotFoundException is documented // as HTTP 400, not 404. @@ -241,7 +240,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ServiceQuotaExceededException", Message: err.Error(), - }) + }, jsonx.V1()) // See API_CreateCostCategoryDefinition: ServiceQuotaExceededException is documented // as HTTP 400, not 409. @@ -250,18 +249,18 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ValidationError", Message: err.Error(), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) // "ValidationError" is CE's documented CommonErrors type for malformed/ // missing-required-member requests (see ErrValidation above) -- it is not // tied to any one operation's model, so it fits here too. case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ValidationError", Message: err.Error(), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) default: diff --git a/services/ce/handler_anomalies_test.go b/services/ce/handler_anomalies_test.go index 78bd01f3b8..dc3154adb3 100644 --- a/services/ce/handler_anomalies_test.go +++ b/services/ce/handler_anomalies_test.go @@ -1,7 +1,8 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -29,7 +31,7 @@ func TestGetAnomalyMonitors_HasCreationDateAndLastUpdatedDate(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) monARN := createOut["MonitorArn"].(string) // Describe it @@ -45,7 +47,7 @@ func TestGetAnomalyMonitors_HasCreationDateAndLastUpdatedDate(t *testing.T) { LastUpdatedDate string `json:"LastUpdatedDate"` } `json:"AnomalyMonitors"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) require.Len(t, getOut.AnomalyMonitors, 1) m := getOut.AnomalyMonitors[0] @@ -76,7 +78,7 @@ func TestGetAnomalyMonitors_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1 := out1["AnomalyMonitors"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["NextPageToken"].(string) @@ -89,7 +91,7 @@ func TestGetAnomalyMonitors_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2 := out2["AnomalyMonitors"].([]any) assert.Len(t, page2, 2) } @@ -110,7 +112,7 @@ func TestGetAnomalySubscriptions_HasAccountId(t *testing.T) { require.Equal(t, http.StatusOK, monRec.Code) var monOut map[string]any - require.NoError(t, json.Unmarshal(monRec.Body.Bytes(), &monOut)) + require.NoError(t, json.Unmarshal(monRec.Body.Bytes(), &monOut, jsonx.V1())) monARN := monOut["MonitorArn"].(string) subRec := doRequest(t, h, "CreateAnomalySubscription", map[string]any{ @@ -133,7 +135,7 @@ func TestGetAnomalySubscriptions_HasAccountId(t *testing.T) { AccountID string `json:"AccountId"` } `json:"AnomalySubscriptions"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) require.Len(t, getOut.AnomalySubscriptions, 1) assert.NotEmpty(t, getOut.AnomalySubscriptions[0].AccountID, "AccountId must be present in subscription") } @@ -153,7 +155,7 @@ func TestGetAnomalySubscriptions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, monRec.Code) var monOut map[string]any - require.NoError(t, json.Unmarshal(monRec.Body.Bytes(), &monOut)) + require.NoError(t, json.Unmarshal(monRec.Body.Bytes(), &monOut, jsonx.V1())) monARN := monOut["MonitorArn"].(string) for i := range 5 { @@ -176,7 +178,7 @@ func TestGetAnomalySubscriptions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1 := out1["AnomalySubscriptions"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["NextPageToken"].(string) @@ -203,7 +205,7 @@ func TestHandler_AnomalyMonitorCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["MonitorArn"]) monARN := out["MonitorArn"].(string) @@ -227,7 +229,7 @@ func TestHandler_AnomalyMonitorCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) monARN := createOut["MonitorArn"].(string) rec2 := doRequest(t, h, "UpdateAnomalyMonitor", map[string]any{ @@ -250,7 +252,7 @@ func TestHandler_AnomalyMonitorCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) monARN := createOut["MonitorArn"].(string) rec2 := doRequest(t, h, "DeleteAnomalyMonitor", map[string]any{ @@ -295,7 +297,7 @@ func TestHandler_AnomalySubscriptionCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["SubscriptionArn"]) }, }, @@ -316,7 +318,7 @@ func TestHandler_AnomalySubscriptionCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) subARN := createOut["SubscriptionArn"].(string) rec2 := doRequest(t, h, "DeleteAnomalySubscription", map[string]any{ @@ -399,7 +401,7 @@ func TestHandler_GetAnomalySubscriptions(t *testing.T) { var out struct { AnomalySubscriptions []map[string]any `json:"AnomalySubscriptions"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.AnomalySubscriptions, tt.wantLen) }) } @@ -461,7 +463,7 @@ func TestHandler_UpdateAnomalySubscription(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) tt.updateBody["SubscriptionArn"] = createOut["SubscriptionArn"] } @@ -470,7 +472,7 @@ func TestHandler_UpdateAnomalySubscription(t *testing.T) { if tt.wantFrequency != "" { var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["SubscriptionArn"]) } }) @@ -650,7 +652,7 @@ func TestHandler_GetAnomalySubscriptions_MonitorArnFilter(t *testing.T) { require.Equal(t, http.StatusOK, monRec.Code) var monOut map[string]any - require.NoError(t, json.NewDecoder(monRec.Body).Decode(&monOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(monRec.Body), &monOut, jsonx.V1())) monARN := monOut["MonitorArn"].(string) // Create subscription attached to monitor. @@ -693,7 +695,7 @@ func TestHandler_GetAnomalySubscriptions_MonitorArnFilter(t *testing.T) { var out struct { AnomalySubscriptions []map[string]any `json:"AnomalySubscriptions"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.AnomalySubscriptions, tt.wantLen) }) } @@ -765,7 +767,7 @@ func TestHandler_UpdateAnomalySubscription_AllBranches(t *testing.T) { require.Equal(t, http.StatusOK, monRec.Code) var monOut map[string]any - require.NoError(t, json.NewDecoder(monRec.Body).Decode(&monOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(monRec.Body), &monOut, jsonx.V1())) monARN := monOut["MonitorArn"].(string) arns, ok := tt.updateBody["MonitorArnList"].([]string) @@ -786,7 +788,7 @@ func TestHandler_UpdateAnomalySubscription_AllBranches(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) subARN := createOut["SubscriptionArn"].(string) tt.updateBody["SubscriptionArn"] = subARN @@ -807,7 +809,7 @@ func TestHandler_UpdateAnomalySubscription_AllBranches(t *testing.T) { Threshold float64 `json:"Threshold"` } `json:"AnomalySubscriptions"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) require.Len(t, getOut.AnomalySubscriptions, 1) assert.Equal(t, tt.wantFrequency, getOut.AnomalySubscriptions[0].Frequency) assert.Equal(t, tt.wantSubName, getOut.AnomalySubscriptions[0].SubscriptionName) @@ -939,7 +941,7 @@ func TestHandler_UpdateAnomalyMonitor_OmittedNameUnchanged(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) monARN := createOut["MonitorArn"].(string) updateRec := doRequest(t, h, "UpdateAnomalyMonitor", map[string]any{ @@ -957,7 +959,7 @@ func TestHandler_UpdateAnomalyMonitor_OmittedNameUnchanged(t *testing.T) { MonitorName string `json:"MonitorName"` } `json:"AnomalyMonitors"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) require.Len(t, getOut.AnomalyMonitors, 1) assert.Equal(t, "KeepMyName", getOut.AnomalyMonitors[0].MonitorName) } diff --git a/services/ce/handler_anomaly_detection_test.go b/services/ce/handler_anomaly_detection_test.go index f5b2792771..f318abe41a 100644 --- a/services/ce/handler_anomaly_detection_test.go +++ b/services/ce/handler_anomaly_detection_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -47,7 +49,7 @@ func TestAnomalyFeedback_PreviousFeedbackOverwritten(t *testing.T) { Feedback string `json:"Feedback"` } `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) require.Len(t, out.Anomalies, 1) assert.Equal(t, "feedback-overwrite-1", out.Anomalies[0].AnomalyID) assert.Equal(t, "NO", out.Anomalies[0].Feedback) @@ -120,7 +122,7 @@ func TestProvideAnomalyFeedback_PersistsAndValidates(t *testing.T) { Feedback string `json:"Feedback"` } `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) require.Len(t, out.Anomalies, 1) assert.Equal(t, "feedback-test-1", out.Anomalies[0].AnomalyID) assert.Equal(t, tt.wantFeedback, out.Anomalies[0].Feedback) @@ -181,7 +183,7 @@ func TestGetAnomalies_ScoreAndImpactAreObjects(t *testing.T) { } `json:"Impact"` } `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.Anomalies, 1) a := out.Anomalies[0] @@ -223,7 +225,7 @@ func TestGetAnomalies_DateIntervalFilters(t *testing.T) { AnomalyID string `json:"AnomalyId"` } `json:"Anomalies"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Anomalies, 1) assert.Equal(t, "recent-anomaly", out.Anomalies[0].AnomalyID) } @@ -283,7 +285,7 @@ func TestGetAnomalies_DateIntervalMatchesOnAnomalyEndDateOnly(t *testing.T) { AnomalyID string `json:"AnomalyId"` } `json:"Anomalies"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.want { require.Len(t, out.Anomalies, 1) @@ -317,7 +319,7 @@ func TestGetAnomalies_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1 := out1["Anomalies"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["NextPageToken"].(string) @@ -370,7 +372,7 @@ func TestHandler_GetAnomalies(t *testing.T) { var out struct { Anomalies []any `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.Anomalies) }) } @@ -452,7 +454,7 @@ func TestHandler_GetAnomalies_Filters(t *testing.T) { var out struct { Anomalies []map[string]any `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Anomalies, tt.wantLen) }) } @@ -483,7 +485,7 @@ func TestHandler_SnapshotRestoreWithAnomalies(t *testing.T) { var out struct { Anomalies []map[string]any `json:"Anomalies"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Anomalies, 1) assert.Equal(t, "snap-anomaly-1", out.Anomalies[0]["AnomalyId"]) } diff --git a/services/ce/handler_commitment_purchase_analysis_test.go b/services/ce/handler_commitment_purchase_analysis_test.go index cbf96d14ed..a3709ce5ca 100644 --- a/services/ce/handler_commitment_purchase_analysis_test.go +++ b/services/ce/handler_commitment_purchase_analysis_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -28,7 +30,7 @@ func TestCommitmentAnalysis_MultipleStartsListed(t *testing.T) { var out struct { AnalysisID string `json:"AnalysisId"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.AnalysisID) analysisIDs = append(analysisIDs, out.AnalysisID) } @@ -48,7 +50,7 @@ func TestCommitmentAnalysis_MultipleStartsListed(t *testing.T) { AnalysisID string `json:"AnalysisId"` } `json:"AnalysisSummaryList"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) require.Len(t, listOut.AnalysisSummaryList, 3) listedIDs := make(map[string]struct{}, 3) @@ -81,7 +83,7 @@ func TestCommitmentPurchaseAnalysis_Lifecycle(t *testing.T) { AnalysisStartedTime string `json:"AnalysisStartedTime"` EstimatedCompletionTime string `json:"EstimatedCompletionTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &startOut, jsonx.V1())) require.NotEmpty(t, startOut.AnalysisID) assert.NotEmpty(t, startOut.AnalysisStartedTime) assert.NotEmpty(t, startOut.EstimatedCompletionTime) @@ -96,7 +98,7 @@ func TestCommitmentPurchaseAnalysis_Lifecycle(t *testing.T) { AnalysisID string `json:"AnalysisId"` AnalysisStatus string `json:"AnalysisStatus"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, startOut.AnalysisID, getOut.AnalysisID) assert.Equal(t, "PROCESSING", getOut.AnalysisStatus) @@ -109,7 +111,7 @@ func TestCommitmentPurchaseAnalysis_Lifecycle(t *testing.T) { AnalysisID string `json:"AnalysisId"` } `json:"AnalysisSummaryList"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) require.Len(t, listOut.AnalysisSummaryList, 1) assert.Equal(t, startOut.AnalysisID, listOut.AnalysisSummaryList[0].AnalysisID) } @@ -128,7 +130,7 @@ func TestSnapshotRestore_IncludesCommitmentAnalyses(t *testing.T) { var startOut struct { AnalysisID string `json:"AnalysisId"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &startOut, jsonx.V1())) // Snapshot + restore snap := h.Snapshot(t.Context()) diff --git a/services/ce/handler_cost_allocation_tags_test.go b/services/ce/handler_cost_allocation_tags_test.go index db09476275..c21ef62bae 100644 --- a/services/ce/handler_cost_allocation_tags_test.go +++ b/services/ce/handler_cost_allocation_tags_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -22,7 +24,7 @@ func TestListCostAllocationTags_EmptyWithNoTags(t *testing.T) { var out struct { CostAllocationTags []any `json:"CostAllocationTags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.CostAllocationTags) assert.Empty(t, out.CostAllocationTags) } @@ -81,7 +83,7 @@ func TestUpdateCostAllocationTagsStatus_MultipleUpdates(t *testing.T) { var out struct { Errors []any `json:"Errors"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Errors, tt.wantErrors) }) } @@ -107,7 +109,7 @@ func TestBackfillMultipleJobs(t *testing.T) { var out struct { BackfillRequests []map[string]any `json:"BackfillRequests"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.BackfillRequests, 3) } @@ -179,7 +181,7 @@ func TestCostAllocationTags_UpdateAndList(t *testing.T) { Type string `json:"Type"` } `json:"CostAllocationTags"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.CostAllocationTags, tt.wantTagCount) for _, tag := range listOut.CostAllocationTags { @@ -217,7 +219,7 @@ func TestCostAllocationTags_ListFiltersWork(t *testing.T) { TagKey string `json:"TagKey"` } `json:"CostAllocationTags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.CostAllocationTags, 2) }) @@ -235,7 +237,7 @@ func TestCostAllocationTags_ListFiltersWork(t *testing.T) { Status string `json:"Status"` } `json:"CostAllocationTags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.CostAllocationTags, 2) for _, tag := range out.CostAllocationTags { @@ -262,7 +264,7 @@ func TestCostAllocationTagBackfill_StateTracking(t *testing.T) { RequestedAt string `json:"requestedAt"` } `json:"BackfillRequest"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &startOut, jsonx.V1())) assert.Equal(t, "2024-01-01T00:00:00Z", startOut.BackfillRequest.BackfillFrom) assert.Equal(t, "PROCESSING", startOut.BackfillRequest.BackfillStatus) @@ -275,7 +277,7 @@ func TestCostAllocationTagBackfill_StateTracking(t *testing.T) { BackfillStatus string `json:"backfillStatus"` } `json:"BackfillRequests"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) require.Len(t, listOut.BackfillRequests, 1) assert.Equal(t, "PROCESSING", listOut.BackfillRequests[0].BackfillStatus) } diff --git a/services/ce/handler_cost_categories_test.go b/services/ce/handler_cost_categories_test.go index 007e036a37..b49b289bf9 100644 --- a/services/ce/handler_cost_categories_test.go +++ b/services/ce/handler_cost_categories_test.go @@ -1,7 +1,8 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -39,7 +41,7 @@ func TestGetCostCategories_MultiRuleCategory(t *testing.T) { ReturnSize int `json:"ReturnSize"` TotalSize int `json:"TotalSize"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.CostCategoryValues, 3) assert.Equal(t, 3, out.ReturnSize) assert.Equal(t, 3, out.TotalSize) @@ -60,7 +62,7 @@ func TestListCostCategoryResourceAssociations(t *testing.T) { var out struct { CostCategoryResourceAssociations []map[string]any `json:"CostCategoryResourceAssociations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.CostCategoryResourceAssociations) } @@ -79,7 +81,7 @@ func TestDescribeCostCategory_HasProcessingStatus(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) catARN := createOut["CostCategoryArn"].(string) descRec := doRequest(t, h, "DescribeCostCategoryDefinition", map[string]any{ @@ -95,7 +97,7 @@ func TestDescribeCostCategory_HasProcessingStatus(t *testing.T) { } `json:"ProcessingStatus"` } `json:"CostCategory"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.NotEmpty(t, descOut.CostCategory.ProcessingStatus, "ProcessingStatus must be present") ps := descOut.CostCategory.ProcessingStatus[0] assert.Equal(t, "COST_EXPLORER", ps.Component) @@ -123,7 +125,7 @@ func TestListCostCategoryDefinitions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1 := out1["CostCategoryReferences"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["NextPageToken"].(string) @@ -136,7 +138,7 @@ func TestListCostCategoryDefinitions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2 := out2["CostCategoryReferences"].([]any) assert.Len(t, page2, 2) } @@ -160,7 +162,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["CostCategoryArn"]) assert.NotEmpty(t, out["EffectiveStart"]) }, @@ -180,7 +182,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) refs, ok := out["CostCategoryReferences"].([]any) require.True(t, ok) assert.NotEmpty(t, refs) @@ -199,7 +201,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) arn := createOut["CostCategoryArn"].(string) // Describe @@ -209,7 +211,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var describeOut map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&describeOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &describeOut, jsonx.V1())) cat := describeOut["CostCategory"].(map[string]any) assert.Equal(t, "DescribeCategory", cat["Name"]) }, @@ -227,7 +229,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) arn := createOut["CostCategoryArn"].(string) // Update @@ -239,7 +241,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var updateOut map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&updateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &updateOut, jsonx.V1())) assert.Equal(t, arn, updateOut["CostCategoryArn"]) }, }, @@ -256,7 +258,7 @@ func TestHandler_CostCategoryCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) arn := createOut["CostCategoryArn"].(string) // Delete @@ -343,7 +345,7 @@ func TestCEHandler_UpdateCostCategoryDefinition_DeepCopy(t *testing.T) { var createOut struct { CostCategoryArn string `json:"CostCategoryArn"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) updateRec := doRequest(t, h, "UpdateCostCategoryDefinition", map[string]any{ "CostCategoryArn": createOut.CostCategoryArn, @@ -363,7 +365,7 @@ func TestCEHandler_UpdateCostCategoryDefinition_DeepCopy(t *testing.T) { } `json:"CostCategory"` } - require.NoError(t, json.NewDecoder(describeRec.Body).Decode(&describeOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(describeRec.Body), &describeOut, jsonx.V1())) assert.Len(t, describeOut.CostCategory.Rules, tt.wantRulesAfterGet) }) } @@ -451,7 +453,7 @@ func TestHandler_GetCostCategories(t *testing.T) { ReturnSize int `json:"ReturnSize"` TotalSize int `json:"TotalSize"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantLen, out.ReturnSize) assert.Equal(t, tt.wantLen, out.TotalSize) @@ -523,7 +525,7 @@ func TestHandler_SortedOutput(t *testing.T) { Name string `json:"Name"` } `json:"CostCategoryReferences"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.CostCategoryReferences, 3) assert.Equal(t, "Alpha", out.CostCategoryReferences[0].Name) assert.Equal(t, "Mango", out.CostCategoryReferences[1].Name) @@ -555,7 +557,7 @@ func TestHandler_SortedOutput(t *testing.T) { var out struct { CostCategoryValues []string `json:"CostCategoryValues"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.CostCategoryValues, 3) assert.Equal(t, []string{"Alpha", "Mike", "Zulu"}, out.CostCategoryValues) }, @@ -592,7 +594,7 @@ func TestHandler_SortedOutput(t *testing.T) { Key string `json:"Key"` } `json:"ResourceTags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.ResourceTags, 3) assert.Equal(t, "Alpha", out.ResourceTags[0].Key) assert.Equal(t, "Mike", out.ResourceTags[1].Key) @@ -634,7 +636,7 @@ func TestHandler_DuplicateCostCategory_WireStatusIs400(t *testing.T) { var out struct { Type string `json:"__type"` } - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out, jsonx.V1())) assert.Equal(t, "ServiceQuotaExceededException", out.Type) } @@ -734,7 +736,7 @@ func TestHandler_UpdateCostCategoryDefinition_RequiredFields(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) tt.update["CostCategoryArn"] = createOut["CostCategoryArn"] rec := doRequest(t, h, "UpdateCostCategoryDefinition", tt.update) diff --git a/services/ce/handler_cost_usage_test.go b/services/ce/handler_cost_usage_test.go index 8af27f5906..8f7b064e63 100644 --- a/services/ce/handler_cost_usage_test.go +++ b/services/ce/handler_cost_usage_test.go @@ -1,7 +1,8 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -35,7 +37,7 @@ func TestGetCostAndUsageWithResources_ResourceIDs(t *testing.T) { ResultsByTime []any `json:"ResultsByTime"` DimensionValueAttributes []any `json:"DimensionValueAttributes"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.ResultsByTime) assert.NotNil(t, out.DimensionValueAttributes) } @@ -77,7 +79,7 @@ func TestGetApproximateUsageRecords_Shape(t *testing.T) { Services map[string]int64 `json:"Services"` TotalRecords int64 `json:"TotalRecords"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.Services) assert.Positive(t, out.TotalRecords) }) @@ -109,7 +111,7 @@ func TestGetCostAndUsageComparisons_Shape(t *testing.T) { } `json:"Metrics"` } `json:"CostAndUsageComparisons"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.CostAndUsageComparisons) assert.NotEmpty(t, out.TotalCostAndUsage["BlendedCost"]) assert.NotEmpty(t, out.CostAndUsageComparisons[0].Metrics["BlendedCost"].ComparisonTimePeriodAmount) @@ -238,7 +240,7 @@ func TestGetCostComparisonDrivers(t *testing.T) { } `json:"CostDrivers"` } `json:"CostComparisonDrivers"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.CostComparisonDrivers) assert.GreaterOrEqual(t, len(out.CostComparisonDrivers), tt.minGroups) assert.LessOrEqual(t, len(out.CostComparisonDrivers), tt.maxGroups) @@ -274,8 +276,8 @@ func TestGetUsageForecast_MatchesCostForecast(t *testing.T) { require.Equal(t, http.StatusOK, usageRec.Code) var costOut, usageOut map[string]any - require.NoError(t, json.NewDecoder(costRec.Body).Decode(&costOut)) - require.NoError(t, json.NewDecoder(usageRec.Body).Decode(&usageOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(costRec.Body), &costOut, jsonx.V1())) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(usageRec.Body), &usageOut, jsonx.V1())) // Both should have Total and ForecastResultsByTime assert.NotNil(t, costOut["Total"]) @@ -299,7 +301,7 @@ func TestGetTags_EmptyKeyReturnsAllKeys(t *testing.T) { ReturnSize int `json:"ReturnSize"` TotalSize int `json:"TotalSize"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) // Ledger may have no tags seeded — assert shape is correct regardless assert.NotNil(t, out.Tags) assert.Equal(t, len(out.Tags), out.ReturnSize) @@ -320,7 +322,7 @@ func TestGetTags_WithTagKey(t *testing.T) { var out struct { Tags []string `json:"Tags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.Tags) } @@ -348,7 +350,7 @@ func TestGetCostAndUsage_GroupByDimensions(t *testing.T) { var out struct { ResultsByTime []map[string]any `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.ResultsByTime) }) } @@ -385,7 +387,7 @@ func TestGetCostAndUsage_AlternateMetrics(t *testing.T) { var out struct { ResultsByTime []map[string]any `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.ResultsByTime) }) } @@ -467,7 +469,7 @@ func TestGetCostAndUsage_ReturnsResultsByTime(t *testing.T) { var out struct { ResultsByTime []any `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) if tt.wantNonEmpty { assert.NotEmpty(t, out.ResultsByTime) @@ -497,7 +499,7 @@ func TestGetCostAndUsage_GroupByProducesGroups(t *testing.T) { } `json:"Groups"` } `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.ResultsByTime) first := out.ResultsByTime[0] @@ -528,7 +530,7 @@ func TestGetCostAndUsage_TotalPresentWhenNoGroupBy(t *testing.T) { Estimated bool `json:"Estimated"` } `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.ResultsByTime) first := out.ResultsByTime[0] @@ -569,7 +571,7 @@ func TestGetDimensionValues_ServiceDimension(t *testing.T) { ReturnSize int `json:"ReturnSize"` TotalSize int `json:"TotalSize"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.DimensionValues) assert.Positive(t, out.ReturnSize) assert.Equal(t, out.ReturnSize, out.TotalSize) @@ -594,7 +596,7 @@ func TestGetDimensionValues_SearchStringFilters(t *testing.T) { Value string `json:"Value"` } `json:"DimensionValues"` } - require.NoError(t, json.NewDecoder(recAll.Body).Decode(&allOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(recAll.Body), &allOut, jsonx.V1())) totalCount := len(allOut.DimensionValues) // Filter by "Lambda" @@ -610,7 +612,7 @@ func TestGetDimensionValues_SearchStringFilters(t *testing.T) { Value string `json:"Value"` } `json:"DimensionValues"` } - require.NoError(t, json.NewDecoder(recFiltered.Body).Decode(&filteredOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(recFiltered.Body), &filteredOut, jsonx.V1())) assert.Less(t, len(filteredOut.DimensionValues), totalCount) for _, dv := range filteredOut.DimensionValues { assert.Contains(t, dv.Value, "Lambda") @@ -671,7 +673,7 @@ func TestGetCostForecast_ReturnsTimeSeries(t *testing.T) { MeanValue string `json:"MeanValue"` } `json:"ForecastResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Total.Amount) assert.NotEmpty(t, out.Total.Unit) assert.NotEmpty(t, out.ForecastResultsByTime) @@ -892,7 +894,7 @@ func TestHandler_Forecast_ReturnsOK(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out["Total"]) forecastResults, ok := out["ForecastResultsByTime"].([]any) require.True(t, ok) @@ -950,7 +952,7 @@ func TestHandler_GetApproximateUsageRecords(t *testing.T) { LookbackPeriod map[string]string `json:"LookbackPeriod"` TotalRecords int64 `json:"TotalRecords"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Positive(t, out.TotalRecords) assert.NotEmpty(t, out.LookbackPeriod["Start"]) assert.NotEmpty(t, out.LookbackPeriod["End"]) @@ -988,7 +990,7 @@ func TestHandler_GetCostAndUsageComparisons(t *testing.T) { var out struct { CostAndUsageComparisons []any `json:"CostAndUsageComparisons"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.CostAndUsageComparisons) }) } @@ -1057,7 +1059,7 @@ func TestHandler_GetCostAndUsageWithResources(t *testing.T) { var out struct { ResultsByTime []any `json:"ResultsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.ResultsByTime) }) } @@ -1093,7 +1095,7 @@ func TestHandler_GetCostComparisonDrivers(t *testing.T) { var out struct { CostComparisonDrivers []any `json:"CostComparisonDrivers"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.CostComparisonDrivers) }) } diff --git a/services/ce/handler_filters_test.go b/services/ce/handler_filters_test.go index 87fffc2016..e0fb2127c7 100644 --- a/services/ce/handler_filters_test.go +++ b/services/ce/handler_filters_test.go @@ -1,7 +1,8 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -42,7 +44,7 @@ func TestGetCostCategoriesFilterAndSortNarrow(t *testing.T) { var unfiltered struct { CostCategoryValues []string `json:"CostCategoryValues"` } - require.NoError(t, json.NewDecoder(unfilteredRec.Body).Decode(&unfiltered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(unfilteredRec.Body), &unfiltered, jsonx.V1())) require.Equal(t, []string{"Alpha", "Bravo", "Charlie"}, unfiltered.CostCategoryValues) filteredBody := map[string]any{ @@ -63,7 +65,7 @@ func TestGetCostCategoriesFilterAndSortNarrow(t *testing.T) { ReturnSize int `json:"ReturnSize"` TotalSize int `json:"TotalSize"` } - require.NoError(t, json.NewDecoder(filteredRec.Body).Decode(&filtered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(filteredRec.Body), &filtered, jsonx.V1())) assert.Equal(t, []string{"Alpha", "Charlie"}, filtered.CostCategoryValues) assert.Equal(t, 2, filtered.ReturnSize) assert.Equal(t, 2, filtered.TotalSize) @@ -79,7 +81,7 @@ func TestGetCostCategoriesFilterAndSortNarrow(t *testing.T) { var sorted struct { CostCategoryValues []string `json:"CostCategoryValues"` } - require.NoError(t, json.NewDecoder(sortedRec.Body).Decode(&sorted)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(sortedRec.Body), &sorted, jsonx.V1())) assert.Equal(t, []string{"Charlie", "Bravo", "Alpha"}, sorted.CostCategoryValues) } @@ -102,7 +104,7 @@ func TestGetDimensionValuesFilterAndSortNarrow(t *testing.T) { Value string `json:"Value"` } `json:"DimensionValues"` } - require.NoError(t, json.NewDecoder(unfilteredRec.Body).Decode(&unfiltered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(unfilteredRec.Body), &unfiltered, jsonx.V1())) require.Len(t, unfiltered.DimensionValues, 12, "synthetic catalog has 12 services") // AWS Lambda is the only service seeded with usage type Lambda-GB-Second, @@ -125,7 +127,7 @@ func TestGetDimensionValuesFilterAndSortNarrow(t *testing.T) { } `json:"DimensionValues"` ReturnSize int `json:"ReturnSize"` } - require.NoError(t, json.NewDecoder(filteredRec.Body).Decode(&filtered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(filteredRec.Body), &filtered, jsonx.V1())) require.Len(t, filtered.DimensionValues, 1) assert.Equal(t, "AWS Lambda", filtered.DimensionValues[0].Value) assert.Equal(t, 1, filtered.ReturnSize) @@ -144,7 +146,7 @@ func TestGetDimensionValuesFilterAndSortNarrow(t *testing.T) { Value string `json:"Value"` } `json:"DimensionValues"` } - require.NoError(t, json.NewDecoder(sortedRec.Body).Decode(&sorted)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(sortedRec.Body), &sorted, jsonx.V1())) require.NotEmpty(t, sorted.DimensionValues) assert.Equal(t, "Amazon Elastic Compute Cloud - Compute", sorted.DimensionValues[0].Value) } @@ -174,7 +176,7 @@ func TestGetTagsFilterAndSortAccepted(t *testing.T) { var out struct { Tags []string `json:"Tags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.Tags, "no ledger entry is ever tagged in this emulator") } @@ -198,7 +200,7 @@ func TestGetSavingsPlansCoverageRegionFilterNarrows(t *testing.T) { var matched struct { SavingsPlansCoverages []any `json:"SavingsPlansCoverages"` } - require.NoError(t, json.NewDecoder(matchRec.Body).Decode(&matched)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(matchRec.Body), &matched, jsonx.V1())) assert.Len(t, matched.SavingsPlansCoverages, 1) missRec := doRequest(t, h, "GetSavingsPlansCoverage", map[string]any{ @@ -212,7 +214,7 @@ func TestGetSavingsPlansCoverageRegionFilterNarrows(t *testing.T) { var missed struct { SavingsPlansCoverages []any `json:"SavingsPlansCoverages"` } - require.NoError(t, json.NewDecoder(missRec.Body).Decode(&missed)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(missRec.Body), &missed, jsonx.V1())) assert.Empty(t, missed.SavingsPlansCoverages) } @@ -232,7 +234,7 @@ func TestGetSavingsPlansPurchaseRecommendationAccountFilterNarrows(t *testing.T) require.Equal(t, http.StatusOK, matchRec.Code) var matched map[string]any - require.NoError(t, json.NewDecoder(matchRec.Body).Decode(&matched)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(matchRec.Body), &matched, jsonx.V1())) assert.NotNil(t, matched["SavingsPlansPurchaseRecommendation"]) missRec := doRequest(t, h, "GetSavingsPlansPurchaseRecommendation", map[string]any{ @@ -243,7 +245,7 @@ func TestGetSavingsPlansPurchaseRecommendationAccountFilterNarrows(t *testing.T) require.Equal(t, http.StatusOK, missRec.Code) var missed map[string]any - require.NoError(t, json.NewDecoder(missRec.Body).Decode(&missed)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(missRec.Body), &missed, jsonx.V1())) assert.Nil(t, missed["SavingsPlansPurchaseRecommendation"]) } @@ -266,7 +268,7 @@ func TestGetReservationPurchaseRecommendationAccountFilterNarrows(t *testing.T) var matched struct { Recommendations []any `json:"Recommendations"` } - require.NoError(t, json.NewDecoder(matchRec.Body).Decode(&matched)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(matchRec.Body), &matched, jsonx.V1())) assert.NotEmpty(t, matched.Recommendations) missRec := doRequest(t, h, "GetReservationPurchaseRecommendation", map[string]any{ @@ -280,7 +282,7 @@ func TestGetReservationPurchaseRecommendationAccountFilterNarrows(t *testing.T) var missed struct { Recommendations []any `json:"Recommendations"` } - require.NoError(t, json.NewDecoder(missRec.Body).Decode(&missed)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(missRec.Body), &missed, jsonx.V1())) assert.Empty(t, missed.Recommendations) } @@ -304,7 +306,7 @@ func TestGetReservationCoverageSortByTimeReorders(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"CoveragesByTime"` } - require.NoError(t, json.NewDecoder(ascRec.Body).Decode(&asc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ascRec.Body), &asc, jsonx.V1())) require.Len(t, asc.CoveragesByTime, 3) assert.Equal(t, "2024-01-01", asc.CoveragesByTime[0].TimePeriod["Start"]) assert.Equal(t, "2024-01-03", asc.CoveragesByTime[2].TimePeriod["Start"]) @@ -322,7 +324,7 @@ func TestGetReservationCoverageSortByTimeReorders(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"CoveragesByTime"` } - require.NoError(t, json.NewDecoder(descRec.Body).Decode(&desc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descRec.Body), &desc, jsonx.V1())) require.Len(t, desc.CoveragesByTime, 3) assert.Equal(t, "2024-01-03", desc.CoveragesByTime[0].TimePeriod["Start"]) assert.Equal(t, "2024-01-01", desc.CoveragesByTime[2].TimePeriod["Start"]) @@ -353,7 +355,7 @@ func TestGetReservationCoverageServiceFilterZeroesCost(t *testing.T) { } `json:"CoverageCost"` } `json:"Total"` } - require.NoError(t, json.NewDecoder(unfilteredRec.Body).Decode(&unfiltered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(unfilteredRec.Body), &unfiltered, jsonx.V1())) require.NotEqual(t, "0.0000", unfiltered.Total.CoverageCost.OnDemandCost) filteredRec := doRequest(t, h, "GetReservationCoverage", map[string]any{ @@ -372,7 +374,7 @@ func TestGetReservationCoverageServiceFilterZeroesCost(t *testing.T) { } `json:"CoverageCost"` } `json:"Total"` } - require.NoError(t, json.NewDecoder(filteredRec.Body).Decode(&filtered)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(filteredRec.Body), &filtered, jsonx.V1())) assert.Equal(t, "0.0000", filtered.Total.CoverageCost.OnDemandCost) } @@ -396,7 +398,7 @@ func TestGetReservationUtilizationSortByTimeReorders(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"UtilizationsByTime"` } - require.NoError(t, json.NewDecoder(descRec.Body).Decode(&desc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descRec.Body), &desc, jsonx.V1())) require.Len(t, desc.UtilizationsByTime, 3) assert.Equal(t, "2024-01-03", desc.UtilizationsByTime[0].TimePeriod["Start"]) assert.Equal(t, "2024-01-01", desc.UtilizationsByTime[2].TimePeriod["Start"]) @@ -424,6 +426,6 @@ func TestGetCostComparisonDriversFilterAccepted(t *testing.T) { var out struct { CostComparisonDrivers []any `json:"CostComparisonDrivers"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.CostComparisonDrivers) } diff --git a/services/ce/handler_reservations_test.go b/services/ce/handler_reservations_test.go index 858e005258..78866bf91d 100644 --- a/services/ce/handler_reservations_test.go +++ b/services/ce/handler_reservations_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -25,7 +27,7 @@ func TestGetReservationCoverage_DailyGranularity(t *testing.T) { var out struct { CoveragesByTime []any `json:"CoveragesByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.CoveragesByTime, 3) } @@ -43,7 +45,7 @@ func TestGetReservationUtilization_DailyGranularity(t *testing.T) { var out struct { UtilizationsByTime []any `json:"UtilizationsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.UtilizationsByTime, 3) } @@ -62,7 +64,7 @@ func TestGetRightsizingRecommendation_IncludesSummary(t *testing.T) { Summary map[string]string `json:"Summary"` RightsizingRecommendations []any `json:"RightsizingRecommendations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.RightsizingRecommendations) assert.NotNil(t, out.Summary) _, hasTotalCount := out.Summary["TotalRecommendationCount"] @@ -92,7 +94,7 @@ func TestGetReservationCoverage_Structure(t *testing.T) { } `json:"Total"` } `json:"CoveragesByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.CoveragesByTime) assert.NotNil(t, out.Total) @@ -121,7 +123,7 @@ func TestGetReservationUtilization_Structure(t *testing.T) { } `json:"Total"` } `json:"UtilizationsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.UtilizationsByTime) assert.NotNil(t, out.Total) @@ -175,7 +177,7 @@ func TestGetReservationPurchaseRecommendation_FieldShape(t *testing.T) { } `json:"RecommendationDetails"` } `json:"Recommendations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.Recommendations) require.NotEmpty(t, out.Recommendations[0].RecommendationDetails) @@ -212,7 +214,7 @@ func TestGetRightsizingRecommendation_FieldShape(t *testing.T) { } `json:"ModifyRecommendationDetail"` } `json:"RightsizingRecommendations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.RightsizingRecommendations) assert.NotNil(t, out.Summary) @@ -253,7 +255,7 @@ func TestHandler_GetReservationCoverage(t *testing.T) { var out struct { CoveragesByTime []any `json:"CoveragesByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.CoveragesByTime) }) } @@ -290,7 +292,7 @@ func TestHandler_GetReservationPurchaseRecommendation(t *testing.T) { var out struct { Recommendations []any `json:"Recommendations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Recommendations) }) } @@ -325,7 +327,7 @@ func TestHandler_GetReservationUtilization(t *testing.T) { var out struct { UtilizationsByTime []any `json:"UtilizationsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.UtilizationsByTime) }) } diff --git a/services/ce/handler_savings_plans_test.go b/services/ce/handler_savings_plans_test.go index 59817097fd..753d359666 100644 --- a/services/ce/handler_savings_plans_test.go +++ b/services/ce/handler_savings_plans_test.go @@ -1,7 +1,8 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -27,7 +29,7 @@ func TestGetSavingsPlanPurchaseRecommendationDetails(t *testing.T) { RecommendationDetailData map[string]any `json:"RecommendationDetailData"` RecommendationDetailID string `json:"RecommendationDetailId"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "detail-abc123", out.RecommendationDetailID) assert.NotEmpty(t, out.RecommendationDetailData) } @@ -56,7 +58,7 @@ func TestListSavingsPlansPurchaseRecommendationGeneration(t *testing.T) { var out struct { GenerationSummaryList []any `json:"GenerationSummaryList"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.GenerationSummaryList) } @@ -75,7 +77,7 @@ func TestStartSavingsPlansPurchaseRecommendationGeneration(t *testing.T) { GenerationStartedTime string `json:"GenerationStartedTime"` EstimatedCompletionTime string `json:"EstimatedCompletionTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.RecommendationID) assert.NotEmpty(t, out.GenerationStartedTime) assert.NotEmpty(t, out.EstimatedCompletionTime) @@ -89,7 +91,7 @@ func TestStartSavingsPlansPurchaseRecommendationGeneration(t *testing.T) { GenerationStatus string `json:"GenerationStatus"` } `json:"GenerationSummaryList"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) require.Len(t, listOut.GenerationSummaryList, 1) assert.Equal(t, out.RecommendationID, listOut.GenerationSummaryList[0].RecommendationID) assert.Equal(t, "PROCESSING", listOut.GenerationSummaryList[0].GenerationStatus) @@ -113,7 +115,7 @@ func TestListSavingsPlansPurchaseRecommendationGeneration_FiltersByStatus(t *tes var out struct { GenerationSummaryList []any `json:"GenerationSummaryList"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.GenerationSummaryList, "job is PROCESSING, must not match a SUCCEEDED filter") } @@ -134,7 +136,7 @@ func TestGetSavingsPlansCoverage(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"SavingsPlansCoverages"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.SavingsPlansCoverages) assert.NotEmpty(t, out.SavingsPlansCoverages[0].Coverage) } @@ -153,7 +155,7 @@ func TestGetSavingsPlansUtilization_DailyGranularity(t *testing.T) { var out struct { SavingsPlansUtilizationsByTime []any `json:"SavingsPlansUtilizationsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.SavingsPlansUtilizationsByTime, 7) } @@ -191,7 +193,7 @@ func TestCeRegion_SavingsPlansCoverageUsesCtxRegion(t *testing.T) { Attributes map[string]string `json:"Attributes"` } `json:"SavingsPlansCoverages"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.SavingsPlansCoverages) assert.Equal(t, tt.wantRegion, out.SavingsPlansCoverages[0].Attributes["Region"]) }) @@ -235,7 +237,7 @@ func TestCeRegion_SavingsPlansPurchaseRecommendationUsesCtxRegion(t *testing.T) RecommendationDetails []map[string]any `json:"SavingsPlansPurchaseRecommendationDetails"` } `json:"SavingsPlansPurchaseRecommendation"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) details := out.SavingsPlansPurchaseRecommendation.RecommendationDetails require.NotEmpty(t, details) spDetails, ok := details[0]["SavingsPlansDetails"].(map[string]any) @@ -291,7 +293,7 @@ func TestGetSavingsPlansUtilization_ReturnsTotalAndByTime(t *testing.T) { } `json:"Total"` SavingsPlansUtilizationsByTime []any `json:"SavingsPlansUtilizationsByTime"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Total.Utilization.TotalCommitment) assert.NotEmpty(t, out.Total.Utilization.UsedCommitment) @@ -320,7 +322,7 @@ func TestGetSavingsPlansUtilizationDetails_ReturnsDetails(t *testing.T) { } `json:"Utilization"` } `json:"SavingsPlansUtilizationDetails"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.SavingsPlansUtilizationDetails) assert.NotNil(t, out.Total) assert.NotEmpty(t, out.TimePeriod) @@ -373,7 +375,7 @@ func TestGetSavingsPlansPurchaseRecommendation_ReturnsRecommendation(t *testing. SavingsPlansPurchaseRecommendationDetails []map[string]any `json:"SavingsPlansPurchaseRecommendationDetails"` } `json:"SavingsPlansPurchaseRecommendation"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.SavingsPlansPurchaseRecommendation.SavingsPlansType) assert.NotEmpty(t, out.SavingsPlansPurchaseRecommendation.SavingsPlansPurchaseRecommendationDetails) assert.NotNil(t, out.Metadata) diff --git a/services/ce/handler_tags_test.go b/services/ce/handler_tags_test.go index 157531ccb5..9d6222fec8 100644 --- a/services/ce/handler_tags_test.go +++ b/services/ce/handler_tags_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -30,7 +32,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) arn := createOut["CostCategoryArn"].(string) // Tag @@ -47,7 +49,7 @@ func TestHandler_TagOperations(t *testing.T) { assert.Equal(t, http.StatusOK, rec3.Code) var listOut map[string]any - require.NoError(t, json.NewDecoder(rec3.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec3.Body), &listOut, jsonx.V1())) tags, _ := listOut["ResourceTags"].([]any) var envVal string for _, tagAny := range tags { @@ -94,7 +96,7 @@ func TestHandler_TagOperations_AnomalyMonitor(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) monitorARN := createOut["MonitorArn"].(string) // Tag. @@ -111,7 +113,7 @@ func TestHandler_TagOperations_AnomalyMonitor(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) tags, _ := listOut["ResourceTags"].([]any) var found bool @@ -153,7 +155,7 @@ func TestHandler_TagOperations_AnomalySubscription(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) subARN := createOut["SubscriptionArn"].(string) // Tag. @@ -170,7 +172,7 @@ func TestHandler_TagOperations_AnomalySubscription(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) tags, _ := listOut["ResourceTags"].([]any) assert.NotEmpty(t, tags) @@ -278,7 +280,7 @@ func TestHandler_ListTagsForResource_EmptyTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) arn := createOut["CostCategoryArn"].(string) listRec := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": arn}) @@ -287,7 +289,7 @@ func TestHandler_ListTagsForResource_EmptyTags(t *testing.T) { var out struct { ResourceTags []map[string]string `json:"ResourceTags"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) // Must be an empty array, not nil/absent. assert.NotNil(t, out.ResourceTags) assert.Empty(t, out.ResourceTags) diff --git a/services/ce/handler_test.go b/services/ce/handler_test.go index 77205600ca..8cc7111f4f 100644 --- a/services/ce/handler_test.go +++ b/services/ce/handler_test.go @@ -3,7 +3,8 @@ package ce_test import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -27,7 +29,7 @@ func doRequestWithMeta( ) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) ctx := awsmeta.Set(context.Background(), meta) @@ -55,7 +57,7 @@ func doRequest(t *testing.T, h *ce.Handler, action string, body any) *httptest.R var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -369,7 +371,7 @@ func TestHandler_Reset(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) refs, _ := listOut["CostCategoryReferences"].([]any) assert.Empty(t, refs) } @@ -472,7 +474,7 @@ func TestHandler_ErrorWireShape(t *testing.T) { var out struct { Type string `json:"__type"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out.Type) }) } diff --git a/services/ce/persistence.go b/services/ce/persistence.go index eb07cbca95..b2f1c2c5da 100644 --- a/services/ce/persistence.go +++ b/services/ce/persistence.go @@ -2,10 +2,12 @@ package ce import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -36,12 +38,12 @@ const ceSnapshotVersion = 1 // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - BackfillJobs []*BackfillJob `json:"backfillJobs"` - AnomalyTTL time.Duration `json:"anomalyTTL"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + BackfillJobs []*BackfillJob `json:"backfillJobs"` + AnomalyTTL time.Duration `json:"anomalyTTL"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -66,7 +68,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { AnomalyTTL: b.anomalyTTL, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ce: failed to marshal snapshot", "error", err) diff --git a/services/ce/persistence_version_test.go b/services/ce/persistence_version_test.go index dd6acf8b81..8bc1a7db62 100644 --- a/services/ce/persistence_version_test.go +++ b/services/ce/persistence_version_test.go @@ -1,12 +1,13 @@ package ce_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ce" ) @@ -18,11 +19,11 @@ func tamperSnapshotVersion(t *testing.T, snap []byte, newVersion int) []byte { var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) raw["version"] = newVersion - out, err := json.Marshal(raw) + out, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) return out @@ -82,10 +83,10 @@ func TestInMemoryBackend_RestoreMissingVersion(t *testing.T) { var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) delete(raw, "version") - legacy, err := json.Marshal(raw) + legacy, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) target := ce.NewInMemoryBackend("000000000000", "us-east-1") diff --git a/services/ce/store.go b/services/ce/store.go index 2b49011d8b..765d332cf0 100644 --- a/services/ce/store.go +++ b/services/ce/store.go @@ -3,12 +3,13 @@ package ce import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -233,7 +234,7 @@ func checkPageTokens(body []byte) error { NextToken string `json:"NextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) for _, tok := range []string{req.NextPageToken, req.NextToken} { if tok == "" { diff --git a/services/ce/usage_validation_test.go b/services/ce/usage_validation_test.go index 00595edad4..d90abe82ec 100644 --- a/services/ce/usage_validation_test.go +++ b/services/ce/usage_validation_test.go @@ -1,13 +1,15 @@ package ce_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func usageBody(start, end, granularity string, extra map[string]any) map[string]any { @@ -59,7 +61,7 @@ func TestGetCostAndUsage_RequestValidation(t *testing.T) { if tt.wantType != "" { var we wireError - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &we)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &we, jsonx.V1())) assert.Contains(t, we.Type, tt.wantType) } }) @@ -80,7 +82,7 @@ func TestGetCostAndUsage_HourlyBuckets(t *testing.T) { TimePeriod map[string]string `json:"TimePeriod"` } `json:"ResultsByTime"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ResultsByTime, 3) assert.Equal(t, "2026-01-01T01:00:00Z", out.ResultsByTime[1].TimePeriod["Start"]) } @@ -127,7 +129,7 @@ func TestRequestEnumValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var we wireError - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &we)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &we, jsonx.V1())) assert.Contains(t, we.Type, "ValidationError") }) } diff --git a/services/cleanrooms/analysis_templates_test.go b/services/cleanrooms/analysis_templates_test.go index 4716b0faed..05f6c9ce30 100644 --- a/services/cleanrooms/analysis_templates_test.go +++ b/services/cleanrooms/analysis_templates_test.go @@ -1,12 +1,14 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAnalysisTemplateHasIDKeys verifies AnalysisTemplate canonical ID keys. @@ -22,14 +24,14 @@ func TestAnalysisTemplateHasIDKeys(t *testing.T) { }) var colResp map[string]any rec := doRequest(t, e, "GET", "/collaborations", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp, jsonx.V1())) colID := colResp["collaborationList"].([]any)[0].(map[string]any)["id"].(string) rec2 := doRequest(t, e, "POST", "/memberships", map[string]any{ "collaborationIdentifier": colID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1())) mID := memResp["membership"].(map[string]any)["id"].(string) // Create analysis template @@ -41,7 +43,7 @@ func TestAnalysisTemplateHasIDKeys(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code, rec3.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) at := resp["analysisTemplate"].(map[string]any) assert.Contains(t, at, "id", "analysisTemplate must have 'id' key") diff --git a/services/cleanrooms/collaborations_test.go b/services/cleanrooms/collaborations_test.go index 06c2ffdf39..7d96cf7719 100644 --- a/services/cleanrooms/collaborations_test.go +++ b/services/cleanrooms/collaborations_test.go @@ -1,12 +1,14 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCollaborationWireShape verifies a Collaboration response uses only the @@ -27,7 +29,7 @@ func TestCollaborationWireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collab := resp["collaboration"].(map[string]any) id, hasID := collab["id"] @@ -58,7 +60,7 @@ func TestCollaborationARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collab := resp["collaboration"].(map[string]any) arn, ok := collab["arn"].(string) @@ -80,7 +82,7 @@ func TestCollaborationQueryLogStatusRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collab := resp["collaboration"].(map[string]any) assert.Equal(t, "ENABLED", collab["queryLogStatus"]) } @@ -101,12 +103,12 @@ func TestCollaborationCreatorMemberAbilities(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collabID := resp["collaboration"].(map[string]any)["id"].(string) listRec := doRequest(t, e, "GET", "/collaborations/"+collabID+"/members", nil) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) members, ok := listResp["memberSummaries"].([]any) require.True(t, ok, "ListMembers must return memberSummaries") require.Len(t, members, 1) @@ -137,7 +139,7 @@ func TestDeleteMember_MarksRemoved(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collabID := resp["collaboration"].(map[string]any)["id"].(string) del := doRequest(t, e, "DELETE", "/collaborations/"+collabID+"/member/222222222222", nil) @@ -146,7 +148,7 @@ func TestDeleteMember_MarksRemoved(t *testing.T) { listRec := doRequest(t, e, "GET", "/collaborations/"+collabID+"/members", nil) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) members := listResp["memberSummaries"].([]any) require.Len(t, members, 2, "removed member must still appear in the member list") @@ -178,7 +180,7 @@ func TestDeleteCollaboration_CascadesMembershipToCollaborationDeleted(t *testing }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collab := resp["collaboration"].(map[string]any) collabID := collab["id"].(string) membershipID := collab["membershipId"].(string) @@ -189,7 +191,7 @@ func TestDeleteCollaboration_CascadesMembershipToCollaborationDeleted(t *testing getRec := doRequest(t, e, "GET", "/memberships/"+membershipID, nil) require.Equal(t, http.StatusOK, getRec.Code, "membership must still be retrievable after collaboration delete") var memResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &memResp, jsonx.V1())) assert.Equal(t, "COLLABORATION_DELETED", memResp["membership"].(map[string]any)["status"]) } @@ -210,7 +212,7 @@ func TestCollaborationChangeRequest_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) collabID := resp["collaboration"].(map[string]any)["id"].(string) createRec := doRequest(t, e, "POST", "/collaborations/"+collabID+"/changeRequests", map[string]any{ @@ -227,7 +229,7 @@ func TestCollaborationChangeRequest_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cr := createResp["collaborationChangeRequest"].(map[string]any) assert.Equal(t, "PENDING", cr["status"]) assert.NotEmpty(t, cr["changes"]) @@ -239,7 +241,7 @@ func TestCollaborationChangeRequest_Lifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, approveRec.Code, approveRec.Body.String()) var approveResp map[string]any - require.NoError(t, json.Unmarshal(approveRec.Body.Bytes(), &approveResp)) + require.NoError(t, json.Unmarshal(approveRec.Body.Bytes(), &approveResp, jsonx.V1())) assert.Equal(t, "APPROVED", approveResp["collaborationChangeRequest"].(map[string]any)["status"]) commitRec := doRequest( @@ -248,7 +250,7 @@ func TestCollaborationChangeRequest_Lifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, commitRec.Code, commitRec.Body.String()) var commitResp map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp, jsonx.V1())) assert.Equal(t, "COMMITTED", commitResp["collaborationChangeRequest"].(map[string]any)["status"]) // COMMIT applies the change's real semantic effect: the ADD_MEMBER change @@ -256,7 +258,7 @@ func TestCollaborationChangeRequest_Lifecycle(t *testing.T) { getRec := doRequest(t, e, "GET", "/collaborations/"+collabID+"/members", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) members, _ := getResp["memberSummaries"].([]any) var found bool for _, m := range members { diff --git a/services/cleanrooms/configured_tables_test.go b/services/cleanrooms/configured_tables_test.go index 697e92b911..0644580c65 100644 --- a/services/cleanrooms/configured_tables_test.go +++ b/services/cleanrooms/configured_tables_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createConfiguredTable(t *testing.T, e *echo.Echo) string { @@ -22,7 +24,7 @@ func createConfiguredTable(t *testing.T, e *echo.Echo) string { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["configuredTable"].(map[string]any)["id"].(string) } @@ -67,7 +69,7 @@ func TestConfiguredTables_Create(t *testing.T) { require.Equal(t, tt.wants.status, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ct := resp["configuredTable"].(map[string]any) id, hasID := ct["id"] @@ -117,7 +119,7 @@ func TestConfiguredTableAnalysisRules_Create(t *testing.T) { require.Equal(t, tt.wants.status, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ar := resp["analysisRule"].(map[string]any) assert.Contains(t, ar, "configuredTableId", "analysisRule must have canonical 'configuredTableId' key") diff --git a/services/cleanrooms/handler.go b/services/cleanrooms/handler.go index e9789412b3..e801accf37 100644 --- a/services/cleanrooms/handler.go +++ b/services/cleanrooms/handler.go @@ -2,7 +2,7 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -464,7 +465,7 @@ func (h *Handler) dispatch( } func mustJSON(v any) []byte { - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return b } diff --git a/services/cleanrooms/handler_analysis_log_exports.go b/services/cleanrooms/handler_analysis_log_exports.go index f7569460a2..f3a88bb684 100644 --- a/services/cleanrooms/handler_analysis_log_exports.go +++ b/services/cleanrooms/handler_analysis_log_exports.go @@ -2,11 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "strconv" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -24,7 +25,7 @@ func (h *Handler) handleStartAnalysisLogExport(_ context.Context, body []byte) ( AnalysisID string `json:"analysisId"` AnalysisType string `json:"analysisType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) e, err := h.Backend.StartAnalysisLogExport( req.MembershipIdentifier, req.AnalysisID, req.AnalysisType, req.ResultConfiguration, @@ -41,7 +42,7 @@ func (h *Handler) handleGetAnalysisLogExport(_ context.Context, body []byte) ([] MembershipIdentifier string `json:"membershipIdentifier"` AnalysisLogExportIdentifier string `json:"analysisLogExportIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) e, err := h.Backend.GetAnalysisLogExport(req.MembershipIdentifier, req.AnalysisLogExportIdentifier) if err != nil { @@ -55,7 +56,7 @@ func (h *Handler) handleListAnalysisLogExports(_ context.Context, body []byte, c var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) limit := 0 if raw := qp(c, exportMaxResultsParamName); raw != "" { diff --git a/services/cleanrooms/handler_analysis_templates.go b/services/cleanrooms/handler_analysis_templates.go index f24b79721a..26abbba470 100644 --- a/services/cleanrooms/handler_analysis_templates.go +++ b/services/cleanrooms/handler_analysis_templates.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetCollaborationAnalysisTemplate( @@ -16,7 +18,7 @@ func (h *Handler) handleGetCollaborationAnalysisTemplate( CollaborationIdentifier string `json:"collaborationIdentifier"` AnalysisTemplateArn string `json:"analysisTemplateArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.GetCollaborationAnalysisTemplate( req.CollaborationIdentifier, req.AnalysisTemplateArn, @@ -36,7 +38,7 @@ func (h *Handler) handleListCollaborationAnalysisTemplates( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationAnalysisTemplates( req.CollaborationIdentifier, qp(c, "maxResults"), @@ -61,7 +63,7 @@ func (h *Handler) handleBatchGetCollaborationAnalysisTemplate( CollaborationIdentifier string `json:"collaborationIdentifier"` AnalysisTemplateArns []string `json:"analysisTemplateArns"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, errs, err := h.Backend.BatchGetCollaborationAnalysisTemplate( req.CollaborationIdentifier, req.AnalysisTemplateArns, @@ -86,7 +88,7 @@ func (h *Handler) handleCreateAnalysisTemplate(_ context.Context, body []byte) ( Format string `json:"format"` AnalysisParameters []map[string]any `json:"analysisParameters"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum("format", crtypes.AnalysisFormat(req.Format)); err != nil { return nil, err } @@ -117,7 +119,7 @@ func (h *Handler) handleGetAnalysisTemplate(_ context.Context, body []byte) ([]b MembershipIdentifier string `json:"membershipIdentifier"` AnalysisTemplateIdentifier string `json:"analysisTemplateIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.GetAnalysisTemplate( req.MembershipIdentifier, req.AnalysisTemplateIdentifier, @@ -137,7 +139,7 @@ func (h *Handler) handleListAnalysisTemplates( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListAnalysisTemplates( req.MembershipIdentifier, qp(c, "maxResults"), @@ -160,7 +162,7 @@ func (h *Handler) handleUpdateAnalysisTemplate(_ context.Context, body []byte) ( AnalysisTemplateIdentifier string `json:"analysisTemplateIdentifier"` Description string `json:"description"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.UpdateAnalysisTemplate( req.MembershipIdentifier, req.AnalysisTemplateIdentifier, @@ -178,7 +180,7 @@ func (h *Handler) handleDeleteAnalysisTemplate(_ context.Context, body []byte) ( MembershipIdentifier string `json:"membershipIdentifier"` AnalysisTemplateIdentifier string `json:"analysisTemplateIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteAnalysisTemplate( req.MembershipIdentifier, diff --git a/services/cleanrooms/handler_analysis_templates_test.go b/services/cleanrooms/handler_analysis_templates_test.go index d4c09bd3ac..2e5bb212ac 100644 --- a/services/cleanrooms/handler_analysis_templates_test.go +++ b/services/cleanrooms/handler_analysis_templates_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAnalysisTemplates_Handlers(t *testing.T) { @@ -20,14 +22,14 @@ func TestAnalysisTemplates_Handlers(t *testing.T) { "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collabID := colResp["collaboration"].(map[string]any)["id"].(string) rec2 := doRequest(t, e, "POST", "/memberships", map[string]any{ "collaborationIdentifier": collabID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - json.Unmarshal(rec2.Body.Bytes(), &memResp) + json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1()) memID := memResp["membership"].(map[string]any)["id"].(string) rec3 := doRequest(t, e, "POST", "/memberships/"+memID+"/analysistemplates", map[string]any{ @@ -36,7 +38,7 @@ func TestAnalysisTemplates_Handlers(t *testing.T) { "source": map[string]any{"text": "SELECT 1"}, }) var atResp map[string]any - json.Unmarshal(rec3.Body.Bytes(), &atResp) + json.Unmarshal(rec3.Body.Bytes(), &atResp, jsonx.V1()) atID := atResp["analysisTemplate"].(map[string]any)["id"].(string) tests := []struct { diff --git a/services/cleanrooms/handler_collaborations.go b/services/cleanrooms/handler_collaborations.go index 49d0543ec9..1fc8dd5d43 100644 --- a/services/cleanrooms/handler_collaborations.go +++ b/services/cleanrooms/handler_collaborations.go @@ -2,12 +2,14 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // collaborationWire shadows the embedded Members tag at depth 0 so the @@ -38,7 +40,7 @@ func (h *Handler) handleCreateCollaboration(_ context.Context, body []byte) ([]b AllowedResultRegions []string `json:"allowedResultRegions"` IsMetricsEnabled bool `json:"isMetricsEnabled"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := firstErr( checkEnumList[crtypes.MemberAbility]("creatorMemberAbilities", req.CreatorMemberAbilities), checkEnum("queryLogStatus", crtypes.CollaborationQueryLogStatus(req.QueryLogStatus)), @@ -86,7 +88,7 @@ func (h *Handler) handleGetCollaboration(_ context.Context, body []byte) ([]byte var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) c, err := h.Backend.GetCollaboration(req.CollaborationIdentifier) if err != nil { return nil, declaredCollaborationError(err) @@ -119,7 +121,7 @@ func (h *Handler) handleUpdateCollaboration(_ context.Context, body []byte) ([]b Description string `json:"description"` AnalyticsEngine string `json:"analyticsEngine"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) col, err := h.Backend.UpdateCollaboration( req.CollaborationIdentifier, req.Name, @@ -137,7 +139,7 @@ func (h *Handler) handleDeleteCollaboration(_ context.Context, body []byte) ([]b var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteCollaboration(req.CollaborationIdentifier) } @@ -150,7 +152,7 @@ func (h *Handler) handleListMembers( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListMembers( req.CollaborationIdentifier, qp(c, "maxResults"), @@ -177,7 +179,7 @@ func (h *Handler) handleDeleteMember(_ context.Context, body []byte) ([]byte, er CollaborationIdentifier string `json:"collaborationIdentifier"` AccountID string `json:"accountId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteMember(req.CollaborationIdentifier, req.AccountID) } @@ -190,7 +192,7 @@ func (h *Handler) handleCreateCollaborationChangeRequest( CollaborationIdentifier string `json:"collaborationIdentifier"` Changes []Change `json:"changes"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) r, err := h.Backend.CreateCollaborationChangeRequest( req.CollaborationIdentifier, req.Changes, @@ -210,7 +212,7 @@ func (h *Handler) handleGetCollaborationChangeRequest( CollaborationIdentifier string `json:"collaborationIdentifier"` ChangeRequestIdentifier string `json:"changeRequestIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) r, err := h.Backend.GetCollaborationChangeRequest( req.CollaborationIdentifier, req.ChangeRequestIdentifier, @@ -230,7 +232,7 @@ func (h *Handler) handleListCollaborationChangeRequests( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationChangeRequests( req.CollaborationIdentifier, qp(c, "status"), @@ -257,7 +259,7 @@ func (h *Handler) handleUpdateCollaborationChangeRequest( ChangeRequestIdentifier string `json:"changeRequestIdentifier"` Action string `json:"action"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) r, err := h.Backend.UpdateCollaborationChangeRequest( req.CollaborationIdentifier, req.ChangeRequestIdentifier, diff --git a/services/cleanrooms/handler_collaborations_test.go b/services/cleanrooms/handler_collaborations_test.go index 624a25773d..7ca3d42596 100644 --- a/services/cleanrooms/handler_collaborations_test.go +++ b/services/cleanrooms/handler_collaborations_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCollaborations_Handlers(t *testing.T) { @@ -22,7 +24,7 @@ func TestCollaborations_Handlers(t *testing.T) { require.Equal(t, http.StatusOK, res.Code) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collabID := colResp["collaboration"].(map[string]any)["id"].(string) tests := []struct { diff --git a/services/cleanrooms/handler_configured_audience_model_associations.go b/services/cleanrooms/handler_configured_audience_model_associations.go index abc4416ece..b2236e3f54 100644 --- a/services/cleanrooms/handler_configured_audience_model_associations.go +++ b/services/cleanrooms/handler_configured_audience_model_associations.go @@ -2,9 +2,11 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetCollaborationConfiguredAudienceModelAssociation( @@ -15,7 +17,7 @@ func (h *Handler) handleGetCollaborationConfiguredAudienceModelAssociation( CollaborationIdentifier string `json:"collaborationIdentifier"` ConfiguredAudienceModelAssociationIdentifier string `json:"configuredAudienceModelAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.GetCollaborationConfiguredAudienceModelAssociation( req.CollaborationIdentifier, req.ConfiguredAudienceModelAssociationIdentifier, @@ -35,7 +37,7 @@ func (h *Handler) handleListCollaborationConfiguredAudienceModelAssociations( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationConfiguredAudienceModelAssociations( req.CollaborationIdentifier, qp(c, "maxResults"), @@ -68,7 +70,7 @@ func (h *Handler) handleCreateConfiguredAudienceModelAssociation( Description string `json:"description"` ManageResourcePolicies bool `json:"manageResourcePolicies"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.CreateConfiguredAudienceModelAssociation( req.MembershipIdentifier, req.ConfiguredAudienceModelArn, @@ -92,7 +94,7 @@ func (h *Handler) handleGetConfiguredAudienceModelAssociation( MembershipIdentifier string `json:"membershipIdentifier"` ConfiguredAudienceModelAssociationIdentifier string `json:"configuredAudienceModelAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.GetConfiguredAudienceModelAssociation( req.MembershipIdentifier, req.ConfiguredAudienceModelAssociationIdentifier, @@ -112,7 +114,7 @@ func (h *Handler) handleListConfiguredAudienceModelAssociations( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListConfiguredAudienceModelAssociations( req.MembershipIdentifier, qp(c, "maxResults"), @@ -139,7 +141,7 @@ func (h *Handler) handleUpdateConfiguredAudienceModelAssociation( Name string `json:"name"` Description string `json:"description"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.UpdateConfiguredAudienceModelAssociation( req.MembershipIdentifier, req.ConfiguredAudienceModelAssociationIdentifier, @@ -161,7 +163,7 @@ func (h *Handler) handleDeleteConfiguredAudienceModelAssociation( MembershipIdentifier string `json:"membershipIdentifier"` ConfiguredAudienceModelAssociationIdentifier string `json:"configuredAudienceModelAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteConfiguredAudienceModelAssociation( req.MembershipIdentifier, diff --git a/services/cleanrooms/handler_configured_audience_model_associations_test.go b/services/cleanrooms/handler_configured_audience_model_associations_test.go index fee26f9899..c7fb6026ea 100644 --- a/services/cleanrooms/handler_configured_audience_model_associations_test.go +++ b/services/cleanrooms/handler_configured_audience_model_associations_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConfiguredAudienceModelAssociations_Handlers(t *testing.T) { @@ -20,14 +22,14 @@ func TestConfiguredAudienceModelAssociations_Handlers(t *testing.T) { "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collabID := colResp["collaboration"].(map[string]any)["id"].(string) rec2 := doRequest(t, e, "POST", "/memberships", map[string]any{ "collaborationIdentifier": collabID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - json.Unmarshal(rec2.Body.Bytes(), &memResp) + json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1()) memID := memResp["membership"].(map[string]any)["id"].(string) tests := []struct { diff --git a/services/cleanrooms/handler_configured_table_associations.go b/services/cleanrooms/handler_configured_table_associations.go index e9af44e4f8..4b7e79d71e 100644 --- a/services/cleanrooms/handler_configured_table_associations.go +++ b/services/cleanrooms/handler_configured_table_associations.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateConfiguredTableAssociation( @@ -20,7 +22,7 @@ func (h *Handler) handleCreateConfiguredTableAssociation( ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` RoleArn string `json:"roleArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.CreateConfiguredTableAssociation( req.MembershipIdentifier, req.Name, @@ -44,7 +46,7 @@ func (h *Handler) handleGetConfiguredTableAssociation( MembershipIdentifier string `json:"membershipIdentifier"` ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.GetConfiguredTableAssociation( req.MembershipIdentifier, req.ConfiguredTableAssociationIdentifier, @@ -64,7 +66,7 @@ func (h *Handler) handleListConfiguredTableAssociations( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListConfiguredTableAssociations( req.MembershipIdentifier, qp(c, "maxResults"), @@ -91,7 +93,7 @@ func (h *Handler) handleUpdateConfiguredTableAssociation( Description string `json:"description"` RoleArn string `json:"roleArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.UpdateConfiguredTableAssociation( req.MembershipIdentifier, req.ConfiguredTableAssociationIdentifier, @@ -113,7 +115,7 @@ func (h *Handler) handleDeleteConfiguredTableAssociation( MembershipIdentifier string `json:"membershipIdentifier"` ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteConfiguredTableAssociation( req.MembershipIdentifier, @@ -131,7 +133,7 @@ func (h *Handler) handleCreateConfiguredTableAssociationAnalysisRule( ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAssociationAnalysisRuleType(req.AnalysisRuleType), @@ -161,7 +163,7 @@ func (h *Handler) handleGetConfiguredTableAssociationAnalysisRule( ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAssociationAnalysisRuleType(req.AnalysisRuleType), @@ -191,7 +193,7 @@ func (h *Handler) handleUpdateConfiguredTableAssociationAnalysisRule( ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAssociationAnalysisRuleType(req.AnalysisRuleType), @@ -221,7 +223,7 @@ func (h *Handler) handleDeleteConfiguredTableAssociationAnalysisRule( ConfiguredTableAssociationIdentifier string `json:"configuredTableAssociationIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAssociationAnalysisRuleType(req.AnalysisRuleType), diff --git a/services/cleanrooms/handler_configured_table_associations_test.go b/services/cleanrooms/handler_configured_table_associations_test.go index e3d7109ec5..946cbd5008 100644 --- a/services/cleanrooms/handler_configured_table_associations_test.go +++ b/services/cleanrooms/handler_configured_table_associations_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConfiguredTableAssociations_Handlers(t *testing.T) { @@ -20,14 +22,14 @@ func TestConfiguredTableAssociations_Handlers(t *testing.T) { "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collabID := colResp["collaboration"].(map[string]any)["id"].(string) rec2 := doRequest(t, e, "POST", "/memberships", map[string]any{ "collaborationIdentifier": collabID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - json.Unmarshal(rec2.Body.Bytes(), &memResp) + json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1()) memID := memResp["membership"].(map[string]any)["id"].(string) rec3 := doRequest(t, e, "POST", "/configuredTables", map[string]any{ @@ -36,7 +38,7 @@ func TestConfiguredTableAssociations_Handlers(t *testing.T) { "allowedColumns": []string{"id"}, "analysisMethod": "DIRECT_QUERY", }) var ctResp map[string]any - json.Unmarshal(rec3.Body.Bytes(), &ctResp) + json.Unmarshal(rec3.Body.Bytes(), &ctResp, jsonx.V1()) ctID := ctResp["configuredTable"].(map[string]any)["id"].(string) tests := []struct { diff --git a/services/cleanrooms/handler_configured_tables.go b/services/cleanrooms/handler_configured_tables.go index 61474b68ad..990d126101 100644 --- a/services/cleanrooms/handler_configured_tables.go +++ b/services/cleanrooms/handler_configured_tables.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateConfiguredTable(_ context.Context, body []byte) ([]byte, error) { @@ -18,7 +20,7 @@ func (h *Handler) handleCreateConfiguredTable(_ context.Context, body []byte) ([ AllowedColumns []string `json:"allowedColumns"` SelectedMethods []string `json:"selectedAnalysisMethods"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := firstErr( checkEnum("analysisMethod", crtypes.AnalysisMethod(req.AnalysisMethod)), @@ -47,7 +49,7 @@ func (h *Handler) handleGetConfiguredTable(_ context.Context, body []byte) ([]by var req struct { ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) ct, err := h.Backend.GetConfiguredTable(req.ConfiguredTableIdentifier) if err != nil { return nil, err @@ -76,7 +78,7 @@ func (h *Handler) handleUpdateConfiguredTable(_ context.Context, body []byte) ([ Description string `json:"description"` SelectedMethods []string `json:"selectedAnalysisMethods"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) ct, err := h.Backend.UpdateConfiguredTable( req.ConfiguredTableIdentifier, req.Name, @@ -94,7 +96,7 @@ func (h *Handler) handleDeleteConfiguredTable(_ context.Context, body []byte) ([ var req struct { ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteConfiguredTable(req.ConfiguredTableIdentifier) } @@ -108,7 +110,7 @@ func (h *Handler) handleCreateConfiguredTableAnalysisRule( ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAnalysisRuleType(req.AnalysisRuleType), @@ -136,7 +138,7 @@ func (h *Handler) handleGetConfiguredTableAnalysisRule( ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAnalysisRuleType(req.AnalysisRuleType), @@ -164,7 +166,7 @@ func (h *Handler) handleUpdateConfiguredTableAnalysisRule( ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAnalysisRuleType(req.AnalysisRuleType), @@ -192,7 +194,7 @@ func (h *Handler) handleDeleteConfiguredTableAnalysisRule( ConfiguredTableIdentifier string `json:"configuredTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.ConfiguredTableAnalysisRuleType(req.AnalysisRuleType), diff --git a/services/cleanrooms/handler_configured_tables_test.go b/services/cleanrooms/handler_configured_tables_test.go index a373d17b35..8f63564886 100644 --- a/services/cleanrooms/handler_configured_tables_test.go +++ b/services/cleanrooms/handler_configured_tables_test.go @@ -1,12 +1,14 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConfiguredTables_Handlers(t *testing.T) { @@ -23,7 +25,7 @@ func TestConfiguredTables_Handlers(t *testing.T) { require.Equal(t, http.StatusOK, res.Code) var ctResp map[string]any - json.Unmarshal(res.Body.Bytes(), &ctResp) + json.Unmarshal(res.Body.Bytes(), &ctResp, jsonx.V1()) ct := ctResp["configuredTable"].(map[string]any) id := ct["id"].(string) diff --git a/services/cleanrooms/handler_id_mapping_tables.go b/services/cleanrooms/handler_id_mapping_tables.go index eb47201eb7..2e56499935 100644 --- a/services/cleanrooms/handler_id_mapping_tables.go +++ b/services/cleanrooms/handler_id_mapping_tables.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateIDMappingTable(_ context.Context, body []byte) ([]byte, error) { @@ -17,7 +19,7 @@ func (h *Handler) handleCreateIDMappingTable(_ context.Context, body []byte) ([] Description string `json:"description"` KmsKeyArn string `json:"kmsKeyArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.CreateIDMappingTable( req.MembershipIdentifier, req.Name, @@ -38,7 +40,7 @@ func (h *Handler) handleGetIDMappingTable(_ context.Context, body []byte) ([]byt MembershipIdentifier string `json:"membershipIdentifier"` IDMappingTableIdentifier string `json:"idMappingTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.GetIDMappingTable(req.MembershipIdentifier, req.IDMappingTableIdentifier) if err != nil { return nil, err @@ -55,7 +57,7 @@ func (h *Handler) handleListIDMappingTables( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListIDMappingTables( req.MembershipIdentifier, qp(c, "maxResults"), @@ -79,7 +81,7 @@ func (h *Handler) handleUpdateIDMappingTable(_ context.Context, body []byte) ([] Description string `json:"description"` KmsKeyArn string `json:"kmsKeyArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.UpdateIDMappingTable( req.MembershipIdentifier, req.IDMappingTableIdentifier, @@ -98,7 +100,7 @@ func (h *Handler) handleDeleteIDMappingTable(_ context.Context, body []byte) ([] MembershipIdentifier string `json:"membershipIdentifier"` IDMappingTableIdentifier string `json:"idMappingTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteIDMappingTable( req.MembershipIdentifier, @@ -112,7 +114,7 @@ func (h *Handler) handlePopulateIDMappingTable(_ context.Context, body []byte) ( IDMappingTableIdentifier string `json:"idMappingTableIdentifier"` JobType string `json:"jobType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch req.JobType { case "", "INCREMENTAL", "BATCH", "DELETE_ONLY": diff --git a/services/cleanrooms/handler_id_namespace_associations.go b/services/cleanrooms/handler_id_namespace_associations.go index 2f678df1ff..ffde89ac6f 100644 --- a/services/cleanrooms/handler_id_namespace_associations.go +++ b/services/cleanrooms/handler_id_namespace_associations.go @@ -2,9 +2,11 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetCollaborationIDNamespaceAssociation( @@ -15,7 +17,7 @@ func (h *Handler) handleGetCollaborationIDNamespaceAssociation( CollaborationIdentifier string `json:"collaborationIdentifier"` IDNamespaceAssociationIdentifier string `json:"idNamespaceAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.GetCollaborationIDNamespaceAssociation( req.CollaborationIdentifier, req.IDNamespaceAssociationIdentifier, @@ -35,7 +37,7 @@ func (h *Handler) handleListCollaborationIDNamespaceAssociations( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationIDNamespaceAssociations( req.CollaborationIdentifier, qp(c, "maxResults"), @@ -64,7 +66,7 @@ func (h *Handler) handleCreateIDNamespaceAssociation( Name string `json:"name"` Description string `json:"description"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.CreateIDNamespaceAssociation( req.MembershipIdentifier, req.Name, @@ -85,7 +87,7 @@ func (h *Handler) handleGetIDNamespaceAssociation(_ context.Context, body []byte MembershipIdentifier string `json:"membershipIdentifier"` IDNamespaceAssociationIdentifier string `json:"idNamespaceAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.GetIDNamespaceAssociation( req.MembershipIdentifier, req.IDNamespaceAssociationIdentifier, @@ -105,7 +107,7 @@ func (h *Handler) handleListIDNamespaceAssociations( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListIDNamespaceAssociations( req.MembershipIdentifier, qp(c, "maxResults"), @@ -132,7 +134,7 @@ func (h *Handler) handleUpdateIDNamespaceAssociation( IDNamespaceAssociationIdentifier string `json:"idNamespaceAssociationIdentifier"` Description string `json:"description"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) a, err := h.Backend.UpdateIDNamespaceAssociation( req.MembershipIdentifier, req.IDNamespaceAssociationIdentifier, @@ -154,7 +156,7 @@ func (h *Handler) handleDeleteIDNamespaceAssociation( MembershipIdentifier string `json:"membershipIdentifier"` IDNamespaceAssociationIdentifier string `json:"idNamespaceAssociationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteIDNamespaceAssociation( req.MembershipIdentifier, diff --git a/services/cleanrooms/handler_intermediate_tables.go b/services/cleanrooms/handler_intermediate_tables.go index 974457f51a..d8c6e384a3 100644 --- a/services/cleanrooms/handler_intermediate_tables.go +++ b/services/cleanrooms/handler_intermediate_tables.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateIntermediateTable(_ context.Context, body []byte) ([]byte, error) { @@ -18,7 +20,7 @@ func (h *Handler) handleCreateIntermediateTable(_ context.Context, body []byte) KmsKeyArn string `json:"kmsKeyArn"` RetentionInDays int32 `json:"retentionInDays"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) it, err := h.Backend.CreateIntermediateTable( req.MembershipIdentifier, req.Name, @@ -40,7 +42,7 @@ func (h *Handler) handleGetIntermediateTable(_ context.Context, body []byte) ([] MembershipIdentifier string `json:"membershipIdentifier"` IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) it, err := h.Backend.GetIntermediateTable(req.MembershipIdentifier, req.IntermediateTableIdentifier) if err != nil { return nil, err @@ -57,7 +59,7 @@ func (h *Handler) handleListIntermediateTables( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListIntermediateTables( req.MembershipIdentifier, qp(c, "maxResults"), @@ -81,7 +83,7 @@ func (h *Handler) handleUpdateIntermediateTable(_ context.Context, body []byte) Description string `json:"description"` KmsKeyArn string `json:"kmsKeyArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) it, err := h.Backend.UpdateIntermediateTable( req.MembershipIdentifier, req.IntermediateTableIdentifier, @@ -100,7 +102,7 @@ func (h *Handler) handleDeleteIntermediateTable(_ context.Context, body []byte) MembershipIdentifier string `json:"membershipIdentifier"` IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteIntermediateTable(req.MembershipIdentifier, req.IntermediateTableIdentifier) } @@ -114,7 +116,7 @@ func (h *Handler) handleListIntermediateTableVersions( MembershipIdentifier string `json:"membershipIdentifier"` IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListIntermediateTableVersions( req.MembershipIdentifier, req.IntermediateTableIdentifier, @@ -143,7 +145,7 @@ func (h *Handler) handlePopulateIntermediateTable(_ context.Context, body []byte IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` AnalysisPayerAccountID string `json:"analysisPayerAccountId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) result, err := h.Backend.PopulateIntermediateTable( req.MembershipIdentifier, req.IntermediateTableIdentifier, @@ -164,7 +166,7 @@ func (h *Handler) handleDisallowIntermediateTable(_ context.Context, body []byte MembershipIdentifier string `json:"membershipIdentifier"` IntermediateTableName string `json:"intermediateTableName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) // IncludeDescendants defaults to true on the wire (see // DisallowIntermediateTableInput's doc comment in the real SDK). includeDescendants := true @@ -184,7 +186,7 @@ func (h *Handler) handleCreateIntermediateTableAnalysisRule(_ context.Context, b IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.IntermediateTableAnalysisRuleType(req.AnalysisRuleType), @@ -211,7 +213,7 @@ func (h *Handler) handleGetIntermediateTableAnalysisRule(_ context.Context, body IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) r, err := h.Backend.GetIntermediateTableAnalysisRule( req.MembershipIdentifier, req.IntermediateTableIdentifier, @@ -231,7 +233,7 @@ func (h *Handler) handleUpdateIntermediateTableAnalysisRule(_ context.Context, b IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.IntermediateTableAnalysisRuleType(req.AnalysisRuleType), @@ -258,7 +260,7 @@ func (h *Handler) handleDeleteIntermediateTableAnalysisRule(_ context.Context, b IntermediateTableIdentifier string `json:"intermediateTableIdentifier"` AnalysisRuleType string `json:"analysisRuleType"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum( "analysisRuleType", crtypes.IntermediateTableAnalysisRuleType(req.AnalysisRuleType), diff --git a/services/cleanrooms/handler_memberships.go b/services/cleanrooms/handler_memberships.go index ee5184e3f4..c1e5c3283f 100644 --- a/services/cleanrooms/handler_memberships.go +++ b/services/cleanrooms/handler_memberships.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateMembership(_ context.Context, body []byte) ([]byte, error) { @@ -20,7 +22,7 @@ func (h *Handler) handleCreateMembership(_ context.Context, body []byte) ([]byte MemberAbilities []string `json:"memberAbilities"` IsMetricsEnabled bool `json:"isMetricsEnabled"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := firstErr( checkEnum("queryLogStatus", crtypes.MembershipQueryLogStatus(req.QueryLogStatus)), checkEnum("jobLogStatus", crtypes.MembershipJobLogStatus(req.JobLogStatus)), @@ -50,7 +52,7 @@ func (h *Handler) handleGetMembership(_ context.Context, body []byte) ([]byte, e var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) m, err := h.Backend.GetMembership(req.MembershipIdentifier) if err != nil { return nil, err @@ -84,7 +86,7 @@ func (h *Handler) handleUpdateMembership(_ context.Context, body []byte) ([]byte QueryLogStatus string `json:"queryLogStatus"` JobLogStatus string `json:"jobLogStatus"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := firstErr( checkEnum("jobLogStatus", crtypes.MembershipJobLogStatus(req.JobLogStatus)), checkEnum("queryLogStatus", crtypes.MembershipQueryLogStatus(req.QueryLogStatus)), @@ -110,7 +112,7 @@ func (h *Handler) handleDeleteMembership(_ context.Context, body []byte) ([]byte var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeleteMembership(req.MembershipIdentifier) } diff --git a/services/cleanrooms/handler_privacy_budgets.go b/services/cleanrooms/handler_privacy_budgets.go index 00d6f523d1..dcd7b5108b 100644 --- a/services/cleanrooms/handler_privacy_budgets.go +++ b/services/cleanrooms/handler_privacy_budgets.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetCollaborationPrivacyBudgetTemplate( @@ -16,7 +18,7 @@ func (h *Handler) handleGetCollaborationPrivacyBudgetTemplate( CollaborationIdentifier string `json:"collaborationIdentifier"` PrivacyBudgetTemplateIdentifier string `json:"privacyBudgetTemplateIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.GetCollaborationPrivacyBudgetTemplate( req.CollaborationIdentifier, req.PrivacyBudgetTemplateIdentifier, @@ -36,7 +38,7 @@ func (h *Handler) handleListCollaborationPrivacyBudgetTemplates( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationPrivacyBudgetTemplates( req.CollaborationIdentifier, qp(c, "maxResults"), @@ -61,7 +63,7 @@ func (h *Handler) handleListCollaborationPrivacyBudgets( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListCollaborationPrivacyBudgets( req.CollaborationIdentifier, qp(c, "privacyBudgetType"), @@ -90,7 +92,7 @@ func (h *Handler) handleCreatePrivacyBudgetTemplate( PrivacyBudgetType string `json:"privacyBudgetType"` AutoRefresh string `json:"autoRefresh"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum("privacyBudgetType", crtypes.PrivacyBudgetType(req.PrivacyBudgetType)); err != nil { return nil, err } @@ -114,7 +116,7 @@ func (h *Handler) handleGetPrivacyBudgetTemplate(_ context.Context, body []byte) MembershipIdentifier string `json:"membershipIdentifier"` PrivacyBudgetTemplateIdentifier string `json:"privacyBudgetTemplateIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.GetPrivacyBudgetTemplate( req.MembershipIdentifier, req.PrivacyBudgetTemplateIdentifier, @@ -134,7 +136,7 @@ func (h *Handler) handleListPrivacyBudgetTemplates( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListPrivacyBudgetTemplates( req.MembershipIdentifier, qp(c, "privacyBudgetType"), @@ -162,7 +164,7 @@ func (h *Handler) handleUpdatePrivacyBudgetTemplate( PrivacyBudgetTemplateIdentifier string `json:"privacyBudgetTemplateIdentifier"` AutoRefresh string `json:"autoRefresh"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) t, err := h.Backend.UpdatePrivacyBudgetTemplate( req.MembershipIdentifier, req.PrivacyBudgetTemplateIdentifier, @@ -184,7 +186,7 @@ func (h *Handler) handleDeletePrivacyBudgetTemplate( MembershipIdentifier string `json:"membershipIdentifier"` PrivacyBudgetTemplateIdentifier string `json:"privacyBudgetTemplateIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.DeletePrivacyBudgetTemplate( req.MembershipIdentifier, @@ -200,7 +202,7 @@ func (h *Handler) handleListPrivacyBudgets( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListPrivacyBudgets( req.MembershipIdentifier, qp(c, "privacyBudgetType"), @@ -223,7 +225,7 @@ func (h *Handler) handlePreviewPrivacyImpact(_ context.Context, body []byte) ([] Parameters map[string]any `json:"parameters"` MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) result, err := h.Backend.PreviewPrivacyImpact(req.MembershipIdentifier, req.Parameters) if err != nil { return nil, err diff --git a/services/cleanrooms/handler_protected_jobs.go b/services/cleanrooms/handler_protected_jobs.go index 7001ced7f6..88a64fe9a8 100644 --- a/services/cleanrooms/handler_protected_jobs.go +++ b/services/cleanrooms/handler_protected_jobs.go @@ -2,9 +2,11 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // protectedJobWire shadows the request-only "type" key; types.ProtectedJob has no type member. @@ -23,7 +25,7 @@ func (h *Handler) handleStartProtectedJob(_ context.Context, body []byte) ([]byt Type string `json:"type"` PayerAccountID string `json:"jobComputePayerAccountId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) j, err := h.Backend.StartProtectedJob( req.MembershipIdentifier, req.Type, @@ -43,7 +45,7 @@ func (h *Handler) handleGetProtectedJob(_ context.Context, body []byte) ([]byte, MembershipIdentifier string `json:"membershipIdentifier"` ProtectedJobIdentifier string `json:"protectedJobIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) j, err := h.Backend.GetProtectedJob(req.MembershipIdentifier, req.ProtectedJobIdentifier) if err != nil { return nil, err @@ -60,7 +62,7 @@ func (h *Handler) handleListProtectedJobs( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListProtectedJobs( req.MembershipIdentifier, qp(c, "status"), @@ -84,7 +86,7 @@ func (h *Handler) handleUpdateProtectedJob(_ context.Context, body []byte) ([]by ProtectedJobIdentifier string `json:"protectedJobIdentifier"` TargetStatus string `json:"targetStatus"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) j, err := h.Backend.UpdateProtectedJob( req.MembershipIdentifier, req.ProtectedJobIdentifier, diff --git a/services/cleanrooms/handler_protected_jobs_test.go b/services/cleanrooms/handler_protected_jobs_test.go index 68ea59ca33..5f628c6a71 100644 --- a/services/cleanrooms/handler_protected_jobs_test.go +++ b/services/cleanrooms/handler_protected_jobs_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestProtectedJobs_Handlers(t *testing.T) { @@ -20,14 +22,14 @@ func TestProtectedJobs_Handlers(t *testing.T) { "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collabID := colResp["collaboration"].(map[string]any)["id"].(string) rec2 := doRequest(t, e, "POST", "/memberships", map[string]any{ "collaborationIdentifier": collabID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - json.Unmarshal(rec2.Body.Bytes(), &memResp) + json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1()) memID := memResp["membership"].(map[string]any)["id"].(string) tests := []struct { diff --git a/services/cleanrooms/handler_protected_queries.go b/services/cleanrooms/handler_protected_queries.go index c85a1d324c..b6c0d1883a 100644 --- a/services/cleanrooms/handler_protected_queries.go +++ b/services/cleanrooms/handler_protected_queries.go @@ -2,9 +2,11 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleStartProtectedQuery(_ context.Context, body []byte) ([]byte, error) { @@ -16,7 +18,7 @@ func (h *Handler) handleStartProtectedQuery(_ context.Context, body []byte) ([]b MembershipIdentifier string `json:"membershipIdentifier"` PayerAccountID string `json:"queryComputePayerAccountId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := validateProtectedType(req.Type); err != nil { return nil, err @@ -41,7 +43,7 @@ func (h *Handler) handleGetProtectedQuery(_ context.Context, body []byte) ([]byt MembershipIdentifier string `json:"membershipIdentifier"` ProtectedQueryIdentifier string `json:"protectedQueryIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) q, err := h.Backend.GetProtectedQuery(req.MembershipIdentifier, req.ProtectedQueryIdentifier) if err != nil { return nil, err @@ -58,7 +60,7 @@ func (h *Handler) handleListProtectedQueries( var req struct { MembershipIdentifier string `json:"membershipIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListProtectedQueries( req.MembershipIdentifier, qp(c, "status"), @@ -82,7 +84,7 @@ func (h *Handler) handleUpdateProtectedQuery(_ context.Context, body []byte) ([] ProtectedQueryIdentifier string `json:"protectedQueryIdentifier"` TargetStatus string `json:"targetStatus"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := validateTargetStatus(req.TargetStatus); err != nil { return nil, err diff --git a/services/cleanrooms/handler_routing.go b/services/cleanrooms/handler_routing.go index 50ab501e41..0fde29aeb3 100644 --- a/services/cleanrooms/handler_routing.go +++ b/services/cleanrooms/handler_routing.go @@ -1,9 +1,12 @@ package cleanrooms import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // classifyPath maps (method, path) to an operation name and primary resource. @@ -643,17 +646,17 @@ func injectPathParams(path, _ string, body []byte) []byte { path = strings.TrimPrefix(path, "/") segs := strings.Split(path, "/") - var m map[string]json.RawMessage + var m map[string]jsontext.Value if len(body) > 0 { - _ = json.Unmarshal(body, &m) + _ = json.Unmarshal(body, &m, jsonx.V1()) } if m == nil { - m = make(map[string]json.RawMessage) + m = make(map[string]jsontext.Value) } setStr := func(key, val string) { if val != "" { - b, _ := json.Marshal(val) + b, _ := json.Marshal(val, jsonx.V1()) m[key] = b } } @@ -673,7 +676,7 @@ func injectPathParams(path, _ string, body []byte) []byte { setStr("resourceArn", arnVal) } - out, _ := json.Marshal(m) + out, _ := json.Marshal(m, jsonx.V1()) return out } diff --git a/services/cleanrooms/handler_schemas.go b/services/cleanrooms/handler_schemas.go index 9921c283c3..c4f5226da6 100644 --- a/services/cleanrooms/handler_schemas.go +++ b/services/cleanrooms/handler_schemas.go @@ -2,10 +2,12 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" crtypes "github.com/aws/aws-sdk-go-v2/service/cleanrooms/types" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleBatchGetSchema(_ context.Context, body []byte) ([]byte, error) { @@ -13,7 +15,7 @@ func (h *Handler) handleBatchGetSchema(_ context.Context, body []byte) ([]byte, CollaborationIdentifier string `json:"collaborationIdentifier"` Names []string `json:"names"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, errs, err := h.Backend.BatchGetSchema(req.CollaborationIdentifier, req.Names) if err != nil { return nil, err @@ -30,7 +32,7 @@ func (h *Handler) handleBatchGetSchemaAnalysisRule(_ context.Context, body []byt Type string `json:"type"` } `json:"schemaAnalysisRuleRequests"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) names := make([]string, 0, len(req.SchemaAnalysisRuleRequests)) var ruleType string for _, r := range req.SchemaAnalysisRuleRequests { @@ -56,7 +58,7 @@ func (h *Handler) handleGetSchema(_ context.Context, body []byte) ([]byte, error CollaborationIdentifier string `json:"collaborationIdentifier"` Name string `json:"name"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) s, err := h.Backend.GetSchema(req.CollaborationIdentifier, req.Name) if err != nil { return nil, err @@ -73,7 +75,7 @@ func (h *Handler) handleListSchemas( var req struct { CollaborationIdentifier string `json:"collaborationIdentifier"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) items, next, err := h.Backend.ListSchemas( req.CollaborationIdentifier, qp(c, "schemaType"), @@ -97,7 +99,7 @@ func (h *Handler) handleGetSchemaAnalysisRule(_ context.Context, body []byte) ([ Name string `json:"name"` Type string `json:"type"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := checkEnum("type", crtypes.AnalysisRuleType(req.Type)); err != nil { return nil, err } diff --git a/services/cleanrooms/handler_schemas_test.go b/services/cleanrooms/handler_schemas_test.go index d15490b244..5bb05ed47d 100644 --- a/services/cleanrooms/handler_schemas_test.go +++ b/services/cleanrooms/handler_schemas_test.go @@ -1,12 +1,14 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSchemas_Handlers(t *testing.T) { @@ -23,7 +25,7 @@ func TestSchemas_Handlers(t *testing.T) { require.Equal(t, http.StatusOK, res.Code) var colResp map[string]any - json.Unmarshal(res.Body.Bytes(), &colResp) + json.Unmarshal(res.Body.Bytes(), &colResp, jsonx.V1()) collab := colResp["collaboration"].(map[string]any) collabID := collab["id"].(string) diff --git a/services/cleanrooms/handler_tags.go b/services/cleanrooms/handler_tags.go index e259526472..44ceb5a767 100644 --- a/services/cleanrooms/handler_tags.go +++ b/services/cleanrooms/handler_tags.go @@ -2,16 +2,18 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]byte, error) { var req struct { ResourceArn string `json:"resourceArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) tags, err := h.Backend.ListTagsForResource(req.ResourceArn) if err != nil { return nil, err @@ -25,7 +27,7 @@ func (h *Handler) handleTagResource(_ context.Context, body []byte) ([]byte, err Tags map[string]string `json:"tags"` ResourceArn string `json:"resourceArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return nil, h.Backend.TagResource(req.ResourceArn, req.Tags) } @@ -39,7 +41,7 @@ func (h *Handler) handleUntagResource( ResourceArn string `json:"resourceArn"` TagKeys []string `json:"tagKeys"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) // tagKeys can also come from query params if len(req.TagKeys) == 0 { req.TagKeys = c.Request().URL.Query()["tagKeys"] diff --git a/services/cleanrooms/handler_test.go b/services/cleanrooms/handler_test.go index 11206a13ad..f3e8ae551e 100644 --- a/services/cleanrooms/handler_test.go +++ b/services/cleanrooms/handler_test.go @@ -2,13 +2,15 @@ package cleanrooms_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cleanrooms" ) @@ -32,7 +34,7 @@ func doRequest( var reqBody []byte if body != nil { var err error - reqBody, err = json.Marshal(body) + reqBody, err = json.Marshal(body, jsonx.V1()) if err != nil { t.Fatalf("marshal request: %v", err) } @@ -65,7 +67,7 @@ func TestCollaborationCRUD(t *testing.T) { t.Fatalf("create: status %d want %d: %s", rec.Code, http.StatusOK, rec.Body.String()) } var createResp map[string]any - if err := json.NewDecoder(rec.Body).Decode(&createResp); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1()); err != nil { t.Fatalf("decode create: %v", err) } if _, ok := createResp["collaboration"]; !ok { @@ -79,7 +81,7 @@ func TestCollaborationCRUD(t *testing.T) { t.Fatalf("list: status %d want %d: %s", rec.Code, http.StatusOK, rec.Body.String()) } var listResp map[string]any - if err := json.NewDecoder(rec.Body).Decode(&listResp); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1()); err != nil { t.Fatalf("decode list: %v", err) } if _, ok := listResp["collaborationList"]; !ok { @@ -126,7 +128,7 @@ func TestConfiguredTableCRUD(t *testing.T) { t.Fatalf("create: status %d want %d: %s", rec.Code, http.StatusOK, rec.Body.String()) } var createResp map[string]any - if err := json.NewDecoder(rec.Body).Decode(&createResp); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1()); err != nil { t.Fatalf("decode: %v", err) } ctID := createResp["configuredTable"].(map[string]any)["id"].(string) @@ -173,7 +175,7 @@ func TestMembershipCRUD(t *testing.T) { t.Fatalf("create collab: %s", colRec.Body.String()) } var colResp map[string]any - _ = json.NewDecoder(colRec.Body).Decode(&colResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(colRec.Body), &colResp, jsonx.V1()) colID := colResp["collaboration"].(map[string]any)["id"].(string) createBody := map[string]any{ @@ -187,7 +189,7 @@ func TestMembershipCRUD(t *testing.T) { t.Fatalf("create: status %d want %d: %s", rec.Code, http.StatusOK, rec.Body.String()) } var createResp map[string]any - _ = json.NewDecoder(rec.Body).Decode(&createResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1()) mID := createResp["membership"].(map[string]any)["id"].(string) // List memberships @@ -223,7 +225,7 @@ func TestTagOperations(t *testing.T) { "creatorMemberAbilities": []string{}, "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - _ = json.NewDecoder(colRec.Body).Decode(&colResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(colRec.Body), &colResp, jsonx.V1()) testARN := colResp["collaboration"].(map[string]any)["arn"].(string) // Tag resource @@ -293,14 +295,14 @@ func TestProtectedQueryLifecycle(t *testing.T) { "creatorMemberAbilities": []string{}, "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - _ = json.NewDecoder(colRec.Body).Decode(&colResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(colRec.Body), &colResp, jsonx.V1()) colID := colResp["collaboration"].(map[string]any)["id"].(string) // Create membership memRec := doRequest(t, e, http.MethodPost, "/memberships", map[string]any{"collaborationIdentifier": colID, "queryLogStatus": "DISABLED"}) var memResp map[string]any - _ = json.NewDecoder(memRec.Body).Decode(&memResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(memRec.Body), &memResp, jsonx.V1()) mID := memResp["membership"].(map[string]any)["id"].(string) // Start protected query @@ -313,7 +315,7 @@ func TestProtectedQueryLifecycle(t *testing.T) { t.Fatalf("start query: status %d: %s", rec.Code, rec.Body.String()) } var resp map[string]any - _ = json.NewDecoder(rec.Body).Decode(&resp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1()) if _, ok := resp["protectedQuery"]; !ok { t.Fatal("missing protectedQuery in response") } diff --git a/services/cleanrooms/id_mapping_tables_test.go b/services/cleanrooms/id_mapping_tables_test.go index b06b8f5950..5aad3ecbed 100644 --- a/services/cleanrooms/id_mapping_tables_test.go +++ b/services/cleanrooms/id_mapping_tables_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHTTP_PopulateIDMappingTable(t *testing.T) { @@ -22,7 +24,7 @@ func TestHTTP_PopulateIDMappingTable(t *testing.T) { }) rec := doRequest(t, e, "GET", "/collaborations", nil) var colResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp, jsonx.V1())) colID := colResp["collaborationList"].([]any)[0].(map[string]any)["id"].(string) // Create Membership @@ -30,7 +32,7 @@ func TestHTTP_PopulateIDMappingTable(t *testing.T) { "collaborationIdentifier": colID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1())) mID := memResp["membership"].(map[string]any)["id"].(string) // Create Table @@ -44,7 +46,7 @@ func TestHTTP_PopulateIDMappingTable(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["idMappingTable"]["id"].(string) // Populate @@ -68,7 +70,7 @@ func createIntermediateTable(t *testing.T, e *echo.Echo, mID string) string { }) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["intermediateTable"].(map[string]any)["id"].(string) } @@ -220,7 +222,7 @@ func TestHTTP_UpdateIntermediateTable(t *testing.T) { map[string]any{"description": "updated"}) require.Equal(t, http.StatusOK, updRec.Code, updRec.Body.String()) var updResp map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) assert.Equal(t, "updated", updResp["intermediateTable"].(map[string]any)["description"]) }) } @@ -268,7 +270,7 @@ func TestHTTP_UpdateIntermediateTableAnalysisRule(t *testing.T) { "/memberships/"+mID+"/intermediateTables/"+tableID+"/analysisRule/CUSTOM", nil) require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rule := getResp["analysisRule"].(map[string]any) policy := rule["analysisRulePolicy"].(map[string]any) v1 := policy["v1"].(map[string]any) @@ -312,7 +314,7 @@ func TestHTTP_PopulateIntermediateTable_AdvancesToSuccess(t *testing.T) { "/memberships/"+mID+"/intermediateTables/"+tableID+"/populate", nil) require.Equal(t, http.StatusOK, popRec.Code, popRec.Body.String()) var popResp map[string]any - require.NoError(t, json.Unmarshal(popRec.Body.Bytes(), &popResp)) + require.NoError(t, json.Unmarshal(popRec.Body.Bytes(), &popResp, jsonx.V1())) assert.Equal(t, tt.wants.analysisType, popResp["analysisType"]) assert.NotEmpty(t, popResp["analysisId"]) assert.NotEmpty(t, popResp["versionId"]) @@ -321,7 +323,7 @@ func TestHTTP_PopulateIntermediateTable_AdvancesToSuccess(t *testing.T) { "/memberships/"+mID+"/intermediateTables/"+tableID, nil) require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) it := getResp["intermediateTable"].(map[string]any) assert.Equal(t, "POPULATE_SUCCESS", it["status"]) assert.Contains(t, it, "intermediateTableVersion") @@ -332,7 +334,7 @@ func TestHTTP_PopulateIntermediateTable_AdvancesToSuccess(t *testing.T) { "/memberships/"+mID+"/intermediateTables/"+tableID+"/versions", nil) require.Equal(t, http.StatusOK, verRec.Code, verRec.Body.String()) var verResp map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp, jsonx.V1())) versions, ok := verResp["intermediateTableVersionSummaries"].([]any) require.True(t, ok) require.Len(t, versions, 1) @@ -429,7 +431,7 @@ func TestIntermediateTables_WireShape(t *testing.T) { getRec := doRequest(t, e, http.MethodGet, "/memberships/"+mID+"/intermediateTables/"+tableID, nil) require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) it := getResp["intermediateTable"].(map[string]any) assert.Contains(t, it, "id") assert.NotContains(t, it, "intermediateTableIdentifier") @@ -446,7 +448,7 @@ func TestIntermediateTables_WireShape(t *testing.T) { }) require.Equal(t, http.StatusOK, ruleRec.Code, ruleRec.Body.String()) var ruleResp map[string]any - require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp)) + require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp, jsonx.V1())) rule := ruleResp["analysisRule"].(map[string]any) assert.Contains(t, rule, "intermediateTableIdentifier") assert.Equal(t, tableID, rule["intermediateTableIdentifier"]) diff --git a/services/cleanrooms/id_namespace_associations_test.go b/services/cleanrooms/id_namespace_associations_test.go index 69e1698f56..b06227e2e3 100644 --- a/services/cleanrooms/id_namespace_associations_test.go +++ b/services/cleanrooms/id_namespace_associations_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createIDNamespaceAssociation(t *testing.T, e *echo.Echo, mID string) string { @@ -21,7 +23,7 @@ func createIDNamespaceAssociation(t *testing.T, e *echo.Echo, mID string) string }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) return createResp["idNamespaceAssociation"]["id"].(string) } diff --git a/services/cleanrooms/list_configured_table_associations_rule_types_test.go b/services/cleanrooms/list_configured_table_associations_rule_types_test.go index 497cab0016..007278aff2 100644 --- a/services/cleanrooms/list_configured_table_associations_rule_types_test.go +++ b/services/cleanrooms/list_configured_table_associations_rule_types_test.go @@ -1,11 +1,13 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListConfiguredTableAssociations_SummaryHasAnalysisRuleTypes proves @@ -30,14 +32,14 @@ func TestListConfiguredTableAssociations_SummaryHasAnalysisRuleTypes(t *testing. "members": []any{}, "queryLogStatus": "DISABLED", }) var colResp map[string]any - require.NoError(t, json.Unmarshal(colRec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(colRec.Body.Bytes(), &colResp, jsonx.V1())) collabID := colResp["collaboration"].(map[string]any)["id"].(string) memRec := doRequest(t, e, http.MethodPost, "/memberships", map[string]any{ "collaborationIdentifier": collabID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &memResp, jsonx.V1())) memID := memResp["membership"].(map[string]any)["id"].(string) ctRec := doRequest(t, e, http.MethodPost, "/configuredTables", map[string]any{ @@ -46,7 +48,7 @@ func TestListConfiguredTableAssociations_SummaryHasAnalysisRuleTypes(t *testing. "allowedColumns": []string{"id"}, "analysisMethod": "DIRECT_QUERY", }) var ctResp map[string]any - require.NoError(t, json.Unmarshal(ctRec.Body.Bytes(), &ctResp)) + require.NoError(t, json.Unmarshal(ctRec.Body.Bytes(), &ctResp, jsonx.V1())) ctID := ctResp["configuredTable"].(map[string]any)["id"].(string) ctaRec := doRequest(t, e, http.MethodPost, "/memberships/"+memID+"/configuredTableAssociations", map[string]any{ @@ -56,7 +58,7 @@ func TestListConfiguredTableAssociations_SummaryHasAnalysisRuleTypes(t *testing. }) require.Equal(t, http.StatusOK, ctaRec.Code) var ctaResp map[string]any - require.NoError(t, json.Unmarshal(ctaRec.Body.Bytes(), &ctaResp)) + require.NoError(t, json.Unmarshal(ctaRec.Body.Bytes(), &ctaResp, jsonx.V1())) ctaID := ctaResp["configuredTableAssociation"].(map[string]any)["id"].(string) ruleRec := doRequest( @@ -74,7 +76,7 @@ func TestListConfiguredTableAssociations_SummaryHasAnalysisRuleTypes(t *testing. var listResp struct { Summaries []map[string]any `json:"configuredTableAssociationSummaries"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Summaries, 1) ruleTypes, ok := listResp.Summaries[0]["analysisRuleTypes"].([]any) diff --git a/services/cleanrooms/memberships_test.go b/services/cleanrooms/memberships_test.go index 57048cce96..6ffc75e8e9 100644 --- a/services/cleanrooms/memberships_test.go +++ b/services/cleanrooms/memberships_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createMembership(t *testing.T, e *echo.Echo, colID string, queryLog string) (map[string]any, string) { @@ -19,7 +21,7 @@ func createMembership(t *testing.T, e *echo.Echo, colID string, queryLog string) }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mem := resp["membership"].(map[string]any) @@ -35,7 +37,7 @@ func createBaseCollaboration(t *testing.T, e *echo.Echo, name string) string { }) var colResp map[string]any rec := doRequest(t, e, "GET", "/collaborations", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp, jsonx.V1())) return colResp["collaborationList"].([]any)[0].(map[string]any)["id"].(string) } @@ -135,7 +137,7 @@ func TestMemberships_List(t *testing.T) { require.Equal(t, tt.wants.status, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["membershipSummaries"].([]any) require.Len(t, summaries, 2) summary := summaries[0].(map[string]any) diff --git a/services/cleanrooms/overwide_collaboration_list_test.go b/services/cleanrooms/overwide_collaboration_list_test.go index 9787ac3cac..0be703eeff 100644 --- a/services/cleanrooms/overwide_collaboration_list_test.go +++ b/services/cleanrooms/overwide_collaboration_list_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestOverWideCollaborationListResponses asserts on the raw response body @@ -270,7 +272,7 @@ func TestOverWideCollaborationListResponses(t *testing.T) { body := tt.raw(t) var decoded map[string]any - require.NoError(t, json.Unmarshal(body, &decoded)) + require.NoError(t, json.Unmarshal(body, &decoded, jsonx.V1())) rawItems, ok := decoded[tt.itemsKey] require.True(t, ok, "missing items key %q in response: %s", tt.itemsKey, body) @@ -309,7 +311,7 @@ func createCleanroomsCollabAndMembership(t *testing.T, e *echo.Echo) (string, st }) require.Equal(t, http.StatusOK, colRec.Code) var colResp map[string]any - require.NoError(t, json.Unmarshal(colRec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(colRec.Body.Bytes(), &colResp, jsonx.V1())) collabID, _ := colResp["collaboration"].(map[string]any)["id"].(string) require.NotEmpty(t, collabID) @@ -318,7 +320,7 @@ func createCleanroomsCollabAndMembership(t *testing.T, e *echo.Echo) (string, st }) require.Equal(t, http.StatusOK, memRec.Code) var memResp map[string]any - require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &memResp, jsonx.V1())) memID, _ := memResp["membership"].(map[string]any)["id"].(string) require.NotEmpty(t, memID) diff --git a/services/cleanrooms/persistence.go b/services/cleanrooms/persistence.go index 9fd8936602..af0c8e1d7a 100644 --- a/services/cleanrooms/persistence.go +++ b/services/cleanrooms/persistence.go @@ -2,7 +2,7 @@ package cleanrooms import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -39,7 +39,7 @@ const cleanroomsSnapshotVersion = 1 // key on (see backend.go's InMemoryBackend field doc comment). It is // persisted directly here. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TagsByArn map[string]map[string]string `json:"tagsByArn"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/cleanrooms/privacy_budgets_test.go b/services/cleanrooms/privacy_budgets_test.go index 0549b4ce72..ddfd096c7b 100644 --- a/services/cleanrooms/privacy_budgets_test.go +++ b/services/cleanrooms/privacy_budgets_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // setupTestEnvironment is a helper to bootstrap a collaboration and membership @@ -22,7 +24,7 @@ func setupTestEnvironment(t *testing.T, e *echo.Echo) (string, string) { }) rec := doRequest(t, e, http.MethodGet, "/collaborations", nil) var colResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &colResp, jsonx.V1())) colID := colResp["collaborationList"].([]any)[0].(map[string]any)["id"].(string) // Create Membership @@ -30,7 +32,7 @@ func setupTestEnvironment(t *testing.T, e *echo.Echo) (string, string) { "collaborationIdentifier": colID, "queryLogStatus": "DISABLED", }) var memResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1())) mID := memResp["membership"].(map[string]any)["id"].(string) return colID, mID @@ -51,7 +53,7 @@ func createBudgetTemplate(t *testing.T, e *echo.Echo, mID string) string { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) return createResp["privacyBudgetTemplate"]["id"].(string) } @@ -319,7 +321,7 @@ func TestPreviewPrivacyImpact(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) impact := resp["privacyImpact"].(map[string]any)["differentialPrivacy"].(map[string]any) aggs := impact["aggregations"].([]any) require.Len(t, aggs, 5) @@ -342,7 +344,7 @@ func TestListPrivacyBudgets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) budgets := resp["privacyBudgetSummaries"].([]any) require.Len(t, budgets, 1) diff --git a/services/cleanrooms/protected_jobs_test.go b/services/cleanrooms/protected_jobs_test.go index 1f05a59dd8..9e9c6b91b1 100644 --- a/services/cleanrooms/protected_jobs_test.go +++ b/services/cleanrooms/protected_jobs_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createProtectedJob(t *testing.T, e *echo.Echo, mID string) string { @@ -21,7 +23,7 @@ func createProtectedJob(t *testing.T, e *echo.Echo, mID string) string { }) require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) return startResp["protectedJob"]["id"].(string) } diff --git a/services/cleanrooms/protected_queries_test.go b/services/cleanrooms/protected_queries_test.go index 6b33ec6d15..102bc037b7 100644 --- a/services/cleanrooms/protected_queries_test.go +++ b/services/cleanrooms/protected_queries_test.go @@ -1,13 +1,15 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createProtectedQuery(t *testing.T, e *echo.Echo, mID string) string { @@ -21,7 +23,7 @@ func createProtectedQuery(t *testing.T, e *echo.Echo, mID string) string { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) return startResp["protectedQuery"]["id"].(string) } @@ -63,7 +65,7 @@ func TestProtectedQueries_Create(t *testing.T) { require.Equal(t, tt.wants.status, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pq := resp["protectedQuery"].(map[string]any) assert.Equal(t, "SUBMITTED", pq["status"], diff --git a/services/cleanrooms/protected_query_lifecycle_test.go b/services/cleanrooms/protected_query_lifecycle_test.go index c60b5ef325..c5b6ecb352 100644 --- a/services/cleanrooms/protected_query_lifecycle_test.go +++ b/services/cleanrooms/protected_query_lifecycle_test.go @@ -1,7 +1,7 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cleanrooms" ) @@ -22,7 +23,7 @@ func queryStatus(t *testing.T, e *echo.Echo, memID, id string) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["protectedQuery"]["status"].(string) } @@ -142,7 +143,7 @@ func TestStartProtectedQuery_KeepsSQLParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) got := resp["protectedQuery"]["sqlParameters"].(map[string]any) assert.Equal(t, tmpl, got["analysisTemplateArn"]) assert.Equal(t, map[string]any{"k": "v"}, got["parameters"]) diff --git a/services/cleanrooms/undeclared_members_test.go b/services/cleanrooms/undeclared_members_test.go index 47b0119745..b501244366 100644 --- a/services/cleanrooms/undeclared_members_test.go +++ b/services/cleanrooms/undeclared_members_test.go @@ -1,7 +1,7 @@ package cleanrooms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cleanrooms" ) @@ -114,7 +115,7 @@ func decodeBody(t *testing.T, b []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(b, &m)) + require.NoError(t, json.Unmarshal(b, &m, jsonx.V1())) return m } diff --git a/services/cloudcontrol/handler.go b/services/cloudcontrol/handler.go index 5744ef34ed..8e7ae80914 100644 --- a/services/cloudcontrol/handler.go +++ b/services/cloudcontrol/handler.go @@ -2,7 +2,7 @@ package cloudcontrol import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -125,12 +126,12 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // marshalError serialises a typed AWS error response into bytes. func marshalError(errType, message string) []byte { - payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}) + payload, _ := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}, jsonx.V1()) return payload } @@ -142,8 +143,6 @@ func marshalError(errType, message string) []byte { // exceptions (e.g. ConcurrentModificationException, ServiceInternalErrorException) use 500. // See e.g. https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_GetResource.html#API_GetResource_Errors func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError switch { case errors.Is(err, ErrClientTokenConflict): @@ -170,7 +169,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, ErrValidation): return ccError(c, http.StatusBadRequest, "InvalidRequestException", err, "The request is invalid.") - case errors.Is(err, errUnknownAction), errors.As(err, &syntaxErr), errors.As(err, &typeErr): + case errors.Is(err, errUnknownAction), jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return ccError(c, http.StatusBadRequest, "InvalidRequestException", err, "The request is invalid.") default: return ccError(c, http.StatusInternalServerError, "ServiceInternalErrorException", err, diff --git a/services/cloudcontrol/handler_test.go b/services/cloudcontrol/handler_test.go index 1f929ac55b..609876b2b3 100644 --- a/services/cloudcontrol/handler_test.go +++ b/services/cloudcontrol/handler_test.go @@ -2,7 +2,7 @@ package cloudcontrol_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -27,7 +28,7 @@ func doRequest(t *testing.T, h *cloudcontrol.Handler, action string, body any) * var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -55,7 +56,7 @@ func errType(t *testing.T, body []byte) string { var env struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(body, &env)) + require.NoError(t, json.Unmarshal(body, &env, jsonx.V1())) return env.Type } diff --git a/services/cloudcontrol/models.go b/services/cloudcontrol/models.go index 79734e1058..75d70111f7 100644 --- a/services/cloudcontrol/models.go +++ b/services/cloudcontrol/models.go @@ -1,8 +1,10 @@ package cloudcontrol import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -24,12 +26,12 @@ type unixEpochTime struct { } func (t unixEpochTime) MarshalJSON() ([]byte, error) { - return json.Marshal(t.Unix()) + return json.Marshal(t.Unix(), jsonx.V1()) } func (t *unixEpochTime) UnmarshalJSON(b []byte) error { var epoch int64 - if err := json.Unmarshal(b, &epoch); err != nil { + if err := json.Unmarshal(b, &epoch, jsonx.V1()); err != nil { return err } diff --git a/services/cloudcontrol/models_test.go b/services/cloudcontrol/models_test.go index d0f0f122c4..e9067fc76d 100644 --- a/services/cloudcontrol/models_test.go +++ b/services/cloudcontrol/models_test.go @@ -1,13 +1,14 @@ package cloudcontrol_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -30,7 +31,7 @@ func TestProgressEvent_OptionalFieldsOmittedWhenTerminalSuccess(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok, "ProgressEvent must be present") @@ -57,7 +58,7 @@ func TestGetResourceRequestStatus_HooksProgressEventOmittedWhenEmpty(t *testing. require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) pe, ok := createOut["ProgressEvent"].(map[string]any) require.True(t, ok) @@ -71,7 +72,7 @@ func TestGetResourceRequestStatus_HooksProgressEventOmittedWhenEmpty(t *testing. require.Equal(t, http.StatusOK, statusRec.Code) var statusOut map[string]any - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusOut)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusOut, jsonx.V1())) assert.NotContains(t, statusOut, "HooksProgressEvent", "HooksProgressEvent must be omitted since this backend has no Hooks concept") diff --git a/services/cloudcontrol/persistence.go b/services/cloudcontrol/persistence.go index 43d226b661..96c48c137b 100644 --- a/services/cloudcontrol/persistence.go +++ b/services/cloudcontrol/persistence.go @@ -2,7 +2,7 @@ package cloudcontrol import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -42,7 +42,7 @@ const cloudcontrolSnapshotVersion = 2 // persisted directly here so a repeated ClientToken remains idempotent (and // conflict-detectable) across a restart. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ClientTokens map[string]clientTokenEntry `json:"clientTokens"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/cloudcontrol/provisioned.go b/services/cloudcontrol/provisioned.go index d087325c99..ee08aaa692 100644 --- a/services/cloudcontrol/provisioned.go +++ b/services/cloudcontrol/provisioned.go @@ -2,10 +2,12 @@ package cloudcontrol import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Provisioner creates, changes and destroys the real resource behind a Cloud @@ -96,7 +98,7 @@ func (h *provisionedHandler) stored(identifier string) (map[string]any, error) { } var model map[string]any - if err := json.Unmarshal([]byte(r.Properties), &model); err != nil { + if err := json.Unmarshal([]byte(r.Properties), &model, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: stored model is not a JSON object", ErrValidation) } diff --git a/services/cloudcontrol/resource_requests_test.go b/services/cloudcontrol/resource_requests_test.go index 2c19918bfa..a78420a32c 100644 --- a/services/cloudcontrol/resource_requests_test.go +++ b/services/cloudcontrol/resource_requests_test.go @@ -1,7 +1,7 @@ package cloudcontrol_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -61,7 +62,7 @@ func TestHandler_GetResourceRequestStatus(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantOp, pe["Operation"]) @@ -189,7 +190,7 @@ func TestHandler_CancelResourceRequest(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantOpStatus, pe["OperationStatus"]) @@ -263,7 +264,7 @@ func TestHandler_CancelResourceRequest_OnlyAllowsInProgress(t *testing.T) { if tt.wantHTTP == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok, "ProgressEvent must be present") assert.Equal(t, "CANCEL_COMPLETE", pe["OperationStatus"]) @@ -350,7 +351,7 @@ func TestHandler_EventTimeIsUnixNumber(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) pe, ok := createOut["ProgressEvent"].(map[string]any) require.True(t, ok) @@ -375,7 +376,7 @@ func TestHandler_EventTimeIsUnixNumber(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok, "ProgressEvent should be present in response") @@ -488,7 +489,7 @@ func TestHandler_ListResourceRequests(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ResourceRequestStatusSummaries"].([]any) require.True(t, ok, "ResourceRequestStatusSummaries should be an array") assert.Len(t, summaries, tt.wantCount) @@ -565,7 +566,7 @@ func TestHandler_ListResourceRequests_FilterByOperationStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, _ := out["ResourceRequestStatusSummaries"].([]any) assert.Len(t, summaries, tt.wantLen, "filter %v", tt.filter) }) @@ -581,7 +582,7 @@ func TestHandler_ListResourceRequests_ContainsExpectedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ResourceRequestStatusSummaries"].([]any) require.True(t, ok) @@ -655,7 +656,7 @@ func TestHandler_ListResourceRequests_EnumValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ResourceRequestStatusSummaries"].([]any) if tt.wantMatches { @@ -693,7 +694,7 @@ func TestHandler_ListResourceRequests_TypeNameFilterIsIgnored(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ResourceRequestStatusSummaries"].([]any) require.True(t, ok) @@ -716,7 +717,7 @@ func TestHandler_ListResourceRequests_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ResourceRequestStatusSummaries"].([]any) require.True(t, ok) @@ -734,7 +735,7 @@ func TestHandler_ListResourceRequests_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) summaries2, ok := out2["ResourceRequestStatusSummaries"].([]any) require.True(t, ok) diff --git a/services/cloudcontrol/resources.go b/services/cloudcontrol/resources.go index ead679b243..dc380f1b0e 100644 --- a/services/cloudcontrol/resources.go +++ b/services/cloudcontrol/resources.go @@ -1,7 +1,7 @@ package cloudcontrol import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -122,7 +123,7 @@ func (b *InMemoryBackend) ListResources( var modelFilter map[string]any if resourceModel != "" { - if err := json.Unmarshal([]byte(resourceModel), &modelFilter); err != nil { + if err := json.Unmarshal([]byte(resourceModel), &modelFilter, jsonx.V1()); err != nil { return []*Resource{}, "" } } @@ -433,7 +434,7 @@ func extractIdentifier(desiredState string) string { } var props map[string]any - if err := json.Unmarshal([]byte(desiredState), &props); err != nil { + if err := json.Unmarshal([]byte(desiredState), &props, jsonx.V1()); err != nil { return "" } @@ -462,7 +463,7 @@ func matchesResourceModel(properties string, modelFilter map[string]any) bool { } var props map[string]any - if err := json.Unmarshal([]byte(properties), &props); err != nil { + if err := json.Unmarshal([]byte(properties), &props, jsonx.V1()); err != nil { return false } @@ -472,8 +473,8 @@ func matchesResourceModel(properties string, modelFilter map[string]any) bool { return false } - wantJSON, errW := json.Marshal(want) - gotJSON, errG := json.Marshal(got) + wantJSON, errW := json.Marshal(want, jsonx.V1()) + gotJSON, errG := json.Marshal(got, jsonx.V1()) if errW != nil || errG != nil || string(wantJSON) != string(gotJSON) { return false @@ -508,13 +509,13 @@ type patchOperation struct { // unchanged with no error (also pre-existing). func applyPatch(document, patchDocument string) (string, error) { var doc map[string]any - if err := json.Unmarshal([]byte(document), &doc); err != nil { + if err := json.Unmarshal([]byte(document), &doc, jsonx.V1()); err != nil { //nolint:nilerr // malformed document: return it unchanged, not an error (pre-existing behavior) return document, nil } var ops []patchOperation - if err := json.Unmarshal([]byte(patchDocument), &ops); err != nil { + if err := json.Unmarshal([]byte(patchDocument), &ops, jsonx.V1()); err != nil { //nolint:nilerr // malformed patch JSON: return document unchanged, not an error (pre-existing behavior) return document, nil } @@ -528,7 +529,7 @@ func applyPatch(document, patchDocument string) (string, error) { } } - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { //nolint:nilerr // doc built entirely from valid JSON decodes, so this can't actually fail; fail closed anyway return document, nil @@ -705,8 +706,8 @@ func deepCopyJSON(v any) any { // comparing equal -- both decode to the same float64 and marshal back // identically) -- same convention as matchesResourceModel above. func jsonValuesEqual(a, b any) bool { - aJSON, errA := json.Marshal(a) - bJSON, errB := json.Marshal(b) + aJSON, errA := json.Marshal(a, jsonx.V1()) + bJSON, errB := json.Marshal(b, jsonx.V1()) return errA == nil && errB == nil && string(aJSON) == string(bJSON) } diff --git a/services/cloudcontrol/resources_test.go b/services/cloudcontrol/resources_test.go index 843c12a826..662e2653be 100644 --- a/services/cloudcontrol/resources_test.go +++ b/services/cloudcontrol/resources_test.go @@ -1,7 +1,7 @@ package cloudcontrol_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -59,7 +60,7 @@ func TestHandler_CreateResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantOp, pe["Operation"]) @@ -119,7 +120,7 @@ func TestHandler_CreateResource_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) pe1 := out1["ProgressEvent"].(map[string]any) // Same clientToken must return the same RequestToken (idempotent). @@ -127,7 +128,7 @@ func TestHandler_CreateResource_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) pe2 := out2["ProgressEvent"].(map[string]any) assert.Equal(t, pe1["RequestToken"], pe2["RequestToken"]) @@ -210,14 +211,14 @@ func TestHandler_ProgressEvent_ResourceModel(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) createPE := createOut["ProgressEvent"].(map[string]any) createModel, ok := createPE["ResourceModel"].(string) require.True(t, ok, "ResourceModel must be present as a string on CreateResource") var createParsed map[string]any - require.NoError(t, json.Unmarshal([]byte(createModel), &createParsed)) + require.NoError(t, json.Unmarshal([]byte(createModel), &createParsed, jsonx.V1())) assert.Equal(t, "model-test", createParsed["LogGroupName"]) updateRec := doRequest(t, h, "UpdateResource", map[string]any{ @@ -228,14 +229,14 @@ func TestHandler_ProgressEvent_ResourceModel(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) updatePE := updateOut["ProgressEvent"].(map[string]any) updateModel, ok := updatePE["ResourceModel"].(string) require.True(t, ok, "ResourceModel must be present as a string on UpdateResource") var updateParsed map[string]any - require.NoError(t, json.Unmarshal([]byte(updateModel), &updateParsed)) + require.NoError(t, json.Unmarshal([]byte(updateModel), &updateParsed, jsonx.V1())) assert.InEpsilon(t, float64(30), updateParsed["RetentionInDays"], 0, "ResourceModel must reflect the patched value") } func TestHandler_GetResource(t *testing.T) { @@ -301,7 +302,7 @@ func TestHandler_GetResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) rd, ok := out["ResourceDescription"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantProps, rd["Properties"]) @@ -325,7 +326,7 @@ func TestHandler_GetResource_PropertiesIsJSONString(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) pe := createOut["ProgressEvent"].(map[string]any) identifier := pe["Identifier"].(string) @@ -336,7 +337,7 @@ func TestHandler_GetResource_PropertiesIsJSONString(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) desc, ok := getOut["ResourceDescription"].(map[string]any) require.True(t, ok, "ResourceDescription must be present") @@ -348,7 +349,7 @@ func TestHandler_GetResource_PropertiesIsJSONString(t *testing.T) { // The string must be valid JSON. var parsed map[string]any - require.NoError(t, json.Unmarshal([]byte(propertiesRaw.(string)), &parsed)) + require.NoError(t, json.Unmarshal([]byte(propertiesRaw.(string)), &parsed, jsonx.V1())) assert.Equal(t, "my-bucket", parsed["BucketName"]) } @@ -479,7 +480,7 @@ func TestHandler_ListResources(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descs, ok := out["ResourceDescriptions"].([]any) require.True(t, ok) assert.Len(t, descs, tt.wantCount) @@ -506,7 +507,7 @@ func TestHandler_ListResources_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1, jsonx.V1())) descs1, ok := out1["ResourceDescriptions"].([]any) require.True(t, ok) @@ -526,7 +527,7 @@ func TestHandler_ListResources_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) descs2, ok := out2["ResourceDescriptions"].([]any) require.True(t, ok) @@ -598,7 +599,7 @@ func TestHandler_DeleteResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantOp, pe["Operation"]) @@ -678,7 +679,7 @@ func TestHandler_UpdateResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantOp, pe["Operation"]) @@ -713,14 +714,14 @@ func TestHandler_UpdateResource_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) pe1 := out1["ProgressEvent"].(map[string]any) rec2 := doRequest(t, h, "UpdateResource", body) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) pe2 := out2["ProgressEvent"].(map[string]any) assert.Equal(t, pe1["RequestToken"], pe2["RequestToken"], @@ -1109,7 +1110,7 @@ func TestHandler_DeleteResource_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) pe1 := out1["ProgressEvent"].(map[string]any) // Without idempotency this second call would 400 with ResourceNotFoundException, @@ -1118,7 +1119,7 @@ func TestHandler_DeleteResource_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) pe2 := out2["ProgressEvent"].(map[string]any) assert.Equal(t, pe1["RequestToken"], pe2["RequestToken"], @@ -1461,7 +1462,7 @@ func TestHandler_ProgressEvent_RequiredFields(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) pe := out["ProgressEvent"].(map[string]any) return map[string]any{ @@ -1479,7 +1480,7 @@ func TestHandler_ProgressEvent_RequiredFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pe, ok := out["ProgressEvent"].(map[string]any) require.True(t, ok, "ProgressEvent must be present") diff --git a/services/cloudcontrol/type_handlers.go b/services/cloudcontrol/type_handlers.go index 3b1fcf67e4..e8259c3748 100644 --- a/services/cloudcontrol/type_handlers.go +++ b/services/cloudcontrol/type_handlers.go @@ -2,13 +2,14 @@ package cloudcontrol import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "sort" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -38,7 +39,7 @@ func (b *InMemoryBackend) typeHandler(typeName string) TypeHandler { } func marshalModel(model map[string]any) (string, error) { - raw, err := json.Marshal(model) + raw, err := json.Marshal(model, jsonx.V1()) if err != nil { return "", fmt.Errorf("%w: %w", ErrValidation, err) } @@ -90,7 +91,7 @@ func (b *InMemoryBackend) CreateResourceContext( } var desired map[string]any - if err := json.Unmarshal([]byte(desiredState), &desired); err != nil { + if err := json.Unmarshal([]byte(desiredState), &desired, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: DesiredState must be a JSON object", ErrValidation) } @@ -202,7 +203,7 @@ func (b *InMemoryBackend) UpdateResourceContext( } var desired map[string]any - if jsonErr := json.Unmarshal([]byte(patched), &desired); jsonErr != nil { + if jsonErr := json.Unmarshal([]byte(patched), &desired, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: patched document is not a JSON object", ErrValidation) } @@ -278,7 +279,7 @@ func parseModelFilter(resourceModel string) (map[string]any, bool) { var filter map[string]any - return filter, json.Unmarshal([]byte(resourceModel), &filter) == nil + return filter, json.Unmarshal([]byte(resourceModel), &filter, jsonx.V1()) == nil } var errInvalidNextToken = fmt.Errorf("%w: NextToken is not valid", ErrValidation) diff --git a/services/cloudformation/cfn_attributes.go b/services/cloudformation/cfn_attributes.go index 9cb2da75de..ecf168b665 100644 --- a/services/cloudformation/cfn_attributes.go +++ b/services/cloudformation/cfn_attributes.go @@ -2,8 +2,10 @@ package cloudformation import ( _ "embed" - "encoding/json" + "encoding/json/v2" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // cfn_attributes.json is generated by cmd/cfnattrgen from the CloudFormation @@ -23,7 +25,7 @@ var ( func resourceAttributeTable() map[string]map[string]struct{} { cfnResourceAttributesOnce.Do(func() { var raw map[string][]string - if err := json.Unmarshal(cfnAttributesJSON, &raw); err != nil { + if err := json.Unmarshal(cfnAttributesJSON, &raw, jsonx.V1()); err != nil { panic("cloudformation: invalid embedded cfn_attributes.json: " + err.Error()) } diff --git a/services/cloudformation/cfn_property_schemas.go b/services/cloudformation/cfn_property_schemas.go index 3f3c1e99e8..60398ec59e 100644 --- a/services/cloudformation/cfn_property_schemas.go +++ b/services/cloudformation/cfn_property_schemas.go @@ -2,12 +2,14 @@ package cloudformation import ( _ "embed" - "encoding/json" + "encoding/json/v2" "fmt" "math" "strconv" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Property kinds in cfn_property_schemas.json, written by cmd/cfnpropgen. @@ -37,7 +39,7 @@ var ( func embeddedPropertySchemas() propertySchemas { cfnPropertySchemasOnce.Do(func() { - if err := json.Unmarshal(cfnPropertySchemasJSON, &cfnPropertySchemas); err != nil { + if err := json.Unmarshal(cfnPropertySchemasJSON, &cfnPropertySchemas, jsonx.V1()); err != nil { panic("cloudformation: invalid embedded cfn_property_schemas.json: " + err.Error()) } }) diff --git a/services/cloudformation/changeset_diff.go b/services/cloudformation/changeset_diff.go index 1ae698fc62..f7bb9d742d 100644 --- a/services/cloudformation/changeset_diff.go +++ b/services/cloudformation/changeset_diff.go @@ -1,12 +1,13 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Replacement / recreation constants used by change-set previews. @@ -431,8 +432,8 @@ func unionMapKeys(a, b map[string]any) []string { } func jsonEqual(a, b any) bool { - ab, err1 := json.Marshal(a) - bb, err2 := json.Marshal(b) + ab, err1 := json.Marshal(a, jsonx.V1()) + bb, err2 := json.Marshal(b, jsonx.V1()) if err1 != nil || err2 != nil { return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b) } @@ -447,7 +448,7 @@ func toJSONString(v any) string { if s, ok := v.(string); ok { return s } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Sprintf("%v", v) } diff --git a/services/cloudformation/cloudcontrol_provisioner.go b/services/cloudformation/cloudcontrol_provisioner.go index bbac51d002..f487216c18 100644 --- a/services/cloudformation/cloudcontrol_provisioner.go +++ b/services/cloudformation/cloudcontrol_provisioner.go @@ -3,7 +3,7 @@ package cloudformation import ( "context" _ "embed" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "reflect" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudcontrol" ) @@ -29,7 +30,7 @@ var ( // against real backends; Cloud Control serves the same set. func ProvisionableTypes() []string { cfnProvisionableTypesOnce.Do(func() { - if err := json.Unmarshal(cfnProvisionableTypesJSON, &cfnProvisionableTypes); err != nil { + if err := json.Unmarshal(cfnProvisionableTypesJSON, &cfnProvisionableTypes, jsonx.V1()); err != nil { panic("cloudformation: invalid embedded cfn_provisionable_types.json: " + err.Error()) } }) diff --git a/services/cloudformation/deletion_policy_test.go b/services/cloudformation/deletion_policy_test.go index 82180ce0eb..2d09b77ca8 100644 --- a/services/cloudformation/deletion_policy_test.go +++ b/services/cloudformation/deletion_policy_test.go @@ -2,13 +2,14 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudformation" ) @@ -53,7 +54,7 @@ func templateWithDeletionPolicy(policy string) string { body, _ := json.Marshal(map[string]any{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": map[string]any{"Bucket": res}, - }) + }, jsonx.V1()) return string(body) } diff --git a/services/cloudformation/drift_detection.go b/services/cloudformation/drift_detection.go index 65b482fff1..17ba7ce3db 100644 --- a/services/cloudformation/drift_detection.go +++ b/services/cloudformation/drift_detection.go @@ -1,12 +1,14 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // pruneDriftDetections removes all drift detection entries associated with a stack @@ -218,12 +220,12 @@ func deepCopyProps(props map[string]any) map[string]any { if props == nil { return nil } - data, err := json.Marshal(props) + data, err := json.Marshal(props, jsonx.V1()) if err != nil { return props } var out map[string]any - if uerr := json.Unmarshal(data, &out); uerr != nil { + if uerr := json.Unmarshal(data, &out, jsonx.V1()); uerr != nil { return props } diff --git a/services/cloudformation/drift_detection_test.go b/services/cloudformation/drift_detection_test.go index 836f35bf0e..87918a1de6 100644 --- a/services/cloudformation/drift_detection_test.go +++ b/services/cloudformation/drift_detection_test.go @@ -2,12 +2,13 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudformation" ) @@ -306,7 +307,7 @@ func TestDeleteStack_ClearsDriftMaps(t *testing.T) { ResourceDriftStatus map[string]map[string]string `json:"resourceDriftStatus"` ResourceDriftDetail map[string]map[string]any `json:"resourceDriftDetail"` } - require.NoError(t, json.Unmarshal(b.Snapshot(context.Background()), &probe)) + require.NoError(t, json.Unmarshal(b.Snapshot(context.Background()), &probe, jsonx.V1())) assert.NotContains(t, probe.ResourceDriftStatus, stack.StackID) assert.NotContains(t, probe.ResourceDriftDetail, stack.StackID) assert.Contains(t, probe.ResourceDriftStatus, otherStack.StackID, diff --git a/services/cloudformation/dynamic_refs.go b/services/cloudformation/dynamic_refs.go index 29989c99d5..5fd024164c 100644 --- a/services/cloudformation/dynamic_refs.go +++ b/services/cloudformation/dynamic_refs.go @@ -2,11 +2,13 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dynamicRefPattern matches CloudFormation dynamic reference strings: @@ -186,7 +188,7 @@ func ResolveDynamicRefsInTemplate(ctx context.Context, tmpl *Template, resolver // If parsing fails or the key is absent, an error is returned. func resolveJSONKey(secretValue, key string) (string, error) { var obj map[string]any - if err := json.Unmarshal([]byte(secretValue), &obj); err != nil { + if err := json.Unmarshal([]byte(secretValue), &obj, jsonx.V1()); err != nil { return "", fmt.Errorf("secret is not valid JSON: %w", err) } diff --git a/services/cloudformation/generated_templates.go b/services/cloudformation/generated_templates.go index 09cb5b3f40..44c55ab745 100644 --- a/services/cloudformation/generated_templates.go +++ b/services/cloudformation/generated_templates.go @@ -1,7 +1,7 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -79,7 +80,7 @@ func marshalGeneratedTemplate(resources map[string]cfnResource) string { AWSTemplateFormatVersion: "2010-09-09", Description: "Generated template", Resources: resources, - }) + }, jsonx.V1()) if err != nil { return `{"AWSTemplateFormatVersion":"2010-09-09","Resources":{}}` } diff --git a/services/cloudformation/handler_type_registry.go b/services/cloudformation/handler_type_registry.go index d848973e63..d7aa1fd2bf 100644 --- a/services/cloudformation/handler_type_registry.go +++ b/services/cloudformation/handler_type_registry.go @@ -1,7 +1,7 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // typeSchemaFor returns the primary identifier property name for a given CloudFormation resource type. @@ -112,11 +113,11 @@ func describeTypeSchemaJSON(typeName string) (string, error) { // Round-trip through a generic map to normalize formatting and to fail // loudly (via the error return) if a catalog entry is ever malformed. var generic map[string]any - if err := json.Unmarshal([]byte(raw), &generic); err != nil { + if err := json.Unmarshal([]byte(raw), &generic, jsonx.V1()); err != nil { return "", err } - normalized, err := json.Marshal(generic) + normalized, err := json.Marshal(generic, jsonx.V1()) if err != nil { return "", err } @@ -143,7 +144,7 @@ func describeTypeSchemaJSON(typeName string) (string, error) { AdditionalProperties: true, } - schemaBytes, err := json.Marshal(schemaObj) + schemaBytes, err := json.Marshal(schemaObj, jsonx.V1()) if err != nil { return "", err } diff --git a/services/cloudformation/persistence.go b/services/cloudformation/persistence.go index 4294a104c3..584c527c42 100644 --- a/services/cloudformation/persistence.go +++ b/services/cloudformation/persistence.go @@ -2,7 +2,7 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -29,7 +29,7 @@ const cfnSnapshotVersion = 1 // comment on registerAllTables) and are persisted exactly as before the // conversion. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Events map[string][]StackEvent `json:"events"` Resources map[string]map[string]*StackResource `json:"resources"` ChangeSets map[string]map[string]*ChangeSet `json:"changeSets"` diff --git a/services/cloudformation/resource_type_schemas_test.go b/services/cloudformation/resource_type_schemas_test.go index f235ffd9b4..a13d193811 100644 --- a/services/cloudformation/resource_type_schemas_test.go +++ b/services/cloudformation/resource_type_schemas_test.go @@ -1,13 +1,15 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // describeTypeXMLResult mirrors the DescribeTypeResult XML shape returned by the @@ -170,7 +172,7 @@ func TestHandler_DescribeType_CatalogSchemas(t *testing.T) { require.NotEmpty(t, parsed.Schema) var schema parsedProviderSchema - require.NoError(t, json.Unmarshal([]byte(parsed.Schema), &schema)) + require.NoError(t, json.Unmarshal([]byte(parsed.Schema), &schema, jsonx.V1())) assert.Equal(t, tc.typeName, schema.TypeName) assert.NotEmpty(t, schema.Description) require.Contains(t, schema.PrimaryIdentifier, tc.wantPrimaryID) @@ -214,7 +216,7 @@ func TestHandler_DescribeType_UnknownType_ValidFallback(t *testing.T) { require.NotEmpty(t, parsed.Schema) var schema parsedProviderSchema - require.NoError(t, json.Unmarshal([]byte(parsed.Schema), &schema)) + require.NoError(t, json.Unmarshal([]byte(parsed.Schema), &schema, jsonx.V1())) assert.Equal(t, "AWS::Totally::Unmodeled", schema.TypeName) require.NotEmpty(t, schema.PrimaryIdentifier) assert.NotEmpty(t, schema.Properties) diff --git a/services/cloudformation/resource_update_inplace.go b/services/cloudformation/resource_update_inplace.go index 21c0bfd90a..5acb836766 100644 --- a/services/cloudformation/resource_update_inplace.go +++ b/services/cloudformation/resource_update_inplace.go @@ -4,12 +4,13 @@ import ( "context" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "time" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" sqsbackend "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -114,7 +115,7 @@ func sqsAttributesFromProps(props map[string]any, params, physicalIDs map[string } if rp, ok := props["RedrivePolicy"]; ok { - if b, err := json.Marshal(resolveDeep(rp, params, physicalIDs)); err == nil { + if b, err := json.Marshal(resolveDeep(rp, params, physicalIDs), jsonx.V1()); err == nil { attrs["RedrivePolicy"] = string(b) } } diff --git a/services/cloudformation/resources.go b/services/cloudformation/resources.go index 32f57ebd4a..6e0df898e2 100644 --- a/services/cloudformation/resources.go +++ b/services/cloudformation/resources.go @@ -2,7 +2,6 @@ package cloudformation import ( "context" - "encoding/json" "fmt" "maps" "math" @@ -16,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/ctxval" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" acmbackend "github.com/blackbirdworks/gopherstack/services/acm" apigwbackend "github.com/blackbirdworks/gopherstack/services/apigateway" apigatewayv2backend "github.com/blackbirdworks/gopherstack/services/apigatewayv2" @@ -3510,7 +3510,7 @@ func int64Val(v any) int64 { return int64(n) case int64: return n - case json.Number: + case jsonx.Number: i, err := n.Int64() if err == nil { return i diff --git a/services/cloudformation/resources_apigatewayv2.go b/services/cloudformation/resources_apigatewayv2.go index bb678e056c..9a7ba36910 100644 --- a/services/cloudformation/resources_apigatewayv2.go +++ b/services/cloudformation/resources_apigatewayv2.go @@ -2,10 +2,11 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" apigatewayv2backend "github.com/blackbirdworks/gopherstack/services/apigatewayv2" ) @@ -99,11 +100,11 @@ func (rc *ResourceCreator) deleteAPIGatewayV2Authorizer(physicalID string) error // decodeProps resolves intrinsics in props and decodes them into out; the // backend inputs' JSON tags match CloudFormation's property names case-insensitively. func decodeProps(props map[string]any, params, physicalIDs map[string]string, out any) error { - raw, err := json.Marshal(resolveDeep(props, params, physicalIDs)) + raw, err := json.Marshal(resolveDeep(props, params, physicalIDs), jsonx.V1()) if err != nil { return fmt.Errorf("encode properties: %w", err) } - if err = json.Unmarshal(raw, out); err != nil { + if err = json.Unmarshal(raw, out, jsonx.V1()); err != nil { return fmt.Errorf("decode properties: %w", err) } diff --git a/services/cloudformation/resources_cfnrest.go b/services/cloudformation/resources_cfnrest.go index 1f9dbefb60..e95c045f71 100644 --- a/services/cloudformation/resources_cfnrest.go +++ b/services/cloudformation/resources_cfnrest.go @@ -1,12 +1,13 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -28,12 +29,12 @@ func decodeCFNProps(dst any, props map[string]any, params, physicalIDs map[strin resolved["Tags"] = tagListProp(props, params, physicalIDs) } - raw, err := json.Marshal(resolved) + raw, err := json.Marshal(resolved, jsonx.V1()) if err != nil { return fmt.Errorf("encode properties: %w", err) } - if err = json.Unmarshal(raw, dst); err != nil { + if err = json.Unmarshal(raw, dst, jsonx.V1()); err != nil { return fmt.Errorf("decode properties: %w", err) } diff --git a/services/cloudformation/resources_connect_content.go b/services/cloudformation/resources_connect_content.go index 1ec915703f..a425ae49f2 100644 --- a/services/cloudformation/resources_connect_content.go +++ b/services/cloudformation/resources_connect_content.go @@ -1,12 +1,13 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" connectbackend "github.com/blackbirdworks/gopherstack/services/connect" ) @@ -21,7 +22,7 @@ func (c *connectCall) viewContent() (*connectbackend.ViewInputContent, error) { return &connectbackend.ViewInputContent{Template: s, Actions: c.actionStrings()}, nil } - raw, err := json.Marshal(template) + raw, err := json.Marshal(template, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/cloudformation/resources_connect_core_test.go b/services/cloudformation/resources_connect_core_test.go index ef8ca381c2..f9bf3c17bb 100644 --- a/services/cloudformation/resources_connect_core_test.go +++ b/services/cloudformation/resources_connect_core_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudformation" connectbackend "github.com/blackbirdworks/gopherstack/services/connect" ) @@ -32,7 +33,7 @@ func connectFlowContent(t *testing.T) string { "Identifier": "end", "Type": "DisconnectParticipant", "Parameters": map[string]any{}, "Transitions": map[string]any{}, }}, - }) + }, jsonx.V1()) require.NoError(t, err) return string(doc) diff --git a/services/cloudformation/resources_connect_people.go b/services/cloudformation/resources_connect_people.go index 4b937f0fda..0e47efad98 100644 --- a/services/cloudformation/resources_connect_people.go +++ b/services/cloudformation/resources_connect_people.go @@ -1,9 +1,11 @@ package cloudformation import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" connectbackend "github.com/blackbirdworks/gopherstack/services/connect" ) @@ -348,10 +350,10 @@ func connectRuleActionMembers() map[string][2]string { // ruleActions turns the template's Actions object (one list per action kind) into the API's list of // {ActionType, Action} entries. -func (c *connectCall) ruleActions() ([]json.RawMessage, error) { +func (c *connectCall) ruleActions() ([]jsontext.Value, error) { actions, _ := c.wire["Actions"].(map[string]any) - var out []json.RawMessage + var out []jsontext.Value for _, key := range sortedKeys(actions) { kind, known := connectRuleActionMembers()[key] @@ -361,7 +363,7 @@ func (c *connectCall) ruleActions() ([]json.RawMessage, error) { list, _ := actions[key].([]any) for _, item := range list { - raw, err := json.Marshal(map[string]any{"ActionType": kind[0], kind[1]: item}) + raw, err := json.Marshal(map[string]any{"ActionType": kind[0], kind[1]: item}, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/cloudformation/resources_connect_workspace.go b/services/cloudformation/resources_connect_workspace.go index 77d79f0fa2..09a6b48b2f 100644 --- a/services/cloudformation/resources_connect_workspace.go +++ b/services/cloudformation/resources_connect_workspace.go @@ -1,9 +1,11 @@ package cloudformation import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" connectbackend "github.com/blackbirdworks/gopherstack/services/connect" ) @@ -56,11 +58,11 @@ func updateConnectWorkspace(c *connectCall, physicalID string) error { return err } - theme := connectbackend.UpdateWorkspaceThemeInput{Theme: json.RawMessage("null")} + theme := connectbackend.UpdateWorkspaceThemeInput{Theme: jsontext.Value("null")} theme.InstanceID, theme.WorkspaceID = meta.InstanceID, meta.WorkspaceID if t, ok := c.wire["Theme"]; ok { - raw, err := json.Marshal(t) + raw, err := json.Marshal(t, jsonx.V1()) if err != nil { return err } diff --git a/services/cloudformation/resources_connectfamily_helpers_test.go b/services/cloudformation/resources_connectfamily_helpers_test.go index 105c65407a..31bbe9f474 100644 --- a/services/cloudformation/resources_connectfamily_helpers_test.go +++ b/services/cloudformation/resources_connectfamily_helpers_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,7 @@ import ( cfntypes "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudformation" @@ -84,7 +85,7 @@ func stackTemplate(t *testing.T, resources map[string]any, outputs map[string]an outs[k] = map[string]any{"Value": v} } - doc, err := json.Marshal(map[string]any{"Resources": resources, "Outputs": outs}) + doc, err := json.Marshal(map[string]any{"Resources": resources, "Outputs": outs}, jsonx.V1()) require.NoError(t, err) return string(doc) diff --git a/services/cloudformation/resources_deep.go b/services/cloudformation/resources_deep.go index 95a65af3a8..c6f8721631 100644 --- a/services/cloudformation/resources_deep.go +++ b/services/cloudformation/resources_deep.go @@ -4,10 +4,11 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ebbackend "github.com/blackbirdworks/gopherstack/services/eventbridge" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -58,7 +59,7 @@ func resolvedJSONProp(props map[string]any, key string, params, physicalIDs map[ case string: return t default: - raw, err := json.Marshal(resolveDeep(t, params, physicalIDs)) + raw, err := json.Marshal(resolveDeep(t, params, physicalIDs), jsonx.V1()) if err != nil { return "" } diff --git a/services/cloudformation/resources_extensibility.go b/services/cloudformation/resources_extensibility.go index c88cc090c0..adce9a8607 100644 --- a/services/cloudformation/resources_extensibility.go +++ b/services/cloudformation/resources_extensibility.go @@ -2,7 +2,8 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net" @@ -13,6 +14,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" snsbackend "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -227,7 +229,7 @@ func startCFNResponseServer( } var resp cfnCustomResourceResponse - _ = json.NewDecoder(r.Body).Decode(&resp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &resp, jsonx.V1()) select { case respCh <- resp: @@ -318,7 +320,7 @@ func (rc *ResourceCreator) createCustomResource( ResourceProperties: props, } - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { return defaultPhysID, nil } @@ -421,7 +423,7 @@ func (rc *ResourceCreator) updateCustomResource( OldResourceProperties: oldProps, } - payload, merr := json.Marshal(event) + payload, merr := json.Marshal(event, jsonx.V1()) if merr != nil { return nil } @@ -487,7 +489,7 @@ func (rc *ResourceCreator) deleteCustomResource( ResourceProperties: props, } - payload, merr := json.Marshal(event) + payload, merr := json.Marshal(event, jsonx.V1()) if merr != nil { return nil } @@ -674,14 +676,14 @@ func (r *MacroRegistry) InvokeMacro( event := map[string]any{ "region": cfnDefaultRegion, "accountId": "000000000000", - "fragment": json.RawMessage(fragmentJSON), + "fragment": jsontext.Value(fragmentJSON), "transformId": macroName, "params": map[string]any{}, "templateParameterValues": params, "requestedTransforms": []string{macroName}, } - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { return fragmentJSON, err } @@ -699,12 +701,12 @@ func (r *MacroRegistry) InvokeMacro( // Parse macro response: {"status": "success", "fragment": {...}} var resp struct { - Status string `json:"status"` - ErrorMessage string `json:"errorMessage,omitempty"` - Fragment json.RawMessage `json:"fragment"` + Status string `json:"status"` + ErrorMessage string `json:"errorMessage,omitempty"` + Fragment jsontext.Value `json:"fragment"` } - if unmarshalErr := json.Unmarshal(result, &resp); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(result, &resp, jsonx.V1()); unmarshalErr != nil { return fragmentJSON, unmarshalErr } diff --git a/services/cloudformation/resources_extensibility_customresource_lifecycle_test.go b/services/cloudformation/resources_extensibility_customresource_lifecycle_test.go index a810cd49e6..67ced1c868 100644 --- a/services/cloudformation/resources_extensibility_customresource_lifecycle_test.go +++ b/services/cloudformation/resources_extensibility_customresource_lifecycle_test.go @@ -2,7 +2,7 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudformation" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -38,7 +39,7 @@ func TestResourceCreator_CustomResource_DeleteEvent(t *testing.T) { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, 0, err } @@ -62,7 +63,7 @@ func TestResourceCreator_CustomResource_DeleteEvent(t *testing.T) { "Status": "SUCCESS", "PhysicalResourceId": ev.PhysicalResourceID, } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{Timeout: 2 * time.Second} req, reqErr := http.NewRequestWithContext( ctx, @@ -129,7 +130,7 @@ func TestResourceCreator_CustomResource_UpdateEvent(t *testing.T) { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, 0, err } @@ -157,7 +158,7 @@ func TestResourceCreator_CustomResource_UpdateEvent(t *testing.T) { "Status": "SUCCESS", "PhysicalResourceId": ev.PhysicalResourceID, } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{Timeout: 2 * time.Second} req, reqErr := http.NewRequestWithContext( ctx, @@ -248,7 +249,7 @@ func TestStack_CustomResource_UpdateStack_SendsUpdateEvent(t *testing.T) { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, 0, err } @@ -266,7 +267,7 @@ func TestStack_CustomResource_UpdateStack_SendsUpdateEvent(t *testing.T) { "Status": "SUCCESS", "PhysicalResourceId": physID, } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{Timeout: 2 * time.Second} req, reqErr := http.NewRequestWithContext( ctx, diff --git a/services/cloudformation/resources_extensibility_customresource_test.go b/services/cloudformation/resources_extensibility_customresource_test.go index 167266a818..2161711146 100644 --- a/services/cloudformation/resources_extensibility_customresource_test.go +++ b/services/cloudformation/resources_extensibility_customresource_test.go @@ -2,7 +2,7 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/services/cloudformation" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" @@ -112,7 +113,7 @@ func TestResourceCreator_CustomResource_ResponseURL_RoundTrip(t *testing.T) { var event struct { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &event); err == nil && event.ResponseURL != "" { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err == nil && event.ResponseURL != "" { select { case capturedURL <- event.ResponseURL: default: @@ -160,7 +161,7 @@ func TestResourceCreator_CustomResource_ResponseURL_RoundTrip(t *testing.T) { "Data": map[string]any{"BucketName": "my-bucket"}, } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{} putReq, _ := http.NewRequestWithContext(t.Context(), http.MethodPut, url, newBytesReader(body)) @@ -319,7 +320,7 @@ func TestResourceCreator_CustomResource_FAILEDResponse(t *testing.T) { var event struct { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &event); err == nil { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err == nil { select { case capturedURL <- event.ResponseURL: default: @@ -363,7 +364,7 @@ func TestResourceCreator_CustomResource_FAILEDResponse(t *testing.T) { "Reason": "Validation error: bad-data is not allowed", "PhysicalResourceId": "failing-resource-001", } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{} req, _ := http.NewRequestWithContext(t.Context(), http.MethodPut, url, newBytesReader(body)) req.ContentLength = int64(len(body)) @@ -395,7 +396,7 @@ func TestStack_CustomResource_GetAtt_DataOutputs(t *testing.T) { var event struct { ResponseURL string `json:"ResponseURL"` } - if err := json.Unmarshal(payload, &event); err == nil { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err == nil { select { case capturedURL <- event.ResponseURL: default: @@ -459,7 +460,7 @@ func TestStack_CustomResource_GetAtt_DataOutputs(t *testing.T) { "BucketArn": "arn:aws:s3:::my-prefix-generated-bucket", }, } - body, _ := json.Marshal(resp) + body, _ := json.Marshal(resp, jsonx.V1()) client := &http.Client{} req, _ := http.NewRequestWithContext(t.Context(), http.MethodPut, url, newBytesReader(body)) req.ContentLength = int64(len(body)) diff --git a/services/cloudformation/resources_extensibility_macro_test.go b/services/cloudformation/resources_extensibility_macro_test.go index d4327d90f5..4e4e6cccdf 100644 --- a/services/cloudformation/resources_extensibility_macro_test.go +++ b/services/cloudformation/resources_extensibility_macro_test.go @@ -2,12 +2,13 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudformation" lambdabackend "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -170,7 +171,7 @@ func TestMacroRegistry_InvokeMacro_WithMockLambda(t *testing.T) { mockLambda := &mockLambdaStorageBackend{ invokeFunc: func(_ context.Context, _ string, _ lambdabackend.InvocationType, _ []byte) ([]byte, int, error) { - respBody, _ := json.Marshal(tt.lambdaResp) + respBody, _ := json.Marshal(tt.lambdaResp, jsonx.V1()) return respBody, 200, nil }, @@ -183,14 +184,14 @@ func TestMacroRegistry_InvokeMacro_WithMockLambda(t *testing.T) { "", ) - fragmentJSON, _ := json.Marshal(tt.fragment) + fragmentJSON, _ := json.Marshal(tt.fragment, jsonx.V1()) result, err := registry.InvokeMacro( t.Context(), lambdabackend.NewHandler(mockLambda), tt.macroName, fragmentJSON, nil, ) require.NoError(t, err) var got map[string]any - require.NoError(t, json.Unmarshal(result, &got)) + require.NoError(t, json.Unmarshal(result, &got, jsonx.V1())) assert.Equal(t, tt.wantFragment, got) }) } @@ -205,7 +206,7 @@ func TestMacroRegistry_InvokeMacro_NoLambdaBackend(t *testing.T) { registry.RegisterForTest("MyMacro", "arn:aws:lambda:us-east-1:000000000000:function:fn", "") fragment := map[string]any{"unchanged": true} - fragmentJSON, _ := json.Marshal(fragment) + fragmentJSON, _ := json.Marshal(fragment, jsonx.V1()) // nil lambda backend → returns fragment unchanged. result, err := registry.InvokeMacro(t.Context(), nil, "MyMacro", fragmentJSON, nil) @@ -221,7 +222,7 @@ func TestMacroRegistry_InvokeMacro_UnknownMacro(t *testing.T) { registry := cloudformation.NewMacroRegistry() fragment := map[string]any{"pass": "through"} - fragmentJSON, _ := json.Marshal(fragment) + fragmentJSON, _ := json.Marshal(fragment, jsonx.V1()) mockLambda := &mockLambdaStorageBackend{} result, err := registry.InvokeMacro( diff --git a/services/cloudformation/resources_iot_more_test.go b/services/cloudformation/resources_iot_more_test.go index 81940b5a48..1449883eeb 100644 --- a/services/cloudformation/resources_iot_more_test.go +++ b/services/cloudformation/resources_iot_more_test.go @@ -6,7 +6,7 @@ import ( "crypto/rand" "crypto/x509" "crypto/x509/pkix" - "encoding/json" + "encoding/json/v2" "encoding/pem" "testing" @@ -14,6 +14,8 @@ import ( cfnsdk "github.com/aws/aws-sdk-go-v2/service/cloudformation" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateStack_IoTMoreTypes(t *testing.T) { @@ -203,7 +205,10 @@ func testIoTCertificate(t *testing.T) { &x509.CertificateRequest{Subject: pkix.Name{CommonName: "device"}}, key) require.NoError(t, err) - csrJSON, err := json.Marshal(string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER}))) + csrJSON, err := json.Marshal( + string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER})), + jsonx.V1(), + ) require.NoError(t, err) tmpl := `{ diff --git a/services/cloudformation/resources_networkmanager.go b/services/cloudformation/resources_networkmanager.go index 006a9ca8d2..d6625aac73 100644 --- a/services/cloudformation/resources_networkmanager.go +++ b/services/cloudformation/resources_networkmanager.go @@ -2,11 +2,12 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" networkmanagerbackend "github.com/blackbirdworks/gopherstack/services/networkmanager" ) @@ -538,7 +539,7 @@ func nmCoreNetworkResource() nmResource { create: func(bk *networkmanagerbackend.InMemoryBackend, c nmCreateCtx) (string, error) { policy := c.str("PolicyDocument") if doc, ok := c.props["PolicyDocument"].(map[string]any); ok { - raw, err := json.Marshal(resolveDeep(doc, c.params, c.physicalIDs)) + raw, err := json.Marshal(resolveDeep(doc, c.params, c.physicalIDs), jsonx.V1()) if err != nil { return "", err } diff --git a/services/cloudformation/resources_oam_test.go b/services/cloudformation/resources_oam_test.go index 023c7d9553..31a64bf564 100644 --- a/services/cloudformation/resources_oam_test.go +++ b/services/cloudformation/resources_oam_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/services/cloudformation" oambackend "github.com/blackbirdworks/gopherstack/services/oam" @@ -96,7 +97,7 @@ func oamTemplate(t *testing.T, sinkName string, linkTypes []string, linkFilter, "LinkArn": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Link", "Arn"}}}, "LinkLabl": map[string]any{"Value": map[string]any{"Fn::GetAtt": []string{"Link", "Label"}}}, }, - }) + }, jsonx.V1()) require.NoError(t, err) return string(doc) diff --git a/services/cloudformation/resources_rum_test.go b/services/cloudformation/resources_rum_test.go index ad0a638a92..7b66e924c4 100644 --- a/services/cloudformation/resources_rum_test.go +++ b/services/cloudformation/resources_rum_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/services/cloudformation" rumbackend "github.com/blackbirdworks/gopherstack/services/rum" @@ -87,7 +88,7 @@ func rumTemplate(name, domain, cwLog, custom, metric, team string) string { rumResMetric: "com.amazon.rum.performance_resource_event", }[metric] - policy, _ := json.Marshal(rumPolicyDocument) + policy, _ := json.Marshal(rumPolicyDocument, jsonx.V1()) return fmt.Sprintf(rumMonitorTemplate, name, domain, cwLog, custom, metric, eventType, policy, team) } diff --git a/services/cloudformation/resources_sagemaker.go b/services/cloudformation/resources_sagemaker.go index 81dbac7d9a..f2c15aa03c 100644 --- a/services/cloudformation/resources_sagemaker.go +++ b/services/cloudformation/resources_sagemaker.go @@ -2,7 +2,7 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "strconv" @@ -267,13 +267,13 @@ func sagemakerFloatProp(props map[string]any, key string) float64 { // rawJSONProp reads a property as opaque JSON, returning nil when absent // (unlike jsonProp's "", which is not valid json.RawMessage). -func rawJSONProp(props map[string]any, key string) json.RawMessage { +func rawJSONProp(props map[string]any, key string) jsontext.Value { s := jsonProp(props, key) if s == "" { return nil } - return json.RawMessage(s) + return jsontext.Value(s) } // ---- AWS::SageMaker::Model ---- diff --git a/services/cloudformation/resources_sagemaker_athena_wafv2_test.go b/services/cloudformation/resources_sagemaker_athena_wafv2_test.go index a11b2cb7f9..e050745bbc 100644 --- a/services/cloudformation/resources_sagemaker_athena_wafv2_test.go +++ b/services/cloudformation/resources_sagemaker_athena_wafv2_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "testing" @@ -553,7 +553,7 @@ func testWAFv2WebACLAssociation(t *testing.T) { // association template below can reference its real ARN. acl, err := backends.WAFv2.Backend.CreateWebACL( t.Context(), "acl-1", "REGIONAL", "", - json.RawMessage(`{"Allow":{}}`), nil, + jsontext.Value(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, diff --git a/services/cloudformation/resources_ssm.go b/services/cloudformation/resources_ssm.go index d147af7838..a1eb48d2d1 100644 --- a/services/cloudformation/resources_ssm.go +++ b/services/cloudformation/resources_ssm.go @@ -2,9 +2,10 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ssmbackend "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -209,5 +210,5 @@ func (rc *ResourceCreator) deleteSSMDocument(ctx context.Context, name string) e // marshalJSON serializes a value to compact JSON bytes. func marshalJSON(v any) ([]byte, error) { - return json.Marshal(v) + return json.Marshal(v, jsonx.V1()) } diff --git a/services/cloudformation/resources_ssm_more.go b/services/cloudformation/resources_ssm_more.go index bcb61a67e2..d3edc31559 100644 --- a/services/cloudformation/resources_ssm_more.go +++ b/services/cloudformation/resources_ssm_more.go @@ -2,10 +2,11 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ssmbackend "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -382,7 +383,7 @@ func jsonProp(props map[string]any, key string) string { return s } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "" } diff --git a/services/cloudformation/resources_wafv2.go b/services/cloudformation/resources_wafv2.go index 1fa6b9c3f9..bd31053531 100644 --- a/services/cloudformation/resources_wafv2.go +++ b/services/cloudformation/resources_wafv2.go @@ -2,7 +2,7 @@ package cloudformation import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" ) @@ -33,7 +33,7 @@ func (rc *ResourceCreator) createWAFv2WebACL( acl, err := rc.backends.WAFv2.Backend.CreateWebACL( ctx, name, scope, "", - json.RawMessage(`{"Allow":{}}`), nil, + jsontext.Value(`{"Allow":{}}`), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, diff --git a/services/cloudformation/sam_api.go b/services/cloudformation/sam_api.go index 35154935f7..5739d68406 100644 --- a/services/cloudformation/sam_api.go +++ b/services/cloudformation/sam_api.go @@ -1,10 +1,12 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "maps" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -188,11 +190,11 @@ func (a *samAPI) stageProps(depID string) map[string]any { func (a *samAPI) body() (map[string]any, error) { doc := map[string]any{} if def := asMap(a.props["DefinitionBody"]); def != nil { - raw, err := json.Marshal(def) + raw, err := json.Marshal(def, jsonx.V1()) if err != nil { return nil, err } - if err = json.Unmarshal(raw, &doc); err != nil { + if err = json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return nil, err } } else { diff --git a/services/cloudformation/sam_events_test.go b/services/cloudformation/sam_events_test.go index d5ab71bba7..d82dfee656 100644 --- a/services/cloudformation/sam_events_test.go +++ b/services/cloudformation/sam_events_test.go @@ -2,7 +2,7 @@ package cloudformation_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -20,6 +20,7 @@ import ( cfnsdk "github.com/aws/aws-sdk-go-v2/service/cloudformation" "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" apigatewayv2backend "github.com/blackbirdworks/gopherstack/services/apigatewayv2" "github.com/blackbirdworks/gopherstack/services/cloudformation" @@ -54,12 +55,12 @@ func (r *recordingInvoker) InvokeFunction( "Version": "2012-10-17", "Statement": []any{map[string]any{ "Action": "execute-api:Invoke", "Effect": effect, "Resource": "*", }}, - }}) + }}, jsonx.V1()) return policy, http.StatusOK, nil } r.calls <- invocation{name: fn, payload: string(payload)} - resp, _ := json.Marshal(map[string]any{"statusCode": 200, "body": fn}) + resp, _ := json.Marshal(map[string]any{"statusCode": 200, "body": fn}, jsonx.V1()) return resp, http.StatusOK, nil } diff --git a/services/cloudformation/sam_misc.go b/services/cloudformation/sam_misc.go index ea165a9402..c68816bbb3 100644 --- a/services/cloudformation/sam_misc.go +++ b/services/cloudformation/sam_misc.go @@ -1,6 +1,10 @@ package cloudformation -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) func samTableAllowed() map[string]bool { return keySet("PrimaryKey", "ProvisionedThroughput", samKeyTableName, "Tags", "SSESpecification", @@ -134,7 +138,7 @@ func (t *samTranslator) translateStateMachine(id string, r map[string]any) error func smDefinition(id string, props, sm map[string]any) error { switch { case props["Definition"] != nil: - raw, err := json.Marshal(props["Definition"]) + raw, err := json.Marshal(props["Definition"], jsonx.V1()) if err != nil { return samErr(id, "Definition is not valid JSON: %v", err) } diff --git a/services/cloudformation/sam_statemachine_events_test.go b/services/cloudformation/sam_statemachine_events_test.go index 14b9ede776..35b530fdae 100644 --- a/services/cloudformation/sam_statemachine_events_test.go +++ b/services/cloudformation/sam_statemachine_events_test.go @@ -1,7 +1,7 @@ package cloudformation_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const samSMDefinition = ` Definition: @@ -47,7 +49,7 @@ func processedResources(t *testing.T, env *samEventEnv) map[string]map[string]an require.NoError( t, - json.Unmarshal([]byte(getTemplate(t, env.client, "sam-stack", types.TemplateStageProcessed)), &doc), + json.Unmarshal([]byte(getTemplate(t, env.client, "sam-stack", types.TemplateStageProcessed)), &doc, jsonx.V1()), ) return doc.Resources diff --git a/services/cloudformation/sam_transform.go b/services/cloudformation/sam_transform.go index f3177abd7a..bda238ffbc 100644 --- a/services/cloudformation/sam_transform.go +++ b/services/cloudformation/sam_transform.go @@ -3,12 +3,15 @@ package cloudformation import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -83,7 +86,7 @@ func samGetAtt(id, attr string) map[string]any { } func samHash(v any) string { - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) sum := sha256.Sum256(raw) return hex.EncodeToString(sum[:])[:samHashLen] @@ -361,7 +364,7 @@ func processedTemplateBody(body string) (string, error) { } else { delete(doc, "Transform") } - out, err := json.MarshalIndent(doc, "", " ") + out, err := json.Marshal(doc, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) return string(out), err } @@ -379,7 +382,7 @@ func expandSAMBody(body string) (string, error) { if err = expandSAMDocument(doc); err != nil { return "", err } - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) return string(out), err } @@ -394,7 +397,7 @@ func decodeTemplateDoc(body string) (map[string]any, error) { jsonBody = converted } var doc map[string]any - if err := json.Unmarshal([]byte(jsonBody), &doc); err != nil { + if err := json.Unmarshal([]byte(jsonBody), &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("failed to parse JSON template: %w", err) } diff --git a/services/cloudformation/stack_policy_eval.go b/services/cloudformation/stack_policy_eval.go index bdb8cfed6a..eed967eae2 100644 --- a/services/cloudformation/stack_policy_eval.go +++ b/services/cloudformation/stack_policy_eval.go @@ -1,10 +1,12 @@ package cloudformation import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Stack policy evaluation semantics below are transcribed from AWS's @@ -59,14 +61,14 @@ type stackPolicyStringSet []string func (s *stackPolicyStringSet) UnmarshalJSON(data []byte) error { var single string - if err := json.Unmarshal(data, &single); err == nil { + if err := json.Unmarshal(data, &single, jsonx.V1()); err == nil { *s = stackPolicyStringSet{single} return nil } var multi []string - if err := json.Unmarshal(data, &multi); err != nil { + if err := json.Unmarshal(data, &multi, jsonx.V1()); err != nil { return err } @@ -91,7 +93,7 @@ const ( // rather than silently never enforcing anything at UpdateStack time. func parseStackPolicyDocument(policy string) (*stackPolicyDocument, error) { var doc stackPolicyDocument - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("malformed stack policy: %w", err) } diff --git a/services/cloudformation/template.go b/services/cloudformation/template.go index 9a5d478237..fc7f0112f5 100644 --- a/services/cloudformation/template.go +++ b/services/cloudformation/template.go @@ -2,7 +2,7 @@ package cloudformation import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -18,6 +18,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" directconnectbackend "github.com/blackbirdworks/gopherstack/services/directconnect" ) @@ -106,7 +107,7 @@ func (t *Template) fromPlain(p templatePlain) { // the real CloudFormation template schema. func (t *Template) UnmarshalJSON(data []byte) error { var p templatePlain - if err := json.Unmarshal(data, &p); err != nil { + if err := json.Unmarshal(data, &p, jsonx.V1()); err != nil { return err } t.fromPlain(p) @@ -189,7 +190,7 @@ func (r *TemplateResource) UnmarshalJSON(data []byte) error { } var p plain - if err := json.Unmarshal(data, &p); err != nil { + if err := json.Unmarshal(data, &p, jsonx.V1()); err != nil { return err } @@ -301,7 +302,7 @@ func ParseTemplate(body string) (*Template, error) { } var tmpl Template - if err := json.Unmarshal([]byte(body), &tmpl); err != nil { + if err := json.Unmarshal([]byte(body), &tmpl, jsonx.V1()); err != nil { return nil, fmt.Errorf("failed to parse JSON template: %w", err) } @@ -360,7 +361,7 @@ func yamlToJSON(body string) (string, error) { return "", err } - out, err := json.Marshal(val) + out, err := json.Marshal(val, jsonx.V1()) if err != nil { return "", fmt.Errorf("failed to serialise normalised YAML template: %w", err) } @@ -492,7 +493,7 @@ func expandLanguageExtensions(body string) (string, error) { } doc["Resources"] = expanded - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return "", fmt.Errorf("failed to serialise expanded template: %w", err) } @@ -513,7 +514,7 @@ func parseGenericTemplate(body string) (map[string]any, error) { } var doc map[string]any - if err := json.Unmarshal([]byte(trimmed), &doc); err != nil { + if err := json.Unmarshal([]byte(trimmed), &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("failed to parse JSON template: %w", err) } @@ -1073,7 +1074,7 @@ func resolveMiscIntrinsic(val map[string]any, ctx resolveCtx) string { // Fn::ToJsonString: serialize value to JSON string (#13) if jsonVal, hasJSON := val["Fn::ToJsonString"]; hasJSON { - data, err := json.Marshal(jsonVal) + data, err := json.Marshal(jsonVal, jsonx.V1()) if err != nil { return "" } @@ -1914,7 +1915,7 @@ func invokeMacroTransform(macroName string, transformSpec map[string]any, ctx re } // Build a minimal fragment from the transform spec parameters. - fragmentJSON, err := json.Marshal(resolvedParams) + fragmentJSON, err := json.Marshal(resolvedParams, jsonx.V1()) if err != nil { return "" } diff --git a/services/cloudformation/template_preflight.go b/services/cloudformation/template_preflight.go index 59687e5ed7..c4045b4cc8 100644 --- a/services/cloudformation/template_preflight.go +++ b/services/cloudformation/template_preflight.go @@ -1,13 +1,14 @@ package cloudformation import ( - "encoding/json" "errors" "reflect" "regexp" "slices" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrTemplateFormat is the "Template format error: ..." family real @@ -65,18 +66,18 @@ func lineColumn(body string, offset int64) (int, int) { // templateParseFormatErr maps a ParseTemplate failure to AWS's synchronous // "Template format error" wording; non-syntax failures pass through unchanged. func templateParseFormatErr(body string, err error) error { - if syn, ok := errors.AsType[*json.SyntaxError](err); ok { - line, col := lineColumn(strings.TrimSpace(body), syn.Offset) + if offset, ok := jsonx.SyntaxError(err); ok { + line, col := lineColumn(strings.TrimSpace(body), offset) return templateFormatErr("JSON not well-formed. (line %d, column %d)", line, col) } - if typ, ok := errors.AsType[*json.UnmarshalTypeError](err); ok { - if strings.HasSuffix(typ.Field, "Description") { + if field, ok := jsonx.TypeError(err); ok { + if strings.HasSuffix(field, "Description") { return templateFormatErr("Every Description member must be a string.") } - return templateFormatErr("%s has an invalid type", typ.Field) + return templateFormatErr("%s has an invalid type", field) } if strings.Contains(err.Error(), "failed to parse YAML template") { diff --git a/services/cloudformation/template_strictness.go b/services/cloudformation/template_strictness.go index fe5707dcf2..05e949eb03 100644 --- a/services/cloudformation/template_strictness.go +++ b/services/cloudformation/template_strictness.go @@ -2,12 +2,14 @@ package cloudformation import ( _ "embed" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "sort" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed cfn_resource_services.json @@ -22,7 +24,7 @@ var ( func knownResourceServices() map[string]struct{} { cfnResourceServicesOnce.Do(func() { var raw []string - if err := json.Unmarshal(cfnResourceServicesJSON, &raw); err != nil { + if err := json.Unmarshal(cfnResourceServicesJSON, &raw, jsonx.V1()); err != nil { panic("cloudformation: invalid embedded cfn_resource_services.json: " + err.Error()) } @@ -272,7 +274,7 @@ var ( // every other type stays unchecked rather than guessed. func requiredResourceProperties() map[string][]string { cfnRequiredPropertiesOnce.Do(func() { - if err := json.Unmarshal(cfnRequiredPropertiesJSON, &cfnRequiredProperties); err != nil { + if err := json.Unmarshal(cfnRequiredPropertiesJSON, &cfnRequiredProperties, jsonx.V1()); err != nil { panic("cloudformation: invalid embedded cfn_required_properties.json: " + err.Error()) } }) diff --git a/services/cloudfront/dataplane_edge.go b/services/cloudfront/dataplane_edge.go index f34aac37f4..31f97d097b 100644 --- a/services/cloudfront/dataplane_edge.go +++ b/services/cloudfront/dataplane_edge.go @@ -3,13 +3,15 @@ package cloudfront import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "slices" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -246,7 +248,7 @@ func (h *Handler) edgeInvoke( } } - payload, _ := json.Marshal(map[string]any{"Records": []any{map[string]any{"cf": cf}}}) + payload, _ := json.Marshal(map[string]any{"Records": []any{map[string]any{"cf": cf}}}, jsonx.V1()) res, fnErr, err := edge.InvokeEdge(ctx, arn.name, arn.version, payload) @@ -264,7 +266,7 @@ func (h *Handler) edgeInvoke( } var out map[string]any - if json.Unmarshal(res, &out) != nil || out == nil { + if json.Unmarshal(res, &out, jsonx.V1()) != nil || out == nil { return nil, edgeValidation( "The Lambda function returned a value that is not a valid request or response object.", ) diff --git a/services/cloudfront/dataplane_function.go b/services/cloudfront/dataplane_function.go index 5f26a50e0e..0ca63448de 100644 --- a/services/cloudfront/dataplane_function.go +++ b/services/cloudfront/dataplane_function.go @@ -1,12 +1,14 @@ package cloudfront import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/url" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -115,7 +117,7 @@ func (h *Handler) runFunction( } var out map[string]any - if err := json.Unmarshal([]byte(res.Output), &out); err != nil { + if err := json.Unmarshal([]byte(res.Output), &out, jsonx.V1()); err != nil { return nil, res, false } diff --git a/services/cloudfront/dataplane_s3_policy.go b/services/cloudfront/dataplane_s3_policy.go index b9c27e2788..7e3fa673fd 100644 --- a/services/cloudfront/dataplane_s3_policy.go +++ b/services/cloudfront/dataplane_s3_policy.go @@ -1,9 +1,12 @@ package cloudfront import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -39,7 +42,7 @@ const ( ) type policyDoc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } type policyStatement struct { @@ -52,17 +55,17 @@ type policyStatement struct { func parseStatements(policyJSON string) []policyStatement { var doc policyDoc - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return nil } var many []policyStatement - if err := json.Unmarshal(doc.Statement, &many); err == nil { + if err := json.Unmarshal(doc.Statement, &many, jsonx.V1()); err == nil { return many } var one policyStatement - if err := json.Unmarshal(doc.Statement, &one); err == nil { + if err := json.Unmarshal(doc.Statement, &one, jsonx.V1()); err == nil { return []policyStatement{one} } diff --git a/services/cloudfront/dataplane_signing.go b/services/cloudfront/dataplane_signing.go index 86f91e57d9..ab2770938f 100644 --- a/services/cloudfront/dataplane_signing.go +++ b/services/cloudfront/dataplane_signing.go @@ -6,13 +6,15 @@ import ( "crypto/sha1" //nolint:gosec // CloudFront signed URLs mandate RSA-SHA1 "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "net" "net/http" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func isSignedQueryKey(name string) bool { @@ -224,7 +226,7 @@ func cannedPolicyDoc(resource string, expires int64) ([]byte, error) { return json.Marshal(cannedPolicy{Statement: []cannedStatement{{ Resource: resource, Condition: cannedCondition{DateLessThan: cannedEpoch{EpochTime: expires}}, - }}}) + }}}, jsonx.V1()) } func rsaSHA1Verify(key *rsa.PublicKey, doc, sig []byte) bool { @@ -240,7 +242,7 @@ func verifyCustomPolicy(v *viewerReq, d *Distribution, key *rsa.PublicKey, polic } var pol signedPolicy - if json.Unmarshal(doc, &pol) != nil || len(pol.Statement) == 0 { + if json.Unmarshal(doc, &pol, jsonx.V1()) != nil || len(pol.Statement) == 0 { return false } diff --git a/services/cloudfront/dataplane_signing_internal_test.go b/services/cloudfront/dataplane_signing_internal_test.go index 7964ec99b7..7e30c91562 100644 --- a/services/cloudfront/dataplane_signing_internal_test.go +++ b/services/cloudfront/dataplane_signing_internal_test.go @@ -1,11 +1,13 @@ package cloudfront import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCannedPolicyDoc(t *testing.T) { @@ -37,7 +39,7 @@ func TestCannedPolicyDoc(t *testing.T) { doc, err := cannedPolicyDoc(tt.resource, 42) require.NoError(t, err) assert.Equal(t, tt.want, string(doc)) - assert.True(t, json.Valid(doc)) + assert.True(t, jsontext.Value(doc).IsValid(jsonx.V1())) }) } } diff --git a/services/cloudfront/distributions_transition_test.go b/services/cloudfront/distributions_transition_test.go index 08464133f4..f060b6d5f8 100644 --- a/services/cloudfront/distributions_transition_test.go +++ b/services/cloudfront/distributions_transition_test.go @@ -1,12 +1,13 @@ package cloudfront_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudfront" ) @@ -131,7 +132,7 @@ func TestDeleteDistribution_CleansUpSideMaps(t *testing.T) { require.NotEmpty(t, data) var probe distSnapshotProbe - require.NoError(t, json.Unmarshal(data, &probe)) + require.NoError(t, json.Unmarshal(data, &probe, jsonx.V1())) _, leaked := probe.FuncAssocs[d.ID] require.False(t, leaked, "distributionFunctionAssociations must not retain a deleted distribution's entry") diff --git a/services/cloudfront/function_exec.go b/services/cloudfront/function_exec.go index c8befa45ca..03461c20b5 100644 --- a/services/cloudfront/function_exec.go +++ b/services/cloudfront/function_exec.go @@ -1,13 +1,15 @@ package cloudfront import ( - "encoding/json" + "encoding/json/v2" "fmt" "html" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // storeKVS adapts the backend's Key Value Stores to a running function. @@ -74,7 +76,7 @@ func (b *InMemoryBackend) ExecuteFunction(name, stage string, event any) (*Funct func (h *Handler) runTestFunction(c *echo.Context, name, stage string, eventObject []byte) error { var event any - if err := json.Unmarshal(eventObject, &event); err != nil { + if err := json.Unmarshal(eventObject, &event, jsonx.V1()); err != nil { return xmlResp(c, http.StatusBadRequest, cfErrorXML("InvalidArgument", "EventObject must be valid JSON")) } diff --git a/services/cloudfront/handler_distribution_tenants.go b/services/cloudfront/handler_distribution_tenants.go index f77e1f182b..954f57e886 100644 --- a/services/cloudfront/handler_distribution_tenants.go +++ b/services/cloudfront/handler_distribution_tenants.go @@ -1,7 +1,7 @@ package cloudfront import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -11,6 +11,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDomainAssociationError maps UpdateDomainAssociation errors. Its own @@ -194,13 +196,13 @@ func (c *tenantCustomizationsXML) toMap() map[string]any { return nil } - raw, err := json.Marshal(c) + raw, err := json.Marshal(c, jsonx.V1()) if err != nil { return nil } var out map[string]any - if json.Unmarshal(raw, &out) != nil { + if json.Unmarshal(raw, &out, jsonx.V1()) != nil { return nil } @@ -212,13 +214,13 @@ func tenantCustomizationsFromMap(m map[string]any) *tenantCustomizationsXML { return nil } - raw, err := json.Marshal(m) + raw, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil } var out tenantCustomizationsXML - if json.Unmarshal(raw, &out) != nil { + if json.Unmarshal(raw, &out, jsonx.V1()) != nil { return nil } diff --git a/services/cloudfront/handler_functions.go b/services/cloudfront/handler_functions.go index 538931e81c..5fd0936fb3 100644 --- a/services/cloudfront/handler_functions.go +++ b/services/cloudfront/handler_functions.go @@ -2,13 +2,15 @@ package cloudfront import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" "encoding/xml" "fmt" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type functionConfigXML struct { @@ -383,7 +385,7 @@ func (h *Handler) handleTestFunction(c *echo.Context, name string) error { ) } - if !json.Valid(eventObject) { + if !jsontext.Value(eventObject).IsValid(jsonx.V1()) { return xmlResp( c, http.StatusBadRequest, diff --git a/services/cloudfront/handler_key_value_store_test.go b/services/cloudfront/handler_key_value_store_test.go index 68b7458743..6e8c188a41 100644 --- a/services/cloudfront/handler_key_value_store_test.go +++ b/services/cloudfront/handler_key_value_store_test.go @@ -1,7 +1,7 @@ package cloudfront_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudfront" ) @@ -412,7 +413,7 @@ func TestInMemoryBackend_KeyValueStore(t *testing.T) { KeyValueStoreData map[string]map[string]string `json:"keyValueStoreData"` KeyValueDataETags map[string]string `json:"keyValueDataETags"` } - require.NoError(t, json.Unmarshal(snap, &decoded)) + require.NoError(t, json.Unmarshal(snap, &decoded, jsonx.V1())) assert.NotContains(t, decoded.KeyValueStoreData, kvs.ID, "deleted KVS's data-plane values must not survive in the persisted snapshot") assert.NotContains(t, decoded.KeyValueDataETags, kvs.ID, diff --git a/services/cloudfront/kvs_import.go b/services/cloudfront/kvs_import.go index 0290080d45..01ce59e584 100644 --- a/services/cloudfront/kvs_import.go +++ b/services/cloudfront/kvs_import.go @@ -2,9 +2,11 @@ package cloudfront import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -64,7 +66,7 @@ func (h *Handler) readKVSImport(ctx context.Context, src *kvsImportSourceXML) ([ func parseKVSImport(raw []byte) ([]*KVSItem, error) { var doc kvsImportDocument - if err := json.Unmarshal(raw, &doc); err != nil { + if err := json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: import source is not valid JSON: %w", ErrValidation, err) } diff --git a/services/cloudfront/lambda_edge_test.go b/services/cloudfront/lambda_edge_test.go index 8d6be91e34..5505e2da27 100644 --- a/services/cloudfront/lambda_edge_test.go +++ b/services/cloudfront/lambda_edge_test.go @@ -3,7 +3,7 @@ package cloudfront_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudfront" ) @@ -48,7 +49,7 @@ func (f *fakeEdge) InvokeEdge(_ context.Context, name, version string, payload [ } `json:"Records"` } - if err := json.Unmarshal(payload, &in); err != nil || len(in.Records) != 1 { + if err := json.Unmarshal(payload, &in, jsonx.V1()); err != nil || len(in.Records) != 1 { return nil, "", fmt.Errorf("%w: bad event", errFakeEdge) } @@ -62,7 +63,7 @@ func (f *fakeEdge) InvokeEdge(_ context.Context, name, version string, payload [ } `json:"Records"` } - _ = json.Unmarshal(payload, &snapshot) + _ = json.Unmarshal(payload, &snapshot, jsonx.V1()) f.mu.Lock() f.calls[name]++ @@ -75,7 +76,7 @@ func (f *fakeEdge) InvokeEdge(_ context.Context, name, version string, payload [ return nil, fnErr, err } - b, _ := json.Marshal(out) + b, _ := json.Marshal(out, jsonx.V1()) return b, "", nil } diff --git a/services/cloudfront/persistence.go b/services/cloudfront/persistence.go index 715b1c985a..1c1af6d512 100644 --- a/services/cloudfront/persistence.go +++ b/services/cloudfront/persistence.go @@ -2,11 +2,13 @@ package cloudfront import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -112,7 +114,7 @@ var dirtyTableNames = struct { // registerAllTables doc for the clean/dirty split), merged into one map so a // single Tables blob round-trips the whole backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` DistributionFunctionAssociations map[string][]FunctionAssociation `json:"distributionFunctionAssociations,omitempty"` DistributionAliases map[string][]string `json:"distributionAliases,omitempty"` @@ -199,7 +201,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "cloudfront: Snapshot marshal failure", "error", err) @@ -277,7 +279,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // b.registry -- see store_setup.go's registerAllTables doc) from an ephemeral DTO // [store.Registry] built from tables, converting each DTO back to a live // Invalidation. Must be called with the lock held. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtoReg := store.NewRegistry() invalidationDTOs := store.Register(dtoReg, dirtyTableNames.invalidations, store.New(invalidationSnapshotKey)) tenantInvalidationDTOs := store.Register( @@ -550,7 +552,7 @@ func tableFrom[T any](snap *backendSnapshot, name string) []*T { } var out []*T - if err := json.Unmarshal(raw, &out); err != nil { + if err := json.Unmarshal(raw, &out, jsonx.V1()); err != nil { return nil } diff --git a/services/cloudfrontkeyvaluestore/handler.go b/services/cloudfrontkeyvaluestore/handler.go index b8d025af7e..cd15e2b7c3 100644 --- a/services/cloudfrontkeyvaluestore/handler.go +++ b/services/cloudfrontkeyvaluestore/handler.go @@ -6,7 +6,7 @@ package cloudfrontkeyvaluestore import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strconv" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -451,7 +452,7 @@ func (h *Handler) handlePutKey(c *echo.Context, kvs *cloudfrontbackend.KeyValueS var req putKeyInput if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeAWSError(c, http.StatusBadRequest, exceptionValidation, "invalid JSON body") } } @@ -549,7 +550,7 @@ func (h *Handler) handleUpdateKeys(c *echo.Context, kvs *cloudfrontbackend.KeyVa var req updateKeysInput if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeAWSError(c, http.StatusBadRequest, exceptionValidation, "invalid JSON body") } } @@ -656,7 +657,7 @@ func epochSeconds(rfc3339 string) float64 { // typical REST delete, their outputs carry a body, so 204 No Content is not // an option). func writeJSON(c *echo.Context, v any) error { - body, err := json.Marshal(v) + body, err := json.Marshal(v, jsonx.V1()) if err != nil { return writeAWSError(c, http.StatusInternalServerError, exceptionInternalServer, "response marshal failed") } diff --git a/services/cloudhsmv2/backups.go b/services/cloudhsmv2/backups.go index c87ed61208..13875e07e2 100644 --- a/services/cloudhsmv2/backups.go +++ b/services/cloudhsmv2/backups.go @@ -7,12 +7,13 @@ import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "slices" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -110,7 +111,7 @@ func policyGrants(policy, account string) bool { Effect string `json:"Effect"` } `json:"Statement"` } - if json.Unmarshal([]byte(policy), &doc) != nil { + if json.Unmarshal([]byte(policy), &doc, jsonx.V1()) != nil { return false } diff --git a/services/cloudhsmv2/handler.go b/services/cloudhsmv2/handler.go index c9c6c786e1..f178614d76 100644 --- a/services/cloudhsmv2/handler.go +++ b/services/cloudhsmv2/handler.go @@ -2,7 +2,7 @@ package cloudhsmv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -36,7 +37,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrInvalidRequest, "malformed request body: %v", err) } } diff --git a/services/cloudhsmv2/persistence.go b/services/cloudhsmv2/persistence.go index f3efa4b1ed..ba92833366 100644 --- a/services/cloudhsmv2/persistence.go +++ b/services/cloudhsmv2/persistence.go @@ -2,7 +2,7 @@ package cloudhsmv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/cloudhsmv2/policies.go b/services/cloudhsmv2/policies.go index 39a851ac7d..14d3087bc2 100644 --- a/services/cloudhsmv2/policies.go +++ b/services/cloudhsmv2/policies.go @@ -2,8 +2,11 @@ package cloudhsmv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (b *InMemoryBackend) policyBackupLocked(sc scope, resourceARN string) (*Backup, error) { @@ -21,10 +24,10 @@ func (b *InMemoryBackend) policyBackupLocked(sc scope, resourceARN string) (*Bac // PutResourcePolicy attaches a policy to a READY backup the caller owns. func (b *InMemoryBackend) PutResourcePolicy(ctx context.Context, resourceARN, policy string) (string, error) { var doc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if policy == "" || json.Unmarshal([]byte(policy), &doc) != nil || len(doc.Statement) == 0 { + if policy == "" || json.Unmarshal([]byte(policy), &doc, jsonx.V1()) != nil || len(doc.Statement) == 0 { return "", fail(ErrInvalidRequest, "Policy must be a JSON policy document with a Statement") } diff --git a/services/cloudtrail/delivery.go b/services/cloudtrail/delivery.go index a9774446d5..19aa741590 100644 --- a/services/cloudtrail/delivery.go +++ b/services/cloudtrail/delivery.go @@ -4,7 +4,8 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" "sync" @@ -13,6 +14,8 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // logFileRecords is the top-level shape of a CloudTrail log file: a single @@ -20,7 +23,7 @@ import ( // User Guide "CloudTrail log file examples"), not part of the pinned SDK -- // see PARITY.md. type logFileRecords struct { - Records []json.RawMessage `json:"Records"` + Records []jsontext.Value `json:"Records"` } // deliveryTarget is a snapshot of the fields deliverLogFile needs from one @@ -107,7 +110,7 @@ var gzipWriterPool = sync.Pool{ //nolint:gochecknoglobals // sync.Pool requires // logFileBody gzip-compresses a single-record CloudTrail log file body. func logFileBody(ev Event) ([]byte, error) { encoded, err := json.Marshal( - logFileRecords{Records: []json.RawMessage{json.RawMessage(ev.CloudTrailEvent)}}, + logFileRecords{Records: []jsontext.Value{jsontext.Value(ev.CloudTrailEvent)}}, jsonx.V1(), ) if err != nil { return nil, err diff --git a/services/cloudtrail/handler.go b/services/cloudtrail/handler.go index 1c3ed6b8aa..59216625ce 100644 --- a/services/cloudtrail/handler.go +++ b/services/cloudtrail/handler.go @@ -1,7 +1,8 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -184,9 +186,9 @@ func (h *Handler) Handler() echo.HandlerFunc { var body []byte if c.Request().Body != nil { - decoder := json.NewDecoder(c.Request().Body) - var raw json.RawMessage - if err := decoder.Decode(&raw); err == nil { + decoder := jsontext.NewDecoder(c.Request().Body) + var raw jsontext.Value + if err := json.UnmarshalDecode(decoder, &raw, jsonx.V1()); err == nil { body = raw } } diff --git a/services/cloudtrail/handler_channels.go b/services/cloudtrail/handler_channels.go index 664471deed..c783e5497f 100644 --- a/services/cloudtrail/handler_channels.go +++ b/services/cloudtrail/handler_channels.go @@ -1,11 +1,12 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -27,7 +28,7 @@ type createChannelBody struct { func (h *Handler) handleCreateChannel(c *echo.Context, body []byte) error { var in createChannelBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -81,7 +82,7 @@ type deleteChannelBody struct { func (h *Handler) handleDeleteChannel(c *echo.Context, body []byte) error { var in deleteChannelBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -100,7 +101,7 @@ type getChannelBody struct { func (h *Handler) handleGetChannel(c *echo.Context, body []byte) error { var in getChannelBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -127,7 +128,7 @@ type updateChannelBody struct { func (h *Handler) handleUpdateChannel(c *echo.Context, body []byte) error { var in updateChannelBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -154,7 +155,7 @@ type listChannelsBody struct { func (h *Handler) handleListChannels(c *echo.Context, body []byte) error { var in listChannelsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), diff --git a/services/cloudtrail/handler_dashboards.go b/services/cloudtrail/handler_dashboards.go index e6d3c9c8c3..284b4b545f 100644 --- a/services/cloudtrail/handler_dashboards.go +++ b/services/cloudtrail/handler_dashboards.go @@ -1,12 +1,13 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -74,7 +75,7 @@ type createDashboardBody struct { func (h *Handler) handleCreateDashboard(c *echo.Context, body []byte) error { var in createDashboardBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -104,7 +105,7 @@ type deleteDashboardBody struct { func (h *Handler) handleDeleteDashboard(c *echo.Context, body []byte) error { var in deleteDashboardBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -123,7 +124,7 @@ type getDashboardBody struct { func (h *Handler) handleGetDashboard(c *echo.Context, body []byte) error { var in getDashboardBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -151,7 +152,7 @@ type updateDashboardBody struct { func (h *Handler) handleUpdateDashboard(c *echo.Context, body []byte) error { var in updateDashboardBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -180,7 +181,7 @@ type listDashboardsBody struct { func (h *Handler) handleListDashboards(c *echo.Context, body []byte) error { var in listDashboardsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -232,7 +233,7 @@ type startDashboardRefreshBody struct { func (h *Handler) handleStartDashboardRefresh(c *echo.Context, body []byte) error { var in startDashboardRefreshBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_event_data_stores.go b/services/cloudtrail/handler_event_data_stores.go index 4e1112ebe5..e5314f57af 100644 --- a/services/cloudtrail/handler_event_data_stores.go +++ b/services/cloudtrail/handler_event_data_stores.go @@ -1,11 +1,12 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -33,7 +34,7 @@ type createEventDataStoreBody struct { func (h *Handler) handleCreateEventDataStore(c *echo.Context, body []byte) error { var in createEventDataStoreBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -74,7 +75,7 @@ type deleteEventDataStoreBody struct { func (h *Handler) handleDeleteEventDataStore(c *echo.Context, body []byte) error { var in deleteEventDataStoreBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -93,7 +94,7 @@ type getEventDataStoreBody struct { func (h *Handler) handleGetEventDataStore(c *echo.Context, body []byte) error { var in getEventDataStoreBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -121,7 +122,7 @@ type updateEventDataStoreBody struct { func (h *Handler) handleUpdateEventDataStore(c *echo.Context, body []byte) error { var in updateEventDataStoreBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -150,7 +151,7 @@ type listEventDataStoresBody struct { func (h *Handler) handleListEventDataStores(c *echo.Context, body []byte) error { var in listEventDataStoresBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -186,7 +187,7 @@ type restoreEventDataStoreBody struct { func (h *Handler) handleRestoreEventDataStore(c *echo.Context, body []byte) error { var in restoreEventDataStoreBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -206,7 +207,7 @@ type startEventDataStoreIngestionBody struct { func (h *Handler) handleStartEventDataStoreIngestion(c *echo.Context, body []byte) error { var in startEventDataStoreIngestionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -225,7 +226,7 @@ type stopEventDataStoreIngestionBody struct { func (h *Handler) handleStopEventDataStoreIngestion(c *echo.Context, body []byte) error { var in stopEventDataStoreIngestionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -244,7 +245,7 @@ type disableFederationBody struct { func (h *Handler) handleDisableFederation(c *echo.Context, body []byte) error { var in disableFederationBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -275,7 +276,7 @@ type enableFederationBody struct { func (h *Handler) handleEnableFederation(c *echo.Context, body []byte) error { var in enableFederationBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_event_selectors.go b/services/cloudtrail/handler_event_selectors.go index 5e68e4ba3e..36fa093faa 100644 --- a/services/cloudtrail/handler_event_selectors.go +++ b/services/cloudtrail/handler_event_selectors.go @@ -1,12 +1,13 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -53,7 +54,7 @@ type putEventSelectorsBody struct { func (h *Handler) handlePutEventSelectors(c *echo.Context, body []byte) error { var in putEventSelectorsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -95,7 +96,7 @@ type getEventSelectorsBody struct { func (h *Handler) handleGetEventSelectors(c *echo.Context, body []byte) error { var in getEventSelectorsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -133,7 +134,7 @@ type putInsightSelectorsBody struct { func (h *Handler) handlePutInsightSelectors(c *echo.Context, body []byte) error { var in putInsightSelectorsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -182,7 +183,7 @@ type getInsightSelectorsBody struct { func (h *Handler) handleGetInsightSelectors(c *echo.Context, body []byte) error { var in getInsightSelectorsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -229,7 +230,7 @@ type getEventConfigurationBody struct { func (h *Handler) handleGetEventConfiguration(c *echo.Context, body []byte) error { var in getEventConfigurationBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -255,7 +256,7 @@ type putEventConfigurationBody struct { func (h *Handler) handlePutEventConfiguration(c *echo.Context, body []byte) error { var in putEventConfigurationBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -336,7 +337,7 @@ type listInsightsDataBody struct { func (h *Handler) handleListInsightsData(c *echo.Context, body []byte) error { var in listInsightsDataBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -382,7 +383,7 @@ type listInsightsMetricDataBody struct { func (h *Handler) handleListInsightsMetricData(c *echo.Context, body []byte) error { var in listInsightsMetricDataBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } if in.EventName == "" { diff --git a/services/cloudtrail/handler_events.go b/services/cloudtrail/handler_events.go index 72354ef6bd..6018e849bb 100644 --- a/services/cloudtrail/handler_events.go +++ b/services/cloudtrail/handler_events.go @@ -1,7 +1,7 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "math" "net/http" "time" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- LookupEvents --- @@ -25,7 +26,7 @@ type lookupEventsBody struct { func (h *Handler) handleLookupEvents(c *echo.Context, body []byte) error { var in lookupEventsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), diff --git a/services/cloudtrail/handler_imports.go b/services/cloudtrail/handler_imports.go index c090c0fb80..fcadc39111 100644 --- a/services/cloudtrail/handler_imports.go +++ b/services/cloudtrail/handler_imports.go @@ -1,7 +1,7 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "time" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -65,7 +66,7 @@ func (in startImportBody) toBackendImportSource() *ImportSource { func (h *Handler) handleStartImport(c *echo.Context, body []byte) error { var in startImportBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -101,7 +102,7 @@ type getImportBody struct { func (h *Handler) handleGetImport(c *echo.Context, body []byte) error { var in getImportBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -125,7 +126,7 @@ type listImportsBody struct { func (h *Handler) handleListImports(c *echo.Context, body []byte) error { var in listImportsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -182,7 +183,7 @@ type stopImportBody struct { func (h *Handler) handleStopImport(c *echo.Context, body []byte) error { var in stopImportBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -233,7 +234,7 @@ type listImportFailuresBody struct { func (h *Handler) handleListImportFailures(c *echo.Context, body []byte) error { var in listImportFailuresBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_queries.go b/services/cloudtrail/handler_queries.go index c6900281dc..ffbc9b79ac 100644 --- a/services/cloudtrail/handler_queries.go +++ b/services/cloudtrail/handler_queries.go @@ -1,13 +1,14 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -36,7 +37,7 @@ type startQueryBody struct { func (h *Handler) handleStartQuery(c *echo.Context, body []byte) error { var in startQueryBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -87,7 +88,7 @@ type cancelQueryBody struct { func (h *Handler) handleCancelQuery(c *echo.Context, body []byte) error { var in cancelQueryBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -125,7 +126,7 @@ type describeQueryBody struct { func (h *Handler) handleDescribeQuery(c *echo.Context, body []byte) error { var in describeQueryBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -188,7 +189,7 @@ type getQueryResultsBody struct { func (h *Handler) handleGetQueryResults(c *echo.Context, body []byte) error { var in getQueryResultsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -241,7 +242,7 @@ type listQueriesBody struct { func (h *Handler) handleListQueries(c *echo.Context, body []byte) error { var in listQueriesBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -329,7 +330,7 @@ type generateQueryBody struct { func (h *Handler) handleGenerateQuery(c *echo.Context, body []byte) error { var in generateQueryBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_resource_policies.go b/services/cloudtrail/handler_resource_policies.go index a7f93d7db4..ef84552a63 100644 --- a/services/cloudtrail/handler_resource_policies.go +++ b/services/cloudtrail/handler_resource_policies.go @@ -1,10 +1,12 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- DeleteResourcePolicy --- @@ -15,7 +17,7 @@ type deleteResourcePolicyBody struct { func (h *Handler) handleDeleteResourcePolicy(c *echo.Context, body []byte) error { var in deleteResourcePolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -34,7 +36,7 @@ type getResourcePolicyBody struct { func (h *Handler) handleGetResourcePolicy(c *echo.Context, body []byte) error { var in getResourcePolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -58,7 +60,7 @@ type putResourcePolicyBody struct { func (h *Handler) handlePutResourcePolicy(c *echo.Context, body []byte) error { var in putResourcePolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_tags.go b/services/cloudtrail/handler_tags.go index 44325dafa7..747dd87297 100644 --- a/services/cloudtrail/handler_tags.go +++ b/services/cloudtrail/handler_tags.go @@ -1,10 +1,12 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- AddTags --- @@ -19,7 +21,7 @@ type addTagsBody struct { func (h *Handler) handleAddTags(c *echo.Context, body []byte) error { var in addTagsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -46,7 +48,7 @@ type removeTagsBody struct { func (h *Handler) handleRemoveTags(c *echo.Context, body []byte) error { var in removeTagsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -70,7 +72,7 @@ type listTagsBody struct { func (h *Handler) handleListTags(c *echo.Context, body []byte) error { var in listTagsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/handler_test.go b/services/cloudtrail/handler_test.go index bf4f236574..71fd921b31 100644 --- a/services/cloudtrail/handler_test.go +++ b/services/cloudtrail/handler_test.go @@ -2,7 +2,8 @@ package cloudtrail_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudtrail" ) @@ -34,7 +36,7 @@ func doCloudTrailOp( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -55,7 +57,7 @@ func parseCloudTrailResp(t *testing.T, rec *httptest.ResponseRecorder) map[strin t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -535,7 +537,7 @@ func TestCloudTrailListOperationsSmoke(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code, "op %s should return 200", op) var m map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &m, jsonx.V1())) } // ListQueries takes EventDataStore as required input (real @@ -551,7 +553,7 @@ func TestCloudTrailListOperationsSmoke(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code, "op ListQueries should return 200") var m map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &m, jsonx.V1())) } // TestCloudTrailAncillaryOperationsSmoke covers ancillary read-only handlers diff --git a/services/cloudtrail/handler_trails.go b/services/cloudtrail/handler_trails.go index ed8f58559a..60bf5429e8 100644 --- a/services/cloudtrail/handler_trails.go +++ b/services/cloudtrail/handler_trails.go @@ -1,12 +1,13 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -44,7 +45,7 @@ type createTrailBody struct { func (h *Handler) handleCreateTrail(c *echo.Context, body []byte) error { var in createTrailBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -87,7 +88,7 @@ type getTrailBody struct { func (h *Handler) handleGetTrail(c *echo.Context, body []byte) error { var in getTrailBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -109,7 +110,7 @@ type describeTrailsBody struct { func (h *Handler) handleDescribeTrails(c *echo.Context, body []byte) error { var in describeTrailsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -144,7 +145,7 @@ type updateTrailBody struct { func (h *Handler) handleUpdateTrail(c *echo.Context, body []byte) error { var in updateTrailBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -176,7 +177,7 @@ type deleteTrailBody struct { func (h *Handler) handleDeleteTrail(c *echo.Context, body []byte) error { var in deleteTrailBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -195,7 +196,7 @@ type startLoggingBody struct { func (h *Handler) handleStartLogging(c *echo.Context, body []byte) error { var in startLoggingBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -218,7 +219,7 @@ type stopLoggingBody struct { func (h *Handler) handleStopLogging(c *echo.Context, body []byte) error { var in stopLoggingBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -241,7 +242,7 @@ type getTrailStatusBody struct { func (h *Handler) handleGetTrailStatus(c *echo.Context, body []byte) error { var in getTrailStatusBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -277,7 +278,7 @@ type listTrailsBody struct { func (h *Handler) handleListTrails(c *echo.Context, body []byte) error { var in listTrailsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body"), @@ -313,7 +314,7 @@ type deregisterOrgDelegatedAdminBody struct { func (h *Handler) handleDeregisterOrganizationDelegatedAdmin(c *echo.Context, body []byte) error { var in deregisterOrgDelegatedAdminBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } @@ -332,7 +333,7 @@ type registerOrgDelegatedAdminBody struct { func (h *Handler) handleRegisterOrganizationDelegatedAdmin(c *echo.Context, body []byte) error { var in registerOrgDelegatedAdminBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterCombinationException", "invalid request body")) } diff --git a/services/cloudtrail/insights_metrics.go b/services/cloudtrail/insights_metrics.go index acbd6db797..5e3989f2e3 100644 --- a/services/cloudtrail/insights_metrics.go +++ b/services/cloudtrail/insights_metrics.go @@ -1,11 +1,13 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -80,7 +82,7 @@ func eventErrorCode(ev Event) string { ErrorCode string `json:"errorCode"` } - if ev.CloudTrailEvent == "" || json.Unmarshal([]byte(ev.CloudTrailEvent), &rec) != nil { + if ev.CloudTrailEvent == "" || json.Unmarshal([]byte(ev.CloudTrailEvent), &rec, jsonx.V1()) != nil { return "" } diff --git a/services/cloudtrail/management_event.go b/services/cloudtrail/management_event.go index c4870507c9..18b93a1bc6 100644 --- a/services/cloudtrail/management_event.go +++ b/services/cloudtrail/management_event.go @@ -1,12 +1,13 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "strconv" "time" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -126,7 +127,7 @@ func (b *InMemoryBackend) RecordManagementEvent(ev service.CloudTrailEventInput) // common case where every string is plain printable ASCII needing no escaping. func renderManagementEvent(d *managementEventDetail) string { if !d.plainStrings() { - blob, err := json.Marshal(d) + blob, err := json.Marshal(d, jsonx.V1()) if err != nil { return "" } diff --git a/services/cloudtrail/management_event_render_whitebox_test.go b/services/cloudtrail/management_event_render_whitebox_test.go index 180805f302..00aa993623 100644 --- a/services/cloudtrail/management_event_render_whitebox_test.go +++ b/services/cloudtrail/management_event_render_whitebox_test.go @@ -1,10 +1,12 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRenderManagementEventMatchesJSONMarshal(t *testing.T) { @@ -56,7 +58,7 @@ func TestRenderManagementEventMatchesJSONMarshal(t *testing.T) { d := base tt.mutate(&d) - want, err := json.Marshal(d) + want, err := json.Marshal(d, jsonx.V1()) require.NoError(t, err) require.Equal(t, string(want), renderManagementEvent(&d)) }) diff --git a/services/cloudtrail/models.go b/services/cloudtrail/models.go index c42ae1818b..50311a9d2b 100644 --- a/services/cloudtrail/models.go +++ b/services/cloudtrail/models.go @@ -1,10 +1,11 @@ package cloudtrail import ( - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -75,7 +76,7 @@ func (e Event) MarshalJSON() ([]byte, error) { }{ alias: alias(e), EventTime: awstime.Epoch(e.EventTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of MarshalJSON: it decodes the epoch-seconds @@ -92,7 +93,7 @@ func (e *Event) UnmarshalJSON(data []byte) error { EventTime float64 `json:"EventTime"` }{alias: (*alias)(e)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/cloudtrail/multi_region_test.go b/services/cloudtrail/multi_region_test.go index bdf01dc7f4..f32c31125b 100644 --- a/services/cloudtrail/multi_region_test.go +++ b/services/cloudtrail/multi_region_test.go @@ -2,7 +2,7 @@ package cloudtrail_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudtrail" ) @@ -42,7 +43,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/cloudtrail/persistence.go b/services/cloudtrail/persistence.go index 4d6b3990fd..77911dc1be 100644 --- a/services/cloudtrail/persistence.go +++ b/services/cloudtrail/persistence.go @@ -2,7 +2,7 @@ package cloudtrail import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -30,7 +30,7 @@ const cloudtrailSnapshotVersion = 1 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` EventConfigs map[string]*EventConfiguration `json:"eventConfigs,omitempty"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/cloudtrail/query_exec.go b/services/cloudtrail/query_exec.go index 2cb1b7eec2..0cc89fc4d4 100644 --- a/services/cloudtrail/query_exec.go +++ b/services/cloudtrail/query_exec.go @@ -2,13 +2,15 @@ package cloudtrail import ( "cmp" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // This file implements a bounded, honest subset of CloudTrail Lake SQL @@ -96,7 +98,7 @@ func eventToRow(ev Event) map[string]string { if ev.CloudTrailEvent != "" { var detail map[string]any - if err := json.Unmarshal([]byte(ev.CloudTrailEvent), &detail); err == nil { + if err := json.Unmarshal([]byte(ev.CloudTrailEvent), &detail, jsonx.V1()); err == nil { flattenJSONInto(row, "", detail) } } @@ -126,7 +128,7 @@ func flattenJSONInto(row map[string]string, prefix string, obj map[string]any) { // missing/null field. default: if _, exists := row[key]; !exists { - if b, err := json.Marshal(tv); err == nil { + if b, err := json.Marshal(tv, jsonx.V1()); err == nil { row[key] = string(b) } } diff --git a/services/cloudtrail/s3_delivery_test.go b/services/cloudtrail/s3_delivery_test.go index 50f71ceeae..a1596762db 100644 --- a/services/cloudtrail/s3_delivery_test.go +++ b/services/cloudtrail/s3_delivery_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudtrail" ) @@ -252,7 +253,7 @@ func TestRecordManagementEvent_DeliversLogFileToS3(t *testing.T) { var records struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(decoded, &records)) + require.NoError(t, json.Unmarshal(decoded, &records, jsonx.V1())) require.Len(t, records.Records, 1) assert.Equal(t, "CreateBucket", records.Records[0]["eventName"]) } diff --git a/services/cloudwatch/alarm_actions.go b/services/cloudwatch/alarm_actions.go index 10ae72f587..562af00410 100644 --- a/services/cloudwatch/alarm_actions.go +++ b/services/cloudwatch/alarm_actions.go @@ -2,12 +2,13 @@ package cloudwatch import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -53,7 +54,7 @@ func (b *InMemoryBackend) buildAlarmActionPayload( "StateChangeTime": time.Now().UTC().Format(time.RFC3339), } // map[string]string marshaling cannot fail; error is intentionally ignored. - bs, _ := json.Marshal(data) + bs, _ := json.Marshal(data, jsonx.V1()) return bs } diff --git a/services/cloudwatch/alarm_history.go b/services/cloudwatch/alarm_history.go index 93014f2eb4..8f73087bac 100644 --- a/services/cloudwatch/alarm_history.go +++ b/services/cloudwatch/alarm_history.go @@ -1,10 +1,11 @@ package cloudwatch import ( - "encoding/json" + "encoding/json/v2" "sort" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -182,7 +183,7 @@ func stateChangeHistoryData(oldState, newState, reason, reasonData string) strin } if reasonData != "" { var parsed any - if json.Unmarshal([]byte(reasonData), &parsed) == nil { + if json.Unmarshal([]byte(reasonData), &parsed, jsonx.V1()) == nil { next["stateReasonData"] = parsed } } @@ -191,7 +192,7 @@ func stateChangeHistoryData(oldState, newState, reason, reasonData string) strin "version": "1.0", "oldState": map[string]any{"stateValue": oldState}, "newState": next, - }) + }, jsonx.V1()) return string(bs) } diff --git a/services/cloudwatch/alarm_reason.go b/services/cloudwatch/alarm_reason.go index 575738d9d7..762f289da2 100644 --- a/services/cloudwatch/alarm_reason.go +++ b/services/cloudwatch/alarm_reason.go @@ -1,12 +1,14 @@ package cloudwatch import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -212,7 +214,7 @@ func alarmReasonData(a MetricAlarm, d alarmEvalDetail, now time.Time) string { "evaluatedDatapoints": evaluated, } - bs, err := json.Marshal(data) + bs, err := json.Marshal(data, jsonx.V1()) if err != nil { return "" } diff --git a/services/cloudwatch/alarm_validation_sdk_test.go b/services/cloudwatch/alarm_validation_sdk_test.go index b468cfd6a8..de91b43197 100644 --- a/services/cloudwatch/alarm_validation_sdk_test.go +++ b/services/cloudwatch/alarm_validation_sdk_test.go @@ -1,7 +1,8 @@ package cloudwatch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" "testing" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatch" ) @@ -76,7 +78,7 @@ func TestSDK_AlarmStateTransitionRealism(t *testing.T) { got := out.MetricAlarms[0] assert.Equal(t, tt.wantState, got.StateValue) assert.Contains(t, aws.ToString(got.StateReason), tt.wantReason) - assert.True(t, json.Valid([]byte(aws.ToString(got.StateReasonData)))) + assert.True(t, jsontext.Value([]byte(aws.ToString(got.StateReasonData))).IsValid(jsonx.V1())) putBreachAlarm(t, client, "a", 6) out, err = client.DescribeAlarms(t.Context(), &cwsdk.DescribeAlarmsInput{}) @@ -96,7 +98,10 @@ func TestSDK_AlarmStateTransitionRealism(t *testing.T) { StateValue string `json:"stateValue"` } `json:"newState"` } - require.NoError(t, json.Unmarshal([]byte(aws.ToString(hist.AlarmHistoryItems[0].HistoryData)), &data)) + require.NoError( + t, + json.Unmarshal([]byte(aws.ToString(hist.AlarmHistoryItems[0].HistoryData)), &data, jsonx.V1()), + ) assert.Equal(t, string(tt.wantState), data.NewState.StateValue) }) } diff --git a/services/cloudwatch/anomaly_detectors.go b/services/cloudwatch/anomaly_detectors.go index 103bcacca4..ccb213f0a4 100644 --- a/services/cloudwatch/anomaly_detectors.go +++ b/services/cloudwatch/anomaly_detectors.go @@ -3,7 +3,7 @@ package cloudwatch import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "math" "slices" @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -27,7 +28,7 @@ func detectorKey(d *AnomalyDetector) string { return anomalyDetectorKey(d.Namespace, d.MetricName, d.Stat, d.Dimensions) } - raw, err := json.Marshal(d.MetricMath) + raw, err := json.Marshal(d.MetricMath, jsonx.V1()) if err != nil { return "math/" + d.ID } diff --git a/services/cloudwatch/contributor_insights_sdk_test.go b/services/cloudwatch/contributor_insights_sdk_test.go index 19503121fd..9f1a5f2c30 100644 --- a/services/cloudwatch/contributor_insights_sdk_test.go +++ b/services/cloudwatch/contributor_insights_sdk_test.go @@ -3,7 +3,7 @@ package cloudwatch_test import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatch" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -431,7 +432,7 @@ func TestInsightRule_PutValidation(t *testing.T) { fiveFilters := jsonRule(`"$.a"`, `,"Filters":[`+ `{"Match":"$.a","IsPresent":true},{"Match":"$.b","IsPresent":true},{"Match":"$.c","IsPresent":true},`+ `{"Match":"$.d","IsPresent":true},{"Match":"$.e","IsPresent":true}]`) + `}` - elevenValues, err := json.Marshal([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}) + elevenValues, err := json.Marshal([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}, jsonx.V1()) require.NoError(t, err) invalid := &cwtypes.InvalidParameterValueException{} diff --git a/services/cloudwatch/dashboard_validation.go b/services/cloudwatch/dashboard_validation.go index dcd1d76bd1..6955e8e67c 100644 --- a/services/cloudwatch/dashboard_validation.go +++ b/services/cloudwatch/dashboard_validation.go @@ -1,9 +1,12 @@ package cloudwatch import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // knownDashboardWidgetTypes are the CloudWatch dashboard widget "type" values @@ -57,10 +60,10 @@ func validateDashboardBody(body string) []DashboardValidationMessage { }} } - dec := json.NewDecoder(strings.NewReader(trimmed)) + dec := jsontext.NewDecoder(strings.NewReader(trimmed), jsonx.V1()) var raw any - if err := dec.Decode(&raw); err != nil { + if err := json.UnmarshalDecode(dec, &raw, jsonx.V1()); err != nil { return []DashboardValidationMessage{{ DataPath: "/", Message: fmt.Sprintf("The dashboard body is not valid JSON: %s", err.Error()), @@ -68,7 +71,11 @@ func validateDashboardBody(body string) []DashboardValidationMessage { }} } - if dec.More() { + if rest := strings.TrimLeft( + trimmed[dec.InputOffset():], + " \t\r\n", + ); rest != "" && rest[0] != ']' && + rest[0] != '}' { return []DashboardValidationMessage{{ DataPath: "/", Message: "The dashboard body contains trailing content after the JSON value", diff --git a/services/cloudwatch/firehose_interop_test.go b/services/cloudwatch/firehose_interop_test.go index 1f8cadd450..3cf5c687b5 100644 --- a/services/cloudwatch/firehose_interop_test.go +++ b/services/cloudwatch/firehose_interop_test.go @@ -2,7 +2,7 @@ package cloudwatch_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "sync" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatch" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -110,7 +111,7 @@ func TestMetricStream_EndToEnd_RealFirehoseBackend(t *testing.T) { body := s3mock.captured()[0] var rec map[string]any - require.NoError(t, json.Unmarshal([]byte(firstLine(body)), &rec)) + require.NoError(t, json.Unmarshal([]byte(firstLine(body)), &rec, jsonx.V1())) assert.Equal(t, "CPUUtilization", rec["metric_name"]) assert.Equal(t, "AWS/EC2", rec["namespace"]) } diff --git a/services/cloudwatch/insight_rule_eval.go b/services/cloudwatch/insight_rule_eval.go index f5a9470a4b..d352eb62f2 100644 --- a/services/cloudwatch/insight_rule_eval.go +++ b/services/cloudwatch/insight_rule_eval.go @@ -2,11 +2,14 @@ package cloudwatch import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // fieldLookup returns the leaf value at a rule field path in one log event. @@ -27,11 +30,10 @@ func (s *insightRuleSpec) lookupFor(msg string) (fieldLookup, bool) { }, true } - dec := json.NewDecoder(bytes.NewReader([]byte(msg))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(msg))) var root map[string]any - if err := dec.Decode(&root); err != nil || root == nil { + if err := json.UnmarshalDecode(dec, &root, jsonx.V1(), jsonx.UseNumber()); err != nil || root == nil { return nil, false } @@ -69,7 +71,7 @@ func jsonLeaf(root any, path string) (string, bool) { switch v := cur.(type) { case string: return v, true - case json.Number: + case jsonx.Number: return v.String(), true case bool: return strconv.FormatBool(v), true diff --git a/services/cloudwatch/insight_rule_spec.go b/services/cloudwatch/insight_rule_spec.go index 5bd476adaf..b421eb3727 100644 --- a/services/cloudwatch/insight_rule_spec.go +++ b/services/cloudwatch/insight_rule_spec.go @@ -1,11 +1,13 @@ package cloudwatch import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -49,7 +51,7 @@ type insightRuleSpec struct { func parseInsightRuleSpec(definition string) (*insightRuleSpec, error) { var spec insightRuleSpec - if err := json.Unmarshal([]byte(definition), &spec); err != nil { + if err := json.Unmarshal([]byte(definition), &spec, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: RuleDefinition has an invalid field type: %s", ErrValidation, err.Error()) } diff --git a/services/cloudwatch/insight_rule_validation.go b/services/cloudwatch/insight_rule_validation.go index d2a142976a..97d14aa7ee 100644 --- a/services/cloudwatch/insight_rule_validation.go +++ b/services/cloudwatch/insight_rule_validation.go @@ -1,9 +1,11 @@ package cloudwatch import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxContributionKeys is Contributor Insights' documented limit on @@ -26,7 +28,7 @@ func validateInsightRuleDefinition(definition string) error { } var raw any - if err := json.Unmarshal([]byte(trimmed), &raw); err != nil { + if err := json.Unmarshal([]byte(trimmed), &raw, jsonx.V1()); err != nil { return fmt.Errorf("%w: RuleDefinition is not valid JSON: %s", ErrValidation, err.Error()) } diff --git a/services/cloudwatch/json_target.go b/services/cloudwatch/json_target.go index ba9562bc39..5cb7d12745 100644 --- a/services/cloudwatch/json_target.go +++ b/services/cloudwatch/json_target.go @@ -3,13 +3,16 @@ package cloudwatch import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "net/http" "strings" "github.com/aws/smithy-go/encoding/cbor" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const jsonContentTypePrefix = "application/x-amz-json" @@ -47,11 +50,10 @@ func (h *Handler) dispatchJSONTarget(op string, body []byte, c *echo.Context) er input := cbor.Map{} if len(bytes.TrimSpace(body)) > 0 { - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) var raw any - if err := dec.Decode(&raw); err != nil { + if err := json.UnmarshalDecode(dec, &raw, jsonx.V1(), jsonx.UseNumber()); err != nil { return writeJSONError(c, http.StatusBadRequest, "SerializationException", err.Error()) } @@ -100,7 +102,7 @@ func writeBufferedAsJSON(c *echo.Context, buf *bufferedResponse) error { } func writeJSON(c *echo.Context, status int, v any) error { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return err } @@ -138,14 +140,14 @@ func jsonToCBOR(v any) cbor.Value { return cbor.String(t) case bool: return cbor.Bool(t) - case json.Number: + case jsonx.Number: return jsonNumberToCBOR(t) default: return &cbor.Nil{} } } -func jsonNumberToCBOR(n json.Number) cbor.Value { +func jsonNumberToCBOR(n jsonx.Number) cbor.Value { if i, err := n.Int64(); err == nil { if i >= 0 { return cbor.Uint(i) diff --git a/services/cloudwatch/json_target_test.go b/services/cloudwatch/json_target_test.go index 7476b280f0..8699a20ce9 100644 --- a/services/cloudwatch/json_target_test.go +++ b/services/cloudwatch/json_target_test.go @@ -3,7 +3,7 @@ package cloudwatch_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -69,7 +70,7 @@ func TestJSONTarget_RoundTrip(t *testing.T) { MetricName string `json:"MetricName"` } `json:"Metrics"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) require.Len(t, out.Metrics, 1) assert.Equal(t, "M", out.Metrics[0].MetricName) }, @@ -90,7 +91,7 @@ func TestJSONTarget_RoundTrip(t *testing.T) { Values []float64 `json:"Values"` } `json:"MetricDataResults"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) require.Len(t, out.MetricDataResults, 1) assert.Equal(t, []float64{-2.5}, out.MetricDataResults[0].Values) assert.Equal(t, []float64{float64(ts)}, out.MetricDataResults[0].Timestamps) @@ -119,7 +120,7 @@ func TestJSONTarget_RoundTrip(t *testing.T) { } func epochStr(n int64) string { - b, _ := json.Marshal(n) + b, _ := json.Marshal(n, jsonx.V1()) return string(b) } diff --git a/services/cloudwatch/metric_stream_delivery.go b/services/cloudwatch/metric_stream_delivery.go index 38d0af6f47..bb2ecf7af3 100644 --- a/services/cloudwatch/metric_stream_delivery.go +++ b/services/cloudwatch/metric_stream_delivery.go @@ -2,9 +2,10 @@ package cloudwatch import ( "context" - "encoding/json" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -105,7 +106,7 @@ func buildMetricStreamRecords( Unit: d.Unit, } - body, err := json.Marshal(rec) + body, err := json.Marshal(rec, jsonx.V1()) if err != nil { continue } diff --git a/services/cloudwatch/metric_stream_delivery_test.go b/services/cloudwatch/metric_stream_delivery_test.go index 64669e3598..d45100dc18 100644 --- a/services/cloudwatch/metric_stream_delivery_test.go +++ b/services/cloudwatch/metric_stream_delivery_test.go @@ -2,13 +2,15 @@ package cloudwatch_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // mockFirehosePutter captures PutRecordBatch calls for assertions. @@ -111,7 +113,7 @@ func TestMetricStream_DeliversToFirehose(t *testing.T) { require.Len(t, calls[0].records, 1) var rec2 map[string]any - require.NoError(t, json.Unmarshal(calls[0].records[0], &rec2)) + require.NoError(t, json.Unmarshal(calls[0].records[0], &rec2, jsonx.V1())) assert.Equal(t, tt.wantMetricName, rec2["metric_name"]) assert.Equal(t, "AWS/EC2", rec2["namespace"]) value := rec2["value"].(map[string]any) diff --git a/services/cloudwatch/metricdata.go b/services/cloudwatch/metricdata.go index 110821c7cd..ab045d826a 100644 --- a/services/cloudwatch/metricdata.go +++ b/services/cloudwatch/metricdata.go @@ -2,12 +2,14 @@ package cloudwatch import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "math" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -36,7 +38,7 @@ type metricDataCursor struct { // encodeMetricDataToken encodes a pagination cursor into an opaque base64 token. func encodeMetricDataToken(c metricDataCursor) string { - raw, err := json.Marshal(c) + raw, err := json.Marshal(c, jsonx.V1()) if err != nil { return "" } @@ -59,7 +61,7 @@ func validateMetricDataWindow(startTime, endTime time.Time, nextToken string) er } var c metricDataCursor - if err = json.Unmarshal(raw, &c); err != nil || c.ResultIndex < 0 || c.PointOffset < 0 { + if err = json.Unmarshal(raw, &c, jsonx.V1()); err != nil || c.ResultIndex < 0 || c.PointOffset < 0 { return ErrInvalidNextToken } @@ -79,7 +81,7 @@ func decodeMetricDataToken(token string) metricDataCursor { } var c metricDataCursor - if err = json.Unmarshal(raw, &c); err != nil { + if err = json.Unmarshal(raw, &c, jsonx.V1()); err != nil { return metricDataCursor{} } diff --git a/services/cloudwatch/persistence.go b/services/cloudwatch/persistence.go index 190556775a..bc021588d7 100644 --- a/services/cloudwatch/persistence.go +++ b/services/cloudwatch/persistence.go @@ -2,9 +2,11 @@ package cloudwatch import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -21,7 +23,7 @@ import ( const cloudwatchSnapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Metrics map[string]map[string]*metricRecord `json:"metrics"` AlarmHistory map[string][]AlarmHistoryItem `json:"alarmHistory"` AccountID string `json:"accountID"` @@ -171,7 +173,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { } h.tagsMu.RUnlock() - data, err := json.Marshal(handlerSnapshot{Backend: backendData, Tags: tagsCopy}) + data, err := json.Marshal(handlerSnapshot{Backend: backendData, Tags: tagsCopy}, jsonx.V1()) if err != nil { return backendData } @@ -196,7 +198,7 @@ func (h *Handler) Restore(ctx context.Context, data []byte) error { func (h *Handler) restoreHome(ctx context.Context, data []byte) error { // Attempt to unmarshal as a handlerSnapshot first. var hs handlerSnapshot - if unmarshalErr := json.Unmarshal(data, &hs); unmarshalErr == nil && hs.Backend != nil { + if unmarshalErr := json.Unmarshal(data, &hs, jsonx.V1()); unmarshalErr == nil && hs.Backend != nil { type restorer interface { Restore(context.Context, []byte) error } diff --git a/services/cloudwatch/persistence_test.go b/services/cloudwatch/persistence_test.go index bb7bf1db55..80f13224ee 100644 --- a/services/cloudwatch/persistence_test.go +++ b/services/cloudwatch/persistence_test.go @@ -1,7 +1,7 @@ package cloudwatch_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatch" ) @@ -625,9 +626,9 @@ func TestInMemoryBackend_Restore_VersionGuard(t *testing.T) { // Corrupt the version field to simulate an incompatible (older/newer) snapshot. var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) raw["version"] = 999999 - corrupted, err := json.Marshal(raw) + corrupted, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) // Restore into a backend that already has unrelated state, to confirm the diff --git a/services/cloudwatch/widget.go b/services/cloudwatch/widget.go index 3e765a7feb..1aecd84050 100644 --- a/services/cloudwatch/widget.go +++ b/services/cloudwatch/widget.go @@ -2,13 +2,16 @@ package cloudwatch import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "image/png" "math" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Widget rendering constants. @@ -40,14 +43,14 @@ const ( // widgetSpec is the decoded MetricWidget JSON document. type widgetSpec struct { - Title string `json:"title"` - Start string `json:"start"` - End string `json:"end"` - Stat string `json:"stat"` - Metrics [][]json.RawMessage `json:"metrics"` - Width int `json:"width"` - Height int `json:"height"` - Period int `json:"period"` + Title string `json:"title"` + Start string `json:"start"` + End string `json:"end"` + Stat string `json:"stat"` + Metrics [][]jsontext.Value `json:"metrics"` + Width int `json:"width"` + Height int `json:"height"` + Period int `json:"period"` } // widgetSeriesQuery describes a single metric line to plot. @@ -108,7 +111,7 @@ func parseWidgetSpec(widgetJSON string) widgetSpec { if strings.TrimSpace(widgetJSON) == "" { return spec } - _ = json.Unmarshal([]byte(widgetJSON), &spec) + _ = json.Unmarshal([]byte(widgetJSON), &spec, jsonx.V1()) return spec } @@ -241,24 +244,24 @@ func scanDurationComponent(s string, unit byte, scale time.Duration) (time.Durat // namespace, metric name, then dimension name/value pairs, optionally followed by // an options object ({"stat":...,"period":...,"label":...}). Render-only entries // (leading object, e.g. metric-math expressions) are skipped. -func parseWidgetSeries(elem []json.RawMessage, spec widgetSpec) (widgetSeriesQuery, bool) { +func parseWidgetSeries(elem []jsontext.Value, spec widgetSpec) (widgetSeriesQuery, bool) { q := widgetSeriesQuery{ stat: firstNonEmpty(spec.Stat, widgetDefaultStat), period: firstPositive(spec.Period, widgetDefaultPeriod), } var strs []string - var opts map[string]json.RawMessage + var opts map[string]jsontext.Value for _, raw := range elem { trimmed := strings.TrimSpace(string(raw)) if strings.HasPrefix(trimmed, "{") { - _ = json.Unmarshal(raw, &opts) + _ = json.Unmarshal(raw, &opts, jsonx.V1()) continue } var s string - if err := json.Unmarshal(raw, &s); err == nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err == nil { strs = append(strs, s) } } @@ -284,25 +287,25 @@ func parseWidgetSeries(elem []json.RawMessage, spec widgetSpec) (widgetSeriesQue } // applyWidgetOptions overlays the trailing options object onto a series query. -func applyWidgetOptions(q *widgetSeriesQuery, opts map[string]json.RawMessage) { +func applyWidgetOptions(q *widgetSeriesQuery, opts map[string]jsontext.Value) { if opts == nil { return } if raw, ok := opts["stat"]; ok { var s string - if json.Unmarshal(raw, &s) == nil && s != "" { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil && s != "" { q.stat = s } } if raw, ok := opts["label"]; ok { var s string - if json.Unmarshal(raw, &s) == nil && s != "" { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil && s != "" { q.label = s } } if raw, ok := opts["period"]; ok { var p int - if json.Unmarshal(raw, &p) == nil && p > 0 { + if json.Unmarshal(raw, &p, jsonx.V1()) == nil && p > 0 { q.period = p } } diff --git a/services/cloudwatchlogs/data_protection_mask.go b/services/cloudwatchlogs/data_protection_mask.go index 7917ca629b..c20ccfa5f1 100644 --- a/services/cloudwatchlogs/data_protection_mask.go +++ b/services/cloudwatchlogs/data_protection_mask.go @@ -2,11 +2,13 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type unmaskContextKey struct{} @@ -133,7 +135,7 @@ func luhnValid(s string) bool { // parseMaskPolicy compiles the masking (Deidentify) statements of doc; unsupported managed identifiers are skipped. func parseMaskPolicy(doc string, since int64) (maskPolicy, error) { var parsed protectionPolicyDoc - if err := json.Unmarshal([]byte(doc), &parsed); err != nil { + if err := json.Unmarshal([]byte(doc), &parsed, jsonx.V1()); err != nil { return maskPolicy{}, fmt.Errorf("%w: policyDocument must be valid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/filter_pattern_json.go b/services/cloudwatchlogs/filter_pattern_json.go index dc046571f0..f8ebfa00bb 100644 --- a/services/cloudwatchlogs/filter_pattern_json.go +++ b/services/cloudwatchlogs/filter_pattern_json.go @@ -1,10 +1,12 @@ package cloudwatchlogs import ( - "encoding/json" + "encoding/json/v2" "regexp" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // compileJSONFilterPattern compiles an AWS CloudWatch Logs JSON selector pattern @@ -26,7 +28,7 @@ func compileJSONFilterPattern(pattern string) func(string) bool { return func(message string) bool { var root any - if err := json.Unmarshal([]byte(strings.TrimSpace(message)), &root); err != nil { + if err := json.Unmarshal([]byte(strings.TrimSpace(message)), &root, jsonx.V1()); err != nil { return false } @@ -42,7 +44,7 @@ func compileJSONFilterPattern(pattern string) func(string) bool { func compileJSONFilterPatternExtract(_ string) func(message, fieldRef string) (string, bool) { return func(message, fieldRef string) (string, bool) { var root any - if err := json.Unmarshal([]byte(strings.TrimSpace(message)), &root); err != nil { + if err := json.Unmarshal([]byte(strings.TrimSpace(message)), &root, jsonx.V1()); err != nil { return "", false } diff --git a/services/cloudwatchlogs/golden_perf_test.go b/services/cloudwatchlogs/golden_perf_test.go index c031a848e5..9209c1d173 100644 --- a/services/cloudwatchlogs/golden_perf_test.go +++ b/services/cloudwatchlogs/golden_perf_test.go @@ -12,7 +12,8 @@ package cloudwatchlogs_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "os" @@ -22,6 +23,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -63,13 +65,13 @@ func checkGoldenLogs(t *testing.T, name string, got []byte) { t.Helper() var parsed any - require.NoError(t, json.Unmarshal(got, &parsed)) - redacted, err := json.Marshal(redactVolatile(parsed)) + require.NoError(t, json.Unmarshal(got, &parsed, jsonx.V1())) + redacted, err := json.Marshal(redactVolatile(parsed), jsonx.V1()) require.NoError(t, err) - var buf bytes.Buffer - require.NoError(t, json.Indent(&buf, redacted, "", " ")) - pretty := buf.Bytes() + indented := jsontext.Value(bytes.Clone(redacted)) + require.NoError(t, indented.Indent(jsonx.V1(), jsontext.WithIndent(" "))) + pretty := []byte(indented) path := goldenLogsPath(name) if os.Getenv("CWL_GOLDEN_UPDATE") != "" { @@ -107,7 +109,7 @@ func seedGoldenStream( } body, err := json.Marshal(map[string]any{ "logGroupName": group, "logStreamName": stream, "logEvents": events, - }) + }, jsonx.V1()) require.NoError(t, err) rec = doLogsRequest(t, h, e, "PutLogEvents", string(body)) @@ -135,7 +137,7 @@ func TestGolden_FilterLogEventsInterleaved(t *testing.T) { "logGroupName": "golden-grp", "filterPattern": "line", "limit": 50, - }) + }, jsonx.V1()) require.NoError(t, err) rec = doLogsRequest(t, h, e, "FilterLogEvents", string(body)) @@ -161,7 +163,7 @@ func TestGolden_GetLogEvents(t *testing.T) { "logGroupName": "golden-grp2", "logStreamName": "s", "limit": 10, - }) + }, jsonx.V1()) require.NoError(t, err) rec = doLogsRequest(t, h, e, "GetLogEvents", string(body)) diff --git a/services/cloudwatchlogs/handler.go b/services/cloudwatchlogs/handler.go index 17960eb777..275138af19 100644 --- a/services/cloudwatchlogs/handler.go +++ b/services/cloudwatchlogs/handler.go @@ -2,7 +2,7 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -259,7 +260,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -406,7 +407,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a standardized JSON error response. @@ -475,7 +476,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin Message: reqErr.Error(), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/cloudwatchlogs/handler_anomaly_detectors.go b/services/cloudwatchlogs/handler_anomaly_detectors.go index f049b5c04e..deeeca8996 100644 --- a/services/cloudwatchlogs/handler_anomaly_detectors.go +++ b/services/cloudwatchlogs/handler_anomaly_detectors.go @@ -2,7 +2,9 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createLogAnomalyDetectorInput struct { @@ -111,7 +113,7 @@ func (h *Handler) handleCreateLogAnomalyDetector( b []byte, ) (any, error) { var input createLogAnomalyDetectorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -135,7 +137,7 @@ func (h *Handler) handleDeleteLogAnomalyDetector( b []byte, ) (any, error) { var input deleteLogAnomalyDetectorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteLogAnomalyDetector(input.AnomalyDetectorArn); err != nil { @@ -150,7 +152,7 @@ func (h *Handler) handleListLogAnomalyDetectors( b []byte, ) (any, error) { var input listLogAnomalyDetectorsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } var filter []string @@ -171,7 +173,7 @@ func (h *Handler) handleUpdateLogAnomalyDetector( b []byte, ) (any, error) { var input updateLogAnomalyDetectorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.UpdateLogAnomalyDetector( @@ -192,7 +194,7 @@ func (h *Handler) handleGetLogAnomalyDetector( b []byte, ) (any, error) { var input getLogAnomalyDetectorInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } d, err := h.Backend.GetLogAnomalyDetector(input.AnomalyDetectorArn) @@ -215,7 +217,7 @@ func (h *Handler) handleGetLogAnomalyDetector( func (h *Handler) handleListAnomalies(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input listAnomaliesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } anomalies, next, err := h.Backend.ListAnomalies(input.AnomalyDetectorArn, input.Limit, input.NextToken) @@ -228,7 +230,7 @@ func (h *Handler) handleListAnomalies(ctx context.Context, b []byte) (any, error func (h *Handler) handleUpdateAnomaly(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input updateAnomalyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/cloudwatchlogs/handler_anomaly_detectors_test.go b/services/cloudwatchlogs/handler_anomaly_detectors_test.go index dcdaf41a4b..50b1cc0209 100644 --- a/services/cloudwatchlogs/handler_anomaly_detectors_test.go +++ b/services/cloudwatchlogs/handler_anomaly_detectors_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -34,7 +35,7 @@ func TestHandler_LogAnomalyDetector_Create(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arn, ok := out["anomalyDetectorArn"].(string) require.True(t, ok) assert.Contains(t, arn, "log-anomaly-detector") @@ -193,7 +194,7 @@ func TestHandler_CreateLogAnomalyDetectorOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -201,7 +202,7 @@ func TestHandler_CreateLogAnomalyDetectorOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { diff --git a/services/cloudwatchlogs/handler_data_protection.go b/services/cloudwatchlogs/handler_data_protection.go index 63ddeb10cd..3d95342fde 100644 --- a/services/cloudwatchlogs/handler_data_protection.go +++ b/services/cloudwatchlogs/handler_data_protection.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type deleteAccountPolicyInput struct { @@ -48,7 +50,7 @@ func (h *Handler) handleDeleteAccountPolicy( b []byte, ) (any, error) { var input deleteAccountPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -64,7 +66,7 @@ func (h *Handler) handlePutAccountPolicy( b []byte, ) (any, error) { var input putAccountPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } policy, err := h.Backend.PutAccountPolicy( @@ -86,7 +88,7 @@ func (h *Handler) handleDescribeAccountPolicies( b []byte, ) (any, error) { var input describeAccountPoliciesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } policies, nextToken, err := h.Backend.DescribeAccountPolicies( @@ -112,7 +114,7 @@ func (h *Handler) handleDeleteDataProtectionPolicy( body []byte, ) (any, error) { var in deleteDataProtectionPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -134,7 +136,7 @@ func (h *Handler) handleGetDataProtectionPolicy( body []byte, ) (any, error) { var in getDataProtectionPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -170,7 +172,7 @@ func (h *Handler) handlePutDataProtectionPolicy( body []byte, ) (any, error) { var in putDataProtectionPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_data_protection_test.go b/services/cloudwatchlogs/handler_data_protection_test.go index 3c4b4343cd..977031c0d8 100644 --- a/services/cloudwatchlogs/handler_data_protection_test.go +++ b/services/cloudwatchlogs/handler_data_protection_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -82,7 +83,7 @@ func TestHandler_DataProtectionPolicy(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -138,7 +139,7 @@ func TestHandler_DeleteAccountPolicyOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -146,7 +147,7 @@ func TestHandler_DeleteAccountPolicyOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { diff --git a/services/cloudwatchlogs/handler_deliveries.go b/services/cloudwatchlogs/handler_deliveries.go index ea5418eaa4..fe019982b5 100644 --- a/services/cloudwatchlogs/handler_deliveries.go +++ b/services/cloudwatchlogs/handler_deliveries.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createDeliveryInput struct { @@ -48,7 +50,7 @@ type deleteDeliveryOutput struct{} func (h *Handler) handleCreateDelivery(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input createDeliveryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -68,7 +70,7 @@ func (h *Handler) handleDescribeDeliveries( b []byte, ) (any, error) { var input describeDeliveriesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } deliveries, next, err := h.Backend.DescribeDeliveries(input.Limit, input.NextToken) @@ -81,7 +83,7 @@ func (h *Handler) handleDescribeDeliveries( func (h *Handler) handleGetDelivery(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input getDeliveryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } d, err := h.Backend.GetDelivery(input.ID) @@ -94,7 +96,7 @@ func (h *Handler) handleGetDelivery(ctx context.Context, b []byte) (any, error) func (h *Handler) handleDeleteDelivery(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input deleteDeliveryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteDelivery(input.ID); err != nil { @@ -144,7 +146,7 @@ func (h *Handler) handlePutDeliveryDestination( body []byte, ) (any, error) { var in putDeliveryDestinationInputFull - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -171,7 +173,7 @@ func (h *Handler) handleGetDeliveryDestination( body []byte, ) (any, error) { var in getDeliveryDestinationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -197,7 +199,7 @@ func (h *Handler) handleDescribeDeliveryDestinations( body []byte, ) (any, error) { var in describeDeliveryDestinationsInput - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) if b := cwlBackend(h); b != nil { dests, next := b.DescribeDeliveryDestinations(in.NextToken, in.Limit) @@ -226,7 +228,7 @@ func (h *Handler) handleDeleteDeliveryDestination( body []byte, ) (any, error) { var in deleteDeliveryDestinationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -249,7 +251,7 @@ func (h *Handler) handlePutDeliveryDestinationPolicy( body []byte, ) (any, error) { var in putDeliveryDestinationPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -273,7 +275,7 @@ func (h *Handler) handleGetDeliveryDestinationPolicy( body []byte, ) (any, error) { var in getDeliveryDestinationPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -298,7 +300,7 @@ func (h *Handler) handleDeleteDeliveryDestinationPolicy( body []byte, ) (any, error) { var in deleteDeliveryDestinationPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -353,7 +355,7 @@ func (h *Handler) handlePutDeliverySource( body []byte, ) (any, error) { var in putDeliverySourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -383,7 +385,7 @@ func (h *Handler) handleGetDeliverySource( body []byte, ) (any, error) { var in getDeliverySourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -409,7 +411,7 @@ func (h *Handler) handleDescribeDeliverySources( body []byte, ) (any, error) { var in describeDeliverySourcesInput - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) if b := cwlBackend(h); b != nil { srcs, next := b.DescribeDeliverySources(in.NextToken, in.Limit) @@ -438,7 +440,7 @@ func (h *Handler) handleDeleteDeliverySource( body []byte, ) (any, error) { var in deleteDeliverySourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -463,7 +465,7 @@ func (h *Handler) handleUpdateDeliveryConfiguration( body []byte, ) (any, error) { var in updateDeliveryConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } diff --git a/services/cloudwatchlogs/handler_deliveries_test.go b/services/cloudwatchlogs/handler_deliveries_test.go index a485b3757b..5da0e86ba1 100644 --- a/services/cloudwatchlogs/handler_deliveries_test.go +++ b/services/cloudwatchlogs/handler_deliveries_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -26,7 +27,7 @@ func TestHandler_Delivery_CreateWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) delivery, ok := out["delivery"].(map[string]any) require.True(t, ok) @@ -242,7 +243,7 @@ func TestHandler_DeliveryDestination(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -284,7 +285,7 @@ func TestHandler_DeliveryDestination_WireShape(t *testing.T) { } var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) putDest, ok := putOut["deliveryDestination"].(map[string]any) require.True(t, ok) checkShape(t, putDest) @@ -293,7 +294,7 @@ func TestHandler_DeliveryDestination_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) getDest, ok := getOut["deliveryDestination"].(map[string]any) require.True(t, ok) checkShape(t, getDest) @@ -302,7 +303,7 @@ func TestHandler_DeliveryDestination_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut, jsonx.V1())) dests, ok := describeOut["deliveryDestinations"].([]any) require.True(t, ok) require.Len(t, dests, 1) @@ -394,7 +395,7 @@ func TestHandler_DeliverySource(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -437,7 +438,7 @@ func TestHandler_DeliverySource_WireShape(t *testing.T) { } var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) putSrc, ok := putOut["deliverySource"].(map[string]any) require.True(t, ok) checkShape(t, putSrc) @@ -446,7 +447,7 @@ func TestHandler_DeliverySource_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) getSrc, ok := getOut["deliverySource"].(map[string]any) require.True(t, ok) checkShape(t, getSrc) @@ -455,7 +456,7 @@ func TestHandler_DeliverySource_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut, jsonx.V1())) srcs, ok := describeOut["deliverySources"].([]any) require.True(t, ok) require.Len(t, srcs, 1) @@ -488,7 +489,7 @@ func TestHandler_UpdateDeliveryConfiguration(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ := resp["delivery"]["id"].(string) return id @@ -512,7 +513,7 @@ func TestHandler_UpdateDeliveryConfiguration(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ := resp["delivery"]["id"].(string) return id @@ -545,7 +546,7 @@ func TestHandler_UpdateDeliveryConfiguration(t *testing.T) { deliveryID = tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body(deliveryID)) + bodyBytes, err := json.Marshal(tt.body(deliveryID), jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -604,7 +605,7 @@ func TestHandler_CreateDeliveryOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -612,7 +613,7 @@ func TestHandler_CreateDeliveryOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { @@ -679,13 +680,13 @@ func TestHandler_DeliveryResponseShape(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } diff --git a/services/cloudwatchlogs/handler_destinations.go b/services/cloudwatchlogs/handler_destinations.go index e542412472..7d80f3868f 100644 --- a/services/cloudwatchlogs/handler_destinations.go +++ b/services/cloudwatchlogs/handler_destinations.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putDestinationInput struct { @@ -18,7 +20,7 @@ func (h *Handler) handlePutDestination( body []byte, ) (any, error) { var in putDestinationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -69,7 +71,7 @@ func (h *Handler) handlePutDestinationPolicy( body []byte, ) (any, error) { var in putDestinationPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -93,7 +95,7 @@ func (h *Handler) handleDescribeDestinations( body []byte, ) (any, error) { var in describeDestinationsInput - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) if b := cwlBackend(h); b != nil { dests, next := b.DescribeDestinations(in.DestinationNamePrefix, in.Limit, in.NextToken) @@ -122,7 +124,7 @@ func (h *Handler) handleDeleteDestination( body []byte, ) (any, error) { var in deleteDestinationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_destinations_test.go b/services/cloudwatchlogs/handler_destinations_test.go index 73c10713d4..decfac1762 100644 --- a/services/cloudwatchlogs/handler_destinations_test.go +++ b/services/cloudwatchlogs/handler_destinations_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -132,7 +133,7 @@ func TestHandler_Destination(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -155,7 +156,7 @@ func TestHandler_Destination_WireShapeIncludesCreationTimeAndAccessPolicy(t *tes require.Equal(t, http.StatusOK, putRec.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) putDest, ok := putOut["destination"].(map[string]any) require.True(t, ok) ct, hasCreationTime := putDest["creationTime"] @@ -172,7 +173,7 @@ func TestHandler_Destination_WireShapeIncludesCreationTimeAndAccessPolicy(t *tes require.Equal(t, http.StatusOK, describeRec.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut, jsonx.V1())) dests, ok := describeOut["destinations"].([]any) require.True(t, ok) require.Len(t, dests, 1) @@ -225,13 +226,13 @@ func TestHandler_DestinationResponseShape(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } diff --git a/services/cloudwatchlogs/handler_export_tasks.go b/services/cloudwatchlogs/handler_export_tasks.go index 796b4370bc..d22576415f 100644 --- a/services/cloudwatchlogs/handler_export_tasks.go +++ b/services/cloudwatchlogs/handler_export_tasks.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type cancelExportTaskInput struct { @@ -146,7 +148,7 @@ func (h *Handler) handleCancelExportTask( b []byte, ) (any, error) { var input cancelExportTaskInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.CancelExportTask(input.TaskID); err != nil { @@ -161,7 +163,7 @@ func (h *Handler) handleCancelImportTask( b []byte, ) (any, error) { var input cancelImportTaskInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -183,7 +185,7 @@ func (h *Handler) handleCreateExportTask( b []byte, ) (any, error) { var input createExportTaskInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -204,7 +206,7 @@ func (h *Handler) handleCreateImportTask( b []byte, ) (any, error) { var input createImportTaskInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -227,7 +229,7 @@ func (h *Handler) handleDescribeExportTasks( b []byte, ) (any, error) { var input describeExportTasksInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } tasks, next, err := h.Backend.DescribeExportTasks(input.TaskID, input.StatusCode, input.Limit, input.NextToken) @@ -248,7 +250,7 @@ func (h *Handler) handleDescribeImportTasks( b []byte, ) (any, error) { var input describeImportTasksInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } tasks, next, err := h.Backend.DescribeImportTasks(input.ImportID, input.Limit, input.NextToken) @@ -279,7 +281,7 @@ func (h *Handler) handleDescribeImportTaskBatches( ImportID string `json:"importId"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } diff --git a/services/cloudwatchlogs/handler_export_tasks_test.go b/services/cloudwatchlogs/handler_export_tasks_test.go index c87881b59a..000ef98f10 100644 --- a/services/cloudwatchlogs/handler_export_tasks_test.go +++ b/services/cloudwatchlogs/handler_export_tasks_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -31,13 +32,13 @@ func TestHandler_ExportTask_CancelRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) taskID, ok := createOut["taskId"].(string) require.True(t, ok) require.NotEmpty(t, taskID) // Cancel the task. - bodyBytes, err := json.Marshal(map[string]any{"taskId": taskID}) + bodyBytes, err := json.Marshal(map[string]any{"taskId": taskID}, jsonx.V1()) require.NoError(t, err) rec = doLogsRequest(t, h, e, "CancelExportTask", string(bodyBytes)) assert.Equal(t, http.StatusOK, rec.Code) @@ -87,7 +88,7 @@ func TestHandler_DescribeExportTasks_WireShape(t *testing.T) { TaskID string `json:"taskId"` } `json:"exportTasks"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ExportTasks, 1) task := out.ExportTasks[0] @@ -102,7 +103,7 @@ func TestHandler_DescribeExportTasks_WireShape(t *testing.T) { // The raw JSON must not carry the old flat keys at the top level of an // export task entry. var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) rawTasks, ok := raw["exportTasks"].([]any) require.True(t, ok) require.Len(t, rawTasks, 1) @@ -130,7 +131,7 @@ func TestHandler_ImportTask_CancelRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) importID, ok := createOut["importId"].(string) require.True(t, ok) require.NotEmpty(t, importID) @@ -140,13 +141,13 @@ func TestHandler_ImportTask_CancelRoundTrip(t *testing.T) { require.NotEmpty(t, importDestARN) // Cancel the task. - bodyBytes, err := json.Marshal(map[string]any{"importId": importID}) + bodyBytes, err := json.Marshal(map[string]any{"importId": importID}, jsonx.V1()) require.NoError(t, err) rec = doLogsRequest(t, h, e, "CancelImportTask", string(bodyBytes)) require.Equal(t, http.StatusOK, rec.Code) var cancelOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cancelOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cancelOut, jsonx.V1())) assert.Equal(t, importID, cancelOut["importId"]) assert.Equal(t, "CANCELLED", cancelOut["importStatus"]) } @@ -254,7 +255,7 @@ func TestHandler_CancelExportTask_StateValidation(t *testing.T) { e := echo.New() h := cloudwatchlogs.NewHandler(backend) - bodyBytes, _ := json.Marshal(map[string]any{"taskId": taskID}) + bodyBytes, _ := json.Marshal(map[string]any{"taskId": taskID}, jsonx.V1()) rec := doLogsRequest(t, h, e, "CancelExportTask", string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) }) @@ -313,7 +314,7 @@ func TestHandler_CancelImportTask_StateValidation(t *testing.T) { e := echo.New() h := cloudwatchlogs.NewHandler(backend) - bodyBytes, _ := json.Marshal(map[string]any{"importId": importID}) + bodyBytes, _ := json.Marshal(map[string]any{"importId": importID}, jsonx.V1()) rec := doLogsRequest(t, h, e, "CancelImportTask", string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) }) @@ -490,7 +491,7 @@ func TestHandler_ExportImportTaskOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -498,7 +499,7 @@ func TestHandler_ExportImportTaskOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { @@ -533,7 +534,7 @@ func TestHandler_ImportTaskBatchesValidation(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, tt.action, string(bodyBytes)) @@ -541,7 +542,7 @@ func TestHandler_ImportTaskBatchesValidation(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.wantListField].([]any) require.True(t, ok, "expected list field %q in response", tt.wantListField) assert.Empty(t, list) diff --git a/services/cloudwatchlogs/handler_index_policies.go b/services/cloudwatchlogs/handler_index_policies.go index 3e6812d3e4..87c91380a4 100644 --- a/services/cloudwatchlogs/handler_index_policies.go +++ b/services/cloudwatchlogs/handler_index_policies.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putIndexPolicyInput struct { @@ -20,7 +22,7 @@ func (h *Handler) handlePutIndexPolicy( body []byte, ) (any, error) { var in putIndexPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -51,7 +53,7 @@ func (h *Handler) handleDescribeIndexPolicies( body []byte, ) (any, error) { var in describeIndexPoliciesInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -77,7 +79,7 @@ func (h *Handler) handleDeleteIndexPolicy( body []byte, ) (any, error) { var in deleteIndexPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_index_policies_test.go b/services/cloudwatchlogs/handler_index_policies_test.go index 1fde81d7ee..7729809ba7 100644 --- a/services/cloudwatchlogs/handler_index_policies_test.go +++ b/services/cloudwatchlogs/handler_index_policies_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -103,7 +104,7 @@ func TestHandler_IndexPolicy(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -141,7 +142,7 @@ func TestHandler_ConfigTemplatesAndFieldIndexes(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, tt.action, string(bodyBytes)) @@ -149,7 +150,7 @@ func TestHandler_ConfigTemplatesAndFieldIndexes(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.wantListField].([]any) require.True(t, ok, "expected list field %q in response", tt.wantListField) assert.Empty(t, list) @@ -204,13 +205,13 @@ func TestHandler_IndexPolicyResponseShape(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } diff --git a/services/cloudwatchlogs/handler_integrations.go b/services/cloudwatchlogs/handler_integrations.go index c1060397f2..dac48c8931 100644 --- a/services/cloudwatchlogs/handler_integrations.go +++ b/services/cloudwatchlogs/handler_integrations.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type associateSourceToS3TableIntegrationInput struct { @@ -20,7 +22,7 @@ func (h *Handler) handleAssociateSourceToS3TableIntegration( b []byte, ) (any, error) { var input associateSourceToS3TableIntegrationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -72,7 +74,7 @@ func (h *Handler) handlePutIntegration( body []byte, ) (any, error) { var in putIntegrationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -159,7 +161,7 @@ func (h *Handler) handleGetIntegration( body []byte, ) (any, error) { var in getIntegrationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -194,7 +196,7 @@ func (h *Handler) handleListIntegrations( body []byte, ) (any, error) { var in listIntegrationsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } @@ -224,7 +226,7 @@ func (h *Handler) handleDeleteIntegration( body []byte, ) (any, error) { var in deleteIntegrationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -250,7 +252,7 @@ func (h *Handler) handleDisassociateSourceFromS3TableIntegration( body []byte, ) (any, error) { var in disassociateSourceFromS3TableIntegrationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } @@ -289,7 +291,7 @@ func (h *Handler) handleListSourcesForS3TableIntegration( body []byte, ) (any, error) { var input listSourcesForS3TableIntegrationInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } diff --git a/services/cloudwatchlogs/handler_integrations_test.go b/services/cloudwatchlogs/handler_integrations_test.go index fa860558e7..5f16fbbd78 100644 --- a/services/cloudwatchlogs/handler_integrations_test.go +++ b/services/cloudwatchlogs/handler_integrations_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -135,7 +136,7 @@ func TestHandler_Integration(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -186,7 +187,7 @@ func TestHandler_AssociateSourceToS3TableIntegrationOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -194,7 +195,7 @@ func TestHandler_AssociateSourceToS3TableIntegrationOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { @@ -252,7 +253,7 @@ func TestHandler_S3TableIntegrationSourceOperations(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, tt.action, string(bodyBytes)) @@ -260,7 +261,7 @@ func TestHandler_S3TableIntegrationSourceOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.wantListField].([]any) require.True(t, ok, "expected list field %q in response", tt.wantListField) assert.Empty(t, list) @@ -280,7 +281,7 @@ func TestHandler_DisassociateSourceFromS3TableIntegration_RoundTrip(t *testing.T require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) identifier, ok := assocResp["identifier"].(string) require.True(t, ok, "expected identifier in AssociateSourceToS3TableIntegration response") require.NotEmpty(t, identifier) @@ -290,7 +291,7 @@ func TestHandler_DisassociateSourceFromS3TableIntegration_RoundTrip(t *testing.T require.Equal(t, http.StatusOK, disRec.Code) var disResp map[string]any - require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp)) + require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp, jsonx.V1())) assert.Equal(t, identifier, disResp["identifier"]) // A second disassociate of the same identifier must now fail: the @@ -340,13 +341,13 @@ func TestHandler_IntegrationResponseShape(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } diff --git a/services/cloudwatchlogs/handler_log_events.go b/services/cloudwatchlogs/handler_log_events.go index e8c76da697..d01248126d 100644 --- a/services/cloudwatchlogs/handler_log_events.go +++ b/services/cloudwatchlogs/handler_log_events.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putLogEventsInput struct { @@ -103,7 +105,7 @@ func (h *Handler) logEventActions() map[string]actionFn { return map[string]actionFn{ "PutLogEvents": func(ctx context.Context, b []byte) (any, error) { var input putLogEventsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } result, err := h.Backend.PutLogEvents( @@ -125,7 +127,7 @@ func (h *Handler) logEventActions() map[string]actionFn { }, "GetLogEvents": func(ctx context.Context, b []byte) (any, error) { var input getLogEventsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } groupName, err := resolveLogGroupRef(input.LogGroupName, input.LogGroupIdentifier) @@ -147,7 +149,7 @@ func (h *Handler) logEventActions() map[string]actionFn { }, "FilterLogEvents": func(ctx context.Context, b []byte) (any, error) { var input filterLogEventsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } groupName, err := resolveLogGroupRef(input.LogGroupName, input.LogGroupIdentifier) @@ -180,7 +182,7 @@ func (h *Handler) logEventActions() map[string]actionFn { func (h *Handler) handleGetLogRecord(ctx context.Context, b []byte) (any, error) { var input getLogRecordInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } record, err := h.Backend.GetLogRecord(withUnmask(ctx, input.Unmask), input.LogRecordPointer) @@ -205,7 +207,7 @@ func (h *Handler) handleGetLogFields(ctx context.Context, body []byte) (any, err LogGroupName string `json:"logGroupName"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } @@ -253,7 +255,7 @@ func (h *Handler) handleGetLogObject(ctx context.Context, body []byte) (any, err Unmask bool `json:"unmask"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } @@ -293,7 +295,7 @@ func (h *Handler) handlePutBearerTokenAuthentication( ctx context.Context, body []byte, ) (any, error) { var in putBearerTokenAuthenticationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -330,7 +332,7 @@ func (h *Handler) handleStartLiveTail(ctx context.Context, body []byte) (any, er LogGroupIdentifiers []string `json:"logGroupIdentifiers"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } diff --git a/services/cloudwatchlogs/handler_log_events_test.go b/services/cloudwatchlogs/handler_log_events_test.go index ae10b15188..98fdc12bdb 100644 --- a/services/cloudwatchlogs/handler_log_events_test.go +++ b/services/cloudwatchlogs/handler_log_events_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -57,7 +58,7 @@ func TestHandler_PutLogEvents_MismatchedSequenceToken_StillAccepted(t *testing.T "logEvents": []any{ map[string]any{"message": "setup", "timestamp": now + int64(i)}, }, - }) + }, jsonx.V1()) doLogsRequest(t, h, e, "PutLogEvents", string(body)) } @@ -66,7 +67,7 @@ func TestHandler_PutLogEvents_MismatchedSequenceToken_StillAccepted(t *testing.T "logStreamName": "s", "sequenceToken": tt.sequenceToken, "logEvents": []any{map[string]any{"message": "new", "timestamp": now}}, - }) + }, jsonx.V1()) rec := doLogsRequest(t, h, e, "PutLogEvents", string(reqBody)) assert.Equal(t, http.StatusOK, rec.Code, @@ -75,7 +76,7 @@ func TestHandler_PutLogEvents_MismatchedSequenceToken_StillAccepted(t *testing.T var okResp struct { NextSequenceToken string `json:"nextSequenceToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &okResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &okResp, jsonx.V1())) assert.Equal(t, strconv.Itoa(tt.setupEvents+1), okResp.NextSequenceToken) }) } @@ -212,7 +213,7 @@ func TestHandler_LogEventsOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -220,13 +221,13 @@ func TestHandler_LogEventsOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) @@ -258,7 +259,7 @@ func TestHandler_PutBearerTokenAuthentication_RoundTrip(t *testing.T) { var desc struct { LogGroups []map[string]any `json:"logGroups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) require.Len(t, desc.LogGroups, 1) assert.Equal(t, true, desc.LogGroups[0]["bearerTokenAuthenticationEnabled"]) @@ -314,7 +315,7 @@ func TestHandler_LiveTailAndLogFieldOperations(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, tt.action, string(bodyBytes)) @@ -322,7 +323,7 @@ func TestHandler_LiveTailAndLogFieldOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.wantListField].([]any) require.True(t, ok, "expected list field %q in response", tt.wantListField) assert.Empty(t, list) @@ -368,7 +369,7 @@ func TestHandler_PutLogEvents_EntityRejection(t *testing.T) { if tt.entity != nil { req["entity"] = tt.entity } - body, _ := json.Marshal(req) + body, _ := json.Marshal(req, jsonx.V1()) rec := doLogsRequest(t, h, e, "PutLogEvents", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -377,7 +378,7 @@ func TestHandler_PutLogEvents_EntityRejection(t *testing.T) { ErrorType string `json:"errorType"` } `json:"rejectedEntityInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantType == "" { assert.Nil(t, out.RejectedEntityInfo) diff --git a/services/cloudwatchlogs/handler_log_groups.go b/services/cloudwatchlogs/handler_log_groups.go index ccbcd39359..1f27cb4199 100644 --- a/services/cloudwatchlogs/handler_log_groups.go +++ b/services/cloudwatchlogs/handler_log_groups.go @@ -2,11 +2,13 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" sdktypes "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createLogGroupInput struct { @@ -124,7 +126,7 @@ func (h *Handler) logGroupActions() map[string]actionFn { // keep that function's cognitive complexity under the gocognit limit. func (h *Handler) handleCreateLogGroup(ctx context.Context, b []byte) (any, error) { var input createLogGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -158,7 +160,7 @@ func (h *Handler) handleCreateLogGroup(ctx context.Context, b []byte) (any, erro func (h *Handler) handleDeleteLogGroup(ctx context.Context, b []byte) (any, error) { var input deleteLogGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteLogGroup(ctx, input.LogGroupName); err != nil { @@ -170,7 +172,7 @@ func (h *Handler) handleDeleteLogGroup(ctx context.Context, b []byte) (any, erro func (h *Handler) handleDescribeLogGroups(ctx context.Context, b []byte) (any, error) { var input describeLogGroupsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -234,7 +236,7 @@ func (h *Handler) retentionActions() map[string]actionFn { return map[string]actionFn{ "PutRetentionPolicy": func(ctx context.Context, b []byte) (any, error) { var input putRetentionPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } days := input.RetentionInDays @@ -246,7 +248,7 @@ func (h *Handler) retentionActions() map[string]actionFn { }, "DeleteRetentionPolicy": func(ctx context.Context, b []byte) (any, error) { var input deleteRetentionPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.SetRetentionPolicy(ctx, input.LogGroupName, nil); err != nil { @@ -260,7 +262,7 @@ func (h *Handler) retentionActions() map[string]actionFn { func (h *Handler) handleAssociateKmsKey(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input associateKmsKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.AssociateKmsKey(input.LogGroupName, input.ResourceIdentifier, input.KmsKeyID); err != nil { @@ -275,7 +277,7 @@ func (h *Handler) handleDisassociateKmsKey( b []byte, ) (any, error) { var input disassociateKmsKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DisassociateKmsKey(input.LogGroupName, input.ResourceIdentifier); err != nil { @@ -287,7 +289,7 @@ func (h *Handler) handleDisassociateKmsKey( func (h *Handler) handleGetLogGroupFields(ctx context.Context, b []byte) (any, error) { var input getLogGroupFieldsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -306,7 +308,7 @@ func (h *Handler) handleGetLogGroupFields(ctx context.Context, b []byte) (any, e func (h *Handler) handleListLogGroups(ctx context.Context, b []byte) (any, error) { var input listLogGroupsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } for _, f := range input.LogGroupTags { @@ -344,7 +346,7 @@ func (h *Handler) handlePutLogGroupDeletionProtection( body []byte, ) (any, error) { var in putLogGroupDeletionProtectionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -388,7 +390,7 @@ func (h *Handler) handleListAggregateLogGroupSummaries( GroupBy string `json:"groupBy"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidationException, err) } } diff --git a/services/cloudwatchlogs/handler_log_groups_test.go b/services/cloudwatchlogs/handler_log_groups_test.go index ddf06b5b3a..2e18ddbcfe 100644 --- a/services/cloudwatchlogs/handler_log_groups_test.go +++ b/services/cloudwatchlogs/handler_log_groups_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -131,7 +132,7 @@ func TestHandler_LogGroupDeletionProtection(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -168,7 +169,7 @@ func TestHandler_PutLogGroupDeletionProtection_WireName(t *testing.T) { body, err := json.Marshal(map[string]any{ "logGroupIdentifier": lg, "deletionProtectionEnabled": tt.enabled, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, handler, e, "PutLogGroupDeletionProtection", string(body)) @@ -217,7 +218,7 @@ func TestHandler_PutRetentionPolicy_ZeroDays_ReturnsInvalidParameter(t *testing. body, _ := json.Marshal(map[string]any{ "logGroupName": "ret-grp", "retentionInDays": tt.retentionInDays, - }) + }, jsonx.V1()) rec := doLogsRequest(t, h, e, "PutRetentionPolicy", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code, @@ -226,7 +227,7 @@ func TestHandler_PutRetentionPolicy_ZeroDays_ReturnsInvalidParameter(t *testing. var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type, "retentionInDays=%d must return InvalidParameterException", tt.retentionInDays) }) @@ -317,7 +318,7 @@ func TestHandler_LogGroupOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -325,13 +326,13 @@ func TestHandler_LogGroupOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) @@ -386,7 +387,7 @@ func TestHandler_RetentionPolicyOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -394,13 +395,13 @@ func TestHandler_RetentionPolicyOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) @@ -458,7 +459,7 @@ func TestHandler_AssociateKmsKeyOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -466,7 +467,7 @@ func TestHandler_AssociateKmsKeyOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { @@ -500,7 +501,7 @@ func TestHandler_AggregateLogGroupSummariesEmpty(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, tt.action, string(bodyBytes)) @@ -508,7 +509,7 @@ func TestHandler_AggregateLogGroupSummariesEmpty(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.wantListField].([]any) require.True(t, ok, "expected list field %q in response", tt.wantListField) assert.Empty(t, list) diff --git a/services/cloudwatchlogs/handler_log_streams.go b/services/cloudwatchlogs/handler_log_streams.go index 0fa2046618..1a2d853064 100644 --- a/services/cloudwatchlogs/handler_log_streams.go +++ b/services/cloudwatchlogs/handler_log_streams.go @@ -2,7 +2,9 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createLogStreamInput struct { @@ -38,7 +40,7 @@ func (h *Handler) logStreamActions() map[string]actionFn { return map[string]actionFn{ "CreateLogStream": func(ctx context.Context, b []byte) (any, error) { var input createLogStreamInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if _, err := h.Backend.CreateLogStream(ctx, input.LogGroupName, input.LogStreamName); err != nil { @@ -49,7 +51,7 @@ func (h *Handler) logStreamActions() map[string]actionFn { }, "DeleteLogStream": func(ctx context.Context, b []byte) (any, error) { var input deleteLogStreamInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteLogStream(ctx, input.LogGroupName, input.LogStreamName); err != nil { @@ -60,7 +62,7 @@ func (h *Handler) logStreamActions() map[string]actionFn { }, "DescribeLogStreams": func(ctx context.Context, b []byte) (any, error) { var input describeLogStreamsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := validateDescribeLimit(input.Limit); err != nil { diff --git a/services/cloudwatchlogs/handler_log_streams_test.go b/services/cloudwatchlogs/handler_log_streams_test.go index 5d78f05e13..2d4a094925 100644 --- a/services/cloudwatchlogs/handler_log_streams_test.go +++ b/services/cloudwatchlogs/handler_log_streams_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -25,7 +26,7 @@ func TestHandler_DeleteLogStream(t *testing.T) { rec := doLogsRequest(t, h, e, "DescribeLogStreams", `{"logGroupName":"g"}`) require.Equal(t, http.StatusOK, rec.Code) var desc1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc1, jsonx.V1())) assert.Len(t, desc1["logStreams"], 1) // Delete it. @@ -36,7 +37,7 @@ func TestHandler_DeleteLogStream(t *testing.T) { rec = doLogsRequest(t, h, e, "DescribeLogStreams", `{"logGroupName":"g"}`) require.Equal(t, http.StatusOK, rec.Code) var desc2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc2, jsonx.V1())) assert.Empty(t, desc2["logStreams"]) // Delete non-existent stream → 404. @@ -171,7 +172,7 @@ func TestHandler_LogStreamOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -179,13 +180,13 @@ func TestHandler_LogStreamOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) diff --git a/services/cloudwatchlogs/handler_lookup_tables.go b/services/cloudwatchlogs/handler_lookup_tables.go index 80ebb3626b..10de41158a 100644 --- a/services/cloudwatchlogs/handler_lookup_tables.go +++ b/services/cloudwatchlogs/handler_lookup_tables.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createLookupTableInput struct { @@ -20,7 +22,7 @@ func (h *Handler) handleCreateLookupTable( body []byte, ) (any, error) { var in createLookupTableInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -53,7 +55,7 @@ func (h *Handler) handleGetLookupTable( body []byte, ) (any, error) { var in getLookupTableInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -83,7 +85,7 @@ func (h *Handler) handleUpdateLookupTable( body []byte, ) (any, error) { var in updateLookupTableInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -112,7 +114,7 @@ func (h *Handler) handleDeleteLookupTable( body []byte, ) (any, error) { var in deleteLookupTableInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -136,7 +138,7 @@ func (h *Handler) handleDescribeLookupTables( body []byte, ) (any, error) { var in describeLookupTablesInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_metric_filters.go b/services/cloudwatchlogs/handler_metric_filters.go index 00a6582879..2c86af05b2 100644 --- a/services/cloudwatchlogs/handler_metric_filters.go +++ b/services/cloudwatchlogs/handler_metric_filters.go @@ -2,7 +2,9 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- PutMetricFilter ---. @@ -53,7 +55,7 @@ type testMetricFilterOutput struct { func (h *Handler) handlePutMetricFilter(ctx context.Context, b []byte) (any, error) { var input putMetricFilterInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.PutMetricFilterWithOptions( @@ -76,7 +78,7 @@ func (h *Handler) handlePutMetricFilter(ctx context.Context, b []byte) (any, err func (h *Handler) handleDescribeMetricFilters(ctx context.Context, b []byte) (any, error) { var input describeMetricFiltersInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } filters, next, err := h.Backend.DescribeMetricFilters( @@ -97,7 +99,7 @@ func (h *Handler) handleDescribeMetricFilters(ctx context.Context, b []byte) (an func (h *Handler) handleDeleteMetricFilter(ctx context.Context, b []byte) (any, error) { var input deleteMetricFilterInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteMetricFilter(ctx, input.LogGroupName, input.FilterName); err != nil { @@ -112,7 +114,7 @@ func (h *Handler) handleTestMetricFilter( b []byte, ) (any, error) { var input testMetricFilterInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } matches, err := h.Backend.TestMetricFilter(input.FilterPattern, input.LogEventMessages) diff --git a/services/cloudwatchlogs/handler_queries.go b/services/cloudwatchlogs/handler_queries.go index 4887014d96..c6a1fd70ed 100644 --- a/services/cloudwatchlogs/handler_queries.go +++ b/services/cloudwatchlogs/handler_queries.go @@ -2,9 +2,11 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type startQueryInput struct { @@ -74,7 +76,7 @@ type listLogGroupsForQueryOutput struct { func (h *Handler) handleStartQuery(ctx context.Context, b []byte) (any, error) { var input startQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -103,7 +105,7 @@ func (h *Handler) handleStartQuery(ctx context.Context, b []byte) (any, error) { func (h *Handler) handleGetQueryResults(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input getQueryResultsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } results, stats, status, err := h.Backend.GetQueryResults(input.QueryID) @@ -140,7 +142,7 @@ func (h *Handler) handleGetQueryResults(ctx context.Context, b []byte) (any, err func (h *Handler) handleStopQuery(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input stopQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.StopQuery(input.QueryID); err != nil { @@ -152,7 +154,7 @@ func (h *Handler) handleStopQuery(ctx context.Context, b []byte) (any, error) { func (h *Handler) handleDescribeQueries(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input describeQueriesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } queries, next, err := h.Backend.DescribeQueries( @@ -179,7 +181,7 @@ func (h *Handler) handleListLogGroupsForQuery( b []byte, ) (any, error) { var input listLogGroupsForQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } groups, err := h.Backend.ListLogGroupsForQuery(input.QueryID) diff --git a/services/cloudwatchlogs/handler_queries_test.go b/services/cloudwatchlogs/handler_queries_test.go index 16ef2d1511..5267878b5c 100644 --- a/services/cloudwatchlogs/handler_queries_test.go +++ b/services/cloudwatchlogs/handler_queries_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -45,7 +46,7 @@ func TestHandler_InsightsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut, jsonx.V1())) queryID := startOut["queryId"] require.NotEmpty(t, queryID) @@ -54,7 +55,7 @@ func TestHandler_InsightsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resultsOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut, jsonx.V1())) assert.Equal(t, "Complete", resultsOut["status"]) rows, ok := resultsOut["results"].([]any) require.True(t, ok) @@ -65,7 +66,7 @@ func TestHandler_InsightsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &descOut, jsonx.V1())) queries, ok := descOut["queries"].([]any) require.True(t, ok) assert.Len(t, queries, 1) @@ -83,7 +84,7 @@ func TestHandler_InsightsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var stopOut map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &stopOut)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &stopOut, jsonx.V1())) assert.Equal(t, true, stopOut["success"]) // GetQueryResults now shows Cancelled. @@ -91,7 +92,7 @@ func TestHandler_InsightsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, rec5.Code) var resultsOut2 map[string]any - require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &resultsOut2)) + require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &resultsOut2, jsonx.V1())) assert.Equal(t, "Cancelled", resultsOut2["status"]) } @@ -163,21 +164,21 @@ func TestHandler_InsightsQueryLanguage(t *testing.T) { "queryString": tt.query, "startTime": 0, "endTime": 0, - }) + }, jsonx.V1()) require.NoError(t, merr) rec := doLogsRequest(t, h, e, "StartQuery", string(bodyJSON)) require.Equal(t, http.StatusOK, rec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut, jsonx.V1())) queryID := startOut["queryId"] rec2 := doLogsRequest(t, h, e, "GetQueryResults", `{"queryId":"`+queryID+`"}`) require.Equal(t, http.StatusOK, rec2.Code) var resultsOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut, jsonx.V1())) rows, ok := resultsOut["results"].([]any) require.True(t, ok, "results should be an array") assert.Len(t, rows, tt.wantResults) @@ -232,14 +233,14 @@ func TestHandler_InsightsARNIdentifier(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, "StartQuery", string(bodyBytes)) require.Equal(t, http.StatusOK, rec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startOut, jsonx.V1())) queryID := startOut["queryId"] require.NotEmpty(t, queryID) @@ -247,7 +248,7 @@ func TestHandler_InsightsARNIdentifier(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resultsOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resultsOut, jsonx.V1())) rows, ok := resultsOut["results"].([]any) require.True(t, ok) assert.Len(t, rows, tt.wantResults) @@ -271,7 +272,7 @@ func TestHandler_DescribeQueries_Pagination(t *testing.T) { "queryString": "fields @message", "startTime": i, "endTime": 0, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, "StartQuery", string(bodyBytes)) @@ -283,7 +284,7 @@ func TestHandler_DescribeQueries_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) page1Queries, ok := page1["queries"].([]any) require.True(t, ok, "page1 queries should be an array") assert.Len(t, page1Queries, 2) @@ -295,14 +296,14 @@ func TestHandler_DescribeQueries_Pagination(t *testing.T) { "logGroupName": "/pg", "maxResults": 2, "nextToken": nextToken, - }) + }, jsonx.V1()) require.NoError(t, err) rec2 := doLogsRequest(t, h, e, "DescribeQueries", string(bodyBytes)) require.Equal(t, http.StatusOK, rec2.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) page2Queries, ok := page2["queries"].([]any) require.True(t, ok, "page2 queries should be an array") assert.Len(t, page2Queries, 1) @@ -416,7 +417,7 @@ func TestHandler_QueryOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -424,13 +425,13 @@ func TestHandler_QueryOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) diff --git a/services/cloudwatchlogs/handler_query_definitions.go b/services/cloudwatchlogs/handler_query_definitions.go index ab82acbb26..b849622350 100644 --- a/services/cloudwatchlogs/handler_query_definitions.go +++ b/services/cloudwatchlogs/handler_query_definitions.go @@ -2,7 +2,9 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- PutQueryDefinition ---. @@ -46,7 +48,7 @@ func (h *Handler) handlePutQueryDefinition( b []byte, ) (any, error) { var input putQueryDefinitionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } id, err := h.Backend.PutQueryDefinitionWithLanguage( @@ -69,7 +71,7 @@ func (h *Handler) handleDescribeQueryDefinitions( b []byte, ) (any, error) { var input describeQueryDefinitionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } defs, next, err := h.Backend.DescribeQueryDefinitionsByLanguage( @@ -90,7 +92,7 @@ func (h *Handler) handleDeleteQueryDefinition( b []byte, ) (any, error) { var input deleteQueryDefinitionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteQueryDefinition(input.QueryDefinitionID); err != nil { diff --git a/services/cloudwatchlogs/handler_resource_policies.go b/services/cloudwatchlogs/handler_resource_policies.go index 244539152f..39aa9697f9 100644 --- a/services/cloudwatchlogs/handler_resource_policies.go +++ b/services/cloudwatchlogs/handler_resource_policies.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putResourcePolicyInput struct { @@ -23,7 +25,7 @@ func (h *Handler) handlePutResourcePolicy( body []byte, ) (any, error) { var in putResourcePolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -58,7 +60,7 @@ func (h *Handler) handleDescribeResourcePolicies( body []byte, ) (any, error) { var in describeResourcePoliciesInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -82,7 +84,7 @@ func (h *Handler) handleDeleteResourcePolicy( body []byte, ) (any, error) { var in deleteResourcePolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_resource_policies_test.go b/services/cloudwatchlogs/handler_resource_policies_test.go index 888a2b5f77..6c9c72186b 100644 --- a/services/cloudwatchlogs/handler_resource_policies_test.go +++ b/services/cloudwatchlogs/handler_resource_policies_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -82,7 +83,7 @@ func TestHandler_ResourcePolicy(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -126,13 +127,13 @@ func TestHandler_ResourcePolicyResponseShape(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } diff --git a/services/cloudwatchlogs/handler_scheduled_queries.go b/services/cloudwatchlogs/handler_scheduled_queries.go index 836e74bd55..ae5688bcf9 100644 --- a/services/cloudwatchlogs/handler_scheduled_queries.go +++ b/services/cloudwatchlogs/handler_scheduled_queries.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createScheduledQueryInput struct { @@ -153,7 +155,7 @@ func (h *Handler) handleCreateScheduledQuery( b []byte, ) (any, error) { var input createScheduledQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -195,7 +197,7 @@ func (h *Handler) handleDeleteScheduledQuery( b []byte, ) (any, error) { var input deleteScheduledQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteScheduledQuery(input.Identifier); err != nil { @@ -210,7 +212,7 @@ func (h *Handler) handleListScheduledQueries( b []byte, ) (any, error) { var input listScheduledQueriesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } queries, next, err := h.Backend.ListScheduledQueries( @@ -233,7 +235,7 @@ func (h *Handler) handleUpdateScheduledQuery( b []byte, ) (any, error) { var input updateScheduledQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -252,7 +254,7 @@ func (h *Handler) handleGetScheduledQuery( b []byte, ) (any, error) { var input getScheduledQueryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } sq, err := h.Backend.GetScheduledQuery(input.Identifier) @@ -274,7 +276,7 @@ func (h *Handler) handleGetScheduledQueryHistory( b []byte, ) (any, error) { var input getScheduledQueryHistoryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/cloudwatchlogs/handler_scheduled_queries_test.go b/services/cloudwatchlogs/handler_scheduled_queries_test.go index 393d065a8f..e4d2e7e1d7 100644 --- a/services/cloudwatchlogs/handler_scheduled_queries_test.go +++ b/services/cloudwatchlogs/handler_scheduled_queries_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -31,7 +32,7 @@ func TestHandler_ScheduledQuery_Create(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) queryARN, ok := out["scheduledQueryArn"].(string) require.True(t, ok) assert.Contains(t, queryARN, "scheduled-query") @@ -60,7 +61,7 @@ func TestHandler_GetScheduledQuery_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) queryARN, ok := createOut["scheduledQueryArn"].(string) require.True(t, ok) require.NotEmpty(t, queryARN) @@ -69,7 +70,7 @@ func TestHandler_GetScheduledQuery_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var sq map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &sq)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &sq, jsonx.V1())) assert.Equal(t, queryARN, sq["scheduledQueryArn"], "wire key must be scheduledQueryArn, not arn") _, hasOldKey := sq["arn"] @@ -129,7 +130,7 @@ func TestHandler_ScheduledQuery_DestinationConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) queryARN, arnOK := createOut["scheduledQueryArn"].(string) require.True(t, arnOK) @@ -137,7 +138,7 @@ func TestHandler_ScheduledQuery_DestinationConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var sq map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &sq)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &sq, jsonx.V1())) destRaw, hasDest := sq["destinationConfiguration"] if !tt.wantS3 && !tt.wantLookup { @@ -282,7 +283,7 @@ func TestHandler_CreateScheduledQueryOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -290,7 +291,7 @@ func TestHandler_CreateScheduledQueryOperations(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantKey != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantVal != "" { assert.Equal(t, tt.wantVal, out[tt.wantKey]) } else { @@ -321,7 +322,7 @@ func TestHandler_GetScheduledQueryHistory_RequiresTimeRange(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) arn, _ := created["scheduledQueryArn"].(string) require.NotEmpty(t, arn) diff --git a/services/cloudwatchlogs/handler_storage_tier_policy.go b/services/cloudwatchlogs/handler_storage_tier_policy.go index 1853cf8301..14ec12c599 100644 --- a/services/cloudwatchlogs/handler_storage_tier_policy.go +++ b/services/cloudwatchlogs/handler_storage_tier_policy.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // storageTierPolicyWireShape maps a StorageTierPolicy to the real @@ -42,7 +44,7 @@ func (h *Handler) handlePutStorageTierPolicy( body []byte, ) (any, error) { var in putStorageTierPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_subscription_filters.go b/services/cloudwatchlogs/handler_subscription_filters.go index 4da6f705ab..735e1133b0 100644 --- a/services/cloudwatchlogs/handler_subscription_filters.go +++ b/services/cloudwatchlogs/handler_subscription_filters.go @@ -2,7 +2,9 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putSubscriptionFilterInput struct { @@ -43,7 +45,7 @@ func (h *Handler) subscriptionFilterActions() map[string]actionFn { return map[string]actionFn{ "PutSubscriptionFilter": func(ctx context.Context, b []byte) (any, error) { var input putSubscriptionFilterInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.PutSubscriptionFilterWithOptions( @@ -63,7 +65,7 @@ func (h *Handler) subscriptionFilterActions() map[string]actionFn { }, "DescribeSubscriptionFilters": func(ctx context.Context, b []byte) (any, error) { var input describeSubscriptionFiltersInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } filters, next, err := h.Backend.DescribeSubscriptionFilters( @@ -78,7 +80,7 @@ func (h *Handler) subscriptionFilterActions() map[string]actionFn { }, "DeleteSubscriptionFilter": func(ctx context.Context, b []byte) (any, error) { var input deleteSubscriptionFilterInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteSubscriptionFilter(ctx, input.LogGroupName, input.FilterName); err != nil { diff --git a/services/cloudwatchlogs/handler_subscription_filters_test.go b/services/cloudwatchlogs/handler_subscription_filters_test.go index f5146adba7..962cff3059 100644 --- a/services/cloudwatchlogs/handler_subscription_filters_test.go +++ b/services/cloudwatchlogs/handler_subscription_filters_test.go @@ -2,7 +2,7 @@ package cloudwatchlogs_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -152,7 +153,7 @@ func TestHandler_SubscriptionFilterOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -160,13 +161,13 @@ func TestHandler_SubscriptionFilterOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) diff --git a/services/cloudwatchlogs/handler_syslog_configurations.go b/services/cloudwatchlogs/handler_syslog_configurations.go index 5609fd91a7..681532efa3 100644 --- a/services/cloudwatchlogs/handler_syslog_configurations.go +++ b/services/cloudwatchlogs/handler_syslog_configurations.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putSyslogConfigurationInput struct { @@ -13,7 +15,7 @@ type putSyslogConfigurationInput struct { func (h *Handler) handlePutSyslogConfiguration(ctx context.Context, body []byte) (any, error) { var in putSyslogConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -39,7 +41,7 @@ func (h *Handler) handleDeleteSyslogConfiguration( body []byte, ) (any, error) { var in deleteSyslogConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -64,7 +66,7 @@ func (h *Handler) handleListSyslogConfigurations( body []byte, ) (any, error) { var in listSyslogConfigurationsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } diff --git a/services/cloudwatchlogs/handler_tags.go b/services/cloudwatchlogs/handler_tags.go index 3f457eadc1..da61a90e39 100644 --- a/services/cloudwatchlogs/handler_tags.go +++ b/services/cloudwatchlogs/handler_tags.go @@ -2,10 +2,11 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "maps" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -136,7 +137,7 @@ func (h *Handler) logTagActions() map[string]actionFn { return map[string]actionFn{ "ListTagsLogGroup": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input listTagsLogGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -144,7 +145,7 @@ func (h *Handler) logTagActions() map[string]actionFn { }, "ListTagsForResource": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input listTagsForResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -152,7 +153,7 @@ func (h *Handler) logTagActions() map[string]actionFn { }, "TagLogGroup": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input tagLogGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } var kv map[string]string @@ -165,7 +166,7 @@ func (h *Handler) logTagActions() map[string]actionFn { }, "UntagLogGroup": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input untagLogGroupInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } h.removeTags(input.LogGroupName, input.Tags) @@ -174,7 +175,7 @@ func (h *Handler) logTagActions() map[string]actionFn { }, "TagResource": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input tagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } h.setTags(input.ResourceArn, maps.Clone(input.Tags)) @@ -183,7 +184,7 @@ func (h *Handler) logTagActions() map[string]actionFn { }, "UntagResource": func(ctx context.Context, b []byte) (any, error) { //nolint:revive // existing issue. var input untagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } h.removeTags(input.ResourceArn, input.TagKeys) diff --git a/services/cloudwatchlogs/handler_tags_test.go b/services/cloudwatchlogs/handler_tags_test.go index ef4204dd59..9da29d833a 100644 --- a/services/cloudwatchlogs/handler_tags_test.go +++ b/services/cloudwatchlogs/handler_tags_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -33,7 +34,7 @@ func TestHandler_TagRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Equal(t, "prod", listResp["tags"]["env"]) assert.Equal(t, "ops", listResp["tags"]["team"]) @@ -42,7 +43,7 @@ func TestHandler_TagRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp2 map[string]map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp2, jsonx.V1())) assert.Len(t, listResp2["tags"], 2) // Remove one tag. @@ -53,7 +54,7 @@ func TestHandler_TagRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listResp3 map[string]map[string]string - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp3, jsonx.V1())) assert.Len(t, listResp3["tags"], 1) assert.Equal(t, "ops", listResp3["tags"]["team"]) } @@ -75,7 +76,7 @@ func TestHandler_TagResource_UntagResource(t *testing.T) { rec = doLogsRequest(t, h, e, "ListTagsForResource", `{"resourceArn":"`+arn+`"}`) require.Equal(t, http.StatusOK, rec.Code) var listOut map[string]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Equal(t, "prod", listOut["tags"]["env"]) assert.Equal(t, "platform", listOut["tags"]["team"]) @@ -87,7 +88,7 @@ func TestHandler_TagResource_UntagResource(t *testing.T) { // Verify env tag removed, team tag remains. rec = doLogsRequest(t, h, e, "ListTagsForResource", `{"resourceArn":"`+arn+`"}`) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut["tags"]["env"]) assert.Equal(t, "platform", listOut["tags"]["team"]) } @@ -111,7 +112,7 @@ func TestHandler_Reset_ClearsTags(t *testing.T) { `{"resourceArn":"arn:aws:logs:us-east-1:123:log-group:/g"}`) require.Equal(t, http.StatusOK, rec.Code) var listOut map[string]map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut["tags"]) } @@ -205,7 +206,7 @@ func TestHandler_TagOperations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -213,13 +214,13 @@ func TestHandler_TagOperations(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) diff --git a/services/cloudwatchlogs/handler_test.go b/services/cloudwatchlogs/handler_test.go index ed85c2b0d2..4e23db3a6d 100644 --- a/services/cloudwatchlogs/handler_test.go +++ b/services/cloudwatchlogs/handler_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -65,7 +66,7 @@ func TestHandler_GetSupportedOperations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.Contains(t, ops, "CreateLogGroup") assert.Contains(t, ops, "PutLogEvents") } @@ -299,14 +300,14 @@ func TestHandler_LookupTables(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "response should contain field %q", field) } @@ -325,7 +326,7 @@ func TestHandler_LookupTable_GetRealResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) tableArn, ok := created["lookupTableArn"].(string) require.True(t, ok) require.NotEmpty(t, tableArn) @@ -334,7 +335,7 @@ func TestHandler_LookupTable_GetRealResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "shape_table", got["lookupTableName"]) assert.Equal(t, "id,name\n1,foo\n", got["tableBody"]) assert.Contains(t, got, "sizeBytes") @@ -402,7 +403,7 @@ func TestHandler_SyslogConfigurations(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) @@ -426,7 +427,7 @@ func TestHandler_SyslogConfiguration_ListResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["syslogConfigurations"].([]any) require.True(t, ok) require.Len(t, list, 1) @@ -496,7 +497,7 @@ func TestHandler_StorageTierPolicy(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) require.Equal(t, tt.wantCode, rec.Code) @@ -506,7 +507,7 @@ func TestHandler_StorageTierPolicy(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantTier, resp["storageTier"]) if tt.wantHasLUT { @@ -550,7 +551,7 @@ func TestHandler_UnknownOperation(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) @@ -558,13 +559,13 @@ func TestHandler_UnknownOperation(t *testing.T) { if tt.wantListField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp[tt.wantListField].([]any), tt.wantListLen) } if tt.wantNotEmptyField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) diff --git a/services/cloudwatchlogs/handler_transformers.go b/services/cloudwatchlogs/handler_transformers.go index 2af8d8dd9c..4f141b167f 100644 --- a/services/cloudwatchlogs/handler_transformers.go +++ b/services/cloudwatchlogs/handler_transformers.go @@ -2,8 +2,10 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putTransformerInput struct { @@ -16,7 +18,7 @@ func (h *Handler) handlePutTransformer( body []byte, ) (any, error) { var in putTransformerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -38,7 +40,7 @@ func (h *Handler) handleGetTransformer( body []byte, ) (any, error) { var in getTransformerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -78,7 +80,7 @@ func (h *Handler) handleDeleteTransformer( body []byte, ) (any, error) { var in deleteTransformerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } @@ -103,7 +105,7 @@ func (h *Handler) handleTestTransformer( LogEventMessages []string `json:"logEventMessages"` } if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } diff --git a/services/cloudwatchlogs/handler_transformers_test.go b/services/cloudwatchlogs/handler_transformers_test.go index 040bd90f76..e69fc09d2b 100644 --- a/services/cloudwatchlogs/handler_transformers_test.go +++ b/services/cloudwatchlogs/handler_transformers_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -112,7 +113,7 @@ func TestHandler_Transformer(t *testing.T) { tt.setup(t, h, e) } - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, h, e, tt.action, string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) diff --git a/services/cloudwatchlogs/insights_parse.go b/services/cloudwatchlogs/insights_parse.go index 9fe13e8782..487e3ac956 100644 --- a/services/cloudwatchlogs/insights_parse.go +++ b/services/cloudwatchlogs/insights_parse.go @@ -1,12 +1,14 @@ package cloudwatchlogs import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strconv" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseParseCommand parses "parse [source] <"glob"|/regex/> [as f1, f2, ...]". @@ -199,7 +201,7 @@ func resolveJSONField(message, name string) cwValue { } var root any - if err := json.Unmarshal([]byte(message), &root); err != nil { + if err := json.Unmarshal([]byte(message), &root, jsonx.V1()); err != nil { return cwValue{} } @@ -273,7 +275,7 @@ func jsonScalar(v any) cwValue { case nil: return cwValue{} default: - if b, err := json.Marshal(t); err == nil { + if b, err := json.Marshal(t, jsonx.V1()); err == nil { return literalString(string(b)) } diff --git a/services/cloudwatchlogs/log_events.go b/services/cloudwatchlogs/log_events.go index c8e807d3f8..518be23d78 100644 --- a/services/cloudwatchlogs/log_events.go +++ b/services/cloudwatchlogs/log_events.go @@ -4,7 +4,8 @@ import ( "cmp" "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "sort" @@ -13,6 +14,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validatePutLogEventsBatch checks the batch size constraints for PutLogEvents. @@ -954,8 +956,8 @@ func jsonMessageFields(message string) []string { return nil } - var obj map[string]json.RawMessage - if err := json.Unmarshal([]byte(trimmed), &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal([]byte(trimmed), &obj, jsonx.V1()); err != nil { return nil } diff --git a/services/cloudwatchlogs/perf_sweep_bench_test.go b/services/cloudwatchlogs/perf_sweep_bench_test.go index ab5cb2f792..074e4a388a 100644 --- a/services/cloudwatchlogs/perf_sweep_bench_test.go +++ b/services/cloudwatchlogs/perf_sweep_bench_test.go @@ -6,7 +6,7 @@ package cloudwatchlogs_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -29,7 +30,7 @@ func invokeLogsB( ) (int, map[string]any) { tb.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(tb, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -41,7 +42,7 @@ func invokeLogsB( var resp map[string]any if rec.Body.Len() > 0 { - require.NoError(tb, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(tb, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) } return rec.Code, resp diff --git a/services/cloudwatchlogs/persistence.go b/services/cloudwatchlogs/persistence.go index c04fc4a132..ec5d874167 100644 --- a/services/cloudwatchlogs/persistence.go +++ b/services/cloudwatchlogs/persistence.go @@ -2,7 +2,7 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -319,10 +319,10 @@ func newDirtyDTORegistry() ( // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/cloudwatchlogs/presence_validation_test.go b/services/cloudwatchlogs/presence_validation_test.go index a4437127fc..1f31e55408 100644 --- a/services/cloudwatchlogs/presence_validation_test.go +++ b/services/cloudwatchlogs/presence_validation_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -50,7 +51,7 @@ func TestGetLogFields_DataSourceTypePresenceValidation(t *testing.T) { handler := cloudwatchlogs.NewHandler(backend) doLogsRequest(t, handler, e, "CreateLogGroup", `{"logGroupName":"grp"}`) - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := doLogsRequest(t, handler, e, "GetLogFields", string(bodyBytes)) @@ -58,7 +59,7 @@ func TestGetLogFields_DataSourceTypePresenceValidation(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } }) @@ -115,14 +116,14 @@ func TestListAggregateLogGroupSummaries_GroupByPresenceValidation(t *testing.T) t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := makeLogsRequest(t, "ListAggregateLogGroupSummaries", string(bodyBytes)) assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantCode == http.StatusBadRequest { assert.Equal(t, tt.wantError, resp["__type"]) diff --git a/services/cloudwatchlogs/subscription_filters.go b/services/cloudwatchlogs/subscription_filters.go index f8b5fddd2f..53b66e2216 100644 --- a/services/cloudwatchlogs/subscription_filters.go +++ b/services/cloudwatchlogs/subscription_filters.go @@ -5,7 +5,7 @@ import ( "compress/gzip" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -283,7 +284,7 @@ func (b *InMemoryBackend) deliverToFilters( // encodeSubscriptionPayload gzips the JSON payload and base64-encodes it. func encodeSubscriptionPayload(payload subscriptionPayload) ([]byte, error) { - raw, err := json.Marshal(payload) + raw, err := json.Marshal(payload, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/cloudwatchlogs/transformers.go b/services/cloudwatchlogs/transformers.go index a47387ce62..0d18ea0701 100644 --- a/services/cloudwatchlogs/transformers.go +++ b/services/cloudwatchlogs/transformers.go @@ -2,10 +2,12 @@ package cloudwatchlogs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutTransformer creates or updates a log transformer. @@ -134,7 +136,7 @@ func applyProcessorsToMessage(message string, processors []map[string]any) strin return message } - out, err := json.Marshal(obj) + out, err := json.Marshal(obj, jsonx.V1()) if err != nil { return message } @@ -149,7 +151,7 @@ func decodeJSONObject(message string) (map[string]any, bool) { } var obj map[string]any - if err := json.Unmarshal([]byte(trimmed), &obj); err != nil { + if err := json.Unmarshal([]byte(trimmed), &obj, jsonx.V1()); err != nil { return nil, false } diff --git a/services/cloudwatchlogs/undeclared_members_test.go b/services/cloudwatchlogs/undeclared_members_test.go index 1e1b3c99c9..1e6c7c42e4 100644 --- a/services/cloudwatchlogs/undeclared_members_test.go +++ b/services/cloudwatchlogs/undeclared_members_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -41,7 +42,7 @@ func TestHandler_DescribeExportTasks_OmitsLogStreamNamePrefix(t *testing.T) { var out struct { ExportTasks []map[string]any `json:"exportTasks"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ExportTasks, 1) assert.NotContains(t, out.ExportTasks[0], "logStreamNamePrefix") assert.Equal(t, "/grp", out.ExportTasks[0]["logGroupName"]) diff --git a/services/cloudwatchlogs/wire_field_fixes_test.go b/services/cloudwatchlogs/wire_field_fixes_test.go index 37e966cf35..b2b17b3a5b 100644 --- a/services/cloudwatchlogs/wire_field_fixes_test.go +++ b/services/cloudwatchlogs/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package cloudwatchlogs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -711,7 +712,7 @@ func TestGetScheduledQueryHistory_RealShape(t *testing.T) { require.Equal(t, http.StatusOK, rawRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rawRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rawRec.Body.Bytes(), &raw, jsonx.V1())) _, hasReal := raw["triggerHistory"] assert.True(t, hasReal, "wrapper key must be triggerHistory") _, hasFabricated := raw["scheduledQueryRunSummaries"] diff --git a/services/codeartifact/domain_owner_and_error_message_test.go b/services/codeartifact/domain_owner_and_error_message_test.go index 6ce1d3cf9d..4e5241bddd 100644 --- a/services/codeartifact/domain_owner_and_error_message_test.go +++ b/services/codeartifact/domain_owner_and_error_message_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDomainOwnerQuery(t *testing.T) { @@ -64,7 +65,7 @@ func TestPackageVersionErrors_CarryMessage(t *testing.T) { } `json:"failedVersions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Contains(t, out.Failed, "99.0.0") assert.Equal(t, "NOT_FOUND", out.Failed["99.0.0"].Code) assert.Contains(t, out.Failed["99.0.0"].Message, "99.0.0") diff --git a/services/codeartifact/handler.go b/services/codeartifact/handler.go index 1ad712b2be..992331a2cc 100644 --- a/services/codeartifact/handler.go +++ b/services/codeartifact/handler.go @@ -2,7 +2,8 @@ package codeartifact import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -632,9 +634,9 @@ func (h *Handler) readRequestBody(c *echo.Context, op string) ([]byte, error) { return raw, nil } - decoder := json.NewDecoder(c.Request().Body) - var raw json.RawMessage - if err := decoder.Decode(&raw); err != nil { + decoder := jsontext.NewDecoder(c.Request().Body) + var raw jsontext.Value + if err := json.UnmarshalDecode(decoder, &raw, jsonx.V1()); err != nil { raw = nil } diff --git a/services/codeartifact/handler_domains.go b/services/codeartifact/handler_domains.go index 96055ddb47..4550877349 100644 --- a/services/codeartifact/handler_domains.go +++ b/services/codeartifact/handler_domains.go @@ -3,12 +3,14 @@ package codeartifact import ( "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const authTokenBytes = 48 @@ -60,7 +62,7 @@ func (h *Handler) handleCreateDomain(c *echo.Context, name string, body []byte) var in createDomainBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -105,7 +107,7 @@ type listDomainsBody struct { func (h *Handler) handleListDomains(c *echo.Context, body []byte) error { var in listDomainsBody if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } all := h.Backend.ListDomains(c.Request().Context()) @@ -217,7 +219,7 @@ type putDomainPermissionsPolicyBody struct { func (h *Handler) handlePutDomainPermissionsPolicy(c *echo.Context, body []byte) error { var in putDomainPermissionsPolicyBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } diff --git a/services/codeartifact/handler_domains_test.go b/services/codeartifact/handler_domains_test.go index 670e0b0415..37d14142cb 100644 --- a/services/codeartifact/handler_domains_test.go +++ b/services/codeartifact/handler_domains_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -50,7 +51,7 @@ func TestHandler_CreateAndDescribeDomain(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) domain, _ := resp["domain"].(map[string]any) assert.Equal(t, tt.domainName, domain["name"]) assert.NotEmpty(t, domain["arn"]) @@ -60,7 +61,7 @@ func TestHandler_CreateAndDescribeDomain(t *testing.T) { descRec := doRequest(t, h, http.MethodGet, "/v1/domain?domain="+tt.domainName, nil) assert.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) ddomain, _ := descResp["domain"].(map[string]any) assert.Equal(t, tt.domainName, ddomain["name"]) } @@ -119,7 +120,7 @@ func TestHandler_ListDomains(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) domains, _ := resp["domains"].([]any) assert.Len(t, domains, 2) } @@ -134,7 +135,7 @@ func TestHandler_GetAuthorizationToken(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["authorizationToken"]) assert.NotEmpty(t, resp["expiration"]) } @@ -167,7 +168,7 @@ func TestHandler_DomainPermissionsPolicy(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(b, &resp)) + require.NoError(t, json.Unmarshal(b, &resp, jsonx.V1())) pol, _ := resp["policy"].(map[string]any) assert.NotEmpty(t, pol["revision"]) assert.NotEmpty(t, pol["resourceArn"]) @@ -189,7 +190,7 @@ func TestHandler_DomainPermissionsPolicy(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(b, &resp)) + require.NoError(t, json.Unmarshal(b, &resp, jsonx.V1())) pol, _ := resp["policy"].(map[string]any) assert.Contains(t, pol["document"], "Allow") }, @@ -279,7 +280,7 @@ func TestHandler_DomainPermissionsPolicy_RevisionLocking(t *testing.T) { }) require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) pol, _ := putResp["policy"].(map[string]any) revision, _ := pol["revision"].(string) require.NotEmpty(t, revision) @@ -296,7 +297,7 @@ func TestHandler_DomainPermissionsPolicy_RevisionLocking(t *testing.T) { getRec := doRequest(t, h, http.MethodGet, "/v1/domain/permissions/policy?domain=lock-domain", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) getPol, _ := getResp["policy"].(map[string]any) assert.NotContains(t, getPol["document"], "Deny") @@ -318,7 +319,7 @@ func TestHandler_DomainPermissionsPolicy_RevisionLocking(t *testing.T) { }) require.Equal(t, http.StatusOK, matchPutRec.Code) var matchPutResp map[string]any - require.NoError(t, json.Unmarshal(matchPutRec.Body.Bytes(), &matchPutResp)) + require.NoError(t, json.Unmarshal(matchPutRec.Body.Bytes(), &matchPutResp, jsonx.V1())) newPol, _ := matchPutResp["policy"].(map[string]any) newRevision, _ := newPol["revision"].(string) require.NotEmpty(t, newRevision) @@ -387,7 +388,7 @@ func TestHandler_RepositoryCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) domainMap, _ := resp["domain"].(map[string]any) count, _ := domainMap["repositoryCount"].(float64) assert.InEpsilon(t, float64(2), count, 0) @@ -405,7 +406,7 @@ func TestHandler_DomainSummaryVsFullDescription(t *testing.T) { listRec := doRequest(t, h, http.MethodPost, "/v1/domains", nil) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) domains, _ := listResp["domains"].([]any) require.Len(t, domains, 1) d, _ := domains[0].(map[string]any) @@ -416,7 +417,7 @@ func TestHandler_DomainSummaryVsFullDescription(t *testing.T) { descRec := doRequest(t, h, http.MethodGet, "/v1/domain?domain=summary-domain", nil) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) dd, _ := descResp["domain"].(map[string]any) count, _ := dd["repositoryCount"].(float64) assert.InEpsilon(t, float64(2), count, 0) @@ -438,7 +439,7 @@ func TestListDomains_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1, _ := out1["domains"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["nextToken"].(string) @@ -448,7 +449,7 @@ func TestListDomains_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2, _ := out2["domains"].([]any) assert.Len(t, page2, 2) } diff --git a/services/codeartifact/handler_internal_error_test.go b/services/codeartifact/handler_internal_error_test.go index c8207c798f..7d927a1b9e 100644 --- a/services/codeartifact/handler_internal_error_test.go +++ b/services/codeartifact/handler_internal_error_test.go @@ -1,7 +1,7 @@ package codeartifact //nolint:testpackage // needs access to the unexported handleError method. import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errUnmatchedForTest = errors.New("boom: matches none of handleError's sentinel checks") @@ -48,7 +50,7 @@ func TestHandleError_DefaultBranchEmitsInternalServerException(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InternalServerException", body["code"]) assert.NotEqual(t, "InternalFailure", body["code"]) } diff --git a/services/codeartifact/handler_list_summary_test.go b/services/codeartifact/handler_list_summary_test.go index 0775835fe2..7f2b7dfa15 100644 --- a/services/codeartifact/handler_list_summary_test.go +++ b/services/codeartifact/handler_list_summary_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,8 @@ import ( casdk "github.com/aws/aws-sdk-go-v2/service/codeartifact" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListPackages_SummaryShape locks that ListPackages emits the @@ -36,7 +38,7 @@ func TestHandler_ListPackages_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkgs, ok := resp["packages"].([]any) require.True(t, ok) require.Len(t, pkgs, 1) @@ -112,7 +114,7 @@ func TestHandler_ListPackageVersions_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) require.Len(t, versions, 1) diff --git a/services/codeartifact/handler_package_groups.go b/services/codeartifact/handler_package_groups.go index 89e2d28fca..8305fb8ba8 100644 --- a/services/codeartifact/handler_package_groups.go +++ b/services/codeartifact/handler_package_groups.go @@ -2,11 +2,13 @@ package codeartifact import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createPackageGroupBody's Pattern field is tagged json:"packageGroup" -- @@ -120,7 +122,7 @@ func (h *Handler) handleCreatePackageGroup(c *echo.Context, domainName string, b var in createPackageGroupBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("ValidationException", "invalid request body"), @@ -423,7 +425,7 @@ func (h *Handler) handleUpdatePackageGroup(c *echo.Context, domainName string, b var in updatePackageGroupBody if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } pattern := c.Request().URL.Query().Get(keyPackageGroup) @@ -496,7 +498,7 @@ func (h *Handler) handleUpdatePackageGroupOriginConfiguration( var in updatePackageGroupOriginConfigurationBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errResp("ValidationException", "invalid request body"), diff --git a/services/codeartifact/handler_package_groups_list_test.go b/services/codeartifact/handler_package_groups_list_test.go index 8469ae50c2..4c49438684 100644 --- a/services/codeartifact/handler_package_groups_list_test.go +++ b/services/codeartifact/handler_package_groups_list_test.go @@ -2,7 +2,7 @@ package codeartifact_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -94,7 +95,7 @@ func TestHandler_ListAllowedRepositoriesForGroup(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["allowedRepositories"]) } }) @@ -161,7 +162,7 @@ func TestHandler_ListAssociatedPackages(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkgs, _ := resp["packages"].([]any) assert.NotNil(t, pkgs) } @@ -199,7 +200,7 @@ func TestHandler_ListAssociatedPackages_Preview(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkgs, _ := resp["packages"].([]any) require.Len(t, pkgs, 1) assert.Equal(t, "react", pkgs[0].(map[string]any)["package"]) @@ -256,7 +257,7 @@ func TestHandler_ListAssociatedPackages_MostSpecificMatch(t *testing.T) { require.Equal(t, http.StatusOK, broadRec.Code) var broadResp map[string]any - require.NoError(t, json.Unmarshal(broadRec.Body.Bytes(), &broadResp)) + require.NoError(t, json.Unmarshal(broadRec.Body.Bytes(), &broadResp, jsonx.V1())) broadPkgs, _ := broadResp["packages"].([]any) require.Len(t, broadPkgs, 1) assert.Equal(t, "react", broadPkgs[0].(map[string]any)["package"]) @@ -272,7 +273,7 @@ func TestHandler_ListAssociatedPackages_MostSpecificMatch(t *testing.T) { require.Equal(t, http.StatusOK, specificRec.Code) var specificResp map[string]any - require.NoError(t, json.Unmarshal(specificRec.Body.Bytes(), &specificResp)) + require.NoError(t, json.Unmarshal(specificRec.Body.Bytes(), &specificResp, jsonx.V1())) specificPkgs, _ := specificResp["packages"].([]any) require.Len(t, specificPkgs, 1) assert.Equal(t, "utils", specificPkgs[0].(map[string]any)["package"]) @@ -323,7 +324,7 @@ func TestHandler_ListAssociatedPackages_WeakMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkgs, _ := resp["packages"].([]any) require.Len(t, pkgs, 2, "both the strong and weak variant are associated with the same group") @@ -342,7 +343,7 @@ func TestHandler_ListAssociatedPackages_WeakMatch(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "WEAK", getResp["associationType"]) } @@ -383,7 +384,7 @@ func TestHandler_GetAssociatedPackageGroup_MostSpecificMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pg, _ := resp["packageGroup"].(map[string]any) require.NotNil(t, pg) assert.Equal(t, "/npm/space/react$", pg["pattern"]) @@ -398,7 +399,7 @@ func TestHandler_GetAssociatedPackageGroup_MostSpecificMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) pg2, _ := resp2["packageGroup"].(map[string]any) require.NotNil(t, pg2) assert.Equal(t, "/npm/*", pg2["pattern"]) @@ -495,7 +496,7 @@ func TestHandler_ListPackageGroups(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, _ := resp["packageGroups"].([]any) assert.Len(t, groups, tt.wantCount) } @@ -582,7 +583,7 @@ func TestHandler_UpdatePackageGroup(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pg, _ := resp["packageGroup"].(map[string]any) assert.NotNil(t, pg) } @@ -690,7 +691,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pg, _ := resp["packageGroup"].(map[string]any) require.NotNil(t, pg) @@ -735,7 +736,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration_AllowedRepositories(t *te require.Equal(t, http.StatusOK, addRec.Code) var addResp map[string]any - require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp)) + require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp, jsonx.V1())) updates, _ := addResp["allowedRepositoryUpdates"].(map[string]any) require.NotNil(t, updates) extUpstream, _ := updates["EXTERNAL_UPSTREAM"].(map[string]any) @@ -752,7 +753,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration_AllowedRepositories(t *te require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) allowed, _ := listResp["allowedRepositories"].([]any) assert.Equal(t, []any{"upgocr-repo"}, allowed) @@ -776,7 +777,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration_AllowedRepositories(t *te require.Equal(t, http.StatusOK, listRec2.Code) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2, jsonx.V1())) allowed2, _ := listResp2["allowedRepositories"].([]any) assert.Empty(t, allowed2) } @@ -828,7 +829,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration_Inheritance(t *testing.T) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) pg, _ := descResp["packageGroup"].(map[string]any) originConfig, _ := pg["originConfiguration"].(map[string]any) restrictions, _ := originConfig["restrictions"].(map[string]any) @@ -859,7 +860,7 @@ func TestHandler_UpdatePackageGroupOriginConfiguration_Inheritance(t *testing.T) require.Equal(t, http.StatusOK, descRec2.Code) var descResp2 map[string]any - require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2)) + require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2, jsonx.V1())) pg2, _ := descResp2["packageGroup"].(map[string]any) originConfig2, _ := pg2["originConfiguration"].(map[string]any) restrictions2, _ := originConfig2["restrictions"].(map[string]any) @@ -891,7 +892,7 @@ func TestListPackageGroups_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1, _ := out1["packageGroups"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["nextToken"].(string) @@ -902,7 +903,7 @@ func TestListPackageGroups_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2, _ := out2["packageGroups"].([]any) assert.Len(t, page2, 2) } diff --git a/services/codeartifact/handler_package_groups_test.go b/services/codeartifact/handler_package_groups_test.go index b1983944ee..e9fcf5a5bb 100644 --- a/services/codeartifact/handler_package_groups_test.go +++ b/services/codeartifact/handler_package_groups_test.go @@ -2,7 +2,7 @@ package codeartifact_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -94,7 +95,7 @@ func TestHandler_CreatePackageGroup(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pg, _ := resp["packageGroup"].(map[string]any) assert.NotEmpty(t, pg["arn"]) assert.Equal(t, "pg-domain", pg["domainName"]) @@ -125,7 +126,7 @@ func TestHandler_PackageGroupCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) pg, _ := createResp["packageGroup"].(map[string]any) assert.Equal(t, "/npm/mygroup/*", pg["pattern"]) assert.Equal(t, "test group", pg["description"]) @@ -302,7 +303,7 @@ func TestHandler_ListSubPackageGroups(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, _ := resp["packageGroups"].([]any) assert.Len(t, groups, tt.wantCount) } @@ -329,7 +330,7 @@ func TestHandler_PackageGroupTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) pg, _ := createResp["packageGroup"].(map[string]any) pgARN, _ := pg["arn"].(string) require.NotEmpty(t, pgARN) @@ -338,7 +339,7 @@ func TestHandler_PackageGroupTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagList, _ := listResp["tags"].([]any) assert.Len(t, tagList, 1) } @@ -383,7 +384,7 @@ func TestHandler_PackageGroupHierarchy(t *testing.T) { allRec := doRequest(t, h, http.MethodPost, "/v1/package-groups?domain=hier-domain", nil) require.Equal(t, http.StatusOK, allRec.Code) var allResp map[string]any - require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &allResp)) + require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &allResp, jsonx.V1())) allGroups, _ := allResp["packageGroups"].([]any) assert.Len(t, allGroups, 5) @@ -397,7 +398,7 @@ func TestHandler_PackageGroupHierarchy(t *testing.T) { ) require.Equal(t, http.StatusOK, subRec.Code) var subResp map[string]any - require.NoError(t, json.Unmarshal(subRec.Body.Bytes(), &subResp)) + require.NoError(t, json.Unmarshal(subRec.Body.Bytes(), &subResp, jsonx.V1())) subGroups, _ := subResp["packageGroups"].([]any) assert.Len(t, subGroups, 2) @@ -411,7 +412,7 @@ func TestHandler_PackageGroupHierarchy(t *testing.T) { ) require.Equal(t, http.StatusOK, subRec2.Code) var subResp2 map[string]any - require.NoError(t, json.Unmarshal(subRec2.Body.Bytes(), &subResp2)) + require.NoError(t, json.Unmarshal(subRec2.Body.Bytes(), &subResp2, jsonx.V1())) subGroups2, _ := subResp2["packageGroups"].([]any) assert.Empty(t, subGroups2) } diff --git a/services/codeartifact/handler_package_version_rejection_test.go b/services/codeartifact/handler_package_version_rejection_test.go index 694ff15b47..ac1f054df4 100644 --- a/services/codeartifact/handler_package_version_rejection_test.go +++ b/services/codeartifact/handler_package_version_rejection_test.go @@ -1,12 +1,14 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_PackageVersionOps_RejectionNotBypassed guards @@ -54,7 +56,7 @@ func TestHandler_PackageVersionOps_RejectionNotBypassed(t *testing.T) { var resp map[string]any require.NoError( - t, json.Unmarshal(rec.Body.Bytes(), &resp), + t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()), "response body must be a single well-formed JSON document, not two concatenated: %s", rec.Body.String(), ) assert.Equal(t, "ValidationException", resp["code"]) diff --git a/services/codeartifact/handler_package_versions.go b/services/codeartifact/handler_package_versions.go index 4c47974849..23a100774b 100644 --- a/services/codeartifact/handler_package_versions.go +++ b/services/codeartifact/handler_package_versions.go @@ -3,13 +3,15 @@ package codeartifact import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func packageVersionToMap(pv *PackageVersion) map[string]any { @@ -182,7 +184,7 @@ func (h *Handler) handleDeletePackageVersions( var in deletePackageVersionsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -238,7 +240,7 @@ func (h *Handler) handleCopyPackageVersions( var in copyPackageVersionsBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -291,7 +293,7 @@ func (h *Handler) handleDisposePackageVersions( var in disposeVersionsBody if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } successful, failed, err := h.Backend.DisposePackageVersions( @@ -742,7 +744,7 @@ func (h *Handler) handleUpdatePackageVersionsStatus( var in updateVersionsStatusBody if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } if in.TargetStatus == "" { diff --git a/services/codeartifact/handler_package_versions_assets_test.go b/services/codeartifact/handler_package_versions_assets_test.go index 35b6f5813f..fec917a576 100644 --- a/services/codeartifact/handler_package_versions_assets_test.go +++ b/services/codeartifact/handler_package_versions_assets_test.go @@ -2,7 +2,7 @@ package codeartifact_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -44,7 +45,7 @@ func TestHandler_PublishPackageVersion_AppearInList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) versions, _ := resp["versions"].([]any) assert.Len(t, versions, 2) } @@ -206,7 +207,7 @@ func TestHandler_GetPackageVersionReadme(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["readme"] assert.True(t, ok) } @@ -240,7 +241,7 @@ func TestHandler_GetPackageVersionReadme_FromPublishedPackageJSON(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "# My Package\n\nUsage instructions.", resp["readme"]) assert.Equal(t, "npm", resp["format"]) assert.Equal(t, "mypkg", resp["package"]) @@ -273,7 +274,7 @@ func TestHandler_GetPackageVersionReadme_NoPackageJSON(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["readme"]) } @@ -310,7 +311,7 @@ func TestHandler_ListPackageVersionDependencies_FromPublishedPackageJSON(t *test require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, _ := resp["dependencies"].([]any) require.Len(t, deps, 4) @@ -394,7 +395,7 @@ func TestHandler_ListPackageVersionAssets(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assets, _ := resp["assets"].([]any) assert.NotNil(t, assets) } @@ -470,7 +471,7 @@ func TestHandler_ListPackageVersionDependencies(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, _ := resp["dependencies"].([]any) assert.NotNil(t, deps) } @@ -551,7 +552,7 @@ func TestHandler_ListPackageVersions(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, _ := resp["versions"].([]any) assert.Len(t, versions, tt.wantCount) } @@ -646,7 +647,7 @@ func TestHandler_PublishPackageVersion(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["version"]) assert.NotEmpty(t, resp["status"]) assert.NotEmpty(t, resp["asset"]) diff --git a/services/codeartifact/handler_package_versions_test.go b/services/codeartifact/handler_package_versions_test.go index 71e314f95b..8829446637 100644 --- a/services/codeartifact/handler_package_versions_test.go +++ b/services/codeartifact/handler_package_versions_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -72,7 +73,7 @@ func TestHandler_DescribePackageVersion(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pv, _ := resp["packageVersion"].(map[string]any) assert.Equal(t, "1.0.0", pv["version"]) assert.NotEmpty(t, pv["status"]) @@ -110,7 +111,7 @@ func TestHandler_DeletePackageVersions(t *testing.T) { // aws-sdk-go-v2 deserializers.go's ...PackageVersionErrorMap/ // ...SuccessfulPackageVersionInfoMap. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failed, _ := resp["failedVersions"].(map[string]any) require.Len(t, failed, 1) failedEntry, _ := failed["99.0.0"].(map[string]any) @@ -162,7 +163,7 @@ func TestHandler_CopyPackageVersions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failed, _ := resp["failedVersions"].(map[string]any) require.Len(t, failed, 1) failedEntry, _ := failed["9.9.9"].(map[string]any) @@ -215,7 +216,7 @@ func TestHandler_PackageVersionRevision(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pv, _ := resp["packageVersion"].(map[string]any) assert.NotEmpty(t, pv["revision"]) } @@ -244,7 +245,7 @@ func TestHandler_SuccessfulVersions(t *testing.T) { // deserializers.go's ...SuccessfulPackageVersionInfoMap/ // ...PackageVersionErrorMap. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) successList, _ := resp["successfulVersions"].(map[string]any) require.Len(t, successList, 1) @@ -279,7 +280,7 @@ func TestHandler_SuccessfulVersions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // "Copied" is not a real PackageVersionStatus enum value (real values: // Published/Unfinished/Unlisted/Archived/Disposed/Deleted) -- the copied @@ -309,7 +310,7 @@ func TestHandler_PackageVersionMap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pv, _ := resp["packageVersion"].(map[string]any) publishedTime, _ := pv["publishedTime"].(float64) @@ -340,7 +341,7 @@ func TestHandler_DisposePackageVersions_StatusChange(t *testing.T) { // aws-sdk-go-v2 deserializers.go's // ...SuccessfulPackageVersionInfoMap/...PackageVersionErrorMap. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) success, _ := resp["successfulVersions"].(map[string]any) entry, _ := success["1.0.0"].(map[string]any) assert.Equal(t, "Disposed", entry["status"]) @@ -358,7 +359,7 @@ func TestHandler_DisposePackageVersions_StatusChange(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) pv, _ := descResp["packageVersion"].(map[string]any) assert.Equal(t, "Disposed", pv["status"]) } @@ -386,7 +387,7 @@ func TestHandler_UpdatePackageVersionsStatus_StatusChange(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) pv, _ := descResp["packageVersion"].(map[string]any) assert.Equal(t, "Archived", pv["status"]) } @@ -408,7 +409,7 @@ func TestHandler_PackageVersionLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, pubRec.Code) var pubResp map[string]any - require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &pubResp)) + require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &pubResp, jsonx.V1())) assert.Equal(t, "1.0.0", pubResp["version"]) assert.Equal(t, "Published", pubResp["status"]) asset, _ := pubResp["asset"].(map[string]any) @@ -422,7 +423,7 @@ func TestHandler_PackageVersionLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) pv, _ := descResp["packageVersion"].(map[string]any) assert.Equal(t, "Published", pv["status"]) @@ -442,7 +443,7 @@ func TestHandler_PackageVersionLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec2.Code) var descResp2 map[string]any - require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2)) + require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2, jsonx.V1())) pv2, _ := descResp2["packageVersion"].(map[string]any) assert.Equal(t, "Archived", pv2["status"]) @@ -462,7 +463,7 @@ func TestHandler_PackageVersionLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec3.Code) var descResp3 map[string]any - require.NoError(t, json.Unmarshal(descRec3.Body.Bytes(), &descResp3)) + require.NoError(t, json.Unmarshal(descRec3.Body.Bytes(), &descResp3, jsonx.V1())) pv3, _ := descResp3["packageVersion"].(map[string]any) assert.Equal(t, "Disposed", pv3["status"]) @@ -482,7 +483,7 @@ func TestHandler_PackageVersionLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) versions, _ := listResp["versions"].([]any) assert.Empty(t, versions) } @@ -520,7 +521,7 @@ func TestHandler_CopyPackageVersions_ToSelf(t *testing.T) { ) require.Equal(t, http.StatusOK, copyRec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(copyRec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(copyRec2.Body.Bytes(), &resp, jsonx.V1())) failed, _ := resp["failedVersions"].(map[string]any) require.Len(t, failed, 1) entry, _ := failed["18.0.0"].(map[string]any) @@ -603,7 +604,7 @@ func TestHandler_DisposePackageVersions(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["successfulVersions"]) assert.NotNil(t, resp["failedVersions"]) } @@ -691,7 +692,7 @@ func TestHandler_UpdatePackageVersionsStatus(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["successfulVersions"]) assert.NotNil(t, resp["failedVersions"]) } @@ -715,7 +716,7 @@ func TestListPackageVersions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1, _ := out1["versions"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["nextToken"].(string) @@ -728,7 +729,7 @@ func TestListPackageVersions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2, _ := out2["versions"].([]any) assert.Len(t, page2, 2) } @@ -768,7 +769,7 @@ func TestPackageVersion_HasPackageName(t *testing.T) { Version string `json:"version"` } `json:"packageVersion"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.pkgName, out.PackageVersion.PackageName) assert.Equal(t, "1.0.0", out.PackageVersion.Version) }) diff --git a/services/codeartifact/handler_packages.go b/services/codeartifact/handler_packages.go index 43e6755026..b452d4e6c8 100644 --- a/services/codeartifact/handler_packages.go +++ b/services/codeartifact/handler_packages.go @@ -1,10 +1,12 @@ package codeartifact import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // packageToMap builds the types.PackageDescription shape used by @@ -188,7 +190,7 @@ func (h *Handler) handlePutPackageOriginConfiguration( var in putPackageOriginConfigurationBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } diff --git a/services/codeartifact/handler_packages_test.go b/services/codeartifact/handler_packages_test.go index f68167d6f6..01f711a220 100644 --- a/services/codeartifact/handler_packages_test.go +++ b/services/codeartifact/handler_packages_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -81,7 +82,7 @@ func TestHandler_DescribePackage(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkg, _ := resp["package"].(map[string]any) assert.Equal(t, "npm", pkg["format"]) assert.Equal(t, "my-pkg", pkg["name"]) @@ -110,7 +111,7 @@ func TestHandler_DeletePackage(t *testing.T) { assert.Equal(t, http.StatusOK, delRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["deletedPackage"]) // Confirm deletion: a second delete should return 404 since the package no longer exists. @@ -144,7 +145,7 @@ func TestHandler_PackageMap(t *testing.T) { // declare only format/name/namespace/originConfiguration); "format" and // "name" are the ones actually on the real shape. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkg, _ := resp["package"].(map[string]any) assert.Equal(t, "npm", pkg["format"]) assert.Equal(t, "mypkg", pkg["name"]) @@ -179,7 +180,7 @@ func TestHandler_MultiFormatPackages(t *testing.T) { allRec := doRequest(t, h, http.MethodPost, "/v1/packages?domain=fmt-multi-domain&repository=fmt-multi-repo", nil) require.Equal(t, http.StatusOK, allRec.Code) var allResp map[string]any - require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &allResp)) + require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &allResp, jsonx.V1())) allPkgs, _ := allResp["packages"].([]any) assert.Len(t, allPkgs, 4) @@ -193,7 +194,7 @@ func TestHandler_MultiFormatPackages(t *testing.T) { ) require.Equal(t, http.StatusOK, npmRec.Code) var npmResp map[string]any - require.NoError(t, json.Unmarshal(npmRec.Body.Bytes(), &npmResp)) + require.NoError(t, json.Unmarshal(npmRec.Body.Bytes(), &npmResp, jsonx.V1())) npmPkgs, _ := npmResp["packages"].([]any) assert.Len(t, npmPkgs, 2) @@ -207,7 +208,7 @@ func TestHandler_MultiFormatPackages(t *testing.T) { ) require.Equal(t, http.StatusOK, pypiRec.Code) var pypiResp map[string]any - require.NoError(t, json.Unmarshal(pypiRec.Body.Bytes(), &pypiResp)) + require.NoError(t, json.Unmarshal(pypiRec.Body.Bytes(), &pypiResp, jsonx.V1())) pypiPkgs, _ := pypiResp["packages"].([]any) assert.Len(t, pypiPkgs, 1) } @@ -311,7 +312,7 @@ func TestHandler_ListPackages(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pkgs, _ := resp["packages"].([]any) assert.Len(t, pkgs, tt.wantCount) } @@ -383,7 +384,7 @@ func TestHandler_PutPackageOriginConfiguration(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) originConfig, _ := resp["originConfiguration"].(map[string]any) require.NotNil(t, originConfig) restrictions, _ := originConfig["restrictions"].(map[string]any) @@ -410,7 +411,7 @@ func TestListPackages_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1, _ := out1["packages"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["nextToken"].(string) @@ -421,7 +422,7 @@ func TestListPackages_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2, _ := out2["packages"].([]any) assert.Len(t, page2, 2) } diff --git a/services/codeartifact/handler_repositories.go b/services/codeartifact/handler_repositories.go index 89509b049d..6d96591bba 100644 --- a/services/codeartifact/handler_repositories.go +++ b/services/codeartifact/handler_repositories.go @@ -1,11 +1,13 @@ package codeartifact import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type upstreamRepoEntry struct { @@ -70,7 +72,7 @@ func (h *Handler) handleCreateRepository(c *echo.Context, domainName, repoName s var in createRepositoryBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -316,7 +318,7 @@ func (h *Handler) handlePutRepositoryPermissionsPolicy( var in putRepositoryPermissionsPolicyBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -408,7 +410,7 @@ func (h *Handler) handleUpdateRepository(c *echo.Context, domainName, repoName s var in updateRepositoryBody if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } var upstreams []string diff --git a/services/codeartifact/handler_repositories_test.go b/services/codeartifact/handler_repositories_test.go index 3adf1efd76..fb75713afd 100644 --- a/services/codeartifact/handler_repositories_test.go +++ b/services/codeartifact/handler_repositories_test.go @@ -1,7 +1,7 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -75,7 +76,7 @@ func TestHandler_CreateRepository(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) assert.Equal(t, tt.repo, repo["name"]) assert.Equal(t, tt.domain, repo["domainName"]) @@ -96,7 +97,7 @@ func TestHandler_DescribeRepository(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) assert.Equal(t, "r1", repo["name"]) assert.Equal(t, "d1", repo["domainName"]) @@ -128,7 +129,7 @@ func TestHandler_ListRepositoriesInDomain(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, _ := resp["repositories"].([]any) assert.Len(t, repos, 2) } @@ -146,7 +147,7 @@ func TestHandler_ListRepositories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, _ := resp["repositories"].([]any) assert.Len(t, repos, 2) } @@ -168,7 +169,7 @@ func TestHandler_GetRepositoryEndpoint(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["repositoryEndpoint"]) } @@ -243,7 +244,7 @@ func TestHandler_AssociateExternalConnection(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["repository"]) } }) @@ -280,7 +281,7 @@ func TestHandler_RepositoryPermissionsPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) pol, _ := putResp["policy"].(map[string]any) assert.NotEmpty(t, pol["revision"]) assert.NotEmpty(t, pol["resourceArn"]) @@ -349,7 +350,7 @@ func TestHandler_RepositoryPermissionsPolicy_RevisionLocking(t *testing.T) { ) require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) pol, _ := putResp["policy"].(map[string]any) revision, _ := pol["revision"].(string) require.NotEmpty(t, revision) @@ -380,7 +381,7 @@ func TestHandler_RepositoryPermissionsPolicy_RevisionLocking(t *testing.T) { ) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) getPol, _ := getResp["policy"].(map[string]any) assert.NotContains(t, getPol["document"], "Deny") @@ -448,7 +449,7 @@ func TestHandler_ExternalConnectionFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) conns, _ := repo["externalConnections"].([]any) require.Len(t, conns, 1) @@ -485,7 +486,7 @@ func TestHandler_UpdateRepository_DescriptionPersists(t *testing.T) { descRec := doRequest(t, h, http.MethodGet, "/v1/repository?domain=ur-desc-domain&repository=ur-desc-repo", nil) require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) assert.Equal(t, "updated", repo["description"]) } @@ -517,7 +518,7 @@ func TestHandler_ExternalConnections_MultipleConnections(t *testing.T) { ) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) repo, _ := descResp["repository"].(map[string]any) conns, _ := repo["externalConnections"].([]any) assert.Len(t, conns, 3) @@ -533,7 +534,7 @@ func TestHandler_ExternalConnections_MultipleConnections(t *testing.T) { ) require.Equal(t, http.StatusOK, disRec.Code) var disResp map[string]any - require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp)) + require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp, jsonx.V1())) disRepo, _ := disResp["repository"].(map[string]any) disConns, _ := disRepo["externalConnections"].([]any) assert.Len(t, disConns, 2) @@ -613,7 +614,7 @@ func TestHandler_DisassociateExternalConnection(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) assert.NotNil(t, repo) } @@ -684,7 +685,7 @@ func TestHandler_UpdateRepository(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, _ := resp["repository"].(map[string]any) assert.NotNil(t, repo) } @@ -706,7 +707,7 @@ func TestListRepositoriesInDomain_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) page1, _ := out1["repositories"].([]any) assert.Len(t, page1, 2) nextToken, ok := out1["nextToken"].(string) @@ -717,7 +718,7 @@ func TestListRepositoriesInDomain_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) page2, _ := out2["repositories"].([]any) assert.Len(t, page2, 2) } @@ -741,7 +742,7 @@ func TestCreateRepository_UpstreamRepositories(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) repo, _ := out["repository"].(map[string]any) upstreams, _ := repo["upstreams"].([]any) require.Len(t, upstreams, 1) @@ -770,7 +771,7 @@ func TestUpdateRepository_UpstreamRepositories(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) repo, _ := out["repository"].(map[string]any) upstreams, _ := repo["upstreams"].([]any) require.Len(t, upstreams, 1) diff --git a/services/codeartifact/handler_tags.go b/services/codeartifact/handler_tags.go index 0f0505673d..6222fad6c4 100644 --- a/services/codeartifact/handler_tags.go +++ b/services/codeartifact/handler_tags.go @@ -1,12 +1,14 @@ package codeartifact import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceBody struct { @@ -46,7 +48,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body [] } var in tagResourceBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } @@ -63,7 +65,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, resourceARN string, body } var in untagResourceBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } diff --git a/services/codeartifact/handler_tags_test.go b/services/codeartifact/handler_tags_test.go index e4426b11e3..b0457742dc 100644 --- a/services/codeartifact/handler_tags_test.go +++ b/services/codeartifact/handler_tags_test.go @@ -1,12 +1,14 @@ package codeartifact_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagsForDomain(t *testing.T) { @@ -21,7 +23,7 @@ func TestHandler_TagsForDomain(t *testing.T) { assert.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) domainMap, _ := createResp["domain"].(map[string]any) domainARN := domainMap["arn"].(string) @@ -30,7 +32,7 @@ func TestHandler_TagsForDomain(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagList, _ := listResp["tags"].([]any) assert.Len(t, tagList, 1) @@ -45,7 +47,7 @@ func TestHandler_TagsForDomain(t *testing.T) { assert.Equal(t, http.StatusOK, listRec2.Code) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2, jsonx.V1())) tagList2, _ := listResp2["tags"].([]any) assert.Len(t, tagList2, 2) @@ -60,7 +62,7 @@ func TestHandler_TagsForDomain(t *testing.T) { assert.Equal(t, http.StatusOK, listRec3.Code) var listResp3 map[string]any - require.NoError(t, json.Unmarshal(listRec3.Body.Bytes(), &listResp3)) + require.NoError(t, json.Unmarshal(listRec3.Body.Bytes(), &listResp3, jsonx.V1())) tagList3, _ := listResp3["tags"].([]any) assert.Len(t, tagList3, 1) } @@ -79,7 +81,7 @@ func TestHandler_SortedTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) domainMap, _ := createResp["domain"].(map[string]any) domainARN, _ := domainMap["arn"].(string) @@ -87,7 +89,7 @@ func TestHandler_SortedTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagList, _ := listResp["tags"].([]any) require.Len(t, tagList, 3) diff --git a/services/codeartifact/handler_test.go b/services/codeartifact/handler_test.go index d0aa8400bb..94c6ff3338 100644 --- a/services/codeartifact/handler_test.go +++ b/services/codeartifact/handler_test.go @@ -5,7 +5,7 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codeartifact" ) @@ -33,7 +34,7 @@ func doRequest(t *testing.T, h *codeartifact.Handler, method, path string, body var bodyReader io.Reader if body != nil { - data, err := json.Marshal(body) + data, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(data) } @@ -684,7 +685,7 @@ func TestHandler_SortedOutput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) domains, _ := resp["domains"].([]any) require.Len(t, domains, 3) @@ -709,7 +710,7 @@ func TestHandler_SortedOutput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, _ := resp["repositories"].([]any) require.Len(t, repos, 3) diff --git a/services/codeartifact/package_versions.go b/services/codeartifact/package_versions.go index db9fe4cf3f..2ce7bfa15b 100644 --- a/services/codeartifact/package_versions.go +++ b/services/codeartifact/package_versions.go @@ -2,13 +2,16 @@ package codeartifact import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "sort" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Package version methods --- @@ -372,20 +375,20 @@ type npmPackageJSON struct { Readme string `json:"readme"` Description string `json:"description"` Homepage string `json:"homepage"` - Repository json.RawMessage `json:"repository"` - License json.RawMessage `json:"license"` + Repository jsontext.Value `json:"repository"` + License jsontext.Value `json:"license"` } // repositoryURL reads package.json's repository, a bare string or an object with a url. func (m *npmPackageJSON) repositoryURL() string { var str string - if json.Unmarshal(m.Repository, &str) == nil { + if json.Unmarshal(m.Repository, &str, jsonx.V1()) == nil { return str } var obj struct { URL string `json:"url"` } - if json.Unmarshal(m.Repository, &obj) == nil { + if json.Unmarshal(m.Repository, &obj, jsonx.V1()) == nil { return obj.URL } @@ -395,13 +398,13 @@ func (m *npmPackageJSON) repositoryURL() string { // licenseName reads package.json's license, a bare SPDX string or an object with a type. func (m *npmPackageJSON) licenseName() string { var str string - if json.Unmarshal(m.License, &str) == nil { + if json.Unmarshal(m.License, &str, jsonx.V1()) == nil { return str } var obj struct { Type string `json:"type"` } - if json.Unmarshal(m.License, &obj) == nil { + if json.Unmarshal(m.License, &obj, jsonx.V1()) == nil { return obj.Type } @@ -417,7 +420,7 @@ func findPackageJSONMetadata(assets []AssetInfo) *npmPackageJSON { } var meta npmPackageJSON - if err := json.Unmarshal(a.Content, &meta); err != nil { + if err := json.Unmarshal(a.Content, &meta, jsonx.V1()); err != nil { return nil } diff --git a/services/codeartifact/persistence.go b/services/codeartifact/persistence.go index a87720a84b..c78c4fd404 100644 --- a/services/codeartifact/persistence.go +++ b/services/codeartifact/persistence.go @@ -2,7 +2,7 @@ package codeartifact import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -103,7 +103,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // value, []ExternalConnection, has no identity of its own -- see // store_setup.go) and is persisted here directly, as before. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ExternalConnections map[string]map[string][]ExternalConnection `json:"externalConnections"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -235,7 +235,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // store_setup.go's registerAllTables doc) from tables via the ephemeral DTO // registry, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("codeartifact: restore snapshot DTO tables: %w", err) diff --git a/services/codebuild/build_batches_test.go b/services/codebuild/build_batches_test.go index 1e86b446af..245d044b74 100644 --- a/services/codebuild/build_batches_test.go +++ b/services/codebuild/build_batches_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCodeBuild_BuildBatch covers RetryBuildBatch, StopBuildBatch, ListBuildBatchesForProject. @@ -27,7 +30,7 @@ func TestCodeBuild_BuildBatch(t *testing.T) { ID string `json:"id"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) batchID := startOut.BuildBatch.ID stopRec := doRequest(t, h, "StopBuildBatch", map[string]any{"id": batchID}) @@ -38,7 +41,7 @@ func TestCodeBuild_BuildBatch(t *testing.T) { BuildBatchStatus string `json:"buildBatchStatus"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&stopOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &stopOut, jsonx.V1())) assert.Equal(t, "STOPPED", stopOut.BuildBatch.BuildBatchStatus) }) @@ -64,7 +67,7 @@ func TestCodeBuild_BuildBatch(t *testing.T) { ID string `json:"id"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) batchID := startOut.BuildBatch.ID require.Equal(t, http.StatusOK, doRequest(t, h, "StopBuildBatch", map[string]any{"id": batchID}).Code) @@ -78,7 +81,7 @@ func TestCodeBuild_BuildBatch(t *testing.T) { ProjectName string `json:"projectName"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(retryRec.Body).Decode(&retryOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(retryRec.Body), &retryOut, jsonx.V1())) assert.NotEqual(t, batchID, retryOut.BuildBatch.ID) assert.Equal(t, "IN_PROGRESS", retryOut.BuildBatch.BuildBatchStatus) assert.Equal(t, "batch-retry-proj", retryOut.BuildBatch.ProjectName) @@ -110,7 +113,7 @@ func TestCodeBuild_BuildBatch(t *testing.T) { var out struct { IDs []string `json:"ids"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.IDs, 2) }) @@ -166,7 +169,7 @@ func TestHandler_DeleteBuildBatch_RemovesBatch(t *testing.T) { ID string `json:"id"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) batchID = startOut.BuildBatch.ID } else { batchID = "ghost-proj:ghost-batch-id" @@ -187,7 +190,7 @@ func TestHandler_DeleteBuildBatch_RemovesBatch(t *testing.T) { var listOut struct { IDs []string `json:"ids"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.NotContains(t, listOut.IDs, batchID, "batch should be removed after delete") } }) @@ -226,7 +229,7 @@ func TestHandler_StartBuildBatch_SetsInProgress(t *testing.T) { StartTime float64 `json:"startTime"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out.BuildBatch.BuildBatchStatus) if tt.wantStartTimeSet { assert.Greater(t, out.BuildBatch.StartTime, float64(0)) @@ -266,7 +269,7 @@ func TestHandler_StopBuildBatch_SetsEndTime(t *testing.T) { ID string `json:"id"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) stopRec := doRequest(t, h, "StopBuildBatch", map[string]any{"id": startOut.BuildBatch.ID}) require.Equal(t, http.StatusOK, stopRec.Code) @@ -277,7 +280,7 @@ func TestHandler_StopBuildBatch_SetsEndTime(t *testing.T) { EndTime float64 `json:"endTime"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out.BuildBatch.BuildBatchStatus) if tt.wantEndTimeSet { assert.Greater(t, out.BuildBatch.EndTime, float64(0)) @@ -300,7 +303,7 @@ func TestHandler_StartBuildBatch_ArnSet(t *testing.T) { var out struct { BuildBatch map[string]any `json:"buildBatch"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) batchArn, _ := out.BuildBatch["arn"].(string) assert.NotEmpty(t, batchArn, "StartBuildBatch must return a non-empty arn") assert.Contains(t, batchArn, "arn:aws:codebuild", "arn must be a valid ARN format") @@ -319,7 +322,7 @@ func TestHandler_RetryBuildBatch_ArnSet(t *testing.T) { var startOut struct { BuildBatch map[string]any `json:"buildBatch"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) batchID, _ := startOut.BuildBatch["id"].(string) require.NotEmpty(t, batchID) require.Equal(t, http.StatusOK, doRequest(t, h, "StopBuildBatch", map[string]any{"id": batchID}).Code) @@ -330,7 +333,7 @@ func TestHandler_RetryBuildBatch_ArnSet(t *testing.T) { var retryOut struct { BuildBatch map[string]any `json:"buildBatch"` } - require.NoError(t, json.Unmarshal(retryRec.Body.Bytes(), &retryOut)) + require.NoError(t, json.Unmarshal(retryRec.Body.Bytes(), &retryOut, jsonx.V1())) arn, _ := retryOut.BuildBatch["arn"].(string) assert.NotEmpty(t, arn, "RetryBuildBatch must return a non-empty arn") } diff --git a/services/codebuild/builds_semantics_test.go b/services/codebuild/builds_semantics_test.go index 50d4302e5c..c95ed63638 100644 --- a/services/codebuild/builds_semantics_test.go +++ b/services/codebuild/builds_semantics_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_RetryBuild_InheritsFields verifies RetryBuild inherits environment/source/serviceRole @@ -31,7 +34,7 @@ func TestHandler_RetryBuild_InheritsFields(t *testing.T) { var startOut struct { Build map[string]any `json:"build"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) buildID, _ := startOut.Build["id"].(string) require.NotEmpty(t, buildID) @@ -41,7 +44,7 @@ func TestHandler_RetryBuild_InheritsFields(t *testing.T) { var retryOut struct { Build map[string]any `json:"build"` } - require.NoError(t, json.Unmarshal(retryRec.Body.Bytes(), &retryOut)) + require.NoError(t, json.Unmarshal(retryRec.Body.Bytes(), &retryOut, jsonx.V1())) b := retryOut.Build assert.Equal(t, "arn:aws:iam::000000000000:role/my-role", b["serviceRole"], @@ -64,7 +67,7 @@ func TestHandler_BatchGetBuilds_ARNLookup(t *testing.T) { var startOut struct { Build map[string]any `json:"build"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) buildArn, _ := startOut.Build["arn"].(string) require.NotEmpty(t, buildArn) @@ -75,7 +78,7 @@ func TestHandler_BatchGetBuilds_ARNLookup(t *testing.T) { Builds []any `json:"builds"` BuildsNotFound []string `json:"buildsNotFound"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Len(t, getOut.Builds, 1, "BatchGetBuilds must find build by ARN") assert.Empty(t, getOut.BuildsNotFound, "ARN lookup must not produce buildsNotFound") } @@ -108,7 +111,7 @@ func TestHandler_StartBuild_OverrideFields(t *testing.T) { var out struct { Build map[string]any `json:"build"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) b := out.Build assert.Equal(t, "arn:aws:iam::000000000000:role/override-role", b["serviceRole"], @@ -190,7 +193,7 @@ func TestHandler_StartBuild_InheritsProjectFields(t *testing.T) { Phases []map[string]any `json:"phases"` } `json:"build"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantServiceRole, out.Build.ServiceRole) assert.Equal(t, "GITHUB", out.Build.Source.Type) assert.Len(t, out.Build.Environment.EnvironmentVariables, 1) @@ -233,7 +236,7 @@ func TestHandler_StartBuild_InitialPhase(t *testing.T) { } `json:"phases"` } `json:"build"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &out, jsonx.V1())) if tt.wantPhasesNonEmpty { require.NotEmpty(t, out.Build.Phases) assert.Equal(t, tt.wantInitialPhase, out.Build.Phases[0].PhaseType) @@ -351,7 +354,7 @@ func TestHandler_StartBuild_EnvVarOverrideMerge(t *testing.T) { } `json:"environment"` } `json:"build"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) envVars := out.Build.Environment.EnvironmentVariables assert.Len(t, envVars, tt.wantEnvCount) diff --git a/services/codebuild/builds_test.go b/services/codebuild/builds_test.go index 0bf78f2557..37fa1917e6 100644 --- a/services/codebuild/builds_test.go +++ b/services/codebuild/builds_test.go @@ -1,13 +1,16 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "sort" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_StartBuild(t *testing.T) { @@ -64,7 +67,7 @@ func TestHandler_StartBuild(t *testing.T) { BuildStatus string `json:"buildStatus"` } `json:"build"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Build.ID) assert.Equal(t, "IN_PROGRESS", out.Build.BuildStatus) } @@ -94,7 +97,7 @@ func TestHandler_StartBuild_TimestampsAreNumbers(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) build, ok := startOut["build"].(map[string]any) require.True(t, ok, "response should contain 'build' object") @@ -109,7 +112,7 @@ func TestHandler_StartBuild_TimestampsAreNumbers(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopOut map[string]any - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&stopOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &stopOut, jsonx.V1())) stoppedBuild, ok := stopOut["build"].(map[string]any) require.True(t, ok, "stop response should contain 'build' object") @@ -170,7 +173,7 @@ func TestHandler_BatchGetBuilds(t *testing.T) { ID string `json:"id"` } `json:"build"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) buildID = startOut.Build.ID } else { buildID = "nonexistent:build123" @@ -185,7 +188,7 @@ func TestHandler_BatchGetBuilds(t *testing.T) { Builds []any `json:"builds"` BuildsNotFound []string `json:"buildsNotFound"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Builds, tt.wantBuildCount) assert.Equal(t, tt.wantNotFound, out.BuildsNotFound) }) @@ -242,7 +245,7 @@ func TestHandler_StopBuild(t *testing.T) { ID string `json:"id"` } `json:"build"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) buildID = startOut.Build.ID } else { buildID = "nonexistent:build999" @@ -257,7 +260,7 @@ func TestHandler_StopBuild(t *testing.T) { BuildStatus string `json:"buildStatus"` } `json:"build"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "STOPPED", out.Build.BuildStatus) } }) @@ -297,7 +300,7 @@ func TestHandler_StopBuild_SetsStoppedNotSucceeded(t *testing.T) { ID string `json:"id"` } `json:"build"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) stopRec := doRequest(t, h, "StopBuild", map[string]any{"id": startOut.Build.ID}) require.Equal(t, http.StatusOK, stopRec.Code) @@ -310,7 +313,7 @@ func TestHandler_StopBuild_SetsStoppedNotSucceeded(t *testing.T) { EndTime float64 `json:"endTime"` } `json:"build"` } - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantBuildStatus, out.Build.BuildStatus) assert.Equal(t, tt.wantCurrentPhase, out.Build.CurrentPhase) assert.Equal(t, tt.wantBuildComplete, out.Build.BuildComplete) @@ -376,7 +379,7 @@ func TestHandler_ListBuildsForProject(t *testing.T) { var out struct { IDs []string `json:"ids"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.IDs, tt.buildCount) } }) @@ -470,7 +473,7 @@ func TestHandler_BatchDeleteBuilds(t *testing.T) { "projectName": "my-project", }) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) build := startResp["build"].(map[string]any) buildID = build["id"].(string) tt.buildIDs = []string{buildID} @@ -482,7 +485,7 @@ func TestHandler_BatchDeleteBuilds(t *testing.T) { assert.Equal(t, tt.wantHTTP, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deleted := resp["buildsDeleted"].([]any) assert.Len(t, deleted, tt.wantDeleted) }) @@ -505,7 +508,7 @@ func TestHandler_BatchDeleteBuilds_NotDeletedList(t *testing.T) { BuildsDeleted []string `json:"buildsDeleted"` BuildsNotDeleted []map[string]any `json:"buildsNotDeleted"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.BuildsDeleted, "no builds deleted when IDs do not exist") assert.Len(t, out.BuildsNotDeleted, 2, "both missing IDs must appear in buildsNotDeleted") @@ -539,7 +542,7 @@ func TestHandler_ListBuilds(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids := resp["ids"].([]any) assert.Len(t, ids, 2) } @@ -573,7 +576,7 @@ func TestHandler_SortedBuilds(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) ids, _ := out["ids"].([]any) require.Len(t, ids, 3) @@ -627,7 +630,7 @@ func TestHandler_RetryBuild(t *testing.T) { if id == "" { startRec := doRequest(t, h, "StartBuild", map[string]any{"projectName": "proj"}) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) build := startResp["build"].(map[string]any) id = build["id"].(string) } diff --git a/services/codebuild/command_executions_test.go b/services/codebuild/command_executions_test.go index 62aefd9470..c9fb9e59b2 100644 --- a/services/codebuild/command_executions_test.go +++ b/services/codebuild/command_executions_test.go @@ -1,7 +1,8 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "sort" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -70,7 +72,7 @@ func TestHandler_BatchGetCommandExecutions(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) executions, _ := out["commandExecutions"].([]any) assert.Len(t, executions, tt.wantFound) @@ -121,7 +123,7 @@ func TestHandler_StartCommandExecution_TypeStored(t *testing.T) { ID string `json:"id"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(sbRec.Body).Decode(&sbOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(sbRec.Body), &sbOut, jsonx.V1())) execRec := doRequest(t, h, "StartCommandExecution", map[string]any{ "sandboxId": sbOut.Sandbox.ID, @@ -139,7 +141,7 @@ func TestHandler_StartCommandExecution_TypeStored(t *testing.T) { EndTime float64 `json:"endTime"` } `json:"commandExecution"` } - require.NoError(t, json.NewDecoder(execRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(execRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out.CommandExecution.Type) assert.Equal(t, tt.command, out.CommandExecution.Command) assert.Equal(t, "SUCCEEDED", out.CommandExecution.Status) @@ -167,7 +169,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { ID string `json:"id"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) sandboxID := startOut.Sandbox.ID doRequest(t, h, "StartCommandExecution", map[string]any{ @@ -189,7 +191,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { var out struct { CommandExecutions []map[string]any `json:"commandExecutions"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.CommandExecutions, 2) }) @@ -222,7 +224,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { ID string `json:"id"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) sandboxID := startOut.Sandbox.ID ids := make([]string, 0, 3) @@ -240,7 +242,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { ID string `json:"id"` } `json:"commandExecution"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) ids = append(ids, out.CommandExecution.ID) } @@ -258,7 +260,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { NextToken string `json:"nextToken"` CommandExecutions []map[string]any `json:"commandExecutions"` } - require.NoError(t, json.NewDecoder(firstPage.Body).Decode(&firstOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(firstPage.Body), &firstOut, jsonx.V1())) require.Len(t, firstOut.CommandExecutions, 2) assert.Equal( t, @@ -280,7 +282,7 @@ func TestCodeBuild_CommandExecutionsForSandbox(t *testing.T) { var secondOut struct { CommandExecutions []map[string]any `json:"commandExecutions"` } - require.NoError(t, json.NewDecoder(secondPage.Body).Decode(&secondOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(secondPage.Body), &secondOut, jsonx.V1())) require.Len(t, secondOut.CommandExecutions, 1) assert.Equal(t, sortedAsc[0], secondOut.CommandExecutions[0]["id"], "the remainder must be the smallest ID") }) diff --git a/services/codebuild/curated_environments_test.go b/services/codebuild/curated_environments_test.go index a301260ad4..f457487e9d 100644 --- a/services/codebuild/curated_environments_test.go +++ b/services/codebuild/curated_environments_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCodeBuild_CuratedEnvironmentImages verifies ListCuratedEnvironmentImages returns @@ -21,7 +24,7 @@ func TestCodeBuild_CuratedEnvironmentImages(t *testing.T) { var out struct { Platforms []map[string]any `json:"platforms"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.Platforms) assert.Equal(t, "UBUNTU", out.Platforms[0]["platform"]) } diff --git a/services/codebuild/engine_env.go b/services/codebuild/engine_env.go index 74f195c96d..c4287e52eb 100644 --- a/services/codebuild/engine_env.go +++ b/services/codebuild/engine_env.go @@ -2,11 +2,13 @@ package codebuild import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errEnvResolve = errors.New("cannot resolve environment variable") @@ -65,7 +67,7 @@ func (r *buildRunner) resolveSecret(ctx context.Context, ref string) (string, er } var obj map[string]any - if jerr := json.Unmarshal([]byte(val), &obj); jerr != nil { + if jerr := json.Unmarshal([]byte(val), &obj, jsonx.V1()); jerr != nil { return "", fmt.Errorf("%w: secret %s is not JSON: %w", errEnvResolve, id, jerr) } diff --git a/services/codebuild/fleets_test.go b/services/codebuild/fleets_test.go index 7442a5027e..0f8eb316b4 100644 --- a/services/codebuild/fleets_test.go +++ b/services/codebuild/fleets_test.go @@ -1,13 +1,16 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateFleet(t *testing.T) { @@ -115,7 +118,7 @@ func TestHandler_BatchGetFleets(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) fleets, _ := out["fleets"].([]any) assert.Len(t, fleets, tt.wantFound) @@ -146,7 +149,7 @@ func TestCodeBuild_Fleet(t *testing.T) { BaseCapacity int `json:"baseCapacity"` } `json:"fleet"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) fleetArn := createOut.Fleet.Arn updRec := doRequest(t, h, "UpdateFleet", map[string]any{ @@ -160,7 +163,7 @@ func TestCodeBuild_Fleet(t *testing.T) { BaseCapacity int `json:"baseCapacity"` } `json:"fleet"` } - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updOut, jsonx.V1())) assert.Equal(t, 5, updOut.Fleet.BaseCapacity) }) @@ -215,7 +218,7 @@ func TestHandler_CreateFleet_StatusSchema(t *testing.T) { BaseCapacity float64 `json:"baseCapacity"` } `json:"fleet"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, tt.wantBaseCapacity, out.Fleet.BaseCapacity, 0) assert.Equal(t, tt.wantStatusCode, out.Fleet.Status.StatusCode) }) @@ -258,7 +261,7 @@ func TestHandler_CreateFleet_ExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out fleetExtendedFields - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Fleet.ID) assert.Equal(t, "ON_DEMAND", out.Fleet.OverflowBehavior) assert.Equal(t, "aws/codebuild/standard:7.0", out.Fleet.ImageID) @@ -282,7 +285,7 @@ func TestHandler_UpdateFleet_ExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut fleetExtendedFields - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) updRec := doRequest(t, h, "UpdateFleet", map[string]any{ "arn": createOut.Fleet.Arn, @@ -294,7 +297,7 @@ func TestHandler_UpdateFleet_ExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var out fleetExtendedFields - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &out, jsonx.V1())) assert.Equal(t, createOut.Fleet.ID, out.Fleet.ID, "id must not change across an update") assert.Equal(t, "QUEUE", out.Fleet.OverflowBehavior) assert.Equal(t, "aws/codebuild/standard:6.0", out.Fleet.ImageID) @@ -498,7 +501,7 @@ func TestHandler_Fleet_NestedConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut fleetNestedConfig - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) out := createOut if tt.updateBody != nil { @@ -509,7 +512,7 @@ func TestHandler_Fleet_NestedConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updOut fleetNestedConfig - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updOut, jsonx.V1())) out = updOut } @@ -566,7 +569,7 @@ func TestHandler_DeleteFleet_RemovesFleet(t *testing.T) { Arn string `json:"arn"` } `json:"fleet"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) fleetArn = createOut.Fleet.Arn } else { fleetArn = tt.deleteArn @@ -582,7 +585,7 @@ func TestHandler_DeleteFleet_RemovesFleet(t *testing.T) { var listOut struct { Fleets []string `json:"fleets"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Empty(t, listOut.Fleets, "fleet should be removed from list after delete") } }) diff --git a/services/codebuild/handler.go b/services/codebuild/handler.go index 91db4fbd44..538213da2e 100644 --- a/services/codebuild/handler.go +++ b/services/codebuild/handler.go @@ -2,7 +2,7 @@ package codebuild import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -268,18 +269,16 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError respond := func(errType string) error { payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: strings.TrimPrefix(err.Error(), errType+": "), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) } @@ -298,7 +297,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err // (all but the parameterless ListCuratedEnvironmentImages, which never // raises errInvalidRequest), so it is a safe blanket fallback here. case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return respond("InvalidInputException") default: // codebuild@v1.72.4's types/errors.go declares no internal-server/ diff --git a/services/codebuild/handler_test.go b/services/codebuild/handler_test.go index 570d69e400..2a68019561 100644 --- a/services/codebuild/handler_test.go +++ b/services/codebuild/handler_test.go @@ -2,7 +2,8 @@ package codebuild_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -32,7 +34,7 @@ func doRequest(t *testing.T, h *codebuild.Handler, action string, body any) *htt var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -125,7 +127,7 @@ func projectARN(t *testing.T, h *codebuild.Handler, name string) string { Arn string `json:"arn"` } `json:"projects"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotEmpty(t, out.Projects) return out.Projects[0].Arn @@ -498,7 +500,7 @@ func TestHandler_Reset(t *testing.T) { listRec := doRequest(t, h, "ListProjects", nil) require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut["projects"], 1) // Reset. @@ -508,7 +510,7 @@ func TestHandler_Reset(t *testing.T) { listRec2 := doRequest(t, h, "ListProjects", nil) require.Equal(t, http.StatusOK, listRec2.Code) var listOut2 map[string]any - require.NoError(t, json.NewDecoder(listRec2.Body).Decode(&listOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec2.Body), &listOut2, jsonx.V1())) assert.Empty(t, listOut2["projects"]) } @@ -665,7 +667,7 @@ func TestHandler_ErrorTypeMapping(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) diff --git a/services/codebuild/multi_region_test.go b/services/codebuild/multi_region_test.go index ccf810d15e..885074aa91 100644 --- a/services/codebuild/multi_region_test.go +++ b/services/codebuild/multi_region_test.go @@ -2,7 +2,7 @@ package codebuild_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/codebuild/pagination_test.go b/services/codebuild/pagination_test.go index 8ef075d487..a7058fc47c 100644 --- a/services/codebuild/pagination_test.go +++ b/services/codebuild/pagination_test.go @@ -1,13 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -27,7 +29,7 @@ func TestHandler_ListProjects_SortOrderDescending(t *testing.T) { var out struct { Projects []string `json:"projects"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, []string{"sort-c", "sort-b", "sort-a"}, out.Projects) } @@ -70,7 +72,7 @@ func TestHandler_ListFleets_MaxResultsPagination(t *testing.T) { NextToken string `json:"nextToken"` Fleets []string `json:"fleets"` } - require.NoError(t, json.NewDecoder(firstRec.Body).Decode(&firstPage)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(firstRec.Body), &firstPage, jsonx.V1())) assert.Len(t, firstPage.Fleets, 2) require.NotEmpty(t, firstPage.NextToken, "a partial page must carry a nextToken") @@ -84,7 +86,7 @@ func TestHandler_ListFleets_MaxResultsPagination(t *testing.T) { NextToken string `json:"nextToken"` Fleets []string `json:"fleets"` } - require.NoError(t, json.NewDecoder(secondRec.Body).Decode(&secondPage)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(secondRec.Body), &secondPage, jsonx.V1())) assert.Len(t, secondPage.Fleets, 1) assert.Empty(t, secondPage.NextToken, "the final page must not carry a nextToken") @@ -110,7 +112,7 @@ func TestHandler_ListBuildBatches_FilterByStatus(t *testing.T) { ID string `json:"id"` } `json:"buildBatch"` } - require.NoError(t, json.NewDecoder(startRec1.Body).Decode(&started1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec1.Body), &started1, jsonx.V1())) stopRec := doRequest(t, h, "StopBuildBatch", map[string]any{"id": started1.BuildBatch.ID}) require.Equal(t, http.StatusOK, stopRec.Code) @@ -126,7 +128,7 @@ func TestHandler_ListBuildBatches_FilterByStatus(t *testing.T) { var out struct { IDs []string `json:"ids"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, []string{started1.BuildBatch.ID}, out.IDs) } @@ -165,7 +167,7 @@ func TestHandler_ListReports_FilterByStatus(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, []string{"arn:aws:codebuild:us-east-1:000000000000:report/filter-rg:bad"}, out.Reports) }) @@ -181,7 +183,7 @@ func TestHandler_ListReports_FilterByStatus(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, []string{"arn:aws:codebuild:us-east-1:000000000000:report/filter-rg:ok"}, out.Reports) }) } diff --git a/services/codebuild/persistence.go b/services/codebuild/persistence.go index 204efca8b8..7cc3e75606 100644 --- a/services/codebuild/persistence.go +++ b/services/codebuild/persistence.go @@ -2,7 +2,7 @@ package codebuild import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -30,12 +30,12 @@ const codebuildSnapshotVersion = 2 // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - ResourcePolicies map[string]string `json:"resourcePolicies"` - BuildBatchNumbers map[string]int64 `json:"buildBatchNumbers"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + ResourcePolicies map[string]string `json:"resourcePolicies"` + BuildBatchNumbers map[string]int64 `json:"buildBatchNumbers"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/codebuild/phase_duration_internal_test.go b/services/codebuild/phase_duration_internal_test.go index 0bb0b204dc..08a6cd22c5 100644 --- a/services/codebuild/phase_duration_internal_test.go +++ b/services/codebuild/phase_duration_internal_test.go @@ -1,12 +1,14 @@ package codebuild import ( - "encoding/json" + "encoding/json/v2" "regexp" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRecordSuccessfulPhasesDurationsAreWholeSeconds(t *testing.T) { @@ -31,7 +33,7 @@ func TestRecordSuccessfulPhasesDurationsAreWholeSeconds(t *testing.T) { recordSuccessfulPhases(build, build.StartTime+tt.elapsed) for _, p := range build.Phases { - raw, err := json.Marshal(p) + raw, err := json.Marshal(p, jsonx.V1()) require.NoError(t, err) assert.NotRegexp(t, `"durationInSeconds":\d*\.`, string(raw)) diff --git a/services/codebuild/projects_schema_test.go b/services/codebuild/projects_schema_test.go index fad71fbfc6..5dfe4c1871 100644 --- a/services/codebuild/projects_schema_test.go +++ b/services/codebuild/projects_schema_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_CreateProject_SourceSchema tests the expanded source schema. @@ -82,7 +85,7 @@ func TestHandler_CreateProject_SourceSchema(t *testing.T) { } `json:"source"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantLocation, out.Project.Source.Location) assert.Equal(t, tt.wantBuildspec, out.Project.Source.Buildspec) assert.Equal(t, tt.wantCloneDepth, out.Project.Source.GitCloneDepth) @@ -157,7 +160,7 @@ func TestHandler_CreateProject_ArtifactsSchema(t *testing.T) { } `json:"artifacts"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out.Project.Artifacts.Type) assert.Equal(t, tt.wantPath, out.Project.Artifacts.Path) assert.Equal(t, tt.wantNamespaceType, out.Project.Artifacts.NamespaceType) @@ -245,7 +248,7 @@ func TestHandler_CreateProject_EnvironmentSchema(t *testing.T) { } `json:"environment"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out.Project.Environment.Type) assert.Equal(t, tt.wantComputeType, out.Project.Environment.ComputeType) assert.Equal(t, tt.wantPrivilegedMode, out.Project.Environment.PrivilegedMode) @@ -317,7 +320,7 @@ func TestHandler_CreateProject_CacheSchema(t *testing.T) { } `json:"cache"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out.Project.Cache.Type) assert.Len(t, out.Project.Cache.Modes, tt.wantModeLen) }) @@ -393,7 +396,7 @@ func TestHandler_CreateProject_Timeouts(t *testing.T) { AutoRetryLimit float64 `json:"autoRetryLimit"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(tt.timeoutInMinutes), out.Project.TimeoutInMinutes, 0) assert.InDelta(t, float64(tt.queuedTimeoutInMinutes), out.Project.QueuedTimeoutInMinutes, 0) assert.InDelta(t, float64(tt.concurrentBuildLimit), out.Project.ConcurrentBuildLimit, 0) @@ -468,7 +471,7 @@ func TestHandler_CreateProject_SecondarySources(t *testing.T) { SecondarySourceVersions []map[string]any `json:"secondarySourceVersions"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Project.SecondarySources, tt.wantSecondaryCount) if tt.secondarySourceVersions != nil { assert.Len(t, out.Project.SecondarySourceVersions, len(tt.secondarySourceVersions)) @@ -524,7 +527,7 @@ func TestHandler_CreateProject_VpcConfig(t *testing.T) { } `json:"vpcConfig"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantVpcID, out.Project.VpcConfig.VpcID) }) } @@ -588,7 +591,7 @@ func TestHandler_UpdateProject_Tags(t *testing.T) { } `json:"tags"` } `json:"project"` } - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &out, jsonx.V1())) var gotVal string for _, tag := range out.Project.Tags { @@ -679,7 +682,7 @@ func TestHandler_CreateProject_LogsConfig(t *testing.T) { } `json:"logsConfig"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantCloudWatchStatus, out.Project.LogsConfig.CloudWatchLogs.Status) assert.Equal(t, tt.wantS3Status, out.Project.LogsConfig.S3Logs.Status) }) @@ -739,7 +742,7 @@ func TestHandler_CreateProject_BuildBatchConfig(t *testing.T) { } `json:"buildBatchConfig"` } `json:"project"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantServiceRole, out.Project.BuildBatchConfig.ServiceRole) assert.InDelta(t, tt.wantMaxBuilds, out.Project.BuildBatchConfig.Restrictions.MaximumBuildsAllowed, 0) }) diff --git a/services/codebuild/projects_test.go b/services/codebuild/projects_test.go index b94ff70da2..1beccbb196 100644 --- a/services/codebuild/projects_test.go +++ b/services/codebuild/projects_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateProject(t *testing.T) { @@ -87,7 +90,7 @@ func TestHandler_CreateProject_TimestampsAreNumbers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) project, ok := out["project"].(map[string]any) require.True(t, ok, "response should contain 'project' object") @@ -151,7 +154,7 @@ func TestHandler_BatchGetProjects(t *testing.T) { Projects []any `json:"projects"` ProjectsNotFound []string `json:"projectsNotFound"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Projects, tt.wantProjectCount) assert.Equal(t, tt.wantNotFound, out.ProjectsNotFound) }) @@ -236,7 +239,7 @@ func TestHandler_Project_SourceVersion(t *testing.T) { SourceVersion string `json:"sourceVersion"` } `json:"project"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) assert.Equal(t, "refs/heads/main", createOut.Project.SourceVersion) updateRec := doRequest(t, h, "UpdateProject", map[string]any{ @@ -250,7 +253,7 @@ func TestHandler_Project_SourceVersion(t *testing.T) { SourceVersion string `json:"sourceVersion"` } `json:"project"` } - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&updateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &updateOut, jsonx.V1())) assert.Equal(t, "pr/42", updateOut.Project.SourceVersion, "UpdateProject must overwrite sourceVersion") } @@ -347,7 +350,7 @@ func TestHandler_ListProjects(t *testing.T) { var out struct { Projects []string `json:"projects"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) for _, pn := range tt.projectNames { assert.Contains(t, out.Projects, pn) @@ -382,7 +385,7 @@ func TestHandler_SortedOutput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) projects, _ := out["projects"].([]any) require.Len(t, projects, 3) @@ -411,7 +414,7 @@ func TestHandler_UpdateProjectVisibility_PublicAlias(t *testing.T) { var createOut struct { Project map[string]any `json:"project"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) projectArn, _ := createOut.Project["arn"].(string) require.NotEmpty(t, projectArn) @@ -426,7 +429,7 @@ func TestHandler_UpdateProjectVisibility_PublicAlias(t *testing.T) { ProjectVisibility string `json:"projectVisibility"` PublicProjectAlias string `json:"publicProjectAlias"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "PUBLIC_READ", out.ProjectVisibility) assert.NotEmpty(t, out.PublicProjectAlias, "UpdateProjectVisibility with PUBLIC_READ must return publicProjectAlias") @@ -453,7 +456,7 @@ func TestCodeBuild_Project(t *testing.T) { ProjectArn string `json:"projectArn"` ProjectVisibility string `json:"projectVisibility"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, arn, out.ProjectArn) assert.Equal(t, "PUBLIC_READ", out.ProjectVisibility) }) @@ -509,6 +512,6 @@ func TestCodeBuild_ListSharedProjects(t *testing.T) { var out struct { Projects []string `json:"projects"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.Projects) } diff --git a/services/codebuild/report_formats.go b/services/codebuild/report_formats.go index 0e39fe2da2..5b61ac8d41 100644 --- a/services/codebuild/report_formats.go +++ b/services/codebuild/report_formats.go @@ -1,13 +1,16 @@ package codebuild import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "fmt" "sort" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -291,7 +294,7 @@ type cucumberFeature struct { func parseCucumber(data []byte, source string) ([]TestCase, error) { var features []cucumberFeature - if err := json.Unmarshal(data, &features); err != nil { + if err := json.Unmarshal(data, &features, jsonx.V1()); err != nil { return nil, fmt.Errorf("parse cucumber %s: %w", source, err) } @@ -513,9 +516,9 @@ type simpleCovFile struct { func parseSimpleCov(data []byte, source string) ([]CodeCoverage, error) { var doc map[string]struct { - Coverage map[string]json.RawMessage `json:"coverage"` + Coverage map[string]jsontext.Value `json:"coverage"` } - if err := json.Unmarshal(data, &doc); err != nil { + if err := json.Unmarshal(data, &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("parse simplecov %s: %w", source, err) } @@ -536,13 +539,13 @@ func parseSimpleCov(data []byte, source string) ([]CodeCoverage, error) { } // decodeSimpleCovFile accepts both the bare line array and the {lines, branches} object. -func decodeSimpleCovFile(raw json.RawMessage) (simpleCovFile, error) { +func decodeSimpleCovFile(raw jsontext.Value) (simpleCovFile, error) { var f simpleCovFile - if err := json.Unmarshal(raw, &f.Lines); err == nil { + if err := json.Unmarshal(raw, &f.Lines, jsonx.V1()); err == nil { return f, nil } - err := json.Unmarshal(raw, &f) + err := json.Unmarshal(raw, &f, jsonx.V1()) return f, err } diff --git a/services/codebuild/reports_test.go b/services/codebuild/reports_test.go index 524d51c82c..cd0195baf1 100644 --- a/services/codebuild/reports_test.go +++ b/services/codebuild/reports_test.go @@ -1,13 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -103,7 +105,7 @@ func TestHandler_BatchGetReportGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) rg, _ := out["reportGroup"].(map[string]any) arns = append(arns, rg["arn"].(string)) } @@ -116,7 +118,7 @@ func TestHandler_BatchGetReportGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) groups, _ := out["reportGroups"].([]any) assert.Len(t, groups, tt.wantFound) @@ -177,7 +179,7 @@ func TestHandler_BatchGetReports(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) reports, _ := out["reports"].([]any) assert.Len(t, reports, tt.wantFound) @@ -202,7 +204,7 @@ func TestCodeBuild_Reports(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.Reports) }) @@ -225,7 +227,7 @@ func TestCodeBuild_Reports(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Reports, 2) }) @@ -247,7 +249,7 @@ func TestCodeBuild_Reports(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Empty(t, out.Reports) }) @@ -302,7 +304,7 @@ func TestCodeBuild_Reports(t *testing.T) { var out struct { Reports []string `json:"reports"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Reports, 2) for _, r := range out.Reports { assert.Contains(t, r, "my-rg") @@ -343,7 +345,7 @@ func TestCodeBuild_ReportGroups(t *testing.T) { Arn string `json:"arn"` } `json:"reportGroup"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) rgArn := createOut.ReportGroup.Arn delRec := doRequest(t, h, "DeleteReportGroup", map[string]any{"arn": rgArn}) @@ -356,7 +358,7 @@ func TestCodeBuild_ReportGroups(t *testing.T) { var batchOut struct { ReportGroupsNotFound []string `json:"reportGroupsNotFound"` } - require.NoError(t, json.NewDecoder(batchRec.Body).Decode(&batchOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(batchRec.Body), &batchOut, jsonx.V1())) assert.Len(t, batchOut.ReportGroupsNotFound, 1) }) @@ -390,7 +392,7 @@ func TestCodeBuild_ReportGroups(t *testing.T) { Arn string `json:"arn"` } `json:"reportGroup"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) rgArn := createOut.ReportGroup.Arn updateRec := doRequest(t, h, "UpdateReportGroup", map[string]any{ @@ -408,7 +410,7 @@ func TestCodeBuild_ReportGroups(t *testing.T) { } `json:"exportConfig"` } `json:"reportGroup"` } - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&updateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &updateOut, jsonx.V1())) assert.Equal(t, "S3", updateOut.ReportGroup.ExportConfig.ExportConfigType) }) @@ -444,7 +446,7 @@ func TestCodeBuild_ReportExtras(t *testing.T) { var out struct { CodeCoverages []any `json:"codeCoverages"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.CodeCoverages) }) @@ -470,7 +472,7 @@ func TestCodeBuild_ReportExtras(t *testing.T) { var out struct { TestCases []any `json:"testCases"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.TestCases) }) @@ -502,7 +504,7 @@ func TestCodeBuild_ReportExtras(t *testing.T) { var out struct { Stats map[string]any `json:"stats"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotNil(t, out.Stats) }) @@ -543,7 +545,7 @@ func TestCodeBuild_ReportExtras(t *testing.T) { var out struct { ReportGroups []string `json:"reportGroups"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.ReportGroups) }) } diff --git a/services/codebuild/resource_policies_test.go b/services/codebuild/resource_policies_test.go index c46bbac726..7eab2816b1 100644 --- a/services/codebuild/resource_policies_test.go +++ b/services/codebuild/resource_policies_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCodeBuild_ResourcePolicy covers Put, Get, Delete. @@ -30,7 +33,7 @@ func TestCodeBuild_ResourcePolicy(t *testing.T) { var putOut struct { ResourceArn string `json:"resourceArn"` } - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&putOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &putOut, jsonx.V1())) assert.Equal(t, resArn, putOut.ResourceArn) getRec := doRequest(t, h, "GetResourcePolicy", map[string]any{"resourceArn": resArn}) @@ -39,7 +42,7 @@ func TestCodeBuild_ResourcePolicy(t *testing.T) { var getOut struct { Policy string `json:"policy"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.JSONEq(t, policy, getOut.Policy) }) @@ -129,7 +132,7 @@ func TestHandler_ResourcePolicy_PutGetRoundTrip(t *testing.T) { var out struct { Policy string `json:"policy"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) assert.JSONEq(t, tt.wantPolicy, out.Policy) } }) diff --git a/services/codebuild/sandboxes_test.go b/services/codebuild/sandboxes_test.go index fd8dab2814..db29a0a446 100644 --- a/services/codebuild/sandboxes_test.go +++ b/services/codebuild/sandboxes_test.go @@ -1,13 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codebuild" ) @@ -59,7 +61,7 @@ func TestHandler_BatchGetSandboxes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) sandboxes, _ := out["sandboxes"].([]any) assert.Len(t, sandboxes, tt.wantFound) @@ -88,7 +90,7 @@ func TestCodeBuild_Sandbox(t *testing.T) { ID string `json:"id"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) sandboxID := startOut.Sandbox.ID stopRec := doRequest(t, h, "StopSandbox", map[string]any{"id": sandboxID}) @@ -99,7 +101,7 @@ func TestCodeBuild_Sandbox(t *testing.T) { Status string `json:"status"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&stopOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &stopOut, jsonx.V1())) assert.Equal(t, "STOPPED", stopOut.Sandbox.Status) }) @@ -128,7 +130,7 @@ func TestCodeBuild_Sandbox(t *testing.T) { var out struct { IDs []string `json:"ids"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.IDs, 2) }) @@ -177,7 +179,7 @@ func TestHandler_StartSandbox_Schema(t *testing.T) { StartTime float64 `json:"startTime"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out.Sandbox.Status) if tt.wantArnSet { assert.NotEmpty(t, out.Sandbox.Arn) @@ -219,7 +221,7 @@ func TestHandler_StopSandbox_SetsEndTime(t *testing.T) { ID string `json:"id"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(startRec.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(startRec.Body), &startOut, jsonx.V1())) stopRec := doRequest(t, h, "StopSandbox", map[string]any{"id": startOut.Sandbox.ID}) require.Equal(t, http.StatusOK, stopRec.Code) @@ -230,7 +232,7 @@ func TestHandler_StopSandbox_SetsEndTime(t *testing.T) { EndTime float64 `json:"endTime"` } `json:"sandbox"` } - require.NoError(t, json.NewDecoder(stopRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(stopRec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out.Sandbox.Status) if tt.wantEndTimeSet { assert.Greater(t, out.Sandbox.EndTime, float64(0)) diff --git a/services/codebuild/source_credentials_test.go b/services/codebuild/source_credentials_test.go index 39b8fa755f..92aa9811c9 100644 --- a/services/codebuild/source_credentials_test.go +++ b/services/codebuild/source_credentials_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCodeBuild_SourceCredentials covers Import, List, Delete. @@ -27,7 +30,7 @@ func TestCodeBuild_SourceCredentials(t *testing.T) { var out struct { Arn string `json:"arn"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Contains(t, out.Arn, "GITHUB") }) @@ -58,7 +61,7 @@ func TestCodeBuild_SourceCredentials(t *testing.T) { var out struct { SourceCredentialsInfos []map[string]any `json:"sourceCredentialsInfos"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.Len(t, out.SourceCredentialsInfos, 1) assert.Equal(t, "BITBUCKET", out.SourceCredentialsInfos[0]["serverType"]) assert.Equal(t, "PERSONAL_ACCESS_TOKEN", out.SourceCredentialsInfos[0]["authType"]) @@ -78,7 +81,7 @@ func TestCodeBuild_SourceCredentials(t *testing.T) { var importOut struct { Arn string `json:"arn"` } - require.NoError(t, json.NewDecoder(importRec.Body).Decode(&importOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(importRec.Body), &importOut, jsonx.V1())) delRec := doRequest(t, h, "DeleteSourceCredentials", map[string]any{"arn": importOut.Arn}) assert.Equal(t, http.StatusOK, delRec.Code) @@ -88,7 +91,7 @@ func TestCodeBuild_SourceCredentials(t *testing.T) { var listOut struct { SourceCredentialsInfos []map[string]any `json:"sourceCredentialsInfos"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Empty(t, listOut.SourceCredentialsInfos) }) diff --git a/services/codebuild/tagswire.go b/services/codebuild/tagswire.go index 312a52a52a..aab1a32c96 100644 --- a/services/codebuild/tagswire.go +++ b/services/codebuild/tagswire.go @@ -1,8 +1,10 @@ package codebuild import ( - "encoding/json" + "encoding/json/v2" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // wireTags is the wire representation of CodeBuild's tags field: a JSON @@ -25,12 +27,12 @@ func (t wireTags) MarshalJSON() ([]byte, error) { sort.Slice(items, func(i, j int) bool { return items[i].Key < items[j].Key }) - return json.Marshal(items) + return json.Marshal(items, jsonx.V1()) } func (t *wireTags) UnmarshalJSON(data []byte) error { var items []wireTag - if err := json.Unmarshal(data, &items); err != nil { + if err := json.Unmarshal(data, &items, jsonx.V1()); err != nil { return err } diff --git a/services/codebuild/webhooks_test.go b/services/codebuild/webhooks_test.go index ecb0f689df..c8cac33ef9 100644 --- a/services/codebuild/webhooks_test.go +++ b/services/codebuild/webhooks_test.go @@ -1,12 +1,15 @@ package codebuild_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateWebhook(t *testing.T) { @@ -107,7 +110,7 @@ func TestHandler_CreateWebhook_ResponseFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) webhook, ok := out["webhook"].(map[string]any) require.True(t, ok, "response should contain 'webhook' object") @@ -167,7 +170,7 @@ func TestCodeBuild_Webhooks(t *testing.T) { BuildType string `json:"buildType"` } `json:"webhook"` } - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &out, jsonx.V1())) assert.Equal(t, "develop", out.Webhook.BranchFilter) assert.Equal(t, "BUILD_BATCH", out.Webhook.BuildType) }) @@ -215,7 +218,7 @@ func TestHandler_CreateWebhook_FilterGroups(t *testing.T) { var out struct { Webhook map[string]any `json:"webhook"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) w := out.Webhook fgs, hasFGs := w["filterGroups"] @@ -263,7 +266,7 @@ func TestHandler_CreateWebhook_ExtendedFields(t *testing.T) { ManualCreation bool `json:"manualCreation"` } `json:"webhook"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, "ACTIVE", out.Webhook.Status) assert.NotEmpty(t, out.Webhook.Secret, "CreateWebhook must return a secret") @@ -295,7 +298,7 @@ func TestHandler_UpdateWebhook_RotateSecret(t *testing.T) { LastModifiedSecret float64 `json:"lastModifiedSecret"` } `json:"webhook"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) originalSecret := createOut.Webhook.Secret require.NotEmpty(t, originalSecret) @@ -312,7 +315,7 @@ func TestHandler_UpdateWebhook_RotateSecret(t *testing.T) { Secret string `json:"secret"` } `json:"webhook"` } - require.NoError(t, json.NewDecoder(noRotateRec.Body).Decode(&noRotateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(noRotateRec.Body), &noRotateOut, jsonx.V1())) assert.Equal(t, originalSecret, noRotateOut.Webhook.Secret, "secret must be unchanged without rotateSecret") rotateRec := doRequest(t, h, "UpdateWebhook", map[string]any{ @@ -327,7 +330,7 @@ func TestHandler_UpdateWebhook_RotateSecret(t *testing.T) { LastModifiedSecret float64 `json:"lastModifiedSecret"` } `json:"webhook"` } - require.NoError(t, json.NewDecoder(rotateRec.Body).Decode(&rotateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rotateRec.Body), &rotateOut, jsonx.V1())) assert.NotEqual(t, originalSecret, rotateOut.Webhook.Secret, "rotateSecret must regenerate the secret") assert.GreaterOrEqual(t, rotateOut.Webhook.LastModifiedSecret, createOut.Webhook.LastModifiedSecret) } @@ -348,7 +351,7 @@ func TestHandler_Webhook_MirroredOnProject(t *testing.T) { var out struct { Projects []map[string]any `json:"projects"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Projects, 1) w, _ := out.Projects[0]["webhook"].(map[string]any) diff --git a/services/codebuild/whitebox_test.go b/services/codebuild/whitebox_test.go index e42202386c..c93a7fdae0 100644 --- a/services/codebuild/whitebox_test.go +++ b/services/codebuild/whitebox_test.go @@ -2,7 +2,8 @@ package codebuild import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,12 +12,14 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doTestRequest(t *testing.T, h *Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -81,7 +84,7 @@ func TestHandler_ListProjects_SortByCreatedTime(t *testing.T) { var out struct { Projects []string `json:"projects"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, []string{"created-z", "created-a", "created-m"}, out.Projects, "CREATED_TIME order must ignore name ordering") } diff --git a/services/codecommit/actor_arn_test.go b/services/codecommit/actor_arn_test.go index 3efe0e891e..85ffedd558 100644 --- a/services/codecommit/actor_arn_test.go +++ b/services/codecommit/actor_arn_test.go @@ -2,7 +2,7 @@ package codecommit_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -30,7 +31,7 @@ func doRequestAsActor( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -80,7 +81,7 @@ func createTestPRForActorArn(t *testing.T, h *codecommit.Handler) (string, strin RevisionID string `json:"revisionId"` } `json:"pullRequest"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.PullRequest.PullRequestID) require.NotEmpty(t, resp.PullRequest.RevisionID) @@ -153,7 +154,7 @@ func TestOverridePullRequestApprovalRules_RecordsCallerAsActorArn(t *testing.T) var resp struct { PullRequestEvents []map[string]any `json:"pullRequestEvents"` } - require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.PullRequestEvents, tt.wantCount) if tt.wantCount > 0 { diff --git a/services/codecommit/handler.go b/services/codecommit/handler.go index e5876418d0..4513a98381 100644 --- a/services/codecommit/handler.go +++ b/services/codecommit/handler.go @@ -2,7 +2,7 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -329,7 +330,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var input struct { RepositoryName string `json:"repositoryName"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return "" } @@ -366,7 +367,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } if action == "PutCommentReaction" { @@ -375,7 +376,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } if option, isPRMerge := pullRequestMergeOption(action); isPRMerge { @@ -384,7 +385,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } if ctxFn, isCtxOp := h.ctxOps[action]; isCtxOp { @@ -393,7 +394,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } fn, ok := h.ops[action] @@ -406,7 +407,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // errCodeEntry maps a backend sentinel error to its AWS HTTP status and exception type. diff --git a/services/codecommit/handler_approval_rule_associations_test.go b/services/codecommit/handler_approval_rule_associations_test.go index d7026455bc..28198947bf 100644 --- a/services/codecommit/handler_approval_rule_associations_test.go +++ b/services/codecommit/handler_approval_rule_associations_test.go @@ -1,12 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AssociateApprovalRuleTemplateWithRepository(t *testing.T) { @@ -154,7 +156,7 @@ func TestHandler_BatchAssociateApprovalRuleTemplateWithRepositories(t *testing.T if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc, _ := resp["associatedRepositoryNames"].([]any) assert.Len(t, assoc, tt.wantAssocCount) @@ -237,7 +239,7 @@ func TestHandler_BatchDisassociateApprovalRuleTemplateFromRepositories(t *testin if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) disassoc, _ := resp["disassociatedRepositoryNames"].([]any) assert.Len(t, disassoc, tt.wantDisassocCount) @@ -262,7 +264,7 @@ func TestHandler_BatchAssociate_EmptySlicesNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Must be JSON array, not null associated := resp["associatedRepositoryNames"] @@ -284,7 +286,7 @@ func TestHandler_BatchDisassociate_EmptySlicesNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) disassoc := resp["disassociatedRepositoryNames"] assert.NotNil(t, disassoc, "disassociatedRepositoryNames must not be null") @@ -310,7 +312,7 @@ func TestHandler_ListAssociatedApprovalRuleTemplatesForRepository(t *testing.T) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := resp["approvalRuleTemplateNames"].([]any) assert.Contains(t, names, "assoc-tmpl") } @@ -335,7 +337,7 @@ func TestHandler_ListRepositoriesForApprovalRuleTemplate(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos := resp["repositoryNames"].([]any) assert.Contains(t, repos, "repo-for-tmpl") } @@ -355,7 +357,7 @@ func TestHandler_ListRepositoriesForApprovalRuleTemplate_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos := resp["repositoryNames"].([]any) assert.Empty(t, repos) } @@ -389,7 +391,7 @@ func TestHandler_ListAssociatedApprovalRuleTemplatesForRepository_AfterAssoc(t * require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := resp["approvalRuleTemplateNames"].([]any) assert.Len(t, names, 2) } @@ -525,7 +527,7 @@ func TestHandler_BatchAssociateAndDisassociate_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc := resp["associatedRepositoryNames"].([]any) errs := resp["errors"].([]any) assert.Len(t, assoc, tt.wantAssocLen) @@ -539,7 +541,7 @@ func TestHandler_BatchAssociateAndDisassociate_TableDriven(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) disassoc := resp["disassociatedRepositoryNames"].([]any) assert.Len(t, disassoc, tt.wantAssocLen) } @@ -589,13 +591,13 @@ func TestListAssociatedApprovalRuleTemplatesForRepository_RepoNotFound(t *testin if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names, ok := resp["approvalRuleTemplateNames"].([]any) require.True(t, ok, "approvalRuleTemplateNames must be a JSON array") assert.Empty(t, names) } else { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "RepositoryDoesNotExistException", errResp["__type"]) } }) @@ -647,13 +649,13 @@ func TestListRepositoriesForApprovalRuleTemplate_TemplateNotFound(t *testing.T) if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, ok := resp["repositoryNames"].([]any) require.True(t, ok, "repositoryNames must be a JSON array") assert.Empty(t, repos) } else { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ApprovalRuleTemplateDoesNotExistException", errResp["__type"]) } }) diff --git a/services/codecommit/handler_approval_rules.go b/services/codecommit/handler_approval_rules.go index 87658bff9a..2483bed47f 100644 --- a/services/codecommit/handler_approval_rules.go +++ b/services/codecommit/handler_approval_rules.go @@ -1,8 +1,10 @@ package codecommit import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createApprovalRuleTemplateInput struct { @@ -48,7 +50,7 @@ func approvalRuleTemplateToMap(t *ApprovalRuleTemplate) map[string]any { func (h *Handler) handleCreateApprovalRuleTemplate(body []byte) (any, error) { var in createApprovalRuleTemplateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -76,7 +78,7 @@ func (h *Handler) handleCreateApprovalRuleTemplate(body []byte) (any, error) { func (h *Handler) handleAssociateApprovalRuleTemplateWithRepository(body []byte) (any, error) { var in associateApprovalRuleTemplateWithRepositoryInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -100,7 +102,7 @@ func (h *Handler) handleAssociateApprovalRuleTemplateWithRepository(body []byte) func (h *Handler) handleBatchAssociateApprovalRuleTemplateWithRepositories(body []byte) (any, error) { var in batchAssociateApprovalRuleTemplateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -129,7 +131,7 @@ func (h *Handler) handleBatchAssociateApprovalRuleTemplateWithRepositories(body func (h *Handler) handleBatchDisassociateApprovalRuleTemplateFromRepositories(body []byte) (any, error) { var in batchDisassociateApprovalRuleTemplateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -160,7 +162,7 @@ func (h *Handler) handleDeleteApprovalRuleTemplate(body []byte) (any, error) { var req struct { ApprovalRuleTemplateName string `json:"approvalRuleTemplateName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" { @@ -184,7 +186,7 @@ func (h *Handler) handleGetApprovalRuleTemplate(body []byte) (any, error) { var req struct { ApprovalRuleTemplateName string `json:"approvalRuleTemplateName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" { @@ -209,7 +211,7 @@ type listPageRequest struct { func (h *Handler) handleListApprovalRuleTemplates(body []byte) (any, error) { var req listPageRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } } @@ -242,7 +244,7 @@ func (h *Handler) handleUpdateApprovalRuleTemplateContent(body []byte) (any, err NewRuleContent string `json:"newRuleContent"` ExistingRuleContentSha string `json:"existingRuleContentSha256"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" { @@ -271,7 +273,7 @@ func (h *Handler) handleUpdateApprovalRuleTemplateDescription(body []byte) (any, ApprovalRuleTemplateName string `json:"approvalRuleTemplateName"` ApprovalRuleTemplateDescription string `json:"approvalRuleTemplateDescription"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" { @@ -299,7 +301,7 @@ func (h *Handler) handleUpdateApprovalRuleTemplateName(body []byte) (any, error) OldApprovalRuleTemplateName string `json:"oldApprovalRuleTemplateName"` NewApprovalRuleTemplateName string `json:"newApprovalRuleTemplateName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.OldApprovalRuleTemplateName == "" || req.NewApprovalRuleTemplateName == "" { @@ -329,7 +331,7 @@ func (h *Handler) handleListAssociatedApprovalRuleTemplatesForRepository(body [] RepositoryName string `json:"repositoryName"` listPageRequest } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -354,7 +356,7 @@ func (h *Handler) handleListRepositoriesForApprovalRuleTemplate(body []byte) (an ApprovalRuleTemplateName string `json:"approvalRuleTemplateName"` listPageRequest } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" { @@ -384,7 +386,7 @@ func (h *Handler) handleDisassociateApprovalRuleTemplateFromRepository(body []by ApprovalRuleTemplateName string `json:"approvalRuleTemplateName"` RepositoryName string `json:"repositoryName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.ApprovalRuleTemplateName == "" || req.RepositoryName == "" { diff --git a/services/codecommit/handler_approval_rules_test.go b/services/codecommit/handler_approval_rules_test.go index cddf5fbd9b..e25831ec3d 100644 --- a/services/codecommit/handler_approval_rules_test.go +++ b/services/codecommit/handler_approval_rules_test.go @@ -1,7 +1,7 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -75,7 +76,7 @@ func TestHandler_CreateApprovalRuleTemplate(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tmpl, ok := resp["approvalRuleTemplate"].(map[string]any) require.True(t, ok) @@ -125,7 +126,7 @@ func TestHandler_GetApprovalRuleTemplate(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tmpl := resp["approvalRuleTemplate"].(map[string]any) assert.Equal(t, "tmpl-get", tmpl["approvalRuleTemplateName"]) @@ -153,7 +154,7 @@ func TestHandler_ListApprovalRuleTemplates(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := resp["approvalRuleTemplateNames"].([]any) assert.Len(t, names, 2) @@ -203,7 +204,7 @@ func TestHandler_UpdateApprovalRuleTemplateContent_Reflected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tmpl := resp["approvalRuleTemplate"].(map[string]any) assert.Equal(t, newContent, tmpl["approvalRuleTemplateContent"]) } @@ -330,7 +331,7 @@ func TestHandler_ApprovalRuleTemplate_CRUD_TableDriven(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tmpl := resp["approvalRuleTemplate"].(map[string]any) assert.Equal(t, tt.tmplName, tmpl["approvalRuleTemplateName"]) assert.Equal(t, tt.content, tmpl["approvalRuleTemplateContent"]) diff --git a/services/codecommit/handler_branches.go b/services/codecommit/handler_branches.go index 05691dfcbe..aa98392084 100644 --- a/services/codecommit/handler_branches.go +++ b/services/codecommit/handler_branches.go @@ -1,8 +1,10 @@ package codecommit import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createBranchInput struct { @@ -13,7 +15,7 @@ type createBranchInput struct { func (h *Handler) handleCreateBranch(body []byte) (any, error) { var in createBranchInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -41,7 +43,7 @@ func (h *Handler) handleDeleteBranch(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` BranchName string `json:"branchName"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -70,7 +72,7 @@ func (h *Handler) handleGetBranch(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` BranchName string `json:"branchName"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -93,7 +95,7 @@ func (h *Handler) handleListBranches(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -123,7 +125,7 @@ func (h *Handler) handleUpdateDefaultBranch(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` DefaultBranchName string `json:"defaultBranchName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_branches_test.go b/services/codecommit/handler_branches_test.go index 09ad7b4b2a..4b3180c9ee 100644 --- a/services/codecommit/handler_branches_test.go +++ b/services/codecommit/handler_branches_test.go @@ -1,12 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateBranch(t *testing.T) { @@ -29,7 +31,7 @@ func TestHandler_CreateBranch(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitResp map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp, jsonx.V1())) commitID := commitResp["commitId"].(string) rec := doRequest(t, h, "CreateBranch", map[string]any{ @@ -108,7 +110,7 @@ func TestHandler_CreateBranch(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitResp map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp, jsonx.V1())) commitID := commitResp["commitId"].(string) doRequest(t, h, "CreateBranch", map[string]any{ @@ -142,7 +144,7 @@ func TestHandler_CreateBranch_CommitValidation(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitResp map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp, jsonx.V1())) realCommitID := commitResp["commitId"].(string) tests := []struct { @@ -181,7 +183,7 @@ func TestHandler_CreateBranch_CommitValidation(t *testing.T) { }) require.Equal(t, http.StatusOK, cr.Code) var cr2 map[string]any - require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &cr2)) + require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &cr2, jsonx.V1())) tt.commitID = cr2["commitId"].(string) } diff --git a/services/codecommit/handler_comments.go b/services/codecommit/handler_comments.go index e1f1630c53..29f1d26da8 100644 --- a/services/codecommit/handler_comments.go +++ b/services/codecommit/handler_comments.go @@ -2,10 +2,11 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -66,7 +67,7 @@ func (h *Handler) handlePostCommentForComparedCommit(ctx context.Context, body [ Content string `json:"content"` ClientRequestToken string `json:"clientRequestToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" || req.Content == "" { @@ -104,7 +105,7 @@ func (h *Handler) handlePostCommentForPullRequest(ctx context.Context, body []by Content string `json:"content"` ClientRequestToken string `json:"clientRequestToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" || req.Content == "" { @@ -139,7 +140,7 @@ func (h *Handler) handlePostCommentReply(ctx context.Context, body []byte) (any, Content string `json:"content"` ClientRequestToken string `json:"clientRequestToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.InReplyTo == "" || req.Content == "" { @@ -167,7 +168,7 @@ func (h *Handler) handleGetComment(body []byte) (any, error) { var req struct { CommentID string `json:"commentId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.CommentID == "" { @@ -229,7 +230,7 @@ func (h *Handler) handleGetCommentsForComparedCommit(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -275,7 +276,7 @@ func (h *Handler) handleGetCommentsForPullRequest(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -324,7 +325,7 @@ func (h *Handler) handleUpdateComment(body []byte) (any, error) { CommentID string `json:"commentId"` Content string `json:"content"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.CommentID == "" { @@ -349,7 +350,7 @@ func (h *Handler) handleDeleteCommentContent(body []byte) (any, error) { var req struct { CommentID string `json:"commentId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.CommentID == "" { diff --git a/services/codecommit/handler_comments_test.go b/services/codecommit/handler_comments_test.go index 58ce95da1d..936665621d 100644 --- a/services/codecommit/handler_comments_test.go +++ b/services/codecommit/handler_comments_test.go @@ -1,13 +1,15 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PostCommentForComparedCommit(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_PostCommentForComparedCommit(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) comment := resp["comment"].(map[string]any) assert.Equal(t, "hello world", comment["content"]) assert.NotEmpty(t, comment["commentId"]) @@ -45,7 +47,7 @@ func TestHandler_PostCommentForPullRequest(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) comment := resp["comment"].(map[string]any) assert.Equal(t, "PR comment", comment["content"]) } @@ -64,7 +66,7 @@ func TestHandler_PostCommentReply(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var parentResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &parentResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &parentResp, jsonx.V1())) parentID := parentResp["comment"].(map[string]any)["commentId"].(string) rec = doRequest(t, h, "PostCommentReply", map[string]any{ @@ -74,7 +76,7 @@ func TestHandler_PostCommentReply(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "reply comment", resp["comment"].(map[string]any)["content"]) } @@ -92,7 +94,7 @@ func TestHandler_GetComment(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) cID := cr["comment"].(map[string]any)["commentId"].(string) rec = doRequest(t, h, "GetComment", map[string]any{"commentId": cID}) @@ -121,7 +123,7 @@ func TestHandler_GetCommentsForComparedCommit(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["commentsForComparedCommitData"].([]any) require.Len(t, groups, 1) assert.Len(t, groups[0].(map[string]any)["comments"], 1) @@ -163,7 +165,7 @@ func TestHandler_GetCommentsForComparedCommit_TableDriven(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["commentsForComparedCommitData"].([]any) if tt.commentCount == 0 { assert.Empty(t, groups) @@ -194,7 +196,7 @@ func TestHandler_GetCommentsForPullRequest(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["commentsForPullRequestData"].([]any) require.Len(t, groups, 1) assert.Len(t, groups[0].(map[string]any)["comments"], 1) @@ -234,7 +236,7 @@ func TestHandler_GetCommentsForPullRequest_TableDriven(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["commentsForPullRequestData"].([]any) if tt.commentCount == 0 { assert.Empty(t, groups) @@ -261,7 +263,7 @@ func TestHandler_UpdateComment(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) cID := cr["comment"].(map[string]any)["commentId"].(string) rec = doRequest(t, h, "UpdateComment", map[string]any{ @@ -271,7 +273,7 @@ func TestHandler_UpdateComment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "updated", resp["comment"].(map[string]any)["content"]) } @@ -289,14 +291,14 @@ func TestHandler_DeleteCommentContent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) cID := cr["comment"].(map[string]any)["commentId"].(string) rec = doRequest(t, h, "DeleteCommentContent", map[string]any{"commentId": cID}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["comment"].(map[string]any)["deleted"]) } @@ -315,7 +317,7 @@ func TestHandler_CommentLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commentID := resp["comment"].(map[string]any)["commentId"].(string) // Update the comment. @@ -325,7 +327,7 @@ func TestHandler_CommentLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "updated content", resp["comment"].(map[string]any)["content"]) // Add reaction. @@ -339,7 +341,7 @@ func TestHandler_CommentLifecycle(t *testing.T) { rec = doRequest(t, h, "GetCommentReactions", map[string]any{"commentId": commentID}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) reactions := resp["reactionsForComment"].([]any) assert.Len(t, reactions, 1) @@ -354,7 +356,7 @@ func TestHandler_CommentLifecycle(t *testing.T) { rec = doRequest(t, h, "DeleteCommentContent", map[string]any{"commentId": commentID}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) c := resp["comment"].(map[string]any) assert.Equal(t, true, c["deleted"]) assert.Empty(t, c["content"]) diff --git a/services/codecommit/handler_commits.go b/services/codecommit/handler_commits.go index baf9860ae0..7d0128030b 100644 --- a/services/codecommit/handler_commits.go +++ b/services/codecommit/handler_commits.go @@ -2,9 +2,11 @@ package codecommit import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type batchGetCommitsInput struct { @@ -70,7 +72,7 @@ func commitToMap(c *Commit) map[string]any { func (h *Handler) handleBatchGetCommits(body []byte) (any, error) { var in batchGetCommitsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -100,7 +102,7 @@ func (h *Handler) handleBatchGetCommits(body []byte) (any, error) { func (h *Handler) handleCreateCommit(body []byte) (any, error) { var in createCommitInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -209,7 +211,7 @@ func (h *Handler) handleGetCommit(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` CommitID string `json:"commitId"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -237,7 +239,7 @@ func (h *Handler) handleGetDifferences(body []byte) (any, error) { NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_commits_test.go b/services/codecommit/handler_commits_test.go index 1c6412a4c4..981da6dece 100644 --- a/services/codecommit/handler_commits_test.go +++ b/services/codecommit/handler_commits_test.go @@ -1,13 +1,15 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateCommit(t *testing.T) { @@ -69,7 +71,7 @@ func TestHandler_CreateCommit(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["commitId"]) assert.NotEmpty(t, resp["treeId"]) } @@ -97,7 +99,7 @@ func TestHandler_CreateCommit_FilesAddedBlobID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) filesAdded, ok := resp["filesAdded"].([]any) require.True(t, ok) require.Len(t, filesAdded, 2) @@ -143,7 +145,7 @@ func TestHandler_CreateCommit_FilesDeletedBlobID(t *testing.T) { require.Equal(t, http.StatusOK, addRec.Code) var addResp map[string]any - require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp)) + require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp, jsonx.V1())) filesAdded, ok := addResp["filesAdded"].([]any) require.True(t, ok) require.Len(t, filesAdded, 1) @@ -162,7 +164,7 @@ func TestHandler_CreateCommit_FilesDeletedBlobID(t *testing.T) { require.Equal(t, http.StatusOK, delRec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp, jsonx.V1())) filesDeleted, ok := delResp["filesDeleted"].([]any) require.True(t, ok) require.Len(t, filesDeleted, 1) @@ -237,7 +239,7 @@ func TestHandler_BatchGetCommits(t *testing.T) { require.Equal(t, http.StatusOK, r.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &resp, jsonx.V1())) commitIDs = append(commitIDs, resp["commitId"].(string)) } @@ -252,7 +254,7 @@ func TestHandler_BatchGetCommits(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commits, _ := resp["commits"].([]any) assert.Len(t, commits, tt.wantFoundCount) @@ -308,7 +310,7 @@ func TestHandler_BatchGetCommits_FullCommitMap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) commitID := createResp["commitId"].(string) rec = doRequest(t, h, "BatchGetCommits", map[string]any{ @@ -318,7 +320,7 @@ func TestHandler_BatchGetCommits_FullCommitMap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commits, ok := resp["commits"].([]any) require.True(t, ok) @@ -392,7 +394,7 @@ func TestHandler_BatchGetCommits_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, branchRec.Code) var brResp map[string]any - require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &brResp)) + require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &brResp, jsonx.V1())) realCommitID := brResp["branch"].(map[string]any)["commitId"].(string) var ids []string @@ -410,7 +412,7 @@ func TestHandler_BatchGetCommits_TableDriven(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commits := resp["commits"].([]any) errors := resp["errors"].([]any) @@ -437,7 +439,7 @@ func TestHandler_CommitParentTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) firstCommitID := firstResp["commitId"].(string) // Second commit on same branch — should have firstCommitID as parent @@ -449,7 +451,7 @@ func TestHandler_CommitParentTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var secondResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp, jsonx.V1())) secondCommitID := secondResp["commitId"].(string) // Fetch both commits via BatchGetCommits and check parent linkage @@ -460,7 +462,7 @@ func TestHandler_CommitParentTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp, jsonx.V1())) commits, ok := batchResp["commits"].([]any) require.True(t, ok) @@ -504,7 +506,7 @@ func TestHandler_CreateCommit_ParentCommitIdOutdated(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ParentCommitIdOutdatedException", resp["__type"]) } @@ -535,7 +537,7 @@ func TestHandler_CreateCommit_NoChange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) firstCommitID, _ := firstResp["commitId"].(string) require.NotEmpty(t, firstCommitID) @@ -549,7 +551,7 @@ func TestHandler_CreateCommit_NoChange(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "NoChangeException", errResp["__type"]) branchRec := doRequest(t, h, "GetBranch", map[string]any{ @@ -558,7 +560,7 @@ func TestHandler_CreateCommit_NoChange(t *testing.T) { require.Equal(t, http.StatusOK, branchRec.Code) var branchResp map[string]any - require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &branchResp)) + require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &branchResp, jsonx.V1())) branch, ok := branchResp["branch"].(map[string]any) require.True(t, ok) assert.Equal(t, firstCommitID, branch["commitId"], "rejected commit must not move the branch tip") @@ -602,7 +604,7 @@ func TestGetCommit_ParentsNotNull(t *testing.T) { require.Equal(t, http.StatusOK, r1.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(r1.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(r1.Body.Bytes(), &firstResp, jsonx.V1())) firstID := firstResp["commitId"].(string) // Create second commit (has first as parent). @@ -614,7 +616,7 @@ func TestGetCommit_ParentsNotNull(t *testing.T) { require.Equal(t, http.StatusOK, r2.Code) var secondResp map[string]any - require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &secondResp, jsonx.V1())) secondID := secondResp["commitId"].(string) ids := []string{firstID, secondID} @@ -627,7 +629,7 @@ func TestGetCommit_ParentsNotNull(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commit, ok := resp["commit"].(map[string]any) require.True(t, ok, "commit field must be present") @@ -664,7 +666,7 @@ func TestGetCommit_FullFieldSet(t *testing.T) { require.Equal(t, http.StatusOK, r.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &createResp, jsonx.V1())) commitID := createResp["commitId"].(string) rec := doRequest(t, h, "GetCommit", map[string]any{ @@ -674,7 +676,7 @@ func TestGetCommit_FullFieldSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commit, ok := resp["commit"].(map[string]any) require.True(t, ok) @@ -719,7 +721,7 @@ func TestHandler_GetCommit_CommitIDNotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CommitIdDoesNotExistException", resp["__type"]) } @@ -747,7 +749,7 @@ func TestHandler_BatchGetCommits_ErrorCodeIsCommitIdDoesNotExist(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) errs, ok := resp["errors"].([]any) require.True(t, ok) @@ -771,7 +773,7 @@ func TestHandler_GetDifferences(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["differences"]) } @@ -831,7 +833,7 @@ func TestGetDifferences_BlobObjectShape(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitOut map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut, jsonx.V1())) commitID := commitOut["commitId"].(string) rec := doRequest(t, h, "GetDifferences", map[string]any{ @@ -843,7 +845,7 @@ func TestGetDifferences_BlobObjectShape(t *testing.T) { var resp struct { Differences []map[string]any `json:"differences"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Differences, tt.wantCount) // Each difference must have afterBlob as an object, not a string. @@ -878,7 +880,7 @@ func TestGetDifferences_FilePathInBlob(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitOut map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut, jsonx.V1())) rec := doRequest(t, h, "GetDifferences", map[string]any{ "repositoryName": "path-repo", @@ -889,7 +891,7 @@ func TestGetDifferences_FilePathInBlob(t *testing.T) { var resp struct { Differences []map[string]any `json:"differences"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Differences, 1) afterBlob := resp.Differences[0]["afterBlob"].(map[string]any) @@ -912,7 +914,7 @@ func TestGetDifferences_EmptyRepoReturnsEmptyArray(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) diffs, ok := resp["differences"].([]any) require.True(t, ok, "differences must be a JSON array, not null") assert.Empty(t, diffs) @@ -946,7 +948,7 @@ func TestGetDifferences_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, commitRec.Code) var commitOut map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut, jsonx.V1())) commitID := commitOut["commitId"].(string) seenPaths := map[string]bool{} @@ -966,7 +968,7 @@ func TestGetDifferences_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) diffs, ok := resp["differences"].([]any) require.True(t, ok) assert.LessOrEqual(t, len(diffs), 2, "each page must respect MaxResults") diff --git a/services/codecommit/handler_files.go b/services/codecommit/handler_files.go index 274bf0cf15..4eccf4ca15 100644 --- a/services/codecommit/handler_files.go +++ b/services/codecommit/handler_files.go @@ -4,9 +4,11 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handlePutFile(body []byte) (any, error) { @@ -21,7 +23,7 @@ func (h *Handler) handlePutFile(body []byte) (any, error) { CommitMessage string `json:"commitMessage"` ParentCommitID string `json:"parentCommitId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" || req.FilePath == "" { @@ -61,7 +63,7 @@ func (h *Handler) handleGetFile(body []byte) (any, error) { CommitSpecifier string `json:"commitSpecifier"` FilePath string `json:"filePath"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" || req.FilePath == "" { @@ -89,7 +91,7 @@ func (h *Handler) handleGetFolder(body []byte) (any, error) { CommitSpecifier string `json:"commitSpecifier"` FolderPath string `json:"folderPath"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -165,7 +167,7 @@ func (h *Handler) handleDeleteFile(body []byte) (any, error) { CommitMessage string `json:"commitMessage"` KeepEmptyFolders bool `json:"keepEmptyFolders"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" || req.FilePath == "" { @@ -196,7 +198,7 @@ func (h *Handler) handleGetBlob(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` BlobID string `json:"blobId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" || req.BlobID == "" { @@ -223,7 +225,7 @@ func (h *Handler) handleGetBlobDifferences(body []byte) (any, error) { BeforeBlobID string `json:"beforeBlobId"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -265,7 +267,7 @@ func (h *Handler) handleListFileCommitHistory(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_files_test.go b/services/codecommit/handler_files_test.go index c90375c158..6ac2d9c63d 100644 --- a/services/codecommit/handler_files_test.go +++ b/services/codecommit/handler_files_test.go @@ -2,13 +2,15 @@ package codecommit_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutFile_GetFile(t *testing.T) { @@ -26,7 +28,7 @@ func TestHandler_PutFile_GetFile(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) putBlobID, _ := putResp["blobId"].(string) assert.NotEmpty(t, putBlobID, "PutFileOutput.blobId is a required AWS field") @@ -38,7 +40,7 @@ func TestHandler_PutFile_GetFile(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "hello.txt", resp["filePath"]) assert.Equal( t, @@ -68,7 +70,7 @@ func TestHandler_PutFile_GetFile(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var blobResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &blobResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &blobResp, jsonx.V1())) assert.Equal(t, "aGVsbG8=", blobResp["content"]) } @@ -95,7 +97,7 @@ func TestHandler_PutFile_SameFileContent(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "SameFileContentException", errResp["__type"]) // Different content at the same path must still succeed. @@ -126,7 +128,7 @@ func TestHandler_GetFolder(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) files := resp["files"].([]any) assert.Len(t, files, 1) } @@ -144,7 +146,7 @@ func TestHandler_DeleteFile(t *testing.T) { }) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) putBlobID, _ := putResp["blobId"].(string) require.NotEmpty(t, putBlobID) putCommitID, _ := putResp["commitId"].(string) @@ -161,7 +163,7 @@ func TestHandler_DeleteFile(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["commitId"]) assert.Equal(t, putBlobID, resp["blobId"], "DeleteFileOutput.blobId must report the blob that was removed from the tree") @@ -183,7 +185,7 @@ func TestHandler_DeleteFile_NotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "FileDoesNotExistException", resp["__type"]) } @@ -211,7 +213,7 @@ func TestHandler_DeleteFile_ParentCommitIdRequired(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ParentCommitIdRequiredException", resp["__type"]) } @@ -243,7 +245,7 @@ func TestHandler_DeleteFile_ParentCommitIdOutdated(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ParentCommitIdOutdatedException", resp["__type"]) } @@ -268,7 +270,7 @@ func TestHandler_GetBlob(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fr map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &fr)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &fr, jsonx.V1())) blobID := fr["blobId"].(string) rec = doRequest(t, h, "GetBlob", map[string]any{ @@ -278,7 +280,7 @@ func TestHandler_GetBlob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["content"]) } @@ -295,7 +297,7 @@ func TestHandler_ListFileCommitHistory(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["revisionDag"]) } @@ -322,7 +324,7 @@ func TestHandler_ListFileCommitHistory_RevisionDagShape(t *testing.T) { }) require.Equal(t, http.StatusOK, firstRec.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstResp, jsonx.V1())) firstCommitID, _ := firstResp["commitId"].(string) require.NotEmpty(t, firstCommitID) @@ -335,7 +337,7 @@ func TestHandler_ListFileCommitHistory_RevisionDagShape(t *testing.T) { }) require.Equal(t, http.StatusOK, secondRec.Code) var secondResp map[string]any - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondResp, jsonx.V1())) secondCommitID, _ := secondResp["commitId"].(string) require.NotEmpty(t, secondCommitID) @@ -346,7 +348,7 @@ func TestHandler_ListFileCommitHistory_RevisionDagShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag, ok := resp["revisionDag"].([]any) require.True(t, ok) require.Len(t, dag, 2) @@ -406,7 +408,7 @@ func TestHandler_ListFileCommitHistory_IncludesPutFileWrites(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag, ok := resp["revisionDag"].([]any) require.True(t, ok) require.Len(t, dag, 1, "the PutFile commit must appear in the file's history") @@ -437,7 +439,7 @@ func TestHandler_ListFileCommitHistory_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ := resp["commitId"].(string) require.NotEmpty(t, id) commitIDs = append(commitIDs, id) @@ -460,7 +462,7 @@ func TestHandler_ListFileCommitHistory_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag, ok := resp["revisionDag"].([]any) require.True(t, ok) assert.LessOrEqual(t, len(dag), 2, "each page must respect maxResults") @@ -536,7 +538,7 @@ func TestHandler_ListFileCommitHistory_TableDriven(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag := resp["revisionDag"].([]any) assert.Len(t, dag, tt.seedCommits) }) @@ -566,7 +568,7 @@ func TestHandler_FileLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "src/main.go", resp["filePath"]) assert.NotEmpty(t, resp["blobId"]) putCommitID, _ := resp["commitId"].(string) @@ -583,7 +585,7 @@ func TestHandler_FileLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) files := resp["files"].([]any) assert.Len(t, files, 1) @@ -664,7 +666,7 @@ func TestGetFolder_AlwaysIncludesSubArrays(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // files array must always be present and correct count. files, ok := resp["files"].([]any) @@ -747,7 +749,7 @@ func TestListFileCommitHistory_FiltersByFilePath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag := resp["revisionDag"].([]any) assert.Len(t, dag, tt.wantCount, "revisionDag must contain %d commits for path %q", tt.wantCount, tt.queryPath) diff --git a/services/codecommit/handler_merges.go b/services/codecommit/handler_merges.go index 8967a767a0..ca59538d2b 100644 --- a/services/codecommit/handler_merges.go +++ b/services/codecommit/handler_merges.go @@ -2,10 +2,11 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type batchDescribeMergeConflictsInput struct { @@ -29,7 +30,7 @@ func isValidMergeOption(opt string) bool { func (h *Handler) handleBatchDescribeMergeConflicts(body []byte) (any, error) { var in batchDescribeMergeConflictsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -106,7 +107,7 @@ func (h *Handler) handleMergePullRequest(ctx context.Context, option string, bod Email string `json:"email"` mergeSettingsWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -157,7 +158,7 @@ func (h *Handler) handleMergeBranchesByFastForward(body []byte) (any, error) { DestinationCommitSpecifier string `json:"destinationCommitSpecifier"` TargetBranch string `json:"targetBranch"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -184,7 +185,7 @@ func (h *Handler) handleGetMergeOptions(body []byte) (any, error) { DestinationCommitSpecifier string `json:"destinationCommitSpecifier"` mergeSettingsWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -229,7 +230,7 @@ func (h *Handler) handleCreateUnreferencedMergeCommit(body []byte) (any, error) CommitMessage string `json:"commitMessage"` mergeSettingsWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -273,7 +274,7 @@ func (h *Handler) handleGetMergeCommit(body []byte) (any, error) { DestinationCommitSpecifier string `json:"destinationCommitSpecifier"` mergeSettingsWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -307,7 +308,7 @@ func (h *Handler) handleGetMergeConflicts(body []byte) (any, error) { MergeOption string `json:"mergeOption"` mergeQueryWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -372,7 +373,7 @@ func (h *Handler) handleDescribeMergeConflicts(body []byte) (any, error) { FilePath string `json:"filePath"` mergeQueryWire } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -458,7 +459,7 @@ func (r mergeBranchesRequest) options() (MergeBranchesOptions, error) { func (h *Handler) handleMergeBranchesBySquash(body []byte) (any, error) { var req mergeBranchesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -485,7 +486,7 @@ func (h *Handler) handleMergeBranchesBySquash(body []byte) (any, error) { func (h *Handler) handleMergeBranchesByThreeWay(body []byte) (any, error) { var req mergeBranchesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_merges_test.go b/services/codecommit/handler_merges_test.go index f7b32ac05b..0bbd37d313 100644 --- a/services/codecommit/handler_merges_test.go +++ b/services/codecommit/handler_merges_test.go @@ -1,13 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -86,7 +87,7 @@ func TestHandler_BatchDescribeMergeConflicts(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "conflicts") assert.Contains(t, resp, "destinationCommitId") assert.Contains(t, resp, "sourceCommitId") @@ -151,7 +152,7 @@ func TestHandler_BatchDescribeMergeConflicts_TableDriven(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) conflicts := resp["conflicts"].([]any) assert.Len(t, conflicts, tt.wantConflicts) assert.Len(t, resp["errors"], tt.wantErrors) @@ -174,7 +175,7 @@ func TestHandler_MergePullRequestByFastForward(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "CLOSED", pr["pullRequestStatus"]) } @@ -193,7 +194,7 @@ func TestHandler_MergePullRequestBySquash(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "CLOSED", pr["pullRequestStatus"]) } @@ -212,7 +213,7 @@ func TestHandler_MergePullRequestByThreeWay(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "CLOSED", pr["pullRequestStatus"]) } @@ -233,7 +234,7 @@ func TestHandler_MergeBranchesByFastForward(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal( t, sourceTip, @@ -271,7 +272,7 @@ func TestHandler_MergeBranchesByFastForward_UnknownSpecifier(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CommitDoesNotExistException", resp["__type"]) }) } @@ -295,7 +296,7 @@ func TestHandler_MergeBranchesBySquash(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commitID, _ := resp["commitId"].(string) require.NotEmpty(t, commitID) @@ -306,7 +307,7 @@ func TestHandler_MergeBranchesBySquash(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) commit, ok := getResp["commit"].(map[string]any) require.True(t, ok) assert.Equal(t, "squash it", commit["message"]) @@ -333,7 +334,7 @@ func TestHandler_MergeBranchesByThreeWay(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commitID, _ := resp["commitId"].(string) require.NotEmpty(t, commitID) @@ -344,7 +345,7 @@ func TestHandler_MergeBranchesByThreeWay(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) commit, ok := getResp["commit"].(map[string]any) require.True(t, ok) parents, ok := commit["parents"].([]any) @@ -373,7 +374,7 @@ func TestHandler_MergeBranchesBySquash_TargetBranch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) commitID, _ := resp["commitId"].(string) assert.Equal(t, commitID, mustBranchTip(t, h, "sq-target-repo", "release"), @@ -408,7 +409,7 @@ func mustBranchTip(t *testing.T, h *codecommit.Handler, repoName, branchName str require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) branch, ok := resp["branch"].(map[string]any) require.True(t, ok) commitID, _ := branch["commitId"].(string) @@ -443,7 +444,7 @@ func TestHandler_MergeBranches_AllStrategies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["commitId"]) assert.NotEmpty(t, resp["treeId"]) }) @@ -465,7 +466,7 @@ func TestHandler_GetMergeOptions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) opts := resp["mergeOptions"].([]any) assert.Len(t, opts, 3) @@ -475,7 +476,7 @@ func TestHandler_GetMergeOptions(t *testing.T) { CommitID string `json:"commitId"` } `json:"branch"` } - require.NoError(t, json.Unmarshal(branch.Body.Bytes(), &branchResp)) + require.NoError(t, json.Unmarshal(branch.Body.Bytes(), &branchResp, jsonx.V1())) assert.Equal(t, branchResp.Branch.CommitID, resp["destinationCommitId"]) assert.Equal(t, branchResp.Branch.CommitID, resp["baseCommitId"], "feature forked from main's tip") } @@ -512,7 +513,7 @@ func TestHandler_MergeOptions_AllStrategies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) opts := resp["mergeOptions"].([]any) assert.Len(t, opts, 3) @@ -541,7 +542,7 @@ func TestHandler_CreateUnreferencedMergeCommit(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["commitId"]) } @@ -593,7 +594,7 @@ func TestHandler_CreateUnreferencedMergeCommit_Success(t *testing.T) { require.Equal(t, http.StatusOK, branchRec.Code) var brResp map[string]any - require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &brResp)) + require.NoError(t, json.Unmarshal(branchRec.Body.Bytes(), &brResp, jsonx.V1())) commitID := brResp["branch"].(map[string]any)["commitId"].(string) rec := doRequest(t, h, "CreateUnreferencedMergeCommit", map[string]any{ @@ -605,7 +606,7 @@ func TestHandler_CreateUnreferencedMergeCommit_Success(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["commitId"]) assert.NotEmpty(t, resp["treeId"]) } @@ -631,7 +632,7 @@ func TestHandler_GetMergeCommit(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["mergedCommitId"]) assert.NotEmpty( t, @@ -672,7 +673,7 @@ func TestGetMergeCommit_ResolvesParents(t *testing.T) { require.Equal(t, http.StatusOK, baseRec.Code) var baseOut map[string]any - require.NoError(t, json.Unmarshal(baseRec.Body.Bytes(), &baseOut)) + require.NoError(t, json.Unmarshal(baseRec.Body.Bytes(), &baseOut, jsonx.V1())) baseCommitID := baseOut["commitId"].(string) // Create feature branch from base. @@ -691,7 +692,7 @@ func TestGetMergeCommit_ResolvesParents(t *testing.T) { require.Equal(t, http.StatusOK, featureRec.Code) var featureOut map[string]any - require.NoError(t, json.Unmarshal(featureRec.Body.Bytes(), &featureOut)) + require.NoError(t, json.Unmarshal(featureRec.Body.Bytes(), &featureOut, jsonx.V1())) featureCommitID := featureOut["commitId"].(string) // Fast-forward merge. @@ -712,7 +713,7 @@ func TestGetMergeCommit_ResolvesParents(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["mergedCommitId"], "GetMergeCommit must return a non-empty mergedCommitId") } @@ -733,7 +734,7 @@ func TestHandler_GetMergeConflicts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // No content-diff engine backs this emulator, so a merge between two // resolvable specifiers is always reported mergeable (see PARITY.md gaps). assert.Equal(t, true, resp["mergeable"]) @@ -757,7 +758,7 @@ func TestHandler_GetMergeConflicts_NoConflicts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["mergeable"]) } @@ -855,7 +856,7 @@ func TestHandler_DescribeMergeConflicts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEqual(t, "feature", resp["sourceCommitId"], "specifiers resolve to commit IDs") assert.NotEmpty(t, resp["sourceCommitId"]) assert.NotEmpty(t, resp["destinationCommitId"]) diff --git a/services/codecommit/handler_pull_request_approvals_test.go b/services/codecommit/handler_pull_request_approvals_test.go index f93034a7bc..1d047eb431 100644 --- a/services/codecommit/handler_pull_request_approvals_test.go +++ b/services/codecommit/handler_pull_request_approvals_test.go @@ -1,13 +1,15 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetPullRequestApprovalStates(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_GetPullRequestApprovalStates(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["approvals"]) } @@ -109,7 +111,7 @@ func TestHandler_GetPullRequestApprovalStates_TableDriven(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) approvals := resp["approvals"].([]any) // Each UpdatePullRequestApprovalState with the same (empty) userARN just overwrites, so max 1. if tt.approveUsers > 0 { @@ -148,7 +150,7 @@ func TestHandler_GetPullRequestOverrideState(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, false, resp["overridden"]) } @@ -166,7 +168,7 @@ func TestHandler_GetPullRequestOverrideState_AfterOverride(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, false, resp["overridden"]) // Override it. @@ -182,7 +184,7 @@ func TestHandler_GetPullRequestOverrideState_AfterOverride(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["overridden"]) } @@ -214,7 +216,7 @@ func TestHandler_CreatePullRequestApprovalRule(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["approvalRule"].(map[string]any) assert.Equal(t, "my-rule", rule["approvalRuleName"]) } @@ -270,7 +272,7 @@ func TestHandler_DescribePullRequestEvents(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["pullRequestEvents"]) } @@ -343,7 +345,7 @@ func TestHandler_DescribePullRequestEvents_TableDriven(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events := resp["pullRequestEvents"].([]any) assert.Len(t, events, tt.wantEvents) }) @@ -369,7 +371,7 @@ func TestHandler_EvaluatePullRequestApprovalRules(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eval := resp["evaluation"].(map[string]any) satisfied := eval["approvalRulesSatisfied"].([]any) require.Len(t, satisfied, 1) @@ -404,7 +406,7 @@ func TestHandler_EvaluatePullRequestApprovalRules_WithRules(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eval := resp["evaluation"].(map[string]any) satisfied := eval["approvalRulesSatisfied"].([]any) assert.Len(t, satisfied, 2) @@ -425,7 +427,7 @@ func TestHandler_PullRequestApprovalRule_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["approvalRule"].(map[string]any) assert.Equal(t, "my-rule", rule["approvalRuleName"]) assert.NotEmpty(t, rule["approvalRuleId"]) @@ -445,7 +447,7 @@ func TestHandler_PullRequestApprovalRule_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eval := resp["evaluation"].(map[string]any) assert.Len(t, eval["approvalRulesSatisfied"].([]any), 1) @@ -463,7 +465,7 @@ func TestHandler_PullRequestApprovalRule_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eval = resp["evaluation"].(map[string]any) assert.Empty(t, eval["approvalRulesSatisfied"]) } diff --git a/services/codecommit/handler_pull_requests.go b/services/codecommit/handler_pull_requests.go index 8ea8e04f99..456b06b35c 100644 --- a/services/codecommit/handler_pull_requests.go +++ b/services/codecommit/handler_pull_requests.go @@ -2,11 +2,12 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -96,7 +97,7 @@ func pullRequestToMap(pr *PullRequest) map[string]any { func (h *Handler) handleCreatePullRequest(body []byte) (any, error) { var in createPullRequestInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -156,7 +157,7 @@ func (h *Handler) handleGetPullRequest(body []byte) (any, error) { var in struct { PullRequestID string `json:"pullRequestId"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -186,7 +187,7 @@ func (h *Handler) handleListPullRequests(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -226,7 +227,7 @@ func (h *Handler) handleGetPullRequestApprovalStates(body []byte) (any, error) { PullRequestID string `json:"pullRequestId"` RevisionID string `json:"revisionId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -252,7 +253,7 @@ func (h *Handler) handleGetPullRequestOverrideState(body []byte) (any, error) { PullRequestID string `json:"pullRequestId"` RevisionID string `json:"revisionId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -287,7 +288,7 @@ func (h *Handler) handleOverridePullRequestApprovalRules(ctx context.Context, bo RevisionID string `json:"revisionId"` OverrideStatus string `json:"overrideStatus"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -309,7 +310,7 @@ func (h *Handler) handleUpdatePullRequestApprovalState(body []byte) (any, error) RevisionID string `json:"revisionId"` ApprovalState string `json:"approvalState"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -328,7 +329,7 @@ func (h *Handler) handleUpdatePullRequestDescription(body []byte) (any, error) { PullRequestID string `json:"pullRequestId"` Description string `json:"description"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -354,7 +355,7 @@ func (h *Handler) handleUpdatePullRequestStatus(body []byte) (any, error) { PullRequestID string `json:"pullRequestId"` PullRequestStatus string `json:"pullRequestStatus"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -383,7 +384,7 @@ func (h *Handler) handleUpdatePullRequestTitle(body []byte) (any, error) { PullRequestID string `json:"pullRequestId"` Title string `json:"title"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -410,7 +411,7 @@ func (h *Handler) handleCreatePullRequestApprovalRule(body []byte) (any, error) ApprovalRuleName string `json:"approvalRuleName"` ApprovalRuleContent string `json:"approvalRuleContent"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" || req.ApprovalRuleName == "" { @@ -441,7 +442,7 @@ func (h *Handler) handleDeletePullRequestApprovalRule(body []byte) (any, error) PullRequestID string `json:"pullRequestId"` ApprovalRuleName string `json:"approvalRuleName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" || req.ApprovalRuleName == "" { @@ -468,7 +469,7 @@ func (h *Handler) handleUpdatePullRequestApprovalRuleContent(body []byte) (any, NewRuleContent string `json:"newRuleContent"` ExistingSha string `json:"existingRuleContentSha256"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" || req.ApprovalRuleName == "" { @@ -500,7 +501,7 @@ func (h *Handler) handleDescribePullRequestEvents(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { @@ -548,7 +549,7 @@ func (h *Handler) handleEvaluatePullRequestApprovalRules(body []byte) (any, erro PullRequestID string `json:"pullRequestId"` RevisionID string `json:"revisionId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.PullRequestID == "" { diff --git a/services/codecommit/handler_pull_requests_test.go b/services/codecommit/handler_pull_requests_test.go index ba106176d6..d286eb645b 100644 --- a/services/codecommit/handler_pull_requests_test.go +++ b/services/codecommit/handler_pull_requests_test.go @@ -1,13 +1,15 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreatePullRequest(t *testing.T) { @@ -82,7 +84,7 @@ func TestHandler_CreatePullRequest(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr, ok := resp["pullRequest"].(map[string]any) require.True(t, ok, "pullRequest key should be present") @@ -154,7 +156,7 @@ func TestHandler_CreatePullRequest_RepoMetadataInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.NotEmpty(t, pr["pullRequestId"]) @@ -226,7 +228,7 @@ func TestHandler_ListPullRequests_StatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["pullRequest"].(map[string]any)["pullRequestId"].(string) } @@ -249,7 +251,7 @@ func TestHandler_ListPullRequests_StatusFilter(t *testing.T) { if tt.wantHTTPCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids := resp["pullRequestIds"].([]any) assert.Len(t, ids, tt.wantCount) } @@ -276,7 +278,7 @@ func TestHandler_ListPullRequests_ClosedFilterIncludesMerged(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var mergeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mergeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mergeResp, jsonx.V1())) mergedPR := mergeResp["pullRequest"].(map[string]any) assert.Equal( t, "CLOSED", mergedPR["pullRequestStatus"], @@ -290,7 +292,7 @@ func TestHandler_ListPullRequests_ClosedFilterIncludesMerged(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) ids := listResp["pullRequestIds"].([]any) require.Len(t, ids, 1) assert.Equal(t, prID, ids[0]) @@ -317,7 +319,7 @@ func TestHandler_ListPullRequests_NumericDescendingOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids := resp["pullRequestIds"].([]any) require.Len(t, ids, 3) @@ -361,7 +363,7 @@ func TestHandler_MergePullRequest_AlreadyMerged(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prID := resp["pullRequest"].(map[string]any)["pullRequestId"].(string) // First merge — should succeed. @@ -373,7 +375,7 @@ func TestHandler_MergePullRequest_AlreadyMerged(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "PullRequestAlreadyClosedException", errResp["__type"]) }) } @@ -405,13 +407,13 @@ func TestHandler_MergePullRequest_StatusBecomesClosed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prID := resp["pullRequest"].(map[string]any)["pullRequestId"].(string) rec = doRequest(t, h, strategy, map[string]any{"pullRequestId": prID}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mergedPR := resp["pullRequest"].(map[string]any) assert.Equal(t, "CLOSED", mergedPR["pullRequestStatus"]) }) @@ -431,7 +433,7 @@ func TestHandler_UpdatePullRequestStatus(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "CLOSED", pr["pullRequestStatus"]) } @@ -488,7 +490,7 @@ func TestHandler_UpdatePullRequestStatus_Validation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prID := resp["pullRequest"].(map[string]any)["pullRequestId"].(string) rec = doRequest(t, h, "UpdatePullRequestStatus", map[string]any{ @@ -552,7 +554,7 @@ func TestHandler_UpdatePullRequestStatus_TableDriven(t *testing.T) { if tt.wantErrType != "" { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp["__type"]) } }) @@ -581,7 +583,7 @@ func TestHandler_PullRequest_FieldsPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr, ok := resp["pullRequest"].(map[string]any) require.True(t, ok) @@ -619,7 +621,7 @@ func TestHandler_UpdatePullRequestDescription(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "new description", pr["description"]) } @@ -637,7 +639,7 @@ func TestHandler_UpdatePullRequestDescription_Reflected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "A much better description", pr["description"]) } @@ -655,7 +657,7 @@ func TestHandler_UpdatePullRequestTitle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "updated title", pr["title"]) } @@ -673,7 +675,7 @@ func TestHandler_UpdatePullRequestTitle_Reflected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) assert.Equal(t, "Updated Title", pr["title"]) assert.Equal(t, prID, pr["pullRequestId"]) diff --git a/services/codecommit/handler_reactions.go b/services/codecommit/handler_reactions.go index a55c68a7e5..97e15f499a 100644 --- a/services/codecommit/handler_reactions.go +++ b/services/codecommit/handler_reactions.go @@ -2,11 +2,12 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -22,7 +23,7 @@ func (h *Handler) handleGetCommentReactions(body []byte) (any, error) { NextToken string `json:"nextToken"` MaxResults int `json:"maxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.CommentID == "" { @@ -97,7 +98,7 @@ func (h *Handler) handlePutCommentReaction(ctx context.Context, body []byte) (an CommentID string `json:"commentId"` ReactionValue string `json:"reactionValue"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.CommentID == "" || req.ReactionValue == "" { diff --git a/services/codecommit/handler_reactions_test.go b/services/codecommit/handler_reactions_test.go index d76ff6c898..ece4dfdd1d 100644 --- a/services/codecommit/handler_reactions_test.go +++ b/services/codecommit/handler_reactions_test.go @@ -1,12 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetCommentReactions(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_GetCommentReactions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) cID := cr["comment"].(map[string]any)["commentId"].(string) doRequest(t, h, "PutCommentReaction", map[string]any{ @@ -35,7 +37,7 @@ func TestHandler_GetCommentReactions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) reactions := resp["reactionsForComment"].([]any) assert.Len(t, reactions, 1) } @@ -54,7 +56,7 @@ func TestHandler_PutCommentReaction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) cID := cr["comment"].(map[string]any)["commentId"].(string) rec = doRequest(t, h, "PutCommentReaction", map[string]any{ diff --git a/services/codecommit/handler_repositories.go b/services/codecommit/handler_repositories.go index 7ec8f411f1..d2c5ec6aef 100644 --- a/services/codecommit/handler_repositories.go +++ b/services/codecommit/handler_repositories.go @@ -1,10 +1,12 @@ package codecommit import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createRepositoryInput struct { @@ -52,7 +54,7 @@ func repoMetadata(r *Repository) map[string]any { func (h *Handler) handleCreateRepository(body []byte) (any, error) { var in createRepositoryInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -72,7 +74,7 @@ func (h *Handler) handleCreateRepository(body []byte) (any, error) { func (h *Handler) handleGetRepository(body []byte) (any, error) { var in getRepositoryInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -88,7 +90,7 @@ func (h *Handler) handleGetRepository(body []byte) (any, error) { func (h *Handler) handleDeleteRepository(body []byte) (any, error) { var in deleteRepositoryInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -113,7 +115,7 @@ func (h *Handler) handleListRepositories(body []byte) (any, error) { MaxResults int `json:"maxResults"` } // Ignore parse errors — all fields are optional. - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) if in.SortBy != "" && in.SortBy != "repositoryName" && in.SortBy != "lastModifiedDate" { return nil, fmt.Errorf("%w: sortBy %q is not valid", ErrInvalidSortBy, in.SortBy) @@ -169,7 +171,7 @@ func (h *Handler) handleListRepositories(body []byte) (any, error) { func (h *Handler) handleBatchGetRepositories(body []byte) (any, error) { var in batchGetRepositoriesInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -198,7 +200,7 @@ func (h *Handler) handleUpdateRepositoryDescription(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` RepositoryDescription string `json:"repositoryDescription"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -213,7 +215,7 @@ func (h *Handler) handleUpdateRepositoryName(body []byte) (any, error) { OldName string `json:"oldName"` NewName string `json:"newName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.OldName == "" || req.NewName == "" { @@ -228,7 +230,7 @@ func (h *Handler) handleUpdateRepositoryEncryptionKey(body []byte) (any, error) RepositoryName string `json:"repositoryName"` KmsKeyID string `json:"kmsKeyId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_repositories_test.go b/services/codecommit/handler_repositories_test.go index 9a69db037a..9977cb07bf 100644 --- a/services/codecommit/handler_repositories_test.go +++ b/services/codecommit/handler_repositories_test.go @@ -1,13 +1,15 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateRepository(t *testing.T) { @@ -48,7 +50,7 @@ func TestHandler_CreateRepository(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta, ok := resp["repositoryMetadata"].(map[string]any) require.True(t, ok, "repositoryMetadata should be present") @@ -182,7 +184,7 @@ func TestHandler_ListRepositories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, ok := resp["repositories"].([]any) require.True(t, ok) @@ -221,7 +223,7 @@ func TestHandler_SortedListRepositories(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["repositories"].([]any) require.True(t, ok) @@ -287,7 +289,7 @@ func TestHandler_DeleteRepository_Cascade_Comments(t *testing.T) { }) require.Equal(t, http.StatusOK, commitRec.Code) var commitOut map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitOut, jsonx.V1())) commitID := commitOut["commitId"].(string) commentRec := doRequest(t, h, "PostCommentForComparedCommit", map[string]any{ @@ -297,7 +299,7 @@ func TestHandler_DeleteRepository_Cascade_Comments(t *testing.T) { }) require.Equal(t, http.StatusOK, commentRec.Code) var commentOut map[string]any - require.NoError(t, json.Unmarshal(commentRec.Body.Bytes(), &commentOut)) + require.NoError(t, json.Unmarshal(commentRec.Body.Bytes(), &commentOut, jsonx.V1())) comment, ok := commentOut["comment"].(map[string]any) require.True(t, ok) commentID, _ := comment["commentId"].(string) @@ -346,7 +348,7 @@ func TestHandler_DeleteRepository_Cascade_FileHistory(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dag, ok := resp["revisionDag"].([]any) require.True(t, ok) assert.Empty(t, dag, @@ -365,7 +367,7 @@ func TestHandler_RepoMetadataTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta, ok := resp["repositoryMetadata"].(map[string]any) require.True(t, ok) @@ -446,7 +448,7 @@ func TestHandler_RepoMetadata_DefaultBranchAndKmsKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta := resp["repositoryMetadata"].(map[string]any) _, hasDefault := meta["defaultBranch"] _, hasKms := meta["kmsKeyId"] @@ -479,7 +481,7 @@ func TestHandler_RepoMetadata_DefaultBranchAndKmsKey(t *testing.T) { rec = doRequest(t, h, "GetRepository", map[string]any{"repositoryName": "repo"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta = resp["repositoryMetadata"].(map[string]any) assert.Equal(t, "main", meta["defaultBranch"]) assert.Equal(t, "arn:aws:kms:us-east-1:123456789012:key/my-key", meta["kmsKeyId"]) @@ -539,7 +541,7 @@ func TestHandler_BatchGetRepositories(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, _ := resp["repositories"].([]any) assert.Len(t, repos, tt.wantFoundCount) @@ -569,7 +571,7 @@ func TestHandler_BatchGetRepositories_MaxLimit(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "MaximumRepositoryNamesExceededException", errResp["__type"]) // Request 25 — should succeed. @@ -591,7 +593,7 @@ func TestHandler_BatchGetRepositories_PartialFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos := resp["repositories"].([]any) notFound := resp["repositoriesNotFound"].([]any) @@ -615,7 +617,7 @@ func TestHandler_GetRepository_FullMetadata(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta := resp["repositoryMetadata"].(map[string]any) assert.NotEmpty(t, meta["repositoryId"]) @@ -644,7 +646,7 @@ func TestHandler_UpdateRepositoryDescription_Reflected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta := resp["repositoryMetadata"].(map[string]any) assert.Equal(t, "new description", meta["repositoryDescription"]) } @@ -657,7 +659,7 @@ func TestHandler_CreateRepository_InvalidName_ErrorType(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidRepositoryNameException", errResp["__type"]) } diff --git a/services/codecommit/handler_tags.go b/services/codecommit/handler_tags.go index 67cd8da3ab..b365ac1fbc 100644 --- a/services/codecommit/handler_tags.go +++ b/services/codecommit/handler_tags.go @@ -1,8 +1,10 @@ package codecommit import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceInput struct { @@ -21,7 +23,7 @@ type listTagsForResourceInput struct { func (h *Handler) handleTagResource(body []byte) (any, error) { var in tagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -38,7 +40,7 @@ func (h *Handler) handleTagResource(body []byte) (any, error) { func (h *Handler) handleUntagResource(body []byte) (any, error) { var in untagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } @@ -55,7 +57,7 @@ func (h *Handler) handleUntagResource(body []byte) (any, error) { func (h *Handler) handleListTagsForResource(body []byte) (any, error) { var in listTagsForResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request body: %w", err) } diff --git a/services/codecommit/handler_tags_test.go b/services/codecommit/handler_tags_test.go index f6e6e7c6bb..750b9b5c6c 100644 --- a/services/codecommit/handler_tags_test.go +++ b/services/codecommit/handler_tags_test.go @@ -1,13 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -31,7 +32,7 @@ func TestHandler_TagAndUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) metaRaw, ok := resp["repositoryMetadata"] require.True(t, ok) @@ -61,7 +62,7 @@ func TestHandler_TagAndUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) metaRaw, ok := resp["repositoryMetadata"] require.True(t, ok) @@ -127,7 +128,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) metaRaw, ok := resp["repositoryMetadata"] require.True(t, ok) @@ -169,7 +170,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagsRaw, ok := resp["tags"].(map[string]any) require.True(t, ok) @@ -192,7 +193,7 @@ func TestHandler_ARN_TagOps_O1(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) meta := createResp["repositoryMetadata"].(map[string]any) repoARN := meta["Arn"].(string) @@ -212,7 +213,7 @@ func TestHandler_ARN_TagOps_O1(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tagMap, ok := tagsResp["tags"].(map[string]any) require.True(t, ok) @@ -231,7 +232,7 @@ func TestHandler_ARN_TagOps_O1(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tagMap, _ = tagsResp["tags"].(map[string]any) assert.Empty(t, tagMap) } diff --git a/services/codecommit/handler_test.go b/services/codecommit/handler_test.go index 4a121736db..c50b9d72aa 100644 --- a/services/codecommit/handler_test.go +++ b/services/codecommit/handler_test.go @@ -2,7 +2,7 @@ package codecommit_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *codecommit.Handler, action string, body any) *ht if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -74,7 +75,7 @@ func createBranchFromMain(t *testing.T, h *codecommit.Handler, repoName, branchN require.Equal(t, http.StatusOK, rec.Code) var branchResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &branchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &branchResp, jsonx.V1())) branchInfo, ok := branchResp["branch"].(map[string]any) require.True(t, ok, "GetBranch response must include a branch object") tipCommitID, _ := branchInfo["commitId"].(string) @@ -111,7 +112,7 @@ func setupPR(t *testing.T, h *codecommit.Handler, repoName string) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pr := resp["pullRequest"].(map[string]any) @@ -578,7 +579,7 @@ func TestHandler_ErrorTypes(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -643,7 +644,7 @@ func TestHandler_NotFoundErrorTypes_AreResourceSpecific(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) }) } diff --git a/services/codecommit/handler_triggers.go b/services/codecommit/handler_triggers.go index 4f9a2ebbc1..ae54ab1d90 100644 --- a/services/codecommit/handler_triggers.go +++ b/services/codecommit/handler_triggers.go @@ -1,15 +1,17 @@ package codecommit import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetRepositoryTriggers(body []byte) (any, error) { var req struct { RepositoryName string `json:"repositoryName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -32,7 +34,7 @@ func (h *Handler) handlePutRepositoryTriggers(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` Triggers []RepositoryTrigger `json:"triggers"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { @@ -53,7 +55,7 @@ func (h *Handler) handleTestRepositoryTriggers(body []byte) (any, error) { RepositoryName string `json:"repositoryName"` Triggers []RepositoryTrigger `json:"triggers"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } if req.RepositoryName == "" { diff --git a/services/codecommit/handler_triggers_test.go b/services/codecommit/handler_triggers_test.go index 9ac61811bf..6b013cc8f6 100644 --- a/services/codecommit/handler_triggers_test.go +++ b/services/codecommit/handler_triggers_test.go @@ -1,12 +1,14 @@ package codecommit_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutGetRepositoryTriggers(t *testing.T) { @@ -33,7 +35,7 @@ func TestHandler_PutGetRepositoryTriggers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) triggers := resp["triggers"].([]any) assert.Len(t, triggers, 1) } @@ -76,7 +78,7 @@ func TestHandler_TestRepositoryTriggers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) succeeded := resp["successfulExecutions"].([]any) require.Len(t, succeeded, 1) assert.Equal(t, "ad-hoc-trigger", succeeded[0]) @@ -89,7 +91,7 @@ func TestHandler_TestRepositoryTriggers(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) succeeded = resp["successfulExecutions"].([]any) assert.Empty(t, succeeded) } @@ -123,7 +125,7 @@ func TestHandler_TriggerLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) got := resp["triggers"].([]any) assert.Len(t, got, 2) @@ -134,7 +136,7 @@ func TestHandler_TriggerLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) succeeded := resp["successfulExecutions"].([]any) assert.Len(t, succeeded, 2) @@ -148,7 +150,7 @@ func TestHandler_TriggerLifecycle(t *testing.T) { rec = doRequest(t, h, "GetRepositoryTriggers", map[string]any{"repositoryName": "repo"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) got = resp["triggers"].([]any) assert.Empty(t, got) } diff --git a/services/codecommit/multi_region_test.go b/services/codecommit/multi_region_test.go index d6fc3fc89c..60b7e22645 100644 --- a/services/codecommit/multi_region_test.go +++ b/services/codecommit/multi_region_test.go @@ -2,7 +2,7 @@ package codecommit_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codecommit" ) @@ -40,7 +41,7 @@ func regionCall(t *testing.T, h *codecommit.Handler, region, op, body string) ma require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/codecommit/persistence.go b/services/codecommit/persistence.go index a30c3ec124..4c3b82a9d8 100644 --- a/services/codecommit/persistence.go +++ b/services/codecommit/persistence.go @@ -2,7 +2,7 @@ package codecommit import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -196,7 +196,7 @@ func buildPersistenceDTORegistry() ( // Repositories, and is rebuilt by rebuildRepositoriesByARN on Restore rather // than persisted. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` RepoTemplateAssoc map[string]map[string]struct{} `json:"repoTemplateAssoc"` PRApprovals map[string]map[string]string `json:"prApprovals"` PROverrides map[string]bool `json:"prOverrides"` @@ -337,7 +337,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // prApprovalRules; see store_setup.go's registerAllTables doc) from tables // via the ephemeral DTO registry, factored out of Restore to keep Restore's // own cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtoReg, commentDTOs, fileDTOs, prApprovalRuleDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("codecommit: restore snapshot DTO tables: %w", err) diff --git a/services/codeconnections/handler.go b/services/codeconnections/handler.go index f43f296419..def97581ec 100644 --- a/services/codeconnections/handler.go +++ b/services/codeconnections/handler.go @@ -2,7 +2,7 @@ package codeconnections import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -180,7 +181,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ResourceName string `json:"ResourceName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ConnectionArn != "": @@ -228,7 +229,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleEchoError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -237,7 +238,7 @@ func (h *Handler) handleEchoError(_ context.Context, c *echo.Context, _ string, payload, marshalErr := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: wireMessage(err, errType), - }) + }, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } diff --git a/services/codeconnections/handler_test.go b/services/codeconnections/handler_test.go index 4a04a2608c..7372e4c5a4 100644 --- a/services/codeconnections/handler_test.go +++ b/services/codeconnections/handler_test.go @@ -10,7 +10,7 @@ package codeconnections_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codeconnections" ) @@ -69,7 +70,7 @@ func doJSON( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -90,7 +91,7 @@ func parseResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -401,7 +402,7 @@ func TestExtractOperationAndResource(t *testing.T) { if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/codeconnections/persistence.go b/services/codeconnections/persistence.go index ae5fa540dd..ed5ea92dfb 100644 --- a/services/codeconnections/persistence.go +++ b/services/codeconnections/persistence.go @@ -2,7 +2,7 @@ package codeconnections import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -51,10 +51,10 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // persistenceDTOTables groups the ephemeral DTO tables Snapshot/Restore @@ -187,7 +187,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // syncConfigurations, syncBlockers; see store_setup.go's registerAllTables // doc) from tables via the ephemeral DTO registry, factored out of Restore to // keep Restore's own cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("codeconnections: restore snapshot DTO tables: %w", err) diff --git a/services/codedeploy/application_revisions_test.go b/services/codedeploy/application_revisions_test.go index e1de1c7bf0..893663e256 100644 --- a/services/codedeploy/application_revisions_test.go +++ b/services/codedeploy/application_revisions_test.go @@ -1,13 +1,14 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -42,7 +43,7 @@ func TestHandler_RegisterApplicationRevision_GetApplicationRevision(t *testing.T require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-app", resp["applicationName"]) revisionInfo, ok := resp["revisionInfo"].(map[string]any) @@ -67,7 +68,7 @@ func TestHandler_GetApplicationRevision_NotRegistered(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "RevisionDoesNotExistException", resp["__type"]) } @@ -106,7 +107,7 @@ func TestHandler_RegisterApplicationRevision_Idempotent(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) revisions, ok := listResp["revisions"].([]any) require.True(t, ok) require.Len(t, revisions, 1) @@ -116,7 +117,7 @@ func TestHandler_RegisterApplicationRevision_Idempotent(t *testing.T) { "revision": s3Revision("bucket", "key"), }) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) revisionInfo, ok := getResp["revisionInfo"].(map[string]any) require.True(t, ok) assert.Equal(t, "v2", revisionInfo["description"]) @@ -141,7 +142,7 @@ func TestHandler_ListApplicationRevisions_MultipleAndFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) revisions, ok := resp["revisions"].([]any) require.True(t, ok) require.Len(t, revisions, 2) @@ -153,7 +154,7 @@ func TestHandler_ListApplicationRevisions_MultipleAndFilters(t *testing.T) { require.Equal(t, http.StatusOK, filteredRec.Code) var filteredResp map[string]any - require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp)) + require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp, jsonx.V1())) filtered, ok := filteredResp["revisions"].([]any) require.True(t, ok) require.Len(t, filtered, 1) @@ -298,7 +299,7 @@ func TestHandler_BatchGetApplicationRevisions(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-app", resp["applicationName"]) } }) @@ -330,7 +331,7 @@ func TestHandler_BatchGetApplicationRevisions_PopulatesRegistered(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) revisions, ok := resp["revisions"].([]any) require.True(t, ok) require.Len(t, revisions, 2) diff --git a/services/codedeploy/applications_test.go b/services/codedeploy/applications_test.go index f009d3fc19..0f7df24d61 100644 --- a/services/codedeploy/applications_test.go +++ b/services/codedeploy/applications_test.go @@ -1,7 +1,7 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -71,7 +72,7 @@ func TestHandler_CreateApplication(t *testing.T) { if tt.wantAppID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["applicationId"]) } }) @@ -118,7 +119,7 @@ func TestHandler_CreateApplication_ComputePlatformValidation(t *testing.T) { if tt.wantErrType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) } }) @@ -175,7 +176,7 @@ func TestHandler_ListApplications(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps, ok := resp["applications"].([]any) require.True(t, ok) assert.Empty(t, apps) @@ -184,7 +185,7 @@ func TestHandler_ListApplications(t *testing.T) { doRequest(t, h, "CreateApplication", map[string]any{"applicationName": "app2"}) rec = doRequest(t, h, "ListApplications", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps, ok = resp["applications"].([]any) require.True(t, ok) assert.Len(t, apps, 2) @@ -206,7 +207,7 @@ func TestApplications_SortedList(t *testing.T) { Applications []string `json:"applications"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, []string{"apple", "mango", "zebra"}, resp.Applications) } @@ -329,7 +330,7 @@ func TestHandler_BatchGetApplications(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) infos, ok := resp["applicationsInfo"].([]any) require.True(t, ok) assert.Len(t, infos, tt.wantCount) diff --git a/services/codedeploy/deployment_configs_test.go b/services/codedeploy/deployment_configs_test.go index 2eca2a61c7..49ade1a09a 100644 --- a/services/codedeploy/deployment_configs_test.go +++ b/services/codedeploy/deployment_configs_test.go @@ -1,12 +1,14 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateDeploymentConfig(t *testing.T) { @@ -57,7 +59,7 @@ func TestHandler_CreateDeploymentConfig(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["deploymentConfigId"]) } }) @@ -240,7 +242,7 @@ func TestDeploymentConfigs_SubStructs(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tt.checkFn(t, resp["deploymentConfigInfo"]) } }) @@ -270,7 +272,7 @@ func TestDeploymentConfigs_DefaultsSeeded(t *testing.T) { var resp struct { DeploymentConfigsList []string `json:"deploymentConfigsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, name := range expectedDefaults { assert.Contains(t, resp.DeploymentConfigsList, name, "missing default config: %s", name) @@ -324,7 +326,7 @@ func TestDeploymentConfigs_DefaultsReturnSubStructs(t *testing.T) { ComputePlatform string `json:"computePlatform"` } `json:"deploymentConfigInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantPlatform, resp.DeploymentConfigInfo.ComputePlatform) require.NotNil(t, resp.DeploymentConfigInfo.TrafficRoutingConfig) assert.Equal(t, tt.wantRoutingType, resp.DeploymentConfigInfo.TrafficRoutingConfig.Type) @@ -342,7 +344,7 @@ func TestDeploymentConfigs_DefaultsCannotDelete(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // DeleteDeploymentConfig's own deserializer models InvalidOperationException // for this case, not DeploymentConfigInUseException (verified against // aws-sdk-go-v2/service/codedeploy deserializers.go). @@ -382,7 +384,7 @@ func TestDeploymentConfigs_InUseCannotDelete(t *testing.T) { assert.Equal(t, http.StatusConflict, delRec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DeploymentConfigInUseException", resp["__type"]) } @@ -400,7 +402,7 @@ func TestDeploymentConfigs_ErrInvalidComputePlatformMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidComputePlatformException", resp["__type"]) } diff --git a/services/codedeploy/deployment_group_tag_filters_test.go b/services/codedeploy/deployment_group_tag_filters_test.go index c9ce92ccf2..7c7783d46a 100644 --- a/services/codedeploy/deployment_group_tag_filters_test.go +++ b/services/codedeploy/deployment_group_tag_filters_test.go @@ -1,13 +1,15 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func ec2TagSetPayload() map[string]any { @@ -124,7 +126,7 @@ func TestDeploymentGroups_TagFilterValidation_Create(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -219,7 +221,7 @@ func TestDeploymentGroups_TagFilterValidation_Update(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) diff --git a/services/codedeploy/deployment_groups_test.go b/services/codedeploy/deployment_groups_test.go index e75db1b623..d45aa51e3b 100644 --- a/services/codedeploy/deployment_groups_test.go +++ b/services/codedeploy/deployment_groups_test.go @@ -1,7 +1,7 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -68,7 +69,7 @@ func TestHandler_CreateDeploymentGroup(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["deploymentGroupId"]) } }) @@ -169,7 +170,7 @@ func TestDeploymentGroups_RichFieldsRoundTrip(t *testing.T) { TerminationHookEnabled bool `json:"terminationHookEnabled"` } `json:"deploymentGroupInfo"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) info := resp.DeploymentGroupInfo assert.Equal(t, "arn:aws:iam::123:role/role", info.ServiceRoleArn) @@ -310,7 +311,7 @@ func TestDeploymentGroups_SortedList(t *testing.T) { DeploymentGroups []string `json:"deploymentGroups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, []string{"a-group", "m-group", "z-group"}, resp.DeploymentGroups) } @@ -483,7 +484,7 @@ func TestDeploymentGroups_Update(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantHooksClean { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hooksNotCleanedUp, _ := resp["hooksNotCleanedUp"].(bool) assert.True(t, hooksNotCleanedUp, "expected hooksNotCleanedUp=true when alarms were removed") } @@ -551,7 +552,7 @@ func TestDeploymentGroups_InheritsComputePlatform(t *testing.T) { ComputePlatform string `json:"computePlatform"` } `json:"deploymentGroupInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.platform, resp.DeploymentGroupInfo.ComputePlatform) }) } @@ -598,7 +599,7 @@ func TestDeploymentGroups_ComputePlatformInheritedViaHandler(t *testing.T) { ComputePlatform string `json:"computePlatform"` } `json:"deploymentGroupInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.platform, out.DeploymentGroupInfo.ComputePlatform, "deployment group must inherit computePlatform from application") }) @@ -655,7 +656,7 @@ func TestHandler_BatchGetDeploymentGroups(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) infos, ok := resp["deploymentGroupsInfo"].([]any) require.True(t, ok) assert.Len(t, infos, tt.wantCount) @@ -681,7 +682,7 @@ func TestDeploymentGroups_BatchGetEmptySlice(t *testing.T) { DeploymentGroupsInfo []any `json:"deploymentGroupsInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Should be an empty array not null assert.NotNil(t, resp.DeploymentGroupsInfo) assert.Empty(t, resp.DeploymentGroupsInfo) @@ -717,7 +718,7 @@ func TestDeploymentGroups_BatchGetRichFields(t *testing.T) { } `json:"ecsServices"` } `json:"deploymentGroupsInfo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.DeploymentGroupsInfo, 1) info := resp.DeploymentGroupsInfo[0] diff --git a/services/codedeploy/deployment_instances_test.go b/services/codedeploy/deployment_instances_test.go index b933f43a46..788a9e566b 100644 --- a/services/codedeploy/deployment_instances_test.go +++ b/services/codedeploy/deployment_instances_test.go @@ -1,13 +1,14 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -65,7 +66,7 @@ func TestDeploymentInstances_BatchGetMissingDeployment(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DeploymentDoesNotExistException", resp["__type"]) } @@ -87,7 +88,7 @@ func TestHandler_BatchGetDeploymentInstances_RealTargets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["instancesSummary"].([]any) require.True(t, ok) // Only the two tag-filter-matched instances resolve as real targets; @@ -144,7 +145,7 @@ func TestHandler_BatchGetDeploymentTargets_ECS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["deploymentTargets"].([]any) require.True(t, ok) require.Len(t, targets, 1) @@ -207,7 +208,7 @@ func TestHandler_GetDeploymentTarget_Lambda(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) target, ok := resp["deploymentTarget"].(map[string]any) require.True(t, ok) assert.Equal(t, "LambdaTarget", target["deploymentTargetType"]) @@ -222,7 +223,7 @@ func TestHandler_GetDeploymentTarget_Lambda(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "DeploymentTargetDoesNotExistException", errResp["__type"]) } @@ -250,7 +251,7 @@ func TestHandler_GetDeploymentInstance_RealMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary, ok := resp["instanceSummary"].(map[string]any) require.True(t, ok) assert.Equal(t, matched[0], summary["instanceId"]) @@ -277,7 +278,7 @@ func TestHandler_ListDeploymentTargets_ListDeploymentInstances_RealTargets(t *te require.Equal(t, http.StatusOK, rec.Code) var targetsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &targetsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &targetsResp, jsonx.V1())) targetIDs, ok := targetsResp["targetIds"].([]any) require.True(t, ok) require.Len(t, targetIDs, 2) @@ -287,7 +288,7 @@ func TestHandler_ListDeploymentTargets_ListDeploymentInstances_RealTargets(t *te require.Equal(t, http.StatusOK, rec.Code) var instResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &instResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &instResp, jsonx.V1())) instances, ok := instResp["instancesList"].([]any) require.True(t, ok) assert.ElementsMatch(t, []any{matched[0], matched[1]}, instances) @@ -339,7 +340,7 @@ func TestHandler_ListDeploymentInstances_StatusAndTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, ok := resp["instancesList"].([]any) require.True(t, ok) assert.Len(t, instances, tt.wantLen) @@ -390,7 +391,7 @@ func TestHandler_ListDeploymentTargets_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targetIDs, ok := resp["targetIds"].([]any) require.True(t, ok) assert.Len(t, targetIDs, tt.wantLen) @@ -425,7 +426,7 @@ func TestHandler_ListDeploymentInstances_ECSIsEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, ok := resp["instancesList"].([]any) require.True(t, ok) assert.Empty(t, instances) @@ -450,7 +451,7 @@ func TestDeploymentTargets_StatusTracksDeploymentStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) target, ok := resp["deploymentTarget"].(map[string]any) require.True(t, ok) instanceTarget, ok := target["instanceTarget"].(map[string]any) diff --git a/services/codedeploy/deployments_test.go b/services/codedeploy/deployments_test.go index c97a1a6dec..2ebac12df6 100644 --- a/services/codedeploy/deployments_test.go +++ b/services/codedeploy/deployments_test.go @@ -1,7 +1,7 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -111,14 +112,14 @@ func TestHandler_CreateDeployment(t *testing.T) { if tt.wantID { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["deploymentId"]) assert.True(t, len(resp["deploymentId"]) > 2 && resp["deploymentId"][:2] == "d-") } if tt.wantErrType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) } }) @@ -153,7 +154,7 @@ func TestDeployments_CreateIDFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["deploymentId"] assert.True(t, deployIDRe.MatchString(id), "deploymentId %q does not match pattern d-[A-Z0-9]{9}", id) } @@ -184,7 +185,7 @@ func TestDeployments_CreateIDFormat_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Regexp(t, deployIDRe, out["deploymentId"], "deploymentId must match d-[A-Z0-9]{9}") }) @@ -209,7 +210,7 @@ func TestDeployments_CreateExtraFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec2 := doRequest(t, h, "GetDeployment", map[string]any{"deploymentId": createResp["deploymentId"]}) require.Equal(t, http.StatusOK, rec2.Code) @@ -222,7 +223,7 @@ func TestDeployments_CreateExtraFields(t *testing.T) { IgnoreApplicationStopFailures bool `json:"ignoreApplicationStopFailures"` } `json:"deploymentInfo"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-description", getResp.DeploymentInfo.Description) assert.Equal(t, "OVERWRITE", getResp.DeploymentInfo.FileExistsBehavior) @@ -253,7 +254,7 @@ func TestDeployments_S3RevisionRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) deployID := createOut["deploymentId"] require.NotEmpty(t, deployID) @@ -274,7 +275,7 @@ func TestDeployments_S3RevisionRoundTrip(t *testing.T) { } `json:"revision"` } `json:"deploymentInfo"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) rev := getOut.DeploymentInfo.Revision assert.Equal(t, "S3", rev.RevisionType, "revisionType must round-trip") @@ -305,7 +306,7 @@ func TestDeployments_GitHubRevisionRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) deployID := createOut["deploymentId"] getRec := doRequest(t, h, "GetDeployment", map[string]any{"deploymentId": deployID}) @@ -322,7 +323,7 @@ func TestDeployments_GitHubRevisionRoundTrip(t *testing.T) { } `json:"revision"` } `json:"deploymentInfo"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) rev := getOut.DeploymentInfo.Revision assert.Equal(t, "GitHub", rev.RevisionType) @@ -397,7 +398,7 @@ func TestDeployments_InfoIncludesConfigName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) info := resp["deploymentInfo"] assert.Equal(t, "CodeDeployDefault.AllAtOnce", info["deploymentConfigName"]) @@ -416,7 +417,7 @@ func TestDeployments_GetDeploymentOverview(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) getRec := doRequest(t, h, "GetDeployment", map[string]any{"deploymentId": createOut["deploymentId"]}) require.Equal(t, http.StatusOK, getRec.Code) @@ -426,7 +427,7 @@ func TestDeployments_GetDeploymentOverview(t *testing.T) { DeploymentOverview map[string]any `json:"deploymentOverview"` } `json:"deploymentInfo"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) ov := getOut.DeploymentInfo.DeploymentOverview assert.NotNil(t, ov, "GetDeployment must include deploymentOverview") @@ -455,7 +456,7 @@ func TestHandler_ListDeployments(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deployments, ok := resp["deployments"].([]any) require.True(t, ok) assert.Len(t, deployments, 1) @@ -483,7 +484,7 @@ func TestDeployments_SortedList(t *testing.T) { Deployments []string `json:"deployments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Deployments, 2) assert.Contains(t, resp.Deployments, d1.DeploymentID) @@ -535,7 +536,7 @@ func TestDeployments_ListStatusFilter(t *testing.T) { var resp struct { Deployments []string `json:"deployments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Deployments, tt.wantLen) }) } @@ -578,7 +579,7 @@ func TestDeployments_ListExternalIDFilter(t *testing.T) { var resp struct { Deployments []string `json:"deployments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Deployments, tt.wantLen) }) } @@ -714,7 +715,7 @@ func TestHandler_ContinueDeployment(t *testing.T) { if tt.wantErrType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) } }) @@ -738,7 +739,7 @@ func TestDeployments_StopDeployment_AlreadyStopped(t *testing.T) { assert.Equal(t, http.StatusConflict, secondStop.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(secondStop.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(secondStop.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "DeploymentAlreadyCompletedException", errResp["__type"]) } @@ -756,7 +757,7 @@ func TestDeployments_StopDeploymentStatus(t *testing.T) { var stopOut struct { Status string `json:"status"` } - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopOut)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopOut, jsonx.V1())) assert.Equal(t, "Succeeded", stopOut.Status, "StopDeploymentOutput.status is the StopStatus enum (Pending|Succeeded), not the deployment status") @@ -768,7 +769,7 @@ func TestDeployments_StopDeploymentStatus(t *testing.T) { Status string `json:"status"` } `json:"deploymentInfo"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "Stopped", getOut.DeploymentInfo.Status, "GetDeployment must reflect Stopped status after StopDeployment") } @@ -821,7 +822,7 @@ func TestHandler_BatchGetDeployments(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) infos, ok := resp["deploymentsInfo"].([]any) require.True(t, ok) assert.Len(t, infos, tt.wantCount) @@ -847,7 +848,7 @@ func TestDeployments_BatchGetReturnsRevision(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) batchRec := doRequest(t, h, "BatchGetDeployments", map[string]any{ "deploymentIds": []string{createOut["deploymentId"]}, @@ -864,7 +865,7 @@ func TestDeployments_BatchGetReturnsRevision(t *testing.T) { var batchOut struct { DeploymentsInfo []batchItem `json:"deploymentsInfo"` } - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchOut)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchOut, jsonx.V1())) require.Len(t, batchOut.DeploymentsInfo, 1) info := batchOut.DeploymentsInfo[0] @@ -887,7 +888,7 @@ func TestDeployments_SkipWaitTime_DeploymentNotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DeploymentDoesNotExistException", resp["__type"]) } @@ -907,7 +908,7 @@ func TestDeployments_SkipWaitTime_DeploymentFound(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) deployID := createOut["deploymentId"] skipRec := doRequest(t, h, "SkipWaitTimeForInstanceTermination", map[string]any{ diff --git a/services/codedeploy/github_tokens_test.go b/services/codedeploy/github_tokens_test.go index 6caf26e03f..7a3c379f5d 100644 --- a/services/codedeploy/github_tokens_test.go +++ b/services/codedeploy/github_tokens_test.go @@ -1,12 +1,14 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGitHubTokens_ListAddDelete(t *testing.T) { @@ -21,7 +23,7 @@ func TestGitHubTokens_ListAddDelete(t *testing.T) { var listResp struct { TokenNameList []string `json:"tokenNameList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.TokenNameList) // Add token via internal method and verify it appears. @@ -29,7 +31,7 @@ func TestGitHubTokens_ListAddDelete(t *testing.T) { rec = doRequest(t, h, "ListGitHubAccountTokenNames", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Equal(t, []string{"my-token"}, listResp.TokenNameList) // Delete the token. @@ -39,7 +41,7 @@ func TestGitHubTokens_ListAddDelete(t *testing.T) { // List should be empty again. rec = doRequest(t, h, "ListGitHubAccountTokenNames", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.TokenNameList) } @@ -51,7 +53,7 @@ func TestGitHubTokens_DeleteNotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "GitHubAccountTokenDoesNotExistException", resp["__type"]) } diff --git a/services/codedeploy/handler.go b/services/codedeploy/handler.go index 63367ebb0f..728c0243fc 100644 --- a/services/codedeploy/handler.go +++ b/services/codedeploy/handler.go @@ -2,7 +2,7 @@ package codedeploy import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -176,7 +177,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var input struct { ApplicationName string `json:"applicationName"` } - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return "" } @@ -263,7 +264,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // errorMapping maps sentinel errors to HTTP status and exception type. @@ -341,7 +342,7 @@ func stripExceptionPrefixes(msg string) string { func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { makePayload := func(code, msg string) []byte { - b, _ := json.Marshal(service.JSONErrorResponse{Type: code, Message: stripExceptionPrefixes(msg)}) + b, _ := json.Marshal(service.JSONErrorResponse{Type: code, Message: stripExceptionPrefixes(msg)}, jsonx.V1()) return b } @@ -352,10 +353,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err } } - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - - if errors.As(err, &syntaxErr) || errors.As(err, &typeErr) { + if jsonx.IsSyntaxError(err) || jsonx.IsTypeError(err) { return c.JSONBlob(http.StatusBadRequest, makePayload("InvalidRequestException", err.Error())) } diff --git a/services/codedeploy/handler_deployment_groups.go b/services/codedeploy/handler_deployment_groups.go index b8a2b34870..569cf84310 100644 --- a/services/codedeploy/handler_deployment_groups.go +++ b/services/codedeploy/handler_deployment_groups.go @@ -2,10 +2,11 @@ package codedeploy import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -58,7 +59,7 @@ type autoScalingGroupEntry struct { // UnmarshalJSON accepts a bare name (SDK AutoScalingGroups []string) or the object form. func (e *autoScalingGroupEntry) UnmarshalJSON(data []byte) error { var name string - if err := json.Unmarshal(data, &name); err == nil { + if err := json.Unmarshal(data, &name, jsonx.V1()); err == nil { *e = autoScalingGroupEntry{Name: name} return nil @@ -67,7 +68,7 @@ func (e *autoScalingGroupEntry) UnmarshalJSON(data []byte) error { type plain autoScalingGroupEntry var p plain - if err := json.Unmarshal(data, &p); err != nil { + if err := json.Unmarshal(data, &p, jsonx.V1()); err != nil { return err } diff --git a/services/codedeploy/handler_test.go b/services/codedeploy/handler_test.go index edb31c703f..48a995c23b 100644 --- a/services/codedeploy/handler_test.go +++ b/services/codedeploy/handler_test.go @@ -2,7 +2,7 @@ package codedeploy_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *codedeploy.Handler, action string, body any) *ht if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -175,7 +176,7 @@ func TestHandler_ExtractResource(t *testing.T) { h := newTestHandler(t) e := echo.New() - bodyBytes, _ := json.Marshal(map[string]string{"applicationName": "my-app"}) + bodyBytes, _ := json.Marshal(map[string]string{"applicationName": "my-app"}, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) diff --git a/services/codedeploy/lifecycle_hooks_test.go b/services/codedeploy/lifecycle_hooks_test.go index 5706b77e97..bcf8e91155 100644 --- a/services/codedeploy/lifecycle_hooks_test.go +++ b/services/codedeploy/lifecycle_hooks_test.go @@ -1,12 +1,14 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestLifecycleHooks_PutExecutionStatus_DeploymentNotFound verifies that @@ -26,7 +28,7 @@ func TestLifecycleHooks_PutExecutionStatus_DeploymentNotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DeploymentDoesNotExistException", resp["__type"]) } @@ -46,7 +48,7 @@ func TestLifecycleHooks_PutExecutionStatus_DeploymentFound(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) deployID := createOut["deploymentId"] hookRec := doRequest(t, h, "PutLifecycleEventHookExecutionStatus", map[string]any{ @@ -59,6 +61,6 @@ func TestLifecycleHooks_PutExecutionStatus_DeploymentFound(t *testing.T) { var hookOut struct { LifecycleEventHookExecutionID string `json:"lifecycleEventHookExecutionId"` } - require.NoError(t, json.Unmarshal(hookRec.Body.Bytes(), &hookOut)) + require.NoError(t, json.Unmarshal(hookRec.Body.Bytes(), &hookOut, jsonx.V1())) assert.Equal(t, "hook-1", hookOut.LifecycleEventHookExecutionID) } diff --git a/services/codedeploy/lifecycle_validation_test.go b/services/codedeploy/lifecycle_validation_test.go index 81e1d63746..9c2acb7c6b 100644 --- a/services/codedeploy/lifecycle_validation_test.go +++ b/services/codedeploy/lifecycle_validation_test.go @@ -1,13 +1,15 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateDeploymentGroup_InputValidation(t *testing.T) { @@ -68,7 +70,7 @@ func TestCreateDeploymentGroup_InputValidation(t *testing.T) { } var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantCode, resp["__type"]) assert.NotContains(t, resp["message"], "Exception:") }) diff --git a/services/codedeploy/multi_region_test.go b/services/codedeploy/multi_region_test.go index 62cbae9fa4..a10c8ca8e5 100644 --- a/services/codedeploy/multi_region_test.go +++ b/services/codedeploy/multi_region_test.go @@ -2,7 +2,7 @@ package codedeploy_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -38,7 +39,7 @@ func regionCall(t *testing.T, h *codedeploy.Handler, region, op, body string) ma require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/codedeploy/on_premises_instances_test.go b/services/codedeploy/on_premises_instances_test.go index 84dbf6e05a..24f31218c9 100644 --- a/services/codedeploy/on_premises_instances_test.go +++ b/services/codedeploy/on_premises_instances_test.go @@ -1,7 +1,7 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codedeploy" ) @@ -90,7 +91,7 @@ func TestHandler_BatchGetOnPremisesInstances(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) infos, ok := resp["instanceInfos"].([]any) require.True(t, ok) assert.Len(t, infos, tt.wantCount) @@ -120,7 +121,7 @@ func TestOnPremisesInstances_TagsAlwaysSlice(t *testing.T) { } `json:"instanceInfos"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.InstanceInfos, 1) // Tags should be an empty slice, not nil/missing assert.NotNil(t, resp.InstanceInfos[0].Tags) @@ -230,7 +231,7 @@ func TestOnPremisesInstances_IamValidation(t *testing.T) { if tt.wantErrType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) } }) @@ -290,7 +291,7 @@ func TestOnPremisesInstances_ListTagFilter(t *testing.T) { var resp struct { InstanceNames []string `json:"instanceNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.ElementsMatch(t, tt.wantNames, resp.InstanceNames) }) } @@ -337,7 +338,7 @@ func TestOnPremisesInstances_NotFoundErrorMapping(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) }) } @@ -354,7 +355,7 @@ func TestGetOnPremisesInstance_NotRegisteredNotDoesNotExist(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InstanceNotRegisteredException", resp["__type"]) assert.NotEqual(t, "InstanceDoesNotExistException", resp["__type"]) @@ -364,6 +365,6 @@ func TestGetOnPremisesInstance_NotRegisteredNotDoesNotExist(t *testing.T) { var listResp struct { InstanceNames []string `json:"instanceNames"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.InstanceNames) } diff --git a/services/codedeploy/persistence.go b/services/codedeploy/persistence.go index f996c46e61..63f92a36f0 100644 --- a/services/codedeploy/persistence.go +++ b/services/codedeploy/persistence.go @@ -2,7 +2,7 @@ package codedeploy import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -149,11 +149,11 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // identity-less set left unconverted (see store_setup.go) and is persisted // here directly, as before. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - GitHubTokens []string `json:"githubTokens,omitempty"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + GitHubTokens []string `json:"githubTokens,omitempty"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. Returns nil on marshal failure. @@ -275,7 +275,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // registerAllTables doc) from tables via the ephemeral DTO registry, // factored out of Restore to keep Restore's own cognitive complexity low. // Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("codedeploy: restore snapshot DTO tables: %w", err) diff --git a/services/codedeploy/store_setup.go b/services/codedeploy/store_setup.go index 0fba4b10c0..e22d1e97de 100644 --- a/services/codedeploy/store_setup.go +++ b/services/codedeploy/store_setup.go @@ -30,8 +30,9 @@ package codedeploy // NOT converted: there is no *T value for store.Table to key on. It remains // a plain map, unchanged by this refactor (see backend.go). import ( - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -61,7 +62,7 @@ func deploymentConfigTableKeyFn(v *DeploymentConfig) string { return v.Deploymen // which is exactly the identity real CodeDeploy uses to deduplicate // registrations of the same revision. func applicationRevisionKey(appName string, r RevisionLocation) string { - b, _ := json.Marshal(r) + b, _ := json.Marshal(r, jsonx.V1()) return appName + "\x00" + string(b) } diff --git a/services/codedeploy/tags_test.go b/services/codedeploy/tags_test.go index f5ea2af983..32dbe20c28 100644 --- a/services/codedeploy/tags_test.go +++ b/services/codedeploy/tags_test.go @@ -1,13 +1,15 @@ package codedeploy_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Tagging(t *testing.T) { @@ -69,7 +71,7 @@ func TestTags_SortedListTagsForResource(t *testing.T) { } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Tags, 3) assert.Equal(t, "aaa", resp.Tags[0].Key) assert.Equal(t, "mmm", resp.Tags[1].Key) @@ -104,7 +106,7 @@ func TestTags_OnDeploymentGroups(t *testing.T) { } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Tags, 1) assert.Equal(t, "env", resp.Tags[0].Key) assert.Equal(t, "prod", resp.Tags[0].Value) @@ -189,7 +191,7 @@ func TestTags_ResourceTagLimits(t *testing.T) { if tt.wantErrType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) } }) @@ -219,7 +221,7 @@ func TestTags_ResourceExceedsMaxTags(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // TagResource's own deserializer models only InvalidTagsToAddException for // tag content, not TagLimitExceededException (that code belongs to // AddTagsToOnPremisesInstances/RemoveTagsFromOnPremisesInstances/ diff --git a/services/codegurureviewer/persistence.go b/services/codegurureviewer/persistence.go index 0ca94e738d..5c7be4e197 100644 --- a/services/codegurureviewer/persistence.go +++ b/services/codegurureviewer/persistence.go @@ -2,7 +2,7 @@ package codegurureviewer import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/codepipeline/async_builtin_actions_test.go b/services/codepipeline/async_builtin_actions_test.go index a945dce975..166ee30585 100644 --- a/services/codepipeline/async_builtin_actions_test.go +++ b/services/codepipeline/async_builtin_actions_test.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "sync" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -198,7 +199,7 @@ func TestBuiltinActions_WaitForBackendState(t *testing.T) { details, lErr := h.Backend.ListActionExecutions(ctx, "p", exec.PipelineExecutionID) require.NoError(t, lErr) - raw, mErr := json.Marshal(details) + raw, mErr := json.Marshal(details, jsonx.V1()) require.NoError(t, mErr) assert.Contains(t, string(raw), tt.wantMsg) } diff --git a/services/codepipeline/custom_action_types_test.go b/services/codepipeline/custom_action_types_test.go index 1cda05da9d..faeb26b739 100644 --- a/services/codepipeline/custom_action_types_test.go +++ b/services/codepipeline/custom_action_types_test.go @@ -2,7 +2,8 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -80,7 +82,7 @@ func TestHandler_CreateCustomActionType(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) at, ok := out["actionType"].(map[string]any) require.True(t, ok) id, ok := at["id"].(map[string]any) @@ -130,7 +132,7 @@ func TestCreateCustomActionType_ActionConfigurationProperties_EmptyNotAbsent(t * require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) actionType, ok := raw["actionType"].(map[string]any) require.True(t, ok, "actionType must be an object") @@ -164,7 +166,7 @@ func TestCreateCustomActionType_ActionConfigurationProperties_RoundTrip(t *testi require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) actionType, ok := raw["actionType"].(map[string]any) require.True(t, ok) @@ -294,7 +296,7 @@ func TestHandler_DeleteCustomActionType_InUse(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) } }) @@ -358,7 +360,7 @@ func TestHandler_GetActionType(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) at, ok := out["actionType"].(map[string]any) require.True(t, ok) id, ok := at["id"].(map[string]any) @@ -402,7 +404,7 @@ func TestGetActionType_ActionTypeDeclarationShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) actionType, ok := raw["actionType"].(map[string]any) require.True(t, ok, "actionType must be an object") @@ -484,7 +486,7 @@ func TestGetActionType_AfterUpdateActionType_ReturnsDeclarationData(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) actionType, ok := raw["actionType"].(map[string]any) require.True(t, ok) @@ -507,7 +509,7 @@ func TestGetActionType_AfterUpdateActionType_ReturnsDeclarationData(t *testing.T require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) items, _ := listOut["actionTypes"].([]any) require.Len(t, items, 1) item0, _ := items[0].(map[string]any) @@ -627,7 +629,7 @@ func TestHandler_ListActionTypes_FullShape(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) items, _ := out["actionTypes"].([]any) assert.Len(t, items, tt.wantCount) @@ -667,7 +669,7 @@ func TestCPPagination_ListActionTypes(t *testing.T) { NextToken string `json:"nextToken"` ActionTypes []map[string]any `json:"actionTypes"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.ActionTypes, 5) assert.Empty(t, out.NextToken, "5 items fit within the 25-cap default page") @@ -707,7 +709,7 @@ func TestCPPagination_ListActionTypes_MultiPage(t *testing.T) { NextToken string `json:"nextToken"` ActionTypes []map[string]any `json:"actionTypes"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) total += len(out.ActionTypes) pages++ @@ -771,7 +773,7 @@ func TestHandler_UpdateActionType_FullFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) at, _ := out["actionType"].(map[string]any) inArt, _ := at["inputArtifactDetails"].(map[string]any) diff --git a/services/codepipeline/deploy_cloudformation.go b/services/codepipeline/deploy_cloudformation.go index bb52766062..8f8de5a2c3 100644 --- a/services/codepipeline/deploy_cloudformation.go +++ b/services/codepipeline/deploy_cloudformation.go @@ -2,11 +2,14 @@ package codepipeline import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -285,7 +288,7 @@ func (b *InMemoryBackend) cfnPublishOutputs( return } - body, err := json.Marshal(st.Outputs) + body, err := json.Marshal(st.Outputs, jsonx.V1()) if err == nil { err = b.putOutputFiles(ctx, p, execID, action, map[string][]byte{file: body}) } @@ -431,12 +434,12 @@ func (b *InMemoryBackend) applyTemplateConfiguration( } var doc struct { - Parameters map[string]any `json:"Parameters"` - Tags map[string]any `json:"Tags"` - StackPolicy json.RawMessage `json:"StackPolicy"` + Parameters map[string]any `json:"Parameters"` + Tags map[string]any `json:"Tags"` + StackPolicy jsontext.Value `json:"StackPolicy"` } - if err = json.Unmarshal(body, &doc); err != nil { + if err = json.Unmarshal(body, &doc, jsonx.V1()); err != nil { return fmt.Errorf("template configuration %q is not valid JSON: %w", ref, err) } @@ -469,7 +472,7 @@ func (b *InMemoryBackend) applyParameterOverrides( ctx context.Context, p *Pipeline, execID string, action Action, raw string, req *StackRequest, ) error { var overrides map[string]any - if err := json.Unmarshal([]byte(raw), &overrides); err != nil { + if err := json.Unmarshal([]byte(raw), &overrides, jsonx.V1()); err != nil { return fmt.Errorf("ParameterOverrides is not a valid JSON object: %w", err) } @@ -506,7 +509,7 @@ func (b *InMemoryBackend) resolveParameterFunction( } var doc map[string]any - if err = json.Unmarshal(body, &doc); err != nil { + if err = json.Unmarshal(body, &doc, jsonx.V1()); err != nil { return "", fmt.Errorf("%s is not a JSON object: %w", scalarString(args[1]), err) } diff --git a/services/codepipeline/deploy_ecs.go b/services/codepipeline/deploy_ecs.go index 3c49a802fd..d6ea044324 100644 --- a/services/codepipeline/deploy_ecs.go +++ b/services/codepipeline/deploy_ecs.go @@ -2,10 +2,12 @@ package codepipeline import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -97,7 +99,7 @@ func (b *InMemoryBackend) ecsStartDeployment( } var defs []imageDefinition - if err = json.Unmarshal(body, &defs); err != nil || len(defs) == 0 { + if err = json.Unmarshal(body, &defs, jsonx.V1()); err != nil || len(defs) == 0 { return "", fmt.Errorf( "%w: image definitions file %q must be a non-empty JSON array of name/imageUri", ErrValidation, diff --git a/services/codepipeline/handler.go b/services/codepipeline/handler.go index d2c660af97..03a8c42efe 100644 --- a/services/codepipeline/handler.go +++ b/services/codepipeline/handler.go @@ -2,7 +2,7 @@ package codepipeline import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -294,7 +295,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -346,10 +347,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err } } - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - - if errors.As(err, &syntaxErr) || errors.As(err, &typeErr) { + if jsonx.IsSyntaxError(err) || jsonx.IsTypeError(err) { return errorBlob(c, http.StatusBadRequest, errTypeValidation, err) } @@ -372,7 +370,7 @@ func errorBlob(c *echo.Context, status int, errType string, err error) error { payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: stripExceptionPrefixes(err.Error()), - }) + }, jsonx.V1()) return c.JSONBlob(status, payload) } diff --git a/services/codepipeline/handler_test.go b/services/codepipeline/handler_test.go index e40334a94e..8489b9042c 100644 --- a/services/codepipeline/handler_test.go +++ b/services/codepipeline/handler_test.go @@ -3,7 +3,7 @@ package codepipeline_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -28,7 +29,7 @@ func doRequest(t *testing.T, h *codepipeline.Handler, action string, body any) * var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -174,7 +175,7 @@ func decodeBody(t *testing.T, data []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(data, &m)) + require.NoError(t, json.Unmarshal(data, &m, jsonx.V1())) return m } @@ -343,7 +344,7 @@ func TestHandler_UnknownAction(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "InvalidActionException", out["__type"]) } @@ -422,7 +423,7 @@ func TestHandler_ErrorEnvelopes(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) }) } @@ -445,7 +446,7 @@ func TestErrValidationMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ValidationException", out["__type"]) } diff --git a/services/codepipeline/jobs_test.go b/services/codepipeline/jobs_test.go index ebb2142fc2..2e5918725c 100644 --- a/services/codepipeline/jobs_test.go +++ b/services/codepipeline/jobs_test.go @@ -2,13 +2,14 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -78,7 +79,7 @@ func TestHandler_AcknowledgeJob(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out["status"]) } }) @@ -133,7 +134,7 @@ func TestHandler_GetJobDetails(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) details, ok := out["jobDetails"].(map[string]any) require.True(t, ok) assert.Equal(t, "jd-1", details["id"]) @@ -176,7 +177,7 @@ func TestGetJobDetails_DataPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) details, ok := out["jobDetails"].(map[string]any) require.True(t, ok, "jobDetails must be present") @@ -284,7 +285,7 @@ func TestHandler_PollForJobs_Filter(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobs, _ := out["jobs"].([]any) gotIDs := make([]string, len(jobs)) @@ -379,7 +380,7 @@ func TestHandler_PollForJobs_MaxBatchSize(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobs, _ := out["jobs"].([]any) assert.Len(t, jobs, tt.wantCount) diff --git a/services/codepipeline/persistence.go b/services/codepipeline/persistence.go index 8d53cd24c1..54c504bf97 100644 --- a/services/codepipeline/persistence.go +++ b/services/codepipeline/persistence.go @@ -2,7 +2,7 @@ package codepipeline import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -96,14 +96,14 @@ type conditionRunEntry struct { // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Executions []executionEntry `json:"executions"` - ActionExecutions []actionExecutionEntry `json:"actionExecutions"` - ActionRevisions []actionRevisionEntry `json:"actionRevisions"` - ConditionRuns []conditionRunEntry `json:"conditionRuns,omitempty"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Executions []executionEntry `json:"executions"` + ActionExecutions []actionExecutionEntry `json:"actionExecutions"` + ActionRevisions []actionRevisionEntry `json:"actionRevisions"` + ConditionRuns []conditionRunEntry `json:"conditionRuns,omitempty"` + Version int `json:"version"` } // customActionTypeKey.String returns a unique string for use as the DTO id @@ -352,7 +352,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds the five resource store.Table values from // snap's per-table JSON, factored out of Restore to keep Restore's own // cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, pipelineDTOs, catDTOs, jobDTOs, webhookDTOs, transitionDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/codepipeline/pipeline_declaration_test.go b/services/codepipeline/pipeline_declaration_test.go index e495533bbf..01ea61a3ca 100644 --- a/services/codepipeline/pipeline_declaration_test.go +++ b/services/codepipeline/pipeline_declaration_test.go @@ -1,13 +1,14 @@ package codepipeline_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -95,7 +96,7 @@ func TestHandler_PipelineDeclaration_V2Fields(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pl, _ := out["pipeline"].(map[string]any) require.NotNil(t, pl) @@ -219,7 +220,7 @@ func TestHandler_Action_ExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) pl := out["pipeline"].(map[string]any) stages := pl["stages"].([]any) diff --git a/services/codepipeline/pipeline_executions_test.go b/services/codepipeline/pipeline_executions_test.go index 6443c16ef8..000994f6d9 100644 --- a/services/codepipeline/pipeline_executions_test.go +++ b/services/codepipeline/pipeline_executions_test.go @@ -2,7 +2,8 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -100,7 +102,7 @@ func TestHandler_PipelineExecution_TerminalStatus(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) execID, _ := startOut["pipelineExecutionId"].(string) require.NotEmpty(t, execID) @@ -108,7 +110,7 @@ func TestHandler_PipelineExecution_TerminalStatus(t *testing.T) { require.Equal(t, tt.httpStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantType != "" { assert.Equal(t, tt.wantType, out["__type"]) @@ -247,7 +249,7 @@ func TestHandler_ListPipelineExecutions_StoresAndReturns(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, _ := out["pipelineExecutionSummaries"].([]any) assert.Len(t, summaries, tt.wantCount) } @@ -293,7 +295,7 @@ func TestListPipelineExecutions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.PipelineExecutionSummaries), 2, "page exceeds maxResults") for _, s := range resp.PipelineExecutionSummaries { @@ -392,7 +394,7 @@ func TestCPPagination_ListPipelineExecutions(t *testing.T) { NextToken string `json:"nextToken"` PipelineExecutionSummaries []map[string]any `json:"pipelineExecutionSummaries"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) total += len(out.PipelineExecutionSummaries) pages++ @@ -432,7 +434,7 @@ func TestListPipelineExecutions_TriggerObject(t *testing.T) { var out struct { PipelineExecutionSummaries []map[string]any `json:"pipelineExecutionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.PipelineExecutionSummaries, 2) for _, exec := range out.PipelineExecutionSummaries { @@ -598,7 +600,7 @@ func TestCPPagination_ListActionExecutions(t *testing.T) { NextToken string `json:"nextToken"` ActionExecutionDetails []map[string]any `json:"actionExecutionDetails"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) total += len(out.ActionExecutionDetails) pages++ diff --git a/services/codepipeline/pipeline_state_test.go b/services/codepipeline/pipeline_state_test.go index 1921f90070..15fcb2d71c 100644 --- a/services/codepipeline/pipeline_state_test.go +++ b/services/codepipeline/pipeline_state_test.go @@ -2,13 +2,14 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -321,7 +322,7 @@ func TestHandler_DisableStageTransition_StageValidation(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) } }) @@ -524,7 +525,7 @@ func TestHandler_GetPipelineState_ActionStates(t *testing.T) { if tt.checkFn != nil { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.checkFn(t, out) } }) @@ -611,7 +612,7 @@ func TestHandler_GetPipelineState_LatestExecution(t *testing.T) { if tt.checkFn != nil { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.checkFn(t, out) } }) @@ -655,7 +656,7 @@ func TestGetPipelineState_PipelineVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.InDelta(t, tt.wantVersion, out["pipelineVersion"], 0, "pipelineVersion mismatch") }) } diff --git a/services/codepipeline/pipeline_state_wire_test.go b/services/codepipeline/pipeline_state_wire_test.go index 8249eade4e..334510079c 100644 --- a/services/codepipeline/pipeline_state_wire_test.go +++ b/services/codepipeline/pipeline_state_wire_test.go @@ -1,7 +1,7 @@ package codepipeline_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -134,7 +135,7 @@ func TestGetPipelineState_OmitsOutboundTransitionState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) stageStates := out["stageStates"].([]any) require.Len(t, stageStates, 1) diff --git a/services/codepipeline/pipelines_test.go b/services/codepipeline/pipelines_test.go index 59c84f843d..021790e452 100644 --- a/services/codepipeline/pipelines_test.go +++ b/services/codepipeline/pipelines_test.go @@ -2,13 +2,14 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -72,7 +73,7 @@ func TestHandler_CreatePipeline(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pipeline, ok := out["pipeline"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, pipeline["name"]) @@ -131,8 +132,8 @@ func TestHandler_CreatePipeline_RoleArnRequired(t *testing.T) { input := tt.pipeline if input == nil { // marshal samplePipeline to map - b, _ := json.Marshal(samplePipeline("role-test")) - require.NoError(t, json.Unmarshal(b, &input)) + b, _ := json.Marshal(samplePipeline("role-test"), jsonx.V1()) + require.NoError(t, json.Unmarshal(b, &input, jsonx.V1())) } rec := doRequest(t, h, "CreatePipeline", map[string]any{"pipeline": input}) @@ -140,7 +141,7 @@ func TestHandler_CreatePipeline_RoleArnRequired(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) } }) @@ -177,7 +178,7 @@ func TestCreatePipeline_DuplicateName_PipelineNameInUseException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec2.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body, jsonx.V1())) errType, ok := body["__type"].(string) require.True(t, ok, "response must have __type field") @@ -200,7 +201,7 @@ func TestCreatePipeline_DuplicateName_NotInvalidStructureException(t *testing.T) require.Equal(t, http.StatusBadRequest, rec2.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &body, jsonx.V1())) errType, _ := body["__type"].(string) assert.NotEqual(t, "InvalidStructureException", errType, @@ -329,7 +330,7 @@ func TestHandler_GetPipeline_VersionHandling(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) } }) @@ -449,7 +450,7 @@ func TestHandler_UpdatePipeline_VersionIsIgnored(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pipeline, _ := out["pipeline"].(map[string]any) assert.InDelta( t, @@ -585,7 +586,7 @@ func TestInMemoryBackend_DeletePipeline_ClearsActionExecutions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var before map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before, jsonx.V1())) beforeDetails, _ := before["actionExecutionDetails"].([]any) require.NotEmpty(t, beforeDetails, "action executions must be recorded before delete") @@ -600,7 +601,7 @@ func TestInMemoryBackend_DeletePipeline_ClearsActionExecutions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var after map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after, jsonx.V1())) afterDetails, _ := after["actionExecutionDetails"].([]any) assert.Empty( t, @@ -683,7 +684,7 @@ func TestDeletePipeline_CascadeActionRevisions(t *testing.T) { require.Equal(t, http.StatusOK, stateRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(stateRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(stateRec.Body.Bytes(), &out, jsonx.V1())) stageStates, _ := out["stageStates"].([]any) require.Len(t, stageStates, 1) stage, _ := stageStates[0].(map[string]any) @@ -738,7 +739,7 @@ func TestHandler_ListPipelines(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pipelines, _ := out["pipelines"].([]any) assert.Len(t, pipelines, tt.wantCount) }) @@ -783,7 +784,7 @@ func TestHandler_ListPipelines_IncludesPipelineType(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pipelines, _ := out["pipelines"].([]any) require.Len(t, pipelines, 1) @@ -812,7 +813,7 @@ func TestSortedListPipelines(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["pipelines"].([]any) require.True(t, ok) @@ -836,7 +837,7 @@ func TestListPipelines_NonNilWhenEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // pipelines key must exist and be an array, not null. list, ok := out["pipelines"] @@ -861,7 +862,7 @@ func TestListPipelines_OmitsPipelineArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list := out["pipelines"].([]any) item := list[0].(map[string]any) @@ -871,7 +872,7 @@ func TestListPipelines_OmitsPipelineArn(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) metadata := getOut["metadata"].(map[string]any) arn, ok := metadata["pipelineArn"].(string) @@ -932,7 +933,7 @@ func TestListPipelines_Pagination(t *testing.T) { NextToken string `json:"nextToken"` Pipelines []map[string]any `json:"pipelines"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Pipelines, tt.wantLen) if tt.wantNextToken { assert.NotEmpty(t, out.NextToken) @@ -976,7 +977,7 @@ func TestListPipelines_FullPagination(t *testing.T) { NextToken string `json:"nextToken"` Pipelines []map[string]any `json:"pipelines"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.LessOrEqual(t, len(out.Pipelines), 2) for _, p := range out.Pipelines { diff --git a/services/codepipeline/rules_test.go b/services/codepipeline/rules_test.go index b32ae50801..4c963e138d 100644 --- a/services/codepipeline/rules_test.go +++ b/services/codepipeline/rules_test.go @@ -2,13 +2,15 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -110,7 +112,7 @@ func TestHandler_ListExecutionsAndRules(t *testing.T) { ActionExecutionID string `json:"actionExecutionId"` } `json:"actionExecutionDetails"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&actionExecs)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &actionExecs, jsonx.V1())) require.NotEmpty(t, actionExecs.ActionExecutionDetails) actionExecutionID := actionExecs.ActionExecutionDetails[0].ActionExecutionID require.NotEmpty(t, actionExecutionID) diff --git a/services/codepipeline/source_actions.go b/services/codepipeline/source_actions.go index db50e1ea98..f9f3c9dfb9 100644 --- a/services/codepipeline/source_actions.go +++ b/services/codepipeline/source_actions.go @@ -2,11 +2,12 @@ package codepipeline import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "strconv" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -65,7 +66,7 @@ func (b *InMemoryBackend) runECRSourceAction( RepositoryName: img.RepositoryName, ImageURI: uri, ImageTags: img.Tags, - }) + }, jsonx.V1()) if err == nil { err = b.putOutputFiles(ctx, p, execID, action, map[string][]byte{imageDetailFile: detail}) } diff --git a/services/codepipeline/tags_test.go b/services/codepipeline/tags_test.go index 6a210bcdc2..f2f6298783 100644 --- a/services/codepipeline/tags_test.go +++ b/services/codepipeline/tags_test.go @@ -2,13 +2,14 @@ package codepipeline_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -173,7 +174,7 @@ func TestHandler_ListTagsForResource_WebhookARN(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) } }) @@ -201,7 +202,7 @@ func TestSortedListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags, ok := out["tags"].([]any) require.True(t, ok) @@ -228,7 +229,7 @@ func TestListTagsForResource_EmptySlice(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags := out["tags"] assert.NotNil(t, tags) @@ -280,7 +281,7 @@ func TestWebhookTagging(t *testing.T) { // Get the webhook ARN. var putOut map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) webhookEntry := putOut["webhook"].(map[string]any) arn := webhookEntry["arn"].(string) require.NotEmpty(t, arn) @@ -308,7 +309,7 @@ func TestWebhookTagging(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) rawTags, _ := listOut["tags"].([]any) gotKeys := make([]string, 0, len(rawTags)) diff --git a/services/codepipeline/third_party_jobs_test.go b/services/codepipeline/third_party_jobs_test.go index ae993d186d..da89b3e178 100644 --- a/services/codepipeline/third_party_jobs_test.go +++ b/services/codepipeline/third_party_jobs_test.go @@ -1,13 +1,14 @@ package codepipeline_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -67,7 +68,7 @@ func TestHandler_AcknowledgeThirdPartyJob(t *testing.T) { if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantStatus, out["status"]) } }) @@ -166,7 +167,7 @@ func TestHandler_PollForThirdPartyJobs_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jobs, _ := out["jobs"].([]any) require.Len(t, jobs, 1) @@ -218,7 +219,7 @@ func TestGetThirdPartyJobDetails_DataPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) details, ok := out["jobDetails"].(map[string]any) require.True(t, ok, "jobDetails must be present") diff --git a/services/codepipeline/webhooks_test.go b/services/codepipeline/webhooks_test.go index 9ed32cbf20..95308746fe 100644 --- a/services/codepipeline/webhooks_test.go +++ b/services/codepipeline/webhooks_test.go @@ -1,7 +1,8 @@ package codepipeline_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codepipeline" ) @@ -107,7 +109,7 @@ func TestHandler_DeregisterWebhookWithThirdParty(t *testing.T) { if tt.httpStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out) } }) @@ -248,7 +250,7 @@ func TestHandler_Webhook_FullModel(t *testing.T) { if tt.checkFn != nil && tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.checkFn(t, out) } }) @@ -329,7 +331,7 @@ func TestHandler_ListWebhooks_DefinitionWrapper(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) webhooks, _ := out["webhooks"].([]any) assert.Len(t, webhooks, tt.wantCount) @@ -499,7 +501,7 @@ func TestCPPagination_ListWebhooks(t *testing.T) { NextToken string `json:"NextToken"` Webhooks []map[string]any `json:"webhooks"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) total += len(out.Webhooks) pages++ @@ -561,7 +563,7 @@ func TestPutWebhook_Filters_EmptyNotAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) webhook, ok := raw["webhook"].(map[string]any) require.True(t, ok, "webhook must be an object") @@ -604,7 +606,7 @@ func TestListWebhooks_Filters_EmptyNotAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) webhooks, ok := raw["webhooks"].([]any) require.True(t, ok, "webhooks must be an array") @@ -651,7 +653,7 @@ func TestListWebhooks_Filters_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) webhooks, ok := raw["webhooks"].([]any) require.True(t, ok) diff --git a/services/codestarconnections/handler.go b/services/codestarconnections/handler.go index 7e6c704228..e3efeb72e4 100644 --- a/services/codestarconnections/handler.go +++ b/services/codestarconnections/handler.go @@ -2,7 +2,7 @@ package codestarconnections import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -183,7 +184,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ResourceName string `json:"ResourceName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ConnectionArn != "": @@ -229,14 +230,12 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } const codestarContentType = "application/x-amz-json-1.0" func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError var errType string var statusCode int @@ -256,7 +255,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err errType, statusCode = "LimitExceededException", http.StatusBadRequest case errors.Is(err, ErrValidation), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): errType, statusCode = errTypeInvalidInput, http.StatusBadRequest default: errType, statusCode = "InternalFailure", http.StatusInternalServerError @@ -265,7 +264,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err payload, marshalErr := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: wireMessage(err, errType), - }) + }, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } diff --git a/services/codestarconnections/handler_connections_test.go b/services/codestarconnections/handler_connections_test.go index 6aff1d4816..0e0c485444 100644 --- a/services/codestarconnections/handler_connections_test.go +++ b/services/codestarconnections/handler_connections_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -50,7 +51,7 @@ func TestHandler_CreateConnection(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out[tt.wantKey]) }) } @@ -119,7 +120,7 @@ func TestHandler_GetConnection(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) conn, ok := out["Connection"].(map[string]any) require.True(t, ok) assert.Equal(t, "test-conn", conn["ConnectionName"]) @@ -209,7 +210,7 @@ func TestHandler_ListConnections(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) conns, ok := out["Connections"].([]any) require.True(t, ok) assert.Len(t, conns, tt.wantCount) @@ -339,7 +340,7 @@ func TestSortedListConnections(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) conns := out["Connections"].([]any) require.Len(t, conns, 3) @@ -372,7 +373,7 @@ func TestGetConnectionIncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) conn := out["Connection"].(map[string]any) _, hasTags := conn["Tags"] assert.False(t, hasTags, "GetConnection should not include Tags in response") @@ -381,7 +382,7 @@ func TestGetConnectionIncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, recTags.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "env", tags[0].(map[string]any)["Key"].(string)) diff --git a/services/codestarconnections/handler_hosts_test.go b/services/codestarconnections/handler_hosts_test.go index 09decc3dc1..8a6670255e 100644 --- a/services/codestarconnections/handler_hosts_test.go +++ b/services/codestarconnections/handler_hosts_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -52,7 +53,7 @@ func TestHandler_CreateHost(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["HostArn"]) }) } @@ -132,7 +133,7 @@ func TestHandler_GetHost(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "test-host", out["Name"]) assert.Equal(t, "GitHubEnterpriseServer", out["ProviderType"]) assert.Equal(t, "https://example.com", out["ProviderEndpoint"]) @@ -152,7 +153,7 @@ func TestHandler_ListHosts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) hosts, ok := out["Hosts"].([]any) require.True(t, ok) assert.Len(t, hosts, 2) @@ -346,7 +347,7 @@ func TestSortedListHosts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) hosts := out["Hosts"].([]any) require.Len(t, hosts, 3) @@ -380,7 +381,7 @@ func TestGetHostIncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &out, jsonx.V1())) _, hasTags := out["Tags"] assert.False(t, hasTags, "GetHost should not include Tags in response") @@ -388,7 +389,7 @@ func TestGetHostIncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, recTags.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "platform", tags[0].(map[string]any)["Value"].(string)) diff --git a/services/codestarconnections/handler_repository_links_test.go b/services/codestarconnections/handler_repository_links_test.go index b8d700cd4b..c897b743d7 100644 --- a/services/codestarconnections/handler_repository_links_test.go +++ b/services/codestarconnections/handler_repository_links_test.go @@ -2,7 +2,7 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -69,7 +70,7 @@ func TestHandler_CreateRepositoryLink(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) info, ok := out["RepositoryLinkInfo"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, info["RepositoryLinkId"]) @@ -138,7 +139,7 @@ func TestHandler_GetRepositoryLink(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) info, ok := out["RepositoryLinkInfo"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-owner", info["OwnerId"]) @@ -226,7 +227,7 @@ func TestHandler_ListRepositoryLinks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) links, ok := out["RepositoryLinks"].([]any) require.True(t, ok) assert.Len(t, links, 2) diff --git a/services/codestarconnections/handler_sync_blockers_test.go b/services/codestarconnections/handler_sync_blockers_test.go index dfa7b2540d..c10c9f0230 100644 --- a/services/codestarconnections/handler_sync_blockers_test.go +++ b/services/codestarconnections/handler_sync_blockers_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -71,7 +72,7 @@ func TestHandler_GetSyncBlockerSummary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summary, ok := out["SyncBlockerSummary"].(map[string]any) require.True(t, ok) assert.Equal(t, "blocker-resource", summary["ResourceName"]) diff --git a/services/codestarconnections/handler_sync_configurations_test.go b/services/codestarconnections/handler_sync_configurations_test.go index 0ffea88f89..dcd64e375e 100644 --- a/services/codestarconnections/handler_sync_configurations_test.go +++ b/services/codestarconnections/handler_sync_configurations_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -84,7 +85,7 @@ func TestHandler_CreateSyncConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) cfg, ok := out["SyncConfiguration"].(map[string]any) require.True(t, ok) assert.Equal(t, "main", cfg["Branch"]) @@ -147,7 +148,7 @@ func TestHandler_GetSyncConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) cfg, ok := out["SyncConfiguration"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-stack", cfg["ResourceName"]) @@ -225,7 +226,7 @@ func TestHandler_RepositoryLink_SyncConfiguration_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recLink.Code) var linkOut map[string]any - require.NoError(t, json.Unmarshal(recLink.Body.Bytes(), &linkOut)) + require.NoError(t, json.Unmarshal(recLink.Body.Bytes(), &linkOut, jsonx.V1())) linkInfo := linkOut["RepositoryLinkInfo"].(map[string]any) linkID := linkInfo["RepositoryLinkId"].(string) require.NotEmpty(t, linkID) @@ -242,7 +243,7 @@ func TestHandler_RepositoryLink_SyncConfiguration_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recSync.Code) var syncOut map[string]any - require.NoError(t, json.Unmarshal(recSync.Body.Bytes(), &syncOut)) + require.NoError(t, json.Unmarshal(recSync.Body.Bytes(), &syncOut, jsonx.V1())) syncCfg := syncOut["SyncConfiguration"].(map[string]any) assert.Equal(t, "my-repo", syncCfg["RepositoryName"]) assert.Equal(t, "GitHub", syncCfg["ProviderType"]) @@ -267,7 +268,7 @@ func TestHandler_RepositoryLink_SyncConfiguration_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) links, ok := listOut["RepositoryLinks"].([]any) require.True(t, ok) assert.Len(t, links, 1) diff --git a/services/codestarconnections/handler_sync_statuses_test.go b/services/codestarconnections/handler_sync_statuses_test.go index bd72b5dfe7..7fe4f1e04b 100644 --- a/services/codestarconnections/handler_sync_statuses_test.go +++ b/services/codestarconnections/handler_sync_statuses_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -74,7 +75,7 @@ func TestHandler_GetRepositorySyncStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) latest, ok := out["LatestSync"].(map[string]any) require.True(t, ok) assert.Equal(t, "SUCCEEDED", latest["Status"]) @@ -136,7 +137,7 @@ func TestHandler_GetResourceSyncStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) latest, ok := out["LatestSync"].(map[string]any) require.True(t, ok) assert.Equal(t, "SUCCEEDED", latest["Status"]) diff --git a/services/codestarconnections/handler_tags_test.go b/services/codestarconnections/handler_tags_test.go index ea5663db45..6cd379bcb9 100644 --- a/services/codestarconnections/handler_tags_test.go +++ b/services/codestarconnections/handler_tags_test.go @@ -2,13 +2,14 @@ package codestarconnections_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -31,7 +32,7 @@ func TestHandler_TagResource_Connection(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) tags, ok := out["Tags"].([]any) require.True(t, ok) require.Len(t, tags, 1) @@ -93,7 +94,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags, ok := out["Tags"].([]any) require.True(t, ok) require.Len(t, tags, 1) @@ -125,7 +126,7 @@ func TestSortedTags(t *testing.T) { require.Equal(t, http.StatusOK, recTags.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) keys := make([]string, len(tags)) @@ -178,7 +179,7 @@ func TestTagResourceOnHost(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "ci", tags[0].(map[string]any)["Value"].(string)) @@ -211,7 +212,7 @@ func TestUntagResourceRemovesKeys(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "keep", tags[0].(map[string]any)["Key"].(string)) diff --git a/services/codestarconnections/handler_test.go b/services/codestarconnections/handler_test.go index a79bfaec9c..d2e7a9ee36 100644 --- a/services/codestarconnections/handler_test.go +++ b/services/codestarconnections/handler_test.go @@ -3,7 +3,7 @@ package codestarconnections_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/codestarconnections" ) @@ -28,7 +29,7 @@ func doRequest(t *testing.T, h *codestarconnections.Handler, action string, body var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -52,7 +53,7 @@ func parseResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -527,7 +528,7 @@ func TestErrValidationMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidInputException", resp["__type"]) } @@ -670,7 +671,7 @@ func TestExtractResource(t *testing.T) { h := newTestHandler(t) - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) e := echo.New() diff --git a/services/codestarconnections/persistence.go b/services/codestarconnections/persistence.go index cd78ca1a20..b224bb20c7 100644 --- a/services/codestarconnections/persistence.go +++ b/services/codestarconnections/persistence.go @@ -2,7 +2,7 @@ package codestarconnections import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -87,10 +87,10 @@ func resourceSyncStatusDTOKeyFn(d *resourceSyncStatusDTO) string { // an incompatible (older or newer) build of this backend as though it were // the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // persistenceDTOTables groups every ephemeral DTO table Snapshot/Restore @@ -246,7 +246,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // syncBlockers; see store_setup.go's registerAllTables doc) from tables via // the ephemeral DTO registry, factored out of Restore to keep Restore's own // cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("codestarconnections: restore snapshot DTO tables: %w", err) diff --git a/services/cognitoidentity/handler.go b/services/cognitoidentity/handler.go index b3c47be5d5..1a1d476a81 100644 --- a/services/cognitoidentity/handler.go +++ b/services/cognitoidentity/handler.go @@ -3,7 +3,7 @@ package cognitoidentity import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -119,7 +120,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { IdentityID string `json:"IdentityId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.IdentityPoolID != "" { return req.IdentityPoolID @@ -186,7 +187,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -252,11 +253,11 @@ func resolveErrorType(err error) (string, int) { } } - if _, ok := errors.AsType[*json.SyntaxError](err); ok { + if _, ok := jsonx.SyntaxError(err); ok { return ErrInvalidParameter.Error(), http.StatusBadRequest } - if _, ok := errors.AsType[*json.UnmarshalTypeError](err); ok { + if _, ok := jsonx.TypeError(err); ok { return ErrInvalidParameter.Error(), http.StatusBadRequest } diff --git a/services/cognitoidentity/handler_credentials_test.go b/services/cognitoidentity/handler_credentials_test.go index 4afb195016..62d5bc9e2f 100644 --- a/services/cognitoidentity/handler_credentials_test.go +++ b/services/cognitoidentity/handler_credentials_test.go @@ -1,13 +1,15 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aws-sdk-go-v2's cognitoidentity deserializer parses Credentials.Expiration with @@ -27,7 +29,7 @@ func TestGetCredentialsForIdentity_ExpirationIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rolesRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -44,7 +46,7 @@ func TestGetCredentialsForIdentity_ExpirationIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetCredentialsForIdentity", map[string]any{ "IdentityId": idOut["IdentityId"], @@ -52,7 +54,7 @@ func TestGetCredentialsForIdentity_ExpirationIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) creds := out["Credentials"].(map[string]any) expiration, ok := creds["Expiration"].(float64) @@ -118,7 +120,7 @@ func TestGetCredentialsForIdentity_CustomRoleArn(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rolesRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -135,7 +137,7 @@ func TestGetCredentialsForIdentity_CustomRoleArn(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) req := map[string]any{"IdentityId": idOut["IdentityId"]} if tt.customRoleArn != "" { @@ -166,7 +168,7 @@ func TestHandler_GetCredentialsForIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rolesRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -183,7 +185,7 @@ func TestHandler_GetCredentialsForIdentity(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetCredentialsForIdentity", map[string]any{ "IdentityId": idOut["IdentityId"], @@ -191,7 +193,7 @@ func TestHandler_GetCredentialsForIdentity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["IdentityId"]) creds, ok := out["Credentials"].(map[string]any) @@ -213,7 +215,7 @@ func TestHandler_GetOpenIDToken(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) idRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -222,7 +224,7 @@ func TestHandler_GetOpenIDToken(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetOpenIdToken", map[string]any{ "IdentityId": idOut["IdentityId"], @@ -230,7 +232,7 @@ func TestHandler_GetOpenIDToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["Token"]) assert.Equal(t, idOut["IdentityId"], out["IdentityId"]) } @@ -294,7 +296,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) body = map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -310,7 +312,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["IdentityId"]) assert.NotEmpty(t, out["Token"]) } @@ -331,7 +333,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity_ExistingIdentity(t *testing. require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) // First call creates a new identity. @@ -344,7 +346,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity_ExistingIdentity(t *testing. require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) identityID1 := out1["IdentityId"].(string) // Second call with same logins should re-use the same identity. @@ -357,7 +359,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity_ExistingIdentity(t *testing. require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) identityID2 := out2["IdentityId"].(string) assert.Equal(t, identityID1, identityID2) @@ -375,7 +377,7 @@ func TestHandler_GetOpenIdTokenForDeveloperIdentity_InvalidDuration(t *testing.T require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetOpenIdTokenForDeveloperIdentity", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], diff --git a/services/cognitoidentity/handler_developer_identities_test.go b/services/cognitoidentity/handler_developer_identities_test.go index bdb1316853..d21aaab442 100644 --- a/services/cognitoidentity/handler_developer_identities_test.go +++ b/services/cognitoidentity/handler_developer_identities_test.go @@ -1,12 +1,14 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_LookupDeveloperIdentity(t *testing.T) { @@ -52,7 +54,7 @@ func TestHandler_LookupDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID = created["IdentityPoolId"].(string) devRec := doCognitoIdentityRequest(t, h, "GetOpenIdTokenForDeveloperIdentity", map[string]any{ @@ -64,7 +66,7 @@ func TestHandler_LookupDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, devRec.Code) var devOut map[string]any - require.NoError(t, json.Unmarshal(devRec.Body.Bytes(), &devOut)) + require.NoError(t, json.Unmarshal(devRec.Body.Bytes(), &devOut, jsonx.V1())) identityID = devOut["IdentityId"].(string) } @@ -89,7 +91,7 @@ func TestHandler_LookupDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) body = map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -101,7 +103,7 @@ func TestHandler_LookupDeveloperIdentity(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["IdentityId"]) } }) @@ -145,7 +147,7 @@ func TestHandler_MergeDeveloperIdentities(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) for _, userID := range []string{"user-src", "user-dst"} { @@ -171,7 +173,7 @@ func TestHandler_MergeDeveloperIdentities(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["IdentityId"]) } }) @@ -226,7 +228,7 @@ func TestHandler_UnlinkIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) getIDRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ @@ -239,7 +241,7 @@ func TestHandler_UnlinkIdentity(t *testing.T) { require.Equal(t, http.StatusOK, getIDRec.Code) var getIDOut map[string]any - require.NoError(t, json.Unmarshal(getIDRec.Body.Bytes(), &getIDOut)) + require.NoError(t, json.Unmarshal(getIDRec.Body.Bytes(), &getIDOut, jsonx.V1())) identityID = getIDOut["IdentityId"].(string) body = map[string]any{ @@ -261,7 +263,7 @@ func TestHandler_UnlinkIdentity(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) logins, ok := descOut["Logins"].([]any) require.True(t, ok) assert.Equal(t, []any{"graph.facebook.com"}, logins) @@ -308,7 +310,7 @@ func TestHandler_UnlinkDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID = created["IdentityPoolId"].(string) tokenRec := doCognitoIdentityRequest(t, h, "GetOpenIdTokenForDeveloperIdentity", map[string]any{ @@ -320,7 +322,7 @@ func TestHandler_UnlinkDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, tokenRec.Code) var tokenOut map[string]any - require.NoError(t, json.Unmarshal(tokenRec.Body.Bytes(), &tokenOut)) + require.NoError(t, json.Unmarshal(tokenRec.Body.Bytes(), &tokenOut, jsonx.V1())) identityID = tokenOut["IdentityId"].(string) body = map[string]any{ @@ -343,7 +345,7 @@ func TestHandler_UnlinkDeveloperIdentity(t *testing.T) { require.Equal(t, http.StatusOK, lookupRec.Code) var lookupOut map[string]any - require.NoError(t, json.Unmarshal(lookupRec.Body.Bytes(), &lookupOut)) + require.NoError(t, json.Unmarshal(lookupRec.Body.Bytes(), &lookupOut, jsonx.V1())) ids, ok := lookupOut["DeveloperUserIdentifierList"].([]any) require.True(t, ok) assert.Empty(t, ids) @@ -364,7 +366,7 @@ func TestHandler_UnlinkIdentity_TokenMismatch_Returns403(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) idRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -376,7 +378,7 @@ func TestHandler_UnlinkIdentity_TokenMismatch_Returns403(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "UnlinkIdentity", map[string]any{ "IdentityId": idOut["IdentityId"], @@ -402,7 +404,7 @@ func TestHandler_UnlinkDeveloperIdentity_WrongUser_Returns403(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) devRec := doCognitoIdentityRequest(t, h, "GetOpenIdTokenForDeveloperIdentity", map[string]any{ @@ -414,7 +416,7 @@ func TestHandler_UnlinkDeveloperIdentity_WrongUser_Returns403(t *testing.T) { require.Equal(t, http.StatusOK, devRec.Code) var devOut map[string]any - require.NoError(t, json.Unmarshal(devRec.Body.Bytes(), &devOut)) + require.NoError(t, json.Unmarshal(devRec.Body.Bytes(), &devOut, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "UnlinkDeveloperIdentity", map[string]any{ "IdentityId": devOut["IdentityId"], diff --git a/services/cognitoidentity/handler_identities_test.go b/services/cognitoidentity/handler_identities_test.go index 24ee102ae1..d8d8bb5200 100644 --- a/services/cognitoidentity/handler_identities_test.go +++ b/services/cognitoidentity/handler_identities_test.go @@ -1,13 +1,16 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetID_UnauthDisabled_EmptyLogins(t *testing.T) { @@ -22,7 +25,7 @@ func TestHandler_GetID_UnauthDisabled_EmptyLogins(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -43,7 +46,7 @@ func TestHandler_ListIdentities_MaxResultsZero(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "ListIdentities", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -64,7 +67,7 @@ func TestHandler_GetID(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -74,7 +77,7 @@ func TestHandler_GetID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["IdentityId"]) } @@ -139,7 +142,7 @@ func TestHandler_DeleteIdentities(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) idRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -148,7 +151,7 @@ func TestHandler_DeleteIdentities(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) body = map[string]any{ "IdentityIdsToDelete": []string{idOut["IdentityId"].(string)}, @@ -160,7 +163,7 @@ func TestHandler_DeleteIdentities(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) unprocessed, _ := out["UnprocessedIdentityIds"].([]any) assert.Len(t, unprocessed, tt.wantLen) } @@ -195,7 +198,7 @@ func TestHandler_DescribeIdentity(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) idRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ "AccountId": "000000000000", @@ -207,7 +210,7 @@ func TestHandler_DescribeIdentity(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) identityID = idOut["IdentityId"].(string) } @@ -219,7 +222,7 @@ func TestHandler_DescribeIdentity(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, identityID, out["IdentityId"]) assert.NotEmpty(t, out["CreationDate"]) logins, _ := out["Logins"].([]any) @@ -257,7 +260,7 @@ func TestHandler_ListIdentities(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID = created["IdentityPoolId"].(string) for _, login := range []map[string]string{ @@ -282,7 +285,7 @@ func TestHandler_ListIdentities(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, poolID, out["IdentityPoolId"]) identities, _ := out["Identities"].([]any) @@ -304,7 +307,7 @@ func TestSortedListIdentities(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) for _, login := range []map[string]string{ @@ -327,7 +330,7 @@ func TestSortedListIdentities(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) identities, _ := listOut["Identities"].([]any) require.Len(t, identities, 3) @@ -389,7 +392,7 @@ func TestListIdentities_MaxResultsValidation(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "ListIdentities", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -425,7 +428,7 @@ func TestSortedLogins(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) idRec := doCognitoIdentityRequest(t, h, "GetId", map[string]any{ @@ -440,7 +443,7 @@ func TestSortedLogins(t *testing.T) { require.Equal(t, http.StatusOK, idRec.Code) var idOut map[string]any - require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut)) + require.NoError(t, json.Unmarshal(idRec.Body.Bytes(), &idOut, jsonx.V1())) identityID := idOut["IdentityId"].(string) rec := doCognitoIdentityRequest(t, h, "DescribeIdentity", map[string]any{ @@ -449,7 +452,7 @@ func TestSortedLogins(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) logins, _ := descOut["Logins"].([]any) require.Len(t, logins, 3) @@ -498,7 +501,7 @@ func TestHandler_GetID_MergesLoginProviders(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) poolID := createOut["IdentityPoolId"].(string) // First call: only google. @@ -509,7 +512,7 @@ func TestHandler_GetID_MergesLoginProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&out1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &out1, jsonx.V1())) id1 := out1["IdentityId"].(string) // Second call: same google + new facebook → must return same ID. @@ -523,7 +526,7 @@ func TestHandler_GetID_MergesLoginProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out2, jsonx.V1())) id2 := out2["IdentityId"].(string) assert.Equal(t, id1, id2, "GetId must return the same identity when any login provider matches") @@ -541,7 +544,7 @@ func TestHandler_ListIdentities_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) poolID := createOut["IdentityPoolId"].(string) for i := range 3 { @@ -559,7 +562,7 @@ func TestHandler_ListIdentities_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&out1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &out1, jsonx.V1())) assert.Len(t, out1["Identities"], 2) nextToken, _ := out1["NextToken"].(string) assert.NotEmpty(t, nextToken) @@ -573,6 +576,6 @@ func TestHandler_ListIdentities_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out2, jsonx.V1())) assert.Len(t, out2["Identities"], 1) } diff --git a/services/cognitoidentity/handler_identity_pool_roles_test.go b/services/cognitoidentity/handler_identity_pool_roles_test.go index ffc2fb37b5..602601f6e8 100644 --- a/services/cognitoidentity/handler_identity_pool_roles_test.go +++ b/services/cognitoidentity/handler_identity_pool_roles_test.go @@ -1,12 +1,15 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_SetGetIdentityPoolRoles_WithRoleMappings(t *testing.T) { @@ -21,7 +24,7 @@ func TestHandler_SetGetIdentityPoolRoles_WithRoleMappings(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) setRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ @@ -45,7 +48,7 @@ func TestHandler_SetGetIdentityPoolRoles_WithRoleMappings(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) roles, ok := out["Roles"].(map[string]any) require.True(t, ok) @@ -73,7 +76,7 @@ func TestHandler_SetGetIdentityPoolRoles(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) setRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -90,7 +93,7 @@ func TestHandler_SetGetIdentityPoolRoles(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) roles, ok := out["Roles"].(map[string]any) require.True(t, ok) @@ -186,7 +189,7 @@ func TestHandler_GetPrincipalTagAttributeMap(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID = created["IdentityPoolId"].(string) } @@ -199,7 +202,7 @@ func TestHandler_GetPrincipalTagAttributeMap(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantDefaults, out["UseDefaults"]) } }) @@ -244,7 +247,7 @@ func TestHandler_SetPrincipalTagAttributeMap(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) body = map[string]any{ @@ -262,7 +265,7 @@ func TestHandler_SetPrincipalTagAttributeMap(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, false, out["UseDefaults"]) tags, _ := out["PrincipalTags"].(map[string]any) @@ -284,7 +287,7 @@ func TestHandler_SetGetPrincipalTagAttributeMap_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) providerName := "cognito-idp.us-east-1.amazonaws.com/us-east-1_Pool1" @@ -307,7 +310,7 @@ func TestHandler_SetGetPrincipalTagAttributeMap_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, poolID, out["IdentityPoolId"]) assert.Equal(t, providerName, out["IdentityProviderName"]) assert.Equal(t, false, out["UseDefaults"]) @@ -329,7 +332,7 @@ func TestHandler_SetIdentityPoolRoles_SingleRole(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -352,7 +355,7 @@ func TestHandler_GetPrincipalTagAttributeMap_EmptyProvider_Returns400(t *testing require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "GetPrincipalTagAttributeMap", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -384,7 +387,7 @@ func TestHandler_GetIdentityPoolRoles_OmitsEmptyRoles(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) poolID := createOut["IdentityPoolId"].(string) setRec := doCognitoIdentityRequest(t, h, "SetIdentityPoolRoles", map[string]any{ @@ -401,7 +404,7 @@ func TestHandler_GetIdentityPoolRoles_OmitsEmptyRoles(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) roles := out["Roles"].(map[string]any) assert.Contains(t, roles, "authenticated") @@ -420,7 +423,7 @@ func TestHandler_SetIdentityPoolRoles_PreservesExistingRole(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) poolID := createOut["IdentityPoolId"].(string) // Set both roles. @@ -446,7 +449,7 @@ func TestHandler_SetIdentityPoolRoles_PreservesExistingRole(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) roles := out["Roles"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/AuthV2", roles["authenticated"]) diff --git a/services/cognitoidentity/handler_identity_pools_test.go b/services/cognitoidentity/handler_identity_pools_test.go index c2e85bc350..b88d6e73b1 100644 --- a/services/cognitoidentity/handler_identity_pools_test.go +++ b/services/cognitoidentity/handler_identity_pools_test.go @@ -1,12 +1,15 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateIdentityPool_OIDCProviderARNs(t *testing.T) { @@ -54,12 +57,12 @@ func TestCreateIdentityPool_OIDCProviderARNs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) // Verify ARNs in CreateIdentityPool response. - raw, _ := json.Marshal(created["OpenIdConnectProviderARNs"]) + raw, _ := json.Marshal(created["OpenIdConnectProviderARNs"], jsonx.V1()) var gotARNs []string - _ = json.Unmarshal(raw, &gotARNs) + _ = json.Unmarshal(raw, &gotARNs, jsonx.V1()) assert.Equal(t, tt.wantARNs, gotARNs, "create response OpenIdConnectProviderARNs mismatch") poolID, _ := created["IdentityPoolId"].(string) @@ -72,11 +75,11 @@ func TestCreateIdentityPool_OIDCProviderARNs(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) - raw, _ = json.Marshal(desc["OpenIdConnectProviderARNs"]) + raw, _ = json.Marshal(desc["OpenIdConnectProviderARNs"], jsonx.V1()) var descARNs []string - _ = json.Unmarshal(raw, &descARNs) + _ = json.Unmarshal(raw, &descARNs, jsonx.V1()) assert.Equal(t, tt.wantARNs, descARNs, "describe response OpenIdConnectProviderARNs mismatch") }) } @@ -118,11 +121,11 @@ func TestCreateIdentityPool_SAMLProviderARNs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) - raw, _ := json.Marshal(created["SamlProviderARNs"]) + raw, _ := json.Marshal(created["SamlProviderARNs"], jsonx.V1()) var gotARNs []string - _ = json.Unmarshal(raw, &gotARNs) + _ = json.Unmarshal(raw, &gotARNs, jsonx.V1()) assert.Equal(t, tt.wantARNs, gotARNs, "SamlProviderARNs mismatch in create response") }) } @@ -177,7 +180,7 @@ func TestUpdateIdentityPool_OIDCAndSAMLARNs(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID, _ := created["IdentityPoolId"].(string) require.NotEmpty(t, poolID) @@ -191,16 +194,16 @@ func TestUpdateIdentityPool_OIDCAndSAMLARNs(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code, "update: %s", updRec.Body.String()) var updated map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updated, jsonx.V1())) - raw, _ := json.Marshal(updated["OpenIdConnectProviderARNs"]) + raw, _ := json.Marshal(updated["OpenIdConnectProviderARNs"], jsonx.V1()) var gotOIDC []string - _ = json.Unmarshal(raw, &gotOIDC) + _ = json.Unmarshal(raw, &gotOIDC, jsonx.V1()) assert.Equal(t, tt.wantOIDC, gotOIDC, "OIDC ARNs after update") - raw, _ = json.Marshal(updated["SamlProviderARNs"]) + raw, _ = json.Marshal(updated["SamlProviderARNs"], jsonx.V1()) var gotSAML []string - _ = json.Unmarshal(raw, &gotSAML) + _ = json.Unmarshal(raw, &gotSAML, jsonx.V1()) assert.Equal(t, tt.wantSAML, gotSAML, "SAML ARNs after update") }) } @@ -267,7 +270,7 @@ func TestListIdentityPools_Pagination(t *testing.T) { IdentityPools []any `json:"IdentityPools"` NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pageCounts = append(pageCounts, len(out.IdentityPools)) token = out.NextToken @@ -304,7 +307,7 @@ func TestListIdentityPools_TokenPastEnd(t *testing.T) { IdentityPools []any `json:"IdentityPools"` NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.IdentityPools, "token past last pool must return empty list, not first page") assert.Empty(t, out.NextToken) @@ -344,7 +347,7 @@ func TestHandler_CreateIdentityPool(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.poolName, out["IdentityPoolName"]) assert.NotEmpty(t, out["IdentityPoolId"]) } @@ -380,7 +383,7 @@ func TestHandler_DeleteIdentityPool(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) poolID = out["IdentityPoolId"].(string) } else { poolID = "us-east-1:nonexistent" @@ -407,7 +410,7 @@ func TestHandler_DescribeIdentityPool(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "DescribeIdentityPool", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -415,7 +418,7 @@ func TestHandler_DescribeIdentityPool(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "desc-pool", out["IdentityPoolName"]) } @@ -438,7 +441,7 @@ func TestHandler_ListIdentityPools(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pools, ok := out["IdentityPools"].([]any) require.True(t, ok) @@ -457,7 +460,7 @@ func TestHandler_UpdateIdentityPool(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) rec := doCognitoIdentityRequest(t, h, "UpdateIdentityPool", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -467,7 +470,7 @@ func TestHandler_UpdateIdentityPool(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, false, out["AllowUnauthenticatedIdentities"]) } @@ -514,7 +517,7 @@ func TestHandler_WithProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "provider-pool", out["IdentityPoolName"]) providers, ok := out["CognitoIdentityProviders"].([]any) @@ -541,7 +544,7 @@ func TestSortedListIdentityPools(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pools, _ := out["IdentityPools"].([]any) require.Len(t, pools, 3) @@ -571,7 +574,7 @@ func TestTagsInIdentityPoolOutput(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) // Tags should be in the CreateIdentityPool response. tags, _ := created["IdentityPoolTags"].(map[string]any) @@ -585,7 +588,7 @@ func TestTagsInIdentityPoolOutput(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) descTags, _ := descOut["IdentityPoolTags"].(map[string]any) assert.Equal(t, "test", descTags["env"]) @@ -603,7 +606,7 @@ func TestDeleteIdentityPool_CleansTagsAndPrincipalTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) arn := "arn:aws:cognito-identity:us-east-1:000000000000:identitypool/" + poolID @@ -648,7 +651,7 @@ func TestHandler_DeveloperProviderName_InCreateAndDescribe(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, "developer.myapp.com", created["DeveloperProviderName"]) descRec := doCognitoIdentityRequest(t, h, "DescribeIdentityPool", map[string]any{ @@ -657,7 +660,7 @@ func TestHandler_DeveloperProviderName_InCreateAndDescribe(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "developer.myapp.com", descOut["DeveloperProviderName"]) } @@ -674,7 +677,7 @@ func TestHandler_UpdateIdentityPool_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) updateRec := doCognitoIdentityRequest(t, h, "UpdateIdentityPool", map[string]any{ @@ -686,7 +689,7 @@ func TestHandler_UpdateIdentityPool_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updated, jsonx.V1())) tags, _ := updated["IdentityPoolTags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "backend", tags["team"]) @@ -744,7 +747,7 @@ func TestHandler_ListIdentityPools_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&out1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &out1, jsonx.V1())) assert.Len(t, out1["IdentityPools"], 2) nextToken, _ := out1["NextToken"].(string) assert.NotEmpty(t, nextToken) @@ -757,6 +760,6 @@ func TestHandler_ListIdentityPools_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out2, jsonx.V1())) assert.Len(t, out2["IdentityPools"], 1) } diff --git a/services/cognitoidentity/handler_tags_test.go b/services/cognitoidentity/handler_tags_test.go index e122f31ddc..2b2689a511 100644 --- a/services/cognitoidentity/handler_tags_test.go +++ b/services/cognitoidentity/handler_tags_test.go @@ -1,12 +1,14 @@ package cognitoidentity_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListTagsForResource(t *testing.T) { @@ -43,7 +45,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) arn = "arn:aws:cognito-identity:us-east-1:000000000000:identitypool/" + poolID } @@ -56,7 +58,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags, _ := out["Tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) } @@ -76,7 +78,7 @@ func TestHandler_TagResource_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) arn := "arn:aws:cognito-identity:us-east-1:000000000000:identitypool/" + poolID @@ -97,7 +99,7 @@ func TestHandler_TagResource_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tags, _ := listOut["Tags"].(map[string]any) assert.Equal(t, "backend", tags["team"]) assert.Equal(t, "alice", tags["owner"]) @@ -116,7 +118,7 @@ func TestHandler_TagResource_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2, jsonx.V1())) tags2, _ := listOut2["Tags"].(map[string]any) assert.Equal(t, "backend", tags2["team"]) assert.NotContains(t, tags2, "owner") @@ -160,7 +162,7 @@ func TestListTagsForResource_EmptyTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) arn := "arn:aws:cognito-identity:us-east-1:000000000000:identitypool/" + poolID @@ -171,7 +173,7 @@ func TestListTagsForResource_EmptyTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Tags should always be present (even if empty), not omitted. tags, hasKey := out["Tags"] diff --git a/services/cognitoidentity/handler_test.go b/services/cognitoidentity/handler_test.go index d9c02b54f2..c644d91277 100644 --- a/services/cognitoidentity/handler_test.go +++ b/services/cognitoidentity/handler_test.go @@ -3,7 +3,7 @@ package cognitoidentity_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidentity" ) @@ -62,7 +63,7 @@ func doCognitoIdentityRequest( ) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -338,7 +339,7 @@ func TestNonNilSlices(t *testing.T) { require.Equal(t, http.StatusOK, listPoolsRec.Code) var listPoolsOut map[string]any - require.NoError(t, json.Unmarshal(listPoolsRec.Body.Bytes(), &listPoolsOut)) + require.NoError(t, json.Unmarshal(listPoolsRec.Body.Bytes(), &listPoolsOut, jsonx.V1())) pools, poolsOK := listPoolsOut["IdentityPools"].([]any) require.True(t, poolsOK, "IdentityPools should be a non-null array") assert.Empty(t, pools) @@ -351,7 +352,7 @@ func TestNonNilSlices(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) listIDsRec := doCognitoIdentityRequest(t, h, "ListIdentities", map[string]any{ "IdentityPoolId": created["IdentityPoolId"], @@ -360,7 +361,7 @@ func TestNonNilSlices(t *testing.T) { require.Equal(t, http.StatusOK, listIDsRec.Code) var listIDsOut map[string]any - require.NoError(t, json.Unmarshal(listIDsRec.Body.Bytes(), &listIDsOut)) + require.NoError(t, json.Unmarshal(listIDsRec.Body.Bytes(), &listIDsOut, jsonx.V1())) identities, idsOK := listIDsOut["Identities"].([]any) require.True(t, idsOK, "Identities should be a non-null array") assert.Empty(t, identities) @@ -389,7 +390,7 @@ func TestSeedHelpers(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "seeded-pool", descOut["IdentityPoolName"]) // Seed an identity. @@ -420,7 +421,7 @@ func TestCountHelpers(t *testing.T) { assert.Equal(t, 1, h.Backend.PoolCount()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) doCognitoIdentityRequest(t, h, "GetId", map[string]any{ @@ -470,7 +471,7 @@ func TestPersistenceRoundTripWithPrincipalTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) poolID := created["IdentityPoolId"].(string) setRec := doCognitoIdentityRequest(t, h, "SetPrincipalTagAttributeMap", map[string]any{ @@ -497,7 +498,7 @@ func TestPersistenceRoundTripWithPrincipalTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) tags, _ := getOut["PrincipalTags"].(map[string]any) assert.Equal(t, "user_id", tags["sub"]) diff --git a/services/cognitoidentity/login_tokens.go b/services/cognitoidentity/login_tokens.go index 2e2508b215..ace6363d06 100644 --- a/services/cognitoidentity/login_tokens.go +++ b/services/cognitoidentity/login_tokens.go @@ -5,10 +5,12 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const jwtSegments = 3 @@ -28,7 +30,7 @@ func parseLoginClaims(token string) (map[string]any, bool) { } var claims map[string]any - if json.Unmarshal(raw, &claims) != nil { + if json.Unmarshal(raw, &claims, jsonx.V1()) != nil { return nil, false } @@ -123,7 +125,7 @@ func (b *InMemoryBackend) verifyLoginSignature(token string, claims map[string]a Kid string `json:"kid"` } - if json.Unmarshal(rawHdr, &hdr) != nil { + if json.Unmarshal(rawHdr, &hdr, jsonx.V1()) != nil { return errBadSignature } diff --git a/services/cognitoidentity/open_id_token.go b/services/cognitoidentity/open_id_token.go index 0c3a422439..8fabc51b7b 100644 --- a/services/cognitoidentity/open_id_token.go +++ b/services/cognitoidentity/open_id_token.go @@ -2,9 +2,11 @@ package cognitoidentity import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -50,12 +52,12 @@ func issueOpenIDToken( claims[openIDTagsClaim] = tags } - header, err := json.Marshal(map[string]string{"alg": "RS256", "typ": "JWT"}) + header, err := json.Marshal(map[string]string{"alg": "RS256", "typ": "JWT"}, jsonx.V1()) if err != nil { return "", fmt.Errorf("encode token header: %w", err) } - payload, err := json.Marshal(claims) + payload, err := json.Marshal(claims, jsonx.V1()) if err != nil { return "", fmt.Errorf("encode token claims: %w", err) } diff --git a/services/cognitoidentity/open_id_token_test.go b/services/cognitoidentity/open_id_token_test.go index c58450d76f..0acec5afd5 100644 --- a/services/cognitoidentity/open_id_token_test.go +++ b/services/cognitoidentity/open_id_token_test.go @@ -3,13 +3,14 @@ package cognitoidentity_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidentity" ) @@ -23,7 +24,7 @@ func tokenClaims(t *testing.T, token string) map[string]any { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) return claims } diff --git a/services/cognitoidentity/persistence.go b/services/cognitoidentity/persistence.go index 77baf9ce8b..edab853440 100644 --- a/services/cognitoidentity/persistence.go +++ b/services/cognitoidentity/persistence.go @@ -2,7 +2,7 @@ package cognitoidentity import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -60,10 +60,10 @@ func principalTagDTOKeyFn(d *principalTagDTO) string { // decoding a snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // persistenceDTOTables groups every ephemeral DTO table buildPersistenceDTORegistry @@ -225,7 +225,7 @@ func unwrapPrincipalTagDTOs(dtos *store.Table[principalTagDTO]) []*PrincipalTagM // restoreResourceTables rebuilds every store.Table on b from snap's per-table JSON, // factored out of Restore to keep Restore's own cognitive complexity low. Callers must // hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/cognitoidentity/persistence_test.go b/services/cognitoidentity/persistence_test.go index 03e51cd828..2db79aa3a9 100644 --- a/services/cognitoidentity/persistence_test.go +++ b/services/cognitoidentity/persistence_test.go @@ -5,11 +5,13 @@ package cognitoidentity //nolint:testpackage // see comment above. import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // testRegionEast and testRegionWest are the two AWS regions exercised by the @@ -220,11 +222,11 @@ func tamperSnapshotVersion(t *testing.T, data []byte, version int) []byte { t.Helper() var snap backendSnapshot - require.NoError(t, json.Unmarshal(data, &snap)) + require.NoError(t, json.Unmarshal(data, &snap, jsonx.V1())) snap.Version = version - out, err := json.Marshal(snap) + out, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) return out diff --git a/services/cognitoidentity/role_selection_test.go b/services/cognitoidentity/role_selection_test.go index da45ff0814..d680153e95 100644 --- a/services/cognitoidentity/role_selection_test.go +++ b/services/cognitoidentity/role_selection_test.go @@ -7,7 +7,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "maps" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidentity" ) @@ -302,10 +303,10 @@ func signedLogin(t *testing.T, key *rsa.PrivateKey, claims map[string]any) strin t.Helper() enc := base64.RawURLEncoding - hdr, err := json.Marshal(map[string]string{"alg": "RS256", "kid": "k1"}) + hdr, err := json.Marshal(map[string]string{"alg": "RS256", "kid": "k1"}, jsonx.V1()) require.NoError(t, err) - body, err := json.Marshal(claims) + body, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) signing := enc.EncodeToString(hdr) + "." + enc.EncodeToString(body) diff --git a/services/cognitoidentity/sdk_login_token_flow_test.go b/services/cognitoidentity/sdk_login_token_flow_test.go index 5bfd506f30..4b311b909b 100644 --- a/services/cognitoidentity/sdk_login_token_flow_test.go +++ b/services/cognitoidentity/sdk_login_token_flow_test.go @@ -2,7 +2,7 @@ package cognitoidentity_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,16 +11,18 @@ import ( sdktypes "github.com/aws/aws-sdk-go-v2/service/cognitoidentity/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func loginJWT(t *testing.T, claims map[string]any) string { t.Helper() enc := base64.RawURLEncoding - hdr, err := json.Marshal(map[string]string{"alg": "RS256"}) + hdr, err := json.Marshal(map[string]string{"alg": "RS256"}, jsonx.V1()) require.NoError(t, err) - body, err := json.Marshal(claims) + body, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) return enc.EncodeToString(hdr) + "." + enc.EncodeToString(body) + ".sig" diff --git a/services/cognitoidp/attribute_custom_message_test.go b/services/cognitoidp/attribute_custom_message_test.go index 2995a2693e..ebdc03c0a1 100644 --- a/services/cognitoidp/attribute_custom_message_test.go +++ b/services/cognitoidp/attribute_custom_message_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -134,7 +135,7 @@ func TestUpdateUserAttributes_CustomMessageAndVerification(t *testing.T) { var resp struct { CodeDeliveryDetailsList []map[string]string `json:"CodeDeliveryDetailsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.CodeDeliveryDetailsList, 1) d := resp.CodeDeliveryDetailsList[0] @@ -216,7 +217,7 @@ func TestGetUserAttributeVerificationCode_FiresCustomMessage(t *testing.T) { var resp struct { CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "subj", resp.CodeDeliveryDetails["CustomMessageSubject"]) assert.Equal(t, "v", metadataOf(t, f.inv, "CustomMessage_VerifyUserAttribute", "clientMetadata")["k"]) } diff --git a/services/cognitoidp/attributes_management_test.go b/services/cognitoidp/attributes_management_test.go index 2e1e66fffb..427f854258 100644 --- a/services/cognitoidp/attributes_management_test.go +++ b/services/cognitoidp/attributes_management_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -133,7 +134,7 @@ func TestHandler_UpdateUserAttributes(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "attr-pool"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -141,7 +142,7 @@ func TestHandler_UpdateUserAttributes(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -168,7 +169,7 @@ func TestHandler_UpdateUserAttributes(t *testing.T) { require.Equal(t, http.StatusOK, authRec.Code) var authData map[string]map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authData)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authData, jsonx.V1())) accessToken := authData["AuthenticationResult"]["AccessToken"].(string) if tt.badToken { @@ -221,7 +222,7 @@ func TestHandler_AdminUpdateUserAttributes(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "admin-attr-pool"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -256,7 +257,7 @@ func TestHandler_AddCustomAttributes(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "test-pool"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["UserPool"].(map[string]any)["Id"].(string) }, @@ -334,7 +335,7 @@ func TestHandler_AdminDeleteUserAttributes(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "attr-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) username := "deleteattr-user" @@ -393,7 +394,7 @@ func TestAddCustomAttributes_RequiresCustomPrefix(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "prefix-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) rec := doCognitoRequest(t, h, "AddCustomAttributes", map[string]any{ @@ -413,7 +414,7 @@ func TestSortedAttributes(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "sorted-attrs-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -434,7 +435,7 @@ func TestSortedAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) attrs := resp["UserAttributes"].([]any) require.GreaterOrEqual(t, len(attrs), 3) @@ -462,7 +463,7 @@ func TestIDTokenUserAttributeClaims(t *testing.T) { require.Equal(t, http.StatusOK, poolRec.Code) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -476,7 +477,7 @@ func TestIDTokenUserAttributeClaims(t *testing.T) { require.Equal(t, http.StatusOK, clientRec.Code) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) signupRec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -490,7 +491,7 @@ func TestIDTokenUserAttributeClaims(t *testing.T) { require.Equal(t, http.StatusOK, signupRec.Code) var signupResp map[string]any - require.NoError(t, json.Unmarshal(signupRec.Body.Bytes(), &signupResp)) + require.NoError(t, json.Unmarshal(signupRec.Body.Bytes(), &signupResp, jsonx.V1())) // AutoVerifiedAttributes only selects which channel receives the confirmation // code; it does not skip confirmation itself (see TestSignUpWithValidation_AutoVerify). @@ -513,7 +514,7 @@ func TestIDTokenUserAttributeClaims(t *testing.T) { require.Equal(t, http.StatusOK, authRec.Code) var authResp map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) idToken := authResp["AuthenticationResult"].(map[string]any)["IdToken"].(string) claims := decodeJWTPayload(t, idToken) @@ -550,7 +551,7 @@ func TestAdminCreateUserSubInAttributes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) user := resp["User"].(map[string]any) attrs := user["Attributes"].([]any) diff --git a/services/cognitoidp/attributes_test.go b/services/cognitoidp/attributes_test.go index 6fbe0dd2c6..1d95583949 100644 --- a/services/cognitoidp/attributes_test.go +++ b/services/cognitoidp/attributes_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -50,7 +51,7 @@ func TestVerifyUserAttribute_RealCodeValidation(t *testing.T) { ID string `json:"Id"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -63,7 +64,7 @@ func TestVerifyUserAttribute_RealCodeValidation(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp.UserPoolClient.ClientID // Sign up and confirm a user with email attribute. @@ -117,7 +118,7 @@ func TestVerifyUserAttribute_RealCodeValidation(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) @@ -279,7 +280,7 @@ func TestAttrVerification_Handler_GetAndVerify(t *testing.T) { CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails,omitempty"` UserConfirmed bool `json:"UserConfirmed,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp, jsonx.V1())) if !signUpResp.UserConfirmed { confirmRec := doCognitoRequest(t, h, "ConfirmSignUp", map[string]any{ @@ -302,7 +303,7 @@ func TestAttrVerification_Handler_GetAndVerify(t *testing.T) { var codeOut struct { CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &codeOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &codeOut, jsonx.V1())) assert.Equal(t, "EMAIL", codeOut.CodeDeliveryDetails["DeliveryMedium"]) assert.NotEmpty(t, codeOut.CodeDeliveryDetails["Destination"]) @@ -449,7 +450,7 @@ func TestHandler_VerifyUserAttribute(t *testing.T) { CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails,omitempty"` UserConfirmed bool `json:"UserConfirmed,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp, jsonx.V1())) if !signUpResp.UserConfirmed { confirmRec := doCognitoRequest(t, h, "ConfirmSignUp", map[string]any{ diff --git a/services/cognitoidp/auth_events_test.go b/services/cognitoidp/auth_events_test.go index 542559a798..572835285a 100644 --- a/services/cognitoidp/auth_events_test.go +++ b/services/cognitoidp/auth_events_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAdminListUserAuthEvents_EmptyButValid(t *testing.T) { @@ -26,7 +28,7 @@ func TestAdminListUserAuthEvents_EmptyButValid(t *testing.T) { NextToken string `json:"NextToken,omitempty"` AuthEvents []map[string]any `json:"AuthEvents,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.AuthEvents) assert.Empty(t, resp.NextToken) @@ -122,7 +124,7 @@ func TestHandler_AdminListUserAuthEvents_Validation(t *testing.T) { var resp struct { AuthEvents []map[string]any `json:"AuthEvents"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.AuthEvents) }) diff --git a/services/cognitoidp/auth_tokens.go b/services/cognitoidp/auth_tokens.go index e6e1fe8a41..205fddc51e 100644 --- a/services/cognitoidp/auth_tokens.go +++ b/services/cognitoidp/auth_tokens.go @@ -4,7 +4,7 @@ import ( "crypto/rsa" "crypto/subtle" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -12,6 +12,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // findUserByAccessTokenLocked finds the live *User for a given access token. @@ -104,7 +106,7 @@ func tokenHeaderKID(token string) string { var hdr struct { Kid string `json:"kid"` } - if json.Unmarshal(raw, &hdr) != nil { + if json.Unmarshal(raw, &hdr, jsonx.V1()) != nil { return "" } diff --git a/services/cognitoidp/auth_tokens_test.go b/services/cognitoidp/auth_tokens_test.go index 7cdb43f65c..87595510c2 100644 --- a/services/cognitoidp/auth_tokens_test.go +++ b/services/cognitoidp/auth_tokens_test.go @@ -2,7 +2,7 @@ package cognitoidp_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -121,7 +122,7 @@ func initiateAuth(t *testing.T, h *cognitoidp.Handler, clientID, username string require.Equal(t, http.StatusOK, rec.Code, "InitiateAuth: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -137,7 +138,7 @@ func jwtClaims(t *testing.T, token string) map[string]any { require.NoError(t, err, "base64 decode JWT payload") var claims map[string]any - require.NoError(t, json.Unmarshal(payload, &claims)) + require.NoError(t, json.Unmarshal(payload, &claims, jsonx.V1())) return claims } @@ -217,7 +218,7 @@ func TestTokenValidity_StoredAndReturned(t *testing.T) { RefreshTokenValidity int32 `json:"RefreshTokenValidity"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, tt.accessTokenValidity, createResp.UserPoolClient.AccessTokenValidity) assert.Equal(t, tt.idTokenValidity, createResp.UserPoolClient.IDTokenValidity) assert.Equal(t, wantRefresh, createResp.UserPoolClient.RefreshTokenValidity) @@ -242,7 +243,7 @@ func TestTokenValidity_StoredAndReturned(t *testing.T) { RefreshTokenValidity int32 `json:"RefreshTokenValidity"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.accessTokenValidity, descResp.UserPoolClient.AccessTokenValidity) assert.Equal(t, tt.idTokenValidity, descResp.UserPoolClient.IDTokenValidity) assert.Equal(t, wantRefresh, descResp.UserPoolClient.RefreshTokenValidity) @@ -268,7 +269,7 @@ func TestTokenValidity_UpdateClient(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clientID := createResp.UserPoolClient.ClientID // Update with validity settings. @@ -291,7 +292,7 @@ func TestTokenValidity_UpdateClient(t *testing.T) { IDTokenValidity int32 `json:"IdTokenValidity"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) assert.Equal(t, int32(5), updResp.UserPoolClient.AccessTokenValidity) assert.Equal(t, int32(5), updResp.UserPoolClient.IDTokenValidity) assert.Equal(t, "minutes", updResp.UserPoolClient.TokenValidityUnits["AccessToken"]) @@ -349,7 +350,7 @@ func TestTokenValidity_HonoredInJWT(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clientID := createResp.UserPoolClient.ClientID // Create and confirm a user, then authenticate. @@ -374,7 +375,7 @@ func TestTokenValidity_HonoredInJWT(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &cr, jsonx.V1())) validClientID := cr.UserPoolClient.ClientID // Sign up user with the validity client. @@ -409,7 +410,7 @@ func TestTokenValidity_HonoredInJWT(t *testing.T) { ExpiresIn float64 `json:"ExpiresIn"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) assert.InDelta(t, tt.wantExpiresIn, authResp.AuthenticationResult.ExpiresIn, 1, "ExpiresIn mismatch") @@ -464,7 +465,7 @@ func TestAuthFlow_RefreshTokenAuth(t *testing.T) { require.Equal(t, http.StatusOK, refreshRec.Code, refreshRec.Body.String()) var refreshResp map[string]any - require.NoError(t, json.Unmarshal(refreshRec.Body.Bytes(), &refreshResp)) + require.NoError(t, json.Unmarshal(refreshRec.Body.Bytes(), &refreshResp, jsonx.V1())) result, ok := refreshResp["AuthenticationResult"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, result["AccessToken"]) @@ -587,7 +588,7 @@ func TestGetTokensFromRefreshToken(t *testing.T) { RefreshToken string `json:"RefreshToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) refreshToken := authResp.AuthenticationResult.RefreshToken require.NotEmpty(t, refreshToken) @@ -603,7 +604,7 @@ func TestGetTokensFromRefreshToken(t *testing.T) { AccessToken string `json:"AccessToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tokenResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tokenResp, jsonx.V1())) assert.NotEmpty(t, tokenResp.AuthenticationResult.AccessToken) } @@ -702,7 +703,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -710,7 +711,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) // Admin-create a confirmed user. @@ -737,7 +738,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { }, }) var authResp map[string]map[string]any - _ = json.Unmarshal(authRec.Body.Bytes(), &authResp) + _ = json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1()) rt := authResp["AuthenticationResult"]["RefreshToken"].(string) return clientID, rt @@ -749,7 +750,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p2"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -757,7 +758,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { "ClientName": "c2", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) return clientID, "totally-invalid-refresh-token" @@ -784,7 +785,7 @@ func TestHandler_RefreshTokenAuth(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["AuthenticationResult"]["AccessToken"]) assert.NotEmpty(t, resp["AuthenticationResult"]["IdToken"]) // After rotation the old token is gone; new one must differ. diff --git a/services/cognitoidp/branding_test.go b/services/cognitoidp/branding_test.go index b9068587fa..fc1fd999b0 100644 --- a/services/cognitoidp/branding_test.go +++ b/services/cognitoidp/branding_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestUICustomization_SetGet_WithImageFile(t *testing.T) { @@ -33,7 +35,7 @@ func TestUICustomization_SetGet_WithImageFile(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"UICustomization"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) require.NotNil(t, setOut.UICustomization) assert.Equal(t, poolID, setOut.UICustomization.UserPoolID) assert.Equal(t, clientID, setOut.UICustomization.ClientID) @@ -56,7 +58,7 @@ func TestUICustomization_SetGet_WithImageFile(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"UICustomization"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) require.NotNil(t, getOut.UICustomization) assert.Equal(t, ".banner { background: blue; }", getOut.UICustomization.CSS) assert.Empty(t, getOut.UICustomization.ImageURL) @@ -80,7 +82,7 @@ func TestUICustomization_Get_Empty(t *testing.T) { CSS string `json:"CSS,omitempty"` } `json:"UICustomization"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.UICustomization) assert.Empty(t, out.UICustomization.CSS) } @@ -155,7 +157,7 @@ func TestUICustomization(t *testing.T) { CSS string `json:"CSS,omitempty"` } `json:"UICustomization"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, ".logo { color: red; }", resp.UICustomization.CSS) } @@ -177,7 +179,7 @@ func TestManagedLoginBranding_CRUD(t *testing.T) { ManagedLoginBrandingID string `json:"ManagedLoginBrandingId,omitempty"` } `json:"ManagedLoginBranding"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) brandingID := createResp.ManagedLoginBranding.ManagedLoginBrandingID require.NotEmpty(t, brandingID) @@ -252,7 +254,7 @@ func TestManagedLoginBranding_SettingsAndAssets_AcceptedAndEchoed(t *testing.T) var createResp struct { ManagedLoginBranding managedLoginBrandingWire `json:"ManagedLoginBranding"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) componentClasses, ok := createResp.ManagedLoginBranding.Settings["componentClasses"].(map[string]any) require.True(t, ok) primaryButton, ok := componentClasses["primaryButton"].(map[string]any) @@ -277,7 +279,7 @@ func TestManagedLoginBranding_SettingsAndAssets_AcceptedAndEchoed(t *testing.T) var updResp struct { ManagedLoginBranding managedLoginBrandingWire `json:"ManagedLoginBranding"` } - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) assert.True(t, updResp.ManagedLoginBranding.UseCognitoProvidedValues) assert.NotEmpty(t, updResp.ManagedLoginBranding.Settings, "omitting Settings on update must not clear it") } diff --git a/services/cognitoidp/delivery_test.go b/services/cognitoidp/delivery_test.go index c675ba3506..4e71afa573 100644 --- a/services/cognitoidp/delivery_test.go +++ b/services/cognitoidp/delivery_test.go @@ -2,7 +2,7 @@ package cognitoidp_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -76,7 +77,7 @@ func newDeliveryEnv(t *testing.T, poolExtra map[string]any) *deliveryEnv { } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pool)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pool, jsonx.V1())) rec = doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ "UserPoolId": pool.UserPool.ID, "ClientName": "app", @@ -89,7 +90,7 @@ func newDeliveryEnv(t *testing.T, poolExtra map[string]any) *deliveryEnv { } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &client)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &client, jsonx.V1())) return &deliveryEnv{h: h, snd: snd, poolID: pool.UserPool.ID, clientID: client.UserPoolClient.ClientID} } @@ -102,7 +103,7 @@ func (e *deliveryEnv) call(t *testing.T, action string, body map[string]any) map var out map[string]any if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out diff --git a/services/cognitoidp/devices_test.go b/services/cognitoidp/devices_test.go index d4c2b484e2..662d044d2d 100644 --- a/services/cognitoidp/devices_test.go +++ b/services/cognitoidp/devices_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -33,7 +34,7 @@ func TestDevices_CRUD(t *testing.T) { var confirmResp struct { UserConfirmationNecessary bool `json:"UserConfirmationNecessary,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &confirmResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &confirmResp, jsonx.V1())) assert.False(t, confirmResp.UserConfirmationNecessary) // ListDevices — discover the generated device key. @@ -43,7 +44,7 @@ func TestDevices_CRUD(t *testing.T) { var listResp struct { Devices []deviceWire `json:"Devices,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Devices, 1) assert.NotContains(t, rec.Body.String(), "DeviceStatus") deviceKey := listResp.Devices[0].DeviceKey @@ -59,7 +60,7 @@ func TestDevices_CRUD(t *testing.T) { var getResp struct { Device deviceWire `json:"Device"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, deviceKey, getResp.Device.DeviceKey) // UpdateDeviceStatus -> remembered @@ -75,7 +76,7 @@ func TestDevices_CRUD(t *testing.T) { "DeviceKey": deviceKey, }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, rec.Body.String(), "DeviceStatus") // ForgetDevice @@ -101,7 +102,7 @@ func TestDevices_CRUD(t *testing.T) { var listResp2 struct { Devices []deviceWire `json:"Devices,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2, jsonx.V1())) assert.Empty(t, listResp2.Devices) } @@ -144,7 +145,7 @@ func TestDevices_NotFoundAndValidation(t *testing.T) { var listResp struct { Devices []deviceWire `json:"Devices,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Devices, 1) rec = doCognitoRequest(t, h, "UpdateDeviceStatus", map[string]any{ @@ -179,7 +180,7 @@ func TestAdminDevices_CRUD(t *testing.T) { var listResp struct { Devices []deviceWire `json:"Devices,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Devices, 1) assert.Equal(t, "device-abc", listResp.Devices[0].DeviceKey) @@ -210,7 +211,7 @@ func TestAdminDevices_CRUD(t *testing.T) { var getResp struct { Device deviceWire `json:"Device"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, rec.Body.String(), "DeviceStatus") // AdminForgetDevice — real deletion when the device exists. @@ -395,7 +396,7 @@ func TestHandler_AdminForgetDevice(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "device-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) username := "device-user" diff --git a/services/cognitoidp/domains_test.go b/services/cognitoidp/domains_test.go index 8bf070a1a2..017b878e72 100644 --- a/services/cognitoidp/domains_test.go +++ b/services/cognitoidp/domains_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -79,7 +80,7 @@ func TestCreateUserPoolDomain_ManagedDomain_EmptyCloudFrontDomain(t *testing.T) var out struct { CloudFrontDomain string `json:"CloudFrontDomain,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantCF { assert.Contains( @@ -114,7 +115,7 @@ func TestUserPoolDomain_Managed(t *testing.T) { var out struct { CloudFrontDomain string `json:"CloudFrontDomain,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Managed domains: AWS returns empty CloudFrontDomain (no CloudFront distribution). assert.Empty(t, out.CloudFrontDomain) } @@ -139,7 +140,7 @@ func TestUserPoolDomain_Custom_WithCertArn(t *testing.T) { var createOut struct { CloudFrontDomain string `json:"CloudFrontDomain,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.Contains(t, createOut.CloudFrontDomain, "cloudfront.net") // Describe should return the domain with status. @@ -159,7 +160,7 @@ func TestUserPoolDomain_Custom_WithCertArn(t *testing.T) { CloudFrontDistribution string `json:"CloudFrontDistribution,omitempty"` } `json:"DomainDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.DomainDescription) assert.Equal(t, "auth.mycompany.com", descOut.DomainDescription.Domain) assert.Equal(t, "ACTIVE", descOut.DomainDescription.Status) @@ -197,7 +198,7 @@ func TestUserPoolDomain_Managed_NoCustomDomainConfig(t *testing.T) { } `json:"CustomDomainConfig,omitempty"` } `json:"DomainDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.DomainDescription) assert.Nil(t, descOut.DomainDescription.CustomDomainConfig) } @@ -231,7 +232,7 @@ func TestUserPoolDomain_Update_WithCertArn(t *testing.T) { var out struct { CloudFrontDomain string `json:"CloudFrontDomain,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out.CloudFrontDomain, "cloudfront.net") } @@ -282,7 +283,7 @@ func TestUserPoolDomain_Describe_AWSAccountIdManagedLoginVersionS3Bucket(t *test var createOut struct { ManagedLoginVersion *int32 `json:"ManagedLoginVersion,omitempty"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) require.NotNil(t, createOut.ManagedLoginVersion, "CreateUserPoolDomain must echo ManagedLoginVersion") assert.Equal(t, tt.wantMLV, *createOut.ManagedLoginVersion) @@ -290,7 +291,7 @@ func TestUserPoolDomain_Describe_AWSAccountIdManagedLoginVersionS3Bucket(t *test require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out domainDescriptionWire - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.DomainDescription) assert.NotEmpty(t, out.DomainDescription.AWSAccountID) @@ -323,7 +324,7 @@ func TestUserPoolDomain_UpdateManagedLoginVersion_OmittedRetainsPrior(t *testing var updateOut struct { ManagedLoginVersion *int32 `json:"ManagedLoginVersion,omitempty"` } - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) require.NotNil(t, updateOut.ManagedLoginVersion, "UpdateUserPoolDomain must echo ManagedLoginVersion") assert.EqualValues(t, 2, *updateOut.ManagedLoginVersion, "omitting the field on update must not reset it") } @@ -429,7 +430,7 @@ func TestDomain_FullCRUDLifecycle(t *testing.T) { var createResp struct { CloudFrontDomain string `json:"CloudFrontDomain,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) // Managed domains: AWS returns empty CloudFrontDomain in the create response. assert.Empty(t, createResp.CloudFrontDomain) @@ -445,7 +446,7 @@ func TestDomain_FullCRUDLifecycle(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"DomainDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "myapp", descResp.DomainDescription.Domain) assert.Equal(t, "ACTIVE", descResp.DomainDescription.Status) @@ -475,6 +476,6 @@ func TestDomain_FullCRUDLifecycle(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"DomainDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterDeleteResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterDeleteResp, jsonx.V1())) assert.Empty(t, afterDeleteResp.DomainDescription.Domain) } diff --git a/services/cognitoidp/federation_providers_test.go b/services/cognitoidp/federation_providers_test.go index 70be4d4e4c..2ae4ee5831 100644 --- a/services/cognitoidp/federation_providers_test.go +++ b/services/cognitoidp/federation_providers_test.go @@ -5,7 +5,8 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/x509" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "net/http" "net/http/httptest" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -48,7 +50,10 @@ func newOAuth2OnlyIDP(t *testing.T, profile map[string]any) *oauth2OnlyIDP { return } - _ = json.NewEncoder(w).Encode(map[string]string{"access_token": "opaque-token", "token_type": "bearer"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"access_token": "opaque-token", "token_type": "bearer"}, + ) case "/me": if r.Header.Get("Authorization") != "Bearer opaque-token" { http.Error(w, "unauthorized", http.StatusUnauthorized) @@ -56,7 +61,7 @@ func newOAuth2OnlyIDP(t *testing.T, profile map[string]any) *oauth2OnlyIDP { return } - _ = json.NewEncoder(w).Encode(idp.profile) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), idp.profile) default: http.NotFound(w, r) } diff --git a/services/cognitoidp/groups_membership_test.go b/services/cognitoidp/groups_membership_test.go index 25c01a9d76..47843fd197 100644 --- a/services/cognitoidp/groups_membership_test.go +++ b/services/cognitoidp/groups_membership_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -236,7 +237,7 @@ func TestHandler_Groups_CRUD(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "grp-pool"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) // Create a group. @@ -283,7 +284,7 @@ func TestHandler_Groups_CRUD(t *testing.T) { assert.Equal(t, http.StatusOK, listRec2.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp, jsonx.V1())) groups := listResp["Groups"].([]any) assert.Empty(t, groups) } @@ -334,7 +335,7 @@ func TestHandler_AdminGroupMembership(t *testing.T) { // Set up pool, user, and group. poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "grp-pool"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -405,7 +406,7 @@ func TestHandler_AdminGroupMembership(t *testing.T) { }) assert.Equal(t, http.StatusOK, listRec2.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp, jsonx.V1())) groups := listResp["Groups"].([]any) assert.Empty(t, groups) } @@ -419,7 +420,7 @@ func TestSortedListGroups(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "sorted-groups-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) for _, name := range []string{"zeta", "admin", "moderator"} { @@ -433,7 +434,7 @@ func TestSortedListGroups(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) groups := listResp["Groups"].([]any) require.Len(t, groups, 3) assert.Equal(t, "admin", groups[0].(map[string]any)["GroupName"]) @@ -447,7 +448,7 @@ func TestSortedAdminListGroupsForUser(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "algfu-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) for _, g := range []string{"zeta", "alpha", "beta"} { @@ -478,7 +479,7 @@ func TestSortedAdminListGroupsForUser(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["Groups"].([]any) require.Len(t, groups, 3) assert.Equal(t, "alpha", groups[0].(map[string]any)["GroupName"]) @@ -537,7 +538,7 @@ func TestAccessTokenGroupsClaim(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) authResult := resp["AuthenticationResult"].(map[string]any) accessToken := authResult["AccessToken"].(string) @@ -593,7 +594,7 @@ func TestAdminListGroupsForUser_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body) var page1 listOut - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Groups, 2) require.NotEmpty(t, page1.NextToken, "first page must return a cursor when more groups remain") @@ -606,7 +607,7 @@ func TestAdminListGroupsForUser_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body) var page2 listOut - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.Groups, 1) require.Empty(t, page2.NextToken) diff --git a/services/cognitoidp/groups_test.go b/services/cognitoidp/groups_test.go index 90926953b9..bb35148c7f 100644 --- a/services/cognitoidp/groups_test.go +++ b/services/cognitoidp/groups_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -186,7 +187,7 @@ func TestGroup_LastModifiedDate_Present(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Greater(t, out.Group.LastModifiedDate, float64(0), "CreateGroup must include LastModifiedDate") @@ -202,7 +203,7 @@ func TestGroup_LastModifiedDate_Present(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Greater(t, out.Group.LastModifiedDate, float64(0), "GetGroup must include LastModifiedDate") @@ -219,7 +220,7 @@ func TestGroup_LastModifiedDate_Present(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Greater(t, out.Group.LastModifiedDate, float64(0), "UpdateGroup must include LastModifiedDate") @@ -235,7 +236,7 @@ func TestGroup_LastModifiedDate_Present(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Groups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Groups, 1) assert.Greater( t, @@ -273,7 +274,7 @@ func TestGroup_Create_WithRoleArn(t *testing.T) { CreationDate float64 `json:"CreationDate,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Equal(t, "admins", out.Group.GroupName) assert.Equal(t, roleArn, out.Group.RoleArn) @@ -310,7 +311,7 @@ func TestGroup_Update_WithRoleArn(t *testing.T) { Precedence int32 `json:"Precedence,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Equal(t, roleArn, out.Group.RoleArn) assert.Equal(t, int32(10), out.Group.Precedence) @@ -344,7 +345,7 @@ func TestGroup_GetGroup_WithRoleArn(t *testing.T) { Precedence int32 `json:"Precedence,omitempty"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Group) assert.Equal(t, "viewers", out.Group.GroupName) assert.Equal(t, roleArn, out.Group.RoleArn) @@ -378,7 +379,7 @@ func TestGroup_ListGroups_Pagination(t *testing.T) { GroupName string `json:"GroupName,omitempty"` } `json:"Groups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Groups, 3) assert.NotEmpty(t, page1.NextToken) @@ -396,7 +397,7 @@ func TestGroup_ListGroups_Pagination(t *testing.T) { GroupName string `json:"GroupName,omitempty"` } `json:"Groups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Groups, 2) assert.Empty(t, page2.NextToken) } @@ -439,7 +440,7 @@ func TestGroup_ListUsersInGroup_Pagination(t *testing.T) { Username string `json:"Username,omitempty"` } `json:"Users"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Users, 2) assert.NotEmpty(t, page1.NextToken) @@ -458,7 +459,7 @@ func TestGroup_ListUsersInGroup_Pagination(t *testing.T) { Username string `json:"Username,omitempty"` } `json:"Users"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Users, 2) assert.Empty(t, page2.NextToken) } diff --git a/services/cognitoidp/handler.go b/services/cognitoidp/handler.go index 6a8436f438..9a42222061 100644 --- a/services/cognitoidp/handler.go +++ b/services/cognitoidp/handler.go @@ -2,7 +2,7 @@ package cognitoidp import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -321,7 +322,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { Username string `json:"Username,omitempty"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.UserPoolID != "" { return req.UserPoolID @@ -421,7 +422,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -483,11 +484,11 @@ func resolveErrorType(err error) (string, int) { } } - if _, ok := errors.AsType[*json.SyntaxError](err); ok { + if _, ok := jsonx.SyntaxError(err); ok { return errInvalidParameterException, http.StatusBadRequest } - if _, ok := errors.AsType[*json.UnmarshalTypeError](err); ok { + if _, ok := jsonx.TypeError(err); ok { return errInvalidParameterException, http.StatusBadRequest } diff --git a/services/cognitoidp/handler_auth_challenges_test.go b/services/cognitoidp/handler_auth_challenges_test.go index 9f4e911a55..7397225c0a 100644 --- a/services/cognitoidp/handler_auth_challenges_test.go +++ b/services/cognitoidp/handler_auth_challenges_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -153,7 +154,7 @@ func TestHandler_AdminRespondToAuthChallenge(t *testing.T) { var authResp struct { Session string `json:"Session,omitempty"` } - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) session = authResp.Session } @@ -234,7 +235,7 @@ func TestHandler_RespondToAuthChallenge_NewPassword(t *testing.T) { Session string `json:"Session,omitempty"` } - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) session = authResp.Session } @@ -259,7 +260,7 @@ func TestHandler_ForgotPasswordConfirmForgotPassword(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "fp-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -267,7 +268,7 @@ func TestHandler_ForgotPasswordConfirmForgotPassword(t *testing.T) { "ClientName": "fp-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -288,7 +289,7 @@ func TestHandler_ForgotPasswordConfirmForgotPassword(t *testing.T) { assert.Equal(t, http.StatusOK, fpRec.Code) var fpResp map[string]any - require.NoError(t, json.Unmarshal(fpRec.Body.Bytes(), &fpResp)) + require.NoError(t, json.Unmarshal(fpRec.Body.Bytes(), &fpResp, jsonx.V1())) details := fpResp["CodeDeliveryDetails"].(map[string]any) code := details["ConfirmationCode"].(string) require.NotEmpty(t, code) @@ -330,7 +331,7 @@ func TestHandler_GetUser_ChangePassword(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "gu-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -338,7 +339,7 @@ func TestHandler_GetUser_ChangePassword(t *testing.T) { "ClientName": "gu-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -366,7 +367,7 @@ func TestHandler_GetUser_ChangePassword(t *testing.T) { assert.Equal(t, http.StatusOK, authRec.Code) var authResp map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) authResult := authResp["AuthenticationResult"].(map[string]any) accessToken := authResult["AccessToken"].(string) @@ -377,7 +378,7 @@ func TestHandler_GetUser_ChangePassword(t *testing.T) { assert.Equal(t, http.StatusOK, guRec.Code) var guResp map[string]any - require.NoError(t, json.Unmarshal(guRec.Body.Bytes(), &guResp)) + require.NoError(t, json.Unmarshal(guRec.Body.Bytes(), &guResp, jsonx.V1())) assert.Equal(t, "guuser", guResp["Username"]) // ChangePassword with wrong old password must fail. @@ -497,7 +498,7 @@ func TestForgotPassword_UserStateValidation(t *testing.T) { if tt.wantType != "" { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) } }) @@ -558,7 +559,7 @@ func TestResendConfirmationCodeAlreadyConfirmed(t *testing.T) { if tt.wantType != "" { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) } }) @@ -607,7 +608,7 @@ func TestConfirmForgotPasswordExpiryCheckedFirst(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fpResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fpResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fpResp, jsonx.V1())) code := tt.useCode if code == "" { @@ -626,7 +627,7 @@ func TestConfirmForgotPasswordExpiryCheckedFirst(t *testing.T) { if tt.wantType != "" { var errResp map[string]any - require.NoError(t, json.Unmarshal(confirmRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(confirmRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) } }) diff --git a/services/cognitoidp/handler_auth_flows_test.go b/services/cognitoidp/handler_auth_flows_test.go index 3b46f04439..8e717ea352 100644 --- a/services/cognitoidp/handler_auth_flows_test.go +++ b/services/cognitoidp/handler_auth_flows_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -32,7 +33,7 @@ func TestHandler_SignUp_PolicyEnforced(t *testing.T) { ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &poolResp, jsonx.V1())) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ "UserPoolId": poolResp.UserPool.ID, @@ -45,7 +46,7 @@ func TestHandler_SignUp_PolicyEnforced(t *testing.T) { ClientID string `json:"ClientId,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp.UserPoolClient.ClientID rec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -100,7 +101,7 @@ func TestSignUp_ConfirmSignUp(t *testing.T) { ID string `json:"Id"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID if tt.policy != nil { @@ -121,7 +122,7 @@ func TestSignUp_ConfirmSignUp(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp.UserPoolClient.ClientID rec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -153,7 +154,7 @@ func TestHandler_SignUp(t *testing.T) { setup: func(h *cognitoidp.Handler) string { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -161,7 +162,7 @@ func TestHandler_SignUp(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) return clientResp["UserPoolClient"]["ClientId"].(string) }, @@ -225,7 +226,7 @@ func TestHandler_ConfirmSignUp(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -233,7 +234,7 @@ func TestHandler_ConfirmSignUp(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) signupRec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -245,7 +246,7 @@ func TestHandler_ConfirmSignUp(t *testing.T) { // Extract confirm code from the CodeDeliveryDetails in the SignUp response. var signupResp map[string]any - _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp) + _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp, jsonx.V1()) code := "" if details, ok := signupResp["CodeDeliveryDetails"].(map[string]any); ok { code, _ = details["ConfirmationCode"].(string) @@ -260,7 +261,7 @@ func TestHandler_ConfirmSignUp(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -268,7 +269,7 @@ func TestHandler_ConfirmSignUp(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) return clientResp["UserPoolClient"]["ClientId"].(string), "nobody", "123456" }, @@ -308,7 +309,7 @@ func TestHandler_InitiateAuth(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -316,7 +317,7 @@ func TestHandler_InitiateAuth(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) signupRec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -328,7 +329,7 @@ func TestHandler_InitiateAuth(t *testing.T) { // Extract the confirmation code from the SignUp response. var signupResp map[string]any - _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp) + _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp, jsonx.V1()) code := "" if details, ok := signupResp["CodeDeliveryDetails"].(map[string]any); ok { code, _ = details["ConfirmationCode"].(string) @@ -352,7 +353,7 @@ func TestHandler_InitiateAuth(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -360,7 +361,7 @@ func TestHandler_InitiateAuth(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) signupRec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -372,7 +373,7 @@ func TestHandler_InitiateAuth(t *testing.T) { // Extract the confirmation code from the SignUp response. var signupResp map[string]any - _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp) + _ = json.Unmarshal(signupRec.Body.Bytes(), &signupResp, jsonx.V1()) code := "" if details, ok := signupResp["CodeDeliveryDetails"].(map[string]any); ok { code, _ = details["ConfirmationCode"].(string) @@ -431,7 +432,7 @@ func TestHandler_AdminInitiateAuth(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -439,7 +440,7 @@ func TestHandler_AdminInitiateAuth(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) clientID := clientResp["UserPoolClient"]["ClientId"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -495,7 +496,7 @@ func TestHandler_AdminConfirmSignUp(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "admin-confirm-pool"}) var poolData map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolData) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolData, jsonx.V1()) poolID := poolData["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -503,7 +504,7 @@ func TestHandler_AdminConfirmSignUp(t *testing.T) { "ClientName": "c", }) var clientData map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientData) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientData, jsonx.V1()) clientID := clientData["UserPoolClient"]["ClientId"].(string) signupRec := doCognitoRequest(t, h, "SignUp", map[string]any{ @@ -552,7 +553,7 @@ func TestAdminNoSRPAuth(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code, "ADMIN_NO_SRP_AUTH should succeed") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasAuth := resp["AuthenticationResult"] assert.True(t, hasAuth, "must have AuthenticationResult") } diff --git a/services/cognitoidp/handler_auth_tokens_test.go b/services/cognitoidp/handler_auth_tokens_test.go index b0d1bc8e1e..30aa011e0c 100644 --- a/services/cognitoidp/handler_auth_tokens_test.go +++ b/services/cognitoidp/handler_auth_tokens_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_SecretHash_InitiateAuth_Via_HTTP(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_SecretHash_InitiateAuth_Via_HTTP(t *testing.T) { ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -39,7 +41,7 @@ func TestHandler_SecretHash_InitiateAuth_Via_HTTP(t *testing.T) { ClientSecret string `json:"ClientSecret,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp.UserPoolClient.ClientID secret := clientResp.UserPoolClient.ClientSecret require.NotEmpty(t, secret) @@ -56,7 +58,7 @@ func TestHandler_SecretHash_InitiateAuth_Via_HTTP(t *testing.T) { var signUpResp struct { CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails,omitempty"` } - require.NoError(t, json.Unmarshal(signUpRec.Body.Bytes(), &signUpResp)) + require.NoError(t, json.Unmarshal(signUpRec.Body.Bytes(), &signUpResp, jsonx.V1())) code := signUpResp.CodeDeliveryDetails["ConfirmationCode"] confirmRec := doCognitoRequest(t, h, "ConfirmSignUp", map[string]any{ @@ -147,7 +149,7 @@ func TestTokenExpiryFor_Backend(t *testing.T) { RefreshTokenValidity int32 `json:"RefreshTokenValidity"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, tt.validity, createResp.UserPoolClient.AccessTokenValidity) assert.Equal(t, tt.unit, createResp.UserPoolClient.TokenValidityUnits[unitKey]) }) @@ -251,12 +253,12 @@ func TestHandler_RevokeToken(t *testing.T) { // Set up pool, client and confirmed user. poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "revoke-pool"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolRec.Body.String() _ = poolID var poolData map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolData) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolData, jsonx.V1()) pID := poolData["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -264,7 +266,7 @@ func TestHandler_RevokeToken(t *testing.T) { "ClientName": "revoke-client", }) var clientData map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientData) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientData, jsonx.V1()) clientID := clientData["UserPoolClient"]["ClientId"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -292,7 +294,7 @@ func TestHandler_RevokeToken(t *testing.T) { require.Equal(t, http.StatusOK, authRec.Code) var authData map[string]map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authData)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authData, jsonx.V1())) refreshToken := authData["AuthenticationResult"]["RefreshToken"].(string) // RevokeToken should succeed (200). diff --git a/services/cognitoidp/handler_test.go b/services/cognitoidp/handler_test.go index a2098b0f0a..6410a5cd4e 100644 --- a/services/cognitoidp/handler_test.go +++ b/services/cognitoidp/handler_test.go @@ -2,7 +2,7 @@ package cognitoidp_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -191,7 +192,7 @@ func TestHandler_JWKS(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -354,7 +355,7 @@ func TestReset(t *testing.T) { ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID assert.Equal(t, 1, b.UserPoolCount()) @@ -423,7 +424,7 @@ func TestNonNilSlices(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "nil-slices-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) // Empty ListUsers must return [] not null. @@ -484,7 +485,7 @@ func TestExportCountHelpers(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "count-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) assert.Equal(t, 1, h.Backend.UserPoolCount()) @@ -593,7 +594,7 @@ func TestHandler_ProvisionedLimits(t *testing.T) { } var resp provisionedLimitResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "API_CATEGORY", resp.Limit.LimitDefinition.LimitClass) assert.EqualValues(t, 120, resp.Limit.FreeLimitValue) @@ -627,7 +628,7 @@ func TestHandler_ProvisionedLimits_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp provisionedLimitResp - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.EqualValues(t, 200, resp.Limit.ProvisionedLimitValue) assert.EqualValues(t, 50, resp.Limit.FreeLimitValue) } diff --git a/services/cognitoidp/handler_users_lifecycle_test.go b/services/cognitoidp/handler_users_lifecycle_test.go index 45ee339057..c330269275 100644 --- a/services/cognitoidp/handler_users_lifecycle_test.go +++ b/services/cognitoidp/handler_users_lifecycle_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -25,7 +26,7 @@ func TestHandler_AdminGetUser(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) poolID := resp["UserPool"]["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -43,7 +44,7 @@ func TestHandler_AdminGetUser(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string), "nobody" }, @@ -95,7 +96,7 @@ func TestHandler_ListUsers(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "test-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -103,7 +104,7 @@ func TestHandler_ListUsers(t *testing.T) { "ClientName": "test-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) if tt.wantCount > 0 { @@ -120,7 +121,7 @@ func TestHandler_ListUsers(t *testing.T) { assert.Equal(t, tt.wantHTTP, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) users := resp["Users"].([]any) assert.Len(t, users, tt.wantCount) }) @@ -155,7 +156,7 @@ func TestHandler_AdminDeleteUser(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "test-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -163,7 +164,7 @@ func TestHandler_AdminDeleteUser(t *testing.T) { "ClientName": "test-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) // Create the user to delete in the first case. @@ -224,7 +225,7 @@ func TestHandler_AdminDisableEnableUser(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "dis-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) username := "dis-user" @@ -252,7 +253,7 @@ func TestHandler_AdminDisableUser_BlocksAuth(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "block-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -260,7 +261,7 @@ func TestHandler_AdminDisableUser_BlocksAuth(t *testing.T) { "ClientName": "block-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -341,7 +342,7 @@ func TestHandler_ListUsers_ReturnsCorrectEnabledState(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "enabled-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) const username = "state-user" @@ -362,7 +363,7 @@ func TestHandler_ListUsers_ReturnsCorrectEnabledState(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) users := listResp["Users"].([]any) require.Len(t, users, 1) assert.Equal(t, tt.wantEnabled, users[0].(map[string]any)["Enabled"].(bool)) @@ -376,7 +377,7 @@ func TestSortedListUsers(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "sorted-users-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) for _, username := range []string{"zeus", "alice", "bob"} { @@ -391,7 +392,7 @@ func TestSortedListUsers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) users := listResp["Users"].([]any) require.Len(t, users, 3) assert.Equal(t, "alice", users[0].(map[string]any)["Username"]) @@ -405,7 +406,7 @@ func TestAdminGetUser_IncludesEnabledAndModifiedDate(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "agu-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -421,7 +422,7 @@ func TestAdminGetUser_IncludesEnabledAndModifiedDate(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.True(t, resp["Enabled"].(bool)) assert.NotZero(t, resp["UserCreateDate"]) assert.NotZero(t, resp["UserLastModifiedDate"]) @@ -433,7 +434,7 @@ func TestAdminCreateUser_IncludesEnabled(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "acu-enabled-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) rec := doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -444,7 +445,7 @@ func TestAdminCreateUser_IncludesEnabled(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.True(t, resp["User"].(map[string]any)["Enabled"].(bool)) } @@ -454,7 +455,7 @@ func TestRefreshToken_DisabledUserBlocked(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "rt-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -462,7 +463,7 @@ func TestRefreshToken_DisabledUserBlocked(t *testing.T) { "ClientName": "rt-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -488,7 +489,7 @@ func TestRefreshToken_DisabledUserBlocked(t *testing.T) { require.Equal(t, http.StatusOK, authRec.Code) var authResp map[string]any - require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp)) + require.NoError(t, json.Unmarshal(authRec.Body.Bytes(), &authResp, jsonx.V1())) refreshToken := authResp["AuthenticationResult"].(map[string]any)["RefreshToken"].(string) // Disable the user. @@ -525,7 +526,7 @@ func TestListUsers_Pagination(t *testing.T) { ID string `json:"Id"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID for i := range 5 { @@ -555,7 +556,7 @@ func TestListUsers_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.Users), 2) for _, u := range resp.Users { diff --git a/services/cognitoidp/handler_users_test.go b/services/cognitoidp/handler_users_test.go index 51b71a4727..755627cd76 100644 --- a/services/cognitoidp/handler_users_test.go +++ b/services/cognitoidp/handler_users_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -36,7 +37,7 @@ func TestHandler_UserSRPAuth_ViaHTTP(t *testing.T) { Session *string `json:"Session,omitempty"` ChallengeParameters map[string]string `json:"ChallengeParameters,omitempty"` } - require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp, jsonx.V1())) require.NotNil(t, initResp.ChallengeName) assert.Equal(t, "PASSWORD_VERIFIER", *initResp.ChallengeName) @@ -55,7 +56,7 @@ func TestHandler_UserSRPAuth_ViaHTTP(t *testing.T) { AccessToken string `json:"AccessToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(respRec.Body.Bytes(), &tokenResp)) + require.NoError(t, json.Unmarshal(respRec.Body.Bytes(), &tokenResp, jsonx.V1())) require.NotNil(t, tokenResp.AuthenticationResult) assert.NotEmpty(t, tokenResp.AuthenticationResult.AccessToken) } @@ -81,7 +82,7 @@ func TestHandler_AdminCreateUser_PolicyEnforced(t *testing.T) { ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID rec := doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ @@ -144,7 +145,7 @@ func TestAuthFlow_UserPasswordAuth(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) authResult, ok := resp["AuthenticationResult"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, authResult["AccessToken"]) @@ -173,7 +174,7 @@ func TestAdminCreateUser(t *testing.T) { Username string `json:"Username"` } `json:"User"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "adminuser", resp.User.Username) } @@ -200,7 +201,7 @@ func TestAdminCreateUser_Suppress(t *testing.T) { UserStatus string `json:"UserStatus,omitempty"` } `json:"User"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.User) assert.Equal(t, "suppressed-user", out.User.Username) assert.Equal(t, "FORCE_CHANGE_PASSWORD", out.User.UserStatus) @@ -234,7 +235,7 @@ func TestAdminCreateUser_Resend(t *testing.T) { UserStatus string `json:"UserStatus,omitempty"` } `json:"User"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.User) assert.Equal(t, "resend-user", out.User.Username) } @@ -261,7 +262,7 @@ func TestAdminCreateUser_DeliveryMediums(t *testing.T) { Username string `json:"Username,omitempty"` } `json:"User"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.User) assert.Equal(t, "delivery-user", out.User.Username) } @@ -299,7 +300,7 @@ func TestAdminSetUserPassword_Permanent(t *testing.T) { var out struct { UserStatus string `json:"UserStatus,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "CONFIRMED", out.UserStatus) } @@ -335,7 +336,7 @@ func TestAdminSetUserPassword_Temporary(t *testing.T) { var out struct { UserStatus string `json:"UserStatus,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "FORCE_CHANGE_PASSWORD", out.UserStatus) } @@ -355,7 +356,7 @@ func TestUserSettings_And_AuthFactors(t *testing.T) { Username string `json:"Username,omitempty"` ConfiguredUserAuthFactors []string `json:"ConfiguredUserAuthFactors,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp, jsonx.V1())) assert.Equal(t, "settings-user", factorsResp.Username) assert.Contains(t, factorsResp.ConfiguredUserAuthFactors, "PASSWORD") assert.NotContains(t, factorsResp.ConfiguredUserAuthFactors, "SMS_OTP") @@ -372,7 +373,7 @@ func TestUserSettings_And_AuthFactors(t *testing.T) { rec = doCognitoRequest(t, h, "GetUserAuthFactors", map[string]any{"AccessToken": accessToken}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp, jsonx.V1())) assert.Contains(t, factorsResp.ConfiguredUserAuthFactors, "SMS_OTP") // Register a WebAuthn credential -> WEB_AUTHN factor appears too. @@ -384,7 +385,7 @@ func TestUserSettings_And_AuthFactors(t *testing.T) { rec = doCognitoRequest(t, h, "GetUserAuthFactors", map[string]any{"AccessToken": accessToken}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &factorsResp, jsonx.V1())) assert.Contains(t, factorsResp.ConfiguredUserAuthFactors, "WEB_AUTHN") // AdminSetUserSettings — admin variant, same persisted state. @@ -486,7 +487,7 @@ func TestHandler_AdminGetUserAuthFactors(t *testing.T) { PreferredMfaSetting string `json:"PreferredMfaSetting,omitempty"` UserMFASettingList []string `json:"UserMFASettingList,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, username, resp.Username) assert.Contains(t, resp.ConfiguredUserAuthFactors, "PASSWORD") assert.Contains(t, resp.ConfiguredUserAuthFactors, "SMS_OTP") @@ -570,7 +571,7 @@ func TestHandler_AdminCreateUser(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -622,7 +623,7 @@ func TestHandler_AdminSetUserPassword(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) poolID := resp["UserPool"]["Id"].(string) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ diff --git a/services/cognitoidp/identity_providers_test.go b/services/cognitoidp/identity_providers_test.go index bc4abaed74..d47f168706 100644 --- a/services/cognitoidp/identity_providers_test.go +++ b/services/cognitoidp/identity_providers_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -48,7 +49,7 @@ func TestCreateIdentityProvider_Duplicate_ReturnsDuplicateProviderException(t *t var errResp struct { Code string `json:"__type,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "DuplicateProviderException", errResp.Code) } else { b := newTestBackend() @@ -123,7 +124,7 @@ func TestUpdateIdentityProvider_ReplacesProviderDetails(t *testing.T) { ProviderDetails map[string]string `json:"ProviderDetails,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.IdentityProvider) assert.Equal(t, "https://new.example.com/metadata", out.IdentityProvider.ProviderDetails["MetadataURL"]) @@ -195,7 +196,7 @@ func TestIdentityProvider_SAML_WithAttributeMapping(t *testing.T) { CreationDate float64 `json:"CreationDate,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) require.NotNil(t, createOut.IdentityProvider) assert.Equal(t, "MySAML", createOut.IdentityProvider.ProviderName) assert.Equal(t, "SAML", createOut.IdentityProvider.ProviderType) @@ -235,7 +236,7 @@ func TestIdentityProvider_OIDC_WithScopes(t *testing.T) { ProviderType string `json:"ProviderType,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.IdentityProvider) assert.Equal(t, "MyOIDC", out.IdentityProvider.ProviderName) assert.Equal(t, "email", out.IdentityProvider.AttributeMapping["email"]) @@ -280,7 +281,7 @@ func TestIdentityProvider_Social_Google(t *testing.T) { ProviderDetails map[string]string `json:"ProviderDetails,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.IdentityProvider) assert.Equal(t, "email", descOut.IdentityProvider.AttributeMapping["email"]) assert.Equal(t, "google-app-id", descOut.IdentityProvider.ProviderDetails["client_id"]) @@ -324,7 +325,7 @@ func TestIdentityProvider_Update_AttributeMapping(t *testing.T) { IdpIdentifiers []string `json:"IdpIdentifiers,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updOut, jsonx.V1())) require.NotNil(t, updOut.IdentityProvider) assert.Equal(t, "id", updOut.IdentityProvider.AttributeMapping["username"]) assert.Contains(t, updOut.IdentityProvider.IdpIdentifiers, "facebook.com") @@ -364,7 +365,7 @@ func TestIdentityProvider_GetByIdentifier(t *testing.T) { CreationDate float64 `json:"CreationDate,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.IdentityProvider) assert.Equal(t, "LoginWithAmazon", out.IdentityProvider.ProviderName) // AttributeMapping/IdpIdentifiers/CreationDate only appear on the "Full" @@ -414,7 +415,7 @@ func TestIdentityProvider_List_WithTimestamps(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Providers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Providers, 3) for _, p := range out.Providers { @@ -544,7 +545,7 @@ func TestIdentityProvider_CRUD(t *testing.T) { ProviderType string `json:"ProviderType,omitempty"` } `json:"IdentityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, "Google", createResp.IdentityProvider.ProviderName) assert.Equal(t, "Google", createResp.IdentityProvider.ProviderType) @@ -573,7 +574,7 @@ func TestIdentityProvider_CRUD(t *testing.T) { ProviderName string `json:"ProviderName,omitempty"` } `json:"Providers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Providers, 1) assert.Equal(t, "Google", listResp.Providers[0].ProviderName) @@ -597,7 +598,7 @@ func TestIdentityProvider_CRUD(t *testing.T) { "UserPoolId": poolID, }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.Providers) } @@ -689,7 +690,7 @@ func TestHandler_AdminDisableProviderForUser(t *testing.T) { if poolID == "" { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "provider-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID = poolResp["UserPool"].(map[string]any)["Id"].(string) createProviderViaHandler(t, h, poolID, "Google", "Google") _, err := h.Backend.CreateFederatedUserForTest(poolID, "Google", "google-123") @@ -743,7 +744,7 @@ func TestListIdentityProviders_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body) var page1 listOut - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Providers, 2) require.NotEmpty(t, page1.NextToken, "first page must return a cursor when more providers remain") @@ -755,7 +756,7 @@ func TestListIdentityProviders_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body) var page2 listOut - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.Providers, 1) require.Empty(t, page2.NextToken) diff --git a/services/cognitoidp/input_validation.go b/services/cognitoidp/input_validation.go index 161b59f11b..dd96df3a15 100644 --- a/services/cognitoidp/input_validation.go +++ b/services/cognitoidp/input_validation.go @@ -1,9 +1,11 @@ package cognitoidp import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -24,7 +26,7 @@ type commonIdentifiers struct { // validateCommonIdentifiers applies the SDK's userPoolId/clientId pattern constraints before dispatch. func validateCommonIdentifiers(body []byte) error { var ids commonIdentifiers - if err := json.Unmarshal(body, &ids); err != nil { + if err := json.Unmarshal(body, &ids, jsonx.V1()); err != nil { return nil //nolint:nilerr // malformed bodies are reported by the op's own decoder } diff --git a/services/cognitoidp/input_validation_test.go b/services/cognitoidp/input_validation_test.go index 213515aee1..275586dc55 100644 --- a/services/cognitoidp/input_validation_test.go +++ b/services/cognitoidp/input_validation_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestInputValidation_ErrorTypes(t *testing.T) { @@ -80,7 +82,7 @@ func TestInputValidation_ErrorTypes(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tc.wantType, errResp.Type) }) } diff --git a/services/cognitoidp/mfa_test.go b/services/cognitoidp/mfa_test.go index db8ebff292..297b31e365 100644 --- a/services/cognitoidp/mfa_test.go +++ b/services/cognitoidp/mfa_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -116,7 +117,7 @@ func TestHandler_GetUser_WithMFAFields(t *testing.T) { PreferredMfaSetting string `json:"PreferredMfaSetting,omitempty"` UserMFASettingList []string `json:"UserMFASettingList,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, []string{"SOFTWARE_TOKEN_MFA"}, resp.UserMFASettingList) assert.Equal(t, "SOFTWARE_TOKEN_MFA", resp.PreferredMfaSetting) } @@ -140,7 +141,7 @@ func TestHandler_RespondToAuthChallenge_SMSMFAFlow(t *testing.T) { var assocResp struct { SecretCode string `json:"SecretCode,omitempty"` } - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) require.NotEmpty(t, assocResp.SecretCode) setupCode, err := cognitoidp.GenerateTOTPCode(assocResp.SecretCode, time.Now()) @@ -173,7 +174,7 @@ func TestHandler_RespondToAuthChallenge_SMSMFAFlow(t *testing.T) { ChallengeName *string `json:"ChallengeName,omitempty"` Session *string `json:"Session,omitempty"` } - require.NoError(t, json.Unmarshal(setMFARec.Body.Bytes(), &mfaInitResp)) + require.NoError(t, json.Unmarshal(setMFARec.Body.Bytes(), &mfaInitResp, jsonx.V1())) require.NotNil(t, mfaInitResp.ChallengeName) require.Equal(t, "SOFTWARE_TOKEN_MFA", *mfaInitResp.ChallengeName) @@ -197,7 +198,7 @@ func TestHandler_RespondToAuthChallenge_SMSMFAFlow(t *testing.T) { AccessToken string `json:"AccessToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(respondRec.Body.Bytes(), &tokenResp)) + require.NoError(t, json.Unmarshal(respondRec.Body.Bytes(), &tokenResp, jsonx.V1())) require.NotNil(t, tokenResp.AuthenticationResult) assert.NotEmpty(t, tokenResp.AuthenticationResult.AccessToken) } @@ -217,7 +218,7 @@ func TestHandler_AssociateSoftwareToken_Accurate(t *testing.T) { var resp struct { SecretCode string `json:"SecretCode,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.SecretCode) assert.Greater(t, len(resp.SecretCode), 10) } @@ -266,7 +267,7 @@ func TestHandler_VerifySoftwareToken_Accurate(t *testing.T) { var assocResp struct { SecretCode string `json:"SecretCode,omitempty"` } - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) require.NotEmpty(t, assocResp.SecretCode) code, err := cognitoidp.GenerateTOTPCode(assocResp.SecretCode, time.Now()) @@ -281,7 +282,7 @@ func TestHandler_VerifySoftwareToken_Accurate(t *testing.T) { var resp struct { Status string `json:"Status,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SUCCESS", resp.Status) } @@ -384,7 +385,7 @@ func TestSetGetMfaConfig_SmsMfaConfiguration(t *testing.T) { } `json:"SmsMfaConfiguration"` MfaConfiguration string `json:"MfaConfiguration,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) assert.Equal(t, "ON", setOut.MfaConfiguration) require.NotNil(t, setOut.SmsMfaConfiguration) assert.Equal(t, "Your code is {####}", setOut.SmsMfaConfiguration.SmsAuthenticationMessage) @@ -403,7 +404,7 @@ func TestSetGetMfaConfig_SmsMfaConfiguration(t *testing.T) { } `json:"SmsMfaConfiguration"` MfaConfiguration string `json:"MfaConfiguration,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "ON", getOut.MfaConfiguration) require.NotNil(t, getOut.SmsMfaConfiguration) assert.Equal(t, "Your code is {####}", getOut.SmsMfaConfiguration.SmsAuthenticationMessage) @@ -430,7 +431,7 @@ func TestSetGetMfaConfig_SoftwareTokenMfa(t *testing.T) { } `json:"SoftwareTokenMfaConfiguration"` MfaConfiguration string `json:"MfaConfiguration,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) assert.Equal(t, "OPTIONAL", setOut.MfaConfiguration) require.NotNil(t, setOut.SoftwareTokenMfaConfiguration) assert.True(t, setOut.SoftwareTokenMfaConfiguration.Enabled) @@ -446,7 +447,7 @@ func TestSetGetMfaConfig_SoftwareTokenMfa(t *testing.T) { Enabled bool `json:"Enabled,omitempty"` } `json:"SoftwareTokenMfaConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) require.NotNil(t, getOut.SoftwareTokenMfaConfiguration) assert.True(t, getOut.SoftwareTokenMfaConfiguration.Enabled) } @@ -473,7 +474,7 @@ func TestSetGetMfaConfig_EmailMfa(t *testing.T) { Subject string `json:"Subject,omitempty"` } `json:"EmailMfaConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) require.NotNil(t, setOut.EmailMfaConfiguration) assert.Equal(t, "Your login code is {####}", setOut.EmailMfaConfiguration.Message) assert.Equal(t, "Login verification", setOut.EmailMfaConfiguration.Subject) @@ -701,7 +702,7 @@ func TestAdminGetUserMFAFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Fields should be present (even if empty/nil for non-MFA user). // The response JSON should decode without error and have the base fields. diff --git a/services/cognitoidp/multi_region_test.go b/services/cognitoidp/multi_region_test.go index 4188d176b6..fa12ceb066 100644 --- a/services/cognitoidp/multi_region_test.go +++ b/services/cognitoidp/multi_region_test.go @@ -2,7 +2,7 @@ package cognitoidp_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -54,7 +55,7 @@ func idpCall(t *testing.T, h *cognitoidp.Handler, region, op, body string) map[s out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out diff --git a/services/cognitoidp/oauth_federation_backend.go b/services/cognitoidp/oauth_federation_backend.go index b0060234ba..6aeb0115f1 100644 --- a/services/cognitoidp/oauth_federation_backend.go +++ b/services/cognitoidp/oauth_federation_backend.go @@ -3,7 +3,7 @@ package cognitoidp import ( "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -308,7 +309,7 @@ func addIdentity(existing string, idp *IdentityProvider, subject, issuer string) func parseIdentities(raw string) []identityRecord { records := make([]identityRecord, 0, 1) if raw != "" { - _ = json.Unmarshal([]byte(raw), &records) + _ = json.Unmarshal([]byte(raw), &records, jsonx.V1()) } return records @@ -328,7 +329,7 @@ func appendIdentity(existing string, rec identityRecord) string { rec.Primary = strconv.FormatBool(len(records) == 0) } - out, err := json.Marshal(append(records, rec)) + out, err := json.Marshal(append(records, rec), jsonx.V1()) if err != nil { return existing } @@ -345,7 +346,7 @@ func removeIdentity(existing, providerName, userID string) string { return "" } - out, err := json.Marshal(records) + out, err := json.Marshal(records, jsonx.V1()) if err != nil { return existing } diff --git a/services/cognitoidp/oauth_federation_helpers_test.go b/services/cognitoidp/oauth_federation_helpers_test.go index 6a0912758f..697ee6539b 100644 --- a/services/cognitoidp/oauth_federation_helpers_test.go +++ b/services/cognitoidp/oauth_federation_helpers_test.go @@ -4,7 +4,8 @@ import ( "crypto/rand" "crypto/rsa" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "math/big" "net/http" @@ -18,6 +19,7 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -62,7 +64,7 @@ func newFakeIDP(t *testing.T) *fakeIDP { func (f *fakeIDP) serve(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/.well-known/openid-configuration": - _ = json.NewEncoder(w).Encode(map[string]string{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{ "issuer": f.srv.URL, "authorization_endpoint": f.srv.URL + "/authorize", "token_endpoint": f.srv.URL + "/token", "jwks_uri": f.srv.URL + "/jwks", }) @@ -72,7 +74,7 @@ func (f *fakeIDP) serve(w http.ResponseWriter, r *http.Request) { f.token(w, r) case "/jwks": pub := f.key.PublicKey - _ = json.NewEncoder(w).Encode(map[string]any{"keys": []map[string]string{{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{"keys": []map[string]string{{ "kty": "RSA", "kid": fedKID, "alg": "RS256", "use": "sig", "n": base64.RawURLEncoding.EncodeToString(pub.N.Bytes()), "e": base64.RawURLEncoding.EncodeToString(big.NewInt(int64(pub.E)).Bytes()), @@ -150,7 +152,7 @@ func (f *fakeIDP) token(w http.ResponseWriter, r *http.Request) { return } - _ = json.NewEncoder(w).Encode(map[string]string{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]string{ "id_token": signed, "access_token": "idp-access", "token_type": "Bearer", }) } diff --git a/services/cognitoidp/oauth_federation_idp.go b/services/cognitoidp/oauth_federation_idp.go index 26d0e580a3..add496e292 100644 --- a/services/cognitoidp/oauth_federation_idp.go +++ b/services/cognitoidp/oauth_federation_idp.go @@ -5,7 +5,8 @@ import ( "crypto/rsa" "crypto/subtle" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -19,6 +20,7 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -201,7 +203,11 @@ func idpFetchJSON( return idpErrorf("%s returned status %d", req.URL.Host, resp.StatusCode) } - if err = json.NewDecoder(io.LimitReader(resp.Body, maxIDPDocBytes)).Decode(out); err != nil { + if err = json.UnmarshalDecode( + jsontext.NewDecoder(io.LimitReader(resp.Body, maxIDPDocBytes)), + out, + jsonx.V1(), + ); err != nil { return idpErrorf("invalid JSON from %s: %v", req.URL.Host, err) } diff --git a/services/cognitoidp/oauth_federation_test.go b/services/cognitoidp/oauth_federation_test.go index c6f9ac278b..b016bbe2ac 100644 --- a/services/cognitoidp/oauth_federation_test.go +++ b/services/cognitoidp/oauth_federation_test.go @@ -3,7 +3,7 @@ package cognitoidp_test import ( "crypto/rand" "crypto/rsa" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -77,7 +78,7 @@ func TestFederatedOIDCCodeFlow(t *testing.T) { assert.Equal(t, "true", user.Attributes["email_verified"]) var stored []map[string]string - require.NoError(t, json.Unmarshal([]byte(user.Attributes["identities"]), &stored)) + require.NoError(t, json.Unmarshal([]byte(user.Attributes["identities"]), &stored, jsonx.V1())) assert.Equal(t, fedSubject, stored[0]["userId"]) }) } diff --git a/services/cognitoidp/oauth_helpers_test.go b/services/cognitoidp/oauth_helpers_test.go index 759a5861e3..4189694c51 100644 --- a/services/cognitoidp/oauth_helpers_test.go +++ b/services/cognitoidp/oauth_helpers_test.go @@ -4,7 +4,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "math/big" "net/http" @@ -18,6 +18,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -259,7 +260,7 @@ func jsonMap(t *testing.T, body []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m), string(body)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1()), string(body)) return m } @@ -277,7 +278,7 @@ func (e *oauthEnv) verifyAgainstJWKS(t *testing.T, tok string) jwt.MapClaims { E string `json:"e"` } `json:"keys"` } - require.NoError(t, json.Unmarshal(body, &set)) + require.NoError(t, json.Unmarshal(body, &set, jsonx.V1())) require.NotEmpty(t, set.Keys) parsed, err := jwt.Parse(tok, func(tk *jwt.Token) (any, error) { diff --git a/services/cognitoidp/oauth_token.go b/services/cognitoidp/oauth_token.go index ee9aed4249..a03abeda56 100644 --- a/services/cognitoidp/oauth_token.go +++ b/services/cognitoidp/oauth_token.go @@ -4,7 +4,7 @@ import ( "crypto/sha256" "crypto/subtle" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -12,6 +12,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -339,7 +341,7 @@ func clientMetadataParam(form url.Values) (map[string]string, *oauthError) { } var metadata map[string]string - if err := json.Unmarshal([]byte(raw), &metadata); err != nil { + if err := json.Unmarshal([]byte(raw), &metadata, jsonx.V1()); err != nil { return nil, newOAuthError(errInvalidRequest, "aws_client_metadata must be a JSON object of strings") } diff --git a/services/cognitoidp/persistence.go b/services/cognitoidp/persistence.go index 8ed0530171..3d48336470 100644 --- a/services/cognitoidp/persistence.go +++ b/services/cognitoidp/persistence.go @@ -4,13 +4,15 @@ import ( "context" "crypto/rsa" "crypto/x509" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "errors" "fmt" "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -133,7 +135,7 @@ type backendSnapshot struct { TokenRevokedBeforeSeq map[string]int64 `json:"tokenRevokedBeforeSeq,omitempty"` TokenRevokedBefore map[string]time.Time `json:"tokenRevokedBefore,omitempty"` RevokedChains map[string]time.Time `json:"revokedChains,omitempty"` - Tables map[string]json.RawMessage `json:"tables,omitempty"` + Tables map[string]jsontext.Value `json:"tables,omitempty"` ResourceTags map[string]map[string]string `json:"resourceTags,omitempty"` RiskConfigurations map[string]*RiskConfiguration `json:"riskConfigurations,omitempty"` LogDeliveryConfigs map[string]*LogDeliveryConfig `json:"logDeliveryConfigs,omitempty"` @@ -345,7 +347,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Endpoint: b.endpoint, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "cognitoidp: failed to marshal backend snapshot", "error", err) @@ -425,7 +427,7 @@ func (b *InMemoryBackend) resetForIncompatibleSnapshotLocked() { // every secondary index registered on it, e.g. clientsByPool/groupsByPool, so // no separate index rebuild step is needed for these). Caller must hold b.mu // in write mode. -func (b *InMemoryBackend) restoreTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreTablesLocked(tables map[string]jsontext.Value) error { dtoReg := store.NewRegistry() poolDTOs := store.Register(dtoReg, "pools", store.New(poolSnapshotKeyFn)) @@ -468,7 +470,7 @@ func (b *InMemoryBackend) restoreTablesLocked(tables map[string]json.RawMessage) // a shape from some other future change) is likewise dropped rather than // failing the whole Restore, unlike dtoReg.RestoreAll's other tables. Caller // must hold b.mu in write mode. -func (b *InMemoryBackend) restoreTermsLocked(ctx context.Context, raw json.RawMessage) { +func (b *InMemoryBackend) restoreTermsLocked(ctx context.Context, raw jsontext.Value) { if len(raw) == 0 { b.terms.Restore(nil) @@ -477,7 +479,7 @@ func (b *InMemoryBackend) restoreTermsLocked(ctx context.Context, raw json.RawMe var items []*Terms - if err := json.Unmarshal(raw, &items); err != nil { + if err := json.Unmarshal(raw, &items, jsonx.V1()); err != nil { logger.Load(ctx).WarnContext(ctx, "cognitoidp: dropping unparseable terms snapshot", "error", err) b.terms.Restore(nil) diff --git a/services/cognitoidp/persistence_internal_test.go b/services/cognitoidp/persistence_internal_test.go index 3b1410442f..f0ac8b87d1 100644 --- a/services/cognitoidp/persistence_internal_test.go +++ b/services/cognitoidp/persistence_internal_test.go @@ -1,12 +1,15 @@ package cognitoidp import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestSnapshotRoundTrip_NonUTCZone guards against the bare-'Z' layout bug: Format's @@ -128,19 +131,19 @@ func TestGlobalSignOut_RestoreFromV2Snapshot(t *testing.T) { data := b.Snapshot(t.Context()) require.NotEmpty(t, data) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(data, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(data, &raw, jsonx.V1())) delete(raw, "tokenSeq") delete(raw, "tokenRevokedBeforeSeq") key := pool.ID + ":" + user.Username - revoked, err := json.Marshal(map[string]time.Time{key: baseTime}) + revoked, err := json.Marshal(map[string]time.Time{key: baseTime}, jsonx.V1()) require.NoError(t, err) raw["tokenRevokedBefore"] = revoked - raw["version"] = json.RawMessage(`2`) + raw["version"] = jsontext.Value(`2`) - patched, err := json.Marshal(raw) + patched, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) b2 := NewInMemoryBackend("000000000000", "us-east-1", "http://localhost:8000") diff --git a/services/cognitoidp/persistence_test.go b/services/cognitoidp/persistence_test.go index 126dfcbab2..4e74060591 100644 --- a/services/cognitoidp/persistence_test.go +++ b/services/cognitoidp/persistence_test.go @@ -2,13 +2,14 @@ package cognitoidp_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -391,7 +392,7 @@ func TestPersistenceRoundTrip(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "persist-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -399,7 +400,7 @@ func TestPersistenceRoundTrip(t *testing.T) { "ClientName": "persist-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) doCognitoRequest(t, h, "AdminCreateUser", map[string]any{ "UserPoolId": poolID, @@ -427,7 +428,7 @@ func TestPersistenceRoundTrip(t *testing.T) { "Username": "persist-user", }) var getUserResp map[string]any - require.NoError(t, json.Unmarshal(getUserRec.Body.Bytes(), &getUserResp)) + require.NoError(t, json.Unmarshal(getUserRec.Body.Bytes(), &getUserResp, jsonx.V1())) assert.False(t, getUserResp["Enabled"].(bool)) } @@ -542,7 +543,7 @@ func TestInMemoryBackend_RestoreDropsPreRedesignTerms(t *testing.T) { require.NotEmpty(t, data) var raw map[string]any - require.NoError(t, json.Unmarshal(data, &raw)) + require.NoError(t, json.Unmarshal(data, &raw, jsonx.V1())) tables, ok := raw["tables"].(map[string]any) require.True(t, ok) @@ -557,7 +558,7 @@ func TestInMemoryBackend_RestoreDropsPreRedesignTerms(t *testing.T) { {"userPoolID": pool.ID, "text": "accept these terms"}, } - spliced, err := json.Marshal(raw) + spliced, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) restored := newTestBackend() diff --git a/services/cognitoidp/realclient_managed_login_and_provisioning_test.go b/services/cognitoidp/realclient_managed_login_and_provisioning_test.go index 9a141afaa0..9878dada6c 100644 --- a/services/cognitoidp/realclient_managed_login_and_provisioning_test.go +++ b/services/cognitoidp/realclient_managed_login_and_provisioning_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -54,7 +55,7 @@ func decodeIdpDocument(t *testing.T, doc interface{ UnmarshalSmithyDocument(v an var v any require.NoError(t, doc.UnmarshalSmithyDocument(&v)) - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/cognitoidp/regions.go b/services/cognitoidp/regions.go index b7002fc752..4022a6fcd0 100644 --- a/services/cognitoidp/regions.go +++ b/services/cognitoidp/regions.go @@ -3,7 +3,7 @@ package cognitoidp import ( "context" "crypto/rsa" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" ) @@ -265,7 +266,7 @@ func targetHints(r *http.Request) ownerHints { Session string `json:"Session"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return ownerHints{ poolID: req.UserPoolID, arn: req.ResourceArn, clientID: req.ClientID, diff --git a/services/cognitoidp/resource_servers_test.go b/services/cognitoidp/resource_servers_test.go index 2962326c0d..8be9eb75ff 100644 --- a/services/cognitoidp/resource_servers_test.go +++ b/services/cognitoidp/resource_servers_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -66,7 +67,7 @@ func TestHandler_ResourceServers_Accurate(t *testing.T) { } `json:"Scopes"` } `json:"ResourceServer"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "My API", resp.ResourceServer.Name) assert.Len(t, resp.ResourceServer.Scopes, 1) assert.Equal(t, "read", resp.ResourceServer.Scopes[0].ScopeName) @@ -98,7 +99,7 @@ func TestResourceServer_CRUD(t *testing.T) { Identifier string `json:"Identifier"` } `json:"ResourceServers"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.ResourceServers, 1) assert.Equal(t, "https://api.example.com", listResp.ResourceServers[0].Identifier) } @@ -279,7 +280,7 @@ func TestHandler_ListResourceServers(t *testing.T) { var resp struct { ResourceServers []map[string]any `json:"ResourceServers,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceServers, tt.count) }) } @@ -399,7 +400,7 @@ func TestListResourceServers_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body) var page1 listOut - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.ResourceServers, 2) require.NotEmpty(t, page1.NextToken, "first page must return a cursor when more resource servers remain") @@ -411,7 +412,7 @@ func TestListResourceServers_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body) var page2 listOut - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.ResourceServers, 1) require.Empty(t, page2.NextToken) diff --git a/services/cognitoidp/saml_federation_test.go b/services/cognitoidp/saml_federation_test.go index 2d939a6e88..9b74116cda 100644 --- a/services/cognitoidp/saml_federation_test.go +++ b/services/cognitoidp/saml_federation_test.go @@ -10,7 +10,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "maps" "math/big" @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -481,7 +482,7 @@ func TestSAMLFederation(t *testing.T) { require.Equal(t, http.StatusOK, form.StatusCode, string(body)) var tok map[string]any - require.NoError(t, json.Unmarshal(body, &tok)) + require.NoError(t, json.Unmarshal(body, &tok, jsonx.V1())) claims := env.verifyAgainstJWKS(t, tok["id_token"].(string)) assert.Equal(t, fedProvider+"_"+samlNameID, claims["cognito:username"]) @@ -527,7 +528,7 @@ func TestSAMLMultiValuedAttributes(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode, string(body)) var tok map[string]any - require.NoError(t, json.Unmarshal(body, &tok)) + require.NoError(t, json.Unmarshal(body, &tok, jsonx.V1())) claims := env.verifyAgainstJWKS(t, tok["id_token"].(string)) assert.Equal(t, tt.want, claims["email"]) diff --git a/services/cognitoidp/saml_slo_test.go b/services/cognitoidp/saml_slo_test.go index 77adbc26dc..99e5094015 100644 --- a/services/cognitoidp/saml_slo_test.go +++ b/services/cognitoidp/saml_slo_test.go @@ -8,7 +8,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "regexp" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -53,7 +54,7 @@ func (e *samlEnv) loginSAML(t *testing.T) string { require.Equal(t, http.StatusOK, resp.StatusCode, string(body)) var tok map[string]any - require.NoError(t, json.Unmarshal(body, &tok)) + require.NoError(t, json.Unmarshal(body, &tok, jsonx.V1())) return tok["access_token"].(string) } diff --git a/services/cognitoidp/security_config_test.go b/services/cognitoidp/security_config_test.go index 74bf1951ce..8a7d338a2c 100644 --- a/services/cognitoidp/security_config_test.go +++ b/services/cognitoidp/security_config_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -60,7 +61,7 @@ func TestSetRiskConfiguration_PersistsRiskExceptionConfiguration(t *testing.T) { } `json:"RiskExceptionConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) require.NotNil(t, setOut.RiskConfiguration) require.NotNil( t, @@ -100,7 +101,7 @@ func TestSetRiskConfiguration_PersistsRiskExceptionConfiguration(t *testing.T) { } `json:"RiskExceptionConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.RiskConfiguration) require.NotNil( t, @@ -138,7 +139,7 @@ func TestRiskConfiguration_CompromisedCredentials(t *testing.T) { } `json:"CompromisedCredentialsRiskConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &setOut, jsonx.V1())) require.NotNil(t, setOut.RiskConfiguration) require.NotNil(t, setOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration) assert.Contains(t, setOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration.EventFilter, "SIGN_IN") @@ -160,7 +161,7 @@ func TestRiskConfiguration_CompromisedCredentials(t *testing.T) { } `json:"CompromisedCredentialsRiskConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.RiskConfiguration) require.NotNil(t, descOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration) assert.Equal(t, "BLOCK", descOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration.Actions.EventAction) @@ -226,7 +227,7 @@ func TestRiskConfiguration_AccountTakeover(t *testing.T) { } `json:"AccountTakeoverRiskConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.RiskConfiguration) require.NotNil(t, out.RiskConfiguration.AccountTakeoverRiskConfiguration) require.NotNil(t, out.RiskConfiguration.AccountTakeoverRiskConfiguration.Actions) @@ -274,7 +275,7 @@ func TestRiskConfiguration_PerClient(t *testing.T) { CompromisedCredentialsRiskConfiguration *struct{} `json:"CompromisedCredentialsRiskConfiguration,omitempty"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &poolOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &poolOut, jsonx.V1())) assert.Nil(t, poolOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration) // Client-level should be set. @@ -293,7 +294,7 @@ func TestRiskConfiguration_PerClient(t *testing.T) { } `json:"CompromisedCredentialsRiskConfiguration"` } `json:"RiskConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &clientOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &clientOut, jsonx.V1())) require.NotNil(t, clientOut.RiskConfiguration.CompromisedCredentialsRiskConfiguration) assert.Equal( t, @@ -414,7 +415,7 @@ func TestSetLogDeliveryConfiguration_LogConfigurationsPersistAndEcho(t *testing. LogConfigurations []map[string]any `json:"LogConfigurations,omitempty"` } `json:"LogDeliveryConfiguration"` } - require.NoError(t, json.Unmarshal(setRec.Body.Bytes(), &setOut)) + require.NoError(t, json.Unmarshal(setRec.Body.Bytes(), &setOut, jsonx.V1())) require.Len(t, setOut.LogDeliveryConfiguration.LogConfigurations, 1, "LogConfigurations is a required accepted field and must not be silently dropped", ) @@ -428,7 +429,7 @@ func TestSetLogDeliveryConfiguration_LogConfigurationsPersistAndEcho(t *testing. LogConfigurations []map[string]any `json:"LogConfigurations,omitempty"` } `json:"LogDeliveryConfiguration"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) require.Len(t, getOut.LogDeliveryConfiguration.LogConfigurations, 1, "Set must actually persist for Get to read back", ) diff --git a/services/cognitoidp/tags_test.go b/services/cognitoidp/tags_test.go index 4508ddee48..0edf0654ec 100644 --- a/services/cognitoidp/tags_test.go +++ b/services/cognitoidp/tags_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags(t *testing.T) { @@ -31,7 +33,7 @@ func TestTags(t *testing.T) { var listResp struct { Tags map[string]string `json:"Tags,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Equal(t, "prod", listResp.Tags["env"]) assert.Equal(t, "platform", listResp.Tags["team"]) @@ -49,7 +51,7 @@ func TestTags(t *testing.T) { var afterUntagResp struct { Tags map[string]string `json:"Tags,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterUntagResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterUntagResp, jsonx.V1())) assert.NotContains(t, afterUntagResp.Tags, "env") assert.Equal(t, "platform", afterUntagResp.Tags["team"]) } diff --git a/services/cognitoidp/temp_password_sdk_test.go b/services/cognitoidp/temp_password_sdk_test.go index d46ef744bf..e766608687 100644 --- a/services/cognitoidp/temp_password_sdk_test.go +++ b/services/cognitoidp/temp_password_sdk_test.go @@ -1,7 +1,8 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -9,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const tempPwd = "Tmp-Secret-9876!x" @@ -108,7 +111,7 @@ func TestTemporaryPassword_NotReturnedByUserOps(t *testing.T) { require.NoError(t, err) attrs := tt.op(t, c, poolID) - raw, err := json.Marshal(attrs) + raw, err := json.Marshal(attrs, jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(raw), tempPwd) assert.NotContains(t, attrNames(attrs), "custom:temporaryPassword") @@ -196,25 +199,25 @@ func TestTemporaryPassword_LegacySnapshotMigrates(t *testing.T) { }) require.NoError(t, err) - var snap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &snap)) + var snap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &snap, jsonx.V1())) - var tables map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap["tables"], &tables)) + var tables map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap["tables"], &tables, jsonx.V1())) var users []map[string]any - require.NoError(t, json.Unmarshal(tables["users"], &users)) + require.NoError(t, json.Unmarshal(tables["users"], &users, jsonx.V1())) require.Len(t, users, 1) delete(users[0], "temporaryPassword") users[0]["attributes"].(map[string]any)["custom:temporaryPassword"] = tempPwd - tables["users"], err = json.Marshal(users) + tables["users"], err = json.Marshal(users, jsonx.V1()) require.NoError(t, err) - snap["tables"], err = json.Marshal(tables) + snap["tables"], err = json.Marshal(tables, jsonx.V1()) require.NoError(t, err) - old, err := json.Marshal(snap) + old, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) fresh := newTestHandler(t) diff --git a/services/cognitoidp/terms_test.go b/services/cognitoidp/terms_test.go index 95edf1255f..aca924818e 100644 --- a/services/cognitoidp/terms_test.go +++ b/services/cognitoidp/terms_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func validTermsBody(poolID, clientID string) map[string]any { @@ -51,7 +53,7 @@ func TestCreateTerms_Validation(t *testing.T) { var errResp struct { Type string `json:"__type,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) }) } @@ -69,7 +71,7 @@ func TestCreateTerms_UnknownClient(t *testing.T) { var errResp struct { Type string `json:"__type,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type) } @@ -88,7 +90,7 @@ func TestCreateTerms_Duplicate(t *testing.T) { var errResp struct { Type string `json:"__type,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "TermsExistsException", errResp.Type) } @@ -109,7 +111,7 @@ func TestTerms_CRUD(t *testing.T) { ClientID string `json:"ClientId,omitempty"` } `json:"Terms"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.Terms) rec = doCognitoRequest(t, h, "CreateTerms", validTermsBody(poolID, clientID)) @@ -128,7 +130,7 @@ func TestTerms_CRUD(t *testing.T) { LastModifiedDate float64 `json:"LastModifiedDate,omitempty"` } `json:"Terms"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) require.NotEmpty(t, createResp.Terms.TermsID) assert.Equal(t, clientID, createResp.Terms.ClientID) assert.Equal(t, poolID, createResp.Terms.UserPoolID) @@ -144,7 +146,7 @@ func TestTerms_CRUD(t *testing.T) { // List returns TermsDescriptionType, which has no ClientId field on the real wire. rec = doCognitoRequest(t, h, "ListTerms", map[string]any{"UserPoolId": poolID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Terms, 1) assert.Equal(t, termsID, listResp.Terms[0].TermsID) assert.Empty(t, listResp.Terms[0].ClientID, "TermsDescriptionType has no ClientId field") @@ -155,7 +157,7 @@ func TestTerms_CRUD(t *testing.T) { "TermsName": "terms-of-use-v2", }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, "terms-of-use-v2", createResp.Terms.TermsName) assert.Equal(t, "NONE", createResp.Terms.Enforcement, "unset fields on update are left unchanged") @@ -163,7 +165,7 @@ func TestTerms_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = doCognitoRequest(t, h, "ListTerms", map[string]any{"UserPoolId": poolID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.Terms) } @@ -205,7 +207,7 @@ func TestTerms_NotFound(t *testing.T) { var errResp struct { Type string `json:"__type,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type) }) } diff --git a/services/cognitoidp/testhelpers_test.go b/services/cognitoidp/testhelpers_test.go index 3365f18849..a1487da2c7 100644 --- a/services/cognitoidp/testhelpers_test.go +++ b/services/cognitoidp/testhelpers_test.go @@ -5,7 +5,7 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -28,7 +29,7 @@ func decodeJWTPayload(t *testing.T, token string) map[string]any { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(payload, &claims)) + require.NoError(t, json.Unmarshal(payload, &claims, jsonx.V1())) return claims } @@ -79,7 +80,7 @@ func setupHandlerPoolAndClient(t *testing.T, h *cognitoidp.Handler, poolName str ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp.UserPool.ID clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -93,7 +94,7 @@ func setupHandlerPoolAndClient(t *testing.T, h *cognitoidp.Handler, poolName str ClientID string `json:"ClientId,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) return poolID, clientResp.UserPoolClient.ClientID } @@ -114,7 +115,7 @@ func signUpAndConfirmViaHandler(t *testing.T, h *cognitoidp.Handler, clientID, u CodeDeliveryDetails map[string]string `json:"CodeDeliveryDetails,omitempty"` UserConfirmed bool `json:"UserConfirmed,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signUpResp, jsonx.V1())) if signUpResp.UserConfirmed { return @@ -147,7 +148,7 @@ func loginViaHandler(t *testing.T, h *cognitoidp.Handler, clientID, username str AccessToken string `json:"AccessToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.AuthenticationResult) return resp.AuthenticationResult.AccessToken @@ -175,7 +176,7 @@ func newTestHandler(t *testing.T) *cognitoidp.Handler { func doCognitoRequest(t *testing.T, h *cognitoidp.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -214,7 +215,7 @@ func setupPoolAndClientNamed(t *testing.T, h *cognitoidp.Handler, poolName, clie require.Equal(t, http.StatusOK, poolRec.Code) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -224,7 +225,7 @@ func setupPoolAndClientNamed(t *testing.T, h *cognitoidp.Handler, poolName, clie require.Equal(t, http.StatusOK, clientRec.Code) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) return poolID, clientID diff --git a/services/cognitoidp/tokens.go b/services/cognitoidp/tokens.go index fb1139d59a..0616fc0669 100644 --- a/services/cognitoidp/tokens.go +++ b/services/cognitoidp/tokens.go @@ -7,7 +7,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "math/big" @@ -19,6 +19,8 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // rsaKeyBits is the size of the RSA key generated for JWT signing. @@ -373,7 +375,7 @@ func (t *tokenIssuer) signIDToken(p TokenParams, now time.Time, idExpiry time.Du if raw := p.Attributes[attrIdentities]; raw != "" { var identities []any - if json.Unmarshal([]byte(raw), &identities) == nil { + if json.Unmarshal([]byte(raw), &identities, jsonx.V1()) == nil { idClaims[attrIdentities] = identities } } @@ -547,5 +549,5 @@ func (t *tokenIssuer) ParseAccessToken(tokenString string) (jwt.MapClaims, error // jwksResponseJSON serializes JWKSResponse as JSON bytes. func jwksResponseJSON(r JWKSResponse) ([]byte, error) { - return json.Marshal(r) + return json.Marshal(r, jsonx.V1()) } diff --git a/services/cognitoidp/user_import_test.go b/services/cognitoidp/user_import_test.go index eb67177334..ff5d778d40 100644 --- a/services/cognitoidp/user_import_test.go +++ b/services/cognitoidp/user_import_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -32,7 +33,7 @@ func TestUserImportJob_CRUD(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp.UserImportJob.JobID require.NotEmpty(t, jobID) assert.Equal(t, "my-import", createResp.UserImportJob.JobName) @@ -55,7 +56,7 @@ func TestUserImportJob_CRUD(t *testing.T) { JobID string `json:"JobId,omitempty"` } `json:"UserImportJobs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.UserImportJobs, 1) // GetCSVHeader @@ -73,7 +74,7 @@ func TestUserImportJob_CRUD(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.Equal(t, "InProgress", startResp.UserImportJob.Status) // Stop @@ -87,7 +88,7 @@ func TestUserImportJob_CRUD(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Equal(t, "Stopped", stopResp.UserImportJob.Status) // Start again on stopped job — error @@ -125,7 +126,7 @@ func TestUserImportJob_SelfCompletesToSucceeded(t *testing.T) { JobID string `json:"JobId,omitempty"` } `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp.UserImportJob.JobID require.NotEmpty(t, jobID) @@ -153,7 +154,7 @@ func TestUserImportJob_SelfCompletesToSucceeded(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) return desc.UserImportJob.Status == "Succeeded" }, 2*time.Second, 10*time.Millisecond, @@ -193,7 +194,7 @@ func TestUserImportJob_EchoesCloudWatchLogsRoleArnAndPasswordHashingAlgorithm(t var createResp struct { UserImportJob userImportJobWire `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, "arn:aws:iam::000000000000:role/CognitoImportRole", createResp.UserImportJob.CloudWatchLogsRoleArn, @@ -213,7 +214,7 @@ func TestUserImportJob_EchoesCloudWatchLogsRoleArnAndPasswordHashingAlgorithm(t var startResp struct { UserImportJob userImportJobWire `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) assert.NotZero(t, startResp.UserImportJob.StartDate) assert.Zero(t, startResp.UserImportJob.CompletionDate) @@ -223,7 +224,7 @@ func TestUserImportJob_EchoesCloudWatchLogsRoleArnAndPasswordHashingAlgorithm(t var stopResp struct { UserImportJob userImportJobWire `json:"UserImportJob"` } - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) assert.NotZero(t, stopResp.UserImportJob.CompletionDate) } @@ -257,7 +258,7 @@ func TestListUserImportJobs_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body) var page1 listOut - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.UserImportJobs, 2) require.NotEmpty(t, page1.PaginationToken, "first page must return a cursor when more import jobs remain") @@ -269,7 +270,7 @@ func TestListUserImportJobs_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body) var page2 listOut - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.UserImportJobs, 1) require.Empty(t, page2.PaginationToken) diff --git a/services/cognitoidp/user_pool_clients_handler_test.go b/services/cognitoidp/user_pool_clients_handler_test.go index 17f5975af8..c62eae2c9c 100644 --- a/services/cognitoidp/user_pool_clients_handler_test.go +++ b/services/cognitoidp/user_pool_clients_handler_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -56,7 +57,7 @@ func TestHandler_UpdateUserPoolClient_WithOpts(t *testing.T) { AllowedOAuthScopes []string `json:"AllowedOAuthScopes,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "renamed-client", resp.UserPoolClient.ClientName) }) } @@ -75,7 +76,7 @@ func TestHandler_CreateUserPoolClient(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -119,7 +120,7 @@ func TestHandler_DescribeUserPoolClient(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -127,7 +128,7 @@ func TestHandler_DescribeUserPoolClient(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) return poolID, clientResp["UserPoolClient"]["ClientId"].(string) }, @@ -138,7 +139,7 @@ func TestHandler_DescribeUserPoolClient(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string), "nonexistent-client" }, @@ -204,7 +205,7 @@ func TestHandler_DeleteUserPoolClient(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -212,7 +213,7 @@ func TestHandler_DeleteUserPoolClient(t *testing.T) { "ClientName": "c", }) var clientResp map[string]map[string]any - _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp) + _ = json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1()) return poolID, clientResp["UserPoolClient"]["ClientId"].(string) }, @@ -223,7 +224,7 @@ func TestHandler_DeleteUserPoolClient(t *testing.T) { setup: func(h *cognitoidp.Handler) (string, string) { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string), "nonexistent-client" }, @@ -275,7 +276,7 @@ func TestHandler_ListUserPoolClients(t *testing.T) { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var poolResp map[string]map[string]any - _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp) + _ = json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1()) poolID := poolResp["UserPool"]["Id"].(string) for i := range tt.numClients { @@ -290,7 +291,7 @@ func TestHandler_ListUserPoolClients(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clients := resp["UserPoolClients"].([]any) assert.Len(t, clients, tt.numClients) }) @@ -337,7 +338,7 @@ func TestHandler_AddUserPoolClientSecret(t *testing.T) { if tt.poolExists { poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "sec-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID = poolResp["UserPool"].(map[string]any)["Id"].(string) } @@ -347,7 +348,7 @@ func TestHandler_AddUserPoolClientSecret(t *testing.T) { "ClientName": "test-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID = clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) } @@ -369,7 +370,7 @@ func TestSortedListUserPoolClients(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "sorted-clients-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) for _, name := range []string{"web-client", "android-client", "ios-client"} { @@ -383,7 +384,7 @@ func TestSortedListUserPoolClients(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) clients := listResp["UserPoolClients"].([]any) require.Len(t, clients, 3) assert.Equal(t, "android-client", clients[0].(map[string]any)["ClientName"]) @@ -397,7 +398,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "secret-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) clientRec := doCognitoRequest(t, h, "CreateUserPoolClient", map[string]any{ @@ -405,7 +406,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { "ClientName": "sec-client", }) var clientResp map[string]any - require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp)) + require.NoError(t, json.Unmarshal(clientRec.Body.Bytes(), &clientResp, jsonx.V1())) clientID := clientResp["UserPoolClient"].(map[string]any)["ClientId"].(string) // No secret yet. @@ -414,7 +415,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { "ClientId": clientID, }) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Empty(t, descResp["UserPoolClient"].(map[string]any)["ClientSecret"]) // AddUserPoolClientSecret creates an independently ClientSecretId-keyed @@ -427,7 +428,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { "ClientId": clientID, }) var addResp map[string]any - require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp)) + require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addResp, jsonx.V1())) descriptor, ok := addResp["ClientSecretDescriptor"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, descriptor["ClientSecretId"]) @@ -438,7 +439,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { "ClientId": clientID, }) var descResp2 map[string]any - require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2)) + require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descResp2, jsonx.V1())) assert.Empty(t, descResp2["UserPoolClient"].(map[string]any)["ClientSecret"]) listRec := doCognitoRequest(t, h, "ListUserPoolClientSecrets", map[string]any{ @@ -446,7 +447,7 @@ func TestDescribeUserPoolClient_IncludesClientSecret(t *testing.T) { "ClientId": clientID, }) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) secrets, ok := listResp["ClientSecrets"].([]any) require.True(t, ok) require.Len(t, secrets, 1) @@ -460,14 +461,14 @@ func TestListUserPoolClients_NonNilWhenEmpty(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "empty-clients-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) rec := doCognitoRequest(t, h, "ListUserPoolClients", map[string]any{"UserPoolId": poolID}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) clients := listResp["UserPoolClients"].([]any) assert.Empty(t, clients) } @@ -486,7 +487,7 @@ func TestClientLastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) client := descResp["UserPoolClient"].(map[string]any) creationDate := client["CreationDate"].(float64) lastModBefore := client["LastModifiedDate"].(float64) @@ -501,7 +502,7 @@ func TestClientLastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, upRec.Code) var upResp map[string]any - require.NoError(t, json.Unmarshal(upRec.Body.Bytes(), &upResp)) + require.NoError(t, json.Unmarshal(upRec.Body.Bytes(), &upResp, jsonx.V1())) updatedClient := upResp["UserPoolClient"].(map[string]any) lastModAfter := updatedClient["LastModifiedDate"].(float64) assert.GreaterOrEqual(t, lastModAfter, creationDate, "LastModifiedDate must be >= CreationDate after update") @@ -526,7 +527,7 @@ func TestClientOAuthRedirectFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) client := resp["UserPoolClient"].(map[string]any) callbackURLs := client["CallbackURLs"].([]any) diff --git a/services/cognitoidp/user_pool_clients_test.go b/services/cognitoidp/user_pool_clients_test.go index ccf9ee1e21..ddd0f02824 100644 --- a/services/cognitoidp/user_pool_clients_test.go +++ b/services/cognitoidp/user_pool_clients_test.go @@ -1,13 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -55,7 +56,7 @@ func TestHandler_CreateUserPoolClient_WithOAuthFields(t *testing.T) { ExplicitAuthFlows []string `json:"ExplicitAuthFlows,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, []string{"code"}, resp.UserPoolClient.AllowedOAuthFlows) assert.ElementsMatch(t, []string{"email", "openid"}, resp.UserPoolClient.AllowedOAuthScopes) assert.Equal(t, []string{"ALLOW_USER_PASSWORD_AUTH"}, resp.UserPoolClient.ExplicitAuthFlows) @@ -81,7 +82,7 @@ func TestHandler_DescribeUserPoolClient_IncludesOAuthFields(t *testing.T) { ClientID string `json:"ClientId,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doCognitoRequest(t, h, "DescribeUserPoolClient", map[string]any{ "UserPoolId": poolID, @@ -96,7 +97,7 @@ func TestHandler_DescribeUserPoolClient_IncludesOAuthFields(t *testing.T) { ExplicitAuthFlows []string `json:"ExplicitAuthFlows,omitempty"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, []string{"code"}, resp.UserPoolClient.AllowedOAuthFlows) assert.Equal(t, []string{"openid"}, resp.UserPoolClient.AllowedOAuthScopes) assert.Equal(t, []string{"ALLOW_USER_PASSWORD_AUTH"}, resp.UserPoolClient.ExplicitAuthFlows) @@ -121,7 +122,7 @@ func TestAppClient_CRUD(t *testing.T) { ClientName string `json:"ClientName"` } `json:"UserPoolClient"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, "my-app-client", createResp.UserPoolClient.ClientName) clientID := createResp.UserPoolClient.ClientID assert.NotEmpty(t, clientID) @@ -135,7 +136,7 @@ func TestAppClient_CRUD(t *testing.T) { ClientID string `json:"ClientId"` } `json:"UserPoolClients"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) var found bool for _, c := range listResp.UserPoolClients { if c.ClientID == clientID { @@ -418,7 +419,7 @@ func TestClientSecrets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp clientSecretsListResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.ClientSecrets) // Add a secret; its ClientSecretId is required to delete it later @@ -436,7 +437,7 @@ func TestClientSecrets(t *testing.T) { ClientSecretValue string `json:"ClientSecretValue"` } `json:"ClientSecretDescriptor"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &addResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &addResp, jsonx.V1())) secretID := addResp.ClientSecretDescriptor.ClientSecretID require.NotEmpty(t, secretID) require.NotEmpty(t, addResp.ClientSecretDescriptor.ClientSecretValue) @@ -446,7 +447,7 @@ func TestClientSecrets(t *testing.T) { "UserPoolId": poolID, "ClientId": clientID, }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.ClientSecrets, 1) assert.Equal(t, secretID, listResp.ClientSecrets[0].ClientSecretID) assert.Empty(t, listResp.ClientSecrets[0].ClientSecretValue) @@ -472,7 +473,7 @@ func TestClientSecrets(t *testing.T) { "UserPoolId": poolID, "ClientId": clientID, }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.ClientSecrets) } @@ -592,7 +593,7 @@ func TestListUserPoolClients_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body) var page1 listOut - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.UserPoolClients, 2) require.NotEmpty(t, page1.NextToken, "first page must return a cursor when more clients remain") @@ -604,7 +605,7 @@ func TestListUserPoolClients_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body) var page2 listOut - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.UserPoolClients, 2) require.Empty(t, page2.NextToken) diff --git a/services/cognitoidp/user_pools_config_test.go b/services/cognitoidp/user_pools_config_test.go index 33940ea1d8..24caabc970 100644 --- a/services/cognitoidp/user_pools_config_test.go +++ b/services/cognitoidp/user_pools_config_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -172,7 +173,7 @@ func TestHandler_ListUserPools(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pools, ok := resp["UserPools"].([]any) require.True(t, ok) @@ -194,7 +195,7 @@ func TestHandler_DescribeUserPool(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "p"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -266,7 +267,7 @@ func TestHandler_DeleteUserPool(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "del-pool"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -307,7 +308,7 @@ func TestHandler_GetUserPoolMfaConfig(t *testing.T) { setup: func(h *cognitoidp.Handler) string { rec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "mfa-pool"}) var resp map[string]map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["UserPool"]["Id"].(string) }, @@ -351,7 +352,7 @@ func TestSortedListUserPools(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pools := resp["UserPools"].([]any) require.Len(t, pools, 3) @@ -366,7 +367,7 @@ func TestDescribeUserPool_IncludesSchemaAttributes(t *testing.T) { h := newTestHandler(t) poolRec := doCognitoRequest(t, h, "CreateUserPool", map[string]any{"PoolName": "schema-pool"}) var poolResp map[string]any - require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp)) + require.NoError(t, json.Unmarshal(poolRec.Body.Bytes(), &poolResp, jsonx.V1())) poolID := poolResp["UserPool"].(map[string]any)["Id"].(string) doCognitoRequest(t, h, "AddCustomAttributes", map[string]any{ @@ -380,7 +381,7 @@ func TestDescribeUserPool_IncludesSchemaAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schema := resp["UserPool"].(map[string]any)["SchemaAttributes"] assert.NotNil(t, schema) schemaList := schema.([]any) @@ -396,7 +397,7 @@ func TestListUserPools_NonNilWhenEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) pools, ok := listResp["UserPools"].([]any) assert.True(t, ok, "UserPools should be an array, not nil") assert.Empty(t, pools) @@ -436,7 +437,7 @@ func TestPasswordPolicyDefaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pool := resp["UserPool"].(map[string]any) policies := pool["Policies"].(map[string]any) @@ -457,7 +458,7 @@ func TestUserPoolLastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pool := createResp["UserPool"].(map[string]any) poolID := pool["Id"].(string) createDate := pool["CreationDate"].(float64) @@ -478,7 +479,7 @@ func TestUserPoolLastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) lastModAfter := descResp["UserPool"].(map[string]any)["LastModifiedDate"].(float64) assert.GreaterOrEqual(t, lastModAfter, createDate, "LastModifiedDate must be >= CreationDate after update") } @@ -493,7 +494,7 @@ func TestUpdateUserPoolLambdaConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) poolID := createResp["UserPool"].(map[string]any)["Id"].(string) lambdaConfig := map[string]any{ @@ -510,7 +511,7 @@ func TestUpdateUserPoolLambdaConfig(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) returnedPool := descResp["UserPool"].(map[string]any) returnedLambda := returnedPool["LambdaConfig"].(map[string]any) assert.Equal(t, "arn:aws:lambda:us-east-1:000000000000:function:pre-signup", returnedLambda["PreSignUp"]) @@ -545,7 +546,7 @@ func TestListUserPools_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.UserPools), 2, "page must not exceed MaxResults") for _, p := range resp.UserPools { diff --git a/services/cognitoidp/user_pools_test.go b/services/cognitoidp/user_pools_test.go index b7a41fd261..7c00f5ce25 100644 --- a/services/cognitoidp/user_pools_test.go +++ b/services/cognitoidp/user_pools_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -179,7 +180,7 @@ func TestHandler_CreateUserPool_WithPasswordPolicy(t *testing.T) { AutoVerifiedAttributes []string `json:"AutoVerifiedAttributes,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.UserPool.Policies) require.NotNil(t, resp.UserPool.Policies.PasswordPolicy) assert.Equal(t, 10, resp.UserPool.Policies.PasswordPolicy.MinimumLength) @@ -205,7 +206,7 @@ func TestHandler_DescribeUserPool_IncludesPolicy(t *testing.T) { ID string `json:"Id,omitempty"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doCognitoRequest(t, h, "DescribeUserPool", map[string]any{"UserPoolId": createResp.UserPool.ID}) require.Equal(t, http.StatusOK, rec.Code) @@ -219,7 +220,7 @@ func TestHandler_DescribeUserPool_IncludesPolicy(t *testing.T) { } `json:"Policies"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.UserPool.Policies) require.NotNil(t, resp.UserPool.Policies.PasswordPolicy) assert.Equal(t, 12, resp.UserPool.Policies.PasswordPolicy.MinimumLength) @@ -251,7 +252,7 @@ func TestUserPool_CRUD(t *testing.T) { Name string `json:"Name"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) poolID := createResp.UserPool.ID assert.Equal(t, tt.poolName, createResp.UserPool.Name) assert.NotEmpty(t, poolID) @@ -265,7 +266,7 @@ func TestUserPool_CRUD(t *testing.T) { ID string `json:"Id"` } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, poolID, descResp.UserPool.ID) // Delete. @@ -588,7 +589,7 @@ func TestHandler_CreateUserPool_MfaConfiguration(t *testing.T) { Id string `json:"Id"` //nolint:revive,staticcheck // matches wire field name. } `json:"UserPool"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec = doCognitoRequest(t, h, "GetUserPoolMfaConfig", map[string]any{ "UserPoolId": createResp.UserPool.Id, @@ -598,7 +599,7 @@ func TestHandler_CreateUserPool_MfaConfiguration(t *testing.T) { var mfaResp struct { MfaConfiguration string `json:"MfaConfiguration,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mfaResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mfaResp, jsonx.V1())) assert.Equal(t, "ON", mfaResp.MfaConfiguration) } @@ -616,7 +617,7 @@ func TestGetUserPoolMfaConfig_DefaultsToOFF(t *testing.T) { var out struct { MfaConfiguration string `json:"MfaConfiguration,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "OFF", out.MfaConfiguration) } @@ -844,7 +845,7 @@ func TestHandler_UserPoolReplicas(t *testing.T) { UserPoolArn string `json:"UserPoolArn,omitempty"` } `json:"UserPoolReplica"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, tt.regionName, createResp.UserPoolReplica.RegionName) assert.Equal(t, "SECONDARY", createResp.UserPoolReplica.Role) assert.Equal(t, "INACTIVE", createResp.UserPoolReplica.Status) @@ -860,7 +861,7 @@ func TestHandler_UserPoolReplicas(t *testing.T) { RegionName string `json:"RegionName,omitempty"` } `json:"UserPoolReplicas,omitempty"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.UserPoolReplicas, 1) assert.Equal(t, tt.regionName, listResp.UserPoolReplicas[0].RegionName) @@ -876,7 +877,7 @@ func TestHandler_UserPoolReplicas(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserPoolReplica"` } - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "ACTIVE", updateResp.UserPoolReplica.Status) deleteRec := doCognitoRequest(t, h, "DeleteUserPoolReplica", map[string]any{ @@ -890,7 +891,7 @@ func TestHandler_UserPoolReplicas(t *testing.T) { Status string `json:"Status,omitempty"` } `json:"UserPoolReplica"` } - require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp, jsonx.V1())) assert.Equal(t, "DELETING", deleteResp.UserPoolReplica.Status) }) } diff --git a/services/cognitoidp/users_test.go b/services/cognitoidp/users_test.go index 860bb98eb9..521fb193d1 100644 --- a/services/cognitoidp/users_test.go +++ b/services/cognitoidp/users_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cognitoidp" ) @@ -866,7 +867,7 @@ func TestDeleteUser_ClearsGroupAndWebAuthnStateOnRecreate(t *testing.T) { func unmarshalBody(t *testing.T, rec *httptest.ResponseRecorder, v any) error { t.Helper() - return json.Unmarshal(rec.Body.Bytes(), v) + return json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1()) } func TestAdminSetUserPassword_PolicyEnforced(t *testing.T) { diff --git a/services/cognitoidp/webauthn_test.go b/services/cognitoidp/webauthn_test.go index e7b7476b4e..2417ec442f 100644 --- a/services/cognitoidp/webauthn_test.go +++ b/services/cognitoidp/webauthn_test.go @@ -1,12 +1,14 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestWebAuthn_CRUD(t *testing.T) { @@ -24,7 +26,7 @@ func TestWebAuthn_CRUD(t *testing.T) { var startResp struct { CredentialCreationOptions map[string]any `json:"CredentialCreationOptions,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) require.NotEmpty(t, startResp.CredentialCreationOptions) assert.NotEmpty(t, startResp.CredentialCreationOptions["challenge"]) rp, ok := startResp.CredentialCreationOptions["rp"].(map[string]any) @@ -59,7 +61,7 @@ func TestWebAuthn_CRUD(t *testing.T) { AuthenticatorTransports []string `json:"AuthenticatorTransports"` } `json:"Credentials,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Credentials, 1) assert.Equal(t, "cred-id-1", listResp.Credentials[0].CredentialID) assert.Equal(t, "platform", listResp.Credentials[0].AuthenticatorAttachment) @@ -88,7 +90,7 @@ func TestWebAuthn_CRUD(t *testing.T) { CredentialID string `json:"CredentialId,omitempty"` } `json:"Credentials,omitempty"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2, jsonx.V1())) assert.Empty(t, listResp2.Credentials) // Delete again — not found. @@ -139,7 +141,7 @@ func TestHandler_CompleteWebAuthnRegistration_Validation(t *testing.T) { AccessToken string `json:"AccessToken,omitempty"` } `json:"AuthenticationResult"` } - require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp, jsonx.V1())) require.NotNil(t, initResp.AuthenticationResult) accessToken := initResp.AuthenticationResult.AccessToken require.NotEmpty(t, accessToken) diff --git a/services/cognitoidp/wire_field_fixes_test.go b/services/cognitoidp/wire_field_fixes_test.go index 6c5ecd8320..ba6d1c424a 100644 --- a/services/cognitoidp/wire_field_fixes_test.go +++ b/services/cognitoidp/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package cognitoidp_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListUserPoolClients_SummaryShape proves ListUserPoolClients returns the @@ -56,7 +58,7 @@ func TestListUserPoolClients_SummaryShape(t *testing.T) { // assert directly on the wire body that no such key is emitted. rec := doCognitoRequest(t, h, "ListUserPoolClients", map[string]any{"UserPoolId": poolID}) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) rawClients, ok := raw["UserPoolClients"].([]any) require.True(t, ok) require.Len(t, rawClients, 1) diff --git a/services/comprehend/handler.go b/services/comprehend/handler.go index 8ddfaf6662..ab2292b253 100644 --- a/services/comprehend/handler.go +++ b/services/comprehend/handler.go @@ -2,7 +2,7 @@ package comprehend import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -155,7 +156,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } var values map[string]any - if unmarshalErr := json.Unmarshal(body, &values); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &values, jsonx.V1()); unmarshalErr != nil { return "" } for _, key := range []string{ @@ -202,7 +203,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt var input map[string]any if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } } @@ -214,7 +215,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt return nil, err } - return json.Marshal(output) + return json.Marshal(output, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -241,7 +242,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err code, status = "KmsKeyValidationException", http.StatusBadRequest } - payload, marshalErr := json.Marshal(service.JSONErrorResponse{Type: code, Message: errMessage(err)}) + payload, marshalErr := json.Marshal(service.JSONErrorResponse{Type: code, Message: errMessage(err)}, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } diff --git a/services/comprehend/handler_test.go b/services/comprehend/handler_test.go index e6fdcc10ca..c49c2e5b2d 100644 --- a/services/comprehend/handler_test.go +++ b/services/comprehend/handler_test.go @@ -2,7 +2,7 @@ package comprehend_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/comprehend" ) @@ -67,7 +68,7 @@ func mergedBody(base, extra map[string]any) map[string]any { func request(t *testing.T, handler *comprehend.Handler, operation string, input map[string]any) map[string]any { t.Helper() - payload, err := json.Marshal(input) + payload, err := json.Marshal(input, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(payload)) req.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -78,7 +79,7 @@ func request(t *testing.T, handler *comprehend.Handler, operation string, input require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var output map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &output)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &output, jsonx.V1())) return output } @@ -107,7 +108,7 @@ func decodeBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } @@ -118,7 +119,7 @@ func decodeBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { func toJSON(t *testing.T, input map[string]any) string { t.Helper() - payload, err := json.Marshal(input) + payload, err := json.Marshal(input, jsonx.V1()) require.NoError(t, err) return string(payload) @@ -892,7 +893,7 @@ func TestProtocolOpList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.NotEmpty(t, ops, "GET / must return non-empty operation list") assert.Contains(t, ops, "DetectSentiment") assert.Contains(t, ops, "DetectEntities") diff --git a/services/comprehend/persistence.go b/services/comprehend/persistence.go index 4555857377..ab0a89612c 100644 --- a/services/comprehend/persistence.go +++ b/services/comprehend/persistence.go @@ -2,7 +2,7 @@ package comprehend import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -41,7 +41,7 @@ const comprehendSnapshotVersion = 1 // nothing for store.Table to key on (see store_setup.go's file doc comment). // They are persisted directly here. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` Policies map[string]string `json:"policies"` PolicyRevisions map[string]string `json:"policyRevisions"` diff --git a/services/comprehend/s3_output.go b/services/comprehend/s3_output.go index 1a0ec15aa7..44ba63abfb 100644 --- a/services/comprehend/s3_output.go +++ b/services/comprehend/s3_output.go @@ -5,7 +5,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "fmt" "path" "slices" @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" awss3 "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" s3backend "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -172,12 +173,12 @@ func outputFiles(job *Job) map[string][]byte { case jobTypeClassification: line, _ := json.Marshal(map[string]any{ "File": input, "Classes": []map[string]any{{"Name": "DEFAULT", "Score": defaultScore}}, - }) + }, jsonx.V1()) return map[string][]byte{"predictions.jsonl": append(line, '\n')} } - line, _ := json.Marshal(jobResultLine(job, input)) + line, _ := json.Marshal(jobResultLine(job, input), jsonx.V1()) return map[string][]byte{"output": append(line, '\n')} } diff --git a/services/connect/contacts.go b/services/connect/contacts.go index eebb94684c..fb8aa74503 100644 --- a/services/connect/contacts.go +++ b/services/connect/contacts.go @@ -2,7 +2,7 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" "maps" "slices" "strings" @@ -40,8 +40,8 @@ type StartOutboundVoiceContactInput struct { Description string RelatedContactID string `json:"RelatedContactId"` ClientToken string - OutboundStrategy json.RawMessage - References json.RawMessage + OutboundStrategy jsontext.Value + References jsontext.Value } // ParticipantDetails names a chat participant. @@ -73,7 +73,7 @@ type StartChatContactInput struct { CustomerID string `json:"CustomerId"` RelatedContactID string `json:"RelatedContactId"` ClientToken string - SegmentAttributes json.RawMessage + SegmentAttributes jsontext.Value } // StartTaskContactInput is the StartTaskContact request. @@ -89,9 +89,9 @@ type StartTaskContactInput struct { QuickConnectID string `json:"QuickConnectId"` TaskTemplateID string `json:"TaskTemplateId"` ClientToken string - SegmentAttributes json.RawMessage - Attachments json.RawMessage - References json.RawMessage + SegmentAttributes jsontext.Value + Attachments jsontext.Value + References jsontext.Value } // ContactRefInput addresses one contact in body-addressed contact operations. @@ -114,8 +114,8 @@ type ContactRefInput struct { ContactID string `json:"ContactId" path:"ContactId"` InstanceID string `json:"InstanceId" path:"InstanceId"` InitialContactID string `json:"InitialContactId"` - SegmentAttributes json.RawMessage - References json.RawMessage + SegmentAttributes jsontext.Value + References jsontext.Value } // ContactPathInput addresses one contact by path. diff --git a/services/connect/datatables.go b/services/connect/datatables.go index ba40dfa647..1157cacb49 100644 --- a/services/connect/datatables.go +++ b/services/connect/datatables.go @@ -2,7 +2,8 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "net/http" @@ -11,6 +12,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -211,11 +213,11 @@ func (t *dataTableRec) primaryAttrs() []*DataTableAttribute { } func (t *dataTableRec) clone() *dataTableRec { - raw, _ := json.Marshal(t) + raw, _ := json.Marshal(t, jsonx.V1()) var out dataTableRec - _ = json.Unmarshal(raw, &out) + _ = json.Unmarshal(raw, &out, jsonx.V1()) return &out } @@ -779,8 +781,8 @@ func checkDTText(v *DataTableValidation, s string) error { } func checkDTList(a *DataTableAttribute, s string) error { - var items []json.RawMessage - if err := json.Unmarshal([]byte(s), &items); err != nil { + var items []jsontext.Value + if err := json.Unmarshal([]byte(s), &items, jsonx.V1()); err != nil { return valueErr("value must be a JSON array") } @@ -798,7 +800,7 @@ func checkDTList(a *DataTableAttribute, s string) error { for _, raw := range items { if a.ValueType == dtTypeNumberList { var f float64 - if json.Unmarshal(raw, &f) != nil { + if json.Unmarshal(raw, &f, jsonx.V1()) != nil { return valueErr("list item %s is not a number", raw) } @@ -810,7 +812,7 @@ func checkDTList(a *DataTableAttribute, s string) error { } var str string - if json.Unmarshal(raw, &str) != nil { + if json.Unmarshal(raw, &str, jsonx.V1()) != nil { return valueErr("list item %s is not text", raw) } diff --git a/services/connect/evaluationforms.go b/services/connect/evaluationforms.go index 1ae1c508dc..a6dce6a97c 100644 --- a/services/connect/evaluationforms.go +++ b/services/connect/evaluationforms.go @@ -2,11 +2,13 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -54,15 +56,15 @@ type evalFormVersion struct { } type formContent struct { - ScoringStrategy json.RawMessage `json:"ScoringStrategy,omitempty"` - AutoEvaluationConfiguration json.RawMessage `json:"AutoEvaluationConfiguration,omitempty"` - ReviewConfiguration json.RawMessage `json:"ReviewConfiguration,omitempty"` - TargetConfiguration json.RawMessage `json:"TargetConfiguration,omitempty"` - LanguageConfiguration json.RawMessage `json:"LanguageConfiguration,omitempty"` - Title string `json:"Title"` - Description string `json:"Description,omitempty"` - AIVersion string `json:"AIVersion,omitempty"` - Items []json.RawMessage `json:"Items"` + ScoringStrategy jsontext.Value `json:"ScoringStrategy,omitempty"` + AutoEvaluationConfiguration jsontext.Value `json:"AutoEvaluationConfiguration,omitempty"` + ReviewConfiguration jsontext.Value `json:"ReviewConfiguration,omitempty"` + TargetConfiguration jsontext.Value `json:"TargetConfiguration,omitempty"` + LanguageConfiguration jsontext.Value `json:"LanguageConfiguration,omitempty"` + Title string `json:"Title"` + Description string `json:"Description,omitempty"` + AIVersion string `json:"AIVersion,omitempty"` + Items []jsontext.Value `json:"Items"` } type evalFormRec struct { @@ -212,9 +214,9 @@ func (w *formWalk) problem(sev, code, desc string) { w.findings = append(w.findings, FormFinding{Description: desc, IssueCode: code, Severity: sev}) } -func (w *formWalk) item(raw json.RawMessage, depth int) { - var u map[string]json.RawMessage - if err := json.Unmarshal(raw, &u); err != nil || len(u) != 1 { +func (w *formWalk) item(raw jsontext.Value, depth int) { + var u map[string]jsontext.Value + if err := json.Unmarshal(raw, &u, jsonx.V1()); err != nil || len(u) != 1 { w.problem(findingError, "InvalidItem", "an item must be an object with exactly one of Section or Question") return @@ -248,14 +250,14 @@ func (w *formWalk) ref(ref string) { } } -func (w *formWalk) section(raw json.RawMessage, depth int) { +func (w *formWalk) section(raw jsontext.Value, depth int) { var s struct { - RefID string `json:"RefId"` - Title string `json:"Title"` - Items []json.RawMessage `json:"Items"` + RefID string `json:"RefId"` + Title string `json:"Title"` + Items []jsontext.Value `json:"Items"` } - if json.Unmarshal(raw, &s) != nil { + if json.Unmarshal(raw, &s, jsonx.V1()) != nil { w.problem(findingError, "InvalidSection", "a Section is not valid") return @@ -278,15 +280,15 @@ func (w *formWalk) section(raw json.RawMessage, depth int) { } } -func (w *formWalk) question(raw json.RawMessage) { +func (w *formWalk) question(raw jsontext.Value) { var q struct { - Props map[string]json.RawMessage `json:"QuestionTypeProperties"` - RefID string `json:"RefId"` - Title string `json:"Title"` - QuestionType string `json:"QuestionType"` + Props map[string]jsontext.Value `json:"QuestionTypeProperties"` + RefID string `json:"RefId"` + Title string `json:"Title"` + QuestionType string `json:"QuestionType"` } - if json.Unmarshal(raw, &q) != nil { + if json.Unmarshal(raw, &q, jsonx.V1()) != nil { w.problem(findingError, "InvalidQuestion", "a Question is not valid") return @@ -313,7 +315,7 @@ func (w *formWalk) question(raw json.RawMessage) { } // inspectForm walks the items and reports structural problems and warnings. -func inspectForm(items []json.RawMessage) *formWalk { +func inspectForm(items []jsontext.Value) *formWalk { w := &formWalk{refs: map[string]bool{}} for _, it := range items { w.item(it, 0) @@ -346,7 +348,7 @@ func checkFormContent(c *formContent) error { Mode string `json:"Mode"` Status string `json:"Status"` } - if json.Unmarshal(c.ScoringStrategy, &s) != nil { + if json.Unmarshal(c.ScoringStrategy, &s, jsonx.V1()) != nil { return invalidParamErr("ScoringStrategy is not valid") } @@ -730,13 +732,13 @@ func (b *Backend) SearchEvaluationForms(in *SearchRequest) (*SearchResult, error } // rejectCriteria refuses criteria members the emulator does not evaluate, at any nesting level. -func rejectCriteria(raw json.RawMessage, members ...string) error { +func rejectCriteria(raw jsontext.Value, members ...string) error { if len(raw) == 0 { return nil } - var node map[string]json.RawMessage - if json.Unmarshal(raw, &node) != nil { + var node map[string]jsontext.Value + if json.Unmarshal(raw, &node, jsonx.V1()) != nil { return invalidParamErr("SearchCriteria is not valid") } @@ -747,8 +749,8 @@ func rejectCriteria(raw json.RawMessage, members ...string) error { } for _, key := range []string{"AndConditions", "OrConditions"} { - var subs []json.RawMessage - if json.Unmarshal(node[key], &subs) != nil { + var subs []jsontext.Value + if json.Unmarshal(node[key], &subs, jsonx.V1()) != nil { continue } diff --git a/services/connect/flows.go b/services/connect/flows.go index d77980fb5f..fb1bc4837b 100644 --- a/services/connect/flows.go +++ b/services/connect/flows.go @@ -4,12 +4,15 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "slices" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -57,7 +60,7 @@ func validateFlowContent(code, content string) error { } var doc flowDoc - if err := json.Unmarshal([]byte(content), &doc); err != nil { + if err := json.Unmarshal([]byte(content), &doc, jsonx.V1()); err != nil { return invalidFlowErr(code, "content is not valid flow language JSON: "+err.Error()) } @@ -402,7 +405,7 @@ type CreateContactFlowModuleInput struct { Settings string ClientToken string instPath - ExternalInvocationConfiguration json.RawMessage + ExternalInvocationConfiguration jsontext.Value } func validateModule(content, settings string) error { @@ -410,7 +413,7 @@ func validateModule(content, settings string) error { return err } - if settings != "" && !json.Valid([]byte(settings)) { + if settings != "" && !jsontext.Value([]byte(settings)).IsValid(jsonx.V1()) { return invalidFlowErr("InvalidContactFlowModuleException", "Settings is not valid JSON") } diff --git a/services/connect/metrics.go b/services/connect/metrics.go index e190e792b2..4db70874da 100644 --- a/services/connect/metrics.go +++ b/services/connect/metrics.go @@ -1,7 +1,7 @@ package connect import ( - "encoding/json" + "encoding/json/jsontext" "slices" "strings" "time" @@ -572,10 +572,10 @@ func sortMetricResults(results []CurrentMetricResult, criteria []CurrentMetricSo // HistoricalMetric names one historical metric and statistic. type HistoricalMetric struct { - Name string `json:"Name"` - Statistic string `json:"Statistic"` - Unit string `json:"Unit"` - Threshold json.RawMessage `json:"Threshold,omitempty"` + Name string `json:"Name"` + Statistic string `json:"Statistic"` + Unit string `json:"Unit"` + Threshold jsontext.Value `json:"Threshold,omitempty"` } // GetMetricDataInput is the GetMetricData request. diff --git a/services/connect/models.go b/services/connect/models.go index 72b4359acc..725ae00a74 100644 --- a/services/connect/models.go +++ b/services/connect/models.go @@ -1,7 +1,7 @@ package connect import ( - "encoding/json" + "encoding/json/jsontext" "github.com/blackbirdworks/gopherstack/pkgs/awstime" ) @@ -167,11 +167,11 @@ type User struct { RoutingProfileID string `json:"RoutingProfileId"` Username string `json:"Username"` SecurityProfileIDs []string `json:"SecurityProfileIds"` - AfterContactWorkConfigs json.RawMessage `json:"AfterContactWorkConfigs,omitempty"` - AutoAcceptConfigs json.RawMessage `json:"AutoAcceptConfigs,omitempty"` - PersistentConnectionConfigs json.RawMessage `json:"PersistentConnectionConfigs,omitempty"` - PhoneNumberConfigs json.RawMessage `json:"PhoneNumberConfigs,omitempty"` - VoiceEnhancementConfigs json.RawMessage `json:"VoiceEnhancementConfigs,omitempty"` + AfterContactWorkConfigs jsontext.Value `json:"AfterContactWorkConfigs,omitempty"` + AutoAcceptConfigs jsontext.Value `json:"AutoAcceptConfigs,omitempty"` + PersistentConnectionConfigs jsontext.Value `json:"PersistentConnectionConfigs,omitempty"` + PhoneNumberConfigs jsontext.Value `json:"PhoneNumberConfigs,omitempty"` + VoiceEnhancementConfigs jsontext.Value `json:"VoiceEnhancementConfigs,omitempty"` } // Summary is the list shape shared by most resources. @@ -192,10 +192,10 @@ type UserSummary struct { // MediaConcurrency limits concurrent contacts of one channel. type MediaConcurrency struct { - Channel string `json:"Channel"` - CrossChannelBehavior json.RawMessage `json:"CrossChannelBehavior,omitempty"` - WorkloadTypeConcurrencies json.RawMessage `json:"WorkloadTypeConcurrencies,omitempty"` - Concurrency int32 `json:"Concurrency"` + Channel string `json:"Channel"` + CrossChannelBehavior jsontext.Value `json:"CrossChannelBehavior,omitempty"` + WorkloadTypeConcurrencies jsontext.Value `json:"WorkloadTypeConcurrencies,omitempty"` + Concurrency int32 `json:"Concurrency"` } // QueueReference names a queue and channel in a routing profile. @@ -246,7 +246,7 @@ type SecurityProfile struct { Stamp AllowedAccessControlTags map[string]string `json:"AllowedAccessControlTags,omitempty"` Tags map[string]string `json:"Tags,omitempty"` - GranularAccessControlConfiguration json.RawMessage `json:"GranularAccessControlConfiguration,omitempty"` + GranularAccessControlConfiguration jsontext.Value `json:"GranularAccessControlConfiguration,omitempty"` AllowedAccessControlHierarchyGroupID string `json:"AllowedAccessControlHierarchyGroupId,omitempty"` Arn string `json:"Arn"` Description string `json:"Description,omitempty"` @@ -385,8 +385,8 @@ type QuickConnectConfig struct { ContactFlowID string `json:"ContactFlowId"` UserID string `json:"UserId"` } `json:"UserConfig,omitempty"` - QuickConnectType string `json:"QuickConnectType"` - FlowConfig json.RawMessage `json:"FlowConfig,omitempty"` + QuickConnectType string `json:"QuickConnectType"` + FlowConfig jsontext.Value `json:"FlowConfig,omitempty"` } // QuickConnect is a saved transfer destination. @@ -441,7 +441,7 @@ type ContactFlowModule struct { State string `json:"State"` Status string `json:"Status"` VersionDescription string `json:"VersionDescription,omitempty"` - ExternalInvocationConfiguration json.RawMessage `json:"ExternalInvocationConfiguration,omitempty"` + ExternalInvocationConfiguration jsontext.Value `json:"ExternalInvocationConfiguration,omitempty"` } // ContactFlowModuleSummary is the list shape of a ContactFlowModule. @@ -580,6 +580,6 @@ type Contact struct { Name string `json:"Name,omitempty"` PreviousContactID string `json:"PreviousContactId,omitempty"` RelatedContactID string `json:"RelatedContactId,omitempty"` - OutboundStrategy json.RawMessage `json:"OutboundStrategy,omitempty"` - SegmentAttributes json.RawMessage `json:"SegmentAttributes,omitempty"` + OutboundStrategy jsontext.Value `json:"OutboundStrategy,omitempty"` + SegmentAttributes jsontext.Value `json:"SegmentAttributes,omitempty"` } diff --git a/services/connect/persistence.go b/services/connect/persistence.go index 5536f01256..66da04122e 100644 --- a/services/connect/persistence.go +++ b/services/connect/persistence.go @@ -2,7 +2,7 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/connect/proficiencies.go b/services/connect/proficiencies.go index e3fcf04154..2f63a96f22 100644 --- a/services/connect/proficiencies.go +++ b/services/connect/proficiencies.go @@ -2,11 +2,13 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "slices" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -210,17 +212,17 @@ func (b *Backend) ListUserProficiencies(in *ProficienciesInput) (*ProficienciesO type UpdateUserConfigInput struct { UserID string `json:"-" path:"UserId"` instPath - AfterContactWorkConfigs json.RawMessage - AutoAcceptConfigs json.RawMessage - PersistentConnectionConfigs json.RawMessage - PhoneNumberConfigs json.RawMessage - VoiceEnhancementConfigs json.RawMessage + AfterContactWorkConfigs jsontext.Value + AutoAcceptConfigs jsontext.Value + PersistentConnectionConfigs jsontext.Value + PhoneNumberConfigs jsontext.Value + VoiceEnhancementConfigs jsontext.Value } var userChannels = []string{"VOICE", "CHAT", "TASK", emailValue} //nolint:gochecknoglobals // immutable lookup table // checkChannelConfigs validates that every entry names a known channel and returns the normalised list. -func checkChannelConfigs(field string, raw json.RawMessage) (json.RawMessage, error) { +func checkChannelConfigs(field string, raw jsontext.Value) (jsontext.Value, error) { if len(raw) == 0 || string(raw) == jsonNull { return nil, nil } @@ -229,7 +231,7 @@ func checkChannelConfigs(field string, raw json.RawMessage) (json.RawMessage, er Channel string `json:"Channel"` } - if err := json.Unmarshal(raw, &items); err != nil { + if err := json.Unmarshal(raw, &items, jsonx.V1()); err != nil { return nil, invalidParamErr("%s is not valid", field) } @@ -251,30 +253,30 @@ func checkChannelConfigs(field string, raw json.RawMessage) (json.RawMessage, er } type userConfigField struct { - dst func(*User) *json.RawMessage + dst func(*User) *jsontext.Value name string - raw json.RawMessage + raw jsontext.Value } func userConfigFields(in *UpdateUserConfigInput) []userConfigField { return []userConfigField{ {name: "AfterContactWorkConfigs", raw: in.AfterContactWorkConfigs, - dst: func(u *User) *json.RawMessage { return &u.AfterContactWorkConfigs }}, + dst: func(u *User) *jsontext.Value { return &u.AfterContactWorkConfigs }}, {name: "AutoAcceptConfigs", raw: in.AutoAcceptConfigs, - dst: func(u *User) *json.RawMessage { return &u.AutoAcceptConfigs }}, + dst: func(u *User) *jsontext.Value { return &u.AutoAcceptConfigs }}, {name: "PersistentConnectionConfigs", raw: in.PersistentConnectionConfigs, - dst: func(u *User) *json.RawMessage { return &u.PersistentConnectionConfigs }}, + dst: func(u *User) *jsontext.Value { return &u.PersistentConnectionConfigs }}, {name: "PhoneNumberConfigs", raw: in.PhoneNumberConfigs, - dst: func(u *User) *json.RawMessage { return &u.PhoneNumberConfigs }}, + dst: func(u *User) *jsontext.Value { return &u.PhoneNumberConfigs }}, {name: "VoiceEnhancementConfigs", raw: in.VoiceEnhancementConfigs, - dst: func(u *User) *json.RawMessage { return &u.VoiceEnhancementConfigs }}, + dst: func(u *User) *jsontext.Value { return &u.VoiceEnhancementConfigs }}, } } // UpdateUserConfig replaces the supplied per-channel settings of a user. func (b *Backend) UpdateUserConfig(ctx context.Context, in *UpdateUserConfigInput) (*empty, error) { fields := userConfigFields(in) - checked := make([]json.RawMessage, len(fields)) + checked := make([]jsontext.Value, len(fields)) for i, f := range fields { raw, err := checkChannelConfigs(f.name, f.raw) diff --git a/services/connect/records.go b/services/connect/records.go index 6eb4a53ce8..4e412b527d 100644 --- a/services/connect/records.go +++ b/services/connect/records.go @@ -1,7 +1,7 @@ package connect import ( - "encoding/json" + "encoding/json/jsontext" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -90,13 +90,13 @@ type promptRec struct { } type contactRec struct { - InstanceID string `json:"instanceId"` - ParticipantID string `json:"participantId,omitempty"` - ParticipantToken string `json:"participantToken,omitempty"` - FlowID string `json:"flowId,omitempty"` - TaskTemplateID string `json:"taskTemplateId,omitempty"` - Contact Contact `json:"contact"` - References json.RawMessage `json:"references,omitempty"` + InstanceID string `json:"instanceId"` + ParticipantID string `json:"participantId,omitempty"` + ParticipantToken string `json:"participantToken,omitempty"` + FlowID string `json:"flowId,omitempty"` + TaskTemplateID string `json:"taskTemplateId,omitempty"` + Contact Contact `json:"contact"` + References jsontext.Value `json:"references,omitempty"` } type integrationRec struct { diff --git a/services/connect/rules.go b/services/connect/rules.go index b4ae08aaa6..9a20d281d2 100644 --- a/services/connect/rules.go +++ b/services/connect/rules.go @@ -2,10 +2,12 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -57,8 +59,8 @@ type Rule struct { PublishStatus string `json:"PublishStatus"` RuleArn string `json:"RuleArn"` RuleID string `json:"RuleId"` - Actions []json.RawMessage `json:"Actions"` - PreEvaluationFilters json.RawMessage `json:"PreEvaluationFilters,omitempty"` + Actions []jsontext.Value `json:"Actions"` + PreEvaluationFilters jsontext.Value `json:"PreEvaluationFilters,omitempty"` } // ActionSummary is the list shape of a rule action. @@ -92,8 +94,8 @@ type CreateRuleInput struct { PublishStatus string ClientToken string instPath - PreEvaluationFilters json.RawMessage - Actions []json.RawMessage + PreEvaluationFilters jsontext.Value + Actions []jsontext.Value } // UpdateRuleInput is the UpdateRule request. @@ -103,8 +105,8 @@ type UpdateRuleInput struct { PublishStatus string RuleID string `json:"-" path:"RuleId"` instPath - PreEvaluationFilters json.RawMessage - Actions []json.RawMessage + PreEvaluationFilters jsontext.Value + Actions []jsontext.Value } // RuleOut is the wire shape of a rule. @@ -113,14 +115,14 @@ type RuleOut struct { RuleID string `json:"RuleId"` } -func ruleActionType(raw json.RawMessage) (string, error) { - var a map[string]json.RawMessage - if err := json.Unmarshal(raw, &a); err != nil { +func ruleActionType(raw jsontext.Value) (string, error) { + var a map[string]jsontext.Value + if err := json.Unmarshal(raw, &a, jsonx.V1()); err != nil { return "", invalidParamErr("Actions contains an invalid action") } var t string - if err := json.Unmarshal(a["ActionType"], &t); err != nil { + if err := json.Unmarshal(a["ActionType"], &t, jsonx.V1()); err != nil { return "", invalidParamErr("every action needs an ActionType") } @@ -136,7 +138,7 @@ func ruleActionType(raw json.RawMessage) (string, error) { return t, nil } -func (b *Backend) checkRuleActions(inst string, actions []json.RawMessage) error { +func (b *Backend) checkRuleActions(inst string, actions []jsontext.Value) error { if len(actions) == 0 || len(actions) > maxRuleActions { return invalidParamErr("Actions must contain 1-%d actions", maxRuleActions) } @@ -157,14 +159,14 @@ func (b *Backend) checkRuleActions(inst string, actions []json.RawMessage) error return nil } -func (b *Backend) checkTaskActionFlow(inst string, raw json.RawMessage) error { +func (b *Backend) checkTaskActionFlow(inst string, raw jsontext.Value) error { var a struct { TaskAction struct { ContactFlowID string `json:"ContactFlowId"` } `json:"TaskAction"` } - if err := json.Unmarshal(raw, &a); err != nil { + if err := json.Unmarshal(raw, &a, jsonx.V1()); err != nil { return invalidParamErr("TaskAction is not valid") } diff --git a/services/connect/search.go b/services/connect/search.go index d45f34779e..755290af2b 100644 --- a/services/connect/search.go +++ b/services/connect/search.go @@ -1,11 +1,13 @@ package connect import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TimeRange bounds a contact search. @@ -70,23 +72,23 @@ type SearchContactsInput struct { TimeRange TimeRange InstanceID string `json:"InstanceId"` NextToken string - SearchCriteria json.RawMessage + SearchCriteria jsontext.Value MaxResults int32 } -func parseCriteria(raw json.RawMessage) (*ContactSearchCriteria, error) { +func parseCriteria(raw jsontext.Value) (*ContactSearchCriteria, error) { var crit ContactSearchCriteria if len(raw) == 0 { return &crit, nil } - if err := json.Unmarshal(raw, &crit); err != nil { + if err := json.Unmarshal(raw, &crit, jsonx.V1()); err != nil { return nil, invalidParamErr("SearchCriteria is not valid") } - var members map[string]json.RawMessage - if err := json.Unmarshal(raw, &members); err != nil { + var members map[string]jsontext.Value + if err := json.Unmarshal(raw, &members, jsonx.V1()); err != nil { return nil, invalidParamErr("SearchCriteria is not valid") } @@ -291,7 +293,7 @@ type ContactSearchSummary struct { InitiationMethod string `json:"InitiationMethod"` Name string `json:"Name,omitempty"` PreviousContactID string `json:"PreviousContactId,omitempty"` - SegmentAttributes json.RawMessage `json:"SegmentAttributes,omitempty"` + SegmentAttributes jsontext.Value `json:"SegmentAttributes,omitempty"` } func summarizeContact(c *contactRec) ContactSearchSummary { diff --git a/services/connect/searchengine.go b/services/connect/searchengine.go index 63d391048b..e27096ffb2 100644 --- a/services/connect/searchengine.go +++ b/services/connect/searchengine.go @@ -1,10 +1,12 @@ package connect import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -124,17 +126,17 @@ type searchSpec struct { fields []string } -func parseSearch(rawCriteria, rawFilter json.RawMessage, spec searchSpec) (*searchCriteria, *searchFilter, error) { +func parseSearch(rawCriteria, rawFilter jsontext.Value, spec searchSpec) (*searchCriteria, *searchFilter, error) { var c searchCriteria var f searchFilter - for raw, dst := range map[*json.RawMessage]any{&rawCriteria: &c, &rawFilter: &f} { + for raw, dst := range map[*jsontext.Value]any{&rawCriteria: &c, &rawFilter: &f} { if len(*raw) == 0 || string(*raw) == jsonNull { continue } - if err := json.Unmarshal(*raw, dst); err != nil { + if err := json.Unmarshal(*raw, dst, jsonx.V1()); err != nil { return nil, nil, invalidParamErr("SearchCriteria or SearchFilter is not valid") } } diff --git a/services/connect/searches.go b/services/connect/searches.go index d628b95bee..5ad78bcbc6 100644 --- a/services/connect/searches.go +++ b/services/connect/searches.go @@ -2,18 +2,21 @@ package connect import ( "cmp" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // SearchRequest is the body shared by the Search* operations. type SearchRequest struct { InstanceID string `json:"InstanceId"` NextToken string - SearchCriteria json.RawMessage - SearchFilter json.RawMessage + SearchCriteria jsontext.Value + SearchFilter jsontext.Value ResourceTypes []string MaxResults int32 } @@ -435,10 +438,10 @@ type TagSet struct { Value string `json:"value"` } -func parseTagSearch(raw json.RawMessage) (func(k, v string) bool, error) { +func parseTagSearch(raw jsontext.Value) (func(k, v string) bool, error) { var c resourceTagsCriteria if len(raw) > 0 && string(raw) != jsonNull { - if err := json.Unmarshal(raw, &c); err != nil { + if err := json.Unmarshal(raw, &c, jsonx.V1()); err != nil { return nil, invalidParamErr("SearchCriteria is not valid") } } diff --git a/services/connect/security.go b/services/connect/security.go index 4809c00633..c729d59969 100644 --- a/services/connect/security.go +++ b/services/connect/security.go @@ -2,7 +2,7 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" "slices" "github.com/google/uuid" @@ -18,13 +18,13 @@ type CreateSecurityProfileInput struct { instPath AllowedAccessControlHierarchyGroupID string `json:"AllowedAccessControlHierarchyGroupId"` Description string - AllowedAIAgents json.RawMessage - Applications json.RawMessage - AllowedFlowModules json.RawMessage + AllowedAIAgents jsontext.Value + Applications jsontext.Value + AllowedFlowModules jsontext.Value HierarchyRestrictedResources []string Permissions []string TagRestrictedResources []string - GranularAccessControlConfiguration json.RawMessage + GranularAccessControlConfiguration jsontext.Value } // UpdateSecurityProfileInput is the UpdateSecurityProfile request. @@ -34,10 +34,10 @@ type UpdateSecurityProfileInput struct { AllowedAccessControlHierarchyGroupID *string `json:"AllowedAccessControlHierarchyGroupId"` ProfileID string `json:"-" path:"SecurityProfileId"` instPath - GranularAccessControlConfiguration json.RawMessage - AllowedAIAgents json.RawMessage - AllowedFlowModules json.RawMessage - Applications json.RawMessage + GranularAccessControlConfiguration jsontext.Value + AllowedAIAgents jsontext.Value + AllowedFlowModules jsontext.Value + Applications jsontext.Value HierarchyRestrictedResources []string Permissions []string TagRestrictedResources []string diff --git a/services/connect/securityextras.go b/services/connect/securityextras.go index f3189ef3a7..0c43c45535 100644 --- a/services/connect/securityextras.go +++ b/services/connect/securityextras.go @@ -2,18 +2,21 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxSecurityExtras = 100 // securityExtras are the Applications, AllowedFlowModules and AllowedAIAgents of a security profile. type securityExtras struct { - AIAgents json.RawMessage `json:"aiAgents,omitempty"` - Applications json.RawMessage `json:"applications,omitempty"` - FlowModules json.RawMessage `json:"flowModules,omitempty"` + AIAgents jsontext.Value `json:"aiAgents,omitempty"` + Applications jsontext.Value `json:"applications,omitempty"` + FlowModules jsontext.Value `json:"flowModules,omitempty"` } type entityProfilesRec struct { @@ -23,7 +26,7 @@ type entityProfilesRec struct { } // checkSecurityExtras validates the three lists and returns them ready to store; nil inputs stay nil. -func (b *Backend) checkSecurityExtras(inst string, aiAgents, apps, modules json.RawMessage) (securityExtras, error) { +func (b *Backend) checkSecurityExtras(inst string, aiAgents, apps, modules jsontext.Value) (securityExtras, error) { var out securityExtras if present(aiAgents) { @@ -53,9 +56,9 @@ func (b *Backend) checkSecurityExtras(inst string, aiAgents, apps, modules json. return out, nil } -func present(raw json.RawMessage) bool { return len(raw) > 0 && string(raw) != jsonNull } +func present(raw jsontext.Value) bool { return len(raw) > 0 && string(raw) != jsonNull } -func checkAIAgents(raw json.RawMessage) error { +func checkAIAgents(raw jsontext.Value) error { var items []struct { Arn string `json:"Arn"` Type string `json:"Type"` @@ -77,7 +80,7 @@ func checkAIAgents(raw json.RawMessage) error { return nil } -func checkApplications(raw json.RawMessage) error { +func checkApplications(raw jsontext.Value) error { var items []struct { Namespace string `json:"Namespace"` Type string `json:"Type"` @@ -100,7 +103,7 @@ func checkApplications(raw json.RawMessage) error { return nil } -func (b *Backend) checkFlowModules(inst string, raw json.RawMessage) error { +func (b *Backend) checkFlowModules(inst string, raw jsontext.Value) error { var items []struct { FlowModuleID string `json:"FlowModuleId"` Type string `json:"Type"` @@ -123,13 +126,13 @@ func (b *Backend) checkFlowModules(inst string, raw json.RawMessage) error { return nil } -func decodeBounded(raw json.RawMessage, dst any, field string) error { - if err := json.Unmarshal(raw, dst); err != nil { +func decodeBounded(raw jsontext.Value, dst any, field string) error { + if err := json.Unmarshal(raw, dst, jsonx.V1()); err != nil { return invalidParamErr("%s is not valid", field) } - var list []json.RawMessage - if json.Unmarshal(raw, &list) == nil && len(list) > maxSecurityExtras { + var list []jsontext.Value + if json.Unmarshal(raw, &list, jsonx.V1()) == nil && len(list) > maxSecurityExtras { return invalidParamErr("%s can hold at most %d entries", field, maxSecurityExtras) } @@ -172,10 +175,10 @@ type SecurityListInput struct { type SecurityListOut map[string]any func (b *Backend) listSecurityExtra( - op, key string, in *SecurityListInput, pick func(*securityExtras) json.RawMessage, + op, key string, in *SecurityListInput, pick func(*securityExtras) jsontext.Value, ) (*SecurityListOut, error) { var ( - items []json.RawMessage + items []jsontext.Value stamp Stamp ) @@ -188,7 +191,7 @@ func (b *Backend) listSecurityExtra( stamp = p.Profile.Stamp if raw := pick(&p.Extras); raw != nil { - err = json.Unmarshal(raw, &items) + err = json.Unmarshal(raw, &items, jsonx.V1()) } return &empty{}, err @@ -216,19 +219,19 @@ func (b *Backend) listSecurityExtra( // ListSecurityProfileApplications lists the applications a security profile grants. func (b *Backend) ListSecurityProfileApplications(in *SecurityListInput) (*SecurityListOut, error) { return b.listSecurityExtra("ListSecurityProfileApplications", "Applications", in, - func(e *securityExtras) json.RawMessage { return e.Applications }) + func(e *securityExtras) jsontext.Value { return e.Applications }) } // ListSecurityProfileFlowModules lists the flow modules a security profile allows. func (b *Backend) ListSecurityProfileFlowModules(in *SecurityListInput) (*SecurityListOut, error) { return b.listSecurityExtra("ListSecurityProfileFlowModules", "AllowedFlowModules", in, - func(e *securityExtras) json.RawMessage { return e.FlowModules }) + func(e *securityExtras) jsontext.Value { return e.FlowModules }) } // ListSecurityProfileAIAgents lists the AI agents a security profile allows. func (b *Backend) ListSecurityProfileAIAgents(in *SecurityListInput) (*SecurityListOut, error) { return b.listSecurityExtra("ListSecurityProfileAIAgents", "AllowedAIAgents", in, - func(e *securityExtras) json.RawMessage { return e.AIAgents }) + func(e *securityExtras) jsontext.Value { return e.AIAgents }) } // EntityProfilesInput is the Associate/Disassociate/ListEntitySecurityProfiles request. diff --git a/services/connect/users.go b/services/connect/users.go index 8fa30a0c57..1a080973ff 100644 --- a/services/connect/users.go +++ b/services/connect/users.go @@ -2,7 +2,7 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" "slices" "unicode" @@ -29,12 +29,12 @@ type CreateUserInput struct { HierarchyGroupID string `json:"HierarchyGroupId"` DirectoryUserID string `json:"DirectoryUserId"` Username string - AfterContactWorkConfigs json.RawMessage - VoiceEnhancementConfigs json.RawMessage - PhoneNumberConfigs json.RawMessage - PersistentConnectionConfigs json.RawMessage + AfterContactWorkConfigs jsontext.Value + VoiceEnhancementConfigs jsontext.Value + PhoneNumberConfigs jsontext.Value + PersistentConnectionConfigs jsontext.Value SecurityProfileIDs []string `json:"SecurityProfileIds"` - AutoAcceptConfigs json.RawMessage + AutoAcceptConfigs jsontext.Value } // UpdateUserInput carries the user update requests; each op reads only its own members. diff --git a/services/connect/views.go b/services/connect/views.go index 5bd749287a..d082f35405 100644 --- a/services/connect/views.go +++ b/services/connect/views.go @@ -2,13 +2,15 @@ package connect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "slices" "strconv" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -113,7 +115,7 @@ func checkViewContent(c *ViewInputContent) (*ViewContent, error) { return nil, invalidParamErr("Content.Template is required") } - if !json.Valid([]byte(c.Template)) { + if !jsontext.Value([]byte(c.Template)).IsValid(jsonx.V1()) { return nil, invalidParamErr("Content.Template must be valid JSON") } @@ -137,7 +139,7 @@ func viewSchema(template string) string { raw, _ := json.Marshal(map[string]any{ "$schema": "http://json-schema.org/draft-07/schema#", fieldType: "object", "properties": props, - }) + }, jsonx.V1()) return string(raw) } diff --git a/services/connect/workspaces.go b/services/connect/workspaces.go index 1f08156e35..cb02205d87 100644 --- a/services/connect/workspaces.go +++ b/services/connect/workspaces.go @@ -3,11 +3,13 @@ package connect import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -59,13 +61,13 @@ type MediaItem struct { type Workspace struct { Tags map[string]string `json:"Tags,omitempty"` Stamp - Arn string `json:"Arn"` - ID string `json:"Id"` - Name string `json:"Name"` - Description string `json:"Description,omitempty"` - Title string `json:"Title,omitempty"` - Visibility string `json:"Visibility"` - Theme json.RawMessage `json:"Theme,omitempty"` + Arn string `json:"Arn"` + ID string `json:"Id"` + Name string `json:"Name"` + Description string `json:"Description,omitempty"` + Title string `json:"Title,omitempty"` + Visibility string `json:"Visibility"` + Theme jsontext.Value `json:"Theme,omitempty"` } // WorkspaceSummary is the list shape of a workspace. @@ -112,19 +114,19 @@ type wsRef struct { instPath } -func checkTheme(raw json.RawMessage) error { +func checkTheme(raw jsontext.Value) error { if len(raw) == 0 || string(raw) == jsonNull { return nil } - var modes map[string]json.RawMessage - if err := json.Unmarshal(raw, &modes); err != nil { + var modes map[string]jsontext.Value + if err := json.Unmarshal(raw, &modes, jsonx.V1()); err != nil { return invalidParamErr("Theme must be an object") } for k, v := range modes { - var cfg map[string]json.RawMessage - if k != "Light" && k != "Dark" || json.Unmarshal(v, &cfg) != nil { + var cfg map[string]jsontext.Value + if k != "Light" && k != "Dark" || json.Unmarshal(v, &cfg, jsonx.V1()) != nil { return invalidParamErr("Theme may only hold Light and Dark theme configurations") } } @@ -151,7 +153,7 @@ type CreateWorkspaceInput struct { Description string Title string instPath - Theme json.RawMessage + Theme jsontext.Value } type createWorkspaceOut struct { @@ -261,7 +263,7 @@ func (b *Backend) UpdateWorkspaceMetadata(ctx context.Context, in *UpdateWorkspa // UpdateWorkspaceThemeInput is the UpdateWorkspaceTheme request. type UpdateWorkspaceThemeInput struct { wsRef - Theme json.RawMessage + Theme jsontext.Value } // UpdateWorkspaceTheme replaces the theme of a workspace. @@ -371,8 +373,8 @@ func (b *Backend) checkPageFields(inst string, in *pageFields) error { } if in.InputData != nil { - var obj map[string]json.RawMessage - if json.Unmarshal([]byte(*in.InputData), &obj) != nil { + var obj map[string]jsontext.Value + if json.Unmarshal([]byte(*in.InputData), &obj, jsonx.V1()) != nil { return invalidParamErr("InputData must be a JSON object") } } diff --git a/services/cosmosdb/account_ops_test.go b/services/cosmosdb/account_ops_test.go index e651ad8e5b..93126cb2bb 100644 --- a/services/cosmosdb/account_ops_test.go +++ b/services/cosmosdb/account_ops_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_AccountRoot covers the database-account root resource ("" or @@ -72,7 +74,7 @@ func TestHandler_AccountRoot_EndpointEchoesRequestHost(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) const wantEndpoint = "http://localhost:32771/" diff --git a/services/cosmosdb/batch.go b/services/cosmosdb/batch.go index a3810d3704..578977b7ca 100644 --- a/services/cosmosdb/batch.go +++ b/services/cosmosdb/batch.go @@ -2,7 +2,8 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxBatchOperations is the Cosmos limit on operations in one transactional batch. @@ -33,10 +35,10 @@ func isBatchRequest(r *http.Request) bool { } type batchOpWire struct { - OperationType string `json:"operationType"` - ID string `json:"id"` - IfMatch string `json:"ifMatch"` - ResourceBody json.RawMessage `json:"resourceBody"` + OperationType string `json:"operationType"` + ID string `json:"id"` + IfMatch string `json:"ifMatch"` + ResourceBody jsontext.Value `json:"resourceBody"` } // batchOp is a decoded batch operation. @@ -59,8 +61,8 @@ type BatchResult struct { func parseBatchOps(raw []byte) ([]batchOp, error) { var wire []batchOpWire - dec := json.NewDecoder(bytes.NewReader(raw)) - if err := dec.Decode(&wire); err != nil || rejectTrailingJSON(dec) != nil { + dec := jsontext.NewDecoder(bytes.NewReader(raw), jsonx.V1()) + if err := json.UnmarshalDecode(dec, &wire, jsonx.V1()); err != nil || rejectTrailingJSON(dec) != nil { return nil, fmt.Errorf("%w: the batch body is not a JSON array of operations", ErrInvalidDocument) } @@ -190,7 +192,7 @@ func (tx *containerTx) runBatchOp(pk string, op batchOp) (BatchResult, error) { } body := documentAsMap(info) - size, _ := json.Marshal(body) + size, _ := json.Marshal(body, jsonx.V1()) return BatchResult{ StatusCode: status, ETag: info.ETag, Body: body, diff --git a/services/cosmosdb/changelog.go b/services/cosmosdb/changelog.go index b26d14e64f..64be63997b 100644 --- a/services/cosmosdb/changelog.go +++ b/services/cosmosdb/changelog.go @@ -1,9 +1,11 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -125,10 +127,10 @@ func partitionKeyObject(paths []string, pkJSON string) map[string]any { var vals []any if len(paths) == 1 { var v any - if json.Unmarshal([]byte(pkJSON), &v) == nil { + if json.Unmarshal([]byte(pkJSON), &v, jsonx.V1()) == nil { vals = []any{v} } - } else if json.Unmarshal([]byte(pkJSON), &vals) != nil { + } else if json.Unmarshal([]byte(pkJSON), &vals, jsonx.V1()) != nil { vals = nil } diff --git a/services/cosmosdb/computed_properties_test.go b/services/cosmosdb/computed_properties_test.go index a6aeefaad9..167ed15110 100644 --- a/services/cosmosdb/computed_properties_test.go +++ b/services/cosmosdb/computed_properties_test.go @@ -1,7 +1,8 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -20,10 +22,10 @@ func computedBackend(t *testing.T, indexing string, props string) *cosmosdb.InMe require.NoError(t, err) spec := cosmosdb.ContainerSpec{ - ID: "c", PartitionKeyPath: "/pk", ComputedProperties: json.RawMessage(props), + ID: "c", PartitionKeyPath: "/pk", ComputedProperties: jsontext.Value(props), } if indexing != "" { - spec.IndexingPolicy = json.RawMessage(indexing) + spec.IndexingPolicy = jsontext.Value(indexing) } _, err = b.CreateContainer("d", spec) @@ -77,7 +79,7 @@ func TestComputedProperties_IndexSelection(t *testing.T) { name: "group by a computed property", indexing: defaultPolicy, query: `SELECT VALUE COUNT(1) FROM c GROUP BY c.cp_lower`, - want: []any{json.Number("1"), json.Number("1"), json.Number("1")}, + want: []any{jsonx.Number("1"), jsonx.Number("1"), jsonx.Number("1")}, }, { name: "select star leaves computed properties out", indexing: defaultPolicy, @@ -207,7 +209,7 @@ func TestComputedProperties_DefinitionRules(t *testing.T) { props = append(props, map[string]string{"name": fmt.Sprintf("p%d", i), "query": "SELECT VALUE 1 FROM c"}) } - raw, err := json.Marshal(props) + raw, err := json.Marshal(props, jsonx.V1()) require.NoError(t, err) s := newLiveServer(t) diff --git a/services/cosmosdb/computed_rules.go b/services/cosmosdb/computed_rules.go index d60e14b0ea..e39a932da9 100644 --- a/services/cosmosdb/computed_rules.go +++ b/services/cosmosdb/computed_rules.go @@ -1,7 +1,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" ) @@ -133,7 +133,7 @@ func (p indexingPolicy) isComputed(path string) bool { } // checkComputedIndexes rejects a spatial index on a computed property. -func checkComputedIndexes(pol indexingPolicy, raw json.RawMessage) error { +func checkComputedIndexes(pol indexingPolicy, raw jsontext.Value) error { props, err := parseComputedProperties(raw) if err != nil || len(props) == 0 { return err diff --git a/services/cosmosdb/conflicts.go b/services/cosmosdb/conflicts.go index 848c2c9c28..bd0c86ff7a 100644 --- a/services/cosmosdb/conflicts.go +++ b/services/cosmosdb/conflicts.go @@ -1,11 +1,14 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Conflict resolution modes (azcosmos ConflictResolutionMode) and the default last-writer-wins path. @@ -24,11 +27,11 @@ type conflictPolicy struct { Procedure string `json:"conflictResolutionProcedure"` } -func parseConflictPolicy(raw json.RawMessage) conflictPolicy { +func parseConflictPolicy(raw jsontext.Value) conflictPolicy { p := conflictPolicy{Mode: conflictModeLWW, Path: conflictPathTS} if len(raw) > 0 { - _ = json.Unmarshal(raw, &p) + _ = json.Unmarshal(raw, &p, jsonx.V1()) } if p.Mode == "" { @@ -76,7 +79,7 @@ func conflictValue(d *storedDocument, path string) float64 { } switch n := cur.(type) { - case json.Number: + case jsonx.Number: if f, err := n.Float64(); err == nil { return f } @@ -279,13 +282,13 @@ func (b *InMemoryBackend) resolveRegion(region string) string { // validateConflictPolicy checks a container's conflictResolutionPolicy: mode LastWriterWins or Custom, a path that // starts with /. -func validateConflictPolicy(raw json.RawMessage) error { +func validateConflictPolicy(raw jsontext.Value) error { if len(raw) == 0 || isJSONNull(raw) { return nil } var p conflictPolicy - if err := json.Unmarshal(raw, &p); err != nil { + if err := json.Unmarshal(raw, &p, jsonx.V1()); err != nil { return fmt.Errorf("%w: conflictResolutionPolicy is malformed", ErrInvalidContainerPolicy) } @@ -304,7 +307,7 @@ func validateConflictPolicy(raw json.RawMessage) error { // conflictPolicyChanged reports whether a replace request names a policy different from the stored one; the policy // can only be set at container creation (Learn, "Manage conflicts between regions"). -func conflictPolicyChanged(stored, requested json.RawMessage) bool { +func conflictPolicyChanged(stored, requested jsontext.Value) bool { return len(requested) > 0 && !isJSONNull(requested) && parseConflictPolicy(stored) != parseConflictPolicy(requested) } diff --git a/services/cosmosdb/container_ops.go b/services/cosmosdb/container_ops.go index b196eb69cc..aa7325ce77 100644 --- a/services/cosmosdb/container_ops.go +++ b/services/cosmosdb/container_ops.go @@ -1,7 +1,8 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // partitionKeyDefSpec is the "partitionKey" sub-object of a container definition: @@ -24,9 +26,9 @@ type containerBodyRequest struct { DefaultTTL *int `json:"defaultTtl"` ID string `json:"id"` PartitionKey partitionKeyDefSpec `json:"partitionKey"` - IndexingPolicy json.RawMessage `json:"indexingPolicy"` + IndexingPolicy jsontext.Value `json:"indexingPolicy"` - ConflictResolutionPolicy json.RawMessage `json:"conflictResolutionPolicy"` + ConflictResolutionPolicy jsontext.Value `json:"conflictResolutionPolicy"` ContainerPolicies } @@ -111,7 +113,7 @@ func (h *Handler) readContainerRequest(c *echo.Context) (containerBodyRequest, b return req, false } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { _ = h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") return req, false @@ -288,12 +290,12 @@ func resourceTS(modified time.Time) int64 { } // echoOrDefault returns raw, or def when raw is unset. -func echoOrDefault(raw json.RawMessage, def string) json.RawMessage { +func echoOrDefault(raw jsontext.Value, def string) jsontext.Value { if len(raw) > 0 { return raw } - return json.RawMessage(def) + return jsontext.Value(def) } // addPolicyFields echoes the container policies; unset unique-key and geospatial settings show their defaults. @@ -301,7 +303,7 @@ func addPolicyFields(body map[string]any, p ContainerPolicies) { body["uniqueKeyPolicy"] = echoOrDefault(p.UniqueKeyPolicy, defaultUniqueKeyPol) body["geospatialConfig"] = echoOrDefault(p.GeospatialConfig, defaultGeoConfig) - for key, raw := range map[string]json.RawMessage{ + for key, raw := range map[string]jsontext.Value{ "vectorEmbeddingPolicy": p.VectorEmbeddingPolicy, "fullTextPolicy": p.FullTextPolicy, "computedProperties": p.ComputedProperties, } { @@ -331,7 +333,7 @@ func containerBody(info ContainerInfo) map[string]any { kind = partitionKindMultiHash } - indexing := json.RawMessage(defaultIndexingPolicy) + indexing := jsontext.Value(defaultIndexingPolicy) if len(info.IndexingPolicy) > 0 { indexing = info.IndexingPolicy } @@ -357,7 +359,7 @@ func containerBody(info ContainerInfo) map[string]any { addPolicyFields(body, info.ContainerPolicies) - body["conflictResolutionPolicy"] = json.RawMessage(defaultConflictResolutionPolicy) + body["conflictResolutionPolicy"] = jsontext.Value(defaultConflictResolutionPolicy) if len(info.ConflictResolutionPolicy) > 0 { body["conflictResolutionPolicy"] = info.ConflictResolutionPolicy } diff --git a/services/cosmosdb/container_policy.go b/services/cosmosdb/container_policy.go index 299d4d190b..b27e0708e3 100644 --- a/services/cosmosdb/container_policy.go +++ b/services/cosmosdb/container_policy.go @@ -2,11 +2,14 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "reflect" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -22,11 +25,11 @@ const ( // ContainerPolicies are the optional container settings that are stored and echoed verbatim; the unique-key // policy is enforced on writes and computed properties are evaluated by queries. type ContainerPolicies struct { - UniqueKeyPolicy json.RawMessage `json:"uniqueKeyPolicy"` - GeospatialConfig json.RawMessage `json:"geospatialConfig"` - VectorEmbeddingPolicy json.RawMessage `json:"vectorEmbeddingPolicy"` - FullTextPolicy json.RawMessage `json:"fullTextPolicy"` - ComputedProperties json.RawMessage `json:"computedProperties"` + UniqueKeyPolicy jsontext.Value `json:"uniqueKeyPolicy"` + GeospatialConfig jsontext.Value `json:"geospatialConfig"` + VectorEmbeddingPolicy jsontext.Value `json:"vectorEmbeddingPolicy"` + FullTextPolicy jsontext.Value `json:"fullTextPolicy"` + ComputedProperties jsontext.Value `json:"computedProperties"` } type uniqueKeyPolicy struct { @@ -40,14 +43,14 @@ type computedProperty struct { Query string `json:"query"` } -func isJSONNull(raw json.RawMessage) bool { +func isJSONNull(raw jsontext.Value) bool { t := bytes.TrimSpace(raw) return len(t) == 0 || bytes.Equal(t, []byte(nullText)) } func (p ContainerPolicies) stored() ContainerPolicies { - for _, f := range []*json.RawMessage{ + for _, f := range []*jsontext.Value{ &p.UniqueKeyPolicy, &p.GeospatialConfig, &p.VectorEmbeddingPolicy, &p.FullTextPolicy, &p.ComputedProperties, } { if isJSONNull(*f) { @@ -81,13 +84,13 @@ func (p ContainerPolicies) validate() error { // validateSearchIndexes checks the indexing policy's vector and full-text indexes against the policies they // refer to. -func validateSearchIndexes(indexing json.RawMessage, p ContainerPolicies) error { +func validateSearchIndexes(indexing jsontext.Value, p ContainerPolicies) error { if len(indexing) == 0 { return nil } var pol indexingPolicy - if err := json.Unmarshal(indexing, &pol); err != nil { + if err := json.Unmarshal(indexing, &pol, jsonx.V1()); err != nil { return fmt.Errorf("%w: indexingPolicy is malformed", ErrInvalidContainerPolicy) } @@ -148,26 +151,27 @@ func (c *storedContainer) checkReplaceIndexes(spec ContainerSpec) error { } // sameJSON reports whether two raw JSON values are semantically equal. -func sameJSON(a, b json.RawMessage) bool { +func sameJSON(a, b jsontext.Value) bool { var va, vb any - return json.Unmarshal(a, &va) == nil && json.Unmarshal(b, &vb) == nil && reflect.DeepEqual(va, vb) + return json.Unmarshal(a, &va, jsonx.V1()) == nil && json.Unmarshal(b, &vb, jsonx.V1()) == nil && + reflect.DeepEqual(va, vb) } -func parseUniqueKeyPolicy(raw json.RawMessage) (uniqueKeyPolicy, error) { +func parseUniqueKeyPolicy(raw jsontext.Value) (uniqueKeyPolicy, error) { var pol uniqueKeyPolicy if isJSONNull(raw) { return pol, nil } - if err := json.Unmarshal(raw, &pol); err != nil { + if err := json.Unmarshal(raw, &pol, jsonx.V1()); err != nil { return pol, fmt.Errorf("%w: uniqueKeyPolicy is malformed", ErrInvalidContainerPolicy) } return pol, nil } -func validateUniqueKeyPolicy(raw json.RawMessage) error { +func validateUniqueKeyPolicy(raw jsontext.Value) error { pol, err := parseUniqueKeyPolicy(raw) if err != nil { return err @@ -192,7 +196,7 @@ func validateUniqueKeyPolicy(raw json.RawMessage) error { return nil } -func validateGeospatialConfig(raw json.RawMessage) error { +func validateGeospatialConfig(raw jsontext.Value) error { if isJSONNull(raw) { return nil } @@ -201,7 +205,12 @@ func validateGeospatialConfig(raw json.RawMessage) error { Type string `json:"type"` } - if err := json.Unmarshal(raw, &cfg); err != nil || (cfg.Type != geoTypeGeography && cfg.Type != geoTypeGeometry) { + if err := json.Unmarshal( + raw, + &cfg, + jsonx.V1(), + ); err != nil || + (cfg.Type != geoTypeGeography && cfg.Type != geoTypeGeometry) { return fmt.Errorf("%w: geospatialConfig.type must be %s or %s", ErrInvalidContainerPolicy, geoTypeGeography, geoTypeGeometry) } @@ -211,13 +220,13 @@ func validateGeospatialConfig(raw json.RawMessage) error { // parseComputedProperties decodes and validates computedProperties: each query must be // SELECT VALUE FROM with nothing else. -func parseComputedProperties(raw json.RawMessage) ([]computedProperty, error) { +func parseComputedProperties(raw jsontext.Value) ([]computedProperty, error) { if isJSONNull(raw) { return nil, nil } var props []computedProperty - if err := json.Unmarshal(raw, &props); err != nil { + if err := json.Unmarshal(raw, &props, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: computedProperties is malformed", ErrInvalidContainerPolicy) } @@ -273,7 +282,7 @@ func isBareSelectValue(stmt *sqlSelectStmt) bool { } // policiesEqualUnique reports whether two raw unique-key policies are semantically identical. -func policiesEqualUnique(a, b json.RawMessage) bool { +func policiesEqualUnique(a, b jsontext.Value) bool { pa, errA := parseUniqueKeyPolicy(a) pb, errB := parseUniqueKeyPolicy(b) @@ -309,7 +318,7 @@ func (c *storedContainer) applyPolicies(p ContainerPolicies, replacing bool) err c.UniqueKeyPolicy = p.UniqueKeyPolicy } - for _, f := range []struct{ dst, src *json.RawMessage }{ + for _, f := range []struct{ dst, src *jsontext.Value }{ {&c.GeospatialConfig, &p.GeospatialConfig}, {&c.VectorEmbeddingPolicy, &p.VectorEmbeddingPolicy}, {&c.FullTextPolicy, &p.FullTextPolicy}, @@ -324,7 +333,7 @@ func (c *storedContainer) applyPolicies(p ContainerPolicies, replacing bool) err } // policyChanged reports whether a replace request carries a setting different from the stored one. -func policyChanged(stored, requested json.RawMessage) bool { +func policyChanged(stored, requested jsontext.Value) bool { return requested != nil && !sameJSON(stored, requested) } diff --git a/services/cosmosdb/container_policy_test.go b/services/cosmosdb/container_policy_test.go index 2eb021bf59..58e9b79231 100644 --- a/services/cosmosdb/container_policy_test.go +++ b/services/cosmosdb/container_policy_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -357,7 +358,7 @@ func TestComputedProperties_UsableInQueries(t *testing.T) { func mustJSON(t *testing.T, v any) []byte { t.Helper() - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return out diff --git a/services/cosmosdb/database_ops.go b/services/cosmosdb/database_ops.go index 950b06c581..e6bd97a137 100644 --- a/services/cosmosdb/database_ops.go +++ b/services/cosmosdb/database_ops.go @@ -1,13 +1,14 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createDatabaseBody is the request body shape for POST /dbs. @@ -58,7 +59,7 @@ func (h *Handler) createDatabase(c *echo.Context) error { } var req createDatabaseBody - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } diff --git a/services/cosmosdb/document_ops.go b/services/cosmosdb/document_ops.go index d82601a695..6ec30ce5ef 100644 --- a/services/cosmosdb/document_ops.go +++ b/services/cosmosdb/document_ops.go @@ -2,7 +2,8 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -75,11 +77,10 @@ func partitionKeyFromHeader(r *http.Request) (string, error) { } func parsePartitionKeyHeader(raw string) (string, error) { - dec := json.NewDecoder(bytes.NewReader([]byte(raw))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(raw)), jsonx.V1()) var arr []any - if err := dec.Decode(&arr); err != nil { + if err := json.UnmarshalDecode(dec, &arr, jsonx.V1(), jsonx.UseNumber()); err != nil { return "", fmt.Errorf("%w: malformed %s header: %w", ErrInvalidDocument, headerPartitionKey, err) } @@ -106,7 +107,7 @@ func parsePartitionKeyHeader(raw string) (string, error) { return canonicalPartitionKeyJSON(arr[0]) } - data, err := json.Marshal(arr) + data, err := json.Marshal(arr, jsonx.V1()) if err != nil { return "", fmt.Errorf("cosmosdb: encode partition key: %w", err) } @@ -370,10 +371,15 @@ func (h *Handler) queryDocuments(c *echo.Context, dbID, collID string) error { var req queryRequestBody - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body), jsonx.V1()) - if decErr := dec.Decode(&req); decErr != nil || rejectTrailingJSON(dec) != nil { + if decErr := json.UnmarshalDecode( + dec, + &req, + jsonx.V1(), + jsonx.UseNumber(), + ); decErr != nil || + rejectTrailingJSON(dec) != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } diff --git a/services/cosmosdb/fulltext.go b/services/cosmosdb/fulltext.go index aa241c758c..24c3288529 100644 --- a/services/cosmosdb/fulltext.go +++ b/services/cosmosdb/fulltext.go @@ -1,12 +1,15 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -32,20 +35,20 @@ type fullTextPolicy struct { FullTextPaths []fullTextPath `json:"fullTextPaths"` } -func parseFullTextPolicy(raw json.RawMessage) (fullTextPolicy, error) { +func parseFullTextPolicy(raw jsontext.Value) (fullTextPolicy, error) { var pol fullTextPolicy if isJSONNull(raw) { return pol, nil } - if err := json.Unmarshal(raw, &pol); err != nil { + if err := json.Unmarshal(raw, &pol, jsonx.V1()); err != nil { return pol, fmt.Errorf("%w: fullTextPolicy is malformed", ErrInvalidContainerPolicy) } return pol, nil } -func validateFullTextPolicy(raw json.RawMessage) error { +func validateFullTextPolicy(raw jsontext.Value) error { pol, err := parseFullTextPolicy(raw) if err != nil { return err diff --git a/services/cosmosdb/fulltext_analysis_test.go b/services/cosmosdb/fulltext_analysis_test.go index d9ad640a26..ff6fa5a61c 100644 --- a/services/cosmosdb/fulltext_analysis_test.go +++ b/services/cosmosdb/fulltext_analysis_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "testing" @@ -21,10 +21,10 @@ func ftBackend(t *testing.T, lang string, texts ...string) *cosmosdb.InMemoryBac policy := fmt.Sprintf(`{"defaultLanguage":%q,"fullTextPaths":[{"path":"/text","language":%q}]}`, lang, lang) _, err = b.CreateContainer("d", cosmosdb.ContainerSpec{ ID: "c", PartitionKeyPath: "/pk", - IndexingPolicy: json.RawMessage( + IndexingPolicy: jsontext.Value( `{"indexingMode":"consistent","includedPaths":[{"path":"/*"}],"excludedPaths":[],` + `"fullTextIndexes":[{"path":"/text"}]}`), - FullTextPolicy: json.RawMessage(policy), + FullTextPolicy: jsontext.Value(policy), }) require.NoError(t, err) diff --git a/services/cosmosdb/handler.go b/services/cosmosdb/handler.go index 33d7407a26..adf55f58c0 100644 --- a/services/cosmosdb/handler.go +++ b/services/cosmosdb/handler.go @@ -4,7 +4,7 @@ import ( "context" "crypto/rand" "crypto/tls" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/devtls" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/odatatable" @@ -827,7 +828,7 @@ func (h *Handler) writeJSON(c *echo.Context, status int, v any) error { return c.Blob(status, "application/json", body) } -func jsonMarshal(v any) ([]byte, error) { return json.Marshal(v) } +func jsonMarshal(v any) ([]byte, error) { return json.Marshal(v, jsonx.V1()) } // cosmosErrorBody is Cosmos DB's JSON error envelope shape: // {"code":"NotFound","message":"..."}. @@ -846,7 +847,7 @@ func (h *Handler) writeError(c *echo.Context, status int, code, message string) // itself somehow failed to marshal, though it never does in practice since // it's built from plain strings). func (h *Handler) writeErrorNoRecurse(c *echo.Context, status int, code, message string) error { - body, _ := json.Marshal(cosmosErrorBody{Code: code, Message: message}) + body, _ := json.Marshal(cosmosErrorBody{Code: code, Message: message}, jsonx.V1()) return c.Blob(status, "application/json", body) } diff --git a/services/cosmosdb/handler_test.go b/services/cosmosdb/handler_test.go index e6237d9eda..841c6a8257 100644 --- a/services/cosmosdb/handler_test.go +++ b/services/cosmosdb/handler_test.go @@ -2,7 +2,7 @@ package cosmosdb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -54,7 +55,7 @@ func decodeBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -107,7 +108,7 @@ func TestHandler_DatabaseLifecycle(t *testing.T) { h := newTestHandler(t) - createBody, err := json.Marshal(map[string]string{"id": "mydb"}) + createBody, err := json.Marshal(map[string]string{"id": "mydb"}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs", nil, createBody) @@ -176,7 +177,7 @@ func TestHandler_CreateDatabase_InvalidInput(t *testing.T) { func createTestDatabase(t *testing.T, h *cosmosdb.Handler) { t.Helper() - body, err := json.Marshal(map[string]string{"id": "mydb"}) + body, err := json.Marshal(map[string]string{"id": "mydb"}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs", nil, body) @@ -189,7 +190,7 @@ func createTestContainer(t *testing.T, h *cosmosdb.Handler) { body, err := json.Marshal(map[string]any{ "id": "mycoll", "partitionKey": map[string]any{"paths": []string{"/pk"}, "kind": "Hash"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls", nil, body) @@ -205,7 +206,7 @@ func TestHandler_ContainerLifecycle(t *testing.T) { body, err := json.Marshal(map[string]any{ "id": "mycoll", "partitionKey": map[string]any{"paths": []string{"/pk"}, "kind": "Hash"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls", nil, body) @@ -255,7 +256,7 @@ func TestHandler_CreateContainer_InvalidPartitionKey(t *testing.T) { body, err := json.Marshal(map[string]any{ "id": "mycoll", "partitionKey": map[string]any{"paths": []string{"/a", "/b"}, "kind": "Hash"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls", nil, body) @@ -276,7 +277,7 @@ func TestHandler_CreateContainer_EmptyPartitionKeyPath(t *testing.T) { body, err := json.Marshal(map[string]any{ "id": "mycoll", "partitionKey": map[string]any{"paths": []string{""}, "kind": "Hash"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls", nil, body) @@ -309,7 +310,7 @@ func TestHandler_DocumentLifecycle(t *testing.T) { createTestDatabase(t, h) createTestContainer(t, h) - docBody, err := json.Marshal(map[string]any{"id": "doc1", "pk": "partA", "value": 42}) + docBody, err := json.Marshal(map[string]any{"id": "doc1", "pk": "partA", "value": 42}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls/mycoll/docs", nil, docBody) @@ -349,7 +350,7 @@ func TestHandler_DocumentLifecycle(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) // Replace with wrong If-Match -> 412. - replaceBody, err := json.Marshal(map[string]any{"pk": "partA", "value": 100}) + replaceBody, err := json.Marshal(map[string]any{"pk": "partA", "value": 100}, jsonx.V1()) require.NoError(t, err) wrongEtagHeaders := map[string]string{ @@ -436,7 +437,7 @@ func TestHandler_ReadFeed(t *testing.T) { createTestContainer(t, h) for _, id := range []string{"a", "b"} { - body, err := json.Marshal(map[string]any{"id": id, "pk": "x"}) + body, err := json.Marshal(map[string]any{"id": id, "pk": "x"}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls/mycoll/docs", nil, body) @@ -458,14 +459,14 @@ func TestHandler_Query(t *testing.T) { createTestContainer(t, h) for i, name := range []string{"alice", "bob"} { - body, err := json.Marshal(map[string]any{"id": name, "pk": "x", "n": i}) + body, err := json.Marshal(map[string]any{"id": name, "pk": "x", "n": i}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls/mycoll/docs", nil, body) require.Equal(t, http.StatusCreated, rec.Code) } - queryBody, err := json.Marshal(map[string]any{"query": "SELECT * FROM c WHERE c.id = 'alice'"}) + queryBody, err := json.Marshal(map[string]any{"query": "SELECT * FROM c WHERE c.id = 'alice'"}, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, http.MethodPost, "/dbs/mydb/colls/mycoll/docs", @@ -476,7 +477,7 @@ func TestHandler_Query(t *testing.T) { assert.InDelta(t, 1, result["_count"], 0) // A malformed query yields 400, never a panic. - badBody, err := json.Marshal(map[string]any{"query": "NOT VALID SQL AT ALL ((("}) + badBody, err := json.Marshal(map[string]any{"query": "NOT VALID SQL AT ALL ((("}, jsonx.V1()) require.NoError(t, err) rec = doRequest(t, h, http.MethodPost, "/dbs/mydb/colls/mycoll/docs", diff --git a/services/cosmosdb/helpers_test.go b/services/cosmosdb/helpers_test.go index 36e43d88b6..d4a6c310ef 100644 --- a/services/cosmosdb/helpers_test.go +++ b/services/cosmosdb/helpers_test.go @@ -2,13 +2,16 @@ package cosmosdb_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // newEchoContextForRequest wraps req in an *echo.Context for tests that call @@ -32,12 +35,11 @@ func newEchoContextForRequest(t *testing.T, req *http.Request) *echo.Context { func decodeJSONBody(t *testing.T, raw string) map[string]any { t.Helper() - dec := json.NewDecoder(bytes.NewReader([]byte(raw))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(raw))) var m map[string]any - require.NoError(t, dec.Decode(&m)) + require.NoError(t, json.UnmarshalDecode(dec, &m, jsonx.V1(), jsonx.UseNumber())) return m } diff --git a/services/cosmosdb/indexing.go b/services/cosmosdb/indexing.go index 66e034d22a..ace0946244 100644 --- a/services/cosmosdb/indexing.go +++ b/services/cosmosdb/indexing.go @@ -1,9 +1,12 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -48,14 +51,14 @@ type indexingPolicy struct { } // parseIndexingPolicy decodes the stored policy; an unset or undecodable one yields the default (index all). -func parseIndexingPolicy(raw json.RawMessage) indexingPolicy { +func parseIndexingPolicy(raw jsontext.Value) indexingPolicy { if len(raw) == 0 { - raw = json.RawMessage(defaultIndexingPolicy) + raw = jsontext.Value(defaultIndexingPolicy) } var pol indexingPolicy - if err := json.Unmarshal(raw, &pol); err != nil { - _ = json.Unmarshal([]byte(defaultIndexingPolicy), &pol) + if err := json.Unmarshal(raw, &pol, jsonx.V1()); err != nil { + _ = json.Unmarshal([]byte(defaultIndexingPolicy), &pol, jsonx.V1()) } return pol @@ -64,7 +67,7 @@ func parseIndexingPolicy(raw json.RawMessage) indexingPolicy { // checkQueryIndexing applies the indexing policy to stmt: multi-property ORDER BY needs a composite index, and a // query whose filter cannot use the index needs the scan switch. func checkQueryIndexing( - stmt *sqlSelectStmt, raw json.RawMessage, opts QueryOptions, computed map[string]sqlExpr, + stmt *sqlSelectStmt, raw jsontext.Value, opts QueryOptions, computed map[string]sqlExpr, ) error { pol := parseIndexingPolicy(raw) pol.computed = make(map[string]struct{}, len(computed)) diff --git a/services/cosmosdb/live_server_test.go b/services/cosmosdb/live_server_test.go index 056b26c1a9..23c5be7917 100644 --- a/services/cosmosdb/live_server_test.go +++ b/services/cosmosdb/live_server_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -35,7 +36,7 @@ func (r rawResponse) object(t *testing.T) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(r.body, &m), string(r.body)) + require.NoError(t, json.Unmarshal(r.body, &m, jsonx.V1()), string(r.body)) return m } @@ -134,13 +135,13 @@ func stripSystem[T ~string | ~[]byte](t *testing.T, raw T) string { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(raw), &m)) + require.NoError(t, json.Unmarshal([]byte(raw), &m, jsonx.V1())) for _, k := range []string{"_rid", "_self", "_etag", "_ts", "_attachments", "_lsn"} { delete(m, k) } - out, err := json.Marshal(m) + out, err := json.Marshal(m, jsonx.V1()) require.NoError(t, err) return string(out) diff --git a/services/cosmosdb/models.go b/services/cosmosdb/models.go index 0650f84281..dd5a37f60c 100644 --- a/services/cosmosdb/models.go +++ b/services/cosmosdb/models.go @@ -4,7 +4,8 @@ import ( "bytes" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -12,6 +13,8 @@ import ( "strconv" "sync/atomic" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // System property names auto-populated on every Cosmos resource. Named @@ -108,9 +111,9 @@ type ContainerSpec struct { ID string PartitionKeyPath string PartitionKeyPaths []string - IndexingPolicy json.RawMessage + IndexingPolicy jsontext.Value - ConflictResolutionPolicy json.RawMessage + ConflictResolutionPolicy jsontext.Value ContainerPolicies } @@ -122,10 +125,10 @@ type ContainerInfo struct { RID string PartitionKeyPath string PartitionKeyPaths []string - IndexingPolicy json.RawMessage + IndexingPolicy jsontext.Value Modified time.Time - ConflictResolutionPolicy json.RawMessage + ConflictResolutionPolicy jsontext.Value ContainerPolicies } @@ -168,16 +171,16 @@ type storedContainer struct { Sprocs map[string]*storedScript `json:"Sprocs,omitempty"` PartitionKeyPath string ID string - GeospatialConfig json.RawMessage `json:"GeospatialConfig,omitempty"` - UniqueKeyPolicy json.RawMessage `json:"UniqueKeyPolicy,omitempty"` - ConflictResolutionPolicy json.RawMessage `json:"ConflictResolutionPolicy,omitempty"` + GeospatialConfig jsontext.Value `json:"GeospatialConfig,omitempty"` + UniqueKeyPolicy jsontext.Value `json:"UniqueKeyPolicy,omitempty"` + ConflictResolutionPolicy jsontext.Value `json:"ConflictResolutionPolicy,omitempty"` Conflicts []*conflictRecord `json:"Conflicts,omitempty"` PartitionKeyPaths []string `json:"PartitionKeyPaths,omitempty"` - VectorEmbeddingPolicy json.RawMessage `json:"VectorEmbeddingPolicy,omitempty"` - FullTextPolicy json.RawMessage `json:"FullTextPolicy,omitempty"` - ComputedProperties json.RawMessage `json:"ComputedProperties,omitempty"` + VectorEmbeddingPolicy jsontext.Value `json:"VectorEmbeddingPolicy,omitempty"` + FullTextPolicy jsontext.Value `json:"FullTextPolicy,omitempty"` + ComputedProperties jsontext.Value `json:"ComputedProperties,omitempty"` ChangeLog []*changeRecord `json:"ChangeLog,omitempty"` - IndexingPolicy json.RawMessage `json:"IndexingPolicy,omitempty"` + IndexingPolicy jsontext.Value `json:"IndexingPolicy,omitempty"` keep time.Duration ChangeFloor int64 `json:"ChangeFloor,omitempty"` ChangeSeq int64 `json:"ChangeSeq,omitempty"` @@ -203,18 +206,18 @@ type storedDocument struct { // snapshot/restore cycle -- exactly the bug class AZURE.md's process rules // call out. type storedDocumentWire struct { - Timestamp time.Time `json:"Timestamp"` - ID string `json:"ID"` - PartitionKeyJSON string `json:"PartitionKeyJSON"` - Origin string `json:"Origin,omitempty"` - Body json.RawMessage `json:"Body"` - Seq int64 `json:"Seq,omitempty"` - GLSN int64 `json:"GLSN,omitempty"` + Timestamp time.Time `json:"Timestamp"` + ID string `json:"ID"` + PartitionKeyJSON string `json:"PartitionKeyJSON"` + Origin string `json:"Origin,omitempty"` + Body jsontext.Value `json:"Body"` + Seq int64 `json:"Seq,omitempty"` + GLSN int64 `json:"GLSN,omitempty"` } // MarshalJSON implements json.Marshaler for persistence snapshots. func (d *storedDocument) MarshalJSON() ([]byte, error) { - bodyBytes, err := json.Marshal(d.Body) + bodyBytes, err := json.Marshal(d.Body, jsonx.V1()) if err != nil { return nil, fmt.Errorf("cosmosdb: marshal stored document body: %w", err) } @@ -222,7 +225,7 @@ func (d *storedDocument) MarshalJSON() ([]byte, error) { return json.Marshal(storedDocumentWire{ Body: bodyBytes, Timestamp: d.Timestamp, ID: d.ID, PartitionKeyJSON: d.PartitionKeyJSON, Seq: d.Seq, GLSN: d.GLSN, Origin: d.Origin, - }) + }, jsonx.V1()) } // UnmarshalJSON implements json.Unmarshaler for persistence snapshots. See @@ -230,7 +233,7 @@ func (d *storedDocument) MarshalJSON() ([]byte, error) { func (d *storedDocument) UnmarshalJSON(data []byte) error { var wire storedDocumentWire - if err := json.Unmarshal(data, &wire); err != nil { + if err := json.Unmarshal(data, &wire, jsonx.V1()); err != nil { return fmt.Errorf("cosmosdb: unmarshal stored document: %w", err) } @@ -247,11 +250,10 @@ func (d *storedDocument) UnmarshalJSON(data []byte) error { return fmt.Errorf("%w: id %q", ErrSnapshotDocumentNullBody, wire.ID) } - dec := json.NewDecoder(bytes.NewReader(wire.Body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(wire.Body)) var body map[string]any - if err := dec.Decode(&body); err != nil { + if err := json.UnmarshalDecode(dec, &body, jsonx.V1(), jsonx.UseNumber()); err != nil { return fmt.Errorf("cosmosdb: unmarshal stored document body: %w", err) } @@ -282,7 +284,7 @@ type documentCompositeKey struct { // rather than delimiter-joined, for the same collision-avoidance reason // documented above and on services/azuretable's identical MarshalText. func (k documentCompositeKey) MarshalText() ([]byte, error) { - return json.Marshal([2]string{k.PartitionKeyJSON, k.ID}) + return json.Marshal([2]string{k.PartitionKeyJSON, k.ID}, jsonx.V1()) } // UnmarshalText implements encoding.TextUnmarshaler, the inverse of @@ -290,7 +292,7 @@ func (k documentCompositeKey) MarshalText() ([]byte, error) { func (k *documentCompositeKey) UnmarshalText(text []byte) error { var pair [2]string - if err := json.Unmarshal(text, &pair); err != nil { + if err := json.Unmarshal(text, &pair, jsonx.V1()); err != nil { return fmt.Errorf("cosmosdb: malformed document composite key %q: %w", text, err) } @@ -318,7 +320,7 @@ func (k *documentCompositeKey) UnmarshalText(text []byte) error { // data never intended to be a key at all. func canonicalPartitionKeyJSON(v any) (string, error) { switch v.(type) { - case nil, string, bool, json.Number, float64, float32, int, int32, int64: + case nil, string, bool, jsonx.Number, float64, float32, int, int32, int64: default: return "", fmt.Errorf( "%w: partition key value must be a scalar (string, number, bool, or null), got %T", @@ -326,7 +328,7 @@ func canonicalPartitionKeyJSON(v any) (string, error) { ) } - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return "", fmt.Errorf("cosmosdb: encode partition key value: %w", err) } @@ -342,11 +344,10 @@ func canonicalPartitionKeyJSON(v any) (string, error) { // them. json.Number round-trips back out through json.Marshal as the exact // original digit sequence. func decodeJSONObject(body []byte) (map[string]any, error) { - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body), jsonx.V1()) var m map[string]any - if err := dec.Decode(&m); err != nil { + if err := json.UnmarshalDecode(dec, &m, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fmt.Errorf("%w: %w", ErrInvalidDocument, err) } @@ -371,9 +372,9 @@ func decodeJSONObject(body []byte) (map[string]any, error) { // *current* enclosing structure -- there isn't one here. Decoding a second // value and requiring io.EOF instead makes the JSON scanner itself validate // what remains, catching those unmatched-delimiter cases too. -func rejectTrailingJSON(dec *json.Decoder) error { +func rejectTrailingJSON(dec *jsontext.Decoder) error { var extra any - if err := dec.Decode(&extra); !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode(dec, &extra, jsonx.V1(), jsonx.UseNumber()); !errors.Is(err, io.EOF) { if err == nil { return ErrUnexpectedTrailingJSON } @@ -393,16 +394,15 @@ func rejectTrailingJSON(dec *json.Decoder) error { // recursion, since it must handle arbitrarily nested maps/slices/scalars // uniformly and preserve json.Number fidelity throughout. func deepCopyJSONValue(v any) (any, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, fmt.Errorf("cosmosdb: deep copy: marshal: %w", err) } - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(data)) var out any - if decodeErr := dec.Decode(&out); decodeErr != nil { + if decodeErr := json.UnmarshalDecode(dec, &out, jsonx.V1(), jsonx.UseNumber()); decodeErr != nil { return nil, fmt.Errorf("cosmosdb: deep copy: unmarshal: %w", decodeErr) } @@ -464,7 +464,7 @@ func documentAsMap(info DocumentInfo) map[string]any { // walk; anything else takes the JSON round-trip so results stay identical. func copyStoredValue(v any) any { switch t := v.(type) { - case nil, string, bool, json.Number: + case nil, string, bool, jsonx.Number: return t case map[string]any: out := make(map[string]any, len(t)) diff --git a/services/cosmosdb/offer_ops.go b/services/cosmosdb/offer_ops.go index 5032d3b538..d2b9221e1c 100644 --- a/services/cosmosdb/offer_ops.go +++ b/services/cosmosdb/offer_ops.go @@ -1,7 +1,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -79,7 +80,7 @@ func specFromHeaders(r *http.Request) (ThroughputSpec, bool, error) { } var raw autopilotRaw - if jsonErr := json.Unmarshal([]byte(auto), &raw); jsonErr != nil { + if jsonErr := json.Unmarshal([]byte(auto), &raw, jsonx.V1()); jsonErr != nil { return ThroughputSpec{}, true, fmt.Errorf("%w: %w", ErrInvalidThroughput, jsonErr) } @@ -232,7 +233,7 @@ func (h *Handler) replaceOffer(c *echo.Context, tb ThroughputBackend, rid string } var wire offerWire - if jsonErr := json.Unmarshal(body, &wire); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &wire, jsonx.V1()); jsonErr != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } diff --git a/services/cosmosdb/pagination_test.go b/services/cosmosdb/pagination_test.go index 77c20ff74e..4e855e1efe 100644 --- a/services/cosmosdb/pagination_test.go +++ b/services/cosmosdb/pagination_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // pageIDs walks every page of a feed, returning each page's ids and asserting the continuation protocol. @@ -149,7 +151,7 @@ func TestPagination_Feeds(t *testing.T) { rec := doRequest(t, h, method, tt.path, headers, body) var decoded map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &decoded) + _ = json.Unmarshal(rec.Body.Bytes(), &decoded, jsonx.V1()) return rec.Code, decoded, rec.Header() } @@ -221,7 +223,7 @@ func TestPagination_QueryContinuationIsStateless(t *testing.T) { var body struct { Documents []string `json:"Documents"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) return append(body.Documents, "next="+rec.Header().Get("X-Ms-Continuation")) } diff --git a/services/cosmosdb/partition_epk.go b/services/cosmosdb/partition_epk.go index 287ed577d3..0324af6dd4 100644 --- a/services/cosmosdb/partition_epk.go +++ b/services/cosmosdb/partition_epk.go @@ -3,10 +3,13 @@ package cosmosdb import ( "bytes" "encoding/binary" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "math/big" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Effective partition key hashing for partition key version 2. Ported from the hashing azcosmos v1.5.0 uses to @@ -157,7 +160,7 @@ func appendEPKComponent(buf []byte, v any) []byte { } return append(buf, epkComponentFalse) - case json.Number: + case jsonx.Number: f, _ := x.Float64() return appendEPKNumber(buf, f) @@ -193,11 +196,10 @@ func epkOfValues(vals []any) u128 { // epkHash is the routing hash of a canonical partition key: a scalar hashes as a whole; a hierarchical key (a JSON // array) routes by its first component, whose hash opens its effective partition key. func epkHash(pkJSON string) u128 { - dec := json.NewDecoder(bytes.NewReader([]byte(pkJSON))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(pkJSON))) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return epkOfValues([]any{pkJSON}) } diff --git a/services/cosmosdb/partitionkey.go b/services/cosmosdb/partitionkey.go index 488b153d90..04d2846c04 100644 --- a/services/cosmosdb/partitionkey.go +++ b/services/cosmosdb/partitionkey.go @@ -1,9 +1,12 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxPartitionKeyPaths is the hierarchical (MultiHash) partition key depth limit. @@ -66,7 +69,7 @@ func partitionKeyForBody(body map[string]any, paths []string) (string, error) { vals[i] = v } - data, err := json.Marshal(vals) + data, err := json.Marshal(vals, jsonx.V1()) if err != nil { return "", fmt.Errorf("cosmosdb: encode partition key: %w", err) } @@ -90,8 +93,8 @@ func partitionKeyArity(pkJSON string) int { return 1 } - var arr []json.RawMessage - if err := json.Unmarshal([]byte(pkJSON), &arr); err != nil { + var arr []jsontext.Value + if err := json.Unmarshal([]byte(pkJSON), &arr, jsonx.V1()); err != nil { return 0 } diff --git a/services/cosmosdb/patch.go b/services/cosmosdb/patch.go index e7bcd282e8..4f81e3afde 100644 --- a/services/cosmosdb/patch.go +++ b/services/cosmosdb/patch.go @@ -2,11 +2,14 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxPatchOperations is the Cosmos limit on operations in one patch request. @@ -24,10 +27,10 @@ const ( ) type patchOp struct { - Op string `json:"op"` - Path string `json:"path"` - From string `json:"from,omitempty"` - Value json.RawMessage `json:"value,omitempty"` + Op string `json:"op"` + Path string `json:"path"` + From string `json:"from,omitempty"` + Value jsontext.Value `json:"value,omitempty"` } type patchRequest struct { @@ -43,8 +46,8 @@ func invalidPatchf(format string, args ...any) error { func parsePatchRequest(raw []byte) (patchRequest, error) { var req patchRequest - dec := json.NewDecoder(bytes.NewReader(raw)) - if err := dec.Decode(&req); err != nil || rejectTrailingJSON(dec) != nil { + dec := jsontext.NewDecoder(bytes.NewReader(raw), jsonx.V1()) + if err := json.UnmarshalDecode(dec, &req, jsonx.V1()); err != nil || rejectTrailingJSON(dec) != nil { return patchRequest{}, invalidPatchf("the patch body is not valid JSON") } @@ -80,16 +83,15 @@ func patchPath(path string) ([]string, error) { return segs, nil } -func decodePatchValue(raw json.RawMessage) (any, error) { +func decodePatchValue(raw jsontext.Value) (any, error) { if len(raw) == 0 { return nil, invalidPatchf("the operation requires a value") } - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, invalidPatchf("invalid value: %v", err) } @@ -342,14 +344,14 @@ func incrValue(cur any, exists bool, delta any) (any, error) { return addNumbers(c, d) } -func addNumbers(a, b json.Number) (json.Number, error) { +func addNumbers(a, b jsonx.Number) (jsonx.Number, error) { x, errX := a.Int64() y, errY := b.Int64() if errX == nil && errY == nil { sum := x + y if (x >= 0) != (y >= 0) || (sum >= 0) == (x >= 0) { - return json.Number(strconv.FormatInt(sum, 10)), nil + return jsonx.Number(strconv.FormatInt(sum, 10)), nil } } @@ -360,7 +362,7 @@ func addNumbers(a, b json.Number) (json.Number, error) { return "", invalidPatchf("incr result is not a finite number") } - return json.Number(strconv.FormatFloat(fx+fy, 'g', -1, 64)), nil + return jsonx.Number(strconv.FormatFloat(fx+fy, 'g', -1, 64)), nil } // evalPatchCondition runs a "from c where ..." predicate against one document. diff --git a/services/cosmosdb/permission_ops.go b/services/cosmosdb/permission_ops.go index e53e86398c..0c760927fd 100644 --- a/services/cosmosdb/permission_ops.go +++ b/services/cosmosdb/permission_ops.go @@ -1,7 +1,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "time" @@ -10,10 +10,10 @@ import ( // permissionWire is the request body of a permission create or replace. type permissionWire struct { - ID string `json:"id"` - Mode string `json:"permissionMode"` - Resource string `json:"resource"` - PartitionKey json.RawMessage `json:"resourcePartitionKey"` + ID string `json:"id"` + Mode string `json:"permissionMode"` + Resource string `json:"resource"` + PartitionKey jsontext.Value `json:"resourcePartitionKey"` } func (h *Handler) handlePermissions(c *echo.Context, dbID, userID string) error { diff --git a/services/cosmosdb/persistence.go b/services/cosmosdb/persistence.go index 749e1ee803..fa7f3d36d3 100644 --- a/services/cosmosdb/persistence.go +++ b/services/cosmosdb/persistence.go @@ -2,7 +2,7 @@ package cosmosdb import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" @@ -21,7 +21,7 @@ const cosmosdbSnapshotVersion = 1 type backendSnapshot struct { Databases map[string]*storedDatabase `json:"databases"` Regions *AccountRegions `json:"regions,omitempty"` - TableAPI json.RawMessage `json:"tableApi,omitempty"` + TableAPI jsontext.Value `json:"tableApi,omitempty"` Version int `json:"version"` } @@ -107,7 +107,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { } // restoreTableAPI restores the attached Table API state; a snapshot without it empties the Table API. -func (b *InMemoryBackend) restoreTableAPI(ctx context.Context, data json.RawMessage) error { +func (b *InMemoryBackend) restoreTableAPI(ctx context.Context, data jsontext.Value) error { if b.tableAPI == nil { return nil } diff --git a/services/cosmosdb/persistence_test.go b/services/cosmosdb/persistence_test.go index 4d86e4cdf1..91505a1b6f 100644 --- a/services/cosmosdb/persistence_test.go +++ b/services/cosmosdb/persistence_test.go @@ -1,12 +1,12 @@ package cosmosdb_test import ( - "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -77,7 +77,7 @@ func TestBackend_SnapshotRestore_Int64PrecisionRoundTrip(t *testing.T) { info, getErr := b2.GetDocument("mydb", "mycoll", pk, tt.name) require.NoError(t, getErr, tt.name) - gotNum, ok := info.Body["big"].(json.Number) + gotNum, ok := info.Body["big"].(jsonx.Number) require.True(t, ok, tt.name) assert.Equal(t, tt.raw, gotNum.String(), tt.name) } diff --git a/services/cosmosdb/query_resources.go b/services/cosmosdb/query_resources.go index 85142c311c..baa2654fc4 100644 --- a/services/cosmosdb/query_resources.go +++ b/services/cosmosdb/query_resources.go @@ -2,12 +2,14 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // queryResources runs the SQL query in the request body over resource bodies (databases or containers), as @@ -25,10 +27,15 @@ func (h *Handler) queryResources(c *echo.Context, listKey string, bodies []map[s var req queryRequestBody - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw), jsonx.V1()) - if decErr := dec.Decode(&req); decErr != nil || rejectTrailingJSON(dec) != nil { + if decErr := json.UnmarshalDecode( + dec, + &req, + jsonx.V1(), + jsonx.UseNumber(), + ); decErr != nil || + rejectTrailingJSON(dec) != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } diff --git a/services/cosmosdb/query_rows.go b/services/cosmosdb/query_rows.go index cf294c6b9b..40b5cfa9eb 100644 --- a/services/cosmosdb/query_rows.go +++ b/services/cosmosdb/query_rows.go @@ -1,9 +1,11 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" "sort" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxParsedQueries bounds the parsed-statement cache. @@ -32,7 +34,7 @@ func (r sqlRow) lookup(seg string) (any, bool) { case "id": return r.doc.ID, true case sysPropTS: - return json.Number(strconv.FormatInt(r.doc.Timestamp.Unix(), 10)), true + return jsonx.Number(strconv.FormatInt(r.doc.Timestamp.Unix(), 10)), true case sysPropETag: return r.src.b.etagFunc(r.doc.Timestamp), true case sysPropAttachments: @@ -56,7 +58,7 @@ func (r sqlRow) lookup(seg string) (any, bool) { v, ok := r.m[seg] if i, isInt := v.(int64); isInt { - return json.Number(strconv.FormatInt(i, 10)), true + return jsonx.Number(strconv.FormatInt(i, 10)), true } return v, ok @@ -221,7 +223,7 @@ func (b *InMemoryBackend) queryLocked( // loadedCharge sums the read cost of the documents the query had to retrieve: those its filter kept when the // indexing policy can serve the filter, every examined document otherwise (or when there is no filter). -func loadedCharge(stmt *sqlSelectStmt, indexing json.RawMessage, res QueryResult) float64 { +func loadedCharge(stmt *sqlSelectStmt, indexing jsontext.Value, res QueryResult) float64 { docs := res.Matched if stmt.where == nil || parseIndexingPolicy(indexing).needsScan(stmt.where) { docs = res.Visited diff --git a/services/cosmosdb/region_http.go b/services/cosmosdb/region_http.go index 969094bded..dd1d4683fe 100644 --- a/services/cosmosdb/region_http.go +++ b/services/cosmosdb/region_http.go @@ -3,7 +3,7 @@ package cosmosdb import ( "context" "crypto/tls" - "encoding/json" + "encoding/json/v2" "fmt" "net" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/telemetry" ) @@ -398,7 +399,7 @@ func (h *Handler) putAdminTopology(c *echo.Context) error { } var req adminTopology - if jsonErr := json.Unmarshal(raw, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(raw, &req, jsonx.V1()); jsonErr != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } diff --git a/services/cosmosdb/regions_conflicts_test.go b/services/cosmosdb/regions_conflicts_test.go index f3d3503624..6f074dc0bc 100644 --- a/services/cosmosdb/regions_conflicts_test.go +++ b/services/cosmosdb/regions_conflicts_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -127,7 +128,7 @@ func jsonRank(t *testing.T, doc string) float64 { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(doc), &m)) + require.NoError(t, json.Unmarshal([]byte(doc), &m, jsonx.V1())) r, _ := m["rank"].(float64) diff --git a/services/cosmosdb/script_engine.go b/services/cosmosdb/script_engine.go index 3ba73a7a62..c3a7a8a2f6 100644 --- a/services/cosmosdb/script_engine.go +++ b/services/cosmosdb/script_engine.go @@ -1,7 +1,6 @@ package cosmosdb import ( - "encoding/json" "errors" "fmt" "math" @@ -10,6 +9,7 @@ import ( "github.com/dop251/goja" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/jsruntime" ) @@ -90,7 +90,7 @@ func toJS(vm *goja.Runtime, v any) goja.Value { return goja.Null() case undef: return goja.Undefined() - case json.Number: + case jsonx.Number: return numberToJS(vm, t) case map[string]any: o := vm.NewObject() @@ -111,7 +111,7 @@ func toJS(vm *goja.Runtime, v any) goja.Value { } } -func numberToJS(vm *goja.Runtime, n json.Number) goja.Value { +func numberToJS(vm *goja.Runtime, n jsonx.Number) goja.Value { if i, err := n.Int64(); err == nil { return vm.ToValue(i) } @@ -137,15 +137,15 @@ func fromJS(v goja.Value) any { func normalizeExport(v any) any { switch t := v.(type) { case int64: - return json.Number(strconv.FormatInt(t, 10)) + return jsonx.Number(strconv.FormatInt(t, 10)) case int: - return json.Number(strconv.Itoa(t)) + return jsonx.Number(strconv.Itoa(t)) case float64: if math.IsNaN(t) || math.IsInf(t, 0) { return nil } - return json.Number(strconv.FormatFloat(t, 'g', -1, 64)) + return jsonx.Number(strconv.FormatFloat(t, 'g', -1, 64)) case map[string]any: out := make(map[string]any, len(t)) for k, e := range t { diff --git a/services/cosmosdb/script_ops.go b/services/cosmosdb/script_ops.go index 06d18cb2d6..1a56c9b39e 100644 --- a/services/cosmosdb/script_ops.go +++ b/services/cosmosdb/script_ops.go @@ -2,7 +2,8 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -224,7 +226,7 @@ func (h *Handler) writeScript( } var req scriptBody - if jsonErr := json.Unmarshal(raw, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(raw, &req, jsonx.V1()); jsonErr != nil { return h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") } @@ -356,10 +358,15 @@ func sprocArgs(raw []byte) ([]any, error) { var args []any - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw), jsonx.V1()) - if err := dec.Decode(&args); err != nil || rejectTrailingJSON(dec) != nil { + if err := json.UnmarshalDecode( + dec, + &args, + jsonx.V1(), + jsonx.UseNumber(), + ); err != nil || + rejectTrailingJSON(dec) != nil { return nil, ErrInvalidDocument } diff --git a/services/cosmosdb/scripts_test.go b/services/cosmosdb/scripts_test.go index 1264a03bf8..485ec9c77c 100644 --- a/services/cosmosdb/scripts_test.go +++ b/services/cosmosdb/scripts_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -22,7 +23,7 @@ const pkA = `["a"]` func scriptJSON(t *testing.T, fields map[string]string) string { t.Helper() - raw, err := json.Marshal(fields) + raw, err := json.Marshal(fields, jsonx.V1()) require.NoError(t, err) return string(raw) @@ -562,7 +563,7 @@ func TestUDF_InQueries(t *testing.T) { s.putScript("udfs", "boom", `function boom(){ throw new Error("x"); }`, nil).status, ) - body, err := json.Marshal(map[string]any{"query": tt.query}) + body, err := json.Marshal(map[string]any{"query": tt.query}, jsonx.V1()) require.NoError(t, err) resp := s.do(http.MethodPost, "/dbs/d/colls/c/docs", map[string]string{ @@ -577,7 +578,7 @@ func TestUDF_InQueries(t *testing.T) { require.Equal(t, want, resp.status, string(resp.body)) if tt.want != "" { - docs, marshalErr := json.Marshal(resp.object(t)["Documents"]) + docs, marshalErr := json.Marshal(resp.object(t)["Documents"], jsonx.V1()) require.NoError(t, marshalErr) assert.JSONEq(t, tt.want, string(docs)) } diff --git a/services/cosmosdb/sdk_test.go b/services/cosmosdb/sdk_test.go index 9a85b0b09a..afffce5e87 100644 --- a/services/cosmosdb/sdk_test.go +++ b/services/cosmosdb/sdk_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -132,7 +133,7 @@ func TestSDK_QueriesPagingTTLAndHierarchicalKeys(t *testing.T) { body, mErr := json.Marshal(map[string]any{ "id": fmt.Sprintf("i%d", i), "tenant": tenant, "user": "u", "n": i, "tags": []string{"x", strconv.Itoa(i)}, - }) + }, jsonx.V1()) require.NoError(t, mErr) _, err = c.CreateItem(ctx, azcosmos.NewPartitionKeyString(tenant).AppendString("u"), body, nil) diff --git a/services/cosmosdb/search_funcs_test.go b/services/cosmosdb/search_funcs_test.go index eee0f0b6e3..f447a35b75 100644 --- a/services/cosmosdb/search_funcs_test.go +++ b/services/cosmosdb/search_funcs_test.go @@ -1,12 +1,13 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -98,7 +99,7 @@ func TestSearchFunctions_ParseErrors(t *testing.T) { func jsonString(t *testing.T, v any) string { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/cosmosdb/search_sdk_test.go b/services/cosmosdb/search_sdk_test.go index ff4bd41892..f61a6d3313 100644 --- a/services/cosmosdb/search_sdk_test.go +++ b/services/cosmosdb/search_sdk_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -66,7 +67,7 @@ func seedSearchContainer(t *testing.T, props azcosmos.ContainerProperties) *azco } for _, d := range docs { - body, mErr := json.Marshal(d) + body, mErr := json.Marshal(d, jsonx.V1()) require.NoError(t, mErr) _, err = c.CreateItem(ctx, azcosmos.NewPartitionKeyString("p"), body, nil) @@ -94,7 +95,7 @@ func queryIDs(t *testing.T, c *azcosmos.ContainerClient, query string) ([]string ID string `json:"id"` } - require.NoError(t, json.Unmarshal(item, &v)) + require.NoError(t, json.Unmarshal(item, &v, jsonx.V1())) ids = append(ids, v.ID) } diff --git a/services/cosmosdb/spatial_index.go b/services/cosmosdb/spatial_index.go index f8f0008ca6..1a6a282bae 100644 --- a/services/cosmosdb/spatial_index.go +++ b/services/cosmosdb/spatial_index.go @@ -1,10 +1,13 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Spatial index types (azcosmos SpatialType, azcosmos v1.5.0 spatial_type.go; Learn "Indexing policies"). @@ -30,12 +33,12 @@ func (b boundingBox) valid() bool { } // geospatialType is the container's geospatial data type; Geography unless the config says Geometry. -func geospatialType(raw json.RawMessage) string { +func geospatialType(raw jsontext.Value) string { var cfg struct { Type string `json:"type"` } - if json.Unmarshal(raw, &cfg) == nil && cfg.Type == geoTypeGeometry { + if json.Unmarshal(raw, &cfg, jsonx.V1()) == nil && cfg.Type == geoTypeGeometry { return geoTypeGeometry } diff --git a/services/cosmosdb/sql_agg.go b/services/cosmosdb/sql_agg.go index 63f0bc35d8..e0d3af152c 100644 --- a/services/cosmosdb/sql_agg.go +++ b/services/cosmosdb/sql_agg.go @@ -1,9 +1,10 @@ package cosmosdb import ( - "encoding/json" "math" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -52,7 +53,7 @@ func (a *aggAcc) add(v any) { } } -func (a *aggAcc) addNumber(n json.Number) { +func (a *aggAcc) addNumber(n jsonx.Number) { a.numCount++ a.sumFloat += numFloat(n) @@ -101,7 +102,7 @@ func (a *aggAcc) result() any { case a.floatSum: return floatResult(a.sumFloat) default: - return json.Number(strconv.FormatInt(a.sumInt, 10)) + return jsonx.Number(strconv.FormatInt(a.sumInt, 10)) } case aggAvg: if a.numCount == 0 { diff --git a/services/cosmosdb/sql_engine_test.go b/services/cosmosdb/sql_engine_test.go index e80a085d70..cc6500322f 100644 --- a/services/cosmosdb/sql_engine_test.go +++ b/services/cosmosdb/sql_engine_test.go @@ -1,12 +1,13 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -137,8 +138,8 @@ func TestExecuteQuery_Engine(t *testing.T) { name: "offset limit params", query: "SELECT VALUE c.id FROM c ORDER BY c.age OFFSET @o LIMIT @l", params: []cosmosdb.QueryParameter{ - {Name: "@o", Value: json.Number("0")}, - {Name: "@l", Value: json.Number("2")}, + {Name: "@o", Value: jsonx.Number("0")}, + {Name: "@l", Value: jsonx.Number("2")}, }, want: `["2","1"]`, }, @@ -194,7 +195,7 @@ func TestExecuteQuery_Engine(t *testing.T) { rows, err := cosmosdb.ExecuteQuery(tt.query, tt.params, docs) require.NoError(t, err) - got, err := json.Marshal(rows) + got, err := json.Marshal(rows, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(got)) diff --git a/services/cosmosdb/sql_eval.go b/services/cosmosdb/sql_eval.go index dc9db26031..5ebe9cf108 100644 --- a/services/cosmosdb/sql_eval.go +++ b/services/cosmosdb/sql_eval.go @@ -1,7 +1,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "fmt" "math" "regexp" @@ -9,6 +9,8 @@ import ( "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // undef is the Cosmos SQL "undefined" value (a missing property, an unbound parameter, a failed operation). @@ -247,7 +249,7 @@ func (ec *evalCtx) evalUnary(n *exprUnary, env []any) any { return undef{} } - return numArith(sqlTokMinus, json.Number("0"), num) + return numArith(sqlTokMinus, jsonx.Number("0"), num) default: if num, ok := toNumber(v); ok { return num @@ -445,16 +447,16 @@ func (ec *evalCtx) evalSubquery(n *exprSubquery, env []any) any { // --- numbers --- -func toNumber(v any) (json.Number, bool) { +func toNumber(v any) (jsonx.Number, bool) { switch t := v.(type) { - case json.Number: + case jsonx.Number: return t, true case int: - return json.Number(strconv.Itoa(t)), true + return jsonx.Number(strconv.Itoa(t)), true case int32: - return json.Number(strconv.FormatInt(int64(t), 10)), true + return jsonx.Number(strconv.FormatInt(int64(t), 10)), true case int64: - return json.Number(strconv.FormatInt(t, 10)), true + return jsonx.Number(strconv.FormatInt(t, 10)), true case float32: return formatFloatNumber(float64(t)) case float64: @@ -464,7 +466,7 @@ func toNumber(v any) (json.Number, bool) { } } -func formatFloatNumber(f float64) (json.Number, bool) { +func formatFloatNumber(f float64) (jsonx.Number, bool) { if math.IsNaN(f) || math.IsInf(f, 0) { return "", false } @@ -474,10 +476,10 @@ func formatFloatNumber(f float64) (json.Number, bool) { format = 'e' } - return json.Number(strconv.FormatFloat(f, format, -1, 64)), true + return jsonx.Number(strconv.FormatFloat(f, format, -1, 64)), true } -func numFloat(n json.Number) float64 { +func numFloat(n jsonx.Number) float64 { f, _ := n.Float64() return f @@ -493,7 +495,7 @@ func floatResult(f float64) any { } // numArith applies + - * / % to a and b, staying in int64 when exact and falling back to float64. -func numArith(op sqlTokenType, a, b json.Number) any { +func numArith(op sqlTokenType, a, b jsonx.Number) any { ai, aErr := a.Int64() bi, bErr := b.Int64() @@ -554,7 +556,7 @@ func intArith(op sqlTokenType, a, b int64) (any, bool) { return nil, false } - return json.Number(strconv.FormatInt(v, 10)), true + return jsonx.Number(strconv.FormatInt(v, 10)), true } func intAdd(a, b int64) (int64, bool) { @@ -720,7 +722,7 @@ func objectsEqual(a, b map[string]any) bool { } // compareJSONNumbers compares as int64 when both are exact integers, else as float64. -func compareJSONNumbers(a, b json.Number) int { +func compareJSONNumbers(a, b jsonx.Number) int { ai, aErr := a.Int64() bi, bErr := b.Int64() @@ -856,7 +858,7 @@ func compareArrays(a, b []any) int { } func canonicalJSON(v any) string { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Sprint(v) } diff --git a/services/cosmosdb/sql_exec_test.go b/services/cosmosdb/sql_exec_test.go index e8986b8c3d..bfa2fcd003 100644 --- a/services/cosmosdb/sql_exec_test.go +++ b/services/cosmosdb/sql_exec_test.go @@ -1,7 +1,6 @@ package cosmosdb_test import ( - "encoding/json" "strings" "testing" "time" @@ -9,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -60,7 +60,7 @@ func TestExecuteQuery_ProjectionWithAlias(t *testing.T) { require.NoError(t, err) require.Len(t, rows, 1) assert.Equal(t, "alice", rowObj(t, rows[0])["n"]) - assert.Equal(t, json.Number("30"), rowObj(t, rows[0])["age"]) + assert.Equal(t, jsonx.Number("30"), rowObj(t, rows[0])["age"]) } func TestExecuteQuery_WhereComparisons(t *testing.T) { diff --git a/services/cosmosdb/sql_ext_test.go b/services/cosmosdb/sql_ext_test.go index 4db3cfddbf..356d500548 100644 --- a/services/cosmosdb/sql_ext_test.go +++ b/services/cosmosdb/sql_ext_test.go @@ -1,12 +1,13 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -115,7 +116,7 @@ func TestExecuteQuery_SpatialAndConversionFunctions(t *testing.T) { require.NoError(t, err) require.Len(t, rows, 1) - got, err := json.Marshal(rows[0]) + got, err := json.Marshal(rows[0], jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/cosmosdb/sql_funcs.go b/services/cosmosdb/sql_funcs.go index 7f33040387..574a4566cc 100644 --- a/services/cosmosdb/sql_funcs.go +++ b/services/cosmosdb/sql_funcs.go @@ -1,13 +1,14 @@ package cosmosdb import ( - "encoding/json" "math" "regexp" "strconv" "strings" "time" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -270,7 +271,7 @@ func intArg(v any) (int, bool) { return int(i), true } -func intValue(i int) any { return json.Number(strconv.Itoa(i)) } +func intValue(i int) any { return jsonx.Number(strconv.Itoa(i)) } func boolArg(args []any, i int) bool { if i >= len(args) { @@ -459,7 +460,7 @@ func parseStringValue(name string, v any) any { } if i, iErr := strconv.ParseInt(s, 10, 64); iErr == nil { - return json.Number(strconv.FormatInt(i, 10)) + return jsonx.Number(strconv.FormatInt(i, 10)) } return floatResult(f) @@ -549,13 +550,13 @@ func callMath(name string, args []any) any { } } -func mathRounding(name string, n json.Number) any { +func mathRounding(name string, n jsonx.Number) any { if i, err := n.Int64(); err == nil { switch { case name == biSign: return intValue(cmpSign(i)) case name == biAbs && i < 0 && i != math.MinInt64: - return json.Number(strconv.FormatInt(-i, 10)) + return jsonx.Number(strconv.FormatInt(-i, 10)) default: return n } @@ -590,7 +591,7 @@ func cmpSign(i int64) int { } } -func mathLog(n json.Number, args []any) any { +func mathLog(n jsonx.Number, args []any) any { f := numFloat(n) if f <= 0 { return undef{} @@ -823,9 +824,9 @@ func (ec *evalCtx) callDate(name string, args []any) any { case biGetcurrentdatetime, biGetcurrentdatetimestatic: return ec.now.Format(dateTimeLayout) case biGetcurrenttimestamp, biGetcurrenttimestampstatic: - return json.Number(strconv.FormatInt(ec.now.UnixMilli(), 10)) + return jsonx.Number(strconv.FormatInt(ec.now.UnixMilli(), 10)) case biGetcurrentticks, biGetcurrentticksstatic: - return json.Number(strconv.FormatInt(ec.now.UnixNano()/ticksPerNano, 10)) + return jsonx.Number(strconv.FormatInt(ec.now.UnixNano()/ticksPerNano, 10)) case biTimestamptodatetime: ms, ok := toNumber(args[0]) if !ok { @@ -841,7 +842,7 @@ func (ec *evalCtx) callDate(name string, args []any) any { return undef{} } - return json.Number(strconv.FormatInt(t.UnixMilli(), 10)) + return jsonx.Number(strconv.FormatInt(t.UnixMilli(), 10)) default: return dateTimeOp(name, args) } diff --git a/services/cosmosdb/sql_funcs_ext.go b/services/cosmosdb/sql_funcs_ext.go index 8f850c67e6..b374ae7a66 100644 --- a/services/cosmosdb/sql_funcs_ext.go +++ b/services/cosmosdb/sql_funcs_ext.go @@ -2,10 +2,13 @@ package cosmosdb import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -18,11 +21,16 @@ const ( // parseJSONContainer implements StringToArray and StringToObject: the string must hold exactly that JSON kind. func parseJSONContainer(name, s string) any { - dec := json.NewDecoder(bytes.NewReader([]byte(s))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(s)), jsonx.V1()) var v any - if err := dec.Decode(&v); err != nil || rejectTrailingJSON(dec) != nil { + if err := json.UnmarshalDecode( + dec, + &v, + jsonx.V1(), + jsonx.UseNumber(), + ); err != nil || + rejectTrailingJSON(dec) != nil { return undef{} } @@ -86,7 +94,7 @@ func dateTicksOp(name string, args []any) any { return undef{} } - return json.Number(strconv.FormatInt(t.Unix()*ticksPerSecond+int64(t.Nanosecond())/ticksPerNano, 10)) + return jsonx.Number(strconv.FormatInt(t.Unix()*ticksPerSecond+int64(t.Nanosecond())/ticksPerNano, 10)) case biTickstodatetime: n, ok := toNumber(args[0]) if !ok { diff --git a/services/cosmosdb/sql_funcs_more.go b/services/cosmosdb/sql_funcs_more.go index 4b5bfdc0a5..9bad347f3b 100644 --- a/services/cosmosdb/sql_funcs_more.go +++ b/services/cosmosdb/sql_funcs_more.go @@ -3,7 +3,6 @@ package cosmosdb import ( "crypto/rand" "encoding/binary" - "encoding/json" "math" "math/big" "regexp" @@ -12,6 +11,8 @@ import ( "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Built-in functions of the Cosmos DB query language reference (Learn, "Functions") beyond the first set: @@ -253,7 +254,7 @@ func trigonometry(name string, x float64) any { // numberBin rounds a down to a multiple of the bin size (default 1): floor(a / size) * size, so a negative size // bins upward as the documented example shows. A zero or non-numeric size has no result. -func numberBin(a json.Number, args []any) any { +func numberBin(a jsonx.Number, args []any) any { size := 1.0 if len(args) > 1 { @@ -277,7 +278,7 @@ func numberBin(a json.Number, args []any) any { q-- } - return json.Number(strconv.FormatInt(q*si, 10)) + return jsonx.Number(strconv.FormatInt(q*si, 10)) } return floatResult(math.Floor(numFloat(a)/size) * size) @@ -311,7 +312,7 @@ func intMath(name string, args []any) any { } if name == biIntbitnot { - return json.Number(strconv.FormatInt(^a, 10)) + return jsonx.Number(strconv.FormatInt(^a, 10)) } b, bok := int64Arg(args[1]) @@ -324,7 +325,7 @@ func intMath(name string, args []any) any { return undef{} } - return json.Number(strconv.FormatInt(r, 10)) + return jsonx.Number(strconv.FormatInt(r, 10)) } func intBinary(name string, a, b int64) (int64, bool) { @@ -810,7 +811,7 @@ func documentIDOf(n *exprCall, env []any) any { return undef{} } - return json.Number(strconv.FormatInt(row.doc.Seq, 10)) + return jsonx.Number(strconv.FormatInt(row.doc.Seq, 10)) } // randomUnit is a uniform number in [0, 1). diff --git a/services/cosmosdb/sql_functions_doc_test.go b/services/cosmosdb/sql_functions_doc_test.go index 795506e23b..e08acff93e 100644 --- a/services/cosmosdb/sql_functions_doc_test.go +++ b/services/cosmosdb/sql_functions_doc_test.go @@ -1,12 +1,13 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -203,7 +204,7 @@ func TestSQLFunctions_DocumentedExamples(t *testing.T) { require.NoError(t, err) require.Len(t, rows, 1) - got, err := json.Marshal(rows[0]) + got, err := json.Marshal(rows[0], jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(got)) }) @@ -343,7 +344,7 @@ func TestSQL_DocumentedStatementForms(t *testing.T) { require.NoError(t, err) - got, marshalErr := json.Marshal(rows) + got, marshalErr := json.Marshal(rows, jsonx.V1()) require.NoError(t, marshalErr) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/cosmosdb/sql_parser.go b/services/cosmosdb/sql_parser.go index 6b8a6a6eda..80d2bce226 100644 --- a/services/cosmosdb/sql_parser.go +++ b/services/cosmosdb/sql_parser.go @@ -1,10 +1,11 @@ package cosmosdb import ( - "encoding/json" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sql_parser.go is a recursive-descent parser for Cosmos DB SQL. @@ -267,7 +268,7 @@ func (p *sqlParser) parseCountOperand(what string) (sqlExpr, error) { p.advance() - return &exprLit{v: json.Number(strconv.Itoa(n))}, nil + return &exprLit{v: jsonx.Number(strconv.Itoa(n))}, nil case sqlTokParam: x := &exprParam{name: p.cur.lit} @@ -883,7 +884,7 @@ func (p *sqlParser) parseUnary() (sqlExpr, error) { p.advance() - return &exprLit{v: json.Number(lit)}, nil + return &exprLit{v: jsonx.Number(lit)}, nil } inner, err := p.parseUnary() @@ -937,7 +938,7 @@ func (p *sqlParser) parsePrimary() (sqlExpr, error) { case sqlTokNumber: p.advance() - return &exprLit{v: json.Number(tok.lit)}, nil + return &exprLit{v: jsonx.Number(tok.lit)}, nil case sqlTokString: p.advance() diff --git a/services/cosmosdb/sql_spatial_doc_test.go b/services/cosmosdb/sql_spatial_doc_test.go index 6387ff30a5..15e021ede7 100644 --- a/services/cosmosdb/sql_spatial_doc_test.go +++ b/services/cosmosdb/sql_spatial_doc_test.go @@ -1,12 +1,14 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -33,7 +35,7 @@ func evalOne(t *testing.T, expr string) any { func asFloat(t *testing.T, v any) float64 { t.Helper() - n, ok := v.(json.Number) + n, ok := v.(jsonx.Number) require.True(t, ok, "%T", v) f, err := n.Float64() @@ -187,7 +189,7 @@ func TestSpatial_GeographySemantics(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - got, err := json.Marshal(evalOne(t, tt.expr)) + got, err := json.Marshal(evalOne(t, tt.expr), jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(got)) }) @@ -243,7 +245,7 @@ func TestSpatial_GeometryContainersUsePlanarMath(t *testing.T) { _, err = b.CreateContainer("d", cosmosdb.ContainerSpec{ ID: "c", PartitionKeyPath: "/pk", - GeospatialConfig: json.RawMessage(`{"type":"` + tt.geo + `"}`), + GeospatialConfig: jsontext.Value(`{"type":"` + tt.geo + `"}`), }) require.NoError(t, err) _, err = b.CreateDocument("d", "c", map[string]any{"id": "1", "pk": "k"}, false) @@ -253,7 +255,7 @@ func TestSpatial_GeometryContainersUsePlanarMath(t *testing.T) { require.NoError(t, err) require.Len(t, res.Rows, 1) - got, err := json.Marshal(res.Rows[0]) + got, err := json.Marshal(res.Rows[0], jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/cosmosdb/store_test.go b/services/cosmosdb/store_test.go index 8bc610eb96..e1fffbda71 100644 --- a/services/cosmosdb/store_test.go +++ b/services/cosmosdb/store_test.go @@ -1,7 +1,6 @@ package cosmosdb_test import ( - "encoding/json" "math" "testing" "time" @@ -9,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -322,7 +322,7 @@ func TestInMemoryBackend_Int64PrecisionPreservedThroughStorage(t *testing.T) { info, err := b.CreateDocument("mydb", "mycoll", body, false) require.NoError(t, err) - gotNum, ok := info.Body["big"].(json.Number) + gotNum, ok := info.Body["big"].(jsonx.Number) require.True(t, ok, "big field must remain a json.Number, not a lossy float64") assert.Equal(t, tt.raw, gotNum.String()) }) diff --git a/services/cosmosdb/table_api.go b/services/cosmosdb/table_api.go index 95c390ac54..11ea881135 100644 --- a/services/cosmosdb/table_api.go +++ b/services/cosmosdb/table_api.go @@ -23,7 +23,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -31,6 +31,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/odatatable" ) @@ -362,7 +363,7 @@ func (h *Handler) createTable(c *echo.Context) error { } var req createTableBody - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return h.writeTableError(c, http.StatusBadRequest, "InvalidInput", "The input is not valid.") } @@ -514,7 +515,7 @@ type tableODataErrorEnvelope struct { func (h *Handler) writeTableJSON(c *echo.Context, status int, v any) error { level := tableODataLevelFromAccept(c.Request().Header.Get("Accept")) - body, err := json.Marshal(v) + body, err := json.Marshal(v, jsonx.V1()) if err != nil { return h.writeTableErrorNoRecurse(c, http.StatusInternalServerError, "InternalError", "Failed to marshal response.") @@ -545,7 +546,7 @@ func (h *Handler) writeTableErrorNoRecurse(c *echo.Context, status int, code, me c.Response().Header().Set("X-Ms-Error-Code", code) body, _ := json.Marshal(tableODataErrorEnvelope{ Error: tableODataErrorDetail{Code: code, Message: tableODataErrorMessage{Lang: tableErrorLang, Value: message}}, - }) + }, jsonx.V1()) return c.Blob(status, "application/json;odata=minimalmetadata;streaming=true;charset=utf-8", body) } diff --git a/services/cosmosdb/throughput_test.go b/services/cosmosdb/throughput_test.go index 75d432c8f6..5b8d1a2021 100644 --- a/services/cosmosdb/throughput_test.go +++ b/services/cosmosdb/throughput_test.go @@ -2,7 +2,7 @@ package cosmosdb_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -480,7 +481,7 @@ func TestThroughput_PersistenceRoundTrip(t *testing.T) { snap := src.Snapshot(t.Context()) var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) dst := cosmosdb.NewInMemoryBackend() require.NoError(t, dst.Restore(t.Context(), snap)) diff --git a/services/cosmosdb/token.go b/services/cosmosdb/token.go index 92bf81bfd0..95f84a145e 100644 --- a/services/cosmosdb/token.go +++ b/services/cosmosdb/token.go @@ -4,13 +4,15 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -93,7 +95,7 @@ func signTokenPayload(masterKey string, payload []byte) []byte { // issueResourceToken builds "type=resource&ver=1&sig=;", the value of a permission's _token. func issueResourceToken(masterKey string, claims tokenClaims) (string, error) { - payload, err := json.Marshal(claims) + payload, err := json.Marshal(claims, jsonx.V1()) if err != nil { return "", fmt.Errorf("cosmosdb: marshal token claims: %w", err) } @@ -126,7 +128,7 @@ func parseResourceToken(masterKey, sig string) (tokenClaims, bool) { } var claims tokenClaims - if json.Unmarshal(payload, &claims) != nil { + if json.Unmarshal(payload, &claims, jsonx.V1()) != nil { return tokenClaims{}, false } diff --git a/services/cosmosdb/triggers.go b/services/cosmosdb/triggers.go index 6b035b20ab..42bf0c680b 100644 --- a/services/cosmosdb/triggers.go +++ b/services/cosmosdb/triggers.go @@ -1,9 +1,11 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // docOp is a document write with the triggers requested for it. @@ -226,7 +228,7 @@ func triggerNames(header string) []string { // patchWithBody applies a patch whose request body (the operations, after any pre-trigger edit) is body. func (tx *containerTx) patchWithBody(op docOp, body map[string]any) (DocumentInfo, error) { - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) if err != nil { return DocumentInfo{}, invalidPatchf("the patch body is not valid JSON") } diff --git a/services/cosmosdb/ttl_test.go b/services/cosmosdb/ttl_test.go index 5b450b5257..591c7284a5 100644 --- a/services/cosmosdb/ttl_test.go +++ b/services/cosmosdb/ttl_test.go @@ -1,7 +1,6 @@ package cosmosdb_test import ( - "encoding/json" "net/http" "sync/atomic" "testing" @@ -10,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -143,7 +143,7 @@ func TestTTL_ExpiredReadsAsAbsentForWrites(t *testing.T) { info, err := b.GetDocument("d", "c", `"a"`, "x") require.NoError(t, err) - assert.Equal(t, json.Number("2"), info.Body["v"]) + assert.Equal(t, jsonx.Number("2"), info.Body["v"]) } func TestTTL_SweepRemovesExpired(t *testing.T) { diff --git a/services/cosmosdb/users.go b/services/cosmosdb/users.go index 360b211e7c..cc4ab07d2a 100644 --- a/services/cosmosdb/users.go +++ b/services/cosmosdb/users.go @@ -1,7 +1,7 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "sort" @@ -46,7 +46,7 @@ type PermissionSpec struct { ID string Mode string Resource string - PartitionKey json.RawMessage + PartitionKey jsontext.Value } // PermissionInfo is a read-only snapshot of a permission. Link is the canonical id-based resource path. @@ -60,7 +60,7 @@ type PermissionInfo struct { Resource string Link string PartitionKeyJSON string - PartitionKey json.RawMessage + PartitionKey jsontext.Value } type storedUser struct { @@ -75,8 +75,8 @@ type storedPermission struct { Mode string Resource string Link string - PartitionKeyJSON string `json:"PartitionKeyJSON,omitempty"` - PartitionKey json.RawMessage `json:"PartitionKey,omitempty"` + PartitionKeyJSON string `json:"PartitionKeyJSON,omitempty"` + PartitionKey jsontext.Value `json:"PartitionKey,omitempty"` } func userInfo(dbID string, u *storedUser) UserInfo { diff --git a/services/cosmosdb/users_ops.go b/services/cosmosdb/users_ops.go index d3cb7a433e..c472e1409a 100644 --- a/services/cosmosdb/users_ops.go +++ b/services/cosmosdb/users_ops.go @@ -1,13 +1,14 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -122,7 +123,7 @@ func (h *Handler) readJSONBody(c *echo.Context, dst any) bool { return false } - if json.Unmarshal(raw, dst) != nil { + if json.Unmarshal(raw, dst, jsonx.V1()) != nil { _ = h.writeError(c, http.StatusBadRequest, "BadRequest", "The input is not valid JSON.") return false diff --git a/services/cosmosdb/users_test.go b/services/cosmosdb/users_test.go index 0e0637f369..132f42bc61 100644 --- a/services/cosmosdb/users_test.go +++ b/services/cosmosdb/users_test.go @@ -1,7 +1,7 @@ package cosmosdb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/cosmosdb" ) @@ -65,7 +66,7 @@ func decodeMap(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/cosmosdb/vector.go b/services/cosmosdb/vector.go index a4940dc3ed..bc93bdb11f 100644 --- a/services/cosmosdb/vector.go +++ b/services/cosmosdb/vector.go @@ -1,11 +1,14 @@ package cosmosdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -50,20 +53,20 @@ func validVectorIndexType(s string) bool { return slices.Contains([]string{vectorIdxFlat, vectorIdxQuantizedFlat, vectorIdxDiskANN}, s) } -func parseVectorPolicy(raw json.RawMessage) (vectorEmbeddingPolicy, error) { +func parseVectorPolicy(raw jsontext.Value) (vectorEmbeddingPolicy, error) { var pol vectorEmbeddingPolicy if isJSONNull(raw) { return pol, nil } - if err := json.Unmarshal(raw, &pol); err != nil { + if err := json.Unmarshal(raw, &pol, jsonx.V1()); err != nil { return pol, fmt.Errorf("%w: vectorEmbeddingPolicy is malformed", ErrInvalidContainerPolicy) } return pol, nil } -func validateVectorPolicy(raw json.RawMessage) error { +func validateVectorPolicy(raw jsontext.Value) error { pol, err := parseVectorPolicy(raw) if err != nil { return err diff --git a/services/cur/delivery.go b/services/cur/delivery.go index bca09016aa..a055f0a667 100644 --- a/services/cur/delivery.go +++ b/services/cur/delivery.go @@ -2,7 +2,7 @@ package cur import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "path" "slices" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/billingexport" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -224,7 +225,7 @@ func writeManifests( periodDir, dataDir string, athena bool, ) error { - mb, err := json.Marshal(m) + mb, err := json.Marshal(m, jsonx.V1()) if err != nil { return fmt.Errorf("encode manifest: %w", err) } @@ -303,7 +304,7 @@ func redshiftManifest(dataURI string) []byte { "globalUploadSettings": map[string]string{ "format": "CSV", "delimiter": ",", "textqualifier": "\"", "containsHeader": "true", }, - }) + }, jsonx.V1()) return b } @@ -314,7 +315,7 @@ func quicksightManifest(dataURI string) []byte { "globalUploadSettings": map[string]string{ "format": "CSV", "delimiter": ",", "textqualifier": "\"", "containsHeader": "true", }, - }) + }, jsonx.V1()) return b } diff --git a/services/cur/delivery_test.go b/services/cur/delivery_test.go index e7f2c5dffe..16797c198c 100644 --- a/services/cur/delivery_test.go +++ b/services/cur/delivery_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "encoding/csv" - "encoding/json" + "encoding/json/v2" "io" "slices" "testing" @@ -16,6 +16,8 @@ import ( sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (f *fixture) object(t *testing.T, key string) []byte { @@ -109,7 +111,7 @@ func TestDelivery_CSVGzip(t *testing.T) { } var m map[string]any - require.NoError(t, json.Unmarshal(f.object(t, manifestKey), &m)) + require.NoError(t, json.Unmarshal(f.object(t, manifestKey), &m, jsonx.V1())) assert.Equal(t, "daily", m["reportName"]) assert.Equal(t, "20260301T000000.000Z", m["billingPeriod"].(map[string]any)["start"]) assert.Equal(t, []any{dataKey}, m["reportKeys"]) diff --git a/services/cur/handler.go b/services/cur/handler.go index fc7e4bd429..a9c3b53a95 100644 --- a/services/cur/handler.go +++ b/services/cur/handler.go @@ -2,7 +2,7 @@ package cur import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/worker" @@ -39,7 +40,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrValidation, "malformed request body: %v", err) } } diff --git a/services/cur/persistence.go b/services/cur/persistence.go index e4b13d9968..dcf27103b0 100644 --- a/services/cur/persistence.go +++ b/services/cur/persistence.go @@ -2,7 +2,7 @@ package cur import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/databrew/datasets_test.go b/services/databrew/datasets_test.go index c9442e1a40..dd6a2986ea 100644 --- a/services/databrew/datasets_test.go +++ b/services/databrew/datasets_test.go @@ -2,13 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -298,7 +299,7 @@ func TestHandlerCreateDataset(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-ds", resp["Name"]) } @@ -326,7 +327,7 @@ func TestHandlerDescribeDataset(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/datasets/ds1", nil) assert.Equal(t, http.StatusOK, rec.Code) var ds map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ds)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ds, jsonx.V1())) assert.Equal(t, "ds1", ds["Name"]) } @@ -347,7 +348,7 @@ func TestHandlerListDatasets(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/datasets", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Datasets"]) } @@ -453,7 +454,7 @@ func TestHandlerCreateDataset_PathOptions(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/datasets/po-wire-ds", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pathOptions, ok := resp["PathOptions"].(map[string]any) require.True(t, ok, "PathOptions must round-trip as an object") filesLimit, ok := pathOptions["FilesLimit"].(map[string]any) diff --git a/services/databrew/handler.go b/services/databrew/handler.go index 5eeb9c3ee4..1b01fea1ca 100644 --- a/services/databrew/handler.go +++ b/services/databrew/handler.go @@ -2,7 +2,8 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -377,18 +379,18 @@ var onceSimpleQueryParamToJSONKey = sync.OnceValue(func() map[string]string { // mergeSimpleQueryParams copies every onceSimpleQueryParamToJSONKey entry // present on the request into m. -func mergeSimpleQueryParams(c *echo.Context, m map[string]json.RawMessage) { +func mergeSimpleQueryParams(c *echo.Context, m map[string]jsontext.Value) { for param, jsonKey := range onceSimpleQueryParamToJSONKey() { if v := c.QueryParam(param); v != "" { - m[jsonKey], _ = json.Marshal(v) + m[jsonKey], _ = json.Marshal(v, jsonx.V1()) } } } func enrichDataBrewBody(c *echo.Context, _, name string, body []byte) ([]byte, error) { - m := make(map[string]json.RawMessage) + m := make(map[string]jsontext.Value) if len(body) > 0 { - if err := json.Unmarshal(body, &m); err != nil { + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -396,11 +398,11 @@ func enrichDataBrewBody(c *echo.Context, _, name string, body []byte) ([]byte, e if name != "" { if existingName, ok := m["Name"]; ok { var parsedName string - if err := json.Unmarshal(existingName, &parsedName); err == nil && parsedName != name { + if err := json.Unmarshal(existingName, &parsedName, jsonx.V1()); err == nil && parsedName != name { return nil, fmt.Errorf("%w: name in body does not match path", errInvalidRequest) } } - nameJSON, _ := json.Marshal(name) + nameJSON, _ := json.Marshal(name, jsonx.V1()) m["Name"] = nameJSON } @@ -413,7 +415,7 @@ func enrichDataBrewBody(c *echo.Context, _, name string, body []byte) ([]byte, e // encoder.AddQuery("tagKeys") per key). Without this, UntagResource always // silently no-ops. if tagKeys := c.QueryParams()["tagKeys"]; len(tagKeys) > 0 { - m["TagKeys"], _ = json.Marshal(tagKeys) + m["TagKeys"], _ = json.Marshal(tagKeys, jsonx.V1()) } // ListRecipeVersions is GET /recipeVersions?name=... (top-level, no path // segment for the recipe name); only set when name isn't already known @@ -421,20 +423,20 @@ func enrichDataBrewBody(c *echo.Context, _, name string, body []byte) ([]byte, e // alias already populated "Name" above). if _, ok := m["Name"]; !ok { if v := c.QueryParam("name"); v != "" { - m["Name"], _ = json.Marshal(v) + m["Name"], _ = json.Marshal(v, jsonx.V1()) } } - result, _ := json.Marshal(m) + result, _ := json.Marshal(m, jsonx.V1()) return result, nil } func enrichDataBrewSubOpBody(path string, body []byte) []byte { segments := strings.Split(path, "/") - m := make(map[string]json.RawMessage) + m := make(map[string]jsontext.Value) if len(body) > 0 { - _ = json.Unmarshal(body, &m) + _ = json.Unmarshal(body, &m, jsonx.V1()) } for i, seg := range segments { @@ -442,26 +444,26 @@ func enrichDataBrewSubOpBody(path string, body []byte) []byte { case "jobRun": // e.g. /jobs/{Name}/jobRun/{RunId} — with or without /databrew/v1/ prefix if i+1 < len(segments) { - runIDJSON, _ := json.Marshal(segments[i+1]) + runIDJSON, _ := json.Marshal(segments[i+1], jsonx.V1()) m["RunId"] = runIDJSON } case "recipeVersion": // e.g. /recipes/{Name}/recipeVersion/{RecipeVersion} if i+1 < len(segments) { - versionJSON, _ := json.Marshal(segments[i+1]) + versionJSON, _ := json.Marshal(segments[i+1], jsonx.V1()) m["RecipeVersion"] = versionJSON } case "tags": // e.g. /databrew/v1/tags/{resourceArn} or /tags/{resourceArn} if i+1 < len(segments) { arn := strings.Join(segments[i+1:], "/") - arnJSON, _ := json.Marshal(arn) + arnJSON, _ := json.Marshal(arn, jsonx.V1()) m["ResourceArn"] = arnJSON } } } - result, _ := json.Marshal(m) + result, _ := json.Marshal(m, jsonx.V1()) return result } diff --git a/services/databrew/handler_datasets.go b/services/databrew/handler_datasets.go index f1c9512dae..9391c42334 100644 --- a/services/databrew/handler_datasets.go +++ b/services/databrew/handler_datasets.go @@ -2,9 +2,11 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseDatasetOp(method, name string) string { @@ -72,7 +74,7 @@ func (h *Handler) handleCreateDataset(ctx context.Context, body []byte) ([]byte, Name string `json:"Name"` Format string `json:"Format"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } ds, err := h.Backend.CreateDataset( @@ -82,14 +84,14 @@ func (h *Handler) handleCreateDataset(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: ds.Name}) + return json.Marshal(map[string]string{keyName: ds.Name}, jsonx.V1()) } func (h *Handler) handleDescribeDataset(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } ds, err := h.Backend.DescribeDataset(ctx, req.Name) @@ -100,7 +102,7 @@ func (h *Handler) handleDescribeDataset(ctx context.Context, body []byte) ([]byt cp := *ds cp.AccountID = "" - return json.Marshal(cp) + return json.Marshal(cp, jsonx.V1()) } func (h *Handler) handleListDatasets(ctx context.Context, body []byte) ([]byte, error) { @@ -108,7 +110,7 @@ func (h *Handler) handleListDatasets(ctx context.Context, body []byte) ([]byte, MaxResults string `json:"MaxResults"` NextToken string `json:"NextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -127,7 +129,7 @@ func (h *Handler) handleUpdateDataset(ctx context.Context, body []byte) ([]byte, Name string `json:"Name"` Format string `json:"Format"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateDataset( @@ -136,19 +138,19 @@ func (h *Handler) handleUpdateDataset(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteDataset(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteDataset(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } diff --git a/services/databrew/handler_jobs.go b/services/databrew/handler_jobs.go index 13921b141d..152646c9b2 100644 --- a/services/databrew/handler_jobs.go +++ b/services/databrew/handler_jobs.go @@ -2,10 +2,12 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseProfileJobOp(method, name string) string { @@ -143,7 +145,7 @@ func (h *Handler) handleCreateProfileJob(ctx context.Context, body []byte) ([]by MaxRetries int `json:"MaxRetries"` Timeout int `json:"Timeout"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } j, err := h.Backend.CreateJob( @@ -172,7 +174,7 @@ func (h *Handler) handleCreateProfileJob(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]string{keyName: j.Name}) + return json.Marshal(map[string]string{keyName: j.Name}, jsonx.V1()) } // outputLocationToOutputs converts a CreateProfileJobInput/UpdateProfileJobInput @@ -204,7 +206,7 @@ func (h *Handler) handleCreateRecipeJob(ctx context.Context, body []byte) ([]byt MaxRetries int `json:"MaxRetries"` Timeout int `json:"Timeout"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } recipeName, recipeVersion := "", "" @@ -238,14 +240,14 @@ func (h *Handler) handleCreateRecipeJob(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]string{keyName: j.Name}) + return json.Marshal(map[string]string{keyName: j.Name}, jsonx.V1()) } func (h *Handler) handleDescribeJob(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } j, err := h.Backend.DescribeJob(ctx, req.Name) @@ -256,7 +258,7 @@ func (h *Handler) handleDescribeJob(ctx context.Context, body []byte) ([]byte, e cp := *j cp.AccountID = "" - return json.Marshal(cp) + return json.Marshal(cp, jsonx.V1()) } func (h *Handler) handleListJobs(ctx context.Context, body []byte) ([]byte, error) { @@ -266,7 +268,7 @@ func (h *Handler) handleListJobs(ctx context.Context, body []byte) ([]byte, erro DatasetName string `json:"DatasetName"` ProjectName string `json:"ProjectName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -295,7 +297,7 @@ func (h *Handler) handleUpdateProfileJob(ctx context.Context, body []byte) ([]by MaxRetries int `json:"MaxRetries"` Timeout int `json:"Timeout"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateJob( @@ -313,7 +315,7 @@ func (h *Handler) handleUpdateProfileJob(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } // handleUpdateRecipeJob handles UpdateRecipeJob, whose wire field for the @@ -332,7 +334,7 @@ func (h *Handler) handleUpdateRecipeJob(ctx context.Context, body []byte) ([]byt MaxRetries int `json:"MaxRetries"` Timeout int `json:"Timeout"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateJob( @@ -348,28 +350,28 @@ func (h *Handler) handleUpdateRecipeJob(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteJob(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteJob(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleStartJobRun(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } run, err := h.Backend.StartJobRun(ctx, req.Name) @@ -377,7 +379,7 @@ func (h *Handler) handleStartJobRun(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]string{"RunId": run.RunID}) + return json.Marshal(map[string]string{"RunId": run.RunID}, jsonx.V1()) } func (h *Handler) handleListJobRuns(ctx context.Context, body []byte) ([]byte, error) { @@ -386,7 +388,7 @@ func (h *Handler) handleListJobRuns(ctx context.Context, body []byte) ([]byte, e MaxResults string `json:"MaxResults"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } maxResults, token, err := listParams(req.MaxResults, req.NextToken) @@ -407,7 +409,7 @@ func (h *Handler) handleDescribeJobRun(ctx context.Context, body []byte) ([]byte Name string `json:"Name"` RunID string `json:"RunId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } run, err := h.Backend.DescribeJobRun(ctx, req.Name, req.RunID) @@ -415,7 +417,7 @@ func (h *Handler) handleDescribeJobRun(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(run) + return json.Marshal(run, jsonx.V1()) } func (h *Handler) handleStopJobRun(ctx context.Context, body []byte) ([]byte, error) { @@ -423,7 +425,7 @@ func (h *Handler) handleStopJobRun(ctx context.Context, body []byte) ([]byte, er Name string `json:"Name"` RunID string `json:"RunId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } run, err := h.Backend.StopJobRun(ctx, req.Name, req.RunID) @@ -431,5 +433,5 @@ func (h *Handler) handleStopJobRun(ctx context.Context, body []byte) ([]byte, er return nil, err } - return json.Marshal(map[string]string{"RunId": run.RunID}) + return json.Marshal(map[string]string{"RunId": run.RunID}, jsonx.V1()) } diff --git a/services/databrew/handler_projects.go b/services/databrew/handler_projects.go index cd55898518..e614ecc9f0 100644 --- a/services/databrew/handler_projects.go +++ b/services/databrew/handler_projects.go @@ -2,11 +2,13 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseProjectOp(method, name, subOp string) string { @@ -88,7 +90,7 @@ func (h *Handler) handleCreateProject(ctx context.Context, body []byte) ([]byte, RoleArn string `json:"RoleArn"` Sample Sample `json:"Sample"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } p, err := h.Backend.CreateProject( @@ -104,14 +106,14 @@ func (h *Handler) handleCreateProject(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: p.Name}) + return json.Marshal(map[string]string{keyName: p.Name}, jsonx.V1()) } func (h *Handler) handleDescribeProject(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } p, err := h.Backend.DescribeProject(ctx, req.Name) @@ -122,7 +124,7 @@ func (h *Handler) handleDescribeProject(ctx context.Context, body []byte) ([]byt cp := *p cp.AccountID = "" - return json.Marshal(cp) + return json.Marshal(cp, jsonx.V1()) } func (h *Handler) handleListProjects(ctx context.Context, body []byte) ([]byte, error) { @@ -130,7 +132,7 @@ func (h *Handler) handleListProjects(ctx context.Context, body []byte) ([]byte, MaxResults string `json:"MaxResults"` NextToken string `json:"NextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -149,28 +151,28 @@ func (h *Handler) handleUpdateProject(ctx context.Context, body []byte) ([]byte, RoleArn string `json:"RoleArn"` Sample Sample `json:"Sample"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateProject(ctx, req.Name, req.RoleArn, req.Sample); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteProject(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteProject(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } // handleStartProjectSession handles StartProjectSession. It cannot emulate a @@ -182,7 +184,7 @@ func (h *Handler) handleStartProjectSession(ctx context.Context, body []byte) ([ Name string `json:"Name"` AssumeControl bool `json:"AssumeControl"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if _, err := h.Backend.OpenProjectSession(ctx, req.Name); err != nil { @@ -192,7 +194,7 @@ func (h *Handler) handleStartProjectSession(ctx context.Context, body []byte) ([ return json.Marshal(map[string]string{ keyName: req.Name, "ClientSessionId": uuid.New().String(), - }) + }, jsonx.V1()) } // handleSendProjectSessionAction handles SendProjectSessionAction. Applying @@ -203,12 +205,12 @@ func (h *Handler) handleSendProjectSessionAction(ctx context.Context, body []byt var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if _, err := h.Backend.DescribeProject(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } diff --git a/services/databrew/handler_recipes.go b/services/databrew/handler_recipes.go index c095156655..380ba1d65a 100644 --- a/services/databrew/handler_recipes.go +++ b/services/databrew/handler_recipes.go @@ -2,10 +2,12 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseRecipeSubOp(method, subOp string) string { @@ -115,7 +117,7 @@ func (h *Handler) handleCreateRecipe(ctx context.Context, body []byte) ([]byte, Name string `json:"Name"` Description string `json:"Description"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -132,7 +134,7 @@ func (h *Handler) handleCreateRecipe(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: r.Name}) + return json.Marshal(map[string]string{keyName: r.Name}, jsonx.V1()) } func (h *Handler) handleDescribeRecipe(ctx context.Context, body []byte) ([]byte, error) { @@ -140,7 +142,7 @@ func (h *Handler) handleDescribeRecipe(ctx context.Context, body []byte) ([]byte Name string `json:"Name"` RecipeVersion string `json:"RecipeVersion"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } r, err := h.Backend.DescribeRecipe(ctx, req.Name, req.RecipeVersion) @@ -148,7 +150,7 @@ func (h *Handler) handleDescribeRecipe(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(r) + return json.Marshal(r, jsonx.V1()) } func (h *Handler) handleListRecipes(ctx context.Context, body []byte) ([]byte, error) { @@ -157,7 +159,7 @@ func (h *Handler) handleListRecipes(ctx context.Context, body []byte) ([]byte, e NextToken string `json:"NextToken"` RecipeVersion string `json:"RecipeVersion"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -173,14 +175,14 @@ func (h *Handler) handlePublishRecipe(ctx context.Context, body []byte) ([]byte, Name string `json:"Name"` Description string `json:"Description"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.PublishRecipe(ctx, req.Name, req.Description); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleUpdateRecipe(ctx context.Context, body []byte) ([]byte, error) { @@ -189,7 +191,7 @@ func (h *Handler) handleUpdateRecipe(ctx context.Context, body []byte) ([]byte, Description string `json:"Description"` Steps []RecipeStep `json:"Steps"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := validateRecipeStepMembers(req.Steps); err != nil { @@ -200,21 +202,21 @@ func (h *Handler) handleUpdateRecipe(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteRecipe(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteRecipe(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleBatchDeleteRecipeVersion(ctx context.Context, body []byte) ([]byte, error) { @@ -222,7 +224,7 @@ func (h *Handler) handleBatchDeleteRecipeVersion(ctx context.Context, body []byt Name string `json:"Name"` RecipeVersions []string `json:"RecipeVersions"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } errs, err := h.Backend.BatchDeleteRecipeVersion(ctx, req.Name, req.RecipeVersions) @@ -230,7 +232,7 @@ func (h *Handler) handleBatchDeleteRecipeVersion(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyName: req.Name, "Errors": errs}) + return json.Marshal(map[string]any{keyName: req.Name, "Errors": errs}, jsonx.V1()) } func (h *Handler) handleDeleteRecipeVersion(ctx context.Context, body []byte) ([]byte, error) { @@ -238,14 +240,14 @@ func (h *Handler) handleDeleteRecipeVersion(ctx context.Context, body []byte) ([ Name string `json:"Name"` RecipeVersion string `json:"RecipeVersion"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteRecipeVersion(ctx, req.Name, req.RecipeVersion); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name, "RecipeVersion": req.RecipeVersion}) + return json.Marshal(map[string]string{keyName: req.Name, "RecipeVersion": req.RecipeVersion}, jsonx.V1()) } func (h *Handler) handleListRecipeVersions(ctx context.Context, body []byte) ([]byte, error) { @@ -254,7 +256,7 @@ func (h *Handler) handleListRecipeVersions(ctx context.Context, body []byte) ([] MaxResults string `json:"MaxResults"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } maxResults, token, err := listParams(req.MaxResults, req.NextToken) diff --git a/services/databrew/handler_rulesets.go b/services/databrew/handler_rulesets.go index 7628821e64..d72d0c4070 100644 --- a/services/databrew/handler_rulesets.go +++ b/services/databrew/handler_rulesets.go @@ -2,9 +2,11 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseRulesetOp(method, name string) string { @@ -65,7 +67,7 @@ func (h *Handler) handleCreateRuleset(ctx context.Context, body []byte) ([]byte, TargetArn string `json:"TargetArn"` Rules []Rule `json:"Rules"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.TargetArn == "" || req.Rules == nil { @@ -81,14 +83,14 @@ func (h *Handler) handleCreateRuleset(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: rs.Name}) + return json.Marshal(map[string]string{keyName: rs.Name}, jsonx.V1()) } func (h *Handler) handleDescribeRuleset(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } rs, err := h.Backend.DescribeRuleset(ctx, req.Name) @@ -96,7 +98,7 @@ func (h *Handler) handleDescribeRuleset(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(newRulesetDescribeView(rs)) + return json.Marshal(newRulesetDescribeView(rs), jsonx.V1()) } func (h *Handler) handleListRulesets(ctx context.Context, body []byte) ([]byte, error) { @@ -105,7 +107,7 @@ func (h *Handler) handleListRulesets(ctx context.Context, body []byte) ([]byte, NextToken string `json:"NextToken"` TargetArn string `json:"TargetArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -126,7 +128,7 @@ func (h *Handler) handleUpdateRuleset(ctx context.Context, body []byte) ([]byte, Description string `json:"Description"` Rules []Rule `json:"Rules"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.Rules == nil { @@ -141,19 +143,19 @@ func (h *Handler) handleUpdateRuleset(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteRuleset(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteRuleset(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } diff --git a/services/databrew/handler_schedules.go b/services/databrew/handler_schedules.go index 683225c9a0..f861ea9816 100644 --- a/services/databrew/handler_schedules.go +++ b/services/databrew/handler_schedules.go @@ -2,9 +2,11 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseScheduleOp(method, name string) string { @@ -64,7 +66,7 @@ func (h *Handler) handleCreateSchedule(ctx context.Context, body []byte) ([]byte CronExpression string `json:"CronExpression"` JobNames []string `json:"JobNames"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } sc, err := h.Backend.CreateSchedule(ctx, req.Name, req.JobNames, req.CronExpression, req.Tags) @@ -72,14 +74,14 @@ func (h *Handler) handleCreateSchedule(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(map[string]string{keyName: sc.Name}) + return json.Marshal(map[string]string{keyName: sc.Name}, jsonx.V1()) } func (h *Handler) handleDescribeSchedule(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } sc, err := h.Backend.DescribeSchedule(ctx, req.Name) @@ -90,7 +92,7 @@ func (h *Handler) handleDescribeSchedule(ctx context.Context, body []byte) ([]by cp := *sc cp.AccountID = "" - return json.Marshal(cp) + return json.Marshal(cp, jsonx.V1()) } func (h *Handler) handleListSchedules(ctx context.Context, body []byte) ([]byte, error) { @@ -99,7 +101,7 @@ func (h *Handler) handleListSchedules(ctx context.Context, body []byte) ([]byte, NextToken string `json:"NextToken"` JobName string `json:"JobName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) maxResults, token, err := listParams(req.MaxResults, req.NextToken) if err != nil { return nil, err @@ -116,26 +118,26 @@ func (h *Handler) handleUpdateSchedule(ctx context.Context, body []byte) ([]byte CronExpression string `json:"CronExpression"` JobNames []string `json:"JobNames"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateSchedule(ctx, req.Name, req.JobNames, req.CronExpression); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } func (h *Handler) handleDeleteSchedule(ctx context.Context, body []byte) ([]byte, error) { var req struct { Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.DeleteSchedule(ctx, req.Name); err != nil { return nil, err } - return json.Marshal(map[string]string{keyName: req.Name}) + return json.Marshal(map[string]string{keyName: req.Name}, jsonx.V1()) } diff --git a/services/databrew/handler_tags.go b/services/databrew/handler_tags.go index e988ed5516..6b1321b3cb 100644 --- a/services/databrew/handler_tags.go +++ b/services/databrew/handler_tags.go @@ -2,9 +2,11 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseTagsOp(method, _ string) string { @@ -47,14 +49,14 @@ func (h *Handler) handleTagResource(ctx context.Context, body []byte) ([]byte, e Tags map[string]string `json:"Tags"` ResourceArn string `json:"ResourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateTagsByArn(ctx, req.ResourceArn, req.Tags, nil); err != nil { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, error) { @@ -62,21 +64,21 @@ func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, ResourceArn string `json:"ResourceArn"` TagKeys []string `json:"TagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if err := h.Backend.UpdateTagsByArn(ctx, req.ResourceArn, nil, req.TagKeys); err != nil { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([]byte, error) { var req struct { ResourceArn string `json:"ResourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } tags, err := h.Backend.FindTagsByArn(ctx, req.ResourceArn) @@ -84,5 +86,5 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(map[string]any{"Tags": tags}) + return json.Marshal(map[string]any{"Tags": tags}, jsonx.V1()) } diff --git a/services/databrew/handler_test.go b/services/databrew/handler_test.go index ac3cfd13d3..4b749e3455 100644 --- a/services/databrew/handler_test.go +++ b/services/databrew/handler_test.go @@ -1,7 +1,7 @@ package databrew_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Handler metadata ---- @@ -30,7 +32,7 @@ func TestHandlerReset(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/datasets", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) datasets := resp["Datasets"].([]any) assert.Empty(t, datasets) } diff --git a/services/databrew/jobs_test.go b/services/databrew/jobs_test.go index cb673e183c..cf3c2ee8ac 100644 --- a/services/databrew/jobs_test.go +++ b/services/databrew/jobs_test.go @@ -2,7 +2,7 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -738,7 +739,7 @@ func TestHandlerUpdateProfileJob(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "upd-profile-j", resp["Name"]) } @@ -811,7 +812,7 @@ func TestHandlerDescribeJobRun(t *testing.T) { runRec := databrewReq(t, h, http.MethodPost, "/databrew/v1/jobs/djr-job/startJobRun", nil) require.Equal(t, http.StatusOK, runRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &startResp, jsonx.V1())) runID, _ := startResp["RunId"].(string) require.NotEmpty(t, runID) @@ -832,7 +833,7 @@ func TestHandlerStopJobRun(t *testing.T) { runRec := databrewReq(t, h, http.MethodPost, "/databrew/v1/jobs/sjr-job/startJobRun", nil) require.Equal(t, http.StatusOK, runRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &startResp, jsonx.V1())) runID, _ := startResp["RunId"].(string) require.NotEmpty(t, runID) @@ -854,7 +855,7 @@ func TestStartJobRun_RunId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["RunID"], "RunID (uppercase D) must not appear — AWS SDK uses RunId") runID, ok := resp["RunId"].(string) assert.True(t, ok, "response must have RunId string field") @@ -935,7 +936,7 @@ func TestListJobs_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs := resp["Jobs"].([]any) assert.Len(t, jobs, tc.wantCount, "query=%v", tc.queryParams) }) @@ -955,7 +956,7 @@ func TestJobRunIdField_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) runID, ok := startResp["RunId"].(string) require.True(t, ok) require.NotEmpty(t, runID) @@ -967,13 +968,13 @@ func TestJobRunIdField_RoundTrip(t *testing.T) { descRec := databrewReq(t, h, http.MethodGet, "/databrew/v1/jobs/rt-job/jobRun/"+runID, nil) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, runID, descResp["RunId"]) stopRec := databrewReq(t, h, http.MethodPost, "/databrew/v1/jobs/rt-job/jobRun/"+runID, nil) require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Equal(t, runID, stopResp["RunId"]) }) } @@ -1394,7 +1395,7 @@ func TestHandlerCreateProfileJob_Extras(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/jobs/pj-extras", nil) require.Equal(t, http.StatusOK, rec.Code) var job map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &job, jsonx.V1())) jobSample, ok := job["JobSample"].(map[string]any) require.True(t, ok, "JobSample must round-trip as an object") assert.Equal(t, "CUSTOM_ROWS", jobSample["Mode"]) @@ -1428,7 +1429,7 @@ func TestHandlerCreateRecipeJob_Extras(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/jobs/rj-extras", nil) require.Equal(t, http.StatusOK, rec.Code) var job map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &job, jsonx.V1())) assert.Equal(t, "SSE-KMS", job["EncryptionMode"]) assert.Equal(t, "ENABLE", job["LogSubscription"]) outputs, ok := job["DataCatalogOutputs"].([]any) diff --git a/services/databrew/paginate_helper.go b/services/databrew/paginate_helper.go index 762b051097..7781059dcd 100644 --- a/services/databrew/paginate_helper.go +++ b/services/databrew/paginate_helper.go @@ -2,10 +2,12 @@ package databrew import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func paginateKeys(keys []string, maxResults int, nextToken string) ([]string, string) { @@ -69,5 +71,5 @@ func marshalPage(key string, items any, next string) ([]byte, error) { out[nextTokenKey] = base64.RawURLEncoding.EncodeToString([]byte(pageTokenPrefix + next)) } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } diff --git a/services/databrew/persistence.go b/services/databrew/persistence.go index 3205f05d08..45e09bcada 100644 --- a/services/databrew/persistence.go +++ b/services/databrew/persistence.go @@ -2,7 +2,7 @@ package databrew import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" @@ -43,7 +43,7 @@ const databrewSnapshotVersion = 1 // directly here, nested the same way it is held on InMemoryBackend // (region -> job name -> run history). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` JobRuns map[string]map[string][]*JobRun `json:"jobRuns"` RecipeVersions map[string]map[string][]*Recipe `json:"recipeVersions"` AccountID string `json:"accountID"` @@ -90,7 +90,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { // "/" (see store_setup.go's *Table accessors); // splitting on the first "/" recovers both parts (region names never // contain "/"). -func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]json.RawMessage) { +func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]jsontext.Value) { for key := range tables { name, region, found := strings.Cut(key, "/") if !found { @@ -144,7 +144,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { } if snap.Tables == nil { - snap.Tables = make(map[string]json.RawMessage) + snap.Tables = make(map[string]jsontext.Value) } b.preRegisterSnapshotTables(snap.Tables) diff --git a/services/databrew/projects_test.go b/services/databrew/projects_test.go index 255f6f9cec..5745c1dcfe 100644 --- a/services/databrew/projects_test.go +++ b/services/databrew/projects_test.go @@ -2,13 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -242,7 +243,7 @@ func TestHandlerUpdateProject(t *testing.T) { desc := databrewReq(t, h, http.MethodGet, "/databrew/v1/projects/upd-proj", nil) require.Equal(t, http.StatusOK, desc.Code) var proj map[string]any - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &proj)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &proj, jsonx.V1())) assert.Equal(t, "orig-ds", proj["DatasetName"], "DatasetName must be immutable via UpdateProject") assert.Equal(t, "arn:aws:iam::123456789012:role/new", proj["RoleArn"]) } @@ -276,7 +277,7 @@ func TestHandlerStartProjectSession(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "sess-proj", resp["Name"]) } @@ -297,7 +298,7 @@ func TestHandlerSendProjectSessionAction(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "action-proj", resp["Name"]) } @@ -314,7 +315,7 @@ func TestHandlerStartProjectSession_ClientSessionID(t *testing.T) { rec := databrewReq(t, h, http.MethodPut, "/databrew/v1/projects/sess-id-proj/startProjectSession", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ClientSessionId"]) } diff --git a/services/databrew/recipes_test.go b/services/databrew/recipes_test.go index 6f0d069734..7602ebc4c5 100644 --- a/services/databrew/recipes_test.go +++ b/services/databrew/recipes_test.go @@ -2,13 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -193,7 +194,7 @@ func TestHandlerCreateRecipe(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-recipe", resp["Name"]) } @@ -239,7 +240,7 @@ func TestHandlerListRecipes(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/recipes", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Recipes"]) } @@ -280,7 +281,7 @@ func TestHandlerListRecipeVersions(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/recipes/ver-r/recipeVersions", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Recipes"]) } @@ -293,7 +294,7 @@ func TestHandlerListRecipeVersions_UnknownRecipe(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/recipes/no-such/recipeVersions", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Recipes"]) } @@ -356,7 +357,7 @@ func TestHandlerBatchDeleteRecipeVersion_LatestWorkingOnly(t *testing.T) { var out struct { Errors []map[string]string `json:"Errors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Errors, "deleting LATEST_WORKING as the only version must succeed with no partial failures") desc := databrewReq(t, h, http.MethodGet, "/databrew/v1/recipes/bdrv-lw-only", nil) @@ -394,7 +395,7 @@ func TestHandlerBatchDeleteRecipeVersion_LatestWorkingBlockedByPublished(t *test ErrorCode string `json:"ErrorCode"` } `json:"Errors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Errors, 1) assert.Equal(t, "LATEST_WORKING", out.Errors[0].RecipeVersion) assert.Equal(t, "ValidationException", out.Errors[0].ErrorCode) @@ -429,7 +430,7 @@ func TestRecipeReference(t *testing.T) { require.Equal(t, http.StatusOK, desc.Code) var job map[string]any - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &job, jsonx.V1())) assert.Nil(t, job["RecipeName"], "RecipeName must not appear in JSON — AWS SDK uses RecipeReference") ref, ok := job["RecipeReference"].(map[string]any) @@ -463,7 +464,7 @@ func TestRecipeReference_HonorsNumericVersion(t *testing.T) { require.Equal(t, http.StatusOK, desc.Code) var job map[string]any - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &job, jsonx.V1())) ref, ok := job["RecipeReference"].(map[string]any) require.True(t, ok, "RecipeReference must be an object") diff --git a/services/databrew/rulesets_test.go b/services/databrew/rulesets_test.go index afcbe72660..83825b6371 100644 --- a/services/databrew/rulesets_test.go +++ b/services/databrew/rulesets_test.go @@ -2,13 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -177,7 +178,7 @@ func TestHandlerCreateRuleset(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-ruleset", resp["Name"]) } @@ -204,7 +205,7 @@ func TestHandlerListRulesets(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/rulesets", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Rulesets"]) } @@ -283,7 +284,7 @@ func TestHandlerListRulesets_RuleCount(t *testing.T) { var resp struct { Rulesets []map[string]any `json:"Rulesets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Rulesets, 1) assert.InDelta(t, float64(1), resp.Rulesets[0]["RuleCount"], 0) } @@ -308,7 +309,7 @@ func TestHandlerListRulesets_NoRulesLeak(t *testing.T) { var resp struct { Rulesets []map[string]any `json:"Rulesets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Rulesets, 1) _, hasRules := resp.Rulesets[0]["Rules"] assert.False(t, hasRules, "ListRulesets item leaked Rules; real types.RulesetItem has no Rules member") @@ -331,7 +332,7 @@ func TestHandlerDescribeRuleset_NoAccountIDOrRuleCountLeak(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/rulesets/no-leak-describe-rs", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasAccountID := resp["AccountId"] assert.False( t, diff --git a/services/databrew/schedules_test.go b/services/databrew/schedules_test.go index ef5173790c..29870ec226 100644 --- a/services/databrew/schedules_test.go +++ b/services/databrew/schedules_test.go @@ -2,12 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Schedule backend ---- @@ -164,7 +166,7 @@ func TestHandlerCreateSchedule(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-schedule", resp["Name"]) } @@ -191,7 +193,7 @@ func TestHandlerListSchedules(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/schedules", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Schedules"]) } diff --git a/services/databrew/store_test.go b/services/databrew/store_test.go index e927d15c09..198896d43c 100644 --- a/services/databrew/store_test.go +++ b/services/databrew/store_test.go @@ -3,7 +3,8 @@ package databrew_test import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -43,7 +45,7 @@ func databrewReq(t *testing.T, h *databrew.Handler, method, path string, body an var buf bytes.Buffer if body != nil { - require.NoError(t, json.NewEncoder(&buf).Encode(body)) + require.NoError(t, json.MarshalEncode(jsontext.NewEncoder(&buf, jsonx.V1()), body)) } req := httptest.NewRequest(method, path, &buf) @@ -198,7 +200,7 @@ func TestHandlerDescribe_NoAccountIDLeak(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasAccountID := resp["AccountId"] assert.False(t, hasAccountID, "Describe leaked AccountId; the real Describe*Output has no AccountId member") }) @@ -224,7 +226,7 @@ func TestHandlerDescribeProject_NoSessionStatusFabrication(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasSessionStatus := resp["SessionStatus"] assert.False(t, hasSessionStatus, "DescribeProject fabricated SessionStatus; types.Project has no such member") } diff --git a/services/databrew/tags_test.go b/services/databrew/tags_test.go index 5f77ef74eb..da8836c869 100644 --- a/services/databrew/tags_test.go +++ b/services/databrew/tags_test.go @@ -2,13 +2,14 @@ package databrew_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/databrew" ) @@ -320,7 +321,7 @@ func TestHandlerListTagsForResource(t *testing.T) { rec := databrewReq(t, h, http.MethodGet, "/databrew/v1/tags/"+ds.Arn, nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Tags"]) } @@ -375,7 +376,7 @@ func TestTagsOps(t *testing.T) { listRec := databrewReq(t, h, http.MethodGet, prefix, nil) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) diff --git a/services/datasync/handler.go b/services/datasync/handler.go index 9cca34a962..02e10e3940 100644 --- a/services/datasync/handler.go +++ b/services/datasync/handler.go @@ -2,7 +2,7 @@ package datasync import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -226,12 +227,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, describeNotFound(err, body) } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError switch { // ErrNotFound/ErrAlreadyExists deliberately map to the SAME wire code as @@ -249,8 +248,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyType: "InvalidRequestException", keyMessage: publicMessage(err), diff --git a/services/datasync/handler_agents_test.go b/services/datasync/handler_agents_test.go index 1f3b549478..53b280983f 100644 --- a/services/datasync/handler_agents_test.go +++ b/services/datasync/handler_agents_test.go @@ -1,13 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -33,7 +34,7 @@ func TestDataSync_Agent(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["AgentArn"], "arn:aws:datasync:us-east-1:000000000000:agent/") }, }, @@ -54,7 +55,7 @@ func TestDataSync_Agent(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ONLINE", resp["Status"]) }, }, @@ -93,7 +94,7 @@ func TestDataSync_Agent(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) agents, ok := resp["Agents"].([]any) require.True(t, ok) assert.Empty(t, agents) @@ -138,7 +139,7 @@ func TestDataSync_AgentCRUD(t *testing.T) { rec := doRequest(t, h, "DescribeAgent", map[string]any{"AgentArn": agentArn}) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-agent", descResp["Name"]) // Update @@ -147,14 +148,14 @@ func TestDataSync_AgentCRUD(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeAgent", map[string]any{"AgentArn": agentArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "updated-agent", descResp["Name"]) // List rec = doRequest(t, h, "ListAgents", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Agents"], 1) // Delete diff --git a/services/datasync/handler_locations_agentarns_test.go b/services/datasync/handler_locations_agentarns_test.go index 6c46772e1d..0929560627 100644 --- a/services/datasync/handler_locations_agentarns_test.go +++ b/services/datasync/handler_locations_agentarns_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // agentArnsLocationCase covers one of the six location types that accept @@ -179,7 +181,7 @@ func TestDataSync_AgentArns_RejectsPhantomAgent(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["__type"]) }) } @@ -206,7 +208,7 @@ func TestDataSync_AgentArns_UpdateRejectsPhantomAgent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -214,7 +216,7 @@ func TestDataSync_AgentArns_UpdateRejectsPhantomAgent(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, "update: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["__type"]) // The rejected update must not have applied: AgentArns on the @@ -223,7 +225,7 @@ func TestDataSync_AgentArns_UpdateRejectsPhantomAgent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.ElementsMatch(t, []any{realAgentArn}, tc.agentArns(t, descResp)) }) } @@ -246,7 +248,7 @@ func TestDataSync_AgentArns_AcceptsRealAgent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -254,7 +256,7 @@ func TestDataSync_AgentArns_AcceptsRealAgent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.ElementsMatch(t, []any{agentArn}, tc.agentArns(t, descResp)) }) } diff --git a/services/datasync/handler_locations_azureblob_test.go b/services/datasync/handler_locations_azureblob_test.go index 4d744fa50a..e52b021b7f 100644 --- a/services/datasync/handler_locations_azureblob_test.go +++ b/services/datasync/handler_locations_azureblob_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_AzureBlob covers the AzureBlob location lifecycle. @@ -31,7 +33,7 @@ func TestDataSync_AzureBlob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) require.NotEmpty(t, locArn) @@ -41,7 +43,7 @@ func TestDataSync_AzureBlob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, locArn, descResp["LocationArn"]) assert.Equal(t, "BLOCK", descResp["BlobType"]) assert.Equal(t, "HOT", descResp["AccessTier"]) @@ -62,7 +64,7 @@ func TestDataSync_AzureBlob(t *testing.T) { // Describe after update rec = doRequest(t, h, "DescribeLocationAzureBlob", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "COOL", descResp["AccessTier"]) // Not found diff --git a/services/datasync/handler_locations_efs_test.go b/services/datasync/handler_locations_efs_test.go index 9c60568625..249b671ad2 100644 --- a/services/datasync/handler_locations_efs_test.go +++ b/services/datasync/handler_locations_efs_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_Efs covers the EFS location lifecycle. @@ -28,7 +30,7 @@ func TestDataSync_Efs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -36,7 +38,7 @@ func TestDataSync_Efs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, locArn, descResp["LocationArn"]) assert.Equal(t, "TLS1_2", descResp["InTransitEncryption"]) assert.Contains(t, descResp["LocationUri"].(string), "efs://") diff --git a/services/datasync/handler_locations_fsxlustre_test.go b/services/datasync/handler_locations_fsxlustre_test.go index 6b9081886b..cdb33839bf 100644 --- a/services/datasync/handler_locations_fsxlustre_test.go +++ b/services/datasync/handler_locations_fsxlustre_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_FsxLustre covers the FSx Lustre location lifecycle. @@ -24,7 +26,7 @@ func TestDataSync_FsxLustre(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -32,7 +34,7 @@ func TestDataSync_FsxLustre(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) // "fsxl://", not the bare "lustre://" real AWS's LocationUri pattern // (`^(efs|nfs|s3|smb|hdfs|fsx[a-z0-9-]+)://...$`) rules out -- see // fsxLustreURIScheme. diff --git a/services/datasync/handler_locations_fsxontap_test.go b/services/datasync/handler_locations_fsxontap_test.go index 92917d6b1d..91e5d06262 100644 --- a/services/datasync/handler_locations_fsxontap_test.go +++ b/services/datasync/handler_locations_fsxontap_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_FsxOntap covers the FSx ONTAP location lifecycle. @@ -29,7 +31,7 @@ func TestDataSync_FsxOntap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -37,7 +39,7 @@ func TestDataSync_FsxOntap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) // NFS protocol -> "nfs://" scheme (ONTAP has no distinct "ontap://" or // "fsxn://" scheme; DataSync reuses the underlying access protocol's own // scheme, matching how FSx Windows reuses "smb://" -- see @@ -57,7 +59,7 @@ func TestDataSync_FsxOntap(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) rec = doRequest(t, h, "DescribeLocationFsxOntap", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "smb://") // Missing StorageVirtualMachineArn diff --git a/services/datasync/handler_locations_fsxopenzfs_test.go b/services/datasync/handler_locations_fsxopenzfs_test.go index 8e8430085d..a0c2678ec2 100644 --- a/services/datasync/handler_locations_fsxopenzfs_test.go +++ b/services/datasync/handler_locations_fsxopenzfs_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_FsxOpenZfs covers the FSx OpenZFS location lifecycle. @@ -29,7 +31,7 @@ func TestDataSync_FsxOpenZfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -37,7 +39,7 @@ func TestDataSync_FsxOpenZfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "fsxz://") // The real DescribeLocationFsxOpenZfsOutput has no FsxFilesystemArn field. assert.Nil(t, descResp["FsxFilesystemArn"]) diff --git a/services/datasync/handler_locations_fsxwindows_test.go b/services/datasync/handler_locations_fsxwindows_test.go index 450a5feb79..dafa9f0059 100644 --- a/services/datasync/handler_locations_fsxwindows_test.go +++ b/services/datasync/handler_locations_fsxwindows_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_FsxWindows covers the FSx Windows location lifecycle. @@ -27,7 +29,7 @@ func TestDataSync_FsxWindows(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -35,7 +37,7 @@ func TestDataSync_FsxWindows(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "smb://") assert.Equal(t, "CORP", descResp["Domain"]) assert.Equal(t, "svcuser", descResp["User"]) @@ -56,7 +58,7 @@ func TestDataSync_FsxWindows(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeLocationFsxWindows", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "NEWDOMAIN", descResp["Domain"]) // Missing FsxFilesystemArn diff --git a/services/datasync/handler_locations_hdfs_test.go b/services/datasync/handler_locations_hdfs_test.go index 5d95a0739b..8604ab7dc4 100644 --- a/services/datasync/handler_locations_hdfs_test.go +++ b/services/datasync/handler_locations_hdfs_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_Hdfs covers the HDFS location lifecycle. @@ -35,7 +37,7 @@ func TestDataSync_Hdfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -43,7 +45,7 @@ func TestDataSync_Hdfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "hdfs://") assert.Equal(t, "SIMPLE", descResp["AuthenticationType"]) assert.Equal(t, "hadoop", descResp["SimpleUser"]) @@ -62,7 +64,7 @@ func TestDataSync_Hdfs(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeLocationHdfs", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "newuser", descResp["SimpleUser"]) nameNodes := descResp["NameNodes"].([]any) require.Len(t, nameNodes, 1) diff --git a/services/datasync/handler_locations_nfs_test.go b/services/datasync/handler_locations_nfs_test.go index d757968c05..65d40f36ed 100644 --- a/services/datasync/handler_locations_nfs_test.go +++ b/services/datasync/handler_locations_nfs_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_Nfs covers the NFS location lifecycle. @@ -29,7 +31,7 @@ func TestDataSync_Nfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -37,7 +39,7 @@ func TestDataSync_Nfs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "nfs://") assert.NotNil(t, descResp["MountOptions"]) assert.NotNil(t, descResp["OnPremConfig"]) @@ -58,7 +60,7 @@ func TestDataSync_Nfs(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeLocationNfs", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) mo := descResp["MountOptions"].(map[string]any) assert.Equal(t, "NFS4_1", mo["Version"]) @@ -120,7 +122,7 @@ func TestDataSync_UpdateLocationNfs_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -132,7 +134,7 @@ func TestDataSync_UpdateLocationNfs_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantURI, descResp["LocationUri"]) }) } diff --git a/services/datasync/handler_locations_objectstorage_test.go b/services/datasync/handler_locations_objectstorage_test.go index de2fe86594..3584f4adbd 100644 --- a/services/datasync/handler_locations_objectstorage_test.go +++ b/services/datasync/handler_locations_objectstorage_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_ObjectStorage covers the ObjectStorage location lifecycle. @@ -30,7 +32,7 @@ func TestDataSync_ObjectStorage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -38,7 +40,7 @@ func TestDataSync_ObjectStorage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "object-storage://") assert.Equal(t, "HTTPS", descResp["ServerProtocol"]) // SecretKey not returned @@ -59,7 +61,7 @@ func TestDataSync_ObjectStorage(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeLocationObjectStorage", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "HTTP", descResp["ServerProtocol"]) // Missing ServerHostname @@ -127,7 +129,7 @@ func TestDataSync_UpdateLocationObjectStorage_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -139,7 +141,7 @@ func TestDataSync_UpdateLocationObjectStorage_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantURI, descResp["LocationUri"]) if proto, isSet := tt.update["ServerProtocol"]; isSet { diff --git a/services/datasync/handler_locations_secretconfig_test.go b/services/datasync/handler_locations_secretconfig_test.go index 659d399069..ee7201640a 100644 --- a/services/datasync/handler_locations_secretconfig_test.go +++ b/services/datasync/handler_locations_secretconfig_test.go @@ -1,7 +1,7 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -126,7 +127,7 @@ func TestDataSync_SecretConfig_CmkRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -134,7 +135,7 @@ func TestDataSync_SecretConfig_CmkRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "describe: %s", rec.Body.String()) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) cmk, ok := descResp["CmkSecretConfig"].(map[string]any) require.True(t, ok, "CmkSecretConfig missing from describe response: %v", descResp) @@ -166,7 +167,7 @@ func TestDataSync_SecretConfig_CustomRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -174,7 +175,7 @@ func TestDataSync_SecretConfig_CustomRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "describe: %s", rec.Body.String()) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) custom, ok := descResp["CustomSecretConfig"].(map[string]any) require.True(t, ok, "CustomSecretConfig missing from describe response: %v", descResp) @@ -239,7 +240,7 @@ func TestDataSync_Smb_KerberosAndDNS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -247,7 +248,7 @@ func TestDataSync_Smb_KerberosAndDNS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "KERBEROS", descResp["AuthenticationType"]) assert.Equal(t, "HOST/kerberosuser@MYDOMAIN.ORG", descResp["KerberosPrincipal"]) @@ -269,7 +270,7 @@ func TestDataSync_Smb_KerberosAndDNS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) rec = doRequest(t, h, "DescribeLocationSmb", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "HOST/other@MYDOMAIN.ORG", descResp["KerberosPrincipal"]) dns, ok = descResp["DnsIpAddresses"].([]any) @@ -322,12 +323,12 @@ func TestDataSync_Smb_AuthenticationTypeEnum(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) rec = doRequest(t, h, "DescribeLocationSmb", map[string]any{"LocationArn": locArn}) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.expectEchoedAs, descResp["AuthenticationType"]) }) } diff --git a/services/datasync/handler_locations_smb_test.go b/services/datasync/handler_locations_smb_test.go index 2200920fa9..8cf9c62d82 100644 --- a/services/datasync/handler_locations_smb_test.go +++ b/services/datasync/handler_locations_smb_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDataSync_Smb covers the SMB location lifecycle. @@ -29,7 +31,7 @@ func TestDataSync_Smb(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) // Describe @@ -37,7 +39,7 @@ func TestDataSync_Smb(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "smb://") assert.Equal(t, "CORP", descResp["Domain"]) assert.Equal(t, "smbuser", descResp["User"]) @@ -62,7 +64,7 @@ func TestDataSync_Smb(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeLocationSmb", map[string]any{"LocationArn": locArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "NEWDOMAIN", descResp["Domain"]) mo := descResp["MountOptions"].(map[string]any) assert.Equal(t, "AUTOMATIC", mo["Version"]) @@ -129,7 +131,7 @@ func TestDataSync_UpdateLocationSmb_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn, ok := createResp["LocationArn"].(string) require.True(t, ok) @@ -141,7 +143,7 @@ func TestDataSync_UpdateLocationSmb_ServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantURI, descResp["LocationUri"]) if domain, isSet := tt.update["Domain"]; isSet { diff --git a/services/datasync/handler_locations_test.go b/services/datasync/handler_locations_test.go index c611b115e1..84011e8154 100644 --- a/services/datasync/handler_locations_test.go +++ b/services/datasync/handler_locations_test.go @@ -1,13 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -36,7 +37,7 @@ func TestDataSync_LocationS3(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["LocationArn"], "arn:aws:datasync:us-east-1:000000000000:location/") }, }, @@ -76,7 +77,7 @@ func TestDataSync_LocationS3(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) locs, ok := resp["Locations"].([]any) require.True(t, ok) assert.Empty(t, locs) @@ -114,14 +115,14 @@ func TestDataSync_LocationS3CRUD(t *testing.T) { rec := doRequest(t, h, "DescribeLocationS3", map[string]any{"LocationArn": locationArn}) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Contains(t, descResp["LocationUri"].(string), "s3://my-test-bucket/") // List rec = doRequest(t, h, "ListLocations", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Locations"], 1) // Delete @@ -195,14 +196,14 @@ func TestDataSync_LocationS3AgentArns(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) locArn := createResp["LocationArn"].(string) rec = doRequest(t, h, "DescribeLocationS3", map[string]any{"LocationArn": locArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) agentArns, ok := descResp["AgentArns"].([]any) require.True(t, ok) require.Len(t, agentArns, 1) diff --git a/services/datasync/handler_tags_test.go b/services/datasync/handler_tags_test.go index 5d074051a9..9b51cc36fe 100644 --- a/services/datasync/handler_tags_test.go +++ b/services/datasync/handler_tags_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDataSync_Tags(t *testing.T) { @@ -30,7 +32,7 @@ func TestDataSync_Tags(t *testing.T) { rec = doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": agentArn}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 2) @@ -44,7 +46,7 @@ func TestDataSync_Tags(t *testing.T) { // Verify untag rec = doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": agentArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags = listResp["Tags"].([]any) assert.Len(t, tags, 1) @@ -79,7 +81,7 @@ func TestDataSync_TagsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) require.True(t, ok) @@ -102,7 +104,7 @@ func TestDataSync_TagsRoundTrip(t *testing.T) { rec = doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": agentArn}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok = listResp["Tags"].([]any) require.True(t, ok) diff --git a/services/datasync/handler_tasks_test.go b/services/datasync/handler_tasks_test.go index d2f28e65e1..141727c413 100644 --- a/services/datasync/handler_tasks_test.go +++ b/services/datasync/handler_tasks_test.go @@ -1,13 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -53,7 +54,7 @@ func TestDataSync_Task(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) tasks, ok := resp["Tasks"].([]any) require.True(t, ok) assert.Empty(t, tasks) @@ -91,7 +92,7 @@ func TestDataSync_TaskCRUD(t *testing.T) { rec := doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "AVAILABLE", descResp["Status"]) assert.Equal(t, "test-task", descResp["Name"]) @@ -101,14 +102,14 @@ func TestDataSync_TaskCRUD(t *testing.T) { // Verify update rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "renamed-task", descResp["Name"]) // List rec = doRequest(t, h, "ListTasks", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Tasks"], 1) // Delete @@ -131,7 +132,7 @@ func TestDataSync_TaskExecution(t *testing.T) { rec := doRequest(t, h, "StartTaskExecution", map[string]any{"TaskArn": taskArn}) assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn, ok := startResp["TaskExecutionArn"].(string) require.True(t, ok) assert.Contains(t, execArn, "/execution/") @@ -144,7 +145,7 @@ func TestDataSync_TaskExecution(t *testing.T) { rec = doRequest(t, h, "ListTaskExecutions", map[string]any{"TaskArn": taskArn}) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["TaskExecutions"], 1) // CancelTaskExecution on an execution already settled into SUCCESS (by @@ -155,7 +156,7 @@ func TestDataSync_TaskExecution(t *testing.T) { // List after the rejected cancel - execution is unchanged, still SUCCESS. rec = doRequest(t, h, "ListTaskExecutions", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) execs, ok := listResp["TaskExecutions"].([]any) require.True(t, ok) require.Len(t, execs, 1) @@ -186,7 +187,7 @@ func TestDataSync_UpdateTaskExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) tests := []struct { @@ -237,7 +238,7 @@ func TestDataSync_UpdateTaskExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var startResp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &startResp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &startResp2, jsonx.V1())) execArn2 := startResp2["TaskExecutionArn"].(string) updRec := doRequest(t, h, "UpdateTaskExecution", map[string]any{ @@ -253,7 +254,7 @@ func TestDataSync_UpdateTaskExecution(t *testing.T) { Options map[string]any `json:"Options"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.InDelta(t, float64(2097152), descResp.Options["BytesPerSecond"], 0) for _, tc := range tests { @@ -280,7 +281,7 @@ func TestDataSync_CancelTaskExecutionStatusChange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) // Cancel. @@ -292,7 +293,7 @@ func TestDataSync_CancelTaskExecutionStatusChange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) execs, ok := listResp["TaskExecutions"].([]any) require.True(t, ok) @@ -351,7 +352,7 @@ func TestDataSync_CancelTaskExecution_RejectsTerminal(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) tt.settle(t, h, execArn) @@ -365,7 +366,7 @@ func TestDataSync_CancelTaskExecution_RejectsTerminal(t *testing.T) { rec = doRequest(t, h, "DescribeTaskExecution", map[string]any{"TaskExecutionArn": execArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantErr, descResp["Status"]) }) } @@ -385,7 +386,7 @@ func TestDataSync_DescribeTaskExecutionLazyAdvance(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) // Before describe: execution exists as LAUNCHING in list. @@ -393,7 +394,7 @@ func TestDataSync_DescribeTaskExecutionLazyAdvance(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) execs := listResp["TaskExecutions"].([]any) require.Len(t, execs, 1) @@ -431,7 +432,7 @@ func TestDataSync_StartTaskExecutionRejectsConcurrent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) // Second start while the first execution is still LAUNCHING must fail. @@ -462,24 +463,24 @@ func TestDataSync_TaskStatusRunningWhileExecuting(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var taskResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp, jsonx.V1())) assert.Equal(t, "AVAILABLE", taskResp["Status"]) rec = doRequest(t, h, "StartTaskExecution", map[string]any{"TaskArn": taskArn}) require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["TaskExecutionArn"].(string) rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp, jsonx.V1())) assert.Equal(t, "RUNNING", taskResp["Status"]) settleExecution(t, h, execArn) rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp, jsonx.V1())) assert.Equal(t, "AVAILABLE", taskResp["Status"]) } @@ -522,14 +523,14 @@ func TestDataSync_TaskSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskArn := createResp["TaskArn"].(string) rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) opts, ok := descResp["Options"].(map[string]any) require.True(t, ok) @@ -571,7 +572,7 @@ func TestDataSync_TaskSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "settings-task-renamed", descResp["Name"]) opts, ok = descResp["Options"].(map[string]any) require.True(t, ok) @@ -587,7 +588,7 @@ func TestDataSync_TaskSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = doRequest(t, h, "DescribeTask", map[string]any{"TaskArn": taskArn}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) excludes, ok = descResp["Excludes"].([]any) require.True(t, ok) require.Len(t, excludes, 1) @@ -609,7 +610,7 @@ func TestDataSync_TaskModeDefaultsToBasic(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "BASIC", descResp["TaskMode"]) } @@ -635,7 +636,7 @@ func TestDataSync_ListTaskExecutionsAllTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) execs, ok := listResp["TaskExecutions"].([]any) require.True(t, ok) @@ -651,7 +652,7 @@ func settleExecution(t *testing.T, h *datasync.Handler, execArn string) map[stri rec := doRequest(t, h, "DescribeTaskExecution", map[string]any{"TaskExecutionArn": execArn}) require.Equal(t, http.StatusOK, rec.Code) out = map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if out["Status"] == "SUCCESS" { break @@ -670,7 +671,7 @@ func TestDataSync_TaskExecutionPhases(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var start map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) execArn := start["TaskExecutionArn"].(string) got := make([]string, 0, 5) @@ -678,7 +679,7 @@ func TestDataSync_TaskExecutionPhases(t *testing.T) { for range 5 { rec = doRequest(t, h, "DescribeTaskExecution", map[string]any{"TaskExecutionArn": execArn}) var d map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &d)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &d, jsonx.V1())) got = append(got, d["Status"].(string)) } diff --git a/services/datasync/handler_test.go b/services/datasync/handler_test.go index 7a682d0371..79919b786a 100644 --- a/services/datasync/handler_test.go +++ b/services/datasync/handler_test.go @@ -2,7 +2,7 @@ package datasync_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -30,7 +31,7 @@ func doRequest(t *testing.T, h *datasync.Handler, action string, body any) *http if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -56,7 +57,7 @@ func createTestAgent(t *testing.T, h *datasync.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["AgentArn"].(string) require.True(t, ok) @@ -77,7 +78,7 @@ func createTestLocationS3(t *testing.T, h *datasync.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["LocationArn"].(string) require.True(t, ok) @@ -96,7 +97,7 @@ func createTestTask(t *testing.T, h *datasync.Handler, srcArn, dstArn string) st require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["TaskArn"].(string) require.True(t, ok) @@ -185,7 +186,7 @@ func TestDataSync_NotFoundReturnsInvalidRequest(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "expected 400 for %s with unknown ARN", tt.action) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["__type"]) }) } diff --git a/services/datasync/persistence.go b/services/datasync/persistence.go index b946dab075..8ded002749 100644 --- a/services/datasync/persistence.go +++ b/services/datasync/persistence.go @@ -2,7 +2,7 @@ package datasync import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -31,7 +31,7 @@ const datasyncSnapshotVersion = 1 // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/datasync/validation.go b/services/datasync/validation.go index 6f3facf08e..d3d40a3fde 100644 --- a/services/datasync/validation.go +++ b/services/datasync/validation.go @@ -1,7 +1,7 @@ package datasync import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" @@ -9,6 +9,7 @@ import ( dstypes "github.com/aws/aws-sdk-go-v2/service/datasync/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -115,7 +116,7 @@ func describeNotFound(err error, body []byte) error { } var fields map[string]any - if json.Unmarshal(body, &fields) != nil { + if json.Unmarshal(body, &fields, jsonx.V1()) != nil { return err } diff --git a/services/datasync/validation_test.go b/services/datasync/validation_test.go index 0783e48a3e..5278fda462 100644 --- a/services/datasync/validation_test.go +++ b/services/datasync/validation_test.go @@ -1,12 +1,14 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDataSync_RequestValidation(t *testing.T) { @@ -86,7 +88,7 @@ func TestDataSync_RequestValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "InvalidRequestException", out["__type"]) assert.Contains(t, out["message"], tt.wantMsg) assert.NotContains(t, out["message"], "InvalidRequestException:") @@ -106,7 +108,7 @@ func TestDataSync_ResourceIDFormats(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var start map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) tests := []struct { name string diff --git a/services/datasync/wire_field_fixes_test.go b/services/datasync/wire_field_fixes_test.go index 9ce0c91ea0..606391660f 100644 --- a/services/datasync/wire_field_fixes_test.go +++ b/services/datasync/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package datasync_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/datasync" ) @@ -169,7 +170,7 @@ func TestListLocations_NoFabricatedCreationTime(t *testing.T) { var resp struct { Locations []map[string]any `json:"Locations"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Locations, 1, "must exercise a non-empty collection") _, hasCreationTime := resp.Locations[0]["CreationTime"] diff --git a/services/dax/handler_clusters.go b/services/dax/handler_clusters.go index 8829275065..2ef509884d 100644 --- a/services/dax/handler_clusters.go +++ b/services/dax/handler_clusters.go @@ -1,10 +1,11 @@ package dax import ( - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createClusterRequest struct { @@ -205,7 +206,7 @@ func toClusterResponse(c *Cluster) clusterResponse { func (h *Handler) handleCreateCluster(body []byte) (any, error) { var req createClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -247,7 +248,7 @@ func (h *Handler) handleCreateCluster(body []byte) (any, error) { func (h *Handler) handleDescribeClusters(body []byte) (any, error) { var req describeClustersRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -279,7 +280,7 @@ func (h *Handler) handleDescribeClusters(body []byte) (any, error) { func (h *Handler) handleUpdateCluster(body []byte) (any, error) { var req updateClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -295,7 +296,7 @@ func (h *Handler) handleUpdateCluster(body []byte) (any, error) { func (h *Handler) handleDeleteCluster(body []byte) (any, error) { var req deleteClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -311,7 +312,7 @@ func (h *Handler) handleDeleteCluster(body []byte) (any, error) { func (h *Handler) handleIncreaseReplicationFactor(body []byte) (any, error) { var req increaseReplicationFactorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -327,7 +328,7 @@ func (h *Handler) handleIncreaseReplicationFactor(body []byte) (any, error) { func (h *Handler) handleDecreaseReplicationFactor(body []byte) (any, error) { var req decreaseReplicationFactorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -343,7 +344,7 @@ func (h *Handler) handleDecreaseReplicationFactor(body []byte) (any, error) { func (h *Handler) handleRebootNode(body []byte) (any, error) { var req rebootNodeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/dax/handler_clusters_test.go b/services/dax/handler_clusters_test.go index 3c42f2672d..aefd34ab8a 100644 --- a/services/dax/handler_clusters_test.go +++ b/services/dax/handler_clusters_test.go @@ -1,13 +1,14 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -81,7 +82,7 @@ func TestHandlerCreateCluster(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -104,7 +105,7 @@ func TestHandlerClusterResponseHasNoTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) _, hasTags := cluster["Tags"] assert.False(t, hasTags, "Cluster response must not include a Tags field") @@ -122,7 +123,7 @@ func TestHandlerCreateCluster_Duplicate(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ClusterAlreadyExistsFault", errResp["__type"]) } @@ -164,7 +165,7 @@ func TestHandlerDescribeClusters(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) assert.Len(t, clusters, tt.wantCount) }) @@ -237,7 +238,7 @@ func TestHandlerUpdateCluster(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -351,7 +352,7 @@ func TestHandlerReplicationFactor(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -407,7 +408,7 @@ func TestHandlerRebootNode(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) diff --git a/services/dax/handler_events.go b/services/dax/handler_events.go index e4dc4b3067..9ee9600be7 100644 --- a/services/dax/handler_events.go +++ b/services/dax/handler_events.go @@ -1,21 +1,22 @@ package dax import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type describeEventsRequest struct { - SourceName string `json:"SourceName"` - SourceType string `json:"SourceType"` - StartTime json.Number `json:"StartTime"` - EndTime json.Number `json:"EndTime"` - NextToken string `json:"NextToken"` - MaxResults int `json:"MaxResults"` - Duration int `json:"Duration"` // minutes to look back; applied when StartTime is absent + SourceName string `json:"SourceName"` + SourceType string `json:"SourceType"` + StartTime jsonx.Number `json:"StartTime"` + EndTime jsonx.Number `json:"EndTime"` + NextToken string `json:"NextToken"` + MaxResults int `json:"MaxResults"` + Duration int `json:"Duration"` // minutes to look back; applied when StartTime is absent } type eventResponse struct { @@ -30,7 +31,7 @@ type eventResponse struct { // awsjson1.1 Timestamp wire format DAX uses -- see smithytime.ParseEpochSeconds // in the real SDK deserializer) into a time.Time, preserving sub-second // precision carried in the fractional part. -func parseEpochSeconds(n json.Number) (time.Time, error) { +func parseEpochSeconds(n jsonx.Number) (time.Time, error) { f, err := n.Float64() if err != nil { return time.Time{}, fmt.Errorf("%w: %w", errInvalidRequest, err) @@ -45,7 +46,7 @@ func parseEpochSeconds(n json.Number) (time.Time, error) { func (h *Handler) handleDescribeEvents(body []byte) (any, error) { var req describeEventsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/dax/handler_events_test.go b/services/dax/handler_events_test.go index 3a5f996aa6..35e2395c2c 100644 --- a/services/dax/handler_events_test.go +++ b/services/dax/handler_events_test.go @@ -1,13 +1,14 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -61,7 +62,7 @@ func TestHandlerDescribeEvents(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) diff --git a/services/dax/handler_parameter_groups.go b/services/dax/handler_parameter_groups.go index e71ffe49c4..5301481fe0 100644 --- a/services/dax/handler_parameter_groups.go +++ b/services/dax/handler_parameter_groups.go @@ -1,8 +1,10 @@ package dax import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createParameterGroupRequest struct { @@ -81,7 +83,7 @@ func toParameterResponse(p *Parameter) parameterResponse { func (h *Handler) handleCreateParameterGroup(body []byte) (any, error) { var req createParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -101,7 +103,7 @@ func (h *Handler) handleCreateParameterGroup(body []byte) (any, error) { func (h *Handler) handleDescribeParameterGroups(body []byte) (any, error) { var req describeParameterGroupsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -136,7 +138,7 @@ func (h *Handler) handleDescribeParameterGroups(body []byte) (any, error) { func (h *Handler) handleUpdateParameterGroup(body []byte) (any, error) { var req updateParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -169,7 +171,7 @@ func (h *Handler) handleUpdateParameterGroup(body []byte) (any, error) { func (h *Handler) handleDeleteParameterGroup(body []byte) (any, error) { var req deleteParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -184,7 +186,7 @@ func (h *Handler) handleDeleteParameterGroup(body []byte) (any, error) { func (h *Handler) handleDescribeParameters(body []byte) (any, error) { var req describeParametersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -217,7 +219,7 @@ func (h *Handler) handleDescribeParameters(body []byte) (any, error) { func (h *Handler) handleDescribeDefaultParameters(body []byte) (any, error) { var req describeDefaultParametersRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -245,7 +247,7 @@ func (h *Handler) handleDescribeDefaultParameters(body []byte) (any, error) { func (h *Handler) handleResetParameterGroup(body []byte) (any, error) { var req resetParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/dax/handler_parameter_groups_test.go b/services/dax/handler_parameter_groups_test.go index fb2cbd0ce4..ec2f21fc7e 100644 --- a/services/dax/handler_parameter_groups_test.go +++ b/services/dax/handler_parameter_groups_test.go @@ -1,13 +1,14 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -120,7 +121,7 @@ func TestHandlerParameterGroups(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -141,6 +142,6 @@ func TestHandlerUpdateParameterGroupRequiresParameterNameValues(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["__type"]) } diff --git a/services/dax/handler_subnet_groups.go b/services/dax/handler_subnet_groups.go index 329db1682e..6df9bf1fa3 100644 --- a/services/dax/handler_subnet_groups.go +++ b/services/dax/handler_subnet_groups.go @@ -1,8 +1,10 @@ package dax import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createSubnetGroupRequest struct { @@ -66,7 +68,7 @@ func toSubnetGroupResponse(sg *SubnetGroup) subnetGroupResponse { func (h *Handler) handleCreateSubnetGroup(body []byte) (any, error) { var req createSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -83,7 +85,7 @@ func (h *Handler) handleCreateSubnetGroup(body []byte) (any, error) { func (h *Handler) handleDescribeSubnetGroups(body []byte) (any, error) { var req describeSubnetGroupsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -115,7 +117,7 @@ func (h *Handler) handleDescribeSubnetGroups(body []byte) (any, error) { func (h *Handler) handleUpdateSubnetGroup(body []byte) (any, error) { var req updateSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -131,7 +133,7 @@ func (h *Handler) handleUpdateSubnetGroup(body []byte) (any, error) { func (h *Handler) handleDeleteSubnetGroup(body []byte) (any, error) { var req deleteSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/dax/handler_subnet_groups_test.go b/services/dax/handler_subnet_groups_test.go index 741846be9e..7d0900e432 100644 --- a/services/dax/handler_subnet_groups_test.go +++ b/services/dax/handler_subnet_groups_test.go @@ -1,13 +1,14 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -104,7 +105,7 @@ func TestHandlerSubnetGroups(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -126,7 +127,7 @@ func TestHandlerSubnetGroupSubnetHasSupportedNetworkTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sg := resp["SubnetGroup"].(map[string]any) subnets := sg["Subnets"].([]any) require.Len(t, subnets, 1) diff --git a/services/dax/handler_tags.go b/services/dax/handler_tags.go index 6bb5336ea3..0e4f4cdb01 100644 --- a/services/dax/handler_tags.go +++ b/services/dax/handler_tags.go @@ -1,10 +1,12 @@ package dax import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceRequest struct { @@ -24,7 +26,7 @@ type listTagsRequest struct { func (h *Handler) handleTagResource(body []byte) (any, error) { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -60,7 +62,7 @@ func (h *Handler) handleTagResource(body []byte) (any, error) { func (h *Handler) handleUntagResource(body []byte) (any, error) { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -87,7 +89,7 @@ func (h *Handler) handleUntagResource(body []byte) (any, error) { func (h *Handler) handleListTags(body []byte) (any, error) { var req listTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/dax/handler_tags_test.go b/services/dax/handler_tags_test.go index 8ff61accca..f96af9c0bc 100644 --- a/services/dax/handler_tags_test.go +++ b/services/dax/handler_tags_test.go @@ -1,7 +1,7 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -29,7 +30,7 @@ func TestHandlerTagResource(t *testing.T) { t.Helper() rec := daxRequest(t, h, "CreateCluster", validClusterBody("tagged-cluster")) var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["Cluster"].(map[string]any)["ClusterArn"].(string) }, @@ -72,14 +73,14 @@ func TestHandlerTagResourceRequiresTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) rec := daxRequest(t, h, "TagResource", map[string]any{"ResourceName": arn}) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["__type"]) } @@ -94,14 +95,14 @@ func TestHandlerUntagResourceRequiresTagKeys(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) rec := daxRequest(t, h, "UntagResource", map[string]any{"ResourceName": arn}) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["__type"]) } @@ -113,7 +114,7 @@ func TestHandlerListTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) tagRec := daxRequest(t, h, "TagResource", map[string]any{ @@ -126,7 +127,7 @@ func TestHandlerListTags(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) assert.NotEmpty(t, tags) } @@ -204,7 +205,7 @@ func TestHandlerCreateClusterTagsAsArray(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.checkTag != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) // The Cluster response carries no Tags field (real AWS has none on @@ -215,7 +216,7 @@ func TestHandlerCreateClusterTagsAsArray(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rawTags := listResp["Tags"].([]any) found := false for _, rt := range rawTags { @@ -287,7 +288,7 @@ func TestHandlerTagResourceValidation(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) rec := daxRequest(t, h, "TagResource", map[string]any{ @@ -300,7 +301,7 @@ func TestHandlerTagResourceValidation(t *testing.T) { } else { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantCode, errResp["__type"]) } }) @@ -317,7 +318,7 @@ func TestHandlerTagResourceQuotaExceeded(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) // Add 50 tags in two batches of 25. @@ -345,7 +346,7 @@ func TestHandlerTagResourceQuotaExceeded(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "TagQuotaPerResourceExceeded", errResp["__type"]) } @@ -359,7 +360,7 @@ func TestHandlerTagResourceReturnsAllTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) // Add first tag. @@ -377,7 +378,7 @@ func TestHandlerTagResourceReturnsAllTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) rawTags := resp["Tags"].([]any) assert.Len(t, rawTags, 2, "TagResource must return all tags on the resource, not just added ones") @@ -402,7 +403,7 @@ func TestHandlerUntagResourceReturnsRemainingTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Cluster"].(map[string]any)["ClusterArn"].(string) tagRec := daxRequest(t, h, "TagResource", map[string]any{ @@ -418,7 +419,7 @@ func TestHandlerUntagResourceReturnsRemainingTags(t *testing.T) { require.Equal(t, http.StatusOK, untagRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(untagRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(untagRec.Body.Bytes(), &resp, jsonx.V1())) rawTags, ok := resp["Tags"].([]any) require.True(t, ok, "UntagResource must return Tags in response") diff --git a/services/dax/handler_test.go b/services/dax/handler_test.go index 4fbde0373c..521e00da74 100644 --- a/services/dax/handler_test.go +++ b/services/dax/handler_test.go @@ -2,7 +2,8 @@ package dax_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -26,7 +28,7 @@ func daxRequest(t *testing.T, h *dax.Handler, target string, body any) *httptest var buf bytes.Buffer if body != nil { - require.NoError(t, json.NewEncoder(&buf).Encode(body)) + require.NoError(t, json.MarshalEncode(jsontext.NewEncoder(&buf, jsonx.V1()), body)) } req := httptest.NewRequest(http.MethodPost, "/", &buf) @@ -163,7 +165,7 @@ func TestHandlerErrorMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantCode, errResp["__type"]) }) } @@ -183,7 +185,7 @@ func TestHandlerCreateSubnetGroupNameNotFormatValidated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sg := resp["SubnetGroup"].(map[string]any) assert.Equal(t, "1sg--bad", sg["SubnetGroupName"]) } @@ -201,7 +203,7 @@ func TestHandlerReset(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) assert.Empty(t, clusters) } diff --git a/services/dax/handler_wire_shape_test.go b/services/dax/handler_wire_shape_test.go index c6014471a4..2a8b6583bd 100644 --- a/services/dax/handler_wire_shape_test.go +++ b/services/dax/handler_wire_shape_test.go @@ -1,7 +1,7 @@ package dax_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -25,7 +26,7 @@ func TestHandlerClusterStatusWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) assert.Equal(t, "creating", cluster["Status"], "wire key must be Status") @@ -48,7 +49,7 @@ func TestHandlerTimestampsAreEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) cluster := createResp["Cluster"].(map[string]any) nodes := cluster["Nodes"].([]any) @@ -63,7 +64,7 @@ func TestHandlerTimestampsAreEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, eventsRec.Code) var eventsResp map[string]any - require.NoError(t, json.Unmarshal(eventsRec.Body.Bytes(), &eventsResp)) + require.NoError(t, json.Unmarshal(eventsRec.Body.Bytes(), &eventsResp, jsonx.V1())) events := eventsResp["Events"].([]any) require.NotEmpty(t, events) @@ -93,7 +94,7 @@ func TestHandlerDescribeEventsAcceptsEpochSecondsRequest(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Events"], "a StartTime in the future should exclude all existing events") past := float64(time.Now().UTC().Add(-time.Hour).Unix()) @@ -104,7 +105,7 @@ func TestHandlerDescribeEventsAcceptsEpochSecondsRequest(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.NotEmpty(t, resp2["Events"], "a StartTime in the past should include existing events") } @@ -155,7 +156,7 @@ func TestHandlerParameterGroupNodeIdsToRebootWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) require.Len(t, clusters, 1) @@ -185,7 +186,7 @@ func TestHandlerClusterNetworkTypeWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) assert.Equal(t, "ipv4", cluster["NetworkType"]) @@ -211,7 +212,7 @@ func TestHandlerDecreaseReplicationFactorNodeIdsToRemoveWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) nodeIDs, ok := cluster["NodeIdsToRemove"].([]any) @@ -233,7 +234,7 @@ func TestHandlerSubnetGroupSupportedNetworkTypesWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sg := resp["SubnetGroup"].(map[string]any) types, ok := sg["SupportedNetworkTypes"].([]any) @@ -263,7 +264,7 @@ func TestHandlerDescribeParametersSourceFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) params := resp["Parameters"].([]any) require.Len(t, params, 1) diff --git a/services/dax/multi_region_test.go b/services/dax/multi_region_test.go index 98cc37b4ca..1bf2150652 100644 --- a/services/dax/multi_region_test.go +++ b/services/dax/multi_region_test.go @@ -2,7 +2,7 @@ package dax_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dax" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/dax/persistence.go b/services/dax/persistence.go index 4dfb239655..133a074a9e 100644 --- a/services/dax/persistence.go +++ b/services/dax/persistence.go @@ -2,11 +2,13 @@ package dax import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -37,7 +39,7 @@ const daxSnapshotVersion = 1 // (older or newer) build of this backend as though it were the current // shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -124,7 +126,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { b.mu.RLock("Snapshot") defer b.mu.RUnlock() - var tables map[string]json.RawMessage + var tables map[string]jsontext.Value tables, tblErr = b.registry.SnapshotAll() @@ -144,7 +146,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { return nil } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).ErrorContext(ctx, "dax: failed to marshal snapshot", "error", err) diff --git a/services/detective/handler_administrator.go b/services/detective/handler_administrator.go index a06fa50f95..0b8faa40b8 100644 --- a/services/detective/handler_administrator.go +++ b/services/detective/handler_administrator.go @@ -1,12 +1,13 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleStartMonitoringMember(c *echo.Context) error { @@ -20,7 +21,7 @@ func (h *Handler) handleStartMonitoringMember(c *echo.Context) error { AccountId string `json:"AccountId"` //nolint:revive,staticcheck // existing issue. } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -57,7 +58,7 @@ func (h *Handler) handleEnableOrganizationAdminAccount(c *echo.Context) error { AccountId string `json:"AccountId"` //nolint:revive,staticcheck // existing issue. } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -84,7 +85,7 @@ func (h *Handler) handleListOrganizationAdminAccounts(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } diff --git a/services/detective/handler_administrator_test.go b/services/detective/handler_administrator_test.go index 82d7560682..20b5725c1c 100644 --- a/services/detective/handler_administrator_test.go +++ b/services/detective/handler_administrator_test.go @@ -1,12 +1,14 @@ package detective_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetective_StartMonitoringMember(t *testing.T) { //nolint:paralleltest // existing issue. @@ -17,7 +19,7 @@ func TestDetective_StartMonitoringMember(t *testing.T) { //nolint:paralleltest / require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) // Add a member (status INVITED, not ACCEPTED_BUT_DISABLED). @@ -98,7 +100,7 @@ func TestOrganizationAdminAccounts(t *testing.T) { //nolint:paralleltest // exis check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) admins, ok := resp["Administrators"].([]any) require.True(t, ok) assert.Empty(t, admins) @@ -134,7 +136,7 @@ func TestOrganizationAdminAccounts(t *testing.T) { //nolint:paralleltest // exis check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) admins, ok := resp["Administrators"].([]any) require.True(t, ok) require.Len(t, admins, 1) @@ -158,7 +160,7 @@ func TestOrganizationAdminAccounts(t *testing.T) { //nolint:paralleltest // exis check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) admins, ok := resp["Administrators"].([]any) require.True(t, ok) assert.Empty(t, admins) diff --git a/services/detective/handler_datasource_packages.go b/services/detective/handler_datasource_packages.go index 5ae981c4c4..89ec997576 100644 --- a/services/detective/handler_datasource_packages.go +++ b/services/detective/handler_datasource_packages.go @@ -1,13 +1,14 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ingestHistoryToJSON encodes a MembershipDatasources.IngestHistory map to @@ -45,7 +46,7 @@ func (h *Handler) handleBatchGetGraphMemberDatasources(c *echo.Context) error { AccountIds []string `json:"AccountIds"` //nolint:revive // existing issue. } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -83,7 +84,7 @@ func (h *Handler) handleBatchGetMembershipDatasources(c *echo.Context) error { GraphArns []string `json:"GraphArns"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -127,7 +128,7 @@ func (h *Handler) handleListDatasourcePackages(c *echo.Context) error { MaxResults int32 `json:"MaxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -169,7 +170,7 @@ func (h *Handler) handleUpdateDatasourcePackages(c *echo.Context) error { DatasourcePackages []string `json:"DatasourcePackages"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/detective/handler_datasource_packages_test.go b/services/detective/handler_datasource_packages_test.go index 25f581746b..7982869ca7 100644 --- a/services/detective/handler_datasource_packages_test.go +++ b/services/detective/handler_datasource_packages_test.go @@ -2,12 +2,14 @@ package detective_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing issue. @@ -18,7 +20,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) // Add a member. @@ -46,7 +48,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) pkgs, ok := resp["DatasourcePackages"].(map[string]any) require.True(t, ok) assert.Contains(t, pkgs, "DETECTIVE_CORE") @@ -69,7 +71,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) pkgs, ok := resp["DatasourcePackages"].(map[string]any) require.True(t, ok) assert.Contains(t, pkgs, "DETECTIVE_CORE") @@ -84,7 +86,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) members, ok := resp["MemberDatasources"].([]any) require.True(t, ok) assert.Len(t, members, 1) @@ -99,7 +101,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedAccounts"].([]any) require.True(t, ok) assert.Len(t, unprocessed, 1) @@ -114,7 +116,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) members, ok := resp["MembershipDatasources"].([]any) require.True(t, ok) assert.Len(t, members, 1) @@ -133,7 +135,7 @@ func TestDetective_Datasources(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedGraphs"].([]any) require.True(t, ok) assert.Len(t, unprocessed, 1) @@ -195,7 +197,7 @@ func TestUpdateDatasourcePackages_InvalidPackageRejected(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/graph", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var gResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp, jsonx.V1())) graphARN := gResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/datasources/update", map[string]any{ @@ -223,7 +225,7 @@ func TestBatchGetGraphMemberDatasources_WireShape(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/graph", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var gResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp, jsonx.V1())) graphARN := gResp["GraphArn"].(string) memberRec := doRequest(t, h, http.MethodPost, "/graph/members", map[string]any{ @@ -247,7 +249,7 @@ func TestBatchGetGraphMemberDatasources_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) members, ok := resp["MemberDatasources"].([]any) require.True(t, ok) require.Len(t, members, 1) @@ -280,7 +282,7 @@ func TestListDatasourcePackagesOpaqueToken(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/graph", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var gResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gResp, jsonx.V1())) graphARN := gResp["GraphArn"].(string) updateRec := doRequest(t, h, http.MethodPost, "/graph/datasources/update", map[string]any{ @@ -295,7 +297,7 @@ func TestListDatasourcePackagesOpaqueToken(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tok, hasTok := resp["NextToken"].(string) require.True(t, hasTok, "NextToken must be present when more results exist") @@ -310,7 +312,7 @@ func TestListDatasourcePackagesOpaqueToken(t *testing.T) { }) require.Equal(t, http.StatusOK, rec3.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp2, jsonx.V1())) _, hasTok2 := resp2["NextToken"] assert.False(t, hasTok2, "NextToken must be absent on the last page") } diff --git a/services/detective/handler_graphs.go b/services/detective/handler_graphs.go index 3aed84dce6..6079dfdfe4 100644 --- a/services/detective/handler_graphs.go +++ b/services/detective/handler_graphs.go @@ -1,12 +1,13 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateGraph(c *echo.Context) error { @@ -20,7 +21,7 @@ func (h *Handler) handleCreateGraph(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } @@ -45,7 +46,7 @@ func (h *Handler) handleDeleteGraph(c *echo.Context) error { GraphArn string `json:"GraphArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -72,7 +73,7 @@ func (h *Handler) handleListGraphs(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } diff --git a/services/detective/handler_graphs_test.go b/services/detective/handler_graphs_test.go index 94749787c4..568002faee 100644 --- a/services/detective/handler_graphs_test.go +++ b/services/detective/handler_graphs_test.go @@ -2,7 +2,7 @@ package detective_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/detective" ) @@ -32,7 +33,7 @@ func TestDetective_Graph(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Contains(t, resp["GraphArn"], "arn:aws:detective:") }, }, @@ -48,7 +49,7 @@ func TestDetective_Graph(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Contains(t, resp["GraphArn"], "arn:aws:detective:") }, }, @@ -86,7 +87,7 @@ func TestDetective_Graph(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) list, ok := resp["GraphList"].([]any) require.True(t, ok) assert.Empty(t, list) @@ -104,7 +105,7 @@ func TestDetective_Graph(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) list, ok := resp["GraphList"].([]any) require.True(t, ok) assert.Len(t, list, 1) @@ -125,7 +126,7 @@ func TestDetective_Graph(t *testing.T) { //nolint:paralleltest // existing issue // get graphArn from listing listRec := doRequest(t, h, http.MethodPost, "/graphs/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) list := listResp["GraphList"].([]any) if len(list) > 0 { graph := list[0].(map[string]any) @@ -158,7 +159,7 @@ func TestGraphARN_Shape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["GraphArn"].(string) require.NotEmpty(t, arn, "CreateGraph must return a GraphArn") @@ -187,7 +188,7 @@ func TestListGraphs_CreatedTime_Present(t *testing.T) { } `json:"GraphList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.GraphList, 1) assert.NotEmpty(t, resp.GraphList[0].CreatedTime, "ListGraphs must include CreatedTime") assert.Contains(t, resp.GraphList[0].CreatedTime, "T", @@ -209,7 +210,7 @@ func TestListGraphs_Pagination_NextToken_Absent_When_All_Fit(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasToken := resp["NextToken"] assert.False(t, hasToken, "NextToken must be absent when all results fit on one page") } diff --git a/services/detective/handler_investigations.go b/services/detective/handler_investigations.go index 0d6eea760f..3146a8654c 100644 --- a/services/detective/handler_investigations.go +++ b/services/detective/handler_investigations.go @@ -1,12 +1,13 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleStartInvestigation(c *echo.Context) error { @@ -22,7 +23,7 @@ func (h *Handler) handleStartInvestigation(c *echo.Context) error { ScopeEndTime string `json:"ScopeEndTime"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -73,7 +74,7 @@ func (h *Handler) handleGetInvestigation(c *echo.Context) error { InvestigationId string `json:"InvestigationId"` //nolint:revive,staticcheck // existing issue. } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -130,7 +131,7 @@ func (h *Handler) handleListInvestigations(c *echo.Context) error { MaxResults int32 `json:"MaxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -203,7 +204,7 @@ func (h *Handler) handleUpdateInvestigationState(c *echo.Context) error { State string `json:"State"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -240,7 +241,7 @@ func (h *Handler) handleListIndicators(c *echo.Context) error { MaxResults int32 `json:"MaxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/detective/handler_investigations_test.go b/services/detective/handler_investigations_test.go index 32ac23e60c..6721542c04 100644 --- a/services/detective/handler_investigations_test.go +++ b/services/detective/handler_investigations_test.go @@ -2,12 +2,14 @@ package detective_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetective_Investigations(t *testing.T) { //nolint:paralleltest // existing issue. @@ -18,7 +20,7 @@ func TestDetective_Investigations(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) unknownArn := missingGraphARN @@ -79,7 +81,7 @@ func TestDetective_Investigations(t *testing.T) { //nolint:paralleltest // exist check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["InvestigationId"]) }, }, @@ -92,7 +94,7 @@ func TestDetective_Investigations(t *testing.T) { //nolint:paralleltest // exist check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) details, ok := resp["InvestigationDetails"].([]any) require.True(t, ok) assert.Len(t, details, 1) @@ -183,7 +185,7 @@ func TestDetective_InvestigationGetAndUpdate(t *testing.T) { //nolint:parallelte require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) // Start investigation. @@ -196,7 +198,7 @@ func TestDetective_InvestigationGetAndUpdate(t *testing.T) { //nolint:parallelte require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) invID := startResp["InvestigationId"].(string) require.NotEmpty(t, invID) @@ -217,7 +219,7 @@ func TestDetective_InvestigationGetAndUpdate(t *testing.T) { //nolint:parallelte check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, invID, resp["InvestigationId"]) assert.Equal(t, graphArn, resp["GraphArn"]) assert.Equal(t, "arn:aws:iam::000000000000:user/alice", resp["EntityArn"]) @@ -241,7 +243,7 @@ func TestDetective_InvestigationGetAndUpdate(t *testing.T) { //nolint:parallelte check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ARCHIVED", resp["State"]) }, }, @@ -254,7 +256,7 @@ func TestDetective_InvestigationGetAndUpdate(t *testing.T) { //nolint:parallelte check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) indicators, ok := resp["Indicators"].([]any) require.True(t, ok) assert.NotEmpty(t, indicators, "ListIndicators should return indicators for an investigation") diff --git a/services/detective/handler_members.go b/services/detective/handler_members.go index 56dc17a52e..3d43acc8ec 100644 --- a/services/detective/handler_members.go +++ b/services/detective/handler_members.go @@ -1,12 +1,13 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateMembers(c *echo.Context) error { @@ -24,7 +25,7 @@ func (h *Handler) handleCreateMembers(c *echo.Context) error { } `json:"Accounts"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -62,7 +63,7 @@ func (h *Handler) handleDeleteMembers(c *echo.Context) error { AccountIDs []string `json:"AccountIds"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -92,7 +93,7 @@ func (h *Handler) handleGetMembers(c *echo.Context) error { AccountIDs []string `json:"AccountIds"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -123,7 +124,7 @@ func (h *Handler) handleListMembers(c *echo.Context) error { MaxResults int32 `json:"MaxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -156,7 +157,7 @@ func (h *Handler) handleAcceptInvitation(c *echo.Context) error { GraphArn string `json:"GraphArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -181,7 +182,7 @@ func (h *Handler) handleRejectInvitation(c *echo.Context) error { GraphArn string `json:"GraphArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -208,7 +209,7 @@ func (h *Handler) handleListInvitations(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } @@ -238,7 +239,7 @@ func (h *Handler) handleDisassociateMembership(c *echo.Context) error { GraphArn string `json:"GraphArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/detective/handler_members_test.go b/services/detective/handler_members_test.go index c9cae3d32a..41085827d9 100644 --- a/services/detective/handler_members_test.go +++ b/services/detective/handler_members_test.go @@ -2,13 +2,15 @@ package detective_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetective_Members(t *testing.T) { //nolint:paralleltest // existing issue. @@ -96,7 +98,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) require.NotEmpty(t, graphArn) @@ -111,7 +113,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi require.Equal(t, http.StatusOK, rec.Code) var createMembersResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createMembersResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createMembersResp, jsonx.V1())) members := createMembersResp["Members"].([]any) assert.Len(t, members, 2) @@ -122,7 +124,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) memberDetails := listResp["MemberDetails"].([]any) assert.Len(t, memberDetails, 2) @@ -134,7 +136,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) gotMembers := getResp["MemberDetails"].([]any) assert.Len(t, gotMembers, 1) unprocessed := getResp["UnprocessedAccounts"].([]any) @@ -148,7 +150,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp, jsonx.V1())) deleted := deleteResp["AccountIds"].([]any) assert.Len(t, deleted, 1) @@ -158,7 +160,7 @@ func TestDetective_MembersLifecycle(t *testing.T) { //nolint:paralleltest // exi }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) memberDetails = listResp["MemberDetails"].([]any) assert.Len(t, memberDetails, 1) } @@ -284,7 +286,7 @@ func TestListMembers_Pagination_NextToken_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) accounts := make([]any, 3) @@ -308,7 +310,7 @@ func TestListMembers_Pagination_NextToken_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page1, jsonx.V1())) memberList1, _ := page1["MemberDetails"].([]any) assert.Len(t, memberList1, 2, "MaxResults=2 must return exactly 2 members") nextToken, hasToken := page1["NextToken"].(string) @@ -321,7 +323,7 @@ func TestListMembers_Pagination_NextToken_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var all map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &all)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &all, jsonx.V1())) _, hasAllToken := all["NextToken"] assert.False(t, hasAllToken, "NextToken must be absent when all members fit") } @@ -339,7 +341,7 @@ func TestMemberDetail_MasterId_Equals_AdministratorId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/members", map[string]any{ @@ -351,7 +353,7 @@ func TestMemberDetail_MasterId_Equals_AdministratorId(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var membersResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &membersResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &membersResp, jsonx.V1())) members, _ := membersResp["Members"].([]any) require.Len(t, members, 1) @@ -376,7 +378,7 @@ func TestMemberDetail_AllRequiredFields_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/members", map[string]any{ @@ -388,7 +390,7 @@ func TestMemberDetail_AllRequiredFields_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var membersResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &membersResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &membersResp, jsonx.V1())) members, _ := membersResp["Members"].([]any) require.Len(t, members, 1) @@ -424,7 +426,7 @@ func TestMemberDetail_DatasourcePackageIngestStates_MirrorsGraph(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/members", map[string]any{ @@ -448,7 +450,7 @@ func TestMemberDetail_DatasourcePackageIngestStates_MirrorsGraph(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) details, _ := getResp["MemberDetails"].([]any) require.Len(t, details, 1) @@ -471,7 +473,7 @@ func TestDeleteMembers_AllUnprocessed_AccountIds_Empty_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/members/removal", map[string]any{ @@ -481,7 +483,7 @@ func TestDeleteMembers_AllUnprocessed_AccountIds_Empty_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) accountIDs, hasKey := resp["AccountIds"] assert.True(t, hasKey, "DeleteMembers response must include AccountIds") @@ -510,7 +512,7 @@ func TestCreateMembers_UnprocessedAccounts_Empty_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/graph/members", map[string]any{ @@ -522,7 +524,7 @@ func TestCreateMembers_UnprocessedAccounts_Empty_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) unprocessed, hasKey := resp["UnprocessedAccounts"] assert.True(t, hasKey, "CreateMembers must always include UnprocessedAccounts") @@ -591,7 +593,7 @@ func TestDetective_Invitations(t *testing.T) { //nolint:paralleltest // existing require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) // Invite account 000000000000 (the backend's own account) will fail; use another. @@ -621,7 +623,7 @@ func TestDetective_Invitations(t *testing.T) { //nolint:paralleltest // existing check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) invitations, ok := resp["Invitations"].([]any) require.True(t, ok) assert.Empty(t, invitations) @@ -700,7 +702,7 @@ func TestDetective_InvitationLifecycle(t *testing.T) { //nolint:paralleltest // require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) // Invite the backend's own account ID so it can accept/reject via the same backend. @@ -724,7 +726,7 @@ func TestDetective_InvitationLifecycle(t *testing.T) { //nolint:paralleltest // require.Equal(t, http.StatusOK, rec3.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &getResp, jsonx.V1())) details := getResp["MemberDetails"].([]any) require.Len(t, details, 1) member := details[0].(map[string]any) diff --git a/services/detective/handler_organization.go b/services/detective/handler_organization.go index 34a8e9249c..f68afd99c8 100644 --- a/services/detective/handler_organization.go +++ b/services/detective/handler_organization.go @@ -1,12 +1,13 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeOrganizationConfiguration(c *echo.Context) error { @@ -19,7 +20,7 @@ func (h *Handler) handleDescribeOrganizationConfiguration(c *echo.Context) error GraphArn string `json:"GraphArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -48,7 +49,7 @@ func (h *Handler) handleUpdateOrganizationConfiguration(c *echo.Context) error { AutoEnable bool `json:"AutoEnable"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/detective/handler_organization_test.go b/services/detective/handler_organization_test.go index 73a2510b62..f8c1b138b4 100644 --- a/services/detective/handler_organization_test.go +++ b/services/detective/handler_organization_test.go @@ -1,12 +1,14 @@ package detective_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestOrganizationConfiguration covers the DescribeOrganizationConfiguration / @@ -22,7 +24,7 @@ func TestOrganizationConfiguration(t *testing.T) { //nolint:paralleltest // exis require.Equal(t, http.StatusOK, rec.Code) var graphResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &graphResp, jsonx.V1())) graphArn := graphResp["GraphArn"].(string) unknownArn := missingGraphARN @@ -58,7 +60,7 @@ func TestOrganizationConfiguration(t *testing.T) { //nolint:paralleltest // exis check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, false, resp["AutoEnable"]) }, }, @@ -92,7 +94,7 @@ func TestOrganizationConfiguration(t *testing.T) { //nolint:paralleltest // exis check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, true, resp["AutoEnable"]) }, }, diff --git a/services/detective/handler_tags.go b/services/detective/handler_tags.go index 519704798f..7eb5b4874f 100644 --- a/services/detective/handler_tags.go +++ b/services/detective/handler_tags.go @@ -1,13 +1,14 @@ package detective import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleTagResource(c *echo.Context) error { @@ -25,7 +26,7 @@ func (h *Handler) handleTagResource(c *echo.Context) error { Tags map[string]string `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/detective/handler_tags_test.go b/services/detective/handler_tags_test.go index 7703213b9e..977e37b52f 100644 --- a/services/detective/handler_tags_test.go +++ b/services/detective/handler_tags_test.go @@ -1,7 +1,7 @@ package detective_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/detective" ) @@ -20,7 +21,7 @@ func TestDetective_Tags(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) tests := []struct { @@ -39,7 +40,7 @@ func TestDetective_Tags(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) tags, ok := resp["Tags"].(map[string]any) require.True(t, ok) assert.Empty(t, tags) @@ -67,7 +68,7 @@ func TestDetective_Tags(t *testing.T) { //nolint:paralleltest // existing issue. tagRec := doRequest(t, h, http.MethodGet, "/tags/"+graphArn, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].(map[string]any) assert.Equal(t, "myval", tags["mykey"]) }, @@ -237,7 +238,7 @@ func TestTagResource_EmptyTags_Succeeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodPost, "/tags/"+graphArn, map[string]any{ @@ -259,7 +260,7 @@ func TestUntagResource_NonExistentKey_Succeeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) req := doRequest(t, h, http.MethodDelete, "/tags/"+graphArn+"?tagKeys=does-not-exist", nil) @@ -279,14 +280,14 @@ func TestListTagsForResource_NoTags_Returns_EmptyObject(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodGet, "/tags/"+graphArn, nil) require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tags, hasKey := resp["Tags"] assert.True(t, hasKey, "ListTagsForResource must include Tags field") @@ -309,14 +310,14 @@ func TestCreateGraph_Tags_VisibleInListTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) graphArn := createResp["GraphArn"].(string) rec2 := doRequest(t, h, http.MethodGet, "/tags/"+graphArn, nil) require.Equal(t, http.StatusOK, rec2.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp, jsonx.V1())) tags, _ := tagsResp["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"], "tags set at graph creation must be visible via ListTagsForResource") diff --git a/services/detective/handler_test.go b/services/detective/handler_test.go index c6cab5fab4..9f7ca6a986 100644 --- a/services/detective/handler_test.go +++ b/services/detective/handler_test.go @@ -2,7 +2,7 @@ package detective_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/detective" ) @@ -33,7 +34,7 @@ func doRequest(t *testing.T, h *detective.Handler, method, path string, body any if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -53,7 +54,7 @@ func doRequest(t *testing.T, h *detective.Handler, method, path string, body any func parseJSON(t *testing.T, data []byte, v any) { t.Helper() - require.NoError(t, json.Unmarshal(data, v)) + require.NoError(t, json.Unmarshal(data, v, jsonx.V1())) } // TestDetectiveHandler_RouteMatcher verifies the RouteMatcher against every @@ -254,7 +255,7 @@ func TestDetective_UnknownOperation_Returns400(t *testing.T) { assert.Equal(t, tc.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidInputException", resp["__type"]) }) } diff --git a/services/detective/persistence.go b/services/detective/persistence.go index 8a95e88bc7..668d507b29 100644 --- a/services/detective/persistence.go +++ b/services/detective/persistence.go @@ -2,7 +2,7 @@ package detective import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -31,7 +31,7 @@ const detectiveSnapshotVersion = 1 // order-sensitive slice; all four are carried directly, matching the // pre-Phase-3.3 snapshot shape for those fields. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` Datasources map[string]map[string]string `json:"datasources"` // DatasourceChangedAt is additive (gopherstack-c902): graphARN -> package diff --git a/services/detective/whitebox_test.go b/services/detective/whitebox_test.go index e357f23e18..ac0641862d 100644 --- a/services/detective/whitebox_test.go +++ b/services/detective/whitebox_test.go @@ -3,7 +3,7 @@ package detective import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body any) *httptest.ResponseRecorder { @@ -22,7 +24,7 @@ func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body any) if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -87,7 +89,7 @@ func TestListInvitationsOpaqueToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tok, hasTok := resp["NextToken"].(string) require.True(t, hasTok, "NextToken must be present when more results exist") @@ -105,7 +107,7 @@ func TestListInvitationsOpaqueToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) invitations, ok := resp2["Invitations"].([]any) require.True(t, ok) assert.Len(t, invitations, 1, "second page must return the remaining invitation") diff --git a/services/directconnect/cloudformation.go b/services/directconnect/cloudformation.go index 92630c6d47..f0a3f4a10a 100644 --- a/services/directconnect/cloudformation.go +++ b/services/directconnect/cloudformation.go @@ -2,7 +2,8 @@ package directconnect import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -11,6 +12,8 @@ import ( "strconv" "strings" "unicode" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // CloudFormation resource types provisioned through CreateCFNResource. @@ -94,15 +97,14 @@ func coerceNumbers(m map[string]any, keys ...string) { } func decodeStrict(m map[string]any, out any) error { - raw, err := json.Marshal(lowerKeys(m)) + raw, err := json.Marshal(lowerKeys(m), jsonx.V1()) if err != nil { return clientError(err.Error()) } - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.DisallowUnknownFields() + dec := jsontext.NewDecoder(bytes.NewReader(raw)) - if err = dec.Decode(out); err != nil { + if err = json.UnmarshalDecode(dec, out, jsonx.V1(), json.RejectUnknownMembers(true)); err != nil { return clientError("invalid properties: " + err.Error()) } diff --git a/services/directconnect/connections.go b/services/directconnect/connections.go index c98a389d53..b06177e054 100644 --- a/services/directconnect/connections.go +++ b/services/directconnect/connections.go @@ -1,10 +1,11 @@ package directconnect import ( - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -511,7 +512,7 @@ func (b *InMemoryBackend) macSecSecretARNLocked(req *associateMacSecKeyRequest) return b.synthesizeMacSecSecretARN(id), nil } - payload, err := json.Marshal(map[string]string{"ckn": req.Ckn, "cak": req.Cak}) + payload, err := json.Marshal(map[string]string{"ckn": req.Ckn, "cak": req.Cak}, jsonx.V1()) if err != nil { return "", serverError(err.Error()) } diff --git a/services/directconnect/handler.go b/services/directconnect/handler.go index 266f6fdcf6..a8aaec871f 100644 --- a/services/directconnect/handler.go +++ b/services/directconnect/handler.go @@ -2,7 +2,8 @@ package directconnect import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -186,8 +188,8 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } - var m map[string]json.RawMessage - if unmarshalErr := json.Unmarshal(body, &m); unmarshalErr != nil { + var m map[string]jsontext.Value + if unmarshalErr := json.Unmarshal(body, &m, jsonx.V1()); unmarshalErr != nil { return "" } @@ -199,11 +201,11 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } // extractFirstResourceByKeys returns the first string resource found for the provided JSON field names. -func extractFirstResourceByKeys(body map[string]json.RawMessage, keys ...string) string { +func extractFirstResourceByKeys(body map[string]jsontext.Value, keys ...string) string { for _, key := range keys { if raw, ok := body[key]; ok { var resourceID string - if err := json.Unmarshal(raw, &resourceID); err == nil && resourceID != "" { + if err := json.Unmarshal(raw, &resourceID, jsonx.V1()); err == nil && resourceID != "" { return resourceID } } @@ -281,7 +283,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin } body := map[string]string{"__type": errType, "message": err.Error()} - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.1") @@ -316,7 +318,7 @@ func decodeBody[T any](body []byte) (*T, error) { var v T if len(body) > 0 { - if err := json.Unmarshal(body, &v); err != nil { + if err := json.Unmarshal(body, &v, jsonx.V1()); err != nil { return nil, clientError("malformed request body: " + err.Error()) } } @@ -328,7 +330,7 @@ func decodeBody[T any](body []byte) (*T, error) { // exception (marshaling our own well-typed wire structs should never // fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, serverError("directconnect: marshal response: " + err.Error()) } diff --git a/services/directconnect/persistence.go b/services/directconnect/persistence.go index 36e672ce18..64811d2667 100644 --- a/services/directconnect/persistence.go +++ b/services/directconnect/persistence.go @@ -2,7 +2,7 @@ package directconnect import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -20,11 +20,11 @@ const directConnectSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Direct Connect // backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` - NextASN int64 `json:"nextAmazonSideAsn"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` + NextASN int64 `json:"nextAmazonSideAsn"` } // Snapshot serialises the backend state to JSON. diff --git a/services/directoryservice/handler.go b/services/directoryservice/handler.go index 8bd4698f88..b527cf1866 100644 --- a/services/directoryservice/handler.go +++ b/services/directoryservice/handler.go @@ -2,7 +2,8 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "slices" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -367,7 +369,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -424,8 +426,8 @@ func (h *Handler) handleTwoFieldOp(c *echo.Context, op twoFieldOp) error { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid body")) } - var raw map[string]json.RawMessage - if jsonErr := json.Unmarshal(body, &raw); jsonErr != nil { + var raw map[string]jsontext.Value + if jsonErr := json.Unmarshal(body, &raw, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -447,14 +449,14 @@ func (h *Handler) handleTwoFieldOp(c *echo.Context, op twoFieldOp) error { // jsonString returns the string value stored under key in raw, or "" if absent // or not a JSON string. -func jsonString(raw map[string]json.RawMessage, key string) string { +func jsonString(raw map[string]jsontext.Value, key string) string { v, ok := raw[key] if !ok { return "" } var s string - if err := json.Unmarshal(v, &s); err != nil { + if err := json.Unmarshal(v, &s, jsonx.V1()); err != nil { return "" } diff --git a/services/directoryservice/handler_ad_assessments.go b/services/directoryservice/handler_ad_assessments.go index 8aa176f156..bb85d0941f 100644 --- a/services/directoryservice/handler_ad_assessments.go +++ b/services/directoryservice/handler_ad_assessments.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // startADAssessmentRequest mirrors the real StartADAssessmentInput, including @@ -43,7 +44,7 @@ func (h *Handler) handleStartADAssessment(c *echo.Context) error { var req startADAssessmentRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -117,7 +118,7 @@ func (h *Handler) handleDeleteADAssessment(c *echo.Context) error { AssessmentID string `json:"AssessmentId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -148,7 +149,7 @@ func (h *Handler) handleDescribeADAssessment(c *echo.Context) error { AssessmentID string `json:"AssessmentId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -246,7 +247,7 @@ func (h *Handler) handleListADAssessments(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_ad_assessments_test.go b/services/directoryservice/handler_ad_assessments_test.go index 214e66cca0..1cc19c8a71 100644 --- a/services/directoryservice/handler_ad_assessments_test.go +++ b/services/directoryservice/handler_ad_assessments_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestADAssessments(t *testing.T) { @@ -28,7 +30,7 @@ func TestADAssessments(t *testing.T) { rec1 := doRequest(t, h, "StartADAssessment", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) assessID, _ := r1["AssessmentId"].(string) assert.NotEmpty(t, assessID) @@ -36,7 +38,7 @@ func TestADAssessments(t *testing.T) { rec2 := doRequest(t, h, "ListADAssessments", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) assessments, _ := r2["Assessments"].([]any) assert.Len(t, assessments, 1) @@ -47,7 +49,7 @@ func TestADAssessments(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) assessment, _ := r3["Assessment"].(map[string]any) assert.Equal(t, assessID, assessment["AssessmentId"]) @@ -69,7 +71,7 @@ func TestADAssessments(t *testing.T) { rec5 := doRequest(t, h, "ListADAssessments", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec5.Code) var r5 map[string]any - require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5)) + require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5, jsonx.V1())) assessments2, _ := r5["Assessments"].([]any) assert.Empty(t, assessments2) @@ -138,7 +140,7 @@ func TestStartADAssessment_ConfigurationValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errBody["__type"]) }) } @@ -179,7 +181,7 @@ func TestStartADAssessment_ConfigurationRoundTrip(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assessID, _ := startResp["AssessmentId"].(string) require.NotEmpty(t, assessID) @@ -188,7 +190,7 @@ func TestStartADAssessment_ConfigurationRoundTrip(t *testing.T) { descRec := doRequest(t, h, "DescribeADAssessment", map[string]any{"AssessmentId": assessID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assessment, _ := descResp["Assessment"].(map[string]any) assert.NotContains(t, assessment, "DirectoryId") @@ -214,7 +216,7 @@ func TestStartADAssessment_ConfigurationRoundTrip(t *testing.T) { listRec := doRequest(t, h, "ListADAssessments", map[string]any{}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, _ := listResp["Assessments"].([]any) require.Len(t, summaries, 1) summary, _ := summaries[0].(map[string]any) diff --git a/services/directoryservice/handler_certificates.go b/services/directoryservice/handler_certificates.go index 9ff8d7c193..3b0af7ebff 100644 --- a/services/directoryservice/handler_certificates.go +++ b/services/directoryservice/handler_certificates.go @@ -2,13 +2,14 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleRegisterCertificate(c *echo.Context) error { @@ -26,7 +27,7 @@ func (h *Handler) handleRegisterCertificate(c *echo.Context) error { Type string `json:"Type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -86,7 +87,7 @@ func (h *Handler) handleListCertificates(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -135,7 +136,7 @@ func (h *Handler) handleDescribeCertificate(c *echo.Context) error { CertificateID string `json:"CertificateId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -179,7 +180,7 @@ func (h *Handler) handleEnableCAEnrollmentPolicy(c *echo.Context) error { PcaConnectorArn string `json:"PcaConnectorArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -210,7 +211,7 @@ func (h *Handler) handleDisableCAEnrollmentPolicy(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -235,7 +236,7 @@ func (h *Handler) handleDescribeCAEnrollmentPolicy(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_certificates_test.go b/services/directoryservice/handler_certificates_test.go index 61689d4c48..d1e5d15cdd 100644 --- a/services/directoryservice/handler_certificates_test.go +++ b/services/directoryservice/handler_certificates_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListCertificates_Pagination(t *testing.T) { @@ -73,7 +75,7 @@ func TestCertificates(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) certID, _ := r1["CertificateId"].(string) assert.NotEmpty(t, certID) @@ -81,7 +83,7 @@ func TestCertificates(t *testing.T) { rec2 := doRequest(t, h, "ListCertificates", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) certs, _ := r2["CertificatesInfo"].([]any) assert.Len(t, certs, 1) @@ -92,7 +94,7 @@ func TestCertificates(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) cert, _ := r3["Certificate"].(map[string]any) assert.Equal(t, certID, cert["CertificateId"]) assert.Equal(t, "test", cert["CommonName"], "CommonName must be parsed from the X.509 subject") @@ -108,7 +110,7 @@ func TestCertificates(t *testing.T) { rec5 := doRequest(t, h, "ListCertificates", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec5.Code) var r5 map[string]any - require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5)) + require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5, jsonx.V1())) certs2, _ := r5["CertificatesInfo"].([]any) assert.Empty(t, certs2) @@ -145,7 +147,7 @@ func TestCAEnrollmentPolicy(t *testing.T) { rec2 := doRequest(t, h, "DescribeCAEnrollmentPolicy", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) assert.Equal(t, "Success", r2["CaEnrollmentPolicyStatus"]) assert.Equal(t, connectorArn, r2["PcaConnectorArn"]) assert.Equal(t, dirID, r2["DirectoryId"]) @@ -158,7 +160,7 @@ func TestCAEnrollmentPolicy(t *testing.T) { rec4 := doRequest(t, h, "DescribeCAEnrollmentPolicy", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) assert.Equal(t, "Disabled", r4["CaEnrollmentPolicyStatus"]) assert.Equal(t, connectorArn, r4["PcaConnectorArn"]) diff --git a/services/directoryservice/handler_client_auth.go b/services/directoryservice/handler_client_auth.go index 84e82e6c20..1f6855cb08 100644 --- a/services/directoryservice/handler_client_auth.go +++ b/services/directoryservice/handler_client_auth.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleEnableClientAuthentication(c *echo.Context) error { //nolint:dupl // enable/disable pair. @@ -21,7 +22,7 @@ func (h *Handler) handleEnableClientAuthentication(c *echo.Context) error { //no Type string `json:"Type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -52,7 +53,7 @@ func (h *Handler) handleDisableClientAuthentication(c *echo.Context) error { //n Type string `json:"Type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -86,7 +87,7 @@ func (h *Handler) handleDescribeClientAuthenticationSettings(c *echo.Context) er } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_client_auth_test.go b/services/directoryservice/handler_client_auth_test.go index a6fb302eb1..ef0c57e76e 100644 --- a/services/directoryservice/handler_client_auth_test.go +++ b/services/directoryservice/handler_client_auth_test.go @@ -1,13 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -37,7 +38,7 @@ func TestClientAuthentication(t *testing.T) { rec2 := doRequest(t, h, "DescribeClientAuthenticationSettings", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) settings, _ := r2["ClientAuthenticationSettingsInfo"].([]any) require.Len(t, settings, 1) setting := settings[0].(map[string]any) @@ -125,7 +126,7 @@ func TestEnableClientAuthentication_Validation(t *testing.T) { }) assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidParameterException", body["__type"]) }) } diff --git a/services/directoryservice/handler_conditional_forwarders.go b/services/directoryservice/handler_conditional_forwarders.go index fcea9f04c6..dd397fe6b9 100644 --- a/services/directoryservice/handler_conditional_forwarders.go +++ b/services/directoryservice/handler_conditional_forwarders.go @@ -2,12 +2,13 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateConditionalForwarder(c *echo.Context) error { //nolint:dupl // existing issue. @@ -23,7 +24,7 @@ func (h *Handler) handleCreateConditionalForwarder(c *echo.Context) error { //no DNSIpv6Addrs []string `json:"DnsIpv6Addrs"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -60,7 +61,7 @@ func (h *Handler) handleUpdateConditionalForwarder(c *echo.Context) error { //no DNSIpv6Addrs []string `json:"DnsIpv6Addrs"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -105,7 +106,7 @@ func (h *Handler) handleDescribeConditionalForwarders(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_conditional_forwarders_test.go b/services/directoryservice/handler_conditional_forwarders_test.go index 287ac36c60..9e0d29bbbb 100644 --- a/services/directoryservice/handler_conditional_forwarders_test.go +++ b/services/directoryservice/handler_conditional_forwarders_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConditionalForwarder_Lifecycle(t *testing.T) { @@ -110,7 +112,7 @@ func TestConditionalForwarders(t *testing.T) { rec2 := doRequest(t, h, "DescribeConditionalForwarders", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) fwds, _ := r2["ConditionalForwarders"].([]any) require.Len(t, fwds, 1) fwd := fwds[0].(map[string]any) @@ -128,7 +130,7 @@ func TestConditionalForwarders(t *testing.T) { rec4 := doRequest(t, h, "DescribeConditionalForwarders", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) fwds2, _ := r4["ConditionalForwarders"].([]any) require.Len(t, fwds2, 1) fwd2 := fwds2[0].(map[string]any) @@ -146,7 +148,7 @@ func TestConditionalForwarders(t *testing.T) { rec6 := doRequest(t, h, "DescribeConditionalForwarders", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec6.Code) var r6 map[string]any - require.NoError(t, json.Unmarshal(rec6.Body.Bytes(), &r6)) + require.NoError(t, json.Unmarshal(rec6.Body.Bytes(), &r6, jsonx.V1())) fwds3, _ := r6["ConditionalForwarders"].([]any) assert.Empty(t, fwds3) diff --git a/services/directoryservice/handler_directories.go b/services/directoryservice/handler_directories.go index 9bbc9c6c65..d4d10e7c01 100644 --- a/services/directoryservice/handler_directories.go +++ b/services/directoryservice/handler_directories.go @@ -1,12 +1,13 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateDirectory(c *echo.Context) error { @@ -29,7 +30,7 @@ func (h *Handler) handleCreateDirectory(c *echo.Context) error { } `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -97,7 +98,7 @@ func (h *Handler) handleCreateMicrosoftAD(c *echo.Context) error { } `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -163,7 +164,7 @@ func (h *Handler) handleDeleteDirectory(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -193,7 +194,7 @@ func (h *Handler) handleDescribeDirectories(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -238,7 +239,7 @@ func (h *Handler) handleCreateAlias(c *echo.Context) error { Alias string `json:"Alias"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -292,7 +293,7 @@ func (h *Handler) handleCreateComputer(c *echo.Context) error { } `json:"ComputerAttributes"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -353,7 +354,7 @@ func (h *Handler) handleResetUserPassword(c *echo.Context) error { NewPassword string `json:"NewPassword"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -398,7 +399,7 @@ func (h *Handler) handleConnectDirectory(c *echo.Context) error { } `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_directories_extra_test.go b/services/directoryservice/handler_directories_extra_test.go index faf6b379be..481fcec993 100644 --- a/services/directoryservice/handler_directories_extra_test.go +++ b/services/directoryservice/handler_directories_extra_test.go @@ -1,7 +1,7 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -403,7 +404,7 @@ func TestCreateComputer(t *testing.T) { assert.Equal(t, tc.wantCode, rec.Code) if tc.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tc.check(t, resp) } }) @@ -492,7 +493,7 @@ func TestConnectDirectory(t *testing.T) { assert.Equal(t, tc.wantCode, rec.Code) if tc.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tc.check(t, resp) } }) diff --git a/services/directoryservice/handler_directories_test.go b/services/directoryservice/handler_directories_test.go index f849321392..7dda57343e 100644 --- a/services/directoryservice/handler_directories_test.go +++ b/services/directoryservice/handler_directories_test.go @@ -1,7 +1,7 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -33,7 +34,7 @@ func TestDirectoryService_CreateDirectory(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) id, ok := resp["DirectoryId"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -79,7 +80,7 @@ func TestDirectoryService_CreateMicrosoftAD(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) id, ok := resp["DirectoryId"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -115,7 +116,7 @@ func TestDirectoryService_DeleteDirectory(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "DeleteDirectory", map[string]any{"DirectoryId": dirID}) @@ -155,7 +156,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs, ok := resp["DirectoryDescriptions"].([]any) require.True(t, ok) assert.Len(t, dirs, 2) @@ -169,7 +170,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "DescribeDirectories", map[string]any{ @@ -178,7 +179,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs, ok := resp["DirectoryDescriptions"].([]any) require.True(t, ok) require.Len(t, dirs, 1) @@ -188,7 +189,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { rec = doRequest(t, h, "DescribeDirectories", map[string]any{ "DirectoryIds": []string{dirID}, }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs = resp["DirectoryDescriptions"].([]any) dir := dirs[0].(map[string]any) assert.Equal(t, dirID, dir["DirectoryId"]) @@ -214,7 +215,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { "Name": "stage.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "DescribeDirectories", map[string]any{"DirectoryIds": []string{dirID}}) @@ -259,7 +260,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { }, }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "DescribeDirectories", map[string]any{"DirectoryIds": []string{dirID}}) @@ -283,7 +284,7 @@ func TestDirectoryService_DescribeDirectories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs, ok := resp["DirectoryDescriptions"].([]any) require.True(t, ok) assert.Empty(t, dirs) @@ -426,7 +427,7 @@ func TestDirectoryService_CreateAlias(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "CreateAlias", map[string]any{ @@ -436,7 +437,7 @@ func TestDirectoryService_CreateAlias(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, dirID, resp["DirectoryId"]) assert.Equal(t, "myalias", resp["Alias"]) }) @@ -462,7 +463,7 @@ func TestDirectoryService_GetDirectoryLimits(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) limits, ok := resp["DirectoryLimits"].(map[string]any) require.True(t, ok) assert.EqualValues(t, 0, limits["CloudOnlyDirectoriesCurrentCount"]) @@ -479,7 +480,7 @@ func TestDirectoryService_GetDirectoryLimits(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) limits := resp["DirectoryLimits"].(map[string]any) assert.EqualValues(t, 1, limits["CloudOnlyDirectoriesCurrentCount"]) }) @@ -495,7 +496,7 @@ func TestDirectoryService_MicrosoftAD_DescribeReturnsType(t *testing.T) { "Edition": "Enterprise", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) rec := doRequest(t, h, "DescribeDirectories", map[string]any{ @@ -504,7 +505,7 @@ func TestDirectoryService_MicrosoftAD_DescribeReturnsType(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs := resp["DirectoryDescriptions"].([]any) require.Len(t, dirs, 1) dir := dirs[0].(map[string]any) @@ -520,7 +521,7 @@ func TestDirectoryService_DeleteDirectoryRemovesSnapshots(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) doRequest(t, h, "CreateSnapshot", map[string]any{"DirectoryId": dirID}) @@ -529,7 +530,7 @@ func TestDirectoryService_DeleteDirectoryRemovesSnapshots(t *testing.T) { descRec := doRequest(t, h, "DescribeSnapshots", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) snaps := descResp["Snapshots"].([]any) assert.Empty(t, snaps) } diff --git a/services/directoryservice/handler_domain_controllers.go b/services/directoryservice/handler_domain_controllers.go index 2be4fcd8e0..229d133ffb 100644 --- a/services/directoryservice/handler_domain_controllers.go +++ b/services/directoryservice/handler_domain_controllers.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeDomainControllers(c *echo.Context) error { @@ -24,7 +25,7 @@ func (h *Handler) handleDescribeDomainControllers(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -76,7 +77,7 @@ func (h *Handler) handleUpdateNumberOfDomainControllers(c *echo.Context) error { DesiredNumber int32 `json:"DesiredNumber"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_domain_controllers_test.go b/services/directoryservice/handler_domain_controllers_test.go index e17de7f22a..15615ceb48 100644 --- a/services/directoryservice/handler_domain_controllers_test.go +++ b/services/directoryservice/handler_domain_controllers_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDomainControllers_Lifecycle(t *testing.T) { @@ -128,7 +130,7 @@ func TestDomainControllers(t *testing.T) { rec1 := doRequest(t, h, "DescribeDomainControllers", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) dcs, _ := r1["DomainControllers"].([]any) assert.Empty(t, dcs) @@ -143,7 +145,7 @@ func TestDomainControllers(t *testing.T) { rec3 := doRequest(t, h, "DescribeDomainControllers", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) dcs2, _ := r3["DomainControllers"].([]any) assert.Len(t, dcs2, 2) diff --git a/services/directoryservice/handler_event_topics.go b/services/directoryservice/handler_event_topics.go index c5fcfea734..309efbae89 100644 --- a/services/directoryservice/handler_event_topics.go +++ b/services/directoryservice/handler_event_topics.go @@ -2,13 +2,14 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleRegisterEventTopic(c *echo.Context) error { @@ -41,7 +42,7 @@ func (h *Handler) handleDescribeEventTopics(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_event_topics_test.go b/services/directoryservice/handler_event_topics_test.go index 343c314b2e..4c588b6c76 100644 --- a/services/directoryservice/handler_event_topics_test.go +++ b/services/directoryservice/handler_event_topics_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDescribeEventTopics_Filtering(t *testing.T) { @@ -95,7 +97,7 @@ func TestEventTopics(t *testing.T) { rec2 := doRequest(t, h, "DescribeEventTopics", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) topics, _ := r2["EventTopics"].([]any) require.Len(t, topics, 1) topic := topics[0].(map[string]any) @@ -112,7 +114,7 @@ func TestEventTopics(t *testing.T) { rec4 := doRequest(t, h, "DescribeEventTopics", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) topics2, _ := r4["EventTopics"].([]any) assert.Empty(t, topics2) diff --git a/services/directoryservice/handler_hybrid_ad.go b/services/directoryservice/handler_hybrid_ad.go index b914b15405..bba1be3782 100644 --- a/services/directoryservice/handler_hybrid_ad.go +++ b/services/directoryservice/handler_hybrid_ad.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // hybridUpdateInfoEntryJSON builds the real types.HybridUpdateInfoEntry wire @@ -58,7 +59,7 @@ func (h *Handler) handleCreateHybridAD(c *echo.Context) error { } `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -96,7 +97,7 @@ func (h *Handler) handleUpdateHybridAD(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -157,7 +158,7 @@ func (h *Handler) handleDescribeHybridADUpdate(c *echo.Context) error { UpdateType string `json:"UpdateType"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_hybrid_ad_test.go b/services/directoryservice/handler_hybrid_ad_test.go index d89dd98c24..4063ab50ca 100644 --- a/services/directoryservice/handler_hybrid_ad_test.go +++ b/services/directoryservice/handler_hybrid_ad_test.go @@ -1,13 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -20,7 +21,7 @@ func mustStartAssessment(t *testing.T, h *directoryservice.Handler, dirID string require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assessmentID, _ := out["AssessmentId"].(string) require.NotEmpty(t, assessmentID) @@ -44,7 +45,7 @@ func TestHybridAD_CreateUpdateDescribeCycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) hybridDirID, _ := createOut["DirectoryId"].(string) require.NotEmpty(t, hybridDirID) assert.NotContains(t, createOut, "RequestId", "CreateHybridADOutput has no RequestId member") @@ -60,7 +61,7 @@ func TestHybridAD_CreateUpdateDescribeCycle(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) updateAssessmentID, _ := updateOut["AssessmentId"].(string) assert.NotEmpty(t, updateAssessmentID) assert.Equal(t, hybridDirID, updateOut["DirectoryId"]) @@ -73,7 +74,7 @@ func TestHybridAD_CreateUpdateDescribeCycle(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) activities, ok := descOut["UpdateActivities"].(map[string]any) require.True(t, ok, "UpdateActivities must be an object") @@ -102,7 +103,7 @@ func TestHybridAD_CreateUpdateDescribeCycle(t *testing.T) { require.Equal(t, http.StatusOK, describeDirRec.Code) var dirOut map[string]any - require.NoError(t, json.Unmarshal(describeDirRec.Body.Bytes(), &dirOut)) + require.NoError(t, json.Unmarshal(describeDirRec.Body.Bytes(), &dirOut, jsonx.V1())) dirs, ok := dirOut["DirectoryDescriptions"].([]any) require.True(t, ok) require.Len(t, dirs, 1) @@ -218,7 +219,7 @@ func TestHybridAD_UpdateHybridAD_Errors(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) hybridDirID, _ := createOut["DirectoryId"].(string) return map[string]any{"DirectoryId": hybridDirID} diff --git a/services/directoryservice/handler_ip_routes.go b/services/directoryservice/handler_ip_routes.go index f71c124de3..2899984731 100644 --- a/services/directoryservice/handler_ip_routes.go +++ b/services/directoryservice/handler_ip_routes.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddIpRoutes(c *echo.Context) error { //nolint:revive,staticcheck // existing issue. @@ -25,7 +26,7 @@ func (h *Handler) handleAddIpRoutes(c *echo.Context) error { //nolint:revive,sta } `json:"IpRoutes"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -57,7 +58,7 @@ func (h *Handler) handleRemoveIpRoutes(c *echo.Context) error { //nolint:revive, CidrIPv6s []string `json:"CidrIpv6s"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -86,7 +87,7 @@ func (h *Handler) handleListIpRoutes(c *echo.Context) error { //nolint:revive,st } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_ip_routes_test.go b/services/directoryservice/handler_ip_routes_test.go index 4f3be468b8..12e19b6e30 100644 --- a/services/directoryservice/handler_ip_routes_test.go +++ b/services/directoryservice/handler_ip_routes_test.go @@ -1,13 +1,15 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListIpRoutes_Pagination(t *testing.T) { @@ -70,7 +72,7 @@ func TestIpRoutes(t *testing.T) { rec2 := doRequest(t, h, "ListIpRoutes", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) routes, _ := r2["IpRoutesInfo"].([]any) assert.Len(t, routes, 1) @@ -85,7 +87,7 @@ func TestIpRoutes(t *testing.T) { rec4 := doRequest(t, h, "ListIpRoutes", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) routes2, _ := r4["IpRoutesInfo"].([]any) assert.Empty(t, routes2) diff --git a/services/directoryservice/handler_ldaps.go b/services/directoryservice/handler_ldaps.go index 810b552a92..e9d25e20e3 100644 --- a/services/directoryservice/handler_ldaps.go +++ b/services/directoryservice/handler_ldaps.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleEnableLDAPS(c *echo.Context) error { //nolint:dupl // existing issue. @@ -21,7 +22,7 @@ func (h *Handler) handleEnableLDAPS(c *echo.Context) error { //nolint:dupl // ex Type string `json:"Type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -55,7 +56,7 @@ func (h *Handler) handleDisableLDAPS(c *echo.Context) error { //nolint:dupl // e Type string `json:"Type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -92,7 +93,7 @@ func (h *Handler) handleDescribeLDAPSSettings(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_ldaps_test.go b/services/directoryservice/handler_ldaps_test.go index 58ed6915fc..a5bfc9d021 100644 --- a/services/directoryservice/handler_ldaps_test.go +++ b/services/directoryservice/handler_ldaps_test.go @@ -1,13 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -37,7 +38,7 @@ func TestLDAPS(t *testing.T) { rec2 := doRequest(t, h, "DescribeLDAPSSettings", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) settings, _ := r2["LDAPSSettingsInfo"].([]any) require.Len(t, settings, 1) setting := settings[0].(map[string]any) @@ -126,6 +127,6 @@ func TestEnableLDAPS_InvalidType(t *testing.T) { }) assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidParameterException", body["__type"]) } diff --git a/services/directoryservice/handler_log_subscriptions.go b/services/directoryservice/handler_log_subscriptions.go index fc868058fe..2eee4d9f44 100644 --- a/services/directoryservice/handler_log_subscriptions.go +++ b/services/directoryservice/handler_log_subscriptions.go @@ -2,13 +2,14 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateLogSubscription(c *echo.Context) error { @@ -30,7 +31,7 @@ func (h *Handler) handleDeleteLogSubscription(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -58,7 +59,7 @@ func (h *Handler) handleListLogSubscriptions(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_log_subscriptions_test.go b/services/directoryservice/handler_log_subscriptions_test.go index d1d786001e..28a7c91c2b 100644 --- a/services/directoryservice/handler_log_subscriptions_test.go +++ b/services/directoryservice/handler_log_subscriptions_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListLogSubscriptions_Pagination(t *testing.T) { @@ -58,7 +60,7 @@ func TestLogSubscriptions(t *testing.T) { rec2 := doRequest(t, h, "ListLogSubscriptions", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) subs, _ := r2["LogSubscriptions"].([]any) assert.Len(t, subs, 1) @@ -70,7 +72,7 @@ func TestLogSubscriptions(t *testing.T) { rec4 := doRequest(t, h, "ListLogSubscriptions", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) subs2, _ := r4["LogSubscriptions"].([]any) assert.Empty(t, subs2) diff --git a/services/directoryservice/handler_radius.go b/services/directoryservice/handler_radius.go index d4118e5f12..890627d7b9 100644 --- a/services/directoryservice/handler_radius.go +++ b/services/directoryservice/handler_radius.go @@ -1,12 +1,13 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type radiusRequest struct { @@ -32,7 +33,7 @@ func (h *Handler) handleEnableRadius(c *echo.Context) error { //nolint:dupl // e var req radiusRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -69,7 +70,7 @@ func (h *Handler) handleDisableRadius(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -92,7 +93,7 @@ func (h *Handler) handleUpdateRadius(c *echo.Context) error { //nolint:dupl // e var req radiusRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_regions.go b/services/directoryservice/handler_regions.go index 894bca4dfe..110ef3e152 100644 --- a/services/directoryservice/handler_regions.go +++ b/services/directoryservice/handler_regions.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddRegion(c *echo.Context) error { @@ -25,7 +26,7 @@ func (h *Handler) handleAddRegion(c *echo.Context) error { RegionName string `json:"RegionName"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -59,7 +60,7 @@ func (h *Handler) handleRemoveRegion(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -87,7 +88,7 @@ func (h *Handler) handleDescribeRegions(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_regions_test.go b/services/directoryservice/handler_regions_test.go index 02cef1a5da..f322f8da91 100644 --- a/services/directoryservice/handler_regions_test.go +++ b/services/directoryservice/handler_regions_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRegions(t *testing.T) { @@ -39,7 +41,7 @@ func TestRegions(t *testing.T) { rec2 := doRequest(t, h, "DescribeRegions", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) regions, _ := r2["RegionsDescription"].([]any) require.Len(t, regions, 1) region := regions[0].(map[string]any) @@ -57,7 +59,7 @@ func TestRegions(t *testing.T) { rec4 := doRequest(t, h, "DescribeRegions", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) regions2, _ := r4["RegionsDescription"].([]any) assert.Empty(t, regions2) @@ -78,6 +80,6 @@ func TestAddRegion_Validation(t *testing.T) { }) assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidParameterException", body["__type"]) } diff --git a/services/directoryservice/handler_schema_extensions.go b/services/directoryservice/handler_schema_extensions.go index 956cd803bf..bfc6d514e5 100644 --- a/services/directoryservice/handler_schema_extensions.go +++ b/services/directoryservice/handler_schema_extensions.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleStartSchemaExtension(c *echo.Context) error { @@ -23,7 +24,7 @@ func (h *Handler) handleStartSchemaExtension(c *echo.Context) error { CreateSnapshotBeforeSchemaExtension bool `json:"CreateSnapshotBeforeSchemaExtension"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -58,7 +59,7 @@ func (h *Handler) handleCancelSchemaExtension(c *echo.Context) error { SchemaExtensionID string `json:"SchemaExtensionId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -90,7 +91,7 @@ func (h *Handler) handleListSchemaExtensions(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_schema_extensions_test.go b/services/directoryservice/handler_schema_extensions_test.go index 1d6cb8a978..34bf0f0794 100644 --- a/services/directoryservice/handler_schema_extensions_test.go +++ b/services/directoryservice/handler_schema_extensions_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSchemaExtensions_StateLifecycle(t *testing.T) { @@ -155,7 +157,7 @@ func TestSchemaExtensions(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) extID, _ := r1["SchemaExtensionId"].(string) assert.NotEmpty(t, extID) @@ -163,7 +165,7 @@ func TestSchemaExtensions(t *testing.T) { rec2 := doRequest(t, h, "ListSchemaExtensions", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) exts, _ := r2["SchemaExtensionsInfo"].([]any) assert.Len(t, exts, 1) diff --git a/services/directoryservice/handler_settings.go b/services/directoryservice/handler_settings.go index c5a8462b51..5efa56a59e 100644 --- a/services/directoryservice/handler_settings.go +++ b/services/directoryservice/handler_settings.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Directory Data Access --- @@ -22,7 +23,7 @@ func (h *Handler) handleEnableDirectoryDataAccess(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -47,7 +48,7 @@ func (h *Handler) handleDisableDirectoryDataAccess(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -72,7 +73,7 @@ func (h *Handler) handleDescribeDirectoryDataAccess(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -115,7 +116,7 @@ func (h *Handler) handleUpdateSettings(c *echo.Context) error { } `json:"Settings"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -149,7 +150,7 @@ func (h *Handler) handleDescribeSettings(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -226,7 +227,7 @@ func (h *Handler) handleUpdateDirectorySetup(c *echo.Context) error { CreateSnapshotBeforeUpdate bool `json:"CreateSnapshotBeforeUpdate"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -285,7 +286,7 @@ func (h *Handler) handleDescribeUpdateDirectory(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_settings_test.go b/services/directoryservice/handler_settings_test.go index ca6827e12e..2c56a6ce24 100644 --- a/services/directoryservice/handler_settings_test.go +++ b/services/directoryservice/handler_settings_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSettings(t *testing.T) { @@ -31,14 +33,14 @@ func TestSettings(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) assert.Equal(t, dirID, r1["DirectoryId"]) // DescribeSettings rec2 := doRequest(t, h, "DescribeSettings", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) settings, _ := r2["SettingEntries"].([]any) require.Len(t, settings, 1) setting := settings[0].(map[string]any) @@ -79,7 +81,7 @@ func TestUpdateDirectorySetup(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) entries, _ := r2["UpdateActivities"].([]any) assert.Len(t, entries, 1) @@ -107,7 +109,7 @@ func TestDirectoryDataAccess(t *testing.T) { rec1 := doRequest(t, h, "DescribeDirectoryDataAccess", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) assert.Equal(t, "Disabled", r1["DataAccessStatus"]) // Enable @@ -118,7 +120,7 @@ func TestDirectoryDataAccess(t *testing.T) { rec3 := doRequest(t, h, "DescribeDirectoryDataAccess", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) assert.Equal(t, "Enabled", r3["DataAccessStatus"]) // Disable @@ -153,7 +155,7 @@ func TestUpdateDirectorySetup_Validation(t *testing.T) { }) assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidParameterException", body["__type"]) }) } diff --git a/services/directoryservice/handler_shared_directories.go b/services/directoryservice/handler_shared_directories.go index d32be60215..44247d338e 100644 --- a/services/directoryservice/handler_shared_directories.go +++ b/services/directoryservice/handler_shared_directories.go @@ -1,13 +1,14 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleShareDirectory(c *echo.Context) error { @@ -26,7 +27,7 @@ func (h *Handler) handleShareDirectory(c *echo.Context) error { } `json:"ShareTarget"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -71,7 +72,7 @@ func (h *Handler) handleUnshareDirectory(c *echo.Context) error { } `json:"UnshareTarget"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -101,7 +102,7 @@ func (h *Handler) handleAcceptSharedDirectory(c *echo.Context) error { SharedDirectoryID string `json:"SharedDirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -144,7 +145,7 @@ func (h *Handler) handleRejectSharedDirectory(c *echo.Context) error { SharedDirectoryID string `json:"SharedDirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -174,7 +175,7 @@ func (h *Handler) handleDescribeSharedDirectories(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } diff --git a/services/directoryservice/handler_shared_directories_test.go b/services/directoryservice/handler_shared_directories_test.go index bb860cba8e..cbdf119ab8 100644 --- a/services/directoryservice/handler_shared_directories_test.go +++ b/services/directoryservice/handler_shared_directories_test.go @@ -1,13 +1,15 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSharedDirectories(t *testing.T) { @@ -34,7 +36,7 @@ func TestSharedDirectories(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) sharedDirID, _ := r1["SharedDirectoryId"].(string) assert.NotEmpty(t, sharedDirID) @@ -45,7 +47,7 @@ func TestSharedDirectories(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) sd, _ := r2["SharedDirectory"].(map[string]any) require.NotNil(t, sd, "AcceptSharedDirectoryOutput.SharedDirectory must be present") assert.Equal(t, sharedDirID, sd["SharedDirectoryId"]) @@ -63,7 +65,7 @@ func TestSharedDirectories(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) dirs, _ := r3["SharedDirectories"].([]any) assert.Len(t, dirs, 1) @@ -80,7 +82,7 @@ func TestSharedDirectories(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) assert.Equal(t, sharedDirID, r2["SharedDirectoryId"]) } }) @@ -151,7 +153,7 @@ func TestShareDirectory_StatusLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, shareRec.Code) var shareResp map[string]any - require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp, jsonx.V1())) sharedID, _ := shareResp["SharedDirectoryId"].(string) require.NotEmpty(t, sharedID) diff --git a/services/directoryservice/handler_snapshots.go b/services/directoryservice/handler_snapshots.go index ec54062a96..a89c3d1a5b 100644 --- a/services/directoryservice/handler_snapshots.go +++ b/services/directoryservice/handler_snapshots.go @@ -1,12 +1,13 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateSnapshot(c *echo.Context) error { @@ -20,7 +21,7 @@ func (h *Handler) handleCreateSnapshot(c *echo.Context) error { Name string `json:"Name"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -48,7 +49,7 @@ func (h *Handler) handleDeleteSnapshot(c *echo.Context) error { SnapshotID string `json:"SnapshotId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -79,7 +80,7 @@ func (h *Handler) handleDescribeSnapshots(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -120,7 +121,7 @@ func (h *Handler) handleGetSnapshotLimits(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -152,7 +153,7 @@ func (h *Handler) handleRestoreFromSnapshot(c *echo.Context) error { SnapshotID string `json:"SnapshotId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_snapshots_test.go b/services/directoryservice/handler_snapshots_test.go index cf531f530e..1bb905fa7b 100644 --- a/services/directoryservice/handler_snapshots_test.go +++ b/services/directoryservice/handler_snapshots_test.go @@ -1,7 +1,7 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -21,7 +22,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["DirectoryId"].(string) } @@ -37,7 +38,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snapID, ok := resp["SnapshotId"].(string) require.True(t, ok) assert.NotEmpty(t, snapID) @@ -56,7 +57,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { dirID := createDir(h) snapRec := doRequest(t, h, "CreateSnapshot", map[string]any{"DirectoryId": dirID}) var snapResp map[string]any - require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp)) + require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp, jsonx.V1())) snapID := snapResp["SnapshotId"].(string) rec := doRequest(t, h, "DeleteSnapshot", map[string]any{"SnapshotId": snapID}) @@ -66,7 +67,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { descRec := doRequest(t, h, "DescribeSnapshots", map[string]any{"SnapshotIds": []string{snapID}}) assert.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) snaps := descResp["Snapshots"].([]any) assert.Empty(t, snaps) }) @@ -87,7 +88,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { "Name": "other.example.com", "Password": "Admin1234!", "Size": "Small", }) var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["DirectoryId"].(string) }() @@ -99,7 +100,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) assert.Len(t, snaps, 1) }) @@ -114,7 +115,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) limits := resp["SnapshotLimits"].(map[string]any) assert.EqualValues(t, 1, limits["ManualSnapshotsCurrentCount"]) }) @@ -125,7 +126,7 @@ func TestDirectoryService_Snapshots(t *testing.T) { dirID := createDir(h) snapRec := doRequest(t, h, "CreateSnapshot", map[string]any{"DirectoryId": dirID}) var snapResp map[string]any - require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp)) + require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp, jsonx.V1())) snapID := snapResp["SnapshotId"].(string) rec := doRequest(t, h, "RestoreFromSnapshot", map[string]any{"SnapshotId": snapID}) @@ -155,11 +156,11 @@ func TestRestoreFromSnapshot_TableDriven(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) snapRec := doRequest(t, h, "CreateSnapshot", map[string]any{"DirectoryId": dirID}) var snapResp map[string]any - require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp)) + require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp, jsonx.V1())) return snapResp["SnapshotId"].(string) }, @@ -179,11 +180,11 @@ func TestRestoreFromSnapshot_TableDriven(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) snapRec := doRequest(t, h, "CreateSnapshot", map[string]any{"DirectoryId": dirID}) var snapResp map[string]any - require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp)) + require.NoError(t, json.Unmarshal(snapRec.Body.Bytes(), &snapResp, jsonx.V1())) snapID := snapResp["SnapshotId"].(string) doRequest(t, h, "DeleteDirectory", map[string]any{"DirectoryId": dirID}) diff --git a/services/directoryservice/handler_sso.go b/services/directoryservice/handler_sso.go index 6d866e829c..2486e4ef0b 100644 --- a/services/directoryservice/handler_sso.go +++ b/services/directoryservice/handler_sso.go @@ -1,12 +1,13 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleEnableSso(c *echo.Context) error { @@ -19,7 +20,7 @@ func (h *Handler) handleEnableSso(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -44,7 +45,7 @@ func (h *Handler) handleDisableSso(c *echo.Context) error { DirectoryID string `json:"DirectoryId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_sso_test.go b/services/directoryservice/handler_sso_test.go index da13dcb679..d35f0d25c9 100644 --- a/services/directoryservice/handler_sso_test.go +++ b/services/directoryservice/handler_sso_test.go @@ -1,12 +1,13 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -18,7 +19,7 @@ func TestDirectoryService_SSO(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["DirectoryId"].(string) } diff --git a/services/directoryservice/handler_tags.go b/services/directoryservice/handler_tags.go index a156333d8e..13a4192efe 100644 --- a/services/directoryservice/handler_tags.go +++ b/services/directoryservice/handler_tags.go @@ -1,12 +1,13 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddTagsToResource(c *echo.Context) error { @@ -23,7 +24,7 @@ func (h *Handler) handleAddTagsToResource(c *echo.Context) error { } `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -51,7 +52,7 @@ func (h *Handler) handleRemoveTagsFromResource(c *echo.Context) error { TagKeys []string `json:"TagKeys"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -79,7 +80,7 @@ func (h *Handler) handleListTagsForResource(c *echo.Context) error { Limit int32 `json:"Limit"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_tags_test.go b/services/directoryservice/handler_tags_test.go index 40fbef0f9e..ff8ba23d1a 100644 --- a/services/directoryservice/handler_tags_test.go +++ b/services/directoryservice/handler_tags_test.go @@ -1,7 +1,7 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -20,7 +21,7 @@ func TestDirectoryService_Tags(t *testing.T) { "Name": "corp.example.com", "Password": "Admin1234!", "Size": "Small", }) var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) return resp["DirectoryId"].(string) } @@ -40,7 +41,7 @@ func TestDirectoryService_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) require.True(t, ok) require.Len(t, tags, 1) @@ -70,7 +71,7 @@ func TestDirectoryService_Tags(t *testing.T) { listRec := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceId": dirID}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "team", tags[0].(map[string]any)["Key"]) @@ -96,12 +97,12 @@ func TestDirectoryService_Tags(t *testing.T) { "Tags": []map[string]any{{"Key": "created", "Value": "yes"}}, }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) dirID := createResp["DirectoryId"].(string) listRec := doRequest(t, h, "ListTagsForResource", map[string]any{"ResourceId": dirID}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "created", tags[0].(map[string]any)["Key"]) diff --git a/services/directoryservice/handler_test.go b/services/directoryservice/handler_test.go index ca8950b562..35cff313ff 100644 --- a/services/directoryservice/handler_test.go +++ b/services/directoryservice/handler_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -62,7 +63,7 @@ func doRequest(t *testing.T, h *directoryservice.Handler, op string, body any) * if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -89,7 +90,7 @@ func mustCreateSimpleAD(t *testing.T, h *directoryservice.Handler, name string) }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, ok := resp["DirectoryId"].(string) require.True(t, ok) require.NotEmpty(t, id) @@ -107,7 +108,7 @@ func mustCreateMicrosoftAD(t *testing.T, h *directoryservice.Handler, name strin }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, ok := resp["DirectoryId"].(string) require.True(t, ok) require.NotEmpty(t, id) @@ -119,7 +120,7 @@ func mustCreateMicrosoftAD(t *testing.T, h *directoryservice.Handler, name strin func respBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/directoryservice/handler_trusts.go b/services/directoryservice/handler_trusts.go index d60c0a5c5e..44c189d5dd 100644 --- a/services/directoryservice/handler_trusts.go +++ b/services/directoryservice/handler_trusts.go @@ -1,7 +1,7 @@ package directoryservice import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/google/uuid" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateTrust(c *echo.Context) error { @@ -29,7 +30,7 @@ func (h *Handler) handleCreateTrust(c *echo.Context) error { ConditionalForwarderIPv6Addrs []string `json:"ConditionalForwarderIpv6Addrs"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -88,7 +89,7 @@ func (h *Handler) handleDeleteTrust(c *echo.Context) error { DeleteAssociatedConditionalForwarder bool `json:"DeleteAssociatedConditionalForwarder"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -120,7 +121,7 @@ func (h *Handler) handleDescribeTrusts(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } } @@ -179,7 +180,7 @@ func (h *Handler) handleUpdateTrust(c *echo.Context) error { SelectiveAuth string `json:"SelectiveAuth"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } @@ -211,7 +212,7 @@ func (h *Handler) handleVerifyTrust(c *echo.Context) error { TrustID string `json:"TrustId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errResp("ClientException", "invalid JSON")) } diff --git a/services/directoryservice/handler_trusts_test.go b/services/directoryservice/handler_trusts_test.go index 0f035f6946..073dfbea56 100644 --- a/services/directoryservice/handler_trusts_test.go +++ b/services/directoryservice/handler_trusts_test.go @@ -1,7 +1,7 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/directoryservice" ) @@ -240,7 +241,7 @@ func TestTrusts(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) trustID, _ := r1["TrustId"].(string) assert.NotEmpty(t, trustID) @@ -248,7 +249,7 @@ func TestTrusts(t *testing.T) { rec2 := doRequest(t, h, "DescribeTrusts", map[string]any{"DirectoryId": dirID}) assert.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) trusts, _ := r2["Trusts"].([]any) require.Len(t, trusts, 1) trust := trusts[0].(map[string]any) @@ -261,27 +262,27 @@ func TestTrusts(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec3.Code) var r3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &r3, jsonx.V1())) assert.Equal(t, trustID, r3["TrustId"]) // Verify rec4 := doRequest(t, h, "VerifyTrust", map[string]any{"TrustId": trustID}) assert.Equal(t, http.StatusOK, rec4.Code) var r4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &r4, jsonx.V1())) assert.Equal(t, trustID, r4["TrustId"]) // Delete rec5 := doRequest(t, h, "DeleteTrust", map[string]any{"TrustId": trustID}) assert.Equal(t, http.StatusOK, rec5.Code) var r5 map[string]any - require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5)) + require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &r5, jsonx.V1())) assert.Equal(t, trustID, r5["TrustId"]) require.Eventually(t, func() bool { var r6 map[string]any rec6 := doRequest(t, h, "DescribeTrusts", map[string]any{"DirectoryId": dirID}) - require.NoError(t, json.Unmarshal(rec6.Body.Bytes(), &r6)) + require.NoError(t, json.Unmarshal(rec6.Body.Bytes(), &r6, jsonx.V1())) trusts2, _ := r6["Trusts"].([]any) return rec6.Code == http.StatusOK && len(trusts2) == 0 diff --git a/services/directoryservice/id_format_test.go b/services/directoryservice/id_format_test.go index d7846cba1c..579db14509 100644 --- a/services/directoryservice/id_format_test.go +++ b/services/directoryservice/id_format_test.go @@ -1,12 +1,14 @@ package directoryservice_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // realIDPattern matches terraform-provider-aws's client-side ValidateFunc for @@ -35,7 +37,7 @@ func TestIDFormats_MatchRealAWSPattern(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var snapResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &snapResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &snapResp, jsonx.V1())) snapID, _ := snapResp["SnapshotId"].(string) require.Regexp(t, realIDPattern, snapID, "snapshot ID") @@ -48,7 +50,7 @@ func TestIDFormats_MatchRealAWSPattern(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var trustResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &trustResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &trustResp, jsonx.V1())) trustID, _ := trustResp["TrustId"].(string) require.Regexp(t, realIDPattern, trustID, "trust ID") } diff --git a/services/directoryservice/persistence.go b/services/directoryservice/persistence.go index 3de6400285..34398ce177 100644 --- a/services/directoryservice/persistence.go +++ b/services/directoryservice/persistence.go @@ -2,9 +2,11 @@ package directoryservice import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -52,7 +54,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Aliases map[string]map[string]string `json:"aliases"` IPRoutes map[string]map[string][]storedIpRoute `json:"ipRoutes"` DirDataAccess map[string]map[string]bool `json:"dirDataAccess"` @@ -257,7 +259,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dto := buildPersistenceDTOTables() if err := dto.registry.RestoreAll(tables); err != nil { @@ -361,7 +363,7 @@ func (b *InMemoryBackend) BackendSnapshot() []byte { Region: b.region, } - data, _ := json.Marshal(snap) + data, _ := json.Marshal(snap, jsonx.V1()) return data } diff --git a/services/dlm/handler.go b/services/dlm/handler.go index 5d73ed9e93..4f25006a4b 100644 --- a/services/dlm/handler.go +++ b/services/dlm/handler.go @@ -2,7 +2,7 @@ package dlm import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -294,7 +295,7 @@ func (h *Handler) handleCreateLifecyclePolicy(c *echo.Context, body []byte) erro CrossRegionCopyTargets []any `json:"CrossRegionCopyTargets"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errBody(errInvalidRequest, "invalid request body")) } @@ -427,7 +428,7 @@ func (h *Handler) handleUpdateLifecyclePolicy(c *echo.Context, policyID string, CrossRegionCopyTargets []any `json:"CrossRegionCopyTargets"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errBody(errInvalidRequest, "invalid request body")) } @@ -464,7 +465,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body [] Tags map[string]string `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errBody(errInvalidRequest, "invalid request body")) } diff --git a/services/dlm/handler_lifecycle_policies_test.go b/services/dlm/handler_lifecycle_policies_test.go index 93b56557de..b41a6e640f 100644 --- a/services/dlm/handler_lifecycle_policies_test.go +++ b/services/dlm/handler_lifecycle_policies_test.go @@ -2,7 +2,7 @@ package dlm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dlm" ) @@ -31,7 +32,7 @@ func createPolicyWithDetails(t *testing.T, h *dlm.Handler, description string, d require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policyID, ok := resp["PolicyId"].(string) require.True(t, ok, "PolicyId missing from response") @@ -43,7 +44,7 @@ func getPoliciesResp(t *testing.T, rec *httptest.ResponseRecorder) []map[string] t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, ok := resp["Policies"].([]any) require.True(t, ok) @@ -241,7 +242,7 @@ func TestHandler_GetLifecyclePolicies_DeterministicOrder(t *testing.T) { assert.JSONEq(t, firstRec.Body.String(), secondRec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["Policies"].([]any) require.True(t, ok) require.Len(t, policies, tc.count) @@ -304,7 +305,7 @@ func TestHandler_UpdateLifecyclePolicy_PolicyDetails(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["PolicyId"].(string) // Update with new PolicyDetails. @@ -318,7 +319,7 @@ func TestHandler_UpdateLifecyclePolicy_PolicyDetails(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy := getResp["Policy"].(map[string]any) details := policy["PolicyDetails"].(map[string]any) assert.Equal(t, tc.wantType, details["PolicyType"]) @@ -374,7 +375,7 @@ func TestHandler_UpdateLifecyclePolicy_ExplicitEmptyVsOmitted(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["PolicyId"].(string) patchRec := doRequest(t, h, http.MethodPatch, fmt.Sprintf("/policies/%s", policyID), tc.patchBody) @@ -384,7 +385,7 @@ func TestHandler_UpdateLifecyclePolicy_ExplicitEmptyVsOmitted(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy := getResp["Policy"].(map[string]any) assert.Equal(t, tc.wantDesc, policy["Description"]) assert.Equal(t, tc.wantRoleArn, policy["ExecutionRoleArn"]) @@ -483,14 +484,14 @@ func TestHandler_CreateLifecyclePolicy_DefaultPolicyFields(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["PolicyId"].(string) getRec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy := getResp["Policy"].(map[string]any) details := policy["PolicyDetails"].(map[string]any) @@ -526,7 +527,7 @@ func TestHandler_UpdateLifecyclePolicy_DefaultPolicyFields(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["PolicyId"].(string) patchRec := doRequest(t, h, http.MethodPatch, fmt.Sprintf("/policies/%s", policyID), map[string]any{ @@ -539,7 +540,7 @@ func TestHandler_UpdateLifecyclePolicy_DefaultPolicyFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy := getResp["Policy"].(map[string]any) details := policy["PolicyDetails"].(map[string]any) @@ -601,14 +602,14 @@ func TestHandler_GetLifecyclePolicy_DefaultPolicyEcho(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["PolicyId"].(string) getRec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy := getResp["Policy"].(map[string]any) assert.Equal(t, tc.want, policy["DefaultPolicy"]) @@ -682,7 +683,7 @@ func TestHandler_CreateLifecyclePolicy_LimitExceeded(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "LimitExceededException", out["__type"]) } @@ -727,7 +728,7 @@ func TestHandler_CreateLifecyclePolicy_MissingRequiredFields(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["__type"]) }) } @@ -864,7 +865,7 @@ func TestHandler_GetLifecyclePolicies_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies := resp["Policies"].([]any) if tc.wantMaxLen > 0 || tc.wantMinLen > 0 { diff --git a/services/dlm/handler_tags_test.go b/services/dlm/handler_tags_test.go index 3cd238f9a1..edb34e9323 100644 --- a/services/dlm/handler_tags_test.go +++ b/services/dlm/handler_tags_test.go @@ -2,7 +2,7 @@ package dlm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dlm" ) @@ -46,7 +47,7 @@ func TestHandler_TagResource_InvalidBody(t *testing.T) { // Get the ARN. rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["Policy"].(map[string]any)["PolicyArn"].(string) req := httptest.NewRequest(http.MethodPost, fmt.Sprintf("/tags/%s", arn), bytes.NewReader(tc.body)) @@ -89,7 +90,7 @@ func TestHandler_UntagResource_MultipleQueryKeys(t *testing.T) { rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["Policy"].(map[string]any)["PolicyArn"].(string) // Tag first. @@ -141,12 +142,12 @@ func TestHandler_TagResource_GovCloudPartitionMatcherRouted(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policyARN := getResp["Policy"].(map[string]any)["PolicyArn"].(string) require.Contains(t, policyARN, "arn:aws-us-gov:dlm:", "sanity: PolicyArn must carry the GovCloud partition") tagPath := fmt.Sprintf("/tags/%s", policyARN) - body, err := json.Marshal(map[string]any{"Tags": map[string]string{"env": "prod"}}) + body, err := json.Marshal(map[string]any{"Tags": map[string]string{"env": "prod"}}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, tagPath, bytes.NewReader(body)) @@ -164,7 +165,7 @@ func TestHandler_TagResource_GovCloudPartitionMatcherRouted(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -203,7 +204,7 @@ func TestHandler_UntagResource_URLEncodedTagKey(t *testing.T) { rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["Policy"].(map[string]any)["PolicyArn"].(string) doRequest(t, h, http.MethodPost, fmt.Sprintf("/tags/%s", arn), map[string]any{ @@ -228,7 +229,7 @@ func TestHandler_UntagResource_URLEncodedTagKey(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) assert.NotContains(t, tags, tc.tagKey, "percent-decoded tag key must be removed") diff --git a/services/dlm/handler_test.go b/services/dlm/handler_test.go index 460b11e078..2d539a1813 100644 --- a/services/dlm/handler_test.go +++ b/services/dlm/handler_test.go @@ -2,7 +2,7 @@ package dlm_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dlm" ) @@ -30,7 +31,7 @@ func doRequest(t *testing.T, h *dlm.Handler, method, path string, body any) *htt if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -57,7 +58,7 @@ func createPolicy(t *testing.T, h *dlm.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policyID, ok := resp["PolicyId"].(string) require.True(t, ok, "PolicyId missing from response") @@ -90,7 +91,7 @@ func TestDLM_LifecyclePolicy(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) assert.Contains(t, resp["PolicyId"], "policy-") }, }, @@ -105,7 +106,7 @@ func TestDLM_LifecyclePolicy(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) policies, ok := resp["Policies"].([]any) require.True(t, ok) assert.Len(t, policies, 1) @@ -124,7 +125,7 @@ func TestDLM_LifecyclePolicy(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) policy, ok := resp["Policy"].(map[string]any) require.True(t, ok) assert.Contains(t, policy["PolicyId"], "policy-") @@ -220,7 +221,7 @@ func TestDLM_Tags(t *testing.T) { policyID := createPolicy(t, h) rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) arn := policy["PolicyArn"].(string) @@ -239,7 +240,7 @@ func TestDLM_Tags(t *testing.T) { policyID := createPolicy(t, h) rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) arn := policy["PolicyArn"].(string) doRequest(t, h, http.MethodPost, fmt.Sprintf("/tags/%s", arn), map[string]any{ @@ -255,7 +256,7 @@ func TestDLM_Tags(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) tags, ok := resp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -268,7 +269,7 @@ func TestDLM_Tags(t *testing.T) { policyID := createPolicy(t, h) rec := doRequest(t, h, http.MethodGet, fmt.Sprintf("/policies/%s", policyID), nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) arn := policy["PolicyArn"].(string) doRequest(t, h, http.MethodPost, fmt.Sprintf("/tags/%s", arn), map[string]any{ @@ -359,7 +360,7 @@ func TestHandler_Reset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies := resp["Policies"].([]any) assert.Empty(t, policies) }) @@ -585,7 +586,7 @@ func TestHandler_MapError_InternalError(t *testing.T) { var bodyBytes []byte if tc.method == http.MethodPost { - bodyBytes, _ = json.Marshal(map[string]any{"Tags": map[string]string{"k": "v"}}) + bodyBytes, _ = json.Marshal(map[string]any{"Tags": map[string]string{"k": "v"}}, jsonx.V1()) } req := httptest.NewRequest(tc.method, tc.path, bytes.NewReader(bodyBytes)) @@ -599,7 +600,7 @@ func TestHandler_MapError_InternalError(t *testing.T) { assert.Equal(t, tc.wantCode, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) }) } diff --git a/services/dlm/persistence.go b/services/dlm/persistence.go index 1bb2b1bd8e..da0faec0d2 100644 --- a/services/dlm/persistence.go +++ b/services/dlm/persistence.go @@ -2,7 +2,7 @@ package dlm import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "math" "strconv" @@ -33,9 +33,9 @@ const dlmSnapshotVersion = 1 // (older or newer) build of this backend as though it were the current // shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Counter int `json:"counter"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Counter int `json:"counter"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. diff --git a/services/dlm/persistence_test.go b/services/dlm/persistence_test.go index a158965a93..0e83b4d51e 100644 --- a/services/dlm/persistence_test.go +++ b/services/dlm/persistence_test.go @@ -2,12 +2,14 @@ package dlm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dlm" ) @@ -307,8 +309,8 @@ func TestPersistence_CurrentVersionRoundTripsThroughJSON(t *testing.T) { snap := b.Snapshot(context.Background()) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) _, hasVersion := raw["version"] assert.True(t, hasVersion, "snapshot must carry a top-level version field") @@ -319,8 +321,8 @@ func TestPersistence_CurrentVersionRoundTripsThroughJSON(t *testing.T) { _, hasCounter := raw["counter"] assert.True(t, hasCounter, "snapshot must carry a top-level counter field") - var tables map[string]json.RawMessage - require.NoError(t, json.Unmarshal(raw["tables"], &tables)) + var tables map[string]jsontext.Value + require.NoError(t, json.Unmarshal(raw["tables"], &tables, jsonx.V1())) _, hasPoliciesTable := tables["policies"] assert.True( diff --git a/services/dms/data_providers.go b/services/dms/data_providers.go index df816c9b90..e489098965 100644 --- a/services/dms/data_providers.go +++ b/services/dms/data_providers.go @@ -2,7 +2,8 @@ package dms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" @@ -10,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -226,8 +228,9 @@ func mergeDataProviderSettings(current, incoming string, exact bool) string { return incoming } - var cur, inc map[string]map[string]json.RawMessage - if json.Unmarshal([]byte(current), &cur) != nil || json.Unmarshal([]byte(incoming), &inc) != nil { + var cur, inc map[string]map[string]jsontext.Value + if json.Unmarshal([]byte(current), &cur, jsonx.V1()) != nil || + json.Unmarshal([]byte(incoming), &inc, jsonx.V1()) != nil { return incoming } @@ -240,7 +243,7 @@ func mergeDataProviderSettings(current, incoming string, exact bool) string { maps.Copy(curFields, fields) } - out, err := json.Marshal(cur) + out, err := json.Marshal(cur, jsonx.V1()) if err != nil { return incoming } diff --git a/services/dms/endpoints.go b/services/dms/endpoints.go index 77c4763f2a..e8d68715eb 100644 --- a/services/dms/endpoints.go +++ b/services/dms/endpoints.go @@ -2,7 +2,8 @@ package dms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" @@ -10,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -419,14 +421,15 @@ func mergeEndpointSettings(current, incoming string, exact bool) string { return incoming } - var cur, inc map[string]json.RawMessage - if json.Unmarshal([]byte(current), &cur) != nil || json.Unmarshal([]byte(incoming), &inc) != nil { + var cur, inc map[string]jsontext.Value + if json.Unmarshal([]byte(current), &cur, jsonx.V1()) != nil || + json.Unmarshal([]byte(incoming), &inc, jsonx.V1()) != nil { return incoming } maps.Copy(cur, inc) - out, err := json.Marshal(cur) + out, err := json.Marshal(cur, jsonx.V1()) if err != nil { return incoming } diff --git a/services/dms/engine.go b/services/dms/engine.go index 52b3305115..da381f970f 100644 --- a/services/dms/engine.go +++ b/services/dms/engine.go @@ -4,13 +4,14 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "sync" "time" "github.com/blackbirdworks/gopherstack/pkgs/dmsengine" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -153,7 +154,7 @@ func endpointConfig(ep *Endpoint) dmsengine.EndpointConfig { Port int `json:"Port"` } - if json.Unmarshal([]byte(raw), &s) == nil && s.ServerName != "" { + if json.Unmarshal([]byte(raw), &s, jsonx.V1()) == nil && s.ServerName != "" { cfg.Server, cfg.Port, cfg.Database = s.ServerName, s.Port, s.DatabaseName cfg.User, cfg.Password = s.Username, s.Password diff --git a/services/dms/handler.go b/services/dms/handler.go index 01e9a6fcbd..2cd5e1f11a 100644 --- a/services/dms/handler.go +++ b/services/dms/handler.go @@ -2,7 +2,7 @@ package dms import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" @@ -332,7 +333,7 @@ func extractField(c *echo.Context, keys ...string) string { } var raw map[string]string - if unmarshalErr := json.Unmarshal(bodyBytes, &raw); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(bodyBytes, &raw, jsonx.V1()); unmarshalErr != nil { return "" } @@ -380,7 +381,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { diff --git a/services/dms/handler_assessment_runs_test.go b/services/dms/handler_assessment_runs_test.go index bc5d16b60e..50239ccc3e 100644 --- a/services/dms/handler_assessment_runs_test.go +++ b/services/dms/handler_assessment_runs_test.go @@ -1,7 +1,7 @@ package dms_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -150,7 +151,7 @@ func TestStartReplicationTaskAssessment(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundFault", body["__type"]) }) @@ -250,7 +251,7 @@ func TestStartReplicationTaskAssessment(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidResourceStateFault", body["__type"]) }) @@ -274,7 +275,7 @@ func TestStartReplicationTaskAssessment(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidResourceStateFault", body["__type"]) }) } diff --git a/services/dms/handler_data_providers.go b/services/dms/handler_data_providers.go index 2d82f1ef47..ae82969d8d 100644 --- a/services/dms/handler_data_providers.go +++ b/services/dms/handler_data_providers.go @@ -2,30 +2,32 @@ package dms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/pkgs/service" ) type createDataProviderInput struct { - DataProviderName *string `json:"DataProviderName"` - Engine *string `json:"Engine"` - Description *string `json:"Description"` - Settings json.RawMessage `json:"Settings"` - Virtual *bool `json:"Virtual"` - Tags []tagEntry `json:"Tags"` + DataProviderName *string `json:"DataProviderName"` + Engine *string `json:"Engine"` + Description *string `json:"Description"` + Settings jsontext.Value `json:"Settings"` + Virtual *bool `json:"Virtual"` + Tags []tagEntry `json:"Tags"` } type dataProviderJSON struct { - DataProviderName string `json:"DataProviderName"` - DataProviderArn string `json:"DataProviderArn"` - Engine string `json:"Engine"` - Description string `json:"Description,omitempty"` - Settings json.RawMessage `json:"Settings,omitempty"` - Virtual bool `json:"Virtual,omitempty"` + DataProviderName string `json:"DataProviderName"` + DataProviderArn string `json:"DataProviderArn"` + Engine string `json:"Engine"` + Description string `json:"Description,omitempty"` + Settings jsontext.Value `json:"Settings,omitempty"` + Virtual bool `json:"Virtual,omitempty"` } type createDataProviderOutput struct { @@ -80,13 +82,13 @@ func isDataProviderSettingsArm(arm string) bool { // validateDataProviderSettings checks that a supplied Settings document is a // union with exactly one known member and returns it as a string. -func validateDataProviderSettings(raw json.RawMessage) (string, error) { +func validateDataProviderSettings(raw jsontext.Value) (string, error) { if len(raw) == 0 || string(raw) == "null" { return "", nil } - var doc map[string]json.RawMessage - if err := json.Unmarshal(raw, &doc); err != nil || len(doc) != 1 { + var doc map[string]jsontext.Value + if err := json.Unmarshal(raw, &doc, jsonx.V1()); err != nil || len(doc) != 1 { return "", fmt.Errorf("%w: Settings must be a union with exactly one member", ErrValidation) } @@ -108,7 +110,7 @@ func dpToJSON(dp *DataProvider) dataProviderJSON { Virtual: dp.Virtual, } if dp.Settings != "" { - out.Settings = json.RawMessage(dp.Settings) + out.Settings = jsontext.Value(dp.Settings) } return out @@ -173,13 +175,13 @@ func (h *Handler) handleDescribeDataProviders( } type modifyDataProviderInput struct { - DataProviderIdentifier *string `json:"DataProviderIdentifier"` - DataProviderName *string `json:"DataProviderName"` - Engine *string `json:"Engine"` - Description *string `json:"Description"` - Virtual *bool `json:"Virtual"` - ExactSettings *bool `json:"ExactSettings"` - Settings json.RawMessage `json:"Settings"` + DataProviderIdentifier *string `json:"DataProviderIdentifier"` + DataProviderName *string `json:"DataProviderName"` + Engine *string `json:"Engine"` + Description *string `json:"Description"` + Virtual *bool `json:"Virtual"` + ExactSettings *bool `json:"ExactSettings"` + Settings jsontext.Value `json:"Settings"` } type modifyDataProviderOutput struct { diff --git a/services/dms/handler_data_providers_test.go b/services/dms/handler_data_providers_test.go index fdbe2237cd..eb884557a6 100644 --- a/services/dms/handler_data_providers_test.go +++ b/services/dms/handler_data_providers_test.go @@ -1,7 +1,7 @@ package dms_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -125,7 +126,7 @@ func TestDeleteDataProvider_NotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundFault", body["__type"]) } diff --git a/services/dms/handler_endpoints.go b/services/dms/handler_endpoints.go index 83db2ccf75..65db07f692 100644 --- a/services/dms/handler_endpoints.go +++ b/services/dms/handler_endpoints.go @@ -2,13 +2,15 @@ package dms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "sync" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -17,25 +19,25 @@ import ( // CreateEndpoint/ModifyEndpoint (api_op_CreateEndpoint.go, databasemigrationservice@v1.66.4). // Blocks are stored as raw JSON and echoed back; no engine consumes them. type engineSettingsFields struct { - DmsTransferSettings json.RawMessage `json:"DmsTransferSettings,omitempty"` - DocDBSettings json.RawMessage `json:"DocDbSettings,omitempty"` - DynamoDBSettings json.RawMessage `json:"DynamoDbSettings,omitempty"` - ElasticsearchSettings json.RawMessage `json:"ElasticsearchSettings,omitempty"` - GcpMySQLSettings json.RawMessage `json:"GcpMySQLSettings,omitempty"` - IBMDb2Settings json.RawMessage `json:"IBMDb2Settings,omitempty"` - KafkaSettings json.RawMessage `json:"KafkaSettings,omitempty"` - KinesisSettings json.RawMessage `json:"KinesisSettings,omitempty"` - MicrosoftSQLServerSettings json.RawMessage `json:"MicrosoftSQLServerSettings,omitempty"` - MongoDBSettings json.RawMessage `json:"MongoDbSettings,omitempty"` - MySQLSettings json.RawMessage `json:"MySQLSettings,omitempty"` - NeptuneSettings json.RawMessage `json:"NeptuneSettings,omitempty"` - OracleSettings json.RawMessage `json:"OracleSettings,omitempty"` - PostgreSQLSettings json.RawMessage `json:"PostgreSQLSettings,omitempty"` - RedisSettings json.RawMessage `json:"RedisSettings,omitempty"` - RedshiftSettings json.RawMessage `json:"RedshiftSettings,omitempty"` - S3Settings json.RawMessage `json:"S3Settings,omitempty"` - SybaseSettings json.RawMessage `json:"SybaseSettings,omitempty"` - TimestreamSettings json.RawMessage `json:"TimestreamSettings,omitempty"` + DmsTransferSettings jsontext.Value `json:"DmsTransferSettings,omitempty"` + DocDBSettings jsontext.Value `json:"DocDbSettings,omitempty"` + DynamoDBSettings jsontext.Value `json:"DynamoDbSettings,omitempty"` + ElasticsearchSettings jsontext.Value `json:"ElasticsearchSettings,omitempty"` + GcpMySQLSettings jsontext.Value `json:"GcpMySQLSettings,omitempty"` + IBMDb2Settings jsontext.Value `json:"IBMDb2Settings,omitempty"` + KafkaSettings jsontext.Value `json:"KafkaSettings,omitempty"` + KinesisSettings jsontext.Value `json:"KinesisSettings,omitempty"` + MicrosoftSQLServerSettings jsontext.Value `json:"MicrosoftSQLServerSettings,omitempty"` + MongoDBSettings jsontext.Value `json:"MongoDbSettings,omitempty"` + MySQLSettings jsontext.Value `json:"MySQLSettings,omitempty"` + NeptuneSettings jsontext.Value `json:"NeptuneSettings,omitempty"` + OracleSettings jsontext.Value `json:"OracleSettings,omitempty"` + PostgreSQLSettings jsontext.Value `json:"PostgreSQLSettings,omitempty"` + RedisSettings jsontext.Value `json:"RedisSettings,omitempty"` + RedshiftSettings jsontext.Value `json:"RedshiftSettings,omitempty"` + S3Settings jsontext.Value `json:"S3Settings,omitempty"` + SybaseSettings jsontext.Value `json:"SybaseSettings,omitempty"` + TimestreamSettings jsontext.Value `json:"TimestreamSettings,omitempty"` } // endpointSecretKeys are the credential members inside the engine settings @@ -46,16 +48,16 @@ var endpointSecretKeys = []string{ //nolint:gochecknoglobals // immutable lookup // rawIsSet reports whether a json.RawMessage field was present in the request // body with a non-null value. -func rawIsSet(raw json.RawMessage) bool { +func rawIsSet(raw jsontext.Value) bool { return len(raw) > 0 && string(raw) != "null" } func (f *engineSettingsFields) entries() []struct { - raw *json.RawMessage + raw *jsontext.Value name string } { return []struct { - raw *json.RawMessage + raw *jsontext.Value name string }{ {&f.DmsTransferSettings, "DmsTransferSettings"}, @@ -89,8 +91,8 @@ func (f *engineSettingsFields) otherSettings() (map[string]string, error) { continue } - var obj map[string]json.RawMessage - if err := json.Unmarshal(*e.raw, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(*e.raw, &obj, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %s must be an object", ErrValidation, e.name) } @@ -113,19 +115,19 @@ func (f *engineSettingsFields) apply(stored map[string]string) { } } -func redactEndpointSecrets(raw string) json.RawMessage { - var obj map[string]json.RawMessage - if json.Unmarshal([]byte(raw), &obj) != nil { - return json.RawMessage(raw) +func redactEndpointSecrets(raw string) jsontext.Value { + var obj map[string]jsontext.Value + if json.Unmarshal([]byte(raw), &obj, jsonx.V1()) != nil { + return jsontext.Value(raw) } for _, k := range endpointSecretKeys { delete(obj, k) } - out, err := json.Marshal(obj) + out, err := json.Marshal(obj, jsonx.V1()) if err != nil { - return json.RawMessage(raw) + return jsontext.Value(raw) } return out @@ -376,7 +378,7 @@ func epToJSON(ep *Endpoint) endpointJSON { } if ep.S3Settings != "" { - out.S3Settings = json.RawMessage(ep.S3Settings) + out.S3Settings = jsontext.Value(ep.S3Settings) } out.apply(ep.EngineSettings) diff --git a/services/dms/handler_endpoints_test.go b/services/dms/handler_endpoints_test.go index c62db0e2ff..ad4af382b5 100644 --- a/services/dms/handler_endpoints_test.go +++ b/services/dms/handler_endpoints_test.go @@ -1,7 +1,7 @@ package dms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -378,7 +379,7 @@ func TestDeleteEndpoint_RejectsIfInUse(t *testing.T) { require.Equal(t, http.StatusBadRequest, delRec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidResourceStateFault", body["__type"], "deleting an endpoint used by a task must return InvalidResourceStateFault") }) diff --git a/services/dms/handler_event_subscriptions_test.go b/services/dms/handler_event_subscriptions_test.go index 0e53c48675..99d77b9a1a 100644 --- a/services/dms/handler_event_subscriptions_test.go +++ b/services/dms/handler_event_subscriptions_test.go @@ -1,13 +1,14 @@ package dms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -65,7 +66,7 @@ func TestCreateEventSubscription_Duplicate(t *testing.T) { require.Equal(t, http.StatusConflict, rec2.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ResourceAlreadyExistsFault", errBody["__type"]) } diff --git a/services/dms/handler_replication_configs.go b/services/dms/handler_replication_configs.go index 562a3424e7..1a5a83666e 100644 --- a/services/dms/handler_replication_configs.go +++ b/services/dms/handler_replication_configs.go @@ -2,12 +2,13 @@ package dms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -449,7 +450,7 @@ func validatePremigrationAssessmentSettings(raw string) error { FailOnAssessmentFailure *bool `json:"FailOnAssessmentFailure"` } - if err := json.Unmarshal([]byte(raw), &settings); err != nil { + if err := json.Unmarshal([]byte(raw), &settings, jsonx.V1()); err != nil { return fmt.Errorf("%w: PremigrationAssessmentSettings is not a valid settings object: %w", ErrValidation, err) } diff --git a/services/dms/handler_replication_tasks.go b/services/dms/handler_replication_tasks.go index c752128118..feecd090c0 100644 --- a/services/dms/handler_replication_tasks.go +++ b/services/dms/handler_replication_tasks.go @@ -2,12 +2,13 @@ package dms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/dmsengine" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -402,7 +403,7 @@ func buildTableStatistics(tableMappings string) []tableStatisticJSON { } var doc tableMappingsDoc - if err := json.Unmarshal([]byte(tableMappings), &doc); err != nil { + if err := json.Unmarshal([]byte(tableMappings), &doc, jsonx.V1()); err != nil { return []tableStatisticJSON{} } diff --git a/services/dms/handler_replication_tasks_test.go b/services/dms/handler_replication_tasks_test.go index 1ee271336a..311f4139df 100644 --- a/services/dms/handler_replication_tasks_test.go +++ b/services/dms/handler_replication_tasks_test.go @@ -1,7 +1,7 @@ package dms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -191,7 +192,7 @@ func TestCreateReplicationTask_ARNValidation(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundFault", body["__type"], "non-existent ARN in CreateReplicationTask must return ResourceNotFoundFault") }) @@ -227,7 +228,7 @@ func TestCreateReplicationTask_InvalidMigrationType(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"], "invalid MigrationType must return ValidationException") }) @@ -306,7 +307,7 @@ func TestStopReplicationTask_NotRunning(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidResourceStateFault", body["__type"], "stopping a non-running task must return InvalidResourceStateFault") }) diff --git a/services/dms/handler_test.go b/services/dms/handler_test.go index 3ae1e74a6a..5bd5257e63 100644 --- a/services/dms/handler_test.go +++ b/services/dms/handler_test.go @@ -2,7 +2,7 @@ package dms_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dms" ) @@ -24,7 +25,7 @@ func newTestDMSHandler() *dms.Handler { func doDMS(t *testing.T, h *dms.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -45,7 +46,7 @@ func parseJSON(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -266,7 +267,7 @@ func TestHandler_ExtractResource(t *testing.T) { t.Parallel() h := newTestDMSHandler() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -733,7 +734,7 @@ func TestValidationException_NotInvalidResourceStateFault(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) errType, ok := body["__type"].(string) require.True(t, ok, "response must have __type field") @@ -800,7 +801,7 @@ func TestInvalidResourceStateFault_ForStateErrors(t *testing.T) { require.Equal(t, http.StatusBadRequest, startAgainRec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(startAgainRec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(startAgainRec.Body.Bytes(), &body, jsonx.V1())) errType, ok := body["__type"].(string) require.True(t, ok, "response must have __type field") diff --git a/services/dms/persistence.go b/services/dms/persistence.go index 25e0ac2f72..59fd28f000 100644 --- a/services/dms/persistence.go +++ b/services/dms/persistence.go @@ -2,9 +2,11 @@ package dms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -43,7 +45,7 @@ const dmsSnapshotVersion = 1 // non-serializable live fields. ResourceTags is the side table that // survives what Tables can't carry -- see reinitTagsLocked. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourceTags map[string]map[string]string `json:"resourceTags,omitempty"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -70,7 +72,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "dms: Snapshot marshal failure", "error", err) diff --git a/services/dms/validation.go b/services/dms/validation.go index 0c5f1b3834..622b8e61ac 100644 --- a/services/dms/validation.go +++ b/services/dms/validation.go @@ -1,11 +1,13 @@ package dms import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -45,7 +47,7 @@ func validateReplicationInstanceInput(identifier, class string, allocatedStorage } func validateTableMappings(mappings string) error { - if mappings != "" && !json.Valid([]byte(mappings)) { + if mappings != "" && !jsontext.Value([]byte(mappings)).IsValid(jsonx.V1()) { return fmt.Errorf("%w: TableMappings must be valid JSON", ErrValidation) } @@ -59,7 +61,7 @@ func (h *Handler) checkMarker(body []byte) error { NextToken *string `json:"NextToken"` } - if json.Unmarshal(body, &in) != nil { + if json.Unmarshal(body, &in, jsonx.V1()) != nil { return nil //nolint:nilerr // malformed bodies are rejected by the op decoder } diff --git a/services/docdb/master_secret.go b/services/docdb/master_secret.go index 1ad5f23abe..f7ed329317 100644 --- a/services/docdb/master_secret.go +++ b/services/docdb/master_secret.go @@ -3,13 +3,14 @@ package docdb import ( "crypto/rand" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net/url" "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -40,7 +41,7 @@ func masterSecretBody(user string) (string, string, error) { password := hex.EncodeToString(raw) - body, err := json.Marshal(map[string]string{"username": user, "password": password}) + body, err := json.Marshal(map[string]string{"username": user, "password": password}, jsonx.V1()) if err != nil { return "", "", fmt.Errorf("encode master user secret: %w", err) } diff --git a/services/docdb/persistence.go b/services/docdb/persistence.go index 8b372b82eb..27f03718ce 100644 --- a/services/docdb/persistence.go +++ b/services/docdb/persistence.go @@ -2,7 +2,7 @@ package docdb import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -52,7 +52,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // guards against decoding a snapshot from an incompatible (older or newer) // build of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string][]Tag `json:"tags"` EventsLog map[string][]Event `json:"eventsLog"` PendingMaintenanceActions map[string]map[string]PendingMaintenanceAction `json:"pendingMaintenanceActions"` @@ -252,7 +252,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, clusterDTOs, instanceDTOs, subnetGroupDTOs, clusterParameterGroupDTOs, clusterSnapshotDTOs, eventSubscriptionDTOs, snapshotAttributesDTOs, globalClusterDTOs := buildPersistenceDTORegistry() diff --git a/services/dsql/handler_clusters.go b/services/dsql/handler_clusters.go index f5a1383f95..953b54e073 100644 --- a/services/dsql/handler_clusters.go +++ b/services/dsql/handler_clusters.go @@ -2,11 +2,13 @@ package dsql import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchClusterOps handles cluster CRUD and vpc-endpoint-service-name operations. @@ -37,7 +39,7 @@ func (h *Handler) dispatchClusterOps( func (h *Handler) handleCreateCluster(ctx context.Context, c *echo.Context, body []byte) error { var req createClusterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeInvalidBody(c) } } @@ -98,7 +100,7 @@ func (h *Handler) handleListClusters(c *echo.Context) error { func (h *Handler) handleUpdateCluster(c *echo.Context, identifier string, body []byte) error { var req updateClusterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeInvalidBody(c) } } diff --git a/services/dsql/handler_policy.go b/services/dsql/handler_policy.go index 1b12f264e9..3eb6f8d5da 100644 --- a/services/dsql/handler_policy.go +++ b/services/dsql/handler_policy.go @@ -1,10 +1,12 @@ package dsql import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchPolicyOps handles cluster resource-policy operations. @@ -32,7 +34,7 @@ func (h *Handler) handleGetClusterPolicy(c *echo.Context, identifier string) err func (h *Handler) handlePutClusterPolicy(c *echo.Context, identifier string, body []byte) error { var req putClusterPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeInvalidBody(c) } diff --git a/services/dsql/handler_streams.go b/services/dsql/handler_streams.go index 7622ba5a3f..0f21015838 100644 --- a/services/dsql/handler_streams.go +++ b/services/dsql/handler_streams.go @@ -1,11 +1,13 @@ package dsql import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchStreamOps handles cluster change-data-capture stream operations. @@ -26,7 +28,7 @@ func (h *Handler) dispatchStreamOps(c *echo.Context, op, resource string, body [ func (h *Handler) handleCreateStream(c *echo.Context, clusterIdentifier string, body []byte) error { var req createStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeInvalidBody(c) } diff --git a/services/dsql/handler_tags.go b/services/dsql/handler_tags.go index 16c71a726c..e34eec5a6f 100644 --- a/services/dsql/handler_tags.go +++ b/services/dsql/handler_tags.go @@ -1,10 +1,12 @@ package dsql import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchTagOps handles the generic ARN-scoped tagging trio. @@ -23,7 +25,7 @@ func (h *Handler) dispatchTagOps(c *echo.Context, op, resource string, body []by func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeInvalidBody(c) } diff --git a/services/dsql/persistence.go b/services/dsql/persistence.go index f5c26dac25..0ff65d6a43 100644 --- a/services/dsql/persistence.go +++ b/services/dsql/persistence.go @@ -2,7 +2,7 @@ package dsql import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -29,8 +29,8 @@ const dsqlSnapshotVersion = 1 // holds one JSON-encoded array per registered table name (clusters, streams // -- see store_setup.go), produced by b.registry.SnapshotAll(). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes backend state to JSON. diff --git a/services/dsql/validation.go b/services/dsql/validation.go index 14f414ab05..a6f7dbacbd 100644 --- a/services/dsql/validation.go +++ b/services/dsql/validation.go @@ -1,7 +1,7 @@ package dsql import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -46,7 +47,7 @@ func (b *InMemoryBackend) dwell(def time.Duration) time.Duration { func validatePolicyDocument(policy string) error { var doc map[string]any - if policy == "" || json.Unmarshal([]byte(policy), &doc) != nil || doc == nil { + if policy == "" || json.Unmarshal([]byte(policy), &doc, jsonx.V1()) != nil || doc == nil { return fmt.Errorf("%w: policy must be a valid JSON policy document", ErrValidation) } diff --git a/services/dynamodb/backup_interface_test.go b/services/dynamodb/backup_interface_test.go index e695473ac5..c1b3217230 100644 --- a/services/dynamodb/backup_interface_test.go +++ b/services/dynamodb/backup_interface_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "log/slog" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -645,7 +646,7 @@ func TestHandler_TagOperations_Via_Handler(t *testing.T) { doHandlerReq := func(target string, payload any) *httptest.ResponseRecorder { t.Helper() - body, marshalErr := json.Marshal(payload) + body, marshalErr := json.Marshal(payload, jsonx.V1()) require.NoError(t, marshalErr) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", target) @@ -689,7 +690,7 @@ func TestHandler_TableMutationOps_Via_Handler(t *testing.T) { doHandlerReq := func(target string, payload any) *httptest.ResponseRecorder { t.Helper() - body, marshalErr := json.Marshal(payload) + body, marshalErr := json.Marshal(payload, jsonx.V1()) require.NoError(t, marshalErr) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", target) @@ -732,7 +733,7 @@ func TestHandler_UpdateTable_Via_Handler(t *testing.T) { body, err := json.Marshal(map[string]any{ "TableName": "UpdateMe", "BillingMode": "PAY_PER_REQUEST", - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -783,7 +784,7 @@ func TestHandler_RestoreTableToPointInTime(t *testing.T) { "PointInTimeRecoverySpecification": map[string]any{ "PointInTimeRecoveryEnabled": true, }, - }) + }, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", "DynamoDB_20120810.UpdateContinuousBackups") req.Header.Set("Content-Type", "application/x-amz-json-1.0") @@ -813,7 +814,7 @@ func TestHandler_RestoreTableToPointInTime(t *testing.T) { tt.setup(t, db) } - body, err := json.Marshal(tt.payload) + body, err := json.Marshal(tt.payload, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -892,7 +893,7 @@ func TestInMemoryDB_ListBackups_BackupTypeFilter(t *testing.T) { body, marshalErr := json.Marshal(map[string]any{ "TableName": "T", "BackupType": "USER", - }) + }, jsonx.V1()) require.NoError(t, marshalErr) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -908,7 +909,7 @@ func TestInMemoryDB_ListBackups_BackupTypeFilter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["BackupSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 2) @@ -931,7 +932,7 @@ func TestInMemoryDB_PutResourcePolicy_EmptyPolicy(t *testing.T) { body, marshalErr := json.Marshal(map[string]any{ "ResourceArn": tableARN, "Policy": "", - }) + }, jsonx.V1()) require.NoError(t, marshalErr) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -1324,7 +1325,7 @@ func TestInMemoryDB_DescribeBackup_ViaHandler(t *testing.T) { require.NoError(t, err) backupArn := aws.ToString(out.BackupDetails.BackupArn) - reqBody, _ := json.Marshal(map[string]string{"BackupArn": backupArn}) + reqBody, _ := json.Marshal(map[string]string{"BackupArn": backupArn}, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(reqBody)) req.Header.Set("Content-Type", "application/x-amz-json-1.0") @@ -1336,7 +1337,7 @@ func TestInMemoryDB_DescribeBackup_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var respBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody, jsonx.V1())) assert.Contains(t, respBody, "BackupDescription") } diff --git a/services/dynamodb/backup_ops.go b/services/dynamodb/backup_ops.go index a4978814af..6b80d17ca6 100644 --- a/services/dynamodb/backup_ops.go +++ b/services/dynamodb/backup_ops.go @@ -2,7 +2,7 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -37,7 +38,7 @@ func backupARN(region, accountID, tableName string, ts time.Time) string { func (h *DynamoDBHandler) createBackup(ctx context.Context, body []byte) (any, error) { var req models.CreateBackupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -65,7 +66,7 @@ func (h *DynamoDBHandler) createBackup(ctx context.Context, body []byte) (any, e func (h *DynamoDBHandler) describeBackup(ctx context.Context, body []byte) (any, error) { var req models.DescribeBackupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -89,7 +90,7 @@ func (h *DynamoDBHandler) describeBackup(ctx context.Context, body []byte) (any, func (h *DynamoDBHandler) deleteBackup(ctx context.Context, body []byte) (any, error) { var req models.DeleteBackupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -107,7 +108,7 @@ func (h *DynamoDBHandler) deleteBackup(ctx context.Context, body []byte) (any, e func (h *DynamoDBHandler) listBackups(ctx context.Context, body []byte) (any, error) { var req models.ListBackupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -420,7 +421,7 @@ func toSDKLSIOverride(lsis []models.LocalSecondaryIndex) []sdktypes.LocalSeconda func (h *DynamoDBHandler) restoreTableFromBackup(ctx context.Context, body []byte) (any, error) { var req models.RestoreTableFromBackupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -500,7 +501,7 @@ func toSDKRestoreDateTime(secs *float64) *time.Time { func (h *DynamoDBHandler) restoreTableToPointInTime(ctx context.Context, body []byte) (any, error) { var req models.RestoreTableToPointInTimeInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/backup_replica_test.go b/services/dynamodb/backup_replica_test.go index 92f6f2b025..62f88014d5 100644 --- a/services/dynamodb/backup_replica_test.go +++ b/services/dynamodb/backup_replica_test.go @@ -3,7 +3,7 @@ package dynamodb_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" @@ -29,7 +30,7 @@ func doBackupRequest( ) (int, map[string]any) { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(raw)) @@ -40,7 +41,7 @@ func doBackupRequest( require.NoError(t, serveEchoHandler(h.Handler(), w, req)) var result map[string]any - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &result, jsonx.V1())) return w.Code, result } diff --git a/services/dynamodb/bench_extract_resource_test.go b/services/dynamodb/bench_extract_resource_test.go index 4a3a1b649e..882f7e5ceb 100644 --- a/services/dynamodb/bench_extract_resource_test.go +++ b/services/dynamodb/bench_extract_resource_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -28,7 +29,7 @@ func BenchmarkExtractResource(b *testing.B) { "TableName": "BenchTable", "Item": item, } - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) if err != nil { b.Fatalf("marshal request body: %v", err) } diff --git a/services/dynamodb/bench_hot_ops_test.go b/services/dynamodb/bench_hot_ops_test.go index 01f5ba388b..86bba4b1e1 100644 --- a/services/dynamodb/bench_hot_ops_test.go +++ b/services/dynamodb/bench_hot_ops_test.go @@ -2,13 +2,14 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" "strconv" "testing" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -26,7 +27,7 @@ func benchRawOp(b *testing.B, h *dynamodb.DynamoDBHandler, action string, body [ func benchMarshal(b *testing.B, v any) []byte { b.Helper() - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { b.Fatal(err) } diff --git a/services/dynamodb/cbor_test.go b/services/dynamodb/cbor_test.go index 403fcd2f20..bea346638b 100644 --- a/services/dynamodb/cbor_test.go +++ b/services/dynamodb/cbor_test.go @@ -3,7 +3,7 @@ package dynamodb_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -478,7 +479,7 @@ func TestDynamoDBCBOR_JSONAndCBORCoexist(t *testing.T) { require.Equal(t, http.StatusOK, getRR2.Code) var jsonResp map[string]any - require.NoError(t, json.Unmarshal(getRR2.Body.Bytes(), &jsonResp)) + require.NoError(t, json.Unmarshal(getRR2.Body.Bytes(), &jsonResp, jsonx.V1())) itemJSON := jsonResp["Item"].(map[string]any) valueJSON := itemJSON["value"].(map[string]any) assert.Equal(t, "from-cbor", valueJSON["S"]) diff --git a/services/dynamodb/condition_check_return_test.go b/services/dynamodb/condition_check_return_test.go index ef200f1f75..aff502b79e 100644 --- a/services/dynamodb/condition_check_return_test.go +++ b/services/dynamodb/condition_check_return_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -34,7 +35,7 @@ func doDDBRequest( var decoded map[string]any if w.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &decoded)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &decoded, jsonx.V1())) } return resp.StatusCode, decoded diff --git a/services/dynamodb/expr/evaluator.go b/services/dynamodb/expr/evaluator.go index 9c899e263d..79ee2471c9 100644 --- a/services/dynamodb/expr/evaluator.go +++ b/services/dynamodb/expr/evaluator.go @@ -2,7 +2,7 @@ package expr import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "math" @@ -11,6 +11,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/dynamonum" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Sentinel errors for evaluator. @@ -480,9 +481,9 @@ func containsList(l, targetVal any) bool { if !isList { return false } - targetJSON, _ := json.Marshal(targetVal) + targetJSON, _ := json.Marshal(targetVal, jsonx.V1()) for _, item := range items { - itemJSON, _ := json.Marshal(item) + itemJSON, _ := json.Marshal(item, jsonx.V1()) if string(itemJSON) == string(targetJSON) { return true } @@ -657,7 +658,7 @@ func (e *Evaluator) toString(v any) string { case nil: return "" default: - b, _ := json.Marshal(s) + b, _ := json.Marshal(s, jsonx.V1()) return string(b) } diff --git a/services/dynamodb/global_tables_test.go b/services/dynamodb/global_tables_test.go index 6a74ba3c6f..1bfd3919fb 100644 --- a/services/dynamodb/global_tables_test.go +++ b/services/dynamodb/global_tables_test.go @@ -1,7 +1,7 @@ package dynamodb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -149,7 +150,7 @@ func TestGlobalTables(t *testing.T) { assert.Equal(t, tt.wantStatus, code) if tt.wantBodyContains != "" { - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), tt.wantBodyContains) } }) @@ -883,7 +884,7 @@ func TestUpdateGlobalTableSettings_NotFound_ViaHandler(t *testing.T) { "GlobalTableName": "NoSuchGT", }) require.Equal(t, http.StatusBadRequest, code) - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), "GlobalTableNotFoundException") } diff --git a/services/dynamodb/golden_perf_test.go b/services/dynamodb/golden_perf_test.go index 9fcccf924c..b3d29cf05c 100644 --- a/services/dynamodb/golden_perf_test.go +++ b/services/dynamodb/golden_perf_test.go @@ -11,7 +11,8 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" "path/filepath" @@ -20,6 +21,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -32,9 +34,9 @@ func goldenPath(name string) string { func checkGolden(t *testing.T, name string, got []byte) { t.Helper() - var buf bytes.Buffer - require.NoError(t, json.Indent(&buf, got, "", " ")) - pretty := buf.Bytes() + indented := jsontext.Value(bytes.Clone(got)) + require.NoError(t, indented.Indent(jsonx.V1(), jsontext.WithIndent(" "))) + pretty := []byte(indented) path := goldenPath(name) if os.Getenv("DYNAMODB_GOLDEN_UPDATE") != "" { @@ -114,7 +116,7 @@ func TestGolden_QueryKeyConditionFilterProjection(t *testing.T) { }) require.Equal(t, 200, code, "Query: %v", resp) - raw, err := json.Marshal(resp) + raw, err := json.Marshal(resp, jsonx.V1()) require.NoError(t, err) checkGolden(t, "golden_query.json", raw) } @@ -141,7 +143,7 @@ func TestGolden_ScanFilter(t *testing.T) { }) require.Equal(t, 200, code, "Scan: %v", resp) - raw, err := json.Marshal(resp) + raw, err := json.Marshal(resp, jsonx.V1()) require.NoError(t, err) checkGolden(t, "golden_scan.json", raw) } @@ -184,7 +186,7 @@ func TestGolden_TransactWriteItems(t *testing.T) { }) require.Equal(t, 200, code, "TransactWriteItems: %v", resp) - raw, err := json.Marshal(resp) + raw, err := json.Marshal(resp, jsonx.V1()) require.NoError(t, err) checkGolden(t, "golden_transact.json", raw) } diff --git a/services/dynamodb/handler.go b/services/dynamodb/handler.go index e4e250cea3..1ac9fd642d 100644 --- a/services/dynamodb/handler.go +++ b/services/dynamodb/handler.go @@ -2,7 +2,7 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "hash/crc32" @@ -19,6 +19,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/chaos" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" @@ -458,7 +459,7 @@ func (h *DynamoDBHandler) ExtractResource(c *echo.Context) string { TableName string `json:"TableName"` BackupArn string `json:"BackupArn"` } - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -614,14 +615,14 @@ func handleOpErr[WireIn any, SDKIn any, SDKOut any, WireOut any]( var input WireIn if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } debugEnabled := log.Enabled(ctx, slog.LevelDebug) if debugEnabled { - inputJSON, _ := json.Marshal(input) + inputJSON, _ := json.Marshal(input, jsonx.V1()) log.DebugContext(ctx, "handler input", "action", action, "input", string(inputJSON)) } @@ -637,7 +638,7 @@ func handleOpErr[WireIn any, SDKIn any, SDKOut any, WireOut any]( wireOutput := fromSDK(sdkOutput) if debugEnabled { - outputJSON, _ := json.Marshal(wireOutput) + outputJSON, _ := json.Marshal(wireOutput, jsonx.V1()) log.DebugContext(ctx, "handler output", "action", action, "output", string(outputJSON)) } @@ -657,14 +658,14 @@ func handleOp[WireIn any, SDKIn any, SDKOut any, WireOut any]( var input WireIn if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } } debugEnabled := log.Enabled(ctx, slog.LevelDebug) if debugEnabled { - inputJSON, _ := json.Marshal(input) + inputJSON, _ := json.Marshal(input, jsonx.V1()) log.DebugContext(ctx, "handler input", "action", action, "input", string(inputJSON)) } @@ -677,7 +678,7 @@ func handleOp[WireIn any, SDKIn any, SDKOut any, WireOut any]( wireOutput := fromSDK(sdkOutput) if debugEnabled { - outputJSON, _ := json.Marshal(wireOutput) + outputJSON, _ := json.Marshal(wireOutput, jsonx.V1()) log.DebugContext(ctx, "handler output", "action", action, "output", string(outputJSON)) } @@ -877,7 +878,7 @@ func validateTableNameFromBody(body []byte) error { TableName string `json:"TableName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.TableName == "" { return nil // missing table name is handled downstream } @@ -894,7 +895,7 @@ func validateTableNameFromBody(body []byte) error { // such response reached a client as smithy.GenericAPIError{Code:"UnknownError"} // (gopherstack-wlo1). func writeDynamoDBDispatchError(c *echo.Context, status int, errType, message string) error { - body, err := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}) + body, err := json.Marshal(service.JSONErrorResponse{Type: errType, Message: message}, jsonx.V1()) if err != nil { return err } @@ -932,7 +933,7 @@ func (h *DynamoDBHandler) handleError( c.Response().Header().Set("Content-Type", "application/x-amz-json-1.0") - payload, _ := json.Marshal(awsErr) + payload, _ := json.Marshal(awsErr, jsonx.V1()) checksum := crc32.ChecksumIEEE(payload) c.Response().Header().Set("X-Amz-Crc32", strconv.FormatUint(uint64(checksum), 10)) @@ -955,9 +956,7 @@ func (h *DynamoDBHandler) classifyError(reqErr error) (int, *Error) { } // Fallback - var syntaxErr *json.SyntaxError - var unmarshalTypeError *json.UnmarshalTypeError - if errors.As(reqErr, &syntaxErr) || errors.As(reqErr, &unmarshalTypeError) { + if jsonx.IsSyntaxError(reqErr) || jsonx.IsTypeError(reqErr) { return http.StatusBadRequest, NewValidationException( "JSON Error: " + reqErr.Error(), ) diff --git a/services/dynamodb/handler_autoscaling.go b/services/dynamodb/handler_autoscaling.go index 1221bacc14..29517a3bf8 100644 --- a/services/dynamodb/handler_autoscaling.go +++ b/services/dynamodb/handler_autoscaling.go @@ -7,11 +7,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -237,7 +238,7 @@ func (h *DynamoDBHandler) handleUpdateTableReplicaAutoScaling( body []byte, ) (any, error) { var req updateTableReplicaAutoScalingInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_backups.go b/services/dynamodb/handler_backups.go index ea7dc0d90b..56e2c66e22 100644 --- a/services/dynamodb/handler_backups.go +++ b/services/dynamodb/handler_backups.go @@ -9,13 +9,14 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "time" "github.com/aws/aws-sdk-go-v2/aws" sdkdynamodb "github.com/aws/aws-sdk-go-v2/service/dynamodb" sdktypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -75,7 +76,7 @@ func continuousBackupsOutputFromSDK( func (h *DynamoDBHandler) describeContinuousBackups(ctx context.Context, body []byte) (any, error) { var req describeContinuousBackupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -106,7 +107,7 @@ type updateContinuousBackupsInput struct { func (h *DynamoDBHandler) updateContinuousBackups(ctx context.Context, body []byte) (any, error) { var req updateContinuousBackupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -219,7 +220,7 @@ func exportDescFieldsFromSDK(d *sdktypes.ExportDescription) exportDescriptionFie func (h *DynamoDBHandler) exportTableToPointInTime(ctx context.Context, body []byte) (any, error) { var req exportTableToPointInTimeInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -250,7 +251,7 @@ type describeExportInput struct { func (h *DynamoDBHandler) describeExport(ctx context.Context, body []byte) (any, error) { var req describeExportInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -280,7 +281,7 @@ type listExportsInput struct { func (h *DynamoDBHandler) listExports(ctx context.Context, body []byte) (any, error) { var req listExportsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -327,7 +328,7 @@ func (h *DynamoDBHandler) describeTableReplicaAutoScaling( body []byte, ) (any, error) { var req describeTableReplicaAutoScalingInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_contributor_insights.go b/services/dynamodb/handler_contributor_insights.go index c0fe17207c..981a7ecaf8 100644 --- a/services/dynamodb/handler_contributor_insights.go +++ b/services/dynamodb/handler_contributor_insights.go @@ -7,11 +7,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -34,7 +35,7 @@ func (h *DynamoDBHandler) handleDescribeContributorInsights( body []byte, ) (any, error) { var req describeContributorInsightsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -91,7 +92,7 @@ func (h *DynamoDBHandler) handleListContributorInsights( body []byte, ) (any, error) { var req listContributorInsightsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -145,7 +146,7 @@ func (h *DynamoDBHandler) handleUpdateContributorInsights( body []byte, ) (any, error) { var req updateContributorInsightsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_debug_test.go b/services/dynamodb/handler_debug_test.go index e866f44ba1..7355abb92c 100644 --- a/services/dynamodb/handler_debug_test.go +++ b/services/dynamodb/handler_debug_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" @@ -98,7 +99,7 @@ func TestDebugLogging(t *testing.T) { echoHandler := h.Handler() if tt.setupTarget != "" { - setupBody, err := json.Marshal(tt.setupInput) + setupBody, err := json.Marshal(tt.setupInput, jsonx.V1()) require.NoError(t, err) setupReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(setupBody)) @@ -115,7 +116,7 @@ func TestDebugLogging(t *testing.T) { logBuffer.Reset() } - body, err := json.Marshal(tt.input) + body, err := json.Marshal(tt.input, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) diff --git a/services/dynamodb/handler_execute_transaction.go b/services/dynamodb/handler_execute_transaction.go index 59aec334d4..1a5036c98c 100644 --- a/services/dynamodb/handler_execute_transaction.go +++ b/services/dynamodb/handler_execute_transaction.go @@ -7,12 +7,13 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -38,7 +39,7 @@ type executeTransactionOutput struct { func (h *DynamoDBHandler) handleExecuteTransaction(ctx context.Context, body []byte) (any, error) { var req executeTransactionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_global_tables.go b/services/dynamodb/handler_global_tables.go index de7336ecb0..bdfb7c4966 100644 --- a/services/dynamodb/handler_global_tables.go +++ b/services/dynamodb/handler_global_tables.go @@ -7,11 +7,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -91,7 +92,7 @@ type listGlobalTablesOutput struct { func (h *DynamoDBHandler) handleCreateGlobalTable(ctx context.Context, body []byte) (any, error) { var req createGlobalTableInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -118,7 +119,7 @@ func (h *DynamoDBHandler) handleCreateGlobalTable(ctx context.Context, body []by func (h *DynamoDBHandler) handleDescribeGlobalTable(ctx context.Context, body []byte) (any, error) { var req describeGlobalTableInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -139,7 +140,7 @@ func (h *DynamoDBHandler) handleDescribeGlobalTableSettings( body []byte, ) (any, error) { var req describeGlobalTableSettingsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -164,7 +165,7 @@ func (h *DynamoDBHandler) handleDescribeGlobalTableSettings( func (h *DynamoDBHandler) handleListGlobalTables(ctx context.Context, body []byte) (any, error) { var req listGlobalTablesInput if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } } @@ -213,7 +214,7 @@ func (h *DynamoDBHandler) handleListGlobalTables(ctx context.Context, body []byt func (h *DynamoDBHandler) handleUpdateGlobalTable(ctx context.Context, body []byte) (any, error) { var req updateGlobalTableInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -419,7 +420,7 @@ func (h *DynamoDBHandler) handleUpdateGlobalTableSettings( body []byte, ) (any, error) { var req updateGlobalTableSettingsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_import.go b/services/dynamodb/handler_import.go index 9963ea32ef..21bc1b39ba 100644 --- a/services/dynamodb/handler_import.go +++ b/services/dynamodb/handler_import.go @@ -7,12 +7,13 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/aws/aws-sdk-go-v2/aws" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -146,7 +147,7 @@ type describeImportOutput struct { func (h *DynamoDBHandler) handleDescribeImport(ctx context.Context, body []byte) (any, error) { var req describeImportInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -179,7 +180,7 @@ type importTableOutput struct { func (h *DynamoDBHandler) handleImportTable(ctx context.Context, body []byte) (any, error) { var req importTableInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -243,7 +244,7 @@ type listImportsInput struct { func (h *DynamoDBHandler) handleListImports(ctx context.Context, body []byte) (any, error) { var req listImportsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_kinesis_streaming.go b/services/dynamodb/handler_kinesis_streaming.go index 49b48067fb..1be7060ab2 100644 --- a/services/dynamodb/handler_kinesis_streaming.go +++ b/services/dynamodb/handler_kinesis_streaming.go @@ -7,11 +7,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -64,7 +65,7 @@ func (h *DynamoDBHandler) handleDescribeKinesisStreamingDestination( body []byte, ) (any, error) { var req describeKinesisInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -96,7 +97,7 @@ func (h *DynamoDBHandler) handleDisableKinesisStreamingDestination( body []byte, ) (any, error) { var req disableKinesisInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -154,7 +155,7 @@ func (h *DynamoDBHandler) handleEnableKinesisStreamingDestination( body []byte, ) (any, error) { var req enableKinesisInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -229,7 +230,7 @@ func (h *DynamoDBHandler) handleUpdateKinesisStreamingDestination( body []byte, ) (any, error) { var req updateKinesisStreamingDestinationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_resource_policy.go b/services/dynamodb/handler_resource_policy.go index 3196e23876..1c01cb4b63 100644 --- a/services/dynamodb/handler_resource_policy.go +++ b/services/dynamodb/handler_resource_policy.go @@ -7,10 +7,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/aws/aws-sdk-go-v2/aws" sdkDDB "github.com/aws/aws-sdk-go-v2/service/dynamodb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resourcePolicyInput is the wire format shared by Get and PutResourcePolicy. @@ -45,7 +47,7 @@ func (h *DynamoDBHandler) handleDeleteResourcePolicy( body []byte, ) (any, error) { var req deleteResourcePolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -67,7 +69,7 @@ func (h *DynamoDBHandler) handleDeleteResourcePolicy( func (h *DynamoDBHandler) handleGetResourcePolicy(ctx context.Context, body []byte) (any, error) { var req resourcePolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -89,7 +91,7 @@ func (h *DynamoDBHandler) handleGetResourcePolicy(ctx context.Context, body []by func (h *DynamoDBHandler) handlePutResourcePolicy(ctx context.Context, body []byte) (any, error) { var req resourcePolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/dynamodb/handler_streams_test.go b/services/dynamodb/handler_streams_test.go index 9970130ec7..06ec18ab14 100644 --- a/services/dynamodb/handler_streams_test.go +++ b/services/dynamodb/handler_streams_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -264,7 +265,7 @@ func TestHandler_ExportAndDescribeExport(t *testing.T) { ExportArn string `json:"ExportArn"` } `json:"ExportDescription"` } - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &exp)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &exp, jsonx.V1())) require.NotEmpty(t, exp.ExportDescription.ExportArn) // DescribeExport on the returned ARN succeeds. @@ -286,7 +287,7 @@ func TestHandler_DescribeTable_ReturnsStreamFields(t *testing.T) { handler, streamARN := newStreamEnabledHandler(t) - reqBody, err := json.Marshal(models.DescribeTableInput{TableName: "StreamHandlerTable"}) + reqBody, err := json.Marshal(models.DescribeTableInput{TableName: "StreamHandlerTable"}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(reqBody)) @@ -299,7 +300,7 @@ func TestHandler_DescribeTable_ReturnsStreamFields(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) var out models.DescribeTableOutput - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out, jsonx.V1())) assert.Equal( t, diff --git a/services/dynamodb/handler_test.go b/services/dynamodb/handler_test.go index 250801fae4..e294e3976f 100644 --- a/services/dynamodb/handler_test.go +++ b/services/dynamodb/handler_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "hash/crc32" "log/slog" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" @@ -386,7 +387,7 @@ func TestHandler_CRC32Header(t *testing.T) { func mustMarshal(t *testing.T, v any) string { t.Helper() - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(data) @@ -423,7 +424,7 @@ func TestHandler_TransactOps_AllActions(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, _ := json.Marshal(tt.body) + bodyBytes, _ := json.Marshal(tt.body, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) req.Header.Set("X-Amz-Target", "DynamoDB_20120810."+tt.action) w := httptest.NewRecorder() diff --git a/services/dynamodb/import_export_s3.go b/services/dynamodb/import_export_s3.go index 29da95e40b..6ec7cfd837 100644 --- a/services/dynamodb/import_export_s3.go +++ b/services/dynamodb/import_export_s3.go @@ -6,7 +6,8 @@ import ( "compress/gzip" "context" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -22,6 +23,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -342,7 +344,7 @@ func parseDynamoDBJSONLines(data []byte) ([]map[string]any, error) { var rec struct { Item map[string]any `json:"Item"` } - if err := json.Unmarshal(line, &rec); err != nil { + if err := json.Unmarshal(line, &rec, jsonx.V1()); err != nil { return nil, fmt.Errorf("parse DynamoDB JSON line: %w", err) } @@ -422,11 +424,11 @@ func (db *InMemoryDB) exportTableToS3( var buf bytes.Buffer gz := gzip.NewWriter(&buf) - enc := json.NewEncoder(gz) + enc := jsontext.NewEncoder(gz, jsonx.V1()) var count int64 for i := range items { - if err := enc.Encode(struct { + if err := json.MarshalEncode(enc, struct { Item map[string]any `json:"Item"` }{Item: items[i]}); err != nil { _ = gz.Close() @@ -454,7 +456,7 @@ func (db *InMemoryDB) exportTableToS3( "tableArn": tableARN, "itemCount": count, "dataFileS3Key": dataKey, - }) + }, jsonx.V1()) if _, err := s3.PutObject(ctx, &s3sdk.PutObjectInput{ Bucket: &bucket, Key: &manifestKey, diff --git a/services/dynamodb/import_export_s3_test.go b/services/dynamodb/import_export_s3_test.go index f58f10f9e6..354b07e1c2 100644 --- a/services/dynamodb/import_export_s3_test.go +++ b/services/dynamodb/import_export_s3_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "sort" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -408,7 +409,7 @@ func TestDescribeImport(t *testing.T) { assert.Equal(t, tt.wantStatus, code) if tt.wantBodyContains != "" { - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), tt.wantBodyContains) } }) diff --git a/services/dynamodb/item_collection_metrics_test.go b/services/dynamodb/item_collection_metrics_test.go index e20699911e..f3eb2dca36 100644 --- a/services/dynamodb/item_collection_metrics_test.go +++ b/services/dynamodb/item_collection_metrics_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -67,7 +68,7 @@ func TestQuery_ConsistentRead_GSI_Rejected(t *testing.T) { }, }, "BillingMode": "PAY_PER_REQUEST", - }) + }, jsonx.V1()) require.NoError(t, err) putItemBody, err := json.Marshal(map[string]any{ @@ -76,7 +77,7 @@ func TestQuery_ConsistentRead_GSI_Rejected(t *testing.T) { "pk": map[string]any{"S": "user1"}, "email": map[string]any{"S": "test@example.com"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) tests := []struct { @@ -144,7 +145,7 @@ func TestQuery_ConsistentRead_GSI_Rejected(t *testing.T) { require.Equal(t, http.StatusOK, w.Code, "PutItem failed: %s", w.Body.String()) // Execute query. - queryRaw, marshalErr := json.Marshal(tc.query) + queryRaw, marshalErr := json.Marshal(tc.query, jsonx.V1()) require.NoError(t, marshalErr) w = makeHandlerJSONRequest(t, h, "DynamoDB_20120810.Query", queryRaw) @@ -159,7 +160,7 @@ func TestQuery_ConsistentRead_GSI_Rejected(t *testing.T) { // marshalJSONBody marshals v to JSON bytes for use with makeHandlerJSONRequest. func marshalJSONBody(t *testing.T, v any) []byte { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return b @@ -223,7 +224,7 @@ func TestPutItem_ItemCollectionMetrics_PKOnly(t *testing.T) { SizeEstimateRangeGB []float64 `json:"SizeEstimateRangeGB"` } `json:"ItemCollectionMetrics"` } - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.ItemCollectionMetrics) // ItemCollectionKey must contain only the partition key, not sk or non-key attrs. @@ -309,7 +310,7 @@ func TestDeleteUpdate_ItemCollectionMetrics(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var upd icmResult - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &upd)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &upd, jsonx.V1())) require.NotNil(t, upd.ItemCollectionMetrics) assert.Contains(t, upd.ItemCollectionMetrics.ItemCollectionKey, "pk") assert.NotContains(t, upd.ItemCollectionMetrics.ItemCollectionKey, "sk") @@ -325,7 +326,7 @@ func TestDeleteUpdate_ItemCollectionMetrics(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var del icmResult - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &del)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &del, jsonx.V1())) require.NotNil(t, del.ItemCollectionMetrics) assert.Contains(t, del.ItemCollectionMetrics.ItemCollectionKey, "pk") assert.NotContains(t, del.ItemCollectionMetrics.ItemCollectionKey, "sk") @@ -374,7 +375,7 @@ func TestBatchWriteItem_ItemCollectionMetrics(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var withMetrics batchWriteICMResult - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &withMetrics)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &withMetrics, jsonx.V1())) require.Contains(t, withMetrics.ItemCollectionMetrics, "bw-icm-tbl") metrics := withMetrics.ItemCollectionMetrics["bw-icm-tbl"] require.Len(t, metrics, 2, "one metric per PutRequest") @@ -430,7 +431,7 @@ func TestTransactWriteItems_ItemCollectionMetrics(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var withMetrics batchWriteICMResult - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &withMetrics)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &withMetrics, jsonx.V1())) require.Contains(t, withMetrics.ItemCollectionMetrics, "tw-icm-tbl") metrics := withMetrics.ItemCollectionMetrics["tw-icm-tbl"] require.Len(t, metrics, 2, "one metric per Put transact item") diff --git a/services/dynamodb/json_check_test.go b/services/dynamodb/json_check_test.go index 3530cac46e..85f9a17266 100644 --- a/services/dynamodb/json_check_test.go +++ b/services/dynamodb/json_check_test.go @@ -1,9 +1,10 @@ package dynamodb_test import ( - "encoding/json" + "encoding/json/v2" "testing" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" "github.com/aws/aws-sdk-go-v2/aws" @@ -49,7 +50,7 @@ func TestSDKJSONMarshaling(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - b, err := json.Marshal(tt.input) + b, err := json.Marshal(tt.input, jsonx.V1()) require.NoError(t, err) require.NotEmpty(t, b) t.Logf("%s JSON: %s", tt.name, string(b)) diff --git a/services/dynamodb/kinesis_streaming_test.go b/services/dynamodb/kinesis_streaming_test.go index 73c9a27fa2..dddf67c95c 100644 --- a/services/dynamodb/kinesis_streaming_test.go +++ b/services/dynamodb/kinesis_streaming_test.go @@ -1,7 +1,7 @@ package dynamodb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -153,7 +154,7 @@ func TestKinesisDestinations(t *testing.T) { assert.Equal(t, tt.wantStatus, code) if tt.wantBodyContains != "" { - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), tt.wantBodyContains) } }) @@ -262,7 +263,7 @@ func TestEnableKinesisStreamingDestination(t *testing.T) { assert.Equal(t, tt.wantStatus, code) if tt.wantBodyContains != "" { - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), tt.wantBodyContains) } }) @@ -492,7 +493,7 @@ func TestUpdateKinesisDestination_NotFound(t *testing.T) { "StreamArn": "arn:aws:kinesis:us-east-1:123:stream/absent", }) require.Equal(t, http.StatusBadRequest, code) - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), "ResourceNotFoundException") } diff --git a/services/dynamodb/partiql.go b/services/dynamodb/partiql.go index 14461e8cc7..7aa3483949 100644 --- a/services/dynamodb/partiql.go +++ b/services/dynamodb/partiql.go @@ -3,7 +3,7 @@ package dynamodb import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "log/slog" @@ -16,6 +16,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -304,7 +305,7 @@ func (r *partiQLRunner) executeStatement( // handleExecuteStatement routes to specific DML/DQL handlers based on the statement type. func (h *DynamoDBHandler) handleExecuteStatement(ctx context.Context, body []byte) (any, error) { var req executeStatementRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -336,7 +337,7 @@ func (h *DynamoDBHandler) handleBatchExecuteStatement( body []byte, ) (any, error) { var req batchExecuteStatementRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -882,7 +883,7 @@ func encodePartiQLNextToken(lastKey map[string]types.AttributeValue) string { wire := models.FromSDKItem(lastKey) - b, err := json.Marshal(wire) + b, err := json.Marshal(wire, jsonx.V1()) if err != nil { return "" } @@ -903,7 +904,7 @@ func decodePartiQLNextToken(token string) map[string]types.AttributeValue { } var wire map[string]any - if unmarshalErr := json.Unmarshal(b, &wire); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(b, &wire, jsonx.V1()); unmarshalErr != nil { return nil } diff --git a/services/dynamodb/partiql_test.go b/services/dynamodb/partiql_test.go index 7776ce05ab..9addcc9c45 100644 --- a/services/dynamodb/partiql_test.go +++ b/services/dynamodb/partiql_test.go @@ -3,7 +3,7 @@ package dynamodb_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "log/slog" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -92,7 +93,7 @@ func partiqlItemsFrom(t *testing.T, rec *httptest.ResponseRecorder) []any { require.Equal(t, http.StatusOK, rec.Code, "response body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Items"].([]any) require.True(t, ok, "Items field missing or wrong type") @@ -335,7 +336,7 @@ func TestPartiQL_Insert(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) item, ok := getResp["Item"].(map[string]any) require.True(t, ok, "item not found for pk=%q", tc.lookupPK) assert.Equal(t, tc.wantVal, item[tc.wantAttr], "attribute %q mismatch", tc.wantAttr) @@ -415,7 +416,7 @@ func TestPartiQL_Update(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) item := getResp["Item"].(map[string]any) assert.Equal(t, tc.wantVal, item[tc.wantAttr]) }) @@ -490,7 +491,7 @@ func TestPartiQL_Delete(t *testing.T) { getRec := doRequest(t, handler, "DynamoDB_20120810.GetItem", getBody) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Nil(t, getResp["Item"], "deleted item should not be present") // Surviving item must still be there. @@ -501,7 +502,7 @@ func TestPartiQL_Delete(t *testing.T) { getRec2 := doRequest(t, handler, "DynamoDB_20120810.GetItem", getBody2) var getResp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2, jsonx.V1())) assert.NotNil(t, getResp2["Item"], "surviving item should still be present") }) } @@ -582,7 +583,7 @@ func TestPartiQL_CompositeKey_CaseInsensitiveAND(t *testing.T) { getRec := doRequest(t, handler, "DynamoDB_20120810.GetItem", getBody) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) if tc.wantGone { assert.Nil(t, getResp["Item"]) @@ -670,7 +671,7 @@ func TestPartiQL_Batch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) responses, ok := resp["Responses"].([]any) require.True(t, ok) require.Len(t, responses, tc.wantLen) @@ -1071,7 +1072,7 @@ func TestBatchExecuteStatement_ParameterConversionFailure_ErrorCode(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) responses, ok := resp["Responses"].([]any) require.True(t, ok) require.Len(t, responses, 1) diff --git a/services/dynamodb/perf_sweep_bench_test.go b/services/dynamodb/perf_sweep_bench_test.go index cf3580f611..9019cc0516 100644 --- a/services/dynamodb/perf_sweep_bench_test.go +++ b/services/dynamodb/perf_sweep_bench_test.go @@ -6,7 +6,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -22,7 +23,7 @@ import ( func invokeOpB(tb testing.TB, handler *dynamodb.DynamoDBHandler, action string, body any) (int, map[string]any) { tb.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(tb, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -32,7 +33,7 @@ func invokeOpB(tb testing.TB, handler *dynamodb.DynamoDBHandler, action string, var resp map[string]any if w.Body.Len() > 0 { - require.NoError(tb, json.Unmarshal(w.Body.Bytes(), &resp)) + require.NoError(tb, json.Unmarshal(w.Body.Bytes(), &resp, jsonx.V1())) } return w.Code, resp diff --git a/services/dynamodb/persistence.go b/services/dynamodb/persistence.go index 6d7f7f1bee..aa0416bba0 100644 --- a/services/dynamodb/persistence.go +++ b/services/dynamodb/persistence.go @@ -2,10 +2,12 @@ package dynamodb import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "log/slog" "strconv" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" @@ -35,7 +37,7 @@ type dbSnapshot struct { type dbSnapshotWire struct { DefaultRegion string `json:"defaultRegion"` AccountID string `json:"accountID"` - Tables json.RawMessage `json:"tables"` + Tables jsontext.Value `json:"tables"` Backups []*Backup `json:"backups,omitempty"` GlobalTables []*StoredGlobalTable `json:"globalTables,omitempty"` Version int `json:"version"` @@ -67,7 +69,7 @@ func (db *InMemoryDB) Snapshot(ctx context.Context) []byte { AccountID: db.accountID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "DynamoDB: failed to serialise snapshot; state will not be persisted", @@ -82,16 +84,16 @@ func (db *InMemoryDB) Snapshot(ctx context.Context) []byte { // marshalTablesRLocked marshals each table under its own table.mu.RLock, then reassembles the JSON array. // Reassembling per-table bytes, rather than marshaling the slice directly, keeps the wire format byte-identical. -func marshalTablesRLocked(tables []*Table) (json.RawMessage, error) { +func marshalTablesRLocked(tables []*Table) (jsontext.Value, error) { if len(tables) == 0 { - return json.RawMessage("null"), nil + return jsontext.Value("null"), nil } - parts := make([]json.RawMessage, len(tables)) + parts := make([]jsontext.Value, len(tables)) for i, t := range tables { t.mu.RLock("Snapshot") - data, err := json.Marshal(t) + data, err := json.Marshal(t, jsonx.V1()) t.mu.RUnlock() if err != nil { @@ -101,7 +103,7 @@ func marshalTablesRLocked(tables []*Table) (json.RawMessage, error) { parts[i] = data } - return json.Marshal(parts) + return json.Marshal(parts, jsonx.V1()) } // Restore loads backend state from a JSON snapshot. diff --git a/services/dynamodb/realism_test.go b/services/dynamodb/realism_test.go index 4393067ce6..96e85df1e9 100644 --- a/services/dynamodb/realism_test.go +++ b/services/dynamodb/realism_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -57,7 +58,7 @@ func TestHandler_Realism(t *testing.T) { Items []map[string]any `json:"Items"` ScannedCount int `json:"ScannedCount"` } - err := json.Unmarshal(w.Body.Bytes(), &output) + err := json.Unmarshal(w.Body.Bytes(), &output, jsonx.V1()) require.NoError(t, err) assert.Less(t, len(output.Items), 20, "Scan should have truncated results") @@ -117,7 +118,7 @@ func TestHandler_Realism(t *testing.T) { LastEvaluatedKey map[string]any `json:"LastEvaluatedKey"` Items []map[string]any `json:"Items"` } - err := json.Unmarshal(w.Body.Bytes(), &output) + err := json.Unmarshal(w.Body.Bytes(), &output, jsonx.V1()) require.NoError(t, err) assert.Less(t, len(output.Items), 20, "Query should have truncated results") @@ -170,7 +171,7 @@ func TestHandler_Realism(t *testing.T) { }, }, } - body, _ := json.Marshal(batchInput) + body, _ := json.Marshal(batchInput, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", "DynamoDB_20120810.BatchGetItem") w := httptest.NewRecorder() @@ -185,7 +186,7 @@ func TestHandler_Realism(t *testing.T) { Responses map[string][]map[string]any `json:"Responses"` UnprocessedKeys map[string]any `json:"UnprocessedKeys"` } - err := json.Unmarshal(w.Body.Bytes(), &output) + err := json.Unmarshal(w.Body.Bytes(), &output, jsonx.V1()) require.NoError(t, err) totalReturned := len(output.Responses[tableName]) diff --git a/services/dynamodb/resource_policy_test.go b/services/dynamodb/resource_policy_test.go index b6edf0914d..413c65588c 100644 --- a/services/dynamodb/resource_policy_test.go +++ b/services/dynamodb/resource_policy_test.go @@ -1,7 +1,7 @@ package dynamodb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" ) @@ -77,7 +78,7 @@ func TestResourcePolicy(t *testing.T) { handler := dynamodb.NewHandler(backend) code, resp := invokeOp(t, handler, "GetResourcePolicy", map[string]any{"ResourceArn": ""}) assert.Equal(t, http.StatusBadRequest, code) - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), "ValidationException") }) @@ -100,7 +101,7 @@ func TestResourcePolicy(t *testing.T) { map[string]any{"ResourceArn": tableARN}, ) assert.Equal(t, http.StatusOK, code2) - bodyBytes, _ := json.Marshal(resp2) + bodyBytes, _ := json.Marshal(resp2, jsonx.V1()) assert.Contains(t, string(bodyBytes), "2012-10-17") }) @@ -116,7 +117,7 @@ func TestResourcePolicy(t *testing.T) { map[string]any{"ResourceArn": tableARN}, ) assert.Equal(t, http.StatusBadRequest, code) - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), "ValidationException") }) @@ -145,7 +146,7 @@ func TestResourcePolicy(t *testing.T) { map[string]any{"ResourceArn": ""}, ) assert.Equal(t, http.StatusBadRequest, code) - bodyBytes, _ := json.Marshal(resp) + bodyBytes, _ := json.Marshal(resp, jsonx.V1()) assert.Contains(t, string(bodyBytes), "ValidationException") }) } diff --git a/services/dynamodb/search_vectors_test.go b/services/dynamodb/search_vectors_test.go index 708ceb3bf3..1ca8e7e6e6 100644 --- a/services/dynamodb/search_vectors_test.go +++ b/services/dynamodb/search_vectors_test.go @@ -2,7 +2,7 @@ package dynamodb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -63,7 +64,7 @@ func TestSearchVectors(t *testing.T) { require.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], "ResourceNotFoundException") assert.Contains(t, errBody["message"], "table not found") }) @@ -82,7 +83,7 @@ func TestSearchVectors(t *testing.T) { require.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], "ResourceNotFoundException") assert.Contains(t, errBody["message"], "Index: vec-index not found") }) diff --git a/services/dynamodb/test_utils_test.go b/services/dynamodb/test_utils_test.go index 762f85ea1e..54f53bc8d0 100644 --- a/services/dynamodb/test_utils_test.go +++ b/services/dynamodb/test_utils_test.go @@ -3,7 +3,7 @@ package dynamodb_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( sdkddb "github.com/aws/aws-sdk-go-v2/service/dynamodb" sdktypes "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" "github.com/blackbirdworks/gopherstack/services/dynamodb" @@ -23,7 +24,7 @@ import ( func mustUnmarshal[T any](t *testing.T, jsonStr string) T { t.Helper() var val T - err := json.Unmarshal([]byte(jsonStr), &val) + err := json.Unmarshal([]byte(jsonStr), &val, jsonx.V1()) require.NoError(t, err) return val @@ -190,7 +191,7 @@ func invokeOp( ) (int, map[string]any) { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -201,7 +202,7 @@ func invokeOp( var resp map[string]any if w.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp, jsonx.V1())) } return w.Code, resp diff --git a/services/dynamodb/transact_ops.go b/services/dynamodb/transact_ops.go index cc2b4512e6..cfcfed186a 100644 --- a/services/dynamodb/transact_ops.go +++ b/services/dynamodb/transact_ops.go @@ -4,12 +4,13 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "sort" "time" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" @@ -210,7 +211,7 @@ func commitTransactTokenLocked(db *InMemoryDB, token, hash string) { // preserves TransactItems' slice order and each Go struct's fixed field // order, so the same request always hashes the same way. func hashTransactWriteItems(items []types.TransactWriteItem) string { - b, err := json.Marshal(items) + b, err := json.Marshal(items, jsonx.V1()) if err != nil { return "" } diff --git a/services/dynamodb/transact_validation.go b/services/dynamodb/transact_validation.go index 5a5c39ac1c..56732069f7 100644 --- a/services/dynamodb/transact_validation.go +++ b/services/dynamodb/transact_validation.go @@ -5,12 +5,13 @@ package dynamodb import ( - "encoding/json" + "encoding/json/v2" "fmt" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -118,7 +119,7 @@ func checkTransactWriteItemSizeAndDupe( // validation error), so it's not surfaced — the item is simply not // tracked in seen and duplicate detection silently skips it, matching // the pre-refactor loop's "continue on marshal error" behavior. - keyBytes, marshalErr := json.Marshal(wireKey) + keyBytes, marshalErr := json.Marshal(wireKey, jsonx.V1()) if marshalErr == nil { twk := transactWriteKey{TableName: tableName, KeyJSON: string(keyBytes)} if seen[twk] { diff --git a/services/dynamodb/wire_codec_internal_test.go b/services/dynamodb/wire_codec_internal_test.go index 8c406032b1..e9b211e97f 100644 --- a/services/dynamodb/wire_codec_internal_test.go +++ b/services/dynamodb/wire_codec_internal_test.go @@ -2,7 +2,8 @@ package dynamodb import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math/rand/v2" "strconv" "strings" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -117,7 +119,7 @@ func TestAppendJSONString_MatchesEncodingJSON(t *testing.T) { } for _, s := range corpus { - want, err := json.Marshal(s) + want, err := json.Marshal(s, jsonx.V1()) require.NoError(t, err) assert.Equal(t, string(want), string(appendJSONString(nil, s)), "input %q", s) } @@ -243,7 +245,7 @@ func TestEncoders_MatchLegacyMarshal(t *testing.T) { items[i] = randItem(rng, 0) } - want, err := json.Marshal(tt.legacy(it, items)) + want, err := json.Marshal(tt.legacy(it, items), jsonx.V1()) require.NoError(t, err) got, release, err := marshalResponse(tt.fast(it, items)) @@ -294,7 +296,7 @@ func TestEncoders_EmptyAndNilOutputs(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - want, err := json.Marshal(tt.legacy()) + want, err := json.Marshal(tt.legacy(), jsonx.V1()) require.NoError(t, err) got, release, err := marshalResponse(tt.fast()) @@ -307,7 +309,7 @@ func TestEncoders_EmptyAndNilOutputs(t *testing.T) { func legacyDecode[In, SDK any](body string, toSDK func(*In) (*SDK, error)) (*SDK, error) { var in In - if err := json.Unmarshal([]byte(body), &in); err != nil { + if err := json.Unmarshal([]byte(body), &in, jsonx.V1()); err != nil { return nil, err } @@ -499,10 +501,15 @@ func TestDecoders_RandomItemsMatchLegacy(t *testing.T) { item := randItem(rng, 0) wireItem := models.FromSDKItem(item) - raw, err := json.Marshal(map[string]any{"TableName": "t", "Item": wireItem}) + raw, err := json.Marshal(map[string]any{"TableName": "t", "Item": wireItem}, jsonx.V1()) require.NoError(t, err) - indented, err := json.MarshalIndent(map[string]any{"TableName": "t", "Item": wireItem}, "", " ") + indented, err := json.Marshal( + map[string]any{"TableName": "t", "Item": wireItem}, + jsonx.V1(), + jsontext.Multiline(true), + jsontext.WithIndent(" "), + ) require.NoError(t, err) for _, body := range [][]byte{raw, indented, pythonEscape(raw)} { @@ -562,7 +569,7 @@ func TestTopLevelStrings_MatchesStructDecode(t *testing.T) { BackupArn string `json:"BackupArn"` } - legacyErr := json.Unmarshal([]byte(body), &data) + legacyErr := json.Unmarshal([]byte(body), &data, jsonx.V1()) table, backup, ok := topLevelStrings([]byte(body)) if !ok { @@ -580,7 +587,7 @@ func legacyWireBytes(t *testing.T, item map[string]any) []byte { t.Helper() sdk, _ := models.ToSDKItem(item) - out, err := json.Marshal(models.FromSDKItem(sdk)) + out, err := json.Marshal(models.FromSDKItem(sdk), jsonx.V1()) require.NoError(t, err) return out @@ -590,11 +597,11 @@ func TestAppendWireItem_MatchesLegacyPipeline(t *testing.T) { t.Parallel() jsonRoundTrip := func(item map[string]any) map[string]any { - raw, err := json.Marshal(item) + raw, err := json.Marshal(item, jsonx.V1()) require.NoError(t, err) var out map[string]any - require.NoError(t, json.Unmarshal(raw, &out)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1())) return out } diff --git a/services/dynamodb/wire_encode.go b/services/dynamodb/wire_encode.go index 886cdf1cda..1fd2c53802 100644 --- a/services/dynamodb/wire_encode.go +++ b/services/dynamodb/wire_encode.go @@ -2,7 +2,7 @@ package dynamodb import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "slices" "strconv" "sync" @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/dynamodb" "github.com/aws/aws-sdk-go-v2/service/dynamodb/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/dynamodb/models" ) @@ -63,7 +64,7 @@ func marshalResponse(v any) ([]byte, func(), error) { return e.bytes(), e.release, nil } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) return b, noopRelease, err } @@ -322,7 +323,7 @@ func appendSDKItems(dst []byte, items []map[string]types.AttributeValue) []byte // appendMarshaled splices json.Marshal(v) for rarely-populated sub-documents. func appendMarshaled(dst []byte, v any) []byte { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return append(dst, "null"...) } diff --git a/services/dynamodbstreams/handler.go b/services/dynamodbstreams/handler.go index 55546fec68..c6284293af 100644 --- a/services/dynamodbstreams/handler.go +++ b/services/dynamodbstreams/handler.go @@ -2,7 +2,7 @@ package dynamodbstreams import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "hash/crc32" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" @@ -99,7 +100,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -154,7 +155,7 @@ func (h *Handler) Handler() echo.HandlerFunc { return h.handleError(ctx, c, operation, reqErr) } - payload, err := json.Marshal(response) + payload, err := json.Marshal(response, jsonx.V1()) if err != nil { log.ErrorContext(ctx, "failed to marshal JSON response", "error", err) @@ -203,7 +204,7 @@ func dispatchGetShardIterator( ) (any, error) { var input dynamodbstreams.GetShardIteratorInput if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errSerialization, err) } } @@ -230,7 +231,7 @@ func dispatchListStreams( ) (any, error) { var input dynamodbstreams.ListStreamsInput if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errSerialization, err) } } @@ -262,7 +263,7 @@ func dispatchGetRecords( ) (any, error) { var input dynamodbstreams.GetRecordsInput if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errSerialization, err) } } @@ -286,7 +287,7 @@ func writeDynamoDBStreamsDispatchError(c *echo.Context, message string) error { body, _ := json.Marshal(map[string]string{ keyErrType: "com.amazonaws.dynamodbstreams.v20120810#InternalServerError", keyMessage: message, - }) + }, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.0") return c.JSONBlob(http.StatusInternalServerError, body) @@ -339,7 +340,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, operation stri body, _ := json.Marshal(map[string]string{ keyErrType: "com.amazonaws.dynamodbstreams.v20120810#" + operation + "Exception", keyMessage: msg, - }) + }, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.0") return c.JSONBlob(http.StatusBadRequest, body) @@ -352,7 +353,7 @@ func dispatchDescribeStream( ) (any, error) { var input dynamodbstreams.DescribeStreamInput if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errSerialization, err) } } @@ -370,7 +371,7 @@ func dispatchDescribeStream( } func writeJSONError(c *echo.Context, status int, errType, message string) error { - body, _ := json.Marshal(map[string]string{keyErrType: errType, keyMessage: message}) + body, _ := json.Marshal(map[string]string{keyErrType: errType, keyMessage: message}, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.0") return c.JSONBlob(status, body) diff --git a/services/dynamodbstreams/handler_errors_test.go b/services/dynamodbstreams/handler_errors_test.go index b8c9416e91..52a433b81e 100644 --- a/services/dynamodbstreams/handler_errors_test.go +++ b/services/dynamodbstreams/handler_errors_test.go @@ -1,13 +1,14 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -49,7 +50,7 @@ func TestHandler_ErrorPropagation_ResourceNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) // Must use a structured error type (not just the operation name). assert.Contains(t, errBody["__type"], "ResourceNotFoundException", @@ -95,7 +96,7 @@ func TestHandler_ErrorPropagation_ValidationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], tt.wantErrType, "error __type must contain %s", tt.wantErrType) }) @@ -140,7 +141,7 @@ func TestHandler_ErrorNamespace_DynamoDBStreams(t *testing.T) { assert.Equal(t, 400, resp.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &errBody, jsonx.V1())) errType := errBody["__type"] assert.Contains(t, errType, tt.wantErr) diff --git a/services/dynamodbstreams/handler_lifecycle_test.go b/services/dynamodbstreams/handler_lifecycle_test.go index 338dc26093..79cde0583c 100644 --- a/services/dynamodbstreams/handler_lifecycle_test.go +++ b/services/dynamodbstreams/handler_lifecycle_test.go @@ -1,7 +1,7 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -77,7 +78,7 @@ func TestHandler_FullLifecycle_StreamsFlow(t *testing.T) { fmt.Sprintf(`{"TableName":"%s"}`, tableName)) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) streams, ok := listOut["Streams"].([]any) require.True(t, ok) require.Len(t, streams, 1) @@ -87,7 +88,7 @@ func TestHandler_FullLifecycle_StreamsFlow(t *testing.T) { fmt.Sprintf(`{"StreamArn":"%s"}`, table.StreamARN)) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) streamDesc := descOut["StreamDescription"].(map[string]any) shards := streamDesc["Shards"].([]any) require.NotEmpty(t, shards) @@ -99,7 +100,7 @@ func TestHandler_FullLifecycle_StreamsFlow(t *testing.T) { table.StreamARN, shardID)) require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter, ok := iterOut["ShardIterator"].(string) require.True(t, ok) @@ -108,7 +109,7 @@ func TestHandler_FullLifecycle_StreamsFlow(t *testing.T) { fmt.Sprintf(`{"ShardIterator":"%s"}`, shardIter)) require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records, ok := recOut["Records"].([]any) require.True(t, ok) require.Len(t, records, 3, "must return all 3 stream events") @@ -124,7 +125,7 @@ func TestHandler_FullLifecycle_StreamsFlow(t *testing.T) { fmt.Sprintf(`{"ShardIterator":"%s"}`, nextIter)) require.Equal(t, http.StatusOK, emptyResp.Code) var emptyOut map[string]any - require.NoError(t, json.Unmarshal(emptyResp.Body.Bytes(), &emptyOut)) + require.NoError(t, json.Unmarshal(emptyResp.Body.Bytes(), &emptyOut, jsonx.V1())) emptyRecords, ok := emptyOut["Records"].([]any) if ok { assert.Empty(t, emptyRecords, "NextShardIterator must return no new records") diff --git a/services/dynamodbstreams/handler_records_test.go b/services/dynamodbstreams/handler_records_test.go index 1885edf9bb..e28b7f66a8 100644 --- a/services/dynamodbstreams/handler_records_test.go +++ b/services/dynamodbstreams/handler_records_test.go @@ -1,7 +1,7 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -30,7 +31,7 @@ func TestHandler_ErrorPropagation_InvalidShardIterator(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.NotEmpty(t, errBody["__type"], "error response must include __type") } @@ -49,7 +50,7 @@ func TestHandler_WireFormat_ApproximateCreationDateTimeIsFloat(t *testing.T) { require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter, ok := iterOut["ShardIterator"].(string) require.True(t, ok) @@ -61,7 +62,7 @@ func TestHandler_WireFormat_ApproximateCreationDateTimeIsFloat(t *testing.T) { // Parse raw JSON to verify ApproximateCreationDateTime is a number (float64), // not a string. The DynamoDB Streams JSON 1.0 protocol encodes it as epoch seconds. var rawOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &rawOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &rawOut, jsonx.V1())) records, ok := rawOut["Records"].([]any) require.True(t, ok) @@ -139,7 +140,7 @@ func TestHandler_WireFormat_AttributeValueEncoding(t *testing.T) { require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter, ok := iterOut["ShardIterator"].(string) require.True(t, ok) @@ -148,7 +149,7 @@ func TestHandler_WireFormat_AttributeValueEncoding(t *testing.T) { require.Equal(t, http.StatusOK, recResp.Code) var rawOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &rawOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &rawOut, jsonx.V1())) records := rawOut["Records"].([]any) require.Len(t, records, 1) @@ -177,7 +178,7 @@ func TestHandler_OpaqueIterator_TokenNotDecodable(t *testing.T) { require.Equal(t, http.StatusOK, w.Code) var out map[string]any - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out, jsonx.V1())) token, ok := out["ShardIterator"].(string) require.True(t, ok) @@ -231,7 +232,7 @@ func TestHandler_GetShardIterator_UnknownShardId(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], "ResourceNotFoundException") } @@ -259,7 +260,7 @@ func TestHandler_GetRecords_EventFields(t *testing.T) { iterResp := doRequest(t, handler, "GetShardIterator", iterBody) require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter := iterOut["ShardIterator"].(string) recResp := doRequest(t, handler, "GetRecords", @@ -267,7 +268,7 @@ func TestHandler_GetRecords_EventFields(t *testing.T) { require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records := recOut["Records"].([]any) require.NotEmpty(t, records) @@ -339,13 +340,13 @@ func TestHandler_GetShardIterator_AtAfterSequenceNumber_ViaHTTP(t *testing.T) { trimIterResp := doRequest(t, handler, "GetShardIterator", trimIterBody) require.Equal(t, http.StatusOK, trimIterResp.Code) var trimIterOut map[string]any - require.NoError(t, json.Unmarshal(trimIterResp.Body.Bytes(), &trimIterOut)) + require.NoError(t, json.Unmarshal(trimIterResp.Body.Bytes(), &trimIterOut, jsonx.V1())) trimIter := trimIterOut["ShardIterator"].(string) allRecResp := doRequest(t, handler, "GetRecords", fmt.Sprintf(`{"ShardIterator":"%s"}`, trimIter)) require.Equal(t, http.StatusOK, allRecResp.Code) var allRecOut map[string]any - require.NoError(t, json.Unmarshal(allRecResp.Body.Bytes(), &allRecOut)) + require.NoError(t, json.Unmarshal(allRecResp.Body.Bytes(), &allRecOut, jsonx.V1())) allRecords := allRecOut["Records"].([]any) require.Len(t, allRecords, 3) midSeq := allRecords[1].(map[string]any)["dynamodb"].(map[string]any)["SequenceNumber"].(string) @@ -379,14 +380,14 @@ func TestHandler_GetShardIterator_AtAfterSequenceNumber_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter := iterOut["ShardIterator"].(string) recResp := doRequest(t, handler, "GetRecords", fmt.Sprintf(`{"ShardIterator":"%s"}`, shardIter)) require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records, _ := recOut["Records"].([]any) assert.Len(t, records, tt.wantCount) }) @@ -426,7 +427,7 @@ func TestHandler_GetShardIterator_AtAfterSequenceNumber_MissingSequenceNumber(t assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], "ValidationException") assert.Contains(t, errBody["__type"], "dynamodbstreams") }) @@ -490,7 +491,7 @@ func TestHandler_ErrorPropagation_TrimmedDataAccess(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], "TrimmedDataAccessException") assert.Contains(t, errBody["__type"], "dynamodbstreams", "error __type must use the dynamodbstreams namespace") @@ -606,13 +607,13 @@ func TestHandler_GetRecords_StreamViewType_RecordShapes(t *testing.T) { iterResp := doRequest(t, handler, "GetShardIterator", iterBody) require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter := iterOut["ShardIterator"].(string) recResp := doRequest(t, handler, "GetRecords", fmt.Sprintf(`{"ShardIterator":"%s"}`, shardIter)) require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records := recOut["Records"].([]any) require.Len(t, records, 2, "must have exactly INSERT + MODIFY records") @@ -693,14 +694,14 @@ func TestHandler_GetRecords_Limit(t *testing.T) { iterResp := doRequest(t, handler, "GetShardIterator", iterBody) require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter := iterOut["ShardIterator"].(string) // First page: Limit=2. recResp := doRequest(t, handler, "GetRecords", fmt.Sprintf(`{"ShardIterator":"%s","Limit":2}`, shardIter)) require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records := recOut["Records"].([]any) require.Len(t, records, 2, "Limit must cap the number of records returned") @@ -711,7 +712,7 @@ func TestHandler_GetRecords_Limit(t *testing.T) { recResp2 := doRequest(t, handler, "GetRecords", fmt.Sprintf(`{"ShardIterator":"%s"}`, nextIter)) require.Equal(t, http.StatusOK, recResp2.Code) var recOut2 map[string]any - require.NoError(t, json.Unmarshal(recResp2.Body.Bytes(), &recOut2)) + require.NoError(t, json.Unmarshal(recResp2.Body.Bytes(), &recOut2, jsonx.V1())) records2 := recOut2["Records"].([]any) assert.Len(t, records2, 3, "remaining 3 records must be returned on the next page") } @@ -792,7 +793,7 @@ func TestHandler_GetShardIterator_AllIteratorTypes_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIter := iterOut["ShardIterator"].(string) recResp := doRequest(t, handler, "GetRecords", @@ -800,7 +801,7 @@ func TestHandler_GetShardIterator_AllIteratorTypes_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, recResp.Code) var recOut map[string]any - require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut)) + require.NoError(t, json.Unmarshal(recResp.Body.Bytes(), &recOut, jsonx.V1())) records, _ := recOut["Records"].([]any) assert.Len(t, records, tt.wantCount) }) diff --git a/services/dynamodbstreams/handler_streams_test.go b/services/dynamodbstreams/handler_streams_test.go index c39602d073..8875d52a2b 100644 --- a/services/dynamodbstreams/handler_streams_test.go +++ b/services/dynamodbstreams/handler_streams_test.go @@ -1,7 +1,7 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -92,7 +93,7 @@ func TestHandler_DescribeStream_ShardGenealogy(t *testing.T) { require.Equal(t, 200, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) streamDesc := descOut["StreamDescription"].(map[string]any) shards := streamDesc["Shards"].([]any) @@ -160,7 +161,7 @@ func TestHandler_DescribeStream_Pagination_ExclusiveStartShardId(t *testing.T) { fmt.Sprintf(`{"StreamArn":"%s","Limit":1}`, table.StreamARN)) require.Equal(t, 200, page1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(page1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(page1.Body.Bytes(), &out1, jsonx.V1())) desc1 := out1["StreamDescription"].(map[string]any) shards1 := desc1["Shards"].([]any) require.Len(t, shards1, 1, "Limit=1 must cap the shard list to 1") @@ -174,7 +175,7 @@ func TestHandler_DescribeStream_Pagination_ExclusiveStartShardId(t *testing.T) { fmt.Sprintf(`{"StreamArn":"%s","ExclusiveStartShardId":"%s"}`, table.StreamARN, lastShardID)) require.Equal(t, 200, page2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(page2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(page2.Body.Bytes(), &out2, jsonx.V1())) desc2 := out2["StreamDescription"].(map[string]any) shards2 := desc2["Shards"].([]any) require.NotEmpty(t, shards2, "second page must return the remaining shards") @@ -217,7 +218,7 @@ func TestHandler_ListStreams_PaginationViaHTTP(t *testing.T) { w1 := doRequest(t, handler, "ListStreams", `{"Limit":1}`) require.Equal(t, 200, w1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(w1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(w1.Body.Bytes(), &out1, jsonx.V1())) streams1 := out1["Streams"].([]any) require.Len(t, streams1, 1) lastArn1, ok := out1["LastEvaluatedStreamArn"].(string) @@ -228,7 +229,7 @@ func TestHandler_ListStreams_PaginationViaHTTP(t *testing.T) { fmt.Sprintf(`{"Limit":1,"ExclusiveStartStreamArn":"%s"}`, lastArn1)) require.Equal(t, 200, w2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(w2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(w2.Body.Bytes(), &out2, jsonx.V1())) streams2 := out2["Streams"].([]any) require.Len(t, streams2, 1) @@ -270,7 +271,7 @@ func TestHandler_DescribeStream_StreamLabel(t *testing.T) { require.Equal(t, 200, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) desc, ok := out["StreamDescription"].(map[string]any) require.True(t, ok) @@ -301,7 +302,7 @@ func TestHandler_DescribeStream_CreationRequestDateTime(t *testing.T) { require.Equal(t, 200, resp.Code) var rawOut map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &rawOut)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &rawOut, jsonx.V1())) desc, ok := rawOut["StreamDescription"].(map[string]any) require.True(t, ok) @@ -326,7 +327,7 @@ func TestHandler_ListStreams_StreamLabel(t *testing.T) { require.Equal(t, 200, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) streams, ok := out["Streams"].([]any) require.True(t, ok) @@ -402,7 +403,7 @@ func TestHandler_DescribeStream_StreamARNConsistency(t *testing.T) { require.Equal(t, 200, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) desc, ok := out["StreamDescription"].(map[string]any) require.True(t, ok) diff --git a/services/dynamodbstreams/handler_test.go b/services/dynamodbstreams/handler_test.go index 54e21a7318..df56fa9cc4 100644 --- a/services/dynamodbstreams/handler_test.go +++ b/services/dynamodbstreams/handler_test.go @@ -2,7 +2,7 @@ package dynamodbstreams_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -260,7 +261,7 @@ func TestHandler_GetRecords(t *testing.T) { require.Equal(t, http.StatusOK, iterResp.Code) var iterOut map[string]any - require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut)) + require.NoError(t, json.Unmarshal(iterResp.Body.Bytes(), &iterOut, jsonx.V1())) shardIterRaw, ok := iterOut["ShardIterator"] require.True(t, ok, "ShardIterator key expected in response") diff --git a/services/dynamodbstreams/handler_wire_test.go b/services/dynamodbstreams/handler_wire_test.go index 769c5b9e53..9ab510ca51 100644 --- a/services/dynamodbstreams/handler_wire_test.go +++ b/services/dynamodbstreams/handler_wire_test.go @@ -1,7 +1,7 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" @@ -127,7 +128,7 @@ func TestHandler_WireFormat_NoResultMetadataLeak(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(descW.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descW.Body.Bytes(), &desc, jsonx.V1())) require.NotEmpty(t, desc.StreamDescription.Shards) body := `{"StreamArn":"` + streamARN + `","ShardId":"` + diff --git a/services/dynamodbstreams/isolation_test.go b/services/dynamodbstreams/isolation_test.go index 3165fc35f0..01a03171e3 100644 --- a/services/dynamodbstreams/isolation_test.go +++ b/services/dynamodbstreams/isolation_test.go @@ -2,7 +2,7 @@ package dynamodbstreams_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -101,7 +102,7 @@ func TestDynamoDBStreamsRegionIsolation(t *testing.T) { StreamArn string `json:"StreamArn"` } `json:"Streams"` } - require.NoError(t, json.Unmarshal(eastResp.Body.Bytes(), &eastOut)) + require.NoError(t, json.Unmarshal(eastResp.Body.Bytes(), &eastOut, jsonx.V1())) require.Len(t, eastOut.Streams, 1) assert.Contains(t, eastOut.Streams[0].StreamArn, "us-east-1") @@ -114,7 +115,7 @@ func TestDynamoDBStreamsRegionIsolation(t *testing.T) { StreamArn string `json:"StreamArn"` } `json:"Streams"` } - require.NoError(t, json.Unmarshal(westResp.Body.Bytes(), &westOut)) + require.NoError(t, json.Unmarshal(westResp.Body.Bytes(), &westOut, jsonx.V1())) require.Len(t, westOut.Streams, 1) assert.Contains(t, westOut.Streams[0].StreamArn, "us-west-2") @@ -158,7 +159,7 @@ func TestDynamoDBStreamsDefaultRegionFallback(t *testing.T) { StreamArn string `json:"StreamArn"` } `json:"Streams"` } - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Streams, 1) assert.Contains(t, out.Streams[0].StreamArn, "eu-central-1") } diff --git a/services/dynamodbstreams/request_errors_test.go b/services/dynamodbstreams/request_errors_test.go index 62d763f652..1f81750052 100644 --- a/services/dynamodbstreams/request_errors_test.go +++ b/services/dynamodbstreams/request_errors_test.go @@ -1,13 +1,14 @@ package dynamodbstreams_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ddbbackend "github.com/blackbirdworks/gopherstack/services/dynamodb" "github.com/blackbirdworks/gopherstack/services/dynamodbstreams" ) @@ -60,7 +61,7 @@ func TestHandler_RequestErrorShapes(t *testing.T) { assert.Equal(t, http.StatusBadRequest, w.Code) var body map[string]string - require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(w.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantType, body["__type"]) assert.NotEmpty(t, body["message"]) diff --git a/services/ec2/cleanup_test.go b/services/ec2/cleanup_test.go index 22d43bf30c..2749e02970 100644 --- a/services/ec2/cleanup_test.go +++ b/services/ec2/cleanup_test.go @@ -1,7 +1,8 @@ package ec2_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "testing" "time" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ec2" ) @@ -1208,8 +1210,8 @@ func TestSnapshot_NoRedundantInstanceIMDSOptions(t *testing.T) { data := b.Snapshot(t.Context()) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(data, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(data, &raw, jsonx.V1())) _, ok := raw["instanceIMDSOptions"] assert.False(t, ok, "instanceIMDSOptions must not be persisted; it is a dead shadow of Instance fields") diff --git a/services/ec2/client_vpn_auth_policy.go b/services/ec2/client_vpn_auth_policy.go index 65e6a9c45f..9ab34853ee 100644 --- a/services/ec2/client_vpn_auth_policy.go +++ b/services/ec2/client_vpn_auth_policy.go @@ -1,8 +1,10 @@ package ec2 import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -49,7 +51,7 @@ func (b *InMemoryBackend) ModifyClientVpnEndpointAuthorizationPolicy( if policyDocument != nil { var doc map[string]any - if err := json.Unmarshal([]byte(*policyDocument), &doc); err != nil || doc == nil { + if err := json.Unmarshal([]byte(*policyDocument), &doc, jsonx.V1()); err != nil || doc == nil { return false, fmt.Errorf("%w: PolicyDocument must be a JSON object", ErrInvalidParameter) } } diff --git a/services/ec2/docker_ports_internal_test.go b/services/ec2/docker_ports_internal_test.go index 77626e61f0..cece872646 100644 --- a/services/ec2/docker_ports_internal_test.go +++ b/services/ec2/docker_ports_internal_test.go @@ -1,7 +1,7 @@ package ec2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,8 @@ import ( mobynetwork "github.com/moby/moby/api/types/network" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestWorldOpenPorts(t *testing.T) { @@ -255,7 +257,7 @@ func TestServePublishedPorts(t *testing.T) { } var body publishedPortsResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.instance, body.InstanceID) require.Len(t, body.Ports, tt.wantPorts) assert.Equal(t, 8080, body.Ports[0].ContainerPort) diff --git a/services/ec2/images_public_catalog_test.go b/services/ec2/images_public_catalog_test.go index ec191ce956..db122f7d4b 100644 --- a/services/ec2/images_public_catalog_test.go +++ b/services/ec2/images_public_catalog_test.go @@ -1,7 +1,7 @@ package ec2_test import ( - "encoding/json" + "encoding/json/v2" "os" "strings" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ec2" ) @@ -28,7 +29,7 @@ func TestSSMPublicParameterAMIsResolve(t *testing.T) { } `json:"parameters"` } - require.NoError(t, json.Unmarshal(raw, &catalog)) + require.NoError(t, json.Unmarshal(raw, &catalog, jsonx.V1())) b := ec2.NewInMemoryBackend("000000000000", "us-east-1") client := newTestEC2Client(t, ec2.NewHandler(b)) diff --git a/services/ec2/imds_test.go b/services/ec2/imds_test.go index 56e755837c..c930de96a4 100644 --- a/services/ec2/imds_test.go +++ b/services/ec2/imds_test.go @@ -3,7 +3,7 @@ package ec2_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ec2" ) @@ -381,7 +382,7 @@ func TestIMDSIdentityDocument(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var doc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1())) assert.Equal(t, f.instanceID, doc["instanceId"]) assert.Equal(t, "us-east-1", doc["region"]) assert.Equal(t, "000000000000", doc["accountId"]) @@ -403,7 +404,7 @@ func TestIMDSIAMCredentials(t *testing.T) { require.Equal(t, http.StatusOK, info.Code) var infoDoc map[string]string - require.NoError(t, json.Unmarshal(info.Body.Bytes(), &infoDoc)) + require.NoError(t, json.Unmarshal(info.Body.Bytes(), &infoDoc, jsonx.V1())) assert.Equal(t, "Success", infoDoc["Code"]) assert.Equal(t, imdsProfile, infoDoc["InstanceProfileArn"]) assert.Equal(t, "AIPAEXAMPLE", infoDoc["InstanceProfileId"]) @@ -415,7 +416,7 @@ func TestIMDSIAMCredentials(t *testing.T) { require.Equal(t, http.StatusOK, cred.Code) var credDoc map[string]string - require.NoError(t, json.Unmarshal(cred.Body.Bytes(), &credDoc)) + require.NoError(t, json.Unmarshal(cred.Body.Bytes(), &credDoc, jsonx.V1())) assert.Equal(t, "Success", credDoc["Code"]) assert.Equal(t, "AWS-HMAC", credDoc["Type"]) assert.Equal(t, "ASIA1", credDoc["AccessKeyId"]) diff --git a/services/ec2/imds_tree.go b/services/ec2/imds_tree.go index 2e76d5aca1..857391dc43 100644 --- a/services/ec2/imds_tree.go +++ b/services/ec2/imds_tree.go @@ -4,11 +4,14 @@ import ( "context" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -295,7 +298,7 @@ func (t *imdsTree) addIdentityDocument(v *imdsView) { } t.leaves["dynamic/instance-identity/document"] = func() (string, error) { - out, err := json.MarshalIndent(doc, "", imdsDocumentIndex) + out, err := json.Marshal(doc, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(imdsDocumentIndex)) return string(out), err } @@ -353,9 +356,9 @@ func (h *Handler) addIAMLeaves(t *imdsTree, v *imdsView) { updated := v.Instance.LaunchTime.UTC().Format(imdsTimeLayout) t.leaves["meta-data/iam/info"] = func() (string, error) { - out, mErr := json.MarshalIndent(imdsInfoDocument{ + out, mErr := json.Marshal(imdsInfoDocument{ Code: imdsCodeSuccess, LastUpdated: updated, InstanceProfileArn: prof.ARN, InstanceProfileID: prof.ID, - }, "", imdsDocumentIndex) + }, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(imdsDocumentIndex)) return string(out), mErr } @@ -366,11 +369,11 @@ func (h *Handler) addIAMLeaves(t *imdsTree, v *imdsView) { return "", cErr } - out, mErr := json.MarshalIndent(imdsCredentialDocument{ + out, mErr := json.Marshal(imdsCredentialDocument{ Code: imdsCodeSuccess, LastUpdated: updated, Type: imdsCredType, AccessKeyID: creds.AccessKeyID, SecretAccessKey: creds.SecretAccessKey, Token: creds.SessionToken, Expiration: creds.Expires.UTC().Format(imdsTimeLayout), - }, "", imdsDocumentIndex) + }, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(imdsDocumentIndex)) return string(out), mErr } diff --git a/services/ec2/ipam_routing_policy.go b/services/ec2/ipam_routing_policy.go index e6f2226666..a2ab92ffdd 100644 --- a/services/ec2/ipam_routing_policy.go +++ b/services/ec2/ipam_routing_policy.go @@ -1,12 +1,13 @@ package ec2 import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "time" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- IPAM Routing Policy Registrations ---- @@ -40,7 +41,7 @@ func (b *InMemoryBackend) newRoutingPolicyDeltaLocked( assocID string, doc routingPolicyDeltaDoc, ) *IpamRoutingPolicyRegistrationDelta { - body, _ := json.Marshal(doc) + body, _ := json.Marshal(doc, jsonx.V1()) delta := &IpamRoutingPolicyRegistrationDelta{ DeltaID: awsid.New("ipam-rpr-delta-"), @@ -294,7 +295,7 @@ func (b *InMemoryBackend) BatchModifyIpamRoutingPolicyRegistrations( } var entries []routingPolicyBatchEntry - if err := json.Unmarshal([]byte(deltaJSON), &entries); err != nil { + if err := json.Unmarshal([]byte(deltaJSON), &entries, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: DeltaJson is not a valid batch document: %w", ErrInvalidParameter, err) } diff --git a/services/ec2/mac_hosts.go b/services/ec2/mac_hosts.go index 2873ad48d6..32aa91d175 100644 --- a/services/ec2/mac_hosts.go +++ b/services/ec2/mac_hosts.go @@ -1,12 +1,14 @@ package ec2 import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // mac_hosts.go: a Mac Dedicated Host has no separate creation API -- it's a @@ -167,7 +169,7 @@ func validateMacCredentials(raw string) error { } var creds macCredentials - if err := json.Unmarshal([]byte(raw), &creds); err != nil { + if err := json.Unmarshal([]byte(raw), &creds, jsonx.V1()); err != nil { return fmt.Errorf("%w: MacCredentials must be a JSON object: %w", ErrInvalidParameter, err) } diff --git a/services/ec2/persistence.go b/services/ec2/persistence.go index e8ecdf3b3b..b8ea0ba82c 100644 --- a/services/ec2/persistence.go +++ b/services/ec2/persistence.go @@ -2,10 +2,12 @@ package ec2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -23,7 +25,7 @@ const ec2SnapshotVersion = 2 type snapTGWRTProp = TransitGatewayRouteTablePropagation type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` SnapshotAttributes map[string]map[string]string `json:"snapshotAttributes"` ImageDeprecated map[string]string `json:"imageDeprecated"` Tags map[string]map[string]string `json:"tags,omitempty"` @@ -167,7 +169,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { ManagedResourceVisibility: b.managedResourceDefaultVisibility, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ec2: Snapshot marshal failure", "error", err) diff --git a/services/ec2/usage_metrics.go b/services/ec2/usage_metrics.go index 42405efaae..cea32f8efd 100644 --- a/services/ec2/usage_metrics.go +++ b/services/ec2/usage_metrics.go @@ -2,7 +2,8 @@ package ec2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" @@ -10,6 +11,7 @@ import ( mobyclient "github.com/moby/moby/client" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -120,7 +122,7 @@ func (d *DockerCompute) Usage(ctx context.Context, providerID string) (InstanceU defer func() { _ = res.Body.Close() }() var stats mobycontainer.StatsResponse - if decodeErr := json.NewDecoder(res.Body).Decode(&stats); decodeErr != nil { + if decodeErr := json.UnmarshalDecode(jsontext.NewDecoder(res.Body), &stats, jsonx.V1()); decodeErr != nil { return InstanceUsage{}, fmt.Errorf("decode container stats: %w", decodeErr) } diff --git a/services/ecr/auth_token_test.go b/services/ecr/auth_token_test.go index a47ec0c9f0..c69e8a913b 100644 --- a/services/ecr/auth_token_test.go +++ b/services/ecr/auth_token_test.go @@ -6,7 +6,7 @@ package ecr_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -261,7 +262,7 @@ func TestECR_GetAuthorizationToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) authData, ok := resp["authorizationData"].([]any) require.True(t, ok) diff --git a/services/ecr/handler.go b/services/ecr/handler.go index 0cad5d68e5..93ac699393 100644 --- a/services/ecr/handler.go +++ b/services/ecr/handler.go @@ -2,7 +2,7 @@ package ecr import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -345,7 +346,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { RepositoryNames []string `json:"repositoryNames"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.RepositoryName != "" { return req.RepositoryName @@ -543,7 +544,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // ecrErr builds the error body for an ECR error response. @@ -611,14 +612,11 @@ func (h *Handler) classifyError(err error) (int, string) { } } - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, errUnknownAction): return http.StatusBadRequest, "UnknownOperationException" case errors.Is(err, ErrInvalidRepositoryName), errors.Is(err, errInvalidRequest), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return http.StatusBadRequest, "InvalidParameterException" default: return http.StatusInternalServerError, "ServerException" diff --git a/services/ecr/handler_images.go b/services/ecr/handler_images.go index e2889d9f3b..c6f80a09af 100644 --- a/services/ecr/handler_images.go +++ b/services/ecr/handler_images.go @@ -5,11 +5,13 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // batchDeleteImageInput is the request body for BatchDeleteImage. @@ -195,7 +197,7 @@ type manifestArtifactFields struct { func parseManifestArtifactFields(manifest string) (string, string) { var parsed manifestArtifactFields - if err := json.Unmarshal([]byte(manifest), &parsed); err != nil { + if err := json.Unmarshal([]byte(manifest), &parsed, jsonx.V1()); err != nil { return "", "" } @@ -212,7 +214,7 @@ func parseManifestAnnotations(manifest string) map[string]string { Annotations map[string]string `json:"annotations"` } - if err := json.Unmarshal([]byte(manifest), &parsed); err != nil || len(parsed.Annotations) == 0 { + if err := json.Unmarshal([]byte(manifest), &parsed, jsonx.V1()); err != nil || len(parsed.Annotations) == 0 { return nil } diff --git a/services/ecr/handler_test.go b/services/ecr/handler_test.go index dcf8399394..28ec8a6f8f 100644 --- a/services/ecr/handler_test.go +++ b/services/ecr/handler_test.go @@ -12,7 +12,7 @@ package ecr_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -82,7 +83,7 @@ func doECRRequest( ) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -124,7 +125,7 @@ func newHandlerWithBackend() (*ecr.Handler, *ecr.InMemoryBackend) { func doAccuracy(t *testing.T, h *ecr.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -141,7 +142,7 @@ func parseAccuracy(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } @@ -469,7 +470,7 @@ func TestECR_LazyEndpointInit(t *testing.T) { h := ecr.NewHandler(backend, nil) // First request — Host header provides the server address. - bodyBytes, err := json.Marshal(map[string]any{"repositoryName": "lazy-repo"}) + bodyBytes, err := json.Marshal(map[string]any{"repositoryName": "lazy-repo"}, jsonx.V1()) require.NoError(t, err) e := echo.New() diff --git a/services/ecr/interfaces_test.go b/services/ecr/interfaces_test.go index 77285d2699..85a072a985 100644 --- a/services/ecr/interfaces_test.go +++ b/services/ecr/interfaces_test.go @@ -7,7 +7,7 @@ package ecr_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -412,7 +413,7 @@ func TestECR_Handler_AcceptsBackendInterface(t *testing.T) { h := ecr.NewHandler(newStubBackend(), nil) - bodyBytes, err := json.Marshal(map[string]any{"repositoryName": "my-repo"}) + bodyBytes, err := json.Marshal(map[string]any{"repositoryName": "my-repo"}, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -424,7 +425,7 @@ func TestECR_Handler_AcceptsBackendInterface(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, ok := resp["repository"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-repo", repo["repositoryName"]) @@ -455,7 +456,7 @@ func TestECR_GetAuthorizationToken_ProxyEndpointFromBackend(t *testing.T) { h := ecr.NewHandler(newStubBackend(), nil) - bodyBytes, err := json.Marshal(map[string]any{}) + bodyBytes, err := json.Marshal(map[string]any{}, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -467,7 +468,7 @@ func TestECR_GetAuthorizationToken_ProxyEndpointFromBackend(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) authData := resp["authorizationData"].([]any) entry := authData[0].(map[string]any) diff --git a/services/ecr/lifecycle.go b/services/ecr/lifecycle.go index d02411d0c9..9c0505fb77 100644 --- a/services/ecr/lifecycle.go +++ b/services/ecr/lifecycle.go @@ -2,10 +2,12 @@ package ecr import ( "context" - "encoding/json" + "encoding/json/v2" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const weeksPerDays = 7 @@ -72,7 +74,7 @@ func evaluateLifecyclePolicy( } var doc lifecyclePolicyDoc - if err := json.Unmarshal([]byte(policyText), &doc); err != nil { + if err := json.Unmarshal([]byte(policyText), &doc, jsonx.V1()); err != nil { return nil } diff --git a/services/ecr/lifecycle_policy_test.go b/services/ecr/lifecycle_policy_test.go index db9a39efa6..2f2e81badb 100644 --- a/services/ecr/lifecycle_policy_test.go +++ b/services/ecr/lifecycle_policy_test.go @@ -6,13 +6,14 @@ package ecr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -174,7 +175,7 @@ func TestECR_DeleteLifecyclePolicy(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.repositoryName, out["repositoryName"]) } }) diff --git a/services/ecr/manifest_meta.go b/services/ecr/manifest_meta.go index c986c754d3..6385a0c65d 100644 --- a/services/ecr/manifest_meta.go +++ b/services/ecr/manifest_meta.go @@ -1,9 +1,12 @@ package ecr import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -33,14 +36,14 @@ type manifestMeta struct { Layers []struct { Size int64 `json:"size"` } `json:"layers"` - Manifests []json.RawMessage `json:"manifests"` + Manifests []jsontext.Value `json:"manifests"` } // manifestMediaTypeAndSize reports the manifest's media type (declared, else // inferred from its shape) and its compressed size: config plus layer sizes. func manifestMediaTypeAndSize(manifest string) (string, int64) { var m manifestMeta - if err := json.Unmarshal([]byte(manifest), &m); err != nil { + if err := json.Unmarshal([]byte(manifest), &m, jsonx.V1()); err != nil { return "", 0 } diff --git a/services/ecr/multi_region_test.go b/services/ecr/multi_region_test.go index 7e427cb3b1..5e502562ba 100644 --- a/services/ecr/multi_region_test.go +++ b/services/ecr/multi_region_test.go @@ -1,7 +1,7 @@ package ecr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -39,7 +40,7 @@ func regionCall(t *testing.T, h *ecr.Handler, region, op, body string) map[strin require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/ecr/persistence.go b/services/ecr/persistence.go index 6f3e364a1a..e36470e2b9 100644 --- a/services/ecr/persistence.go +++ b/services/ecr/persistence.go @@ -2,7 +2,7 @@ package ecr import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -52,7 +52,7 @@ const ecrSnapshotVersion = 2 // lifecycleLastEvaluated were never persisted before this conversion and // still aren't. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` RepoTags map[string]map[string]string `json:"repoTags,omitempty"` UploadedLayers map[string]map[string]int64 `json:"uploadedLayers,omitempty"` RegistryScanningConfig *RegistryScanningSettings `json:"registryScanningConfig,omitempty"` diff --git a/services/ecr/realism_validation_test.go b/services/ecr/realism_validation_test.go index f68b202195..4c0b7e0c4e 100644 --- a/services/ecr/realism_validation_test.go +++ b/services/ecr/realism_validation_test.go @@ -1,7 +1,7 @@ package ecr_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -87,7 +89,7 @@ func TestECRWire_InputValidation(t *testing.T) { } var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) assert.False(t, strings.HasPrefix(out["message"], tt.wantType), out["message"]) }) diff --git a/services/ecr/repositories_test.go b/services/ecr/repositories_test.go index e1e716ba53..40e2adce69 100644 --- a/services/ecr/repositories_test.go +++ b/services/ecr/repositories_test.go @@ -8,13 +8,14 @@ package ecr_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -53,7 +54,7 @@ func TestECR_CreateRepository(t *testing.T) { if tt.wantARN || tt.wantURI { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, ok := resp["repository"].(map[string]any) require.True(t, ok) @@ -141,7 +142,7 @@ func TestECR_DescribeRepositories(t *testing.T) { if tt.wantLen > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repos, ok := resp["repositories"].([]any) require.True(t, ok) @@ -200,7 +201,7 @@ func TestECR_DeleteRepository(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) repo, ok := resp["repository"].(map[string]any) require.True(t, ok) diff --git a/services/ecr/tags_test.go b/services/ecr/tags_test.go index 97ff4939d3..ac9f33c1b8 100644 --- a/services/ecr/tags_test.go +++ b/services/ecr/tags_test.go @@ -6,13 +6,14 @@ package ecr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecr" ) @@ -26,7 +27,7 @@ func TestECR_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) repo := createResp["repository"].(map[string]any) arn := repo["repositoryArn"].(string) @@ -35,7 +36,7 @@ func TestECR_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags, ok := out["tags"] require.True(t, ok, "response should contain 'tags' field") assert.IsType(t, []any{}, tags, "tags should be an array") @@ -253,7 +254,7 @@ func TestListTagsForResource_HandlerSortsKeys(t *testing.T) { Value string `json:"Value"` } `json:"tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) gotKeys := make([]string, 0, len(resp.Tags)) for _, tag := range resp.Tags { @@ -299,7 +300,7 @@ func TestCreateRepository_TagsRoundTrip(t *testing.T) { RepositoryARN string `json:"repositoryArn"` } `json:"repository"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp.Repository.RepositoryARN listRec := doAccuracy(t, h, "ListTagsForResource", map[string]any{ @@ -310,7 +311,7 @@ func TestCreateRepository_TagsRoundTrip(t *testing.T) { var listResp struct { Tags []any `json:"tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Tags, tt.wantLen) }) } diff --git a/services/ecr/validation.go b/services/ecr/validation.go index 5ab3c4c29d..443c356b18 100644 --- a/services/ecr/validation.go +++ b/services/ecr/validation.go @@ -1,10 +1,12 @@ package ecr import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -33,7 +35,7 @@ func validateRepositoryName(name string) error { func validateJSONObject(field, text string) error { var doc map[string]any - if err := json.Unmarshal([]byte(text), &doc); err != nil || doc == nil { + if err := json.Unmarshal([]byte(text), &doc, jsonx.V1()); err != nil || doc == nil { return invalidParam("Invalid parameter at '%s' failed to satisfy constraint: 'Invalid JSON syntax'", field) } @@ -50,7 +52,7 @@ func validateRepositoryPolicyText(text string) error { func validateLifecyclePolicyText(text string) error { var doc lifecyclePolicyDoc - if err := json.Unmarshal([]byte(text), &doc); err != nil { + if err := json.Unmarshal([]byte(text), &doc, jsonx.V1()); err != nil { return invalidParam("Lifecycle policy validation failure: Invalid JSON") } diff --git a/services/ecrpublic/digest.go b/services/ecrpublic/digest.go index e2df656a20..5c337db6b9 100644 --- a/services/ecrpublic/digest.go +++ b/services/ecrpublic/digest.go @@ -3,7 +3,9 @@ package ecrpublic import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func sha256Digest(data []byte) string { @@ -52,7 +54,7 @@ type manifestDoc struct { func parseManifest(manifest string) (manifestDoc, bool) { var m manifestDoc - return m, json.Unmarshal([]byte(manifest), &m) == nil + return m, json.Unmarshal([]byte(manifest), &m, jsonx.V1()) == nil } // referencedDigests returns every layer/config digest an image manifest diff --git a/services/ecrpublic/handler.go b/services/ecrpublic/handler.go index 92a97f83c7..3d4ac88af6 100644 --- a/services/ecrpublic/handler.go +++ b/services/ecrpublic/handler.go @@ -2,7 +2,7 @@ package ecrpublic import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -95,7 +96,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { RepositoryName string `json:"repositoryName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.RepositoryName } @@ -149,7 +150,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -234,14 +235,10 @@ func classifyError(err error) (int, string) { } } - var syntaxErr *json.SyntaxError - - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, errUnknownAction): return http.StatusBadRequest, "UnknownOperationException" - case errors.As(err, &syntaxErr), errors.As(err, &typeErr): + case jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return http.StatusBadRequest, "InvalidParameterException" case errors.Is(err, awserr.ErrNotFound): return http.StatusBadRequest, "RepositoryNotFoundException" diff --git a/services/ecrpublic/images_and_layers_test.go b/services/ecrpublic/images_and_layers_test.go index 1d26dd0d67..36c590e24a 100644 --- a/services/ecrpublic/images_and_layers_test.go +++ b/services/ecrpublic/images_and_layers_test.go @@ -4,7 +4,7 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -13,6 +13,8 @@ import ( "github.com/aws/smithy-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func layerDigest(data []byte) string { @@ -78,7 +80,7 @@ func buildManifest(configDigest string, layerDigests ...string) string { m.Layers = append(m.Layers, layer{Digest: d}) } - b, _ := json.Marshal(m) + b, _ := json.Marshal(m, jsonx.V1()) return string(b) } diff --git a/services/ecrpublic/manifest_index_test.go b/services/ecrpublic/manifest_index_test.go index f2838b621c..324c649e66 100644 --- a/services/ecrpublic/manifest_index_test.go +++ b/services/ecrpublic/manifest_index_test.go @@ -1,7 +1,7 @@ package ecrpublic_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/smithy-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func buildIndex(t *testing.T, childDigests ...string) string { @@ -28,7 +30,7 @@ func buildIndex(t *testing.T, childDigests ...string) string { doc.Manifests = append(doc.Manifests, child{Digest: d}) } - b, err := json.Marshal(doc) + b, err := json.Marshal(doc, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/ecrpublic/persistence.go b/services/ecrpublic/persistence.go index 2d5b142862..022f3e2b1a 100644 --- a/services/ecrpublic/persistence.go +++ b/services/ecrpublic/persistence.go @@ -2,7 +2,7 @@ package ecrpublic import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "maps" @@ -34,7 +34,7 @@ const ecrPublicSnapshotVersion = 1 // LayerUploads (in-flight sessions) is deliberately NOT persisted, matching // AWS: an in-progress upload does not survive a restart. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TagIndex map[string]map[string]tagBinding `json:"tagIndex,omitempty"` UploadedLayers map[string]map[string]int64 `json:"uploadedLayers,omitempty"` RegistryCatalogData RegistryCatalogData `json:"registryCatalogData"` diff --git a/services/ecrpublic/policy.go b/services/ecrpublic/policy.go index 5eecd7f604..420db903df 100644 --- a/services/ecrpublic/policy.go +++ b/services/ecrpublic/policy.go @@ -1,9 +1,11 @@ package ecrpublic import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // GetRepositoryPolicy returns the repository's resource policy text. @@ -29,7 +31,8 @@ func (b *InMemoryBackend) GetRepositoryPolicy(registryID, name string) (string, // SetRepositoryPolicy sets or replaces the repository's resource policy text. func (b *InMemoryBackend) SetRepositoryPolicy(registryID, name, policyText string) (string, error) { - if !json.Valid([]byte(policyText)) || !strings.HasPrefix(strings.TrimSpace(policyText), "{") { + if !jsontext.Value([]byte(policyText)).IsValid(jsonx.V1()) || + !strings.HasPrefix(strings.TrimSpace(policyText), "{") { return "", fmt.Errorf( "%w: Invalid parameter at 'PolicyText' failed to satisfy constraint: 'Invalid repository policy provided'", ErrInvalidParameter) diff --git a/services/ecs/capacity_provider_strategy_validation_test.go b/services/ecs/capacity_provider_strategy_validation_test.go index 355f21b0db..3f19606e49 100644 --- a/services/ecs/capacity_provider_strategy_validation_test.go +++ b/services/ecs/capacity_provider_strategy_validation_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCapacityProviderStrategy_RejectsUnknownProvider proves that every @@ -169,7 +171,7 @@ func TestCapacityProviderStrategy_AcceptsCreatedProvider(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) strategy := cluster["defaultCapacityProviderStrategy"].([]any) require.Len(t, strategy, 1) @@ -202,7 +204,7 @@ func TestRunTask_CapacityProviderStrategy_SetsCapacityProviderName(t *testing.T) require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) require.Len(t, tasks, 1) task := tasks[0].(map[string]any) diff --git a/services/ecs/docker_inputs.go b/services/ecs/docker_inputs.go index de18c2b688..3178305555 100644 --- a/services/ecs/docker_inputs.go +++ b/services/ecs/docker_inputs.go @@ -2,11 +2,12 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/registryauth" ) @@ -85,7 +86,7 @@ func (b *InMemoryBackend) resolveRegistryAuth(ctx context.Context, cd ContainerD Password string `json:"password"` } - if json.Unmarshal([]byte(raw), &creds) != nil || creds.Username == "" || creds.Password == "" { + if json.Unmarshal([]byte(raw), &creds, jsonx.V1()) != nil || creds.Username == "" || creds.Password == "" { return "", secretLaunchError(sourceASM, param, errRegistryCredentials) } diff --git a/services/ecs/docker_inputs_internal_test.go b/services/ecs/docker_inputs_internal_test.go index 21d2726c35..daf68e93f0 100644 --- a/services/ecs/docker_inputs_internal_test.go +++ b/services/ecs/docker_inputs_internal_test.go @@ -3,11 +3,13 @@ package ecs import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type fakeEnvStore struct { @@ -122,7 +124,7 @@ func TestRepositoryCredentials(t *testing.T) { var ac map[string]string - require.NoError(t, json.Unmarshal(raw, &ac)) + require.NoError(t, json.Unmarshal(raw, &ac, jsonx.V1())) assert.Equal(t, tt.wantUser, ac["username"]) assert.Equal(t, "hunter2", ac["password"]) assert.Equal(t, "registry.example.com", ac["serveraddress"]) diff --git a/services/ecs/docker_linklocal_live_internal_test.go b/services/ecs/docker_linklocal_live_internal_test.go index 5c36c5694c..cb2618da67 100644 --- a/services/ecs/docker_linklocal_live_internal_test.go +++ b/services/ecs/docker_linklocal_live_internal_test.go @@ -2,7 +2,8 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net" "net/http" @@ -21,6 +22,7 @@ import ( dockernetwork "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/network" "github.com/blackbirdworks/gopherstack/internal/dockercompat/client" "github.com/blackbirdworks/gopherstack/internal/linklocal" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -85,7 +87,10 @@ func TestDockerRunnerLiveRelativeCredentialsURI(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/_gopherstack/ecs/credentials/"+taskID, func(w http.ResponseWriter, _ *http.Request) { - _ = json.NewEncoder(w).Encode(map[string]string{"AccessKeyId": "ASIALIVE", "Token": "tok"}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"AccessKeyId": "ASIALIVE", "Token": "tok"}, + ) }) srv := &http.Server{Handler: mux, ReadHeaderTimeout: time.Second} diff --git a/services/ecs/docker_secrets.go b/services/ecs/docker_secrets.go index 0adaa9bf32..2ba02d237b 100644 --- a/services/ecs/docker_secrets.go +++ b/services/ecs/docker_secrets.go @@ -2,10 +2,13 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -169,8 +172,8 @@ func resolveParameter(ctx context.Context, resolver SecretsResolver, ref secretR } func jsonSecretField(secret, key string) (string, error) { - var fields map[string]json.RawMessage - if err := json.Unmarshal([]byte(secret), &fields); err != nil { + var fields map[string]jsontext.Value + if err := json.Unmarshal([]byte(secret), &fields, jsonx.V1()); err != nil { return "", fmt.Errorf("secret value is not a JSON object: %w", err) } @@ -180,7 +183,7 @@ func jsonSecretField(secret, key string) (string, error) { } var s string - if json.Unmarshal(raw, &s) == nil { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil { return s, nil } diff --git a/services/ecs/docker_usage.go b/services/ecs/docker_usage.go index 05b4a3dc18..18ede3b67b 100644 --- a/services/ecs/docker_usage.go +++ b/services/ecs/docker_usage.go @@ -2,7 +2,11 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const cpuUnitsPerVCPU = 1024.0 @@ -66,7 +70,7 @@ func (r *realDockerRunner) TaskUsage(ctx context.Context, taskArn string) (float var sample dockerStatsSample - decodeErr := json.NewDecoder(body).Decode(&sample) + decodeErr := json.UnmarshalDecode(jsontext.NewDecoder(body), &sample, jsonx.V1()) _ = body.Close() if decodeErr != nil { @@ -83,7 +87,7 @@ func (r *realDockerRunner) TaskUsage(ctx context.Context, taskArn string) (float } // ContainerStatsJSON returns one raw Docker stats sample for containerID. -func (r *realDockerRunner) ContainerStatsJSON(ctx context.Context, containerID string) (json.RawMessage, error) { +func (r *realDockerRunner) ContainerStatsJSON(ctx context.Context, containerID string) (jsontext.Value, error) { body, err := r.cli.ContainerStats(ctx, containerID) if err != nil { return nil, err @@ -91,8 +95,8 @@ func (r *realDockerRunner) ContainerStatsJSON(ctx context.Context, containerID s defer body.Close() - var raw json.RawMessage - if decErr := json.NewDecoder(body).Decode(&raw); decErr != nil { + var raw jsontext.Value + if decErr := json.UnmarshalDecode(jsontext.NewDecoder(body), &raw, jsonx.V1()); decErr != nil { return nil, decErr } diff --git a/services/ecs/events.go b/services/ecs/events.go index fa8fb9cc12..3350db2612 100644 --- a/services/ecs/events.go +++ b/services/ecs/events.go @@ -2,10 +2,11 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -47,7 +48,7 @@ func (b *InMemoryBackend) emitLocked(detailType string, resources []string, deta return } - body, err := json.Marshal(detail) + body, err := json.Marshal(detail, jsonx.V1()) if err != nil { return } diff --git a/services/ecs/events_internal_test.go b/services/ecs/events_internal_test.go index d6a29817ca..1f63c20fa4 100644 --- a/services/ecs/events_internal_test.go +++ b/services/ecs/events_internal_test.go @@ -2,7 +2,7 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type publishedEvent struct { @@ -30,7 +31,7 @@ func (p *recordingPublisher) PublishEvent( ctx context.Context, source, detailType string, resources []string, detail string, ) { var d map[string]any - if err := json.Unmarshal([]byte(detail), &d); err != nil { + if err := json.Unmarshal([]byte(detail), &d, jsonx.V1()); err != nil { panic(err) } diff --git a/services/ecs/handler.go b/services/ecs/handler.go index b5392ba8e1..a761d2d3d4 100644 --- a/services/ecs/handler.go +++ b/services/ecs/handler.go @@ -2,7 +2,7 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -194,7 +195,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { TaskSet string `json:"taskSet"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ClusterName != "": @@ -355,7 +356,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // Reset clears the backend state. @@ -368,8 +369,6 @@ func (h *Handler) Reset() { } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError switch { case errors.Is(err, awserr.ErrNotFound): @@ -395,8 +394,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err }, ) case errors.Is(err, awserr.ErrInvalidParameter), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): code := errorCode(err) return c.JSON( diff --git a/services/ecs/handler_account_settings_test.go b/services/ecs/handler_account_settings_test.go index f76f2d5120..7e44d82754 100644 --- a/services/ecs/handler_account_settings_test.go +++ b/services/ecs/handler_account_settings_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -40,7 +41,7 @@ func TestAccountSettings_AllValidNames(t *testing.T) { require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) settings := listOut["settings"].([]any) assert.GreaterOrEqual(t, len(settings), len(validNames)) } @@ -71,7 +72,7 @@ func TestAccountSettings_PutDefault_vs_Put(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) settings := listOut["settings"].([]any) assert.GreaterOrEqual(t, len(settings), 1) } @@ -99,7 +100,7 @@ func TestAccountSettings_Delete(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) settings := listOut["settings"].([]any) assert.Empty(t, settings) } @@ -123,7 +124,7 @@ func TestAccountSettings_OverwriteExisting(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) settings := listOut["settings"].([]any) require.NotEmpty(t, settings) // Last write wins @@ -150,7 +151,7 @@ func TestAccountSettings_TaskLongArnFormat(t *testing.T) { require.Equal(t, http.StatusOK, putResp.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut, jsonx.V1())) setting := putOut["setting"].(map[string]any) assert.Equal(t, "taskLongArnFormat", setting["name"]) assert.Equal(t, "enabled", setting["value"]) @@ -168,7 +169,7 @@ func TestAccountSettings_ContainerInstanceLongArnFormat(t *testing.T) { require.Equal(t, http.StatusOK, putResp.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut, jsonx.V1())) setting := putOut["setting"].(map[string]any) assert.Equal(t, "containerInstanceLongArnFormat", setting["name"]) assert.Equal(t, "enabled", setting["value"]) @@ -192,7 +193,7 @@ func TestAccountSettings_FargateSettings(t *testing.T) { require.Equal(t, http.StatusOK, putResp.Code, "PutAccountSetting %s", name) var putOut map[string]any - require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putResp.Body.Bytes(), &putOut, jsonx.V1())) setting := putOut["setting"].(map[string]any) assert.Equal(t, name, setting["name"]) } @@ -215,7 +216,7 @@ func TestAccountSettings_ServiceLongArnFormat(t *testing.T) { require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) settings := listOut["settings"].([]any) require.NotEmpty(t, settings) assert.Equal(t, "enabled", settings[0].(map[string]any)["value"]) @@ -273,7 +274,7 @@ func TestECS_DeleteAccountSetting(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) setting, ok := resp["setting"].(map[string]any) require.True(t, ok) @@ -293,7 +294,7 @@ func TestECS_ListAccountSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) settings, ok := resp["settings"].([]any) require.True(t, ok) @@ -321,7 +322,7 @@ func TestECS_ListAccountSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) settings, ok := resp["settings"].([]any) require.True(t, ok) @@ -376,7 +377,7 @@ func TestECS_PutAccountSetting(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) setting, ok := resp["setting"].(map[string]any) require.True(t, ok) @@ -423,7 +424,7 @@ func TestECS_PutAccountSettingDefault(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) setting, ok := resp["setting"].(map[string]any) require.True(t, ok) diff --git a/services/ecs/handler_agent_ops_test.go b/services/ecs/handler_agent_ops_test.go index 99064f0c5b..be2fc4b57a 100644 --- a/services/ecs/handler_agent_ops_test.go +++ b/services/ecs/handler_agent_ops_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -34,7 +35,7 @@ func TestECS_DescribeServiceRevisions(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svc := svcResp["service"].(map[string]any) deployments := svc["deployments"].([]any) @@ -93,7 +94,7 @@ func TestECS_DescribeServiceRevisions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) revs, _ := resp["serviceRevisions"].([]any) failures, _ := resp["failures"].([]any) @@ -158,7 +159,7 @@ func TestECS_DescribeServiceRevisions_TracksUpdate(t *testing.T) { }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) revs, _ := resp["serviceRevisions"].([]any) assert.Len(t, revs, 2, "both the original and rotated revision remain describable") } @@ -177,7 +178,7 @@ func TestECS_DiscoverPollEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["endpoint"], testRegion) assert.Contains(t, resp["serviceConnectEndpoint"], testRegion) @@ -202,7 +203,7 @@ func TestECS_SubmitTaskStateChange(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp, jsonx.V1())) tasks := runResp["tasks"].([]any) require.Len(t, tasks, 1) task := tasks[0].(map[string]any) @@ -220,7 +221,7 @@ func TestECS_SubmitTaskStateChange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACK", resp["acknowledgment"]) descRec := doECSRequest(t, h, "DescribeTasks", map[string]any{ @@ -230,7 +231,7 @@ func TestECS_SubmitTaskStateChange(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) descTasks := descResp["tasks"].([]any) require.Len(t, descTasks, 1) @@ -259,7 +260,7 @@ func TestECS_SubmitTaskStateChange_UnknownTaskIsNoop(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACK", resp["acknowledgment"]) } @@ -278,7 +279,7 @@ func TestECS_SubmitContainerStateChange(t *testing.T) { }) var runResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp, jsonx.V1())) taskArn := runResp["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) rec := doECSRequest(t, h, "SubmitContainerStateChange", map[string]any{ @@ -299,7 +300,7 @@ func TestECS_SubmitContainerStateChange(t *testing.T) { }) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) updated := descResp["tasks"].([]any)[0].(map[string]any) container := updated["containers"].([]any)[0].(map[string]any) @@ -326,7 +327,7 @@ func TestECS_SubmitAttachmentStateChanges(t *testing.T) { }) var runResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp, jsonx.V1())) task := runResp["tasks"].([]any)[0].(map[string]any) taskArn := task["taskArn"].(string) attachments, _ := task["attachments"].([]any) @@ -347,7 +348,7 @@ func TestECS_SubmitAttachmentStateChanges(t *testing.T) { }) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) updated := descResp["tasks"].([]any)[0].(map[string]any) updatedAttachments := updated["attachments"].([]any) require.NotEmpty(t, updatedAttachments) @@ -392,7 +393,7 @@ func TestHandler_DiscoverPollEndpoint(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantEndpointPfx, out["endpoint"]) if tt.wantTelemetry { assert.NotEmpty(t, out["telemetryEndpoint"]) @@ -477,7 +478,7 @@ func TestHandler_SubmitTaskStateChange(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) tasks := runOut["tasks"].([]any) require.NotEmpty(t, tasks) taskArn = tasks[0].(map[string]any)["taskArn"].(string) @@ -488,7 +489,7 @@ func TestHandler_SubmitTaskStateChange(t *testing.T) { if tt.wantACK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ACK", out["acknowledgment"]) } }) @@ -574,7 +575,7 @@ func TestHandler_SubmitContainerStateChange(t *testing.T) { }) require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) taskArn = runOut["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) } @@ -588,7 +589,7 @@ func TestHandler_SubmitContainerStateChange(t *testing.T) { if tt.wantACK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ACK", out["acknowledgment"]) } }) @@ -664,7 +665,7 @@ func TestHandler_SubmitAttachmentStateChanges(t *testing.T) { if tt.wantACK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ACK", out["acknowledgment"]) } }) @@ -695,7 +696,7 @@ func TestHandler_DescribeServiceRevisions(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) return svc["serviceArn"].(string) @@ -749,7 +750,7 @@ func TestHandler_DescribeServiceRevisions(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) revs, _ := out["serviceRevisions"].([]any) assert.Len(t, revs, tt.wantRevCount) @@ -798,7 +799,7 @@ func TestHandler_DescribeServiceRevisions_CreateAndUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) revs := out2["serviceRevisions"].([]any) require.Len(t, revs, 1, "expected one revision after CreateService") rev := revs[0].(map[string]any) @@ -828,7 +829,7 @@ func TestHandler_DescribeServiceRevisions_CreateAndUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var out3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &out3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &out3, jsonx.V1())) revs3 := out3["serviceRevisions"].([]any) assert.Len(t, revs3, 1, "expected one revision after UpdateService") } diff --git a/services/ecs/handler_attributes_test.go b/services/ecs/handler_attributes_test.go index a54f867e9d..34e47b1c60 100644 --- a/services/ecs/handler_attributes_test.go +++ b/services/ecs/handler_attributes_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -72,7 +73,7 @@ func TestAttributes_PutListDelete_Roundtrip(t *testing.T) { }) require.Equal(t, http.StatusOK, ciResp.Code) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) // Put attributes @@ -102,7 +103,7 @@ func TestAttributes_PutListDelete_Roundtrip(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) attrs := listOut["attributes"].([]any) assert.Len(t, attrs, 2) @@ -126,7 +127,7 @@ func TestAttributes_PutListDelete_Roundtrip(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp2.Code) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(listResp2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(listResp2.Body.Bytes(), &listOut2, jsonx.V1())) attrs2 := listOut2["attributes"].([]any) assert.Len(t, attrs2, 1) assert.Equal(t, "com.example.zone", attrs2[0].(map[string]any)["name"]) @@ -144,7 +145,7 @@ func TestAttributes_FilterByName(t *testing.T) { }) require.Equal(t, http.StatusOK, ciResp.Code) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) doECSRequest(t, h, "PutAttributes", map[string]any{ @@ -173,7 +174,7 @@ func TestAttributes_FilterByName(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) attrs := listOut["attributes"].([]any) assert.Len(t, attrs, 1) assert.Equal(t, "ecs.gpu", attrs[0].(map[string]any)["name"]) @@ -192,7 +193,7 @@ func TestListAttributes_TargetID_Filter(t *testing.T) { }) require.Equal(t, http.StatusOK, ci1Resp.Code) var ci1Out map[string]any - require.NoError(t, json.Unmarshal(ci1Resp.Body.Bytes(), &ci1Out)) + require.NoError(t, json.Unmarshal(ci1Resp.Body.Bytes(), &ci1Out, jsonx.V1())) ci1Arn := ci1Out["containerInstance"].(map[string]any)["containerInstanceArn"].(string) ci2Resp := doECSRequest(t, h, "RegisterContainerInstance", map[string]any{ @@ -201,7 +202,7 @@ func TestListAttributes_TargetID_Filter(t *testing.T) { }) require.Equal(t, http.StatusOK, ci2Resp.Code) var ci2Out map[string]any - require.NoError(t, json.Unmarshal(ci2Resp.Body.Bytes(), &ci2Out)) + require.NoError(t, json.Unmarshal(ci2Resp.Body.Bytes(), &ci2Out, jsonx.V1())) ci2Arn := ci2Out["containerInstance"].(map[string]any)["containerInstanceArn"].(string) doECSRequest(t, h, "PutAttributes", map[string]any{ @@ -231,7 +232,7 @@ func TestListAttributes_TargetID_Filter(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) attrs := listOut["attributes"].([]any) require.Len(t, attrs, 1) assert.Equal(t, "us-east-1a", attrs[0].(map[string]any)["value"]) @@ -262,7 +263,7 @@ func TestListAttributes_TargetID_Filter_NotFound(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) attrs := listOut["attributes"].([]any) assert.Empty(t, attrs) } @@ -304,7 +305,7 @@ func TestListAttributes_TargetID_NoFilter_ReturnsAll(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) attrs := listOut["attributes"].([]any) assert.Len(t, attrs, 3) } @@ -372,7 +373,7 @@ func TestECS_DeleteAttributes(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) attrs, ok := resp["attributes"].([]any) require.True(t, ok) @@ -435,7 +436,7 @@ func TestECS_PutAndListAttributes(t *testing.T) { } var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) attrs, ok := putResp["attributes"].([]any) require.True(t, ok) @@ -446,7 +447,7 @@ func TestECS_PutAndListAttributes(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) listedAttrs, ok := listResp["attributes"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_capacity_providers_test.go b/services/ecs/handler_capacity_providers_test.go index 3603289464..3466750940 100644 --- a/services/ecs/handler_capacity_providers_test.go +++ b/services/ecs/handler_capacity_providers_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -34,7 +35,7 @@ func TestCapacityProvider_ASGBacked_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cp := out["capacityProvider"].(map[string]any) require.Equal(t, "asg-cp", cp["name"]) @@ -69,7 +70,7 @@ func TestCapacityProvider_ASGBacked_NoManagedScaling(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cp := out["capacityProvider"].(map[string]any) asg := cp["autoScalingGroupProvider"].(map[string]any) assert.Nil(t, asg["managedScaling"]) @@ -93,7 +94,7 @@ func TestCapacityProvider_FARGATE_Types(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) providers := out["capacityProviders"].([]any) require.Len(t, providers, 2) @@ -141,7 +142,7 @@ func TestCapacityProvider_Update_ManagedScaling(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cp := out["capacityProvider"].(map[string]any) asg := cp["autoScalingGroupProvider"].(map[string]any) ms := asg["managedScaling"].(map[string]any) @@ -160,7 +161,7 @@ func TestCapacityProvider_DeleteByARN(t *testing.T) { }) require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) cpArn := createOut["capacityProvider"].(map[string]any)["capacityProviderArn"].(string) require.NotEmpty(t, cpArn) @@ -192,7 +193,7 @@ func TestCapacityProvider_FARGATE_BuiltIn_DescribeWithoutCreate(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) providers := out["capacityProviders"].([]any) require.Len(t, providers, 1) cp := providers[0].(map[string]any) @@ -211,7 +212,7 @@ func TestCapacityProvider_FARGATE_SPOT_BuiltIn(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) providers := out["capacityProviders"].([]any) require.Len(t, providers, 2) @@ -242,7 +243,7 @@ func TestCapacityProvider_FARGATE_BuiltIn_WithCreated(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) providers := out["capacityProviders"].([]any) require.Len(t, providers, 2) @@ -267,7 +268,7 @@ func TestCapacityProvider_Unknown_ReturnsFailure(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["capacityProviders"]) failures := out["failures"].([]any) @@ -322,7 +323,7 @@ func TestECS_CreateCapacityProvider(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cp, ok := resp["capacityProvider"].(map[string]any) require.True(t, ok) @@ -395,7 +396,7 @@ func TestECS_DeleteCapacityProvider(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cp, ok := resp["capacityProvider"].(map[string]any) require.True(t, ok) @@ -514,7 +515,7 @@ func TestECS_DescribeCapacityProviders(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) providers, ok := resp["capacityProviders"].([]any) require.True(t, ok) @@ -540,7 +541,7 @@ func TestECS_DescribeCapacityProviders_SortedByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) providers, ok := resp["capacityProviders"].([]any) require.True(t, ok) @@ -559,7 +560,7 @@ func TestECS_DescribeCapacityProviders_ByARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["capacityProvider"].(map[string]any)["capacityProviderArn"].(string) @@ -572,7 +573,7 @@ func TestECS_DescribeCapacityProviders_ByARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) providers, ok := resp["capacityProviders"].([]any) require.True(t, ok) @@ -713,7 +714,7 @@ func TestDescribeCapacityProviders_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cps, ok := resp["capacityProviders"].([]any) require.True(t, ok) @@ -750,7 +751,7 @@ func TestDescribeCapacityProviders_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cp := resp["capacityProviders"].([]any)[0].(map[string]any) assert.Nil(t, cp["tags"]) }) @@ -765,7 +766,7 @@ func TestDescribeCapacityProviders_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cp := resp["capacityProviders"].([]any)[0].(map[string]any) tags := cp["tags"].([]any) require.Len(t, tags, 1) @@ -797,7 +798,7 @@ func TestDescribeCapacityProviders_ClusterFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cps := resp["capacityProviders"].([]any) require.Len(t, cps, 2) @@ -825,7 +826,7 @@ func TestDescribeCapacityProviders_ClusterFilter_UnknownCluster(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cps := resp["capacityProviders"].([]any) assert.Empty(t, cps) } diff --git a/services/ecs/handler_cluster_tags_test.go b/services/ecs/handler_cluster_tags_test.go index 5198069136..b058592a4c 100644 --- a/services/ecs/handler_cluster_tags_test.go +++ b/services/ecs/handler_cluster_tags_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestECS_CreateCluster_TagsAndCapacityProviders proves that CreateCluster @@ -49,7 +51,7 @@ func TestECS_CreateCluster_TagsAndCapacityProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) cluster := createResp["cluster"].(map[string]any) @@ -77,7 +79,7 @@ func TestECS_CreateCluster_TagsAndCapacityProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) described := describeResp["clusters"].([]any)[0].(map[string]any) assert.Nil(t, described["tags"], "tags must be omitted when include=TAGS is not requested") @@ -90,7 +92,7 @@ func TestECS_CreateCluster_TagsAndCapacityProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var describeTaggedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeTaggedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeTaggedResp, jsonx.V1())) describedTagged := describeTaggedResp["clusters"].([]any)[0].(map[string]any) taggedTags, ok := describedTagged["tags"].([]any) diff --git a/services/ecs/handler_clusters_test.go b/services/ecs/handler_clusters_test.go index 1eede85592..c47979e86e 100644 --- a/services/ecs/handler_clusters_test.go +++ b/services/ecs/handler_clusters_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -44,7 +45,7 @@ func TestECS_CreateCluster(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster, ok := resp["cluster"].(map[string]any) require.True(t, ok) @@ -133,7 +134,7 @@ func TestECS_DescribeClusters(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantCount > 0 { clusters, ok := resp["clusters"].([]any) @@ -402,7 +403,7 @@ func TestCluster_PutCapacityProviders_WithStrategy(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) providers := cluster["capacityProviders"].([]any) assert.Len(t, providers, 2) @@ -427,7 +428,7 @@ func TestClusterSetting_ContainerInsights_Enable(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) settings := cluster["settings"].([]any) require.Len(t, settings, 1) @@ -456,7 +457,7 @@ func TestClusterSetting_ContainerInsights_Disable(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) settings := cluster["settings"].([]any) assert.Equal(t, "disabled", settings[0].(map[string]any)["value"]) @@ -476,7 +477,7 @@ func TestCreateCluster_WithSettings(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) rawSettings := cluster["settings"] require.NotNil(t, rawSettings, "settings should be present in response") @@ -508,7 +509,7 @@ func TestUpdateCluster_DoesNotAcceptCapacityProviders(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) cluster := out["cluster"].(map[string]any) providers, ok := cluster["capacityProviders"].([]any) require.True(t, ok) @@ -533,7 +534,7 @@ func TestDescribeClusters_MultipleClusters(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out, jsonx.V1())) clusters := out["clusters"].([]any) assert.Len(t, clusters, 3) } @@ -554,7 +555,7 @@ func TestListClusters_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) arns := out["clusterArns"].([]any) assert.Len(t, arns, 3) assert.NotEmpty(t, out["nextToken"]) @@ -654,7 +655,7 @@ func TestECS_PutClusterCapacityProviders(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster, ok := resp["cluster"].(map[string]any) require.True(t, ok) @@ -707,7 +708,7 @@ func TestECS_UpdateClusterSettings(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) c, ok := resp["cluster"].(map[string]any) require.True(t, ok) @@ -729,7 +730,7 @@ func TestDescribeClusters_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["clusters"].([]any) assert.Empty(t, clusters) @@ -754,7 +755,7 @@ func TestDescribeClusters_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["clusters"].([]any) assert.Len(t, clusters, 1) @@ -776,7 +777,7 @@ func TestDescribeClusters_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["clusters"].([]any) assert.Empty(t, clusters) @@ -796,7 +797,7 @@ func TestDescribeClusters_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["clusters"].([]any) require.Len(t, clusters, 1) @@ -821,7 +822,7 @@ func TestCluster_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster, ok := resp["cluster"].(map[string]any) require.True(t, ok, "cluster key must be present") @@ -846,7 +847,7 @@ func TestCluster_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["cluster"].(map[string]any) @@ -872,7 +873,7 @@ func TestCluster_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["clusters"].([]any) require.Len(t, clusters, 1) @@ -935,7 +936,7 @@ func TestECS_UpdateCluster(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster, ok := resp["cluster"].(map[string]any) require.True(t, ok) @@ -989,7 +990,7 @@ func TestBackend_EnrichCluster_CachedCounters(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) for _, task := range runOut["tasks"].([]any) { taskArns = append(taskArns, task.(map[string]any)["taskArn"].(string)) } @@ -1009,7 +1010,7 @@ func TestBackend_EnrichCluster_CachedCounters(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) clusters := descOut["clusters"].([]any) require.Len(t, clusters, 1) c := clusters[0].(map[string]any) @@ -1035,7 +1036,7 @@ func TestBackend_EnrichCluster_RunAndStopUpdatesCounters(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) c := out["clusters"].([]any)[0].(map[string]any) return c["runningTasksCount"].(float64), c["pendingTasksCount"].(float64) @@ -1054,7 +1055,7 @@ func TestBackend_EnrichCluster_RunAndStopUpdatesCounters(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) tasks := runOut["tasks"].([]any) require.Len(t, tasks, 2) diff --git a/services/ecs/handler_container_instances.go b/services/ecs/handler_container_instances.go index d3ae7babe0..efa1bc1ac4 100644 --- a/services/ecs/handler_container_instances.go +++ b/services/ecs/handler_container_instances.go @@ -2,9 +2,10 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -54,7 +55,7 @@ func ec2InstanceIDFromIdentityDocument(doc string) string { InstanceID string `json:"instanceId"` } - if err := json.Unmarshal([]byte(doc), &parsed); err != nil { + if err := json.Unmarshal([]byte(doc), &parsed, jsonx.V1()); err != nil { return "" } diff --git a/services/ecs/handler_container_instances_test.go b/services/ecs/handler_container_instances_test.go index 4715230853..ce1d34aa4e 100644 --- a/services/ecs/handler_container_instances_test.go +++ b/services/ecs/handler_container_instances_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -23,7 +24,7 @@ func TestContainerInstance_DRAINING_State(t *testing.T) { }) require.Equal(t, http.StatusOK, ciResp.Code) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) assert.Equal(t, "ACTIVE", ciOut["containerInstance"].(map[string]any)["status"]) @@ -36,7 +37,7 @@ func TestContainerInstance_DRAINING_State(t *testing.T) { require.Equal(t, http.StatusOK, drainResp.Code) var drainOut map[string]any - require.NoError(t, json.Unmarshal(drainResp.Body.Bytes(), &drainOut)) + require.NoError(t, json.Unmarshal(drainResp.Body.Bytes(), &drainOut, jsonx.V1())) instances := drainOut["containerInstances"].([]any) require.Len(t, instances, 1) assert.Equal(t, "DRAINING", instances[0].(map[string]any)["status"]) @@ -48,7 +49,7 @@ func TestContainerInstance_DRAINING_State(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) described := descOut["containerInstances"].([]any) require.Len(t, described, 1) assert.Equal(t, "DRAINING", described[0].(map[string]any)["status"]) @@ -65,7 +66,7 @@ func TestContainerInstance_DRAINING_to_ACTIVE(t *testing.T) { "instanceIdentityDocument": fakeInstanceIdentityDocument("i-react-5678"), }) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) // Drain then re-activate @@ -82,7 +83,7 @@ func TestContainerInstance_DRAINING_to_ACTIVE(t *testing.T) { require.Equal(t, http.StatusOK, activeResp.Code) var activeOut map[string]any - require.NoError(t, json.Unmarshal(activeResp.Body.Bytes(), &activeOut)) + require.NoError(t, json.Unmarshal(activeResp.Body.Bytes(), &activeOut, jsonx.V1())) instances := activeOut["containerInstances"].([]any) assert.Equal(t, "ACTIVE", instances[0].(map[string]any)["status"]) } @@ -99,7 +100,7 @@ func TestContainerInstance_UpdateAgent(t *testing.T) { }) require.Equal(t, http.StatusOK, ciResp.Code) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) resp := doECSRequest(t, h, "UpdateContainerAgent", map[string]any{ @@ -109,7 +110,7 @@ func TestContainerInstance_UpdateAgent(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) ci := out["containerInstance"].(map[string]any) assert.NotEmpty(t, ci["containerInstanceArn"]) } @@ -129,7 +130,7 @@ func TestContainerInstance_Deregister_Force(t *testing.T) { "instanceIdentityDocument": fakeInstanceIdentityDocument("i-force-1234"), }) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) // Start a task on this container instance @@ -152,7 +153,7 @@ func TestContainerInstance_Deregister_Force(t *testing.T) { "cluster": "deregforce-cluster", }) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["containerInstanceArns"].([]any) assert.Empty(t, arns) } @@ -219,7 +220,7 @@ func TestECS_RegisterContainerInstance(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ci := resp["containerInstance"].(map[string]any) assert.Equal(t, tt.wantID, ci["ec2InstanceId"]) @@ -302,7 +303,7 @@ func TestECS_ListContainerInstances(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["containerInstanceArns"].([]any) assert.Len(t, arns, tt.wantLen) @@ -348,7 +349,7 @@ func TestECS_DescribeContainerInstances(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) ciArn := regResp["containerInstance"].(map[string]any)["containerInstanceArn"].(string) @@ -364,7 +365,7 @@ func TestECS_DescribeContainerInstances(t *testing.T) { require.Equal(t, tt.wantCode, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) cis := resp["containerInstances"].([]any) assert.Len(t, cis, tt.wantLen) @@ -391,7 +392,7 @@ func TestECS_DescribeContainerInstances_NotFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, _ := resp["containerInstances"].([]any) assert.Empty(t, instances) @@ -428,7 +429,7 @@ func TestECS_DeregisterContainerInstance(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) ciArn := regResp["containerInstance"].(map[string]any)["containerInstanceArn"].(string) @@ -442,7 +443,7 @@ func TestECS_DeregisterContainerInstance(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) ci := resp["containerInstance"].(map[string]any) assert.Equal(t, "INACTIVE", ci["status"]) @@ -545,7 +546,7 @@ func TestECS_UpdateContainerInstancesState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) ciArn := regResp["containerInstance"].(map[string]any)["containerInstanceArn"].(string) @@ -559,7 +560,7 @@ func TestECS_UpdateContainerInstancesState(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) cis := resp["containerInstances"].([]any) require.Len(t, cis, 1) @@ -585,7 +586,7 @@ func TestECS_UpdateContainerInstancesState_NotFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["containerInstances"]) @@ -633,7 +634,7 @@ func TestECS_UpdateContainerAgent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) ci := regResp["containerInstance"].(map[string]any) containerInstanceArn = ci["containerInstanceArn"].(string) } else { @@ -651,7 +652,7 @@ func TestECS_UpdateContainerAgent(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ci, ok := resp["containerInstance"].(map[string]any) require.True(t, ok) @@ -678,7 +679,7 @@ func TestDescribeContainerInstances_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, _ := resp["containerInstances"].([]any) assert.Empty(t, instances) @@ -702,7 +703,7 @@ func TestDescribeContainerInstances_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, regResp.Code) var regOut map[string]any - require.NoError(t, json.Unmarshal(regResp.Body.Bytes(), ®Out)) + require.NoError(t, json.Unmarshal(regResp.Body.Bytes(), ®Out, jsonx.V1())) ciArn := regOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) rec := doECSRequest(t, h, "DescribeContainerInstances", map[string]any{ @@ -715,7 +716,7 @@ func TestDescribeContainerInstances_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, _ := resp["containerInstances"].([]any) assert.Len(t, instances, 1) @@ -750,7 +751,7 @@ func TestDescribeContainerInstances_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) instances, _ := resp["containerInstances"].([]any) assert.Len(t, instances, 2) @@ -778,7 +779,7 @@ func TestDescribeContainerInstances_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, ciResp.Code) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArn := ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) tagResp := doECSRequest(t, h, "TagResource", map[string]any{ @@ -797,7 +798,7 @@ func TestDescribeContainerInstances_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ci := resp["containerInstances"].([]any)[0].(map[string]any) assert.Nil(t, ci["tags"]) }) @@ -813,7 +814,7 @@ func TestDescribeContainerInstances_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ci := resp["containerInstances"].([]any)[0].(map[string]any) tags := ci["tags"].([]any) require.Len(t, tags, 1) diff --git a/services/ecs/handler_daemon_test.go b/services/ecs/handler_daemon_test.go index bba2c08db8..7e023e3aee 100644 --- a/services/ecs/handler_daemon_test.go +++ b/services/ecs/handler_daemon_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -29,7 +30,7 @@ func registerDaemonTaskDef(t *testing.T, h *ecs.Handler, family string) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["daemonTaskDefinitionArn"].(string) require.NotEmpty(t, arn) @@ -45,7 +46,7 @@ func createCapacityProviderForDaemon(t *testing.T, h *ecs.Handler, name string) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cp, ok := resp["capacityProvider"].(map[string]any) require.True(t, ok) @@ -103,7 +104,7 @@ func TestECS_RegisterDaemonTaskDefinition(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["daemonTaskDefinitionArn"].(string) assert.Contains(t, arn, "daemon-task-definition/agent-family:1") @@ -155,7 +156,7 @@ func TestECS_DescribeDaemonTaskDefinition(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td, ok := resp["daemonTaskDefinition"].(map[string]any) require.True(t, ok) @@ -176,7 +177,7 @@ func TestECS_DeleteDaemonTaskDefinition(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, arn, resp["daemonTaskDefinitionArn"]) // Deleted revisions are excluded from the default ACTIVE-only describe lookup by family. @@ -188,7 +189,7 @@ func TestECS_DeleteDaemonTaskDefinition(t *testing.T) { rec = doECSRequest(t, h, "DescribeDaemonTaskDefinition", map[string]any{"daemonTaskDefinition": arn}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td, ok := resp["daemonTaskDefinition"].(map[string]any) require.True(t, ok) assert.Equal(t, "DELETED", td["status"]) @@ -208,7 +209,7 @@ func TestECS_ListDaemonTaskDefinitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tds, ok := resp["daemonTaskDefinitions"].([]any) require.True(t, ok) @@ -216,7 +217,7 @@ func TestECS_ListDaemonTaskDefinitions(t *testing.T) { rec = doECSRequest(t, h, "ListDaemonTaskDefinitions", map[string]any{"familyPrefix": "list-family-a"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tds, ok = resp["daemonTaskDefinitions"].([]any) require.True(t, ok) assert.Len(t, tds, 1) @@ -372,7 +373,7 @@ func TestECS_CreateDaemon(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACTIVE", resp["status"]) assert.NotEmpty(t, resp["daemonArn"]) assert.NotEmpty(t, resp["deploymentArn"]) @@ -415,7 +416,7 @@ func TestECS_DescribeDaemon(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) require.NotEmpty(t, daemonArn) @@ -423,7 +424,7 @@ func TestECS_DescribeDaemon(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) d, ok := resp["daemon"].(map[string]any) require.True(t, ok) @@ -616,7 +617,7 @@ func TestECS_UpdateDaemon(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) firstDeploymentArn, _ := created["deploymentArn"].(string) @@ -628,7 +629,7 @@ func TestECS_UpdateDaemon(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACTIVE", resp["status"]) assert.NotEqual(t, firstDeploymentArn, resp["deploymentArn"]) @@ -655,14 +656,14 @@ func TestECS_DeleteDaemon(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) rec = doECSRequest(t, h, "DeleteDaemon", map[string]any{"daemonArn": daemonArn}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DELETE_IN_PROGRESS", resp["status"]) // Deleted daemons are gone from state; a subsequent Describe 404s. @@ -693,7 +694,7 @@ func TestECS_ListDaemons(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) daemons, ok := resp["daemonSummariesList"].([]any) require.True(t, ok) @@ -701,7 +702,7 @@ func TestECS_ListDaemons(t *testing.T) { rec = doECSRequest(t, h, "ListDaemons", map[string]any{"capacityProviderArns": []string{"arn:none"}}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) daemons, ok = resp["daemonSummariesList"].([]any) require.True(t, ok) assert.Empty(t, daemons) @@ -730,14 +731,14 @@ func TestECS_ListDaemons_OmittedClusterScopesToDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) daemons, ok := resp["daemonSummariesList"].([]any) require.True(t, ok) assert.Empty(t, daemons, "omitted clusterArn must scope to default cluster, not every cluster") rec = doECSRequest(t, h, "ListDaemons", map[string]any{"clusterArn": "other-cluster"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) daemons, ok = resp["daemonSummariesList"].([]any) require.True(t, ok) assert.Len(t, daemons, 1) @@ -760,7 +761,7 @@ func TestECS_DescribeDaemonDeployments(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) deploymentArn, _ := created["deploymentArn"].(string) require.NotEmpty(t, deploymentArn) @@ -770,7 +771,7 @@ func TestECS_DescribeDaemonDeployments(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, ok := resp["daemonDeployments"].([]any) require.True(t, ok) @@ -804,14 +805,14 @@ func TestECS_ListDaemonDeployments(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) rec = doECSRequest(t, h, "ListDaemonDeployments", map[string]any{"daemonArn": daemonArn}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, ok := resp["daemonDeployments"].([]any) require.True(t, ok) @@ -833,14 +834,14 @@ func TestECS_DescribeDaemonRevisions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) rec = doECSRequest(t, h, "DescribeDaemon", map[string]any{"daemonArn": daemonArn}) require.Equal(t, http.StatusOK, rec.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described, jsonx.V1())) d, ok := described["daemon"].(map[string]any) require.True(t, ok) revs, ok := d["currentRevisions"].([]any) @@ -857,7 +858,7 @@ func TestECS_DescribeDaemonRevisions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) revisions, ok := resp["daemonRevisions"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_describe_taskdef_tags_test.go b/services/ecs/handler_describe_taskdef_tags_test.go index 8b8c4b1cf0..f0f551d3f4 100644 --- a/services/ecs/handler_describe_taskdef_tags_test.go +++ b/services/ecs/handler_describe_taskdef_tags_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -72,7 +73,7 @@ func TestECS_DescribeTaskDefinitionInclude(t *testing.T) { Tags []ecs.Tag `json:"tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) gotKeys := make([]string, 0, len(resp.Tags)) for _, tag := range resp.Tags { diff --git a/services/ecs/handler_express_gateway_test.go b/services/ecs/handler_express_gateway_test.go index 264e8c2da8..b2c5fcf147 100644 --- a/services/ecs/handler_express_gateway_test.go +++ b/services/ecs/handler_express_gateway_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -74,7 +75,7 @@ func TestECS_CreateExpressGatewayService(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc, ok := resp["service"].(map[string]any) require.True(t, ok) @@ -127,7 +128,7 @@ func TestECS_DeleteExpressGatewayService(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r, jsonx.V1())) return r["service"].(map[string]any)["serviceArn"].(string) }, @@ -170,7 +171,7 @@ func TestECS_DeleteExpressGatewayService(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc, ok := resp["service"].(map[string]any) require.True(t, ok) @@ -198,7 +199,7 @@ func TestECS_DescribeExpressGatewayService(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r, jsonx.V1())) return r["service"].(map[string]any)["serviceArn"].(string) }, @@ -234,7 +235,7 @@ func TestECS_DescribeExpressGatewayService(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc, ok := resp["service"].(map[string]any) require.True(t, ok) @@ -258,7 +259,7 @@ func TestECS_ExpressGatewayService_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["service"].(map[string]any)["serviceArn"].(string) @@ -309,7 +310,7 @@ func TestECS_UpdateExpressGatewayService(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) svc := createResp["service"].(map[string]any) serviceArn = svc["serviceArn"].(string) } else { @@ -328,7 +329,7 @@ func TestECS_UpdateExpressGatewayService(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // UpdateExpressGatewayServiceOutput.Service is the narrower // UpdatedExpressGatewayService shape (types.UpdatedExpressGatewayService): @@ -349,7 +350,7 @@ func TestECS_UpdateExpressGatewayService(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) descSvc := descResp["service"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/new-infra", descSvc["infrastructureRoleArn"]) }) @@ -419,7 +420,7 @@ func TestExpressGatewayService_TagResource_VisibleOnDescribe(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) serviceArn := createOut["service"].(map[string]any)["serviceArn"].(string) tagResp := doECSRequest(t, h, "TagResource", map[string]any{ @@ -435,7 +436,7 @@ func TestExpressGatewayService_TagResource_VisibleOnDescribe(t *testing.T) { require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) listTags := listOut["tags"].([]any) require.Len(t, listTags, 1) assert.Equal(t, "team", listTags[0].(map[string]any)["key"]) @@ -448,7 +449,7 @@ func TestExpressGatewayService_TagResource_VisibleOnDescribe(t *testing.T) { require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) descTags := descOut["service"].(map[string]any)["tags"].([]any) require.Len(t, descTags, 1) assert.Equal(t, "team", descTags[0].(map[string]any)["key"]) @@ -460,7 +461,7 @@ func TestExpressGatewayService_TagResource_VisibleOnDescribe(t *testing.T) { require.Equal(t, http.StatusOK, noTagsResp.Code) var noTagsOut map[string]any - require.NoError(t, json.Unmarshal(noTagsResp.Body.Bytes(), &noTagsOut)) + require.NoError(t, json.Unmarshal(noTagsResp.Body.Bytes(), &noTagsOut, jsonx.V1())) assert.Nil(t, noTagsOut["service"].(map[string]any)["tags"]) } diff --git a/services/ecs/handler_service_config_test.go b/services/ecs/handler_service_config_test.go index 10f9b74814..d09dff96b3 100644 --- a/services/ecs/handler_service_config_test.go +++ b/services/ecs/handler_service_config_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestService_CapacityProviderStrategy_Roundtrip(t *testing.T) { @@ -34,7 +36,7 @@ func TestService_CapacityProviderStrategy_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) strategy := svc["capacityProviderStrategy"].([]any) require.Len(t, strategy, 2) @@ -85,7 +87,7 @@ func TestService_CapacityProviderStrategy_UpdateService(t *testing.T) { require.Equal(t, http.StatusOK, updateResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) strategy := svc["capacityProviderStrategy"].([]any) assert.Len(t, strategy, 2) @@ -119,7 +121,7 @@ func TestService_CircuitBreaker_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) @@ -156,7 +158,7 @@ func TestService_CircuitBreaker_EnabledNoRollback(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) cb := dc["deploymentCircuitBreaker"].(map[string]any) @@ -196,7 +198,7 @@ func TestService_CircuitBreaker_UpdatePreserved(t *testing.T) { require.Equal(t, http.StatusOK, updateResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) cb := dc["deploymentCircuitBreaker"].(map[string]any) @@ -224,7 +226,7 @@ func TestService_DeploymentConfig_Defaults(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) // AWS defaults: minimumHealthyPercent=100, maximumPercent=200 @@ -265,7 +267,7 @@ func TestServiceConnect_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) sc := primaryServiceConnect(t, svc) assert.Equal(t, true, sc["enabled"]) @@ -307,7 +309,7 @@ func TestServiceConnect_Disabled(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) sc := primaryServiceConnect(t, svc) assert.Equal(t, false, sc["enabled"]) @@ -341,7 +343,7 @@ func TestServiceConnect_UpdateService(t *testing.T) { require.Equal(t, http.StatusOK, updateResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) sc := primaryServiceConnect(t, svc) assert.Equal(t, true, sc["enabled"]) @@ -375,7 +377,7 @@ func TestServiceDiscovery_CloudMap_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) registries := svc["serviceRegistries"].([]any) require.Len(t, registries, 1) @@ -420,7 +422,7 @@ func TestServiceDiscovery_MultipleRegistries(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) registries := svc["serviceRegistries"].([]any) assert.Len(t, registries, 2) @@ -454,7 +456,7 @@ func TestServiceDiscovery_DescribeServices_Preserved(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out, jsonx.V1())) services := out["services"].([]any) require.Len(t, services, 1) svc := services[0].(map[string]any) diff --git a/services/ecs/handler_service_deployments_test.go b/services/ecs/handler_service_deployments_test.go index 46a2e96464..af9b866a8d 100644 --- a/services/ecs/handler_service_deployments_test.go +++ b/services/ecs/handler_service_deployments_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -32,7 +33,7 @@ func TestServiceDeployment_DescribeList_Roundtrip(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) briefs := listOut["serviceDeployments"].([]any) require.NotEmpty(t, briefs) firstArn := briefs[0].(map[string]any)["serviceDeploymentArn"].(string) @@ -42,7 +43,7 @@ func TestServiceDeployment_DescribeList_Roundtrip(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) deps := descOut["serviceDeployments"].([]any) assert.Len(t, deps, 1) dep := deps[0].(map[string]any) @@ -85,7 +86,7 @@ func TestECS_ListServiceDeployments_StableOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) briefs := resp["serviceDeployments"].([]any) require.Len(t, briefs, 3) @@ -118,7 +119,7 @@ func TestStopServiceDeployment(t *testing.T) { }) require.Equal(t, http.StatusOK, stopResp.Code) var stopOut map[string]any - require.NoError(t, json.Unmarshal(stopResp.Body.Bytes(), &stopOut)) + require.NoError(t, json.Unmarshal(stopResp.Body.Bytes(), &stopOut, jsonx.V1())) assert.Equal(t, depArn, stopOut["serviceDeploymentArn"]) assert.NotContains(t, stopOut, "serviceDeployment") @@ -204,7 +205,7 @@ func TestECS_DescribeServiceDeployments(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deployments := resp["serviceDeployments"].([]any) failures := resp["failures"].([]any) @@ -240,7 +241,7 @@ func TestECS_ListServiceDeployments(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) briefs, ok := resp["serviceDeployments"].([]any) require.True(t, ok) @@ -276,7 +277,7 @@ func TestECS_ListServiceDeployments_Shape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasOldShape := resp["serviceDeploymentArns"] assert.False(t, hasOldShape, "response must not carry the bare serviceDeploymentArns shape") @@ -355,7 +356,7 @@ func TestECS_StopServiceDeployment(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["serviceDeploymentArn"]) assert.NotContains(t, resp, "serviceDeployment") @@ -427,7 +428,7 @@ func TestECS_ContinueServiceDeployment(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, tt.wantTypeIsIn, resp["__type"]) }) } diff --git a/services/ecs/handler_service_deployments_wiring_test.go b/services/ecs/handler_service_deployments_wiring_test.go index a3ce2fa160..dbc8ebff5c 100644 --- a/services/ecs/handler_service_deployments_wiring_test.go +++ b/services/ecs/handler_service_deployments_wiring_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestECS_ServiceDeployments_RealDeploymentsAreVisible proves @@ -77,7 +79,7 @@ func TestECS_ServiceDeployments_RealDeploymentsAreVisible(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) briefs, ok := listResp["serviceDeployments"].([]any) require.True(t, ok) @@ -93,7 +95,7 @@ func TestECS_ServiceDeployments_RealDeploymentsAreVisible(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) deployments, ok := describeResp["serviceDeployments"].([]any) require.True(t, ok) @@ -145,7 +147,7 @@ func TestECS_ServiceDeployments_DeletedOnServiceDelete(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) briefs, ok := listResp["serviceDeployments"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_service_fields_test.go b/services/ecs/handler_service_fields_test.go index ec1c1a9a61..8b5b995bba 100644 --- a/services/ecs/handler_service_fields_test.go +++ b/services/ecs/handler_service_fields_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestService_EnableExecuteCommand_Create(t *testing.T) { @@ -30,7 +32,7 @@ func TestService_EnableExecuteCommand_Create(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) assert.Equal(t, true, svc["enableExecuteCommand"]) } @@ -55,7 +57,7 @@ func TestService_EnableExecuteCommand_Default_False(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) eec := svc["enableExecuteCommand"] assert.NotEqual(t, true, eec) @@ -87,7 +89,7 @@ func TestService_EnableExecuteCommand_UpdateService(t *testing.T) { require.Equal(t, http.StatusOK, updResp.Code) var updOut map[string]any - require.NoError(t, json.Unmarshal(updResp.Body.Bytes(), &updOut)) + require.NoError(t, json.Unmarshal(updResp.Body.Bytes(), &updOut, jsonx.V1())) svc := updOut["service"].(map[string]any) assert.Equal(t, true, svc["enableExecuteCommand"]) @@ -100,7 +102,7 @@ func TestService_EnableExecuteCommand_UpdateService(t *testing.T) { require.Equal(t, http.StatusOK, disResp.Code) var disOut map[string]any - require.NoError(t, json.Unmarshal(disResp.Body.Bytes(), &disOut)) + require.NoError(t, json.Unmarshal(disResp.Body.Bytes(), &disOut, jsonx.V1())) disSvc := disOut["service"].(map[string]any) eec := disSvc["enableExecuteCommand"] assert.NotEqual(t, true, eec) @@ -131,7 +133,7 @@ func TestService_EnableExecuteCommand_DescribeServices(t *testing.T) { require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) svcs := descOut["services"].([]any) require.Len(t, svcs, 1) assert.Equal(t, true, svcs[0].(map[string]any)["enableExecuteCommand"]) @@ -159,7 +161,7 @@ func TestService_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc := resp["service"].(map[string]any) @@ -192,7 +194,7 @@ func TestService_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc := resp["service"].(map[string]any) @@ -229,7 +231,7 @@ func TestService_EmptyArrays_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["services"].([]any) require.Len(t, services, 1) @@ -268,7 +270,7 @@ func TestHandler_CreateService_DeploymentConfigDefaults(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) assert.InDelta(t, float64(100), dc["minimumHealthyPercent"], 0.001) @@ -297,7 +299,7 @@ func TestHandler_CreateService_DeploymentConfigCustom(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) assert.InDelta(t, float64(50), dc["minimumHealthyPercent"], 0.001) @@ -343,7 +345,7 @@ func TestHandler_CreateService_DeploymentController_Rolling_Accepted(t *testing. assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentController"].(map[string]any) assert.Equal(t, "ROLLING", dc["type"]) @@ -374,7 +376,7 @@ func TestHandler_CreateService_LoadBalancers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) lbs := svc["loadBalancers"].([]any) require.Len(t, lbs, 1) @@ -408,7 +410,7 @@ func TestHandler_CreateService_ServiceRegistries(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) regs := svc["serviceRegistries"].([]any) require.Len(t, regs, 1) @@ -441,7 +443,7 @@ func TestHandler_CreateService_NetworkConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) nc := svc["networkConfiguration"].(map[string]any) avpc := nc["awsvpcConfiguration"].(map[string]any) @@ -476,7 +478,7 @@ func TestHandler_UpdateService_NetworkConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) nc := svc["networkConfiguration"].(map[string]any) avpc := nc["awsvpcConfiguration"].(map[string]any) @@ -512,7 +514,7 @@ func TestHandler_UpdateService_LoadBalancers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) lbs := svc["loadBalancers"].([]any) require.Len(t, lbs, 1) @@ -545,7 +547,7 @@ func TestHandler_UpdateService_DeploymentConfig_MinMaxPercent(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) dc := svc["deploymentConfiguration"].(map[string]any) assert.InDelta(t, float64(25), dc["minimumHealthyPercent"], 0.001) diff --git a/services/ecs/handler_services_deployments_test.go b/services/ecs/handler_services_deployments_test.go index 80cde2865e..a3fde5f6b3 100644 --- a/services/ecs/handler_services_deployments_test.go +++ b/services/ecs/handler_services_deployments_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -104,7 +105,7 @@ func TestECS_ListServices(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["serviceArns"].([]any) assert.Len(t, arns, tt.wantLen) @@ -195,7 +196,7 @@ func TestDescribeServices_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["services"].([]any) assert.Empty(t, services) @@ -225,7 +226,7 @@ func TestDescribeServices_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["services"].([]any) assert.Len(t, services, 1) @@ -273,7 +274,7 @@ func TestDescribeServices_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["services"].([]any) assert.Len(t, services, 2) @@ -302,7 +303,7 @@ func TestHandler_CreateService_PropagateTags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) assert.Equal(t, "SERVICE", svc["propagateTags"]) } @@ -325,7 +326,7 @@ func TestHandler_CreateService_PropagateTags_DefaultNone(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["service"].(map[string]any) assert.Equal(t, "NONE", svc["propagateTags"]) } @@ -342,7 +343,7 @@ func TestCreateService_DeploymentsField_Populated(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) // Create cluster + service. @@ -357,7 +358,7 @@ func TestCreateService_DeploymentsField_Populated(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code, svcRec.Body.String()) var svcOut map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcOut, jsonx.V1())) svc := svcOut["service"].(map[string]any) require.Contains(t, svc, "deployments", "service response must include deployments") @@ -383,7 +384,7 @@ func TestUpdateService_DeploymentRotation_OnTaskDefChange(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(tdRec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(tdRec1.Body.Bytes(), &out1, jsonx.V1())) tdArn1 := out1["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) tdRec2 := doECSRequest(t, h, "RegisterTaskDefinition", map[string]any{ @@ -392,7 +393,7 @@ func TestUpdateService_DeploymentRotation_OnTaskDefChange(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(tdRec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(tdRec2.Body.Bytes(), &out2, jsonx.V1())) tdArn2 := out2["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) doECSRequest(t, h, "CreateCluster", map[string]any{"clusterName": "staging"}) @@ -414,7 +415,7 @@ func TestUpdateService_DeploymentRotation_OnTaskDefChange(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code, updRec.Body.String()) var updOut map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updOut)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updOut, jsonx.V1())) svc := updOut["service"].(map[string]any) deployments := svc["deployments"].([]any) @@ -442,7 +443,7 @@ func TestDescribeServices_DeploymentsField(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) doECSRequest(t, h, "CreateCluster", map[string]any{"clusterName": "ds-cluster"}) @@ -461,7 +462,7 @@ func TestDescribeServices_DeploymentsField(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) services := descOut["services"].([]any) require.Len(t, services, 1) @@ -528,7 +529,7 @@ func TestECS_CreateService_Tags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc, ok := resp["service"].(map[string]any) require.True(t, ok) @@ -623,7 +624,7 @@ func TestDeploymentRolloutState_CompletedWhenDesiredMet(t *testing.T) { require.Equal(t, http.StatusOK, descResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &out, jsonx.V1())) svcs, ok := out["services"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_services_test.go b/services/ecs/handler_services_test.go index d8407f1ece..dbde9abc6c 100644 --- a/services/ecs/handler_services_test.go +++ b/services/ecs/handler_services_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -78,7 +79,7 @@ func TestECS_CreateService(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc := resp["service"].(map[string]any) assert.NotEmpty(t, svc["serviceArn"]) @@ -131,7 +132,7 @@ func TestECS_DescribeServices(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) svcs := resp["services"].([]any) assert.GreaterOrEqual(t, len(svcs), 1) @@ -141,7 +142,7 @@ func TestECS_DescribeServices(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) svcs3 := resp3["services"].([]any) require.Len(t, svcs3, 1) @@ -198,7 +199,7 @@ func TestECS_UpdateService(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) svc := resp["service"].(map[string]any) assert.Equal(t, tt.wantDC, int(svc["desiredCount"].(float64))) @@ -224,7 +225,7 @@ func TestECS_DeleteService(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) svc := resp["service"].(map[string]any) assert.Equal(t, "del-svc", svc["serviceName"]) @@ -237,7 +238,7 @@ func TestECS_DeleteService(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) svcs3, _ := resp3["services"].([]any) require.Len(t, svcs3, 1) @@ -251,7 +252,7 @@ func TestECS_DeleteService(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var resp4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4, jsonx.V1())) assert.Empty(t, resp4["serviceArns"]) } @@ -579,7 +580,7 @@ func TestCreateService_Tags_PropagateToResource(t *testing.T) { }) require.Equal(t, http.StatusOK, svcResp.Code) var svcOut map[string]any - require.NoError(t, json.Unmarshal(svcResp.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(svcResp.Body.Bytes(), &svcOut, jsonx.V1())) tags := svcOut["service"].(map[string]any)["tags"].([]any) assert.Len(t, tags, 2) } @@ -611,7 +612,7 @@ func TestListServices_LaunchTypeFilter(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["serviceArns"].([]any) assert.Len(t, arns, 3) } @@ -642,7 +643,7 @@ func TestDescribeServices_MultipleServices(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) services := descOut["services"].([]any) assert.Len(t, services, 4) } @@ -736,7 +737,7 @@ func TestListServicesByNamespace_Filter(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out, jsonx.V1())) arns := out["serviceArns"].([]any) assert.Len(t, arns, 2, "only the two services actually attached to the payments namespace") } @@ -768,7 +769,7 @@ func TestService_Tags_ResourceTagSync(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) serviceArn := createOut["service"].(map[string]any)["serviceArn"].(string) listRec := doECSRequest( @@ -777,7 +778,7 @@ func TestService_Tags_ResourceTagSync(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "team", tags[0].(map[string]any)["key"]) @@ -905,7 +906,7 @@ func TestService_Tags_ResourceTagSync(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) serviceArn := createOut["service"].(map[string]any)["serviceArn"].(string) deleteRec := doECSRequest(t, h, "DeleteService", map[string]any{ @@ -915,7 +916,7 @@ func TestService_Tags_ResourceTagSync(t *testing.T) { require.Equal(t, http.StatusOK, deleteRec.Code) var deleteOut map[string]any - require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteOut)) + require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteOut, jsonx.V1())) deletedTags := deleteOut["service"].(map[string]any)["tags"].([]any) require.Len(t, deletedTags, 1) assert.Equal(t, "team", deletedTags[0].(map[string]any)["key"]) @@ -926,7 +927,7 @@ func TestService_Tags_ResourceTagSync(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut["tags"]) }, }, diff --git a/services/ecs/handler_tags_test.go b/services/ecs/handler_tags_test.go index df4ba118d5..2b898e3aba 100644 --- a/services/ecs/handler_tags_test.go +++ b/services/ecs/handler_tags_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -92,7 +93,7 @@ func TestTagResource_Service(t *testing.T) { "desiredCount": 1, }) var svcOut map[string]any - require.NoError(t, json.Unmarshal(svcResp.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(svcResp.Body.Bytes(), &svcOut, jsonx.V1())) svcArn := svcOut["service"].(map[string]any)["serviceArn"].(string) // Tag @@ -111,7 +112,7 @@ func TestTagResource_Service(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["tags"].([]any) assert.Len(t, tags, 2) } @@ -136,7 +137,7 @@ func TestTagResource_Overwrite(t *testing.T) { "resourceArn": fakeArn, }) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "prod", tags[0].(map[string]any)["value"]) @@ -167,7 +168,7 @@ func TestUntagResource(t *testing.T) { "resourceArn": fakeArn, }) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "team", tags[0].(map[string]any)["key"]) @@ -191,7 +192,7 @@ func TestCreateCapacityProvider_TagsVisibleViaListTagsForResource(t *testing.T) require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) cpArn := createOut["capacityProvider"].(map[string]any)["capacityProviderArn"].(string) listResp := doECSRequest(t, h, "ListTagsForResource", map[string]any{ @@ -200,7 +201,7 @@ func TestCreateCapacityProvider_TagsVisibleViaListTagsForResource(t *testing.T) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) tags := listOut["tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "env", tags[0].(map[string]any)["key"]) @@ -222,7 +223,7 @@ func TestDescribeCapacityProviders_TagResource_ReflectsInDescribe(t *testing.T) require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) cpArn := createOut["capacityProvider"].(map[string]any)["capacityProviderArn"].(string) tagResp := doECSRequest(t, h, "TagResource", map[string]any{ @@ -238,7 +239,7 @@ func TestDescribeCapacityProviders_TagResource_ReflectsInDescribe(t *testing.T) require.Equal(t, http.StatusOK, describeResp.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &describeOut, jsonx.V1())) providers := describeOut["capacityProviders"].([]any) require.Len(t, providers, 1) tags := providers[0].(map[string]any)["tags"].([]any) @@ -264,7 +265,7 @@ func TestTagResource_Cluster(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out, jsonx.V1())) tags := out["tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "owner", tags[0].(map[string]any)["key"]) @@ -334,7 +335,7 @@ func TestECS_Tagging(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) tagList, ok := resp["tags"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_task_definition_fields_test.go b/services/ecs/handler_task_definition_fields_test.go index 6009c299bf..0bdeec7c3c 100644 --- a/services/ecs/handler_task_definition_fields_test.go +++ b/services/ecs/handler_task_definition_fields_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTaskDefinition_RuntimePlatform_Roundtrip(t *testing.T) { @@ -27,7 +29,7 @@ func TestTaskDefinition_RuntimePlatform_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rp := td["runtimePlatform"].(map[string]any) assert.Equal(t, "ARM64", rp["cpuArchitecture"]) @@ -41,7 +43,7 @@ func TestTaskDefinition_RuntimePlatform_Roundtrip(t *testing.T) { ) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) descTD := descOut["taskDefinition"].(map[string]any) assert.Equal(t, "ARM64", descTD["runtimePlatform"].(map[string]any)["cpuArchitecture"]) } @@ -64,7 +66,7 @@ func TestTaskDefinition_RuntimePlatform_X86(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rp := td["runtimePlatform"].(map[string]any) assert.Equal(t, "X86_64", rp["cpuArchitecture"]) @@ -89,7 +91,7 @@ func TestTaskDefinition_RuntimePlatform_Windows(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rp := td["runtimePlatform"].(map[string]any) assert.Equal(t, "WINDOWS_SERVER_2022_FULL", rp["operatingSystemFamily"]) @@ -116,7 +118,7 @@ func TestTaskDefinition_EphemeralStorage_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) es := td["ephemeralStorage"].(map[string]any) assert.InDelta(t, float64(50), es["sizeInGiB"], 0.001) @@ -129,7 +131,7 @@ func TestTaskDefinition_EphemeralStorage_Roundtrip(t *testing.T) { ) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) descTD := descOut["taskDefinition"].(map[string]any) assert.InDelta(t, float64(50), descTD["ephemeralStorage"].(map[string]any)["sizeInGiB"], 0.001) } @@ -146,7 +148,7 @@ func TestTaskDefinition_EphemeralStorage_Default(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) _, hasEph := td["ephemeralStorage"] assert.False(t, hasEph, "ephemeralStorage should be absent when not set") @@ -176,7 +178,7 @@ func TestTaskDefinition_InferenceAccelerators_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) accs := td["inferenceAccelerators"].([]any) @@ -212,7 +214,7 @@ func TestTaskDefinition_InferenceAccelerators_Multiple(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) accs := td["inferenceAccelerators"].([]any) assert.Len(t, accs, 2) @@ -239,7 +241,7 @@ func TestContainerDef_GPU_ResourceRequirement(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cds := td["containerDefinitions"].([]any) require.Len(t, cds, 1) @@ -275,7 +277,7 @@ func TestContainerDef_GPU_MultipleContainers(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cds := td["containerDefinitions"].([]any) require.Len(t, cds, 2) @@ -312,7 +314,7 @@ func TestContainerDef_EnvironmentFiles_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cds := td["containerDefinitions"].([]any) cd := cds[0].(map[string]any) @@ -359,7 +361,7 @@ func TestContainerDef_EnvironmentFiles_WithEnv(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cd := td["containerDefinitions"].([]any)[0].(map[string]any) @@ -411,7 +413,7 @@ func TestTaskDefinition_AllAdvancedFields_Combined(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rp := td["runtimePlatform"].(map[string]any) @@ -461,7 +463,7 @@ func TestTaskDefinition_BackwardCompat_NoNewFields(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) // New fields should be absent @@ -495,7 +497,7 @@ func TestTaskDefinition_Volumes_EmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) @@ -524,7 +526,7 @@ func TestTaskDefinition_Volumes_EmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) @@ -560,7 +562,7 @@ func TestTaskDefinition_Volumes_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) vols, _ := td["volumes"].([]any) @@ -588,7 +590,7 @@ func TestHandler_RegisterTaskDefinition_RequiresCompatibilities(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rcs := td["requiresCompatibilities"].([]any) require.Len(t, rcs, 1) @@ -658,7 +660,7 @@ func TestHandler_RegisterTaskDefinition_TaskRoleArn(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/task-role", td["taskRoleArn"]) assert.Equal(t, "arn:aws:iam::000000000000:role/exec-role", td["executionRoleArn"]) @@ -698,7 +700,7 @@ func TestHandler_RegisterTaskDefinition_Volumes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) vols := td["volumes"].([]any) require.Len(t, vols, 2) @@ -734,7 +736,7 @@ func TestHandler_RegisterTaskDefinition_LogConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cd := td["containerDefinitions"].([]any)[0].(map[string]any) lc := cd["logConfiguration"].(map[string]any) @@ -764,7 +766,7 @@ func TestHandler_RegisterTaskDefinition_Secrets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cd := td["containerDefinitions"].([]any)[0].(map[string]any) secrets := cd["secrets"].([]any) @@ -798,7 +800,7 @@ func TestHandler_RegisterTaskDefinition_PortMapping_Extended(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cd := td["containerDefinitions"].([]any)[0].(map[string]any) pm := cd["portMappings"].([]any)[0].(map[string]any) @@ -831,7 +833,7 @@ func TestHandler_RegisterTaskDefinition_HealthCheck(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) cd := td["containerDefinitions"].([]any)[0].(map[string]any) hc := cd["healthCheck"].(map[string]any) @@ -858,7 +860,7 @@ func TestHandler_DescribeTaskDefinition_Volumes_RoundTrip(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) vols := td["volumes"].([]any) require.Len(t, vols, 1) @@ -886,7 +888,7 @@ func TestHandler_DescribeTaskDefinition_RequiresCompatibilities_RoundTrip(t *tes assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) td := out["taskDefinition"].(map[string]any) rcs := td["requiresCompatibilities"].([]any) assert.Len(t, rcs, 2) @@ -937,7 +939,7 @@ func TestECS_RegisterTaskDefinition_CPU_Memory(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td, ok := resp["taskDefinition"].(map[string]any) require.True(t, ok) diff --git a/services/ecs/handler_task_definitions_test.go b/services/ecs/handler_task_definitions_test.go index b6cb457a8f..ac5bca6cb9 100644 --- a/services/ecs/handler_task_definitions_test.go +++ b/services/ecs/handler_task_definitions_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -92,7 +93,7 @@ func TestECS_RegisterTaskDefinition(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td, ok := resp["taskDefinition"].(map[string]any) require.True(t, ok) @@ -119,7 +120,7 @@ func TestECS_RegisterTaskDefinition_MultipleRevisions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) assert.Equal(t, i, int(td["revision"].(float64))) @@ -145,7 +146,7 @@ func TestECS_DescribeTaskDefinition(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) assert.Equal(t, "web", td["family"]) @@ -174,14 +175,14 @@ func TestECS_DeregisterTaskDefinition(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) tdArn := createResp["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) rec2 := doECSRequest(t, h, "DeregisterTaskDefinition", map[string]any{"taskDefinition": tdArn}) require.Equal(t, http.StatusOK, rec2.Code) var deregResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &deregResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &deregResp, jsonx.V1())) td := deregResp["taskDefinition"].(map[string]any) assert.Equal(t, "INACTIVE", td["status"]) @@ -206,7 +207,7 @@ func TestECS_ListTaskDefinitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["taskDefinitionArns"].([]any) assert.GreaterOrEqual(t, len(arns), 3) @@ -216,7 +217,7 @@ func TestECS_ListTaskDefinitions(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) arns2 := resp2["taskDefinitionArns"].([]any) assert.Len(t, arns2, 2) @@ -317,7 +318,7 @@ func TestECS_Handler_ListTaskDefinitions_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns, ok := resp["taskDefinitionArns"].([]any) require.True(t, ok) @@ -391,7 +392,7 @@ func TestECS_ListTaskDefinitions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["taskDefinitionArns"].([]any) assert.GreaterOrEqual(t, len(arns), tt.wantMinCount) @@ -421,7 +422,7 @@ func TestECS_ListTaskDefinitions_TokenChaining(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) arns1 := page1["taskDefinitionArns"].([]any) assert.Len(t, arns1, 2) @@ -440,7 +441,7 @@ func TestECS_ListTaskDefinitions_TokenChaining(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) arns2 := page2["taskDefinitionArns"].([]any) assert.GreaterOrEqual(t, len(arns2), 1) @@ -482,7 +483,7 @@ func TestECS_TaskDefinitionRevisionCap(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) td := resp["taskDefinition"].(map[string]any) latestRev := int(td["revision"].(float64)) @@ -498,7 +499,7 @@ func TestECS_TaskDefinitionRevisionCap(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) arns := listResp["taskDefinitionArns"].([]any) assert.LessOrEqual(t, len(arns), 100, "stored revisions should not exceed the cap") @@ -524,7 +525,7 @@ func TestTaskDefinition_MultipleRevisions_SameFamily(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["taskDefinitionArns"].([]any) assert.Len(t, arns, 3) @@ -534,7 +535,7 @@ func TestTaskDefinition_MultipleRevisions_SameFamily(t *testing.T) { }) require.Equal(t, http.StatusOK, famResp.Code) var famOut map[string]any - require.NoError(t, json.Unmarshal(famResp.Body.Bytes(), &famOut)) + require.NoError(t, json.Unmarshal(famResp.Body.Bytes(), &famOut, jsonx.V1())) families := famOut["families"].([]any) assert.Len(t, families, 1) assert.Equal(t, "rev-family", families[0]) @@ -558,7 +559,7 @@ func TestTaskDefinition_Deregister_Specific_Revision(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) td := descOut["taskDefinition"].(map[string]any) rev1Arn := td["taskDefinitionArn"].(string) require.NotEmpty(t, rev1Arn) @@ -569,7 +570,7 @@ func TestTaskDefinition_Deregister_Specific_Revision(t *testing.T) { }) require.Equal(t, http.StatusOK, deregResp.Code) var deregOut map[string]any - require.NoError(t, json.Unmarshal(deregResp.Body.Bytes(), &deregOut)) + require.NoError(t, json.Unmarshal(deregResp.Body.Bytes(), &deregOut, jsonx.V1())) deregTd := deregOut["taskDefinition"].(map[string]any) assert.Equal(t, "INACTIVE", deregTd["status"]) @@ -580,7 +581,7 @@ func TestTaskDefinition_Deregister_Specific_Revision(t *testing.T) { }) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["taskDefinitionArns"].([]any) assert.Len(t, arns, 2) } @@ -597,7 +598,7 @@ func TestTaskDefinition_DeleteDefinitions_Batch(t *testing.T) { "containerDefinitions": []any{map[string]any{"name": "app", "image": "nginx"}}, }) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) // Deregister first (required before delete) td := out["taskDefinition"].(map[string]any) arn := td["taskDefinitionArn"].(string) @@ -611,7 +612,7 @@ func TestTaskDefinition_DeleteDefinitions_Batch(t *testing.T) { require.Equal(t, http.StatusOK, deleteResp.Code) var deleteOut map[string]any - require.NoError(t, json.Unmarshal(deleteResp.Body.Bytes(), &deleteOut)) + require.NoError(t, json.Unmarshal(deleteResp.Body.Bytes(), &deleteOut, jsonx.V1())) deleted := deleteOut["taskDefinitions"].([]any) assert.Len(t, deleted, 3) } @@ -640,7 +641,7 @@ func TestTaskDefinition_ListByStatus_Active_Inactive(t *testing.T) { "status": "ACTIVE", }) var activeOut map[string]any - require.NoError(t, json.Unmarshal(activeResp.Body.Bytes(), &activeOut)) + require.NoError(t, json.Unmarshal(activeResp.Body.Bytes(), &activeOut, jsonx.V1())) assert.Len(t, activeOut["taskDefinitionArns"].([]any), 1) // List INACTIVE @@ -649,7 +650,7 @@ func TestTaskDefinition_ListByStatus_Active_Inactive(t *testing.T) { "status": "INACTIVE", }) var inactiveOut map[string]any - require.NoError(t, json.Unmarshal(inactiveResp.Body.Bytes(), &inactiveOut)) + require.NoError(t, json.Unmarshal(inactiveResp.Body.Bytes(), &inactiveOut, jsonx.V1())) assert.Len(t, inactiveOut["taskDefinitionArns"].([]any), 1) } @@ -676,7 +677,7 @@ func TestTaskDefinitionFamilies_MultipleStatus(t *testing.T) { }) require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) families := out["families"].([]any) famNames := make([]string, 0, len(families)) for _, f := range families { @@ -707,7 +708,7 @@ func TestECS_DeleteTaskDefinitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r, jsonx.V1())) arn := r["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) doECSRequest( @@ -733,7 +734,7 @@ func TestECS_DeleteTaskDefinitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r, jsonx.V1())) return r["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) }, @@ -781,7 +782,7 @@ func TestECS_DeleteTaskDefinitions(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deleted := resp["taskDefinitions"].([]any) failures := resp["failures"].([]any) @@ -828,7 +829,7 @@ func TestHandler_ListTaskDefinitions_StatusFilter(t *testing.T) { }) require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) arn1 := out1["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) rec2 := doECSRequest(t, h, "RegisterTaskDefinition", map[string]any{ @@ -852,7 +853,7 @@ func TestHandler_ListTaskDefinitions_StatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["taskDefinitionArns"].([]any) require.Len(t, arns, 1) assert.Contains(t, arns[0].(string), tt.wantContains) @@ -906,7 +907,7 @@ func TestECS_ListTaskDefinitionFamilies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) families, ok := resp["families"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_task_exec_test.go b/services/ecs/handler_task_exec_test.go index 24ab8b04ec..a3980eda04 100644 --- a/services/ecs/handler_task_exec_test.go +++ b/services/ecs/handler_task_exec_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -25,7 +26,7 @@ func TestECS_StopTask(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var runResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp, jsonx.V1())) taskArn := runResp["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) @@ -36,7 +37,7 @@ func TestECS_StopTask(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) task := resp2["task"].(map[string]any) assert.Equal(t, "STOPPED", task["lastStatus"]) @@ -59,7 +60,7 @@ func TestECS_ListTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) arns := resp["taskArns"].([]any) assert.Len(t, arns, 3) @@ -82,7 +83,7 @@ func TestECS_ListTasks_DesiredStatusDefaultsToRunning(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var runResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp, jsonx.V1())) tasks := runResp["tasks"].([]any) require.Len(t, tasks, 2) stoppedArn := tasks[0].(map[string]any)["taskArn"].(string) @@ -94,14 +95,14 @@ func TestECS_ListTasks_DesiredStatusDefaultsToRunning(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["taskArns"].([]any) assert.Len(t, arns, 1, "omitted desiredStatus must default to RUNNING only") assert.NotContains(t, arns, stoppedArn) rec = doECSRequest(t, h, "ListTasks", map[string]any{"desiredStatus": "STOPPED"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns = resp["taskArns"].([]any) assert.Equal(t, []any{stoppedArn}, arns) } @@ -208,7 +209,7 @@ func TestECS_ListTasks_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["taskArns"].([]any) assert.GreaterOrEqual(t, len(arns), tt.wantMinCount) @@ -238,7 +239,7 @@ func TestECS_ListTasks_TokenChaining(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) arns1 := page1["taskArns"].([]any) assert.Len(t, arns1, 2) @@ -252,7 +253,7 @@ func TestECS_ListTasks_TokenChaining(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) arns2 := page2["taskArns"].([]any) assert.GreaterOrEqual(t, len(arns2), 1) @@ -287,7 +288,7 @@ func TestECSExec_Basic(t *testing.T) { }) require.Equal(t, http.StatusOK, runResp.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) tasks := runOut["tasks"].([]any) require.Len(t, tasks, 1) taskArn := tasks[0].(map[string]any)["taskArn"].(string) @@ -320,7 +321,7 @@ func TestECSExec_NonInteractive(t *testing.T) { "enableExecuteCommand": true, }) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) taskArn := runOut["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) execResp := doECSRequest(t, h, "ExecuteCommand", map[string]any{ @@ -351,7 +352,7 @@ func TestTaskProtection_Enable_Disable(t *testing.T) { "count": 1, }) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) taskArn := runOut["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) // Enable protection @@ -365,7 +366,7 @@ func TestTaskProtection_Enable_Disable(t *testing.T) { require.Equal(t, http.StatusOK, protResp.Code) var protOut map[string]any - require.NoError(t, json.Unmarshal(protResp.Body.Bytes(), &protOut)) + require.NoError(t, json.Unmarshal(protResp.Body.Bytes(), &protOut, jsonx.V1())) prot := protOut["protectedTasks"].([]any)[0].(map[string]any) assert.Equal(t, true, prot["protectionEnabled"]) @@ -376,7 +377,7 @@ func TestTaskProtection_Enable_Disable(t *testing.T) { }) require.Equal(t, http.StatusOK, getResp.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getResp.Body.Bytes(), &getOut, jsonx.V1())) protTasks := getOut["protectedTasks"].([]any) assert.Len(t, protTasks, 1) assert.Equal(t, true, protTasks[0].(map[string]any)["protectionEnabled"]) @@ -411,7 +412,7 @@ func TestStartTask_MultipleInstances(t *testing.T) { ), }) var ciOut map[string]any - require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut)) + require.NoError(t, json.Unmarshal(ciResp.Body.Bytes(), &ciOut, jsonx.V1())) ciArns[i] = ciOut["containerInstance"].(map[string]any)["containerInstanceArn"].(string) } @@ -423,7 +424,7 @@ func TestStartTask_MultipleInstances(t *testing.T) { require.Equal(t, http.StatusOK, startResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) assert.Len(t, tasks, 3) } @@ -453,7 +454,7 @@ func TestECS_ExecuteCommand(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) taskArn := resp["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) @@ -486,7 +487,7 @@ func TestECS_ExecuteCommand(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) taskArn := resp["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) @@ -518,7 +519,7 @@ func TestECS_ExecuteCommand(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["clusterArn"]) assert.NotEmpty(t, resp["taskArn"]) @@ -552,7 +553,7 @@ func TestTask_EnableExecuteCommand_RunTask(t *testing.T) { require.Equal(t, http.StatusOK, runResp.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) tasks := runOut["tasks"].([]any) require.Len(t, tasks, 1) assert.Equal(t, true, tasks[0].(map[string]any)["enableExecuteCommand"]) @@ -586,7 +587,7 @@ func TestTask_EnableExecuteCommand_ServicePropagation(t *testing.T) { listResp := doECSRequest(t, h2, "ListTasks", map[string]any{"cluster": "svc-exec-cluster"}) require.Equal(t, http.StatusOK, listResp.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["taskArns"].([]any) require.NotEmpty(t, arns) taskArn := arns[0].(string) @@ -597,7 +598,7 @@ func TestTask_EnableExecuteCommand_ServicePropagation(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) tasks := descOut["tasks"].([]any) require.Len(t, tasks, 1) assert.Equal(t, true, tasks[0].(map[string]any)["enableExecuteCommand"]) @@ -643,7 +644,7 @@ func TestECS_TaskProtection(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runResp map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runResp, jsonx.V1())) tasks := runResp["tasks"].([]any) require.Len(t, tasks, 1) taskArn := tasks[0].(map[string]any)["taskArn"].(string) @@ -657,7 +658,7 @@ func TestECS_TaskProtection(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) protectedTasks, ok := resp["protectedTasks"].([]any) require.True(t, ok) @@ -674,7 +675,7 @@ func TestECS_TaskProtection(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) protTasks, ok := getResp["protectedTasks"].([]any) require.True(t, ok) @@ -749,7 +750,7 @@ func TestECS_StartTask_WithSetup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) taskList, ok := resp["tasks"].([]any) require.True(t, ok) @@ -782,7 +783,7 @@ func TestECS_ListTasksFiltered(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns, ok := resp["taskArns"].([]any) require.True(t, ok) @@ -796,7 +797,7 @@ func TestECS_ListTasksFiltered(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) arns2, ok := resp2["taskArns"].([]any) require.True(t, ok) @@ -827,7 +828,7 @@ func TestECS_StartTask_StartedBy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, ok := resp["tasks"].([]any) require.True(t, ok) @@ -876,7 +877,7 @@ func TestECS_ListTasksFiltered_ContainerInstance(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns, ok := resp["taskArns"].([]any) require.True(t, ok) @@ -924,7 +925,7 @@ func TestExecuteCommand_RequiresFlag(t *testing.T) { require.Equal(t, http.StatusOK, runResp.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) taskArn := runOut["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) execResp := doECSRequest(t, h, "ExecuteCommand", map[string]any{ diff --git a/services/ecs/handler_task_sets_test.go b/services/ecs/handler_task_sets_test.go index 0223d97e3c..ae2b953562 100644 --- a/services/ecs/handler_task_sets_test.go +++ b/services/ecs/handler_task_sets_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -70,7 +71,7 @@ func TestTaskSet_ExternalController_CreateDescribeDelete(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) taskSet := createOut["taskSet"].(map[string]any) taskSetArn := taskSet["taskSetArn"].(string) require.NotEmpty(t, taskSetArn) @@ -85,7 +86,7 @@ func TestTaskSet_ExternalController_CreateDescribeDelete(t *testing.T) { }) require.Equal(t, http.StatusOK, describeResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &descOut, jsonx.V1())) taskSets := descOut["taskSets"].([]any) require.Len(t, taskSets, 1) @@ -131,7 +132,7 @@ func TestTaskSet_DescribeUpdateDeleteByShortID(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) taskSet := createOut["taskSet"].(map[string]any) shortID := taskSet["id"].(string) require.NotEmpty(t, shortID) @@ -145,7 +146,7 @@ func TestTaskSet_DescribeUpdateDeleteByShortID(t *testing.T) { require.Equal(t, http.StatusOK, describeResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(describeResp.Body.Bytes(), &descOut, jsonx.V1())) require.Len(t, descOut["taskSets"].([]any), 1) require.Empty(t, descOut["failures"]) @@ -191,7 +192,7 @@ func TestTaskSet_UpdateScale(t *testing.T) { }) require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) taskSetArn := createOut["taskSet"].(map[string]any)["taskSetArn"].(string) // Update scale to 100% @@ -203,7 +204,7 @@ func TestTaskSet_UpdateScale(t *testing.T) { }) require.Equal(t, http.StatusOK, updateResp.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateResp.Body.Bytes(), &updateOut, jsonx.V1())) updatedScale := updateOut["taskSet"].(map[string]any)["scale"].(map[string]any) assert.InDelta(t, float64(100), updatedScale["value"], 0.001) } @@ -235,7 +236,7 @@ func TestTaskSet_UpdateServicePrimaryTaskSet_Switch(t *testing.T) { }) require.Equal(t, http.StatusOK, resp1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(resp1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(resp1.Body.Bytes(), &out1, jsonx.V1())) taskSet1Arn := out1["taskSet"].(map[string]any)["taskSetArn"].(string) resp2 := doECSRequest(t, h, "CreateTaskSet", map[string]any{ @@ -246,7 +247,7 @@ func TestTaskSet_UpdateServicePrimaryTaskSet_Switch(t *testing.T) { }) require.Equal(t, http.StatusOK, resp2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(resp2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(resp2.Body.Bytes(), &out2, jsonx.V1())) taskSet2Arn := out2["taskSet"].(map[string]any)["taskSetArn"].(string) // Update primary task set to ts1 @@ -265,7 +266,7 @@ func TestTaskSet_UpdateServicePrimaryTaskSet_Switch(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) ts := descOut["taskSets"].([]any)[0].(map[string]any) assert.Equal(t, "PRIMARY", ts["status"]) @@ -285,7 +286,7 @@ func TestTaskSet_UpdateServicePrimaryTaskSet_Switch(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp2.Code) var descOut2 map[string]any - require.NoError(t, json.Unmarshal(descResp2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(descResp2.Body.Bytes(), &descOut2, jsonx.V1())) ts1After := descOut2["taskSets"].([]any)[0].(map[string]any) assert.NotEqual(t, "PRIMARY", ts1After["status"]) } @@ -325,7 +326,7 @@ func TestTaskSet_DescribeAll_NoFilter(t *testing.T) { }) require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["taskSets"].([]any), 3) } @@ -398,7 +399,7 @@ func TestECS_CreateTaskSet(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ts := resp["taskSet"].(map[string]any) assert.NotEmpty(t, ts["taskSetArn"]) @@ -447,7 +448,7 @@ func TestECS_DescribeTaskSets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) tsArn := createResp["taskSet"].(map[string]any)["taskSetArn"].(string) @@ -486,7 +487,7 @@ func TestECS_DescribeTaskSets(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sets := resp["taskSets"].([]any) assert.Len(t, sets, tt.wantLen) @@ -517,7 +518,7 @@ func TestECS_UpdateTaskSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) tsArn := createResp["taskSet"].(map[string]any)["taskSetArn"].(string) @@ -558,7 +559,7 @@ func TestECS_UpdateTaskSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) tsArn := createResp["taskSet"].(map[string]any)["taskSetArn"].(string) @@ -585,7 +586,7 @@ func TestECS_UpdateTaskSet(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ts := resp["taskSet"].(map[string]any) scale := ts["scale"].(map[string]any) @@ -616,7 +617,7 @@ func TestECS_DeleteTaskSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) tsArn := createResp["taskSet"].(map[string]any)["taskSetArn"].(string) @@ -670,7 +671,7 @@ func TestECS_DeleteTaskSet(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) sets, _ := resp["taskSets"].([]any) assert.Empty(t, sets) @@ -704,7 +705,7 @@ func TestECS_UpdateServicePrimaryTaskSet(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var ts1Resp map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &ts1Resp)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &ts1Resp, jsonx.V1())) ts1Arn := ts1Resp["taskSet"].(map[string]any)["taskSetArn"].(string) @@ -763,7 +764,7 @@ func TestECS_UpdateServicePrimaryTaskSet(t *testing.T) { if tt.wantPrimary { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ts := resp["taskSet"].(map[string]any) assert.Equal(t, input["_ts1Arn"], ts["taskSetArn"]) @@ -816,7 +817,7 @@ func TestTaskSet_LoadBalancers_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) ts := out["taskSet"].(map[string]any) lbs := ts["loadBalancers"].([]any) @@ -867,7 +868,7 @@ func TestTaskSet_ServiceRegistries_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) ts := out["taskSet"].(map[string]any) srs := ts["serviceRegistries"].([]any) require.Len(t, srs, 1) @@ -907,7 +908,7 @@ func TestTaskSet_DescribePreservesLBAndNC(t *testing.T) { }) require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) tsArn := createOut["taskSet"].(map[string]any)["taskSetArn"].(string) descResp := doECSRequest(t, h, "DescribeTaskSets", map[string]any{ @@ -917,7 +918,7 @@ func TestTaskSet_DescribePreservesLBAndNC(t *testing.T) { }) require.Equal(t, http.StatusOK, descResp.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &descOut, jsonx.V1())) sets := descOut["taskSets"].([]any) require.Len(t, sets, 1) ts := sets[0].(map[string]any) @@ -945,7 +946,7 @@ func TestDescribeTaskSets_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createOut, jsonx.V1())) taskSetArn := createOut["taskSet"].(map[string]any)["taskSetArn"].(string) // CreateTaskSet echoes tags unconditionally (no Include gating on Create). @@ -963,7 +964,7 @@ func TestDescribeTaskSets_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ts := resp["taskSets"].([]any)[0].(map[string]any) assert.Nil(t, ts["tags"]) }) @@ -980,7 +981,7 @@ func TestDescribeTaskSets_TagsRequireInclude(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ts := resp["taskSets"].([]any)[0].(map[string]any) tags := ts["tags"].([]any) require.Len(t, tags, 1) @@ -1010,7 +1011,7 @@ func TestCreateTaskSet_CapacityProviderStrategy_Roundtrip(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) strategy := out["taskSet"].(map[string]any)["capacityProviderStrategy"].([]any) require.Len(t, strategy, 2) } @@ -1039,7 +1040,7 @@ func TestDescribeTaskSets_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sets, _ := resp["taskSets"].([]any) assert.Empty(t, sets) @@ -1066,7 +1067,7 @@ func TestDescribeTaskSets_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) realArn := created["taskSet"].(map[string]any)["taskSetArn"].(string) rec := doECSRequest(t, h, "DescribeTaskSets", map[string]any{ @@ -1077,7 +1078,7 @@ func TestDescribeTaskSets_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sets, _ := resp["taskSets"].([]any) require.Len(t, sets, 1) diff --git a/services/ecs/handler_tasks_fields_test.go b/services/ecs/handler_tasks_fields_test.go index a03fb90b93..243eebefe4 100644 --- a/services/ecs/handler_tasks_fields_test.go +++ b/services/ecs/handler_tasks_fields_test.go @@ -1,13 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -32,7 +33,7 @@ func TestRunTask_ContainersField_Populated(t *testing.T) { require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) // Run a task. @@ -43,7 +44,7 @@ func TestRunTask_ContainersField_Populated(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code, runRec.Body.String()) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) tasks := runOut["tasks"].([]any) require.Len(t, tasks, 1) @@ -88,14 +89,14 @@ func TestRunTask_ContainersStatus_Synced_To_Running(t *testing.T) { require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) runRec := doECSRequest(t, h, "RunTask", map[string]any{"taskDefinition": tdArn}) require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) containers := task["containers"].([]any) @@ -129,14 +130,14 @@ func TestRunTask_ContainersHealthStatus_WithHealthCheck(t *testing.T) { require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) runRec := doECSRequest(t, h, "RunTask", map[string]any{"taskDefinition": tdArn}) require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) containers := task["containers"].([]any) @@ -163,7 +164,7 @@ func TestRunTask_PropagateTagsTaskDefinition(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) // Run a task with propagateTags=TASK_DEFINITION. @@ -174,7 +175,7 @@ func TestRunTask_PropagateTagsTaskDefinition(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code, runRec.Body.String()) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) tags, ok := task["tags"].([]any) @@ -205,7 +206,7 @@ func TestRunTask_PropagateTagsTaskDefinition_ExplicitTagWins(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) // Explicit tag overrides the propagated one. @@ -217,7 +218,7 @@ func TestRunTask_PropagateTagsTaskDefinition_ExplicitTagWins(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) tags := task["tags"].([]any) @@ -243,7 +244,7 @@ func TestRunTask_ECSManagedTags_Injected(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) doECSRequest(t, h, "CreateCluster", map[string]any{"clusterName": "mycluster"}) @@ -256,7 +257,7 @@ func TestRunTask_ECSManagedTags_Injected(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code, runRec.Body.String()) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) tags, ok := task["tags"].([]any) @@ -285,7 +286,7 @@ func TestRunTask_Tags_InResponse(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) runRec := doECSRequest(t, h, "RunTask", map[string]any{ @@ -295,7 +296,7 @@ func TestRunTask_Tags_InResponse(t *testing.T) { require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) task := runOut["tasks"].([]any)[0].(map[string]any) tags, ok := task["tags"].([]any) @@ -318,14 +319,14 @@ func TestDescribeTasks_ContainersField_Present(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) runRec := doECSRequest(t, h, "RunTask", map[string]any{"taskDefinition": tdArn}) require.Equal(t, http.StatusOK, runRec.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) taskArn := runOut["tasks"].([]any)[0].(map[string]any)["taskArn"].(string) // DescribeTasks must also return containers. @@ -335,7 +336,7 @@ func TestDescribeTasks_ContainersField_Present(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) tasks := descOut["tasks"].([]any) require.Len(t, tasks, 1) @@ -368,7 +369,7 @@ func TestECS_RunTask_StartedBy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, ok := resp["tasks"].([]any) require.True(t, ok) diff --git a/services/ecs/handler_tasks_test.go b/services/ecs/handler_tasks_test.go index 190ee4b97d..a4801c700e 100644 --- a/services/ecs/handler_tasks_test.go +++ b/services/ecs/handler_tasks_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -78,7 +79,7 @@ func TestECS_RunTask(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks := resp["tasks"].([]any) assert.Len(t, tasks, tt.wantLen) @@ -105,7 +106,7 @@ func TestECS_DescribeTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var runResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runResp, jsonx.V1())) taskArns := make([]string, 0, 2) for _, t := range runResp["tasks"].([]any) { @@ -117,7 +118,7 @@ func TestECS_DescribeTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2["tasks"].([]any), 2) // Describe specific task. @@ -125,7 +126,7 @@ func TestECS_DescribeTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) assert.Len(t, resp3["tasks"].([]any), 1) } @@ -161,7 +162,7 @@ func TestECS_Handler_RunTask_WithGroup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks := resp["tasks"].([]any) task := tasks[0].(map[string]any) @@ -202,7 +203,7 @@ func TestECS_Handler_DescribeTasks_NotFound(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, _ := resp["tasks"].([]any) assert.Empty(t, tasks) @@ -312,7 +313,7 @@ func TestRunTask_WithOverrides(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) require.Len(t, tasks, 1) } @@ -336,7 +337,7 @@ func TestRunTask_Count_Multiple(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) assert.Len(t, tasks, 5) @@ -365,7 +366,7 @@ func TestDescribeTasks_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, _ := resp["tasks"].([]any) assert.Empty(t, tasks) @@ -390,7 +391,7 @@ func TestDescribeTasks_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, runResp.Code) var runOut map[string]any - require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runResp.Body.Bytes(), &runOut, jsonx.V1())) tasksRaw, _ := runOut["tasks"].([]any) require.Len(t, tasksRaw, 1) taskArn := tasksRaw[0].(map[string]any)["taskArn"].(string) @@ -401,7 +402,7 @@ func TestDescribeTasks_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, _ := resp["tasks"].([]any) assert.Len(t, tasks, 1) @@ -438,7 +439,7 @@ func TestDescribeTasks_FailureSemantics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, _ := resp["tasks"].([]any) assert.Empty(t, tasks) @@ -471,7 +472,7 @@ func TestHandler_RunTask_NetworkConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) require.Len(t, tasks, 1) task := tasks[0].(map[string]any) @@ -558,7 +559,7 @@ func TestHandler_RunTask_PropagateTags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tasks := out["tasks"].([]any) require.Len(t, tasks, 1) task := tasks[0].(map[string]any) diff --git a/services/ecs/handler_test.go b/services/ecs/handler_test.go index dbcf888dda..f0fd4f007a 100644 --- a/services/ecs/handler_test.go +++ b/services/ecs/handler_test.go @@ -3,7 +3,7 @@ package ecs_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -46,7 +47,7 @@ func doECSRequest( ) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -74,7 +75,7 @@ func fakeInstanceIdentityDocument(instanceID string) string { "instanceId": instanceID, "region": testRegion, "accountId": testAccountID, - }) + }, jsonx.V1()) if err != nil { panic(err) } @@ -124,7 +125,7 @@ func registerTestTaskDef(t *testing.T, h *ecs.Handler, family string) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) } @@ -500,7 +501,7 @@ func TestConcurrent_CreateServices(t *testing.T) { "serviceName": "concurrent-svc-" + string(rune('a'+idx)), "taskDefinition": "concurrent-task", "desiredCount": 1, - }) + }, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -540,7 +541,7 @@ func TestConcurrent_RegisterContainerInstances(t *testing.T) { "instanceIdentityDocument": fakeInstanceIdentityDocument( "i-concurrent-" + string(rune('a'+idx)), ), - }) + }, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -565,7 +566,7 @@ func TestConcurrent_RegisterContainerInstances(t *testing.T) { "cluster": "concurrent-ci-cluster", }) var listOut map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listOut, jsonx.V1())) arns := listOut["containerInstanceArns"].([]any) assert.Len(t, arns, 20) } @@ -584,7 +585,7 @@ func TestHandler_Reset_ClearsAll(t *testing.T) { listResp := doECSRequest(t, h, "ListClusters", map[string]any{}) require.Equal(t, http.StatusOK, listResp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &out, jsonx.V1())) // No custom clusters after reset arns := out["clusterArns"].([]any) for _, arn := range arns { @@ -691,7 +692,7 @@ func TestHandler_Reset_ClearsCapacityProviders(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cps, ok := resp["capacityProviders"].([]any) require.True(t, ok) @@ -870,7 +871,7 @@ func TestHandler_Snapshot_Restore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cps, ok := resp["capacityProviders"].([]any) require.True(t, ok) diff --git a/services/ecs/lambda_hooks.go b/services/ecs/lambda_hooks.go index 508fa2fc27..f191d5681f 100644 --- a/services/ecs/lambda_hooks.go +++ b/services/ecs/lambda_hooks.go @@ -2,10 +2,12 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/v2" "maps" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -43,7 +45,7 @@ func parseHookResponse(resp []byte, invokeErr error) (string, time.Duration, map } var r hookResponse - if json.Unmarshal(resp, &r) != nil { + if json.Unmarshal(resp, &r, jsonx.V1()) != nil { return hookStatusFailed, 0, nil } @@ -146,7 +148,7 @@ func (inv *hookInvocation) payload() []byte { event["hookDetails"] = inv.hookDetails } - raw, _ := json.Marshal(event) + raw, _ := json.Marshal(event, jsonx.V1()) return raw } diff --git a/services/ecs/models.go b/services/ecs/models.go index 0d0c16d00b..7e6be6f796 100644 --- a/services/ecs/models.go +++ b/services/ecs/models.go @@ -1,8 +1,10 @@ package ecs import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Load balancer, logging, secrets, and volume models ---- @@ -913,7 +915,7 @@ func (c *ContainerDefinition) UnmarshalJSON(data []byte) error { type plain ContainerDefinition p := plain{Essential: true} - if err := json.Unmarshal(data, &p); err != nil { + if err := json.Unmarshal(data, &p, jsonx.V1()); err != nil { return err } diff --git a/services/ecs/multi_region_test.go b/services/ecs/multi_region_test.go index 89a98ecbda..a16d66c70d 100644 --- a/services/ecs/multi_region_test.go +++ b/services/ecs/multi_region_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -39,7 +40,7 @@ func regionCall(t *testing.T, h *ecs.Handler, region, op, body string) map[strin require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/ecs/pagination_test.go b/services/ecs/pagination_test.go index 84fd1a6dc7..1030f7cf2e 100644 --- a/services/ecs/pagination_test.go +++ b/services/ecs/pagination_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -26,7 +27,7 @@ func TestPaginationCoverage(t *testing.T) { rec := doECSRequest(t, h, "DescribeCapacityProviders", map[string]any{"maxResults": 2}) require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) cps := body["capacityProviders"].([]any) assert.Len(t, cps, 2) assert.NotEmpty(t, body["nextToken"]) @@ -40,7 +41,7 @@ func TestPaginationCoverage(t *testing.T) { } first := doECSRequest(t, h, "DescribeCapacityProviders", map[string]any{"maxResults": 2}) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) next := b1["nextToken"].(string) second := doECSRequest( @@ -51,7 +52,7 @@ func TestPaginationCoverage(t *testing.T) { ) require.Equal(t, http.StatusOK, second.Code) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) cps := b2["capacityProviders"].([]any) assert.Len(t, cps, 1) assert.Empty(t, b2["nextToken"]) @@ -75,7 +76,7 @@ func TestPaginationCoverage(t *testing.T) { rec := doECSRequest(t, h, "DescribeCapacityProviders", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["capacityProviders"].([]any), 100) assert.NotEmpty(t, body["nextToken"]) }) @@ -101,7 +102,7 @@ func TestPaginationCoverage_ListTaskDefFamilies(t *testing.T) { rec := doECSRequest(t, h, "ListTaskDefinitionFamilies", map[string]any{"maxResults": 2}) require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["families"].([]any), 2) assert.NotEmpty(t, body["nextToken"]) }) @@ -122,7 +123,7 @@ func TestPaginationCoverage_ListTaskDefFamilies(t *testing.T) { } first := doECSRequest(t, h, "ListTaskDefinitionFamilies", map[string]any{"maxResults": 2}) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) next := b1["nextToken"].(string) second := doECSRequest( t, @@ -131,7 +132,7 @@ func TestPaginationCoverage_ListTaskDefFamilies(t *testing.T) { map[string]any{"maxResults": 2, "nextToken": next}, ) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) assert.Len(t, b2["families"].([]any), 1) assert.Empty(t, b2["nextToken"]) }) @@ -159,7 +160,7 @@ func TestPaginationCoverage_ListTaskDefFamilies(t *testing.T) { map[string]any{"familyPrefix": "web", "maxResults": 1}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["families"].([]any), 1) assert.NotEmpty(t, body["nextToken"]) }, @@ -200,7 +201,7 @@ func TestPaginationCoverage_ListServices(t *testing.T) { map[string]any{"namespace": "frontend", "maxResults": 1}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["serviceArns"].([]any), 1) assert.NotEmpty(t, body["nextToken"]) }) @@ -238,7 +239,7 @@ func TestPaginationCoverage_ListServices(t *testing.T) { map[string]any{"namespace": "frontend", "maxResults": 2}, ) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) second := doECSRequest( t, h, @@ -250,7 +251,7 @@ func TestPaginationCoverage_ListServices(t *testing.T) { }, ) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) assert.Len(t, b2["serviceArns"].([]any), 1) assert.Empty(t, b2["nextToken"]) }) @@ -290,7 +291,7 @@ func TestPaginationCoverage_ListServices(t *testing.T) { map[string]any{"namespace": "frontend"}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["serviceArns"].([]any), 100) assert.NotEmpty(t, body["nextToken"]) }) @@ -326,7 +327,7 @@ func TestPaginationCoverage_ListServiceDeployments(t *testing.T) { map[string]any{"cluster": "default", "service": "svc", "maxResults": 2}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["serviceDeployments"].([]any), 2) assert.NotEmpty(t, body["nextToken"]) }) @@ -358,7 +359,7 @@ func TestPaginationCoverage_ListServiceDeployments(t *testing.T) { map[string]any{"cluster": "default", "service": "svc", "maxResults": 2}, ) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) second := doECSRequest( t, h, @@ -371,7 +372,7 @@ func TestPaginationCoverage_ListServiceDeployments(t *testing.T) { }, ) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) assert.Len(t, b2["serviceDeployments"].([]any), 1) assert.Empty(t, b2["nextToken"]) }) @@ -403,7 +404,7 @@ func TestPaginationCoverage_ListServiceDeployments(t *testing.T) { map[string]any{"cluster": "default", "service": "svc"}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["serviceDeployments"].([]any), 100) assert.NotEmpty(t, body["nextToken"]) }) @@ -425,7 +426,7 @@ func TestPaginationCoverage_ListAccountSettings(t *testing.T) { } rec := doECSRequest(t, h, "ListAccountSettings", map[string]any{"maxResults": 2}) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["settings"].([]any), 2) assert.NotEmpty(t, body["nextToken"]) }) @@ -443,7 +444,7 @@ func TestPaginationCoverage_ListAccountSettings(t *testing.T) { } first := doECSRequest(t, h, "ListAccountSettings", map[string]any{"maxResults": 2}) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) second := doECSRequest( t, h, @@ -451,7 +452,7 @@ func TestPaginationCoverage_ListAccountSettings(t *testing.T) { map[string]any{"maxResults": 2, "nextToken": b1["nextToken"].(string)}, ) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) assert.Len(t, b2["settings"].([]any), 1) assert.Empty(t, b2["nextToken"]) }) @@ -478,7 +479,7 @@ func TestPaginationCoverage_ListAccountSettings(t *testing.T) { map[string]any{"name": "containerInsights", "maxResults": 2}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["settings"].([]any), 2) assert.NotEmpty(t, body["nextToken"]) }) @@ -501,7 +502,7 @@ func TestPaginationCoverage_ListAccountSettings(t *testing.T) { } rec := doECSRequest(t, h, "ListAccountSettings", map[string]any{}) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["settings"].([]any), 100) assert.NotEmpty(t, body["nextToken"]) }) @@ -532,7 +533,7 @@ func TestPaginationCoverage_ListAttributes(t *testing.T) { } rec := doECSRequest(t, h, "ListAttributes", map[string]any{"maxResults": 2}) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["attributes"].([]any), 2) assert.NotEmpty(t, body["nextToken"]) }) @@ -559,7 +560,7 @@ func TestPaginationCoverage_ListAttributes(t *testing.T) { } first := doECSRequest(t, h, "ListAttributes", map[string]any{"maxResults": 2}) var b1 map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &b1, jsonx.V1())) second := doECSRequest( t, h, @@ -567,7 +568,7 @@ func TestPaginationCoverage_ListAttributes(t *testing.T) { map[string]any{"maxResults": 2, "nextToken": b1["nextToken"].(string)}, ) var b2 map[string]any - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b2, jsonx.V1())) assert.Len(t, b2["attributes"].([]any), 1) assert.Empty(t, b2["nextToken"]) }) @@ -599,7 +600,7 @@ func TestPaginationCoverage_ListAttributes(t *testing.T) { map[string]any{"targetType": "container-instance", "maxResults": 1}, ) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["attributes"].([]any), 1) assert.NotEmpty(t, body["nextToken"]) }) @@ -628,7 +629,7 @@ func TestPaginationCoverage_ListAttributes(t *testing.T) { } rec := doECSRequest(t, h, "ListAttributes", map[string]any{}) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Len(t, body["attributes"].([]any), 100) assert.NotEmpty(t, body["nextToken"]) }) diff --git a/services/ecs/persistence.go b/services/ecs/persistence.go index b70e6306aa..324087e7a8 100644 --- a/services/ecs/persistence.go +++ b/services/ecs/persistence.go @@ -2,7 +2,7 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -34,7 +34,7 @@ const ecsSnapshotVersion = 1 // The remaining fields are resources deliberately left as plain maps by // registerAllTables (see its exclusion list) and so are still serialised directly. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TaskDefinitions map[string][]*TaskDefinition `json:"taskDefinitions"` Attributes map[string]map[string]*Attribute `json:"attributes"` DaemonTaskDefinitions map[string][]*DaemonTaskDefinition `json:"daemonTaskDefinitions"` diff --git a/services/ecs/realism_validation_test.go b/services/ecs/realism_validation_test.go index 50b0504802..783784032e 100644 --- a/services/ecs/realism_validation_test.go +++ b/services/ecs/realism_validation_test.go @@ -1,13 +1,15 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestECSWire_InputValidation(t *testing.T) { @@ -91,7 +93,7 @@ func TestECSWire_InputValidation(t *testing.T) { } var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) assert.False(t, strings.HasPrefix(out["message"], tt.wantType), out["message"]) }) diff --git a/services/ecs/reconciler_test.go b/services/ecs/reconciler_test.go index fad1921da6..e318462307 100644 --- a/services/ecs/reconciler_test.go +++ b/services/ecs/reconciler_test.go @@ -1,11 +1,13 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestReconciler_MinimumHealthyPercent_CapsScaleDown(t *testing.T) { @@ -19,7 +21,7 @@ func TestReconciler_MinimumHealthyPercent_CapsScaleDown(t *testing.T) { }) require.Equal(t, http.StatusOK, tdRec.Code) var tdOut map[string]any - require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut)) + require.NoError(t, json.Unmarshal(tdRec.Body.Bytes(), &tdOut, jsonx.V1())) tdArn := tdOut["taskDefinition"].(map[string]any)["taskDefinitionArn"].(string) doECSRequest(t, h, "CreateCluster", map[string]any{"clusterName": "test"}) diff --git a/services/ecs/run_task_count_test.go b/services/ecs/run_task_count_test.go index 271447d7e3..b903517600 100644 --- a/services/ecs/run_task_count_test.go +++ b/services/ecs/run_task_count_test.go @@ -1,12 +1,14 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRunTaskCount(t *testing.T) { @@ -40,7 +42,7 @@ func TestRunTaskCount(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["tasks"], tt.want) }) } diff --git a/services/ecs/service_deployment_filters_test.go b/services/ecs/service_deployment_filters_test.go index 2f4f2b90d1..829840beae 100644 --- a/services/ecs/service_deployment_filters_test.go +++ b/services/ecs/service_deployment_filters_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -128,7 +129,7 @@ func TestListDaemonDeployments_CreatedAtFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) daemonArn, _ := created["daemonArn"].(string) require.NotEmpty(t, daemonArn) diff --git a/services/ecs/task_metadata.go b/services/ecs/task_metadata.go index 49cb6d019c..609ca87976 100644 --- a/services/ecs/task_metadata.go +++ b/services/ecs/task_metadata.go @@ -2,7 +2,7 @@ package ecs import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "net/http" "strconv" @@ -24,7 +24,7 @@ var ErrContainerStatsUnavailable = errors.New("container stats unavailable") // containerStatsRunner is implemented by runners that can report a container's resource stats. type containerStatsRunner interface { - ContainerStatsJSON(ctx context.Context, containerID string) (json.RawMessage, error) + ContainerStatsJSON(ctx context.Context, containerID string) (jsontext.Value, error) } type metadataLimits struct { @@ -298,7 +298,7 @@ func (b *InMemoryBackend) TaskMetadataFor(taskID string, withTags bool) (TaskMet return doc, true } -func (b *InMemoryBackend) containerStats(ctx context.Context, containerID string) (json.RawMessage, error) { +func (b *InMemoryBackend) containerStats(ctx context.Context, containerID string) (jsontext.Value, error) { r, ok := b.runner.(containerStatsRunner) if !ok { return nil, ErrContainerStatsUnavailable @@ -412,7 +412,7 @@ func (h *Handler) serveStats(c *echo.Context, bk *InMemoryBackend, containers [] ctx, cancel := context.WithTimeout(c.Request().Context(), statsTimeout) defer cancel() - all := make(map[string]json.RawMessage, len(containers)) + all := make(map[string]jsontext.Value, len(containers)) for _, cm := range containers { raw, err := bk.containerStats(ctx, cm.DockerID) diff --git a/services/ecs/task_metadata_test.go b/services/ecs/task_metadata_test.go index 26149530d9..dbea811d49 100644 --- a/services/ecs/task_metadata_test.go +++ b/services/ecs/task_metadata_test.go @@ -2,7 +2,8 @@ package ecs_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/ecs" ) @@ -45,8 +47,8 @@ func (m *metaIssuer) IssueTaskCredentials(roleArn, session string) (ecs.RoleCred type statsRunner struct{ ecs.TaskRunner } -func (statsRunner) ContainerStatsJSON(_ context.Context, id string) (json.RawMessage, error) { - return json.RawMessage(`{"id":"` + id + `","cpu_stats":{"online_cpus":2},"memory_stats":{"usage":1024}}`), nil +func (statsRunner) ContainerStatsJSON(_ context.Context, id string) (jsontext.Value, error) { + return jsontext.Value(`{"id":"` + id + `","cpu_stats":{"online_cpus":2},"memory_stats":{"usage":1024}}`), nil } type metaFixture struct { @@ -111,7 +113,7 @@ func (f *metaFixture) get(t *testing.T, path string) (int, map[string]any) { defer resp.Body.Close() var out map[string]any - _ = json.NewDecoder(resp.Body).Decode(&out) + _ = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1()) return resp.StatusCode, out } diff --git a/services/ecs/taskdef_validation.go b/services/ecs/taskdef_validation.go index c4379721e5..8980697657 100644 --- a/services/ecs/taskdef_validation.go +++ b/services/ecs/taskdef_validation.go @@ -1,11 +1,12 @@ package ecs import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -206,7 +207,7 @@ func validateNextToken(body []byte) error { NextToken string `json:"nextToken"` } - if json.Unmarshal(body, &in) == nil && in.NextToken != "" && page.ValidateToken(in.NextToken) != nil { + if json.Unmarshal(body, &in, jsonx.V1()) == nil && in.NextToken != "" && page.ValidateToken(in.NextToken) != nil { return fmt.Errorf("%w: Invalid token", ErrInvalidParameter) } diff --git a/services/ecs/undeclared_members_test.go b/services/ecs/undeclared_members_test.go index 059bde0c3b..773358428a 100644 --- a/services/ecs/undeclared_members_test.go +++ b/services/ecs/undeclared_members_test.go @@ -1,7 +1,7 @@ package ecs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ecs/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_UndeclaredMembersAbsent(t *testing.T) { @@ -63,7 +65,7 @@ func TestHandler_UndeclaredMembersAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) obj := tc.path(out) for _, a := range tc.absent { diff --git a/services/efs/file_system_policy.go b/services/efs/file_system_policy.go index cab1fb5a5f..e3e70d49ba 100644 --- a/services/efs/file_system_policy.go +++ b/services/efs/file_system_policy.go @@ -2,8 +2,10 @@ package efs import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // DescribeFileSystemPolicy returns the resource-based policy for a file system. @@ -48,7 +50,7 @@ func (b *InMemoryBackend) DeleteFileSystemPolicy(ctx context.Context, fileSystem // PutFileSystemPolicy sets the resource-based policy for a file system. // The policy must be valid JSON and no larger than 20 KB. func (b *InMemoryBackend) PutFileSystemPolicy(ctx context.Context, fileSystemID, policy string) error { - if !json.Valid([]byte(policy)) { + if !jsontext.Value([]byte(policy)).IsValid(jsonx.V1()) { return fmt.Errorf("%w: FileSystemPolicy is not valid JSON", ErrInvalidPolicy) } if len(policy) > maxFileSystemPolicyBytes { diff --git a/services/efs/handler.go b/services/efs/handler.go index ddca51aa5f..da0386fa32 100644 --- a/services/efs/handler.go +++ b/services/efs/handler.go @@ -2,7 +2,8 @@ package efs import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -13,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -455,9 +457,9 @@ func (h *Handler) Handler() echo.HandlerFunc { var body []byte if c.Request().Body != nil { - decoder := json.NewDecoder(c.Request().Body) - var raw json.RawMessage - if err := decoder.Decode(&raw); err == nil { + decoder := jsontext.NewDecoder(c.Request().Body) + var raw jsontext.Value + if err := json.UnmarshalDecode(decoder, &raw, jsonx.V1()); err == nil { body = raw } } diff --git a/services/efs/handler_access_points.go b/services/efs/handler_access_points.go index a61d58c32b..cb80abcba2 100644 --- a/services/efs/handler_access_points.go +++ b/services/efs/handler_access_points.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createAccessPointBody struct { @@ -17,7 +19,7 @@ type createAccessPointBody struct { func (h *Handler) handleCreateAccessPoint(c *echo.Context, body []byte) error { var in createAccessPointBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_access_points_test.go b/services/efs/handler_access_points_test.go index a1523b82f4..8219268a22 100644 --- a/services/efs/handler_access_points_test.go +++ b/services/efs/handler_access_points_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -261,7 +262,7 @@ func TestAccessPoint_ClientTokenIdempotency_HTTP(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) firstRec := doREST(t, h, http.MethodPost, "/2015-02-01/access-points", map[string]any{ "FileSystemId": fsOut.FileSystemID, @@ -272,7 +273,7 @@ func TestAccessPoint_ClientTokenIdempotency_HTTP(t *testing.T) { var firstOut struct { AccessPointID string `json:"AccessPointId"` } - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstOut)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstOut, jsonx.V1())) secondRec := doREST(t, h, http.MethodPost, "/2015-02-01/access-points", map[string]any{ "FileSystemId": fsOut.FileSystemID, @@ -283,7 +284,7 @@ func TestAccessPoint_ClientTokenIdempotency_HTTP(t *testing.T) { var secondOut struct { AccessPointID string `json:"AccessPointId"` } - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondOut)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondOut, jsonx.V1())) assert.Equal(t, firstOut.AccessPointID, secondOut.AccessPointID, "repeated CreateAccessPoint with same ClientToken must return the same access point") @@ -304,7 +305,7 @@ func TestDeleteAccessPoint_CleansAPIndex(t *testing.T) { require.Equal(t, http.StatusOK, apRec.Code) var apOut map[string]any - require.NoError(t, json.Unmarshal(apRec.Body.Bytes(), &apOut)) + require.NoError(t, json.Unmarshal(apRec.Body.Bytes(), &apOut, jsonx.V1())) apID := apOut["AccessPointId"].(string) blockRec := doREST(t, h, http.MethodDelete, "/2015-02-01/file-systems/"+fsID, nil) diff --git a/services/efs/handler_account_preferences.go b/services/efs/handler_account_preferences.go index f2df42b005..ccd7136e1e 100644 --- a/services/efs/handler_account_preferences.go +++ b/services/efs/handler_account_preferences.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeAccountPreferences(c *echo.Context) error { @@ -30,7 +32,7 @@ type putAccountPreferencesBody struct { func (h *Handler) handlePutAccountPreferences(c *echo.Context, body []byte) error { var in putAccountPreferencesBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_backup_policy.go b/services/efs/handler_backup_policy.go index 955a44b50f..71fc5ee336 100644 --- a/services/efs/handler_backup_policy.go +++ b/services/efs/handler_backup_policy.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeBackupPolicy(c *echo.Context, fileSystemID string) error { @@ -28,7 +30,7 @@ type putBackupPolicyBody struct { func (h *Handler) handlePutBackupPolicy(c *echo.Context, fileSystemID string, body []byte) error { var in putBackupPolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_backup_policy_test.go b/services/efs/handler_backup_policy_test.go index 6ba4997209..5a70c56594 100644 --- a/services/efs/handler_backup_policy_test.go +++ b/services/efs/handler_backup_policy_test.go @@ -1,13 +1,14 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -114,7 +115,7 @@ func TestBackupPolicy_EnabledRoundTrip(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) putRec := doREST(t, h, http.MethodPut, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/backup-policy", @@ -130,7 +131,7 @@ func TestBackupPolicy_EnabledRoundTrip(t *testing.T) { Status string `json:"Status"` } `json:"BackupPolicy"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "ENABLED", descOut.BackupPolicy.Status) } @@ -150,7 +151,7 @@ func TestBackupPolicy_InvalidStatusRejected(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rec := doREST(t, h, http.MethodPut, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/backup-policy", diff --git a/services/efs/handler_file_system_policy.go b/services/efs/handler_file_system_policy.go index f5a8e1a814..4f147b6c4e 100644 --- a/services/efs/handler_file_system_policy.go +++ b/services/efs/handler_file_system_policy.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeFileSystemPolicy(c *echo.Context, fileSystemID string) error { @@ -38,7 +40,7 @@ func (h *Handler) handlePutFileSystemPolicy( body []byte, ) error { var in putFileSystemPolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_file_system_policy_test.go b/services/efs/handler_file_system_policy_test.go index e6c340d00e..3910cdd3ee 100644 --- a/services/efs/handler_file_system_policy_test.go +++ b/services/efs/handler_file_system_policy_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -262,7 +263,7 @@ func TestFileSystemPolicy_RoundTrip(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) policy := `{"Version":"2012-10-17","Statement":[` + `{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"elasticfilesystem:ClientMount"}]}` @@ -279,7 +280,7 @@ func TestFileSystemPolicy_RoundTrip(t *testing.T) { var descOut struct { Policy string `json:"Policy"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.JSONEq(t, policy, descOut.Policy, "DescribeFileSystemPolicy must return the stored policy verbatim") diff --git a/services/efs/handler_file_systems.go b/services/efs/handler_file_systems.go index de95e45729..bcfe658f75 100644 --- a/services/efs/handler_file_systems.go +++ b/services/efs/handler_file_systems.go @@ -1,12 +1,13 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -24,7 +25,7 @@ type createFileSystemBody struct { func (h *Handler) handleCreateFileSystem(c *echo.Context, body []byte) error { var in createFileSystemBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } @@ -154,7 +155,7 @@ type updateFileSystemBody struct { func (h *Handler) handleUpdateFileSystem(c *echo.Context, fileSystemID string, body []byte) error { var in updateFileSystemBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_file_systems_test.go b/services/efs/handler_file_systems_test.go index d5bb634666..3afba87518 100644 --- a/services/efs/handler_file_systems_test.go +++ b/services/efs/handler_file_systems_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -613,7 +614,7 @@ func TestSizeInBytes_IncludesStorageClassBreakdown(t *testing.T) { var createOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) descRec := doREST(t, h, http.MethodGet, "/2015-02-01/file-systems?FileSystemId="+createOut.FileSystemID, nil) @@ -624,7 +625,7 @@ func TestSizeInBytes_IncludesStorageClassBreakdown(t *testing.T) { SizeInBytes map[string]any `json:"SizeInBytes"` } `json:"FileSystems"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.Len(t, descOut.FileSystems, 1) sib := descOut.FileSystems[0].SizeInBytes @@ -655,7 +656,7 @@ func TestDeleteFileSystem_RejectedWhenMountTargetsExist(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) mtRec := doREST(t, h, http.MethodPost, "/2015-02-01/mount-targets", map[string]any{ "FileSystemId": fsOut.FileSystemID, @@ -685,7 +686,7 @@ func TestFileSystem_CreatingToAvailableLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "creating", out["LifeCycleState"], "newly created FS should be in 'creating' state immediately after CreateFileSystem") @@ -701,7 +702,7 @@ func TestFileSystem_CreatingToAvailableLifecycle(t *testing.T) { LifeCycleState string `json:"LifeCycleState"` } `json:"FileSystems"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) require.NotEmpty(t, descOut.FileSystems) return descOut.FileSystems[0].LifeCycleState @@ -850,7 +851,7 @@ func TestDescribeFileSystems_PaginationMarker(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page fsPage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page, jsonx.V1())) require.NotEmpty(t, page.FileSystems, "page must not be empty while a marker is being followed") pageSizes = append(pageSizes, len(page.FileSystems)) diff --git a/services/efs/handler_lifecycle_config.go b/services/efs/handler_lifecycle_config.go index dd840e8b2b..f218bde313 100644 --- a/services/efs/handler_lifecycle_config.go +++ b/services/efs/handler_lifecycle_config.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putLifecycleConfigBody struct { @@ -28,7 +30,7 @@ func (h *Handler) handlePutLifecycleConfiguration( body []byte, ) error { var in putLifecycleConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_lifecycle_config_test.go b/services/efs/handler_lifecycle_config_test.go index 3e8162231c..50e7201aaa 100644 --- a/services/efs/handler_lifecycle_config_test.go +++ b/services/efs/handler_lifecycle_config_test.go @@ -1,12 +1,14 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestLifecycleConfiguration tests DescribeLifecycleConfiguration and PutLifecycleConfiguration. @@ -142,7 +144,7 @@ func TestLifecyclePolicy_InvalidTransitionRejected(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rec := doREST(t, h, http.MethodPut, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/lifecycle-configuration", diff --git a/services/efs/handler_mount_target_security_groups.go b/services/efs/handler_mount_target_security_groups.go index 3f8ab3fdfd..fd04a6dcf4 100644 --- a/services/efs/handler_mount_target_security_groups.go +++ b/services/efs/handler_mount_target_security_groups.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeMountTargetSecurityGroups( @@ -34,7 +36,7 @@ func (h *Handler) handleModifyMountTargetSecurityGroups( body []byte, ) error { var in modifyMountTargetSGBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_mount_targets.go b/services/efs/handler_mount_targets.go index 4208533d9c..b132daba17 100644 --- a/services/efs/handler_mount_targets.go +++ b/services/efs/handler_mount_targets.go @@ -1,11 +1,13 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createMountTargetBody struct { @@ -19,7 +21,7 @@ type createMountTargetBody struct { func (h *Handler) handleCreateMountTarget(c *echo.Context, body []byte) error { var in createMountTargetBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_mount_targets_test.go b/services/efs/handler_mount_targets_test.go index cf6ba7d98f..d0aa26b006 100644 --- a/services/efs/handler_mount_targets_test.go +++ b/services/efs/handler_mount_targets_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -559,7 +560,7 @@ func TestMountTarget_SecurityGroupLimitEnforced(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rec := doREST(t, h, http.MethodPost, "/2015-02-01/mount-targets", map[string]any{ "FileSystemId": fsOut.FileSystemID, @@ -589,7 +590,7 @@ func TestMountTarget_DuplicateSubnetRejected(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) firstRec := doREST(t, h, http.MethodPost, "/2015-02-01/mount-targets", map[string]any{ "FileSystemId": fsOut.FileSystemID, @@ -633,7 +634,7 @@ func TestCreateMountTarget_PopulatesVpcAndAZ(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "CreateMountTarget: %s", rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) vpcID, _ := out["VpcId"].(string) azName, _ := out["AvailabilityZoneName"].(string) @@ -666,7 +667,7 @@ func TestCreateMountTarget_VpcIDStablePerSubnet(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var mt1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &mt1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &mt1, jsonx.V1())) rec2 := doREST(t, h, http.MethodPost, "/2015-02-01/mount-targets", map[string]any{ "FileSystemId": fsID2, @@ -675,7 +676,7 @@ func TestCreateMountTarget_VpcIDStablePerSubnet(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var mt2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &mt2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &mt2, jsonx.V1())) assert.Equal(t, mt1["VpcId"], mt2["VpcId"], "same subnet should yield same VpcId across different file systems") @@ -697,7 +698,7 @@ func TestCreateMountTarget_OneZone_InheritsAZ(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fsOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fsOut, jsonx.V1())) fsID := fsOut["FileSystemId"].(string) mtRec := doREST(t, h, http.MethodPost, "/2015-02-01/mount-targets", map[string]any{ @@ -707,7 +708,7 @@ func TestCreateMountTarget_OneZone_InheritsAZ(t *testing.T) { require.Equal(t, http.StatusOK, mtRec.Code) var mt map[string]any - require.NoError(t, json.Unmarshal(mtRec.Body.Bytes(), &mt)) + require.NoError(t, json.Unmarshal(mtRec.Body.Bytes(), &mt, jsonx.V1())) assert.Equal(t, az, mt["AvailabilityZoneName"], "mount target should inherit FS AvailabilityZoneName for One Zone storage class") @@ -770,7 +771,7 @@ func TestDescribeMountTargets_Pagination_HTTP(t *testing.T) { } var pg1 mtPage - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &pg1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &pg1, jsonx.V1())) require.Len(t, pg1.MountTargets, 3) require.NotEmpty(t, pg1.NextMarker) @@ -779,7 +780,7 @@ func TestDescribeMountTargets_Pagination_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var pg2 mtPage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &pg2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &pg2, jsonx.V1())) // 5 items, pageSize=3: page1=[0,1,2] marker=items[3], page2 resumes AT items[3] => [3,4]. assert.Len(t, pg2.MountTargets, 2) assert.Empty(t, pg2.NextMarker) @@ -815,7 +816,7 @@ func TestDeleteMountTarget_CleansSubnetIndex(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var mt1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &mt1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &mt1, jsonx.V1())) mtID := mt1["MountTargetId"].(string) delRec := doREST(t, h, http.MethodDelete, "/2015-02-01/mount-targets/"+mtID, nil) diff --git a/services/efs/handler_replication.go b/services/efs/handler_replication.go index f09b965a77..4cab8409f8 100644 --- a/services/efs/handler_replication.go +++ b/services/efs/handler_replication.go @@ -1,10 +1,12 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createReplicationConfigBody struct { @@ -17,7 +19,7 @@ func (h *Handler) handleCreateReplicationConfiguration( body []byte, ) error { var in createReplicationConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } @@ -132,7 +134,7 @@ func (h *Handler) handleUpdateFileSystemProtection( body []byte, ) error { var in updateFileSystemProtectionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/handler_replication_test.go b/services/efs/handler_replication_test.go index e981e135d7..0ee5845815 100644 --- a/services/efs/handler_replication_test.go +++ b/services/efs/handler_replication_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -351,7 +352,7 @@ func TestReplicationConfiguration_SourceOwnerInResponse(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rcRec := doREST(t, h, http.MethodPost, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/replication-configuration", @@ -365,7 +366,7 @@ func TestReplicationConfiguration_SourceOwnerInResponse(t *testing.T) { var rcOut struct { SourceFileSystemOwnerID string `json:"SourceFileSystemOwnerId"` } - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut, jsonx.V1())) assert.NotEmpty(t, rcOut.SourceFileSystemOwnerID, "SourceFileSystemOwnerId must be present in CreateReplicationConfiguration response") @@ -393,7 +394,7 @@ func TestReplicationConfiguration_DestinationHasOwnerNoArn(t *testing.T) { var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rcRec := doREST(t, h, http.MethodPost, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/replication-configuration", @@ -405,7 +406,7 @@ func TestReplicationConfiguration_DestinationHasOwnerNoArn(t *testing.T) { require.Equal(t, http.StatusOK, rcRec.Code, "CreateReplicationConfiguration failed: %s", rcRec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &raw, jsonx.V1())) dests, ok := raw["Destinations"].([]any) require.True(t, ok) require.Len(t, dests, 1) @@ -420,7 +421,7 @@ func TestReplicationConfiguration_DestinationHasOwnerNoArn(t *testing.T) { Status string `json:"Status"` } `json:"Destinations"` } - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut, jsonx.V1())) require.Len(t, rcOut.Destinations, 1) d := rcOut.Destinations[0] @@ -448,7 +449,7 @@ func TestDescribeReplicationConfigurations_ByDestinationFileSystemID(t *testing. var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rcRec := doREST(t, h, http.MethodPost, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/replication-configuration", @@ -464,7 +465,7 @@ func TestDescribeReplicationConfigurations_ByDestinationFileSystemID(t *testing. FileSystemID string `json:"FileSystemId"` } `json:"Destinations"` } - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut, jsonx.V1())) require.Len(t, rcOut.Destinations, 1) destFSID := rcOut.Destinations[0].FileSystemID @@ -483,7 +484,7 @@ func TestDescribeReplicationConfigurations_ByDestinationFileSystemID(t *testing. SourceFileSystemID string `json:"SourceFileSystemId"` } `json:"Replications"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Replications, 1, "DescribeReplicationConfigurations must return result when filtering by destination FS ID") @@ -602,7 +603,7 @@ func TestCreateReplicationConfiguration_AssignsDestinationFileSystemID(t *testin var fsOut struct { FileSystemID string `json:"FileSystemId"` } - require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(fsRec.Body.Bytes(), &fsOut, jsonx.V1())) rcRec := doREST(t, h, http.MethodPost, "/2015-02-01/file-systems/"+fsOut.FileSystemID+"/replication-configuration", @@ -618,7 +619,7 @@ func TestCreateReplicationConfiguration_AssignsDestinationFileSystemID(t *testin FileSystemID string `json:"FileSystemId"` } `json:"Destinations"` } - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcOut, jsonx.V1())) require.Len(t, rcOut.Destinations, 1) assert.NotEmpty(t, rcOut.Destinations[0].FileSystemID, diff --git a/services/efs/handler_tags.go b/services/efs/handler_tags.go index 5702059043..afdbd1c8b9 100644 --- a/services/efs/handler_tags.go +++ b/services/efs/handler_tags.go @@ -1,13 +1,14 @@ package efs import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -17,7 +18,7 @@ type tagResourceBody struct { func (h *Handler) handleTagResource(c *echo.Context, resourceID string, body []byte) error { var in tagResourceBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } @@ -110,7 +111,7 @@ type createTagsBody struct { func (h *Handler) handleCreateTags(c *echo.Context, fileSystemID string, body []byte) error { var in createTagsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } @@ -128,7 +129,7 @@ type deleteTagsBody struct { func (h *Handler) handleDeleteTags(c *echo.Context, fileSystemID string, body []byte) error { var in deleteTagsBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequest", "invalid request body")) } diff --git a/services/efs/helpers_test.go b/services/efs/helpers_test.go index 9d05f6d4f5..2228963364 100644 --- a/services/efs/helpers_test.go +++ b/services/efs/helpers_test.go @@ -2,7 +2,7 @@ package efs_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -37,7 +38,7 @@ func doREST( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -58,7 +59,7 @@ func parseResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/efs/persistence.go b/services/efs/persistence.go index cbfc3f542d..8c58b6fce5 100644 --- a/services/efs/persistence.go +++ b/services/efs/persistence.go @@ -2,7 +2,7 @@ package efs import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -52,7 +52,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` LifecyclePolicies map[string]map[string][]LifecyclePolicy `json:"lifecyclePolicies"` BackupPolicies map[string]map[string]string `json:"backupPolicies"` FileSystemPolicies map[string]map[string]string `json:"fileSystemPolicies"` @@ -199,7 +199,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/efs/wire_sdk_roundtrip_test.go b/services/efs/wire_sdk_roundtrip_test.go index 7c0cd26100..a0d159ee19 100644 --- a/services/efs/wire_sdk_roundtrip_test.go +++ b/services/efs/wire_sdk_roundtrip_test.go @@ -1,7 +1,7 @@ package efs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/efs" ) @@ -91,7 +92,7 @@ func TestReplicationDestination_NoFabricatedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "CreateReplicationConfiguration failed: %s", rec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) dests, ok := raw["Destinations"].([]any) require.True(t, ok) diff --git a/services/eks/addons.go b/services/eks/addons.go index fde0c8cd77..88af4e5733 100644 --- a/services/eks/addons.go +++ b/services/eks/addons.go @@ -1,7 +1,7 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "time" @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -445,7 +446,7 @@ func (b *InMemoryBackend) DescribeAddonConfiguration(addonName, addonVersion str schema, _ := json.Marshal(map[string]any{ keyType: "object", "properties": map[string]any{}, - }) + }, jsonx.V1()) return map[string]any{ keyAddonName: addonName, diff --git a/services/eks/capability_configuration.go b/services/eks/capability_configuration.go index 4678daca59..f013a834db 100644 --- a/services/eks/capability_configuration.go +++ b/services/eks/capability_configuration.go @@ -1,6 +1,12 @@ package eks -import "encoding/json" +import ( + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // Wire-shape request/response bodies and validation/conversion for // Capability.Configuration -- gopherstack-wf8f item 1. Every field/key here @@ -424,12 +430,12 @@ func (c *Capability) UnmarshalJSON(data []byte) error { aux := struct { *capabilityAlias - Configuration json.RawMessage `json:"configuration"` + Configuration jsontext.Value `json:"configuration"` }{ capabilityAlias: (*capabilityAlias)(c), } - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -440,7 +446,7 @@ func (c *Capability) UnmarshalJSON(data []byte) error { } var cfg CapabilityConfiguration - if err := json.Unmarshal(aux.Configuration, &cfg); err == nil { + if err := json.Unmarshal(aux.Configuration, &cfg, jsonx.V1()); err == nil { c.Configuration = &cfg } diff --git a/services/eks/cluster_config_blocks.go b/services/eks/cluster_config_blocks.go index 833d07808a..08260ad311 100644 --- a/services/eks/cluster_config_blocks.go +++ b/services/eks/cluster_config_blocks.go @@ -1,27 +1,30 @@ package eks import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // clusterConfigBlocksBody holds the cluster config members stored and echoed verbatim. type clusterConfigBlocksBody struct { - ControlPlaneScalingConfig json.RawMessage `json:"controlPlaneScalingConfig"` - KubeAPIServerConfig json.RawMessage `json:"kubeApiServerConfig"` - KubeControllerManagerConfig json.RawMessage `json:"kubeControllerManagerConfig"` - KubeSchedulerConfig json.RawMessage `json:"kubeSchedulerConfig"` - OutpostConfig json.RawMessage `json:"outpostConfig"` - RemoteNetworkConfig json.RawMessage `json:"remoteNetworkConfig"` - ZonalShiftConfig json.RawMessage `json:"zonalShiftConfig"` + ControlPlaneScalingConfig jsontext.Value `json:"controlPlaneScalingConfig"` + KubeAPIServerConfig jsontext.Value `json:"kubeApiServerConfig"` + KubeControllerManagerConfig jsontext.Value `json:"kubeControllerManagerConfig"` + KubeSchedulerConfig jsontext.Value `json:"kubeSchedulerConfig"` + OutpostConfig jsontext.Value `json:"outpostConfig"` + RemoteNetworkConfig jsontext.Value `json:"remoteNetworkConfig"` + ZonalShiftConfig jsontext.Value `json:"zonalShiftConfig"` } // blocks returns the supplied members keyed by wire name; outpostConfig is create-only. -func (b clusterConfigBlocksBody) blocks(forCreate bool) map[string]json.RawMessage { - all := map[string]json.RawMessage{ +func (b clusterConfigBlocksBody) blocks(forCreate bool) map[string]jsontext.Value { + all := map[string]jsontext.Value{ "controlPlaneScalingConfig": b.ControlPlaneScalingConfig, "kubeApiServerConfig": b.KubeAPIServerConfig, "kubeControllerManagerConfig": b.KubeControllerManagerConfig, @@ -51,10 +54,10 @@ func validTiers() []string { return []string{"standard", "tier-xl", "tier-2xl", "tier-4xl", "tier-8xl"} } -func validateConfigBlocks(blocks map[string]json.RawMessage) error { +func validateConfigBlocks(blocks map[string]jsontext.Value) error { for key, raw := range blocks { - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil { return fmt.Errorf("%w: %s must be an object", ErrValidation, key) } } @@ -63,7 +66,7 @@ func validateConfigBlocks(blocks map[string]json.RawMessage) error { var cfg struct { Tier string `json:"tier"` } - _ = json.Unmarshal(raw, &cfg) + _ = json.Unmarshal(raw, &cfg, jsonx.V1()) if cfg.Tier != "" && !slices.Contains(validTiers(), cfg.Tier) { return fmt.Errorf("%w: controlPlaneScalingConfig.tier must be one of %s", @@ -89,7 +92,7 @@ func configBlockParamType(key string) string { return strings.ToUpper(key[:1]) + key[1:] } -func cloneConfigBlocks(src map[string]json.RawMessage) map[string]json.RawMessage { +func cloneConfigBlocks(src map[string]jsontext.Value) map[string]jsontext.Value { if src == nil { return nil } @@ -98,14 +101,14 @@ func cloneConfigBlocks(src map[string]json.RawMessage) map[string]json.RawMessag } // applyConfigBlocksLocked replaces the stored blocks and returns the update params. Caller holds b.mu. -func applyConfigBlocksLocked(c *Cluster, blocks map[string]json.RawMessage) []UpdateParam { +func applyConfigBlocksLocked(c *Cluster, blocks map[string]jsontext.Value) []UpdateParam { if len(blocks) == 0 { return nil } merged := cloneConfigBlocks(c.ConfigBlocks) if merged == nil { - merged = make(map[string]json.RawMessage, len(blocks)) + merged = make(map[string]jsontext.Value, len(blocks)) } var params []UpdateParam @@ -128,11 +131,11 @@ func applyConfigBlocksLocked(c *Cluster, blocks map[string]json.RawMessage) []Up return params } -func blockTier(raw json.RawMessage) string { +func blockTier(raw jsontext.Value) string { var cfg struct { Tier string `json:"tier"` } - _ = json.Unmarshal(raw, &cfg) + _ = json.Unmarshal(raw, &cfg, jsonx.V1()) return cfg.Tier } diff --git a/services/eks/cluster_options_test.go b/services/eks/cluster_options_test.go index fa8e520a93..cae5d09560 100644 --- a/services/eks/cluster_options_test.go +++ b/services/eks/cluster_options_test.go @@ -4,7 +4,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "io" "net/http" @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -405,7 +406,7 @@ func TestServePublishedPorts(t *testing.T) { HostPort int `json:"hostPort"` } `json:"ports"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "c1", body.ClusterName) require.Len(t, body.Ports, tt.wantPorts) assert.Equal(t, 8080, body.Ports[0].ContainerPort) diff --git a/services/eks/clusters.go b/services/eks/clusters.go index 9dbb787b08..4f0b334d49 100644 --- a/services/eks/clusters.go +++ b/services/eks/clusters.go @@ -2,7 +2,7 @@ package eks import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "strings" @@ -21,7 +21,7 @@ type ClusterOptionalConfig struct { AccessConfig *AccessConfig ComputeConfig *ComputeConfig StorageConfig *StorageConfig - ConfigBlocks map[string]json.RawMessage + ConfigBlocks map[string]jsontext.Value UpgradePolicySupportType string CreatorARN string LogEntries []ClusterLogEntry diff --git a/services/eks/clusters_test.go b/services/eks/clusters_test.go index 7d5addd1d3..8a7d959f39 100644 --- a/services/eks/clusters_test.go +++ b/services/eks/clusters_test.go @@ -1,7 +1,7 @@ package eks_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -231,7 +232,7 @@ func TestVpcConfig_HandlerJSON_Fields(t *testing.T) { rec := doREST(t, h, http.MethodGet, "/clusters/c1", nil) body := rec.Body.Bytes() var raw map[string]any - require.NoError(t, json.Unmarshal(body, &raw)) + require.NoError(t, json.Unmarshal(body, &raw, jsonx.V1())) cluster := raw["cluster"].(map[string]any) vpc := cluster["resourcesVpcConfig"].(map[string]any) @@ -748,11 +749,11 @@ func TestSortedListClusters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) resp := parseResp(t, rec) - raw, err := json.Marshal(resp["clusters"]) + raw, err := json.Marshal(resp["clusters"], jsonx.V1()) require.NoError(t, err) var names []string - require.NoError(t, json.Unmarshal(raw, &names)) + require.NoError(t, json.Unmarshal(raw, &names, jsonx.V1())) require.Equal(t, []string{"aaa", "bbb", "mmm", "zzz"}, names) } diff --git a/services/eks/handler.go b/services/eks/handler.go index ab446700ec..29d52702a1 100644 --- a/services/eks/handler.go +++ b/services/eks/handler.go @@ -1,7 +1,8 @@ package eks import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -10,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -539,9 +541,9 @@ func (h *Handler) Handler() echo.HandlerFunc { var body []byte if c.Request().Body != nil { - decoder := json.NewDecoder(c.Request().Body) - var raw json.RawMessage - if err := decoder.Decode(&raw); err == nil { + decoder := jsontext.NewDecoder(c.Request().Body) + var raw jsontext.Value + if err := json.UnmarshalDecode(decoder, &raw, jsonx.V1()); err == nil { body = raw } } diff --git a/services/eks/handler_access_entries.go b/services/eks/handler_access_entries.go index 23fc3bb7bc..f4abf78bac 100644 --- a/services/eks/handler_access_entries.go +++ b/services/eks/handler_access_entries.go @@ -1,13 +1,14 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -146,7 +147,7 @@ type createAccessEntryBody struct { func (h *Handler) handleCreateAccessEntry(c *echo.Context, clusterName string, body []byte) error { var in createAccessEntryBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -224,7 +225,7 @@ type updateAccessEntryBody struct { func (h *Handler) handleUpdateAccessEntry(c *echo.Context, clusterName, principalARN string, body []byte) error { var in updateAccessEntryBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } @@ -248,7 +249,7 @@ type associateAccessPolicyBody struct { func (h *Handler) handleAssociateAccessPolicy(c *echo.Context, clusterName, principalARN string, body []byte) error { var in associateAccessPolicyBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } diff --git a/services/eks/handler_addons.go b/services/eks/handler_addons.go index f815cb8cf0..bbc628d2a6 100644 --- a/services/eks/handler_addons.go +++ b/services/eks/handler_addons.go @@ -1,7 +1,7 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "slices" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -147,7 +148,7 @@ type createAddonBody struct { func (h *Handler) handleCreateAddon(c *echo.Context, clusterName string, body []byte) error { var in createAddonBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -234,7 +235,7 @@ type updateAddonBody struct { func (h *Handler) handleUpdateAddon(c *echo.Context, clusterName, addonName string, body []byte) error { var in updateAddonBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_capabilities.go b/services/eks/handler_capabilities.go index 23507d9aeb..ccf684ff88 100644 --- a/services/eks/handler_capabilities.go +++ b/services/eks/handler_capabilities.go @@ -1,11 +1,12 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -147,7 +148,7 @@ type createCapabilityBody struct { func (h *Handler) handleCreateCapability(c *echo.Context, clusterName string, body []byte) error { var in createCapabilityBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -233,7 +234,7 @@ type updateCapabilityBody struct { func (h *Handler) handleUpdateCapability(c *echo.Context, clusterName, capabilityName string, body []byte) error { var in updateCapabilityBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_certificate_authorities.go b/services/eks/handler_certificate_authorities.go index 66e6d3c04e..44081b6c4f 100644 --- a/services/eks/handler_certificate_authorities.go +++ b/services/eks/handler_certificate_authorities.go @@ -1,12 +1,13 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -134,7 +135,7 @@ func certificateAuthorityIdempotencyFingerprintBody(clusterName, id string) []by payload["certificateAuthorityId"] = id } - raw, err := json.Marshal(payload) + raw, err := json.Marshal(payload, jsonx.V1()) if err != nil { return nil } @@ -149,7 +150,7 @@ type createCertificateAuthorityBody struct { func (h *Handler) handleCreateCertificateAuthority(c *echo.Context, clusterName string, body []byte) error { var in createCertificateAuthorityBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } } @@ -176,7 +177,7 @@ type activateCertificateAuthorityBody struct { func (h *Handler) handleActivateCertificateAuthority(c *echo.Context, clusterName, id string, body []byte) error { var in activateCertificateAuthorityBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } } diff --git a/services/eks/handler_clusters.go b/services/eks/handler_clusters.go index a884273d74..c4cebac5ba 100644 --- a/services/eks/handler_clusters.go +++ b/services/eks/handler_clusters.go @@ -1,7 +1,7 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "slices" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -302,7 +303,7 @@ type createClusterBody struct { func (h *Handler) handleCreateCluster(c *echo.Context, body []byte) error { var in createClusterBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -349,7 +350,7 @@ func (h *Handler) handleCreateCluster(c *echo.Context, body []byte) error { netCfg = withNetworkDefaults(netCfg) var blocksIn clusterConfigBlocksBody - _ = json.Unmarshal(body, &blocksIn) + _ = json.Unmarshal(body, &blocksIn, jsonx.V1()) opt := buildClusterOptConfig(in) opt.CreatorARN = awsmeta.CallerArn(c.Request().Context()) @@ -476,7 +477,7 @@ type registerClusterBody struct { func (h *Handler) handleRegisterCluster(c *echo.Context, body []byte) error { var in registerClusterBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } diff --git a/services/eks/handler_fargate_profiles.go b/services/eks/handler_fargate_profiles.go index 0b9c3d4708..da2ad862ad 100644 --- a/services/eks/handler_fargate_profiles.go +++ b/services/eks/handler_fargate_profiles.go @@ -1,11 +1,12 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -102,7 +103,7 @@ type createFargateProfileBody struct { func (h *Handler) handleCreateFargateProfile(c *echo.Context, clusterName string, body []byte) error { var in createFargateProfileBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } diff --git a/services/eks/handler_identity_providers.go b/services/eks/handler_identity_providers.go index 71ee2752c3..377dc17877 100644 --- a/services/eks/handler_identity_providers.go +++ b/services/eks/handler_identity_providers.go @@ -1,12 +1,13 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -84,7 +85,7 @@ type associateIdentityProviderConfigBody struct { func (h *Handler) handleAssociateIdentityProviderConfig(c *echo.Context, clusterName string, body []byte) error { var in associateIdentityProviderConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -163,7 +164,7 @@ type describeIDPRequestBody struct { func (h *Handler) handleDescribeIdentityProviderConfig(c *echo.Context, clusterName string, body []byte) error { var in describeIDPRequestBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } @@ -233,7 +234,7 @@ type disassociateIDPBody struct { func (h *Handler) handleDisassociateIdentityProviderConfig(c *echo.Context, clusterName string, body []byte) error { var in disassociateIDPBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_insights.go b/services/eks/handler_insights.go index c1dfe454d2..470bfa5b9b 100644 --- a/services/eks/handler_insights.go +++ b/services/eks/handler_insights.go @@ -1,12 +1,13 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -102,7 +103,7 @@ func (h *Handler) handleListInsights(c *echo.Context, clusterName string, body [ // A malformed body is tolerated (ListInsights' filter/pagination // fields are all optional) rather than rejected, matching the // permissive parsing used by every other optional-body op here. - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } if in.Filter != nil { diff --git a/services/eks/handler_irsa.go b/services/eks/handler_irsa.go index af9ddb616a..7674d1accd 100644 --- a/services/eks/handler_irsa.go +++ b/services/eks/handler_irsa.go @@ -1,7 +1,8 @@ package eks import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "time" @@ -9,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -111,7 +113,7 @@ func (h *Handler) serveMintToken(c *echo.Context, cluster string) error { var in serviceAccountTokenBody if c.Request().Body != nil { - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return h.handleError(c, errMsgf(ErrValidation, "invalid request body")) } } diff --git a/services/eks/handler_node_groups.go b/services/eks/handler_node_groups.go index 70ce993eab..fe936ddef5 100644 --- a/services/eks/handler_node_groups.go +++ b/services/eks/handler_node_groups.go @@ -1,7 +1,7 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -294,7 +295,7 @@ type createNodegroupBody struct { func (h *Handler) handleCreateNodegroup(c *echo.Context, clusterName string, body []byte) error { var in createNodegroupBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -448,7 +449,7 @@ func (h *Handler) handleUpdateNodegroupConfig( ) error { var in updateNodegroupConfigInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } @@ -524,7 +525,7 @@ type updateNodegroupVersionBody struct { func (h *Handler) handleUpdateNodegroupVersion(c *echo.Context, clusterName, nodegroupName string, body []byte) error { var in updateNodegroupVersionBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_pod_identity.go b/services/eks/handler_pod_identity.go index 604ea36023..6b4e800545 100644 --- a/services/eks/handler_pod_identity.go +++ b/services/eks/handler_pod_identity.go @@ -1,12 +1,13 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -138,7 +139,7 @@ type createPodIdentityAssociationBody struct { func (h *Handler) handleCreatePodIdentityAssociation(c *echo.Context, clusterName string, body []byte) error { var in createPodIdentityAssociationBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -232,7 +233,7 @@ type updatePodIdentityBody struct { func (h *Handler) handleUpdatePodIdentityAssociation(c *echo.Context, clusterName, assocID string, body []byte) error { var in updatePodIdentityBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_subscriptions.go b/services/eks/handler_subscriptions.go index b3144c682b..b8b787eb32 100644 --- a/services/eks/handler_subscriptions.go +++ b/services/eks/handler_subscriptions.go @@ -1,7 +1,7 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "slices" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -144,7 +145,7 @@ func validateSubscriptionTerm(t *subscriptionTermJSON) error { func (h *Handler) handleCreateEksAnywhereSubscription(c *echo.Context, body []byte) error { var in createEksAnywhereSubscriptionBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -227,7 +228,7 @@ type updateSubscriptionBody struct { func (h *Handler) handleUpdateEksAnywhereSubscription(c *echo.Context, id string, body []byte) error { var in updateSubscriptionBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/handler_tags.go b/services/eks/handler_tags.go index f86e83b335..99e01cdb49 100644 --- a/services/eks/handler_tags.go +++ b/services/eks/handler_tags.go @@ -1,11 +1,13 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dispatchTagOps handles the generic ARN-based tag operations. @@ -62,7 +64,7 @@ type tagResourceBody struct { func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body []byte) error { var in tagResourceBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("BadRequestException", "invalid request body")) } diff --git a/services/eks/handler_test.go b/services/eks/handler_test.go index ac3549e183..f8ef960e42 100644 --- a/services/eks/handler_test.go +++ b/services/eks/handler_test.go @@ -2,7 +2,7 @@ package eks_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -50,7 +51,7 @@ func doREST( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -70,7 +71,7 @@ func parseResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/eks/handler_updates.go b/services/eks/handler_updates.go index f3d3e2cb13..54042d33be 100644 --- a/services/eks/handler_updates.go +++ b/services/eks/handler_updates.go @@ -1,13 +1,14 @@ package eks import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -84,7 +85,7 @@ type associateEncryptionConfigBody struct { func (h *Handler) handleAssociateEncryptionConfig(c *echo.Context, clusterName string, body []byte) error { var in associateEncryptionConfigBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", "invalid request body")) } @@ -149,7 +150,7 @@ func (h *Handler) handleUpdateClusterConfig(c *echo.Context, clusterName string, var in updateClusterConfigBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } @@ -157,7 +158,7 @@ func (h *Handler) handleUpdateClusterConfig(c *echo.Context, clusterName string, cfgUpd := buildClusterConfigUpdate(in) var blocksIn clusterConfigBlocksBody - _ = json.Unmarshal(body, &blocksIn) + _ = json.Unmarshal(body, &blocksIn, jsonx.V1()) cfgUpd.ConfigBlocks = blocksIn.blocks(false) return h.withIdempotency(c, opUpdateClusterConfig, in.ClientRequestToken, body, func() (int, any, error) { @@ -270,7 +271,7 @@ type updateClusterVersionBody struct { func (h *Handler) handleUpdateClusterVersion(c *echo.Context, clusterName string, body []byte) error { var in updateClusterVersionBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } @@ -369,7 +370,7 @@ type cancelUpdateBody struct { func (h *Handler) handleCancelUpdate(c *echo.Context, clusterName, updateID string, body []byte) error { var in cancelUpdateBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("InvalidParameterException", err.Error())) } } diff --git a/services/eks/idempotency.go b/services/eks/idempotency.go index e59e5f7569..50645f93a5 100644 --- a/services/eks/idempotency.go +++ b/services/eks/idempotency.go @@ -3,12 +3,14 @@ package eks import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -39,12 +41,12 @@ const idempotencyTokenTTL = 24 * time.Hour const maxIdempotencyRecords = 1024 type idempotencyRecord struct { - CreatedAt time.Time `json:"createdAt"` - Op string `json:"op"` - Token string `json:"token"` - Fingerprint string `json:"fingerprint"` - Body json.RawMessage `json:"body"` - StatusCode int `json:"statusCode"` + CreatedAt time.Time `json:"createdAt"` + Op string `json:"op"` + Token string `json:"token"` + Fingerprint string `json:"fingerprint"` + Body jsontext.Value `json:"body"` + StatusCode int `json:"statusCode"` } func idempotencyKey(op, token string) string { return op + "\x00" + token } @@ -59,7 +61,7 @@ func idempotencyKeyFn(v *idempotencyRecord) string { return idempotencyKey(v.Op, // byte-identically. func idempotencyFingerprint(reqBody []byte) string { var v map[string]any - if err := json.Unmarshal(reqBody, &v); err != nil { + if err := json.Unmarshal(reqBody, &v, jsonx.V1()); err != nil { sum := sha256.Sum256(reqBody) return hex.EncodeToString(sum[:]) @@ -67,7 +69,7 @@ func idempotencyFingerprint(reqBody []byte) string { delete(v, "clientRequestToken") - canon, err := json.Marshal(v) + canon, err := json.Marshal(v, jsonx.V1()) if err != nil { canon = reqBody } @@ -100,7 +102,7 @@ func idempotencyExpired(rec *idempotencyRecord, now time.Time) bool { } // storeIdempotency records a successful (2xx) response for later replay. -func (b *InMemoryBackend) storeIdempotency(op, token, fingerprint string, statusCode int, body json.RawMessage) { +func (b *InMemoryBackend) storeIdempotency(op, token, fingerprint string, statusCode int, body jsontext.Value) { b.mu.Lock("storeIdempotency") defer b.mu.Unlock() @@ -158,7 +160,7 @@ func (h *Handler) withIdempotency( } var body any - if err := json.Unmarshal(rec.Body, &body); err != nil { + if err := json.Unmarshal(rec.Body, &body, jsonx.V1()); err != nil { return c.JSON(http.StatusInternalServerError, errResp("InternalFailure", err.Error())) } @@ -171,7 +173,7 @@ func (h *Handler) withIdempotency( } if status >= http.StatusOK && status < http.StatusMultipleChoices { - if raw, mErr := json.Marshal(body); mErr == nil { + if raw, mErr := json.Marshal(body, jsonx.V1()); mErr == nil { h.Backend.storeIdempotency(op, token, fp, status, raw) } } diff --git a/services/eks/irsa.go b/services/eks/irsa.go index fada781d57..dd74360fac 100644 --- a/services/eks/irsa.go +++ b/services/eks/irsa.go @@ -5,7 +5,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "math/big" "slices" @@ -13,6 +13,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -284,12 +286,12 @@ func serviceAccountClaims(issuer string, req ServiceAccountTokenRequest, now, ex } func signServiceAccountJWT(key *rsa.PrivateKey, claims map[string]any) (string, error) { - hdr, err := json.Marshal(map[string]string{"alg": jwtAlgRS256, "kid": irsaKeyID(&key.PublicKey)}) + hdr, err := json.Marshal(map[string]string{"alg": jwtAlgRS256, "kid": irsaKeyID(&key.PublicKey)}, jsonx.V1()) if err != nil { return "", err } - body, err := json.Marshal(claims) + body, err := json.Marshal(claims, jsonx.V1()) if err != nil { return "", err } diff --git a/services/eks/irsa_test.go b/services/eks/irsa_test.go index ea7040d5c6..84889d4592 100644 --- a/services/eks/irsa_test.go +++ b/services/eks/irsa_test.go @@ -5,7 +5,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "math/big" "net/http" "net/http/httptest" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -34,7 +35,7 @@ func jwtParts(t *testing.T, token string) (map[string]any, map[string]any, []byt for i, dst := range []*map[string]any{&hdr, &claims} { raw, err := base64.RawURLEncoding.DecodeString(parts[i]) require.NoError(t, err) - require.NoError(t, json.Unmarshal(raw, dst)) + require.NoError(t, json.Unmarshal(raw, dst, jsonx.V1())) } sig, err := base64.RawURLEncoding.DecodeString(parts[2]) @@ -301,7 +302,7 @@ func TestOIDCEndpoints(t *testing.T) { if tt.wantKey != "" { var doc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1())) assert.Contains(t, doc, tt.wantKey) } }) diff --git a/services/eks/k8s_api.go b/services/eks/k8s_api.go index df399162f7..e4d6310468 100644 --- a/services/eks/k8s_api.go +++ b/services/eks/k8s_api.go @@ -5,13 +5,15 @@ import ( "context" "crypto/tls" "crypto/x509" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" "net/http" "net/url" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -111,7 +113,7 @@ func (a *k8sAPI) getJSON(ctx context.Context, path string, out any) error { return err } - if err = json.Unmarshal(raw, out); err != nil { + if err = json.Unmarshal(raw, out, jsonx.V1()); err != nil { return fmt.Errorf("decode %s: %w", path, err) } @@ -120,7 +122,7 @@ func (a *k8sAPI) getJSON(ctx context.Context, path string, out any) error { // apply server-side-applies obj (JSON is valid YAML) at path, forcing field ownership. func (a *k8sAPI) apply(ctx context.Context, path string, obj any) error { - raw, err := json.Marshal(obj) + raw, err := json.Marshal(obj, jsonx.V1()) if err != nil { return fmt.Errorf("encode %s: %w", path, err) } @@ -132,7 +134,7 @@ func (a *k8sAPI) apply(ctx context.Context, path string, obj any) error { } func (a *k8sAPI) mergePatch(ctx context.Context, path string, patch any) error { - raw, err := json.Marshal(patch) + raw, err := json.Marshal(patch, jsonx.V1()) if err != nil { return fmt.Errorf("encode %s: %w", path, err) } diff --git a/services/eks/k8s_proxy.go b/services/eks/k8s_proxy.go index b767fb5b34..2329ee1de9 100644 --- a/services/eks/k8s_proxy.go +++ b/services/eks/k8s_proxy.go @@ -9,7 +9,8 @@ import ( "crypto/tls" "crypto/x509" "crypto/x509/pkix" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "errors" "fmt" @@ -24,6 +25,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -188,7 +190,7 @@ func (p *k8sProxy) close() { _ = p.srv.Close() } func writeK8sStatus(w http.ResponseWriter, code int, reason string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - _ = json.NewEncoder(w).Encode(map[string]any{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{ keyKind: "Status", keyAPIVersion: "v1", "status": "Failure", keyMessage: reason, "reason": reason, keyCode: code, }) diff --git a/services/eks/k8s_reconcile_internal_test.go b/services/eks/k8s_reconcile_internal_test.go index 965146dc18..58766a901e 100644 --- a/services/eks/k8s_reconcile_internal_test.go +++ b/services/eks/k8s_reconcile_internal_test.go @@ -2,7 +2,8 @@ package eks import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const rbacPrefix = "/apis/rbac.authorization.k8s.io/v1/" @@ -125,7 +127,7 @@ func (f *fakeK8s) listBindings(set map[string]bool, nsMode string) map[string]an func writeJSON(w http.ResponseWriter, v any) { w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(v) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), v) } // engineRuntime records containers and registers a node in the fake API for every agent started. diff --git a/services/eks/models.go b/services/eks/models.go index 2981183033..50dc3bd263 100644 --- a/services/eks/models.go +++ b/services/eks/models.go @@ -1,10 +1,12 @@ package eks import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -148,7 +150,7 @@ func (a activationExpiry) Time() time.Time { return time.Time(a) } func (a activationExpiry) IsZero() bool { return time.Time(a).IsZero() } func (a activationExpiry) MarshalJSON() ([]byte, error) { - return json.Marshal(time.Time(a)) + return json.Marshal(time.Time(a), jsonx.V1()) } func (a *activationExpiry) UnmarshalJSON(data []byte) error { @@ -157,14 +159,14 @@ func (a *activationExpiry) UnmarshalJSON(data []byte) error { } var t time.Time - if err := json.Unmarshal(data, &t); err == nil { + if err := json.Unmarshal(data, &t, jsonx.V1()); err == nil { *a = activationExpiry(t) return nil } var epochSeconds float64 - if err := json.Unmarshal(data, &epochSeconds); err != nil { + if err := json.Unmarshal(data, &epochSeconds, jsonx.V1()); err != nil { return fmt.Errorf("activationExpiry: unsupported JSON value %s: %w", data, err) } @@ -201,23 +203,23 @@ type Cluster struct { StorageConfig *StorageConfig `json:"storageConfig,omitempty"` ConnectorConfig *ConnectorConfig `json:"connectorConfig,omitempty"` // ConfigBlocks holds the opaque create/update config members keyed by wire name. - ConfigBlocks map[string]json.RawMessage `json:"configBlocks,omitempty"` - ARN string `json:"arn"` - Name string `json:"name"` - Endpoint string `json:"endpoint,omitempty"` - OIDCIssuer string `json:"oidcIssuer,omitempty"` - Version string `json:"version"` - Status string `json:"status"` - RoleARN string `json:"roleArn,omitempty"` - AccountID string `json:"accountId"` - Region string `json:"region"` - PlatformVersion string `json:"platformVersion,omitempty"` - CreatorARN string `json:"creatorArn,omitempty"` - CertificateAuthority string `json:"certificateAuthority,omitempty"` - UpgradePolicySupportType string `json:"upgradePolicySupportType,omitempty"` - ClusterLogging []ClusterLogEntry `json:"clusterLogging,omitempty"` - EncryptionConfig []EncryptionConfig `json:"encryptionConfig,omitempty"` - DeletionProtection bool `json:"deletionProtection,omitempty"` + ConfigBlocks map[string]jsontext.Value `json:"configBlocks,omitempty"` + ARN string `json:"arn"` + Name string `json:"name"` + Endpoint string `json:"endpoint,omitempty"` + OIDCIssuer string `json:"oidcIssuer,omitempty"` + Version string `json:"version"` + Status string `json:"status"` + RoleARN string `json:"roleArn,omitempty"` + AccountID string `json:"accountId"` + Region string `json:"region"` + PlatformVersion string `json:"platformVersion,omitempty"` + CreatorARN string `json:"creatorArn,omitempty"` + CertificateAuthority string `json:"certificateAuthority,omitempty"` + UpgradePolicySupportType string `json:"upgradePolicySupportType,omitempty"` + ClusterLogging []ClusterLogEntry `json:"clusterLogging,omitempty"` + EncryptionConfig []EncryptionConfig `json:"encryptionConfig,omitempty"` + DeletionProtection bool `json:"deletionProtection,omitempty"` } // NodegroupTaint represents a Kubernetes taint applied to managed nodes. diff --git a/services/eks/multi_region_test.go b/services/eks/multi_region_test.go index b8aabb515d..a532b948c6 100644 --- a/services/eks/multi_region_test.go +++ b/services/eks/multi_region_test.go @@ -1,7 +1,8 @@ package eks_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -41,7 +43,7 @@ func regionCall(t *testing.T, h *eks.Handler, region, method, path, body string) out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out @@ -130,9 +132,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/eks/node_groups_test.go b/services/eks/node_groups_test.go index 20e9fa9097..70889e0772 100644 --- a/services/eks/node_groups_test.go +++ b/services/eks/node_groups_test.go @@ -1,7 +1,7 @@ package eks_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -975,11 +976,11 @@ func TestSortedListNodegroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) resp := parseResp(t, rec) - raw, err := json.Marshal(resp["nodegroups"]) + raw, err := json.Marshal(resp["nodegroups"], jsonx.V1()) require.NoError(t, err) var names []string - require.NoError(t, json.Unmarshal(raw, &names)) + require.NoError(t, json.Unmarshal(raw, &names, jsonx.V1())) require.Equal(t, []string{"aaa", "mmm", "zzz"}, names) } diff --git a/services/eks/persistence.go b/services/eks/persistence.go index 8a87bdb81d..1ca5a7c70a 100644 --- a/services/eks/persistence.go +++ b/services/eks/persistence.go @@ -2,9 +2,11 @@ package eks import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -50,7 +52,7 @@ import ( const eksSnapshotVersion = 2 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` AccessPolicies map[string]map[string][]*AccessPolicyAssociation `json:"accessPolicies,omitempty"` EncryptionConfigs map[string][]EncryptionConfig `json:"encryptionConfigs,omitempty"` AccountID string `json:"accountId"` @@ -79,7 +81,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "eks: Snapshot marshal failed", "error", err) diff --git a/services/eks/pod_identity_auth.go b/services/eks/pod_identity_auth.go index 1941656df9..62c83aed9b 100644 --- a/services/eks/pod_identity_auth.go +++ b/services/eks/pod_identity_auth.go @@ -5,7 +5,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "slices" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -124,7 +125,7 @@ type audience []string func (a *audience) UnmarshalJSON(raw []byte) error { var one string - if json.Unmarshal(raw, &one) == nil { + if json.Unmarshal(raw, &one, jsonx.V1()) == nil { *a = audience{one} return nil @@ -132,7 +133,7 @@ func (a *audience) UnmarshalJSON(raw []byte) error { var many []string - if err := json.Unmarshal(raw, &many); err != nil { + if err := json.Unmarshal(raw, &many, jsonx.V1()); err != nil { return err } @@ -163,7 +164,7 @@ func verifyPodIdentityToken(token, issuer string, pub *rsa.PublicKey, now time.T } var c podIdentityClaims - if json.Unmarshal(raw, &c) != nil { + if json.Unmarshal(raw, &c, jsonx.V1()) != nil { return nil, errMsgf(ErrInvalidToken, "The token payload is malformed.") } @@ -309,7 +310,7 @@ func (h *Handler) handleAssumeRoleForPodIdentity(c *echo.Context, clusterName st Token string `json:"token"` } - if err := json.Unmarshal(body, &in); err != nil || in.Token == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Token == "" { return h.handleError(c, errMsgf(ErrValidation, "token is required.")) } diff --git a/services/eks/updates.go b/services/eks/updates.go index cf447837bf..45cee74ef9 100644 --- a/services/eks/updates.go +++ b/services/eks/updates.go @@ -1,7 +1,8 @@ package eks import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" @@ -10,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // updateTransitionDelay is the async delay before an InProgress Update reaches @@ -81,7 +83,7 @@ func (b *InMemoryBackend) AssociateEncryptionConfig( result := make([]EncryptionConfig, len(stored)) copy(result, stored) - encryptionConfigJSON, err := json.Marshal(result) + encryptionConfigJSON, err := json.Marshal(result, jsonx.V1()) if err != nil { return nil, nil, fmt.Errorf("marshal encryption config: %w", err) } @@ -111,7 +113,7 @@ type ClusterConfigUpdate struct { ComputeConfig *ComputeConfig StorageConfig *StorageConfig // ConfigBlocks are the opaque config members, keyed by wire name. - ConfigBlocks map[string]json.RawMessage + ConfigBlocks map[string]jsontext.Value DeletionProtection *bool ElasticLoadBalancing *bool UpgradeSupportType string diff --git a/services/eks/updates_test.go b/services/eks/updates_test.go index e8719f8c76..e482ca5e55 100644 --- a/services/eks/updates_test.go +++ b/services/eks/updates_test.go @@ -1,7 +1,7 @@ package eks_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eks" ) @@ -624,7 +625,7 @@ func TestLogging_HTTP_AllTypes_In_Response(t *testing.T) { rec2 := doREST(t, h, http.MethodGet, "/clusters/logging-http-all", nil) cluster := parseClusterResp(t, rec2) - raw, _ := json.Marshal(cluster) + raw, _ := json.Marshal(cluster, jsonx.V1()) body := string(raw) for _, lt := range []string{"api", "audit", "authenticator", "controllerManager", "scheduler"} { diff --git a/services/elasticache/persistence.go b/services/elasticache/persistence.go index 4da5251368..14ff8c6d85 100644 --- a/services/elasticache/persistence.go +++ b/services/elasticache/persistence.go @@ -2,7 +2,7 @@ package elasticache import ( "context" - "encoding/json" + "encoding/json/jsontext" "time" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -66,7 +66,7 @@ type clusterSnapshot struct { // directly below as region -> that table's own deterministic // [store.Table.Snapshot] slice. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Clusters map[string][]*clusterSnapshot `json:"clusters"` ReplicationGroups map[string][]*ReplicationGroup `json:"replicationGroups"` ParameterGroups map[string][]*CacheParameterGroup `json:"parameterGroups"` diff --git a/services/elasticache/persistence_test.go b/services/elasticache/persistence_test.go index 9547503578..5b3ba830b9 100644 --- a/services/elasticache/persistence_test.go +++ b/services/elasticache/persistence_test.go @@ -2,12 +2,13 @@ package elasticache_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elasticache" ) @@ -205,10 +206,10 @@ func TestInMemoryBackend_Restore_IncompatibleVersion(t *testing.T) { // current elasticacheSnapshotVersion constant. var raw map[string]any - require.NoError(t, json.Unmarshal(original.Snapshot(ctx), &raw)) + require.NoError(t, json.Unmarshal(original.Snapshot(ctx), &raw, jsonx.V1())) raw["version"] = -1 - badSnap, err := json.Marshal(raw) + badSnap, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) fresh := elasticache.NewInMemoryBackend("redis", "000000000000", "us-east-1", nil) diff --git a/services/elasticbeanstalk/persistence.go b/services/elasticbeanstalk/persistence.go index 1cf141771a..bcd449b678 100644 --- a/services/elasticbeanstalk/persistence.go +++ b/services/elasticbeanstalk/persistence.go @@ -2,7 +2,7 @@ package elasticbeanstalk import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -53,7 +53,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ManagedActionHistory map[string]map[string][]*ManagedActionHistory `json:"managedActionHistory,omitempty"` Events map[string][]*EventRecord `json:"events,omitempty"` DeletedEnvironments map[string][]*Environment `json:"deletedEnvironments,omitempty"` @@ -243,7 +243,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/elasticbeanstalk/store_test.go b/services/elasticbeanstalk/store_test.go index 1ac070a850..308a14265a 100644 --- a/services/elasticbeanstalk/store_test.go +++ b/services/elasticbeanstalk/store_test.go @@ -2,12 +2,13 @@ package elasticbeanstalk_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elasticbeanstalk" ) @@ -65,7 +66,7 @@ func TestInMemoryBackend_Snapshot_NotNilOnFreshBackend(t *testing.T) { // Must be valid JSON. var m map[string]any - require.NoError(t, json.Unmarshal(snap, &m)) + require.NoError(t, json.Unmarshal(snap, &m, jsonx.V1())) } // TestInMemoryBackend_SeedHelpers_PopulateAllCollections verifies that seed diff --git a/services/elasticsearch/handler.go b/services/elasticsearch/handler.go index 6ec0d16def..d630ab1d5f 100644 --- a/services/elasticsearch/handler.go +++ b/services/elasticsearch/handler.go @@ -2,7 +2,7 @@ package elasticsearch import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -537,7 +538,7 @@ func (h *Handler) decodeRequest(w http.ResponseWriter, r *http.Request, out any) return true } - if err = json.Unmarshal(body, out); err != nil { + if err = json.Unmarshal(body, out, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return false diff --git a/services/elasticsearch/handler_domain_advanced_options_test.go b/services/elasticsearch/handler_domain_advanced_options_test.go index d98ff37c6a..0e8ec6b040 100644 --- a/services/elasticsearch/handler_domain_advanced_options_test.go +++ b/services/elasticsearch/handler_domain_advanced_options_test.go @@ -1,12 +1,14 @@ package elasticsearch_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestElasticsearchHandler_CreateDomain_VPCOptions verifies VPCOptions @@ -401,7 +403,7 @@ func TestElasticsearchBackend_CreateDomain_InvalidAutoTuneDesiredState(t *testin body := []byte(`{"DomainName":"raw-autotune","AutoTuneOptions":{"DesiredState":"BOGUS"}}`) var decoded map[string]any - require.NoError(t, json.Unmarshal(body, &decoded)) + require.NoError(t, json.Unmarshal(body, &decoded, jsonx.V1())) resp := doRequest(t, h, http.MethodPost, "/2015-01-01/es/domain", decoded) defer resp.Body.Close() diff --git a/services/elasticsearch/handler_domain_config.go b/services/elasticsearch/handler_domain_config.go index 4e2859f34d..bf0b83b4e1 100644 --- a/services/elasticsearch/handler_domain_config.go +++ b/services/elasticsearch/handler_domain_config.go @@ -1,7 +1,7 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // updateDomainConfigRequest is the request body for UpdateElasticsearchDomainConfig. @@ -38,7 +39,7 @@ func (h *Handler) handleUpdateDomainConfig(w http.ResponseWriter, r *http.Reques } var req updateDomainConfigRequest - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_domain_fields_test.go b/services/elasticsearch/handler_domain_fields_test.go index 98d1b233e7..d6240ed841 100644 --- a/services/elasticsearch/handler_domain_fields_test.go +++ b/services/elasticsearch/handler_domain_fields_test.go @@ -1,12 +1,15 @@ package elasticsearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestElasticsearchHandler_DomainDedicatedMaster verifies dedicated master @@ -57,7 +60,7 @@ func TestElasticsearchHandler_DomainDedicatedMaster(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) cfg := status["ElasticsearchClusterConfig"].(map[string]any) @@ -116,7 +119,7 @@ func TestElasticsearchHandler_DomainZoneAwareness(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) cfg := status["ElasticsearchClusterConfig"].(map[string]any) @@ -178,7 +181,7 @@ func TestElasticsearchHandler_DomainWarm(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) cfg := status["ElasticsearchClusterConfig"].(map[string]any) @@ -243,7 +246,7 @@ func TestElasticsearchHandler_DomainEBSIopsAndThroughput(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) ebs := status["EBSOptions"].(map[string]any) @@ -291,7 +294,7 @@ func TestElasticsearchHandler_DomainEncryptionAtRest(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) enc := status["EncryptionAtRestOptions"].(map[string]any) @@ -338,7 +341,7 @@ func TestElasticsearchHandler_DomainNodeToNodeEncryption(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) n2n := status["NodeToNodeEncryptionOptions"].(map[string]any) @@ -393,7 +396,7 @@ func TestElasticsearchHandler_DomainEndpointOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) endpoint := status["DomainEndpointOptions"].(map[string]any) @@ -467,7 +470,7 @@ func TestElasticsearchHandler_DomainSnapshotOptions(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) snap := status["SnapshotOptions"].(map[string]any) @@ -536,7 +539,7 @@ func TestElasticsearchHandler_DomainAdvancedOptions(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) advOpts := status["AdvancedOptions"].(map[string]any) @@ -602,7 +605,7 @@ func TestElasticsearchHandler_DomainAccessPolicies(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) assert.Equal(t, tc.wantPolicy, status["AccessPolicies"]) @@ -683,7 +686,7 @@ func TestElasticsearchHandler_UpdateDomainNewFields(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) status := out["DomainStatus"].(map[string]any) tc.checkFn(t, status) diff --git a/services/elasticsearch/handler_domain_lifecycle.go b/services/elasticsearch/handler_domain_lifecycle.go index 17d8aeb5f6..736a1ac990 100644 --- a/services/elasticsearch/handler_domain_lifecycle.go +++ b/services/elasticsearch/handler_domain_lifecycle.go @@ -1,13 +1,14 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strconv" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -46,7 +47,7 @@ func (h *Handler) handleCancelElasticsearchServiceSoftwareUpdate(w http.Response } var req cancelSoftwareUpdateRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_domains.go b/services/elasticsearch/handler_domains.go index b012dfc60e..714a96014a 100644 --- a/services/elasticsearch/handler_domains.go +++ b/services/elasticsearch/handler_domains.go @@ -1,13 +1,14 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" "time" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // domainZoneAwarenessConfig holds zone awareness sub-config. @@ -333,7 +334,7 @@ func (h *Handler) handleCreateDomain(w http.ResponseWriter, r *http.Request) { } var req domainJSON - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -553,7 +554,7 @@ func (h *Handler) handleDescribeElasticsearchDomains(w http.ResponseWriter, r *h } var req describeDomainsRequest - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_domains_test.go b/services/elasticsearch/handler_domains_test.go index 6db1b1bc79..e2315c946f 100644 --- a/services/elasticsearch/handler_domains_test.go +++ b/services/elasticsearch/handler_domains_test.go @@ -2,7 +2,8 @@ package elasticsearch_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elasticsearch" ) @@ -237,7 +239,7 @@ func TestElasticsearchHandler_ListDomainNames(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) names, ok := out["DomainNames"].([]any) require.True(t, ok) @@ -363,7 +365,7 @@ func TestElasticsearchHandler_DomainCollectionRouteMatrix(t *testing.T) { var out map[string]any if resp.Header.Get("Content-Type") != "" { - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) } resp.Body.Close() @@ -442,7 +444,7 @@ func TestElasticsearchHandler_DescribeElasticsearchDomains(t *testing.T) { assert.Equal(t, tt.wantCode, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainStatusList"].([]any) require.True(t, ok) @@ -611,7 +613,7 @@ func TestElasticsearchHandler_NonNilEmptyDomainList(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) domainNames, ok := out["DomainNames"] require.True(t, ok) diff --git a/services/elasticsearch/handler_outbound_connections.go b/services/elasticsearch/handler_outbound_connections.go index 8b9e6235d4..e24913f14b 100644 --- a/services/elasticsearch/handler_outbound_connections.go +++ b/services/elasticsearch/handler_outbound_connections.go @@ -1,11 +1,12 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // outboundConnectionJSON is the JSON representation of an outbound cross-cluster connection. @@ -37,7 +38,7 @@ func (h *Handler) handleCreateOutboundCrossClusterSearchConnection(w http.Respon } var req createOutboundConnectionRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_packages.go b/services/elasticsearch/handler_packages.go index eec513afcc..7ae9a6ba13 100644 --- a/services/elasticsearch/handler_packages.go +++ b/services/elasticsearch/handler_packages.go @@ -1,7 +1,7 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "slices" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -68,7 +69,7 @@ func (h *Handler) handleCreatePackage(w http.ResponseWriter, r *http.Request) { } var req createPackageRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_tags.go b/services/elasticsearch/handler_tags.go index 37b723561e..c43a80f549 100644 --- a/services/elasticsearch/handler_tags.go +++ b/services/elasticsearch/handler_tags.go @@ -1,7 +1,7 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -9,6 +9,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -52,7 +53,7 @@ func (h *Handler) handleAddTags(w http.ResponseWriter, r *http.Request) { } var req addTagsInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -130,7 +131,7 @@ func (h *Handler) handleRemoveTags(w http.ResponseWriter, r *http.Request) { } var req removeTagsInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/handler_tags_test.go b/services/elasticsearch/handler_tags_test.go index 8e07d4b789..52f7492e5d 100644 --- a/services/elasticsearch/handler_tags_test.go +++ b/services/elasticsearch/handler_tags_test.go @@ -1,7 +1,8 @@ package elasticsearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestElasticsearchHandler_Tags(t *testing.T) { @@ -63,7 +66,7 @@ func TestElasticsearchHandler_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, listResp.StatusCode) var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) tagList, ok := listOut["TagList"].([]any) require.True(t, ok) @@ -300,7 +303,7 @@ func TestElasticsearchHandler_SortedListTagsResponse(t *testing.T) { Value string `json:"Value"` } `json:"TagList"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) require.Len(t, out.TagList, 3) assert.Equal(t, "aaa", out.TagList[0].Key) assert.Equal(t, "mmm", out.TagList[1].Key) @@ -365,7 +368,7 @@ func TestElasticsearchHandler_AddTags_DuplicateKeyRejected(t *testing.T) { assert.Equal(t, tt.wantCode, resp.StatusCode) if tt.wantCode == http.StatusBadRequest { var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Contains(t, out["message"], "Duplicate tag key") } }) @@ -421,7 +424,7 @@ func TestElasticsearchHandler_AddRemoveTags_UnknownARN(t *testing.T) { require.Equal(t, http.StatusBadRequest, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Contains(t, out["message"], "domain not found") }) } diff --git a/services/elasticsearch/handler_test.go b/services/elasticsearch/handler_test.go index b0d34f98b6..30f114b4dc 100644 --- a/services/elasticsearch/handler_test.go +++ b/services/elasticsearch/handler_test.go @@ -2,7 +2,8 @@ package elasticsearch_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elasticsearch" ) @@ -27,7 +29,7 @@ func doRequest(t *testing.T, h *elasticsearch.Handler, method, path string, body var reqBody io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) @@ -53,7 +55,7 @@ func createDomainAndGetARN(t *testing.T, h *elasticsearch.Handler, domainName st }) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() status := createOut["DomainStatus"].(map[string]any) @@ -78,7 +80,7 @@ func readJSONBody(t *testing.T, resp *http.Response) map[string]any { require.NoError(t, err) var m map[string]any - require.NoError(t, json.Unmarshal(b, &m)) + require.NoError(t, json.Unmarshal(b, &m, jsonx.V1())) return m } diff --git a/services/elasticsearch/handler_versions_test.go b/services/elasticsearch/handler_versions_test.go index f5f8099c4b..4789518b77 100644 --- a/services/elasticsearch/handler_versions_test.go +++ b/services/elasticsearch/handler_versions_test.go @@ -1,12 +1,15 @@ package elasticsearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestElasticsearchHandler_ListElasticsearchVersions verifies all 22 valid @@ -33,7 +36,7 @@ func TestElasticsearchHandler_ListElasticsearchVersions(t *testing.T) { var out struct { ElasticsearchVersions []string `json:"ElasticsearchVersions"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) require.Len(t, out.ElasticsearchVersions, 22, "expected all 22 versions") versionSet := make(map[string]bool) @@ -100,7 +103,7 @@ func TestElasticsearchHandler_CompatibleVersionsDomain(t *testing.T) { TargetVersions []string `json:"TargetVersions"` } `json:"CompatibleElasticsearchVersions"` } - require.NoError(t, json.NewDecoder(compatResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(compatResp.Body), &out, jsonx.V1())) require.Len(t, out.CompatibleElasticsearchVersions, 1) assert.Equal(t, tc.wantSourceVersion, out.CompatibleElasticsearchVersions[0].SourceVersion) }) diff --git a/services/elasticsearch/handler_vpc_endpoints.go b/services/elasticsearch/handler_vpc_endpoints.go index a73f7289f8..f7cfcd6f16 100644 --- a/services/elasticsearch/handler_vpc_endpoints.go +++ b/services/elasticsearch/handler_vpc_endpoints.go @@ -1,12 +1,13 @@ package elasticsearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // keyNextToken is the required (always-empty, single-page emulator) pagination @@ -50,7 +51,7 @@ func (h *Handler) handleCreateVpcEndpoint(w http.ResponseWriter, r *http.Request } var req createVpcEndpointRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -144,7 +145,7 @@ func (h *Handler) handleAuthorizeVpcEndpointAccess(w http.ResponseWriter, r *htt } var req authorizeVpcEndpointAccessRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/elasticsearch/persistence.go b/services/elasticsearch/persistence.go index 0a21fa91b7..cb5ebf8b28 100644 --- a/services/elasticsearch/persistence.go +++ b/services/elasticsearch/persistence.go @@ -2,7 +2,7 @@ package elasticsearch import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -96,7 +96,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` PackagesByName map[string]map[string]string `json:"packagesByName"` PackageAssociations map[string]map[string][]string `json:"packageAssociations"` PackageAssociationDetails packageAssociationDetails `json:"packageAssociationDetails,omitempty"` @@ -245,7 +245,7 @@ func (b *InMemoryBackend) rebuildArnIndex() { // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/elasticsearch/persistence_test.go b/services/elasticsearch/persistence_test.go index b7d4076c31..a3a150ebff 100644 --- a/services/elasticsearch/persistence_test.go +++ b/services/elasticsearch/persistence_test.go @@ -2,12 +2,13 @@ package elasticsearch_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elasticsearch" ) @@ -519,7 +520,7 @@ func TestElasticsearch_SnapshotWarnOnEmptyState(t *testing.T) { require.NotNil(t, snap) var v map[string]any - require.NoError(t, json.Unmarshal(snap, &v)) + require.NoError(t, json.Unmarshal(snap, &v, jsonx.V1())) } // TestElasticsearch_PersistenceReservedAndVpcAccessCombined verifies that VPC diff --git a/services/elb/persistence.go b/services/elb/persistence.go index 54f08dfcb5..674c6b9053 100644 --- a/services/elb/persistence.go +++ b/services/elb/persistence.go @@ -2,9 +2,10 @@ package elb import ( "context" - "encoding/json" + "encoding/json/v2" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -217,7 +218,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Version: snapshotVersion, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "elb: Snapshot marshal failure", "error", err) diff --git a/services/elb/persistence_test.go b/services/elb/persistence_test.go index d5c01cc2a2..a8845c1524 100644 --- a/services/elb/persistence_test.go +++ b/services/elb/persistence_test.go @@ -2,7 +2,7 @@ package elb_test import ( "context" - "encoding/json" + "encoding/json/jsontext" "encoding/xml" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/blackbirdworks/gopherstack/services/elb" @@ -370,7 +371,7 @@ func TestPersistenceEmptySnapshot(t *testing.T) { b := newBackend() snap := b.Snapshot(t.Context()) require.NotNil(t, snap) - require.True(t, json.Valid(snap)) + require.True(t, jsontext.Value(snap).IsValid(jsonx.V1())) } // TestPersistenceRoundTripBackendServerDescriptions verifies that Snapshot/Restore preserves diff --git a/services/elbv2/dataplane.go b/services/elbv2/dataplane.go index b4a32fd47b..0af8c8af4e 100644 --- a/services/elbv2/dataplane.go +++ b/services/elbv2/dataplane.go @@ -2,7 +2,8 @@ package elbv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/netip" @@ -15,6 +16,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -300,5 +303,5 @@ func (h *Handler) serveListenerEndpoints(w http.ResponseWriter) { sort.Slice(out, func(i, j int) bool { return out[i].ListenerArn < out[j].ListenerArn }) w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(out) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), out) } diff --git a/services/elbv2/dataplane_lambda.go b/services/elbv2/dataplane_lambda.go index c3e6dda871..dc02331ebf 100644 --- a/services/elbv2/dataplane_lambda.go +++ b/services/elbv2/dataplane_lambda.go @@ -2,7 +2,7 @@ package elbv2 import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "mime" "net/http" @@ -11,6 +11,7 @@ import ( "unicode/utf8" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxLambdaTargetBodyBytes is the 1 MB request body limit for ALB Lambda targets. @@ -72,7 +73,7 @@ func (h *Handler) serveLambda(w http.ResponseWriter, req *dpRequest, tg *TargetG setForwardHeaders(hdr, req) hdr.Set("Host", req.host) - payload, err := json.Marshal(buildALBEvent(req, tg, hdr, body)) + payload, err := json.Marshal(buildALBEvent(req, tg, hdr, body), jsonx.V1()) if err != nil { writeDPError(w, http.StatusBadGateway, msgBadGateway) @@ -169,7 +170,7 @@ func isTextContent(ct string) bool { func writeLambdaResponse(w http.ResponseWriter, payload []byte) { var resp albResponse - if err := json.Unmarshal(payload, &resp); err != nil || resp.StatusCode == nil { + if err := json.Unmarshal(payload, &resp, jsonx.V1()); err != nil || resp.StatusCode == nil { writeDPError(w, http.StatusBadGateway, msgBadGateway) return diff --git a/services/elbv2/dataplane_lambda_test.go b/services/elbv2/dataplane_lambda_test.go index 6968c88f16..7f332b5539 100644 --- a/services/elbv2/dataplane_lambda_test.go +++ b/services/elbv2/dataplane_lambda_test.go @@ -3,7 +3,7 @@ package elbv2_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -13,6 +13,8 @@ import ( elbv2types "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const testFnARN = "arn:aws:lambda:us-east-1:123456789012:function:web" @@ -43,7 +45,7 @@ func (f *fakeInvoker) event(t *testing.T) map[string]any { var ev map[string]any - require.NoError(t, json.Unmarshal(f.payload, &ev)) + require.NoError(t, json.Unmarshal(f.payload, &ev, jsonx.V1())) return ev } diff --git a/services/elbv2/persistence.go b/services/elbv2/persistence.go index 62217465f4..0355a96ce4 100644 --- a/services/elbv2/persistence.go +++ b/services/elbv2/persistence.go @@ -2,7 +2,7 @@ package elbv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "time" @@ -37,7 +37,7 @@ const elbv2SnapshotVersion = 2 // ResourcePolicies / TargetReadyAt / TargetDrainingUntil are persisted // separately because they are not store.Table-shaped -- see store_setup.go. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourcePolicies map[string]string `json:"resourcePolicies"` TargetReadyAt map[string]map[string]time.Time `json:"targetReadyAt"` TargetDrainingUntil map[string]map[string]time.Time `json:"targetDrainingUntil"` diff --git a/services/elbv2/target_groups_test.go b/services/elbv2/target_groups_test.go index fcfe897c49..7135de0ccc 100644 --- a/services/elbv2/target_groups_test.go +++ b/services/elbv2/target_groups_test.go @@ -2,7 +2,7 @@ package elbv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/elbv2" ) @@ -255,7 +256,7 @@ func TestDeleteTargetGroup_LifecycleMapsCleaned(t *testing.T) { TargetReadyAt map[string]map[string]time.Time `json:"targetReadyAt"` TargetDrainingUntil map[string]map[string]time.Time `json:"targetDrainingUntil"` } - require.NoError(t, json.Unmarshal(h.Snapshot(context.Background()), &snap)) + require.NoError(t, json.Unmarshal(h.Snapshot(context.Background()), &snap, jsonx.V1())) byField := map[string]map[string]map[string]time.Time{ "targetReadyAt": snap.TargetReadyAt, diff --git a/services/emr/handler.go b/services/emr/handler.go index f19fb36497..859c94bf65 100644 --- a/services/emr/handler.go +++ b/services/emr/handler.go @@ -2,7 +2,7 @@ package emr import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -193,7 +194,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { TargetResourceArn string `json:"TargetResourceArn"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ClusterID != "": @@ -330,7 +331,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // handleError maps backend errors to EMR's wire error shape. EMR's modeled diff --git a/services/emr/handler_cluster_settings_test.go b/services/emr/handler_cluster_settings_test.go index fcfc28034c..2b20cf6c71 100644 --- a/services/emr/handler_cluster_settings_test.go +++ b/services/emr/handler_cluster_settings_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTerminationProtection(t *testing.T) { @@ -19,7 +21,7 @@ func TestTerminationProtection(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) clusterID := create.JobFlowID protectRec := doEMRRequest(t, h, "SetTerminationProtection", map[string]any{ @@ -63,7 +65,7 @@ func TestSetKeepJobFlowAliveWhenNoSteps_SyncsAutoTerminate(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) clusterID := create.JobFlowID describe := func() bool { @@ -75,7 +77,7 @@ func TestSetKeepJobFlowAliveWhenNoSteps_SyncsAutoTerminate(t *testing.T) { AutoTerminate bool `json:"AutoTerminate"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.Cluster.AutoTerminate } @@ -107,7 +109,7 @@ func TestModifyCluster(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) modRec := doEMRRequest(t, h, "ModifyCluster", map[string]any{ "ClusterId": create.JobFlowID, @@ -118,7 +120,7 @@ func TestModifyCluster(t *testing.T) { var modOut struct { StepConcurrencyLevel int `json:"StepConcurrencyLevel"` } - require.NoError(t, json.Unmarshal(modRec.Body.Bytes(), &modOut)) + require.NoError(t, json.Unmarshal(modRec.Body.Bytes(), &modOut, jsonx.V1())) assert.Equal(t, 5, modOut.StepConcurrencyLevel) } @@ -132,7 +134,7 @@ func TestModifyCluster_InvalidRange(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) modRec := doEMRRequest(t, h, "ModifyCluster", map[string]any{ "ClusterId": create.JobFlowID, diff --git a/services/emr/handler_clusters_test.go b/services/emr/handler_clusters_test.go index 96bdd04d2b..a1f8af0705 100644 --- a/services/emr/handler_clusters_test.go +++ b/services/emr/handler_clusters_test.go @@ -2,7 +2,7 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -54,7 +55,7 @@ func TestEMR_RunJobFlow(t *testing.T) { ClusterArn string `json:"ClusterArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.JobFlowID) assert.Contains(t, out.ClusterArn, "elasticmapreduce") }) @@ -95,7 +96,7 @@ func TestEMR_DescribeCluster(t *testing.T) { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) clusterID := tt.clusterID if clusterID == "" { @@ -114,7 +115,7 @@ func TestEMR_DescribeCluster(t *testing.T) { } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, clusterID, out.Cluster.ID) assert.Equal(t, "test-cluster", out.Cluster.Name) } @@ -160,7 +161,7 @@ func TestEMR_ListClusters(t *testing.T) { Clusters []any `json:"Clusters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.Clusters), tt.wantMinCount) }) } @@ -183,7 +184,7 @@ func TestEMR_TerminateJobFlows(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return []string{out.JobFlowID} }, @@ -282,7 +283,7 @@ func TestRunJobFlow_SecurityConfigurationValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errOut["__type"]) }) @@ -322,7 +323,7 @@ func TestRunJobFlow_DefaultReleaseLabel(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": out.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -332,7 +333,7 @@ func TestRunJobFlow_DefaultReleaseLabel(t *testing.T) { ReleaseLabel string `json:"ReleaseLabel"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, emr.DefaultReleaseLabel, desc.Cluster.ReleaseLabel) } @@ -349,7 +350,7 @@ func TestRunJobFlow_ApplicationsDefaulted(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": out.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -361,7 +362,7 @@ func TestRunJobFlow_ApplicationsDefaulted(t *testing.T) { } `json:"Applications"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.NotEmpty(t, desc.Cluster.Applications) } @@ -389,7 +390,7 @@ func TestListClusters_DateFilter(t *testing.T) { ID string `json:"Id"` } `json:"Clusters"` } - require.NoError(t, json.Unmarshal(listInRange.Body.Bytes(), &inRange)) + require.NoError(t, json.Unmarshal(listInRange.Body.Bytes(), &inRange, jsonx.V1())) assert.Len(t, inRange.Clusters, 1) listOld := doEMRRequest(t, h, "ListClusters", map[string]any{ @@ -402,7 +403,7 @@ func TestListClusters_DateFilter(t *testing.T) { ID string `json:"Id"` } `json:"Clusters"` } - require.NoError(t, json.Unmarshal(listOld.Body.Bytes(), &old)) + require.NoError(t, json.Unmarshal(listOld.Body.Bytes(), &old, jsonx.V1())) assert.Empty(t, old.Clusters) } @@ -427,7 +428,7 @@ func TestConfigurations_RunJobFlow(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": out.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -443,7 +444,7 @@ func TestConfigurations_RunJobFlow(t *testing.T) { } `json:"Configurations"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) require.Len(t, desc.Cluster.Configurations, 1) assert.Equal(t, "spark-defaults", desc.Cluster.Configurations[0].Classification) assert.Equal(t, "4g", desc.Cluster.Configurations[0].Properties["spark.executor.memory"]) @@ -466,7 +467,7 @@ func TestClusterFields_EbsAndOS(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": out.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -478,7 +479,7 @@ func TestClusterFields_EbsAndOS(t *testing.T) { EbsRootVolumeSize int `json:"EbsRootVolumeSize"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, 64, desc.Cluster.EbsRootVolumeSize) assert.Equal(t, "2.0.20230718", desc.Cluster.OSReleaseLabel) assert.Equal(t, "ami-0123456789abcdef0", desc.Cluster.CustomAmiID) @@ -579,13 +580,13 @@ func TestDescribeCluster_TagsEmptyNotAbsent(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) cluster, ok := raw["Cluster"].(map[string]any) require.True(t, ok, "Cluster must be an object") @@ -612,13 +613,13 @@ func TestDescribeCluster_TagsRoundTrip(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) cluster := raw["Cluster"].(map[string]any) tags := cluster["Tags"].([]any) @@ -642,7 +643,7 @@ func TestDescribeCluster_TagsEmptyAfterRemove(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rmRec := doEMRRequest(t, h, "RemoveTags", map[string]any{ "ResourceId": create.JobFlowID, @@ -654,7 +655,7 @@ func TestDescribeCluster_TagsEmptyAfterRemove(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) cluster := raw["Cluster"].(map[string]any) tags, hasKey := cluster["Tags"] @@ -673,7 +674,7 @@ func TestErrorMapping_NotFound_ClusterNotFoundException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errOut["__type"]) } @@ -728,7 +729,7 @@ func newSessionForTest(t *testing.T, h *emr.Handler, clusterName string) (string var cluster struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cluster)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cluster, jsonx.V1())) startRec := doEMRRequest(t, h, "StartSession", map[string]any{"ClusterId": cluster.JobFlowID}) require.Equal(t, http.StatusOK, startRec.Code, startRec.Body.String()) @@ -736,7 +737,7 @@ func newSessionForTest(t *testing.T, h *emr.Handler, clusterName string) (string var session struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &session)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &session, jsonx.V1())) return cluster.JobFlowID, session.ID } @@ -765,7 +766,7 @@ func TestEMR_StartSession(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.JobFlowID }, @@ -789,7 +790,7 @@ func TestEMR_StartSession(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) termRec := doEMRRequest(t, h, "TerminateJobFlows", map[string]any{ "JobFlowIds": []string{out.JobFlowID}, @@ -822,7 +823,7 @@ func TestEMR_StartSession(t *testing.T) { ARN string `json:"Arn"` State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.ID) assert.Equal(t, clusterID, out.ClusterID) assert.Equal(t, emr.SessionStateSubmitted, out.State) @@ -879,7 +880,7 @@ func TestEMR_GetSession(t *testing.T) { State string `json:"State"` } `json:"Session"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, sessionID, out.Session.ID) assert.Equal(t, clusterID, out.Session.ClusterID) assert.Equal(t, emr.SessionStateSubmitted, out.Session.State) @@ -921,7 +922,7 @@ func TestEMR_ListSessions(t *testing.T) { var cluster struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cluster)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cluster, jsonx.V1())) for range tt.numSessions { startRec := doEMRRequest(t, h, "StartSession", map[string]any{"ClusterId": cluster.JobFlowID}) @@ -941,7 +942,7 @@ func TestEMR_ListSessions(t *testing.T) { ID string `json:"Id"` } `json:"Sessions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Sessions, tt.wantCount) }) } @@ -996,7 +997,7 @@ func TestEMR_TerminateSession(t *testing.T) { SessionID string `json:"SessionId"` State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, clusterID, out.ClusterID) assert.Equal(t, sessionID, out.SessionID) assert.Equal(t, emr.SessionStateTerminated, out.State) @@ -1050,7 +1051,7 @@ func TestEMR_GetSessionEndpoint(t *testing.T) { Endpoint string `json:"Endpoint"` AuthToken string `json:"AuthToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.Endpoint) assert.NotEmpty(t, out.AuthToken) assert.Contains(t, out.Credentials, "UsernamePassword") @@ -1104,7 +1105,7 @@ func TestEMR_TerminateJobFlows_CascadesToSessions(t *testing.T) { State string `json:"State"` } `json:"Session"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, emr.SessionStateTerminated, out.Session.State, "session must be terminated when its cluster is terminated") }) diff --git a/services/emr/handler_instance_fleets_test.go b/services/emr/handler_instance_fleets_test.go index ff19295b17..7c29afb470 100644 --- a/services/emr/handler_instance_fleets_test.go +++ b/services/emr/handler_instance_fleets_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -23,7 +24,7 @@ func TestEMR_ListInstanceFleets(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) rec := doEMRRequest(t, h, "ListInstanceFleets", map[string]any{ "ClusterId": createOut.JobFlowID, @@ -35,7 +36,7 @@ func TestEMR_ListInstanceFleets(t *testing.T) { InstanceFleets []emr.InstanceFleet `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.InstanceFleets) } @@ -71,7 +72,7 @@ func TestEMR_AddInstanceFleet(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) clusterID := tt.clusterID if clusterID == "" { @@ -94,7 +95,7 @@ func TestEMR_AddInstanceFleet(t *testing.T) { ClusterID string `json:"ClusterId"` InstanceFleetID string `json:"InstanceFleetId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.InstanceFleetID) assert.Equal(t, clusterID, out.ClusterID) assert.Contains(t, out.ClusterArn, "elasticmapreduce") @@ -114,7 +115,7 @@ func TestEMR_AddInstanceFleet_ListInstanceFleets(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) // Add a fleet. addRec := doEMRRequest(t, h, "AddInstanceFleet", map[string]any{ @@ -138,7 +139,7 @@ func TestEMR_AddInstanceFleet_ListInstanceFleets(t *testing.T) { Name string `json:"Name"` } `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.InstanceFleets, 1) assert.Equal(t, "task-fleet", listOut.InstanceFleets[0].Name) assert.NotEmpty(t, listOut.InstanceFleets[0].ID) @@ -165,7 +166,7 @@ func TestInstanceFleet_CapacityTargets(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) addRec := doEMRRequest(t, h, "AddInstanceFleet", map[string]any{ "ClusterId": create.JobFlowID, @@ -193,7 +194,7 @@ func TestInstanceFleet_CapacityTargets(t *testing.T) { ProvisionedSpotCapacity int `json:"ProvisionedSpotCapacity"` } `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.InstanceFleets, 1) f := out.InstanceFleets[0] assert.Equal(t, 5, f.TargetOnDemandCapacity) @@ -234,7 +235,7 @@ func TestListInstanceFleetsTyped(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) addRec := doEMRRequest(t, h, "AddInstanceFleet", map[string]any{ "ClusterId": createOut.JobFlowID, @@ -250,7 +251,7 @@ func TestListInstanceFleetsTyped(t *testing.T) { var out struct { InstanceFleets []emr.InstanceFleet `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.InstanceFleets, 1) assert.Equal(t, "typed-fleet", out.InstanceFleets[0].Name) assert.NotEmpty(t, out.InstanceFleets[0].ID) diff --git a/services/emr/handler_instance_groups_test.go b/services/emr/handler_instance_groups_test.go index da4fe31db5..fe184951a6 100644 --- a/services/emr/handler_instance_groups_test.go +++ b/services/emr/handler_instance_groups_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -48,7 +49,7 @@ func TestEMR_ListInstanceGroups(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) rec := doEMRRequest(t, h, "ListInstanceGroups", map[string]any{ "ClusterId": createOut.JobFlowID, @@ -63,7 +64,7 @@ func TestEMR_ListInstanceGroups(t *testing.T) { } `json:"Status"` } `json:"InstanceGroups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.InstanceGroups, tt.wantCount) for _, g := range out.InstanceGroups { @@ -116,7 +117,7 @@ func TestEMR_AddInstanceGroups(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) jobFlowID := tt.jobFlowID if jobFlowID == "" { @@ -138,7 +139,7 @@ func TestEMR_AddInstanceGroups(t *testing.T) { JobFlowID string `json:"JobFlowId"` InstanceGroupIDs []string `json:"InstanceGroupIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.InstanceGroupIDs, 1) assert.Equal(t, jobFlowID, out.JobFlowID) assert.Contains(t, out.ClusterArn, "elasticmapreduce") @@ -194,7 +195,7 @@ func TestModifyInstanceGroups(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) listRec := doEMRRequest(t, h, "ListInstanceGroups", map[string]any{"ClusterId": create.JobFlowID}) var listOut struct { @@ -202,7 +203,7 @@ func TestModifyInstanceGroups(t *testing.T) { ID string `json:"Id"` } `json:"InstanceGroups"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.InstanceGroups) modRec := doEMRRequest(t, h, "ModifyInstanceGroups", map[string]any{ @@ -238,7 +239,7 @@ func TestInstanceGroup_BidPrice(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) listRec := doEMRRequest(t, h, "ListInstanceGroups", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, listRec.Code) @@ -249,7 +250,7 @@ func TestInstanceGroup_BidPrice(t *testing.T) { BidPrice string `json:"BidPrice"` } `json:"InstanceGroups"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.InstanceGroups, 1) assert.Equal(t, "SPOT", out.InstanceGroups[0].Market) assert.Equal(t, "0.05", out.InstanceGroups[0].BidPrice) @@ -322,8 +323,8 @@ func TestBuildInstanceGroups_UniqueIDs(t *testing.T) { var c1, c2 struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &c1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &c2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &c1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &c2, jsonx.V1())) // Gather instance group IDs via ListInstanceGroups for each cluster allIDs := make(map[string]bool) @@ -336,7 +337,7 @@ func TestBuildInstanceGroups_UniqueIDs(t *testing.T) { ID string `json:"Id"` } `json:"InstanceGroups"` } - require.NoError(t, json.Unmarshal(igRec.Body.Bytes(), &igOut)) + require.NoError(t, json.Unmarshal(igRec.Body.Bytes(), &igOut, jsonx.V1())) for _, ig := range igOut.InstanceGroups { assert.False(t, allIDs[ig.ID], "duplicate instance group ID %s", ig.ID) diff --git a/services/emr/handler_instances_test.go b/services/emr/handler_instances_test.go index 50e0b0ff40..4d8b9e1034 100644 --- a/services/emr/handler_instances_test.go +++ b/services/emr/handler_instances_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListInstances(t *testing.T) { @@ -27,7 +29,7 @@ func TestListInstances(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) listRec := doEMRRequest(t, h, "ListInstances", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, listRec.Code) @@ -38,7 +40,7 @@ func TestListInstances(t *testing.T) { Ec2InstanceID string `json:"Ec2InstanceId"` } `json:"Instances"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Instances, 3) } @@ -53,7 +55,7 @@ func TestListInstances_InstanceFleets(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) addFleet := func(fleetType string, onDemand, spot int) string { rec := doEMRRequest(t, h, "AddInstanceFleet", map[string]any{ @@ -70,7 +72,7 @@ func TestListInstances_InstanceFleets(t *testing.T) { var out struct { InstanceFleetID string `json:"InstanceFleetId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.InstanceFleetID } @@ -116,7 +118,7 @@ func TestListInstances_InstanceFleets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out instancesResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Instances, tt.wantLen) for _, inst := range out.Instances { diff --git a/services/emr/handler_job_flows_test.go b/services/emr/handler_job_flows_test.go index efd29a67bf..0a8135d0a5 100644 --- a/services/emr/handler_job_flows_test.go +++ b/services/emr/handler_job_flows_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDescribeJobFlows(t *testing.T) { @@ -19,7 +21,7 @@ func TestDescribeJobFlows(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeJobFlows", map[string]any{ "JobFlowIds": []string{create.JobFlowID}, @@ -32,7 +34,7 @@ func TestDescribeJobFlows(t *testing.T) { Name string `json:"Name"` } `json:"JobFlows"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.JobFlows, 1) assert.Equal(t, create.JobFlowID, out.JobFlows[0].JobFlowID) assert.Equal(t, "jf-cluster", out.JobFlows[0].Name) @@ -65,7 +67,7 @@ func TestDescribeJobFlows_EmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) flows, hasKey := raw["JobFlows"] assert.True(t, hasKey, "DescribeJobFlows must include 'JobFlows' key") diff --git a/services/emr/handler_notebook_executions_test.go b/services/emr/handler_notebook_executions_test.go index e033d742db..fcd592d1b1 100644 --- a/services/emr/handler_notebook_executions_test.go +++ b/services/emr/handler_notebook_executions_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -31,7 +32,7 @@ func TestNotebookExecution(t *testing.T) { var startOut struct { NotebookExecutionID string `json:"NotebookExecutionId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut.NotebookExecutionID) // Describe it. @@ -47,7 +48,7 @@ func TestNotebookExecution(t *testing.T) { NotebookExecutionName string `json:"NotebookExecutionName"` } `json:"NotebookExecution"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, startOut.NotebookExecutionID, descOut.NotebookExecution.NotebookExecutionID) assert.Equal(t, "RUNNING", descOut.NotebookExecution.Status) assert.Equal(t, "test-run", descOut.NotebookExecution.NotebookExecutionName) @@ -62,7 +63,7 @@ func TestNotebookExecution(t *testing.T) { Status string `json:"Status"` } `json:"NotebookExecutions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.NotebookExecutions, 1) assert.Equal(t, startOut.NotebookExecutionID, listOut.NotebookExecutions[0].NotebookExecutionID) @@ -83,7 +84,7 @@ func TestNotebookExecution(t *testing.T) { Status string `json:"Status"` } `json:"NotebookExecution"` } - require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descOut2, jsonx.V1())) assert.Equal(t, "STOPPED", descOut2.NotebookExecution.Status) } @@ -127,7 +128,7 @@ func TestNotebookExecution_ListFilter(t *testing.T) { NotebookExecutionID string `json:"NotebookExecutionId"` } `json:"NotebookExecutions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.NotebookExecutions, 3) } @@ -155,7 +156,7 @@ func TestNotebookExecution_ListNoParamsOrTagsLeak(t *testing.T) { var raw struct { NotebookExecutions []map[string]any `json:"NotebookExecutions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.NotebookExecutions, 1) item := raw.NotebookExecutions[0] @@ -232,7 +233,7 @@ func TestNotebookExecution_TagsEmptyNotAbsent(t *testing.T) { var start struct { NotebookExecutionID string `json:"NotebookExecutionId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &start, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeNotebookExecution", map[string]any{ "NotebookExecutionId": start.NotebookExecutionID, @@ -240,7 +241,7 @@ func TestNotebookExecution_TagsEmptyNotAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) ne, ok := raw["NotebookExecution"].(map[string]any) require.True(t, ok, "NotebookExecution must be an object") diff --git a/services/emr/handler_persistent_app_ui_test.go b/services/emr/handler_persistent_app_ui_test.go index 51ee63559b..a4b9093d30 100644 --- a/services/emr/handler_persistent_app_ui_test.go +++ b/services/emr/handler_persistent_app_ui_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -48,7 +49,7 @@ func TestEMR_CreatePersistentAppUI(t *testing.T) { var out struct { PersistentAppUIID string `json:"PersistentAppUIId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.PersistentAppUIID) } }) @@ -65,7 +66,7 @@ func TestGetClusterSessionCredentials(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "GetClusterSessionCredentials", map[string]any{ "ClusterId": create.JobFlowID, @@ -77,7 +78,7 @@ func TestGetClusterSessionCredentials(t *testing.T) { Credentials map[string]any `json:"Credentials"` ExpiresAt float64 `json:"ExpiresAt"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.Credentials) assert.NotZero(t, out.ExpiresAt) } @@ -92,7 +93,7 @@ func TestGetClusterSessionCredentials_MissingRole(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "GetClusterSessionCredentials", map[string]any{ "ClusterId": create.JobFlowID, @@ -131,6 +132,6 @@ func TestGetOnClusterPresignedURL_NonExistentCluster(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errOut["__type"]) } diff --git a/services/emr/handler_policies_test.go b/services/emr/handler_policies_test.go index 20959928a0..9d8c49edb2 100644 --- a/services/emr/handler_policies_test.go +++ b/services/emr/handler_policies_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestManagedScalingPolicy(t *testing.T) { @@ -19,7 +21,7 @@ func TestManagedScalingPolicy(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) clusterID := create.JobFlowID putRec := doEMRRequest(t, h, "PutManagedScalingPolicy", map[string]any{ @@ -45,7 +47,7 @@ func TestManagedScalingPolicy(t *testing.T) { } `json:"ComputeLimits"` } `json:"ManagedScalingPolicy"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "InstanceFleetUnits", getOut.ManagedScalingPolicy.ComputeLimits.UnitType) assert.Equal(t, 10, getOut.ManagedScalingPolicy.ComputeLimits.MaximumCapacityUnits) @@ -63,7 +65,7 @@ func TestAutoTerminationPolicy(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) clusterID := create.JobFlowID putRec := doEMRRequest(t, h, "PutAutoTerminationPolicy", map[string]any{ @@ -80,7 +82,7 @@ func TestAutoTerminationPolicy(t *testing.T) { IdleTimeout int64 `json:"IdleTimeout"` } `json:"AutoTerminationPolicy"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, int64(3600), getOut.AutoTerminationPolicy.IdleTimeout) } @@ -94,7 +96,7 @@ func TestAutoTerminationPolicy_InvalidTimeout(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) putRec := doEMRRequest(t, h, "PutAutoTerminationPolicy", map[string]any{ "ClusterId": create.JobFlowID, @@ -116,7 +118,7 @@ func TestBlockPublicAccessConfiguration(t *testing.T) { BlockPublicSecurityGroupRules bool `json:"BlockPublicSecurityGroupRules"` } `json:"BlockPublicAccessConfiguration"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.True(t, getOut.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules) putRec := doEMRRequest(t, h, "PutBlockPublicAccessConfiguration", map[string]any{ @@ -128,7 +130,7 @@ func TestBlockPublicAccessConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) getRec2 := doEMRRequest(t, h, "GetBlockPublicAccessConfiguration", map[string]any{}) - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut, jsonx.V1())) assert.False(t, getOut.BlockPublicAccessConfiguration.BlockPublicSecurityGroupRules) } @@ -149,7 +151,7 @@ func TestAutoScalingPolicy(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) listRec := doEMRRequest(t, h, "ListInstanceGroups", map[string]any{"ClusterId": create.JobFlowID}) var listOut struct { @@ -157,7 +159,7 @@ func TestAutoScalingPolicy(t *testing.T) { ID string `json:"Id"` } `json:"InstanceGroups"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.InstanceGroups) groupID := listOut.InstanceGroups[0].ID @@ -177,7 +179,7 @@ func TestAutoScalingPolicy(t *testing.T) { } `json:"Constraints"` } `json:"AutoScalingPolicy"` } - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) require.NotNil(t, putOut.AutoScalingPolicy) assert.Equal(t, 10, putOut.AutoScalingPolicy.Constraints.MaxCapacity) diff --git a/services/emr/handler_release_labels_test.go b/services/emr/handler_release_labels_test.go index 3bedf9f21a..d62f68087e 100644 --- a/services/emr/handler_release_labels_test.go +++ b/services/emr/handler_release_labels_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListReleaseLabels(t *testing.T) { @@ -20,7 +22,7 @@ func TestListReleaseLabels(t *testing.T) { var out struct { ReleaseLabels []string `json:"ReleaseLabels"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.ReleaseLabels) assert.Contains(t, out.ReleaseLabels, "emr-7.3.0") } @@ -39,7 +41,7 @@ func TestDescribeReleaseLabel(t *testing.T) { Name string `json:"Name"` } `json:"Applications"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "emr-7.3.0", out.ReleaseLabel) assert.NotEmpty(t, out.Applications) } @@ -58,6 +60,6 @@ func TestListSupportedInstanceTypes(t *testing.T) { VCPU int `json:"VCPU"` } `json:"SupportedInstanceTypes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.SupportedInstanceTypes) } diff --git a/services/emr/handler_security_configurations_test.go b/services/emr/handler_security_configurations_test.go index 5dc8fb0dd3..1f2598ad4d 100644 --- a/services/emr/handler_security_configurations_test.go +++ b/services/emr/handler_security_configurations_test.go @@ -2,7 +2,7 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -103,7 +104,7 @@ func TestEMR_SecurityConfiguration(t *testing.T) { Name string `json:"Name"` CreationDateTime float64 `json:"CreationDateTime"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.scName, out.Name) assert.NotZero(t, out.CreationDateTime) } @@ -154,7 +155,7 @@ func TestListSecurityConfigurations(t *testing.T) { Name string `json:"Name"` } `json:"SecurityConfigurations"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecurityConfigurations, 3) assert.Equal(t, "alpha", out.SecurityConfigurations[0].Name) } @@ -223,7 +224,7 @@ func TestDescribeSecurityConfiguration(t *testing.T) { SecurityConfiguration string `json:"SecurityConfiguration"` CreationDateTime float64 `json:"CreationDateTime"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.scName, out.Name) assert.NotZero(t, out.CreationDateTime) assert.JSONEq(t, `{"EncryptionConfiguration":{}}`, out.SecurityConfiguration) diff --git a/services/emr/handler_steps_test.go b/services/emr/handler_steps_test.go index 723a035171..29a044f94f 100644 --- a/services/emr/handler_steps_test.go +++ b/services/emr/handler_steps_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -33,7 +34,7 @@ func TestEMR_AddJobFlowSteps(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) rec := doEMRRequest(t, h, "AddJobFlowSteps", map[string]any{ "JobFlowId": createOut.JobFlowID, @@ -52,7 +53,7 @@ func TestEMR_AddJobFlowSteps(t *testing.T) { StepIDs []string `json:"StepIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.StepIDs, 1) assert.Contains(t, out.StepIDs[0], "s-") } @@ -68,7 +69,7 @@ func TestEMR_AddJobFlowSteps_RejectsTerminatedCluster(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) termRec := doEMRRequest(t, h, "TerminateJobFlows", map[string]any{ "JobFlowIds": []string{createOut.JobFlowID}, @@ -91,7 +92,7 @@ func TestEMR_AddJobFlowSteps_RejectsTerminatedCluster(t *testing.T) { var errBody struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errBody.Type) listRec := doEMRRequest(t, h, "ListSteps", map[string]any{"ClusterId": createOut.JobFlowID}) @@ -100,7 +101,7 @@ func TestEMR_AddJobFlowSteps_RejectsTerminatedCluster(t *testing.T) { var listOut struct { Steps []any `json:"Steps"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut.Steps) } @@ -115,7 +116,7 @@ func TestEMR_ListBootstrapActions(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) rec := doEMRRequest(t, h, "ListBootstrapActions", map[string]any{ "ClusterId": createOut.JobFlowID, @@ -127,7 +128,7 @@ func TestEMR_ListBootstrapActions(t *testing.T) { BootstrapActions []any `json:"BootstrapActions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.BootstrapActions) } @@ -163,7 +164,7 @@ func TestEMR_CancelSteps(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) clusterID := tt.clusterID if clusterID == "" { @@ -181,7 +182,7 @@ func TestEMR_CancelSteps(t *testing.T) { var out struct { CancelStepsInfoList []any `json:"CancelStepsInfoList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.CancelStepsInfoList) } }) @@ -199,7 +200,7 @@ func TestSteps(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) clusterID := create.JobFlowID addRec := doEMRRequest(t, h, "AddJobFlowSteps", map[string]any{ @@ -222,7 +223,7 @@ func TestSteps(t *testing.T) { var addOut struct { StepIDs []string `json:"StepIds"` } - require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addOut)) + require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &addOut, jsonx.V1())) require.Len(t, addOut.StepIDs, 2) assert.NotEmpty(t, addOut.StepIDs[0]) @@ -234,7 +235,7 @@ func TestSteps(t *testing.T) { ID string `json:"Id"` } `json:"Steps"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Steps, 2) descRec := doEMRRequest(t, h, "DescribeStep", map[string]any{ @@ -332,7 +333,7 @@ func TestListBootstrapActions_RoundTrip(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) listRec := doEMRRequest(t, h, "ListBootstrapActions", map[string]any{ "ClusterId": createOut.JobFlowID, @@ -346,7 +347,7 @@ func TestListBootstrapActions_RoundTrip(t *testing.T) { Args []string `json:"Args"` } `json:"BootstrapActions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) if tt.wantActions == nil { assert.Empty(t, listOut.BootstrapActions) @@ -423,7 +424,7 @@ func TestCancelSteps_ReturnsPerStepInfo(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) // List steps to get IDs listRec := doEMRRequest(t, h, "ListSteps", map[string]any{"ClusterId": create.JobFlowID}) @@ -434,7 +435,7 @@ func TestCancelSteps_ReturnsPerStepInfo(t *testing.T) { ID string `json:"Id"` } `json:"Steps"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.Steps) stepID := listOut.Steps[0].ID @@ -450,7 +451,7 @@ func TestCancelSteps_ReturnsPerStepInfo(t *testing.T) { Status string `json:"Status"` } `json:"CancelStepsInfoList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.CancelStepsInfoList, 1) assert.Equal(t, stepID, out.CancelStepsInfoList[0].StepID) assert.NotEmpty(t, out.CancelStepsInfoList[0].Status) diff --git a/services/emr/handler_studios_test.go b/services/emr/handler_studios_test.go index 94c40ea677..c4e0983b05 100644 --- a/services/emr/handler_studios_test.go +++ b/services/emr/handler_studios_test.go @@ -2,7 +2,7 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -52,7 +53,7 @@ func TestEMR_Studio(t *testing.T) { var out struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.StudioID }, @@ -112,7 +113,7 @@ func TestEMR_Studio(t *testing.T) { StudioID string `json:"StudioId"` URL string `json:"Url"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.StudioID) assert.NotEmpty(t, out.URL) } @@ -178,7 +179,7 @@ func TestEMR_StudioSessionMapping(t *testing.T) { var studioOut struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(studioRec.Body.Bytes(), &studioOut)) + require.NoError(t, json.Unmarshal(studioRec.Body.Bytes(), &studioOut, jsonx.V1())) studioID = studioOut.StudioID var rec *httptest.ResponseRecorder @@ -253,7 +254,7 @@ func TestEMR_DeleteStudio_CascadesSessionMappings(t *testing.T) { var studioOut struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(studioRec.Body.Bytes(), &studioOut)) + require.NoError(t, json.Unmarshal(studioRec.Body.Bytes(), &studioOut, jsonx.V1())) // Create a session mapping. mappingRec := doEMRRequest(t, h, "CreateStudioSessionMapping", map[string]any{ @@ -296,7 +297,7 @@ func TestStudio_DescribeAndList(t *testing.T) { var create struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) studioID := create.StudioID descRec := doEMRRequest(t, h, "DescribeStudio", map[string]any{"StudioId": studioID}) @@ -307,7 +308,7 @@ func TestStudio_DescribeAndList(t *testing.T) { Name string `json:"Name"` } `json:"Studio"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "my-studio", desc.Studio.Name) listRec := doEMRRequest(t, h, "ListStudios", map[string]any{}) @@ -318,7 +319,7 @@ func TestStudio_DescribeAndList(t *testing.T) { Name string `json:"Name"` } `json:"Studios"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Studios, 1) } @@ -340,7 +341,7 @@ func TestStudioSessionMapping_GetUpdateList(t *testing.T) { var create struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) studioID := create.StudioID doEMRRequest(t, h, "CreateStudioSessionMapping", map[string]any{ @@ -358,7 +359,7 @@ func TestStudioSessionMapping_GetUpdateList(t *testing.T) { SessionPolicyArn string `json:"SessionPolicyArn"` } `json:"SessionMappings"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.SessionMappings, 1) updateRec := doEMRRequest(t, h, "UpdateStudioSessionMapping", map[string]any{ @@ -381,7 +382,7 @@ func TestStudioSessionMapping_GetUpdateList(t *testing.T) { SessionPolicyArn string `json:"SessionPolicyArn"` } `json:"SessionMapping"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "arn:policy:new", getOut.SessionMapping.SessionPolicyArn) } @@ -502,13 +503,13 @@ func TestDescribeStudio_TagsEmptyNotAbsent(t *testing.T) { var create struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeStudio", map[string]any{"StudioId": create.StudioID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) studio, ok := raw["Studio"].(map[string]any) require.True(t, ok, "Studio must be an object") @@ -538,13 +539,13 @@ func TestDescribeStudio_SubnetIdsEmptyNotAbsent(t *testing.T) { var create struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "DescribeStudio", map[string]any{"StudioId": create.StudioID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) studio := raw["Studio"].(map[string]any) @@ -573,7 +574,7 @@ func TestListStudioSessionMappings_EmptyNotNull(t *testing.T) { var create struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "ListStudioSessionMappings", map[string]any{ "StudioId": create.StudioID, @@ -581,7 +582,7 @@ func TestListStudioSessionMappings_EmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) mappings, hasKey := raw["SessionMappings"] assert.True(t, hasKey, "ListStudioSessionMappings must include 'SessionMappings' key") @@ -615,7 +616,7 @@ func TestWireShape_CreateStudio_Description(t *testing.T) { var out struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeStudio", map[string]any{"StudioId": out.StudioID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -625,7 +626,7 @@ func TestWireShape_CreateStudio_Description(t *testing.T) { Description string `json:"Description"` } `json:"Studio"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "a test studio", desc.Studio.Description, "CreateStudio must forward Description to the created Studio") } @@ -654,7 +655,7 @@ func TestWireShape_UpdateStudio_AppliesSubnetIds(t *testing.T) { var created struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) updateRec := doEMRRequest(t, h, "UpdateStudio", map[string]any{ "StudioId": created.StudioID, @@ -670,7 +671,7 @@ func TestWireShape_UpdateStudio_AppliesSubnetIds(t *testing.T) { SubnetIDs []string `json:"SubnetIds"` } `json:"Studio"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.ElementsMatch(t, []string{"subnet-1", "subnet-2"}, desc.Studio.SubnetIDs, "UpdateStudio must apply SubnetIds from the request, not discard them") } diff --git a/services/emr/handler_tags_test.go b/services/emr/handler_tags_test.go index 8129d90cec..da3a3376e9 100644 --- a/services/emr/handler_tags_test.go +++ b/services/emr/handler_tags_test.go @@ -2,13 +2,14 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -37,7 +38,7 @@ func TestEMR_AddAndRemoveTags(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) addRec := doEMRRequest(t, h, "AddTags", map[string]any{ "ResourceId": createOut.JobFlowID, @@ -75,7 +76,7 @@ func TestEMR_ListTagsForResource(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) return createOut.JobFlowID }, @@ -96,7 +97,7 @@ func TestEMR_ListTagsForResource(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) return createOut.JobFlowID }, @@ -131,7 +132,7 @@ func TestEMR_ListTagsForResource(t *testing.T) { var tagOut struct { Tags []emr.Tag `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagOut, jsonx.V1())) tt.checkTags(t, tagOut.Tags) } }) @@ -270,7 +271,7 @@ func TestListTagsForResource_ReturnsList(t *testing.T) { var createOut struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) listRec := doEMRRequest(t, h, "ListTagsForResource", map[string]any{ "ResourceId": createOut.JobFlowID, @@ -280,7 +281,7 @@ func TestListTagsForResource_ReturnsList(t *testing.T) { var out struct { Tags []emr.Tag `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Tags, 2) // Verify sorted order. assert.Equal(t, "a", out.Tags[0].Key) diff --git a/services/emr/handler_test.go b/services/emr/handler_test.go index b0db401029..a92ae1b82d 100644 --- a/services/emr/handler_test.go +++ b/services/emr/handler_test.go @@ -3,7 +3,7 @@ package emr_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -42,7 +43,7 @@ func newTestHandler(t *testing.T) *emr.Handler { func doEMRRequest(t *testing.T, h *emr.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -270,7 +271,7 @@ func TestEMR_ExtractResource(t *testing.T) { h := newTestHandler(t) e := echo.New() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -469,7 +470,7 @@ func TestErrValidationMapping(t *testing.T) { var errBody struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) // EMR's real error model has only InvalidRequestException (client fault) // and InternalServerException (server fault) -- no ValidationException. assert.Equal(t, "InvalidRequestException", errBody.Type) diff --git a/services/emr/handler_wire_shape_test.go b/services/emr/handler_wire_shape_test.go index bc82328d83..0448a2048e 100644 --- a/services/emr/handler_wire_shape_test.go +++ b/services/emr/handler_wire_shape_test.go @@ -1,7 +1,7 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( emrtypes "github.com/aws/aws-sdk-go-v2/service/emr/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestWireShape_ListClusters_IncludesTimeline verifies ListClusters' per-cluster @@ -39,7 +41,7 @@ func TestWireShape_ListClusters_IncludesTimeline(t *testing.T) { } `json:"Status"` } `json:"Clusters"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Clusters, 1) assert.NotZero(t, out.Clusters[0].Status.Timeline.CreationDateTime) assert.NotZero(t, out.Clusters[0].Status.Timeline.ReadyDateTime) @@ -60,7 +62,7 @@ func TestWireShape_ModifyInstanceFleet_AppliesCapacities(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) addRec := doEMRRequest(t, h, "AddInstanceFleet", map[string]any{ "ClusterId": create.JobFlowID, @@ -76,7 +78,7 @@ func TestWireShape_ModifyInstanceFleet_AppliesCapacities(t *testing.T) { var added struct { InstanceFleetID string `json:"InstanceFleetId"` } - require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &added)) + require.NoError(t, json.Unmarshal(addRec.Body.Bytes(), &added, jsonx.V1())) modRec := doEMRRequest(t, h, "ModifyInstanceFleet", map[string]any{ "ClusterId": create.JobFlowID, @@ -100,7 +102,7 @@ func TestWireShape_ModifyInstanceFleet_AppliesCapacities(t *testing.T) { ProvisionedSpotCapacity int `json:"ProvisionedSpotCapacity"` } `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.InstanceFleets, 1) f := out.InstanceFleets[0] assert.Equal(t, 8, f.TargetOnDemandCapacity) @@ -134,7 +136,7 @@ func TestWireShape_CancelSteps_RealEnumValues(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) listRec := doEMRRequest(t, h, "ListSteps", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, listRec.Code) @@ -144,7 +146,7 @@ func TestWireShape_CancelSteps_RealEnumValues(t *testing.T) { ID string `json:"Id"` } `json:"Steps"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.Steps) stepID := listOut.Steps[0].ID @@ -162,7 +164,7 @@ func TestWireShape_CancelSteps_RealEnumValues(t *testing.T) { Status string `json:"Status"` } `json:"CancelStepsInfoList"` } - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstOut)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &firstOut, jsonx.V1())) require.Len(t, firstOut.CancelStepsInfoList, 1) assert.Equal(t, "SUBMITTED", firstOut.CancelStepsInfoList[0].Status) @@ -180,7 +182,7 @@ func TestWireShape_CancelSteps_RealEnumValues(t *testing.T) { Reason string `json:"Reason"` } `json:"CancelStepsInfoList"` } - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondOut)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &secondOut, jsonx.V1())) require.Len(t, secondOut.CancelStepsInfoList, 1) assert.Equal(t, "FAILED", secondOut.CancelStepsInfoList[0].Status) assert.NotEmpty(t, secondOut.CancelStepsInfoList[0].Reason) @@ -207,7 +209,7 @@ func TestWireShape_NotebookExecution_EpochTimestamps(t *testing.T) { var started struct { NotebookExecutionID string `json:"NotebookExecutionId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeNotebookExecution", map[string]any{ "NotebookExecutionId": started.NotebookExecutionID, @@ -219,7 +221,7 @@ func TestWireShape_NotebookExecution_EpochTimestamps(t *testing.T) { StartTime float64 `json:"StartTime"` } `json:"NotebookExecution"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.NotZero(t, out.NotebookExecution.StartTime) } @@ -239,7 +241,7 @@ func TestWireShape_GetOnClusterAppUIPresignedURL_FieldName(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "GetOnClusterAppUIPresignedURL", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, rec.Code) @@ -248,13 +250,13 @@ func TestWireShape_GetOnClusterAppUIPresignedURL_FieldName(t *testing.T) { PresignedURL string `json:"PresignedURL"` PresignedURLReady bool `json:"PresignedURLReady"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.PresignedURL) assert.True(t, out.PresignedURLReady) // The old, wrong field name must not be the only thing populated. var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.NotContains(t, raw, "URL") } @@ -274,7 +276,7 @@ func TestWireShape_GetPersistentAppUIPresignedURL_ReadyFlag(t *testing.T) { PresignedURL string `json:"PresignedURL"` PresignedURLReady bool `json:"PresignedURLReady"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.PresignedURL) assert.True(t, out.PresignedURLReady) } @@ -297,7 +299,7 @@ func TestWireShape_RunJobFlow_JobFlowRole(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -309,7 +311,7 @@ func TestWireShape_RunJobFlow_JobFlowRole(t *testing.T) { } `json:"Ec2InstanceAttributes"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "EMR_EC2_DefaultRole", out.Cluster.Ec2InstanceAttributes.IamInstanceProfile) } @@ -338,7 +340,7 @@ func TestWireShape_RunJobFlow_InlinePolicies(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) msRec := doEMRRequest(t, h, "GetManagedScalingPolicy", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, msRec.Code) @@ -350,7 +352,7 @@ func TestWireShape_RunJobFlow_InlinePolicies(t *testing.T) { } `json:"ComputeLimits"` } `json:"ManagedScalingPolicy"` } - require.NoError(t, json.Unmarshal(msRec.Body.Bytes(), &msOut)) + require.NoError(t, json.Unmarshal(msRec.Body.Bytes(), &msOut, jsonx.V1())) assert.Equal(t, 10, msOut.ManagedScalingPolicy.ComputeLimits.MaximumCapacityUnits) atRec := doEMRRequest(t, h, "GetAutoTerminationPolicy", map[string]any{"ClusterId": create.JobFlowID}) @@ -361,7 +363,7 @@ func TestWireShape_RunJobFlow_InlinePolicies(t *testing.T) { IdleTimeout int64 `json:"IdleTimeout"` } `json:"AutoTerminationPolicy"` } - require.NoError(t, json.Unmarshal(atRec.Body.Bytes(), &atOut)) + require.NoError(t, json.Unmarshal(atRec.Body.Bytes(), &atOut, jsonx.V1())) assert.Equal(t, int64(3600), atOut.AutoTerminationPolicy.IdleTimeout) } @@ -382,13 +384,13 @@ func TestWireShape_GetManagedScalingPolicy_OmitsFieldWhenUnset(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "GetManagedScalingPolicy", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.NotContains(t, raw, "ManagedScalingPolicy") } @@ -406,13 +408,13 @@ func TestWireShape_GetAutoTerminationPolicy_OmitsFieldWhenUnset(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &create, jsonx.V1())) rec := doEMRRequest(t, h, "GetAutoTerminationPolicy", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.NotContains(t, raw, "AutoTerminationPolicy") } @@ -436,7 +438,7 @@ func TestWireShape_AddTags_StudioResource(t *testing.T) { var created struct { StudioID string `json:"StudioId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) addRec := doEMRRequest(t, h, "AddTags", map[string]any{ "ResourceId": created.StudioID, @@ -453,7 +455,7 @@ func TestWireShape_AddTags_StudioResource(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Tags, 1) assert.Equal(t, "env", listOut.Tags[0].Key) assert.Equal(t, "prod", listOut.Tags[0].Value) @@ -470,7 +472,7 @@ func TestWireShape_AddTags_StudioResource(t *testing.T) { var listOut2 struct { Tags []struct{} `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2, jsonx.V1())) assert.Empty(t, listOut2.Tags) } @@ -501,7 +503,7 @@ func TestWireShape_RunJobFlow_InstanceFleets(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -511,7 +513,7 @@ func TestWireShape_RunJobFlow_InstanceFleets(t *testing.T) { InstanceCollectionType string `json:"InstanceCollectionType"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "INSTANCE_FLEET", descOut.Cluster.InstanceCollectionType) listRec := doEMRRequest(t, h, "ListInstanceFleets", map[string]any{"ClusterId": create.JobFlowID}) @@ -523,7 +525,7 @@ func TestWireShape_RunJobFlow_InstanceFleets(t *testing.T) { TargetOnDemandCapacity int `json:"TargetOnDemandCapacity"` } `json:"InstanceFleets"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.InstanceFleets, 1) assert.Equal(t, "primary", listOut.InstanceFleets[0].Name) assert.Equal(t, 1, listOut.InstanceFleets[0].TargetOnDemandCapacity) @@ -553,7 +555,7 @@ func TestWireShape_RunJobFlow_KerberosAttributesAndPlacementGroups(t *testing.T) var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -569,7 +571,7 @@ func TestWireShape_RunJobFlow_KerberosAttributesAndPlacementGroups(t *testing.T) } `json:"PlacementGroups"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "EC2.INTERNAL", out.Cluster.KerberosAttributes.Realm) require.Len(t, out.Cluster.PlacementGroups, 1) assert.Equal(t, "MASTER", out.Cluster.PlacementGroups[0].InstanceRole) @@ -607,7 +609,7 @@ func TestWireShape_RunJobFlow_OptionalClusterFields(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -629,7 +631,7 @@ func TestWireShape_RunJobFlow_OptionalClusterFields(t *testing.T) { } `json:"MonitoringConfiguration"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "arn:aws:kms:us-east-1:123456789012:key/abc", out.Cluster.LogEncryptionKmsKeyID) assert.Equal(t, "NONE", out.Cluster.RepoUpgradeOnBoot) @@ -664,7 +666,7 @@ func TestWireShape_RunJobFlow_AutoTerminate(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, descRec.Code) @@ -675,7 +677,7 @@ func TestWireShape_RunJobFlow_AutoTerminate(t *testing.T) { KeepJobFlowAliveWhenNoSteps bool `json:"KeepJobFlowAliveWhenNoSteps"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.True(t, out.Cluster.KeepJobFlowAliveWhenNoSteps) assert.False(t, out.Cluster.AutoTerminate) } @@ -702,7 +704,7 @@ func TestWireShape_ListClusters_NoFabricatedReleaseLabel(t *testing.T) { var raw struct { Clusters []map[string]any `json:"Clusters"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.Clusters, 1) _, hasReleaseLabel := raw.Clusters[0]["ReleaseLabel"] diff --git a/services/emr/janitor_test.go b/services/emr/janitor_test.go index d82b23e24b..4a9d0ed2ac 100644 --- a/services/emr/janitor_test.go +++ b/services/emr/janitor_test.go @@ -2,7 +2,7 @@ package emr_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -250,7 +251,7 @@ func TestEMR_Handler_Reset(t *testing.T) { Clusters []any `json:"Clusters"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Clusters) } diff --git a/services/emr/kerberos_secrets_test.go b/services/emr/kerberos_secrets_test.go index a5fe937663..572839fd5b 100644 --- a/services/emr/kerberos_secrets_test.go +++ b/services/emr/kerberos_secrets_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDescribeCluster_KerberosAttributesOmitPasswords(t *testing.T) { @@ -41,7 +43,7 @@ func TestDescribeCluster_KerberosAttributesOmitPasswords(t *testing.T) { var create struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &create, jsonx.V1())) desc := doEMRRequest(t, h, "DescribeCluster", map[string]any{"ClusterId": create.JobFlowID}) require.Equal(t, http.StatusOK, desc.Code) @@ -51,7 +53,7 @@ func TestDescribeCluster_KerberosAttributesOmitPasswords(t *testing.T) { KerberosAttributes map[string]any `json:"KerberosAttributes"` } `json:"Cluster"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &out, jsonx.V1())) ka := out.Cluster.KerberosAttributes assert.Equal(t, "EC2.INTERNAL", ka["Realm"]) diff --git a/services/emr/models.go b/services/emr/models.go index 79d00e007c..06bff5463d 100644 --- a/services/emr/models.go +++ b/services/emr/models.go @@ -1,8 +1,11 @@ package emr import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // regionContextKey is the context key under which the per-request AWS region is stored. @@ -585,13 +588,13 @@ type KerberosAttributes struct { func (k KerberosAttributes) MarshalJSON() ([]byte, error) { type plain KerberosAttributes - raw, err := json.Marshal(plain(k)) + raw, err := json.Marshal(plain(k), jsonx.V1()) if err != nil { return nil, err } - var fields map[string]json.RawMessage - if err = json.Unmarshal(raw, &fields); err != nil { + var fields map[string]jsontext.Value + if err = json.Unmarshal(raw, &fields, jsonx.V1()); err != nil { return nil, err } @@ -599,7 +602,7 @@ func (k KerberosAttributes) MarshalJSON() ([]byte, error) { delete(fields, secret) } - return json.Marshal(fields) + return json.Marshal(fields, jsonx.V1()) } // PlacementGroupConfig is the placement group configuration for a single diff --git a/services/emr/persistence.go b/services/emr/persistence.go index 0773a53a33..a7abc31f6a 100644 --- a/services/emr/persistence.go +++ b/services/emr/persistence.go @@ -2,7 +2,7 @@ package emr import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "time" @@ -89,7 +89,7 @@ func regionOnlyDTOKeyFn[V any](d *regionOnlyDTO[V]) string { return d.Region } // guards against decoding a snapshot from an incompatible (older or newer) // build of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ArnIndex map[string]map[string]string `json:"arnIndex"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -321,7 +321,7 @@ func unwrapRegionOnlyDTOs[V any](dtos *store.Table[regionOnlyDTO[V]], setRegion // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/emr/request_validation_test.go b/services/emr/request_validation_test.go index 2364c2b1dc..fbaf8d943b 100644 --- a/services/emr/request_validation_test.go +++ b/services/emr/request_validation_test.go @@ -1,12 +1,14 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEMR_RequestValidation(t *testing.T) { @@ -78,13 +80,13 @@ func TestEMR_RequestValidation(t *testing.T) { var out struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(created.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(created.Body.Bytes(), &out, jsonx.V1())) rec := doEMRRequest(t, h, tt.action, tt.body(out.JobFlowID)) require.Equal(t, http.StatusBadRequest, rec.Code) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errOut["__type"]) assert.Contains(t, errOut["message"], tt.wantMsg) assert.NotContains(t, errOut["message"], "Exception:") diff --git a/services/emr/security_configurations.go b/services/emr/security_configurations.go index 929463d5e7..19d5e22f80 100644 --- a/services/emr/security_configurations.go +++ b/services/emr/security_configurations.go @@ -2,12 +2,13 @@ package emr import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -63,7 +64,7 @@ func (b *InMemoryBackend) CreateSecurityConfiguration( return nil, fmt.Errorf("%w: Name is required", ErrValidation) } - if !json.Valid([]byte(securityConfig)) { + if !jsontext.Value([]byte(securityConfig)).IsValid(jsonx.V1()) { return nil, fmt.Errorf("%w: SecurityConfiguration must be valid JSON", ErrValidation) } diff --git a/services/emr/validation.go b/services/emr/validation.go index ad620798de..e253b80477 100644 --- a/services/emr/validation.go +++ b/services/emr/validation.go @@ -1,11 +1,12 @@ package emr import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -62,7 +63,7 @@ func checkMarker(body []byte) error { NextToken string `json:"NextToken"` } - if json.Unmarshal(body, &in) == nil { + if json.Unmarshal(body, &in, jsonx.V1()) == nil { for _, tok := range []string{in.Marker, in.NextToken} { if page.ValidateToken(tok) != nil { return fmt.Errorf("%w: Invalid marker", ErrValidation) diff --git a/services/emr/wire_field_fixes_test.go b/services/emr/wire_field_fixes_test.go index f8efa367bb..cdfdcb8b84 100644 --- a/services/emr/wire_field_fixes_test.go +++ b/services/emr/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package emr_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http/httptest" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/emr" ) @@ -250,7 +251,7 @@ func TestWireShape_Cluster_TerminatedAt_NotOnWire(t *testing.T) { var created struct { JobFlowID string `json:"JobFlowId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) termRec := doEMRRequest(t, h, "TerminateJobFlows", map[string]any{"JobFlowIds": []string{created.JobFlowID}}) require.Equal(t, 200, termRec.Code) @@ -261,7 +262,7 @@ func TestWireShape_Cluster_TerminatedAt_NotOnWire(t *testing.T) { var raw struct { Cluster map[string]any `json:"Cluster"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) _, hasTerminatedAt := raw.Cluster["TerminatedAt"] assert.False(t, hasTerminatedAt, "Cluster must not carry a TerminatedAt field on the wire -- real types.Cluster has no such member") @@ -331,7 +332,7 @@ func TestWireShape_StudioSummary_NoFabricatedFields(t *testing.T) { var raw struct { Studios []map[string]any `json:"Studios"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.Studios, 1) _, hasArn := raw.Studios[0]["StudioArn"] @@ -431,7 +432,7 @@ func TestWireShape_DescribePersistentAppUI_RealShape(t *testing.T) { JobFlowID string `json:"JobFlowId"` ClusterArn string `json:"ClusterArn"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cluster)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cluster, jsonx.V1())) createUIRec := doEMRRequest(t, h, "CreatePersistentAppUI", map[string]any{ "TargetResourceArn": cluster.ClusterArn, @@ -441,7 +442,7 @@ func TestWireShape_DescribePersistentAppUI_RealShape(t *testing.T) { var createdUI struct { PersistentAppUIID string `json:"PersistentAppUIId"` } - require.NoError(t, json.Unmarshal(createUIRec.Body.Bytes(), &createdUI)) + require.NoError(t, json.Unmarshal(createUIRec.Body.Bytes(), &createdUI, jsonx.V1())) descRec := doEMRRequest(t, h, "DescribePersistentAppUI", map[string]any{ "PersistentAppUIId": createdUI.PersistentAppUIID, @@ -451,7 +452,7 @@ func TestWireShape_DescribePersistentAppUI_RealShape(t *testing.T) { var raw struct { PersistentAppUI map[string]any `json:"PersistentAppUI"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) _, hasArn := raw.PersistentAppUI["TargetResourceArn"] _, hasRole := raw.PersistentAppUI["RuntimeRoleEnabledCluster"] diff --git a/services/emrserverless/handler.go b/services/emrserverless/handler.go index 5adc5a7192..9c9a691adc 100644 --- a/services/emrserverless/handler.go +++ b/services/emrserverless/handler.go @@ -1,7 +1,7 @@ package emrserverless import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -771,7 +772,7 @@ type createApplicationResponse struct { func (h *Handler) handleCreateApplication(c *echo.Context, body []byte) error { var in createApplicationBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -879,7 +880,7 @@ func applyAutoConfigDefaults(extra map[string]any, whenAbsent bool) { func (h *Handler) handleUpdateApplication(c *echo.Context, applicationID string, body []byte) error { var in updateApplicationBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -974,7 +975,7 @@ type startJobRunResponse struct { func (h *Handler) handleStartJobRun(c *echo.Context, applicationID string, body []byte) error { var in startJobRunBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } @@ -1189,7 +1190,7 @@ type tagResourceBody struct { func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body []byte) error { var in tagResourceBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } diff --git a/services/emrserverless/handler_applications_test.go b/services/emrserverless/handler_applications_test.go index 65d9043c01..fa63b2c466 100644 --- a/services/emrserverless/handler_applications_test.go +++ b/services/emrserverless/handler_applications_test.go @@ -1,7 +1,7 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -34,7 +35,7 @@ func createAppWithArch(t *testing.T, h *emrserverless.Handler, name, releaseLabe require.Equal(t, http.StatusOK, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) id := out["applicationId"] require.NotEmpty(t, id) @@ -146,7 +147,7 @@ func TestHandler_CreateApplication_Architecture(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) app, _ := out["application"].(map[string]any) if tt.wantInOutput { diff --git a/services/emrserverless/handler_job_runs_test.go b/services/emrserverless/handler_job_runs_test.go index ac555a3f0c..f39789287c 100644 --- a/services/emrserverless/handler_job_runs_test.go +++ b/services/emrserverless/handler_job_runs_test.go @@ -1,7 +1,7 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -31,7 +32,7 @@ func startJobRunWithMode(t *testing.T, h *emrserverless.Handler, appID, mode str require.Equal(t, http.StatusOK, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) id := out["jobRunId"] require.NotEmpty(t, id) @@ -151,7 +152,7 @@ func TestHandler_StartJobRun_DefaultsModeToBATCH(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jr, _ := out["jobRun"].(map[string]any) assert.Equal(t, tt.expectedMode, jr["mode"]) }) @@ -423,7 +424,7 @@ func TestHandler_GetJobRun_HasAttemptAndReleaseLabel(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) jr, _ := out["jobRun"].(map[string]any) attempt, hasAttempt := jr["attempt"] diff --git a/services/emrserverless/handler_list_summary_test.go b/services/emrserverless/handler_list_summary_test.go index 8f5e77ae1f..b9fcf48111 100644 --- a/services/emrserverless/handler_list_summary_test.go +++ b/services/emrserverless/handler_list_summary_test.go @@ -1,7 +1,7 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -144,7 +145,7 @@ func listSingleEMR( require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp[listKey].([]any) require.True(t, ok, "%s response missing %q list", path, listKey) diff --git a/services/emrserverless/handler_sessions_test.go b/services/emrserverless/handler_sessions_test.go index da14757795..28fcb47b54 100644 --- a/services/emrserverless/handler_sessions_test.go +++ b/services/emrserverless/handler_sessions_test.go @@ -1,7 +1,7 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -280,7 +281,7 @@ func TestHandler_SessionFilteringAndPersistence(t *testing.T) { var filtered struct { Sessions []map[string]any `json:"sessions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtered)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtered, jsonx.V1())) require.Len(t, filtered.Sessions, 1) assert.Equal(t, emrserverless.SessionStateTerminated, filtered.Sessions[0]["state"]) diff --git a/services/emrserverless/handler_test.go b/services/emrserverless/handler_test.go index 4b8a071ab9..0a1195cbbf 100644 --- a/services/emrserverless/handler_test.go +++ b/services/emrserverless/handler_test.go @@ -2,7 +2,7 @@ package emrserverless_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *emrserverless.Handler, method, path string, body var reqBody *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) } else { @@ -50,7 +51,7 @@ func doRequest(t *testing.T, h *emrserverless.Handler, method, path string, body func mustUnmarshal(t *testing.T, rec *httptest.ResponseRecorder, v any) { t.Helper() - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1())) } // createApp is a test helper that creates an application and returns its ID. @@ -623,7 +624,7 @@ func TestHandlerReset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) apps := out["applications"].([]any) assert.Empty(t, apps) } diff --git a/services/emrserverless/multi_region_test.go b/services/emrserverless/multi_region_test.go index 77b70dd9a8..e3e3ef2f2a 100644 --- a/services/emrserverless/multi_region_test.go +++ b/services/emrserverless/multi_region_test.go @@ -2,7 +2,7 @@ package emrserverless_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/emrserverless/persistence.go b/services/emrserverless/persistence.go index fd464127c0..32b048a6fc 100644 --- a/services/emrserverless/persistence.go +++ b/services/emrserverless/persistence.go @@ -2,10 +2,12 @@ package emrserverless import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -33,7 +35,7 @@ const emrserverlessSnapshotVersion = 1 // against decoding a snapshot from an incompatible (older or newer) build of // this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` SessionTokens map[string]map[string]string `json:"sessionTokens"` ApplicationTokens map[string]string `json:"applicationTokens"` JobRunTokens map[string]map[string]string `json:"jobRunTokens"` @@ -70,7 +72,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "emrserverless: Snapshot marshal failure", "error", err) diff --git a/services/emrserverless/persistence_test.go b/services/emrserverless/persistence_test.go index 582f2d9acf..e32e66121d 100644 --- a/services/emrserverless/persistence_test.go +++ b/services/emrserverless/persistence_test.go @@ -1,7 +1,7 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/emrserverless" ) @@ -168,10 +169,10 @@ func Test_Persistence_VersionMismatch(t *testing.T) { require.NotNil(t, snap) var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) tt.mutateSnap(t, raw) - mutated, err := json.Marshal(raw) + mutated, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) // Restore into a backend that already holds unrelated state, to diff --git a/services/emrserverless/request_validation_test.go b/services/emrserverless/request_validation_test.go index a77b459cd0..3eca0f0c42 100644 --- a/services/emrserverless/request_validation_test.go +++ b/services/emrserverless/request_validation_test.go @@ -1,12 +1,14 @@ package emrserverless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRequestValidation(t *testing.T) { @@ -47,7 +49,7 @@ func TestRequestValidation(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["code"]) assert.Contains(t, out["message"], tt.wantMsg) assert.NotContains(t, out["message"], "Exception:") @@ -73,7 +75,7 @@ func TestJobRunLifecycle(t *testing.T) { State string `json:"state"` } `json:"jobRun"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) got = append(got, out.JobRun.State) } diff --git a/services/emrserverless/session_handler.go b/services/emrserverless/session_handler.go index f81f3daa86..3e2f9a0be5 100644 --- a/services/emrserverless/session_handler.go +++ b/services/emrserverless/session_handler.go @@ -1,7 +1,7 @@ package emrserverless import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -9,6 +9,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type startSessionBody struct { @@ -23,7 +25,7 @@ type startSessionBody struct { func (h *Handler) handleStartSession(c *echo.Context, applicationID string, body []byte) error { var in startSessionBody if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errResp("ValidationException", "invalid request body")) } } diff --git a/services/eventbridge/delivery.go b/services/eventbridge/delivery.go index de2e349e1b..e5fd72cb07 100644 --- a/services/eventbridge/delivery.go +++ b/services/eventbridge/delivery.go @@ -2,7 +2,7 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "strconv" @@ -11,6 +11,7 @@ import ( "time" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/google/uuid" @@ -675,7 +676,7 @@ func sendToDLQ( return } - payload, _ := json.Marshal(envelope) + payload, _ := json.Marshal(envelope, jsonx.V1()) var err error if withAttrs, ok := dt.SQS.(SQSAttributeSender); ok { @@ -732,7 +733,7 @@ func indexedRulesForEvent( // buildEventEnvelope creates a JSON string representing the normalized event for pattern matching. func buildEventEnvelope(entry EventEntry) string { - b, _ := json.Marshal(buildEventEnvelopeMap(entry)) + b, _ := json.Marshal(buildEventEnvelopeMap(entry), jsonx.V1()) return string(b) } @@ -760,7 +761,7 @@ func buildEventEnvelopeMap(entry EventEntry) map[string]any { if entry.Detail != "" { var detail map[string]any - switch err := json.Unmarshal([]byte(entry.Detail), &detail); { + switch err := json.Unmarshal([]byte(entry.Detail), &detail, jsonx.V1()); { case err != nil: envelope["detail"] = entry.Detail case detail == nil: @@ -969,7 +970,7 @@ func buildPayload(target *Target, envelope map[string]any) string { return applyInputTransformer(target.InputTransformer, envelope) } - b, _ := json.Marshal(envelope) + b, _ := json.Marshal(envelope, jsonx.V1()) return string(b) } @@ -987,7 +988,7 @@ func parseDeliveryDetail(entry EventEntry) any { } var d any - if err := json.Unmarshal([]byte(entry.Detail), &d); err != nil { + if err := json.Unmarshal([]byte(entry.Detail), &d, jsonx.V1()); err != nil { return entry.Detail } @@ -1157,7 +1158,7 @@ func entryFromEnvelope(envelope map[string]any, busName string) EventEntry { } if detail, ok := envelope["detail"]; ok { - if b, err := json.Marshal(detail); err == nil { + if b, err := json.Marshal(detail, jsonx.V1()); err == nil { entry.Detail = string(b) } } diff --git a/services/eventbridge/delivery_api_destination.go b/services/eventbridge/delivery_api_destination.go index 944e359411..952dedfd52 100644 --- a/services/eventbridge/delivery_api_destination.go +++ b/services/eventbridge/delivery_api_destination.go @@ -2,7 +2,7 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httpclient" "github.com/blackbirdworks/gopherstack/pkgs/httptarget" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -125,7 +126,7 @@ func mergeBodyParameters(payload string, params []ConnectionBodyParameter) strin } var obj map[string]any - if err := json.Unmarshal([]byte(payload), &obj); err != nil || obj == nil { + if err := json.Unmarshal([]byte(payload), &obj, jsonx.V1()); err != nil || obj == nil { return payload } @@ -133,7 +134,7 @@ func mergeBodyParameters(payload string, params []ConnectionBodyParameter) strin obj[p.Key] = p.Value } - merged, err := json.Marshal(obj) + merged, err := json.Marshal(obj, jsonx.V1()) if err != nil { return payload } @@ -253,7 +254,7 @@ func fetchOAuthToken(ctx context.Context, oauth *ResolvedOAuth) (string, error) var tokenResp struct { AccessToken string `json:"access_token"` } - if err = json.Unmarshal(data, &tokenResp); err != nil { + if err = json.Unmarshal(data, &tokenResp, jsonx.V1()); err != nil { return "", err } if tokenResp.AccessToken == "" { diff --git a/services/eventbridge/delivery_api_destination_test.go b/services/eventbridge/delivery_api_destination_test.go index a1502b59c7..f49253a917 100644 --- a/services/eventbridge/delivery_api_destination_test.go +++ b/services/eventbridge/delivery_api_destination_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -333,7 +334,7 @@ func TestAPIDestinationDelivery_BodyMerge(t *testing.T) { require.Len(t, reqs, 1) var got map[string]any - require.NoError(t, json.Unmarshal([]byte(reqs[0].body), &got)) + require.NoError(t, json.Unmarshal([]byte(reqs[0].body), &got, jsonx.V1())) assert.Equal(t, "world", got["hello"]) assert.Equal(t, "yes", got["injected"]) } diff --git a/services/eventbridge/delivery_ssm_appsync.go b/services/eventbridge/delivery_ssm_appsync.go index 2cd4275c7f..b5ccf0c0f6 100644 --- a/services/eventbridge/delivery_ssm_appsync.go +++ b/services/eventbridge/delivery_ssm_appsync.go @@ -2,12 +2,13 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // arnParts is the field count of arn:partition:service:region:account:resource. @@ -111,7 +112,7 @@ func BuildSSMCommandRequest(target *Target, payload string) (SSMCommandRequest, var in ssmInput - _ = json.Unmarshal([]byte(payload), &in) + _ = json.Unmarshal([]byte(payload), &in, jsonx.V1()) name := in.DocumentName if name == "" { @@ -136,7 +137,7 @@ func BuildSSMAutomationRequest(target *Target, payload string) SSMAutomationRequ var raw map[string]any - _ = json.Unmarshal([]byte(payload), &raw) + _ = json.Unmarshal([]byte(payload), &raw, jsonx.V1()) params := raw if p, ok := raw["Parameters"].(map[string]any); ok { @@ -197,7 +198,7 @@ func deliverToAppSync(ctx context.Context, target *Target, dt DeliveryTargets, p var vars map[string]any - if err := json.Unmarshal([]byte(payload), &vars); err != nil { + if err := json.Unmarshal([]byte(payload), &vars, jsonx.V1()); err != nil { return logTargetErr(ctx, "AppSync", fmt.Errorf("payload is not a JSON object: %w", err)) } diff --git a/services/eventbridge/delivery_test.go b/services/eventbridge/delivery_test.go index 88a12d4266..1047c315c3 100644 --- a/services/eventbridge/delivery_test.go +++ b/services/eventbridge/delivery_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -442,8 +443,8 @@ func TestDelivery_SharedEventIDAcrossTargets(t *testing.T) { msg1 := sqsMock1.MessagesFor("arn:aws:sqs:us-east-1:000000000000:queue-a")[0] msg2 := sqsMock2.MessagesFor("arn:aws:sqs:us-east-1:000000000000:queue-b")[0] - require.NoError(t, json.Unmarshal([]byte(msg1), &id1)) - require.NoError(t, json.Unmarshal([]byte(msg2), &id2)) + require.NoError(t, json.Unmarshal([]byte(msg1), &id1, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(msg2), &id2, jsonx.V1())) assert.NotEmpty(t, id1.ID) assert.Equal(t, id1.ID, id2.ID, "all targets for the same rule+event must share the same event id") }) diff --git a/services/eventbridge/delivery_transform.go b/services/eventbridge/delivery_transform.go index 16b80cf33d..f056983f63 100644 --- a/services/eventbridge/delivery_transform.go +++ b/services/eventbridge/delivery_transform.go @@ -2,10 +2,13 @@ package eventbridge import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // inputPathsMapKeyRe validates InputPathsMap variable names per AWS spec. @@ -19,7 +22,7 @@ func applyInputPath(path string, envelope map[string]any) string { return "" } - b, _ := json.Marshal(val) + b, _ := json.Marshal(val, jsonx.V1()) return string(b) } @@ -175,9 +178,8 @@ func jsonEscapeInner(s string) string { // mirrors AWS, which does not HTML-escape input-transformer substitutions. func marshalNoHTMLEscape(v any) []byte { var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) - if err := enc.Encode(v); err != nil { + enc := jsontext.NewEncoder(&buf, jsonx.V1(), jsontext.EscapeForHTML(false)) + if err := json.MarshalEncode(enc, v); err != nil { return nil } diff --git a/services/eventbridge/envelope_map_test.go b/services/eventbridge/envelope_map_test.go index 473c3d1495..bdad4c8c5f 100644 --- a/services/eventbridge/envelope_map_test.go +++ b/services/eventbridge/envelope_map_test.go @@ -1,11 +1,13 @@ package eventbridge //nolint:testpackage // needs buildEventEnvelopeMap. import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestBuildEventEnvelopeMap_MatchesJSONRoundTrip(t *testing.T) { @@ -36,7 +38,7 @@ func TestBuildEventEnvelopeMap_MatchesJSONRoundTrip(t *testing.T) { t.Parallel() var viaJSON map[string]any - require.NoError(t, json.Unmarshal([]byte(buildEventEnvelope(tt.entry)), &viaJSON)) + require.NoError(t, json.Unmarshal([]byte(buildEventEnvelope(tt.entry)), &viaJSON, jsonx.V1())) require.Equal(t, viaJSON, buildEventEnvelopeMap(tt.entry)) }) } diff --git a/services/eventbridge/event_buses.go b/services/eventbridge/event_buses.go index 74bfc84bdc..e406502a61 100644 --- a/services/eventbridge/event_buses.go +++ b/services/eventbridge/event_buses.go @@ -2,12 +2,14 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // CreateEventBusParams holds the input for CreateEventBus. @@ -250,7 +252,7 @@ func (b *InMemoryBackend) PutPermission(ctx context.Context, input PutPermission // If a raw Policy JSON is provided it replaces the whole policy. if input.Policy != "" { var doc eventBusPolicyDocument - if err := json.Unmarshal([]byte(input.Policy), &doc); err == nil { + if err := json.Unmarshal([]byte(input.Policy), &doc, jsonx.V1()); err == nil { policy.Statements = make(map[string]*EventBusPolicyStatement, len(doc.Statement)) for _, s := range doc.Statement { policy.Statements[s.Sid] = s @@ -342,7 +344,7 @@ func (b *InMemoryBackend) GetEventBusPolicy(ctx context.Context, eventBusName st sort.Slice(stmts, func(i, j int) bool { return stmts[i].Sid < stmts[j].Sid }) - data, err := json.Marshal(eventBusPolicyDocument{Version: policyDocumentVersion, Statement: stmts}) + data, err := json.Marshal(eventBusPolicyDocument{Version: policyDocumentVersion, Statement: stmts}, jsonx.V1()) if err != nil { return "", err } @@ -386,7 +388,7 @@ func (b *InMemoryBackend) PutEventBusPolicy(ctx context.Context, input PutEventB } var doc eventBusPolicyDocument - if err := json.Unmarshal([]byte(input.Policy), &doc); err != nil { + if err := json.Unmarshal([]byte(input.Policy), &doc, jsonx.V1()); err != nil { return fmt.Errorf("%w: policy must be valid JSON: %w", ErrInvalidParameter, err) } diff --git a/services/eventbridge/event_buses_test.go b/services/eventbridge/event_buses_test.go index 387225135f..022361a923 100644 --- a/services/eventbridge/event_buses_test.go +++ b/services/eventbridge/event_buses_test.go @@ -3,7 +3,7 @@ package eventbridge_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -166,7 +167,7 @@ func TestGetEventBusPolicy_IsPolicyDocumentNotBareArray(t *testing.T) { Sid string `json:"Sid"` } `json:"Statement"` } - require.NoError(t, json.Unmarshal([]byte(policy), &doc), + require.NoError(t, json.Unmarshal([]byte(policy), &doc, jsonx.V1()), "Policy must be an IAM-style document (an object with a Statement array), not a bare array") assert.Equal(t, "2012-10-17", doc.Version) require.Len(t, doc.Statement, 1) diff --git a/services/eventbridge/export_test.go b/services/eventbridge/export_test.go index 6ccc6ac186..533bb5e5ba 100644 --- a/services/eventbridge/export_test.go +++ b/services/eventbridge/export_test.go @@ -2,9 +2,11 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // RegionContextKeyForTest exports the regionContextKey type for external tests. @@ -30,7 +32,7 @@ func CompilePatternErrorForTest(pattern string) error { // despite carrying a shape validation would normally reject. func MatchCompiledPatternBypassingValidationForTest(patternJSON, event string) bool { var pattern map[string]any - if err := json.Unmarshal([]byte(patternJSON), &pattern); err != nil { + if err := json.Unmarshal([]byte(patternJSON), &pattern, jsonx.V1()); err != nil { panic(err) } diff --git a/services/eventbridge/handler_api_destinations.go b/services/eventbridge/handler_api_destinations.go index 22036fd6a9..1211f56aad 100644 --- a/services/eventbridge/handler_api_destinations.go +++ b/services/eventbridge/handler_api_destinations.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createAPIDestinationOutput struct { @@ -19,7 +21,7 @@ func (h *Handler) apiDestinationActions() map[string]actionFn { return map[string]actionFn{ "CreateApiDestination": func(ctx context.Context, b []byte) (any, error) { var input CreateAPIDestinationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } dst, err := h.Backend.CreateAPIDestination(ctx, input) @@ -38,7 +40,7 @@ func (h *Handler) apiDestinationActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteAPIDestination(ctx, input.Name); err != nil { @@ -120,7 +122,7 @@ func (h *Handler) extendedAPIDestinationActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -138,7 +140,7 @@ func (h *Handler) extendedAPIDestinationActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } dsts, next, err := h.Backend.ListAPIDestinations( @@ -160,7 +162,7 @@ func (h *Handler) extendedAPIDestinationActions() map[string]actionFn { }, "UpdateApiDestination": func(ctx context.Context, b []byte) (any, error) { var input UpdateAPIDestinationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } dst, err := h.Backend.UpdateAPIDestination(ctx, input) diff --git a/services/eventbridge/handler_archives.go b/services/eventbridge/handler_archives.go index fbade3a164..09f4d1303c 100644 --- a/services/eventbridge/handler_archives.go +++ b/services/eventbridge/handler_archives.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createArchiveOutput struct { @@ -86,7 +88,7 @@ func (h *Handler) archiveActions() map[string]actionFn { return map[string]actionFn{ "CreateArchive": func(ctx context.Context, b []byte) (any, error) { var input CreateArchiveInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } archive, err := h.Backend.CreateArchive(ctx, input) @@ -111,7 +113,7 @@ func (h *Handler) extendedArchiveActions() map[string]actionFn { var input struct { ArchiveName string `json:"ArchiveName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -121,7 +123,7 @@ func (h *Handler) extendedArchiveActions() map[string]actionFn { var input struct { ArchiveName string `json:"ArchiveName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -140,7 +142,7 @@ func (h *Handler) extendedArchiveActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } archives, next, err := h.Backend.ListArchives( @@ -162,7 +164,7 @@ func (h *Handler) extendedArchiveActions() map[string]actionFn { }, "UpdateArchive": func(ctx context.Context, b []byte) (any, error) { var input UpdateArchiveInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } archive, err := h.Backend.UpdateArchive(ctx, input) diff --git a/services/eventbridge/handler_connections.go b/services/eventbridge/handler_connections.go index caa063a089..98ba355153 100644 --- a/services/eventbridge/handler_connections.go +++ b/services/eventbridge/handler_connections.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createConnectionOutput struct { @@ -104,7 +106,7 @@ func (h *Handler) connectionActions() map[string]actionFn { return map[string]actionFn{ "CreateConnection": func(ctx context.Context, b []byte) (any, error) { var input CreateConnectionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } conn, err := h.Backend.CreateConnection(ctx, input) @@ -123,7 +125,7 @@ func (h *Handler) connectionActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } conn, err := h.Backend.DeauthorizeConnection(ctx, input.Name) @@ -153,7 +155,7 @@ func (h *Handler) extendedConnectionActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -163,7 +165,7 @@ func (h *Handler) extendedConnectionActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -181,7 +183,7 @@ func (h *Handler) extendedConnectionActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } conns, next, err := h.Backend.ListConnections( @@ -203,7 +205,7 @@ func (h *Handler) extendedConnectionActions() map[string]actionFn { }, "UpdateConnection": func(ctx context.Context, b []byte) (any, error) { var input UpdateConnectionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } conn, err := h.Backend.UpdateConnection(ctx, input) diff --git a/services/eventbridge/handler_dispatch.go b/services/eventbridge/handler_dispatch.go index 0bca911b97..3893f7c6c4 100644 --- a/services/eventbridge/handler_dispatch.go +++ b/services/eventbridge/handler_dispatch.go @@ -2,7 +2,7 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -346,7 +347,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -440,7 +441,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a standardized JSON error response. @@ -509,7 +510,7 @@ func (h *Handler) handleError( Message: stripExceptionPrefix(reqErr.Error()), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/eventbridge/handler_endpoints.go b/services/eventbridge/handler_endpoints.go index 3c60fa51a6..b09676c70c 100644 --- a/services/eventbridge/handler_endpoints.go +++ b/services/eventbridge/handler_endpoints.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createEndpointOutput matches real CreateEndpointOutput @@ -76,7 +78,7 @@ func (h *Handler) endpointActions() map[string]actionFn { return map[string]actionFn{ "CreateEndpoint": func(ctx context.Context, b []byte) (any, error) { var input CreateEndpointInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } ep, err := h.Backend.CreateEndpoint(ctx, input) @@ -104,7 +106,7 @@ func (h *Handler) extendedEndpointActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -114,7 +116,7 @@ func (h *Handler) extendedEndpointActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } ep, err := h.Backend.DescribeEndpoint(ctx, input.Name) @@ -130,7 +132,7 @@ func (h *Handler) extendedEndpointActions() map[string]actionFn { NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } eps, next, err := h.Backend.ListEndpoints(ctx, input.NamePrefix, input.NextToken, input.MaxResults) @@ -150,7 +152,7 @@ func (h *Handler) extendedEndpointActions() map[string]actionFn { }, "UpdateEndpoint": func(ctx context.Context, b []byte) (any, error) { var input UpdateEndpointInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } ep, err := h.Backend.UpdateEndpoint(ctx, input) diff --git a/services/eventbridge/handler_endpoints_test.go b/services/eventbridge/handler_endpoints_test.go index 7a98ccc224..13d9735a85 100644 --- a/services/eventbridge/handler_endpoints_test.go +++ b/services/eventbridge/handler_endpoints_test.go @@ -1,7 +1,8 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -65,14 +67,14 @@ func TestHandler_Endpoint_TimestampsAreEpochSeconds(t *testing.T) { rec = auditMakeRequest(t, h, e, "DescribeEndpoint", map[string]any{"Name": "epoch-endpoint"}) assert.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) creationRaw, ok := raw["CreationTime"] require.True(t, ok, "CreationTime must be present") var f float64 - require.NoError(t, json.Unmarshal(creationRaw, &f), + require.NoError(t, json.Unmarshal(creationRaw, &f, jsonx.V1()), "CreationTime must be a JSON number (epoch seconds), got: %s", string(creationRaw)) assert.Greater(t, f, float64(0)) } diff --git a/services/eventbridge/handler_event_buses.go b/services/eventbridge/handler_event_buses.go index b99b7274ed..97c52d4d1b 100644 --- a/services/eventbridge/handler_event_buses.go +++ b/services/eventbridge/handler_event_buses.go @@ -2,8 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -116,7 +117,7 @@ func (h *Handler) eventBusActions() map[string]actionFn { func (h *Handler) handleCreateEventBus(ctx context.Context, b []byte) (any, error) { var input createEventBusInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } bus, err := h.Backend.CreateEventBus(ctx, CreateEventBusParams{ @@ -149,7 +150,7 @@ func (h *Handler) handleCreateEventBus(ctx context.Context, b []byte) (any, erro func (h *Handler) handleDeleteEventBus(ctx context.Context, b []byte) (any, error) { var input deleteEventBusInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } // Capture ARN before deletion so we can clean up tags. @@ -166,7 +167,7 @@ func (h *Handler) handleDeleteEventBus(ctx context.Context, b []byte) (any, erro func (h *Handler) handleListEventBuses(ctx context.Context, b []byte) (any, error) { var input listEventBusesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } buses, next, err := h.Backend.ListEventBuses(ctx, input.NamePrefix, input.NextToken, input.Limit) @@ -184,7 +185,7 @@ func (h *Handler) handleListEventBuses(ctx context.Context, b []byte) (any, erro func (h *Handler) handleDescribeEventBus(ctx context.Context, b []byte) (any, error) { var input describeEventBusInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } bus, err := h.Backend.DescribeEventBus(ctx, input.Name) @@ -202,7 +203,7 @@ func (h *Handler) eventBusManagementActions() map[string]actionFn { return map[string]actionFn{ "UpdateEventBus": func(ctx context.Context, b []byte) (any, error) { var input UpdateEventBusInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } bus, err := h.Backend.UpdateEventBus(ctx, input) @@ -228,7 +229,7 @@ func (h *Handler) eventBusManagementActions() map[string]actionFn { }, "PutPermission": func(ctx context.Context, b []byte) (any, error) { var input PutPermissionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -236,7 +237,7 @@ func (h *Handler) eventBusManagementActions() map[string]actionFn { }, "RemovePermission": func(ctx context.Context, b []byte) (any, error) { var input RemovePermissionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -249,7 +250,7 @@ func (h *Handler) policyActions() map[string]actionFn { return map[string]actionFn{ "GetEventBusPolicy": func(ctx context.Context, b []byte) (any, error) { var input GetEventBusPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } policy, err := h.Backend.GetEventBusPolicy(ctx, input.EventBusName) @@ -263,7 +264,7 @@ func (h *Handler) policyActions() map[string]actionFn { }, "PutEventBusPolicy": func(ctx context.Context, b []byte) (any, error) { var input PutEventBusPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/eventbridge/handler_event_buses_test.go b/services/eventbridge/handler_event_buses_test.go index 1c1de7b328..026915c7fc 100644 --- a/services/eventbridge/handler_event_buses_test.go +++ b/services/eventbridge/handler_event_buses_test.go @@ -2,7 +2,8 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -59,7 +61,7 @@ func TestHandler_DescribeEventBus_EchoesPolicy(t *testing.T) { var describeResp struct { Policy string `json:"Policy"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Contains(t, describeResp.Policy, "allow-policy-echo") rec = auditMakeRequest(t, h, e, "ListEventBuses", map[string]any{}) @@ -71,7 +73,7 @@ func TestHandler_DescribeEventBus_EchoesPolicy(t *testing.T) { Policy string `json:"Policy"` } `json:"EventBuses"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) found := false for _, bus := range listResp.EventBuses { if bus.Name == "default" { @@ -97,14 +99,14 @@ func TestHandler_EventBus_TimestampsAreEpochSeconds(t *testing.T) { rec := auditMakeRequest(t, h, e, "DescribeEventBus", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) creationRaw, ok := raw["CreationTime"] require.True(t, ok, "CreationTime must be present") var f float64 - require.NoError(t, json.Unmarshal(creationRaw, &f), + require.NoError(t, json.Unmarshal(creationRaw, &f, jsonx.V1()), "CreationTime must be a JSON number (epoch seconds), got: %s", string(creationRaw)) assert.Greater(t, f, float64(0)) } @@ -170,7 +172,7 @@ func TestCreateEventBus_TagsPersisted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) busArn := createResp["EventBusArn"] require.NotEmpty(t, busArn) @@ -183,7 +185,7 @@ func TestCreateEventBus_TagsPersisted(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) got := make(map[string]string, len(tagsResp.Tags)) for _, kv := range tagsResp.Tags { @@ -363,7 +365,7 @@ func TestHandler_CreateEventBus(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["EventBusArn"], tt.wantArnPart) }) } @@ -411,7 +413,7 @@ func TestHandler_CreateAndListEventBuses(t *testing.T) { CreationTime float64 `json:"CreationTime"` } `json:"EventBuses"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.GreaterOrEqual(t, len(resp.EventBuses), tt.wantMinCount) }) } diff --git a/services/eventbridge/handler_event_sources.go b/services/eventbridge/handler_event_sources.go index 548a2f3546..16a6a9e789 100644 --- a/services/eventbridge/handler_event_sources.go +++ b/services/eventbridge/handler_event_sources.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type ( @@ -16,7 +18,7 @@ func (h *Handler) eventSourceActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.ActivateEventSource(ctx, input.Name); err != nil { @@ -29,7 +31,7 @@ func (h *Handler) eventSourceActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeactivateEventSource(ctx, input.Name); err != nil { @@ -84,7 +86,7 @@ func (h *Handler) extendedEventSourceActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -101,7 +103,7 @@ func (h *Handler) extendedEventSourceActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } srcs, next, err := h.Backend.ListEventSources(ctx, input.NamePrefix, input.NextToken, int(input.Limit)) diff --git a/services/eventbridge/handler_event_sources_test.go b/services/eventbridge/handler_event_sources_test.go index 1677ed7ab3..1f2298843a 100644 --- a/services/eventbridge/handler_event_sources_test.go +++ b/services/eventbridge/handler_event_sources_test.go @@ -1,7 +1,8 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -55,16 +57,16 @@ func TestDescribeEventSourceAndListEventSources_TimestampsAreEpochFloat(t *testi rec := auditMakeRequest(t, h, e, tt.action, input) require.Equal(t, http.StatusOK, rec.Code) - var creationRaw json.RawMessage + var creationRaw jsontext.Value if tt.action == "DescribeEventSource" { - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) creationRaw = raw["CreationTime"] } else { var raw struct { - EventSources []map[string]json.RawMessage `json:"EventSources"` + EventSources []map[string]jsontext.Value `json:"EventSources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.EventSources, 1) creationRaw = raw.EventSources[0]["CreationTime"] } @@ -72,7 +74,7 @@ func TestDescribeEventSourceAndListEventSources_TimestampsAreEpochFloat(t *testi require.NotNil(t, creationRaw, "CreationTime must be present") var f float64 - err := json.Unmarshal(creationRaw, &f) + err := json.Unmarshal(creationRaw, &f, jsonx.V1()) require.NoError(t, err, "CreationTime must be a JSON number (epoch seconds), got: %s", string(creationRaw)) assert.Greater(t, f, float64(0)) }) diff --git a/services/eventbridge/handler_events.go b/services/eventbridge/handler_events.go index c65385f31f..c65b5a08f4 100644 --- a/services/eventbridge/handler_events.go +++ b/services/eventbridge/handler_events.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putEventsInput struct { @@ -33,7 +35,7 @@ func (h *Handler) eventsActions() map[string]actionFn { return map[string]actionFn{ "PutEvents": func(ctx context.Context, b []byte) (any, error) { var input putEventsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } entries, err := h.Backend.PutEvents(ctx, input.Entries) diff --git a/services/eventbridge/handler_events_test.go b/services/eventbridge/handler_events_test.go index e1b4eee9ed..cb06d99614 100644 --- a/services/eventbridge/handler_events_test.go +++ b/services/eventbridge/handler_events_test.go @@ -1,7 +1,7 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -77,7 +78,7 @@ func TestHandler_PutEvents(t *testing.T) { Entries []eventbridge.EventResultEntry `json:"Entries"` FailedEntryCount int `json:"FailedEntryCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantFailedCount, resp.FailedEntryCount) assert.Len(t, resp.Entries, tt.wantEntryCount) for _, entry := range resp.Entries { diff --git a/services/eventbridge/handler_partner_sources.go b/services/eventbridge/handler_partner_sources.go index 011e423e3c..3000bcb2b3 100644 --- a/services/eventbridge/handler_partner_sources.go +++ b/services/eventbridge/handler_partner_sources.go @@ -2,8 +2,10 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createPartnerEventSourceOutput struct { @@ -28,7 +30,7 @@ func (h *Handler) partnerSourceActions() map[string]actionFn { Name string `json:"Name"` Account string `json:"Account"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } src, err := h.Backend.CreatePartnerEventSource(ctx, input.Name, input.Account) @@ -48,7 +50,7 @@ func (h *Handler) extendedPartnerSourceActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -58,7 +60,7 @@ func (h *Handler) extendedPartnerSourceActions() map[string]actionFn { var input struct { Name string `json:"Name"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -70,7 +72,7 @@ func (h *Handler) extendedPartnerSourceActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } srcs, next, err := h.Backend.ListPartnerEventSources( @@ -93,7 +95,7 @@ func (h *Handler) extendedPartnerSourceActions() map[string]actionFn { EventSourceName string `json:"EventSourceName"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if input.EventSourceName == "" { @@ -121,7 +123,7 @@ func (h *Handler) extendedPartnerSourceActions() map[string]actionFn { }, "PutPartnerEvents": func(ctx context.Context, b []byte) (any, error) { var input putEventsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } entries, err := h.Backend.PutPartnerEvents(ctx, input.Entries) diff --git a/services/eventbridge/handler_registries.go b/services/eventbridge/handler_registries.go index 34afc0567c..b2310f9d63 100644 --- a/services/eventbridge/handler_registries.go +++ b/services/eventbridge/handler_registries.go @@ -2,14 +2,16 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) registryActions() map[string]actionFn { return map[string]actionFn{ opCreateRegistry: func(ctx context.Context, b []byte) (any, error) { var input CreateRegistryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -19,7 +21,7 @@ func (h *Handler) registryActions() map[string]actionFn { var input struct { RegistryName string `json:"RegistryName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -29,7 +31,7 @@ func (h *Handler) registryActions() map[string]actionFn { var input struct { RegistryName string `json:"RegistryName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -41,7 +43,7 @@ func (h *Handler) registryActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } regs, next, err := h.Backend.ListRegistries(ctx, input.NamePrefix, input.NextToken, int(input.Limit)) @@ -56,7 +58,7 @@ func (h *Handler) registryActions() map[string]actionFn { }, opUpdateRegistry: func(ctx context.Context, b []byte) (any, error) { var input UpdateRegistryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/eventbridge/handler_replays.go b/services/eventbridge/handler_replays.go index daf9164522..f73a113d89 100644 --- a/services/eventbridge/handler_replays.go +++ b/services/eventbridge/handler_replays.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type cancelReplayOutput struct { @@ -85,7 +87,7 @@ func (h *Handler) replayActions() map[string]actionFn { var input struct { ReplayName string `json:"ReplayName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } replay, err := h.Backend.CancelReplay(ctx, input.ReplayName) @@ -109,7 +111,7 @@ func (h *Handler) extendedReplayActions() map[string]actionFn { var input struct { ReplayName string `json:"ReplayName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } replay, err := h.Backend.DescribeReplay(ctx, input.ReplayName) @@ -127,7 +129,7 @@ func (h *Handler) extendedReplayActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } replays, next, err := h.Backend.ListReplays( @@ -149,7 +151,7 @@ func (h *Handler) extendedReplayActions() map[string]actionFn { }, "StartReplay": func(ctx context.Context, b []byte) (any, error) { var input StartReplayInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } replay, err := h.Backend.StartReplay(ctx, input) diff --git a/services/eventbridge/handler_replays_test.go b/services/eventbridge/handler_replays_test.go index 066f135ab5..0529a522a6 100644 --- a/services/eventbridge/handler_replays_test.go +++ b/services/eventbridge/handler_replays_test.go @@ -1,7 +1,8 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -82,14 +84,14 @@ func TestStartReplay_ReplayStartTimeIsEpochFloat(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) replayStartRaw, ok := raw["ReplayStartTime"] require.True(t, ok, "ReplayStartTime must be present in StartReplay response") var f float64 - err := json.Unmarshal(replayStartRaw, &f) + err := json.Unmarshal(replayStartRaw, &f, jsonx.V1()) require.NoError( t, err, @@ -131,14 +133,14 @@ func TestHandler_DescribeReplay_TimestampsAreEpochSeconds(t *testing.T) { rec = auditMakeRequest(t, h, e, "DescribeReplay", map[string]any{"ReplayName": "epoch-replay"}) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) startRaw, ok := raw["EventStartTime"] require.True(t, ok, "EventStartTime must be present") var f float64 - require.NoError(t, json.Unmarshal(startRaw, &f), + require.NoError(t, json.Unmarshal(startRaw, &f, jsonx.V1()), "EventStartTime must be a JSON number (epoch seconds), got: %s", string(startRaw)) assert.Greater(t, f, float64(0)) } diff --git a/services/eventbridge/handler_rules.go b/services/eventbridge/handler_rules.go index 9ac09598e0..f5322d17ae 100644 --- a/services/eventbridge/handler_rules.go +++ b/services/eventbridge/handler_rules.go @@ -2,8 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -85,7 +86,7 @@ func (h *Handler) ruleActions() map[string]actionFn { return map[string]actionFn{ "PutRule": func(ctx context.Context, b []byte) (any, error) { var input PutRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } rule, err := h.Backend.PutRule(ctx, input) @@ -100,7 +101,7 @@ func (h *Handler) ruleActions() map[string]actionFn { }, "DeleteRule": func(ctx context.Context, b []byte) (any, error) { var input deleteRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } // Capture ARN before deletion so we can clean up tags. @@ -116,7 +117,7 @@ func (h *Handler) ruleActions() map[string]actionFn { }, "ListRules": func(ctx context.Context, b []byte) (any, error) { var input listRulesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } rules, next, err := h.Backend.ListRules( @@ -139,7 +140,7 @@ func (h *Handler) ruleActions() map[string]actionFn { }, "DescribeRule": func(ctx context.Context, b []byte) (any, error) { var input describeRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -158,7 +159,7 @@ func (h *Handler) ruleQueryActions() map[string]actionFn { TargetArn string `json:"TargetArn"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } names, next, err := h.Backend.ListRuleNamesByTarget( @@ -182,7 +183,7 @@ func (h *Handler) ruleQueryActions() map[string]actionFn { Event string `json:"Event"` EventPattern string `json:"EventPattern"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } result, err := h.Backend.TestEventPattern(ctx, input.EventPattern, input.Event) @@ -201,7 +202,7 @@ func (h *Handler) ruleStateActions() map[string]actionFn { return map[string]actionFn{ "EnableRule": func(ctx context.Context, b []byte) (any, error) { var input enableRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.EnableRule(ctx, input.Name, input.EventBusName); err != nil { @@ -212,7 +213,7 @@ func (h *Handler) ruleStateActions() map[string]actionFn { }, "DisableRule": func(ctx context.Context, b []byte) (any, error) { var input disableRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DisableRule(ctx, input.Name, input.EventBusName); err != nil { diff --git a/services/eventbridge/handler_rules_test.go b/services/eventbridge/handler_rules_test.go index 515156884c..0b19c1e77f 100644 --- a/services/eventbridge/handler_rules_test.go +++ b/services/eventbridge/handler_rules_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -52,7 +53,7 @@ func TestHandler_TestEventPattern(t *testing.T) { var resp struct { Result bool `json:"Result"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.True(t, resp.Result) } @@ -124,7 +125,7 @@ func TestPutRule_TagsPersisted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) ruleArn := putResp["RuleArn"] require.NotEmpty(t, ruleArn) @@ -137,7 +138,7 @@ func TestPutRule_TagsPersisted(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) got := make(map[string]string, len(tagsResp.Tags)) for _, kv := range tagsResp.Tags { @@ -187,7 +188,7 @@ func TestDeleteRule_CleansUpTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut, jsonx.V1())) ruleARN := putOut["RuleArn"] require.NotEmpty(t, ruleARN) @@ -248,7 +249,7 @@ func TestHandler_PutRuleAndListRules(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var putResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assert.Contains(t, putResp["RuleArn"], tt.wantArnPart) rec = makeRequestWithHandler(t, handler, e, "ListRules", `{}`) @@ -257,7 +258,7 @@ func TestHandler_PutRuleAndListRules(t *testing.T) { var listResp struct { Rules []eventbridge.Rule `json:"Rules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Rules, tt.wantRuleLen) assert.Equal(t, tt.wantRuleName, listResp.Rules[0].Name) }) @@ -300,7 +301,7 @@ func TestHandler_DescribeRule(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var rule eventbridge.Rule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule, jsonx.V1())) assert.Equal(t, tt.wantRuleName, rule.Name) assert.Equal(t, tt.wantDescription, rule.Description) assert.Equal(t, tt.wantState, rule.State) @@ -346,13 +347,13 @@ func TestHandler_EnableDisableRule(t *testing.T) { rec = makeRequestWithHandler(t, handler, e, "DescribeRule", `{"Name":"`+tt.ruleName+`"}`) var rule eventbridge.Rule - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule, jsonx.V1())) assert.Equal(t, tt.wantDisabledState, rule.State) makeRequestWithHandler(t, handler, e, "EnableRule", `{"Name":"`+tt.ruleName+`"}`) rec = makeRequestWithHandler(t, handler, e, "DescribeRule", `{"Name":"`+tt.ruleName+`"}`) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &rule, jsonx.V1())) assert.Equal(t, tt.wantEnabledState, rule.State) }) } diff --git a/services/eventbridge/handler_schemas.go b/services/eventbridge/handler_schemas.go index ede2802171..5de4d85f62 100644 --- a/services/eventbridge/handler_schemas.go +++ b/services/eventbridge/handler_schemas.go @@ -2,14 +2,16 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) schemaActions() map[string]actionFn { return map[string]actionFn{ opCreateSchema: func(ctx context.Context, b []byte) (any, error) { var input CreateSchemaInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -20,7 +22,7 @@ func (h *Handler) schemaActions() map[string]actionFn { RegistryName string `json:"RegistryName"` SchemaName string `json:"SchemaName"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -32,7 +34,7 @@ func (h *Handler) schemaActions() map[string]actionFn { SchemaName string `json:"SchemaName"` SchemaVersion string `json:"SchemaVersion"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -50,7 +52,7 @@ func (h *Handler) schemaActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } schemas, next, err := h.Backend.ListSchemas( @@ -76,7 +78,7 @@ func (h *Handler) schemaActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } schemas, next, err := h.Backend.SearchSchemas( @@ -97,7 +99,7 @@ func (h *Handler) schemaActions() map[string]actionFn { }, opUpdateSchema: func(ctx context.Context, b []byte) (any, error) { var input UpdateSchemaInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -115,7 +117,7 @@ func (h *Handler) schemaVersionActions() map[string]actionFn { NextToken string `json:"NextToken"` Limit int32 `json:"Limit"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } versions, next, err := h.Backend.ListSchemaVersions( @@ -140,7 +142,7 @@ func (h *Handler) schemaVersionActions() map[string]actionFn { SchemaName string `json:"SchemaName"` SchemaVersion string `json:"SchemaVersion"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -157,7 +159,7 @@ func (h *Handler) schemaVersionActions() map[string]actionFn { SchemaName string `json:"SchemaName"` SchemaVersion string `json:"SchemaVersion"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -170,7 +172,7 @@ func (h *Handler) schemaVersionActions() map[string]actionFn { }, opGetDiscoveredSchema: func(ctx context.Context, b []byte) (any, error) { var input GetDiscoveredSchemaInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } content, err := h.Backend.GetDiscoveredSchema(ctx, input) @@ -189,7 +191,7 @@ func (h *Handler) codeBindingActions() map[string]actionFn { return map[string]actionFn{ opPutCodeBinding: func(ctx context.Context, b []byte) (any, error) { var input PutCodeBindingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -197,7 +199,7 @@ func (h *Handler) codeBindingActions() map[string]actionFn { }, opDescribeCodeBinding: func(ctx context.Context, b []byte) (any, error) { var input DescribeCodeBindingInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -205,7 +207,7 @@ func (h *Handler) codeBindingActions() map[string]actionFn { }, "ListCodeBindings": func(ctx context.Context, b []byte) (any, error) { var input ListCodeBindingsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } bindings, next, err := h.Backend.ListCodeBindings(ctx, input) @@ -225,7 +227,7 @@ func (h *Handler) codeBindingActions() map[string]actionFn { Language string `json:"Language"` SchemaVersion string `json:"SchemaVersion"` } - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } src, err := h.Backend.GetCodeBindingSource( diff --git a/services/eventbridge/handler_schemas_rest.go b/services/eventbridge/handler_schemas_rest.go index 88e722d682..1c630c26f5 100644 --- a/services/eventbridge/handler_schemas_rest.go +++ b/services/eventbridge/handler_schemas_rest.go @@ -2,7 +2,7 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // schemasRESTLimit parses the "limit" query param (schemas@v1.37.4 @@ -828,7 +829,7 @@ func (h *Handler) schemasRESTOps() map[string]schemasRESTOpFunc { } func (h *Handler) writeSchemasREST(c *echo.Context, body any) error { - payload, err := json.Marshal(body) + payload, err := json.Marshal(body, jsonx.V1()) if err != nil { return h.writeSchemasRESTError(c, err) } @@ -865,7 +866,7 @@ func (h *Handler) writeSchemasRESTError(c *echo.Context, err error) error { c.Response().Header().Set("Content-Type", schemasRESTContentType) c.Response().Header().Set("X-Amzn-Errortype", code) - payload, marshalErr := json.Marshal(map[string]string{"message": err.Error()}) + payload, marshalErr := json.Marshal(map[string]string{"message": err.Error()}, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } @@ -883,7 +884,7 @@ func schemasRESTDecodeBody(r *http.Request, out any) error { return nil } - if uerr := json.Unmarshal(body, out); uerr != nil { + if uerr := json.Unmarshal(body, out, jsonx.V1()); uerr != nil { return fmt.Errorf("%w: invalid JSON", ErrInvalidParameter) } diff --git a/services/eventbridge/handler_schemas_test.go b/services/eventbridge/handler_schemas_test.go index ae12ef9e96..3c04bcc881 100644 --- a/services/eventbridge/handler_schemas_test.go +++ b/services/eventbridge/handler_schemas_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -233,7 +234,7 @@ func TestHandler_DeleteSchemaVersion_LastVersionReturns400(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) // Schema still exists and is intact. diff --git a/services/eventbridge/handler_tags.go b/services/eventbridge/handler_tags.go index 49086079d7..021d988159 100644 --- a/services/eventbridge/handler_tags.go +++ b/services/eventbridge/handler_tags.go @@ -2,9 +2,10 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -34,7 +35,7 @@ func (h *Handler) tagActions() map[string]actionFn { return map[string]actionFn{ "ListTagsForResource": func(ctx context.Context, b []byte) (any, error) { var input listTagsForResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.requireTaggable(ctx, input.ResourceARN); err != nil { @@ -50,7 +51,7 @@ func (h *Handler) tagActions() map[string]actionFn { }, "TagResource": func(ctx context.Context, b []byte) (any, error) { var input tagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.requireTaggable(ctx, input.ResourceARN); err != nil { @@ -66,7 +67,7 @@ func (h *Handler) tagActions() map[string]actionFn { }, "UntagResource": func(ctx context.Context, b []byte) (any, error) { var input untagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.requireTaggable(ctx, input.ResourceARN); err != nil { diff --git a/services/eventbridge/handler_tags_test.go b/services/eventbridge/handler_tags_test.go index a4b0f674ec..8f1a1d14bb 100644 --- a/services/eventbridge/handler_tags_test.go +++ b/services/eventbridge/handler_tags_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -107,7 +108,7 @@ func TestHandler_TagOperations(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Tags, tt.wantTagCount) if len(tt.wantTags) > 0 { diff --git a/services/eventbridge/handler_targets.go b/services/eventbridge/handler_targets.go index c552bca5df..53c51b27eb 100644 --- a/services/eventbridge/handler_targets.go +++ b/services/eventbridge/handler_targets.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putTargetsInput struct { @@ -44,7 +46,7 @@ func (h *Handler) targetActions() map[string]actionFn { return map[string]actionFn{ "PutTargets": func(ctx context.Context, b []byte) (any, error) { var input putTargetsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } failed, err := h.Backend.PutTargets(ctx, input.Rule, input.EventBusName, input.Targets) @@ -62,7 +64,7 @@ func (h *Handler) targetActions() map[string]actionFn { }, "RemoveTargets": func(ctx context.Context, b []byte) (any, error) { var input removeTargetsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } failed, err := h.Backend.RemoveTargetsForce(ctx, input.Rule, input.EventBusName, input.IDs, input.Force) @@ -80,7 +82,7 @@ func (h *Handler) targetActions() map[string]actionFn { }, "ListTargetsByRule": func(ctx context.Context, b []byte) (any, error) { var input listTargetsByRuleInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } targets, next, err := h.Backend.ListTargetsByRule( diff --git a/services/eventbridge/handler_targets_test.go b/services/eventbridge/handler_targets_test.go index a3b746063a..350781e2e1 100644 --- a/services/eventbridge/handler_targets_test.go +++ b/services/eventbridge/handler_targets_test.go @@ -1,7 +1,7 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -87,7 +88,7 @@ func TestHandler_PutTargetsListAndRemove(t *testing.T) { FailedEntries []eventbridge.FailedEntry `json:"FailedEntries"` FailedEntryCount int `json:"FailedEntryCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assert.Equal(t, 0, putResp.FailedEntryCount) rec = makeRequestWithHandler(t, handler, e, "ListTargetsByRule", `{"Rule":"`+tt.ruleName+`"}`) @@ -96,7 +97,7 @@ func TestHandler_PutTargetsListAndRemove(t *testing.T) { var listResp struct { Targets []eventbridge.Target `json:"Targets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Targets, tt.wantInitialCount) rec = makeRequestWithHandler(t, handler, e, "RemoveTargets", @@ -104,7 +105,7 @@ func TestHandler_PutTargetsListAndRemove(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) rec = makeRequestWithHandler(t, handler, e, "ListTargetsByRule", `{"Rule":"`+tt.ruleName+`"}`) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Targets, tt.wantRemainingCount) assert.Equal(t, tt.wantRemainingID, listResp.Targets[0].ID) }) diff --git a/services/eventbridge/handler_test.go b/services/eventbridge/handler_test.go index 7fbcbc31a2..c0d6b65a61 100644 --- a/services/eventbridge/handler_test.go +++ b/services/eventbridge/handler_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -104,7 +105,7 @@ func TestHandler_GetSupportedOperations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) for _, op := range tt.wantOps { assert.Contains(t, ops, op) } @@ -183,7 +184,7 @@ func TestHandler_DispatchErrors(t *testing.T) { } if tt.wantErrorType != "" { var errResp service.JSONErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrorType, errResp.Type) } }) @@ -312,7 +313,7 @@ func auditMakeRequest( body map[string]any, ) *httptest.ResponseRecorder { t.Helper() - b, _ := json.Marshal(body) + b, _ := json.Marshal(body, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(b))) req.Header.Set("X-Amz-Target", "AmazonEventBridge."+action) rec := httptest.NewRecorder() @@ -759,6 +760,6 @@ func TestCancelReplay_TerminalStateMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp service.JSONErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "IllegalStatusException", errResp.Type) } diff --git a/services/eventbridge/metrics.go b/services/eventbridge/metrics.go index 96713e4fbb..bba9d09e7f 100644 --- a/services/eventbridge/metrics.go +++ b/services/eventbridge/metrics.go @@ -2,10 +2,11 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AWS/Events rule metrics per docs.aws.amazon.com/eventbridge/latest/userguide/eb-monitoring.html. @@ -48,7 +49,7 @@ func (b *InMemoryBackend) observePutEvents( put("PutEventsEntriesCount", ebUnitCount, float64(len(entries))) put("PutEventsLatency", ebUnitMillis, float64(elapsed.Milliseconds())) - if body, mErr := json.Marshal(entries); mErr == nil { + if body, mErr := json.Marshal(entries, jsonx.V1()); mErr == nil { put("PutEventsRequestSize", ebUnitBytes, float64(len(body))) } } diff --git a/services/eventbridge/pattern.go b/services/eventbridge/pattern.go index 79861834ff..338230779b 100644 --- a/services/eventbridge/pattern.go +++ b/services/eventbridge/pattern.go @@ -1,14 +1,14 @@ package eventbridge import ( - "encoding/json" - "errors" + "encoding/json/v2" "fmt" "reflect" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/eventpattern" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -32,7 +32,7 @@ func compilePattern(patternJSON string) (*compiledPattern, error) { } var pattern map[string]any - if err := json.Unmarshal([]byte(patternJSON), &pattern); err != nil { + if err := json.Unmarshal([]byte(patternJSON), &pattern, jsonx.V1()); err != nil { return nil, err } @@ -268,7 +268,7 @@ func matchCompiledPattern(compiled *compiledPattern, event string) bool { } var eventData map[string]any - if err := json.Unmarshal([]byte(event), &eventData); err != nil { + if err := json.Unmarshal([]byte(event), &eventData, jsonx.V1()); err != nil { return false } @@ -682,12 +682,9 @@ func matchWildcard(pattern, s string) bool { func invalidPatternErr(err error) error { reason := "Invalid JSON" - var syn *json.SyntaxError - var typ *json.UnmarshalTypeError - switch { - case errors.As(err, &syn): - case errors.As(err, &typ): + case jsonx.IsSyntaxError(err): + case jsonx.IsTypeError(err): reason = "Filter is not an object" default: reason = strings.TrimPrefix(err.Error(), ErrInvalidParameter.Error()+": ") diff --git a/services/eventbridge/persistence.go b/services/eventbridge/persistence.go index 5ae382cbee..3a0b97d122 100644 --- a/services/eventbridge/persistence.go +++ b/services/eventbridge/persistence.go @@ -2,11 +2,13 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" "sync" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -59,7 +61,7 @@ const eventbridgeSnapshotVersion = 1 // no reason to leave bus policies unpersisted the way the genuinely // unkeyable maps above are. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` BusPolicies map[string]map[string]*EventBusPolicy `json:"busPolicies,omitempty"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -93,7 +95,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx). WarnContext(ctx, "persistence: snapshot marshal failed", "service", "eventbridge", "error", err) @@ -116,7 +118,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { // first "/" recovers the prefix, and tableAccessorsByPrefix's rules/targets // entries split the remainder again themselves (region never contains "/", // but bus/rule names may). -func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]json.RawMessage) { +func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]jsontext.Value) { for key := range tables { name, rest, found := strings.Cut(key, "/") if !found { @@ -168,7 +170,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { } if snap.Tables == nil { - snap.Tables = make(map[string]json.RawMessage) + snap.Tables = make(map[string]jsontext.Value) } b.preRegisterSnapshotTables(snap.Tables) diff --git a/services/eventbridge/persistence_test.go b/services/eventbridge/persistence_test.go index 43380bd71c..8bea5601fd 100644 --- a/services/eventbridge/persistence_test.go +++ b/services/eventbridge/persistence_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -309,7 +310,7 @@ func TestHandler_Snapshot_IncludesTags(t *testing.T) { tagBody, err := json.Marshal(map[string]any{ "ResourceARN": tt.resourceARN, "Tags": []map[string]string{{"Key": k, "Value": v}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := makeRequestWithHandler(t, h, e, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -322,7 +323,7 @@ func TestHandler_Snapshot_IncludesTags(t *testing.T) { fresh := eventbridge.NewHandler(eventbridge.NewInMemoryBackendWithConfig("123456789012", "us-east-1")) require.NoError(t, fresh.Restore(t.Context(), snap)) - listBody, err := json.Marshal(map[string]string{"ResourceARN": tt.resourceARN}) + listBody, err := json.Marshal(map[string]string{"ResourceARN": tt.resourceARN}, jsonx.V1()) require.NoError(t, err) rec := makeRequestWithFreshHandler(t, fresh, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -333,7 +334,7 @@ func TestHandler_Snapshot_IncludesTags(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Tags, tt.wantTagCount) if tt.wantTagCount > 0 { @@ -387,7 +388,7 @@ func TestHandler_Reset_ClearsTags(t *testing.T) { tagBody, err := json.Marshal(map[string]any{ "ResourceARN": tt.resourceARN, "Tags": []map[string]string{{"Key": k, "Value": v}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := makeRequestWithHandler(t, h, e, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -400,7 +401,7 @@ func TestHandler_Reset_ClearsTags(t *testing.T) { `{"Name":"bleed-rule","EventPattern":"{\"source\":[\"test\"]}"}`) require.Equal(t, http.StatusOK, put.Code) - listBody, err := json.Marshal(map[string]string{"ResourceARN": tt.resourceARN}) + listBody, err := json.Marshal(map[string]string{"ResourceARN": tt.resourceARN}, jsonx.V1()) require.NoError(t, err) rec := makeRequestWithHandler(t, h, e, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -411,7 +412,7 @@ func TestHandler_Reset_ClearsTags(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.Tags, "tags should be cleared after Reset()") }) } @@ -558,7 +559,7 @@ func TestHandlerReset(t *testing.T) { var resp struct { Tags []map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.Tags) } diff --git a/services/eventbridge/put_events.go b/services/eventbridge/put_events.go index 22bba2abe2..dc78b8173c 100644 --- a/services/eventbridge/put_events.go +++ b/services/eventbridge/put_events.go @@ -2,7 +2,7 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/apptrace" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxPutEventsEntries is AWS's per-request cap on PutEvents/PutPartnerEvents @@ -298,7 +299,7 @@ func putEventsEntryBytes(e EventEntry) int { // (MalformedDetail) or whose bus does not exist (ResourceNotFoundException). func (b *InMemoryBackend) validatePutEventsTarget(region string, e EventEntry) (string, string, bool) { var detail map[string]any - if err := json.Unmarshal([]byte(e.Detail), &detail); err != nil { + if err := json.Unmarshal([]byte(e.Detail), &detail, jsonx.V1()); err != nil { return "MalformedDetail", "Detail is malformed.", false } diff --git a/services/eventbridge/put_events_test.go b/services/eventbridge/put_events_test.go index 5542c491e7..298cf66d82 100644 --- a/services/eventbridge/put_events_test.go +++ b/services/eventbridge/put_events_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -255,14 +256,14 @@ func TestPutEvents_FailedEntryCount(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - body, err := json.Marshal(map[string]any{"Entries": tt.entries}) + body, err := json.Marshal(map[string]any{"Entries": tt.entries}, jsonx.V1()) require.NoError(t, err) rec := makeRequest(t, tt.action, string(body)) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var got putEventsResult - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantFailedCount, got.FailedEntryCount) diff --git a/services/eventbridge/region_isolation_test.go b/services/eventbridge/region_isolation_test.go index 90442cb985..522428e9c0 100644 --- a/services/eventbridge/region_isolation_test.go +++ b/services/eventbridge/region_isolation_test.go @@ -2,12 +2,14 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -230,17 +232,17 @@ func TestDefaultBus_RulesAndRestoreInSiblingRegion(t *testing.T) { _, err = b.CreateEventBus(ctx, eventbridge.CreateEventBusParams{Name: "custom"}) require.NoError(t, err) - var snap map[string]json.RawMessage + var snap map[string]jsontext.Value - require.NoError(t, json.Unmarshal(b.Snapshot(ctx), &snap)) + require.NoError(t, json.Unmarshal(b.Snapshot(ctx), &snap, jsonx.V1())) - var tables map[string]json.RawMessage + var tables map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap["tables"], &tables)) + require.NoError(t, json.Unmarshal(snap["tables"], &tables, jsonx.V1())) var buses []map[string]any - require.NoError(t, json.Unmarshal(tables["buses/"+euRegion], &buses)) + require.NoError(t, json.Unmarshal(tables["buses/"+euRegion], &buses, jsonx.V1())) legacy := make([]map[string]any, 0, len(buses)) @@ -252,13 +254,13 @@ func TestDefaultBus_RulesAndRestoreInSiblingRegion(t *testing.T) { require.Len(t, legacy, 1, "legacy snapshot keeps only the custom bus") - tables["buses/"+euRegion], err = json.Marshal(legacy) + tables["buses/"+euRegion], err = json.Marshal(legacy, jsonx.V1()) require.NoError(t, err) - snap["tables"], err = json.Marshal(tables) + snap["tables"], err = json.Marshal(tables, jsonx.V1()) require.NoError(t, err) - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) restored := eventbridge.NewInMemoryBackend() diff --git a/services/eventbridge/rule_arn_format_test.go b/services/eventbridge/rule_arn_format_test.go index c183a9394f..70df82c680 100644 --- a/services/eventbridge/rule_arn_format_test.go +++ b/services/eventbridge/rule_arn_format_test.go @@ -1,7 +1,7 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -166,7 +167,7 @@ func legacySnapshot(t *testing.T, data []byte) []byte { Tags map[string]map[string]string `json:"tags,omitempty"` Backend []byte `json:"backend"` } - require.NoError(t, json.Unmarshal(data, &snap)) + require.NoError(t, json.Unmarshal(data, &snap, jsonx.V1())) modern := ruleARNPrefix + "r1" legacy := ruleARNPrefix + "default/r1" @@ -179,7 +180,7 @@ func legacySnapshot(t *testing.T, data []byte) []byte { } snap.Tags = tags - out, err := json.Marshal(snap) + out, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) return out diff --git a/services/eventbridge/rules.go b/services/eventbridge/rules.go index fb40d36d9b..88cd327026 100644 --- a/services/eventbridge/rules.go +++ b/services/eventbridge/rules.go @@ -2,11 +2,13 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // checkManagedRule returns ManagedRuleException if rule is owned by an AWS @@ -379,7 +381,7 @@ func (b *InMemoryBackend) TestEventPattern( func isValidJSON(s string) bool { var v any - return json.Unmarshal([]byte(s), &v) == nil + return json.Unmarshal([]byte(s), &v, jsonx.V1()) == nil } var ruleNamePattern = regexp.MustCompile(`^[.\-_A-Za-z0-9]+$`) diff --git a/services/eventbridge/ssm_integration.go b/services/eventbridge/ssm_integration.go index 5619c70666..ed65a5017b 100644 --- a/services/eventbridge/ssm_integration.go +++ b/services/eventbridge/ssm_integration.go @@ -2,7 +2,9 @@ package eventbridge import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ssmParameterPolicyEventSource/DetailType are the real AWS wire values SSM @@ -35,7 +37,7 @@ func (b *InMemoryBackend) NotifyParameterPolicyAction( detail, err := json.Marshal(ssmParameterPolicyEventDetail{ ParameterName: parameterName, PolicyType: policyType, - }) + }, jsonx.V1()) if err != nil { return err } diff --git a/services/eventbridge/targets_test.go b/services/eventbridge/targets_test.go index 550fa85f29..f67fe22b0e 100644 --- a/services/eventbridge/targets_test.go +++ b/services/eventbridge/targets_test.go @@ -2,7 +2,7 @@ package eventbridge_test import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -698,7 +699,7 @@ func TestInputTransformer_ProducesValidJSON(t *testing.T) { assert.JSONEq(t, tt.wantJSONEq, got) } if tt.wantValid { - assert.True(t, json.Valid([]byte(got)), "expected valid JSON, got %q", got) + assert.True(t, jsontext.Value([]byte(got)).IsValid(jsonx.V1()), "expected valid JSON, got %q", got) } }) } @@ -744,7 +745,7 @@ func TestInputTransformer_ValueContextEndToEnd(t *testing.T) { }, 2*time.Second, 10*time.Millisecond) msg := sqsMock.MessagesFor(queueARN)[0] - assert.True(t, json.Valid([]byte(msg)), "delivered payload must be valid JSON: %q", msg) + assert.True(t, jsontext.Value([]byte(msg)).IsValid(jsonx.V1()), "delivered payload must be valid JSON: %q", msg) assert.JSONEq(t, `{"wrapped":"it.svc"}`, msg) } diff --git a/services/eventbridge/wire_field_fixes_test.go b/services/eventbridge/wire_field_fixes_test.go index e82774300c..d710a030bf 100644 --- a/services/eventbridge/wire_field_fixes_test.go +++ b/services/eventbridge/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -387,7 +388,7 @@ func TestPutPermission_Condition_RoundTripsThroughPolicy(t *testing.T) { Sid string `json:"Sid"` } `json:"Statement"` } - require.NoError(t, json.Unmarshal([]byte(aws.ToString(described.Policy)), &doc)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(described.Policy)), &doc, jsonx.V1())) require.Len(t, doc.Statement, 1) assert.Equal(t, "OrgGrant", doc.Statement[0].Sid) require.NotEmpty( diff --git a/services/eventbridge/wire_time.go b/services/eventbridge/wire_time.go index c6f5bb243e..d92c19143d 100644 --- a/services/eventbridge/wire_time.go +++ b/services/eventbridge/wire_time.go @@ -1,8 +1,10 @@ package eventbridge import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseEpochSecondsPtr converts an AWS json-1.1 wire-format epoch-seconds @@ -45,7 +47,7 @@ type wireEventEntry struct { // quoted RFC3339 string. func (e *EventEntry) UnmarshalJSON(data []byte) error { var w wireEventEntry - if err := json.Unmarshal(data, &w); err != nil { + if err := json.Unmarshal(data, &w, jsonx.V1()); err != nil { return err } @@ -78,7 +80,7 @@ type wireStartReplayInput struct { // struct-tag-driven json.Unmarshal. func (in *StartReplayInput) UnmarshalJSON(data []byte) error { var w wireStartReplayInput - if err := json.Unmarshal(data, &w); err != nil { + if err := json.Unmarshal(data, &w, jsonx.V1()); err != nil { return err } diff --git a/services/eventbridge/wire_time_test.go b/services/eventbridge/wire_time_test.go index 905e95798f..09e2570d54 100644 --- a/services/eventbridge/wire_time_test.go +++ b/services/eventbridge/wire_time_test.go @@ -1,13 +1,14 @@ package eventbridge_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/eventbridge" ) @@ -55,7 +56,7 @@ func TestEventEntry_UnmarshalJSON_TimeIsEpochSeconds(t *testing.T) { t.Parallel() var entry eventbridge.EventEntry - err := json.Unmarshal([]byte(tt.body), &entry) + err := json.Unmarshal([]byte(tt.body), &entry, jsonx.V1()) if tt.wantErr { require.Error(t, err) @@ -97,7 +98,7 @@ func TestStartReplayInput_UnmarshalJSON_TimesAreEpochSeconds(t *testing.T) { }` var input eventbridge.StartReplayInput - require.NoError(t, json.Unmarshal([]byte(body), &input)) + require.NoError(t, json.Unmarshal([]byte(body), &input, jsonx.V1())) assert.True(t, time.Unix(1_700_000_000, 0).UTC().Equal(input.EventStartTime)) assert.True(t, time.Unix(1_700_003_600, 0).UTC().Equal(input.EventEndTime)) diff --git a/services/firehose/delivery_http.go b/services/firehose/delivery_http.go index 35e5b564f6..b8fb795af0 100644 --- a/services/firehose/delivery_http.go +++ b/services/firehose/delivery_http.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "mime" @@ -17,6 +18,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -60,7 +62,10 @@ func buildHTTPEndpointBody(requestID string, records [][]byte) ([]byte, error) { httpRecords = append(httpRecords, httpRecord{Data: base64.StdEncoding.EncodeToString(rec)}) } - return json.Marshal(httpPayload{RequestID: requestID, Timestamp: time.Now().UnixMilli(), Records: httpRecords}) + return json.Marshal( + httpPayload{RequestID: requestID, Timestamp: time.Now().UnixMilli(), Records: httpRecords}, + jsonx.V1(), + ) } // buildHTTPEndpointRequest constructs one POST with the documented Firehose request headers. @@ -97,7 +102,7 @@ func buildHTTPEndpointRequest( attrs[a.AttributeName] = a.AttributeValue } - if raw, mErr := json.Marshal(map[string]any{"commonAttributes": attrs}); mErr == nil { + if raw, mErr := json.Marshal(map[string]any{"commonAttributes": attrs}, jsonx.V1()); mErr == nil { req.Header.Set("X-Amz-Firehose-Common-Attributes", string(raw)) } } @@ -219,10 +224,10 @@ func validateHTTPResponse(resp *http.Response, raw []byte, requestID string) err } var out struct { - Timestamp *json.RawMessage `json:"timestamp"` - RequestID string `json:"requestId"` + Timestamp *jsontext.Value `json:"timestamp"` + RequestID string `json:"requestId"` } - if err := json.Unmarshal(raw, &out); err != nil || out.RequestID != requestID || out.Timestamp == nil { + if err := json.Unmarshal(raw, &out, jsonx.V1()); err != nil || out.RequestID != requestID || out.Timestamp == nil { return errHTTPResponse } @@ -233,7 +238,7 @@ func endpointErrorMessage(raw []byte, status int) string { var out struct { ErrorMessage string `json:"errorMessage"` } - if json.Unmarshal(raw, &out) == nil && out.ErrorMessage != "" { + if json.Unmarshal(raw, &out, jsonx.V1()) == nil && out.ErrorMessage != "" { return out.ErrorMessage } diff --git a/services/firehose/delivery_opensearch.go b/services/firehose/delivery_opensearch.go index 8d02b9fef4..1bb1bcd8ed 100644 --- a/services/firehose/delivery_opensearch.go +++ b/services/firehose/delivery_opensearch.go @@ -3,12 +3,13 @@ package firehose import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -151,7 +152,7 @@ func indexInProcess(idx OpenSearchIndexer, domainARN, index string, records [][] for _, rec := range records { var doc map[string]any - if err := json.Unmarshal(rec, &doc); err != nil { + if err := json.Unmarshal(rec, &doc, jsonx.V1()); err != nil { failed = append( failed, failureRecord(rec, "", "ES.JsonProcessingException", "record is not a JSON object", 1), diff --git a/services/firehose/delivery_realism_helpers_test.go b/services/firehose/delivery_realism_helpers_test.go index 17743a4df8..e89fd490aa 100644 --- a/services/firehose/delivery_realism_helpers_test.go +++ b/services/firehose/delivery_realism_helpers_test.go @@ -7,7 +7,7 @@ import ( "context" "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -21,6 +21,7 @@ import ( "github.com/klauspost/compress/snappy" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -115,7 +116,7 @@ type transformEvent struct { // metadata.partitionKeys{"tenant": }. func contentTransform(payload []byte, _ int) ([]byte, error) { var ev transformEvent - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, err } @@ -140,7 +141,7 @@ func contentTransform(payload []byte, _ int) ([]byte, error) { } } - return json.Marshal(map[string]any{"records": recs}) + return json.Marshal(map[string]any{"records": recs}, jsonx.V1()) } // denyAuthorizer denies the listed actions; role "untrusted" cannot be assumed. diff --git a/services/firehose/delivery_realism_test.go b/services/firehose/delivery_realism_test.go index e1a22fc15c..cf555cf6f7 100644 --- a/services/firehose/delivery_realism_test.go +++ b/services/firehose/delivery_realism_test.go @@ -2,7 +2,8 @@ package firehose_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -219,7 +221,7 @@ func TestS3Delivery_LambdaProcessorResults(t *testing.T) { var ev transformEvent require.Equal(t, 1, fn.callCount()) - require.NoError(t, json.Unmarshal(fn.payloads[0], &ev)) + require.NoError(t, json.Unmarshal(fn.payloads[0], &ev, jsonx.V1())) assert.NotEmpty(t, ev.InvocationID) assert.Equal(t, rtTestRegion, ev.Region) assert.Regexp(t, `^arn:aws:firehose:us-east-1:000000000000:deliverystream/proc$`, ev.DeliveryStreamARN) @@ -234,7 +236,7 @@ func TestS3Delivery_LambdaProcessorResults(t *testing.T) { require.Len(t, failed, 1) var envlp map[string]string - require.NoError(t, json.Unmarshal(failed[0].body, &envlp)) + require.NoError(t, json.Unmarshal(failed[0].body, &envlp, jsonx.V1())) assert.Equal(t, testLambdaARN, envlp["lambdaARN"]) assert.Equal(t, "ProcessingFailed", envlp["errorCode"]) assert.Equal(t, base64.StdEncoding.EncodeToString([]byte("fail-three")), envlp["rawData"]) @@ -422,7 +424,10 @@ func (e *endpoint) serve(t *testing.T) *httptest.Server { func replyOK(w http.ResponseWriter, requestID string) { w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(map[string]any{"requestId": requestID, "timestamp": time.Now().UnixMilli()}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]any{"requestId": requestID, "timestamp": time.Now().UnixMilli()}, + ) } func TestHTTPEndpoint_RequestContract(t *testing.T) { @@ -468,7 +473,7 @@ func TestHTTPEndpoint_RequestContract(t *testing.T) { } `json:"records"` Timestamp int64 `json:"timestamp"` } - require.NoError(t, json.Unmarshal(call.body, &body)) + require.NoError(t, json.Unmarshal(call.body, &body, jsonx.V1())) assert.Equal(t, call.headers.Get("X-Amz-Firehose-Request-Id"), body.RequestID) assert.Positive(t, body.Timestamp) require.Len(t, body.Records, 2) diff --git a/services/firehose/delivery_splunk.go b/services/firehose/delivery_splunk.go index e3b0a906c3..40116d2f8e 100644 --- a/services/firehose/delivery_splunk.go +++ b/services/firehose/delivery_splunk.go @@ -3,11 +3,12 @@ package firehose import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -25,7 +26,7 @@ func buildSplunkBody(records [][]byte, hecType string) ([]byte, string) { var buf bytes.Buffer for _, rec := range records { - line, marshalErr := json.Marshal(hecEvent{Event: string(rec)}) + line, marshalErr := json.Marshal(hecEvent{Event: string(rec)}, jsonx.V1()) if marshalErr != nil { continue } diff --git a/services/firehose/flush_test.go b/services/firehose/flush_test.go index eeb823ce62..d3809037cf 100644 --- a/services/firehose/flush_test.go +++ b/services/firehose/flush_test.go @@ -3,7 +3,7 @@ package firehose_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -498,7 +499,7 @@ func TestHTTPEndpoint_DeliveryFormat_ViaHandler(t *testing.T) { } `json:"records"` Timestamp int64 `json:"timestamp"` } - require.NoError(t, json.Unmarshal(requests[0].body, &payload)) + require.NoError(t, json.Unmarshal(requests[0].body, &payload, jsonx.V1())) assert.NotEmpty(t, payload.RequestID) assert.Positive(t, payload.Timestamp) @@ -541,7 +542,7 @@ func TestOpenSearch_BulkNDJSON_ViaHandler(t *testing.T) { require.GreaterOrEqual(t, len(lines), 2, "NDJSON must have at least action+document lines") var action map[string]any - require.NoError(t, json.Unmarshal([]byte(lines[0]), &action)) + require.NoError(t, json.Unmarshal([]byte(lines[0]), &action, jsonx.V1())) _, hasIndex := action["index"] assert.True(t, hasIndex, "first NDJSON line must be an index action") } @@ -603,7 +604,7 @@ func TestSplunk_Modes_ViaHandler(t *testing.T) { assert.Contains(t, string(requests[0].body), "splunk-raw-data") } else { var evtBody map[string]any - require.NoError(t, json.Unmarshal(requests[0].body, &evtBody)) + require.NoError(t, json.Unmarshal(requests[0].body, &evtBody, jsonx.V1())) _, hasEvent := evtBody["event"] assert.True(t, hasEvent, "Event mode must wrap data in {event:...}") } @@ -629,7 +630,7 @@ func okLambdaResponse(records ...struct{ id, data string }) []byte { Data: base64.StdEncoding.EncodeToString([]byte(r.data)), }) } - b, _ := json.Marshal(out) + b, _ := json.Marshal(out, jsonx.V1()) return b } @@ -689,7 +690,7 @@ func TestLambdaTransform_AllDestinations(t *testing.T) { Data string `json:"data"` } `json:"records"` } - require.NoError(t, json.Unmarshal(srv.captured()[0].body, &payload)) + require.NoError(t, json.Unmarshal(srv.captured()[0].body, &payload, jsonx.V1())) require.Len(t, payload.Records, 1) decoded, decErr := base64.StdEncoding.DecodeString(payload.Records[0].Data) require.NoError(t, decErr) diff --git a/services/firehose/formats.go b/services/firehose/formats.go index e7fd0a2f54..4e8e0f3cdf 100644 --- a/services/firehose/formats.go +++ b/services/firehose/formats.go @@ -2,10 +2,12 @@ package firehose import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // DataFormatConversionConfig controls record-format conversion (JSON → Parquet/ORC). @@ -168,7 +170,7 @@ func convertRecords( // record is not a valid JSON object, which the caller treats as a conversion failure. func deserializeRecord(deser *Deserializer, rec []byte) ([]byte, bool) { var obj map[string]any - if err := json.Unmarshal(bytes.TrimSpace(rec), &obj); err != nil { + if err := json.Unmarshal(bytes.TrimSpace(rec), &obj, jsonx.V1()); err != nil { return nil, false } @@ -225,13 +227,13 @@ func marshalCanonical(obj map[string]any) ([]byte, error) { if i > 0 { buf.WriteByte(',') } - keyJSON, err := json.Marshal(k) + keyJSON, err := json.Marshal(k, jsonx.V1()) if err != nil { return nil, err } buf.Write(keyJSON) buf.WriteByte(':') - valJSON, err := json.Marshal(obj[k]) + valJSON, err := json.Marshal(obj[k], jsonx.V1()) if err != nil { return nil, err } diff --git a/services/firehose/formats_infer_test.go b/services/firehose/formats_infer_test.go index 6a411b08dc..06aa7cf168 100644 --- a/services/firehose/formats_infer_test.go +++ b/services/firehose/formats_infer_test.go @@ -1,11 +1,11 @@ package firehose_test import ( - "encoding/json" "testing" "github.com/stretchr/testify/assert" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -19,23 +19,23 @@ func TestInferColumnsWidens(t *testing.T) { }{ { name: "int then float", want: "double", - objs: []map[string]any{{"c": json.Number("3")}, {"c": json.Number("3.5")}}, + objs: []map[string]any{{"c": jsonx.Number("3")}, {"c": jsonx.Number("3.5")}}, }, { name: "float then int", want: "double", - objs: []map[string]any{{"c": json.Number("3.5")}, {"c": json.Number("3")}}, + objs: []map[string]any{{"c": jsonx.Number("3.5")}, {"c": jsonx.Number("3")}}, }, { name: "string then int", want: "string", - objs: []map[string]any{{"c": "abc"}, {"c": json.Number("5")}}, + objs: []map[string]any{{"c": "abc"}, {"c": jsonx.Number("5")}}, }, { name: "int then string", want: "string", - objs: []map[string]any{{"c": json.Number("5")}, {"c": "abc"}}, + objs: []map[string]any{{"c": jsonx.Number("5")}, {"c": "abc"}}, }, { name: "leading null", want: "bigint", - objs: []map[string]any{{"c": nil}, {"c": json.Number("5")}}, + objs: []map[string]any{{"c": nil}, {"c": jsonx.Number("5")}}, }, { name: "only null", want: "string", @@ -43,7 +43,7 @@ func TestInferColumnsWidens(t *testing.T) { }, { name: "bool and int", want: "string", - objs: []map[string]any{{"c": true}, {"c": json.Number("1")}}, + objs: []map[string]any{{"c": true}, {"c": jsonx.Number("1")}}, }, } diff --git a/services/firehose/formats_parquet.go b/services/firehose/formats_parquet.go index cd2929e0c3..3d030bdd7f 100644 --- a/services/firehose/formats_parquet.go +++ b/services/firehose/formats_parquet.go @@ -3,12 +3,14 @@ package firehose import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "sort" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -120,7 +122,7 @@ func inferType(v any) string { switch t := v.(type) { case bool: return colBoolean - case json.Number: + case jsonx.Number: if _, err := t.Int64(); err == nil { return colBigint } @@ -132,11 +134,10 @@ func inferType(v any) string { } func decodeObject(rec []byte) (map[string]any, bool) { - dec := json.NewDecoder(bytes.NewReader(bytes.TrimSpace(rec))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(bytes.TrimSpace(rec))) var obj map[string]any - if err := dec.Decode(&obj); err != nil || obj == nil { + if err := json.UnmarshalDecode(dec, &obj, jsonx.V1(), jsonx.UseNumber()); err != nil || obj == nil { return nil, false } @@ -162,10 +163,10 @@ func cellFor(obj map[string]any, col string) any { return t case bool: return t - case json.Number: + case jsonx.Number: return t.String() default: - b, err := json.Marshal(t) + b, err := json.Marshal(t, jsonx.V1()) if err != nil { return nil } diff --git a/services/firehose/handler.go b/services/firehose/handler.go index 448dfb73bc..099c821b0f 100644 --- a/services/firehose/handler.go +++ b/services/firehose/handler.go @@ -2,7 +2,7 @@ package firehose import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -145,7 +146,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req deliveryStreamNameInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.DeliveryStreamName } @@ -195,12 +196,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError respond := func(status int, errType string) error { msg := strings.TrimPrefix(err.Error(), errType+": ") @@ -218,7 +217,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, errUnknownAction): return respond(http.StatusBadRequest, "UnknownOperationException") case errors.Is(err, errInvalidRequest), errors.Is(err, awserr.ErrInvalidParameter), - errors.Is(err, ErrValidation), errors.As(err, &syntaxErr), errors.As(err, &typeErr): + errors.Is(err, ErrValidation), jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return respond(http.StatusBadRequest, "InvalidArgumentException") default: return c.JSON(http.StatusInternalServerError, map[string]string{errFieldMessage: err.Error()}) diff --git a/services/firehose/handler_delivery_streams.go b/services/firehose/handler_delivery_streams.go index e646932a98..4e0ad367a7 100644 --- a/services/firehose/handler_delivery_streams.go +++ b/services/firehose/handler_delivery_streams.go @@ -2,7 +2,7 @@ package firehose import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" @@ -328,7 +328,7 @@ type createDeliveryStreamInput struct { // not a typed struct) so handleCreateDeliveryStream can reject it explicitly instead // of silently dropping it and creating a stream with zero destinations -- see // validateSingleDestination. - AmazonOpenSearchServerlessDestinationConfiguration json.RawMessage `json:"AmazonOpenSearchServerlessDestinationConfiguration,omitempty"` //nolint:lll // AWS field name + AmazonOpenSearchServerlessDestinationConfiguration jsontext.Value `json:"AmazonOpenSearchServerlessDestinationConfiguration,omitempty"` //nolint:lll // AWS field name DatabaseSourceConfiguration *databaseSourceConfigurationInput `json:"DatabaseSourceConfiguration"` //nolint:lll // AWS field name DirectPutSourceConfiguration *directPutSourceConfigurationInput `json:"DirectPutSourceConfiguration"` //nolint:lll // AWS field name DeliveryStreamEncryptionConfigurationInput *EncryptionConfigInput `json:"DeliveryStreamEncryptionConfigurationInput"` //nolint:lll // AWS field name diff --git a/services/firehose/handler_delivery_streams_test.go b/services/firehose/handler_delivery_streams_test.go index cdd8203d49..db49e56ab5 100644 --- a/services/firehose/handler_delivery_streams_test.go +++ b/services/firehose/handler_delivery_streams_test.go @@ -1,7 +1,7 @@ package firehose_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -530,7 +531,7 @@ func TestDeleteThenDescribeReturns404(t *testing.T) { assert.Equal(t, http.StatusNotFound, descRec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -681,7 +682,7 @@ func TestDescribeDeliveryStream_SourceField(t *testing.T) { Source *firehose.SourceDescription `json:"Source"` } `json:"DeliveryStreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.DeliveryStreamDescription.Source) require.NotNil(t, out.DeliveryStreamDescription.Source.KinesisStreamSourceDescription) assert.Equal(t, "arn:aws:kinesis:us-east-1:000000000000:stream/my-ks", @@ -761,7 +762,7 @@ func TestDescribeDeliveryStream_Timestamps(t *testing.T) { LastUpdateTimestamp *int64 `json:"LastUpdateTimestamp"` } `json:"DeliveryStreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out.DeliveryStreamDescription.CreateTimestamp) assert.NotNil(t, out.DeliveryStreamDescription.LastUpdateTimestamp) assert.Positive(t, *out.DeliveryStreamDescription.CreateTimestamp) @@ -1139,7 +1140,7 @@ func TestListDeliveryStreams_Empty(t *testing.T) { DeliveryStreamNames []string `json:"DeliveryStreamNames"` HasMoreDeliveryStreams bool `json:"HasMoreDeliveryStreams"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.DeliveryStreamNames) assert.False(t, out.HasMoreDeliveryStreams) } @@ -1161,7 +1162,7 @@ func TestListDeliveryStreams_Limit(t *testing.T) { DeliveryStreamNames []string `json:"DeliveryStreamNames"` HasMoreDeliveryStreams bool `json:"HasMoreDeliveryStreams"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.DeliveryStreamNames, 2) assert.True(t, out.HasMoreDeliveryStreams) } @@ -1183,7 +1184,7 @@ func TestListDeliveryStreams_ExclusiveStart(t *testing.T) { var out struct { DeliveryStreamNames []string `json:"DeliveryStreamNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, []string{"b-stream", "c-stream"}, out.DeliveryStreamNames) } @@ -1205,7 +1206,7 @@ func TestListDeliveryStreams_Pagination(t *testing.T) { DeliveryStreamNames []string `json:"DeliveryStreamNames"` HasMoreDeliveryStreams bool `json:"HasMoreDeliveryStreams"` } - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.DeliveryStreamNames, 2) assert.True(t, page1.HasMoreDeliveryStreams) @@ -1219,7 +1220,7 @@ func TestListDeliveryStreams_Pagination(t *testing.T) { DeliveryStreamNames []string `json:"DeliveryStreamNames"` HasMoreDeliveryStreams bool `json:"HasMoreDeliveryStreams"` } - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.DeliveryStreamNames, 2) // No overlap between pages. for _, n := range page2.DeliveryStreamNames { @@ -1249,7 +1250,7 @@ func TestListDeliveryStreams_TypeFilter(t *testing.T) { var out struct { DeliveryStreamNames []string `json:"DeliveryStreamNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out.DeliveryStreamNames, "direct-put-stream") assert.NotContains(t, out.DeliveryStreamNames, "kinesis-src-stream-lf") @@ -1259,7 +1260,7 @@ func TestListDeliveryStreams_TypeFilter(t *testing.T) { var out2 struct { DeliveryStreamNames []string `json:"DeliveryStreamNames"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Contains(t, out2.DeliveryStreamNames, "kinesis-src-stream-lf") assert.NotContains(t, out2.DeliveryStreamNames, "direct-put-stream") @@ -1273,7 +1274,7 @@ func TestListDeliveryStreams_TypeFilter(t *testing.T) { var outInvalid struct { DeliveryStreamNames []string `json:"DeliveryStreamNames"` } - require.NoError(t, json.Unmarshal(recInvalid.Body.Bytes(), &outInvalid)) + require.NoError(t, json.Unmarshal(recInvalid.Body.Bytes(), &outInvalid, jsonx.V1())) assert.NotContains(t, outInvalid.DeliveryStreamNames, "direct-put-stream") assert.NotContains(t, outInvalid.DeliveryStreamNames, "kinesis-src-stream-lf") } diff --git a/services/firehose/handler_destination_updates.go b/services/firehose/handler_destination_updates.go index 9cc06868fa..d19c1d6326 100644 --- a/services/firehose/handler_destination_updates.go +++ b/services/firehose/handler_destination_updates.go @@ -2,7 +2,7 @@ package firehose import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" ) @@ -29,7 +29,7 @@ type updateDestinationInput struct { // AmazonOpenSearchServerlessDestinationUpdate: see createDeliveryStreamInput's // AmazonOpenSearchServerlessDestinationConfiguration doc comment -- same // unimplemented-11th-destination-type reasoning, captured only to reject explicitly. - AmazonOpenSearchServerlessDestinationUpdate json.RawMessage `json:"AmazonOpenSearchServerlessDestinationUpdate,omitempty"` //nolint:lll // AWS field name + AmazonOpenSearchServerlessDestinationUpdate jsontext.Value `json:"AmazonOpenSearchServerlessDestinationUpdate,omitempty"` //nolint:lll // AWS field name } type updateDestinationOutput struct{} diff --git a/services/firehose/handler_destination_updates_test.go b/services/firehose/handler_destination_updates_test.go index 888e8786e2..b127f5d165 100644 --- a/services/firehose/handler_destination_updates_test.go +++ b/services/firehose/handler_destination_updates_test.go @@ -1,13 +1,14 @@ package firehose_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -85,7 +86,7 @@ func TestUpdateDestination_Success_VersionIncrements(t *testing.T) { } `json:"Destinations"` } `json:"DeliveryStreamDescription"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &descOut, jsonx.V1())) versionBefore := descOut.DeliveryStreamDescription.VersionID rec := doFirehoseRequest(t, h, "UpdateDestination", map[string]any{ @@ -112,7 +113,7 @@ func TestUpdateDestination_Success_VersionIncrements(t *testing.T) { } `json:"Destinations"` } `json:"DeliveryStreamDescription"` } - require.NoError(t, json.Unmarshal(desc2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(desc2.Body.Bytes(), &descOut2, jsonx.V1())) assert.NotEqual(t, versionBefore, descOut2.DeliveryStreamDescription.VersionID) require.Len(t, descOut2.DeliveryStreamDescription.Destinations, 1) assert.Equal(t, "arn:aws:s3:::updated-bucket", @@ -247,7 +248,7 @@ func TestUpdateDestination_VersionMismatchRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ConcurrentModificationException", body["__type"]) } diff --git a/services/firehose/handler_records_test.go b/services/firehose/handler_records_test.go index bb16b06e4c..d518b27c15 100644 --- a/services/firehose/handler_records_test.go +++ b/services/firehose/handler_records_test.go @@ -2,13 +2,14 @@ package firehose_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -82,7 +83,7 @@ func TestPutRecord_Success_ReturnsRecordId(t *testing.T) { var out struct { RecordID string `json:"RecordId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.RecordID) } @@ -170,7 +171,7 @@ func TestKinesisStreamAsSource_PutRecordRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", body["__type"]) } @@ -249,7 +250,7 @@ func TestPutRecordBatch_Success_ResponseShape(t *testing.T) { RequestResponses []any `json:"RequestResponses"` FailedPutCount int `json:"FailedPutCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, 0, out.FailedPutCount) assert.NotNil(t, out.RequestResponses) } @@ -303,7 +304,7 @@ func TestPutRecordBatch_ResponseShape(t *testing.T) { } `json:"RequestResponses"` FailedPutCount int `json:"FailedPutCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, 0, out.FailedPutCount, "FailedPutCount must always be 0") assert.Len(t, out.RequestResponses, len(tc.recordData), "one response per record") @@ -355,7 +356,7 @@ func TestPutRecordBatch_PerRecordRecordId(t *testing.T) { } `json:"RequestResponses"` FailedPutCount int `json:"FailedPutCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, 0, out.FailedPutCount) require.Len(t, out.RequestResponses, tt.recordCount, @@ -457,7 +458,7 @@ func TestPutRecord_EncryptedField(t *testing.T) { var putOut struct { Encrypted bool `json:"Encrypted"` } - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putOut, jsonx.V1())) assert.Equal(t, tt.wantEncrypted, putOut.Encrypted, "PutRecord Encrypted mismatch") batchRec := doFirehoseRequest(t, h, "PutRecordBatch", map[string]any{ @@ -469,7 +470,7 @@ func TestPutRecord_EncryptedField(t *testing.T) { var batchOut struct { Encrypted bool `json:"Encrypted"` } - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchOut)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchOut, jsonx.V1())) assert.Equal(t, tt.wantEncrypted, batchOut.Encrypted, "PutRecordBatch Encrypted mismatch") }) } diff --git a/services/firehose/handler_tags_test.go b/services/firehose/handler_tags_test.go index c1ceaa052b..92cc0e625a 100644 --- a/services/firehose/handler_tags_test.go +++ b/services/firehose/handler_tags_test.go @@ -1,13 +1,14 @@ package firehose_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -148,7 +149,7 @@ func TestUntagDeliveryStream_RemovesSpecificKeys(t *testing.T) { var out struct { Tags []map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Tags, 1) assert.Equal(t, "team", out.Tags[0]["Key"]) } @@ -280,7 +281,7 @@ func TestListTagsForDeliveryStream_Limit(t *testing.T) { Tags []map[string]string `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Tags, 3) assert.True(t, out.HasMoreTags) } @@ -313,7 +314,7 @@ func TestListTagsForDeliveryStream_ExclusiveStart(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Tags, 2) assert.Equal(t, "b-key", out.Tags[0].Key) assert.Equal(t, "c-key", out.Tags[1].Key) @@ -409,7 +410,7 @@ func TestTagsLifecycle(t *testing.T) { Tags []map[string]string `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Tags, 4) assert.False(t, listOut.HasMoreTags) // Keys must be sorted: env, region, team, version. @@ -425,7 +426,7 @@ func TestTagsLifecycle(t *testing.T) { Tags []map[string]string `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Tags, 2) assert.True(t, page1.HasMoreTags) assert.Equal(t, "env", page1.Tags[0]["Key"]) @@ -441,7 +442,7 @@ func TestTagsLifecycle(t *testing.T) { Tags []map[string]string `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2, jsonx.V1())) require.Len(t, page2.Tags, 2) assert.False(t, page2.HasMoreTags) assert.Equal(t, "team", page2.Tags[0]["Key"]) @@ -459,7 +460,7 @@ func TestTagsLifecycle(t *testing.T) { var finalOut struct { Tags []map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(finalRec.Body.Bytes(), &finalOut)) + require.NoError(t, json.Unmarshal(finalRec.Body.Bytes(), &finalOut, jsonx.V1())) require.Len(t, finalOut.Tags, 2) keys := map[string]bool{} diff --git a/services/firehose/handler_test.go b/services/firehose/handler_test.go index 59faed73d5..97634dc783 100644 --- a/services/firehose/handler_test.go +++ b/services/firehose/handler_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "log/slog" "maps" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -33,7 +34,7 @@ func doFirehoseRequest(t *testing.T, h *firehose.Handler, action string, body an var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -90,7 +91,7 @@ func auditCreateStream(t *testing.T, h *firehose.Handler, name string, extra map var out struct { DeliveryStreamARN string `json:"DeliveryStreamARN"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.DeliveryStreamARN } @@ -104,7 +105,7 @@ func auditDescribe(t *testing.T, h *firehose.Handler, name string) map[string]an require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["DeliveryStreamDescription"].(map[string]any) } @@ -423,7 +424,7 @@ func TestErrorResponse_ResourceInUseException_HasType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceInUseException", body["__type"], "duplicate-stream error must carry __type=ResourceInUseException") } @@ -475,7 +476,7 @@ func TestErrorResponse_InvalidArgumentException_HasType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", body["__type"], "validation error must carry __type=InvalidArgumentException; got: %v", body) }) @@ -491,7 +492,7 @@ func TestErrorResponse_ResourceNotFoundException_HasType(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"], "not-found error must carry __type=ResourceNotFoundException") } @@ -504,7 +505,7 @@ func TestErrorResponse_UnknownOperation_HasType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "UnknownOperationException", body["__type"], "unknown operation must carry __type=UnknownOperationException") } diff --git a/services/firehose/http_endpoint_secret_test.go b/services/firehose/http_endpoint_secret_test.go index 3441dd79d2..bb78cfc88d 100644 --- a/services/firehose/http_endpoint_secret_test.go +++ b/services/firehose/http_endpoint_secret_test.go @@ -1,12 +1,14 @@ package firehose_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDescribeDeliveryStream_HTTPEndpointOmitsAccessKey(t *testing.T) { @@ -51,7 +53,7 @@ func TestDescribeDeliveryStream_HTTPEndpointOmitsAccessKey(t *testing.T) { } `json:"Destinations"` } `json:"DeliveryStreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.DeliveryStreamDescription.Destinations, 1) ec := out.DeliveryStreamDescription.Destinations[0].HTTP.EndpointConfiguration diff --git a/services/firehose/isolation_test.go b/services/firehose/isolation_test.go index d7a55dbe3f..f904eff5f6 100644 --- a/services/firehose/isolation_test.go +++ b/services/firehose/isolation_test.go @@ -2,7 +2,7 @@ package firehose //nolint:testpackage // existing issue. import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestFirehoseRegionIsolation(t *testing.T) { //nolint:paralleltest // existing issue. @@ -25,7 +26,7 @@ func TestFirehoseRegionIsolation(t *testing.T) { //nolint:paralleltest // existi DeliveryStreamName: name, DeliveryStreamType: "DirectPut", } - body, _ := json.Marshal(input) + body, _ := json.Marshal(input, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", firehoseTargetPrefix+"CreateDeliveryStream") req.Header.Set( @@ -43,7 +44,7 @@ func TestFirehoseRegionIsolation(t *testing.T) { //nolint:paralleltest // existi listStreams := func(region string) []string { input := listDeliveryStreamsInput{} - body, _ := json.Marshal(input) + body, _ := json.Marshal(input, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("X-Amz-Target", firehoseTargetPrefix+"ListDeliveryStreams") req.Header.Set( @@ -59,7 +60,7 @@ func TestFirehoseRegionIsolation(t *testing.T) { //nolint:paralleltest // existi assert.Equal(t, http.StatusOK, rec.Code) var output listDeliveryStreamsOutput - err = json.Unmarshal(rec.Body.Bytes(), &output) + err = json.Unmarshal(rec.Body.Bytes(), &output, jsonx.V1()) require.NoError(t, err) return output.DeliveryStreamNames diff --git a/services/firehose/non_s3_delivery_test.go b/services/firehose/non_s3_delivery_test.go index ba1c4e6461..9f08e931d9 100644 --- a/services/firehose/non_s3_delivery_test.go +++ b/services/firehose/non_s3_delivery_test.go @@ -3,7 +3,8 @@ package firehose_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -50,7 +52,7 @@ func newCaptureServer(t *testing.T, statusCode int) *captureServer { cs.mu.Unlock() w.Header().Set("Content-Type", "application/json") w.WriteHeader(statusCode) - _ = json.NewEncoder(w).Encode(map[string]any{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{ "requestId": r.Header.Get("X-Amz-Firehose-Request-Id"), "timestamp": time.Now().UnixMilli(), }) @@ -151,7 +153,7 @@ func TestFirehose_HTTPEndpoint_Delivery(t *testing.T) { } `json:"records"` Timestamp int64 `json:"timestamp"` } - require.NoError(t, json.Unmarshal(reqs[0].body, &payload)) + require.NoError(t, json.Unmarshal(reqs[0].body, &payload, jsonx.V1())) assert.NotEmpty(t, payload.RequestID) assert.Positive(t, payload.Timestamp) diff --git a/services/firehose/partitioning.go b/services/firehose/partitioning.go index 1eaf96cb91..2eed5d7491 100644 --- a/services/firehose/partitioning.go +++ b/services/firehose/partitioning.go @@ -1,9 +1,11 @@ package firehose import ( - "encoding/json" + "encoding/json/v2" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // partitionQueryNamespace is the Firehose namespace for jq-derived partition keys. @@ -81,7 +83,7 @@ func partitionValue( if !*parsed { *parsed = true - if err := json.Unmarshal(rec, obj); err != nil { + if err := json.Unmarshal(rec, obj, jsonx.V1()); err != nil { return "", false } } @@ -292,7 +294,7 @@ func scalarToString(v any) (string, bool) { } return "false", true - case json.Number: + case jsonx.Number: return val.String(), true case float64: // Render integers without a trailing ".0" to match typical partition values. diff --git a/services/firehose/persistence.go b/services/firehose/persistence.go index 321c066787..3269eba568 100644 --- a/services/firehose/persistence.go +++ b/services/firehose/persistence.go @@ -2,10 +2,12 @@ package firehose import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -39,10 +41,10 @@ const firehoseSnapshotVersion = 2 // key is derived from), so no DTO layer is needed the way services/ses or // services/neptune required for region-nested types with a hidden field. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -66,7 +68,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "firehose: failed to marshal snapshot", "error", err) diff --git a/services/firehose/persistence_test.go b/services/firehose/persistence_test.go index ad82d67cea..c1a5bebe0a 100644 --- a/services/firehose/persistence_test.go +++ b/services/firehose/persistence_test.go @@ -2,12 +2,13 @@ package firehose_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/firehose" ) @@ -252,9 +253,9 @@ func TestInMemoryBackend_RestoreVersionMismatch(t *testing.T) { require.NotNil(t, raw) var generic map[string]any - require.NoError(t, json.Unmarshal(raw, &generic)) + require.NoError(t, json.Unmarshal(raw, &generic, jsonx.V1())) tt.mutate(t, generic) - mutated, err := json.Marshal(generic) + mutated, err := json.Marshal(generic, jsonx.V1()) require.NoError(t, err) // Target already holds unrelated state, which the version-mismatch path must diff --git a/services/firehose/transform.go b/services/firehose/transform.go index a0b8020b03..0bb730a404 100644 --- a/services/firehose/transform.go +++ b/services/firehose/transform.go @@ -3,7 +3,7 @@ package firehose import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strconv" @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -94,7 +95,7 @@ func failureRecord(raw []byte, lambdaARN, code, msg string, attempts int) []byte AttemptEndingTimestamp: now, RawData: base64.StdEncoding.EncodeToString(raw), LambdaARN: lambdaARN, - }) + }, jsonx.V1()) if err != nil { return raw } @@ -126,7 +127,7 @@ func buildLambdaTransformPayload(records [][]byte, streamARN, region string) ([] } } - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { return nil, nil } @@ -145,7 +146,7 @@ func parseLambdaTransformResponse( ErrorMessage string `json:"errorMessage"` Records []lambdaTransformResponseRecord `json:"records"` } - if err := json.Unmarshal(result, &resp); err != nil { + if err := json.Unmarshal(result, &resp, jsonx.V1()); err != nil { return transformOutcome{}, &transformError{code: codeLambdaJSON, err: err} } diff --git a/services/fis/actions_test.go b/services/fis/actions_test.go index 9c230c8c77..4a74c23e3c 100644 --- a/services/fis/actions_test.go +++ b/services/fis/actions_test.go @@ -1,7 +1,7 @@ package fis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -612,7 +613,7 @@ func TestFISHandler_StopExperiment_AlreadyStopped(t *testing.T) { } `json:"experiment"` } - if err := json.Unmarshal(rec3.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1()); err != nil { return false } @@ -710,7 +711,7 @@ func TestFISHandler_ExperimentFails_WhenActionProviderFails(t *testing.T) { rec3 := doRequest(t, h, http.MethodGet, "/experiments/"+expID, nil) require.Equal(t, http.StatusOK, rec3.Code) - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &finalResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &finalResp, jsonx.V1())) require.Equal(t, "failed", finalResp.Experiment.Status.Status) // Regression test: cleanupActions used to unconditionally overwrite @@ -799,7 +800,7 @@ func TestFISHandler_ExperimentSucceeds_WithMockActionProvider(t *testing.T) { } `json:"experiment"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) require.Equal(t, "completed", resp.Experiment.Status.Status) }) } diff --git a/services/fis/experiment_actions_mode_test.go b/services/fis/experiment_actions_mode_test.go index af73407e38..ebc5822b5d 100644 --- a/services/fis/experiment_actions_mode_test.go +++ b/services/fis/experiment_actions_mode_test.go @@ -1,7 +1,8 @@ package fis_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -39,10 +41,10 @@ func actionsModeTemplateBody() map[string]any { // pollExperimentUntilTerminal polls GET /experiments/{id} until the experiment // reaches a terminal status and returns the decoded response body. -func pollExperimentUntilTerminal(t *testing.T, h *fis.Handler, expID string) map[string]json.RawMessage { +func pollExperimentUntilTerminal(t *testing.T, h *fis.Handler, expID string) map[string]jsontext.Value { t.Helper() - var result map[string]json.RawMessage + var result map[string]jsontext.Value require.Eventually(t, func() bool { r := doRequest(t, h, http.MethodGet, "/experiments/"+expID, nil) @@ -51,10 +53,10 @@ func pollExperimentUntilTerminal(t *testing.T, h *fis.Handler, expID string) map } var full struct { - Experiment map[string]json.RawMessage `json:"experiment"` + Experiment map[string]jsontext.Value `json:"experiment"` } - if err := json.Unmarshal(r.Body.Bytes(), &full); err != nil { + if err := json.Unmarshal(r.Body.Bytes(), &full, jsonx.V1()); err != nil { return false } @@ -62,7 +64,7 @@ func pollExperimentUntilTerminal(t *testing.T, h *fis.Handler, expID string) map Status string `json:"status"` } - if err := json.Unmarshal(full.Experiment["status"], &status); err != nil { + if err := json.Unmarshal(full.Experiment["status"], &status, jsonx.V1()); err != nil { return false } @@ -127,7 +129,7 @@ func TestStartExperiment_ActionsMode_SkipAll_SkipsActionsAndProvider(t *testing. Status string `json:"status"` } - require.NoError(t, json.Unmarshal(exp["status"], &status)) + require.NoError(t, json.Unmarshal(exp["status"], &status, jsonx.V1())) assert.Equal(t, "completed", status.Status) var actions map[string]struct { @@ -136,7 +138,7 @@ func TestStartExperiment_ActionsMode_SkipAll_SkipsActionsAndProvider(t *testing. } `json:"status"` } - require.NoError(t, json.Unmarshal(exp["actions"], &actions)) + require.NoError(t, json.Unmarshal(exp["actions"], &actions, jsonx.V1())) require.Contains(t, actions, "modeAction") assert.Equal(t, "skipped", actions["modeAction"].Status.Status) @@ -188,7 +190,7 @@ func TestStartExperiment_ActionsMode_RunAll_InvokesProvider(t *testing.T) { Status string `json:"status"` } - require.NoError(t, json.Unmarshal(exp["status"], &status)) + require.NoError(t, json.Unmarshal(exp["status"], &status, jsonx.V1())) assert.Equal(t, "completed", status.Status) assert.Equal(t, 1, mock.Calls, "run-all must invoke the external action provider exactly once") }) diff --git a/services/fis/experiment_execution_test.go b/services/fis/experiment_execution_test.go index f868fdaf2d..298545dc4e 100644 --- a/services/fis/experiment_execution_test.go +++ b/services/fis/experiment_execution_test.go @@ -1,7 +1,7 @@ package fis_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -75,7 +76,7 @@ func TestFISHandler_ExperimentCompletesAfterDuration(t *testing.T) { } `json:"experiment"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) require.Equal(t, "completed", resp.Experiment.Status.Status) }) } @@ -156,7 +157,7 @@ func TestFISHandler_ExperimentCompletes_NoTimedActions(t *testing.T) { } `json:"experiment"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp, jsonx.V1())) require.Equal(t, "completed", resp.Experiment.Status.Status) }) } diff --git a/services/fis/experiment_reports_test.go b/services/fis/experiment_reports_test.go index 666af94159..2b35b29de3 100644 --- a/services/fis/experiment_reports_test.go +++ b/services/fis/experiment_reports_test.go @@ -1,7 +1,8 @@ package fis_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -228,7 +230,7 @@ func startExperimentAndPollTerminal(t *testing.T, h *fis.Handler, templateID str Experiment experimentReportPollResult `json:"experiment"` } - if err := json.Unmarshal(r.Body.Bytes(), &full); err != nil { + if err := json.Unmarshal(r.Body.Bytes(), &full, jsonx.V1()); err != nil { return false } @@ -321,13 +323,13 @@ func TestGetExperiment_NoReportConfig_OmitsReportFields(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value mustJSON(t, rec, &raw) - var exp map[string]json.RawMessage + var exp map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw["experiment"], &exp)) + require.NoError(t, json.Unmarshal(raw["experiment"], &exp, jsonx.V1())) _, hasReportConfig := exp["experimentReportConfiguration"] _, hasReport := exp["experimentReport"] diff --git a/services/fis/experiment_status_test.go b/services/fis/experiment_status_test.go index b74c153c6c..0889d871fa 100644 --- a/services/fis/experiment_status_test.go +++ b/services/fis/experiment_status_test.go @@ -1,7 +1,8 @@ package fis_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -51,13 +53,13 @@ func TestExperiment_EndTime_AbsentBeforeComplete(t *testing.T) { require.Equal(t, http.StatusCreated, rec2.Code) // Immediately after start, endTime should be absent (omitempty). - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value mustJSON(t, rec2, &raw) - var expRaw map[string]json.RawMessage + var expRaw map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw)) + require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw, jsonx.V1())) _, hasEndTime := expRaw["endTime"] assert.False(t, hasEndTime, "endTime must be absent on a running experiment") } @@ -113,13 +115,13 @@ func TestExperiment_EndTime_PresentAfterComplete(t *testing.T) { rec3 := doRequest(t, h, http.MethodGet, "/experiments/"+expID, nil) require.Equal(t, http.StatusOK, rec3.Code) - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value mustJSON(t, rec3, &raw) - var expRaw map[string]json.RawMessage + var expRaw map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw)) + require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw, jsonx.V1())) statusRaw, hasStatus := expRaw["status"] require.True(t, hasStatus) @@ -128,7 +130,7 @@ func TestExperiment_EndTime_PresentAfterComplete(t *testing.T) { Status string `json:"status"` } - require.NoError(t, json.Unmarshal(statusRaw, &status)) + require.NoError(t, json.Unmarshal(statusRaw, &status, jsonx.V1())) require.Equal(t, "completed", status.Status) endTimeRaw, hasEndTime := expRaw["endTime"] @@ -136,7 +138,7 @@ func TestExperiment_EndTime_PresentAfterComplete(t *testing.T) { var endTime float64 - require.NoError(t, json.Unmarshal(endTimeRaw, &endTime)) + require.NoError(t, json.Unmarshal(endTimeRaw, &endTime, jsonx.V1())) assert.Greater(t, endTime, 0.0, "endTime must be a positive Unix timestamp") }) } @@ -359,13 +361,13 @@ func TestExperiment_StatusAndState_BothPresent(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value mustJSON(t, rec, &raw) - var expRaw map[string]json.RawMessage + var expRaw map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw)) + require.NoError(t, json.Unmarshal(raw["experiment"], &expRaw, jsonx.V1())) _, hasStatus := expRaw["status"] _, hasState := expRaw["state"] assert.True(t, hasStatus, "experiment must have 'status' field") @@ -522,22 +524,22 @@ func TestExperimentStatus_ErrorField_Present(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) - var resp map[string]json.RawMessage + var resp map[string]jsontext.Value mustJSON(t, rec, &resp) expRaw := resp["experiment"] - var exp map[string]json.RawMessage + var exp map[string]jsontext.Value - require.NoError(t, json.Unmarshal(expRaw, &exp)) + require.NoError(t, json.Unmarshal(expRaw, &exp, jsonx.V1())) statusRaw, ok := exp["status"] require.True(t, ok, "experiment should have status field") - var status map[string]json.RawMessage + var status map[string]jsontext.Value - require.NoError(t, json.Unmarshal(statusRaw, &status)) + require.NoError(t, json.Unmarshal(statusRaw, &status, jsonx.V1())) // state.error should be absent for non-failed experiments (omitempty). _, hasError := status["error"] diff --git a/services/fis/experiments_test.go b/services/fis/experiments_test.go index 4c46837045..a8ee5a72c5 100644 --- a/services/fis/experiments_test.go +++ b/services/fis/experiments_test.go @@ -1,7 +1,7 @@ package fis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -532,7 +533,7 @@ func TestListExperiments_FilterByStatus(t *testing.T) { } `json:"experiments"` } - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &gr, jsonx.V1())) assert.NotEmpty(t, gr.Experiments) }) } diff --git a/services/fis/handler_experiment_templates.go b/services/fis/handler_experiment_templates.go index e8adb7019d..4da3662003 100644 --- a/services/fis/handler_experiment_templates.go +++ b/services/fis/handler_experiment_templates.go @@ -2,10 +2,12 @@ package fis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -18,7 +20,7 @@ func (h *Handler) handleCreateExperimentTemplate( body []byte, ) error { var input createExperimentTemplateRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "invalid request body: "+err.Error(), "") } @@ -45,7 +47,7 @@ func (h *Handler) handleGetExperimentTemplate(c *echo.Context, id string) error func (h *Handler) handleUpdateExperimentTemplate(c *echo.Context, id string, body []byte) error { var input updateExperimentTemplateRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "invalid request body: "+err.Error(), id) } diff --git a/services/fis/handler_experiments.go b/services/fis/handler_experiments.go index ceed6b3a4c..11fb193a1d 100644 --- a/services/fis/handler_experiments.go +++ b/services/fis/handler_experiments.go @@ -2,11 +2,13 @@ package fis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "slices" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -15,7 +17,7 @@ import ( func (h *Handler) handleStartExperiment(ctx context.Context, c *echo.Context, body []byte) error { var input startExperimentRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "invalid request body: "+err.Error(), "") } diff --git a/services/fis/handler_safety_levers.go b/services/fis/handler_safety_levers.go index bdc6a747a0..d79ada85a1 100644 --- a/services/fis/handler_safety_levers.go +++ b/services/fis/handler_safety_levers.go @@ -1,10 +1,12 @@ package fis import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -22,7 +24,7 @@ func (h *Handler) handleGetSafetyLever(c *echo.Context, id string) error { func (h *Handler) handleUpdateSafetyLeverState(c *echo.Context, id string, body []byte) error { var input updateSafetyLeverStateRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "invalid request body: "+err.Error(), id) } diff --git a/services/fis/handler_tags.go b/services/fis/handler_tags.go index ad4140cb96..26b54195a2 100644 --- a/services/fis/handler_tags.go +++ b/services/fis/handler_tags.go @@ -1,11 +1,13 @@ package fis import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -17,7 +19,7 @@ func (h *Handler) handleTagResource(c *echo.Context, arnStr string, body []byte) Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "invalid request body: "+err.Error(), arnStr) } diff --git a/services/fis/handler_target_account_configurations.go b/services/fis/handler_target_account_configurations.go index 9e27a7dfd4..4961009de4 100644 --- a/services/fis/handler_target_account_configurations.go +++ b/services/fis/handler_target_account_configurations.go @@ -1,7 +1,7 @@ package fis import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -31,7 +32,7 @@ func (h *Handler) handleCreateTargetAccountConfiguration( templateID, accountID := splitCompositeID(compositeID) var input createTargetAccountConfigurationRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -101,7 +102,7 @@ func (h *Handler) handleUpdateTargetAccountConfiguration( templateID, accountID := splitCompositeID(compositeID) var input updateTargetAccountConfigurationRequest - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/fis/handler_test.go b/services/fis/handler_test.go index a8250958f1..5b9280c50d 100644 --- a/services/fis/handler_test.go +++ b/services/fis/handler_test.go @@ -3,7 +3,7 @@ package fis_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -36,7 +37,7 @@ func doRequest(t *testing.T, h *fis.Handler, method, path string, body any) *htt if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -55,7 +56,7 @@ func doRequest(t *testing.T, h *fis.Handler, method, path string, body any) *htt func mustJSON(t *testing.T, rec *httptest.ResponseRecorder, v any) { t.Helper() - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), v, jsonx.V1())) } // ---------------------------------------- @@ -99,7 +100,7 @@ func seedTemplate(t *testing.T, h *fis.Handler) string { // jsonUnmarshalFIS decodes JSON from a recorder into v. func jsonUnmarshalFIS(t *testing.T, data []byte, v any) { t.Helper() - require.NoError(t, json.Unmarshal(data, v)) + require.NoError(t, json.Unmarshal(data, v, jsonx.V1())) } func TestFISHandler_Name(t *testing.T) { diff --git a/services/fis/persistence.go b/services/fis/persistence.go index e1c9ebb6d9..18d79353b0 100644 --- a/services/fis/persistence.go +++ b/services/fis/persistence.go @@ -2,11 +2,13 @@ package fis import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -32,11 +34,11 @@ const fisSnapshotVersion = 1 // snapshot either, so idempotency tokens do not survive a snapshot/restore // cycle -- this preserves that pre-existing behaviour unchanged. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - SafetyLever *SafetyLever `json:"safetyLever"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + SafetyLever *SafetyLever `json:"safetyLever"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -59,7 +61,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "fis: Snapshot marshal failure", "error", err) diff --git a/services/fis/safety_levers_test.go b/services/fis/safety_levers_test.go index 52827f70c3..ae2e274286 100644 --- a/services/fis/safety_levers_test.go +++ b/services/fis/safety_levers_test.go @@ -2,7 +2,8 @@ package fis_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -74,13 +76,13 @@ func TestFISHandler_GetSafetyLever_NoTagsFieldOnWire(t *testing.T) { rec2 := doRequest(t, h, http.MethodGet, "/safetyLevers/000000000000", nil) require.Equal(t, http.StatusOK, rec2.Code) - var raw map[string]json.RawMessage + var raw map[string]jsontext.Value mustJSON(t, rec2, &raw) - var lever map[string]json.RawMessage + var lever map[string]jsontext.Value - require.NoError(t, json.Unmarshal(raw["safetyLever"], &lever)) + require.NoError(t, json.Unmarshal(raw["safetyLever"], &lever, jsonx.V1())) _, hasTags := lever["tags"] assert.False(t, hasTags, "GetSafetyLever response must not include a tags field") diff --git a/services/fis/target_resolution_test.go b/services/fis/target_resolution_test.go index 68bed50db0..4994964329 100644 --- a/services/fis/target_resolution_test.go +++ b/services/fis/target_resolution_test.go @@ -2,13 +2,14 @@ package fis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/fis" ) @@ -142,7 +143,7 @@ func TestStartExperiment_TargetResolution(t *testing.T) { Status string `json:"status"` Reason string `json:"reason"` } - require.NoError(t, json.Unmarshal(exp["status"], &status)) + require.NoError(t, json.Unmarshal(exp["status"], &status, jsonx.V1())) assert.Equal(t, tt.wantStatus, status.Status) assert.Equal(t, tt.wantReason, status.Reason) @@ -152,7 +153,7 @@ func TestStartExperiment_TargetResolution(t *testing.T) { Status string `json:"status"` } `json:"state"` } - require.NoError(t, json.Unmarshal(exp["actions"], &actions)) + require.NoError(t, json.Unmarshal(exp["actions"], &actions, jsonx.V1())) assert.Equal(t, tt.wantActions, actions["act"].State.Status) } diff --git a/services/fis/wire_field_test.go b/services/fis/wire_field_test.go index 85315a0c61..864e3933b1 100644 --- a/services/fis/wire_field_test.go +++ b/services/fis/wire_field_test.go @@ -1,7 +1,8 @@ package fis_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http/httptest" "testing" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/fis" @@ -229,11 +231,11 @@ func assertNoRawKey(t *testing.T, url, listKey, itemKey string) { t.Cleanup(func() { _ = resp.Body.Close() }) - var body map[string]json.RawMessage - require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) + var body map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1())) - var items []map[string]json.RawMessage - require.NoError(t, json.Unmarshal(body[listKey], &items)) + var items []map[string]jsontext.Value + require.NoError(t, json.Unmarshal(body[listKey], &items, jsonx.V1())) require.NotEmpty(t, items) for _, item := range items { diff --git a/services/forecast/handler.go b/services/forecast/handler.go index fdc672d6bc..9c6bf169fc 100644 --- a/services/forecast/handler.go +++ b/services/forecast/handler.go @@ -2,7 +2,7 @@ package forecast import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -126,7 +127,7 @@ func (h *Handler) Handler() echo.HandlerFunc { func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byte, error) { var input map[string]any - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } @@ -165,7 +166,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt return nil, err } - return json.Marshal(output) + return json.Marshal(output, jsonx.V1()) } func (h *Handler) execute(action string, spec operationSpec, input map[string]any) (map[string]any, error) { @@ -250,7 +251,7 @@ func (h *Handler) dispatchListMonitorEvaluations(input map[string]any) ([]byte, out["NextToken"] = pg.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } // filterMonitorEvaluations applies ListMonitorEvaluations's Filters @@ -321,7 +322,7 @@ func (h *Handler) dispatchDeleteResourceTree(input map[string]any) ([]byte, erro return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) dispatchResumeResource(input map[string]any) ([]byte, error) { @@ -330,7 +331,7 @@ func (h *Handler) dispatchResumeResource(input map[string]any) ([]byte, error) { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) dispatchStopResource(input map[string]any) ([]byte, error) { @@ -339,7 +340,7 @@ func (h *Handler) dispatchStopResource(input map[string]any) ([]byte, error) { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) dispatchGetAccuracyMetrics(input map[string]any) ([]byte, error) { @@ -348,7 +349,7 @@ func (h *Handler) dispatchGetAccuracyMetrics(input map[string]any) ([]byte, erro return nil, err } - return json.Marshal(metrics) + return json.Marshal(metrics, jsonx.V1()) } func (h *Handler) dispatchListTagsForResource(input map[string]any) ([]byte, error) { @@ -361,7 +362,7 @@ func (h *Handler) dispatchListTagsForResource(input map[string]any) ([]byte, err tagList = append(tagList, map[string]string{"Key": k, "Value": v}) } - return json.Marshal(map[string]any{"Tags": tagList}) + return json.Marshal(map[string]any{"Tags": tagList}, jsonx.V1()) } func (h *Handler) dispatchTagResource(input map[string]any) ([]byte, error) { @@ -370,7 +371,7 @@ func (h *Handler) dispatchTagResource(input map[string]any) ([]byte, error) { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) dispatchUntagResource(input map[string]any) ([]byte, error) { @@ -385,7 +386,7 @@ func (h *Handler) dispatchUntagResource(input map[string]any) ([]byte, error) { return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func resourceIdentifier(spec operationSpec, input map[string]any) string { @@ -600,7 +601,10 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err code, errType = http.StatusInternalServerError, "InternalServerException" } - payload, marshalErr := json.Marshal(map[string]string{"__type": errType, "message": publicMessage(err, errType)}) + payload, marshalErr := json.Marshal( + map[string]string{"__type": errType, "message": publicMessage(err, errType)}, + jsonx.V1(), + ) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } diff --git a/services/forecast/handler_sdk_route_table_test.go b/services/forecast/handler_sdk_route_table_test.go index c91589b8da..94ec160973 100644 --- a/services/forecast/handler_sdk_route_table_test.go +++ b/services/forecast/handler_sdk_route_table_test.go @@ -1,7 +1,7 @@ package forecast_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/forecast" ) @@ -167,7 +168,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var resp struct { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEqual(t, "InvalidInputException: "+tc.op, resp.Message, "target=%s op=%s: dispatched to the unmatched-route handler, body=%s", tc.target, tc.op, rec.Body.String()) diff --git a/services/forecast/handler_test.go b/services/forecast/handler_test.go index ecef421812..350a6cd5f7 100644 --- a/services/forecast/handler_test.go +++ b/services/forecast/handler_test.go @@ -2,7 +2,7 @@ package forecast_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/forecast" ) @@ -40,7 +41,7 @@ func request(t *testing.T, h *forecast.Handler, operation string, body map[strin func doRequest(t *testing.T, h *forecast.Handler, operation string, body map[string]any) *httptest.ResponseRecorder { t.Helper() - payload, err := json.Marshal(body) + payload, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -69,7 +70,7 @@ func unmarshalResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string] t.Helper() var response map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response, jsonx.V1())) return response } diff --git a/services/forecast/persistence.go b/services/forecast/persistence.go index ec45b7e8a9..7bac31da80 100644 --- a/services/forecast/persistence.go +++ b/services/forecast/persistence.go @@ -2,7 +2,7 @@ package forecast import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -41,7 +41,7 @@ const forecastSnapshotVersion = 1 // restored tables instead of trusting a persisted copy that could otherwise // drift out of sync with the tables. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Evaluations map[string][]MonitorEvaluation `json:"evaluations"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` diff --git a/services/forecast/store.go b/services/forecast/store.go index c59a6278c6..e59cea3732 100644 --- a/services/forecast/store.go +++ b/services/forecast/store.go @@ -1,7 +1,7 @@ package forecast import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "sort" @@ -9,6 +9,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -344,13 +345,13 @@ func cloneMap(data map[string]any) map[string]any { return make(map[string]any) } - encoded, err := json.Marshal(data) + encoded, err := json.Marshal(data, jsonx.V1()) if err != nil { return make(map[string]any) } var result map[string]any - if unmarshalErr := json.Unmarshal(encoded, &result); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(encoded, &result, jsonx.V1()); unmarshalErr != nil { return make(map[string]any) } diff --git a/services/fsx/client_request_token_test.go b/services/fsx/client_request_token_test.go index 7f8d4aa5ac..3f742a41da 100644 --- a/services/fsx/client_request_token_test.go +++ b/services/fsx/client_request_token_test.go @@ -1,7 +1,7 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -17,7 +18,7 @@ func responseID(t *testing.T, body []byte, outKey, idKey string) string { var out map[string]map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) id, ok := out[outKey][idKey].(string) require.True(t, ok, string(body)) diff --git a/services/fsx/data_repository_and_cache_config_test.go b/services/fsx/data_repository_and_cache_config_test.go index dc097dfdc4..8cd831c7a9 100644 --- a/services/fsx/data_repository_and_cache_config_test.go +++ b/services/fsx/data_repository_and_cache_config_test.go @@ -1,13 +1,15 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDataRepositoryAssociation_S3Configuration(t *testing.T) { @@ -90,7 +92,7 @@ func TestDataRepositoryAssociation_S3Configuration(t *testing.T) { } `json:"Associations"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Associations, 1) assert.Equal(t, tt.wantExport, out.Associations[0].S3.AutoExportPolicy.Events) assert.Equal(t, tt.wantImport, out.Associations[0].S3.AutoImportPolicy.Events) @@ -130,7 +132,7 @@ func TestDeleteDataRepositoryAssociation_DeleteDataInFileSystem(t *testing.T) { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "DELETING", out["Lifecycle"]) assert.Equal(t, tt.flag, out["DeleteDataInFileSystem"]) }) @@ -176,7 +178,7 @@ func TestCreateFileCache_AssociationsAndCopyTags(t *testing.T) { } `json:"FileCache"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) require.Len(t, created.FileCache.DRAIDs, 1) require.NotNil(t, created.FileCache.CopyTags) assert.Equal(t, tt.copyTags, *created.FileCache.CopyTags) @@ -200,7 +202,7 @@ func TestCreateFileCache_AssociationsAndCopyTags(t *testing.T) { } `json:"Associations"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &assoc)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &assoc, jsonx.V1())) require.Len(t, assoc.Associations, 1) a := assoc.Associations[0] diff --git a/services/fsx/file_cache_wire_test.go b/services/fsx/file_cache_wire_test.go index 9d2c1220e9..26c731e1d0 100644 --- a/services/fsx/file_cache_wire_test.go +++ b/services/fsx/file_cache_wire_test.go @@ -1,7 +1,7 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/fsx/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // testFileCacheLustreConfig builds a minimal valid CreateFileCache @@ -74,7 +76,7 @@ func TestFileCache_TagsWireShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) fcID := createOut["FileCache"].(map[string]any)["FileCacheId"].(string) describeRec := doFSxRequest(t, h, "DescribeFileCaches", map[string]any{ @@ -83,7 +85,7 @@ func TestFileCache_TagsWireShape(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut, jsonx.V1())) caches, ok := describeOut["FileCaches"].([]any) require.True(t, ok) @@ -113,7 +115,7 @@ func TestFileCache_TagsWireShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) fcID := createOut["FileCache"].(map[string]any)["FileCacheId"].(string) updateRec := doFSxRequest(t, h, "UpdateFileCache", map[string]any{ @@ -123,7 +125,7 @@ func TestFileCache_TagsWireShape(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) fc, ok := updateOut["FileCache"].(map[string]any) require.True(t, ok) diff --git a/services/fsx/file_system_type_configuration_test.go b/services/fsx/file_system_type_configuration_test.go index 394ee02d02..3377fb111b 100644 --- a/services/fsx/file_system_type_configuration_test.go +++ b/services/fsx/file_system_type_configuration_test.go @@ -1,12 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestFSx_FileSystem_WindowsConfiguration locks the wire shape of the @@ -31,7 +33,7 @@ func TestFSx_FileSystem_WindowsConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fs := out["FileSystem"].(map[string]any) require.Contains(t, fs, "WindowsConfiguration") @@ -62,7 +64,7 @@ func TestFSx_FileSystem_OntapConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fs := out["FileSystem"].(map[string]any) require.Contains(t, fs, "OntapConfiguration") @@ -96,7 +98,7 @@ func TestFSx_FileSystem_OpenZFSConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fs := out["FileSystem"].(map[string]any) require.Contains(t, fs, "OpenZFSConfiguration") @@ -114,7 +116,7 @@ func TestFSx_FileSystem_OpenZFSConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeOut, jsonx.V1())) volumes := describeOut["Volumes"].([]any) require.Len(t, volumes, 1) assert.Equal(t, "fsx", volumes[0].(map[string]any)["Name"]) @@ -150,7 +152,7 @@ func TestFSx_CreateFileSystem_MissingConfiguration(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "MissingFileSystemConfiguration", out["__type"]) }) } @@ -210,7 +212,7 @@ func TestFSx_CreateFileSystem_RequiredConfigMembers(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "BadRequest", out["__type"]) }) } @@ -235,7 +237,7 @@ func TestFSx_UpdateFileSystem_TypeSpecificConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fs := out["FileSystem"].(map[string]any) winCfg := fs["WindowsConfiguration"].(map[string]any) assert.InEpsilon(t, float64(32), winCfg["ThroughputCapacity"], 0) @@ -257,7 +259,7 @@ func TestFSx_CreateFileSystemFromBackup_CarriesTypeConfig(t *testing.T) { require.Equal(t, http.StatusOK, backupRec.Code) var backupOut map[string]any - require.NoError(t, json.Unmarshal(backupRec.Body.Bytes(), &backupOut)) + require.NoError(t, json.Unmarshal(backupRec.Body.Bytes(), &backupOut, jsonx.V1())) backupID := backupOut["Backup"].(map[string]any)["BackupId"].(string) restoreRec := doFSxRequest( @@ -269,7 +271,7 @@ func TestFSx_CreateFileSystemFromBackup_CarriesTypeConfig(t *testing.T) { require.Equal(t, http.StatusOK, restoreRec.Code) var restoreOut map[string]any - require.NoError(t, json.Unmarshal(restoreRec.Body.Bytes(), &restoreOut)) + require.NoError(t, json.Unmarshal(restoreRec.Body.Bytes(), &restoreOut, jsonx.V1())) restoredFS := restoreOut["FileSystem"].(map[string]any) require.Contains(t, restoredFS, "WindowsConfiguration") diff --git a/services/fsx/file_systems.go b/services/fsx/file_systems.go index b26db974dd..180699575a 100644 --- a/services/fsx/file_systems.go +++ b/services/fsx/file_systems.go @@ -1,7 +1,7 @@ package fsx import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "regexp" @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // storedFileSystem is the persisted form of a FileSystem. @@ -486,7 +487,7 @@ func fingerprintCreateFileSystemInput(input *createFileSystemInput) (string, err cp := *input cp.ClientRequestToken = "" - b, err := json.Marshal(cp) + b, err := json.Marshal(cp, jsonx.V1()) if err != nil { return "", fmt.Errorf("canonicalize CreateFileSystem request: %w", err) } diff --git a/services/fsx/handler.go b/services/fsx/handler.go index ba6804a5ec..c1ef5bbf11 100644 --- a/services/fsx/handler.go +++ b/services/fsx/handler.go @@ -2,7 +2,7 @@ package fsx import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -198,7 +199,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ResourceARN string `json:"ResourceARN"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ResourceARN != "": @@ -326,7 +327,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - out, err := json.Marshal(result) + out, err := json.Marshal(result, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/fsx/handler_backups_test.go b/services/fsx/handler_backups_test.go index 88fe101835..d32a710184 100644 --- a/services/fsx/handler_backups_test.go +++ b/services/fsx/handler_backups_test.go @@ -1,7 +1,7 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -22,7 +23,7 @@ func TestFSx_Backup(t *testing.T) { rec := doFSxRequest(t, h, "CreateBackup", map[string]any{"FileSystemId": fsID}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bk := resp["Backup"].(map[string]any) assert.Contains(t, bk["BackupId"].(string), "backup-") assert.Contains(t, bk["ResourceARN"].(string), "arn:aws:fsx:") @@ -46,7 +47,7 @@ func TestFSx_Backup(t *testing.T) { rec := doFSxRequest(t, h, "DescribeBackups", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bks := resp["Backups"].([]any) assert.Len(t, bks, 2) }) @@ -58,7 +59,7 @@ func TestFSx_Backup(t *testing.T) { rec := doFSxRequest(t, h, "DescribeBackups", map[string]any{"BackupIds": []string{bkID}}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bks := resp["Backups"].([]any) require.Len(t, bks, 1) assert.Equal(t, bkID, bks[0].(map[string]any)["BackupId"]) @@ -92,7 +93,7 @@ func TestFSx_Backup(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["FileSystem"].(map[string]any) assert.Contains(t, fs["FileSystemId"].(string), "fs-") assert.Equal(t, "AVAILABLE", fs["Lifecycle"]) @@ -141,7 +142,7 @@ func TestFSx_CreateFileSystemFromBackup_FileSystemTypeVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["FileSystem"].(map[string]any) got, _ := fs["FileSystemTypeVersion"].(string) @@ -184,7 +185,7 @@ func TestFSx_CopyBackup(t *testing.T) { if tc.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) bk := out["Backup"].(map[string]any) assert.Contains(t, bk["BackupId"].(string), "backup-") newID := bk["BackupId"].(string) @@ -219,7 +220,7 @@ func TestFSx_DeleteBackup_Response(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, bkID, resp["BackupId"]) assert.Equal(t, tc.wantLC, resp["Lifecycle"]) }) @@ -261,7 +262,7 @@ func TestFSx_BackupNotFound_ErrorCode(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) }) } diff --git a/services/fsx/handler_data_repository_associations_test.go b/services/fsx/handler_data_repository_associations_test.go index 4a5e343788..73cebdef89 100644 --- a/services/fsx/handler_data_repository_associations_test.go +++ b/services/fsx/handler_data_repository_associations_test.go @@ -1,13 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -42,7 +43,7 @@ func TestFSx_DataRepositoryAssociation(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) a := out["Association"].(map[string]any) assert.Contains(t, a["AssociationId"].(string), "dra-") assert.Equal(t, tc.fsPath, a["FileSystemPath"]) @@ -67,7 +68,7 @@ func TestFSx_DataRepositoryAssociationLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) id := cr["Association"].(map[string]any)["AssociationId"].(string) assert.Equal(t, 1, fsx.DRACount(b)) @@ -79,7 +80,7 @@ func TestFSx_DataRepositoryAssociationLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur, jsonx.V1())) assert.Equal(t, "s3://bucket/new", ur["Association"].(map[string]any)["DataRepositoryPath"]) // describe @@ -88,7 +89,7 @@ func TestFSx_DataRepositoryAssociationLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec3.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["Associations"].([]any), 1) // delete diff --git a/services/fsx/handler_data_repository_tasks_test.go b/services/fsx/handler_data_repository_tasks_test.go index af58826f38..65004c612c 100644 --- a/services/fsx/handler_data_repository_tasks_test.go +++ b/services/fsx/handler_data_repository_tasks_test.go @@ -1,13 +1,15 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestFSx_DataRepositoryTask(t *testing.T) { @@ -45,7 +47,7 @@ func TestFSx_DataRepositoryTask(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) task := out["DataRepositoryTask"].(map[string]any) assert.Contains(t, task["TaskId"].(string), "task-") assert.Equal(t, "EXECUTING", task["Lifecycle"]) @@ -105,7 +107,7 @@ func TestFSx_DataRepositoryTaskLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) taskID := cr["DataRepositoryTask"].(map[string]any)["TaskId"].(string) // describe @@ -114,14 +116,14 @@ func TestFSx_DataRepositoryTaskLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["DataRepositoryTasks"].([]any), 1) // cancel rec3 := doFSxRequest(t, h, "CancelDataRepositoryTask", map[string]any{"TaskId": taskID}) require.Equal(t, http.StatusOK, rec3.Code) var car map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &car)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &car, jsonx.V1())) assert.Equal(t, "CANCELING", car["Lifecycle"]) }) } @@ -158,7 +160,7 @@ func TestFSx_CreateDataRepositoryTask_RejectsConcurrentExecuting(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "DataRepositoryTaskExecuting", out["__type"]) }) @@ -183,7 +185,7 @@ func TestFSx_CreateDataRepositoryTask_RejectsConcurrentExecuting(t *testing.T) { rec1 := doFSxRequest(t, h, "CreateDataRepositoryTask", newTaskBody(fsID)) require.Equal(t, http.StatusOK, rec1.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &cr, jsonx.V1())) taskID := cr["DataRepositoryTask"].(map[string]any)["TaskId"].(string) cancelRec := doFSxRequest(t, h, "CancelDataRepositoryTask", map[string]any{"TaskId": taskID}) @@ -242,7 +244,7 @@ func TestDataRepositoryTask_TagsStoredAtCreation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) task := out["DataRepositoryTask"].(map[string]any) taskARN := task["ResourceARN"].(string) @@ -253,7 +255,7 @@ func TestDataRepositoryTask_TagsStoredAtCreation(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, "ListTagsForResource on DRT must succeed") var tagOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagOut, jsonx.V1())) tags, ok := tagOut["Tags"].([]any) require.True(t, ok, "Tags must be a JSON array") @@ -279,7 +281,7 @@ func TestDataRepositoryTask_TagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) taskARN := out["DataRepositoryTask"].(map[string]any)["ResourceARN"].(string) // TagResource on a DRT ARN must succeed. @@ -294,7 +296,7 @@ func TestDataRepositoryTask_TagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var tagOut map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagOut)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagOut, jsonx.V1())) tags := tagOut["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "added", tags[0].(map[string]any)["Key"]) diff --git a/services/fsx/handler_file_caches_test.go b/services/fsx/handler_file_caches_test.go index 2bfb7686ba..efe22302fd 100644 --- a/services/fsx/handler_file_caches_test.go +++ b/services/fsx/handler_file_caches_test.go @@ -1,13 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -83,7 +84,7 @@ func TestFSx_CreateFileCache_RequiresLustreConfiguration(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tc.wantType, out["__type"]) }) } @@ -104,7 +105,7 @@ func TestFSx_CreateFileCache_RequiresLustreConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fc := out["FileCache"].(map[string]any) lc, ok := fc["LustreConfiguration"].(map[string]any) require.True(t, ok, "response must have a LustreConfiguration block") @@ -188,7 +189,7 @@ func TestFSx_FileCache(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) c := out["FileCache"].(map[string]any) assert.Contains(t, c["FileCacheId"].(string), "fc-") assert.Equal(t, "AVAILABLE", c["Lifecycle"]) @@ -218,7 +219,7 @@ func TestFSx_FileCacheLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["FileCaches"].([]any), 1) // update @@ -234,7 +235,7 @@ func TestFSx_FileCacheLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur, jsonx.V1())) lc := ur["FileCache"].(map[string]any)["LustreConfiguration"].(map[string]any) assert.Equal(t, "3:04:05", lc["WeeklyMaintenanceStartTime"]) @@ -242,7 +243,7 @@ func TestFSx_FileCacheLifecycle(t *testing.T) { rec3 := doFSxRequest(t, h, "DeleteFileCache", map[string]any{"FileCacheId": fcID}) require.Equal(t, http.StatusOK, rec3.Code) var del map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del, jsonx.V1())) assert.Equal(t, fcID, del["FileCacheId"]) assert.Equal(t, "DELETING", del["Lifecycle"]) assert.Equal(t, 0, fsx.FileCacheCount(b)) diff --git a/services/fsx/handler_file_systems_test.go b/services/fsx/handler_file_systems_test.go index d2d3cbc2dd..2581fd80bb 100644 --- a/services/fsx/handler_file_systems_test.go +++ b/services/fsx/handler_file_systems_test.go @@ -1,13 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -29,7 +30,7 @@ func TestFSx_FileSystem(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["FileSystem"].(map[string]any) assert.Contains(t, fs["FileSystemId"].(string), "fs-") assert.Contains(t, fs["ResourceARN"].(string), "arn:aws:fsx:") @@ -52,7 +53,7 @@ func TestFSx_FileSystem(t *testing.T) { rec := doFSxRequest(t, h, "DescribeFileSystems", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fss := resp["FileSystems"].([]any) assert.Len(t, fss, 2) }) @@ -65,7 +66,7 @@ func TestFSx_FileSystem(t *testing.T) { rec := doFSxRequest(t, h, "DescribeFileSystems", map[string]any{"FileSystemIds": []string{id}}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fss := resp["FileSystems"].([]any) require.Len(t, fss, 1) assert.Equal(t, id, fss[0].(map[string]any)["FileSystemId"]) @@ -101,7 +102,7 @@ func TestFSx_FileSystem(t *testing.T) { rec := doFSxRequest(t, h, "UpdateFileSystem", map[string]any{"FileSystemId": id, "StorageCapacity": 64}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["FileSystem"].(map[string]any) assert.Equal(t, id, fs["FileSystemId"]) }) @@ -131,13 +132,13 @@ func TestFSx_FileSystem(t *testing.T) { rec1 := doFSxRequest(t, h, "CreateFileSystem", body) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) fs1 := resp1["FileSystem"].(map[string]any) rec2 := doFSxRequest(t, h, "CreateFileSystem", body) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) fs2 := resp2["FileSystem"].(map[string]any) // Prove it's the SAME resource, not just a second success: identical @@ -169,7 +170,7 @@ func TestFSx_FileSystem(t *testing.T) { }) require.Equal(t, http.StatusBadRequest, rec2.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "IncompatibleParameterError", errResp["__type"]) assert.Equal(t, 1, fsx.FileSystemCount(fsx.GetBackend(h)), "mismatched retry must not create a resource") }) @@ -189,8 +190,8 @@ func TestFSx_FileSystem(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp1, resp2 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.NotEqual( t, resp1["FileSystem"].(map[string]any)["FileSystemId"], @@ -213,7 +214,7 @@ func TestFSx_FileSystem(t *testing.T) { }) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidNetworkSettings", errResp["__type"]) }) @@ -228,7 +229,7 @@ func TestFSx_FileSystem(t *testing.T) { }) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidNetworkSettings", errResp["__type"]) }) @@ -404,7 +405,7 @@ func TestFSx_DeleteFileSystem_Response(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantID { assert.Equal(t, id, resp["FileSystemId"]) @@ -458,7 +459,7 @@ func TestFSx_Aliases(t *testing.T) { require.Equal(t, tc.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) aliases := out["Aliases"].([]any) assert.Len(t, aliases, tc.wantCount) assert.Equal(t, tc.lifecycle, aliases[0].(map[string]any)["Lifecycle"]) @@ -482,7 +483,7 @@ func TestFSx_AliasesLifecycle(t *testing.T) { rec := doFSxRequest(t, h, "DescribeFileSystemAliases", map[string]any{"FileSystemId": fsID}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Aliases"].([]any), 1) }) @@ -502,14 +503,14 @@ func TestFSx_AliasesLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) aliases := out["Aliases"].([]any) assert.Len(t, aliases, 1) assert.Equal(t, "DELETING", aliases[0].(map[string]any)["Lifecycle"]) rec2 := doFSxRequest(t, h, "DescribeFileSystemAliases", map[string]any{"FileSystemId": fsID}) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Empty(t, out2["Aliases"].([]any)) }) } @@ -558,7 +559,7 @@ func TestFSx_ReleaseFileSystemNfsV3Locks(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["FileSystem"]) } }) @@ -605,7 +606,7 @@ func TestFSx_StartMisconfiguredStateRecovery(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["FileSystem"]) } }) diff --git a/services/fsx/handler_s3_access_points_test.go b/services/fsx/handler_s3_access_points_test.go index 201c703aa6..1f9f7f3965 100644 --- a/services/fsx/handler_s3_access_points_test.go +++ b/services/fsx/handler_s3_access_points_test.go @@ -1,12 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestFSx_S3AccessPoint(t *testing.T) { @@ -59,7 +61,7 @@ func TestFSx_S3AccessPoint(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ap := out["S3AccessPointAttachment"].(map[string]any) assert.Equal(t, tc.apName, ap["Name"]) assert.Equal(t, "AVAILABLE", ap["Lifecycle"]) @@ -93,7 +95,7 @@ func TestFSx_S3AccessPointLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["S3AccessPointAttachments"].([]any), 1) // detach: real DetachAndDeleteS3AccessPointInput has no FileSystemId member. @@ -106,7 +108,7 @@ func TestFSx_S3AccessPointLifecycle(t *testing.T) { rec3 := doFSxRequest(t, h, "DescribeS3AccessPointAttachments", map[string]any{}) require.Equal(t, http.StatusOK, rec3.Code) var dr2 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &dr2)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &dr2, jsonx.V1())) assert.Empty(t, dr2["S3AccessPointAttachments"].([]any)) }) } diff --git a/services/fsx/handler_shared_vpc_configuration_test.go b/services/fsx/handler_shared_vpc_configuration_test.go index eb98d13165..466437fae0 100644 --- a/services/fsx/handler_shared_vpc_configuration_test.go +++ b/services/fsx/handler_shared_vpc_configuration_test.go @@ -1,12 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestFSx_SharedVpcConfiguration(t *testing.T) { @@ -47,7 +49,7 @@ func TestFSx_SharedVpcConfiguration(t *testing.T) { rec := doFSxRequest(t, h, "DescribeSharedVpcConfiguration", map[string]any{}) require.Equal(t, tc.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tc.wantEnabled, out["EnableFsxRouteTableUpdatesFromParticipantAccounts"]) }) } diff --git a/services/fsx/handler_snapshots_test.go b/services/fsx/handler_snapshots_test.go index edabddc164..bad63fb805 100644 --- a/services/fsx/handler_snapshots_test.go +++ b/services/fsx/handler_snapshots_test.go @@ -1,13 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -49,7 +50,7 @@ func TestFSx_Snapshot(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) s := out["Snapshot"].(map[string]any) assert.Contains(t, s["SnapshotId"].(string), "fsvolsnap-") assert.Equal(t, "AVAILABLE", s["Lifecycle"]) @@ -75,7 +76,7 @@ func TestFSx_SnapshotLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) snapID := cr["Snapshot"].(map[string]any)["SnapshotId"].(string) assert.Equal(t, 1, fsx.SnapshotCount(b)) @@ -86,7 +87,7 @@ func TestFSx_SnapshotLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["Snapshots"].([]any), 1) // update @@ -96,14 +97,14 @@ func TestFSx_SnapshotLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec3.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &ur, jsonx.V1())) assert.Equal(t, "snap-renamed", ur["Snapshot"].(map[string]any)["Name"]) // delete rec4 := doFSxRequest(t, h, "DeleteSnapshot", map[string]any{"SnapshotId": snapID}) require.Equal(t, http.StatusOK, rec4.Code) var del map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &del)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &del, jsonx.V1())) assert.Equal(t, snapID, del["SnapshotId"]) assert.Equal(t, "DELETING", del["Lifecycle"]) assert.Equal(t, 0, fsx.SnapshotCount(b)) @@ -125,7 +126,7 @@ func TestFSx_CopySnapshotAndUpdateVolume(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) snapARN := cr["Snapshot"].(map[string]any)["ResourceARN"].(string) rec2 := doFSxRequest(t, h, "CopySnapshotAndUpdateVolume", map[string]any{ @@ -134,7 +135,7 @@ func TestFSx_CopySnapshotAndUpdateVolume(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, volID, out["VolumeId"]) assert.NotEmpty(t, out["Lifecycle"]) actions := out["AdministrativeActions"].([]any) diff --git a/services/fsx/handler_storage_virtual_machines_test.go b/services/fsx/handler_storage_virtual_machines_test.go index 148b0cb082..9b451f122c 100644 --- a/services/fsx/handler_storage_virtual_machines_test.go +++ b/services/fsx/handler_storage_virtual_machines_test.go @@ -1,13 +1,14 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -50,7 +51,7 @@ func TestFSx_StorageVirtualMachine(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svm := out["StorageVirtualMachine"].(map[string]any) assert.Contains(t, svm["StorageVirtualMachineId"].(string), "svm-") assert.Equal(t, "CREATED", svm["Lifecycle"]) @@ -78,7 +79,7 @@ func TestFSx_SVMLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["StorageVirtualMachines"].([]any), 1) // update: SvmAdminPassword is the real op's only scalar updatable @@ -90,7 +91,7 @@ func TestFSx_SVMLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur, jsonx.V1())) assert.Equal(t, svmID, ur["StorageVirtualMachine"].(map[string]any)["StorageVirtualMachineId"]) // delete @@ -99,7 +100,7 @@ func TestFSx_SVMLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec3.Code) var del map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del, jsonx.V1())) assert.Equal(t, svmID, del["StorageVirtualMachineId"]) assert.Equal(t, "DELETING", del["Lifecycle"]) assert.Equal(t, 0, fsx.SVMCount(b)) diff --git a/services/fsx/handler_tags_test.go b/services/fsx/handler_tags_test.go index 4ed4d665ec..bec07c5fb2 100644 --- a/services/fsx/handler_tags_test.go +++ b/services/fsx/handler_tags_test.go @@ -1,7 +1,8 @@ package fsx_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -25,7 +27,7 @@ func TestFSx_Tags(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["FileSystem"].(map[string]any)["ResourceARN"].(string) } @@ -52,7 +54,7 @@ func TestFSx_Tags(t *testing.T) { rec := doFSxRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].([]any) assert.Len(t, tags, 1) tag := tags[0].(map[string]any) @@ -72,7 +74,7 @@ func TestFSx_Tags(t *testing.T) { rec := doFSxRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].([]any) assert.Len(t, tags, 1) assert.Equal(t, "Name", tags[0].(map[string]any)["Key"]) @@ -148,7 +150,7 @@ func TestFSx_TagValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arn := out["FileSystem"].(map[string]any)["ResourceARN"].(string) @@ -160,7 +162,7 @@ func TestFSx_TagValidation(t *testing.T) { if tc.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) } }) @@ -204,7 +206,7 @@ func TestFSx_TagValidation_OnCreate(t *testing.T) { if tc.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) } }) @@ -227,7 +229,7 @@ func TestFSx_TagLimit(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arn := out["FileSystem"].(map[string]any)["ResourceARN"].(string) @@ -248,7 +250,7 @@ func TestFSx_TagLimit(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // TagResource's own switch (fsx@v1.68.4 deserializers.go // deserializeOpErrorTagResource) does not declare // ServiceLimitExceeded; BadRequest is the correct wire type @@ -269,7 +271,7 @@ func TestFSx_TagLimit(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arn := out["FileSystem"].(map[string]any)["ResourceARN"].(string) @@ -312,7 +314,7 @@ func TestListTagsForResource_EmptyIsArray(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["FileSystem"].(map[string]any)["ResourceARN"].(string) }, @@ -324,7 +326,7 @@ func TestListTagsForResource_EmptyIsArray(t *testing.T) { rec := doFSxRequest(t, h, "CreateBackup", map[string]any{"FileSystemId": fsID}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["Backup"].(map[string]any)["ResourceARN"].(string) }, @@ -342,8 +344,8 @@ func TestListTagsForResource_EmptyIsArray(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) // Parse the raw JSON to verify "Tags" is an array, not null. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) tagsRaw, ok := raw["Tags"] require.True(t, ok, "Tags key must be present") @@ -398,7 +400,7 @@ func Test_TagOps_UnknownARN_ReturnsResourceNotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ResourceNotFound", errBody["__type"], "%s on an unknown ARN must return the generic ResourceNotFound code", tt.op) }) diff --git a/services/fsx/handler_test.go b/services/fsx/handler_test.go index 1147cc1db1..4e83ca551a 100644 --- a/services/fsx/handler_test.go +++ b/services/fsx/handler_test.go @@ -2,7 +2,7 @@ package fsx_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -33,7 +34,7 @@ func doFSxRequest(t *testing.T, h *fsx.Handler, op string, body any) *httptest.R if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -76,7 +77,7 @@ func createFS(t *testing.T, h *fsx.Handler, fsType string) string { rec := doFSxRequest(t, h, "CreateFileSystem", fileSystemCreateBody(fsType)) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["FileSystem"].(map[string]any)["FileSystemId"].(string) } @@ -87,7 +88,7 @@ func createFSandBackup(t *testing.T, h *fsx.Handler, fsType string) string { rec := doFSxRequest(t, h, "CreateBackup", map[string]any{"FileSystemId": fsID}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["Backup"].(map[string]any)["BackupId"].(string) } @@ -123,7 +124,7 @@ func createVolume(t *testing.T, h *fsx.Handler, fsID, volType, name string) stri rec := doFSxRequest(t, h, "CreateVolume", body) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["Volume"].(map[string]any)["VolumeId"].(string) } @@ -136,7 +137,7 @@ func openZFSRootVolumeID(t *testing.T, h *fsx.Handler, fsID string) string { rec := doFSxRequest(t, h, "DescribeFileSystems", map[string]any{"FileSystemIds": []string{fsID}}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fileSystems, ok := out["FileSystems"].([]any) require.True(t, ok) require.Len(t, fileSystems, 1) @@ -156,7 +157,7 @@ func createSVM(t *testing.T, h *fsx.Handler, fsID, name string) string { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["StorageVirtualMachine"].(map[string]any)["StorageVirtualMachineId"].(string) } @@ -172,7 +173,7 @@ func createFileCache(t *testing.T, h *fsx.Handler, cacheType string) string { // }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["FileCache"].(map[string]any)["FileCacheId"].(string) } @@ -196,7 +197,7 @@ func decodeField(t *testing.T, rec *httptest.ResponseRecorder, field string) map require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) obj, ok := out[field].(map[string]any) require.True(t, ok, "response must contain object field %q, got %v", field, out) diff --git a/services/fsx/handler_volumes_test.go b/services/fsx/handler_volumes_test.go index 3d2cc3ff14..1fc4af2f55 100644 --- a/services/fsx/handler_volumes_test.go +++ b/services/fsx/handler_volumes_test.go @@ -1,7 +1,7 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -74,7 +75,7 @@ func TestFSx_Volume(t *testing.T) { if !tc.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) v := out["Volume"].(map[string]any) assert.Contains(t, v["VolumeId"].(string), "fsvol-") assert.Equal(t, "AVAILABLE", v["Lifecycle"]) @@ -102,7 +103,7 @@ func TestFSx_VolumeLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var dr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dr, jsonx.V1())) assert.Len(t, dr["Volumes"].([]any), 1) // update @@ -112,14 +113,14 @@ func TestFSx_VolumeLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &ur, jsonx.V1())) assert.Equal(t, "vol-renamed", ur["Volume"].(map[string]any)["Name"]) // delete rec3 := doFSxRequest(t, h, "DeleteVolume", map[string]any{"VolumeId": volID}) require.Equal(t, http.StatusOK, rec3.Code) var del map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &del, jsonx.V1())) assert.Equal(t, volID, del["VolumeId"]) assert.Equal(t, "DELETING", del["Lifecycle"]) assert.Equal(t, 0, fsx.VolumeCount(b)) @@ -142,7 +143,7 @@ func TestFSx_CreateVolumeFromBackup(t *testing.T) { }) require.Equal(t, http.StatusOK, svmRec.Code) var svmOut map[string]any - require.NoError(t, json.Unmarshal(svmRec.Body.Bytes(), &svmOut)) + require.NoError(t, json.Unmarshal(svmRec.Body.Bytes(), &svmOut, jsonx.V1())) svmID := svmOut["StorageVirtualMachine"].(map[string]any)["StorageVirtualMachineId"].(string) rec := doFSxRequest(t, h, "CreateVolumeFromBackup", map[string]any{ @@ -155,7 +156,7 @@ func TestFSx_CreateVolumeFromBackup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) v := out["Volume"].(map[string]any) assert.Contains(t, v["VolumeId"].(string), "fsvol-") assert.Equal(t, "restored-vol", v["Name"]) @@ -176,7 +177,7 @@ func TestFSx_CreateVolumeFromBackup(t *testing.T) { }) require.Equal(t, http.StatusOK, svmRec.Code) var svmOut map[string]any - require.NoError(t, json.Unmarshal(svmRec.Body.Bytes(), &svmOut)) + require.NoError(t, json.Unmarshal(svmRec.Body.Bytes(), &svmOut, jsonx.V1())) svmID := svmOut["StorageVirtualMachine"].(map[string]any)["StorageVirtualMachineId"].(string) rec := doFSxRequest(t, h, "CreateVolumeFromBackup", map[string]any{ @@ -219,7 +220,7 @@ func TestFSx_RestoreVolumeFromSnapshot(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) snapID := cr["Snapshot"].(map[string]any)["SnapshotId"].(string) // restore @@ -229,7 +230,7 @@ func TestFSx_RestoreVolumeFromSnapshot(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, volID, out["VolumeId"]) assert.NotEmpty(t, out["Lifecycle"]) actions := out["AdministrativeActions"].([]any) diff --git a/services/fsx/idempotency.go b/services/fsx/idempotency.go index 624a8e1e28..4a5374c793 100644 --- a/services/fsx/idempotency.go +++ b/services/fsx/idempotency.go @@ -1,9 +1,11 @@ package fsx import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const clientRequestTokenField = "ClientRequestToken" @@ -11,19 +13,19 @@ const clientRequestTokenField = "ClientRequestToken" // tokenFingerprint canonicalises input minus its ClientRequestToken so a retry // with the same parameters hashes equal and a changed one does not. func tokenFingerprint(input any) (string, error) { - raw, err := json.Marshal(input) + raw, err := json.Marshal(input, jsonx.V1()) if err != nil { return "", fmt.Errorf("canonicalize request: %w", err) } var fields map[string]any - if err = json.Unmarshal(raw, &fields); err != nil { + if err = json.Unmarshal(raw, &fields, jsonx.V1()); err != nil { return "", fmt.Errorf("canonicalize request: %w", err) } delete(fields, clientRequestTokenField) - out, err := json.Marshal(fields) + out, err := json.Marshal(fields, jsonx.V1()) if err != nil { return "", fmt.Errorf("canonicalize request: %w", err) } diff --git a/services/fsx/interfaces.go b/services/fsx/interfaces.go index 9471a45ac5..b78437d688 100644 --- a/services/fsx/interfaces.go +++ b/services/fsx/interfaces.go @@ -2,7 +2,7 @@ package fsx import ( "context" - "encoding/json" + "encoding/json/jsontext" "strconv" "time" ) @@ -230,10 +230,10 @@ type LustreConfiguration struct { DriveCacheType string `json:"DriveCacheType,omitempty"` MountName string `json:"MountName,omitempty"` WeeklyMaintenanceStartTime string `json:"WeeklyMaintenanceStartTime,omitempty"` - RootSquashConfiguration json.RawMessage `json:"RootSquashConfiguration,omitempty"` - DataReadCacheConfiguration json.RawMessage `json:"DataReadCacheConfiguration,omitempty"` - MetadataConfiguration json.RawMessage `json:"MetadataConfiguration,omitempty"` - LogConfiguration json.RawMessage `json:"LogConfiguration,omitempty"` + RootSquashConfiguration jsontext.Value `json:"RootSquashConfiguration,omitempty"` + DataReadCacheConfiguration jsontext.Value `json:"DataReadCacheConfiguration,omitempty"` + MetadataConfiguration jsontext.Value `json:"MetadataConfiguration,omitempty"` + LogConfiguration jsontext.Value `json:"LogConfiguration,omitempty"` AutomaticBackupRetentionDays int32 `json:"AutomaticBackupRetentionDays,omitempty"` ThroughputCapacity int32 `json:"ThroughputCapacity,omitempty"` PerUnitStorageThroughput int32 `json:"PerUnitStorageThroughput,omitempty"` diff --git a/services/fsx/lustre_config.go b/services/fsx/lustre_config.go index 12996df350..6b0380e39e 100644 --- a/services/fsx/lustre_config.go +++ b/services/fsx/lustre_config.go @@ -1,10 +1,13 @@ package fsx import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -25,41 +28,41 @@ var weeklyMaintenancePattern = regexp.MustCompile(`^[1-7]:([01]\d|2[0-3]):?([0-5 // createLustreConfiguration mirrors CreateFileSystemLustreConfiguration. type createLustreConfiguration struct { - DriveCacheType string `json:"DriveCacheType,omitempty"` - ImportPath string `json:"ImportPath,omitempty"` - WeeklyMaintenanceStartTime string `json:"WeeklyMaintenanceStartTime,omitempty"` - ExportPath string `json:"ExportPath,omitempty"` - DeploymentType string `json:"DeploymentType,omitempty"` - AutoImportPolicy string `json:"AutoImportPolicy,omitempty"` - DailyAutomaticBackupStartTime string `json:"DailyAutomaticBackupStartTime,omitempty"` - DataCompressionType string `json:"DataCompressionType,omitempty"` - DataReadCacheConfiguration json.RawMessage `json:"DataReadCacheConfiguration,omitempty"` - RootSquashConfiguration json.RawMessage `json:"RootSquashConfiguration,omitempty"` - LogConfiguration json.RawMessage `json:"LogConfiguration,omitempty"` - MetadataConfiguration json.RawMessage `json:"MetadataConfiguration,omitempty"` - AutomaticBackupRetentionDays int32 `json:"AutomaticBackupRetentionDays,omitempty"` - ImportedFileChunkSize int32 `json:"ImportedFileChunkSize,omitempty"` - PerUnitStorageThroughput int32 `json:"PerUnitStorageThroughput,omitempty"` - ThroughputCapacity int32 `json:"ThroughputCapacity,omitempty"` - CopyTagsToBackups bool `json:"CopyTagsToBackups,omitempty"` - EfaEnabled bool `json:"EfaEnabled,omitempty"` + DriveCacheType string `json:"DriveCacheType,omitempty"` + ImportPath string `json:"ImportPath,omitempty"` + WeeklyMaintenanceStartTime string `json:"WeeklyMaintenanceStartTime,omitempty"` + ExportPath string `json:"ExportPath,omitempty"` + DeploymentType string `json:"DeploymentType,omitempty"` + AutoImportPolicy string `json:"AutoImportPolicy,omitempty"` + DailyAutomaticBackupStartTime string `json:"DailyAutomaticBackupStartTime,omitempty"` + DataCompressionType string `json:"DataCompressionType,omitempty"` + DataReadCacheConfiguration jsontext.Value `json:"DataReadCacheConfiguration,omitempty"` + RootSquashConfiguration jsontext.Value `json:"RootSquashConfiguration,omitempty"` + LogConfiguration jsontext.Value `json:"LogConfiguration,omitempty"` + MetadataConfiguration jsontext.Value `json:"MetadataConfiguration,omitempty"` + AutomaticBackupRetentionDays int32 `json:"AutomaticBackupRetentionDays,omitempty"` + ImportedFileChunkSize int32 `json:"ImportedFileChunkSize,omitempty"` + PerUnitStorageThroughput int32 `json:"PerUnitStorageThroughput,omitempty"` + ThroughputCapacity int32 `json:"ThroughputCapacity,omitempty"` + CopyTagsToBackups bool `json:"CopyTagsToBackups,omitempty"` + EfaEnabled bool `json:"EfaEnabled,omitempty"` } // storedLustreExtras keeps the Lustre members that have no counterpart on the shared // storedFileSystem fields. type storedLustreExtras struct { - AutoImportPolicy string `json:"autoImportPolicy,omitempty"` - DataCompressionType string `json:"dataCompression,omitempty"` - DriveCacheType string `json:"driveCache,omitempty"` - ExportPath string `json:"exportPath,omitempty"` - ImportPath string `json:"importPath,omitempty"` - RootSquashConfiguration json.RawMessage `json:"rootSquash,omitempty"` - DataReadCacheConfiguration json.RawMessage `json:"dataReadCache,omitempty"` - MetadataConfiguration json.RawMessage `json:"metadata,omitempty"` - LogConfiguration json.RawMessage `json:"log,omitempty"` - ImportedFileChunkSize int32 `json:"importedChunk,omitempty"` - PerUnitStorageThroughput int32 `json:"perUnitThroughput,omitempty"` - EfaEnabled bool `json:"efa,omitempty"` + AutoImportPolicy string `json:"autoImportPolicy,omitempty"` + DataCompressionType string `json:"dataCompression,omitempty"` + DriveCacheType string `json:"driveCache,omitempty"` + ExportPath string `json:"exportPath,omitempty"` + ImportPath string `json:"importPath,omitempty"` + RootSquashConfiguration jsontext.Value `json:"rootSquash,omitempty"` + DataReadCacheConfiguration jsontext.Value `json:"dataReadCache,omitempty"` + MetadataConfiguration jsontext.Value `json:"metadata,omitempty"` + LogConfiguration jsontext.Value `json:"log,omitempty"` + ImportedFileChunkSize int32 `json:"importedChunk,omitempty"` + PerUnitStorageThroughput int32 `json:"perUnitThroughput,omitempty"` + EfaEnabled bool `json:"efa,omitempty"` } func validLustreThroughputs(deployment, storageType string) []int32 { @@ -230,12 +233,12 @@ func applyLustreConfig(fs *storedFileSystem, cfg *createLustreConfiguration) err } // metadataMode extracts MetadataConfiguration.Mode for defaultLustreVersion. -func metadataMode(raw json.RawMessage) string { +func metadataMode(raw jsontext.Value) string { var m struct { Mode string `json:"Mode"` } - if len(raw) == 0 || json.Unmarshal(raw, &m) != nil { + if len(raw) == 0 || json.Unmarshal(raw, &m, jsonx.V1()) != nil { return "" } @@ -244,17 +247,17 @@ func metadataMode(raw json.RawMessage) string { // updateLustreConfiguration mirrors UpdateFileSystemLustreConfiguration. type updateLustreConfiguration struct { - AutoImportPolicy string `json:"AutoImportPolicy,omitempty"` - DailyAutomaticBackupStartTime string `json:"DailyAutomaticBackupStartTime,omitempty"` - DataCompressionType string `json:"DataCompressionType,omitempty"` - WeeklyMaintenanceStartTime string `json:"WeeklyMaintenanceStartTime,omitempty"` - RootSquashConfiguration json.RawMessage `json:"RootSquashConfiguration,omitempty"` - DataReadCacheConfiguration json.RawMessage `json:"DataReadCacheConfiguration,omitempty"` - MetadataConfiguration json.RawMessage `json:"MetadataConfiguration,omitempty"` - LogConfiguration json.RawMessage `json:"LogConfiguration,omitempty"` - AutomaticBackupRetentionDays int32 `json:"AutomaticBackupRetentionDays,omitempty"` - PerUnitStorageThroughput int32 `json:"PerUnitStorageThroughput,omitempty"` - ThroughputCapacity int32 `json:"ThroughputCapacity,omitempty"` + AutoImportPolicy string `json:"AutoImportPolicy,omitempty"` + DailyAutomaticBackupStartTime string `json:"DailyAutomaticBackupStartTime,omitempty"` + DataCompressionType string `json:"DataCompressionType,omitempty"` + WeeklyMaintenanceStartTime string `json:"WeeklyMaintenanceStartTime,omitempty"` + RootSquashConfiguration jsontext.Value `json:"RootSquashConfiguration,omitempty"` + DataReadCacheConfiguration jsontext.Value `json:"DataReadCacheConfiguration,omitempty"` + MetadataConfiguration jsontext.Value `json:"MetadataConfiguration,omitempty"` + LogConfiguration jsontext.Value `json:"LogConfiguration,omitempty"` + AutomaticBackupRetentionDays int32 `json:"AutomaticBackupRetentionDays,omitempty"` + PerUnitStorageThroughput int32 `json:"PerUnitStorageThroughput,omitempty"` + ThroughputCapacity int32 `json:"ThroughputCapacity,omitempty"` } func applyLustreUpdate(fs *storedFileSystem, cfg *updateLustreConfiguration) error { @@ -321,7 +324,7 @@ func setIf(dst *string, v string) { } } -func setRaw(dst *json.RawMessage, v json.RawMessage) { +func setRaw(dst *jsontext.Value, v jsontext.Value) { if len(v) > 0 { *dst = v } diff --git a/services/fsx/multi_region_test.go b/services/fsx/multi_region_test.go index 56fcdbcae1..14cd76ff19 100644 --- a/services/fsx/multi_region_test.go +++ b/services/fsx/multi_region_test.go @@ -2,7 +2,7 @@ package fsx_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/fsx/openzfs_volume_config_test.go b/services/fsx/openzfs_volume_config_test.go index a54ba9047b..cc246b9227 100644 --- a/services/fsx/openzfs_volume_config_test.go +++ b/services/fsx/openzfs_volume_config_test.go @@ -1,7 +1,7 @@ package fsx_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -70,7 +71,7 @@ func (f zfsFixture) describe(t *testing.T, volID string) map[string]any { } `json:"Volumes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Volumes, 1) return out.Volumes[0].OpenZFSConfiguration @@ -200,7 +201,7 @@ func TestOpenZFSVolume_CopyTagsToSnapshots(t *testing.T) { } `json:"Snapshot"` } - require.NoError(t, json.Unmarshal(snap.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(snap.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Snapshot.Tags, tt.want) }) } diff --git a/services/fsx/page_token.go b/services/fsx/page_token.go index b611d04f14..f7466c22dc 100644 --- a/services/fsx/page_token.go +++ b/services/fsx/page_token.go @@ -3,8 +3,11 @@ package fsx import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -13,18 +16,18 @@ const ( ) // tokenFromBody returns the body's decoded fields and its non-empty NextToken, if any. -func tokenFromBody(body []byte) (map[string]json.RawMessage, string, bool) { +func tokenFromBody(body []byte) (map[string]jsontext.Value, string, bool) { if !bytes.Contains(body, []byte(`"`+nextTokenField+`"`)) { return nil, "", false } - var m map[string]json.RawMessage - if err := json.Unmarshal(body, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { return nil, "", false } var tok string - if err := json.Unmarshal(m[nextTokenField], &tok); err != nil || tok == "" { + if err := json.Unmarshal(m[nextTokenField], &tok, jsonx.V1()); err != nil || tok == "" { return nil, "", false } @@ -44,9 +47,9 @@ func decodeNextToken(body []byte) ([]byte, error) { return nil, fmt.Errorf("%w: NextToken is not valid", ErrValidation) } - m[nextTokenField], _ = json.Marshal(string(key)) + m[nextTokenField], _ = json.Marshal(string(key), jsonx.V1()) - out, err := json.Marshal(m) + out, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: %w", ErrValidation, err) } @@ -61,9 +64,9 @@ func encodeNextToken(body []byte) []byte { return body } - m[nextTokenField], _ = json.Marshal(base64.RawURLEncoding.EncodeToString([]byte(key))) + m[nextTokenField], _ = json.Marshal(base64.RawURLEncoding.EncodeToString([]byte(key)), jsonx.V1()) - out, err := json.Marshal(m) + out, err := json.Marshal(m, jsonx.V1()) if err != nil { return body } diff --git a/services/fsx/persistence.go b/services/fsx/persistence.go index 7a860acf75..c3388c7700 100644 --- a/services/fsx/persistence.go +++ b/services/fsx/persistence.go @@ -2,7 +2,7 @@ package fsx import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -36,7 +36,7 @@ const fsxSnapshotVersion = 2 // store_setup.go's file doc comment for why they do not fit store.Table's // keyed-by-identity-value shape. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` Aliases map[string][]string `json:"aliases"` CreateFileSystemTokens map[string]fsCreateTokenEntry `json:"createFileSystemTokens"` diff --git a/services/fsx/persistence_test.go b/services/fsx/persistence_test.go index 6e2f86ae3a..6b3f85a752 100644 --- a/services/fsx/persistence_test.go +++ b/services/fsx/persistence_test.go @@ -8,7 +8,7 @@ package fsx_test // sharedVpcEnabled scalar, and a snapshot-version-mismatch test. import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/fsx" ) @@ -148,7 +149,7 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { require.Equal(t, http.StatusOK, dedupRec.Code) var dedupOut map[string]any - require.NoError(t, json.Unmarshal(dedupRec.Body.Bytes(), &dedupOut)) + require.NoError(t, json.Unmarshal(dedupRec.Body.Bytes(), &dedupOut, jsonx.V1())) assert.Equal(t, fsID, dedupOut["FileSystem"].(map[string]any)["FileSystemId"]) assert.Equal( t, fsx.FileSystemCount(b), fsx.FileSystemCount(fresh), "dedup replay must not create a new file system", @@ -190,7 +191,7 @@ func assertFullStateRestored(t *testing.T, h *fsx.Handler, ids fullStateIDs) { require.Equal(t, http.StatusOK, rec.Code) var fsOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fsOut, jsonx.V1())) fsList, ok := fsOut["FileSystems"].([]any) require.True(t, ok) require.Len(t, fsList, 1) @@ -212,7 +213,7 @@ func assertFullStateRestored(t *testing.T, h *fsx.Handler, ids fullStateIDs) { require.Equal(t, http.StatusOK, rec.Code) var aliasOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aliasOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aliasOut, jsonx.V1())) aliasList, ok := aliasOut["Aliases"].([]any) require.True(t, ok) require.Len(t, aliasList, 1) @@ -260,7 +261,7 @@ func assertFullStateRestored(t *testing.T, h *fsx.Handler, ids fullStateIDs) { require.Equal(t, http.StatusOK, rec.Code) var vpcOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vpcOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vpcOut, jsonx.V1())) assert.Equal(t, "true", vpcOut["EnableFsxRouteTableUpdatesFromParticipantAccounts"]) rec = doFSxRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": fsRecord["ResourceARN"]}) @@ -275,7 +276,7 @@ func assertOutputLen(t *testing.T, rec *httptest.ResponseRecorder, field string) t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out[field].([]any) require.True(t, ok, "field %q missing or not an array in response %s", field, rec.Body.String()) @@ -305,7 +306,7 @@ func createTaggedFS(t *testing.T, h *fsx.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fs, ok := out["FileSystem"].(map[string]any) require.True(t, ok) @@ -327,7 +328,7 @@ func createBackupForFS(t *testing.T, h *fsx.Handler, fsID string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) backup, ok := out["Backup"].(map[string]any) require.True(t, ok) @@ -349,7 +350,7 @@ func createDRA(t *testing.T, h *fsx.Handler, fsID string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assoc, ok := out["Association"].(map[string]any) require.True(t, ok) @@ -377,7 +378,7 @@ func createDRT(t *testing.T, h *fsx.Handler, fsID string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) task, ok := out["DataRepositoryTask"].(map[string]any) require.True(t, ok) @@ -398,7 +399,7 @@ func createVolSnapshot(t *testing.T, h *fsx.Handler, volumeID string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) snap, ok := out["Snapshot"].(map[string]any) require.True(t, ok) @@ -423,7 +424,7 @@ func createS3AP(t *testing.T, h *fsx.Handler, volumeID string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ap, ok := out["S3AccessPointAttachment"].(map[string]any) require.True(t, ok) diff --git a/services/gcpapigateway/auth.go b/services/gcpapigateway/auth.go index 87c6616941..cc898179a7 100644 --- a/services/gcpapigateway/auth.go +++ b/services/gcpapigateway/auth.go @@ -8,7 +8,7 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "errors" "fmt" @@ -21,6 +21,7 @@ import ( "github.com/golang-jwt/jwt/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -143,7 +144,7 @@ func parseKeySet(raw []byte) map[string]crypto.PublicKey { Keys []jwk `json:"keys"` } - if json.Unmarshal(raw, &set) == nil && len(set.Keys) > 0 { + if json.Unmarshal(raw, &set, jsonx.V1()) == nil && len(set.Keys) > 0 { for _, k := range set.Keys { if pub, err := k.public(); err == nil { keys[k.Kid] = pub @@ -154,7 +155,7 @@ func parseKeySet(raw []byte) map[string]crypto.PublicKey { } var certs map[string]string - if json.Unmarshal(raw, &certs) != nil { + if json.Unmarshal(raw, &certs, jsonx.V1()) != nil { return keys } diff --git a/services/gcpapigateway/dataplane.go b/services/gcpapigateway/dataplane.go index cf425f8731..b00fb6eb35 100644 --- a/services/gcpapigateway/dataplane.go +++ b/services/gcpapigateway/dataplane.go @@ -3,7 +3,8 @@ package gcpapigateway import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,8 @@ import ( "time" "github.com/golang-jwt/jwt/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -156,7 +159,7 @@ func apiOfConfig(config string) string { func writeErr(w http.ResponseWriter, status int, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(map[string]any{"code": status, "message": msg}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{"code": status, "message": msg}) } // DataPlane serves requests to gateways. @@ -288,7 +291,7 @@ func (b *InMemoryBackend) forward( } if claims != nil { - if raw, mErr := json.Marshal(claims); mErr == nil { + if raw, mErr := json.Marshal(claims, jsonx.V1()); mErr == nil { out.Header.Set(userinfoHeader, base64.RawURLEncoding.EncodeToString(raw)) } } diff --git a/services/gcpapigateway/helpers_test.go b/services/gcpapigateway/helpers_test.go index f582c07536..27ed8dbee5 100644 --- a/services/gcpapigateway/helpers_test.go +++ b/services/gcpapigateway/helpers_test.go @@ -2,7 +2,8 @@ package gcpapigateway_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpapigateway" ) @@ -169,7 +171,7 @@ func (e *env) do(t *testing.T, req *http.Request) reply { require.NoError(t, err) r := reply{status: resp.StatusCode, raw: string(raw)} - _ = json.Unmarshal(raw, &r.body) + _ = json.Unmarshal(raw, &r.body, jsonx.V1()) return r } @@ -188,7 +190,7 @@ func echoBackend(t *testing.T) *httptest.Server { w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Backend", "echo") - _ = json.NewEncoder(w).Encode(map[string]any{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{ "method": r.Method, "path": r.URL.Path, "query": r.URL.RawQuery, "headers": hdr, "body": string(body), }) })) diff --git a/services/gcpapigateway/persistence.go b/services/gcpapigateway/persistence.go index 10278b5993..f9b41fb9c4 100644 --- a/services/gcpapigateway/persistence.go +++ b/services/gcpapigateway/persistence.go @@ -2,7 +2,7 @@ package gcpapigateway import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/apigateway/apiv1/apigatewaypb" @@ -18,9 +18,9 @@ import ( const snapshotVersion = 1 type recSnap struct { - Resource json.RawMessage `json:"resource"` - Policy json.RawMessage `json:"policy,omitempty"` - Life life `json:"life"` + Resource jsontext.Value `json:"resource"` + Policy jsontext.Value `json:"policy,omitempty"` + Life life `json:"life"` } type backendSnapshot struct { @@ -32,7 +32,7 @@ type backendSnapshot struct { Seq uint64 `json:"seq"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { if m == nil || !m.ProtoReflect().IsValid() { return nil } @@ -49,7 +49,7 @@ func unmarshalPB(raw []byte, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } -func restorePolicy(raw json.RawMessage) (*iampb.Policy, error) { +func restorePolicy(raw jsontext.Value) (*iampb.Policy, error) { if len(raw) == 0 { return nil, nil //nolint:nilnil // no policy stored } diff --git a/services/gcpapigateway/security_test.go b/services/gcpapigateway/security_test.go index f7949bc4e5..1d0ea11ee0 100644 --- a/services/gcpapigateway/security_test.go +++ b/services/gcpapigateway/security_test.go @@ -6,7 +6,8 @@ import ( "crypto/rand" "crypto/rsa" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "math/big" @@ -19,6 +20,8 @@ import ( "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -110,7 +113,7 @@ func newSigner(t *testing.T) *signer { s := &signer{rsa: sharedRSA(), ec: ec} s.jwks = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - _ = json.NewEncoder(w).Encode(map[string]any{"keys": []map[string]string{ + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{"keys": []map[string]string{ {"kty": "RSA", "kid": "rsa-1", "n": b64u(s.rsa.N), "e": b64u(big.NewInt(int64(s.rsa.E)))}, { "kty": "EC", @@ -396,7 +399,7 @@ func TestJWTUserinfoForwarded(t *testing.T) { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) assert.Equal(t, "user-1", claims["sub"]) assert.Equal(t, "u@example.com", claims["email"]) assert.Equal(t, "Bearer "+tok, hdr["X-Forwarded-Authorization"]) diff --git a/services/gcpartifactregistry/filehttp.go b/services/gcpartifactregistry/filehttp.go index 1a9f3515a9..65307a2410 100644 --- a/services/gcpartifactregistry/filehttp.go +++ b/services/gcpartifactregistry/filehttp.go @@ -3,7 +3,8 @@ package gcpartifactregistry import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "mime" @@ -18,6 +19,7 @@ import ( "google.golang.org/protobuf/encoding/protojson" "github.com/blackbirdworks/gopherstack/pkgs/gcprest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -49,7 +51,7 @@ func writeRESTError(w http.ResponseWriter, err error) { body, _ := json.Marshal(map[string]any{"error": map[string]any{ "code": gcprest.HTTPStatus(st.Code()), "message": st.Message(), "status": codeName(st.Code()), - }}) + }}, jsonx.V1()) w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(gcprest.HTTPStatus(st.Code())) @@ -95,7 +97,7 @@ func readMultipart(r *http.Request) (uploadReq, []byte, error) { } var req uploadReq - if err = json.NewDecoder(meta).Decode(&req); err != nil { + if err = json.UnmarshalDecode(jsontext.NewDecoder(meta), &req, jsonx.V1()); err != nil { return uploadReq{}, nil, errInvalid("The upload metadata is not valid JSON: %v", err) } diff --git a/services/gcpartifactregistry/files.go b/services/gcpartifactregistry/files.go index 4dac4c9b5f..d53a7d8b87 100644 --- a/services/gcpartifactregistry/files.go +++ b/services/gcpartifactregistry/files.go @@ -4,7 +4,7 @@ import ( "cmp" "context" "encoding/hex" - "encoding/json" + "encoding/json/v2" "maps" "regexp" "slices" @@ -15,6 +15,7 @@ import ( "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -77,7 +78,7 @@ func (b *InMemoryBackend) dockerFiles(ctx context.Context, ref repoRef) []*artif add(d, int64(len(m.Body)), src) var doc manifestBlobs - if json.Unmarshal(m.Body, &doc) != nil { + if json.Unmarshal(m.Body, &doc, jsonx.V1()) != nil { continue } diff --git a/services/gcpartifactregistry/files_test.go b/services/gcpartifactregistry/files_test.go index 3423f1fb37..740847e795 100644 --- a/services/gcpartifactregistry/files_test.go +++ b/services/gcpartifactregistry/files_test.go @@ -1,7 +1,7 @@ package gcpartifactregistry_test import ( - "encoding/json" + "encoding/json/v2" "testing" "cloud.google.com/go/artifactregistry/apiv1/artifactregistrypb" @@ -12,6 +12,7 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/fieldmaskpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" ) @@ -54,7 +55,7 @@ func configDigest(t *testing.T, img ocitest.Image) string { } `json:"config"` } - require.NoError(t, json.Unmarshal(img.Body, &doc)) + require.NoError(t, json.Unmarshal(img.Body, &doc, jsonx.V1())) return doc.Config.Digest } diff --git a/services/gcpartifactregistry/helpers_test.go b/services/gcpartifactregistry/helpers_test.go index a1f4158d7f..e6ad4a7b77 100644 --- a/services/gcpartifactregistry/helpers_test.go +++ b/services/gcpartifactregistry/helpers_test.go @@ -4,7 +4,7 @@ import ( "context" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net" "net/http" "slices" @@ -17,6 +17,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" "github.com/blackbirdworks/gopherstack/services/gcpartifactregistry" ) @@ -108,7 +109,7 @@ func decodeJSON(t *testing.T, body []byte) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out } diff --git a/services/gcpartifactregistry/npm.go b/services/gcpartifactregistry/npm.go index 68ccc38146..472a7a190b 100644 --- a/services/gcpartifactregistry/npm.go +++ b/services/gcpartifactregistry/npm.go @@ -5,13 +5,16 @@ import ( "crypto/sha512" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "maps" "net/http" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -28,10 +31,10 @@ type npmAttachment struct { } type npmPublishDoc struct { - DistTags map[string]string `json:"dist-tags"` - Versions map[string]json.RawMessage `json:"versions"` - Attachments map[string]npmAttachment `json:"_attachments"` - Name string `json:"name"` + DistTags map[string]string `json:"dist-tags"` + Versions map[string]jsontext.Value `json:"versions"` + Attachments map[string]npmAttachment `json:"_attachments"` + Name string `json:"name"` } func writeNPMError(w http.ResponseWriter, code int, msg string) { @@ -123,7 +126,7 @@ func readNPMDoc(w http.ResponseWriter, r *http.Request) (npmPublishDoc, bool) { var doc npmPublishDoc body := http.MaxBytesReader(w, r.Body, maxNPMDocBytes) - if err := json.NewDecoder(body).Decode(&doc); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(body), &doc, jsonx.V1()); err != nil { writeNPMError(w, http.StatusBadRequest, "Invalid package document: "+err.Error()) return doc, false @@ -201,7 +204,7 @@ func (b *InMemoryBackend) publishNPM(w http.ResponseWriter, r *http.Request, rc } func npmVersionFile( - pkg, version string, manifest json.RawMessage, atts map[string]npmAttachment, + pkg, version string, manifest jsontext.Value, atts map[string]npmAttachment, ) (pkgFile, int, string) { if !npmVersionRe.MatchString(version) { return pkgFile{}, http.StatusBadRequest, "Invalid semver version " + version + "." @@ -278,7 +281,7 @@ func (b *InMemoryBackend) serveNPMPackument(w http.ResponseWriter, r *http.Reque } base := baseURL(r, npmRoute, rc) - docs := map[string]json.RawMessage{} + docs := map[string]jsontext.Value{} times := map[string]string{} rev := sha1.New() //nolint:gosec // opaque revision token @@ -305,10 +308,10 @@ func (b *InMemoryBackend) serveNPMPackument(w http.ResponseWriter, r *http.Reque } // withDist adds the dist block npm clients install from to a stored version manifest. -func withDist(f *genFile, manifest []byte, tarballURL string) json.RawMessage { - var m map[string]json.RawMessage - if json.Unmarshal(manifest, &m) != nil { - m = map[string]json.RawMessage{} +func withDist(f *genFile, manifest []byte, tarballURL string) jsontext.Value { + var m map[string]jsontext.Value + if json.Unmarshal(manifest, &m, jsonx.V1()) != nil { + m = map[string]jsontext.Value{} } s1 := sha1.Sum(f.Data) //nolint:gosec // npm dist.shasum is SHA-1 by protocol @@ -316,10 +319,10 @@ func withDist(f *genFile, manifest []byte, tarballURL string) json.RawMessage { dist, _ := json.Marshal(map[string]any{ "tarball": tarballURL, "shasum": hex.EncodeToString(s1[:]), "integrity": "sha512-" + base64.StdEncoding.EncodeToString(s512[:]), - }) + }, jsonx.V1()) m["dist"] = dist - out, _ := json.Marshal(m) + out, _ := json.Marshal(m, jsonx.V1()) return out } @@ -414,7 +417,11 @@ func (b *InMemoryBackend) putNPMTag( w http.ResponseWriter, r *http.Request, rc repoCtx, pkg, tag string, existing map[string]bool, ) { var version string - if err := json.NewDecoder(io.LimitReader(r.Body, maxTagBody)).Decode(&version); err != nil { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(io.LimitReader(r.Body, maxTagBody)), + &version, + jsonx.V1(), + ); err != nil { writeNPMError(w, http.StatusBadRequest, "The body must be a JSON string holding a version.") return diff --git a/services/gcpartifactregistry/persistence.go b/services/gcpartifactregistry/persistence.go index 0e7f7ff00d..e52d39a859 100644 --- a/services/gcpartifactregistry/persistence.go +++ b/services/gcpartifactregistry/persistence.go @@ -2,7 +2,7 @@ package gcpartifactregistry import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/artifactregistry/apiv1/artifactregistrypb" @@ -19,8 +19,8 @@ import ( const snapshotVersion = 1 type repoSnap struct { - Repository json.RawMessage `json:"repository"` - IAM json.RawMessage `json:"iam,omitempty"` + Repository jsontext.Value `json:"repository"` + IAM jsontext.Value `json:"iam,omitempty"` } type backendSnapshot struct { @@ -31,14 +31,14 @@ type backendSnapshot struct { GenericVers map[string]*resMeta `json:"genericVersions,omitempty"` GenericFiles map[string]*genFile `json:"genericFiles,omitempty"` PackageTags map[string]map[string]string `json:"packageTags,omitempty"` - Rules map[string]json.RawMessage `json:"rules,omitempty"` - Settings map[string]json.RawMessage `json:"projectSettings,omitempty"` - VPCSC map[string]json.RawMessage `json:"vpcscConfigs,omitempty"` - Operations map[string]json.RawMessage `json:"operations"` + Rules map[string]jsontext.Value `json:"rules,omitempty"` + Settings map[string]jsontext.Value `json:"projectSettings,omitempty"` + VPCSC map[string]jsontext.Value `json:"vpcscConfigs,omitempty"` + Operations map[string]jsontext.Value `json:"operations"` Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -47,7 +47,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } @@ -133,8 +133,8 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { return nil } -func marshalAll[T proto.Message](in map[string]T) map[string]json.RawMessage { - out := make(map[string]json.RawMessage, len(in)) +func marshalAll[T proto.Message](in map[string]T) map[string]jsontext.Value { + out := make(map[string]jsontext.Value, len(in)) for k, v := range in { out[k] = marshalPB(v) } @@ -142,7 +142,7 @@ func marshalAll[T proto.Message](in map[string]T) map[string]json.RawMessage { return out } -func unmarshalAll[T proto.Message](in map[string]json.RawMessage, newMsg func() T) (map[string]T, error) { +func unmarshalAll[T proto.Message](in map[string]jsontext.Value, newMsg func() T) (map[string]T, error) { out := make(map[string]T, len(in)) for k, raw := range in { diff --git a/services/gcpartifactregistry/pkgfmt.go b/services/gcpartifactregistry/pkgfmt.go index 6f49fd5eb2..aa15364dd0 100644 --- a/services/gcpartifactregistry/pkgfmt.go +++ b/services/gcpartifactregistry/pkgfmt.go @@ -2,7 +2,7 @@ package gcpartifactregistry import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "regexp" @@ -13,6 +13,7 @@ import ( "cloud.google.com/go/artifactregistry/apiv1/artifactregistrypb" "github.com/blackbirdworks/gopherstack/pkgs/gcprest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -160,7 +161,7 @@ func writePlain(w http.ResponseWriter, code int, msg string) { } func writeJSONBody(w http.ResponseWriter, code int, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { writePlain(w, http.StatusInternalServerError, err.Error()) diff --git a/services/gcpartifactregistry/pkgfmt_test.go b/services/gcpartifactregistry/pkgfmt_test.go index 2c6edfd9a6..d8b383d88e 100644 --- a/services/gcpartifactregistry/pkgfmt_test.go +++ b/services/gcpartifactregistry/pkgfmt_test.go @@ -7,7 +7,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "io" "mime/multipart" @@ -17,6 +17,7 @@ import ( "testing" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "cloud.google.com/go/artifactregistry/apiv1/artifactregistrypb" "github.com/stretchr/testify/assert" @@ -160,7 +161,7 @@ func npmPublishBody(t *testing.T, name, version, tag string, tarball []byte) []b }}, } - raw, err := json.Marshal(doc) + raw, err := json.Marshal(doc, jsonx.V1()) require.NoError(t, err) return raw @@ -392,7 +393,7 @@ func TestNPMProtocol(t *testing.T) { "name": "left-pad", "dist-tags": map[string]string{"latest": "1.0.0"}, "versions": map[string]any{"1.0.0": map[string]any{}}, } - raw, _ := json.Marshal(unpub) + raw, _ := json.Marshal(unpub, jsonx.V1()) require.Equal( t, diff --git a/services/gcpartifactregistry/python.go b/services/gcpartifactregistry/python.go index b3bc5ab05e..7f4f78b99c 100644 --- a/services/gcpartifactregistry/python.go +++ b/services/gcpartifactregistry/python.go @@ -4,13 +4,15 @@ import ( "crypto/md5" //nolint:gosec // twine sends md5_digest by protocol "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "html" "io" "net/http" "net/url" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -100,7 +102,12 @@ func (b *InMemoryBackend) uploadPython(w http.ResponseWriter, r *http.Request, r norm := pyNormalize(name) doc, _ := json.Marshal( - pyDoc{Name: name, RequiresPython: r.FormValue("requires_python"), SHA256: hex.EncodeToString(sum[:])}, + pyDoc{ + Name: name, + RequiresPython: r.FormValue("requires_python"), + SHA256: hex.EncodeToString(sum[:]), + }, + jsonx.V1(), ) err = b.putPackageFile(rc.ref, pkgFile{ @@ -194,7 +201,7 @@ func (b *InMemoryBackend) pyProject(w http.ResponseWriter, r *http.Request, rc r for _, v := range versions { for _, nf := range v.files { var d pyDoc - _ = json.Unmarshal(nf.file.Doc, &d) + _ = json.Unmarshal(nf.file.Doc, &d, jsonx.V1()) filename := nf.id[strings.LastIndex(nf.id, ":")+1:] href := "/python/" + rc.ref.project + "/" + rc.ref.id + "/packages/" + url.PathEscape(norm) + "/" + diff --git a/services/gcpartifactregistry/util.go b/services/gcpartifactregistry/util.go index 5e365bba1a..97383fc0ed 100644 --- a/services/gcpartifactregistry/util.go +++ b/services/gcpartifactregistry/util.go @@ -1,10 +1,12 @@ package gcpartifactregistry import ( - "encoding/json" + "encoding/json/v2" "os" "sort" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func sortStrings(s []string) { sort.Strings(s) } @@ -13,4 +15,4 @@ func removeAll(path string) { _ = os.RemoveAll(path) } func timeFromNanos(n int64) time.Time { return time.Unix(0, n).UTC() } -func marshalJSON(v any) ([]byte, error) { return json.Marshal(v) } +func marshalJSON(v any) ([]byte, error) { return json.Marshal(v, jsonx.V1()) } diff --git a/services/gcpbatch/persistence.go b/services/gcpbatch/persistence.go index ca47826643..5a34accd44 100644 --- a/services/gcpbatch/persistence.go +++ b/services/gcpbatch/persistence.go @@ -2,7 +2,7 @@ package gcpbatch import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -17,8 +17,8 @@ import ( const snapshotVersion = 1 type jobSnap struct { - Rec *jobRec `json:"rec"` - Job json.RawMessage `json:"job"` + Rec *jobRec `json:"rec"` + Job jsontext.Value `json:"job"` } type backendSnapshot struct { diff --git a/services/gcpbigquery/autodetect.go b/services/gcpbigquery/autodetect.go index 3f72ac8a6f..f9d31b3f41 100644 --- a/services/gcpbigquery/autodetect.go +++ b/services/gcpbigquery/autodetect.go @@ -2,7 +2,8 @@ package gcpbigquery import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -10,6 +11,7 @@ import ( "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -176,15 +178,14 @@ func dedupeNames(fs []bqsql.Field) []bqsql.Field { } func detectJSON(lc loadConfig, data []byte) ([]bqsql.Field, error) { - dec := json.NewDecoder(bytes.NewReader(decodeText(data, lc.Encoding))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(decodeText(data, lc.Encoding))) var fields []bqsql.Field for range detectSample { var obj map[string]any - err := dec.Decode(&obj) + err := json.UnmarshalDecode(dec, &obj, jsonx.V1(), jsonx.UseNumber()) if errors.Is(err, io.EOF) { break } @@ -281,7 +282,7 @@ func inferJSONField(name string, v any) (bqsql.Field, bool) { return f, len(f.Fields) > 0 case bool: f.Type = litBoolean - case json.Number: + case jsonx.Number: f.Type = litInteger if _, err := t.Int64(); err != nil { f.Type = litFloat diff --git a/services/gcpbigquery/bqsql/engine_test.go b/services/gcpbigquery/bqsql/engine_test.go index a75559cf3a..121244e995 100644 --- a/services/gcpbigquery/bqsql/engine_test.go +++ b/services/gcpbigquery/bqsql/engine_test.go @@ -1,13 +1,15 @@ package bqsql_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -28,7 +30,7 @@ func fieldsJSON(t *testing.T, s string) []bqsql.Field { var fs []bqsql.Field - require.NoError(t, json.Unmarshal([]byte(s), &fs)) + require.NoError(t, json.Unmarshal([]byte(s), &fs, jsonx.V1())) require.NoError(t, bqsql.NormalizeSchema(fs)) return fs @@ -37,12 +39,11 @@ func fieldsJSON(t *testing.T, s string) []bqsql.Field { func rowsJSON(t *testing.T, fs []bqsql.Field, s string) [][]any { t.Helper() - dec := json.NewDecoder(strings.NewReader(s)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(s)) var raw []map[string]any - require.NoError(t, dec.Decode(&raw)) + require.NoError(t, json.UnmarshalDecode(dec, &raw, jsonx.V1(), jsonx.UseNumber())) out := make([][]any, len(raw)) @@ -222,7 +223,7 @@ func TestSelectQueries(t *testing.T) { return } - got, merr := json.Marshal(wireRows(res)) + got, merr := json.Marshal(wireRows(res), jsonx.V1()) require.NoError(t, merr) assert.JSONEq(t, tt.want, string(got)) }) diff --git a/services/gcpbigquery/bqsql/sqlvalues.go b/services/gcpbigquery/bqsql/sqlvalues.go index 1e9c7ff135..5be3ab2179 100644 --- a/services/gcpbigquery/bqsql/sqlvalues.go +++ b/services/gcpbigquery/bqsql/sqlvalues.go @@ -4,10 +4,13 @@ import ( "bytes" "database/sql/driver" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ToSQLite converts a stored value into the value bound into SQLite: scalars map to INTEGER, REAL or TEXT and @@ -111,7 +114,7 @@ func writeJSONRecord(buf *bytes.Buffer, fields []Field, stored any) { buf.WriteByte(',') } - name, _ := json.Marshal(fl.Name) + name, _ := json.Marshal(fl.Name, jsonx.V1()) buf.Write(name) buf.WriteByte(':') @@ -133,7 +136,7 @@ func writeJSONScalar(buf *bytes.Buffer, k Kind, s string) { case KindFloat: f, _ := parseFloatText(s) if math.IsNaN(f) || math.IsInf(f, 0) { - q, _ := json.Marshal(s) + q, _ := json.Marshal(s, jsonx.V1()) buf.Write(q) return @@ -142,7 +145,7 @@ func writeJSONScalar(buf *bytes.Buffer, k Kind, s string) { buf.WriteString(strconv.FormatFloat(f, 'g', -1, bitSize)) case KindUnknown, KindString, KindBytes, KindTimestamp, KindDate, KindTime, KindDatetime, KindNumeric, KindBigNumeric, KindJSON, KindGeography, KindStruct, KindArray: - q, _ := json.Marshal(s) + q, _ := json.Marshal(s, jsonx.V1()) buf.Write(q) } } @@ -177,11 +180,10 @@ func fromJSONText(f Field, v any) (any, error) { return nil, valueErr("expected JSON text for %s, got %T", f.Name, v) } - dec := json.NewDecoder(strings.NewReader(text)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(text)) var node any - if err := dec.Decode(&node); err != nil { + if err := json.UnmarshalDecode(dec, &node, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, valueErr("invalid JSON for %s: %v", f.Name, err) } diff --git a/services/gcpbigquery/bqsql/udf_array.go b/services/gcpbigquery/bqsql/udf_array.go index e4e7f7db7d..418a096ffe 100644 --- a/services/gcpbigquery/bqsql/udf_array.go +++ b/services/gcpbigquery/bqsql/udf_array.go @@ -3,16 +3,18 @@ package bqsql import ( "bytes" "database/sql/driver" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func decodeJSONArray(v driver.Value) ([]any, error) { - dec := json.NewDecoder(strings.NewReader(toStr(v))) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(toStr(v))) var arr []any - if err := dec.Decode(&arr); err != nil { + if err := json.UnmarshalDecode(dec, &arr, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, errBQ("expected an ARRAY value") } @@ -22,9 +24,8 @@ func decodeJSONArray(v driver.Value) ([]any, error) { func encodeJSON(v any) string { var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) - _ = enc.Encode(v) + enc := jsontext.NewEncoder(&buf, jsonx.V1(), jsontext.EscapeForHTML(false)) + _ = json.MarshalEncode(enc, v) return strings.TrimSpace(buf.String()) } @@ -34,7 +35,7 @@ func jsonToSQL(v any) driver.Value { switch t := v.(type) { case nil: return nil - case json.Number: + case jsonx.Number: if n, err := t.Int64(); err == nil { return n } diff --git a/services/gcpbigquery/bqsql/udf_json.go b/services/gcpbigquery/bqsql/udf_json.go index 7b95dd8105..5d52d43200 100644 --- a/services/gcpbigquery/bqsql/udf_json.go +++ b/services/gcpbigquery/bqsql/udf_json.go @@ -3,11 +3,14 @@ package bqsql import ( "crypto/rand" "database/sql/driver" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -56,7 +59,7 @@ func udfParseJSON(a []driver.Value) (driver.Value, error) { } s := toStr(a[0]) - if !json.Valid([]byte(s)) { + if !jsontext.Value([]byte(s)).IsValid(jsonx.V1()) { return nil, errBQ("syntax error while parsing value in JSON") } @@ -75,7 +78,7 @@ func udfJSONValue(scalarOnly bool) udfFn { } var doc any - if err := json.Unmarshal([]byte(toStr(a[0])), &doc); err != nil { + if err := json.Unmarshal([]byte(toStr(a[0])), &doc, jsonx.V1()); err != nil { return nil, errBQ("Invalid JSON: %v", err) } @@ -103,7 +106,7 @@ func jsonNodeText(node any, scalarOnly bool) driver.Value { } } - b, _ := json.Marshal(node) + b, _ := json.Marshal(node, jsonx.V1()) return string(b) } diff --git a/services/gcpbigquery/bqsql/udf_regex.go b/services/gcpbigquery/bqsql/udf_regex.go index 043783687c..9d163c95be 100644 --- a/services/gcpbigquery/bqsql/udf_regex.go +++ b/services/gcpbigquery/bqsql/udf_regex.go @@ -2,9 +2,11 @@ package bqsql import ( "database/sql/driver" - "encoding/json" + "encoding/json/v2" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func compileRe(v driver.Value) (*regexp.Regexp, error) { @@ -138,7 +140,7 @@ func udfRegexExtractAll(a []driver.Value) (driver.Value, error) { out = append(out, firstGroup(m)) } - b, _ := json.Marshal(out) + b, _ := json.Marshal(out, jsonx.V1()) return string(b), nil } diff --git a/services/gcpbigquery/bqsql/udf_str.go b/services/gcpbigquery/bqsql/udf_str.go index e2b5d95efd..c53a33b5c0 100644 --- a/services/gcpbigquery/bqsql/udf_str.go +++ b/services/gcpbigquery/bqsql/udf_str.go @@ -8,10 +8,12 @@ import ( "database/sql/driver" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "strings" "unicode" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func strFn(n int32, f func(s string, a []driver.Value) (driver.Value, error)) udfDef { @@ -379,7 +381,7 @@ func udfSplit(a []driver.Value) (driver.Value, error) { parts = []string{""} } - b, _ := json.Marshal(parts) + b, _ := json.Marshal(parts, jsonx.V1()) return string(b), nil } diff --git a/services/gcpbigquery/bqsql/udf_time.go b/services/gcpbigquery/bqsql/udf_time.go index 61a24c0acf..bbd2e08888 100644 --- a/services/gcpbigquery/bqsql/udf_time.go +++ b/services/gcpbigquery/bqsql/udf_time.go @@ -2,10 +2,12 @@ package bqsql import ( "database/sql/driver" - "encoding/json" + "encoding/json/v2" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseAny parses a stored temporal text value and reports which family it belongs to. @@ -661,7 +663,7 @@ func udfGenerateDates(a []driver.Value) (driver.Value, error) { t, _, _ = parseAny(next) } - b, _ := json.Marshal(out) + b, _ := json.Marshal(out, jsonx.V1()) return string(b), nil } diff --git a/services/gcpbigquery/bqsql/values.go b/services/gcpbigquery/bqsql/values.go index 6213d6f74c..eb1b9f81ac 100644 --- a/services/gcpbigquery/bqsql/values.go +++ b/services/gcpbigquery/bqsql/values.go @@ -2,7 +2,8 @@ package bqsql import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "math" @@ -10,6 +11,8 @@ import ( "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Canonical stored encodings of temporal values. @@ -168,7 +171,7 @@ func storedString(v any) (string, error) { return t, nil case []byte: return string(t), nil - case json.Number: + case jsonx.Number: return t.String(), nil case bool: return strconv.FormatBool(t), nil @@ -183,14 +186,14 @@ func storedString(v any) (string, error) { func storedJSON(v any) (string, error) { if s, ok := v.(string); ok { - if !json.Valid([]byte(s)) { + if !jsontext.Value([]byte(s)).IsValid(jsonx.V1()) { return "", valueErr("invalid JSON text") } return s, nil } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "", valueErr("cannot encode JSON: %v", err) } @@ -204,7 +207,7 @@ func numberText(v any) (string, bool) { return strings.TrimSpace(t), true case []byte: return strings.TrimSpace(string(t)), true - case json.Number: + case jsonx.Number: return t.String(), true case int64: return strconv.FormatInt(t, decimalBase), true @@ -293,7 +296,7 @@ func storedBool(v any) (string, error) { return strconv.FormatBool(t), nil case int64: return strconv.FormatBool(t != 0), nil - case json.Number: + case jsonx.Number: return strconv.FormatBool(t.String() != "0"), nil case string: switch strings.ToLower(strings.TrimSpace(t)) { @@ -449,7 +452,7 @@ func epochTime(v any) (time.Time, bool) { var f float64 switch t := v.(type) { - case json.Number: + case jsonx.Number: g, err := t.Float64() if err != nil { return time.Time{}, false diff --git a/services/gcpbigquery/handler.go b/services/gcpbigquery/handler.go index c880a3bed4..7abd7bb8cf 100644 --- a/services/gcpbigquery/handler.go +++ b/services/gcpbigquery/handler.go @@ -2,7 +2,8 @@ package gcpbigquery import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -179,11 +181,10 @@ func decodeObject(data []byte) (map[string]any, error) { return map[string]any{}, nil } - dec := json.NewDecoder(strings.NewReader(string(data))) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(string(data))) var body map[string]any - if err := dec.Decode(&body); err != nil { + if err := json.UnmarshalDecode(dec, &body, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, errInvalid("Invalid JSON payload received: %v", err) } @@ -366,10 +367,9 @@ func (h *Handler) insertAll(c *echo.Context, rt route) error { return newErr(http.StatusRequestEntityTooLarge, "uploadTooLarge", "Request body is too large or unreadable.") } - dec := json.NewDecoder(strings.NewReader(string(data))) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(string(data))) - if err := dec.Decode(&req); err != nil { + if err := json.UnmarshalDecode(dec, &req, jsonx.V1(), jsonx.UseNumber()); err != nil { return errInvalid("Invalid JSON payload received: %v", err) } diff --git a/services/gcpbigquery/jobs_extract.go b/services/gcpbigquery/jobs_extract.go index 6bc1f41408..8429e0fd9f 100644 --- a/services/gcpbigquery/jobs_extract.go +++ b/services/gcpbigquery/jobs_extract.go @@ -3,13 +3,15 @@ package gcpbigquery import ( "bytes" "compress/gzip" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -214,30 +216,30 @@ func encodeCSV(ec extractConfig, t *Table) ([]byte, error) { return buf.Bytes(), nil } -func jsonCell(f bqsql.Field, v any) json.RawMessage { +func jsonCell(f bqsql.Field, v any) jsontext.Value { if v == nil && f.Mode != bqsql.ModeRepeated { - return json.RawMessage("null") + return jsontext.Value("null") } k, _ := bqsql.KindOf(f.Type) if k == bqsql.KindStruct || f.Mode == bqsql.ModeRepeated { text, _ := bqsql.ToSQLite(f, v).(string) - return json.RawMessage(text) + return jsontext.Value(text) } s, _ := v.(string) switch k { case bqsql.KindInt, bqsql.KindBool, bqsql.KindNumeric, bqsql.KindBigNumeric: - return json.RawMessage(s) + return jsontext.Value(s) case bqsql.KindFloat: if f, err := strconv.ParseFloat( s, 64, ); err == nil && !math.IsNaN(f) && !math.IsInf(f, 0) { - return json.RawMessage(strconv.FormatFloat(f, 'g', -1, 64)) + return jsontext.Value(strconv.FormatFloat(f, 'g', -1, 64)) } case bqsql.KindTimestamp: if t, err := time.Parse(bqsql.TimestampLayout, s); err == nil { @@ -249,7 +251,7 @@ func jsonCell(f bqsql.Field, v any) json.RawMessage { bqsql.KindStruct, bqsql.KindArray: } - q, _ := json.Marshal(s) + q, _ := json.Marshal(s, jsonx.V1()) return q } @@ -265,7 +267,7 @@ func encodeNDJSON(t *Table) []byte { buf.WriteByte(',') } - name, _ := json.Marshal(f.Name) + name, _ := json.Marshal(f.Name, jsonx.V1()) buf.Write(name) buf.WriteByte(':') buf.Write(jsonCell(f, row[i])) diff --git a/services/gcpbigquery/jobs_query.go b/services/gcpbigquery/jobs_query.go index db8ea1c476..f0eb0a30d3 100644 --- a/services/gcpbigquery/jobs_query.go +++ b/services/gcpbigquery/jobs_query.go @@ -2,13 +2,14 @@ package gcpbigquery import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "regexp" "strconv" "strings" "sync" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -38,7 +39,7 @@ type datasetRef struct { func intOf(v any) (int, bool) { switch t := v.(type) { - case json.Number: + case jsonx.Number: n, err := t.Int64() return int(n), err == nil @@ -56,12 +57,12 @@ func intOf(v any) (int, bool) { func decodeQueryConfig(raw any) (queryConfig, error) { var qc queryConfig - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return qc, errInvalid("Invalid query configuration") } - if err = json.Unmarshal(b, &qc); err != nil { + if err = json.Unmarshal(b, &qc, jsonx.V1()); err != nil { return qc, errInvalid("Invalid query configuration: %v", err) } diff --git a/services/gcpbigquery/load_formats.go b/services/gcpbigquery/load_formats.go index 37fe198667..f37c8221cc 100644 --- a/services/gcpbigquery/load_formats.go +++ b/services/gcpbigquery/load_formats.go @@ -3,12 +3,14 @@ package gcpbigquery import ( "bytes" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -133,8 +135,7 @@ func csvRow(lc loadConfig, fields []bqsql.Field, rec []string) ([]any, error) { } func parseJSONInput(lc loadConfig, fields []bqsql.Field, data []byte) ([][]any, []error, error) { - dec := json.NewDecoder(bytes.NewReader(decodeText(data, lc.Encoding))) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(decodeText(data, lc.Encoding)), jsonx.V1()) var ( rows [][]any @@ -144,7 +145,7 @@ func parseJSONInput(lc loadConfig, fields []bqsql.Field, data []byte) ([][]any, for n := 1; ; n++ { var obj map[string]any - err := dec.Decode(&obj) + err := json.UnmarshalDecode(dec, &obj, jsonx.V1(), jsonx.UseNumber()) if errors.Is(err, io.EOF) { return rows, bad, nil } diff --git a/services/gcpbigquery/tables.go b/services/gcpbigquery/tables.go index cbaba8067d..c784afe0f9 100644 --- a/services/gcpbigquery/tables.go +++ b/services/gcpbigquery/tables.go @@ -2,10 +2,11 @@ package gcpbigquery import ( "context" - "encoding/json" + "encoding/json/v2" "sort" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/services/gcpbigquery/bqsql" ) @@ -24,7 +25,7 @@ func decodeSchema(raw any) ([]bqsql.Field, error) { return nil, nil } - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, errInvalid("Invalid schema") } @@ -33,7 +34,7 @@ func decodeSchema(raw any) ([]bqsql.Field, error) { Fields []bqsql.Field `json:"fields"` } - if err = json.Unmarshal(b, &s); err != nil { + if err = json.Unmarshal(b, &s, jsonx.V1()); err != nil { return nil, errInvalid("Invalid schema: %v", err) } diff --git a/services/gcpbigtable/persistence.go b/services/gcpbigtable/persistence.go index bab8da7450..d62b30f428 100644 --- a/services/gcpbigtable/persistence.go +++ b/services/gcpbigtable/persistence.go @@ -2,7 +2,7 @@ package gcpbigtable import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/bigtable/admin/apiv2/adminpb" @@ -34,35 +34,35 @@ type rowSnap struct { } type tableSnap struct { - Table json.RawMessage `json:"table"` - Policy json.RawMessage `json:"policy,omitempty"` - Splits [][]byte `json:"splits,omitempty"` - Rows []rowSnap `json:"rows,omitempty"` + Table jsontext.Value `json:"table"` + Policy jsontext.Value `json:"policy,omitempty"` + Splits [][]byte `json:"splits,omitempty"` + Rows []rowSnap `json:"rows,omitempty"` } type backupSnap struct { - Backup json.RawMessage `json:"backup"` - Policy json.RawMessage `json:"policy,omitempty"` - Table tableSnap `json:"table"` + Backup jsontext.Value `json:"backup"` + Policy jsontext.Value `json:"policy,omitempty"` + Table tableSnap `json:"table"` } type instSnap struct { - Clusters map[string]json.RawMessage `json:"clusters,omitempty"` - Profiles map[string]json.RawMessage `json:"profiles,omitempty"` - Tables map[string]tableSnap `json:"tables,omitempty"` - Backups map[string]backupSnap `json:"backups,omitempty"` - Instance json.RawMessage `json:"instance"` - Policy json.RawMessage `json:"policy,omitempty"` + Clusters map[string]jsontext.Value `json:"clusters,omitempty"` + Profiles map[string]jsontext.Value `json:"profiles,omitempty"` + Tables map[string]tableSnap `json:"tables,omitempty"` + Backups map[string]backupSnap `json:"backups,omitempty"` + Instance jsontext.Value `json:"instance"` + Policy jsontext.Value `json:"policy,omitempty"` } type backendSnapshot struct { - Instances map[string]instSnap `json:"instances"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` - Seq uint64 `json:"seq"` + Instances map[string]instSnap `json:"instances"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` + Seq uint64 `json:"seq"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { if m == nil || !m.ProtoReflect().IsValid() { return nil } @@ -124,7 +124,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { for name, r := range b.instances { s := instSnap{ Instance: marshalPB(r.pb), Policy: marshalPB(r.policy), - Clusters: map[string]json.RawMessage{}, Profiles: map[string]json.RawMessage{}, + Clusters: map[string]jsontext.Value{}, Profiles: map[string]jsontext.Value{}, Tables: map[string]tableSnap{}, Backups: map[string]backupSnap{}, } diff --git a/services/gcpcloudbuild/bindings.go b/services/gcpcloudbuild/bindings.go index 7f89ff16b4..33c0905648 100644 --- a/services/gcpcloudbuild/bindings.go +++ b/services/gcpcloudbuild/bindings.go @@ -2,11 +2,14 @@ package gcpcloudbuild import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "regexp" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errBindingMissing = errors.New("not present in the payload") @@ -32,10 +35,9 @@ func bindPayload(subs map[string]string, body []byte) (map[string]string, error) } if !parsed { - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) - if err := dec.Decode(&doc); err != nil { + if err := json.UnmarshalDecode(dec, &doc, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, errInvalid( "The webhook payload is not valid JSON, so $(body...) bindings cannot resolve: %v.", err) } @@ -79,13 +81,13 @@ func lookupBinding(doc any, path string) (string, error) { return "", nil case string: return v, nil - case json.Number: + case jsonx.Number: return v.String(), nil case bool: return strconv.FormatBool(v), nil } - raw, err := json.Marshal(cur) + raw, err := json.Marshal(cur, jsonx.V1()) if err != nil { return "", errBindingMissing } diff --git a/services/gcpcloudbuild/persistence.go b/services/gcpcloudbuild/persistence.go index 9106fb5ead..f5a5c75439 100644 --- a/services/gcpcloudbuild/persistence.go +++ b/services/gcpcloudbuild/persistence.go @@ -2,7 +2,7 @@ package gcpcloudbuild import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb" @@ -19,20 +19,20 @@ import ( const snapshotVersion = 1 type buildSnap struct { - OpName string `json:"opName"` - Build json.RawMessage `json:"build"` - Orig json.RawMessage `json:"orig"` + OpName string `json:"opName"` + Build jsontext.Value `json:"build"` + Orig jsontext.Value `json:"orig"` } type backendSnapshot struct { - Builds map[string]buildSnap `json:"builds"` - Triggers map[string]json.RawMessage `json:"triggers"` - Pools map[string]json.RawMessage `json:"workerPools"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` + Builds map[string]buildSnap `json:"builds"` + Triggers map[string]jsontext.Value `json:"triggers"` + Pools map[string]jsontext.Value `json:"workerPools"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -41,7 +41,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } @@ -54,8 +54,8 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { snap := backendSnapshot{ Version: snapshotVersion, Operations: b.ops.Snapshot(), Builds: make(map[string]buildSnap, len(b.builds)), - Triggers: make(map[string]json.RawMessage, len(b.triggers)), - Pools: make(map[string]json.RawMessage, len(b.pools)), + Triggers: make(map[string]jsontext.Value, len(b.triggers)), + Pools: make(map[string]jsontext.Value, len(b.pools)), } for k, rec := range b.builds { @@ -170,7 +170,7 @@ func restoreBuilds(in map[string]buildSnap) (map[string]*buildRec, error) { return out, nil } -func restoreMap[T proto.Message](in map[string]json.RawMessage, mk func() T) (map[string]T, error) { +func restoreMap[T proto.Message](in map[string]jsontext.Value, mk func() T) (map[string]T, error) { out := make(map[string]T, len(in)) for k, raw := range in { diff --git a/services/gcpcloudbuild/publish.go b/services/gcpcloudbuild/publish.go index 1a64bad914..04762ccf67 100644 --- a/services/gcpcloudbuild/publish.go +++ b/services/gcpcloudbuild/publish.go @@ -4,7 +4,7 @@ import ( "context" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/url" @@ -17,6 +17,7 @@ import ( "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -221,7 +222,7 @@ func (r *runner) writeManifest(bucket, prefix string, lines []manifestLine) (str var sb strings.Builder for _, l := range lines { - raw, err := json.Marshal(l) + raw, err := json.Marshal(l, jsonx.V1()) if err != nil { return "", fmt.Errorf("encode manifest: %w", err) } diff --git a/services/gcpcloudbuild/pubsubtrigger.go b/services/gcpcloudbuild/pubsubtrigger.go index d7f49dc36a..d7959f72db 100644 --- a/services/gcpcloudbuild/pubsubtrigger.go +++ b/services/gcpcloudbuild/pubsubtrigger.go @@ -2,11 +2,12 @@ package gcpcloudbuild import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "time" "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -65,5 +66,5 @@ func pubsubPayload( "publishTime": published.UTC().Format(time.RFC3339Nano), }, "subscription": subscription, - }) + }, jsonx.V1()) } diff --git a/services/gcpcloudtasks/helpers_test.go b/services/gcpcloudtasks/helpers_test.go index 0b69aabd85..47c1299021 100644 --- a/services/gcpcloudtasks/helpers_test.go +++ b/services/gcpcloudtasks/helpers_test.go @@ -3,7 +3,7 @@ package gcpcloudtasks_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -23,6 +23,7 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpcloudtasks" ) @@ -201,7 +202,7 @@ func decodeJWT(t *testing.T, token string) map[string]any { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) return claims } diff --git a/services/gcpcloudtasks/persistence.go b/services/gcpcloudtasks/persistence.go index 2d1123f88e..c171328803 100644 --- a/services/gcpcloudtasks/persistence.go +++ b/services/gcpcloudtasks/persistence.go @@ -2,7 +2,7 @@ package gcpcloudtasks import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -20,22 +20,22 @@ import ( const snapshotVersion = 1 type queueSnap struct { - Tasks map[string]json.RawMessage `json:"tasks,omitempty"` - Queue json.RawMessage `json:"queue"` + Tasks map[string]jsontext.Value `json:"tasks,omitempty"` + Queue jsontext.Value `json:"queue"` } type backendSnapshot struct { - Queues map[string]queueSnap `json:"queues"` - Tombstones map[string]time.Time `json:"tombstones"` - Policies map[string]json.RawMessage `json:"policies"` - Cmek map[string]json.RawMessage `json:"cmek"` - Ops map[string]json.RawMessage `json:"operations,omitempty"` - EtagSeq uint64 `json:"etagSeq"` - TaskSeq uint64 `json:"taskSeq"` - Version int `json:"version"` + Queues map[string]queueSnap `json:"queues"` + Tombstones map[string]time.Time `json:"tombstones"` + Policies map[string]jsontext.Value `json:"policies"` + Cmek map[string]jsontext.Value `json:"cmek"` + Ops map[string]jsontext.Value `json:"operations,omitempty"` + EtagSeq uint64 `json:"etagSeq"` + TaskSeq uint64 `json:"taskSeq"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -44,7 +44,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } @@ -59,12 +59,12 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { TaskSeq: b.taskSeq, Queues: make(map[string]queueSnap, len(b.queues)), Tombstones: make(map[string]time.Time, len(b.tombstones)), - Policies: make(map[string]json.RawMessage, len(b.policies)), - Cmek: make(map[string]json.RawMessage, len(b.cmek)), + Policies: make(map[string]jsontext.Value, len(b.policies)), + Cmek: make(map[string]jsontext.Value, len(b.cmek)), } for name, q := range b.queues { - qs := queueSnap{Queue: marshalPB(q.pb), Tasks: make(map[string]json.RawMessage, len(q.tasks))} + qs := queueSnap{Queue: marshalPB(q.pb), Tasks: make(map[string]jsontext.Value, len(q.tasks))} for tn, t := range q.tasks { qs.Tasks[tn] = marshalPB(t.pb) } diff --git a/services/gcpcompute/filter.go b/services/gcpcompute/filter.go index 79100c77d0..ecba84d2cd 100644 --- a/services/gcpcompute/filter.go +++ b/services/gcpcompute/filter.go @@ -1,11 +1,13 @@ package gcpcompute import ( - "encoding/json" + "encoding/json/v2" "regexp" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const quotePair = 2 @@ -325,13 +327,13 @@ func parseFilter(expr string) (filterNode, *APIError) { } func toDoc(item any) map[string]any { - data, err := json.Marshal(item) + data, err := json.Marshal(item, jsonx.V1()) if err != nil { return nil } var m map[string]any - _ = json.Unmarshal(data, &m) + _ = json.Unmarshal(data, &m, jsonx.V1()) return m } diff --git a/services/gcpcompute/handler.go b/services/gcpcompute/handler.go index 3af0e8daa2..9b21fbfb22 100644 --- a/services/gcpcompute/handler.go +++ b/services/gcpcompute/handler.go @@ -2,7 +2,7 @@ package gcpcompute import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" @@ -264,11 +265,11 @@ func decode[T any](rq *request) (*T, map[string]any, *APIError) { return v, raw, nil } - if err := json.Unmarshal(rq.body, v); err != nil { + if err := json.Unmarshal(rq.body, v, jsonx.V1()); err != nil { return nil, nil, errInvalid("Invalid JSON payload received. %v", err) } - if err := json.Unmarshal(rq.body, &raw); err != nil { + if err := json.Unmarshal(rq.body, &raw, jsonx.V1()); err != nil { return nil, nil, errInvalid("Invalid JSON payload received. %v", err) } diff --git a/services/gcpcompute/labels.go b/services/gcpcompute/labels.go index 1e4dab58ca..d8e7d5aa23 100644 --- a/services/gcpcompute/labels.go +++ b/services/gcpcompute/labels.go @@ -1,10 +1,12 @@ package gcpcompute import ( - "encoding/json" + "encoding/json/v2" "maps" "regexp" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -74,7 +76,7 @@ func labelFP(labels map[string]string) string { pairs[i] = [2]string{k, labels[k]} } - data, _ := json.Marshal(pairs) + data, _ := json.Marshal(pairs, jsonx.V1()) return fingerprint(string(data)) } diff --git a/services/gcpcompute/lb_neg_test.go b/services/gcpcompute/lb_neg_test.go index c9f5e27464..6267b871a5 100644 --- a/services/gcpcompute/lb_neg_test.go +++ b/services/gcpcompute/lb_neg_test.go @@ -1,7 +1,7 @@ package gcpcompute_test import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "testing" @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/api/iterator" "google.golang.org/protobuf/proto" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type globalAttach = computepb.GlobalNetworkEndpointGroupsAttachEndpointsRequest @@ -416,7 +418,7 @@ func TestNEGAsBackend(t *testing.T) { } `json:"items"` } - require.NoError(t, json.Unmarshal([]byte(body), &listed)) + require.NoError(t, json.Unmarshal([]byte(body), &listed, jsonx.V1())) require.Len(t, listed.Items, 1) require.Len(t, listed.Items[0].Healths, 1) assert.Equal(t, "HEALTHY", listed.Items[0].Healths[0].HealthState) diff --git a/services/gcpcompute/meta.go b/services/gcpcompute/meta.go index 229f954476..57029e4b95 100644 --- a/services/gcpcompute/meta.go +++ b/services/gcpcompute/meta.go @@ -5,8 +5,10 @@ import ( "crypto/sha256" "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -95,13 +97,13 @@ func clone[T any](v *T) *T { return nil } - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } out := new(T) - if err = json.Unmarshal(data, out); err != nil { + if err = json.Unmarshal(data, out, jsonx.V1()); err != nil { return v } @@ -127,13 +129,13 @@ func regionOfZone(zone string) string { } func fromDoc[T any](m map[string]any) (*T, error) { - data, err := json.Marshal(m) + data, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil, err } out := new(T) - if err = json.Unmarshal(data, out); err != nil { + if err = json.Unmarshal(data, out, jsonx.V1()); err != nil { return nil, err } diff --git a/services/gcpcompute/rest_test.go b/services/gcpcompute/rest_test.go index 566dea5e28..8aa9b5749e 100644 --- a/services/gcpcompute/rest_test.go +++ b/services/gcpcompute/rest_test.go @@ -1,7 +1,7 @@ package gcpcompute_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/api/iterator" "google.golang.org/protobuf/proto" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listDoc struct { @@ -29,7 +31,7 @@ func getJSON[T any](t *testing.T, e *env, path string, want int) T { require.Equal(t, want, status, body) var out T - require.NoError(t, json.Unmarshal([]byte(body), &out), body) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1()), body) return out } @@ -209,7 +211,7 @@ func TestListQueryErrors(t *testing.T) { } `json:"error"` } - require.NoError(t, json.Unmarshal([]byte(body), &doc)) + require.NoError(t, json.Unmarshal([]byte(body), &doc, jsonx.V1())) assert.Equal(t, http.StatusBadRequest, doc.Error.Code) require.NotEmpty(t, doc.Error.Errors) assert.Equal(t, "invalid", doc.Error.Errors[0].Reason) @@ -473,7 +475,7 @@ func TestErrorBodyShape(t *testing.T) { } `json:"error"` } - require.NoError(t, json.Unmarshal([]byte(body), &doc)) + require.NoError(t, json.Unmarshal([]byte(body), &doc, jsonx.V1())) assert.Equal(t, 404, doc.Error.Code) assert.Equal(t, "The resource 'projects/p/global/networks/ghost' was not found", doc.Error.Message) require.Len(t, doc.Error.Errors, 1) diff --git a/services/gcpcontainer/persistence.go b/services/gcpcontainer/persistence.go index d65acfa1d8..2bc0a871d5 100644 --- a/services/gcpcontainer/persistence.go +++ b/services/gcpcontainer/persistence.go @@ -2,7 +2,7 @@ package gcpcontainer import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -18,32 +18,32 @@ import ( const snapshotVersion = 1 type poolSnap struct { - PrevVersion string `json:"prevVersion"` - DeleteOp string `json:"deleteOp"` - Pool json.RawMessage `json:"pool"` - Size int32 `json:"size"` + PrevVersion string `json:"prevVersion"` + DeleteOp string `json:"deleteOp"` + Pool jsontext.Value `json:"pool"` + Size int32 `json:"size"` } type clusterSnap struct { - Rotation *rotationRec `json:"rotation,omitempty"` - Cluster json.RawMessage `json:"cluster"` - Project string `json:"project"` - Failure string `json:"failure"` - DeleteOp string `json:"deleteOp"` - Pools []poolSnap `json:"pools"` + Rotation *rotationRec `json:"rotation,omitempty"` + Cluster jsontext.Value `json:"cluster"` + Project string `json:"project"` + Failure string `json:"failure"` + DeleteOp string `json:"deleteOp"` + Pools []poolSnap `json:"pools"` } type opSnap struct { - EndAt time.Time `json:"endAt"` - Project string `json:"project"` - Location string `json:"location"` - Cluster string `json:"cluster"` - Pool string `json:"pool"` - Failure string `json:"failure"` - Op json.RawMessage `json:"op"` - Kind opKind `json:"kind"` - Manual bool `json:"manual"` - Finished bool `json:"finished"` + EndAt time.Time `json:"endAt"` + Project string `json:"project"` + Location string `json:"location"` + Cluster string `json:"cluster"` + Pool string `json:"pool"` + Failure string `json:"failure"` + Op jsontext.Value `json:"op"` + Kind opKind `json:"kind"` + Manual bool `json:"manual"` + Finished bool `json:"finished"` } type backendSnapshot struct { @@ -53,7 +53,7 @@ type backendSnapshot struct { Seq uint64 `json:"seq"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { raw, err := protojson.Marshal(m) if err != nil { return nil diff --git a/services/gcpcontainer/rest_test.go b/services/gcpcontainer/rest_test.go index ca4c1aa1b4..c9c5fbb218 100644 --- a/services/gcpcontainer/rest_test.go +++ b/services/gcpcontainer/rest_test.go @@ -3,7 +3,7 @@ package gcpcontainer_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -115,7 +116,7 @@ func (e *env) raw(t *testing.T, method, path string, body any) (int, map[string] var rdr io.Reader if body != nil { - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rdr = bytes.NewReader(raw) @@ -136,7 +137,7 @@ func (e *env) raw(t *testing.T, method, path string, body any) (int, map[string] require.NoError(t, err) if len(raw) > 0 { - require.NoError(t, json.Unmarshal(raw, &out), string(raw)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1()), string(raw)) } return resp.StatusCode, out diff --git a/services/gcpdatastore/persistence.go b/services/gcpdatastore/persistence.go index 093551b1af..2b6c07b43b 100644 --- a/services/gcpdatastore/persistence.go +++ b/services/gcpdatastore/persistence.go @@ -2,7 +2,7 @@ package gcpdatastore import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -18,20 +18,20 @@ import ( const snapshotVersion = 1 type entitySnap struct { - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` - Entity json.RawMessage `json:"entity"` - Version int64 `json:"version"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` + Entity jsontext.Value `json:"entity"` + Version int64 `json:"version"` } type backendSnapshot struct { - LastCommit time.Time `json:"lastCommit"` - Entities map[string]entitySnap `json:"entities"` - UsedIDs map[string][]int64 `json:"usedIds"` - Indexes map[string]json.RawMessage `json:"indexes"` - Operations map[string]json.RawMessage `json:"operations"` - NextIndex int64 `json:"nextIndex"` - Version int `json:"version"` + LastCommit time.Time `json:"lastCommit"` + Entities map[string]entitySnap `json:"entities"` + UsedIDs map[string][]int64 `json:"usedIds"` + Indexes map[string]jsontext.Value `json:"indexes"` + Operations map[string]jsontext.Value `json:"operations"` + NextIndex int64 `json:"nextIndex"` + Version int `json:"version"` } // Snapshot serialises the current state of every entity, reserved ids, indexes and operations. @@ -46,7 +46,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NextIndex: b.nextIndex, Entities: make(map[string]entitySnap, len(b.ents)), UsedIDs: make(map[string][]int64, len(b.used)), - Indexes: make(map[string]json.RawMessage, len(b.indexes)), + Indexes: make(map[string]jsontext.Value, len(b.indexes)), Operations: b.ops.Snapshot(), } diff --git a/services/gcpdns/handler.go b/services/gcpdns/handler.go index 885c5f6025..be0ef10350 100644 --- a/services/gcpdns/handler.go +++ b/services/gcpdns/handler.go @@ -2,7 +2,7 @@ package gcpdns import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( pkgdns "github.com/blackbirdworks/gopherstack/pkgs/dns" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" @@ -185,11 +186,11 @@ func decode[T any](c *echo.Context) (*T, map[string]any, error) { return v, raw, nil } - if err = json.Unmarshal(data, v); err != nil { + if err = json.Unmarshal(data, v, jsonx.V1()); err != nil { return nil, nil, errInvalid("Invalid JSON payload received. %v", err) } - if err = json.Unmarshal(data, &raw); err != nil { + if err = json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return nil, nil, errInvalid("Invalid JSON payload received. %v", err) } diff --git a/services/gcpdns/handler_test.go b/services/gcpdns/handler_test.go index 37543094fe..c612f2887f 100644 --- a/services/gcpdns/handler_test.go +++ b/services/gcpdns/handler_test.go @@ -1,7 +1,8 @@ package gcpdns_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "strings" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpdns" ) @@ -65,7 +67,7 @@ func TestWireErrorsAndRouting(t *testing.T) { } `json:"error"` } - require.NoError(t, json.Unmarshal(raw, &body), string(raw)) + require.NoError(t, json.Unmarshal(raw, &body, jsonx.V1()), string(raw)) assert.Equal(t, tt.status, body.Error.Code) assert.NotEmpty(t, body.Error.Message) require.Len(t, body.Error.Errors, 1) @@ -89,7 +91,7 @@ func TestWireShapes(t *testing.T) { var m map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &m, jsonx.V1())) return m } diff --git a/services/gcpdns/rrsets.go b/services/gcpdns/rrsets.go index 2e2b5209ad..c32c30fb1b 100644 --- a/services/gcpdns/rrsets.go +++ b/services/gcpdns/rrsets.go @@ -1,7 +1,7 @@ package gcpdns import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" @@ -10,6 +10,7 @@ import ( "github.com/miekg/dns" dnsapi "google.golang.org/api/dns/v1" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -52,8 +53,8 @@ func sameRRSet(a, b *dnsapi.ResourceRecordSet) bool { return false } - ar, _ := json.Marshal(a.RoutingPolicy) - br, _ := json.Marshal(b.RoutingPolicy) + ar, _ := json.Marshal(a.RoutingPolicy, jsonx.V1()) + br, _ := json.Marshal(b.RoutingPolicy, jsonx.V1()) return string(ar) == string(br) } diff --git a/services/gcpdns/store.go b/services/gcpdns/store.go index a42edd648f..9dbfce8f08 100644 --- a/services/gcpdns/store.go +++ b/services/gcpdns/store.go @@ -3,13 +3,14 @@ package gcpdns import ( "crypto/rand" "encoding/binary" - "encoding/json" + "encoding/json/v2" "strings" "time" "github.com/miekg/dns" dnsapi "google.golang.org/api/dns/v1" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -109,13 +110,13 @@ func clone[T any](v *T) *T { return nil } - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } out := new(T) - if err = json.Unmarshal(data, out); err != nil { + if err = json.Unmarshal(data, out, jsonx.V1()); err != nil { return v } @@ -154,25 +155,25 @@ func mergePatch(dst, patch map[string]any) { } func patched[T any](cur *T, patch map[string]any) (*T, error) { - data, err := json.Marshal(cur) + data, err := json.Marshal(cur, jsonx.V1()) if err != nil { return nil, errInvalid("Invalid JSON payload received.") } var m map[string]any - if err = json.Unmarshal(data, &m); err != nil { + if err = json.Unmarshal(data, &m, jsonx.V1()); err != nil { return nil, errInvalid("Invalid JSON payload received.") } mergePatch(m, patch) - data, err = json.Marshal(m) + data, err = json.Marshal(m, jsonx.V1()) if err != nil { return nil, errInvalid("Invalid JSON payload received.") } out := new(T) - if err = json.Unmarshal(data, out); err != nil { + if err = json.Unmarshal(data, out, jsonx.V1()); err != nil { return nil, errInvalid("Invalid JSON payload received: %v", err) } diff --git a/services/gcpeventarc/delivery.go b/services/gcpeventarc/delivery.go index 3e0c681290..2eea1a3e79 100644 --- a/services/gcpeventarc/delivery.go +++ b/services/gcpeventarc/delivery.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net" "net/http" @@ -18,6 +19,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/gcpdispatch" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -96,7 +98,11 @@ func (b *InMemoryBackend) servePush(w http.ResponseWriter, r *http.Request) { } var env pushedEnvelope - if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, maxPushBytes)).Decode(&env); err != nil { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(w, r.Body, maxPushBytes)), + &env, + jsonx.V1(), + ); err != nil { http.Error(w, "invalid push envelope: "+err.Error(), http.StatusBadRequest) return @@ -162,20 +168,20 @@ func (b *InMemoryBackend) deliverToWorkflow( } type structuredEvent struct { - SpecVersion string `json:"specversion"` - ID string `json:"id"` - Source string `json:"source"` - Type string `json:"type"` - DataContentType string `json:"datacontenttype"` - Subject string `json:"subject,omitempty"` - Time string `json:"time,omitempty"` - Data json.RawMessage `json:"data"` + SpecVersion string `json:"specversion"` + ID string `json:"id"` + Source string `json:"source"` + Type string `json:"type"` + DataContentType string `json:"datacontenttype"` + Subject string `json:"subject,omitempty"` + Time string `json:"time,omitempty"` + Data jsontext.Value `json:"data"` } func workflowArgument(ev cloudEvent) ([]byte, error) { - data := json.RawMessage(ev.body) - if !json.Valid(data) { - quoted, err := json.Marshal(string(ev.body)) + data := jsontext.Value(ev.body) + if !jsontext.Value(data).IsValid(jsonx.V1()) { + quoted, err := json.Marshal(string(ev.body), jsonx.V1()) if err != nil { return nil, err } @@ -186,12 +192,12 @@ func workflowArgument(ev cloudEvent) ([]byte, error) { return json.Marshal(structuredEvent{ SpecVersion: "1.0", ID: ev.id, Source: ev.source, Type: ev.typ, Subject: ev.subject, Time: ev.time, DataContentType: contentTypeJSON, Data: data, - }) + }, jsonx.V1()) } func buildEvent(t *eventarcpb.Trigger, env pushedEnvelope) (cloudEvent, bool) { if eventType(t.GetEventFilters()) == typePubsubPublished { - body, err := json.Marshal(pushedEnvelope{Subscription: env.Subscription, Message: env.Message}) + body, err := json.Marshal(pushedEnvelope{Subscription: env.Subscription, Message: env.Message}, jsonx.V1()) if err != nil { return cloudEvent{}, false } diff --git a/services/gcpeventarc/delivery_test.go b/services/gcpeventarc/delivery_test.go index 5e9ea1f2c4..ce9465c500 100644 --- a/services/gcpeventarc/delivery_test.go +++ b/services/gcpeventarc/delivery_test.go @@ -2,7 +2,7 @@ package gcpeventarc_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -14,6 +14,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/fieldmaskpb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPubsubDelivery(t *testing.T) { @@ -89,7 +91,7 @@ func TestPubsubDelivery(t *testing.T) { } `json:"message"` Subscription string `json:"subscription"` } - require.NoError(t, json.Unmarshal(got.body, &body)) + require.NoError(t, json.Unmarshal(got.body, &body, jsonx.V1())) raw, err := base64.StdEncoding.DecodeString(body.Message.Data) require.NoError(t, err) @@ -231,7 +233,7 @@ func TestStorageDelivery(t *testing.T) { assert.Equal(t, "application/json", got.header.Get("Content-Type")) var data map[string]any - require.NoError(t, json.Unmarshal(got.body, &data)) + require.NoError(t, json.Unmarshal(got.body, &data, jsonx.V1())) assert.Equal(t, "photos", data["bucket"]) assert.Equal(t, strings.TrimPrefix(tt.subject, "objects/"), data["name"]) }) diff --git a/services/gcpeventarc/persistence.go b/services/gcpeventarc/persistence.go index 245db08d77..3d34b43ba1 100644 --- a/services/gcpeventarc/persistence.go +++ b/services/gcpeventarc/persistence.go @@ -2,7 +2,7 @@ package gcpeventarc import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/eventarc/apiv1/eventarcpb" @@ -18,27 +18,27 @@ import ( const snapshotVersion = 1 type triggerSnap struct { - Trigger json.RawMessage `json:"trigger"` - Policy json.RawMessage `json:"policy,omitempty"` - OwnedTopic bool `json:"ownedTopic,omitempty"` + Trigger jsontext.Value `json:"trigger"` + Policy jsontext.Value `json:"policy,omitempty"` + OwnedTopic bool `json:"ownedTopic,omitempty"` } type channelSnap struct { - Channel json.RawMessage `json:"channel"` - Policy json.RawMessage `json:"policy,omitempty"` + Channel jsontext.Value `json:"channel"` + Policy jsontext.Value `json:"policy,omitempty"` } type backendSnapshot struct { - Triggers map[string]triggerSnap `json:"triggers"` - Channels map[string]channelSnap `json:"channels"` - Connections map[string]json.RawMessage `json:"connections"` - Configs map[string]json.RawMessage `json:"configs"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` - Seq uint64 `json:"seq"` + Triggers map[string]triggerSnap `json:"triggers"` + Channels map[string]channelSnap `json:"channels"` + Connections map[string]jsontext.Value `json:"connections"` + Configs map[string]jsontext.Value `json:"configs"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` + Seq uint64 `json:"seq"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { if m == nil || !m.ProtoReflect().IsValid() { return nil } @@ -55,7 +55,7 @@ func unmarshalPB(raw []byte, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } -func restorePolicy(raw json.RawMessage) (*iampb.Policy, error) { +func restorePolicy(raw jsontext.Value) (*iampb.Policy, error) { if len(raw) == 0 { return nil, nil //nolint:nilnil // no policy stored } @@ -77,8 +77,8 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Version: snapshotVersion, Seq: b.seq, Triggers: make(map[string]triggerSnap, len(b.triggers)), Channels: make(map[string]channelSnap, len(b.channels)), - Connections: make(map[string]json.RawMessage, len(b.conns)), - Configs: make(map[string]json.RawMessage, len(b.configs)), + Connections: make(map[string]jsontext.Value, len(b.conns)), + Configs: make(map[string]jsontext.Value, len(b.configs)), Operations: b.ops.Snapshot(), } diff --git a/services/gcpeventarc/workflow_delivery_test.go b/services/gcpeventarc/workflow_delivery_test.go index d32e207427..a194103177 100644 --- a/services/gcpeventarc/workflow_delivery_test.go +++ b/services/gcpeventarc/workflow_delivery_test.go @@ -2,7 +2,7 @@ package gcpeventarc_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "testing" "cloud.google.com/go/eventarc/apiv1/eventarcpb" @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/protobuf/types/known/fieldmaskpb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const eventWorkflow = ` @@ -94,7 +96,7 @@ func TestPubsubEventStartsWorkflowExecution(t *testing.T) { require.Equal(t, executionspb.Execution_SUCCEEDED, execs[0].GetState(), execs[0].GetError().GetPayload()) var arg map[string]any - require.NoError(t, json.Unmarshal([]byte(execs[0].GetArgument()), &arg)) + require.NoError(t, json.Unmarshal([]byte(execs[0].GetArgument()), &arg, jsonx.V1())) assert.Equal(t, "1.0", arg["specversion"]) assert.Equal(t, "google.cloud.pubsub.topic.v1.messagePublished", arg["type"]) @@ -111,7 +113,7 @@ func TestPubsubEventStartsWorkflowExecution(t *testing.T) { Subscription string `json:"subscription"` } `json:"data"` } - require.NoError(t, json.Unmarshal([]byte(execs[0].GetResult()), &res)) + require.NoError(t, json.Unmarshal([]byte(execs[0].GetResult()), &res, jsonx.V1())) assert.Equal(t, "1.0", res.Specversion) assert.Equal(t, "//pubsub.googleapis.com/"+topic, res.Source) @@ -148,7 +150,7 @@ func TestStorageEventStartsWorkflowExecution(t *testing.T) { Name string `json:"name"` } `json:"data"` } - require.NoError(t, json.Unmarshal([]byte(execs[0].GetResult()), &res)) + require.NoError(t, json.Unmarshal([]byte(execs[0].GetResult()), &res, jsonx.V1())) assert.Equal(t, "google.cloud.storage.object.v1.finalized", res.Type) assert.Equal(t, "events-bkt", res.Data.Bucket) assert.Equal(t, "dir/a.txt", res.Data.Name) diff --git a/services/gcpfirestore/persistence.go b/services/gcpfirestore/persistence.go index 9604e8a4a9..1609f61c9f 100644 --- a/services/gcpfirestore/persistence.go +++ b/services/gcpfirestore/persistence.go @@ -2,7 +2,7 @@ package gcpfirestore import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -17,9 +17,9 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - LastCommit time.Time `json:"lastCommit"` - Docs map[string]json.RawMessage `json:"docs"` - Version int `json:"version"` + LastCommit time.Time `json:"lastCommit"` + Docs map[string]jsontext.Value `json:"docs"` + Version int `json:"version"` } // Snapshot serialises the current state of every document; version history and transactions are not persisted. @@ -30,7 +30,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { snap := backendSnapshot{ Version: snapshotVersion, LastCommit: b.lastCommit, - Docs: make(map[string]json.RawMessage, len(b.docs)), + Docs: make(map[string]jsontext.Value, len(b.docs)), } for name, rec := range b.docs { diff --git a/services/gcpfunctions/docker_test.go b/services/gcpfunctions/docker_test.go index ec796726d6..a04e097978 100644 --- a/services/gcpfunctions/docker_test.go +++ b/services/gcpfunctions/docker_test.go @@ -4,7 +4,7 @@ import ( "context" "crypto/rand" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" "log/slog" "net/http" "os" @@ -109,7 +109,7 @@ func TestDocker_StorageTriggeredFunction(t *testing.T) { } gcs := gcpstorage.NewInMemoryBackend() - _, err = gcs.CreateBucket("test-project", gcpstorage.Patch{"name": json.RawMessage(`"inbox"`)}) + _, err = gcs.CreateBucket("test-project", gcpstorage.Patch{"name": jsontext.Value(`"inbox"`)}) require.NoError(t, err) e := newEnv(t, false) diff --git a/services/gcpfunctions/fake_runtime_test.go b/services/gcpfunctions/fake_runtime_test.go index a103f6fc09..be4924b62b 100644 --- a/services/gcpfunctions/fake_runtime_test.go +++ b/services/gcpfunctions/fake_runtime_test.go @@ -2,7 +2,8 @@ package gcpfunctions_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type received struct { @@ -118,7 +120,7 @@ func (f *fakeRuntime) CreateAndStart(_ context.Context, spec container.Spec) (st } w.WriteHeader(int(f.reply.Load())) - _ = json.NewEncoder(w).Encode(rec) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), rec) })} go f.serve(c, l, addr) diff --git a/services/gcpfunctions/helpers_test.go b/services/gcpfunctions/helpers_test.go index d733c2e9e1..d3d2de1596 100644 --- a/services/gcpfunctions/helpers_test.go +++ b/services/gcpfunctions/helpers_test.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -21,6 +21,7 @@ import ( "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/status" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpfunctions" ) @@ -222,7 +223,7 @@ func decode(t *testing.T, body string) received { var r received - require.NoError(t, json.Unmarshal([]byte(body), &r)) + require.NoError(t, json.Unmarshal([]byte(body), &r, jsonx.V1())) return r } diff --git a/services/gcpfunctions/ingress.go b/services/gcpfunctions/ingress.go index 2aea6a1ad2..324e7681e2 100644 --- a/services/gcpfunctions/ingress.go +++ b/services/gcpfunctions/ingress.go @@ -2,7 +2,8 @@ package gcpfunctions import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net" @@ -17,6 +18,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/gcpevents" "github.com/blackbirdworks/gopherstack/pkgs/gcpscale" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -303,7 +305,11 @@ func (b *InMemoryBackend) serveEvent(w http.ResponseWriter, r *http.Request) { } var env pushEnvelope - if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, maxEventBytes)).Decode(&env); err != nil { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(w, r.Body, maxEventBytes)), + &env, + jsonx.V1(), + ); err != nil { http.Error(w, "invalid push envelope: "+err.Error(), http.StatusBadRequest) return @@ -315,7 +321,7 @@ func (b *InMemoryBackend) serveEvent(w http.ResponseWriter, r *http.Request) { return } - body, err := json.Marshal(env) + body, err := json.Marshal(env, jsonx.V1()) if err != nil { http.Error(w, "encode event: "+err.Error(), http.StatusInternalServerError) diff --git a/services/gcpfunctions/persistence.go b/services/gcpfunctions/persistence.go index bdb3c5eff6..5241b6f699 100644 --- a/services/gcpfunctions/persistence.go +++ b/services/gcpfunctions/persistence.go @@ -2,7 +2,7 @@ package gcpfunctions import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/functions/apiv2/functionspb" @@ -18,11 +18,11 @@ import ( const snapshotVersion = 1 type fnSnap struct { - Function json.RawMessage `json:"function"` - Failure string `json:"failure"` - SubName string `json:"subName"` - Zip []byte `json:"zip"` - RevSeq int `json:"revSeq"` + Function jsontext.Value `json:"function"` + Failure string `json:"failure"` + SubName string `json:"subName"` + Zip []byte `json:"zip"` + RevSeq int `json:"revSeq"` } type uploadSnap struct { @@ -31,10 +31,10 @@ type uploadSnap struct { } type backendSnapshot struct { - Functions map[string]fnSnap `json:"functions"` - Uploads map[string]uploadSnap `json:"uploads"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` + Functions map[string]fnSnap `json:"functions"` + Uploads map[string]uploadSnap `json:"uploads"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` } // Snapshot serialises all functions and sources; containers are not part of it. diff --git a/services/gcpiam/keymat.go b/services/gcpiam/keymat.go index 9f65dac486..155e3a52b2 100644 --- a/services/gcpiam/keymat.go +++ b/services/gcpiam/keymat.go @@ -6,7 +6,8 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "math/big" "net/url" @@ -14,6 +15,8 @@ import ( "cloud.google.com/go/iam/admin/apiv1/adminpb" pkcs12 "software.sslmate.com/src/go-pkcs12" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -118,7 +121,7 @@ func (m *material) credentials(acct *adminpb.ServiceAccount, keyID string) ([]by return nil, errInternal(err) } - out, err := json.MarshalIndent(credentialsFile{ + out, err := json.Marshal(credentialsFile{ Type: credentialsType, ProjectID: acct.GetProjectId(), PrivateKeyID: keyID, @@ -130,7 +133,7 @@ func (m *material) credentials(acct *adminpb.ServiceAccount, keyID string) ([]by AuthProviderX509CertURL: authCertsURL, ClientX509CertURL: clientCertPrefix + url.PathEscape(acct.GetEmail()), UniverseDomain: universeDomain, - }, "", " ") + }, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return nil, errInternal(err) } diff --git a/services/gcpiam/keys_test.go b/services/gcpiam/keys_test.go index d1577c53c1..992af2dfb7 100644 --- a/services/gcpiam/keys_test.go +++ b/services/gcpiam/keys_test.go @@ -6,7 +6,7 @@ import ( "crypto/rsa" "crypto/sha256" "crypto/x509" - "encoding/json" + "encoding/json/v2" "encoding/pem" "math/big" "testing" @@ -17,6 +17,8 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" pkcs12 "software.sslmate.com/src/go-pkcs12" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type keyFile struct { @@ -39,7 +41,7 @@ func createKey(t *testing.T, e *env, sa *adminpb.ServiceAccount) (*adminpb.Servi require.NoError(t, err) var kf keyFile - require.NoError(t, json.Unmarshal(key.GetPrivateKeyData(), &kf)) + require.NoError(t, json.Unmarshal(key.GetPrivateKeyData(), &kf, jsonx.V1())) return key, kf } @@ -123,7 +125,11 @@ func TestKeyAlgorithmsAndFormats(t *testing.T) { assert.Equal(t, adminpb.ServiceAccountKeyAlgorithm_KEY_ALG_RSA_2048, small.GetKeyAlgorithm()) var kf keyFile - require.NoError(t, json.Unmarshal(small.GetPrivateKeyData(), &kf), "default type is the credentials file") + require.NoError( + t, + json.Unmarshal(small.GetPrivateKeyData(), &kf, jsonx.V1()), + "default type is the credentials file", + ) assert.Equal(t, 2048, parsePrivate(t, kf.PrivateKey).N.BitLen()) p12, err := e.client.CreateServiceAccountKey(t.Context(), &adminpb.CreateServiceAccountKeyRequest{ diff --git a/services/gcpiam/persistence.go b/services/gcpiam/persistence.go index ac740127b7..fd93423ac8 100644 --- a/services/gcpiam/persistence.go +++ b/services/gcpiam/persistence.go @@ -2,7 +2,7 @@ package gcpiam import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -19,23 +19,23 @@ import ( const snapshotVersion = 1 type keySnap struct { - Key json.RawMessage `json:"key"` - Cert []byte `json:"cert,omitempty"` - Public []byte `json:"public,omitempty"` - Private []byte `json:"private,omitempty"` + Key jsontext.Value `json:"key"` + Cert []byte `json:"cert,omitempty"` + Public []byte `json:"public,omitempty"` + Private []byte `json:"private,omitempty"` } type accountSnap struct { Keys map[string]keySnap `json:"keys,omitempty"` System *keySnap `json:"system,omitempty"` DeletedAt time.Time `json:"deletedAt"` - Account json.RawMessage `json:"account"` - Policy json.RawMessage `json:"policy,omitempty"` + Account jsontext.Value `json:"account"` + Policy jsontext.Value `json:"policy,omitempty"` } type roleSnap struct { - DeletedAt time.Time `json:"deletedAt"` - Role json.RawMessage `json:"role"` + DeletedAt time.Time `json:"deletedAt"` + Role jsontext.Value `json:"role"` } type backendSnapshot struct { @@ -45,7 +45,7 @@ type backendSnapshot struct { Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -54,7 +54,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } diff --git a/services/gcpiam/sign.go b/services/gcpiam/sign.go index 803846aaaa..a9c38d98c3 100644 --- a/services/gcpiam/sign.go +++ b/services/gcpiam/sign.go @@ -7,12 +7,15 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "time" "cloud.google.com/go/iam/admin/apiv1/adminpb" "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -160,7 +163,7 @@ func (b *InMemoryBackend) SignJwt(name, payload string) (string, string, error) return "", "", err } - header, err := json.Marshal(map[string]string{"alg": "RS256", "typ": "JWT", "kid": keyID}) + header, err := json.Marshal(map[string]string{"alg": "RS256", "typ": "JWT", "kid": keyID}, jsonx.V1()) if err != nil { return "", "", errInternal(err) } @@ -179,17 +182,16 @@ func (b *InMemoryBackend) SignJwt(name, payload string) (string, string, error) func (b *InMemoryBackend) jwtClaims(payload string) ([]byte, error) { var claims map[string]any - dec := json.NewDecoder(strings.NewReader(payload)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(payload)) - if err := dec.Decode(&claims); err != nil || claims == nil { + if err := json.UnmarshalDecode(dec, &claims, jsonx.V1(), jsonx.UseNumber()); err != nil || claims == nil { return nil, errInvalid("The JWT payload must be a serialized JSON object.") } now := b.now() if raw, ok := claims["exp"]; ok { - num, isNum := raw.(json.Number) + num, isNum := raw.(jsonx.Number) exp, err := num.Int64() if !isNum || err != nil { @@ -203,7 +205,7 @@ func (b *InMemoryBackend) jwtClaims(payload string) ([]byte, error) { claims["exp"] = now.Add(jwtDefaultTTL).Unix() } - out, err := json.Marshal(claims) + out, err := json.Marshal(claims, jsonx.V1()) if err != nil { return nil, errInternal(err) } diff --git a/services/gcpiam/sign_test.go b/services/gcpiam/sign_test.go index fdcc93cdf7..a485f5b042 100644 --- a/services/gcpiam/sign_test.go +++ b/services/gcpiam/sign_test.go @@ -2,7 +2,7 @@ package gcpiam_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func systemPublicKey(t *testing.T, e *env, sa *adminpb.ServiceAccount, keyID string) []byte { @@ -61,14 +63,14 @@ func TestSignJwt(t *testing.T) { require.NoError(t, err) var header map[string]string - require.NoError(t, json.Unmarshal(hdr, &header)) + require.NoError(t, json.Unmarshal(hdr, &header, jsonx.V1())) assert.Equal(t, map[string]string{"alg": "RS256", "typ": "JWT", "kid": keyID}, header) body, err := enc.DecodeString(parts[1]) require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(body, &claims)) + require.NoError(t, json.Unmarshal(body, &claims, jsonx.V1())) assert.Equal(t, "someone", claims["sub"]) assert.InDelta(t, float64(now+3600), claims["exp"], 0, "exp defaults to one hour") @@ -137,7 +139,7 @@ func (e *env) signJwt(t *testing.T, name, payload string) (string, string, error } func itoa(n int64) string { - b, _ := json.Marshal(n) + b, _ := json.Marshal(n, jsonx.V1()) return string(b) } diff --git a/services/gcpidentitytoolkit/handler.go b/services/gcpidentitytoolkit/handler.go index 5f46d821da..75ff9a0c93 100644 --- a/services/gcpidentitytoolkit/handler.go +++ b/services/gcpidentitytoolkit/handler.go @@ -4,7 +4,7 @@ import ( "context" "crypto/rsa" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -21,6 +21,7 @@ import ( idtkv2 "google.golang.org/api/identitytoolkit/v2" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -159,11 +160,11 @@ func readJSON[T any](c *echo.Context) (*T, map[string]any, error) { return v, raw, nil } - if err = json.Unmarshal(data, v); err != nil { + if err = json.Unmarshal(data, v, jsonx.V1()); err != nil { return nil, nil, errInvalidArg("Invalid JSON payload received. %v", err) } - if err = json.Unmarshal(data, &raw); err != nil { + if err = json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return nil, nil, errInvalidArg("Invalid JSON payload received. %v", err) } diff --git a/services/gcpidentitytoolkit/helpers_test.go b/services/gcpidentitytoolkit/helpers_test.go index a15f4771e1..66619c080e 100644 --- a/services/gcpidentitytoolkit/helpers_test.go +++ b/services/gcpidentitytoolkit/helpers_test.go @@ -3,7 +3,8 @@ package gcpidentitytoolkit_test import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpidentitytoolkit" ) @@ -106,7 +108,7 @@ func (e *env) do(t *testing.T, method, path, auth string, body any) result { var rdr *bytes.Reader if body != nil { - data, err := json.Marshal(body) + data, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rdr = bytes.NewReader(data) @@ -129,7 +131,7 @@ func (e *env) do(t *testing.T, method, path, auth string, body any) result { defer resp.Body.Close() out := result{status: resp.StatusCode} - _ = json.NewDecoder(resp.Body).Decode(&out.body) + _ = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out.body, jsonx.V1()) return out } diff --git a/services/gcpidentitytoolkit/store.go b/services/gcpidentitytoolkit/store.go index 8a290cc0f5..b9899279d3 100644 --- a/services/gcpidentitytoolkit/store.go +++ b/services/gcpidentitytoolkit/store.go @@ -7,7 +7,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/hex" - "encoding/json" + "encoding/json/v2" "encoding/pem" "math/big" "sort" @@ -16,6 +16,7 @@ import ( idtkv2 "google.golang.org/api/identitytoolkit/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -365,13 +366,13 @@ func cloneJSON[T any](v *T) *T { return nil } - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } out := new(T) - if json.Unmarshal(data, out) != nil { + if json.Unmarshal(data, out, jsonx.V1()) != nil { return v } @@ -401,25 +402,25 @@ func mergePatch(dst, patch map[string]any) { } func patched[T any](cur *T, patch map[string]any) (*T, error) { - data, err := json.Marshal(cur) + data, err := json.Marshal(cur, jsonx.V1()) if err != nil { return nil, errInvalidArg("Invalid JSON payload received.") } var m map[string]any - if err = json.Unmarshal(data, &m); err != nil { + if err = json.Unmarshal(data, &m, jsonx.V1()); err != nil { return nil, errInvalidArg("Invalid JSON payload received.") } mergePatch(m, patch) - data, err = json.Marshal(m) + data, err = json.Marshal(m, jsonx.V1()) if err != nil { return nil, errInvalidArg("Invalid JSON payload received.") } out := new(T) - if err = json.Unmarshal(data, out); err != nil { + if err = json.Unmarshal(data, out, jsonx.V1()); err != nil { return nil, errInvalidArg("Invalid JSON payload received: %v", err) } diff --git a/services/gcpidentitytoolkit/tokens.go b/services/gcpidentitytoolkit/tokens.go index ee7ff38336..da1efa44bf 100644 --- a/services/gcpidentitytoolkit/tokens.go +++ b/services/gcpidentitytoolkit/tokens.go @@ -5,13 +5,15 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "maps" "strings" "time" "github.com/golang-jwt/jwt/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -48,7 +50,7 @@ func (b *InMemoryBackend) signRefreshLocked(p refreshPayload) (string, error) { return "", err } - body, err := json.Marshal(p) + body, err := json.Marshal(p, jsonx.V1()) if err != nil { return "", err //nolint:wrapcheck // unreachable } @@ -84,7 +86,7 @@ func (b *InMemoryBackend) parseRefreshLocked(tok string) (*refreshPayload, bool) } var p refreshPayload - if json.Unmarshal(body, &p) != nil { + if json.Unmarshal(body, &p, jsonx.V1()) != nil { return nil, false } @@ -126,7 +128,7 @@ func (b *InMemoryBackend) tokenClaims( if u.CustomAttrs != "" { var custom map[string]any - if json.Unmarshal([]byte(u.CustomAttrs), &custom) == nil { + if json.Unmarshal([]byte(u.CustomAttrs), &custom, jsonx.V1()) == nil { maps.Copy(claims, custom) } } diff --git a/services/gcpidentitytoolkit/users.go b/services/gcpidentitytoolkit/users.go index f80ddb0c4b..8d330c2f02 100644 --- a/services/gcpidentitytoolkit/users.go +++ b/services/gcpidentitytoolkit/users.go @@ -2,7 +2,7 @@ package gcpidentitytoolkit import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/mail" "regexp" "strconv" @@ -12,6 +12,7 @@ import ( idtkv2 "google.golang.org/api/identitytoolkit/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -286,7 +287,7 @@ func parseClaims(raw string) (string, error) { } var m map[string]any - if err := json.Unmarshal([]byte(raw), &m); err != nil { + if err := json.Unmarshal([]byte(raw), &m, jsonx.V1()); err != nil { return "", idtk("INVALID_CLAIMS") } diff --git a/services/gcpidentitytoolkit/wire.go b/services/gcpidentitytoolkit/wire.go index f7d20370bc..7c553ed636 100644 --- a/services/gcpidentitytoolkit/wire.go +++ b/services/gcpidentitytoolkit/wire.go @@ -2,8 +2,10 @@ package gcpidentitytoolkit import ( "bytes" - "encoding/json" + "encoding/json/v2" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // flexInt decodes a JSON number or a quoted number, the two forms Google clients send for int64 fields. @@ -84,7 +86,7 @@ func (u userWire) MarshalJSON() ([]byte, error) { aux.ValidSince = strconv.FormatInt(int64(u.ValidSince), 10) } - return json.Marshal(aux) + return json.Marshal(aux, jsonx.V1()) } // authRequest is the union of the request fields the account operations read. @@ -128,14 +130,14 @@ type flexStrings []string func (f *flexStrings) UnmarshalJSON(data []byte) error { var one string - if json.Unmarshal(data, &one) == nil { + if json.Unmarshal(data, &one, jsonx.V1()) == nil { *f = flexStrings{one} return nil } var many []string - if err := json.Unmarshal(data, &many); err != nil { + if err := json.Unmarshal(data, &many, jsonx.V1()); err != nil { return err //nolint:wrapcheck // surfaced as a JSON decode error } diff --git a/services/gcpkms/persistence.go b/services/gcpkms/persistence.go index dd23f7ede1..b756ce28c3 100644 --- a/services/gcpkms/persistence.go +++ b/services/gcpkms/persistence.go @@ -2,7 +2,7 @@ package gcpkms import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/iam/apiv1/iampb" @@ -19,34 +19,34 @@ const snapshotVersion = 1 // Key material is stored unencrypted in the snapshot: this is a local emulator, not a secure key store. type versionSnap struct { - Version json.RawMessage `json:"version"` - Material []byte `json:"material,omitempty"` - Deleted bool `json:"deleted,omitempty"` + Version jsontext.Value `json:"version"` + Material []byte `json:"material,omitempty"` + Deleted bool `json:"deleted,omitempty"` } type keySnap struct { - Key json.RawMessage `json:"key"` - Versions []versionSnap `json:"versions,omitempty"` - Primary int64 `json:"primary"` + Key jsontext.Value `json:"key"` + Versions []versionSnap `json:"versions,omitempty"` + Primary int64 `json:"primary"` } type jobSnap struct { - Job json.RawMessage `json:"job"` - Private []byte `json:"private,omitempty"` + Job jsontext.Value `json:"job"` + Private []byte `json:"private,omitempty"` } type backendSnapshot struct { - Rings map[string]json.RawMessage `json:"rings"` - Keys map[string]keySnap `json:"keys"` - Jobs map[string]jobSnap `json:"jobs"` - Retired map[string]json.RawMessage `json:"retired,omitempty"` - Ops map[string]json.RawMessage `json:"operations,omitempty"` - Policies map[string]json.RawMessage `json:"policies"` - EtagSeq uint64 `json:"etagSeq"` - Version int `json:"version"` + Rings map[string]jsontext.Value `json:"rings"` + Keys map[string]keySnap `json:"keys"` + Jobs map[string]jobSnap `json:"jobs"` + Retired map[string]jsontext.Value `json:"retired,omitempty"` + Ops map[string]jsontext.Value `json:"operations,omitempty"` + Policies map[string]jsontext.Value `json:"policies"` + EtagSeq uint64 `json:"etagSeq"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -55,7 +55,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } @@ -67,11 +67,11 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { snap := backendSnapshot{ Version: snapshotVersion, EtagSeq: b.etagSeq, - Rings: make(map[string]json.RawMessage, len(b.rings)), + Rings: make(map[string]jsontext.Value, len(b.rings)), Keys: make(map[string]keySnap, len(b.keys)), Jobs: make(map[string]jobSnap, len(b.jobs)), - Retired: make(map[string]json.RawMessage, len(b.retired)), - Policies: make(map[string]json.RawMessage, len(b.policies)), + Retired: make(map[string]jsontext.Value, len(b.retired)), + Policies: make(map[string]jsontext.Value, len(b.policies)), } for name, r := range b.rings { diff --git a/services/gcplogging/export_bq.go b/services/gcplogging/export_bq.go index 0998eb4867..a417ec3a09 100644 --- a/services/gcplogging/export_bq.go +++ b/services/gcplogging/export_bq.go @@ -1,12 +1,14 @@ package gcplogging import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" "cloud.google.com/go/logging/apiv2/loggingpb" "google.golang.org/protobuf/encoding/protojson" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func bqField(name, typ string) map[string]any { @@ -31,7 +33,7 @@ func bqRow(e *loggingpb.LogEntry) (map[string]any, error) { } doc := map[string]any{} - if err = json.Unmarshal(raw, &doc); err != nil { + if err = json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("decode entry: %w", err) } @@ -46,7 +48,7 @@ func bqRow(e *loggingpb.LogEntry) (map[string]any, error) { } if f["type"] == "JSON" { - enc, _ := json.Marshal(v) + enc, _ := json.Marshal(v, jsonx.V1()) v = string(enc) } diff --git a/services/gcplogging/filter_eval.go b/services/gcplogging/filter_eval.go index 43aa799498..72bb834a8e 100644 --- a/services/gcplogging/filter_eval.go +++ b/services/gcplogging/filter_eval.go @@ -1,7 +1,7 @@ package gcplogging import ( - "encoding/json" + "encoding/json/v2" "hash/fnv" "math" "net/url" @@ -13,6 +13,8 @@ import ( ltype "google.golang.org/genproto/googleapis/logging/type" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // entryDoc lazily renders a log entry as JSON-shaped data for filter evaluation. @@ -42,7 +44,7 @@ func (d *entryDoc) doc() map[string]any { raw, _ = protojson.Marshal(stripped) } - _ = json.Unmarshal(raw, &d.m) + _ = json.Unmarshal(raw, &d.m, jsonx.V1()) return d.m } @@ -199,7 +201,7 @@ func scalarString(v any) string { return "" } - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return string(b) } diff --git a/services/gcplogging/persistence.go b/services/gcplogging/persistence.go index e6f4ca289e..ecadec7139 100644 --- a/services/gcplogging/persistence.go +++ b/services/gcplogging/persistence.go @@ -2,7 +2,7 @@ package gcplogging import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "time" @@ -21,9 +21,9 @@ var errBadSnapshot = errors.New("gcplogging: corrupt snapshot") const snapshotVersion = 1 type bucketSnap struct { - DeleteRequested time.Time `json:"deleteRequested"` - Bucket json.RawMessage `json:"bucket"` - Entries []int `json:"entries,omitempty"` + DeleteRequested time.Time `json:"deleteRequested"` + Bucket jsontext.Value `json:"bucket"` + Entries []int `json:"entries,omitempty"` } type seriesSnap struct { @@ -36,26 +36,26 @@ type seriesSnap struct { } type metricSnap struct { - Metric json.RawMessage `json:"metric"` - Series []seriesSnap `json:"series,omitempty"` + Metric jsontext.Value `json:"metric"` + Series []seriesSnap `json:"series,omitempty"` } type backendSnapshot struct { - Buckets map[string]bucketSnap `json:"buckets"` - Views map[string]json.RawMessage `json:"views"` - Sinks map[string]json.RawMessage `json:"sinks"` - Exclusions map[string]json.RawMessage `json:"exclusions"` - Metrics map[string]metricSnap `json:"metrics"` - Settings map[string]json.RawMessage `json:"settings"` - Cmek map[string]json.RawMessage `json:"cmek"` - Ops map[string]json.RawMessage `json:"ops"` - Entries []json.RawMessage `json:"entries"` - Seeded []string `json:"seeded"` - Seq uint64 `json:"seq"` - Version int `json:"version"` + Buckets map[string]bucketSnap `json:"buckets"` + Views map[string]jsontext.Value `json:"views"` + Sinks map[string]jsontext.Value `json:"sinks"` + Exclusions map[string]jsontext.Value `json:"exclusions"` + Metrics map[string]metricSnap `json:"metrics"` + Settings map[string]jsontext.Value `json:"settings"` + Cmek map[string]jsontext.Value `json:"cmek"` + Ops map[string]jsontext.Value `json:"ops"` + Entries []jsontext.Value `json:"entries"` + Seeded []string `json:"seeded"` + Seq uint64 `json:"seq"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -64,12 +64,12 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } -func snapMap[T proto.Message](in map[string]T) map[string]json.RawMessage { - out := make(map[string]json.RawMessage, len(in)) +func snapMap[T proto.Message](in map[string]T) map[string]jsontext.Value { + out := make(map[string]jsontext.Value, len(in)) for k, v := range in { out[k] = marshalPB(v) } @@ -136,7 +136,7 @@ func snapMetric(rec *metricRec) metricSnap { return ms } -func restoreMap[T proto.Message](raw map[string]json.RawMessage, newT func() T) (map[string]T, error) { +func restoreMap[T proto.Message](raw map[string]jsontext.Value, newT func() T) (map[string]T, error) { out := make(map[string]T, len(raw)) for k, r := range raw { @@ -235,7 +235,7 @@ func (b *InMemoryBackend) load(snap *backendSnapshot) error { return b.loadMetrics(snap.Metrics) } -func decodeEntries(raw []json.RawMessage) ([]*loggingpb.LogEntry, error) { +func decodeEntries(raw []jsontext.Value) ([]*loggingpb.LogEntry, error) { out := make([]*loggingpb.LogEntry, len(raw)) for i, r := range raw { diff --git a/services/gcpmonitoring/alerts_test.go b/services/gcpmonitoring/alerts_test.go index cca9d3d8c2..b04e2746b3 100644 --- a/services/gcpmonitoring/alerts_test.go +++ b/services/gcpmonitoring/alerts_test.go @@ -1,7 +1,7 @@ package gcpmonitoring_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" @@ -11,6 +11,8 @@ import ( "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/fieldmaskpb" "google.golang.org/protobuf/types/known/wrapperspb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const alertTopic = "projects/" + testProject + "/topics/alerts" @@ -90,7 +92,7 @@ func decode(t *testing.T, msg published) payload { t.Helper() var p payload - require.NoError(t, json.Unmarshal([]byte(msg.data), &p)) + require.NoError(t, json.Unmarshal([]byte(msg.data), &p, jsonx.V1())) return p } diff --git a/services/gcpmonitoring/helpers_test.go b/services/gcpmonitoring/helpers_test.go index a901703408..3e1859f32c 100644 --- a/services/gcpmonitoring/helpers_test.go +++ b/services/gcpmonitoring/helpers_test.go @@ -2,7 +2,7 @@ package gcpmonitoring_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync" "sync/atomic" @@ -22,6 +22,7 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpmonitoring" ) @@ -265,7 +266,7 @@ func mustLabels(t *testing.T, msg published) map[string]string { } `json:"metric"` } `json:"incident"` } - require.NoError(t, json.Unmarshal([]byte(msg.data), &p)) + require.NoError(t, json.Unmarshal([]byte(msg.data), &p, jsonx.V1())) return p.Incident.Metric.Labels } diff --git a/services/gcpmonitoring/notify.go b/services/gcpmonitoring/notify.go index 8d8f9d4294..d0e79d7eab 100644 --- a/services/gcpmonitoring/notify.go +++ b/services/gcpmonitoring/notify.go @@ -3,7 +3,7 @@ package gcpmonitoring import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -15,6 +15,7 @@ import ( "cloud.google.com/go/monitoring/apiv3/v2/monitoringpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -83,7 +84,7 @@ func (b *InMemoryBackend) record(d Delivery) { // deliver sends the notification to every target; failures are logged and recorded, never fatal. func (b *InMemoryBackend) deliver(ctx context.Context, n notification) { - payload, err := json.Marshal(incidentPayload(n)) + payload, err := json.Marshal(incidentPayload(n), jsonx.V1()) if err != nil { return } diff --git a/services/gcpmonitoring/persistence.go b/services/gcpmonitoring/persistence.go index 4fb4a96f72..f4617c9ab3 100644 --- a/services/gcpmonitoring/persistence.go +++ b/services/gcpmonitoring/persistence.go @@ -2,7 +2,7 @@ package gcpmonitoring import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -19,38 +19,38 @@ import ( const snapshotVersion = 1 type seriesSnap struct { - Project string `json:"project"` - Unit string `json:"unit,omitempty"` - Series json.RawMessage `json:"series"` + Project string `json:"project"` + Unit string `json:"unit,omitempty"` + Series jsontext.Value `json:"series"` } type channelSnap struct { CodeAt time.Time `json:"codeAt"` Sensitive map[string]string `json:"sensitive,omitempty"` Code string `json:"code,omitempty"` - Channel json.RawMessage `json:"channel"` + Channel jsontext.Value `json:"channel"` } type uptimeSnap struct { - LastRun time.Time `json:"lastRun"` - Config json.RawMessage `json:"config"` + LastRun time.Time `json:"lastRun"` + Config jsontext.Value `json:"config"` } type backendSnapshot struct { - Descriptors map[string]json.RawMessage `json:"descriptors"` - Policies map[string]json.RawMessage `json:"policies"` - Groups map[string]json.RawMessage `json:"groups"` - Snoozes map[string]json.RawMessage `json:"snoozes,omitempty"` - Services map[string]json.RawMessage `json:"services,omitempty"` - SLOs map[string]json.RawMessage `json:"slos,omitempty"` - Channels map[string]channelSnap `json:"channels"` - Uptime map[string]uptimeSnap `json:"uptime"` - Series []seriesSnap `json:"series"` - Incidents []Incident `json:"incidents"` - Version int `json:"version"` + Descriptors map[string]jsontext.Value `json:"descriptors"` + Policies map[string]jsontext.Value `json:"policies"` + Groups map[string]jsontext.Value `json:"groups"` + Snoozes map[string]jsontext.Value `json:"snoozes,omitempty"` + Services map[string]jsontext.Value `json:"services,omitempty"` + SLOs map[string]jsontext.Value `json:"slos,omitempty"` + Channels map[string]channelSnap `json:"channels"` + Uptime map[string]uptimeSnap `json:"uptime"` + Series []seriesSnap `json:"series"` + Incidents []Incident `json:"incidents"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -59,12 +59,12 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } -func snapMap[T proto.Message](in map[string]T) map[string]json.RawMessage { - out := make(map[string]json.RawMessage, len(in)) +func snapMap[T proto.Message](in map[string]T) map[string]jsontext.Value { + out := make(map[string]jsontext.Value, len(in)) for k, v := range in { out[k] = marshalPB(v) } @@ -72,7 +72,7 @@ func snapMap[T proto.Message](in map[string]T) map[string]json.RawMessage { return out } -func restoreMap[T proto.Message](raw map[string]json.RawMessage, newT func() T) (map[string]T, error) { +func restoreMap[T proto.Message](raw map[string]jsontext.Value, newT func() T) (map[string]T, error) { out := make(map[string]T, len(raw)) for k, r := range raw { diff --git a/services/gcpmonitoring/promql_http.go b/services/gcpmonitoring/promql_http.go index 4923a48982..dba68777cd 100644 --- a/services/gcpmonitoring/promql_http.go +++ b/services/gcpmonitoring/promql_http.go @@ -1,7 +1,8 @@ package gcpmonitoring import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/amp/promql" ) @@ -69,7 +71,7 @@ type promResponse struct { func writePromJSON(w http.ResponseWriter, code int, body promResponse) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - _ = json.NewEncoder(w).Encode(body) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), body) } func promError(w http.ResponseWriter, code int, errType, msg string) { diff --git a/services/gcpmonitoring/promql_test.go b/services/gcpmonitoring/promql_test.go index 89b6e5c8dc..296f9dabdb 100644 --- a/services/gcpmonitoring/promql_test.go +++ b/services/gcpmonitoring/promql_test.go @@ -1,7 +1,7 @@ package gcpmonitoring_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -18,6 +18,7 @@ import ( "google.golang.org/genproto/googleapis/api/monitoredres" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -67,7 +68,7 @@ func (e *env) promQuery(t *testing.T, q string) promReply { require.Equal(t, http.StatusOK, code, string(body)) var r promReply - require.NoError(t, json.Unmarshal(body, &r)) + require.NoError(t, json.Unmarshal(body, &r, jsonx.V1())) return r } @@ -165,7 +166,7 @@ func TestPromQLRangeQuery(t *testing.T) { require.Equal(t, http.StatusOK, code, string(body)) var r promReply - require.NoError(t, json.Unmarshal(body, &r)) + require.NoError(t, json.Unmarshal(body, &r, jsonx.V1())) require.Equal(t, "matrix", r.Data.ResultType) require.Len(t, r.Data.Result, 1) @@ -294,7 +295,7 @@ func TestPromQLProjectIsolation(t *testing.T) { require.Equal(t, http.StatusOK, code) var r promReply - require.NoError(t, json.Unmarshal(body, &r)) + require.NoError(t, json.Unmarshal(body, &r, jsonx.V1())) assert.Empty(t, r.Data.Result) } @@ -363,7 +364,7 @@ func TestPromQLErrors(t *testing.T) { assert.Equal(t, tt.status, code, string(body)) var r promReply - require.NoError(t, json.Unmarshal(body, &r)) + require.NoError(t, json.Unmarshal(body, &r, jsonx.V1())) assert.Equal(t, "error", r.Status) assert.Equal(t, tt.errType, r.ErrorType) }) diff --git a/services/gcppubsub/avro.go b/services/gcppubsub/avro.go index a45e90ab47..dfd8b71890 100644 --- a/services/gcppubsub/avro.go +++ b/services/gcppubsub/avro.go @@ -2,13 +2,15 @@ package gcppubsub import ( "encoding/binary" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "math" "slices" "strings" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errAvro = errors.New("avro") @@ -71,7 +73,7 @@ func primitiveKind(s string) (avroKind, bool) { func parseAvroSchema(def string) (*avroType, error) { var raw any - if err := json.Unmarshal([]byte(def), &raw); err != nil { + if err := json.Unmarshal([]byte(def), &raw, jsonx.V1()); err != nil { return nil, avroErr("schema is not valid JSON: %v", err) } diff --git a/services/gcppubsub/persistence.go b/services/gcppubsub/persistence.go index 01bd7669ca..702eb7c9a3 100644 --- a/services/gcppubsub/persistence.go +++ b/services/gcppubsub/persistence.go @@ -2,7 +2,7 @@ package gcppubsub import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "time" @@ -22,34 +22,34 @@ var errNullMessage = errors.New("gcppubsub: snapshot has a null message") const snapshotVersion = 1 type topicSnap struct { - Topic json.RawMessage `json:"topic"` - Retained []*message `json:"retained,omitempty"` + Topic jsontext.Value `json:"topic"` + Retained []*message `json:"retained,omitempty"` } type subSnap struct { - LastActive time.Time `json:"lastActive"` - Sub json.RawMessage `json:"sub"` - Msgs []*subMsg `json:"msgs,omitempty"` + LastActive time.Time `json:"lastActive"` + Sub jsontext.Value `json:"sub"` + Msgs []*subMsg `json:"msgs,omitempty"` } type pbSnapSnap struct { - Created time.Time `json:"created"` - Snapshot json.RawMessage `json:"snapshot"` - Unacked []string `json:"unacked,omitempty"` + Created time.Time `json:"created"` + Snapshot jsontext.Value `json:"snapshot"` + Unacked []string `json:"unacked,omitempty"` } type backendSnapshot struct { - Topics map[string]topicSnap `json:"topics"` - Subs map[string]subSnap `json:"subs"` - Snapshots map[string]pbSnapSnap `json:"snapshots"` - Schemas map[string]*schemaRec `json:"schemas"` - Policies map[string]json.RawMessage `json:"policies,omitempty"` - LastMsg int64 `json:"lastMsg"` - EtagSeq uint64 `json:"etagSeq,omitempty"` - Version int `json:"version"` + Topics map[string]topicSnap `json:"topics"` + Subs map[string]subSnap `json:"subs"` + Snapshots map[string]pbSnapSnap `json:"snapshots"` + Schemas map[string]*schemaRec `json:"schemas"` + Policies map[string]jsontext.Value `json:"policies,omitempty"` + LastMsg int64 `json:"lastMsg"` + EtagSeq uint64 `json:"etagSeq,omitempty"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -58,7 +58,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } @@ -73,7 +73,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Version: snapshotVersion, LastMsg: b.lastMsg, EtagSeq: iamSeq, - Policies: make(map[string]json.RawMessage, len(iamPolicies)), + Policies: make(map[string]jsontext.Value, len(iamPolicies)), Schemas: b.schemas, Topics: make(map[string]topicSnap, len(b.topics)), Subs: make(map[string]subSnap, len(b.subs)), @@ -153,7 +153,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { return nil } -func decodePolicies(raw map[string]json.RawMessage) (map[string]*iampb.Policy, error) { +func decodePolicies(raw map[string]jsontext.Value) (map[string]*iampb.Policy, error) { out := make(map[string]*iampb.Policy, len(raw)) for n, r := range raw { diff --git a/services/gcppubsub/push.go b/services/gcppubsub/push.go index e5fb82157e..2a9e6c23ee 100644 --- a/services/gcppubsub/push.go +++ b/services/gcppubsub/push.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "sync" "time" @@ -12,6 +12,7 @@ import ( "cloud.google.com/go/pubsub/v2/apiv1/pubsubpb" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -196,7 +197,7 @@ func (b *InMemoryBackend) sendPush( } var err error - if body, err = json.Marshal(env); err != nil { + if body, err = json.Marshal(env, jsonx.V1()); err != nil { return false } diff --git a/services/gcppubsub/schema.go b/services/gcppubsub/schema.go index b28c9953d8..a7d4dad0bc 100644 --- a/services/gcppubsub/schema.go +++ b/services/gcppubsub/schema.go @@ -2,7 +2,8 @@ package gcppubsub import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "time" @@ -12,6 +13,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -110,9 +112,10 @@ func validateData(typ pubsubpb.Schema_Type, def string, enc pubsubpb.Encoding, d } var v any - dec := json.NewDecoder(bytes.NewReader(data)) + dec := jsontext.NewDecoder(bytes.NewReader(data), jsonx.V1()) - return dec.Decode(&v) == nil && !dec.More() && t.validJSON(v) + return json.UnmarshalDecode(dec, &v, jsonx.V1()) == nil && !moreJSON(data, dec.InputOffset()) && + t.validJSON(v) case pubsubpb.Schema_PROTOCOL_BUFFER: if enc == pubsubpb.Encoding_BINARY { return validWire(data) @@ -120,7 +123,7 @@ func validateData(typ pubsubpb.Schema_Type, def string, enc pubsubpb.Encoding, d var v map[string]any - return json.Unmarshal(data, &v) == nil + return json.Unmarshal(data, &v, jsonx.V1()) == nil case pubsubpb.Schema_TYPE_UNSPECIFIED: return false default: @@ -480,3 +483,11 @@ func (b *InMemoryBackend) ValidateMessage(req *pubsubpb.ValidateMessageRequest) return nil } + +// moreJSON mirrors encoding/json Decoder.More: data remains after offset and +// does not start with a closing bracket. +func moreJSON(data []byte, offset int64) bool { + rest := bytes.TrimLeft(data[offset:], " \t\r\n") + + return len(rest) > 0 && rest[0] != ']' && rest[0] != '}' +} diff --git a/services/gcppubsub/sdk_test.go b/services/gcppubsub/sdk_test.go index 5e9090b772..fd44b1bde1 100644 --- a/services/gcppubsub/sdk_test.go +++ b/services/gcppubsub/sdk_test.go @@ -3,7 +3,8 @@ package gcppubsub_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "sync" @@ -24,6 +25,7 @@ import ( "google.golang.org/protobuf/types/known/fieldmaskpb" "google.golang.org/protobuf/types/known/timestamppb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcppubsub" ) @@ -840,7 +842,7 @@ func TestSDKPushSubscription(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var env envelope - _ = json.NewDecoder(r.Body).Decode(&env) + _ = json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &env, jsonx.V1()) mu.Lock() fail := first diff --git a/services/gcpredis/persistence.go b/services/gcpredis/persistence.go index 1a4410e3ed..03cc7db5da 100644 --- a/services/gcpredis/persistence.go +++ b/services/gcpredis/persistence.go @@ -2,7 +2,7 @@ package gcpredis import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/redis/apiv1/redispb" @@ -18,15 +18,15 @@ import ( const snapshotVersion = 1 type instSnap struct { - Instance json.RawMessage `json:"instance"` - AuthString string `json:"authString,omitempty"` - Keyspace []byte `json:"keyspace,omitempty"` + Instance jsontext.Value `json:"instance"` + AuthString string `json:"authString,omitempty"` + Keyspace []byte `json:"keyspace,omitempty"` } type backendSnapshot struct { - Instances map[string]instSnap `json:"instances"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` + Instances map[string]instSnap `json:"instances"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` } // Snapshot serialises every instance with its keyspace; Redis servers and TLS CAs are rebuilt on restore. diff --git a/services/gcpredis/rest_test.go b/services/gcpredis/rest_test.go index 96f602d482..cde3957b77 100644 --- a/services/gcpredis/rest_test.go +++ b/services/gcpredis/rest_test.go @@ -1,7 +1,7 @@ package gcpredis_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/gcprest/resttest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -69,7 +70,7 @@ func TestRESTFlow(t *testing.T) { Auth bool `json:"authEnabled"` } - return json.Unmarshal(body, &inst) == nil && inst.State == "READY" && inst.Host != "" && + return json.Unmarshal(body, &inst, jsonx.V1()) == nil && inst.State == "READY" && inst.Host != "" && assert.True(t, inst.Auth) }, 10*time.Second, 5*time.Millisecond) } diff --git a/services/gcpresourcemanager/helpers_test.go b/services/gcpresourcemanager/helpers_test.go index 02982e6659..f9138a8792 100644 --- a/services/gcpresourcemanager/helpers_test.go +++ b/services/gcpresourcemanager/helpers_test.go @@ -2,7 +2,7 @@ package gcpresourcemanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync/atomic" "testing" @@ -19,6 +19,7 @@ import ( "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/status" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpresourcemanager" ) @@ -200,7 +201,8 @@ func codeOf(err error) codes.Code { var c codes.Code - if json.Unmarshal([]byte(ge.Body), &body) == nil && c.UnmarshalJSON([]byte(`"`+body.Error.Status+`"`)) == nil { + if json.Unmarshal([]byte(ge.Body), &body, jsonx.V1()) == nil && + c.UnmarshalJSON([]byte(`"`+body.Error.Status+`"`)) == nil { return c } } diff --git a/services/gcpresourcemanager/persistence.go b/services/gcpresourcemanager/persistence.go index 5d4455e118..8d71f07a1d 100644 --- a/services/gcpresourcemanager/persistence.go +++ b/services/gcpresourcemanager/persistence.go @@ -2,7 +2,7 @@ package gcpresourcemanager import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -23,8 +23,8 @@ type backendSnapshot struct { TagValues map[string]*tagValueRec `json:"tagValues"` Bindings map[string]*bindingRec `json:"tagBindings"` Enabled map[string]map[string]time.Time `json:"enabledServices"` - Policies map[string]json.RawMessage `json:"policies"` - Ops map[string]json.RawMessage `json:"operations"` + Policies map[string]jsontext.Value `json:"policies"` + Ops map[string]jsontext.Value `json:"operations"` Seed string `json:"seed"` Version int `json:"version"` PolicySeq uint64 `json:"policySeq"` @@ -39,7 +39,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { snap := backendSnapshot{ Version: snapshotVersion, Seed: b.seed, Projects: b.projects, Folders: b.folders, TagKeys: b.tagKeys, TagValues: b.tagValues, Bindings: b.bindings, Enabled: b.enabled, PolicySeq: seq, - Policies: make(map[string]json.RawMessage, len(policies)), Ops: b.lro.Snapshot(), + Policies: make(map[string]jsontext.Value, len(policies)), Ops: b.lro.Snapshot(), } for n, p := range policies { diff --git a/services/gcpresourcemanager/v1.go b/services/gcpresourcemanager/v1.go index b55c7012f6..3ec478d845 100644 --- a/services/gcpresourcemanager/v1.go +++ b/services/gcpresourcemanager/v1.go @@ -1,7 +1,8 @@ package gcpresourcemanager import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "regexp" @@ -16,6 +17,7 @@ import ( "google.golang.org/protobuf/proto" "github.com/blackbirdworks/gopherstack/pkgs/gcprest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -102,7 +104,7 @@ func writeV1Error(w http.ResponseWriter, err error) { st, _ := status.FromError(err) httpCode := gcprest.HTTPStatus(st.Code()) - details := make([]json.RawMessage, 0, len(st.Proto().GetDetails())) + details := make([]jsontext.Value, 0, len(st.Proto().GetDetails())) for _, d := range st.Proto().GetDetails() { if raw, mErr := protojson.Marshal(d); mErr == nil { @@ -140,7 +142,7 @@ func codeName(c codes.Code) string { } func writeV1JSON(w http.ResponseWriter, code int, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -177,7 +179,7 @@ func readBody(r *http.Request, into any) error { return nil } - if err = json.Unmarshal(raw, into); err != nil { + if err = json.Unmarshal(raw, into, jsonx.V1()); err != nil { return errInvalid("Invalid JSON payload: %v", err) } diff --git a/services/gcprun/persistence.go b/services/gcprun/persistence.go index b1a1db2f8a..5f554717b2 100644 --- a/services/gcprun/persistence.go +++ b/services/gcprun/persistence.go @@ -2,7 +2,7 @@ package gcprun import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/iam/apiv1/iampb" @@ -20,38 +20,38 @@ import ( const snapshotVersion = 1 type svcSnap struct { - Failure string `json:"failure"` - Service json.RawMessage `json:"service"` - RevSeq int `json:"revSeq"` + Failure string `json:"failure"` + Service jsontext.Value `json:"service"` + RevSeq int `json:"revSeq"` } type revSnap struct { - StartErr string `json:"startErr"` - Revision json.RawMessage `json:"revision"` - Seq int `json:"seq"` + StartErr string `json:"startErr"` + Revision jsontext.Value `json:"revision"` + Seq int `json:"seq"` } type taskSnap struct { - State string `json:"state"` - Task json.RawMessage `json:"task"` + State string `json:"state"` + Task jsontext.Value `json:"task"` } type backendSnapshot struct { - Services map[string]svcSnap `json:"services"` - Revisions map[string]revSnap `json:"revisions"` - Jobs map[string]json.RawMessage `json:"jobs"` - Executions map[string]json.RawMessage `json:"executions"` - Tasks map[string]taskSnap `json:"tasks"` - Operations map[string]json.RawMessage `json:"operations"` - DeletedSvc map[string]json.RawMessage `json:"deletedServices"` - DeletedJob map[string]json.RawMessage `json:"deletedJobs"` - DeletedExe map[string]json.RawMessage `json:"deletedExecutions"` - IAM map[string]json.RawMessage `json:"iamPolicies"` - IAMSeq uint64 `json:"iamSeq"` - Version int `json:"version"` + Services map[string]svcSnap `json:"services"` + Revisions map[string]revSnap `json:"revisions"` + Jobs map[string]jsontext.Value `json:"jobs"` + Executions map[string]jsontext.Value `json:"executions"` + Tasks map[string]taskSnap `json:"tasks"` + Operations map[string]jsontext.Value `json:"operations"` + DeletedSvc map[string]jsontext.Value `json:"deletedServices"` + DeletedJob map[string]jsontext.Value `json:"deletedJobs"` + DeletedExe map[string]jsontext.Value `json:"deletedExecutions"` + IAM map[string]jsontext.Value `json:"iamPolicies"` + IAMSeq uint64 `json:"iamSeq"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { raw, err := protojson.Marshal(m) if err != nil { return nil @@ -60,8 +60,8 @@ func marshalPB(m proto.Message) json.RawMessage { return raw } -func marshalMap[T proto.Message](m map[string]T) map[string]json.RawMessage { - out := make(map[string]json.RawMessage, len(m)) +func marshalMap[T proto.Message](m map[string]T) map[string]jsontext.Value { + out := make(map[string]jsontext.Value, len(m)) for k, v := range m { out[k] = marshalPB(v) } @@ -69,7 +69,7 @@ func marshalMap[T proto.Message](m map[string]T) map[string]json.RawMessage { return out } -func unmarshalMap[T proto.Message](raw map[string]json.RawMessage, mk func() T, what string) (map[string]T, error) { +func unmarshalMap[T proto.Message](raw map[string]jsontext.Value, mk func() T, what string) (map[string]T, error) { out := make(map[string]T, len(raw)) for k, r := range raw { @@ -84,7 +84,7 @@ func unmarshalMap[T proto.Message](raw map[string]json.RawMessage, mk func() T, return out, nil } -func unmarshalPB[T proto.Message](raw json.RawMessage, m T) (T, error) { +func unmarshalPB[T proto.Message](raw jsontext.Value, m T) (T, error) { err := (protojson.UnmarshalOptions{DiscardUnknown: true}).Unmarshal(raw, m) return m, err @@ -99,8 +99,8 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Version: snapshotVersion, Services: make(map[string]svcSnap, len(b.services)), Revisions: make(map[string]revSnap, len(b.revisions)), - Jobs: make(map[string]json.RawMessage, len(b.jobs)), - Executions: make(map[string]json.RawMessage, len(b.executions)), + Jobs: make(map[string]jsontext.Value, len(b.jobs)), + Executions: make(map[string]jsontext.Value, len(b.executions)), Tasks: make(map[string]taskSnap, len(b.tasks)), Operations: b.ops.Snapshot(), } diff --git a/services/gcpscheduler/helpers_test.go b/services/gcpscheduler/helpers_test.go index 239ab77283..2c6e9a7c50 100644 --- a/services/gcpscheduler/helpers_test.go +++ b/services/gcpscheduler/helpers_test.go @@ -3,7 +3,7 @@ package gcpscheduler_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -21,6 +21,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpscheduler" ) @@ -165,7 +166,7 @@ func decodeJWT(t *testing.T, token string) map[string]any { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) return claims } diff --git a/services/gcpscheduler/persistence.go b/services/gcpscheduler/persistence.go index 46a777a29c..25fff0d21a 100644 --- a/services/gcpscheduler/persistence.go +++ b/services/gcpscheduler/persistence.go @@ -2,7 +2,7 @@ package gcpscheduler import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -17,10 +17,10 @@ import ( const snapshotVersion = 1 type jobSnap struct { - RetryAt time.Time `json:"retryAt"` - ExecStart time.Time `json:"execStart"` - Job json.RawMessage `json:"job"` - Failures int32 `json:"failures"` + RetryAt time.Time `json:"retryAt"` + ExecStart time.Time `json:"execStart"` + Job jsontext.Value `json:"job"` + Failures int32 `json:"failures"` } type backendSnapshot struct { diff --git a/services/gcpsecretmanager/persistence.go b/services/gcpsecretmanager/persistence.go index ad3b5fc1ff..8da62144cb 100644 --- a/services/gcpsecretmanager/persistence.go +++ b/services/gcpsecretmanager/persistence.go @@ -2,7 +2,7 @@ package gcpsecretmanager import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/iam/apiv1/iampb" @@ -18,16 +18,16 @@ import ( const snapshotVersion = 1 type versionSnap struct { - Version json.RawMessage `json:"version"` - Data []byte `json:"data,omitempty"` - Num int64 `json:"num"` + Version jsontext.Value `json:"version"` + Data []byte `json:"data,omitempty"` + Num int64 `json:"num"` } type secretSnap struct { - Secret json.RawMessage `json:"secret"` - Policy json.RawMessage `json:"policy,omitempty"` - Versions []versionSnap `json:"versions,omitempty"` - NextVer int64 `json:"nextVer"` + Secret jsontext.Value `json:"secret"` + Policy jsontext.Value `json:"policy,omitempty"` + Versions []versionSnap `json:"versions,omitempty"` + NextVer int64 `json:"nextVer"` } type backendSnapshot struct { @@ -36,7 +36,7 @@ type backendSnapshot struct { Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { out, err := protojson.Marshal(m) if err != nil { return nil @@ -45,7 +45,7 @@ func marshalPB(m proto.Message) json.RawMessage { return out } -func unmarshalPB(raw json.RawMessage, m proto.Message) error { +func unmarshalPB(raw jsontext.Value, m proto.Message) error { return protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(raw, m) } diff --git a/services/gcpspanner/persistence.go b/services/gcpspanner/persistence.go index 1932704bba..54e7645c85 100644 --- a/services/gcpspanner/persistence.go +++ b/services/gcpspanner/persistence.go @@ -2,7 +2,7 @@ package gcpspanner import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "cloud.google.com/go/iam/apiv1/iampb" @@ -20,21 +20,21 @@ import ( const snapshotVersion = 1 type dbSnap struct { - Database json.RawMessage `json:"database"` - DDL []string `json:"ddl,omitempty"` + Database jsontext.Value `json:"database"` + DDL []string `json:"ddl,omitempty"` } type instSnap struct { Databases map[string]dbSnap `json:"databases,omitempty"` - Instance json.RawMessage `json:"instance"` - Policy json.RawMessage `json:"policy,omitempty"` + Instance jsontext.Value `json:"instance"` + Policy jsontext.Value `json:"policy,omitempty"` } type backendSnapshot struct { - Instances map[string]instSnap `json:"instances"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` - EtagSeq uint64 `json:"etagSeq"` + Instances map[string]instSnap `json:"instances"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` + EtagSeq uint64 `json:"etagSeq"` } // Snapshot serialises instances, policies, databases and their DDL. Table data lives in the emulator and is not diff --git a/services/gcpspanner/rest_test.go b/services/gcpspanner/rest_test.go index fac931f18d..882b835182 100644 --- a/services/gcpspanner/rest_test.go +++ b/services/gcpspanner/rest_test.go @@ -1,7 +1,7 @@ package gcpspanner_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -32,7 +33,7 @@ func restDo(t *testing.T, base, method, path, body string) (int, map[string]any) out := map[string]any{} if len(raw) > 0 { - require.NoError(t, json.Unmarshal(raw, &out), string(raw)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1()), string(raw)) } return resp.StatusCode, out diff --git a/services/gcpsql/backups.go b/services/gcpsql/backups.go index 9f3a93e350..c41d603633 100644 --- a/services/gcpsql/backups.go +++ b/services/gcpsql/backups.go @@ -2,17 +2,18 @@ package gcpsql import ( "context" - "encoding/json" "slices" "sort" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // RestoreBackupInput is the restoreBackupContext of instances.restoreBackup. type RestoreBackupInput struct { - BackupRunID json.Number `json:"backupRunId"` - InstanceID string `json:"instanceId"` - Project string `json:"project"` + BackupRunID jsonx.Number `json:"backupRunId"` + InstanceID string `json:"instanceId"` + Project string `json:"project"` } func (b *InMemoryBackend) nextBackupID() string { diff --git a/services/gcpsql/handler.go b/services/gcpsql/handler.go index 2c2d6f5983..a794dc6986 100644 --- a/services/gcpsql/handler.go +++ b/services/gcpsql/handler.go @@ -2,7 +2,8 @@ package gcpsql import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -160,7 +162,7 @@ func decode[T any](c *echo.Context) (T, error) { return v, nil } - if err = json.Unmarshal(data, &v); err != nil { + if err = json.Unmarshal(data, &v, jsonx.V1()); err != nil { return v, errInvalid("Invalid JSON payload received: %v", err) } @@ -171,7 +173,7 @@ func decode[T any](c *echo.Context) (T, error) { func decodeContext[T any](c *echo.Context, key string) (T, map[string]any, error) { var typed T - wrapper, err := decode[map[string]json.RawMessage](c) + wrapper, err := decode[map[string]jsontext.Value](c) if err != nil { return typed, nil, err } @@ -181,13 +183,13 @@ func decodeContext[T any](c *echo.Context, key string) (T, map[string]any, error return typed, nil, errInvalid("Missing parameter: %s.", key) } - if err = json.Unmarshal(raw, &typed); err != nil { + if err = json.Unmarshal(raw, &typed, jsonx.V1()); err != nil { return typed, nil, errInvalid("Invalid %s: %v", key, err) } var echoed map[string]any - _ = json.Unmarshal(raw, &echoed) + _ = json.Unmarshal(raw, &echoed, jsonx.V1()) return typed, echoed, nil } diff --git a/services/gcpsql/settingsdef.go b/services/gcpsql/settingsdef.go index 4c41d0337e..f0f4047144 100644 --- a/services/gcpsql/settingsdef.go +++ b/services/gcpsql/settingsdef.go @@ -3,8 +3,10 @@ package gcpsql import ( "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const retainDays = 7 @@ -133,7 +135,7 @@ func flagsSig(f []Flag) string { } func etagOf(v any) string { - data, _ := json.Marshal(v) + data, _ := json.Marshal(v, jsonx.V1()) sum := sha256.Sum256(data) return base64.RawURLEncoding.EncodeToString(sum[:16]) diff --git a/services/gcpstorage/acl.go b/services/gcpstorage/acl.go index 906c352014..80e3594ae1 100644 --- a/services/gcpstorage/acl.go +++ b/services/gcpstorage/acl.go @@ -1,11 +1,13 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ACLEntry is one access-control entry; the derived fields (email, domain, projectTeam) are rendered from Entity. @@ -239,7 +241,7 @@ func (b *Bucket) ubla() bool { } raw, ok := b.Config["iamConfiguration"] - if !ok || json.Unmarshal(raw, &cfg) != nil { + if !ok || json.Unmarshal(raw, &cfg, jsonx.V1()) != nil { return false } diff --git a/services/gcpstorage/events.go b/services/gcpstorage/events.go index 5e4892699a..a51cf868a7 100644 --- a/services/gcpstorage/events.go +++ b/services/gcpstorage/events.go @@ -1,8 +1,11 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ObjectEventType names a change to an object, matching the suffix of the google.cloud.storage.object.v1 event types. @@ -27,8 +30,8 @@ type ObjectEvent struct { } // Data is the event payload: the object resource, as the Cloud Storage JSON API renders it. -func (e ObjectEvent) Data() json.RawMessage { - raw, err := json.Marshal(objectResource("", e.Object)) +func (e ObjectEvent) Data() jsontext.Value { + raw, err := json.Marshal(objectResource("", e.Object), jsonx.V1()) if err != nil { return nil } diff --git a/services/gcpstorage/events_test.go b/services/gcpstorage/events_test.go index 2bf146afdd..01b8456be6 100644 --- a/services/gcpstorage/events_test.go +++ b/services/gcpstorage/events_test.go @@ -1,7 +1,7 @@ package gcpstorage_test import ( - "encoding/json" + "encoding/json/v2" "sync" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpstorage" ) @@ -146,7 +147,7 @@ func TestObjectEventData(t *testing.T) { require.Len(t, rec.got, 1) var data map[string]any - require.NoError(t, json.Unmarshal(rec.got[0].Data(), &data)) + require.NoError(t, json.Unmarshal(rec.got[0].Data(), &data, jsonx.V1())) assert.Equal(t, "ev-data", data["bucket"]) assert.Equal(t, "dir/a.txt", data["name"]) assert.Equal(t, "5", data["size"]) diff --git a/services/gcpstorage/handler_acl.go b/services/gcpstorage/handler_acl.go index 480d59e4a4..fefeaa9016 100644 --- a/services/gcpstorage/handler_acl.go +++ b/services/gcpstorage/handler_acl.go @@ -1,10 +1,12 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type aclBody struct { @@ -96,7 +98,7 @@ func (h *Handler) aclWrite(c *echo.Context, rt route, t aclTarget, base string) } var in aclBody - if jsonErr := json.Unmarshal(body, &in); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &in, jsonx.V1()); jsonErr != nil { return errInvalid("Invalid JSON payload received.") } diff --git a/services/gcpstorage/handler_bucket.go b/services/gcpstorage/handler_bucket.go index 6ebae2633f..1b2afd6421 100644 --- a/services/gcpstorage/handler_bucket.go +++ b/services/gcpstorage/handler_bucket.go @@ -1,13 +1,14 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/gcpiampolicy" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func errRequired(param string) *APIError { @@ -121,7 +122,7 @@ func (h *Handler) setIamPolicy(c *echo.Context, rt route) error { } var in IAMPolicy - if jsonErr := json.Unmarshal(body, &in); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &in, jsonx.V1()); jsonErr != nil { return errInvalid("Invalid JSON payload received.") } diff --git a/services/gcpstorage/handler_object.go b/services/gcpstorage/handler_object.go index cf7d82a198..a0273ae1f6 100644 --- a/services/gcpstorage/handler_object.go +++ b/services/gcpstorage/handler_object.go @@ -1,12 +1,14 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type objectsJSON struct { @@ -229,7 +231,7 @@ func (h *Handler) composeObject(c *echo.Context, rt route) error { } var req composeRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return errInvalid("Invalid JSON payload received.") } diff --git a/services/gcpstorage/handler_test.go b/services/gcpstorage/handler_test.go index 169d835165..64217a38e8 100644 --- a/services/gcpstorage/handler_test.go +++ b/services/gcpstorage/handler_test.go @@ -2,7 +2,7 @@ package gcpstorage_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpstorage" @@ -129,7 +130,7 @@ func TestErrorEnvelope(t *testing.T) { } `json:"error"` } - require.NoError(t, json.Unmarshal([]byte(body), &env), body) + require.NoError(t, json.Unmarshal([]byte(body), &env, jsonx.V1()), body) assert.Equal(t, tt.status, env.Error.Code) assert.NotEmpty(t, env.Error.Message) require.Len(t, env.Error.Errors, 1) @@ -200,7 +201,7 @@ func TestUploadsAndDownloads(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode, body) var obj map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &obj)) + require.NoError(t, json.Unmarshal([]byte(body), &obj, jsonx.V1())) assert.Equal(t, "a/b.bin", obj["name"]) assert.Equal(t, "6", obj["size"]) assert.Equal(t, "application/x-bin", obj["contentType"]) @@ -297,7 +298,7 @@ func TestRewriteAndPatch(t *testing.T) { Done bool `json:"done"` } - require.NoError(t, json.Unmarshal([]byte(body), &rw)) + require.NoError(t, json.Unmarshal([]byte(body), &rw, jsonx.V1())) assert.Equal(t, "storage#rewriteResponse", rw.Kind) assert.True(t, rw.Done) assert.Equal(t, "4", rw.Total) @@ -318,7 +319,7 @@ func TestRewriteAndPatch(t *testing.T) { Metageneration string `json:"metageneration"` } - require.NoError(t, json.Unmarshal([]byte(body), &obj)) + require.NoError(t, json.Unmarshal([]byte(body), &obj, jsonx.V1())) assert.Equal(t, map[string]string{"b": "2"}, obj.Metadata) assert.Empty(t, obj.ContentLang) assert.Equal(t, "3", obj.Metageneration) diff --git a/services/gcpstorage/iam.go b/services/gcpstorage/iam.go index 5257307624..07e18c0d14 100644 --- a/services/gcpstorage/iam.go +++ b/services/gcpstorage/iam.go @@ -3,12 +3,14 @@ package gcpstorage import ( "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/v2" "cloud.google.com/go/iam/apiv1/iampb" "google.golang.org/genproto/googleapis/type/expr" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type conditionJSON struct { @@ -36,7 +38,7 @@ func policyToPB(p IAMPolicy) *iampb.Policy { if len(bd.Condition) > 0 && string(bd.Condition) != "null" { var c conditionJSON - _ = json.Unmarshal(bd.Condition, &c) + _ = json.Unmarshal(bd.Condition, &c, jsonx.V1()) pb.Condition = &expr.Expr{Expression: c.Expression, Title: c.Title, Description: c.Description} } @@ -53,7 +55,10 @@ func policyFromPB(p *iampb.Policy) IAMPolicy { ib := IAMBinding{Role: bd.GetRole(), Members: bd.GetMembers()} if c := bd.GetCondition(); c != nil { - ib.Condition, _ = json.Marshal(conditionJSON{c.GetExpression(), c.GetTitle(), c.GetDescription()}) + ib.Condition, _ = json.Marshal( + conditionJSON{c.GetExpression(), c.GetTitle(), c.GetDescription()}, + jsonx.V1(), + ) } out.Bindings = append(out.Bindings, ib) diff --git a/services/gcpstorage/iam_policy_test.go b/services/gcpstorage/iam_policy_test.go index ea03211981..0724dcf0e7 100644 --- a/services/gcpstorage/iam_policy_test.go +++ b/services/gcpstorage/iam_policy_test.go @@ -1,12 +1,14 @@ package gcpstorage_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -72,7 +74,7 @@ func TestBucketIAMConditions(t *testing.T) { Etag string `json:"etag"` } - require.NoError(t, json.Unmarshal([]byte(seeded), &cur)) + require.NoError(t, json.Unmarshal([]byte(seeded), &cur, jsonx.V1())) if tt.freshEtag { body = `{"etag":"` + cur.Etag + `","version":3}` @@ -87,7 +89,7 @@ func TestBucketIAMConditions(t *testing.T) { Version int `json:"version"` } - require.NoError(t, json.Unmarshal([]byte(out), &got)) + require.NoError(t, json.Unmarshal([]byte(out), &got, jsonx.V1())) assert.Equal(t, tt.wantPolVer, got.Version) } }) diff --git a/services/gcpstorage/models.go b/services/gcpstorage/models.go index af57c686f1..a609e891ed 100644 --- a/services/gcpstorage/models.go +++ b/services/gcpstorage/models.go @@ -1,7 +1,7 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/jsontext" "maps" "slices" "time" @@ -9,9 +9,9 @@ import ( // IAMBinding is one role binding of a bucket IAM policy. type IAMBinding struct { - Condition json.RawMessage `json:"condition,omitempty"` - Role string `json:"role"` - Members []string `json:"members"` + Condition jsontext.Value `json:"condition,omitempty"` + Role string `json:"role"` + Members []string `json:"members"` } // IAMPolicy is a bucket IAM policy. @@ -70,21 +70,21 @@ func (o *Object) clone() *Object { // Bucket is a bucket with all of its object versions. type Bucket struct { - Created time.Time `json:"created"` - Updated time.Time `json:"updated"` - Objects map[string][]*Object `json:"objects"` - Labels map[string]string `json:"labels,omitempty"` - Config map[string]json.RawMessage `json:"config,omitempty"` - Project string `json:"project"` - Name string `json:"name"` - Location string `json:"location"` - StorageClass string `json:"storageClass"` - ACL []ACLEntry `json:"acl,omitempty"` - DefaultObjectACL []ACLEntry `json:"defaultObjectAcl,omitempty"` - IAM IAMPolicy `json:"iam"` - Metageneration int64 `json:"metageneration"` - Versioning bool `json:"versioning,omitempty"` - DefaultEventBasedHold bool `json:"defaultEventBasedHold,omitempty"` + Created time.Time `json:"created"` + Updated time.Time `json:"updated"` + Objects map[string][]*Object `json:"objects"` + Labels map[string]string `json:"labels,omitempty"` + Config map[string]jsontext.Value `json:"config,omitempty"` + Project string `json:"project"` + Name string `json:"name"` + Location string `json:"location"` + StorageClass string `json:"storageClass"` + ACL []ACLEntry `json:"acl,omitempty"` + DefaultObjectACL []ACLEntry `json:"defaultObjectAcl,omitempty"` + IAM IAMPolicy `json:"iam"` + Metageneration int64 `json:"metageneration"` + Versioning bool `json:"versioning,omitempty"` + DefaultEventBasedHold bool `json:"defaultEventBasedHold,omitempty"` } // clone copies the bucket metadata without its objects. diff --git a/services/gcpstorage/patch.go b/services/gcpstorage/patch.go index 74fd400833..332733f9e8 100644 --- a/services/gcpstorage/patch.go +++ b/services/gcpstorage/patch.go @@ -2,13 +2,16 @@ package gcpstorage import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Patch is a decoded JSON request body, keyed by field name. A null value // clears the field, as in a JSON merge patch. -type Patch map[string]json.RawMessage +type Patch map[string]jsontext.Value const ( keyContentType = "contentType" @@ -26,16 +29,16 @@ const ( defaultContentType = "application/octet-stream" ) -func isNull(raw json.RawMessage) bool { return string(bytes.TrimSpace(raw)) == "null" } +func isNull(raw jsontext.Value) bool { return string(bytes.TrimSpace(raw)) == "null" } -func decodeField[T any](raw json.RawMessage, field string) (T, *APIError) { +func decodeField[T any](raw jsontext.Value, field string) (T, *APIError) { var v T if isNull(raw) { return v, nil } - if err := json.Unmarshal(raw, &v); err != nil { + if err := json.Unmarshal(raw, &v, jsonx.V1()); err != nil { return v, errInvalid("Invalid value for field '" + field + "'.") } @@ -58,7 +61,7 @@ func validStorageClass(sc string) bool { } } -func mergeStringMap(raw json.RawMessage, dst map[string]string, field string) (map[string]string, *APIError) { +func mergeStringMap(raw jsontext.Value, dst map[string]string, field string) (map[string]string, *APIError) { if isNull(raw) { return nil, nil } @@ -233,7 +236,7 @@ func applyBucket(b *Bucket, p Patch, create bool) *APIError { } if b.Config == nil { - b.Config = map[string]json.RawMessage{} + b.Config = map[string]jsontext.Value{} } b.Config[k] = raw diff --git a/services/gcpstorage/util.go b/services/gcpstorage/util.go index 9783374d69..4ea8004312 100644 --- a/services/gcpstorage/util.go +++ b/services/gcpstorage/util.go @@ -1,15 +1,18 @@ package gcpstorage import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func itoa(n int) string { return strconv.Itoa(n) } -func marshalRaw(v any) json.RawMessage { - raw, _ := json.Marshal(v) //nolint:errchkjson // strings and string maps always marshal +func marshalRaw(v any) jsontext.Value { + raw, _ := json.Marshal(v, jsonx.V1()) //nolint:errchkjson // strings and string maps always marshal return raw } diff --git a/services/gcpstorage/wire.go b/services/gcpstorage/wire.go index 7d4e38d4dd..4535cda5a6 100644 --- a/services/gcpstorage/wire.go +++ b/services/gcpstorage/wire.go @@ -2,10 +2,12 @@ package gcpstorage import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type objectJSON struct { @@ -222,7 +224,7 @@ func decodePatch(body []byte) (Patch, *APIError) { return p, nil } - if err := json.Unmarshal(body, &p); err != nil || p == nil { + if err := json.Unmarshal(body, &p, jsonx.V1()); err != nil || p == nil { return nil, errInvalid("Invalid JSON payload received.") } diff --git a/services/gcpworkflows/callbacks.go b/services/gcpworkflows/callbacks.go index 4cd02ace24..d1fedf2525 100644 --- a/services/gcpworkflows/callbacks.go +++ b/services/gcpworkflows/callbacks.go @@ -2,7 +2,8 @@ package gcpworkflows import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -10,6 +11,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/wfinterp" ) @@ -74,8 +76,10 @@ func IsCallbackPath(path string) bool { func writeJSONError(w http.ResponseWriter, code int, status, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) - _ = json.NewEncoder(w). - Encode(map[string]any{"error": map[string]any{"code": code, "message": msg, "status": status}}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]any{"error": map[string]any{"code": code, "message": msg, "status": status}}, + ) } func (b *InMemoryBackend) serveCallback(w http.ResponseWriter, r *http.Request) { diff --git a/services/gcpworkflows/integration_test.go b/services/gcpworkflows/integration_test.go index 1754c5440a..3f46d248ca 100644 --- a/services/gcpworkflows/integration_test.go +++ b/services/gcpworkflows/integration_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/gcprest/resttest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/gcpfirestore" "github.com/blackbirdworks/gopherstack/services/gcppubsub" @@ -468,4 +469,6 @@ func TestRESTFlow(t *testing.T) { }) } -func jsonUnmarshal(raw []byte, v any) error { return json.Unmarshal(bytes.TrimSpace(raw), v) } +func jsonUnmarshal(raw []byte, v any) error { + return json.Unmarshal(bytes.TrimSpace(raw), v, jsonx.V1()) +} diff --git a/services/gcpworkflows/persistence.go b/services/gcpworkflows/persistence.go index 0a4bba082b..2cf0135f01 100644 --- a/services/gcpworkflows/persistence.go +++ b/services/gcpworkflows/persistence.go @@ -2,7 +2,7 @@ package gcpworkflows import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -23,17 +23,17 @@ var errNoRevisions = errors.New("no revisions") const snapshotVersion = 1 type workflowSnap struct { - Revisions []json.RawMessage `json:"revisions"` + Revisions []jsontext.Value `json:"revisions"` } type backendSnapshot struct { - Workflows map[string]workflowSnap `json:"workflows"` - Executions map[string]json.RawMessage `json:"executions"` - Operations map[string]json.RawMessage `json:"operations"` - Version int `json:"version"` + Workflows map[string]workflowSnap `json:"workflows"` + Executions map[string]jsontext.Value `json:"executions"` + Operations map[string]jsontext.Value `json:"operations"` + Version int `json:"version"` } -func marshalPB(m proto.Message) json.RawMessage { +func marshalPB(m proto.Message) jsontext.Value { raw, err := protojson.Marshal(m) if err != nil { return nil @@ -54,12 +54,12 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { snap := backendSnapshot{ Version: snapshotVersion, Workflows: make(map[string]workflowSnap, len(b.workflows)), - Executions: make(map[string]json.RawMessage, len(b.execs)), + Executions: make(map[string]jsontext.Value, len(b.execs)), Operations: b.ops.Snapshot(), } for n, rec := range b.workflows { - ws := workflowSnap{Revisions: make([]json.RawMessage, len(rec.revs))} + ws := workflowSnap{Revisions: make([]jsontext.Value, len(rec.revs))} for i, r := range rec.revs { ws.Revisions[i] = marshalPB(r) } diff --git a/services/glacier/handler_archives_test.go b/services/glacier/handler_archives_test.go index 1900a12e56..f46c33c4c0 100644 --- a/services/glacier/handler_archives_test.go +++ b/services/glacier/handler_archives_test.go @@ -3,7 +3,7 @@ package glacier_test import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -57,7 +58,7 @@ func TestUploadDeleteArchive(t *testing.T) { assert.Equal(t, http.StatusCreated, rec2.Code) var uploadResp map[string]any - err = json.Unmarshal(rec2.Body.Bytes(), &uploadResp) + err = json.Unmarshal(rec2.Body.Bytes(), &uploadResp, jsonx.V1()) require.NoError(t, err) archiveID := uploadResp["archiveId"].(string) @@ -190,7 +191,7 @@ func TestUploadArchive_TreeHashReturnedInResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, expectedHash, resp["checksum"]) assert.Equal(t, expectedHash, rec.Header().Get("X-Amz-Sha256-Tree-Hash")) } diff --git a/services/glacier/handler_data_retrieval_policy.go b/services/glacier/handler_data_retrieval_policy.go index 42d20a5879..f5054237ab 100644 --- a/services/glacier/handler_data_retrieval_policy.go +++ b/services/glacier/handler_data_retrieval_policy.go @@ -1,11 +1,13 @@ package glacier import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDataRetrievalPolicy handles GetDataRetrievalPolicy and SetDataRetrievalPolicy. @@ -30,7 +32,7 @@ func (h *Handler) handleGetDataRetrievalPolicy(c *echo.Context) error { } var parsed any - if err := json.Unmarshal([]byte(policy), &parsed); err == nil { + if err := json.Unmarshal([]byte(policy), &parsed, jsonx.V1()); err == nil { return c.JSON(http.StatusOK, parsed) } @@ -39,7 +41,7 @@ func (h *Handler) handleGetDataRetrievalPolicy(c *echo.Context) error { func (h *Handler) handleSetDataRetrievalPolicy(c *echo.Context, body []byte) error { var req dataRetrievalPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid data retrieval policy: "+err.Error()) } diff --git a/services/glacier/handler_data_retrieval_policy_test.go b/services/glacier/handler_data_retrieval_policy_test.go index 9811be5c4c..f6a85eeaba 100644 --- a/services/glacier/handler_data_retrieval_policy_test.go +++ b/services/glacier/handler_data_retrieval_policy_test.go @@ -1,13 +1,15 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDataRetrievalPolicy(t *testing.T) { @@ -43,7 +45,7 @@ func TestDataRetrievalPolicy(t *testing.T) { if tt.wantPolicy { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Policy") } }) @@ -86,7 +88,7 @@ func TestDataRetrievalPolicy_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.NotEmpty(t, got) }) } @@ -112,7 +114,7 @@ func TestDataRetrievalPolicy_DefaultFreeTier(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) policy, ok := got["Policy"].(map[string]any) require.True(t, ok) @@ -198,7 +200,7 @@ func TestDataRetrievalPolicy_GetDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) rules := policy["Rules"].([]any) @@ -269,7 +271,7 @@ func TestDataRetrievalPolicy_SetAndGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) rules := policy["Rules"].([]any) require.NotEmpty(t, rules) diff --git a/services/glacier/handler_job_output_test.go b/services/glacier/handler_job_output_test.go index 6046bdecfe..55d51dde09 100644 --- a/services/glacier/handler_job_output_test.go +++ b/services/glacier/handler_job_output_test.go @@ -2,7 +2,7 @@ package glacier_test import ( "encoding/csv" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -50,7 +51,7 @@ func TestGetJobOutput_ArchiveDescriptionHeader(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) rec = doRequest(t, h, http.MethodGet, @@ -203,7 +204,7 @@ func TestInventoryCSV_RFC4180QuotedDescriptions(t *testing.T) { require.Equal(t, http.StatusAccepted, jobRec.Code) var jobResp map[string]string - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp, jsonx.V1())) jobID := jobResp["jobId"] require.NotEmpty(t, jobID) @@ -242,7 +243,7 @@ func TestInventoryCSV_DescriptionWithDoubleQuote(t *testing.T) { require.Equal(t, http.StatusAccepted, jobRec.Code) var jobResp map[string]string - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp, jsonx.V1())) jobID := jobResp["jobId"] outRec := doRequest(t, h, http.MethodGet, @@ -278,7 +279,7 @@ func TestGetJobOutput_CompletedFilter_Integration(t *testing.T) { require.Equal(t, http.StatusAccepted, jobRec.Code) var jr map[string]string - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr, jsonx.V1())) jobID := jr["jobId"] require.NotEmpty(t, jobID) @@ -340,7 +341,7 @@ func TestGetJobOutput_SHA256Header(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) rec = doRequest(t, h, http.MethodGet, @@ -361,7 +362,7 @@ func uploadArchiveData(t *testing.T, h *glacier.Handler, vaultName string, data require.NoError(t, h.Handler()(c)) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["archiveId"] require.NotEmpty(t, id) @@ -375,7 +376,7 @@ func initiateJobWithBody(t *testing.T, h *glacier.Handler, vaultName, body strin rec := doRequestWithHeaders(t, h, http.MethodPost, "/"+testAccountID+"/vaults/"+vaultName+"/jobs", body, nil) require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["jobId"] require.NotEmpty(t, id) @@ -413,7 +414,7 @@ func TestArchiveRetrieval_FullLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/arch-lifecycle/jobs/"+jobID, "", nil) require.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "Succeeded", desc["StatusCode"]) assert.Equal(t, true, desc["Completed"]) @@ -551,7 +552,7 @@ func TestInventoryRetrieval_JSONLifecycle(t *testing.T) { assert.Equal(t, "application/json", rec.Header().Get("Content-Type")) var inv map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inv)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inv, jsonx.V1())) archList, ok := inv["ArchiveList"].([]any) require.True(t, ok) assert.Len(t, archList, tt.archiveCount) @@ -634,7 +635,7 @@ func TestInventoryRetrieval_InventorySizeInBytes(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &desc, jsonx.V1())) raw, present := desc["InventorySizeInBytes"] assert.True(t, present, "InventorySizeInBytes must be present after GetJobOutput") got := int64(raw.(float64)) @@ -663,7 +664,7 @@ func TestInventoryRetrieval_LastInventoryDateUpdated(t *testing.T) { rec := doRequestWithHeaders(t, h, http.MethodGet, "/"+testAccountID+"/vaults/lastinv-vault", "", nil) require.Equal(t, http.StatusOK, rec.Code) var vaultDesc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vaultDesc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vaultDesc, jsonx.V1())) assert.Empty(t, vaultDesc["LastInventoryDate"]) initiateJobWithBody(t, h, "lastinv-vault", `{"Type":"inventory-retrieval"}`) @@ -671,7 +672,7 @@ func TestInventoryRetrieval_LastInventoryDateUpdated(t *testing.T) { // After job: LastInventoryDate set. rec = doRequestWithHeaders(t, h, http.MethodGet, "/"+testAccountID+"/vaults/lastinv-vault", "", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vaultDesc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vaultDesc, jsonx.V1())) assert.NotEmpty(t, vaultDesc["LastInventoryDate"], tt.name) }) } diff --git a/services/glacier/handler_jobs.go b/services/glacier/handler_jobs.go index cc0ec7f1a6..2e34357979 100644 --- a/services/glacier/handler_jobs.go +++ b/services/glacier/handler_jobs.go @@ -3,7 +3,7 @@ package glacier import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -11,11 +11,13 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleInitiateJob(c *echo.Context, vaultName string, body []byte) error { var req initiateJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -265,7 +267,7 @@ func (h *Handler) writeInventoryJSON(c *echo.Context, j *Job, vaultName string, "VaultARN": j.VaultARN, "InventoryDate": j.CompletionDate, "ArchiveList": items, - }) + }, jsonx.V1()) if err != nil { return h.writeError( c, diff --git a/services/glacier/handler_jobs_test.go b/services/glacier/handler_jobs_test.go index 4452779c4c..312e0c0cb5 100644 --- a/services/glacier/handler_jobs_test.go +++ b/services/glacier/handler_jobs_test.go @@ -1,7 +1,8 @@ package glacier_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -48,7 +50,7 @@ func TestInitiateListDescribeJob(t *testing.T) { assert.Equal(t, http.StatusAccepted, rec.Code) var jobResp map[string]any - err := json.Unmarshal(rec.Body.Bytes(), &jobResp) + err := json.Unmarshal(rec.Body.Bytes(), &jobResp, jsonx.V1()) require.NoError(t, err) jobID := jobResp["jobId"].(string) @@ -63,7 +65,7 @@ func TestInitiateListDescribeJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - err = json.Unmarshal(rec.Body.Bytes(), &descResp) + err = json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1()) require.NoError(t, err) assert.Equal(t, jobID, descResp["JobId"]) @@ -122,7 +124,7 @@ func TestJobTier_StoredInDescribeJob(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) rec = doRequest(t, h, http.MethodGet, @@ -130,7 +132,7 @@ func TestJobTier_StoredInDescribeJob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Bulk", descResp["Tier"]) } @@ -150,7 +152,7 @@ func TestInventoryJob_UpdatesLastInventoryDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) _, hasDate := desc["LastInventoryDate"] assert.False(t, hasDate, "LastInventoryDate should not be set before first inventory") @@ -165,7 +167,7 @@ func TestInventoryJob_UpdatesLastInventoryDate(t *testing.T) { "/"+testAccountID+"/vaults/inv-date-vault", "") require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) lastInventory, ok := desc["LastInventoryDate"] assert.True(t, ok, "LastInventoryDate should be set after inventory job") assert.NotEmpty(t, lastInventory) @@ -184,7 +186,7 @@ func TestArchiveJob_DoesNotUpdateLastInventoryDate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var archResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp, jsonx.V1())) archiveID := archResp["archiveId"].(string) // Initiate archive-retrieval job. @@ -244,7 +246,7 @@ func TestListJobs_LimitAndMarker(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobList := resp["JobList"] if jobList == nil { @@ -304,7 +306,7 @@ func TestArchiveRetrievalJob_StoresRetrievalByteRange(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var archResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp, jsonx.V1())) archiveID := archResp["archiveId"].(string) // Initiate archive retrieval with RetrievalByteRange. @@ -314,7 +316,7 @@ func TestArchiveRetrievalJob_StoresRetrievalByteRange(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) // DescribeJob should reflect the stored range. @@ -323,7 +325,7 @@ func TestArchiveRetrievalJob_StoresRetrievalByteRange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) // The RetrievalByteRange field is forwarded from the request. _ = descResp } @@ -468,7 +470,7 @@ func TestDescribeJob_ArchiveSizeInBytes(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) rec = doRequest( @@ -481,7 +483,7 @@ func TestDescribeJob_ArchiveSizeInBytes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var jobResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp, jsonx.V1())) if tt.wantSizePresent { assert.NotNil(t, jobResp["ArchiveSizeInBytes"]) } @@ -540,7 +542,7 @@ func TestDescribeJob_ArchiveSHA256TreeHash(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"].(string) rec = doRequest(t, h, http.MethodGet, @@ -548,7 +550,7 @@ func TestDescribeJob_ArchiveSHA256TreeHash(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var jobResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp, jsonx.V1())) if tt.wantArchiveSHA { assert.Equal(t, "cafebabe", jobResp["ArchiveSHA256TreeHash"], @@ -594,7 +596,7 @@ func initiateJob(t *testing.T, h *glacier.Handler, vaultName, jobType string) st require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobID, ok := resp["jobId"].(string) require.True(t, ok, "jobId missing from initiate response") @@ -635,7 +637,7 @@ func TestInitiateJob_StartsInProgress(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "InProgress", desc["StatusCode"]) }) } @@ -678,7 +680,7 @@ func TestInitiateJob_SucceedsAfterDelay(t *testing.T) { ) require.Equal(t, http.StatusOK, recEarly.Code) var earlyDesc map[string]any - require.NoError(t, json.Unmarshal(recEarly.Body.Bytes(), &earlyDesc)) + require.NoError(t, json.Unmarshal(recEarly.Body.Bytes(), &earlyDesc, jsonx.V1())) assert.Equal(t, "InProgress", earlyDesc["StatusCode"]) // After the delay elapses the job should be Succeeded. @@ -687,7 +689,7 @@ func TestInitiateJob_SucceedsAfterDelay(t *testing.T) { recLate := doRequest(t, h, http.MethodGet, "/"+testAccountID+"/vaults/"+tt.vaultName+"/jobs/"+jobID, "") require.Equal(t, http.StatusOK, recLate.Code) var lateDesc map[string]any - require.NoError(t, json.Unmarshal(recLate.Body.Bytes(), &lateDesc)) + require.NoError(t, json.Unmarshal(recLate.Body.Bytes(), &lateDesc, jsonx.V1())) assert.Equal(t, "Succeeded", lateDesc["StatusCode"]) }) }) @@ -721,7 +723,7 @@ func TestInitiateJob_ZeroDelay_ImmediateSucceeded(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "Succeeded", desc["StatusCode"]) }) } @@ -762,8 +764,8 @@ func TestListJobs_JobListAlwaysPresent(t *testing.T) { "/"+testAccountID+"/vaults/listjobs-audit-vault/jobs", "") require.Equal(t, http.StatusOK, rec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, present := resp["JobList"] assert.True(t, present, "JobList key must always be present in ListJobs response") @@ -821,7 +823,7 @@ func TestDescribeJob_SNSTopicPresent(t *testing.T) { require.Equal(t, http.StatusAccepted, initRec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"] require.NotEmpty(t, jobID) @@ -829,18 +831,18 @@ func TestDescribeJob_SNSTopicPresent(t *testing.T) { "/"+testAccountID+"/vaults/snstopic-audit-vault/jobs/"+jobID, "") require.Equal(t, http.StatusOK, descRec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) snsRaw, present := resp["SNSTopic"] if tt.wantPresent { assert.True(t, present, "SNSTopic must be present when job was initiated with SNSTopic") var got string - require.NoError(t, json.Unmarshal(snsRaw, &got)) + require.NoError(t, json.Unmarshal(snsRaw, &got, jsonx.V1())) assert.Equal(t, tt.wantSNSTopic, got) } else if present { var got string - require.NoError(t, json.Unmarshal(snsRaw, &got)) + require.NoError(t, json.Unmarshal(snsRaw, &got, jsonx.V1())) assert.Empty(t, got, "SNSTopic should be empty or absent when not set") } }) @@ -889,7 +891,7 @@ func TestDescribeJob_RetrievalByteRange(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var archResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &archResp, jsonx.V1())) archiveID := archResp["archiveId"] require.NotEmpty(t, archiveID) @@ -906,7 +908,7 @@ func TestDescribeJob_RetrievalByteRange(t *testing.T) { require.Equal(t, http.StatusAccepted, initRec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(initRec.Body.Bytes(), &initResp, jsonx.V1())) jobID := initResp["jobId"] require.NotEmpty(t, jobID) @@ -914,18 +916,18 @@ func TestDescribeJob_RetrievalByteRange(t *testing.T) { "/"+testAccountID+"/vaults/byterange-audit-vault/jobs/"+jobID, "") require.Equal(t, http.StatusOK, descRec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) rangeRaw, present := resp["RetrievalByteRange"] if tt.wantInResp { assert.True(t, present, "RetrievalByteRange must be present when set on the job") var got string - require.NoError(t, json.Unmarshal(rangeRaw, &got)) + require.NoError(t, json.Unmarshal(rangeRaw, &got, jsonx.V1())) assert.Equal(t, tt.byteRange, got) } else if present { var got string - require.NoError(t, json.Unmarshal(rangeRaw, &got)) + require.NoError(t, json.Unmarshal(rangeRaw, &got, jsonx.V1())) assert.Empty(t, got, "RetrievalByteRange should be empty or absent when not set") } }) @@ -1020,7 +1022,7 @@ func TestListJobs_CompletedFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs := resp["JobList"].([]any) assert.Len(t, jobs, tt.wantCount) }) @@ -1054,7 +1056,7 @@ func TestListJobs_StatusCodeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs := resp["JobList"].([]any) assert.Len(t, jobs, tt.wantCount) }) @@ -1127,7 +1129,7 @@ func TestDescribeJob_Fidelity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantAction, resp["Action"]) assert.Equal(t, tt.wantTier, resp["Tier"]) assert.NotEmpty(t, resp["JobId"]) @@ -1164,7 +1166,7 @@ func TestDescribeJob_ArchiveSizePopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) archiveSize, ok := resp["ArchiveSizeInBytes"].(float64) assert.True(t, ok, "ArchiveSizeInBytes must be present for archive-retrieval job") assert.InDelta(t, float64(len(tt.content)), archiveSize, 0) diff --git a/services/glacier/handler_multipart_uploads_test.go b/services/glacier/handler_multipart_uploads_test.go index 06b76914fa..12755b75b8 100644 --- a/services/glacier/handler_multipart_uploads_test.go +++ b/services/glacier/handler_multipart_uploads_test.go @@ -1,7 +1,8 @@ package glacier_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -83,7 +85,7 @@ func TestInitiateMultipartUpload(t *testing.T) { if tt.wantUploadID { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["uploadId"]) uploadID := rec.Header().Get("X-Amz-Multipart-Upload-Id") @@ -257,7 +259,7 @@ func TestCompleteMultipartUpload(t *testing.T) { if tt.wantArchive { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["archiveId"]) assert.NotEmpty(t, rec.Header().Get("X-Amz-Archive-Id")) } @@ -377,7 +379,7 @@ func TestListMultipartUploads(t *testing.T) { var resp struct { UploadsList []any `json:"UploadsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.UploadsList, tt.wantCount) }) } @@ -469,7 +471,7 @@ func TestListParts(t *testing.T) { var resp struct { Parts []any `json:"Parts"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Parts, tt.wantParts) } }) @@ -541,7 +543,7 @@ func TestMultipartUpload_FullRoundTrip(t *testing.T) { var partsResp struct { Parts []any `json:"Parts"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &partsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &partsResp, jsonx.V1())) assert.Len(t, partsResp.Parts, 1) // List uploads — should have 1 @@ -551,7 +553,7 @@ func TestMultipartUpload_FullRoundTrip(t *testing.T) { var uploadsResp struct { UploadsList []any `json:"UploadsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp, jsonx.V1())) assert.Len(t, uploadsResp.UploadsList, 1) // Complete the upload @@ -567,13 +569,13 @@ func TestMultipartUpload_FullRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var completeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &completeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &completeResp, jsonx.V1())) assert.NotEmpty(t, completeResp["archiveId"]) // After completion, list uploads should be empty rec = doRequest(t, h, http.MethodGet, "/-/vaults/"+tt.vaultName+"/multipart-uploads", "") require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp, jsonx.V1())) assert.Empty(t, uploadsResp.UploadsList) }) } @@ -818,7 +820,7 @@ func TestUploadMultipartPart_RequiresContentRange(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] require.NotEmpty(t, uploadID) @@ -893,7 +895,7 @@ func TestCompleteMultipartUpload_RequiresHeaders(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] require.NotEmpty(t, uploadID) @@ -953,7 +955,7 @@ func TestListMultipartUploads_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) uploads := resp["UploadsList"].([]any) assert.Len(t, uploads, 2) @@ -1007,7 +1009,7 @@ func TestListParts_Pagination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var upResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &upResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &upResp, jsonx.V1())) uploadID := upResp["uploadId"].(string) // Upload 3 parts. @@ -1029,7 +1031,7 @@ func TestListParts_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var partsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &partsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &partsResp, jsonx.V1())) parts := partsResp["Parts"].([]any) require.Len(t, parts, 3) @@ -1039,7 +1041,7 @@ func TestListParts_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var pPage1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pPage1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pPage1, jsonx.V1())) assert.Len(t, pPage1["Parts"].([]any), 1) assert.NotEmpty(t, pPage1["Marker"]) } @@ -1082,7 +1084,7 @@ func TestListParts_PartsAlwaysArray(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] require.NotEmpty(t, uploadID) @@ -1101,8 +1103,8 @@ func TestListParts_PartsAlwaysArray(t *testing.T) { "/"+testAccountID+"/vaults/listparts-audit-vault/multipart-uploads/"+uploadID, "") require.Equal(t, http.StatusOK, listRec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) partsRaw, present := resp["Parts"] assert.True(t, present, "Parts key must be present in ListParts response") @@ -1150,7 +1152,7 @@ func TestMultipartUpload_FullLifecycle(t *testing.T) { "", headers) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] require.NotEmpty(t, uploadID) // Location header must be set. @@ -1175,7 +1177,7 @@ func TestMultipartUpload_FullLifecycle(t *testing.T) { "", nil) require.Equal(t, http.StatusOK, rec2.Code) var listParts map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listParts)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listParts, jsonx.V1())) parts := listParts["Parts"].([]any) assert.Len(t, parts, 1) @@ -1189,7 +1191,7 @@ func TestMultipartUpload_FullLifecycle(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec3.Code) var completeResp map[string]string - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &completeResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &completeResp, jsonx.V1())) archiveID := completeResp["archiveId"] assert.NotEmpty(t, archiveID) assert.Equal(t, checksum, rec3.Header().Get("X-Amz-Sha256-Tree-Hash")) @@ -1199,7 +1201,7 @@ func TestMultipartUpload_FullLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/mp-lifecycle-"+tt.name+"/multipart-uploads", "", nil) require.Equal(t, http.StatusOK, rec4.Code) var listUploads map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &listUploads)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &listUploads, jsonx.V1())) uploads := listUploads["UploadsList"].([]any) assert.Empty(t, uploads) @@ -1215,7 +1217,7 @@ func TestMultipartUpload_FullLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/mp-lifecycle-"+tt.name, "", nil) require.Equal(t, http.StatusOK, descVault.Code) var vaultDesc map[string]any - require.NoError(t, json.Unmarshal(descVault.Body.Bytes(), &vaultDesc)) + require.NoError(t, json.Unmarshal(descVault.Body.Bytes(), &vaultDesc, jsonx.V1())) assert.EqualValues(t, 1, vaultDesc["NumberOfArchives"]) }) } @@ -1242,7 +1244,7 @@ func TestMultipartUpload_AbortLifecycle(t *testing.T) { "", map[string]string{"X-Amz-Part-Size": "1048576"}) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] // Abort. @@ -1255,7 +1257,7 @@ func TestMultipartUpload_AbortLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/mp-abort-vault/multipart-uploads", "", nil) require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) uploads := listResp["UploadsList"].([]any) assert.Empty(t, uploads, tt.name) @@ -1293,7 +1295,7 @@ func TestListParts_MarkerNotFound(t *testing.T) { map[string]string{"X-Amz-Part-Size": "1048576"}) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] require.NotEmpty(t, uploadID) @@ -1303,8 +1305,8 @@ func TestListParts_MarkerNotFound(t *testing.T) { "", nil) require.Equal(t, http.StatusOK, rec2.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) partsRaw := resp["Parts"] assert.Equal(t, "[]", string(partsRaw), tt.name) }) @@ -1338,7 +1340,7 @@ func TestListParts_MarkerPagination(t *testing.T) { "", map[string]string{"X-Amz-Part-Size": "1048576"}) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] // Upload 2 parts. @@ -1363,7 +1365,7 @@ func TestListParts_MarkerPagination(t *testing.T) { "", nil) require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) parts1 := page1["Parts"].([]any) require.Len(t, parts1, 1) markerVal, hasMarker := page1["Marker"].(string) @@ -1375,7 +1377,7 @@ func TestListParts_MarkerPagination(t *testing.T) { rec = doRequestWithHeaders(t, h, http.MethodGet, secondPage, "", nil) require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) parts2 := page2["Parts"].([]any) assert.Len(t, parts2, 1) _, hasMarker2 := page2["Marker"] diff --git a/services/glacier/handler_provisioned_capacity_test.go b/services/glacier/handler_provisioned_capacity_test.go index d59ad91ac9..9ea26411e5 100644 --- a/services/glacier/handler_provisioned_capacity_test.go +++ b/services/glacier/handler_provisioned_capacity_test.go @@ -1,7 +1,7 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -51,7 +52,7 @@ func TestListProvisionedCapacity(t *testing.T) { var resp struct { ProvisionedCapacityList []any `json:"ProvisionedCapacityList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ProvisionedCapacityList, tt.wantCount) }) } @@ -84,7 +85,7 @@ func TestPurchaseProvisionedCapacity(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["capacityId"]) assert.NotEmpty(t, rec.Header().Get("X-Amz-Capacity-Id")) }) @@ -113,7 +114,7 @@ func TestProvisionedCapacity_MaxTwoPerAccount(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "LimitExceededException", errResp["code"]) } @@ -139,7 +140,7 @@ func TestProvisionedCapacity_ExpiresAfterOneMonth(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) capList := resp["ProvisionedCapacityList"].([]any) require.Len(t, capList, 1) @@ -222,7 +223,7 @@ func TestProvisionedCapacity_PurchaseAndList(t *testing.T) { "/"+testAccountID+"/provisioned-capacity", "", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list := resp["ProvisionedCapacityList"].([]any) assert.Len(t, list, tt.wantCount) }) @@ -274,7 +275,7 @@ func TestProvisionedCapacity_DatesPresent(t *testing.T) { "/"+testAccountID+"/provisioned-capacity", "", nil) require.Equal(t, http.StatusCreated, rec.Code) var purchaseResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &purchaseResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &purchaseResp, jsonx.V1())) capID := purchaseResp["capacityId"] require.NotEmpty(t, capID) @@ -282,7 +283,7 @@ func TestProvisionedCapacity_DatesPresent(t *testing.T) { "/"+testAccountID+"/provisioned-capacity", "", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list := listResp["ProvisionedCapacityList"].([]any) require.Len(t, list, 1) capItem := list[0].(map[string]any) diff --git a/services/glacier/handler_tags.go b/services/glacier/handler_tags.go index 84acc34460..902f142035 100644 --- a/services/glacier/handler_tags.go +++ b/services/glacier/handler_tags.go @@ -1,15 +1,17 @@ package glacier import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddTagsToVault(c *echo.Context, vaultName string, body []byte) error { var req addTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -36,7 +38,7 @@ func (h *Handler) handleListTagsForVault(c *echo.Context, vaultName string) erro func (h *Handler) handleRemoveTagsFromVault(c *echo.Context, vaultName string, body []byte) error { var req removeTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/glacier/handler_tags_test.go b/services/glacier/handler_tags_test.go index af667371bd..0e88b8b20a 100644 --- a/services/glacier/handler_tags_test.go +++ b/services/glacier/handler_tags_test.go @@ -1,7 +1,7 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags(t *testing.T) { @@ -56,7 +58,7 @@ func TestTags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - err = json.Unmarshal(rec.Body.Bytes(), &tagsResp) + err = json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1()) require.NoError(t, err) tags := tagsResp["Tags"].(map[string]any) @@ -118,7 +120,7 @@ func TestTags_KeyValidation(t *testing.T) { h := newTestHandler() createVault(t, h, "tag-val-vault") - tagsJSON, _ := json.Marshal(tt.tags) + tagsJSON, _ := json.Marshal(tt.tags, jsonx.V1()) body := fmt.Sprintf(`{"Tags":%s}`, tagsJSON) rec := doRequest(t, h, http.MethodPost, "/"+testAccountID+"/vaults/tag-val-vault/tags?operation=add", body) @@ -155,7 +157,7 @@ func TestTags_ExactLimitAccepted(t *testing.T) { tags[fmt.Sprintf("key-%02d", i)] = fmt.Sprintf("val-%02d", i) } - body, err := json.Marshal(map[string]any{"Tags": tags}) + body, err := json.Marshal(map[string]any{"Tags": tags}, jsonx.V1()) require.NoError(t, err) rec := doRequestWithHeaders(t, h, http.MethodPost, @@ -248,7 +250,7 @@ func TestTags_ListTagsEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].(map[string]any) assert.True(t, ok, tt.name) assert.Empty(t, tags) diff --git a/services/glacier/handler_test.go b/services/glacier/handler_test.go index 6124101b8f..7a7653724d 100644 --- a/services/glacier/handler_test.go +++ b/services/glacier/handler_test.go @@ -1,7 +1,8 @@ package glacier_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -230,7 +232,7 @@ func TestHandlerReset(t *testing.T) { var out struct { VaultList []any `json:"VaultList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.VaultList, tt.wantAfter) }) } @@ -582,7 +584,7 @@ func TestErrorResponse_IncludesTypeField(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.NotEmpty(t, errBody["code"], "error body should have code field") assert.NotEmpty(t, errBody["__type"], "error body should have __type field") @@ -646,7 +648,7 @@ func TestErrorResponse_FormatFields(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) // Both "code" and "__type" must be present (SDK compatibility). assert.Equal(t, tt.wantCodeKey, errResp["code"]) assert.Equal(t, tt.wantCodeKey, errResp["__type"]) @@ -732,8 +734,8 @@ func TestPagination_MarkerNotFound_EmptyList(t *testing.T) { rec := doRequestWithHeaders(t, h, tt.method, tt.path, "", nil) require.Equal(t, http.StatusOK, rec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, ok := resp[tt.jsonKey] assert.True(t, ok, "%s key must be present", tt.jsonKey) assert.Equal(t, "[]", string(raw), "%s must be [] not null when marker not found", tt.jsonKey) diff --git a/services/glacier/handler_vault_access_policy.go b/services/glacier/handler_vault_access_policy.go index 3aae3be999..23ca7c2666 100644 --- a/services/glacier/handler_vault_access_policy.go +++ b/services/glacier/handler_vault_access_policy.go @@ -1,15 +1,17 @@ package glacier import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleSetVaultAccessPolicy(c *echo.Context, vaultName string, body []byte) error { var req vaultAccessPolicy - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/glacier/handler_vault_access_policy_test.go b/services/glacier/handler_vault_access_policy_test.go index f7a7293fd1..347c9dff80 100644 --- a/services/glacier/handler_vault_access_policy_test.go +++ b/services/glacier/handler_vault_access_policy_test.go @@ -1,13 +1,15 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAccessPolicy(t *testing.T) { @@ -87,7 +89,7 @@ func TestAccessPolicy_SetGetDelete(t *testing.T) { "/"+testAccountID+"/vaults/access-policy-vault/access-policy", "", nil) require.Equal(t, http.StatusOK, rec.Code) var policyResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp, jsonx.V1())) assert.NotEmpty(t, policyResp["Policy"]) // DELETE. diff --git a/services/glacier/handler_vault_lock.go b/services/glacier/handler_vault_lock.go index 8fe7ed7509..d15a1784c7 100644 --- a/services/glacier/handler_vault_lock.go +++ b/services/glacier/handler_vault_lock.go @@ -1,10 +1,12 @@ package glacier import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleVaultLock(c *echo.Context, op, resource string, body []byte) error { @@ -20,7 +22,7 @@ func (h *Handler) handleVaultLock(c *echo.Context, op, resource string, body []b case opInitiateVaultLock: var req vaultLockPolicyRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid request body: "+err.Error()) } diff --git a/services/glacier/handler_vault_lock_test.go b/services/glacier/handler_vault_lock_test.go index a0134caba4..8384329043 100644 --- a/services/glacier/handler_vault_lock_test.go +++ b/services/glacier/handler_vault_lock_test.go @@ -1,7 +1,7 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -65,7 +66,7 @@ func TestGetVaultLock(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantState, resp["State"]) } }) @@ -276,7 +277,7 @@ func TestCompleteVaultLock_Success(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) lockID := resp["lockId"] require.NotEmpty(t, lockID) @@ -316,7 +317,7 @@ func TestInitiateVaultLock_ReadsPolicy(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["lockId"]) }) } @@ -384,7 +385,7 @@ func TestVaultLock_CompleteClearsExpirationDate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var lockResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockResp, jsonx.V1())) lockID := lockResp["lockId"].(string) rec = doRequest(t, h, http.MethodPost, @@ -396,7 +397,7 @@ func TestVaultLock_CompleteClearsExpirationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "Locked", getResp["State"]) // ExpirationDate must be absent after completing a lock per AWS spec. _, hasExpiration := getResp["ExpirationDate"] @@ -420,7 +421,7 @@ func TestVaultLock_LockedStateHasNoExpirationDate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) lockID := initResp["lockId"].(string) // InProgress state should have ExpirationDate. @@ -429,7 +430,7 @@ func TestVaultLock_LockedStateHasNoExpirationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var inProgressResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inProgressResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inProgressResp, jsonx.V1())) assert.Equal(t, "InProgress", inProgressResp["State"]) assert.NotEmpty(t, inProgressResp["ExpirationDate"], "InProgress lock should have ExpirationDate") @@ -444,7 +445,7 @@ func TestVaultLock_LockedStateHasNoExpirationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var lockedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockedResp, jsonx.V1())) assert.Equal(t, "Locked", lockedResp["State"]) exp, hasExp := lockedResp["ExpirationDate"] @@ -533,7 +534,7 @@ func TestVaultLock_FullLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/lock-lifecycle-vault/lock-policy", body, nil) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) lockID := initResp["lockId"] require.NotEmpty(t, lockID) @@ -542,7 +543,7 @@ func TestVaultLock_FullLifecycle(t *testing.T) { "/"+testAccountID+"/vaults/lock-lifecycle-vault/lock-policy", "", nil) require.Equal(t, http.StatusOK, rec.Code) var lockState map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockState)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockState, jsonx.V1())) assert.Equal(t, "InProgress", lockState["State"]) assert.NotEmpty(t, lockState["ExpirationDate"]) @@ -555,7 +556,7 @@ func TestVaultLock_FullLifecycle(t *testing.T) { rec = doRequestWithHeaders(t, h, http.MethodGet, "/"+testAccountID+"/vaults/lock-lifecycle-vault/lock-policy", "", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockState)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lockState, jsonx.V1())) assert.Equal(t, "Locked", lockState["State"], tt.name) }) } diff --git a/services/glacier/handler_vault_notifications.go b/services/glacier/handler_vault_notifications.go index b582d32f86..7890decc67 100644 --- a/services/glacier/handler_vault_notifications.go +++ b/services/glacier/handler_vault_notifications.go @@ -1,10 +1,12 @@ package glacier import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleSetVaultNotifications( @@ -13,7 +15,7 @@ func (h *Handler) handleSetVaultNotifications( body []byte, ) error { var req vaultNotificationConfig - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/glacier/handler_vault_notifications_test.go b/services/glacier/handler_vault_notifications_test.go index c52373957e..68b2388ac3 100644 --- a/services/glacier/handler_vault_notifications_test.go +++ b/services/glacier/handler_vault_notifications_test.go @@ -1,13 +1,15 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestNotifications(t *testing.T) { @@ -96,7 +98,7 @@ func TestVaultNotifications_EventValidation(t *testing.T) { h := newTestHandler() createVault(t, h, "notif-vault") - eventsJSON, _ := json.Marshal(tt.events) + eventsJSON, _ := json.Marshal(tt.events, jsonx.V1()) body := fmt.Sprintf(`{"SNSTopic":"arn:aws:sns:us-east-1:000000000000:test","Events":%s}`, eventsJSON) rec := doRequest(t, h, http.MethodPut, "/"+testAccountID+"/vaults/notif-vault/notification-configuration", body) @@ -195,7 +197,7 @@ func TestVaultNotifications_SetGetDelete(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) // SET. - eventsJSON, _ := json.Marshal(tt.events) + eventsJSON, _ := json.Marshal(tt.events, jsonx.V1()) body := `{"SNSTopic":"` + tt.topic + `","Events":` + string(eventsJSON) + `}` rec = doRequestWithHeaders(t, h, http.MethodPut, "/"+testAccountID+"/vaults/notif-vault-"+tt.name+"/notification-configuration", body, nil) @@ -206,7 +208,7 @@ func TestVaultNotifications_SetGetDelete(t *testing.T) { "/"+testAccountID+"/vaults/notif-vault-"+tt.name+"/notification-configuration", "", nil) require.Equal(t, http.StatusOK, rec.Code) var notifResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ¬ifResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ¬ifResp, jsonx.V1())) assert.Equal(t, tt.topic, notifResp["SNSTopic"]) events, ok := notifResp["Events"].([]any) require.True(t, ok) diff --git a/services/glacier/handler_vaults_test.go b/services/glacier/handler_vaults_test.go index d478f9a5b7..7372536fe1 100644 --- a/services/glacier/handler_vaults_test.go +++ b/services/glacier/handler_vaults_test.go @@ -2,7 +2,8 @@ package glacier_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -46,7 +48,7 @@ func TestCreateDescribeDeleteVault(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var describeResp map[string]any - err := json.Unmarshal(rec.Body.Bytes(), &describeResp) + err := json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1()) require.NoError(t, err) assert.Equal(t, tt.vaultName, describeResp["VaultName"]) @@ -218,7 +220,7 @@ func TestListVaults_AfterReset(t *testing.T) { VaultList []any `json:"VaultList"` } - err := json.NewDecoder(rec.Body).Decode(&resp) + err := json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1()) require.NoError(t, err) assert.Len(t, resp.VaultList, tt.wantCount) @@ -237,7 +239,7 @@ func TestAccountIDDash_SubstitutedInListVaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vaultList := resp["VaultList"].([]any) assert.Len(t, vaultList, 1) } @@ -253,7 +255,7 @@ func TestAccountIDReal_WorksLikeDash(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vaultList := resp["VaultList"].([]any) assert.Len(t, vaultList, 1) } @@ -297,7 +299,7 @@ func TestListVaults_LimitValidation(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantLen > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vaultList := resp["VaultList"].([]any) assert.Len(t, vaultList, tt.wantLen) } @@ -320,7 +322,7 @@ func TestListVaults_MarkerPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) list1 := page1["VaultList"].([]any) assert.Len(t, list1, 2) @@ -334,7 +336,7 @@ func TestListVaults_MarkerPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) list2 := page2["VaultList"].([]any) assert.Len(t, list2, 2) @@ -465,7 +467,7 @@ func uploadArchiveHTTP(t *testing.T, h *glacier.Handler, vaultName string) strin require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp["archiveId"]) return resp["archiveId"] @@ -495,7 +497,7 @@ func assertVaultDeleteRejected(t *testing.T, h *glacier.Handler, vaultName strin require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["code"]) descRec := doRequest(t, h, http.MethodGet, "/"+testAccountID+"/vaults/"+vaultName, "") @@ -579,7 +581,7 @@ func TestDeleteVault_InventorySemantics(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["code"]) descRec := doRequest(t, h, http.MethodGet, "/"+testAccountID+"/vaults/"+vaultName, "") @@ -720,7 +722,7 @@ func TestDeleteVault_WithActiveMultipartUploads(t *testing.T) { "", map[string]string{"X-Amz-Part-Size": "1048576"}) require.Equal(t, http.StatusCreated, rec.Code) var initResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &initResp, jsonx.V1())) uploadID := initResp["uploadId"] // Delete vault (empty archives = ok, multipart uploads get cleaned). @@ -767,7 +769,7 @@ func TestCreateVault_Idempotent(t *testing.T) { rec := doRequestWithHeaders(t, h, http.MethodGet, "/"+testAccountID+"/vaults", "", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) vl := listResp["VaultList"].([]any) assert.Len(t, vl, 1) }) @@ -847,7 +849,7 @@ func TestDescribeVault_ArchiveStatsAsOfInventory(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/"+testAccountID+"/vaults/"+vaultName, "") require.Equal(t, http.StatusOK, rec.Code) var v map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &v)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &v, jsonx.V1())) if tt.wantAbsent { _, hasArchives := v["NumberOfArchives"] @@ -946,7 +948,7 @@ func TestVault_CrossAccountIsolation(t *testing.T) { listRecB := doRequestWithHeaders(t, hB, http.MethodGet, "/account-bbb/vaults", "", nil) require.Equal(t, http.StatusOK, listRecB.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRecB.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRecB.Body.Bytes(), &listResp, jsonx.V1())) vl := listResp["VaultList"].([]any) require.Len(t, vl, 1, tt.name) v := vl[0].(map[string]any) @@ -990,7 +992,7 @@ func TestVault_CrossRegionIsolation(t *testing.T) { recW := doRequestWithHeaders(t, hW, http.MethodGet, "/same-acct/vaults", "", nil) require.Equal(t, http.StatusOK, recW.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(recW.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recW.Body.Bytes(), &listResp, jsonx.V1())) vl := listResp["VaultList"].([]any) assert.Empty(t, vl, tt.name) }) @@ -1023,7 +1025,7 @@ func TestVaultARN_Format(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["VaultARN"].(string) assert.NotEmpty(t, arn) wantARN := "arn:aws:glacier:" + testRegion + ":" + testAccountID + ":vaults/" + tt.vaultName @@ -1092,7 +1094,7 @@ func TestListVaults_LimitAndMarkerCombined(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list := resp["VaultList"].([]any) require.Len(t, list, len(tt.wantNames)) for i, want := range tt.wantNames { diff --git a/services/glacier/inventory_retrieval_test.go b/services/glacier/inventory_retrieval_test.go index 80731a6bc9..e6fbb1123c 100644 --- a/services/glacier/inventory_retrieval_test.go +++ b/services/glacier/inventory_retrieval_test.go @@ -1,13 +1,14 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -51,7 +52,7 @@ func inventoryArchiveIDs(t *testing.T, body []byte) []string { ArchiveID string `json:"ArchiveId"` } `json:"ArchiveList"` } - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) ids := make([]string, len(resp.ArchiveList)) for i, a := range resp.ArchiveList { @@ -177,7 +178,7 @@ func TestInitiateJob_InventoryRetrieval_InvalidParameters(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["code"]) }) } @@ -200,7 +201,7 @@ func TestDescribeJob_InventoryRetrieval_EchoesParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasTopLevelFormat := resp["Format"] assert.False(t, hasTopLevelFormat, "top-level Format is not a real GlacierJobDescription field") @@ -231,7 +232,7 @@ func TestDescribeJob_ArchiveRetrieval_NoInventoryRetrievalParameters(t *testing. require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, has := resp["InventoryRetrievalParameters"] assert.False(t, has) diff --git a/services/glacier/oldshape_restore_test.go b/services/glacier/oldshape_restore_test.go index 8a4d015adc..cd1ded1d2d 100644 --- a/services/glacier/oldshape_restore_test.go +++ b/services/glacier/oldshape_restore_test.go @@ -1,12 +1,15 @@ package glacier_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // stripOldShapeVaultFields simulates a snapshot taken before gopherstack-x8em/ @@ -17,14 +20,14 @@ import ( func stripOldShapeVaultFields(t *testing.T, snap []byte) []byte { t.Helper() - var top map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &top)) + var top map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &top, jsonx.V1())) - var tables map[string]json.RawMessage - require.NoError(t, json.Unmarshal(top["tables"], &tables)) + var tables map[string]jsontext.Value + require.NoError(t, json.Unmarshal(top["tables"], &tables, jsonx.V1())) var vaults []map[string]any - require.NoError(t, json.Unmarshal(tables["vaults"], &vaults)) + require.NoError(t, json.Unmarshal(tables["vaults"], &vaults, jsonx.V1())) for _, v := range vaults { delete(v, "numberOfArchivesAtLastInventory") @@ -32,15 +35,15 @@ func stripOldShapeVaultFields(t *testing.T, snap []byte) []byte { delete(v, "writeSinceLastInventory") } - vaultsRaw, err := json.Marshal(vaults) + vaultsRaw, err := json.Marshal(vaults, jsonx.V1()) require.NoError(t, err) tables["vaults"] = vaultsRaw - tablesRaw, err := json.Marshal(tables) + tablesRaw, err := json.Marshal(tables, jsonx.V1()) require.NoError(t, err) top["tables"] = tablesRaw - out, err := json.Marshal(top) + out, err := json.Marshal(top, jsonx.V1()) require.NoError(t, err) return out @@ -75,7 +78,7 @@ func TestRestoreOldShapeSnapshot_DeleteVaultGuard(t *testing.T) { t.Logf("DescribeVault on restored old-shape vault: %s", rec.Body.String()) var describeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) assert.NotEmpty(t, describeResp["LastInventoryDate"], "LastInventoryDate must survive restore") _, hasNumArchives := describeResp["NumberOfArchives"] assert.False(t, hasNumArchives, diff --git a/services/glacier/persistence.go b/services/glacier/persistence.go index 5c35c7582b..07b1d5ab9d 100644 --- a/services/glacier/persistence.go +++ b/services/glacier/persistence.go @@ -2,7 +2,7 @@ package glacier import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -49,7 +49,7 @@ type provisionedCapacitySnapshot struct { // persisted directly alongside Tables, exactly as they were before this // conversion. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` DataRetrievalPolicies map[string]string `json:"dataRetrievalPolicies,omitempty"` MultipartParts []multipartPartSnapshot `json:"multipartParts"` ProvisionedCapacity []provisionedCapacitySnapshot `json:"provisionedCapacity"` diff --git a/services/glacier/persistence_test.go b/services/glacier/persistence_test.go index 901621a48f..7d23068436 100644 --- a/services/glacier/persistence_test.go +++ b/services/glacier/persistence_test.go @@ -1,13 +1,14 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -370,7 +371,7 @@ func TestPersistenceRoundTrip_DataRetrievalPolicy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.NotEmpty(t, got) }) } @@ -425,7 +426,7 @@ func TestPersistenceRoundTrip_MultipartAndCapacity(t *testing.T) { var uploadsResp struct { UploadsList []any `json:"UploadsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &uploadsResp, jsonx.V1())) assert.Len(t, uploadsResp.UploadsList, 1) // Verify provisioned capacity is restored @@ -435,7 +436,7 @@ func TestPersistenceRoundTrip_MultipartAndCapacity(t *testing.T) { var capsResp struct { ProvisionedCapacityList []any `json:"ProvisionedCapacityList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &capsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &capsResp, jsonx.V1())) assert.Len(t, capsResp.ProvisionedCapacityList, 1) }) } @@ -475,7 +476,7 @@ func TestPersistenceRoundTrip_SelectAndRangeInventoryJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var selectResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &selectResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &selectResp, jsonx.V1())) assert.Equal(t, "Select", selectResp["Action"]) assert.NotEmpty(t, selectResp["JobOutputPath"]) @@ -502,7 +503,7 @@ func TestPersistenceRoundTrip_SelectAndRangeInventoryJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var invResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &invResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &invResp, jsonx.V1())) invParams, ok := invResp["InventoryRetrievalParameters"].(map[string]any) require.True(t, ok, "InventoryRetrievalParameters must survive restore: %#v", invResp) diff --git a/services/glacier/select_output.go b/services/glacier/select_output.go index def34b2eab..7256b088ee 100644 --- a/services/glacier/select_output.go +++ b/services/glacier/select_output.go @@ -27,11 +27,12 @@ package glacier import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "github.com/aws/aws-sdk-go-v2/aws" s3sdk "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -155,7 +156,7 @@ func writeSelectS3Output( // the (unreachable in practice, since callers pass only structs/maps of strings) // marshal error -- a malformed manifest object is still safer than a panic. func marshalSelectOutputJSON(v any) []byte { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return []byte("{}") } diff --git a/services/glacier/select_output_test.go b/services/glacier/select_output_test.go index 7fc148e1ef..e7c002bf09 100644 --- a/services/glacier/select_output_test.go +++ b/services/glacier/select_output_test.go @@ -2,7 +2,7 @@ package glacier_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" s3backend "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -210,7 +211,7 @@ func TestGetJobOutput_Select_S3ErrorManifestOnQueryFailure(t *testing.T) { "OutputLocation": map[string]any{ "S3": map[string]any{"BucketName": testOutputBucket, "Prefix": "out/"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) jobID := initiateJobWithBody(t, h, "select-s3-error-vault", string(body)) diff --git a/services/glacier/select_test.go b/services/glacier/select_test.go index a7c885a340..17d798ef1d 100644 --- a/services/glacier/select_test.go +++ b/services/glacier/select_test.go @@ -1,13 +1,15 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const selectTestArchive = "1,alice,30\n2,bob,25\n3,carol,40\n" @@ -31,7 +33,7 @@ func basicSelectBody(archiveID, expression string) string { "OutputLocation": map[string]any{ "S3": map[string]any{"BucketName": "results-bucket", "Prefix": "out/"}, }, - }) + }, jsonx.V1()) return string(body) } @@ -56,7 +58,7 @@ func TestInitiateJob_Select_Success(t *testing.T) { assert.Contains(t, gotPathHeader, wantPath) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, gotPathHeader, resp["jobOutputPath"]) assert.NotEmpty(t, resp["jobId"]) } @@ -208,7 +210,7 @@ func TestInitiateJob_Select_Validation(t *testing.T) { maps.Copy(payload, tt.overrides) - body, err := json.Marshal(payload) + body, err := json.Marshal(payload, jsonx.V1()) require.NoError(t, err) rec := doRequest( @@ -218,7 +220,7 @@ func TestInitiateJob_Select_Validation(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code, rec.Body.String()) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantCode, errResp["code"]) }) } @@ -237,7 +239,7 @@ func TestInitiateJob_Select_ArchiveNotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code, rec.Body.String()) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["code"]) } @@ -336,7 +338,7 @@ func TestGetJobOutput_Select_HeaderNames(t *testing.T) { "OutputLocation": map[string]any{ "S3": map[string]any{"BucketName": "bucket"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) jobID := initiateJobWithBody(t, h, "select-header-vault", string(body)) @@ -372,7 +374,7 @@ func TestGetJobOutput_Select_QuoteFieldsAlways(t *testing.T) { "OutputLocation": map[string]any{ "S3": map[string]any{"BucketName": "bucket"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) jobID := initiateJobWithBody(t, h, "select-quote-vault", string(body)) @@ -423,7 +425,7 @@ func TestDescribeJob_Select_EchoesParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Select", resp["Action"]) assert.NotEmpty(t, resp["JobOutputPath"]) diff --git a/services/glacier/vault_lock_policy_eval.go b/services/glacier/vault_lock_policy_eval.go index 3ba465a6a2..ee836c2944 100644 --- a/services/glacier/vault_lock_policy_eval.go +++ b/services/glacier/vault_lock_policy_eval.go @@ -1,10 +1,13 @@ package glacier import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Vault Lock and vault access policy evaluation is transcribed from AWS's @@ -24,7 +27,7 @@ type vaultLockPolicyDocument struct { type vaultLockPolicyStatement struct { Condition map[string]map[string]glacierPolicyStringSet `json:"Condition"` - Principal json.RawMessage `json:"Principal"` + Principal jsontext.Value `json:"Principal"` Effect string `json:"Effect"` Action glacierPolicyStringSet `json:"Action"` Resource glacierPolicyStringSet `json:"Resource"` @@ -35,23 +38,23 @@ type vaultLockPolicyStatement struct { type glacierPolicyStringSet []string func (s *glacierPolicyStringSet) UnmarshalJSON(data []byte) error { - var multi []json.RawMessage - if err := json.Unmarshal(data, &multi); err != nil { - multi = []json.RawMessage{data} + var multi []jsontext.Value + if err := json.Unmarshal(data, &multi, jsonx.V1()); err != nil { + multi = []jsontext.Value{data} } out := make(glacierPolicyStringSet, 0, len(multi)) for _, raw := range multi { var str string - if err := json.Unmarshal(raw, &str); err == nil { + if err := json.Unmarshal(raw, &str, jsonx.V1()); err == nil { out = append(out, str) continue } - var num json.Number - if err := json.Unmarshal(raw, &num); err != nil { + var num jsonx.Number + if err := json.Unmarshal(raw, &num, jsonx.V1()); err != nil { return fmt.Errorf("unsupported policy value %s: %w", raw, err) } @@ -78,7 +81,7 @@ const ( // InitiateVaultLock time rather than silently never enforcing anything. func parseVaultLockPolicyDocument(policy string) (*vaultLockPolicyDocument, error) { var doc vaultLockPolicyDocument - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("malformed vault lock policy: %w", err) } @@ -135,7 +138,7 @@ func evaluateVaultPolicyDeny(policy string, req *policyRequest) (bool, error) { // principalMatches reports whether a statement's Principal covers the caller. A // missing Principal is treated as the wildcard. -func principalMatches(raw json.RawMessage, req *policyRequest) bool { +func principalMatches(raw jsontext.Value, req *policyRequest) bool { if len(raw) == 0 { return true } @@ -143,11 +146,11 @@ func principalMatches(raw json.RawMessage, req *policyRequest) bool { var set glacierPolicyStringSet var single string - if json.Unmarshal(raw, &single) == nil { + if json.Unmarshal(raw, &single, jsonx.V1()) == nil { set = glacierPolicyStringSet{single} } else { var obj map[string]glacierPolicyStringSet - if json.Unmarshal(raw, &obj) != nil { + if json.Unmarshal(raw, &obj, jsonx.V1()) != nil { return false } diff --git a/services/glacier/writesince_writesites_test.go b/services/glacier/writesince_writesites_test.go index 4089f8d181..523dd60f26 100644 --- a/services/glacier/writesince_writesites_test.go +++ b/services/glacier/writesince_writesites_test.go @@ -1,7 +1,7 @@ package glacier_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glacier" ) @@ -107,7 +108,7 @@ func TestDeleteVault_WriteSinceLastInventory_CompleteMultipartUpload(t *testing. require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var completeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &completeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &completeResp, jsonx.V1())) archiveID, _ := completeResp["archiveId"].(string) require.NotEmpty(t, archiveID) diff --git a/services/globalaccelerator/handler.go b/services/globalaccelerator/handler.go index fd9443325e..4c270da8df 100644 --- a/services/globalaccelerator/handler.go +++ b/services/globalaccelerator/handler.go @@ -2,7 +2,7 @@ package globalaccelerator import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -41,7 +42,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrInvalidArgument, "malformed request body: %v", err) } } diff --git a/services/globalaccelerator/handler_test.go b/services/globalaccelerator/handler_test.go index f0446ed961..cb83d3e9d5 100644 --- a/services/globalaccelerator/handler_test.go +++ b/services/globalaccelerator/handler_test.go @@ -1,7 +1,7 @@ package globalaccelerator_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/globalaccelerator" ) @@ -113,7 +114,7 @@ func TestHandler_ErrorEnvelope(t *testing.T) { assert.NotEmpty(t, rec.Header().Get("X-Amz-Crc32")) var got map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tc.code, got["__type"]) assert.NotEmpty(t, got["message"]) assert.Equal(t, got["message"], got["Message"]) @@ -141,7 +142,7 @@ func TestHandler_EmptyBodyAndResponseShapes(t *testing.T) { Accelerator map[string]any `json:"Accelerator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.IsType(t, float64(0), out.Accelerator["CreatedTime"], "timestamps are epoch-seconds numbers") assert.IsType(t, float64(0), out.Accelerator["LastModifiedTime"]) assert.Equal(t, true, out.Accelerator["Enabled"]) @@ -210,7 +211,7 @@ func TestErrorTable_CoversEverySentinel(t *testing.T) { require.NoError(t, globalaccelerator.WriteErrorForTest(c, tc.err)) var got map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tc.code, got["__type"]) }) } diff --git a/services/globalaccelerator/persistence.go b/services/globalaccelerator/persistence.go index c25b39eae7..eb869627db 100644 --- a/services/globalaccelerator/persistence.go +++ b/services/globalaccelerator/persistence.go @@ -2,7 +2,7 @@ package globalaccelerator import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,11 +12,11 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Seq int64 `json:"seq"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Seq int64 `json:"seq"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/glue/blueprint_include_flags_test.go b/services/glue/blueprint_include_flags_test.go index c43ac1c685..ea69aca524 100644 --- a/services/glue/blueprint_include_flags_test.go +++ b/services/glue/blueprint_include_flags_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -65,7 +66,7 @@ func TestGetBlueprint_IncludeFlags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) bp, _ := out["Blueprint"].(map[string]any) if tt.action == "BatchGetBlueprints" { diff --git a/services/glue/crawl_run.go b/services/glue/crawl_run.go index 830955d049..0a2b83900c 100644 --- a/services/glue/crawl_run.go +++ b/services/glue/crawl_run.go @@ -1,7 +1,7 @@ package glue import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -186,7 +187,7 @@ func configuredMergeNewColumns(cfg string) bool { } `json:"CrawlerOutput"` } - if err := json.Unmarshal([]byte(cfg), &doc); err != nil { + if err := json.Unmarshal([]byte(cfg), &doc, jsonx.V1()); err != nil { return false } diff --git a/services/glue/crawler_lake.go b/services/glue/crawler_lake.go index 5fd96f178c..c70e077482 100644 --- a/services/glue/crawler_lake.go +++ b/services/glue/crawler_lake.go @@ -3,7 +3,8 @@ package glue import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -13,6 +14,8 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -163,5 +166,5 @@ func moveToPartitionKeys(cols []Column, names []string) ([]Column, []Column) { } func decodeJSON(data []byte, v any) error { - return json.NewDecoder(bytes.NewReader(data)).Decode(v) + return json.UnmarshalDecode(jsontext.NewDecoder(bytes.NewReader(data)), v, jsonx.V1()) } diff --git a/services/glue/crawler_s3.go b/services/glue/crawler_s3.go index 5fce70e74f..39149ab9ea 100644 --- a/services/glue/crawler_s3.go +++ b/services/glue/crawler_s3.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "maps" @@ -18,6 +19,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -523,40 +525,41 @@ func mergeJSONTypes(a, b string) string { } } -func decodeJSONObject(line []byte) ([]string, []json.RawMessage, bool) { - dec := json.NewDecoder(bytes.NewReader(line)) - if tok, err := dec.Token(); err != nil || tok != json.Delim('{') { +func decodeJSONObject(line []byte) ([]string, []jsontext.Value, bool) { + dec := jsontext.NewDecoder(bytes.NewReader(line), jsonx.V1()) + if tok, err := dec.ReadToken(); err != nil || tok.Kind() != '{' { return nil, nil, false } var keys []string - var vals []json.RawMessage + var vals []jsontext.Value - for dec.More() { - kt, err := dec.Token() + for dec.PeekKind() != '}' { + kt, err := dec.ReadToken() if err != nil { return nil, nil, false } - var raw json.RawMessage - if err = dec.Decode(&raw); err != nil { + key := kt.String() + + raw, err := dec.ReadValue() + if err != nil { return nil, nil, false } - keys = append(keys, fmt.Sprint(kt)) - vals = append(vals, raw) + keys = append(keys, key) + vals = append(vals, raw.Clone()) } return keys, vals, true } -func jsonType(raw json.RawMessage) string { - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() +func jsonType(raw jsontext.Value) string { + dec := jsontext.NewDecoder(bytes.NewReader(raw)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return avroString } @@ -569,7 +572,7 @@ func jsonValueType(v any) string { return "" case bool: return avroBoolean - case json.Number: + case jsonx.Number: if _, err := x.Int64(); err == nil { return typeBigint } diff --git a/services/glue/get_partitions_index_test.go b/services/glue/get_partitions_index_test.go index bc03b9cad0..1563285533 100644 --- a/services/glue/get_partitions_index_test.go +++ b/services/glue/get_partitions_index_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -122,7 +123,7 @@ func TestPagination_GetPartitions_RoundTripOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out page - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) for _, p := range out.Partitions { seen = append(seen, p.Values[0]) diff --git a/services/glue/get_partitions_segment_test.go b/services/glue/get_partitions_segment_test.go index 8a5b8a780b..ca51a9a6a0 100644 --- a/services/glue/get_partitions_segment_test.go +++ b/services/glue/get_partitions_segment_test.go @@ -1,13 +1,15 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGetPartitions_Segment(t *testing.T) { @@ -57,7 +59,7 @@ func TestGetPartitions_Segment(t *testing.T) { var out struct { Partitions []map[string]any `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Partitions, tt.wantCount) }) } @@ -107,7 +109,7 @@ func TestGetPartitions_ExcludeColumnSchema(t *testing.T) { } `json:"StorageDescriptor"` } `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Partitions, 1) assert.Len(t, out.Partitions[0].StorageDescriptor.Columns, tt.wantColumns) assert.Equal(t, "s3://bucket/p", out.Partitions[0].StorageDescriptor.Location) diff --git a/services/glue/glossary_client_token_test.go b/services/glue/glossary_client_token_test.go index 1baa212713..eda8759ea8 100644 --- a/services/glue/glossary_client_token_test.go +++ b/services/glue/glossary_client_token_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateGlossary_ClientToken(t *testing.T) { @@ -34,7 +36,7 @@ func TestCreateGlossary_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["Id"].(string) } @@ -46,7 +48,7 @@ func TestCreateGlossary_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["Id"].(string) } diff --git a/services/glue/handler.go b/services/glue/handler.go index de6085a5b5..3b480a63b8 100644 --- a/services/glue/handler.go +++ b/services/glue/handler.go @@ -2,7 +2,7 @@ package glue import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -175,7 +176,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ConnectionName string `json:"ConnectionName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) switch { case req.ResourceArn != "": @@ -232,7 +233,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // glueErrorCodes maps every sentinel this package returns to its AWS error diff --git a/services/glue/handler_blueprints_test.go b/services/glue/handler_blueprints_test.go index acd16a293b..74a024aecc 100644 --- a/services/glue/handler_blueprints_test.go +++ b/services/glue/handler_blueprints_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/glue/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestBlueprint_CRUD(t *testing.T) { @@ -368,7 +370,7 @@ func TestBlueprint_Run_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, startBpRec1.Code) var startBpOut1 map[string]any - require.NoError(t, json.Unmarshal(startBpRec1.Body.Bytes(), &startBpOut1)) + require.NoError(t, json.Unmarshal(startBpRec1.Body.Bytes(), &startBpOut1, jsonx.V1())) assert.NotEmpty(t, startBpOut1["RunId"]) startRec := doGlueRequest(t, h, "StartBlueprintRun", map[string]any{ @@ -377,7 +379,7 @@ func TestBlueprint_Run_Lifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"].(string) getBpRunRec := doGlueRequest(t, h, "GetBlueprintRun", map[string]any{ @@ -390,7 +392,7 @@ func TestBlueprint_Run_Lifecycle(t *testing.T) { getBpRunsRec := doGlueRequest(t, h, "GetBlueprintRuns", map[string]any{"BlueprintName": "bp-run"}) require.Equal(t, http.StatusOK, getBpRunsRec.Code) var getBpRunsOut map[string]any - require.NoError(t, json.Unmarshal(getBpRunsRec.Body.Bytes(), &getBpRunsOut)) + require.NoError(t, json.Unmarshal(getBpRunsRec.Body.Bytes(), &getBpRunsOut, jsonx.V1())) bpRuns := getBpRunsOut["BlueprintRuns"].([]any) assert.GreaterOrEqual(t, len(bpRuns), 1) } diff --git a/services/glue/handler_catalogs_test.go b/services/glue/handler_catalogs_test.go index 8b1aa2ada9..5f777f3492 100644 --- a/services/glue/handler_catalogs_test.go +++ b/services/glue/handler_catalogs_test.go @@ -1,13 +1,15 @@ package glue_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -19,7 +21,7 @@ func dispatchNewOp(t *testing.T, h *glue.Handler, op string, body any) map[strin t.Fatalf("op %s: got status %d, body: %s", op, rr.Code, rr.Body.String()) } var out map[string]any - if err := json.NewDecoder(rr.Body).Decode(&out); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(rr.Body), &out, jsonx.V1()); err != nil { t.Fatalf("decode response: %v", err) } @@ -202,7 +204,7 @@ func TestCatalogImport_Lifecycle(t *testing.T) { ImportCompleted bool `json:"ImportCompleted"` } `json:"ImportStatus"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tc.wantCompleted, out.ImportStatus.ImportCompleted) if tc.wantCompleted { @@ -231,7 +233,7 @@ func TestCatalogImport_Idempotent(t *testing.T) { ImportCompleted bool `json:"ImportCompleted"` } `json:"ImportStatus"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.True(t, out.ImportStatus.ImportCompleted) } @@ -293,7 +295,7 @@ func TestCatalogImportStatus(t *testing.T) { ImportCompleted bool `json:"ImportCompleted"` } `json:"ImportStatus"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tc.wantCompleted, out.ImportStatus.ImportCompleted) if tc.wantCompleted { diff --git a/services/glue/handler_classifiers_test.go b/services/glue/handler_classifiers_test.go index 1e2da3a96e..1e30293212 100644 --- a/services/glue/handler_classifiers_test.go +++ b/services/glue/handler_classifiers_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestClassifier_CRUD(t *testing.T) { @@ -148,7 +150,7 @@ func TestClassifier_GetClassifiers(t *testing.T) { rec := doGlueRequest(t, h, "GetClassifiers", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) classifiers := out["Classifiers"].([]any) assert.Len(t, classifiers, 2) } diff --git a/services/glue/handler_column_statistics_test.go b/services/glue/handler_column_statistics_test.go index 521f3b8e84..408457fc6c 100644 --- a/services/glue/handler_column_statistics_test.go +++ b/services/glue/handler_column_statistics_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -53,7 +54,7 @@ func TestStopColumnStatisticsTaskRun_NotFound(t *testing.T) { var out struct { RunID string `json:"ColumnStatisticsTaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.RunID, "expected ColumnStatisticsTaskRunId in response") } @@ -355,7 +356,7 @@ func TestColumnStatisticsTaskSettings(t *testing.T) { }) require.Equal(t, http.StatusOK, startCSTRec.Code) var startCSTOut map[string]any - require.NoError(t, json.Unmarshal(startCSTRec.Body.Bytes(), &startCSTOut)) + require.NoError(t, json.Unmarshal(startCSTRec.Body.Bytes(), &startCSTOut, jsonx.V1())) assert.NotEmpty(t, startCSTOut["ColumnStatisticsTaskRunId"]) doGlueRequest(t, h, "StartColumnStatisticsTaskRun", map[string]any{ @@ -374,7 +375,7 @@ func TestColumnStatisticsTaskSettings(t *testing.T) { }) require.Equal(t, http.StatusOK, startCSTRec2.Code) var startCSTOut2 map[string]any - require.NoError(t, json.Unmarshal(startCSTRec2.Body.Bytes(), &startCSTOut2)) + require.NoError(t, json.Unmarshal(startCSTRec2.Body.Bytes(), &startCSTOut2, jsonx.V1())) cstRunID := startCSTOut2["ColumnStatisticsTaskRunId"].(string) getCSTRunRec := doGlueRequest(t, h, "GetColumnStatisticsTaskRun", map[string]any{ @@ -440,7 +441,7 @@ func TestColumnStatisticsTaskRunSchedule_RequiresExistingSettings(t *testing.T) } `json:"Schedule"` } `json:"ColumnStatisticsTaskSettings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "SCHEDULED", out.ColumnStatisticsTaskSettings.Schedule.State) rec = doGlueRequest(t, h, "StopColumnStatisticsTaskRunSchedule", map[string]any{ @@ -452,7 +453,7 @@ func TestColumnStatisticsTaskRunSchedule_RequiresExistingSettings(t *testing.T) "DatabaseName": "db", "TableName": "tbl", }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "NOT_SCHEDULED", out.ColumnStatisticsTaskSettings.Schedule.State) } diff --git a/services/glue/handler_connection_types_sdk_test.go b/services/glue/handler_connection_types_sdk_test.go index 73b8149286..b63bc711b4 100644 --- a/services/glue/handler_connection_types_sdk_test.go +++ b/services/glue/handler_connection_types_sdk_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -121,7 +122,7 @@ func TestConnectionTypeWireShape(t *testing.T) { SupportedDataOperations []string `json:"SupportedDataOperations"` } `json:"Capabilities"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.ElementsMatch(t, []string{"READ", "WRITE"}, out.Capabilities.SupportedDataOperations) }, }, @@ -133,7 +134,7 @@ func TestConnectionTypeWireShape(t *testing.T) { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.NotContains(t, out, "Category", "DescribeConnectionTypeOutput has no Category member on the real wire") }, @@ -151,7 +152,7 @@ func TestConnectionTypeWireShape(t *testing.T) { Categories []string `json:"Categories"` } `json:"ConnectionTypes"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) found := false diff --git a/services/glue/handler_connection_types_test.go b/services/glue/handler_connection_types_test.go index 27fabdd8ce..80fa171b3f 100644 --- a/services/glue/handler_connection_types_test.go +++ b/services/glue/handler_connection_types_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDeleteConnectionType verifies real state mutation: built-in types are @@ -75,7 +77,7 @@ func TestDeleteConnectionType_CustomRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, regRec.Code) var regOut map[string]any - require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Out)) + require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Out, jsonx.V1())) assert.NotEmpty(t, regOut["ConnectionTypeArn"], "RegisterConnectionType must return ConnectionTypeArn") delRec := doGlueRequest(t, h, "DeleteConnectionType", map[string]any{"ConnectionType": "MyCustomConn"}) diff --git a/services/glue/handler_connections_test.go b/services/glue/handler_connections_test.go index 9e26a7dfcc..6797de49fe 100644 --- a/services/glue/handler_connections_test.go +++ b/services/glue/handler_connections_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -41,7 +42,7 @@ func TestDescribeEntity_ValidConnection(t *testing.T) { var out struct { Fields []any `json:"Fields"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out.Fields) } @@ -77,7 +78,7 @@ func TestGetEntityRecords_ValidConnection(t *testing.T) { NextToken string `json:"NextToken"` Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Records) // Each record must conform to the Account schema. for _, r := range out.Records { @@ -286,7 +287,7 @@ func TestConnection_NetworkType(t *testing.T) { getRec := doGlueRequest(t, h, "GetConnection", map[string]any{"Name": "network-conn"}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) conn := out["Connection"].(map[string]any) assert.Equal(t, "NETWORK", conn["ConnectionType"]) props := conn["ConnectionProperties"].(map[string]any) @@ -323,7 +324,7 @@ func TestConnection_CredentialsPersistAfterUpdate(t *testing.T) { getRec := doGlueRequest(t, h, "GetConnection", map[string]any{"Name": "cred-conn"}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) conn := out["Connection"].(map[string]any) props := conn["ConnectionProperties"].(map[string]any) assert.Equal(t, "user2", props["USERNAME"]) @@ -405,7 +406,7 @@ func TestConnectionCRUD(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } }) @@ -455,7 +456,7 @@ func TestConnectionGetFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) conn := out["Connection"].(map[string]any) assert.Equal(t, tt.wantConnType, conn["ConnectionType"]) if tt.wantCreation { @@ -500,7 +501,7 @@ func TestGetConnections(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, _ := out["ConnectionList"].([]any) assert.Len(t, list, tt.wantLen) }) @@ -553,7 +554,7 @@ func TestConnectionTagging(t *testing.T) { rec := doGlueRequest(t, h, "GetTags", map[string]any{"ResourceArn": connARN}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } @@ -567,7 +568,7 @@ func TestConnectionTagging(t *testing.T) { rec2 := doGlueRequest(t, h, "GetTags", map[string]any{"ResourceArn": connARN}) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) tags, _ := out2["Tags"].(map[string]any) _, hasFoo := tags["foo"] assert.False(t, hasFoo) @@ -684,7 +685,7 @@ func TestUpdateConnection_Updates(t *testing.T) { ConnectionProperties map[string]string `json:"ConnectionProperties"` } `json:"Connection"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "jdbc:mysql://newhost:3306/db", out.Connection.ConnectionProperties["JDBC_CONNECTION_URL"]) } diff --git a/services/glue/handler_crawlers_test.go b/services/glue/handler_crawlers_test.go index 336d135c6d..11c981e032 100644 --- a/services/glue/handler_crawlers_test.go +++ b/services/glue/handler_crawlers_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -72,7 +73,7 @@ func Test_Crawler_CreateOptions_RoundTrip(t *testing.T) { } `json:"Targets"` } `json:"Crawler"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "cron(0 12 * * ? *)", out.Crawler.Schedule.ScheduleExpression) assert.Equal(t, `{"Version":1.0}`, out.Crawler.Configuration) @@ -86,7 +87,7 @@ func Test_Crawler_CreateOptions_RoundTrip(t *testing.T) { cat := out cat.Crawler.Targets.CatalogTargets = nil - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cat)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cat, jsonx.V1())) require.Len(t, cat.Crawler.Targets.CatalogTargets, 1) assert.Equal(t, "db1", cat.Crawler.Targets.CatalogTargets[0].DatabaseName) @@ -100,7 +101,7 @@ func Test_Crawler_CreateOptions_RoundTrip(t *testing.T) { rec = doGlueRequest(t, h, "GetCrawler", map[string]any{"Name": "crawler1"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "curated_", out.Crawler.TablePrefix) } @@ -265,7 +266,7 @@ func TestCrawler_Lifecycle_States(t *testing.T) { if tt.wantState != "" && tt.wantCode == http.StatusOK { getRec := doGlueRequest(t, h, "GetCrawler", map[string]any{"Name": "cr-lifecycle"}) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) cr := out["Crawler"].(map[string]any) assert.Equal(t, tt.wantState, cr["State"]) } @@ -412,7 +413,7 @@ func TestHTTPBatchGetCrawlers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) crawlers, ok := out["Crawlers"].([]any) require.True(t, ok) assert.Len(t, crawlers, 1) @@ -453,7 +454,7 @@ func TestListCrawlers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) names, _ := out["CrawlerNames"].([]any) assert.Len(t, names, tt.wantLen) @@ -515,7 +516,7 @@ func TestCrawlerErrors(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantErrorType, out["__type"]) }) } @@ -582,7 +583,7 @@ func TestCrawlerSchedule(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } }) @@ -660,7 +661,7 @@ func TestListCrawls_ReturnsRealCrawlHistory(t *testing.T) { var before struct { Crawls []map[string]any `json:"Crawls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before, jsonx.V1())) assert.Empty(t, before.Crawls, "no crawl has started yet") rec = doGlueRequest(t, h, "StartCrawler", map[string]any{"Name": "my-crawler"}) @@ -672,7 +673,7 @@ func TestListCrawls_ReturnsRealCrawlHistory(t *testing.T) { var after struct { Crawls []map[string]any `json:"Crawls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after, jsonx.V1())) require.Len(t, after.Crawls, 1) assert.NotEmpty(t, after.Crawls[0]["CrawlId"]) assert.NotEmpty(t, after.Crawls[0]["StartTime"]) diff --git a/services/glue/handler_custom_entity_types_test.go b/services/glue/handler_custom_entity_types_test.go index 7ddd30f446..c3db87a363 100644 --- a/services/glue/handler_custom_entity_types_test.go +++ b/services/glue/handler_custom_entity_types_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -181,7 +182,7 @@ func TestCustomEntityType_RegexAndContextWords_Persist(t *testing.T) { rec := doGlueRequest(t, h, "GetCustomEntityType", map[string]any{"Name": "CreditCard"}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, `\d{4}-\d{4}-\d{4}-\d{4}`, out["RegexString"]) ctxWords, ok := out["ContextWords"].([]any) require.True(t, ok) @@ -271,7 +272,7 @@ func TestGetCustomEntityType_Found(t *testing.T) { Name string `json:"Name"` RegexString string `json:"RegexString"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "MY_TYPE", out.Name) assert.Equal(t, `\d+`, out.RegexString) } diff --git a/services/glue/handler_data_quality_rulesets_test.go b/services/glue/handler_data_quality_rulesets_test.go index ab49f9baa6..8a86a34dc9 100644 --- a/services/glue/handler_data_quality_rulesets_test.go +++ b/services/glue/handler_data_quality_rulesets_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -56,7 +57,7 @@ func TestCancelDQRecommendationRun_NotFound(t *testing.T) { var out struct { RunID string `json:"RunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.RunID, "expected RunId in response") runID = out.RunID } @@ -177,13 +178,13 @@ func TestDataQuality_RuleRecommendationRun(t *testing.T) { startRec := doGlueRequest(t, h, "StartDataQualityRuleRecommendationRun", map[string]any{}) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"].(string) getRecommendRec := doGlueRequest(t, h, "GetDataQualityRuleRecommendationRun", map[string]any{"RunId": runID}) require.Equal(t, http.StatusOK, getRecommendRec.Code) var getRecommendOut map[string]any - require.NoError(t, json.Unmarshal(getRecommendRec.Body.Bytes(), &getRecommendOut)) + require.NoError(t, json.Unmarshal(getRecommendRec.Body.Bytes(), &getRecommendOut, jsonx.V1())) assert.NotEmpty(t, getRecommendOut["RunId"]) listRecommendRec := doGlueRequest(t, h, "ListDataQualityRuleRecommendationRuns", map[string]any{}) @@ -243,7 +244,7 @@ func TestDataQualityRulesets(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } }) @@ -293,7 +294,7 @@ func TestDataQualityRulesetTagging(t *testing.T) { if tt.check != nil { var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } }) @@ -380,7 +381,7 @@ func TestHandlerDataQuality_GetDataQualityRuleset(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "my-ruleset", out["Name"]) } }) @@ -496,7 +497,7 @@ func TestHandlerDataQuality_ListDataQualityRulesets(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) rulesets, _ := out["Rulesets"].([]any) assert.Len(t, rulesets, tt.wantLen) }) @@ -540,7 +541,7 @@ func TestHandlerDataQuality_StartDataQualityRulesetEvaluationRun(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["RunId"]) } }) @@ -585,7 +586,7 @@ func TestHandlerDataQuality_GetDataQualityRulesetEvaluationRun(t *testing.T) { ) require.Equal(t, http.StatusOK, startRec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &out, jsonx.V1())) runID = out["RunId"] } @@ -594,7 +595,7 @@ func TestHandlerDataQuality_GetDataQualityRulesetEvaluationRun(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["RunId"]) } }) @@ -618,7 +619,7 @@ func TestHandlerDataQuality_BatchGetDataQualityRulesetEvaluationRun(t *testing.T ) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"] require.NotEmpty(t, runID) @@ -631,7 +632,7 @@ func TestHandlerDataQuality_BatchGetDataQualityRulesetEvaluationRun(t *testing.T Runs []map[string]any `json:"Runs"` RunsNotFound []string `json:"RunsNotFound"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Runs, 1) assert.Equal(t, runID, out.Runs[0]["RunId"]) assert.Equal(t, []string{"no-such-run"}, out.RunsNotFound) @@ -671,7 +672,7 @@ func TestHandlerDataQuality_CancelDataQualityRulesetEvaluationRun(t *testing.T) ) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"] if tt.preCancel { diff --git a/services/glue/handler_data_quality_stats_test.go b/services/glue/handler_data_quality_stats_test.go index 8889a62100..a757772d4f 100644 --- a/services/glue/handler_data_quality_stats_test.go +++ b/services/glue/handler_data_quality_stats_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -23,7 +24,7 @@ func TestDataQualityRecommendationRun(t *testing.T) { var startOut struct { RunID string `json:"RunId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) require.NotEmpty(t, startOut.RunID) // List @@ -104,13 +105,13 @@ func TestDataQuality_EvaluationRun_GetAndCancel(t *testing.T) { ) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"].(string) getEvalRec := doGlueRequest(t, h, "GetDataQualityRulesetEvaluationRun", map[string]any{"RunId": runID}) require.Equal(t, http.StatusOK, getEvalRec.Code) var getEvalOut map[string]any - require.NoError(t, json.Unmarshal(getEvalRec.Body.Bytes(), &getEvalOut)) + require.NoError(t, json.Unmarshal(getEvalRec.Body.Bytes(), &getEvalOut, jsonx.V1())) assert.Equal(t, "RUNNING", getEvalOut["Status"]) cancelEvalRec := doGlueRequest(t, h, "CancelDataQualityRulesetEvaluationRun", map[string]any{"RunId": runID}) @@ -133,7 +134,7 @@ func TestGetDataQualityModel_RequiresProfileID(t *testing.T) { var out struct { Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "SUCCEEDED", out.Status) } @@ -155,7 +156,7 @@ func TestGetDataQualityModelResult_RequiresBothIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out, "Model") assert.NotContains(t, out, "Status", "GetDataQualityModelResult has no Status field in the real API") } @@ -174,7 +175,7 @@ func TestDataQualityStatisticAnnotations_RealStore(t *testing.T) { var empty struct { Annotations []map[string]any `json:"Annotations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty, jsonx.V1())) assert.Empty(t, empty.Annotations) rec = doGlueRequest(t, h, "PutDataQualityProfileAnnotation", map[string]any{}) @@ -196,7 +197,7 @@ func TestDataQualityStatisticAnnotations_RealStore(t *testing.T) { var batchOut struct { FailedInclusionAnnotations []map[string]any `json:"FailedInclusionAnnotations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchOut, jsonx.V1())) require.Len(t, batchOut.FailedInclusionAnnotations, 1) assert.Equal(t, "stat-2", batchOut.FailedInclusionAnnotations[0]["StatisticId"]) @@ -206,14 +207,14 @@ func TestDataQualityStatisticAnnotations_RealStore(t *testing.T) { var out struct { Annotations []map[string]any `json:"Annotations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Annotations, 2, "the profile-wide and the per-statistic annotation") rec = doGlueRequest(t, h, "ListDataQualityStatisticAnnotations", map[string]any{ "ProfileId": "profile-1", "StatisticId": "stat-1", }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Annotations, 1) assert.Equal(t, "stat-1", out.Annotations[0]["StatisticId"]) } @@ -232,7 +233,7 @@ func TestDataQualityEvaluationRuns_Stateful(t *testing.T) { var out struct { Runs []any `json:"Runs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Runs) }) @@ -260,7 +261,7 @@ func TestDataQualityEvaluationRuns_Stateful(t *testing.T) { var out struct { Runs []any `json:"Runs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Runs, 1) }) } @@ -279,7 +280,7 @@ func TestListDataQualityResults_Stateful(t *testing.T) { var out struct { Results []any `json:"Results"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Results) }) @@ -298,7 +299,7 @@ func TestListDataQualityResults_Stateful(t *testing.T) { var out struct { Results []any `json:"Results"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Results, 2) }) } @@ -351,7 +352,7 @@ func TestDataQualityRecommendationRun_Stateful(t *testing.T) { var startOut struct { RunID string `json:"RunId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut.RunID) getRec := doGlueRequest(t, h, "GetDataQualityRuleRecommendationRun", map[string]any{ @@ -363,7 +364,7 @@ func TestDataQualityRecommendationRun_Stateful(t *testing.T) { RunID string `json:"RunId"` Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, startOut.RunID, getOut.RunID) assert.NotEmpty(t, getOut.Status) } @@ -433,7 +434,7 @@ func TestGetDataQualityResult_Found(t *testing.T) { ResultID string `json:"ResultId"` Score float64 `json:"Score"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "result-abc", out.ResultID) assert.InDelta(t, 0.95, out.Score, 0.001) } diff --git a/services/glue/handler_databases_test.go b/services/glue/handler_databases_test.go index 6e4d77847b..41738babb1 100644 --- a/services/glue/handler_databases_test.go +++ b/services/glue/handler_databases_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -268,7 +269,7 @@ func TestTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) resource := out if tt.resourceKey != "" { diff --git a/services/glue/handler_dev_endpoints_test.go b/services/glue/handler_dev_endpoints_test.go index 651a1aeed0..606914b319 100644 --- a/services/glue/handler_dev_endpoints_test.go +++ b/services/glue/handler_dev_endpoints_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -140,7 +141,7 @@ func TestDevEndpoint_UpdateAndGet(t *testing.T) { getRec := doGlueRequest(t, h, "GetDevEndpoint", map[string]any{"EndpointName": "dep-upd"}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) dep := out["DevEndpoint"].(map[string]any) args, ok := dep["Arguments"].(map[string]any) require.True(t, ok) @@ -197,7 +198,7 @@ func TestUpdateDevEndpoint_PublicKeys(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) dep := out["DevEndpoint"].(map[string]any) keysRaw, ok := dep["PublicKeys"].([]any) require.True(t, ok) @@ -237,6 +238,6 @@ func TestDevEndpoint_ResourceNumberLimitExceeded(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ResourceNumberLimitExceededException", out["__type"]) } diff --git a/services/glue/handler_entities_test.go b/services/glue/handler_entities_test.go index bd9197dee3..344cad5ac0 100644 --- a/services/glue/handler_entities_test.go +++ b/services/glue/handler_entities_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -47,7 +48,7 @@ func TestHandler_DescribeEntity_Fields(t *testing.T) { FieldType string `json:"FieldType"` } `json:"Fields"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Fields) names := make([]string, 0, len(out.Fields)) @@ -129,7 +130,7 @@ func TestHandler_ListEntities(t *testing.T) { EntityName string `json:"EntityName"` } `json:"Entities"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.Entities), tc.wantMin) }) } @@ -154,7 +155,7 @@ func TestHandler_GetEntityRecords_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Records, 2) require.NotEmpty(t, page1.NextToken) @@ -169,7 +170,7 @@ func TestHandler_GetEntityRecords_Pagination(t *testing.T) { var page2 struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.NotEmpty(t, page2.Records) assert.NotEqual(t, page1.Records[0]["Id"], page2.Records[0]["Id"]) } @@ -201,7 +202,7 @@ func TestHandler_ConnectionTypeLifecycle(t *testing.T) { var regOut struct { ConnectionTypeArn string `json:"ConnectionTypeArn"` } - require.NoError(t, json.Unmarshal(reg.Body.Bytes(), ®Out)) + require.NoError(t, json.Unmarshal(reg.Body.Bytes(), ®Out, jsonx.V1())) assert.NotEmpty(t, regOut.ConnectionTypeArn, "RegisterConnectionType must return ConnectionTypeArn") // It appears in ListConnectionTypes alongside built-ins. @@ -213,7 +214,7 @@ func TestHandler_ConnectionTypeLifecycle(t *testing.T) { ConnectionType string `json:"ConnectionType"` } `json:"ConnectionTypes"` } - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &listOut, jsonx.V1())) names := make([]string, 0, len(listOut.ConnectionTypes)) for _, ct := range listOut.ConnectionTypes { @@ -231,7 +232,7 @@ func TestHandler_ConnectionTypeLifecycle(t *testing.T) { var descOut struct { RestConfiguration map[string]any `json:"RestConfiguration"` } - require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(desc.Body.Bytes(), &descOut, jsonx.V1())) require.NotNil(t, descOut.RestConfiguration) validationCfg, _ := descOut.RestConfiguration["ValidationEndpointConfiguration"].(map[string]any) require.NotNil(t, validationCfg) @@ -386,7 +387,7 @@ func TestHandler_ListEntities_NativeCatalog(t *testing.T) { var out struct { Entities []glue.EntityDescriptor `json:"Entities"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Entities) }) @@ -402,7 +403,7 @@ func TestHandler_ListEntities_NativeCatalog(t *testing.T) { var out struct { Entities []glue.EntityDescriptor `json:"Entities"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Entities, 1) assert.Equal(t, "salesdb", out.Entities[0].EntityName) assert.Equal(t, "DATABASES", out.Entities[0].Category) @@ -421,7 +422,7 @@ func TestHandler_ListEntities_NativeCatalog(t *testing.T) { var out struct { Entities []glue.EntityDescriptor `json:"Entities"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Entities, 1) assert.Equal(t, "salesdb.orders", out.Entities[0].EntityName) assert.Equal(t, "TABLES", out.Entities[0].Category) @@ -451,7 +452,7 @@ func TestHandler_ListEntities_NativeCatalog(t *testing.T) { var out struct { Entities []glue.EntityDescriptor `json:"Entities"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) names := make([]string, 0, len(out.Entities)) for _, e := range out.Entities { @@ -485,7 +486,7 @@ func TestHandler_GetEntityRecords_NativeCatalog(t *testing.T) { var out struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Records, 3) for _, r := range out.Records { @@ -541,7 +542,7 @@ func TestHandler_GetEntityRecords_NativeCatalog(t *testing.T) { NextToken string `json:"NextToken"` Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Records, 2) require.NotEmpty(t, page1.NextToken) @@ -555,7 +556,7 @@ func TestHandler_GetEntityRecords_NativeCatalog(t *testing.T) { var page2 struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) require.NotEmpty(t, page2.Records) assert.NotEqual(t, page1.Records[0]["id"], page2.Records[0]["id"]) }) diff --git a/services/glue/handler_etl_test.go b/services/glue/handler_etl_test.go index 3c3d28944a..5cb7cf391f 100644 --- a/services/glue/handler_etl_test.go +++ b/services/glue/handler_etl_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateScript verifies that CreateScript generates non-empty ETL code from DagNodes/DagEdges. @@ -97,7 +99,7 @@ func TestCreateScript(t *testing.T) { PythonScript string `json:"PythonScript"` ScalaCode string `json:"ScalaCode"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.wantPythonNonEmpty { assert.NotEmpty(t, out.PythonScript) @@ -170,7 +172,7 @@ func TestGetDataflowGraph(t *testing.T) { DagNodes []any `json:"DagNodes"` DagEdges []any `json:"DagEdges"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.DagNodes, tc.wantNodeCount) assert.Len(t, out.DagEdges, tc.wantEdgeCount) }) @@ -213,7 +215,7 @@ func TestGetDataflowGraph_RoundTrip(t *testing.T) { var scriptOut struct { PythonScript string `json:"PythonScript"` } - require.NoError(t, json.Unmarshal(scriptRec.Body.Bytes(), &scriptOut)) + require.NoError(t, json.Unmarshal(scriptRec.Body.Bytes(), &scriptOut, jsonx.V1())) require.NotEmpty(t, scriptOut.PythonScript) // Parse the script back to a DAG. @@ -226,7 +228,7 @@ func TestGetDataflowGraph_RoundTrip(t *testing.T) { DagNodes []any `json:"DagNodes"` DagEdges []any `json:"DagEdges"` } - require.NoError(t, json.Unmarshal(graphRec.Body.Bytes(), &graphOut)) + require.NoError(t, json.Unmarshal(graphRec.Body.Bytes(), &graphOut, jsonx.V1())) // Should have recovered 2 nodes (DataSource + DataSink) and 1 edge. assert.Len(t, graphOut.DagNodes, 2) @@ -312,7 +314,7 @@ func TestGetMapping_DerivesFromRealSchema(t *testing.T) { var out struct { Mapping []map[string]any `json:"Mapping"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Mapping, tc.wantLen) assert.Equal(t, "id", out.Mapping[0]["SourcePath"]) }) @@ -365,7 +367,7 @@ func TestGetPlan_Languages(t *testing.T) { PythonScript string `json:"PythonScript"` ScalaCode string `json:"ScalaCode"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.wantPython { assert.NotEmpty(t, out.PythonScript) @@ -430,7 +432,7 @@ func TestGetPlan(t *testing.T) { PythonScript string `json:"PythonScript"` ScalaCode string `json:"ScalaCode"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.wantPython { assert.NotEmpty(t, out.PythonScript) diff --git a/services/glue/handler_identity_center_test.go b/services/glue/handler_identity_center_test.go index 920b6d3da9..1cdced9c1b 100644 --- a/services/glue/handler_identity_center_test.go +++ b/services/glue/handler_identity_center_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGlueIdentityCenter(t *testing.T) { @@ -48,7 +50,7 @@ func TestGlueIdentityCenter_Stateful(t *testing.T) { var getOut struct { InstanceArn string `json:"InstanceArn"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "arn:aws:sso:::instance/ssoins-1234", getOut.InstanceArn) updateRec := doGlueRequest(t, h, "UpdateGlueIdentityCenterConfiguration", map[string]any{ diff --git a/services/glue/handler_integrations_test.go b/services/glue/handler_integrations_test.go index 6d7a8bc653..c1a13bd091 100644 --- a/services/glue/handler_integrations_test.go +++ b/services/glue/handler_integrations_test.go @@ -1,13 +1,15 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDescribeInboundIntegrations verifies integrations are returned from the backend. @@ -63,7 +65,7 @@ func TestDescribeInboundIntegrations(t *testing.T) { var out struct { InboundIntegrations []any `json:"InboundIntegrations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.InboundIntegrations), tc.wantMinCount) }) } @@ -192,7 +194,7 @@ func TestIntegration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.Equal(t, "my-integration", createOut["IntegrationName"]) assert.Equal(t, "arn:aws:s3:::my-source-bucket", createOut["SourceArn"]) assert.Equal(t, "arn:aws:redshift:us-east-1:123456789012:cluster/my-target", createOut["TargetArn"]) @@ -213,7 +215,7 @@ func TestIntegration(t *testing.T) { var inboundOut struct { InboundIntegrations []any `json:"InboundIntegrations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inboundOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inboundOut, jsonx.V1())) assert.Len(t, inboundOut.InboundIntegrations, 1, "IntegrationArn filter should match the created integration") // ModifyIntegration, addressed by ARN like a real client would (see @@ -222,7 +224,7 @@ func TestIntegration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var modifyOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &modifyOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &modifyOut, jsonx.V1())) assert.Equal(t, "my-integration", modifyOut["IntegrationName"]) assert.Equal(t, integrationARN, modifyOut["IntegrationArn"]) assert.Equal(t, "arn:aws:s3:::my-source-bucket", modifyOut["SourceArn"]) @@ -235,7 +237,7 @@ func TestIntegration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteOut, jsonx.V1())) assert.Equal(t, "my-integration", deleteOut["IntegrationName"]) assert.Equal(t, integrationARN, deleteOut["IntegrationArn"]) assert.Equal(t, "arn:aws:s3:::my-source-bucket", deleteOut["SourceArn"]) @@ -261,7 +263,7 @@ func TestIntegration_ReachesActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.Equal(t, "CREATING", createOut["Status"]) require.Eventually(t, func() bool { @@ -277,7 +279,7 @@ func TestIntegration_ReachesActive(t *testing.T) { Status string `json:"Status"` } `json:"Integrations"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) return len(out.Integrations) == 1 && out.Integrations[0].Status == "ACTIVE" }, 2*time.Second, 10*time.Millisecond) @@ -297,7 +299,7 @@ func TestListIntegrationResourceProperties_ReturnsStoredEntries(t *testing.T) { var empty struct { IntegrationResourcePropertyList []map[string]any `json:"IntegrationResourcePropertyList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty, jsonx.V1())) assert.Empty(t, empty.IntegrationResourcePropertyList) doGlueRequest(t, h, "CreateIntegrationResourceProperty", map[string]any{ @@ -311,7 +313,7 @@ func TestListIntegrationResourceProperties_ReturnsStoredEntries(t *testing.T) { var out struct { IntegrationResourcePropertyList []map[string]any `json:"IntegrationResourcePropertyList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.IntegrationResourcePropertyList, 1) assert.Equal(t, "arn:aws:glue:us-east-1:123456789012:connection/conn1", out.IntegrationResourcePropertyList[0]["ResourceArn"]) @@ -348,7 +350,7 @@ func TestUpdateIntegrationResourceProperty_RequiresExistingEntry(t *testing.T) { var out struct { SourceProcessingProperties map[string]any `json:"SourceProcessingProperties"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "updated", out.SourceProcessingProperties["key"]) } @@ -387,7 +389,7 @@ func TestUpdateIntegrationTableProperties_RequiresExistingEntry(t *testing.T) { var out struct { SourceTableConfig map[string]string `json:"SourceTableConfig"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "updated", out.SourceTableConfig["key"]) } diff --git a/services/glue/handler_jobs.go b/services/glue/handler_jobs.go index e5a8fb4203..4a69daf35e 100644 --- a/services/glue/handler_jobs.go +++ b/services/glue/handler_jobs.go @@ -2,7 +2,7 @@ package glue import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" gluetypes "github.com/aws/aws-sdk-go-v2/service/glue/types" @@ -35,13 +35,13 @@ type createJobInput struct { // jobExtraMembers are the CreateJob/JobUpdate members shared by both inputs. type jobExtraMembers struct { - NonOverridableArguments map[string]string `json:"NonOverridableArguments,omitempty"` - CodeGenConfigurationNodes map[string]json.RawMessage `json:"CodeGenConfigurationNodes,omitempty"` - JobRunQueuingEnabled *bool `json:"JobRunQueuingEnabled,omitempty"` - LogURI string `json:"LogUri,omitempty"` - SecurityConfiguration string `json:"SecurityConfiguration,omitempty"` - ExecutionClass string `json:"ExecutionClass,omitempty"` - MaintenanceWindow string `json:"MaintenanceWindow,omitempty"` + NonOverridableArguments map[string]string `json:"NonOverridableArguments,omitempty"` + CodeGenConfigurationNodes map[string]jsontext.Value `json:"CodeGenConfigurationNodes,omitempty"` + JobRunQueuingEnabled *bool `json:"JobRunQueuingEnabled,omitempty"` + LogURI string `json:"LogUri,omitempty"` + SecurityConfiguration string `json:"SecurityConfiguration,omitempty"` + ExecutionClass string `json:"ExecutionClass,omitempty"` + MaintenanceWindow string `json:"MaintenanceWindow,omitempty"` } func (m jobExtraMembers) apply(j *Job) { diff --git a/services/glue/handler_jobs_test.go b/services/glue/handler_jobs_test.go index 896478fe47..887531f3e6 100644 --- a/services/glue/handler_jobs_test.go +++ b/services/glue/handler_jobs_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -49,7 +50,7 @@ func Test_StartTrigger_OnDemand_StaysCreatedAndFiresJobRun(t *testing.T) { JobRunState string `json:"JobRunState"` } `json:"JobRuns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &runsOut, jsonx.V1())) require.Len(t, runsOut.JobRuns, 1) assert.NotEmpty(t, runsOut.JobRuns[0].JobRunState) } @@ -158,7 +159,7 @@ func Test_Job_MaxCapacity(t *testing.T) { MaxCapacity float64 `json:"MaxCapacity"` } `json:"Job"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.InDelta(t, tc.body["MaxCapacity"], out.Job.MaxCapacity, 0.0001) }) } @@ -448,7 +449,7 @@ func TestJobLifecycle(t *testing.T) { if tt.check != nil && rec.Code == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.check(t, out) } }) @@ -534,7 +535,7 @@ func TestBatchStopJobRun(t *testing.T) { runRec := doGlueRequest(t, h, "StartJobRun", map[string]any{"JobName": "j"}) var runOut map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &runOut, jsonx.V1())) runID := runOut["JobRunId"].(string) doGlueRequest(t, h, "BatchStopJobRun", map[string]any{ @@ -547,7 +548,7 @@ func TestBatchStopJobRun(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) errs, _ := out["Errors"].([]any) assert.Len(t, errs, tt.wantErrors) }) @@ -606,7 +607,7 @@ func TestUpdateJobFromSourceControl_ValidatesJob(t *testing.T) { } `json:"SourceControlDetails"` } `json:"Job"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "GITHUB", out.Job.SourceControlDetails.Provider) assert.Equal(t, "my-repo", out.Job.SourceControlDetails.Repository) assert.Equal(t, "main", out.Job.SourceControlDetails.Branch) @@ -699,7 +700,7 @@ func TestHandlerJobRuns_StartJobRun(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["JobRunId"]) } }) @@ -749,7 +750,7 @@ func TestHandlerJobRuns_GetJobRun(t *testing.T) { rec := doGlueRequest(t, h, "StartJobRun", map[string]any{"JobName": "my-job"}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) runID = out["JobRunId"] } @@ -758,7 +759,7 @@ func TestHandlerJobRuns_GetJobRun(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["JobRun"]) } }) @@ -805,7 +806,7 @@ func TestHandlerJobRuns_GetJobRuns(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) runs, ok := out["JobRuns"].([]any) require.True(t, ok) assert.Len(t, runs, tt.numRuns) @@ -855,7 +856,7 @@ func TestHandlerJobRuns_BatchStopJobRun(t *testing.T) { startRec := doGlueRequest(t, h, "StartJobRun", map[string]any{"JobName": "my-job"}) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) realRunID := startOut["JobRunId"] stopIDs := []string{realRunID} @@ -867,7 +868,7 @@ func TestHandlerJobRuns_BatchStopJobRun(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) errs, _ := out["Errors"].([]any) assert.Len(t, errs, tt.wantErrors) }) @@ -910,7 +911,7 @@ func TestHandlerJobRuns_GetJobBookmark(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["JobBookmarkEntry"]) }) } diff --git a/services/glue/handler_materialized_views_test.go b/services/glue/handler_materialized_views_test.go index 19c98be9bf..1df4994549 100644 --- a/services/glue/handler_materialized_views_test.go +++ b/services/glue/handler_materialized_views_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestStopMaterializedViewRefreshTaskRun_NotFound verifies that @@ -53,7 +55,7 @@ func TestStopMaterializedViewRefreshTaskRun_NotFound(t *testing.T) { var out struct { RunID string `json:"MaterializedViewRefreshTaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.RunID, "expected MaterializedViewRefreshTaskRunId in response") } @@ -99,7 +101,7 @@ func TestMaterializedViewRefreshTaskRun(t *testing.T) { }) require.Equal(t, http.StatusOK, startRefreshRec1.Code) var startRefreshOut1 map[string]any - require.NoError(t, json.Unmarshal(startRefreshRec1.Body.Bytes(), &startRefreshOut1)) + require.NoError(t, json.Unmarshal(startRefreshRec1.Body.Bytes(), &startRefreshOut1, jsonx.V1())) assert.NotEmpty(t, startRefreshOut1["MaterializedViewRefreshTaskRunId"]) startRec := doGlueRequest(t, h, "StartMaterializedViewRefreshTaskRun", map[string]any{ @@ -108,7 +110,7 @@ func TestMaterializedViewRefreshTaskRun(t *testing.T) { }) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["MaterializedViewRefreshTaskRunId"].(string) getRefreshRec := doGlueRequest(t, h, "GetMaterializedViewRefreshTaskRun", map[string]any{ @@ -145,7 +147,7 @@ func TestMaterializedViewRefresh_Stateful(t *testing.T) { var startOut struct { RunID string `json:"MaterializedViewRefreshTaskRunId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut.RunID) getRec := doGlueRequest(t, h, "GetMaterializedViewRefreshTaskRun", map[string]any{ @@ -159,7 +161,7 @@ func TestMaterializedViewRefresh_Stateful(t *testing.T) { Status string `json:"Status"` } `json:"MaterializedViewRefreshTaskRun"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, startOut.RunID, getOut.Run.RunID) assert.Equal(t, "RUNNING", getOut.Run.Status) @@ -179,7 +181,7 @@ func TestMaterializedViewRefresh_Stateful(t *testing.T) { Status string `json:"Status"` } `json:"MaterializedViewRefreshTaskRun"` } - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2, jsonx.V1())) assert.Equal(t, "STOPPED", getOut2.Run.Status) }) diff --git a/services/glue/handler_ml_test.go b/services/glue/handler_ml_test.go index 9026881424..d83a300070 100644 --- a/services/glue/handler_ml_test.go +++ b/services/glue/handler_ml_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -84,7 +85,7 @@ func TestMLTransform_CRUD(t *testing.T) { createRec := doGlueRequest(t, h, "CreateMLTransform", createBody) if createRec.Code == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) transformID, _ = out["TransformId"].(string) } @@ -106,7 +107,7 @@ func TestMLTransform_Delete(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) transformID := out["TransformId"].(string) rec := doGlueRequest(t, h, "DeleteMLTransform", map[string]any{"TransformId": transformID}) @@ -232,7 +233,7 @@ func createTestMLTransform(t *testing.T, h *glue.Handler, name string) string { var out struct { TransformID string `json:"TransformId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.TransformID) return out.TransformID @@ -296,7 +297,7 @@ func TestMLLabelingSetGenerationTaskRun(t *testing.T) { var out struct { TaskRunID string `json:"TaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.TaskRunID) } @@ -337,7 +338,7 @@ func TestMLExportImportLabels(t *testing.T) { var out struct { TaskRunID string `json:"TaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.TaskRunID) }) } @@ -380,7 +381,7 @@ func TestGetMLTaskRun(t *testing.T) { var startOut struct { TaskRunID string `json:"TaskRunId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) getRec := doGlueRequest(t, h, "GetMLTaskRun", map[string]any{ "TransformId": transformID, @@ -393,7 +394,7 @@ func TestGetMLTaskRun(t *testing.T) { TaskRunID string `json:"TaskRunId"` Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, transformID, getOut.TransformID) assert.Equal(t, startOut.TaskRunID, getOut.TaskRunID) assert.Equal(t, "RUNNING", getOut.Status) @@ -413,7 +414,7 @@ func TestGetMLTaskRun(t *testing.T) { var getOut2 struct { Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getOut2, jsonx.V1())) assert.Equal(t, "STOPPED", getOut2.Status) }) } @@ -432,7 +433,7 @@ func TestGetMLTaskRuns(t *testing.T) { var out struct { TaskRuns []any `json:"TaskRuns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.TaskRuns) }) @@ -457,7 +458,7 @@ func TestGetMLTaskRuns(t *testing.T) { var out struct { TaskRuns []any `json:"TaskRuns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.TaskRuns, 3) }) } @@ -491,7 +492,7 @@ func TestGetMLTaskRuns_SDKPagination_TotalOrderNoTiesLost(t *testing.T) { var out struct { TaskRunID string `json:"TaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.TaskRunID) wantIDs[out.TaskRunID] = true } @@ -543,7 +544,7 @@ func TestGetMLTaskRuns_SDKFilter_ByStatus(t *testing.T) { var started struct { TaskRunID string `json:"TaskRunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) cancelRec := doGlueRequest(t, h, "CancelMLTaskRun", map[string]any{ "TransformId": transformID, @@ -625,7 +626,7 @@ func TestListMLTransforms_Stateful(t *testing.T) { var out struct { TransformIDs []string `json:"TransformIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.TransformIDs, tc.wantLen) }) } diff --git a/services/glue/handler_pagination_test.go b/services/glue/handler_pagination_test.go index e086978989..fe552b090c 100644 --- a/services/glue/handler_pagination_test.go +++ b/services/glue/handler_pagination_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPagination_GetDatabases(t *testing.T) { @@ -90,7 +92,7 @@ func TestPagination_GetDatabases(t *testing.T) { NextToken string `json:"NextToken"` DatabaseList []any `json:"DatabaseList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.DatabaseList, tc.wantCount) if tc.wantHasNext { assert.NotEmpty(t, out.NextToken) @@ -188,7 +190,7 @@ func TestPagination_GetTables(t *testing.T) { NextToken string `json:"NextToken"` TableList []any `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.TableList, tc.wantCount) if tc.wantHasNext { assert.NotEmpty(t, out.NextToken) @@ -281,7 +283,7 @@ func TestPagination_GetPartitions(t *testing.T) { NextToken string `json:"NextToken"` Partitions []any `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Partitions, tc.wantCount) if tc.wantHasNext { assert.NotEmpty(t, out.NextToken) diff --git a/services/glue/handler_partition_indexes_test.go b/services/glue/handler_partition_indexes_test.go index 56b271151a..e1b020a005 100644 --- a/services/glue/handler_partition_indexes_test.go +++ b/services/glue/handler_partition_indexes_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -120,7 +121,7 @@ func TestPartitionIndexLifecycle(t *testing.T) { } `json:"Keys"` } `json:"PartitionIndexDescriptorList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Indexes, 2) assert.Equal(t, "year_idx", out.Indexes[0].IndexName) assert.Equal(t, "ACTIVE", out.Indexes[0].IndexStatus) diff --git a/services/glue/handler_partitions_test.go b/services/glue/handler_partitions_test.go index 16c0881527..5f1057c7ed 100644 --- a/services/glue/handler_partitions_test.go +++ b/services/glue/handler_partitions_test.go @@ -2,7 +2,7 @@ package glue_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -112,7 +113,7 @@ func Test_BatchGetPartition_ReturnsRealPartitions(t *testing.T) { Values []string `json:"Values"` } `json:"UnprocessedKeys"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Partitions, 1) assert.Equal(t, []string{"2024-01-01"}, out.Partitions[0].Values) @@ -303,7 +304,7 @@ func TestAuditGlue_GetPartitions_Expression(t *testing.T) { Values []string `json:"Values"` } `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) got := make([][]string, len(out.Partitions)) for i, p := range out.Partitions { @@ -390,7 +391,7 @@ func TestHTTPBatchCreatePartition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["Partitions"]) } @@ -398,7 +399,7 @@ func TestHTTPBatchCreatePartition(t *testing.T) { func postGlue(t *testing.T, h *glue.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bs, err := json.Marshal(body) + bs, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bs)) @@ -467,7 +468,7 @@ func TestGetPartition_Found(t *testing.T) { Values []string `json:"Values"` } `json:"Partition"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, []string{"2024", "01"}, out.Partition.Values) } @@ -503,7 +504,7 @@ func TestGetPartitions_List(t *testing.T) { Values []string `json:"Values"` } `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Partitions, 2) } @@ -553,7 +554,7 @@ func TestUpdatePartition_Updates(t *testing.T) { } `json:"StorageDescriptor"` } `json:"Partition"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "s3://updated-bucket/tbl3", out.Partition.StorageDescriptor.Location) } @@ -608,7 +609,7 @@ func TestBatchUpdatePartition_Updates(t *testing.T) { var out struct { Errors []any `json:"Errors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Errors) } diff --git a/services/glue/handler_resource_limits_test.go b/services/glue/handler_resource_limits_test.go index 5fe9433883..5ceba77b3b 100644 --- a/services/glue/handler_resource_limits_test.go +++ b/services/glue/handler_resource_limits_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -26,7 +27,7 @@ func assertResourceLimitExceeded(t *testing.T, h *glue.Handler, action string, b assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ResourceNumberLimitExceededException", out["__type"]) } @@ -327,7 +328,7 @@ func TestResourceNumberLimitExceeded_PartitionsPerTable(t *testing.T) { } `json:"Errors"` Partitions []map[string]any `json:"Partitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Partitions, testResourceCap) require.Len(t, out.Errors, 1) diff --git a/services/glue/handler_resource_policies_test.go b/services/glue/handler_resource_policies_test.go index bc41a2ee10..68fcdf8395 100644 --- a/services/glue/handler_resource_policies_test.go +++ b/services/glue/handler_resource_policies_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func Test_PutResourcePolicy_ExistsConditions(t *testing.T) { @@ -58,7 +60,7 @@ func Test_PutResourcePolicy_HashCondition(t *testing.T) { var out struct { PolicyHash string `json:"PolicyHash"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.PolicyHash) // Stale hash -> ConditionCheckFailureException, and the policy is untouched. @@ -90,7 +92,7 @@ func Test_DeleteResourcePolicy_HashCondition(t *testing.T) { var out struct { PolicyHash string `json:"PolicyHash"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Wrong hash -> rejected, policy stays. rec = doGlueRequest(t, h, "DeleteResourcePolicy", map[string]any{ @@ -126,7 +128,7 @@ func TestGetResourcePolicies_ReturnsStoredPolicies(t *testing.T) { var empty struct { GetResourcePoliciesResponseList []map[string]any `json:"GetResourcePoliciesResponseList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty, jsonx.V1())) assert.Empty(t, empty.GetResourcePoliciesResponseList) doGlueRequest(t, h, "PutResourcePolicy", map[string]any{ @@ -143,7 +145,7 @@ func TestGetResourcePolicies_ReturnsStoredPolicies(t *testing.T) { var out struct { GetResourcePoliciesResponseList []map[string]any `json:"GetResourcePoliciesResponseList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.GetResourcePoliciesResponseList, 2) for _, p := range out.GetResourcePoliciesResponseList { diff --git a/services/glue/handler_schemas.go b/services/glue/handler_schemas.go index 3cb0620f32..34d7f691df 100644 --- a/services/glue/handler_schemas.go +++ b/services/glue/handler_schemas.go @@ -2,7 +2,7 @@ package glue import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -11,6 +11,8 @@ import ( "time" gluetypes "github.com/aws/aws-sdk-go-v2/service/glue/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validateSchemaDefinition checks a schema definition string against its DataFormat. @@ -611,7 +613,7 @@ type schemaVersionNumberInput struct { func (s *schemaVersionNumberInput) UnmarshalJSON(data []byte) error { var n int64 - if err := json.Unmarshal(data, &n); err == nil { + if err := json.Unmarshal(data, &n, jsonx.V1()); err == nil { s.Number = n return nil @@ -621,7 +623,7 @@ func (s *schemaVersionNumberInput) UnmarshalJSON(data []byte) error { VersionNumber int64 `json:"VersionNumber"` } - if err := json.Unmarshal(data, &v); err != nil { + if err := json.Unmarshal(data, &v, jsonx.V1()); err != nil { return err } diff --git a/services/glue/handler_schemas_test.go b/services/glue/handler_schemas_test.go index f11ff40776..c97b28113f 100644 --- a/services/glue/handler_schemas_test.go +++ b/services/glue/handler_schemas_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -123,7 +124,7 @@ func TestCheckSchemaVersionValidity(t *testing.T) { Error string `json:"Error"` Valid bool `json:"Valid"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tc.wantValid, out.Valid) if tc.wantError != "" { @@ -187,7 +188,7 @@ func TestDeleteSchemaVersions(t *testing.T) { VersionNumber int64 `json:"VersionNumber"` } `json:"SchemaVersionErrors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SchemaVersionErrors, tc.wantErrCount) }) } @@ -219,7 +220,7 @@ func TestDeleteSchemaVersions_Stateful(t *testing.T) { VersionNumber int64 `json:"VersionNumber"` } `json:"SchemaVersionErrors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Version 9 doesn't exist → 1 error. require.Len(t, out.SchemaVersionErrors, 1) @@ -413,7 +414,7 @@ func TestSchemaRegistry_SchemaVersion_CRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, registerRec.Code) var registerOut map[string]any - require.NoError(t, json.Unmarshal(registerRec.Body.Bytes(), ®isterOut)) + require.NoError(t, json.Unmarshal(registerRec.Body.Bytes(), ®isterOut, jsonx.V1())) assert.NotEmpty(t, registerOut["SchemaVersionId"]) getSchemaVersionRec := doGlueRequest(t, h, "GetSchemaVersion", map[string]any{ @@ -422,7 +423,7 @@ func TestSchemaRegistry_SchemaVersion_CRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, getSchemaVersionRec.Code) var getSchemaVersionOut map[string]any - require.NoError(t, json.Unmarshal(getSchemaVersionRec.Body.Bytes(), &getSchemaVersionOut)) + require.NoError(t, json.Unmarshal(getSchemaVersionRec.Body.Bytes(), &getSchemaVersionOut, jsonx.V1())) assert.EqualValues(t, 1, getSchemaVersionOut["VersionNumber"]) listSchemaVersionsRec := doGlueRequest(t, h, "ListSchemaVersions", map[string]any{ @@ -437,7 +438,7 @@ func TestSchemaRegistry_SchemaVersion_CRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, checkValidityRec.Code) var checkValidityOut map[string]any - require.NoError(t, json.Unmarshal(checkValidityRec.Body.Bytes(), &checkValidityOut)) + require.NoError(t, json.Unmarshal(checkValidityRec.Body.Bytes(), &checkValidityOut, jsonx.V1())) assert.True(t, checkValidityOut["Valid"].(bool)) } @@ -483,7 +484,7 @@ func TestCreateSchema_WithDefinition_PopulatesVersionFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.InDelta(t, tt.wantLatest, out["LatestSchemaVersion"], 0) assert.InDelta(t, tt.wantNext, out["NextSchemaVersion"], 0) @@ -554,7 +555,7 @@ func setupTestSchema(t *testing.T, h *glue.Handler) string { var sv1Out struct { SchemaVersionID string `json:"SchemaVersionId"` } - require.NoError(t, json.Unmarshal(reg1Rec.Body.Bytes(), &sv1Out)) + require.NoError(t, json.Unmarshal(reg1Rec.Body.Bytes(), &sv1Out, jsonx.V1())) reg2Rec := doGlueRequest(t, h, "RegisterSchemaVersion", map[string]any{ "SchemaId": map[string]any{"RegistryName": "reg1", "SchemaName": "schema1"}, @@ -565,7 +566,7 @@ func setupTestSchema(t *testing.T, h *glue.Handler) string { var sv2Out struct { SchemaVersionID string `json:"SchemaVersionId"` } - require.NoError(t, json.Unmarshal(reg2Rec.Body.Bytes(), &sv2Out)) + require.NoError(t, json.Unmarshal(reg2Rec.Body.Bytes(), &sv2Out, jsonx.V1())) return sv1Out.SchemaVersionID } @@ -632,7 +633,7 @@ func TestSchemaVersionMetadata_Lifecycle(t *testing.T) { } `json:"MetadataInfoMap"` SchemaVersionID string `json:"SchemaVersionId"` } - require.NoError(t, json.Unmarshal(queryRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(queryRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, v1ID, out.SchemaVersionID) got := make(map[string]string, len(out.MetadataInfo)) @@ -659,7 +660,7 @@ func TestSchemaVersionMetadata_EmptyQuery(t *testing.T) { var out struct { MetadataInfo map[string]any `json:"MetadataInfoMap"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.MetadataInfo) } @@ -714,7 +715,7 @@ func TestGetSchemaByDefinition_Stateful(t *testing.T) { SchemaVersionID string `json:"SchemaVersionId"` Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.SchemaVersionID) assert.Equal(t, "AVAILABLE", out.Status) } @@ -764,7 +765,7 @@ func TestGetSchemaVersionsDiff_Stateful(t *testing.T) { var out struct { Diff string `json:"Diff"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.wantDiff { assert.NotEmpty(t, out.Diff) @@ -884,7 +885,7 @@ func TestGetSchemaVersionsDiff(t *testing.T) { var out struct { Diff string `json:"Diff"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.wantDiff { assert.NotEmpty(t, out.Diff) @@ -917,7 +918,7 @@ func TestListRegistries_OmitsGetOnlyFields(t *testing.T) { var out struct { Registries []map[string]any `json:"Registries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Registries, 1) item := out.Registries[0] @@ -950,7 +951,7 @@ func TestListSchemas_OmitsGetOnlyFields(t *testing.T) { var out struct { Schemas []map[string]any `json:"Schemas"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Schemas, 1) item := out.Schemas[0] @@ -990,7 +991,7 @@ func TestListSchemaVersions_OmitsGetOnlyFields(t *testing.T) { var out struct { Schemas []map[string]any `json:"Schemas"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Schemas, 1) item := out.Schemas[0] diff --git a/services/glue/handler_smoke_test.go b/services/glue/handler_smoke_test.go index 63ef170d4d..8d4e1c97eb 100644 --- a/services/glue/handler_smoke_test.go +++ b/services/glue/handler_smoke_test.go @@ -2,7 +2,7 @@ package glue_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,13 +10,14 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) // doGlueOp is a helper to POST a JSON body to the Glue handler via echo. func doGlueOp(t *testing.T, h *glue.Handler, op string, body any) *httptest.ResponseRecorder { t.Helper() - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) if err != nil { t.Fatalf("marshal request: %v", err) } diff --git a/services/glue/handler_table_optimizers_test.go b/services/glue/handler_table_optimizers_test.go index ba5c7a0d33..247c94f20e 100644 --- a/services/glue/handler_table_optimizers_test.go +++ b/services/glue/handler_table_optimizers_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListTableOptimizerRuns_ReturnsRealHistory verifies ListTableOptimizerRuns @@ -50,7 +52,7 @@ func TestListTableOptimizerRuns_ReturnsRealHistory(t *testing.T) { var out struct { TableOptimizerRuns []map[string]any `json:"TableOptimizerRuns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.TableOptimizerRuns, 1) assert.Equal(t, "completed", out.TableOptimizerRuns[0]["eventType"]) } diff --git a/services/glue/handler_tables_test.go b/services/glue/handler_tables_test.go index 00d754b65e..b23a365ebc 100644 --- a/services/glue/handler_tables_test.go +++ b/services/glue/handler_tables_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -100,7 +101,7 @@ func Test_TableStorageDescriptor_RoundTrip(t *testing.T) { Retention int `json:"Retention"` } `json:"Table"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "hive", out.Table.Owner) assert.Equal(t, 7, out.Table.Retention) @@ -212,7 +213,7 @@ func TestAuditGlue_GetTables_Expression(t *testing.T) { Name string `json:"Name"` } `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) gotNames := make([]string, len(out.TableList)) for i, tbl := range out.TableList { @@ -253,7 +254,7 @@ func TestHTTPBatchDeleteTable(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) errs, ok := out["Errors"].([]any) require.True(t, ok) assert.Empty(t, errs) @@ -299,7 +300,7 @@ func TestCloneTableWithColumns(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) assert.NotNil(t, tbl) @@ -356,7 +357,7 @@ func TestSearchTables_EmptyFilter(t *testing.T) { Name string `json:"Name"` } `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.TableList, 2) } @@ -382,7 +383,7 @@ func TestSearchTables_WithFilter(t *testing.T) { Name string `json:"Name"` } `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.TableList, 1) assert.Equal(t, "orders", out.TableList[0].Name) } diff --git a/services/glue/handler_test.go b/services/glue/handler_test.go index f11b70cd22..f5db9da77e 100644 --- a/services/glue/handler_test.go +++ b/services/glue/handler_test.go @@ -2,7 +2,7 @@ package glue_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -43,7 +44,7 @@ func dqEvalRunRequiredFields(rulesetNames []string) map[string]any { func doGlueRequest(t *testing.T, h *glue.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -229,7 +230,7 @@ func TestGlue_DatabaseLifecycle(t *testing.T) { CatalogID string `json:"CatalogId"` } `json:"Database"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "mydb", getOut.Database.Name) assert.Equal(t, testAccountID, getOut.Database.CatalogID) @@ -242,7 +243,7 @@ func TestGlue_DatabaseLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"DatabaseList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.DatabaseList, 1) // Delete @@ -289,7 +290,7 @@ func TestGlue_TableLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"Table"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "mytable", getOut.Table.Name) // Update table @@ -311,7 +312,7 @@ func TestGlue_TableLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.TableList, 1) // Delete table @@ -364,7 +365,7 @@ func TestGlue_CrawlerLifecycle(t *testing.T) { State string `json:"State"` } `json:"Crawler"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "my-crawler", getOut.Crawler.Name) assert.Equal(t, "READY", getOut.Crawler.State) @@ -377,7 +378,7 @@ func TestGlue_CrawlerLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"Crawlers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Crawlers, 1) // UpdateCrawler @@ -420,7 +421,7 @@ func TestGlue_JobLifecycle(t *testing.T) { var createOut struct { Name string `json:"Name"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.Equal(t, "my-job", createOut.Name) // GetJob @@ -432,7 +433,7 @@ func TestGlue_JobLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"Job"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "my-job", getOut.Job.Name) // GetJobs @@ -444,7 +445,7 @@ func TestGlue_JobLifecycle(t *testing.T) { Name string `json:"Name"` } `json:"Jobs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Jobs, 1) // UpdateJob @@ -460,7 +461,7 @@ func TestGlue_JobLifecycle(t *testing.T) { var updateOut struct { JobName string `json:"JobName"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateOut, jsonx.V1())) assert.Equal(t, "my-job", updateOut.JobName) // DeleteJob @@ -502,7 +503,7 @@ func TestGlue_Tags(t *testing.T) { var tagsOut struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut, jsonx.V1())) assert.Equal(t, "value1", tagsOut.Tags["key1"]) // TagResource @@ -527,7 +528,7 @@ func TestGlue_Tags(t *testing.T) { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &finalTagsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &finalTagsOut, jsonx.V1())) assert.NotContains(t, finalTagsOut.Tags, "key1") assert.Equal(t, "value2", finalTagsOut.Tags["key2"]) } @@ -635,7 +636,7 @@ func TestGlue_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -716,7 +717,7 @@ func TestGlue_CrawlerTagsLifecycle(t *testing.T) { var tagsOut struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut, jsonx.V1())) assert.Equal(t, "tag", tagsOut.Tags["extra"]) assert.Equal(t, "test", tagsOut.Tags["env"]) @@ -767,7 +768,7 @@ func TestGlue_JobTagsLifecycle(t *testing.T) { var tagsOut struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsOut, jsonx.V1())) assert.Equal(t, "prod", tagsOut.Tags["env"]) assert.Equal(t, "data", tagsOut.Tags["team"]) @@ -882,7 +883,7 @@ func idFromResponse(t *testing.T, body []byte) string { var out struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) require.NotEmpty(t, out.ID) return out.ID @@ -1202,7 +1203,7 @@ func TestGlue_AssociateGlossaryTerms_TableDriven(t *testing.T) { var assocOut struct { GlossaryTerms []string `json:"GlossaryTerms"` } - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocOut)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocOut, jsonx.V1())) require.Contains(t, assocOut.GlossaryTerms, termID) return map[string]any{"AssetIdentifier": "asset-2", "GlossaryTermIdentifiers": []string{termID}} @@ -1213,7 +1214,7 @@ func TestGlue_AssociateGlossaryTerms_TableDriven(t *testing.T) { var out struct { GlossaryTerms []string `json:"GlossaryTerms"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Empty(t, out.GlossaryTerms) }, }, @@ -1246,7 +1247,7 @@ func TestGlue_AssociateGlossaryTerms_TableDriven(t *testing.T) { var out struct { GlossaryTerms []string `json:"GlossaryTerms"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Empty(t, out.GlossaryTerms, "deleted glossary term must be disassociated from the asset") }, }, diff --git a/services/glue/handler_triggers_test.go b/services/glue/handler_triggers_test.go index eaad998da5..a38b9cd53d 100644 --- a/services/glue/handler_triggers_test.go +++ b/services/glue/handler_triggers_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -22,7 +23,7 @@ func triggerState(t *testing.T, h *glue.Handler, name string) string { State string `json:"State"` } `json:"Trigger"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.Trigger.State } @@ -174,7 +175,7 @@ func TestTrigger_GetTrigger(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if !tt.wantErr { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) trig, ok := out["Trigger"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-trigger", trig["Name"]) @@ -278,7 +279,7 @@ func TestTrigger_StartStopActivate(t *testing.T) { if tt.wantCode == http.StatusOK && tt.wantState != "" { get := doGlueRequest(t, h, "GetTrigger", map[string]any{"Name": "t1"}) var out map[string]any - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) trig := out["Trigger"].(map[string]any) assert.Equal(t, tt.wantState, trig["State"]) } @@ -305,7 +306,7 @@ func TestTrigger_BatchGetAndList(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) triggers := out["Triggers"].([]any) assert.Len(t, triggers, 2) missing := out["TriggersNotFound"].([]any) @@ -352,7 +353,7 @@ func TestTrigger_WithActions(t *testing.T) { getRec := doGlueRequest(t, h, "GetTrigger", map[string]any{"Name": "trig-actions"}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) trig := out["Trigger"].(map[string]any) actions := trig["Actions"].([]any) assert.Len(t, actions, 2) diff --git a/services/glue/handler_unfiltered_test.go b/services/glue/handler_unfiltered_test.go index d5e73e56a6..e07b763d15 100644 --- a/services/glue/handler_unfiltered_test.go +++ b/services/glue/handler_unfiltered_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetUnfilteredTableMetadata exercises the GetUnfilteredTableMetadata handler. @@ -26,7 +28,7 @@ func TestGetUnfilteredTableMetadata(t *testing.T) { var out struct { AuthorizedColumns []string `json:"AuthorizedColumns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out.AuthorizedColumns) }) @@ -59,7 +61,7 @@ func TestGetUnfilteredTableMetadata(t *testing.T) { } `json:"Table"` AuthorizedColumns []string `json:"AuthorizedColumns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "uftbl", out.Table.Name) assert.NotNil(t, out.AuthorizedColumns) }) @@ -79,7 +81,7 @@ func TestGetUnfilteredTableMetadata(t *testing.T) { var out struct { IsRegisteredWithLakeFormation bool `json:"IsRegisteredWithLakeFormation"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.False(t, out.IsRegisteredWithLakeFormation) }) } @@ -102,7 +104,7 @@ func TestGetUnfilteredPartitionMetadata(t *testing.T) { var out struct { AuthorizedColumns []string `json:"AuthorizedColumns"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out.AuthorizedColumns) }) @@ -141,7 +143,7 @@ func TestGetUnfilteredPartitionMetadata(t *testing.T) { AuthorizedColumns []string `json:"AuthorizedColumns"` IsRegisteredWithLakeFormation bool `json:"IsRegisteredWithLakeFormation"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, []string{"2024", "01"}, out.Partition.Values) assert.NotNil(t, out.AuthorizedColumns) assert.False(t, out.IsRegisteredWithLakeFormation) @@ -165,7 +167,7 @@ func TestGetUnfilteredPartitionsMetadata(t *testing.T) { var out struct { UnfilteredPartitions []any `json:"UnfilteredPartitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.UnfilteredPartitions) }) @@ -195,7 +197,7 @@ func TestGetUnfilteredPartitionsMetadata(t *testing.T) { var out struct { UnfilteredPartitions []any `json:"UnfilteredPartitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.UnfilteredPartitions) }) @@ -216,7 +218,7 @@ func TestGetUnfilteredPartitionsMetadata(t *testing.T) { var out struct { UnfilteredPartitions []any `json:"UnfilteredPartitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.UnfilteredPartitions, 2) }) @@ -241,7 +243,7 @@ func TestGetUnfilteredPartitionsMetadata(t *testing.T) { AuthorizedColumns []string `json:"AuthorizedColumns"` } `json:"UnfilteredPartitions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.UnfilteredPartitions, 1) assert.Equal(t, []string{"2024"}, out.UnfilteredPartitions[0].Partition.Values) assert.NotNil(t, out.UnfilteredPartitions[0].AuthorizedColumns) @@ -287,7 +289,7 @@ func TestUnfilteredMetadata_IntegrationFlow(t *testing.T) { Name string `json:"Name"` } `json:"Table"` } - require.NoError(t, json.Unmarshal(tblMetaRec.Body.Bytes(), &tblMeta)) + require.NoError(t, json.Unmarshal(tblMetaRec.Body.Bytes(), &tblMeta, jsonx.V1())) assert.Equal(t, "integ-uf-tbl", tblMeta.Table.Name) // GetUnfilteredPartitionsMetadata lists all partitions. @@ -300,7 +302,7 @@ func TestUnfilteredMetadata_IntegrationFlow(t *testing.T) { var partsMeta struct { UnfilteredPartitions []any `json:"UnfilteredPartitions"` } - require.NoError(t, json.Unmarshal(partsMetaRec.Body.Bytes(), &partsMeta)) + require.NoError(t, json.Unmarshal(partsMetaRec.Body.Bytes(), &partsMeta, jsonx.V1())) assert.Len(t, partsMeta.UnfilteredPartitions, 1) // GetUnfilteredPartitionMetadata retrieves the specific partition. @@ -316,6 +318,6 @@ func TestUnfilteredMetadata_IntegrationFlow(t *testing.T) { Values []string `json:"Values"` } `json:"Partition"` } - require.NoError(t, json.Unmarshal(partMetaRec.Body.Bytes(), &partMeta)) + require.NoError(t, json.Unmarshal(partMetaRec.Body.Bytes(), &partMeta, jsonx.V1())) assert.Equal(t, []string{"2024", "06"}, partMeta.Partition.Values) } diff --git a/services/glue/handler_usage_profiles_test.go b/services/glue/handler_usage_profiles_test.go index 451b071fc3..f0be268bd7 100644 --- a/services/glue/handler_usage_profiles_test.go +++ b/services/glue/handler_usage_profiles_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDeleteUsageProfile_NotFound verifies that DeleteUsageProfile raises @@ -203,7 +205,7 @@ func TestGetUsageProfile_FullFields(t *testing.T) { CreatedOn float64 `json:"CreatedOn"` LastModifiedOn float64 `json:"LastModifiedOn"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "full-profile", out.Name) assert.Equal(t, "test description", out.Description) assert.NotZero(t, out.CreatedOn) diff --git a/services/glue/handler_user_defined_functions_test.go b/services/glue/handler_user_defined_functions_test.go index 7352992ed1..4d6d5dd5ea 100644 --- a/services/glue/handler_user_defined_functions_test.go +++ b/services/glue/handler_user_defined_functions_test.go @@ -1,7 +1,8 @@ package glue_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -139,7 +141,7 @@ func TestGetUserDefinedFunctions_Pattern(t *testing.T) { FunctionName string `json:"FunctionName"` } `json:"UserDefinedFunctions"` } - require.NoError(t, json.NewDecoder(rr.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rr.Body), &out, jsonx.V1())) got := make([]string, 0, len(out.UserDefinedFunctions)) for _, u := range out.UserDefinedFunctions { diff --git a/services/glue/handler_workflows_test.go b/services/glue/handler_workflows_test.go index fcd4aa65cd..4a1d2bd030 100644 --- a/services/glue/handler_workflows_test.go +++ b/services/glue/handler_workflows_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -74,7 +75,7 @@ func TestWorkflow_CRUD(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if tt.op == "GetWorkflow" && tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) wf := out["Workflow"].(map[string]any) assert.Equal(t, "wf1", wf["Name"]) } @@ -131,7 +132,7 @@ func TestWorkflow_DeleteAndList(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) wfs := out["Workflows"].([]any) assert.Len(t, wfs, 2) missing := out["MissingWorkflows"].([]any) @@ -150,7 +151,7 @@ func TestWorkflow_RunLifecycle(t *testing.T) { rec := doGlueRequest(t, h, "StartWorkflowRun", map[string]any{"Name": "wf-run"}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["RunId"]) }) @@ -171,20 +172,20 @@ func TestWorkflow_GetRunAndProperties(t *testing.T) { startRec := doGlueRequest(t, h, "StartWorkflowRun", map[string]any{"Name": "wf-props"}) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"].(string) getRunRec := doGlueRequest(t, h, "GetWorkflowRun", map[string]any{"Name": "wf-props", "RunId": runID}) require.Equal(t, http.StatusOK, getRunRec.Code) var getRunOut map[string]any - require.NoError(t, json.Unmarshal(getRunRec.Body.Bytes(), &getRunOut)) + require.NoError(t, json.Unmarshal(getRunRec.Body.Bytes(), &getRunOut, jsonx.V1())) run := getRunOut["Run"].(map[string]any) assert.Equal(t, runID, run["WorkflowRunId"]) getRunsRec := doGlueRequest(t, h, "GetWorkflowRuns", map[string]any{"Name": "wf-props"}) require.Equal(t, http.StatusOK, getRunsRec.Code) var getRunsOut map[string]any - require.NoError(t, json.Unmarshal(getRunsRec.Body.Bytes(), &getRunsOut)) + require.NoError(t, json.Unmarshal(getRunsRec.Body.Bytes(), &getRunsOut, jsonx.V1())) runs := getRunsOut["Runs"].([]any) assert.Len(t, runs, 1) @@ -206,7 +207,7 @@ func TestWorkflow_GetRunAndProperties(t *testing.T) { }) require.Equal(t, http.StatusOK, getPropsRec.Code) var getPropsOut map[string]any - require.NoError(t, json.Unmarshal(getPropsRec.Body.Bytes(), &getPropsOut)) + require.NoError(t, json.Unmarshal(getPropsRec.Body.Bytes(), &getPropsOut, jsonx.V1())) props := getPropsOut["RunProperties"].(map[string]any) assert.Equal(t, "staging", props["env"]) @@ -235,7 +236,7 @@ func TestWorkflow_UpdateDefaultRunProperties(t *testing.T) { getRec := doGlueRequest(t, h, "GetWorkflow", map[string]any{"Name": "wf-drp"}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) wf, ok := out["Workflow"].(map[string]any) require.True(t, ok) props, ok := wf["DefaultRunProperties"].(map[string]any) @@ -351,7 +352,7 @@ func TestResumeWorkflowRun_Stateful(t *testing.T) { RunID string `json:"RunId"` NodeIDs []string `json:"NodeIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.RunID) assert.NotEqual(t, runID, out.RunID, "resume must mint a new RunId, not echo the original") assert.Equal(t, []string{"node-a"}, out.NodeIDs) @@ -373,7 +374,7 @@ func startedWorkflowRun(t *testing.T, h *glue.Handler, name string) (string, str var startOut struct { RunID string `json:"RunId"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) return name, startOut.RunID } @@ -407,7 +408,7 @@ func TestResumeWorkflowRun_EchoesRequestedNodes(t *testing.T) { RunID string `json:"RunId"` NodeIDs []string `json:"NodeIds"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, []string{"node-a", "node-b"}, out.NodeIDs) assert.NotEqual(t, runID, out.RunID) } @@ -502,7 +503,7 @@ func TestWorkflow_Graph(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) wf := out["Workflow"].(map[string]any) if !tt.includeGraph { @@ -547,19 +548,19 @@ func TestWorkflow_LastRun(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out["Workflow"].(map[string]any), "LastRun") startRec := doGlueRequest(t, h, "StartWorkflowRun", map[string]any{"Name": "graphwf"}) require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"].(string) rec = doGlueRequest(t, h, "GetWorkflow", map[string]any{"Name": "graphwf"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) wf := out["Workflow"].(map[string]any) assert.NotContains(t, wf, "Graph") @@ -587,7 +588,7 @@ func TestStopWorkflowRun_StateGuard(t *testing.T) { getRec := doGlueRequest(t, h, "GetWorkflowRun", map[string]any{"Name": wfName, "RunId": runID}) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "RUNNING", getOut["Run"].(map[string]any)["Status"]) stopRec := doGlueRequest(t, h, "StopWorkflowRun", map[string]any{"Name": wfName, "RunId": runID}) @@ -595,20 +596,20 @@ func TestStopWorkflowRun_StateGuard(t *testing.T) { getRec = doGlueRequest(t, h, "GetWorkflowRun", map[string]any{"Name": wfName, "RunId": runID}) require.Equal(t, http.StatusOK, getRec.Code) - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "STOPPED", getOut["Run"].(map[string]any)["Status"]) // Stopping again must fail: the run is no longer RUNNING. stopAgainRec := doGlueRequest(t, h, "StopWorkflowRun", map[string]any{"Name": wfName, "RunId": runID}) assert.Equal(t, http.StatusBadRequest, stopAgainRec.Code) var errOut map[string]string - require.NoError(t, json.Unmarshal(stopAgainRec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(stopAgainRec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "IllegalWorkflowStateException", errOut["__type"]) // Stopping a nonexistent run is EntityNotFoundException, not the state error. missingRec := doGlueRequest(t, h, "StopWorkflowRun", map[string]any{"Name": wfName, "RunId": "no-such-run"}) assert.Equal(t, http.StatusBadRequest, missingRec.Code) - require.NoError(t, json.Unmarshal(missingRec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(missingRec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "EntityNotFoundException", errOut["__type"]) } @@ -667,7 +668,7 @@ func TestSDKRoundTrip_GetWorkflowRuns_Pagination(t *testing.T) { var out struct { RunID string `json:"RunId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) wantIDs[out.RunID] = true } require.Len(t, wantIDs, numRuns) diff --git a/services/glue/models.go b/services/glue/models.go index 54ce6dec3d..012eef0f24 100644 --- a/services/glue/models.go +++ b/services/glue/models.go @@ -1,8 +1,11 @@ package glue import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // DatabaseInput is the input for creating or updating a Glue database. @@ -359,13 +362,13 @@ type Job struct { // NonOverridableArguments are job arguments a run cannot override. NonOverridableArguments map[string]string `json:"NonOverridableArguments,omitempty"` // CodeGenConfigurationNodes is the visual-job DAG, stored verbatim. - CodeGenConfigurationNodes map[string]json.RawMessage `json:"CodeGenConfigurationNodes,omitempty"` - JobRunQueuingEnabled *bool `json:"JobRunQueuingEnabled,omitempty"` - Command JobCommand `json:"Command,omitzero"` - LogURI string `json:"LogUri,omitempty"` - SecurityConfiguration string `json:"SecurityConfiguration,omitempty"` - ExecutionClass string `json:"ExecutionClass,omitempty"` - MaintenanceWindow string `json:"MaintenanceWindow,omitempty"` + CodeGenConfigurationNodes map[string]jsontext.Value `json:"CodeGenConfigurationNodes,omitempty"` + JobRunQueuingEnabled *bool `json:"JobRunQueuingEnabled,omitempty"` + Command JobCommand `json:"Command,omitzero"` + LogURI string `json:"LogUri,omitempty"` + SecurityConfiguration string `json:"SecurityConfiguration,omitempty"` + ExecutionClass string `json:"ExecutionClass,omitempty"` + MaintenanceWindow string `json:"MaintenanceWindow,omitempty"` // JobMode describes how the job was created (SCRIPT/VISUAL/NOTEBOOK); // missing or null defaults to SCRIPT (glue@v1.157.0 api_op_CreateJob.go). JobMode string `json:"JobMode,omitempty"` @@ -651,7 +654,7 @@ func (b *JobBookmark) UnmarshalJSON(data []byte) error { ActiveRun string `json:"ActiveRun,omitempty"` }{alias: (*alias)(b)} - if err := json.Unmarshal(data, aux); err != nil { + if err := json.Unmarshal(data, aux, jsonx.V1()); err != nil { return err } @@ -926,7 +929,7 @@ func (p *IntegrationResourceProperty) UnmarshalJSON(data []byte) error { *alias }{alias: (*alias)(p)} - if err := json.Unmarshal(data, aux); err != nil { + if err := json.Unmarshal(data, aux, jsonx.V1()); err != nil { return err } diff --git a/services/glue/multi_region_test.go b/services/glue/multi_region_test.go index 3259d292f0..c7e76a9e1b 100644 --- a/services/glue/multi_region_test.go +++ b/services/glue/multi_region_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -40,7 +41,7 @@ func regionCall(t *testing.T, h *glue.Handler, region, op, body string) map[stri require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/glue/persistence.go b/services/glue/persistence.go index e33e76525b..615a28885e 100644 --- a/services/glue/persistence.go +++ b/services/glue/persistence.go @@ -2,7 +2,7 @@ package glue import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" @@ -47,7 +47,7 @@ const glueSnapshotVersion = 3 // singletons and JobRun*At timer maps, is not a map[string]*T at all) -- and // so is still persisted directly, exactly as before this refactor. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` PartitionIndexes map[string]*PartitionIndex `json:"partitionIndexes"` TableColumnStats map[string]*ColumnStatistics `json:"tableColumnStats"` PartitionColumnStats map[string]*ColumnStatistics `json:"partitionColumnStats"` diff --git a/services/glue/persistence_test.go b/services/glue/persistence_test.go index 344d5b58fc..07b3cf72e9 100644 --- a/services/glue/persistence_test.go +++ b/services/glue/persistence_test.go @@ -1,13 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -367,11 +368,11 @@ func TestInMemoryBackend_Restore_VersionMismatch(t *testing.T) { // Corrupt the version field so Restore hits the mismatch branch, without // hardcoding the rest of the snapshot's shape. var generic map[string]any - require.NoError(t, json.Unmarshal(snap, &generic)) + require.NoError(t, json.Unmarshal(snap, &generic, jsonx.V1())) require.Contains(t, generic, "version") generic["version"] = 999 - mutated, err := json.Marshal(generic) + mutated, err := json.Marshal(generic, jsonx.V1()) require.NoError(t, err) restored := glue.NewInMemoryBackend("123456789012", "us-east-1") diff --git a/services/glue/policy_shares.go b/services/glue/policy_shares.go index 5fca62dc3f..8f46ad7094 100644 --- a/services/glue/policy_shares.go +++ b/services/glue/policy_shares.go @@ -1,10 +1,12 @@ package glue import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // glueAccountIDLen is the number of digits in an AWS account ID. @@ -34,14 +36,14 @@ type stringOrSlice []string func (s *stringOrSlice) UnmarshalJSON(data []byte) error { var str string - if err := json.Unmarshal(data, &str); err == nil { + if err := json.Unmarshal(data, &str, jsonx.V1()); err == nil { *s = []string{str} return nil } var slice []string - if err := json.Unmarshal(data, &slice); err != nil { + if err := json.Unmarshal(data, &slice, jsonx.V1()); err != nil { return err } @@ -59,19 +61,19 @@ type policyPrincipal struct { func (p *policyPrincipal) UnmarshalJSON(data []byte) error { var str string - if err := json.Unmarshal(data, &str); err == nil { + if err := json.Unmarshal(data, &str, jsonx.V1()); err == nil { p.IsWildcard = str == "*" return nil } - var m map[string]json.RawMessage - if err := json.Unmarshal(data, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(data, &m, jsonx.V1()); err != nil { return err } if v, ok := m["AWS"]; ok { - _ = json.Unmarshal(v, &p.AWS) + _ = json.Unmarshal(v, &p.AWS, jsonx.V1()) } return nil @@ -112,7 +114,7 @@ func isAllDigits(s string) bool { // specific principals, so a public ("*") or same-account-only grant creates no share. func crossAccountGrant(policyJSON, ownerAccountID string) ([]string, []string) { var doc policyDoc - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return nil, nil } diff --git a/services/glue/schema_avro.go b/services/glue/schema_avro.go index b018904210..8248fb7ebc 100644 --- a/services/glue/schema_avro.go +++ b/services/glue/schema_avro.go @@ -1,10 +1,12 @@ package glue import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errAvroSchema = errors.New("invalid AVRO schema") @@ -64,7 +66,7 @@ func avroIsPrimitive(t string) bool { func parseAvro(def string) (*avroNode, error) { var v any - if err := json.Unmarshal([]byte(def), &v); err != nil { + if err := json.Unmarshal([]byte(def), &v, jsonx.V1()); err != nil { return nil, fmt.Errorf("schema is not valid JSON: %w", err) } diff --git a/services/glue/schema_json.go b/services/glue/schema_json.go index 673c0e7829..1ba220af8e 100644 --- a/services/glue/schema_json.go +++ b/services/glue/schema_json.go @@ -1,13 +1,15 @@ package glue import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" "reflect" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errJSONSchema = errors.New("invalid JSON schema") @@ -34,7 +36,7 @@ type jsonSchemaDoc map[string]any func parseJSONSchema(def string) (jsonSchemaDoc, error) { var v any - if err := json.Unmarshal([]byte(def), &v); err != nil { + if err := json.Unmarshal([]byte(def), &v, jsonx.V1()); err != nil { return nil, fmt.Errorf("schema is not valid JSON: %w", err) } diff --git a/services/glue/search_tables_sort_test.go b/services/glue/search_tables_sort_test.go index b6bc5a9beb..61b060b765 100644 --- a/services/glue/search_tables_sort_test.go +++ b/services/glue/search_tables_sort_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSearchTables_SortCriteria(t *testing.T) { @@ -76,7 +78,7 @@ func TestSearchTables_SortCriteria(t *testing.T) { Name string `json:"Name"` } `json:"TableList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) got := make([]string, 0, len(out.TableList)) for _, tbl := range out.TableList { diff --git a/services/glue/session_docker.go b/services/glue/session_docker.go index a113b7473b..e5f70d5ac1 100644 --- a/services/glue/session_docker.go +++ b/services/glue/session_docker.go @@ -3,7 +3,7 @@ package glue import ( "context" _ "embed" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "os" @@ -11,6 +11,8 @@ import ( "strconv" "sync/atomic" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed session_repl.pyrepl @@ -95,12 +97,12 @@ func (e *dockerSessionEngine) image(glueVersion string) string { func sparkCommand(name string) bool { return name == "glueetl" || name == "gluestreaming" } func sessionEnv(spec SessionSpec) ([]string, error) { - args, err := json.Marshal(spec.DefaultArguments) + args, err := json.Marshal(spec.DefaultArguments, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode default arguments: %w", err) } - conf, err := json.Marshal(parseSparkConf(spec.DefaultArguments["--conf"])) + conf, err := json.Marshal(parseSparkConf(spec.DefaultArguments["--conf"]), jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode spark conf: %w", err) } @@ -222,7 +224,7 @@ func (p *dockerSession) awaitReady(ctx context.Context, timeout time.Duration) e Status string `json:"status"` Message string `json:"message"` } - if json.Unmarshal(data, &r) == nil && r.Status == "ok" { + if json.Unmarshal(data, &r, jsonx.V1()) == nil && r.Status == "ok" { return nil } else if r.Status == "error" { return fmt.Errorf("%w: %s", errReplStart, r.Message) @@ -273,7 +275,7 @@ func (p *dockerSession) Run(ctx context.Context, code string) (StatementResult, p.seq++ n := p.seq - body, err := json.Marshal(map[string]string{"code": code}) + body, err := json.Marshal(map[string]string{"code": code}, jsonx.V1()) if err != nil { return StatementResult{}, fmt.Errorf("encode statement: %w", err) } @@ -306,7 +308,7 @@ func (p *dockerSession) awaitResponse(ctx context.Context, n int) (replResponse, for { if data, err := os.ReadFile(path); err == nil { var r replResponse - if err = json.Unmarshal(data, &r); err != nil { + if err = json.Unmarshal(data, &r, jsonx.V1()); err != nil { return r, fmt.Errorf("decode interpreter response: %w", err) } diff --git a/services/glue/timestamp_wire_shape_test.go b/services/glue/timestamp_wire_shape_test.go index 94f79c7c86..743d0dbfa0 100644 --- a/services/glue/timestamp_wire_shape_test.go +++ b/services/glue/timestamp_wire_shape_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestStartedOn_IsEpochSecondsNumber locks down a fix for a systemic bug @@ -37,7 +39,7 @@ func TestStartedOn_IsEpochSecondsNumber(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID, ok := startOut["RunId"].(string) require.True(t, ok) @@ -48,7 +50,7 @@ func TestStartedOn_IsEpochSecondsNumber(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) run, ok := getOut["BlueprintRun"].(map[string]any) require.True(t, ok) @@ -79,7 +81,7 @@ func TestStartedOn_IsEpochSecondsNumber(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID, ok := startOut["ColumnStatisticsTaskRunId"].(string) require.True(t, ok) @@ -89,7 +91,7 @@ func TestStartedOn_IsEpochSecondsNumber(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) run, ok := getOut["ColumnStatisticsTaskRun"].(map[string]any) require.True(t, ok) diff --git a/services/glue/trigger_conditional_test.go b/services/glue/trigger_conditional_test.go index 3dcd9465a7..c5fb701f96 100644 --- a/services/glue/trigger_conditional_test.go +++ b/services/glue/trigger_conditional_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -172,7 +173,7 @@ func TestConditionalTrigger_Fires(t *testing.T) { PredecessorRuns []pred `json:"PredecessorRuns"` } `json:"JobRun"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var got []string for _, p := range out.JobRun.PredecessorRuns { diff --git a/services/glue/wire_arn_no_leak_test.go b/services/glue/wire_arn_no_leak_test.go index 95da48ec01..41fbbb70e9 100644 --- a/services/glue/wire_arn_no_leak_test.go +++ b/services/glue/wire_arn_no_leak_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -21,7 +22,7 @@ func assertRawObjectHasNoArn(t *testing.T, body []byte, path ...string) map[stri t.Helper() var decoded map[string]any - require.NoError(t, json.Unmarshal(body, &decoded)) + require.NoError(t, json.Unmarshal(body, &decoded, jsonx.V1())) obj := decoded for i, key := range path { @@ -50,7 +51,7 @@ func assertNoArnInArray(t *testing.T, body []byte, containerKey string) { t.Helper() var decoded map[string]any - require.NoError(t, json.Unmarshal(body, &decoded)) + require.NoError(t, json.Unmarshal(body, &decoded, jsonx.V1())) arr, ok := decoded[containerKey].([]any) require.Truef(t, ok, "missing array key %q in response", containerKey) diff --git a/services/glue/wire_field_fixes_test.go b/services/glue/wire_field_fixes_test.go index a8e4044c95..bb8fb80f0f 100644 --- a/services/glue/wire_field_fixes_test.go +++ b/services/glue/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/glue" ) @@ -128,7 +129,7 @@ func TestCancelDataQualityRulesetEvaluationRun_StatusIsLegalEnumMember(t *testin ) require.Equal(t, 200, startRec.Code) var startOut map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) runID := startOut["RunId"] cancelRec := doGlueRequest(t, h, "CancelDataQualityRulesetEvaluationRun", map[string]any{"RunId": runID}) @@ -140,7 +141,7 @@ func TestCancelDataQualityRulesetEvaluationRun_StatusIsLegalEnumMember(t *testin var getOut struct { Status string `json:"Status"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, string(types.TaskStatusTypeStopped), getOut.Status) } diff --git a/services/glue/workflow_run_options_test.go b/services/glue/workflow_run_options_test.go index 57283d20f8..0a3f96a392 100644 --- a/services/glue/workflow_run_options_test.go +++ b/services/glue/workflow_run_options_test.go @@ -1,12 +1,14 @@ package glue_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestStartWorkflowRun_RunProperties(t *testing.T) { @@ -47,7 +49,7 @@ func TestStartWorkflowRun_RunProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var start map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) rec = doGlueRequest(t, h, "GetWorkflowRunProperties", map[string]any{ "Name": "wf", "RunId": start["RunId"], @@ -55,7 +57,7 @@ func TestStartWorkflowRun_RunProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.want, got["RunProperties"]) }) } @@ -86,7 +88,7 @@ func TestGetWorkflowRun_IncludeGraph(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var start map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) body := map[string]any{"Name": "graphwf", "IncludeGraph": tt.includeGraph} if tt.action == "GetWorkflowRun" { @@ -97,7 +99,7 @@ func TestGetWorkflowRun_IncludeGraph(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) run, _ := out["Run"].(map[string]any) if tt.action == "GetWorkflowRuns" { diff --git a/services/grafana/handler.go b/services/grafana/handler.go index b348173ece..9d3f4692d2 100644 --- a/services/grafana/handler.go +++ b/services/grafana/handler.go @@ -2,7 +2,7 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -378,7 +379,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { status, errType = http.StatusNotFound, "ResourceNotFoundException" } - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) diff --git a/services/grafana/handler_api_keys.go b/services/grafana/handler_api_keys.go index e7810bbf69..cffd003af5 100644 --- a/services/grafana/handler_api_keys.go +++ b/services/grafana/handler_api_keys.go @@ -2,8 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createWorkspaceAPIKeyRequest mirrors CreateWorkspaceApiKeyInput's JSON body. @@ -17,7 +19,7 @@ func (h *Handler) handleCreateWorkspaceAPIKey(_ context.Context, r *http.Request segs := rawPathSegments(r) var req createWorkspaceAPIKeyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -30,7 +32,7 @@ func (h *Handler) handleCreateWorkspaceAPIKey(_ context.Context, r *http.Request "key": key.Key, "keyName": key.KeyName, keyWorkspaceID: key.WorkspaceID, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteWorkspaceAPIKey(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -44,5 +46,5 @@ func (h *Handler) handleDeleteWorkspaceAPIKey(_ context.Context, r *http.Request return json.Marshal(map[string]any{ "keyName": keyName, keyWorkspaceID: workspaceID, - }) + }, jsonx.V1()) } diff --git a/services/grafana/handler_authentication.go b/services/grafana/handler_authentication.go index 8280c044b2..0168993276 100644 --- a/services/grafana/handler_authentication.go +++ b/services/grafana/handler_authentication.go @@ -2,8 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeWorkspaceAuthentication(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -14,14 +16,14 @@ func (h *Handler) handleDescribeWorkspaceAuthentication(_ context.Context, r *ht return nil, err } - return json.Marshal(map[string]any{"authentication": toAuthenticationDescriptionWire(w)}) + return json.Marshal(map[string]any{"authentication": toAuthenticationDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleUpdateWorkspaceAuthentication(_ context.Context, r *http.Request, body []byte) ([]byte, error) { segs := rawPathSegments(r) var req updateWorkspaceAuthenticationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -30,5 +32,5 @@ func (h *Handler) handleUpdateWorkspaceAuthentication(_ context.Context, r *http return nil, err } - return json.Marshal(map[string]any{"authentication": toAuthenticationDescriptionWire(w)}) + return json.Marshal(map[string]any{"authentication": toAuthenticationDescriptionWire(w)}, jsonx.V1()) } diff --git a/services/grafana/handler_configuration.go b/services/grafana/handler_configuration.go index 7fae1d95b0..fe720481b2 100644 --- a/services/grafana/handler_configuration.go +++ b/services/grafana/handler_configuration.go @@ -2,8 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeWorkspaceConfiguration(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -17,14 +19,14 @@ func (h *Handler) handleDescribeWorkspaceConfiguration(_ context.Context, r *htt return json.Marshal(map[string]any{ "configuration": configuration, "grafanaVersion": grafanaVersion, - }) + }, jsonx.V1()) } func (h *Handler) handleUpdateWorkspaceConfiguration(_ context.Context, r *http.Request, body []byte) ([]byte, error) { segs := rawPathSegments(r) var req updateWorkspaceConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -32,5 +34,5 @@ func (h *Handler) handleUpdateWorkspaceConfiguration(_ context.Context, r *http. return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/grafana/handler_license.go b/services/grafana/handler_license.go index 4a80cb6095..5b698bf4db 100644 --- a/services/grafana/handler_license.go +++ b/services/grafana/handler_license.go @@ -2,8 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // grafanaTokenHeader is the HTTP header AssociateLicenseInput.GrafanaToken is @@ -24,7 +26,7 @@ func (h *Handler) handleAssociateLicense(_ context.Context, r *http.Request, _ [ return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleDisassociateLicense(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -36,5 +38,5 @@ func (h *Handler) handleDisassociateLicense(_ context.Context, r *http.Request, return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } diff --git a/services/grafana/handler_permissions.go b/services/grafana/handler_permissions.go index 8c1018978b..4473dfa450 100644 --- a/services/grafana/handler_permissions.go +++ b/services/grafana/handler_permissions.go @@ -2,9 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -31,14 +32,14 @@ func (h *Handler) handleListPermissions(_ context.Context, r *http.Request, _ [] out["nextToken"] = p.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } func (h *Handler) handleUpdatePermissions(ctx context.Context, r *http.Request, body []byte) ([]byte, error) { segs := rawPathSegments(r) var req updatePermissionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -51,5 +52,5 @@ func (h *Handler) handleUpdatePermissions(ctx context.Context, r *http.Request, errs = []updateErrorWire{} } - return json.Marshal(map[string]any{"errors": errs}) + return json.Marshal(map[string]any{"errors": errs}, jsonx.V1()) } diff --git a/services/grafana/handler_service_account_tokens.go b/services/grafana/handler_service_account_tokens.go index 58ec308346..9c4e0ab87d 100644 --- a/services/grafana/handler_service_account_tokens.go +++ b/services/grafana/handler_service_account_tokens.go @@ -2,9 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -22,7 +23,7 @@ func (h *Handler) handleCreateWorkspaceServiceAccountToken( workspaceID, serviceAccountID := segs[1], segs[3] var req createWorkspaceServiceAccountTokenRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -39,7 +40,7 @@ func (h *Handler) handleCreateWorkspaceServiceAccountToken( Name: tok.Name, Key: tok.Key, }, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteWorkspaceServiceAccountToken( @@ -56,7 +57,7 @@ func (h *Handler) handleDeleteWorkspaceServiceAccountToken( keyServiceAccountID: serviceAccountID, "tokenId": tokenID, keyWorkspaceID: workspaceID, - }) + }, jsonx.V1()) } func (h *Handler) handleListWorkspaceServiceAccountTokens( @@ -89,5 +90,5 @@ func (h *Handler) handleListWorkspaceServiceAccountTokens( out["nextToken"] = p.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } diff --git a/services/grafana/handler_service_accounts.go b/services/grafana/handler_service_accounts.go index 39e45561f3..de6440d641 100644 --- a/services/grafana/handler_service_accounts.go +++ b/services/grafana/handler_service_accounts.go @@ -2,9 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -19,7 +20,7 @@ func (h *Handler) handleCreateWorkspaceServiceAccount(_ context.Context, r *http segs := rawPathSegments(r) var req createWorkspaceServiceAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -33,7 +34,7 @@ func (h *Handler) handleCreateWorkspaceServiceAccount(_ context.Context, r *http "name": sa.Name, "grafanaRole": sa.GrafanaRole, keyWorkspaceID: sa.WorkspaceID, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteWorkspaceServiceAccount(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -47,7 +48,7 @@ func (h *Handler) handleDeleteWorkspaceServiceAccount(_ context.Context, r *http return json.Marshal(map[string]any{ keyServiceAccountID: serviceAccountID, keyWorkspaceID: workspaceID, - }) + }, jsonx.V1()) } func (h *Handler) handleListWorkspaceServiceAccounts(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -74,5 +75,5 @@ func (h *Handler) handleListWorkspaceServiceAccounts(_ context.Context, r *http. out["nextToken"] = p.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } diff --git a/services/grafana/handler_tags.go b/services/grafana/handler_tags.go index ffaed0350c..4f8ce3c970 100644 --- a/services/grafana/handler_tags.go +++ b/services/grafana/handler_tags.go @@ -2,8 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // tagResourceRequest mirrors TagResourceInput's JSON body. @@ -20,7 +22,7 @@ func (h *Handler) handleListTagsForResource(_ context.Context, r *http.Request, return nil, err } - return json.Marshal(map[string]any{"tags": tags}) + return json.Marshal(map[string]any{"tags": tags}, jsonx.V1()) } func (h *Handler) handleTagResource(ctx context.Context, r *http.Request, body []byte) ([]byte, error) { @@ -28,7 +30,7 @@ func (h *Handler) handleTagResource(ctx context.Context, r *http.Request, body [ resourceArn := segs[1] var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -36,7 +38,7 @@ func (h *Handler) handleTagResource(ctx context.Context, r *http.Request, body [ return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) handleUntagResource(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -48,5 +50,5 @@ func (h *Handler) handleUntagResource(ctx context.Context, r *http.Request, _ [] return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/grafana/handler_versions.go b/services/grafana/handler_versions.go index 56d8221680..659e630094 100644 --- a/services/grafana/handler_versions.go +++ b/services/grafana/handler_versions.go @@ -2,9 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -34,5 +35,5 @@ func (h *Handler) handleListVersions(_ context.Context, r *http.Request, _ []byt out["nextToken"] = p.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } diff --git a/services/grafana/handler_workspaces.go b/services/grafana/handler_workspaces.go index d84fb08e10..79adfa8f22 100644 --- a/services/grafana/handler_workspaces.go +++ b/services/grafana/handler_workspaces.go @@ -2,9 +2,10 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -12,7 +13,7 @@ const grafanaDefaultPageSize = 100 func (h *Handler) handleCreateWorkspace(_ context.Context, _ *http.Request, body []byte) ([]byte, error) { var req createWorkspaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -21,7 +22,7 @@ func (h *Handler) handleCreateWorkspace(_ context.Context, _ *http.Request, body return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleDescribeWorkspace(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -32,14 +33,14 @@ func (h *Handler) handleDescribeWorkspace(_ context.Context, r *http.Request, _ return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleUpdateWorkspace(_ context.Context, r *http.Request, body []byte) ([]byte, error) { segs := rawPathSegments(r) var req updateWorkspaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, validationError("invalid request body: " + err.Error()) } @@ -48,7 +49,7 @@ func (h *Handler) handleUpdateWorkspace(_ context.Context, r *http.Request, body return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleDeleteWorkspace(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -59,7 +60,7 @@ func (h *Handler) handleDeleteWorkspace(_ context.Context, r *http.Request, _ [] return nil, err } - return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}) + return json.Marshal(map[string]any{keyWorkspace: toWorkspaceDescriptionWire(w)}, jsonx.V1()) } func (h *Handler) handleListWorkspaces(_ context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -81,5 +82,5 @@ func (h *Handler) handleListWorkspaces(_ context.Context, r *http.Request, _ []b out["nextToken"] = p.Next } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } diff --git a/services/grafana/persistence.go b/services/grafana/persistence.go index 8425a6c15e..717c4eb000 100644 --- a/services/grafana/persistence.go +++ b/services/grafana/persistence.go @@ -2,7 +2,7 @@ package grafana import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -19,12 +19,12 @@ const grafanaSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Grafana backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` - NextServiceAccountID uint64 `json:"nextServiceAccountId"` - NextTokenID uint64 `json:"nextTokenId"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` + NextServiceAccountID uint64 `json:"nextServiceAccountId"` + NextTokenID uint64 `json:"nextTokenId"` } // Snapshot serialises the backend state to JSON. diff --git a/services/guardduty/coverage_statistics_test.go b/services/guardduty/coverage_statistics_test.go index f799cec38a..bc1241fafa 100644 --- a/services/guardduty/coverage_statistics_test.go +++ b/services/guardduty/coverage_statistics_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -30,7 +31,7 @@ func TestCoverage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.NotNil(t, listResp["resources"]) // GetCoverageStatistics requires statisticsType (gopherstack-h910: this @@ -45,7 +46,7 @@ func TestCoverage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var byTypeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byTypeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byTypeResp, jsonx.V1())) stats, ok := byTypeResp["coverageStatistics"].(map[string]any) require.True(t, ok) assert.Contains(t, stats, "countByResourceType") @@ -57,7 +58,7 @@ func TestCoverage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var byStatusResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byStatusResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byStatusResp, jsonx.V1())) stats, ok = byStatusResp["coverageStatistics"].(map[string]any) require.True(t, ok) assert.Contains(t, stats, "countByCoverageStatus") diff --git a/services/guardduty/cross_service_test.go b/services/guardduty/cross_service_test.go index 2176fbc93f..d68cffab95 100644 --- a/services/guardduty/cross_service_test.go +++ b/services/guardduty/cross_service_test.go @@ -1,12 +1,13 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/guardduty" organizationsbackend "github.com/blackbirdworks/gopherstack/services/organizations" @@ -97,7 +98,7 @@ func TestMemberOps_AutoEnableOrganizationMembersAll_AllowedAfterAccountLeavesOrg require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Empty(t, out["unprocessedAccounts"], "account should have been processed, not left unprocessed") }) } diff --git a/services/guardduty/detectors_test.go b/services/guardduty/detectors_test.go index 5a041c1cc8..2259eea74e 100644 --- a/services/guardduty/detectors_test.go +++ b/services/guardduty/detectors_test.go @@ -1,7 +1,7 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "regexp" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -40,7 +41,7 @@ func TestDetector_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp["detectorId"]) }, }, @@ -54,7 +55,7 @@ func TestDetector_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ENABLED", resp["status"]) assert.NotEmpty(t, resp["serviceRole"]) assert.Equal(t, "SIX_HOURS", resp["findingPublishingFrequency"]) @@ -73,7 +74,7 @@ func TestDetector_Lifecycle(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/detector/"+id, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "FIFTEEN_MINUTES", resp["findingPublishingFrequency"]) }, }, @@ -90,7 +91,7 @@ func TestDetector_Lifecycle(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/detector/"+id, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DISABLED", resp["status"]) }, }, @@ -117,7 +118,7 @@ func TestDetector_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, ok := resp["detectorIds"].([]any) require.True(t, ok) require.Len(t, ids, 1) @@ -155,12 +156,12 @@ func TestDetector_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["detectorId"].(string) rec = doRequest(t, h, http.MethodGet, "/detector/"+id, nil) var det map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &det)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &det, jsonx.V1())) tags, ok := det["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "test", tags["env"]) @@ -218,7 +219,7 @@ func TestDetector_Timestamps_Present(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range []string{"createdAt", "updatedAt"} { raw, ok := resp[field] @@ -241,7 +242,7 @@ func TestDetector_UpdatedAt_Advances(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var before map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &before, jsonx.V1())) createdAt := before["createdAt"].(string) updatedAt1 := before["updatedAt"].(string) @@ -256,7 +257,7 @@ func TestDetector_UpdatedAt_Advances(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var after map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &after, jsonx.V1())) createdAt2 := after["createdAt"].(string) updatedAt2 := after["updatedAt"].(string) @@ -279,7 +280,7 @@ func TestDetector_Tags_EmptyMap_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["tags"] require.True(t, exists, "GetDetector response must include 'tags' key") @@ -299,7 +300,7 @@ func TestListDetectors_Empty_State(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["detectorIds"] require.True(t, exists, "ListDetectors must include 'detectorIds' key") diff --git a/services/guardduty/entity_sets_test.go b/services/guardduty/entity_sets_test.go index 88108bde72..da9e2c28de 100644 --- a/services/guardduty/entity_sets_test.go +++ b/services/guardduty/entity_sets_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -36,7 +37,7 @@ func TestThreatEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) setID, _ := createResp["threatEntitySetId"].(string) require.NotEmpty(t, setID) @@ -45,7 +46,7 @@ func TestThreatEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-threat-set", getResp["name"]) assert.Equal(t, "ACTIVE", getResp["status"]) @@ -61,7 +62,7 @@ func TestThreatEntitySets(t *testing.T) { // Verify update rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/threatentityset/"+setID, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "updated-threat-set", getResp["name"]) assert.Equal(t, "INACTIVE", getResp["status"]) @@ -70,7 +71,7 @@ func TestThreatEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) ids, _ := listResp["threatEntitySetIds"].([]any) assert.Len(t, ids, 1) assert.Equal(t, setID, ids[0]) @@ -81,7 +82,7 @@ func TestThreatEntitySets(t *testing.T) { // List after delete rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/threatentityset", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) idsAfter, _ := listResp["threatEntitySetIds"].([]any) assert.Empty(t, idsAfter) }, @@ -133,7 +134,7 @@ func TestTrustedEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) setID, _ := createResp["trustedEntitySetId"].(string) require.NotEmpty(t, setID) @@ -142,7 +143,7 @@ func TestTrustedEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-trusted-set", getResp["name"]) assert.Equal(t, "ACTIVE", getResp["status"]) @@ -156,7 +157,7 @@ func TestTrustedEntitySets(t *testing.T) { // Verify update rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/trustedentityset/"+setID, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "updated-trusted-set", getResp["name"]) assert.Equal(t, "INACTIVE", getResp["status"]) @@ -165,7 +166,7 @@ func TestTrustedEntitySets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) ids, _ := listResp["trustedEntitySetIds"].([]any) assert.Len(t, ids, 1) assert.Equal(t, setID, ids[0]) @@ -176,7 +177,7 @@ func TestTrustedEntitySets(t *testing.T) { // List after delete rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/trustedentityset", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) idsAfter, _ := listResp["trustedEntitySetIds"].([]any) assert.Empty(t, idsAfter) }, diff --git a/services/guardduty/filters_test.go b/services/guardduty/filters_test.go index 3449d9e22f..1e71382880 100644 --- a/services/guardduty/filters_test.go +++ b/services/guardduty/filters_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -31,14 +32,14 @@ func TestFilter_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) assert.Equal(t, "my-filter", cr["name"]) rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/filter/my-filter", nil) require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "ARCHIVE", gr["action"]) assert.InDelta(t, 1.0, gr["rank"], 0.01) assert.Equal(t, "test filter", gr["description"]) @@ -62,7 +63,7 @@ func TestFilter_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/filter/upd-filter", nil) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "ARCHIVE", gr["action"]) assert.InDelta(t, 2.0, gr["rank"], 0.01) }, @@ -96,7 +97,7 @@ func TestFilter_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names, ok := resp["filterNames"].([]any) require.True(t, ok) assert.Len(t, names, 3) @@ -132,7 +133,7 @@ func TestListFilters_Empty_State(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["filterNames"] require.True(t, exists, "ListFilters must include 'filterNames' key") @@ -160,7 +161,7 @@ func TestFilter_Tags_EmptyMap_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["tags"] require.True(t, exists, "GetFilter response must include 'tags' key") diff --git a/services/guardduty/finding_criteria.go b/services/guardduty/finding_criteria.go index 7134ff90f9..266d64761b 100644 --- a/services/guardduty/finding_criteria.go +++ b/services/guardduty/finding_criteria.go @@ -1,12 +1,14 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "regexp" "slices" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Condition represents a single finding-criteria condition, matching @@ -45,13 +47,13 @@ func conditionsFromRaw(raw map[string]any) map[string]Condition { return nil } - data, err := json.Marshal(raw) + data, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil } var fc FindingCriteria - if unmarshalErr := json.Unmarshal(data, &fc); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &fc, jsonx.V1()); unmarshalErr != nil { return nil } @@ -71,13 +73,13 @@ type SortCriteria struct { // resolved the same way a real GuardDuty backend would resolve them against // the finding document. func findingToFieldMap(f *Finding) map[string]any { - data, marshalErr := json.Marshal(f) + data, marshalErr := json.Marshal(f, jsonx.V1()) if marshalErr != nil { return map[string]any{} } var m map[string]any - if unmarshalErr := json.Unmarshal(data, &m); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &m, jsonx.V1()); unmarshalErr != nil { return map[string]any{} } diff --git a/services/guardduty/finding_criteria_test.go b/services/guardduty/finding_criteria_test.go index 05dd1293cd..f2f531c127 100644 --- a/services/guardduty/finding_criteria_test.go +++ b/services/guardduty/finding_criteria_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -20,7 +21,7 @@ func listFindings(t *testing.T, h *guardduty.Handler, detectorID string, body an require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/guardduty/finding_statistics_test.go b/services/guardduty/finding_statistics_test.go index 026eaa1cc0..74429a52fe 100644 --- a/services/guardduty/finding_statistics_test.go +++ b/services/guardduty/finding_statistics_test.go @@ -1,12 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGetFindingsStatistics_GroupBy(t *testing.T) { @@ -67,7 +69,7 @@ func TestGetFindingsStatistics_GroupBy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs, ok := resp["findingStatistics"].(map[string]any) require.True(t, ok) @@ -109,7 +111,7 @@ func TestGetFindingsStatistics_GroupBy_Unset_ReturnsCountBySeverity(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["findingStatistics"].(map[string]any) assert.Contains(t, fs, "countBySeverity") @@ -139,7 +141,7 @@ func TestGetFindingsStatistics_FindingCriteria(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs := resp["findingStatistics"].(map[string]any) groups, ok := fs["groupedByFindingType"].([]any) diff --git a/services/guardduty/findings_test.go b/services/guardduty/findings_test.go index e0fd0bff5c..20efdb8eff 100644 --- a/services/guardduty/findings_test.go +++ b/services/guardduty/findings_test.go @@ -1,7 +1,7 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -32,7 +33,7 @@ func TestFindings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var lr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr, jsonx.V1())) ids, ok := lr["findingIds"].([]any) require.True(t, ok) assert.Len(t, ids, 1) @@ -49,7 +50,7 @@ func TestFindings(t *testing.T) { // List to get IDs rec := doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/findings", nil) var lr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr, jsonx.V1())) ids := lr["findingIds"].([]any) // Get by ID @@ -59,7 +60,7 @@ func TestFindings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) findings, ok := gr["findings"].([]any) require.True(t, ok) require.Len(t, findings, 1) @@ -75,7 +76,7 @@ func TestFindings(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/findings", nil) var lr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr, jsonx.V1())) ids := lr["findingIds"].([]any) fid := ids[0].(string) @@ -90,7 +91,7 @@ func TestFindings(t *testing.T) { "findingIds": []string{fid}, }) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) findings := gr["findings"].([]any) f := findings[0].(map[string]any) svc := f["service"].(map[string]any) @@ -105,7 +106,7 @@ func TestFindings(t *testing.T) { rec = doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/findings/get", map[string]any{ "findingIds": []string{fid}, }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) findings = gr["findings"].([]any) f = findings[0].(map[string]any) svc = f["service"].(map[string]any) @@ -127,7 +128,7 @@ func TestFindings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["findingStatistics"]) }, }, @@ -141,7 +142,7 @@ func TestFindings(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/findings", nil) var lr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lr, jsonx.V1())) ids := lr["findingIds"].([]any) rec = doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/findings/feedback", map[string]any{ @@ -173,7 +174,7 @@ func TestListFindings_Empty_State(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["findingIds"] require.True(t, exists, "ListFindings must include 'findingIds' key") @@ -195,7 +196,7 @@ func TestGetFindings_Empty_Input(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["findings"] require.True(t, exists, "GetFindings must include 'findings' key") @@ -425,7 +426,7 @@ func TestGetFindingsStatistics_Handler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs, ok := resp["findingStatistics"].(map[string]any) require.True(t, ok) diff --git a/services/guardduty/handler_coverage_statistics.go b/services/guardduty/handler_coverage_statistics.go index ee29e46cb5..3a12dd45be 100644 --- a/services/guardduty/handler_coverage_statistics.go +++ b/services/guardduty/handler_coverage_statistics.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetCoverageStatistics(detectorID string, body []byte) (any, int, error) { @@ -11,7 +13,7 @@ func (h *Handler) handleGetCoverageStatistics(detectorID string, body []byte) (a } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -35,7 +37,7 @@ func (h *Handler) handleListCoverage(detectorID string, body []byte) (any, int, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/guardduty/handler_detectors.go b/services/guardduty/handler_detectors.go index f3d49e70b6..6b6486f787 100644 --- a/services/guardduty/handler_detectors.go +++ b/services/guardduty/handler_detectors.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchDetectorOps(op, path, query string, body []byte) (any, int, bool, error) { @@ -49,7 +51,7 @@ func (h *Handler) handleCreateDetector(body []byte) (any, int, error) { Features []DetectorFeature `json:"features"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -105,7 +107,7 @@ func (h *Handler) handleUpdateDetector(detectorID string, body []byte) (int, err Features []DetectorFeature `json:"features"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_entity_sets.go b/services/guardduty/handler_entity_sets.go index 52b81316b7..ae4e515b69 100644 --- a/services/guardduty/handler_entity_sets.go +++ b/services/guardduty/handler_entity_sets.go @@ -1,10 +1,11 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchEntitySetOps(op, path, query string, body []byte) (any, int, bool, error) { @@ -87,7 +88,7 @@ func (h *Handler) handleCreateThreatEntitySet( //nolint:dupl // existing issue. ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -176,7 +177,7 @@ func (h *Handler) handleUpdateThreatEntitySet(detectorID, setID string, body []b ExpectedBucketOwner string `json:"expectedBucketOwner"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -212,7 +213,7 @@ func (h *Handler) handleCreateTrustedEntitySet( //nolint:dupl // existing issue. ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -298,7 +299,7 @@ func (h *Handler) handleUpdateTrustedEntitySet(detectorID, setID string, body [] ExpectedBucketOwner string `json:"expectedBucketOwner"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_filters.go b/services/guardduty/handler_filters.go index d02fceb97b..402cb3270e 100644 --- a/services/guardduty/handler_filters.go +++ b/services/guardduty/handler_filters.go @@ -1,10 +1,11 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchFilterOps(op, path, query string, body []byte) (any, int, bool, error) { @@ -54,7 +55,7 @@ func (h *Handler) handleCreateFilter(detectorID string, body []byte) (any, int, Rank int32 `json:"rank"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -122,7 +123,7 @@ func (h *Handler) handleUpdateFilter(detectorID, filterName string, body []byte) Rank int32 `json:"rank"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_findings.go b/services/guardduty/handler_findings.go index afc5307b33..10b05f6d92 100644 --- a/services/guardduty/handler_findings.go +++ b/services/guardduty/handler_findings.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchFindingOps(op, path string, body []byte) (any, int, bool, error) { @@ -54,7 +56,7 @@ func (h *Handler) handleGetFindings(detectorID string, body []byte) (any, int, e FindingIDs []string `json:"findingIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -79,7 +81,7 @@ func (h *Handler) handleListFindings(detectorID string, body []byte) (any, int, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -116,7 +118,7 @@ func (h *Handler) handleArchiveFindings(detectorID string, body []byte) (int, er FindingIDs []string `json:"findingIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -132,7 +134,7 @@ func (h *Handler) handleUnarchiveFindings(detectorID string, body []byte) (int, FindingIDs []string `json:"findingIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -149,7 +151,7 @@ func (h *Handler) handleCreateSampleFindings(detectorID string, body []byte) (in } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } @@ -170,7 +172,7 @@ func (h *Handler) handleGetFindingsStatistics(detectorID string, body []byte) (a } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -195,7 +197,7 @@ func (h *Handler) handleUpdateFindingsFeedback(detectorID string, body []byte) ( FindingIDs []string `json:"findingIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_investigations.go b/services/guardduty/handler_investigations.go index 61388fbc18..e6a40ba0d6 100644 --- a/services/guardduty/handler_investigations.go +++ b/services/guardduty/handler_investigations.go @@ -1,10 +1,11 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchInvestigationOps(op, path string, body []byte) (any, int, bool, error) { @@ -37,7 +38,7 @@ func (h *Handler) handleCreateInvestigation(detectorID string, body []byte) (any ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -80,7 +81,7 @@ func (h *Handler) handleListInvestigations(detectorID string, body []byte) (any, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/guardduty/handler_ip_and_threatintel_sets.go b/services/guardduty/handler_ip_and_threatintel_sets.go index 5f58e7e2d2..93f6a31efb 100644 --- a/services/guardduty/handler_ip_and_threatintel_sets.go +++ b/services/guardduty/handler_ip_and_threatintel_sets.go @@ -1,9 +1,11 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validSetFormats are the enum values IpSetFormat and ThreatIntelSetFormat @@ -60,7 +62,7 @@ func (h *Handler) handleCreateIPSet(detectorID string, body []byte) (any, int, e ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -126,7 +128,7 @@ func (h *Handler) handleUpdateIPSet(detectorID, ipSetID string, body []byte) (in ExpectedBucketOwner string `json:"expectedBucketOwner"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -210,7 +212,7 @@ func (h *Handler) handleCreateThreatIntelSet(detectorID string, body []byte) (an ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -276,7 +278,7 @@ func (h *Handler) handleUpdateThreatIntelSet(detectorID, setID string, body []by ExpectedBucketOwner string `json:"expectedBucketOwner"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_ip_and_threatintel_sets_test.go b/services/guardduty/handler_ip_and_threatintel_sets_test.go index eb264ecfe3..ee8744b8d9 100644 --- a/services/guardduty/handler_ip_and_threatintel_sets_test.go +++ b/services/guardduty/handler_ip_and_threatintel_sets_test.go @@ -1,12 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGuardDuty_CreateIPSet_FormatValidation(t *testing.T) { @@ -44,7 +46,7 @@ func TestGuardDuty_CreateIPSet_FormatValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "BadRequestException", errOut["__type"]) return @@ -90,7 +92,7 @@ func TestGuardDuty_CreateThreatIntelSet_FormatValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "BadRequestException", errOut["__type"]) return diff --git a/services/guardduty/handler_malware_protection.go b/services/guardduty/handler_malware_protection.go index 6fb7710bcf..3dcc6cb70d 100644 --- a/services/guardduty/handler_malware_protection.go +++ b/services/guardduty/handler_malware_protection.go @@ -1,12 +1,13 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "sync" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -188,7 +189,7 @@ func (h *Handler) handleDescribeMalwareScans(detectorID string, body []byte) (an var req malwareScanFilterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -210,7 +211,7 @@ func (h *Handler) handleListMalwareScans(query string, body []byte) (any, int, e var req malwareScanFilterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -239,7 +240,7 @@ func (h *Handler) handleStartMalwareScan(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -343,7 +344,7 @@ func (h *Handler) handleUpdateMalwareScanSettings(detectorID string, body []byte EbsSnapshotPreservation string `json:"ebsSnapshotPreservation"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -368,7 +369,7 @@ func (h *Handler) handleCreateMalwareProtectionPlan(body []byte) (any, int, erro ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -479,7 +480,7 @@ func (h *Handler) handleUpdateMalwareProtectionPlan(planID string, body []byte) Role string `json:"role"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -508,7 +509,7 @@ func (h *Handler) handleSendObjectMalwareScan(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/guardduty/handler_members.go b/services/guardduty/handler_members.go index dc2b230250..ad02a3ecf7 100644 --- a/services/guardduty/handler_members.go +++ b/services/guardduty/handler_members.go @@ -1,9 +1,11 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // keyMembers is the real required response key for GetMembers, ListMembers, @@ -157,7 +159,7 @@ func (h *Handler) handleCreateMembers(detectorID string, body []byte) (any, int, AccountDetails []map[string]any `json:"accountDetails"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -173,7 +175,7 @@ func (h *Handler) handleDeleteMembers(detectorID string, body []byte) (any, int, AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -190,7 +192,7 @@ func (h *Handler) handleGetMembers(detectorID string, body []byte) (any, int, er AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -215,7 +217,7 @@ func (h *Handler) handleInviteMembers(detectorID string, body []byte) (any, int, AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -253,7 +255,7 @@ func (h *Handler) handleStartMonitoringMembers(detectorID string, body []byte) ( AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -270,7 +272,7 @@ func (h *Handler) handleStopMonitoringMembers(detectorID string, body []byte) (a AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -287,7 +289,7 @@ func (h *Handler) handleDisassociateMembers(detectorID string, body []byte) (any AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -304,7 +306,7 @@ func (h *Handler) handleGetMemberDetectors(detectorID string, body []byte) (any, AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -326,7 +328,7 @@ func (h *Handler) handleUpdateMemberDetectors(detectorID string, body []byte) (a Features []DetectorFeature `json:"features"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -346,7 +348,7 @@ func (h *Handler) handleAcceptAdministratorInvitation(detectorID string, body [] InvitationID string `json:"invitationId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -363,7 +365,7 @@ func (h *Handler) handleAcceptInvitation(detectorID string, body []byte) (int, e InvitationID string `json:"invitationId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -379,7 +381,7 @@ func (h *Handler) handleDeclineInvitations(body []byte) (any, int, error) { AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -393,7 +395,7 @@ func (h *Handler) handleDeleteInvitations(body []byte) (any, int, error) { AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_organization.go b/services/guardduty/handler_organization.go index 9172447775..ab580c6313 100644 --- a/services/guardduty/handler_organization.go +++ b/services/guardduty/handler_organization.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchOrgOps(op, path, query string, body []byte) (any, int, bool, error) { @@ -70,7 +72,7 @@ func (h *Handler) handleEnableOrganizationAdminAccount(body []byte) (int, error) AdminAccountID string `json:"adminAccountId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -86,7 +88,7 @@ func (h *Handler) handleDisableOrganizationAdminAccount(body []byte) (int, error AdminAccountID string `json:"adminAccountId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -160,7 +162,7 @@ func (h *Handler) handleUpdateOrganizationConfiguration(detectorID string, body Features []OrgFeature `json:"features"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_publishing_destinations.go b/services/guardduty/handler_publishing_destinations.go index 261572bde8..1287f2effe 100644 --- a/services/guardduty/handler_publishing_destinations.go +++ b/services/guardduty/handler_publishing_destinations.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchPublishingDestOps(op, path, query string, body []byte) (any, int, bool, error) { @@ -49,7 +51,7 @@ func (h *Handler) handleCreatePublishingDestination(detectorID string, body []by ClientToken string `json:"clientToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -137,7 +139,7 @@ func (h *Handler) handleUpdatePublishingDestination(detectorID, destID string, b DestinationProperties DestinationProperties `json:"destinationProperties"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_tags.go b/services/guardduty/handler_tags.go index b23eebb641..b9eac5640a 100644 --- a/services/guardduty/handler_tags.go +++ b/services/guardduty/handler_tags.go @@ -1,10 +1,12 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) dispatchTagOps(op, path, query string, body []byte) (any, int, error) { @@ -44,7 +46,7 @@ func (h *Handler) handleTagResource(resourceARN string, body []byte) (int, error Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/guardduty/handler_tagsync_test.go b/services/guardduty/handler_tagsync_test.go index 9f50e7dfe9..7702bc45b1 100644 --- a/services/guardduty/handler_tagsync_test.go +++ b/services/guardduty/handler_tagsync_test.go @@ -14,7 +14,7 @@ package guardduty_test // regression coverage before now. import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -39,7 +40,7 @@ func doJSON(t *testing.T, h *guardduty.Handler, method, path string, body any) m require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/guardduty/handler_test.go b/services/guardduty/handler_test.go index 8549e3718c..a0139b9f15 100644 --- a/services/guardduty/handler_test.go +++ b/services/guardduty/handler_test.go @@ -2,7 +2,7 @@ package guardduty_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -30,7 +31,7 @@ func doRequest(t *testing.T, h *guardduty.Handler, method, path string, body any if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -54,7 +55,7 @@ func createTestDetector(t *testing.T, h *guardduty.Handler) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, ok := resp["detectorId"].(string) require.True(t, ok) require.NotEmpty(t, id) diff --git a/services/guardduty/handler_usage.go b/services/guardduty/handler_usage.go index e0354339af..16b3c694b3 100644 --- a/services/guardduty/handler_usage.go +++ b/services/guardduty/handler_usage.go @@ -1,8 +1,10 @@ package guardduty import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetUsageStatistics(detectorID string, body []byte) (any, int, error) { @@ -18,7 +20,7 @@ func (h *Handler) handleGetUsageStatistics(detectorID string, body []byte) (any, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -85,7 +87,7 @@ func (h *Handler) handleGetRemainingFreeTrialDays(detectorID string, body []byte } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/guardduty/handler_wireshape_test.go b/services/guardduty/handler_wireshape_test.go index 9a4b8a9a32..8fbd5f418b 100644 --- a/services/guardduty/handler_wireshape_test.go +++ b/services/guardduty/handler_wireshape_test.go @@ -19,13 +19,15 @@ package guardduty_test // scanStartedAt/scanCompletedAt epoch fields. import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -113,8 +115,8 @@ func TestWireShape_DescribePublishingDestination_UsesRealKeysAndTags(t *testing. rec := doRequest(t, h, http.MethodGet, "/detector/"+detID+"/publishingDestination/"+destID, nil) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasWrongKey := raw["publishingFailureStartedAt"] assert.False(t, hasWrongKey, "must not use the made-up publishingFailureStartedAt wire key") @@ -123,7 +125,7 @@ func TestWireShape_DescribePublishingDestination_UsesRealKeysAndTags(t *testing. assert.True(t, hasRightKey, "must use the real publishingFailureStartTimestamp wire key") var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) tags, _ := got["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"], "tags supplied at creation must be returned by DescribePublishingDestination") } @@ -149,8 +151,8 @@ func TestWireShape_GetMalwareScan_UsesRealFieldNames(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/malware-scan/"+scanID, nil) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) for _, badKey := range []string{"accountId", "resourceDetails", "findings", "scanStartTime", "scanEndTime"} { _, present := raw[badKey] @@ -171,7 +173,7 @@ func TestWireShape_GetMalwareScan_UsesRealFieldNames(t *testing.T) { } var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, detID, got["detectorId"], "detectorId must resolve to the account's own detector") assert.Equal(t, "EC2_INSTANCE", got["resourceType"], "resourceType must be inferred from the resource ARN") @@ -267,14 +269,14 @@ func TestWireShape_Investigation_NoFabricatedAnalysis(t *testing.T) { getRec := doRequest(t, h, http.MethodGet, "/detector/"+detID+"/investigation/"+invID, nil) require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) - var getRaw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw)) + var getRaw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw, jsonx.V1())) invRaw, ok := getRaw["investigation"] require.True(t, ok, "GetInvestigationOutput must have an investigation member") - var inv map[string]json.RawMessage - require.NoError(t, json.Unmarshal(invRaw, &inv)) + var inv map[string]jsontext.Value + require.NoError(t, json.Unmarshal(invRaw, &inv, jsonx.V1())) for _, fabricatable := range []string{ "cloud", "confidence", "endTime", "error", "metadata", "risk", "riskLevel", "summary", "title", @@ -285,18 +287,18 @@ func TestWireShape_Investigation_NoFabricatedAnalysis(t *testing.T) { } var got map[string]any - require.NoError(t, json.Unmarshal(invRaw, &got)) + require.NoError(t, json.Unmarshal(invRaw, &got, jsonx.V1())) assert.Equal(t, "RUNNING", got["status"], "an investigation this backend cannot analyze must stay RUNNING") assert.Equal(t, "Investigate finding in this account", got["triggerPrompt"]) listRec := doRequest(t, h, http.MethodPost, "/detector/"+detID+"/investigation/list", nil) require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) - var listRaw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listRaw)) + var listRaw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listRaw, jsonx.V1())) - var summaries []map[string]json.RawMessage - require.NoError(t, json.Unmarshal(listRaw["investigations"], &summaries)) + var summaries []map[string]jsontext.Value + require.NoError(t, json.Unmarshal(listRaw["investigations"], &summaries, jsonx.V1())) require.Len(t, summaries, 1) for _, fabricatable := range []string{"confidence", "endTime", "riskLevel", "title"} { @@ -305,7 +307,7 @@ func TestWireShape_Investigation_NoFabricatedAnalysis(t *testing.T) { } var summary map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &summary)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &summary, jsonx.V1())) invList, ok := summary["investigations"].([]any) require.True(t, ok) require.Len(t, invList, 1) diff --git a/services/guardduty/ip_sets_test.go b/services/guardduty/ip_sets_test.go index 5b8d1eead4..e07332274e 100644 --- a/services/guardduty/ip_sets_test.go +++ b/services/guardduty/ip_sets_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -31,7 +32,7 @@ func TestIPSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) ipSetID := cr["ipSetId"].(string) require.NotEmpty(t, ipSetID) @@ -39,7 +40,7 @@ func TestIPSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "my-ipset", gr["name"]) assert.Equal(t, "TXT", gr["format"]) assert.Equal(t, "ACTIVE", gr["status"]) @@ -53,7 +54,7 @@ func TestIPSet_CRUD(t *testing.T) { "name": "upd-ipset", "format": "TXT", "location": "s3://b/f.txt", }) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) ipSetID := cr["ipSetId"].(string) rec = doRequest(t, h, http.MethodPost, "/detector/"+detectorID+"/ipset/"+ipSetID, map[string]any{ @@ -64,7 +65,7 @@ func TestIPSet_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/ipset/"+ipSetID, nil) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "updated-ipset", gr["name"]) assert.Equal(t, "ACTIVE", gr["status"]) }, @@ -77,7 +78,7 @@ func TestIPSet_CRUD(t *testing.T) { "name": "del-ipset", "format": "TXT", "location": "s3://b/f.txt", }) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) ipSetID := cr["ipSetId"].(string) rec = doRequest(t, h, http.MethodDelete, "/detector/"+detectorID+"/ipset/"+ipSetID, nil) @@ -87,7 +88,7 @@ func TestIPSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "DELETED", gr["status"]) rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/ipset", nil) @@ -111,7 +112,7 @@ func TestIPSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, ok := resp["ipSetIds"].([]any) require.True(t, ok) assert.Len(t, ids, 3) @@ -125,12 +126,12 @@ func TestIPSet_CRUD(t *testing.T) { "name": "inactive-ipset", "format": "TXT", "location": "s3://b/f.txt", }) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) ipSetID := cr["ipSetId"].(string) rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/ipset/"+ipSetID, nil) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "INACTIVE", gr["status"]) }, }, @@ -156,7 +157,7 @@ func TestListIPSets_Empty_State(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["ipSetIds"] require.True(t, exists, "ListIPSets must include 'ipSetIds' key") @@ -182,14 +183,14 @@ func TestIPSet_Tags_EmptyMap_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) ipSetID := createResp["ipSetId"].(string) rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/ipset/"+ipSetID, nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["tags"] require.True(t, exists, "GetIPSet response must include 'tags' key") diff --git a/services/guardduty/malware_protection_plan_schema.go b/services/guardduty/malware_protection_plan_schema.go index 06032c603e..d9027ce7a3 100644 --- a/services/guardduty/malware_protection_plan_schema.go +++ b/services/guardduty/malware_protection_plan_schema.go @@ -1,6 +1,10 @@ package guardduty -import "encoding/json" +import ( + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // ProtectedResourceInput mirrors types.CreateProtectedResource (also reused // verbatim by GetMalwareProtectionPlanOutput.ProtectedResource -- Create and @@ -56,13 +60,13 @@ func decodeProtectedResource(raw map[string]any) (*ProtectedResourceInput, error return &ProtectedResourceInput{}, nil } - data, marshalErr := json.Marshal(raw) + data, marshalErr := json.Marshal(raw, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } var pr ProtectedResourceInput - if unmarshalErr := json.Unmarshal(data, &pr); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &pr, jsonx.V1()); unmarshalErr != nil { return nil, unmarshalErr } @@ -74,13 +78,13 @@ func decodeMalwareProtectionPlanActions(raw map[string]any) (*MalwareProtectionP return &MalwareProtectionPlanActionsInput{}, nil } - data, marshalErr := json.Marshal(raw) + data, marshalErr := json.Marshal(raw, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } var a MalwareProtectionPlanActionsInput - if unmarshalErr := json.Unmarshal(data, &a); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &a, jsonx.V1()); unmarshalErr != nil { return nil, unmarshalErr } diff --git a/services/guardduty/malware_protection_test.go b/services/guardduty/malware_protection_test.go index bcfdf87788..4ec144e155 100644 --- a/services/guardduty/malware_protection_test.go +++ b/services/guardduty/malware_protection_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -30,7 +31,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) scanID, _ := startResp["scanId"].(string) require.NotEmpty(t, scanID) @@ -39,7 +40,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, scanID, getResp["scanId"]) // ListMalwareScans @@ -47,7 +48,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) scans, _ := listResp["scans"].([]any) assert.Len(t, scans, 1) }, @@ -77,7 +78,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["scans"]) }, }, @@ -133,7 +134,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var settingsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settingsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &settingsResp, jsonx.V1())) assert.Equal(t, "RETENTION_WITH_FINDING", settingsResp["ebsSnapshotPreservation"]) }, }, @@ -167,7 +168,7 @@ func TestMalwareScanning(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["scanId"]) }, }, @@ -375,7 +376,7 @@ func TestMalwareProtectionPlans(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) planID, _ := createResp["malwareProtectionPlanId"].(string) require.NotEmpty(t, planID) @@ -384,7 +385,7 @@ func TestMalwareProtectionPlans(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, planID, getResp["malwareProtectionPlanId"]) // UpdateMalwareProtectionPlan uses PATCH on the real wire -- @@ -401,7 +402,7 @@ func TestMalwareProtectionPlans(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) plans, _ := listResp["malwareProtectionPlans"].([]any) assert.Len(t, plans, 1) @@ -411,7 +412,7 @@ func TestMalwareProtectionPlans(t *testing.T) { // List after delete rec = doRequest(t, h, http.MethodGet, "/malware-protection-plan", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) plansAfter, _ := listResp["malwareProtectionPlans"].([]any) assert.Empty(t, plansAfter) }, @@ -461,7 +462,7 @@ func TestUpdateMalwareProtectionPlan_PreservesBucketName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) planID, _ := createResp["malwareProtectionPlanId"].(string) require.NotEmpty(t, planID) @@ -481,7 +482,7 @@ func TestUpdateMalwareProtectionPlan_PreservesBucketName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) protectedResource, ok := getResp["protectedResource"].(map[string]any) require.True(t, ok, "protectedResource must survive the update") diff --git a/services/guardduty/members_test.go b/services/guardduty/members_test.go index 864eb9cc13..0ec28fdb60 100644 --- a/services/guardduty/members_test.go +++ b/services/guardduty/members_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" organizationsbackend "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -36,7 +37,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Empty(t, createResp["unprocessedAccounts"]) // ListMembers @@ -44,7 +45,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) members, _ := listResp["members"].([]any) assert.Len(t, members, 2) @@ -55,7 +56,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) got, _ := getResp["members"].([]any) assert.Len(t, got, 1) @@ -68,7 +69,7 @@ func TestMembers(t *testing.T) { // ListMembers after delete rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/member", nil) var listAfter map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listAfter)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listAfter, jsonx.V1())) membersAfter, _ := listAfter["members"].([]any) assert.Empty(t, membersAfter) }, @@ -99,7 +100,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members, _ := resp["members"].([]any) require.Len(t, members, 1) @@ -310,7 +311,7 @@ func TestMemberOps_AutoEnableOrganizationMembersAll_Rejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "BadRequestException", errOut["__type"]) }) } @@ -382,7 +383,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var countResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &countResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &countResp, jsonx.V1())) assert.NotNil(t, countResp["invitationsCount"]) // ListInvitations @@ -390,7 +391,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.NotNil(t, listResp["invitations"]) }, }, @@ -431,7 +432,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var adminResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &adminResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &adminResp, jsonx.V1())) assert.NotNil(t, adminResp["administrator"]) // DisassociateFromAdministratorAccount @@ -458,7 +459,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var masterResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &masterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &masterResp, jsonx.V1())) assert.NotNil(t, masterResp["master"]) // DisassociateFromMasterAccount diff --git a/services/guardduty/multi_region_test.go b/services/guardduty/multi_region_test.go index 463e56d8fa..42983a102c 100644 --- a/services/guardduty/multi_region_test.go +++ b/services/guardduty/multi_region_test.go @@ -2,7 +2,7 @@ package guardduty_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/guardduty/organization_test.go b/services/guardduty/organization_test.go index 65dc7147ed..2e5a71b027 100644 --- a/services/guardduty/organization_test.go +++ b/services/guardduty/organization_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -34,7 +35,7 @@ func TestOrganization(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) accounts, _ := listResp["adminAccounts"].([]any) assert.Len(t, accounts, 1) @@ -46,7 +47,7 @@ func TestOrganization(t *testing.T) { // List after disable rec = doRequest(t, h, http.MethodGet, "/admin", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) accounts2, _ := listResp["adminAccounts"].([]any) assert.Empty(t, accounts2) }, @@ -63,7 +64,7 @@ func TestOrganization(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.NotNil(t, descResp["autoEnable"]) // UpdateOrganizationConfiguration @@ -74,7 +75,7 @@ func TestOrganization(t *testing.T) { // Verify update rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/admin", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, true, descResp["autoEnable"]) }, }, diff --git a/services/guardduty/persistence.go b/services/guardduty/persistence.go index cb0ae8037f..65e27f9826 100644 --- a/services/guardduty/persistence.go +++ b/services/guardduty/persistence.go @@ -2,7 +2,7 @@ package guardduty import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -110,7 +110,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // identity of their own -- see store_setup.go) and is persisted here // directly, as before. MemberSeq is a scalar counter, also carried directly. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountId"` Region string `json:"region"` @@ -308,7 +308,7 @@ func unwrapByDetectorDTOs[V any](dtos *store.Table[byDetectorDTO[V]], setDetecto // restoreDirtyTables rebuilds every "dirty" store.Table on b from tables via // the ephemeral DTO registry, factored out of Restore to keep Restore's own // cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("guardduty: restore snapshot DTO tables: %w", err) diff --git a/services/guardduty/publishing_destinations_test.go b/services/guardduty/publishing_destinations_test.go index 5414bca43f..6ae3fe265f 100644 --- a/services/guardduty/publishing_destinations_test.go +++ b/services/guardduty/publishing_destinations_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -36,7 +37,7 @@ func TestPublishingDestinations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) destID, _ := createResp["destinationId"].(string) require.NotEmpty(t, destID) @@ -45,7 +46,7 @@ func TestPublishingDestinations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "S3", descResp["destinationType"]) // UpdatePublishingDestination @@ -62,7 +63,7 @@ func TestPublishingDestinations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) dests, _ := listResp["destinations"].([]any) assert.Len(t, dests, 1) @@ -72,7 +73,7 @@ func TestPublishingDestinations(t *testing.T) { // List after delete rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/publishingDestination", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) destsAfter, _ := listResp["destinations"].([]any) assert.Empty(t, destsAfter) }, diff --git a/services/guardduty/tags_test.go b/services/guardduty/tags_test.go index e838b42fe9..f6f53eda4e 100644 --- a/services/guardduty/tags_test.go +++ b/services/guardduty/tags_test.go @@ -1,7 +1,7 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -34,7 +35,7 @@ func TestTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -56,7 +57,7 @@ func TestTags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/tags/"+arn, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].(map[string]any) assert.NotContains(t, tags, "k1") assert.Equal(t, "v2", tags["k2"]) @@ -72,7 +73,7 @@ func TestTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Empty(t, tags) @@ -101,7 +102,7 @@ func TestTagResource_Merges_Creation_Tags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["detectorId"].(string) arn := fmt.Sprintf("arn:aws:guardduty:us-east-1:123456789012:detector/%s", id) @@ -115,7 +116,7 @@ func TestTagResource_Merges_Creation_Tags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["tags"].(map[string]any) assert.Equal(t, "test", tags["env"], "creation-time tag must be preserved") @@ -134,7 +135,7 @@ func TestUntagResource_Removes_Only_Specified_Key(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["detectorId"].(string) arn := fmt.Sprintf("arn:aws:guardduty:us-east-1:123456789012:detector/%s", id) @@ -146,7 +147,7 @@ func TestUntagResource_Removes_Only_Specified_Key(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["tags"].(map[string]any) assert.Equal(t, "v1", tags["k1"], "k1 must be preserved") diff --git a/services/guardduty/threat_intel_sets_test.go b/services/guardduty/threat_intel_sets_test.go index ba34e2cb9e..5dc1b25b06 100644 --- a/services/guardduty/threat_intel_sets_test.go +++ b/services/guardduty/threat_intel_sets_test.go @@ -1,13 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/guardduty" ) @@ -31,7 +32,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) setID := cr["threatIntelSetId"].(string) require.NotEmpty(t, setID) @@ -39,7 +40,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "my-threatset", gr["name"]) assert.Equal(t, "ACTIVE", gr["status"]) }, @@ -52,7 +53,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { "name": "upd-threat", "format": "TXT", "location": "s3://b/t.txt", "activate": true, }) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) setID := cr["threatIntelSetId"].(string) activate := false @@ -63,7 +64,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/threatintelset/"+setID, nil) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "INACTIVE", gr["status"]) }, }, @@ -75,7 +76,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { "name": "del-threat", "format": "TXT", "location": "s3://b/t.txt", }) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) setID := cr["threatIntelSetId"].(string) rec = doRequest(t, h, http.MethodDelete, "/detector/"+detectorID+"/threatintelset/"+setID, nil) @@ -85,7 +86,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, "DELETED", gr["status"]) rec = doRequest(t, h, http.MethodGet, "/detector/"+detectorID+"/threatintelset", nil) @@ -109,7 +110,7 @@ func TestThreatIntelSet_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids, ok := resp["threatIntelSetIds"].([]any) require.True(t, ok) assert.Len(t, ids, 2) @@ -137,7 +138,7 @@ func TestListThreatIntelSets_Empty_State(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["threatIntelSetIds"] require.True(t, exists, "ListThreatIntelSets must include 'threatIntelSetIds' key") @@ -163,14 +164,14 @@ func TestThreatIntelSet_Tags_EmptyMap_Not_Null(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) setID := createResp["threatIntelSetId"].(string) rec = doRequest(t, h, http.MethodGet, "/detector/"+id+"/threatintelset/"+setID, nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) raw, exists := resp["tags"] require.True(t, exists, "GetThreatIntelSet response must include 'tags' key") diff --git a/services/guardduty/usage_test.go b/services/guardduty/usage_test.go index f9d4df400f..979d9e80ca 100644 --- a/services/guardduty/usage_test.go +++ b/services/guardduty/usage_test.go @@ -1,12 +1,14 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetUsageStatistics_WireShape locks the GetUsageStatistics fix: the @@ -24,7 +26,7 @@ func TestGetUsageStatistics_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) us, ok := resp["usageStatistics"].(map[string]any) require.True(t, ok, "response must be wrapped under usageStatistics") @@ -66,7 +68,7 @@ func TestGetUsageStatistics_UsageStatisticType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) us := resp["usageStatistics"].(map[string]any) assert.Contains(t, us, "sumByAccount") @@ -93,7 +95,7 @@ func TestGetUsageStatistics_SumByFeature_ReflectsEnabledFeatures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) detID := createResp["detectorId"].(string) rec = doRequest(t, h, http.MethodPost, "/detector/"+detID+"/usage/statistics", map[string]any{ @@ -102,7 +104,7 @@ func TestGetUsageStatistics_SumByFeature_ReflectsEnabledFeatures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) us := resp["usageStatistics"].(map[string]any) features, ok := us["sumByFeature"].([]any) @@ -140,7 +142,7 @@ func TestGetRemainingFreeTrialDays_HonorsAccountIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts, ok := resp["accounts"].([]any) require.True(t, ok) diff --git a/services/guardduty/wire_field_fixes_test.go b/services/guardduty/wire_field_fixes_test.go index 889c77444b..e9d3b40e2d 100644 --- a/services/guardduty/wire_field_fixes_test.go +++ b/services/guardduty/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package guardduty_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/guardduty" @@ -366,7 +367,7 @@ func TestListMalwareProtectionPlans_NoInventedArn(t *testing.T) { var raw struct { MalwareProtectionPlans []map[string]any `json:"malwareProtectionPlans"` } - require.NoError(t, json.Unmarshal(body, &raw)) + require.NoError(t, json.Unmarshal(body, &raw, jsonx.V1())) require.NotEmpty(t, raw.MalwareProtectionPlans) for _, entry := range raw.MalwareProtectionPlans { diff --git a/services/iam/accounts.go b/services/iam/accounts.go index 8ff7b4fb8f..95cd9aabff 100644 --- a/services/iam/accounts.go +++ b/services/iam/accounts.go @@ -2,7 +2,7 @@ package iam import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "strings" @@ -223,13 +223,13 @@ func (h *Handler) forAccount(root *InMemoryBackend, acct string) *Handler { return sh } -func (h *Handler) accountSnapshots(ctx context.Context) map[string]json.RawMessage { +func (h *Handler) accountSnapshots(ctx context.Context) map[string]jsontext.Value { root, ok := h.Backend.(*InMemoryBackend) if !ok { return nil } - var out map[string]json.RawMessage + var out map[string]jsontext.Value for _, id := range root.Accounts() { data := h.forAccount(root, id).Snapshot(ctx) @@ -238,7 +238,7 @@ func (h *Handler) accountSnapshots(ctx context.Context) map[string]json.RawMessa } if out == nil { - out = make(map[string]json.RawMessage) + out = make(map[string]jsontext.Value) } out[id] = data @@ -247,7 +247,7 @@ func (h *Handler) accountSnapshots(ctx context.Context) map[string]json.RawMessa return out } -func (h *Handler) restoreAccounts(ctx context.Context, snaps map[string]json.RawMessage) error { +func (h *Handler) restoreAccounts(ctx context.Context, snaps map[string]jsontext.Value) error { root, ok := h.Backend.(*InMemoryBackend) if !ok { return nil diff --git a/services/iam/aws_managed.go b/services/iam/aws_managed.go index d5b1ed86a7..0015de82c5 100644 --- a/services/iam/aws_managed.go +++ b/services/iam/aws_managed.go @@ -1,16 +1,18 @@ package iam import ( - "bytes" "crypto/sha256" _ "embed" "encoding/base32" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "strings" "sync" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed data/aws_managed_policies.json @@ -23,13 +25,13 @@ type awsManagedFile struct { } type awsManagedEntry struct { - Name string `json:"name"` - Path string `json:"path"` - PolicyID string `json:"policyId"` - DefaultVersionID string `json:"defaultVersionId"` - CreateDate time.Time `json:"createDate"` - UpdateDate time.Time `json:"updateDate"` - Document json.RawMessage `json:"document"` + Name string `json:"name"` + Path string `json:"path"` + PolicyID string `json:"policyId"` + DefaultVersionID string `json:"defaultVersionId"` + CreateDate time.Time `json:"createDate"` + UpdateDate time.Time `json:"updateDate"` + Document jsontext.Value `json:"document"` } type awsManagedCatalog struct { @@ -49,7 +51,7 @@ var loadAWSManagedCatalog = sync.OnceValue(func() *awsManagedCatalog { func parseAWSManagedCatalog(raw []byte) (*awsManagedCatalog, error) { var file awsManagedFile - if err := json.Unmarshal(raw, &file); err != nil { + if err := json.Unmarshal(raw, &file, jsonx.V1()); err != nil { return nil, fmt.Errorf("iam: parse AWS managed policy catalog: %w", err) } @@ -59,8 +61,8 @@ func parseAWSManagedCatalog(raw []byte) (*awsManagedCatalog, error) { } for _, e := range file.Policies { - var doc bytes.Buffer - if err := json.Compact(&doc, e.Document); err != nil { + doc := e.Document.Clone() + if err := doc.Compact(jsonx.V1()); err != nil { return nil, fmt.Errorf("iam: AWS managed policy %q document: %w", e.Name, err) } @@ -74,7 +76,7 @@ func parseAWSManagedCatalog(raw []byte) (*awsManagedCatalog, error) { PolicyID: e.PolicyID, Arn: arn, Path: e.Path, - PolicyDocument: doc.String(), + PolicyDocument: string(doc), DefaultVersionID: e.DefaultVersionID, CreateDate: e.CreateDate.UTC(), UpdateDate: e.UpdateDate.UTC(), diff --git a/services/iam/aws_managed_test.go b/services/iam/aws_managed_test.go index 4e6f6b0595..604de57460 100644 --- a/services/iam/aws_managed_test.go +++ b/services/iam/aws_managed_test.go @@ -1,7 +1,8 @@ package iam_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io/fs" "net/url" "os" @@ -17,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -475,13 +477,13 @@ func TestAWSManagedPolicyCatalog_Integrity(t *testing.T) { var file struct { Policies []struct { - Name string `json:"name"` - Path string `json:"path"` - DefaultVersionID string `json:"defaultVersionId"` - Document json.RawMessage `json:"document"` + Name string `json:"name"` + Path string `json:"path"` + DefaultVersionID string `json:"defaultVersionId"` + Document jsontext.Value `json:"document"` } `json:"policies"` } - require.NoError(t, json.Unmarshal(raw, &file)) + require.NoError(t, json.Unmarshal(raw, &file, jsonx.V1())) seen := map[string]bool{} @@ -496,7 +498,7 @@ func TestAWSManagedPolicyCatalog_Integrity(t *testing.T) { Version string `json:"Version"` Statement []any `json:"Statement"` } - require.NoError(t, json.Unmarshal(p.Document, &d), key) + require.NoError(t, json.Unmarshal(p.Document, &d, jsonx.V1()), key) assert.Equal(t, "2012-10-17", d.Version, key) assert.NotEmpty(t, d.Statement, key) } diff --git a/services/iam/conditions_test.go b/services/iam/conditions_test.go index e9dd5387ba..d0fd241e7f 100644 --- a/services/iam/conditions_test.go +++ b/services/iam/conditions_test.go @@ -2,11 +2,12 @@ package iam_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -1058,7 +1059,7 @@ func TestConditionTagKeyFallsThroughToExtra(t *testing.T) { // mustJSON marshals v to a compact JSON string, panicking on error (test-only). func mustJSON(v any) string { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { panic("marshal policy: " + err.Error()) } diff --git a/services/iam/enforcement_integration_test.go b/services/iam/enforcement_integration_test.go index b3e00d0241..da088c1515 100644 --- a/services/iam/enforcement_integration_test.go +++ b/services/iam/enforcement_integration_test.go @@ -2,7 +2,7 @@ package iam_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -19,6 +19,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -202,7 +203,7 @@ func TestEnforcement_ConditionOperators_SDKIntegration(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - policyBytes, marshalErr := json.Marshal(tt.policy) + policyBytes, marshalErr := json.Marshal(tt.policy, jsonx.V1()) require.NoError(t, marshalErr) const ( @@ -260,7 +261,7 @@ func TestEnforcement_MultiServiceSDKIntegration(t *testing.T) { }, }, } - analystPolicyBytes, marshalErr := json.Marshal(analystPolicy) + analystPolicyBytes, marshalErr := json.Marshal(analystPolicy, jsonx.V1()) require.NoError(t, marshalErr) analystPolicyDoc := string(analystPolicyBytes) diff --git a/services/iam/evaluator.go b/services/iam/evaluator.go index 7c7b2f870d..2970367b72 100644 --- a/services/iam/evaluator.go +++ b/services/iam/evaluator.go @@ -1,11 +1,12 @@ package iam import ( - "encoding/json" + "encoding/json/v2" "maps" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/safemap" ) @@ -68,7 +69,7 @@ func parsePolicyDocumentCached(expanded string) (PolicyDocument, bool) { var pd PolicyDocument - err := json.Unmarshal([]byte(expanded), &pd) + err := json.Unmarshal([]byte(expanded), &pd, jsonx.V1()) entry := &cachedPolicyDoc{doc: pd, ok: err == nil} parsedPolicyCache.Set(expanded, entry) diff --git a/services/iam/handler_inline_policies.go b/services/iam/handler_inline_policies.go index d0797fd8a2..93ca66236f 100644 --- a/services/iam/handler_inline_policies.go +++ b/services/iam/handler_inline_policies.go @@ -1,11 +1,14 @@ package iam import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/url" "sort" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) iamInlinePolicyDispatchTable() map[string]iamActionFn { @@ -284,10 +287,10 @@ func contextKeysFromPolicyDocuments(docs []string) []string { } var parsed struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if err := json.Unmarshal([]byte(doc), &parsed); err != nil { + if err := json.Unmarshal([]byte(doc), &parsed, jsonx.V1()); err != nil { // Malformed documents are skipped; GetContextKeys is best-effort. continue } diff --git a/services/iam/middleware.go b/services/iam/middleware.go index 547735ed14..a34c961c07 100644 --- a/services/iam/middleware.go +++ b/services/iam/middleware.go @@ -3,7 +3,7 @@ package iam import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/http" "strings" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/iampolicystream" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -752,7 +753,7 @@ func writeJSONRPCAccessDenied(c *echo.Context, action, msg string) error { Message: cmp.Or(msg, "User is not authorized to perform: "+action), } - body, err := json.Marshal(resp) + body, err := json.Marshal(resp, jsonx.V1()) if err != nil { return c.String(http.StatusBadRequest, `{"__type":"AccessDeniedException"}`) } diff --git a/services/iam/persistence.go b/services/iam/persistence.go index 6d65e24168..fca1c9f695 100644 --- a/services/iam/persistence.go +++ b/services/iam/persistence.go @@ -2,7 +2,7 @@ package iam import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -32,7 +32,7 @@ type backendSnapshot struct { PolicyVersions map[string][]StoredPolicyVersion `json:"policyVersions,omitempty"` RoleByARN map[string]string `json:"roleByARN,omitempty"` PolicyByARN map[string]string `json:"policyByARN,omitempty"` - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` PolicyAttachments map[string]policyAttachmentRefs `json:"policyAttachments,omitempty"` DeletedV1Policies map[string]bool `json:"deletedV1Policies,omitempty"` AccountProperties map[string]string `json:"accountProperties,omitempty"` @@ -329,8 +329,8 @@ func parseVersionNum(id string) int { type handlerSnapshot struct { Tags map[string]map[string]string `json:"tags,omitempty"` // Accounts holds each non-default account's handler snapshot. - Accounts map[string]json.RawMessage `json:"accounts,omitempty"` - Backend json.RawMessage `json:"backend,omitempty"` + Accounts map[string]jsontext.Value `json:"accounts,omitempty"` + Backend jsontext.Value `json:"backend,omitempty"` } // Snapshot implements persistence.Persistable. It combines the backend's own @@ -344,7 +344,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { if s, ok := h.Backend.(snapshotter); ok { if b := s.Snapshot(ctx); len(b) > 0 { - snap.Backend = json.RawMessage(b) + snap.Backend = jsontext.Value(b) } } diff --git a/services/iam/policy_validation.go b/services/iam/policy_validation.go index d8fb1f883f..8cc7a0511d 100644 --- a/services/iam/policy_validation.go +++ b/services/iam/policy_validation.go @@ -1,9 +1,12 @@ package iam import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // IAM policy-grammar validation. @@ -46,14 +49,14 @@ func isSupportedPolicyVersion(v string) bool { // rawStatement is a statement decoded with field presence preserved so that // "absent" can be distinguished from "present but empty". type rawStatement struct { - Effect *string `json:"Effect"` - Condition map[string]map[string]json.RawMessage `json:"Condition"` - Action json.RawMessage `json:"Action"` - NotAction json.RawMessage `json:"NotAction"` - Resource json.RawMessage `json:"Resource"` - NotResource json.RawMessage `json:"NotResource"` - Principal json.RawMessage `json:"Principal"` - NotPrincipal json.RawMessage `json:"NotPrincipal"` + Effect *string `json:"Effect"` + Condition map[string]map[string]jsontext.Value `json:"Condition"` + Action jsontext.Value `json:"Action"` + NotAction jsontext.Value `json:"NotAction"` + Resource jsontext.Value `json:"Resource"` + NotResource jsontext.Value `json:"NotResource"` + Principal jsontext.Value `json:"Principal"` + NotPrincipal jsontext.Value `json:"NotPrincipal"` } // validateIdentityPolicyDocument validates an identity-based policy document @@ -66,8 +69,8 @@ func validateIdentityPolicyDocument(policyDocument string) error { } // Top level must be a JSON object. - var top map[string]json.RawMessage - if err := json.Unmarshal([]byte(policyDocument), &top); err != nil { + var top map[string]jsontext.Value + if err := json.Unmarshal([]byte(policyDocument), &top, jsonx.V1()); err != nil { return fmt.Errorf("%w: policy document must be a JSON object", ErrMalformedPolicyDocument) } @@ -99,13 +102,13 @@ func validateIdentityPolicyDocument(policyDocument string) error { } // validatePolicyVersion checks the optional Version element. -func validatePolicyVersion(raw json.RawMessage) error { +func validatePolicyVersion(raw jsontext.Value) error { if raw == nil { return nil } var version string - if err := json.Unmarshal(raw, &version); err != nil { + if err := json.Unmarshal(raw, &version, jsonx.V1()); err != nil { return fmt.Errorf("%w: Version must be a string", ErrMalformedPolicyDocument) } @@ -121,11 +124,11 @@ func validatePolicyVersion(raw json.RawMessage) error { // decodeStatements accepts either a single statement object or an array of // statement objects, matching AWS's tolerance of both shapes. -func decodeStatements(raw json.RawMessage) ([]rawStatement, error) { +func decodeStatements(raw jsontext.Value) ([]rawStatement, error) { trimmed := strings.TrimSpace(string(raw)) if strings.HasPrefix(trimmed, "[") { var arr []rawStatement - if err := json.Unmarshal(raw, &arr); err != nil { + if err := json.Unmarshal(raw, &arr, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: Statement array is malformed", ErrMalformedPolicyDocument) } @@ -133,7 +136,7 @@ func decodeStatements(raw json.RawMessage) ([]rawStatement, error) { } var single rawStatement - if err := json.Unmarshal(raw, &single); err != nil { + if err := json.Unmarshal(raw, &single, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: Statement must be an object or array of objects", ErrMalformedPolicyDocument) } diff --git a/services/iam/request_scope.go b/services/iam/request_scope.go index 02e81702b2..3fddcddeec 100644 --- a/services/iam/request_scope.go +++ b/services/iam/request_scope.go @@ -2,7 +2,7 @@ package iam import ( "cmp" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -148,7 +149,7 @@ func filterPrincipalDocs(docs []string, condCtx ConditionContext) []string { func filterPrincipalDoc(doc string, condCtx ConditionContext) string { var raw map[string]any - if json.Unmarshal([]byte(doc), &raw) != nil { + if json.Unmarshal([]byte(doc), &raw, jsonx.V1()) != nil { return doc } @@ -162,7 +163,7 @@ func filterPrincipalDoc(doc string, condCtx ConditionContext) string { raw["Statement"] = kept - out, err := json.Marshal(raw) + out, err := json.Marshal(raw, jsonx.V1()) if err != nil { return doc } diff --git a/services/iam/resource_arn.go b/services/iam/resource_arn.go index 60d2c5fbdd..8b1bcaf65a 100644 --- a/services/iam/resource_arn.go +++ b/services/iam/resource_arn.go @@ -2,7 +2,7 @@ package iam import ( "context" - "encoding/json" + "encoding/json/v2" "net" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -230,7 +231,7 @@ func extractJSONTargetResourceARN(r *http.Request, target, accountID, region str } var payload jsonTargetResourcePayload - if jsonErr := json.Unmarshal(body, &payload); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &payload, jsonx.V1()); jsonErr != nil { return "" } diff --git a/services/iam/role_templates.go b/services/iam/role_templates.go index 2db30fd155..288582ab74 100644 --- a/services/iam/role_templates.go +++ b/services/iam/role_templates.go @@ -1,13 +1,14 @@ package iam import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "strconv" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func roleTemplateVersionKey(templateArn string, minorVersion int32) string { @@ -196,7 +197,7 @@ type acquiredRoleSpec struct { // returning an error without having mutated any backend state. func buildAcquiredRoleSpec(tv *RoleTemplateVersion, values map[string]string) (*acquiredRoleSpec, error) { assumeRolePolicy := substituteTemplateParams(tv.AssumeRolePolicyDocumentTemplate, values) - if assumeRolePolicy != "" && !json.Valid([]byte(assumeRolePolicy)) { + if assumeRolePolicy != "" && !jsontext.Value([]byte(assumeRolePolicy)).IsValid(jsonx.V1()) { return nil, fmt.Errorf("%w: invalid JSON in AssumeRolePolicyDocument", ErrMalformedPolicyDocument) } diff --git a/services/iam/roles.go b/services/iam/roles.go index 9fb017549e..2a13d95d57 100644 --- a/services/iam/roles.go +++ b/services/iam/roles.go @@ -1,7 +1,8 @@ package iam import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -31,7 +33,7 @@ func (b *InMemoryBackend) CreateRole( return nil, quotaExceeded("RolesPerAccount", limit) } - if assumeRolePolicyDocument != "" && !json.Valid([]byte(assumeRolePolicyDocument)) { + if assumeRolePolicyDocument != "" && !jsontext.Value([]byte(assumeRolePolicyDocument)).IsValid(jsonx.V1()) { return nil, fmt.Errorf( "%w: invalid JSON in AssumeRolePolicyDocument", ErrMalformedPolicyDocument, @@ -403,7 +405,7 @@ func (b *InMemoryBackend) UpdateAssumeRolePolicy(roleName, policyDocument string return fmt.Errorf("%w: role %q not found", ErrRoleNotFound, roleName) } - if policyDocument != "" && !json.Valid([]byte(policyDocument)) { + if policyDocument != "" && !jsontext.Value([]byte(policyDocument)).IsValid(jsonx.V1()) { return fmt.Errorf( "%w: invalid JSON in AssumeRolePolicyDocument", ErrMalformedPolicyDocument, @@ -451,7 +453,7 @@ func (b *InMemoryBackend) UpdateRole(roleName, description string) error { // parseJSON is a thin wrapper around json.Unmarshal for readability. func parseJSON(s string, v any) error { - return json.Unmarshal([]byte(s), v) //nolint:wrapcheck // thin delegation; callers handle the error + return json.Unmarshal([]byte(s), v, jsonx.V1()) //nolint:wrapcheck // thin delegation; callers handle the error } // TagRole merges the given key-value pairs into the role's Tags field. @@ -522,7 +524,7 @@ type trustPrincipal struct { func (p *trustPrincipal) UnmarshalJSON(data []byte) error { // Try string first. var s string - if err := json.Unmarshal(data, &s); err == nil { + if err := json.Unmarshal(data, &s, jsonx.V1()); err == nil { if s == "*" { p.AllowAll = true } else { @@ -533,8 +535,8 @@ func (p *trustPrincipal) UnmarshalJSON(data []byte) error { } // Try typed map. - var m map[string]json.RawMessage - if err := json.Unmarshal(data, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(data, &m, jsonx.V1()); err != nil { return err //nolint:wrapcheck // UnmarshalJSON interface; wrapping changes the type } @@ -543,10 +545,10 @@ func (p *trustPrincipal) UnmarshalJSON(data []byte) error { // Value can be a string or []string. var single string - if err := json.Unmarshal(v, &single); err == nil { + if err := json.Unmarshal(v, &single, jsonx.V1()); err == nil { vals = []string{single} } else { - if err2 := json.Unmarshal(v, &vals); err2 != nil { + if err2 := json.Unmarshal(v, &vals, jsonx.V1()); err2 != nil { continue } } @@ -685,11 +687,11 @@ func (b *InMemoryBackend) validateTrustPolicyPrincipal(policyJSON string) error var doc struct { Statement []struct { - Principal json.RawMessage `json:"Principal"` + Principal jsontext.Value `json:"Principal"` } `json:"Statement"` } - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return nil //nolint:nilerr // JSON validity confirmed upstream; this path handles schema mismatch } @@ -699,7 +701,7 @@ func (b *InMemoryBackend) validateTrustPolicyPrincipal(policyJSON string) error } var p trustPrincipal - if err := json.Unmarshal(stmt.Principal, &p); err != nil { + if err := json.Unmarshal(stmt.Principal, &p, jsonx.V1()); err != nil { return fmt.Errorf( "%w: statement[%d] Principal has unsupported shape", ErrMalformedPolicyDocument, i, diff --git a/services/identitystore/epoch_time_test.go b/services/identitystore/epoch_time_test.go index e3705776cd..73a5895e81 100644 --- a/services/identitystore/epoch_time_test.go +++ b/services/identitystore/epoch_time_test.go @@ -1,12 +1,14 @@ package identitystore //nolint:testpackage // epochTime is unexported; white-box unit tests of its wire encoding. import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestEpochTimeMarshalJSON verifies epochTime renders as an AWS @@ -43,7 +45,7 @@ func TestEpochTimeMarshalJSON(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - got, err := json.Marshal(epochTime(tt.in)) + got, err := json.Marshal(epochTime(tt.in), jsonx.V1()) require.NoError(t, err) assert.Equal(t, tt.want, string(got)) }) @@ -87,7 +89,7 @@ func TestEpochTimeUnmarshalJSON(t *testing.T) { var got epochTime - err := json.Unmarshal([]byte(tt.in), &got) + err := json.Unmarshal([]byte(tt.in), &got, jsonx.V1()) if tt.wantErr { require.Error(t, err) @@ -110,11 +112,11 @@ func TestEpochTimeRoundTrip(t *testing.T) { original := time.Now().UTC() - data, err := json.Marshal(epochTime(original)) + data, err := json.Marshal(epochTime(original), jsonx.V1()) require.NoError(t, err) var restored epochTime - require.NoError(t, json.Unmarshal(data, &restored)) + require.NoError(t, json.Unmarshal(data, &restored, jsonx.V1())) assert.WithinDuration(t, original, time.Time(restored), time.Millisecond) } diff --git a/services/identitystore/guard_sentinel_test.go b/services/identitystore/guard_sentinel_test.go index f54ff33709..cd7615a537 100644 --- a/services/identitystore/guard_sentinel_test.go +++ b/services/identitystore/guard_sentinel_test.go @@ -2,7 +2,7 @@ package identitystore //nolint:testpackage // pins errResponseWritten + unexport import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const internalTestStoreID = "d-1234567890" @@ -34,7 +35,7 @@ func newInternalTestContext(t *testing.T, body []byte) (*echo.Context, *httptest func mustJSON(t *testing.T, v any) []byte { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return b diff --git a/services/identitystore/handler.go b/services/identitystore/handler.go index 98477ab150..796a197084 100644 --- a/services/identitystore/handler.go +++ b/services/identitystore/handler.go @@ -3,7 +3,7 @@ package identitystore import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -129,7 +130,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { IdentityStoreID string `json:"IdentityStoreId"` } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -306,7 +307,7 @@ func (h *Handler) parseAlternateIDRequest(c *echo.Context, body []byte) (alterna IdentityStoreID string `json:"IdentityStoreId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { _ = h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") return alternateIDResult{}, errResponseWritten @@ -444,7 +445,7 @@ func validNextToken(body []byte) bool { NextToken string `json:"NextToken"` } - if json.Unmarshal(body, &req) != nil || req.NextToken == "" { + if json.Unmarshal(body, &req, jsonx.V1()) != nil || req.NextToken == "" { return true } diff --git a/services/identitystore/handler_group_memberships.go b/services/identitystore/handler_group_memberships.go index d6c1bd6b4f..6c1f343f42 100644 --- a/services/identitystore/handler_group_memberships.go +++ b/services/identitystore/handler_group_memberships.go @@ -2,12 +2,14 @@ package identitystore import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxIsMemberInGroupsIDs is the maximum number of GroupIds allowed per IsMemberInGroups request. @@ -74,7 +76,7 @@ type listGroupMembershipsRequest struct { func (h *Handler) handleCreateGroupMembership(ctx context.Context, c *echo.Context, body []byte) error { var req createGroupMembershipRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -103,7 +105,7 @@ func (h *Handler) handleCreateGroupMembership(ctx context.Context, c *echo.Conte func (h *Handler) handleDescribeGroupMembership(ctx context.Context, c *echo.Context, body []byte) error { var req describeGroupMembershipRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -125,7 +127,7 @@ func (h *Handler) handleDescribeGroupMembership(ctx context.Context, c *echo.Con func (h *Handler) handleListGroupMemberships(ctx context.Context, c *echo.Context, body []byte) error { var req listGroupMembershipsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -152,7 +154,7 @@ func (h *Handler) handleListGroupMemberships(ctx context.Context, c *echo.Contex func (h *Handler) handleDeleteGroupMembership(ctx context.Context, c *echo.Context, body []byte) error { var req deleteGroupMembershipRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -173,7 +175,7 @@ func (h *Handler) handleDeleteGroupMembership(ctx context.Context, c *echo.Conte func (h *Handler) handleGetGroupMembershipID(ctx context.Context, c *echo.Context, body []byte) error { var req getGroupMembershipIDRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -202,7 +204,7 @@ func (h *Handler) handleGetGroupMembershipID(ctx context.Context, c *echo.Contex func (h *Handler) handleListGroupMembershipsForMember(ctx context.Context, c *echo.Context, body []byte) error { var req listGroupMembershipsForMemberRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -229,7 +231,7 @@ func (h *Handler) handleListGroupMembershipsForMember(ctx context.Context, c *ec func (h *Handler) handleIsMemberInGroups(ctx context.Context, c *echo.Context, body []byte) error { var req isMemberInGroupsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/identitystore/handler_groups.go b/services/identitystore/handler_groups.go index 23253dd6e0..68fc6cbb66 100644 --- a/services/identitystore/handler_groups.go +++ b/services/identitystore/handler_groups.go @@ -2,11 +2,13 @@ package identitystore import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -56,7 +58,7 @@ type deleteGroupRequest struct { func (h *Handler) handleCreateGroup(ctx context.Context, c *echo.Context, body []byte) error { var req createGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -84,7 +86,7 @@ func (h *Handler) handleCreateGroup(ctx context.Context, c *echo.Context, body [ func (h *Handler) handleDescribeGroup(ctx context.Context, c *echo.Context, body []byte) error { var req describeGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -107,7 +109,7 @@ func (h *Handler) handleDescribeGroup(ctx context.Context, c *echo.Context, body //nolint:dupl // structurally parallel to handleListUsers; both validate MaxResults, filter, paginate func (h *Handler) handleListGroups(ctx context.Context, c *echo.Context, body []byte) error { var req listGroupsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -135,7 +137,7 @@ func (h *Handler) handleListGroups(ctx context.Context, c *echo.Context, body [] func (h *Handler) handleUpdateGroup(ctx context.Context, c *echo.Context, body []byte) error { var req updateGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -160,7 +162,7 @@ func (h *Handler) handleUpdateGroup(ctx context.Context, c *echo.Context, body [ func (h *Handler) handleDeleteGroup(ctx context.Context, c *echo.Context, body []byte) error { var req deleteGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/identitystore/handler_guard_test.go b/services/identitystore/handler_guard_test.go index fbd0dce956..180b04eba9 100644 --- a/services/identitystore/handler_guard_test.go +++ b/services/identitystore/handler_guard_test.go @@ -1,13 +1,14 @@ package identitystore_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/identitystore" ) @@ -303,7 +304,7 @@ func TestRequireIdentityStoreIDGuardReadsSingleWellFormedBody(t *testing.T) { var resp map[string]any require.NoError( t, - json.Unmarshal(rec.Body.Bytes(), &resp), + json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()), "response body must be a single well-formed JSON document, not two writes concatenated: %s", rec.Body.String(), ) diff --git a/services/identitystore/handler_test.go b/services/identitystore/handler_test.go index 024d1261e2..6acc68ac91 100644 --- a/services/identitystore/handler_test.go +++ b/services/identitystore/handler_test.go @@ -2,7 +2,7 @@ package identitystore_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/identitystore" ) @@ -37,7 +38,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -58,7 +59,7 @@ func parseResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -179,7 +180,7 @@ func TestExtractOperationAndResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) diff --git a/services/identitystore/handler_users.go b/services/identitystore/handler_users.go index 7b60c439a2..98b812f4fb 100644 --- a/services/identitystore/handler_users.go +++ b/services/identitystore/handler_users.go @@ -2,11 +2,13 @@ package identitystore import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -82,7 +84,7 @@ type listUsersRequest struct { func (h *Handler) handleCreateUser(ctx context.Context, c *echo.Context, body []byte) error { var req createUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -121,7 +123,7 @@ func (h *Handler) handleCreateUser(ctx context.Context, c *echo.Context, body [] func (h *Handler) handleDescribeUser(ctx context.Context, c *echo.Context, body []byte) error { var req describeUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -144,7 +146,7 @@ func (h *Handler) handleDescribeUser(ctx context.Context, c *echo.Context, body //nolint:dupl // structurally parallel to handleListGroups; both validate MaxResults, filter, paginate func (h *Handler) handleListUsers(ctx context.Context, c *echo.Context, body []byte) error { var req listUsersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -172,7 +174,7 @@ func (h *Handler) handleListUsers(ctx context.Context, c *echo.Context, body []b func (h *Handler) handleUpdateUser(ctx context.Context, c *echo.Context, body []byte) error { var req updateUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -197,7 +199,7 @@ func (h *Handler) handleUpdateUser(ctx context.Context, c *echo.Context, body [] func (h *Handler) handleDeleteUser(ctx context.Context, c *echo.Context, body []byte) error { var req deleteUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/identitystore/models.go b/services/identitystore/models.go index 09872ab585..f0b52becb9 100644 --- a/services/identitystore/models.go +++ b/services/identitystore/models.go @@ -1,10 +1,11 @@ package identitystore import ( - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---------------------------------------- @@ -23,13 +24,13 @@ type epochTime time.Time // MarshalJSON renders t as AWS JSON-protocol epoch seconds. func (t epochTime) MarshalJSON() ([]byte, error) { - return json.Marshal(awstime.Epoch(time.Time(t))) + return json.Marshal(awstime.Epoch(time.Time(t)), jsonx.V1()) } // UnmarshalJSON parses AWS JSON-protocol epoch seconds back into t. func (t *epochTime) UnmarshalJSON(data []byte) error { var seconds float64 - if err := json.Unmarshal(data, &seconds); err != nil { + if err := json.Unmarshal(data, &seconds, jsonx.V1()); err != nil { return err } diff --git a/services/identitystore/persistence.go b/services/identitystore/persistence.go index f3eee1f31c..2baeda14db 100644 --- a/services/identitystore/persistence.go +++ b/services/identitystore/persistence.go @@ -2,7 +2,7 @@ package identitystore import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -49,11 +49,11 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Counter int `json:"counter"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Counter int `json:"counter"` + Version int `json:"version"` } // persistenceDTOTables groups every ephemeral DTO table @@ -169,7 +169,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { diff --git a/services/inspector2/handler.go b/services/inspector2/handler.go index 7c8c6b3237..c11209e6ea 100644 --- a/services/inspector2/handler.go +++ b/services/inspector2/handler.go @@ -1,7 +1,7 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -390,7 +391,7 @@ func decodeFilterListRequest(c *echo.Context, maxResultsLimit int32) (filterList } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { _ = c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) return req, false diff --git a/services/inspector2/handler_cis_scans.go b/services/inspector2/handler_cis_scans.go index 7b282ed8b5..bc812b670b 100644 --- a/services/inspector2/handler_cis_scans.go +++ b/services/inspector2/handler_cis_scans.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -58,7 +59,7 @@ func (h *Handler) handleCreateCisScanConfiguration(c *echo.Context) error { SecurityLevel string `json:"securityLevel"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -89,7 +90,7 @@ func (h *Handler) handleDeleteCisScanConfiguration(c *echo.Context) error { ScanConfigurationArn string `json:"scanConfigurationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -114,7 +115,7 @@ func (h *Handler) handleUpdateCisScanConfiguration(c *echo.Context) error { SecurityLevel string `json:"securityLevel"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -171,7 +172,7 @@ func (h *Handler) handleStartCisSession(c *echo.Context) error { ScanJobID string `json:"scanJobId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -199,7 +200,7 @@ func (h *Handler) handleStopCisSession(c *echo.Context) error { ScanJobID string `json:"scanJobId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -221,7 +222,7 @@ func (h *Handler) handleSendCisSessionHealth(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -255,7 +256,7 @@ func (h *Handler) handleSendCisSessionTelemetry(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -281,7 +282,7 @@ func (h *Handler) handleGetCisScanReport(c *echo.Context) error { ReportFormat string `json:"reportFormat"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -314,7 +315,7 @@ func (h *Handler) handleGetCisScanResultDetails(c *echo.Context) error { MaxResults int32 `json:"maxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -415,7 +416,7 @@ func (h *Handler) listCisAggregation(c *echo.Context, l cisAggregationListing) e MaxResults int32 `json:"maxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_cis_scans_test.go b/services/inspector2/handler_cis_scans_test.go index c5b6175dc6..3101596ac8 100644 --- a/services/inspector2/handler_cis_scans_test.go +++ b/services/inspector2/handler_cis_scans_test.go @@ -5,13 +5,14 @@ package inspector2_test // canned data, and that unknown scan ARNs degrade benignly. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -27,7 +28,7 @@ func createCisConfig(t *testing.T, h *inspector2.Handler, name string, accountID require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["scanConfigurationArn"].(string) require.True(t, ok) require.NotEmpty(t, arn) @@ -43,7 +44,7 @@ func firstScanArn(t *testing.T, h *inspector2.Handler, cfgARN string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) scans, _ := resp["scans"].([]any) for _, raw := range scans { @@ -71,7 +72,7 @@ func TestCisScans_CreatedConfigMaterializesScan(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var empty map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty, jsonx.V1())) scans, _ := empty["scans"].([]any) assert.Empty(t, scans) @@ -79,7 +80,7 @@ func TestCisScans_CreatedConfigMaterializesScan(t *testing.T) { cfgARN := createCisConfig(t, h, "scan-a", []string{"111111111111"}) rec = auditDo(t, h, http.MethodPost, "/cis/scan/list", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &empty, jsonx.V1())) scans, _ = empty["scans"].([]any) require.Len(t, scans, 1) @@ -102,7 +103,7 @@ func TestCisScans_ResultDetailsReflectConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, _ := resp["scanResultDetails"].([]any) // Two target accounts x catalog checks => non-empty, and every result is @@ -137,7 +138,7 @@ func TestCisScans_ReportReflectsScan(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["status"]) assert.Equal(t, scanARN, resp["scanArn"]) // totalChecks reported as a JSON number. @@ -160,7 +161,7 @@ func TestCisScans_AggregationsConsistent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var byCheck map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byCheck)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byCheck, jsonx.V1())) checks, _ := byCheck["checkAggregations"].([]any) require.NotEmpty(t, checks) @@ -178,7 +179,7 @@ func TestCisScans_AggregationsConsistent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var byTarget map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byTarget)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &byTarget, jsonx.V1())) targets, _ := byTarget["targetResourceAggregations"].([]any) assert.Len(t, targets, 2) } @@ -198,7 +199,7 @@ func TestCisScans_DeleteConfigRemovesScans(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) scans, _ := resp["scans"].([]any) assert.Empty(t, scans) } @@ -227,7 +228,7 @@ func TestCisScans_UnknownScanArnDegradesBenignly(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp[tc.key] assert.True(t, ok) }) @@ -323,7 +324,7 @@ func TestCisScanConfigurationLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["scanConfigurationArn"]) }, }, @@ -336,7 +337,7 @@ func TestCisScanConfigurationLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) cfgs, _ := resp["scanConfigurations"].([]any) assert.Len(t, cfgs, 1) }, @@ -415,7 +416,7 @@ func TestCisScanConfigurationFullCycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) cfgARN, _ := createResp["scanConfigurationArn"].(string) require.NotEmpty(t, cfgARN) @@ -434,7 +435,7 @@ func TestCisScanConfigurationFullCycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) cfgs, _ := listResp["scanConfigurations"].([]any) assert.Empty(t, cfgs) } @@ -559,7 +560,7 @@ func TestCisSessionOps(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["status"]) }, }, @@ -572,7 +573,7 @@ func TestCisSessionOps(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) _, ok := resp["scanResultDetails"] assert.True(t, ok) }, @@ -586,7 +587,7 @@ func TestCisSessionOps(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) scans, _ := resp["scans"].([]any) assert.Empty(t, scans) }, @@ -600,7 +601,7 @@ func TestCisSessionOps(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) _, ok := resp["checkAggregations"] assert.True(t, ok) }, @@ -614,7 +615,7 @@ func TestCisSessionOps(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) _, ok := resp["targetResourceAggregations"] assert.True(t, ok) }, diff --git a/services/inspector2/handler_code_security.go b/services/inspector2/handler_code_security.go index 534a6cdced..d4daf8d4dd 100644 --- a/services/inspector2/handler_code_security.go +++ b/services/inspector2/handler_code_security.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -61,7 +62,7 @@ func (h *Handler) handleCreateCodeSecurityIntegration(c *echo.Context) error { Type string `json:"type"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -91,7 +92,7 @@ func (h *Handler) handleDeleteCodeSecurityIntegration(c *echo.Context) error { IntegrationArn string `json:"integrationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -115,7 +116,7 @@ func (h *Handler) handleGetCodeSecurityIntegration(c *echo.Context) error { IntegrationArn string `json:"integrationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -164,7 +165,7 @@ func (h *Handler) handleUpdateCodeSecurityIntegration(c *echo.Context) error { IntegrationArn string `json:"integrationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -226,7 +227,7 @@ func (h *Handler) handleCreateCodeSecurityScanConfiguration(c *echo.Context) err } `json:"configuration"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -252,7 +253,7 @@ func (h *Handler) handleDeleteCodeSecurityScanConfiguration(c *echo.Context) err ScanConfigurationArn string `json:"scanConfigurationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -277,7 +278,7 @@ func (h *Handler) handleGetCodeSecurityScanConfiguration(c *echo.Context) error ScanConfigurationArn string `json:"scanConfigurationArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -354,7 +355,7 @@ func (h *Handler) handleUpdateCodeSecurityScanConfiguration(c *echo.Context) err } `json:"configuration"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -483,7 +484,7 @@ func (h *Handler) handleBatchAssociateCodeSecurityScanConfiguration( AssociateConfigurationRequests []codeSecurityBatchItemRequest `json:"associateConfigurationRequests"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -554,7 +555,7 @@ func (h *Handler) handleBatchDisassociateCodeSecurityScanConfiguration( DisassociateConfigurationRequests []codeSecurityBatchItemRequest `json:"disassociateConfigurationRequests"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -594,7 +595,7 @@ func (h *Handler) handleListCodeSecurityScanConfigurationAssociations(c *echo.Co MaxResults int32 `json:"maxResults"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -637,7 +638,7 @@ func (h *Handler) handleStartCodeSecurityScan(c *echo.Context) error { } `json:"resource"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -667,7 +668,7 @@ func (h *Handler) handleGetCodeSecurityScan(c *echo.Context) error { ScanID string `json:"scanId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_code_security_test.go b/services/inspector2/handler_code_security_test.go index a93d07dbd0..43ec4ac15d 100644 --- a/services/inspector2/handler_code_security_test.go +++ b/services/inspector2/handler_code_security_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -25,7 +26,7 @@ func TestCodeSecurityIntegrationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) integARN, _ := createResp["integrationArn"].(string) require.NotEmpty(t, integARN) assert.Equal(t, "ACTIVE", createResp["status"]) @@ -37,7 +38,7 @@ func TestCodeSecurityIntegrationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, integARN, getResp["integrationArn"]) // List @@ -45,7 +46,7 @@ func TestCodeSecurityIntegrationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) integrations, _ := listResp["integrations"].([]any) assert.Len(t, integrations, 1) @@ -132,7 +133,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) cfgARN, _ := createResp["scanConfigurationArn"].(string) require.NotEmpty(t, cfgARN) @@ -143,7 +144,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "ACCOUNT", getResp["level"]) assert.NotContains(t, getResp, "status") configuration, ok := getResp["configuration"].(map[string]any) @@ -155,7 +156,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) cfgs, _ := listResp["configurations"].([]any) require.Len(t, cfgs, 1) summary, ok := cfgs[0].(map[string]any) @@ -191,7 +192,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var batchAssocResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchAssocResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchAssocResp, jsonx.V1())) successful, _ := batchAssocResp["successfulAssociations"].([]any) assert.Len(t, successful, 1) @@ -202,7 +203,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp, jsonx.V1())) assocs, _ := assocResp["associations"].([]any) assert.Len(t, assocs, 1) @@ -224,7 +225,7 @@ func TestCodeSecurityScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var assocResp2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp2, jsonx.V1())) assocs2, _ := assocResp2["associations"].([]any) assert.Empty(t, assocs2) @@ -380,7 +381,7 @@ func TestCodeSecurityScanConfigurationValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) cfgARN, _ := createResp["scanConfigurationArn"].(string) require.NotEmpty(t, cfgARN) @@ -403,7 +404,7 @@ func TestCodeSecurityScanLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) scanID, _ := startResp["scanId"].(string) require.NotEmpty(t, scanID) @@ -414,7 +415,7 @@ func TestCodeSecurityScanLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, scanID, getResp["scanId"]) } @@ -505,7 +506,7 @@ func TestConnectorLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -537,7 +538,7 @@ func TestConnectorLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["items"].([]any) assert.Len(t, items, 1) @@ -553,7 +554,7 @@ func TestConnectorLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, rec2.Body.String()) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) items2, _ := resp2["items"].([]any) assert.Empty(t, items2) }, @@ -572,12 +573,12 @@ func TestConnectorLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, connectorArn, resp["connectorArn"]) listRec := auditDo(t, h, http.MethodPost, "/connector/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["items"].([]any) require.Len(t, items, 1) @@ -612,7 +613,7 @@ func TestConnectorLifecycle(t *testing.T) { listRec := auditDo(t, h, http.MethodPost, "/connector/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp["items"].([]any)) }, }, @@ -693,7 +694,7 @@ func TestConnectorScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) cfgs, ok := listResp["scanConfigurations"].([]any) require.True(t, ok) require.Len(t, cfgs, 1) @@ -739,7 +740,7 @@ func TestConnectorScanConfigurationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfgs, _ := resp["scanConfigurations"].([]any) require.Len(t, cfgs, 1) assert.Equal(t, arnA, cfgs[0].(map[string]any)["awsConfigConnectorArn"]) diff --git a/services/inspector2/handler_connectors.go b/services/inspector2/handler_connectors.go index 6861ff880d..b238162dff 100644 --- a/services/inspector2/handler_connectors.go +++ b/services/inspector2/handler_connectors.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -98,7 +99,7 @@ func (h *Handler) handleCreateConnector(c *echo.Context) error { } var req createConnectorRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) } @@ -152,7 +153,7 @@ func (h *Handler) handleUpdateConnector(c *echo.Context) error { } var req updateConnectorRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) } @@ -190,7 +191,7 @@ func (h *Handler) handleDeleteConnector(c *echo.Context) error { ConnectorArn string `json:"connectorArn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) } @@ -405,7 +406,7 @@ func decodeListConnectorsRequest(c *echo.Context) (listConnectorsRequest, bool) } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { _ = c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) return req, false @@ -479,7 +480,7 @@ func (h *Handler) handleListConnectorScanConfigurations(c *echo.Context) error { var req listConnectorScanConfigurationsRequest if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) } } @@ -533,7 +534,7 @@ func (h *Handler) handleUpdateConnectorScanConfiguration(c *echo.Context) error } var req updateConnectorScanConfigurationRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse(errValidation, "invalid JSON")) } diff --git a/services/inspector2/handler_coverage_reporting.go b/services/inspector2/handler_coverage_reporting.go index 2ab081bcec..81142c5cdd 100644 --- a/services/inspector2/handler_coverage_reporting.go +++ b/services/inspector2/handler_coverage_reporting.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -90,7 +91,7 @@ func (h *Handler) handleListCoverageStatistics(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_coverage_reporting_test.go b/services/inspector2/handler_coverage_reporting_test.go index 9da706e235..7e98228367 100644 --- a/services/inspector2/handler_coverage_reporting_test.go +++ b/services/inspector2/handler_coverage_reporting_test.go @@ -1,7 +1,7 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -20,7 +21,7 @@ func TestListCoverageEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, ok := resp["coveredResources"].([]any) require.True(t, ok) assert.Empty(t, resources) @@ -53,7 +54,7 @@ func TestListCoverageSeeded(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, ok := resp["coveredResources"].([]any) require.True(t, ok) require.Len(t, resources, 2) @@ -71,7 +72,7 @@ func TestListCoverageSeeded(t *testing.T) { }, }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, ok = resp["coveredResources"].([]any) require.True(t, ok) require.Len(t, resources, 1) @@ -106,7 +107,7 @@ func TestListCoverageStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InDelta(t, float64(3), resp["totalCounts"], 0) groups, ok := resp["countsByGroup"].([]any) require.True(t, ok) @@ -117,7 +118,7 @@ func TestListCoverageStatistics(t *testing.T) { "groupBy": "RESOURCE_TYPE", }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InDelta(t, float64(3), resp["totalCounts"], 0) groups, ok = resp["countsByGroup"].([]any) @@ -231,7 +232,7 @@ func TestListCoverage_FilterCriteriaFacets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, ok := resp["coveredResources"].([]any) require.True(t, ok) require.Len(t, resources, 1) diff --git a/services/inspector2/handler_ec2_configuration.go b/services/inspector2/handler_ec2_configuration.go index 55a53aa2b9..c5d2d04398 100644 --- a/services/inspector2/handler_ec2_configuration.go +++ b/services/inspector2/handler_ec2_configuration.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -49,7 +50,7 @@ func (h *Handler) handleUpdateEc2DeepInspectionConfiguration(c *echo.Context) er } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -85,7 +86,7 @@ func (h *Handler) handleUpdateOrgEc2DeepInspectionConfiguration(c *echo.Context) } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -111,7 +112,7 @@ func (h *Handler) handleBatchGetMemberEc2DeepInspectionStatus(c *echo.Context) e } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -141,7 +142,7 @@ func (h *Handler) handleBatchUpdateMemberEc2DeepInspectionStatus(c *echo.Context } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_ec2_configuration_test.go b/services/inspector2/handler_ec2_configuration_test.go index 935b035207..77b8c98d0d 100644 --- a/services/inspector2/handler_ec2_configuration_test.go +++ b/services/inspector2/handler_ec2_configuration_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEc2DeepInspectionConfiguration(t *testing.T) { @@ -36,7 +38,7 @@ func TestEc2DeepInspectionConfiguration(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) _, ok := resp["status"] assert.True(t, ok) }, @@ -50,7 +52,7 @@ func TestEc2DeepInspectionConfiguration(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) paths, _ := resp["packagePaths"].([]any) assert.Len(t, paths, 2) }, @@ -79,7 +81,7 @@ func TestEc2DeepInspectionConfiguration(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) members, _ := resp["accountIds"].([]any) assert.Len(t, members, 1) }, @@ -100,7 +102,7 @@ func TestEc2DeepInspectionConfiguration(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) accounts, _ := resp["accountIds"].([]any) assert.Len(t, accounts, 1) }, diff --git a/services/inspector2/handler_ecr_configuration.go b/services/inspector2/handler_ecr_configuration.go index 47e53c0f36..aa2d71d0cc 100644 --- a/services/inspector2/handler_ecr_configuration.go +++ b/services/inspector2/handler_ecr_configuration.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -32,7 +33,7 @@ func (h *Handler) handleGetClustersForImage(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_ecr_configuration_test.go b/services/inspector2/handler_ecr_configuration_test.go index fab46cc0f3..811c78b1ae 100644 --- a/services/inspector2/handler_ecr_configuration_test.go +++ b/services/inspector2/handler_ecr_configuration_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetClustersForImage exercises the fixed request shape: real @@ -24,7 +26,7 @@ func TestGetClustersForImage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["cluster"] assert.True(t, ok) } diff --git a/services/inspector2/handler_enablement.go b/services/inspector2/handler_enablement.go index 1bc1177837..1d07e0857c 100644 --- a/services/inspector2/handler_enablement.go +++ b/services/inspector2/handler_enablement.go @@ -1,7 +1,7 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "regexp" "slices" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -35,7 +36,7 @@ func (h *Handler) handleToggle(c *echo.Context, enable bool) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -123,7 +124,7 @@ func (h *Handler) handleBatchGetAccountStatus(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } @@ -196,7 +197,7 @@ func (h *Handler) handleGetConfiguration(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } } @@ -245,7 +246,7 @@ func (h *Handler) handleUpdateConfiguration(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -293,7 +294,7 @@ func (h *Handler) handleListAccountPermissions(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_enablement_test.go b/services/inspector2/handler_enablement_test.go index e577802608..fefed7d48f 100644 --- a/services/inspector2/handler_enablement_test.go +++ b/services/inspector2/handler_enablement_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -29,7 +30,7 @@ func TestEnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts, ok := resp["accounts"].([]any) require.True(t, ok) require.Len(t, accounts, 1) @@ -54,7 +55,7 @@ func TestEnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts, ok := resp["accounts"].([]any) require.True(t, ok) require.Len(t, accounts, 1) @@ -98,7 +99,7 @@ func TestBatchGetAccountStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts, ok := resp["accounts"].([]any) require.True(t, ok) require.Len(t, accounts, 1) @@ -119,7 +120,7 @@ func TestBatchGetAccountStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts := resp["accounts"].([]any) acc := accounts[0].(map[string]any) state := acc["state"].(map[string]any) @@ -152,7 +153,7 @@ func TestConfigurationGetUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasEC2 := resp["ec2Configuration"] assert.True(t, hasEC2) _, hasECR := resp["ecrConfiguration"] @@ -177,7 +178,7 @@ func TestConfigurationGetUpdate(t *testing.T) { // Verify via get getRec := auditDo(t, h, http.MethodPost, "/configuration/get", nil) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ec2Cfg := getResp["ec2Configuration"].(map[string]any) scanModeState := ec2Cfg["scanModeState"].(map[string]any) @@ -219,7 +220,7 @@ func TestAccountPermissions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) perms, ok := resp["permissions"].([]any) require.True(t, ok) @@ -244,7 +245,7 @@ func TestAccountPermissionsFilteredByService(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) perms, ok := resp["permissions"].([]any) require.True(t, ok) @@ -367,7 +368,7 @@ func TestEnableDisablePerResourceType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts := resp["accounts"].([]any) require.Len(t, accounts, 1) diff --git a/services/inspector2/handler_encryption.go b/services/inspector2/handler_encryption.go index 6f7c9c0a1f..cacb372695 100644 --- a/services/inspector2/handler_encryption.go +++ b/services/inspector2/handler_encryption.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -47,7 +48,7 @@ func (h *Handler) handleResetEncryptionKey(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -74,7 +75,7 @@ func (h *Handler) handleUpdateEncryptionKey(c *echo.Context) error { ScanType string `json:"scanType"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_encryption_test.go b/services/inspector2/handler_encryption_test.go index fd1f3ed103..4f249b92c8 100644 --- a/services/inspector2/handler_encryption_test.go +++ b/services/inspector2/handler_encryption_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEncryptionKeyLifecycle(t *testing.T) { @@ -36,7 +38,7 @@ func TestEncryptionKeyLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "AWS_OWNED_KEY", resp["kmsKeyId"]) }, }, diff --git a/services/inspector2/handler_filters.go b/services/inspector2/handler_filters.go index 0d7f8f6522..d7ed28d9c0 100644 --- a/services/inspector2/handler_filters.go +++ b/services/inspector2/handler_filters.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateFilter handles POST /filters/create. @@ -26,7 +27,7 @@ func (h *Handler) handleCreateFilter(c *echo.Context) error { Reason string `json:"reason"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -72,7 +73,7 @@ func (h *Handler) handleUpdateFilter(c *echo.Context) error { Name string `json:"name"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -109,7 +110,7 @@ func (h *Handler) handleDeleteFilter(c *echo.Context) error { Arn string `json:"arn"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -142,7 +143,7 @@ func (h *Handler) handleListFilters(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_filters_test.go b/services/inspector2/handler_filters_test.go index 3a807a37ac..f0590cb04b 100644 --- a/services/inspector2/handler_filters_test.go +++ b/services/inspector2/handler_filters_test.go @@ -1,7 +1,7 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -66,7 +67,7 @@ func TestFilterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) filters, ok := resp["filters"].([]any) require.True(t, ok) require.Len(t, filters, 1) @@ -89,7 +90,7 @@ func TestFilterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) filters := resp["filters"].([]any) require.Len(t, filters, 1) @@ -116,7 +117,7 @@ func TestFilterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) filters := resp["filters"].([]any) require.Len(t, filters, 1) @@ -139,13 +140,13 @@ func TestFilterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, filterARN, resp["arn"]) // Verify via list listRec := auditDo(t, h, http.MethodPost, "/filters/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) filters := listResp["filters"].([]any) require.Len(t, filters, 1) @@ -176,7 +177,7 @@ func TestFilterLifecycle(t *testing.T) { // Use a list check to verify filter was created listRec := auditDo(t, h, http.MethodPost, "/filters/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["filters"].([]any), 1) rec := auditDo(t, h, http.MethodPost, "/filters/delete", map[string]any{ @@ -186,7 +187,7 @@ func TestFilterLifecycle(t *testing.T) { listRec2 := auditDo(t, h, http.MethodPost, "/filters/list", map[string]any{}) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2, jsonx.V1())) assert.Empty(t, listResp2["filters"].([]any)) }, }, @@ -226,7 +227,7 @@ func TestFilterLifecycle(t *testing.T) { listRec := auditDo(t, h, http.MethodPost, "/filters/list", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) filters := listResp["filters"].([]any) require.Len(t, filters, 1) diff --git a/services/inspector2/handler_findings.go b/services/inspector2/handler_findings.go index 5299e98cb2..afe56d49b7 100644 --- a/services/inspector2/handler_findings.go +++ b/services/inspector2/handler_findings.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -186,7 +187,7 @@ func (h *Handler) handleCreateFindingsReport(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -215,7 +216,7 @@ func (h *Handler) handleCancelFindingsReport(c *echo.Context) error { ReportID string `json:"reportId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -237,7 +238,7 @@ func (h *Handler) handleGetFindingsReportStatus(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -286,7 +287,7 @@ func (h *Handler) handleListFindingAggregations(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -316,7 +317,7 @@ func (h *Handler) handleSearchVulnerabilities(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -404,7 +405,7 @@ func (h *Handler) handleBatchGetCodeSnippet(c *echo.Context) error { FindingArns []string `json:"findingArns"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -430,7 +431,7 @@ func (h *Handler) handleBatchGetFindingDetails(c *echo.Context) error { FindingArns []string `json:"findingArns"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_findings_core_test.go b/services/inspector2/handler_findings_core_test.go index a0cbb60c19..76c62c5ec7 100644 --- a/services/inspector2/handler_findings_core_test.go +++ b/services/inspector2/handler_findings_core_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -27,7 +28,7 @@ func TestListFindingsBasic(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, ok := resp["findings"] require.True(t, ok) require.NotNil(t, findings) @@ -379,7 +380,7 @@ func TestListFindingsResponseStructure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "findings", "response must have findings key") } diff --git a/services/inspector2/handler_findings_reports_test.go b/services/inspector2/handler_findings_reports_test.go index 62438032ad..eb3d1b275e 100644 --- a/services/inspector2/handler_findings_reports_test.go +++ b/services/inspector2/handler_findings_reports_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -28,7 +29,7 @@ func TestFindingsReportLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) reportID, _ := createResp["reportId"].(string) require.NotEmpty(t, reportID) @@ -39,7 +40,7 @@ func TestFindingsReportLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var statusResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &statusResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &statusResp, jsonx.V1())) assert.Equal(t, reportID, statusResp["reportId"]) assert.Equal(t, "SUCCEEDED", statusResp["status"]) @@ -74,7 +75,7 @@ func TestFindingAggregations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["responses"] assert.True(t, ok) } @@ -106,7 +107,7 @@ func TestSearchVulnerabilities(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vulns, ok := resp["vulnerabilities"].([]any) require.True(t, ok) @@ -134,7 +135,7 @@ func TestSearchVulnerabilitiesNoMatches(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vulns, ok := resp["vulnerabilities"].([]any) require.True(t, ok) @@ -161,7 +162,7 @@ func TestBatchGetCodeSnippet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["codeSnippetResults"].([]any) require.True(t, ok) @@ -207,7 +208,7 @@ func TestBatchGetFindingDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) details, ok := resp["findingDetails"].([]any) require.True(t, ok) diff --git a/services/inspector2/handler_members.go b/services/inspector2/handler_members.go index aa25e8fd2c..2eaf30b7bc 100644 --- a/services/inspector2/handler_members.go +++ b/services/inspector2/handler_members.go @@ -1,13 +1,14 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -32,7 +33,7 @@ func (h *Handler) handleAssociateMember(c *echo.Context) error { AccountID string `json:"accountId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -56,7 +57,7 @@ func (h *Handler) handleDisassociateMember(c *echo.Context) error { AccountID string `json:"accountId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -77,7 +78,7 @@ func (h *Handler) handleGetMember(c *echo.Context) error { AccountID string `json:"accountId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -116,7 +117,7 @@ func (h *Handler) handleListMembers(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_members_test.go b/services/inspector2/handler_members_test.go index ba92c735ed..9e52bb1dd1 100644 --- a/services/inspector2/handler_members_test.go +++ b/services/inspector2/handler_members_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestMembersLifecycle(t *testing.T) { @@ -36,7 +38,7 @@ func TestMembersLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "111111111111", resp["accountId"]) }, }, @@ -64,7 +66,7 @@ func TestMembersLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) m, _ := resp["member"].(map[string]any) assert.Equal(t, "222222222222", m["accountId"]) }, @@ -78,7 +80,7 @@ func TestMembersLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) members, _ := resp["members"].([]any) assert.Len(t, members, 1) }, diff --git a/services/inspector2/handler_organization.go b/services/inspector2/handler_organization.go index a6dbb3d0cb..23f1d0a9f7 100644 --- a/services/inspector2/handler_organization.go +++ b/services/inspector2/handler_organization.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -40,7 +41,7 @@ func (h *Handler) handleEnableDelegatedAdminAccount(c *echo.Context) error { ClientToken string `json:"clientToken"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -73,7 +74,7 @@ func (h *Handler) handleDisableDelegatedAdminAccount(c *echo.Context) error { DelegatedAdminAccountID string `json:"delegatedAdminAccountId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -148,7 +149,7 @@ func (h *Handler) handleUpdateOrganizationConfiguration(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), diff --git a/services/inspector2/handler_organization_test.go b/services/inspector2/handler_organization_test.go index 7c36eed66c..a386c90c6d 100644 --- a/services/inspector2/handler_organization_test.go +++ b/services/inspector2/handler_organization_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDelegatedAdminAccountLifecycle(t *testing.T) { @@ -36,7 +38,7 @@ func TestDelegatedAdminAccountLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "333333333333", resp["delegatedAdminAccountId"]) assert.Equal(t, "ENABLED", resp["status"]) }, @@ -50,7 +52,7 @@ func TestDelegatedAdminAccountLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) d, _ := resp["delegatedAdmin"].(map[string]any) assert.Equal(t, "333333333333", d["accountId"]) }, @@ -64,7 +66,7 @@ func TestDelegatedAdminAccountLifecycle(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) admins, _ := resp["delegatedAdminAccounts"].([]any) assert.Len(t, admins, 1) }, @@ -150,7 +152,7 @@ func TestOrganizationConfiguration(t *testing.T) { t.Helper() assert.Equal(t, http.StatusOK, code) var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) _, ok := resp["autoEnable"] assert.True(t, ok) }, diff --git a/services/inspector2/handler_sbom.go b/services/inspector2/handler_sbom.go index a40b3346cb..a44d611ba9 100644 --- a/services/inspector2/handler_sbom.go +++ b/services/inspector2/handler_sbom.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -36,7 +37,7 @@ func (h *Handler) handleCreateSbomExport(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -62,7 +63,7 @@ func (h *Handler) handleCancelSbomExport(c *echo.Context) error { ReportID string `json:"reportId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } @@ -83,7 +84,7 @@ func (h *Handler) handleGetSbomExport(c *echo.Context) error { ReportID string `json:"reportId"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_sbom_test.go b/services/inspector2/handler_sbom_test.go index 3989d0f6f7..b0a4e0e53e 100644 --- a/services/inspector2/handler_sbom_test.go +++ b/services/inspector2/handler_sbom_test.go @@ -1,12 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSbomExportLifecycle(t *testing.T) { @@ -28,7 +30,7 @@ func TestSbomExportLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) reportID, _ := createResp["reportId"].(string) require.NotEmpty(t, reportID) @@ -39,7 +41,7 @@ func TestSbomExportLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["status"]) assert.Equal(t, "CYCLONEDX_1_4", getResp["format"]) diff --git a/services/inspector2/handler_tags.go b/services/inspector2/handler_tags.go index d97c85c755..3a75aa2584 100644 --- a/services/inspector2/handler_tags.go +++ b/services/inspector2/handler_tags.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleListTagsForResource handles GET /tags/{resourceArn}. @@ -50,7 +51,7 @@ func (h *Handler) handleTagResource(c *echo.Context) error { Tags map[string]string `json:"tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_tags_test.go b/services/inspector2/handler_tags_test.go index 155a0ee66f..455e81a6a2 100644 --- a/services/inspector2/handler_tags_test.go +++ b/services/inspector2/handler_tags_test.go @@ -1,7 +1,7 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -40,7 +41,7 @@ func TestTagsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "security", tags["team"]) @@ -72,7 +73,7 @@ func TestTagsLifecycle(t *testing.T) { listRec := auditDo(t, h, http.MethodGet, "/tags/"+filterARN, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].(map[string]any) assert.Equal(t, "yes", tags["keep"]) _, hasRemove := tags["remove"] @@ -122,7 +123,7 @@ func TestTagsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code, listRec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].(map[string]any) assert.Empty(t, tags) }, diff --git a/services/inspector2/handler_test.go b/services/inspector2/handler_test.go index eed8c2e36a..956e160b76 100644 --- a/services/inspector2/handler_test.go +++ b/services/inspector2/handler_test.go @@ -8,7 +8,7 @@ package inspector2_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -56,7 +57,7 @@ func auditDo(t *testing.T, h *inspector2.Handler, method, path string, body any) if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -82,7 +83,7 @@ func auditCreateFilter(t *testing.T, h *inspector2.Handler, name string) string require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["arn"].(string) require.True(t, ok) require.NotEmpty(t, arn) @@ -95,7 +96,7 @@ func auditCreateFilter(t *testing.T, h *inspector2.Handler, name string) string func inspector2UnmarshalError(t *testing.T, data []byte, v any) error { t.Helper() - return json.Unmarshal(data, v) + return json.Unmarshal(data, v, jsonx.V1()) } // auditCreateConnector creates an Azure connector named name, associated @@ -116,7 +117,7 @@ func auditCreateConnector(t *testing.T, h *inspector2.Handler, name, awsConfigCo require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, ok := resp["connectorArn"].(string) require.True(t, ok) require.NotEmpty(t, arn) @@ -149,7 +150,7 @@ func parityDo(t *testing.T, h *inspector2.Handler, method, path string, body any if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -185,7 +186,7 @@ func parityListFindings(t *testing.T, h *inspector2.Handler, body map[string]any require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, ok := resp["findings"].([]any) if !ok { @@ -205,7 +206,7 @@ func parityListFindingsWithToken( require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["findings"].([]any) nextToken, _ := resp["nextToken"].(string) diff --git a/services/inspector2/handler_usage.go b/services/inspector2/handler_usage.go index 4fea58a369..c520724591 100644 --- a/services/inspector2/handler_usage.go +++ b/services/inspector2/handler_usage.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -32,7 +33,7 @@ func (h *Handler) handleListUsageTotals(c *echo.Context) error { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON( http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON"), @@ -60,7 +61,7 @@ func (h *Handler) handleBatchGetFreeTrialInfo(c *echo.Context) error { AccountIDs []string `json:"accountIds"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return c.JSON(http.StatusBadRequest, errorResponse("ValidationException", "invalid JSON")) } diff --git a/services/inspector2/handler_usage_test.go b/services/inspector2/handler_usage_test.go index 3677fda903..798e80f8cd 100644 --- a/services/inspector2/handler_usage_test.go +++ b/services/inspector2/handler_usage_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -21,7 +22,7 @@ func TestUsageTotals(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) totals, ok := resp["totals"].([]any) require.True(t, ok) require.Len(t, totals, 1) @@ -56,7 +57,7 @@ func TestUsageTotalsReflectsEnabledCoverage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) totals, ok := resp["totals"].([]any) require.True(t, ok) require.Len(t, totals, 1) @@ -84,7 +85,7 @@ func TestBatchGetFreeTrialInfo(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accounts, _ := resp["accounts"].([]any) assert.Len(t, accounts, 1) } diff --git a/services/inspector2/paging.go b/services/inspector2/paging.go index 297a3f6741..0683290e8b 100644 --- a/services/inspector2/paging.go +++ b/services/inspector2/paging.go @@ -1,12 +1,13 @@ package inspector2 import ( - "encoding/json" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const defaultPageSize = 100 @@ -30,7 +31,7 @@ func readPageRequest(c *echo.Context) (pageRequest, error) { } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return req, fmt.Errorf("%w: invalid JSON", ErrValidation) } } diff --git a/services/inspector2/persistence.go b/services/inspector2/persistence.go index c091672cfe..67fbdc2dbd 100644 --- a/services/inspector2/persistence.go +++ b/services/inspector2/persistence.go @@ -2,10 +2,12 @@ package inspector2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -79,7 +81,7 @@ const findingsTableName = "findings" // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` EnabledTypes map[string]bool `json:"enabledTypes"` MemberEnabled map[string]map[string]bool `json:"memberEnabled,omitempty"` @@ -121,7 +123,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { dtos[i] = toFindingSnapshot(f) } - findingsData, err := json.Marshal(dtos) + findingsData, err := json.Marshal(dtos, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "inspector2: snapshot findings table marshal failed", "error", err) @@ -194,7 +196,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { if hasFindings { var dtos []*findingSnapshot - if err := json.Unmarshal(findingsRaw, &dtos); err != nil { + if err := json.Unmarshal(findingsRaw, &dtos, jsonx.V1()); err != nil { return fmt.Errorf("inspector2: restore findings table: %w", err) } diff --git a/services/inspector2/required_output_members_test.go b/services/inspector2/required_output_members_test.go index 122e316d00..43a23682fd 100644 --- a/services/inspector2/required_output_members_test.go +++ b/services/inspector2/required_output_members_test.go @@ -1,7 +1,7 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/inspector2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestUpdateOrganizationConfiguration_AutoEnableAlwaysPresent proves @@ -53,6 +55,6 @@ func TestUpdateOrganizationConfiguration_MissingAutoEnableRejected(t *testing.T) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } diff --git a/services/inspector2/wire_field_fixes_y1zn_test.go b/services/inspector2/wire_field_fixes_y1zn_test.go index b9ccda981b..94cde9bb57 100644 --- a/services/inspector2/wire_field_fixes_y1zn_test.go +++ b/services/inspector2/wire_field_fixes_y1zn_test.go @@ -1,13 +1,14 @@ package inspector2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/inspector2" ) @@ -76,7 +77,7 @@ func TestListFindingAggregations_NoLowKey_RealClient(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) responses, ok := out["responses"].([]any) require.True(t, ok) require.NotEmpty(t, responses) diff --git a/services/iot/authorizer_invoke.go b/services/iot/authorizer_invoke.go index 8300b8a44a..3ebfda334f 100644 --- a/services/iot/authorizer_invoke.go +++ b/services/iot/authorizer_invoke.go @@ -7,7 +7,8 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "errors" "fmt" @@ -15,6 +16,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -99,11 +101,11 @@ type authorizerMQTTData struct { } type authorizerResponse struct { - DisconnectAfterInSeconds *int64 `json:"disconnectAfterInSeconds"` - RefreshAfterInSeconds *int64 `json:"refreshAfterInSeconds"` - PrincipalID string `json:"principalId"` - PolicyDocuments []json.RawMessage `json:"policyDocuments"` - IsAuthenticated bool `json:"isAuthenticated"` + DisconnectAfterInSeconds *int64 `json:"disconnectAfterInSeconds"` + RefreshAfterInSeconds *int64 `json:"refreshAfterInSeconds"` + PrincipalID string `json:"principalId"` + PolicyDocuments []jsontext.Value `json:"policyDocuments"` + IsAuthenticated bool `json:"isAuthenticated"` } // TestInvokeAuthorizer invokes the authorizer's Lambda function with the request. @@ -166,7 +168,7 @@ func (b *InMemoryBackend) InvokeAuthorizer( return nil, fmt.Errorf("%w: %w", errRuleActionDenied, err) } - payload, err := json.Marshal(buildAuthorizerEvent(req, verified)) + payload, err := json.Marshal(buildAuthorizerEvent(req, verified), jsonx.V1()) if err != nil { return nil, fmt.Errorf("authorizer event: %w", err) } @@ -247,7 +249,7 @@ func verifyTokenSignature(keys map[string]string, req *AuthorizerRequest) bool { func parseAuthorizerResponse(raw []byte) (*TestInvokeAuthorizerOutput, error) { var resp authorizerResponse - if err := json.Unmarshal(raw, &resp); err != nil { + if err := json.Unmarshal(raw, &resp, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: not a JSON object", ErrInvalidAuthorizerResponse) } @@ -269,7 +271,7 @@ func parseAuthorizerResponse(raw []byte) (*TestInvokeAuthorizerOutput, error) { doc := string(d) var asString string - if json.Unmarshal(d, &asString) == nil { + if json.Unmarshal(d, &asString, jsonx.V1()) == nil { doc = asString } diff --git a/services/iot/broker_auth.go b/services/iot/broker_auth.go index 08c8e28526..0b991fecbe 100644 --- a/services/iot/broker_auth.go +++ b/services/iot/broker_auth.go @@ -9,7 +9,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -23,6 +23,7 @@ import ( "github.com/mochi-mqtt/server/v2/packets" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -325,7 +326,7 @@ func (b *InMemoryBackend) thingGroupARNsLocked(thingName string) []string { } func jsonEscape(v string) string { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil || len(raw) < 2 { return "" } diff --git a/services/iot/broker_commands.go b/services/iot/broker_commands.go index d5927f45b1..30a90515ba 100644 --- a/services/iot/broker_commands.go +++ b/services/iot/broker_commands.go @@ -1,9 +1,11 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "errors" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -77,7 +79,7 @@ func (b *Broker) handleCommandResponse(r commandResponse, payload []byte) { } reply := func(outcome string, body map[string]any) { - out, err := json.Marshal(body) + out, err := json.Marshal(body, jsonx.V1()) if err != nil { return } @@ -101,7 +103,7 @@ func (b *Broker) handleCommandResponse(r commandResponse, payload []byte) { } var body commandResponseBody - if err := json.Unmarshal(payload, &body); err != nil { + if err := json.Unmarshal(payload, &body, jsonx.V1()); err != nil { reject(jobsCodeInvalidJSON, "payload is not valid JSON", "") return diff --git a/services/iot/broker_custom_auth_test.go b/services/iot/broker_custom_auth_test.go index e0dad7d18a..ac8326faef 100644 --- a/services/iot/broker_custom_auth_test.go +++ b/services/iot/broker_custom_auth_test.go @@ -9,7 +9,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "net/url" @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -40,7 +41,7 @@ type fakeAuthLambda struct { func (f *fakeAuthLambda) RequestLambda(_ context.Context, _, _ string, payload []byte) ([]byte, error) { var ev map[string]any - if err := json.Unmarshal(payload, &ev); err != nil { + if err := json.Unmarshal(payload, &ev, jsonx.V1()); err != nil { return nil, err } @@ -49,7 +50,7 @@ func (f *fakeAuthLambda) RequestLambda(_ context.Context, _, _ string, payload [ respond := f.respond f.mu.Unlock() - return json.Marshal(respond(ev)) + return json.Marshal(respond(ev), jsonx.V1()) } func (f *fakeAuthLambda) calls() []map[string]any { @@ -68,7 +69,7 @@ func (f *fakeAuthLambda) setRespond(r func(map[string]any) any) { func authzResponse(principal string, refresh, disconnect int, statements ...string) map[string]any { var doc any - _ = json.Unmarshal([]byte(authPolicy(statements...)), &doc) + _ = json.Unmarshal([]byte(authPolicy(statements...)), &doc, jsonx.V1()) out := map[string]any{"isAuthenticated": true, "principalId": principal, "policyDocuments": []any{doc}} if refresh > 0 { diff --git a/services/iot/broker_events.go b/services/iot/broker_events.go index 71f20dab72..2b9e614e16 100644 --- a/services/iot/broker_events.go +++ b/services/iot/broker_events.go @@ -1,13 +1,15 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "strings" "sync/atomic" "github.com/google/uuid" mqtt "github.com/mochi-mqtt/server/v2" "github.com/mochi-mqtt/server/v2/packets" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -41,7 +43,7 @@ func lifecycleEligible(clientID string) bool { } func (b *Broker) publishLifecycle(topic string, payload map[string]any) { - raw, err := json.Marshal(payload) + raw, err := json.Marshal(payload, jsonx.V1()) if err != nil { return } diff --git a/services/iot/broker_events_test.go b/services/iot/broker_events_test.go index 5df3d3e3cc..6172551ccc 100644 --- a/services/iot/broker_events_test.go +++ b/services/iot/broker_events_test.go @@ -1,7 +1,7 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -79,7 +80,7 @@ func (w *eventWatcher) next(t *testing.T, topic string) map[string]any { } var out map[string]any - require.NoError(t, json.Unmarshal(m.Payload(), &out)) + require.NoError(t, json.Unmarshal(m.Payload(), &out, jsonx.V1())) return out case <-timeout: @@ -174,7 +175,7 @@ func TestBrokerLifecycleEvents(t *testing.T) { select { case m := <-w.msgs: var p map[string]any - require.NoError(t, json.Unmarshal(m.Payload(), &p)) + require.NoError(t, json.Unmarshal(m.Payload(), &p, jsonx.V1())) switch { case p["clientId"] != "dev-dup": @@ -645,7 +646,7 @@ func TestBrokerConnectFailedEvent(t *testing.T) { assert.Equal(t, "$aws/events/presence/connect_failed/intruder", m.Topic()) var p map[string]any - require.NoError(t, json.Unmarshal(m.Payload(), &p)) + require.NoError(t, json.Unmarshal(m.Payload(), &p, jsonx.V1())) assert.Equal(t, "connect_failed", p["eventType"]) assert.Equal(t, "AUTHORIZATION_FAILED", p["connectFailureReason"]) assert.Equal(t, "intruder", p["clientId"]) diff --git a/services/iot/broker_jobs.go b/services/iot/broker_jobs.go index 8e8f9b55e9..7c52d227ba 100644 --- a/services/iot/broker_jobs.go +++ b/services/iot/broker_jobs.go @@ -1,11 +1,14 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -85,7 +88,7 @@ type jobsExecutionWire struct { JobID string `json:"jobId"` ThingName string `json:"thingName,omitempty"` Status JobExecutionStatus `json:"status,omitempty"` - JobDocument json.RawMessage `json:"jobDocument,omitempty"` + JobDocument jsontext.Value `json:"jobDocument,omitempty"` ApproxSecondsBeforeTimedOut int64 `json:"approximateSecondsBeforeTimedOut,omitempty"` QueuedAt int64 `json:"queuedAt"` StartedAt int64 `json:"startedAt,omitempty"` @@ -111,16 +114,16 @@ func executionWire(e *DeviceJobExecution) *jobsExecutionWire { } // documentRaw embeds a JSON job document as an object; MQTT carries it unquoted, unlike the HTTP API. -func documentRaw(doc string) json.RawMessage { +func documentRaw(doc string) jsontext.Value { if doc == "" { return nil } - if json.Valid([]byte(doc)) { - return json.RawMessage(doc) + if jsontext.Value([]byte(doc)).IsValid(jsonx.V1()) { + return jsontext.Value(doc) } - quoted, _ := json.Marshal(doc) + quoted, _ := json.Marshal(doc, jsonx.V1()) return quoted } @@ -140,7 +143,7 @@ type jobsRequestBody struct { func (b *Broker) handleJobsRequest(topic string, req jobsRequest, payload []byte) { var body jobsRequestBody if len(payload) > 0 { - if err := json.Unmarshal(payload, &body); err != nil { + if err := json.Unmarshal(payload, &body, jsonx.V1()); err != nil { b.publishJobs(topic+jobsSuffixReject, map[string]any{ "code": jobsCodeInvalidJSON, jobsKeyMessage: "payload is not valid JSON", @@ -343,7 +346,7 @@ func (b *Broker) rejectJobs(topic, clientToken, code, message string, state map[ } func (b *Broker) publishJobs(topic string, body map[string]any) { - payload, err := json.Marshal(body) + payload, err := json.Marshal(body, jsonx.V1()) if err != nil { return } diff --git a/services/iot/broker_jobs_test.go b/services/iot/broker_jobs_test.go index fa049cee80..3096075281 100644 --- a/services/iot/broker_jobs_test.go +++ b/services/iot/broker_jobs_test.go @@ -2,7 +2,7 @@ package iot_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -113,7 +114,7 @@ func (e *jobsMQTTEnv) expect(t *testing.T, suffix string) map[string]any { } var out map[string]any - require.NoError(t, json.Unmarshal(m.Payload(), &out)) + require.NoError(t, json.Unmarshal(m.Payload(), &out, jsonx.V1())) return out case <-timer.C: diff --git a/services/iot/command_executions_test.go b/services/iot/command_executions_test.go index 5b6f143eb8..6c621e1669 100644 --- a/services/iot/command_executions_test.go +++ b/services/iot/command_executions_test.go @@ -2,7 +2,7 @@ package iot_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http/httptest" @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -401,7 +402,7 @@ func TestCommandExecutionDeviceLifecycle(t *testing.T) { e.respond(t, id, `{"status":"IN_PROGRESS","clientToken":"b"}`) var rejected map[string]string - require.NoError(t, json.Unmarshal(e.expect(t, base+"rejected/json"), &rejected)) + require.NoError(t, json.Unmarshal(e.expect(t, base+"rejected/json"), &rejected, jsonx.V1())) assert.Equal(t, "TerminalStateReached", rejected["error"]) assert.Equal(t, "b", rejected["clientToken"]) @@ -457,7 +458,7 @@ func TestCommandExecutionDeviceRejections(t *testing.T) { t, json.Unmarshal( e.expect(t, "$aws/commands/things/"+cmdThing+"/executions/"+id+"/response/rejected/json"), - &got, + &got, jsonx.V1(), ), ) assert.Equal(t, tt.wantErr, got["error"]) @@ -475,7 +476,7 @@ func TestCommandExecutionDeviceRejections(t *testing.T) { t, json.Unmarshal( e.expect(t, "$aws/commands/things/"+cmdThing+"/executions/ghost/response/rejected/json"), - &got, + &got, jsonx.V1(), ), ) assert.Equal(t, "ResourceNotFound", got["error"]) diff --git a/services/iot/events.go b/services/iot/events.go index ab6b70ee94..5e2c7c63c0 100644 --- a/services/iot/events.go +++ b/services/iot/events.go @@ -1,13 +1,15 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "maps" "slices" "strings" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // UpdateEventConfigurations keys that gate registry events. @@ -92,7 +94,7 @@ func (b *InMemoryBackend) flushEvents() { } for _, ev := range events { - raw, err := json.Marshal(ev.payload) + raw, err := json.Marshal(ev.payload, jsonx.V1()) if err != nil { continue } diff --git a/services/iot/handler.go b/services/iot/handler.go index 975a598aef..4665c3b240 100644 --- a/services/iot/handler.go +++ b/services/iot/handler.go @@ -2,7 +2,8 @@ package iot import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -14,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -322,7 +324,7 @@ func (h *Handler) handleCreateThing(c *echo.Context) error { BillingGroupName string `json:"billingGroupName"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -549,7 +551,7 @@ func (h *Handler) handleUpdateThing(c *echo.Context) error { var body UpdateThingInput - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_audit_suppressions_list_test.go b/services/iot/handler_audit_suppressions_list_test.go index 47718618e0..3d026cae91 100644 --- a/services/iot/handler_audit_suppressions_list_test.go +++ b/services/iot/handler_audit_suppressions_list_test.go @@ -1,12 +1,14 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListAuditSuppressions_FilterOrderAndPagination proves @@ -38,7 +40,7 @@ func TestListAuditSuppressions_FilterOrderAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) suppressions, _ := out["suppressions"].([]any) require.Len(t, suppressions, 1) }) @@ -51,7 +53,7 @@ func TestListAuditSuppressions_FilterOrderAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) suppressions, _ := out["suppressions"].([]any) require.Len(t, suppressions, 1) }) @@ -63,7 +65,7 @@ func TestListAuditSuppressions_FilterOrderAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) suppressions, _ := out["suppressions"].([]any) require.Len(t, suppressions, 3) @@ -79,7 +81,7 @@ func TestListAuditSuppressions_FilterOrderAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) suppressions, _ := out["suppressions"].([]any) require.Len(t, suppressions, 3) @@ -95,7 +97,7 @@ func TestListAuditSuppressions_FilterOrderAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) suppressions, _ := out["suppressions"].([]any) require.Len(t, suppressions, 2) assert.NotEmpty(t, out["nextToken"]) diff --git a/services/iot/handler_billing_groups.go b/services/iot/handler_billing_groups.go index b39aa2e97a..babc149f45 100644 --- a/services/iot/handler_billing_groups.go +++ b/services/iot/handler_billing_groups.go @@ -1,19 +1,22 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddThingToBillingGroup(c *echo.Context) error { var body AddThingToBillingGroupInput - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_billing_groups_test.go b/services/iot/handler_billing_groups_test.go index 7546d6289c..b8cac09850 100644 --- a/services/iot/handler_billing_groups_test.go +++ b/services/iot/handler_billing_groups_test.go @@ -1,12 +1,14 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestNewOps_BillingGroup tests BillingGroup CRUD. @@ -75,7 +77,7 @@ func TestBillingGroup_UpdateVersionConflict_Rejected(t *testing.T) { var errBody struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "VersionConflictException", errBody.Type) out := iotOK(t, h, http.MethodGet, "/billing-groups/ver-group", nil) diff --git a/services/iot/handler_certificates.go b/services/iot/handler_certificates.go index e9ab84ba71..0016760a5a 100644 --- a/services/iot/handler_certificates.go +++ b/services/iot/handler_certificates.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -141,7 +143,7 @@ func (h *Handler) handleCreateCertificateFromCsr(c *echo.Context) error { var body struct { CertificateSigningRequest string `json:"certificateSigningRequest"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -174,7 +176,7 @@ func (h *Handler) handleRegisterCertificate(c *echo.Context) error { CACertificatePem string `json:"caCertificatePem"` Status string `json:"status"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -199,7 +201,7 @@ func (h *Handler) handleRegisterCertificateWithoutCA(c *echo.Context) error { CertificatePem string `json:"certificatePem"` Status string `json:"status"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -372,7 +374,7 @@ func (h *Handler) handleCreateCertificateProvider(c *echo.Context) error { Tags []tags.KV `json:"tags,omitempty"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -450,7 +452,7 @@ func (h *Handler) handleUpdateCertificateProvider(c *echo.Context) error { AccountDefaultForOperations []string `json:"accountDefaultForOperations"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_certificates_test.go b/services/iot/handler_certificates_test.go index 5ac7896aad..78d92457b7 100644 --- a/services/iot/handler_certificates_test.go +++ b/services/iot/handler_certificates_test.go @@ -1,7 +1,7 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -121,7 +122,7 @@ func TestListCertificatesByCA(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) certs, _ := out["certificates"].([]any) require.Len(t, certs, 1) @@ -632,7 +633,7 @@ func TestDescribeCertificate_ReturnsPem(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) certID, _ := cr["certificateId"].(string) require.NotEmpty(t, certID) @@ -640,7 +641,7 @@ func TestDescribeCertificate_ReturnsPem(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &desc, jsonx.V1())) certDesc, _ := desc["certificateDescription"].(map[string]any) pem, _ := certDesc["certificatePem"].(string) assert.NotEmpty(t, pem, "certificatePem must be present in DescribeCertificate response") @@ -737,7 +738,7 @@ func TestTransferCertificate_ReturnsArn(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) certID, _ := cr["certificateId"].(string) certARN, _ := cr["certificateArn"].(string) require.NotEmpty(t, certID) @@ -748,7 +749,7 @@ func TestTransferCertificate_ReturnsArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) transferredARN, _ := resp["transferredCertificateArn"].(string) assert.Equal(t, certARN, transferredARN, "transferredCertificateArn must be the cert ARN, not ID") } @@ -795,7 +796,7 @@ func TestListOutgoingCertificates_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) certs, _ := out["outgoingCertificates"].([]any) assert.LessOrEqual(t, len(certs), 1) assert.NotEmpty(t, out["nextMarker"]) diff --git a/services/iot/handler_helpers.go b/services/iot/handler_helpers.go index fb29116175..ee5d7ce73a 100644 --- a/services/iot/handler_helpers.go +++ b/services/iot/handler_helpers.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -9,6 +10,8 @@ import ( "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // errTypeInvalidRequest is the AWS IoT restjson1 __type for a malformed or @@ -20,7 +23,12 @@ const errTypeInvalidRequest = "InvalidRequestException" const maxTopicRuleBodyBytes int64 = 1 << 20 func readBody(c *echo.Context, dst any) error { - if err := json.NewDecoder(c.Request().Body).Decode(dst); err != nil && !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + dst, + jsonx.V1(), + ); err != nil && + !errors.Is(err, io.EOF) { if jsonErr := c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}); jsonErr != nil { return jsonErr } diff --git a/services/iot/handler_helpers_test.go b/services/iot/handler_helpers_test.go index fe9e4c9ff5..39c0f689ff 100644 --- a/services/iot/handler_helpers_test.go +++ b/services/iot/handler_helpers_test.go @@ -2,7 +2,8 @@ package iot_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -48,15 +50,15 @@ func TestReadBodyMalformedWritesExactlyOneDocument(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) - dec := json.NewDecoder(rec.Body) + dec := jsontext.NewDecoder(rec.Body) var first map[string]any - require.NoError(t, dec.Decode(&first)) + require.NoError(t, json.UnmarshalDecode(dec, &first, jsonx.V1())) require.Contains(t, first, "__type") require.Contains(t, first, "message") var second map[string]any - err := dec.Decode(&second) + err := json.UnmarshalDecode(dec, &second, jsonx.V1()) require.ErrorIs( t, err, @@ -95,7 +97,7 @@ func TestReadBodyMalformed_RealSDKClient_DecodesInvalidRequestException(t *testi require.Equal(t, http.StatusBadRequest, rec.Code) - errorType, message, err := restjson.GetErrorInfo(json.NewDecoder(rec.Body)) + errorType, message, err := restjson.GetErrorInfo(jsonx.SDKDecoder(rec.Body)) require.NoError(t, err) assert.Equal(t, "InvalidRequestException", errorType, "a real client must decode a modeled error code, not fall through to UnknownError") diff --git a/services/iot/handler_indexing.go b/services/iot/handler_indexing.go index 6ab042b8dc..60e89ad97b 100644 --- a/services/iot/handler_indexing.go +++ b/services/iot/handler_indexing.go @@ -1,13 +1,16 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resolveIndexOps maps fleet-indexing REST paths to their operation names. @@ -96,7 +99,12 @@ func (h *Handler) dispatchIndexOps(c *echo.Context, op string) (bool, error) { const keyCount = "count" func decodeJSONBody(c *echo.Context, v any) error { - if err := json.NewDecoder(c.Request().Body).Decode(v); err != nil && !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + v, + jsonx.V1(), + ); err != nil && + !errors.Is(err, io.EOF) { return err } diff --git a/services/iot/handler_jobs.go b/services/iot/handler_jobs.go index c783d29b74..b9eb838756 100644 --- a/services/iot/handler_jobs.go +++ b/services/iot/handler_jobs.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -9,6 +10,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAssociateTargetsWithJob(c *echo.Context) error { @@ -22,7 +25,7 @@ func (h *Handler) handleAssociateTargetsWithJob(c *echo.Context) error { Targets []string `json:"targets"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -379,7 +382,12 @@ func (h *Handler) handleCancelJobExecution(c *echo.Context) error { ExpectedVersion int64 `json:"expectedVersion"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &body, + jsonx.V1(), + ); err != nil && + !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_jobs_test.go b/services/iot/handler_jobs_test.go index 12cb7a44e6..12ea1231b0 100644 --- a/services/iot/handler_jobs_test.go +++ b/services/iot/handler_jobs_test.go @@ -2,7 +2,7 @@ package iot_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -233,7 +234,7 @@ func TestJobExecution_RoutingAndStateGuards(t *testing.T) { assert.Equal(t, http.StatusConflict, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidStateTransitionException", body["__type"]) }, }, @@ -278,7 +279,7 @@ func TestJobExecution_RoutingAndStateGuards(t *testing.T) { assert.Equal(t, http.StatusConflict, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "VersionConflictException", body["__type"]) }, }, @@ -888,7 +889,7 @@ func TestHandler_ListJobsNamespaceFilter(t *testing.T) { JobID string `json:"jobId"` } `json:"jobs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) got := make([]string, 0, len(out.Jobs)) for _, j := range out.Jobs { got = append(got, j.JobID) diff --git a/services/iot/handler_packages.go b/services/iot/handler_packages.go index e8c94ce54b..be0ee8cb82 100644 --- a/services/iot/handler_packages.go +++ b/services/iot/handler_packages.go @@ -1,13 +1,16 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxPackagePathSegments is the number of segments in /packages/{pkg}/versions/{ver}/sbom. @@ -35,7 +38,7 @@ func (h *Handler) handleAssociateSbomWithPackageVersion(c *echo.Context) error { Sbom *SbomDocument `json:"sbom"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_policies.go b/services/iot/handler_policies.go index d0459553fe..494f147463 100644 --- a/services/iot/handler_policies.go +++ b/services/iot/handler_policies.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -189,7 +191,7 @@ func (h *Handler) handleCreatePolicy(c *echo.Context) error { Tags []tags.KV `json:"tags,omitempty"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -218,7 +220,7 @@ func (h *Handler) handleAttachPolicy(c *echo.Context) error { Target string `json:"target"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -307,7 +309,7 @@ func (h *Handler) handleDetachPolicy(c *echo.Context) error { Target string `json:"target"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -343,7 +345,7 @@ func (h *Handler) handleListAttachedPolicies(c *echo.Context) error { Target string `json:"target"` Recursive bool `json:"recursive"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -408,7 +410,7 @@ func (h *Handler) handleCreatePolicyVersion(c *echo.Context) error { PolicyDocument string `json:"policyDocument"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_policies_test.go b/services/iot/handler_policies_test.go index 2291fe87cb..9e3c611522 100644 --- a/services/iot/handler_policies_test.go +++ b/services/iot/handler_policies_test.go @@ -1,7 +1,8 @@ package iot_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -105,7 +107,7 @@ func TestListPrincipalThingsV2_WireShapeAndFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) objs, _ := out["principalThingObjects"].([]any) require.Len(t, objs, 1) entry, ok := objs[0].(map[string]any) @@ -186,7 +188,7 @@ func TestPolicyPrincipalListing_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policies, _ := out["policies"].([]any) assert.LessOrEqual(t, len(policies), 1) assert.NotEmpty(t, out["nextMarker"]) @@ -209,7 +211,7 @@ func TestPolicyPrincipalListing_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) princs, _ := out["principals"].([]any) assert.LessOrEqual(t, len(princs), 1) assert.NotEmpty(t, out["nextMarker"]) @@ -229,7 +231,7 @@ func TestPolicyPrincipalListing_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) targets, _ := out["targets"].([]any) assert.LessOrEqual(t, len(targets), 1) assert.NotEmpty(t, out["nextMarker"]) @@ -252,7 +254,7 @@ func TestPolicyPrincipalListing_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) things, _ := out["things"].([]any) assert.LessOrEqual(t, len(things), 1) assert.NotEmpty(t, out["nextToken"]) @@ -456,7 +458,7 @@ func TestHandler_ListPolicies_Response(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) policies, ok := out["policies"] require.True(t, ok, "response must have 'policies' key") @@ -480,7 +482,7 @@ func TestHandler_GetPolicy_HTTP(t *testing.T) { // creationDate/lastModifiedDate are JSON numbers (epoch seconds), not // RFC3339 strings, so this must decode into map[string]any. var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, "http-policy", out["policyName"]) assert.NotEmpty(t, out["policyArn"]) @@ -1011,7 +1013,7 @@ func TestGetPolicyVersion_ReturnsPolicyArnAndName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "parb-pol2", resp["policyName"], "policyName must be in GetPolicyVersion response") policyARN, _ := resp["policyArn"].(string) assert.NotEmpty(t, policyARN, "policyArn must be in GetPolicyVersion response") diff --git a/services/iot/handler_routing_test.go b/services/iot/handler_routing_test.go index 4e5604d5f7..d0df4bf156 100644 --- a/services/iot/handler_routing_test.go +++ b/services/iot/handler_routing_test.go @@ -2,7 +2,7 @@ package iot_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -40,7 +41,7 @@ func TestHandler_Operations(t *testing.T) { validateOutput: func(t *testing.T, body []byte) { t.Helper() var out map[string]string - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.Equal(t, "my-thing", out["thingName"]) }, }, @@ -101,7 +102,7 @@ func TestHandler_Operations(t *testing.T) { var reqBody []byte if tt.body != nil { var err error - reqBody, err = json.Marshal(tt.body) + reqBody, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } @@ -372,7 +373,7 @@ func TestHandler_NewOperations(t *testing.T) { var reqBody []byte if tt.body != nil { var err error - reqBody, err = json.Marshal(tt.body) + reqBody, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/iot/handler_tags_wire_test.go b/services/iot/handler_tags_wire_test.go index dfde622508..2732824dad 100644 --- a/services/iot/handler_tags_wire_test.go +++ b/services/iot/handler_tags_wire_test.go @@ -1,7 +1,7 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -38,7 +39,7 @@ func decodeTagList(t *testing.T, body []byte) map[string]string { Value string `json:"Value"` } `json:"tags"` } - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) out := make(map[string]string, len(resp.Tags)) for _, item := range resp.Tags { out[item.Key] = item.Value @@ -435,7 +436,7 @@ func TestCreateThenListTagsForResourceRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, "body: %s", createRec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) resourceARN, ok := created[tt.arnField].(string) require.Truef(t, ok && resourceARN != "", "response missing %q: %s", tt.arnField, createRec.Body.String()) @@ -463,7 +464,7 @@ func TestTagUntagResourceAfterCreationTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, "body: %s", createRec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) resourceARN, _ := created["thingGroupArn"].(string) require.NotEmpty(t, resourceARN) diff --git a/services/iot/handler_test.go b/services/iot/handler_test.go index 5b6dd7c9d8..c31c73dcc6 100644 --- a/services/iot/handler_test.go +++ b/services/iot/handler_test.go @@ -2,7 +2,8 @@ package iot_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -27,7 +29,7 @@ func doIoTRequest(t *testing.T, h *iot.Handler, method, path string, body any) * var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -66,7 +68,7 @@ func iotRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) if err != nil { t.Fatalf("marshal request body: %v", err) } @@ -93,7 +95,7 @@ func iotOK(t *testing.T, h *iot.Handler, method, path string, body any) map[stri return map[string]any{} } var out map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil { + if err := json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()); err != nil { t.Fatalf("decode response: %v", err) } @@ -134,7 +136,7 @@ func doRefRequest( if body != nil { var err error - raw, err = json.Marshal(body) + raw, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -166,7 +168,7 @@ func doRequest(t *testing.T, h *iot.Handler, method, path string, body any) *htt if body != nil { var err error - reqBody, err = json.Marshal(body) + reqBody, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -204,7 +206,7 @@ func r3JSON(t *testing.T, h *iot.Handler, method, path string, body any, out any t.Helper() code, raw := r3Req(t, h, method, path, body) if out != nil { - require.NoError(t, json.Unmarshal(raw, out)) + require.NoError(t, json.Unmarshal(raw, out, jsonx.V1())) } return code @@ -541,7 +543,7 @@ func TestHandler_ListThings_ResponseFormat(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) things, ok := out["things"] require.True(t, ok, "response must have 'things' key") @@ -587,7 +589,7 @@ func TestHandler_ListThingPrincipals_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) principals, ok := out["principals"].([]any) require.True(t, ok) require.Len(t, principals, 1) @@ -641,7 +643,7 @@ func TestDescribeThing_DefaultClientId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clientID, _ := resp["defaultClientId"].(string) assert.Equal(t, tt.thingName, clientID, "defaultClientId must equal thingName") }) @@ -680,7 +682,7 @@ func TestListThings_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.Things), 2, "page exceeds maxResults") for _, th := range resp.Things { @@ -733,7 +735,7 @@ func TestListThingGroupsForThing_WireShapeAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) groups, ok := out["thingGroups"].([]any) require.True(t, ok) require.Len(t, groups, total) @@ -751,7 +753,7 @@ func TestListThingGroupsForThing_WireShapeAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) groups, _ := out["thingGroups"].([]any) assert.LessOrEqual(t, len(groups), 2) assert.NotEmpty(t, out["nextToken"]) @@ -780,7 +782,7 @@ func TestListThingPrincipals_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) principals, _ := out["principals"].([]any) assert.LessOrEqual(t, len(principals), 2) assert.NotEmpty(t, out["nextToken"]) @@ -815,7 +817,7 @@ func TestListThingPrincipalsV2_ThingPrincipalTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) objs, _ := out["thingPrincipalObjects"].([]any) require.Len(t, objs, 1, "EXCLUSIVE_THING filter must return only the EXCLUSIVE_THING attachment") entry, _ := objs[0].(map[string]any) @@ -827,7 +829,7 @@ func TestListThingPrincipalsV2_ThingPrincipalTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) objs2, _ := out2["thingPrincipalObjects"].([]any) require.Len(t, objs2, 1) entry2, _ := objs2[0].(map[string]any) diff --git a/services/iot/handler_thing_groups.go b/services/iot/handler_thing_groups.go index 4ab50661d4..5a9434550d 100644 --- a/services/iot/handler_thing_groups.go +++ b/services/iot/handler_thing_groups.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -10,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -90,7 +92,7 @@ func (h *Handler) dispatchThingGroupOps(c *echo.Context, op string) (bool, error func (h *Handler) handleAddThingToThingGroup(c *echo.Context) error { var body AddThingToThingGroupInput - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -115,7 +117,7 @@ func (h *Handler) handleCreateThingGroup(c *echo.Context) error { Tags []tags.KV `json:"tags,omitempty"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -222,7 +224,7 @@ func (h *Handler) handleUpdateThingGroup(c *echo.Context) error { ExpectedVersion *int64 `json:"expectedVersion"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -266,7 +268,7 @@ func (h *Handler) handleDeleteThingGroup(c *echo.Context) error { func (h *Handler) handleRemoveThingFromThingGroup(c *echo.Context) error { var body RemoveThingFromThingGroupInput - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_thing_types.go b/services/iot/handler_thing_types.go index f10681ff2d..2eabbddabe 100644 --- a/services/iot/handler_thing_types.go +++ b/services/iot/handler_thing_types.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -10,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -72,7 +74,7 @@ func (h *Handler) handleCreateThingType(c *echo.Context) error { Tags []tags.KV `json:"tags,omitempty"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -170,7 +172,7 @@ func (h *Handler) handleDeprecateThingType(c *echo.Context) error { UndoDeprecate bool `json:"undoDeprecate"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_thing_types_test.go b/services/iot/handler_thing_types_test.go index 75843409e7..f330c9a2ce 100644 --- a/services/iot/handler_thing_types_test.go +++ b/services/iot/handler_thing_types_test.go @@ -1,7 +1,8 @@ package iot_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -149,7 +151,7 @@ func TestHandler_DescribeThing_IncludesThingTypeName(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, "SensorType", out["thingTypeName"]) } diff --git a/services/iot/handler_thingtype_searchable_test.go b/services/iot/handler_thingtype_searchable_test.go index 318c84eff6..a0a3b0fb2d 100644 --- a/services/iot/handler_thingtype_searchable_test.go +++ b/services/iot/handler_thingtype_searchable_test.go @@ -1,12 +1,14 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestIoT_ThingTypes_SearchableAttributes validates that searchableAttributes @@ -65,7 +67,7 @@ func TestIoT_ThingTypes_SearchableAttributes(t *testing.T) { } `json:"thingTypeProperties"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantSearchable, resp.ThingTypeProperties.SearchableAttributes) }) } diff --git a/services/iot/handler_topic_rules.go b/services/iot/handler_topic_rules.go index b520dd13a0..6ce0ca07c9 100644 --- a/services/iot/handler_topic_rules.go +++ b/services/iot/handler_topic_rules.go @@ -1,7 +1,8 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resolveTopicRuleDestinationOps resolves the topic-rule-destination op @@ -148,14 +150,14 @@ func (h *Handler) handleCreateTopicRule(c *echo.Context) error { var wrapped struct { TopicRulePayload *TopicRulePayload `json:"topicRulePayload"` } - if jsonErr := json.Unmarshal(rawBody, &wrapped); jsonErr != nil && !errors.Is(jsonErr, io.EOF) { + if jsonErr := json.Unmarshal(rawBody, &wrapped, jsonx.V1()); jsonErr != nil && !errors.Is(jsonErr, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, jsonErr.Error()}) } payload := wrapped.TopicRulePayload if payload == nil { var flat TopicRulePayload - if jsonErr := json.Unmarshal(rawBody, &flat); jsonErr == nil && flat.SQL != "" { + if jsonErr := json.Unmarshal(rawBody, &flat, jsonx.V1()); jsonErr == nil && flat.SQL != "" { payload = &flat } } @@ -329,14 +331,14 @@ func (h *Handler) handleReplaceTopicRule(c *echo.Context) error { var wrapped struct { TopicRulePayload *TopicRulePayload `json:"topicRulePayload"` } - if jsonErr := json.Unmarshal(rawBody, &wrapped); jsonErr != nil && !errors.Is(jsonErr, io.EOF) { + if jsonErr := json.Unmarshal(rawBody, &wrapped, jsonx.V1()); jsonErr != nil && !errors.Is(jsonErr, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, jsonErr.Error()}) } payload := wrapped.TopicRulePayload if payload == nil { var flat TopicRulePayload - if jsonErr := json.Unmarshal(rawBody, &flat); jsonErr == nil && flat.SQL != "" { + if jsonErr := json.Unmarshal(rawBody, &flat, jsonx.V1()); jsonErr == nil && flat.SQL != "" { payload = &flat } } @@ -416,7 +418,7 @@ func (h *Handler) handleCreateTopicRuleDestination(c *echo.Context) error { var body struct { DestinationConfiguration *TopicRuleDestinationConfiguration `json:"destinationConfiguration"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } @@ -472,7 +474,7 @@ func (h *Handler) handleUpdateTopicRuleDestination(c *echo.Context) error { ARN string `json:"arn"` Status string `json:"status"` } - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && !errors.Is(err, io.EOF) { return c.JSON(http.StatusBadRequest, awsErrBody{errTypeInvalidRequest, err.Error()}) } diff --git a/services/iot/handler_topic_rules_test.go b/services/iot/handler_topic_rules_test.go index d1480c0ed0..f860e33841 100644 --- a/services/iot/handler_topic_rules_test.go +++ b/services/iot/handler_topic_rules_test.go @@ -1,7 +1,8 @@ package iot_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -102,7 +104,7 @@ func TestGetTopicRule_RuleWrapper(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ruleArn") assert.Contains(t, resp, "rule") }) @@ -169,7 +171,7 @@ func TestCreateAndGetTopicRule_Handler(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ruleArn") assert.Contains(t, resp, "rule") }) @@ -356,7 +358,7 @@ func TestHandler_ListTopicRules_ResponseFormat(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) rules, ok := out["rules"] require.True(t, ok, "response must have 'rules' key") @@ -411,7 +413,7 @@ func TestHandler_GetTopicRule_IncludesAWSSQLVersion(t *testing.T) { require.Equal(t, http.StatusOK, resp.Code) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) rule, ok := out["rule"].(map[string]any) require.True(t, ok) diff --git a/services/iot/jobs_data_plane_test.go b/services/iot/jobs_data_plane_test.go index a97badcc56..30de4839d5 100644 --- a/services/iot/jobs_data_plane_test.go +++ b/services/iot/jobs_data_plane_test.go @@ -2,7 +2,8 @@ package iot_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/iot" @@ -55,7 +57,7 @@ func newJobsDataEnv(t *testing.T) jobsDataEnv { func (e jobsDataEnv) device(t *testing.T, method, path string, body any) (int, map[string]any) { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), method, e.url+path, bytes.NewReader(raw)) @@ -69,7 +71,7 @@ func (e jobsDataEnv) device(t *testing.T, method, path string, body any) (int, m defer resp.Body.Close() out := map[string]any{} - _ = json.NewDecoder(resp.Body).Decode(&out) + _ = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1()) return resp.StatusCode, out } diff --git a/services/iot/multi_region_test.go b/services/iot/multi_region_test.go index 9eb2ae4ba1..bf3891c4b3 100644 --- a/services/iot/multi_region_test.go +++ b/services/iot/multi_region_test.go @@ -2,7 +2,7 @@ package iot_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -41,7 +42,7 @@ func regionCall(t *testing.T, h *iot.Handler, region, method, path, body string) out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out diff --git a/services/iot/names.go b/services/iot/names.go index 4cc7a69bb4..ae7987385c 100644 --- a/services/iot/names.go +++ b/services/iot/names.go @@ -1,10 +1,13 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "regexp" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxEntityNameLen = 128 @@ -41,13 +44,13 @@ func malformedPolicy(format string, args ...any) error { // validatePolicyDocument checks the document is JSON with a Version and well-formed Statement entries. func validatePolicyDocument(doc string) error { - var v map[string]json.RawMessage - if err := json.Unmarshal([]byte(doc), &v); err != nil { + var v map[string]jsontext.Value + if err := json.Unmarshal([]byte(doc), &v, jsonx.V1()); err != nil { return malformedPolicy("policy document is not valid JSON") } var version string - if raw, ok := v["Version"]; !ok || json.Unmarshal(raw, &version) != nil || version == "" { + if raw, ok := v["Version"]; !ok || json.Unmarshal(raw, &version, jsonx.V1()) != nil || version == "" { return malformedPolicy("policy document must have a string Version") } @@ -56,15 +59,15 @@ func validatePolicyDocument(doc string) error { return malformedPolicy("policy document must have a Statement") } - var statements []map[string]json.RawMessage + var statements []map[string]jsontext.Value - if err := json.Unmarshal(raw, &statements); err != nil { - var single map[string]json.RawMessage - if json.Unmarshal(raw, &single) != nil { + if err := json.Unmarshal(raw, &statements, jsonx.V1()); err != nil { + var single map[string]jsontext.Value + if json.Unmarshal(raw, &single, jsonx.V1()) != nil { return malformedPolicy("Statement must be an object or an array of objects") } - statements = []map[string]json.RawMessage{single} + statements = []map[string]jsontext.Value{single} } for _, st := range statements { @@ -76,9 +79,10 @@ func validatePolicyDocument(doc string) error { return nil } -func validatePolicyStatement(st map[string]json.RawMessage) error { +func validatePolicyStatement(st map[string]jsontext.Value) error { var effect string - if raw, ok := st["Effect"]; !ok || json.Unmarshal(raw, &effect) != nil || (effect != "Allow" && effect != "Deny") { + if raw, ok := st["Effect"]; !ok || json.Unmarshal(raw, &effect, jsonx.V1()) != nil || + (effect != "Allow" && effect != "Deny") { return malformedPolicy("statement Effect must be Allow or Deny") } @@ -91,17 +95,17 @@ func validatePolicyStatement(st map[string]json.RawMessage) error { return nil } -func stringOrList(raw json.RawMessage) bool { +func stringOrList(raw jsontext.Value) bool { if len(raw) == 0 { return false } var one string - if json.Unmarshal(raw, &one) == nil { + if json.Unmarshal(raw, &one, jsonx.V1()) == nil { return one != "" } var many []string - return json.Unmarshal(raw, &many) == nil && len(many) > 0 + return json.Unmarshal(raw, &many, jsonx.V1()) == nil && len(many) > 0 } diff --git a/services/iot/ota_options.go b/services/iot/ota_options.go index 62227d1f10..d20d7d2478 100644 --- a/services/iot/ota_options.go +++ b/services/iot/ota_options.go @@ -1,9 +1,11 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -63,10 +65,10 @@ func otaJobInput(opts OTAUpdateOptions, roleARN string) *CreateJobInput { // remapJSON copies the keys src shares with dst's JSON tags; an unmarshal failure leaves dst as is. func remapJSON(src map[string]any, dst any) { - raw, err := json.Marshal(src) + raw, err := json.Marshal(src, jsonx.V1()) if err != nil { return } - _ = json.Unmarshal(raw, dst) + _ = json.Unmarshal(raw, dst, jsonx.V1()) } diff --git a/services/iot/ota_updates.go b/services/iot/ota_updates.go index 9ce95dafd1..7f28e482fe 100644 --- a/services/iot/ota_updates.go +++ b/services/iot/ota_updates.go @@ -1,12 +1,13 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // OTAUpdate represents an AWS IoT OTA update. @@ -74,7 +75,7 @@ func (b *InMemoryBackend) CreateOTAUpdate( now := float64(time.Now().Unix()) jobID := "AFR_OTA-" + id - doc, docErr := json.Marshal(map[string]any{"afr_ota": map[string]any{"files": files}}) + doc, docErr := json.Marshal(map[string]any{"afr_ota": map[string]any{"files": files}}, jsonx.V1()) if docErr != nil { return nil, fmt.Errorf("building OTA job document: %w", docErr) } diff --git a/services/iot/persistence.go b/services/iot/persistence.go index e2dc6a04f6..6e05fe0a12 100644 --- a/services/iot/persistence.go +++ b/services/iot/persistence.go @@ -2,11 +2,13 @@ package iot import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -35,7 +37,7 @@ import ( const iotSnapshotVersion = 3 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` AuditTasks map[string]string `json:"auditTasks"` ClientRequestTokens map[string]string `json:"clientRequestTokens,omitempty"` OpReplay []string `json:"opReplay,omitempty"` @@ -175,7 +177,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { DefaultAuthorizer: cfgSnap.DefaultAuthorizer, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "iot: failed to snapshot backend state", "error", err) @@ -456,7 +458,7 @@ func fromTopicRuleDestSnap(s *topicRuleDestSnap) *TopicRuleDestination { // out-of-band), so registry.SnapshotAll's generic encoding would drop it; // the topicRuleDestSnap DTO carries it through instead. Must be called with // b.mu held (read or write). -func (b *InMemoryBackend) snapshotTopicRuleDestinationsTable() (map[string]json.RawMessage, error) { +func (b *InMemoryBackend) snapshotTopicRuleDestinationsTable() (map[string]jsontext.Value, error) { destDTOReg := store.NewRegistry() destDTOs := store.Register(destDTOReg, topicRuleDestinationsTableName, store.New(topicRuleDestSnapKey)) @@ -476,7 +478,7 @@ func (b *InMemoryBackend) snapshotTopicRuleDestinationsTable() (map[string]json. // DTO entry in tables (the inverse of snapshotTopicRuleDestinationsTable). // Extracted from Restore to keep it within the repo's funlen limit. Must be // called with b.mu held (write). -func (b *InMemoryBackend) restoreTopicRuleDestinationsTable(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreTopicRuleDestinationsTable(tables map[string]jsontext.Value) error { destDTOReg := store.NewRegistry() destDTOs := store.Register(destDTOReg, topicRuleDestinationsTableName, store.New(topicRuleDestSnapKey)) diff --git a/services/iot/policy_evaluation.go b/services/iot/policy_evaluation.go index 2ee476f19c..a5c404bf27 100644 --- a/services/iot/policy_evaluation.go +++ b/services/iot/policy_evaluation.go @@ -1,11 +1,13 @@ package iot import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AuthInfo describes one action/resources pair to evaluate authorization for. @@ -237,14 +239,14 @@ type flexStringList []string func (f *flexStringList) UnmarshalJSON(data []byte) error { var single string - if err := json.Unmarshal(data, &single); err == nil { + if err := json.Unmarshal(data, &single, jsonx.V1()); err == nil { *f = []string{single} return nil } var list []string - if err := json.Unmarshal(data, &list); err != nil { + if err := json.Unmarshal(data, &list, jsonx.V1()); err != nil { return err } @@ -264,7 +266,7 @@ func parseIoTPolicyDocument(doc string) ([]iamStatement, error) { } `json:"Statement"` } - if err := json.Unmarshal([]byte(doc), &raw); err != nil { + if err := json.Unmarshal([]byte(doc), &raw, jsonx.V1()); err != nil { return nil, err } diff --git a/services/iot/realism_test.go b/services/iot/realism_test.go index bb61a6470b..719c263798 100644 --- a/services/iot/realism_test.go +++ b/services/iot/realism_test.go @@ -1,13 +1,15 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func iotErr(t *testing.T, body []byte) (string, string) { @@ -17,7 +19,7 @@ func iotErr(t *testing.T, body []byte) (string, string) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out.Type, out.Message } diff --git a/services/iot/rule_actions.go b/services/iot/rule_actions.go index 67dd71abd6..32d645b2e9 100644 --- a/services/iot/rule_actions.go +++ b/services/iot/rule_actions.go @@ -3,7 +3,8 @@ package iot import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" @@ -14,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -30,7 +32,7 @@ const ( opDelete = "DELETE" ) -type actionRunner func(h *ruleHook, rule *TopicRule, msg *ruleMessage, raw json.RawMessage) error +type actionRunner func(h *ruleHook, rule *TopicRule, msg *ruleMessage, raw jsontext.Value) error type otherRunner struct { run actionRunner @@ -83,8 +85,8 @@ func (h *ruleHook) allow(roleARN, resource string, actions ...string) error { return nil } -func decodeAction(raw json.RawMessage, dst any) error { - if err := json.Unmarshal(raw, dst); err != nil { +func decodeAction(raw jsontext.Value, dst any) error { + if err := json.Unmarshal(raw, dst, jsonx.V1()); err != nil { return fmt.Errorf("decode action: %w", err) } @@ -132,7 +134,7 @@ type kinesisWire struct { PartitionKey string `json:"partitionKey"` } -func (h *ruleHook) runKinesis(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runKinesis(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w kinesisWire if err := decodeAction(raw, &w); err != nil { return err @@ -166,7 +168,7 @@ type firehoseWire struct { BatchMode bool `json:"batchMode"` } -func (h *ruleHook) runFirehose(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runFirehose(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w firehoseWire if err := decodeAction(raw, &w); err != nil { return err @@ -214,8 +216,8 @@ func (m *ruleMessage) batchElements(batch bool) ([][]byte, error) { return [][]byte{m.payload}, nil } - var elems []json.RawMessage - if err := json.Unmarshal(m.payload, &elems); err != nil { + var elems []jsontext.Value + if err := json.Unmarshal(m.payload, &elems, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: payload is not a valid JSON array", errTemplate) } @@ -226,7 +228,7 @@ func (m *ruleMessage) batchElements(batch bool) ([][]byte, error) { out := make([][]byte, len(elems)) for i, e := range elems { var s string - if json.Unmarshal(e, &s) == nil { + if json.Unmarshal(e, &s, jsonx.V1()) == nil { out[i] = []byte(s) continue @@ -251,7 +253,7 @@ type dynamoDBWire struct { Operation string `json:"operation"` } -func (h *ruleHook) runDynamoDB(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runDynamoDB(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w dynamoDBWire if err := decodeAction(raw, &w); err != nil { return err @@ -324,10 +326,9 @@ func keyAttribute(keyType, value string) map[string]any { func payloadAttribute(payload []byte) map[string]any { var obj map[string]any - dec := json.NewDecoder(bytes.NewReader(payload)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(payload)) - if err := dec.Decode(&obj); err == nil && obj != nil { + if err := json.UnmarshalDecode(dec, &obj, jsonx.V1(), jsonx.UseNumber()); err == nil && obj != nil { return jsonToAttribute(obj) } @@ -350,7 +351,7 @@ func jsonToAttribute(v any) map[string]any { } return map[string]any{"L": l} - case json.Number: + case jsonx.Number: return map[string]any{"N": t.String()} case string: return map[string]any{"S": t} @@ -368,7 +369,7 @@ type dynamoDBv2Wire struct { } `json:"putItem"` } -func (h *ruleHook) runDynamoDBv2(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runDynamoDBv2(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w dynamoDBv2Wire if err := decodeAction(raw, &w); err != nil { return err @@ -405,7 +406,7 @@ type s3Wire struct { CannedACL string `json:"cannedAcl"` } -func (h *ruleHook) runS3(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runS3(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w s3Wire if err := decodeAction(raw, &w); err != nil { return err @@ -436,7 +437,7 @@ type cloudwatchMetricWire struct { MetricTimestamp string `json:"metricTimestamp"` } -func (h *ruleHook) runCloudwatchMetric(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runCloudwatchMetric(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w cloudwatchMetricWire if err := decodeAction(raw, &w); err != nil { return err @@ -481,7 +482,7 @@ type cloudwatchAlarmWire struct { StateValue string `json:"stateValue"` } -func (h *ruleHook) runCloudwatchAlarm(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runCloudwatchAlarm(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w cloudwatchAlarmWire if err := decodeAction(raw, &w); err != nil { return err @@ -515,7 +516,7 @@ type batchedLogEvent struct { Message *string `json:"message"` } -func (h *ruleHook) runCloudwatchLogs(rule *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runCloudwatchLogs(rule *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w cloudwatchLogsWire if err := decodeAction(raw, &w); err != nil { return err @@ -552,7 +553,7 @@ func (m *ruleMessage) logEvents(batch bool) ([]LogEvent, error) { } var elems []batchedLogEvent - if err := json.Unmarshal(m.payload, &elems); err != nil { + if err := json.Unmarshal(m.payload, &elems, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: batchMode needs an array of {timestamp,message}", errTemplate) } @@ -579,7 +580,7 @@ type stepFunctionsWire struct { ExecutionNamePrefix string `json:"executionNamePrefix"` } -func (h *ruleHook) runStepFunctions(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runStepFunctions(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w stepFunctionsWire if err := decodeAction(raw, &w); err != nil { return err @@ -611,7 +612,7 @@ type iotAnalyticsWire struct { BatchMode bool `json:"batchMode"` } -func (h *ruleHook) runIoTAnalytics(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runIoTAnalytics(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w iotAnalyticsWire if err := decodeAction(raw, &w); err != nil { return err diff --git a/services/iot/rule_authz.go b/services/iot/rule_authz.go index 09d99a536f..f782868565 100644 --- a/services/iot/rule_authz.go +++ b/services/iot/rule_authz.go @@ -2,12 +2,13 @@ package iot import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -122,7 +123,7 @@ func (h *ruleHook) runErrorAction( "base64OriginalPayload": base64.StdEncoding.EncodeToString(msg.original), "failedAction": failedAction, "failedActionReason": "Failed to run action. Message: " + cause.Error(), - }) + }, jsonx.V1()) if err != nil { return } diff --git a/services/iot/rule_http.go b/services/iot/rule_http.go index cbb06ced9b..da5975123c 100644 --- a/services/iot/rule_http.go +++ b/services/iot/rule_http.go @@ -5,7 +5,7 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "io" @@ -18,6 +18,7 @@ import ( v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -60,7 +61,7 @@ type httpWire struct { } // runHTTP posts the projected payload to a URL covered by an ENABLED destination (iot https-rule-action). -func (h *ruleHook) runHTTP(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runHTTP(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w httpWire if err := decodeAction(raw, &w); err != nil { return err @@ -141,7 +142,7 @@ func (b *InMemoryBackend) requireHTTPDestination(rawURL string) error { } func contentTypeFor(payload []byte) string { - if json.Valid(payload) { + if jsontext.Value(payload).IsValid(jsonx.V1()) { return "application/json" } diff --git a/services/iot/rule_http_destinations.go b/services/iot/rule_http_destinations.go index f1c9ce0c6a..10dc0ad5bf 100644 --- a/services/iot/rule_http_destinations.go +++ b/services/iot/rule_http_destinations.go @@ -3,7 +3,7 @@ package iot import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -93,7 +94,7 @@ func sendConfirmation(c confirmation) error { body, err := json.Marshal(map[string]string{ keyArn: c.destARN, "confirmationToken": c.token, "enableUrl": c.enableURL, "messageType": msgTypeConfirmation, - }) + }, jsonx.V1()) if err != nil { return err } @@ -148,7 +149,7 @@ func httpActionsOf(actions []RuleAction, errAction *RuleAction) ([]httpWire, err } var w httpWire - if err := json.Unmarshal(raw, &w); err != nil { + if err := json.Unmarshal(raw, &w, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: http action: %w", ErrValidation, err) } diff --git a/services/iot/rule_lookups.go b/services/iot/rule_lookups.go index 8ef4ef9d18..3687a7cd7a 100644 --- a/services/iot/rule_lookups.go +++ b/services/iot/rule_lookups.go @@ -2,12 +2,13 @@ package iot import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/aws/aws-sdk-go-v2/aws" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -175,7 +176,7 @@ func describeThingJSON(bk *InMemoryBackend, thing string) ([]byte, error) { return nil, err } - return json.Marshal(thingDescription(t)) + return json.Marshal(thingDescription(t), jsonx.V1()) } func thingGroupsJSON(bk *InMemoryBackend, thing string) ([]byte, error) { @@ -190,5 +191,5 @@ func thingGroupsJSON(bk *InMemoryBackend, thing string) ([]byte, error) { groups = append(groups, entry) } - return json.Marshal(map[string]any{keyThingGroups: groups}) + return json.Marshal(map[string]any{keyThingGroups: groups}, jsonx.V1()) } diff --git a/services/iot/rule_republish.go b/services/iot/rule_republish.go index fcf26ef1c7..7cb9fb3fbd 100644 --- a/services/iot/rule_republish.go +++ b/services/iot/rule_republish.go @@ -2,7 +2,7 @@ package iot import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" "strconv" @@ -38,7 +38,7 @@ type republishWire struct { Qos int32 `json:"qos"` } -func (h *ruleHook) runRepublish(_ *TopicRule, msg *ruleMessage, raw json.RawMessage) error { +func (h *ruleHook) runRepublish(_ *TopicRule, msg *ruleMessage, raw jsontext.Value) error { var w republishWire if err := decodeAction(raw, &w); err != nil { return err diff --git a/services/iot/sql_value.go b/services/iot/sql_value.go index 8b04e773ce..d954c35441 100644 --- a/services/iot/sql_value.go +++ b/services/iot/sql_value.go @@ -2,12 +2,15 @@ package iot import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sqlUndefined is the SQL Undefined value: omitted from JSON output. @@ -77,52 +80,55 @@ var errBadJSON = errors.New("invalid json") // decodeJSONValue parses a complete JSON document. func decodeJSONValue(data []byte, v2016 bool) (any, error) { - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(data), jsonx.V1()) v, err := decodeToken(dec, v2016) if err != nil { return nil, err } - if _, err = dec.Token(); !errors.Is(err, io.EOF) { + if _, err = dec.ReadToken(); !errors.Is(err, io.EOF) { return nil, errBadJSON } return v, nil } -func decodeToken(dec *json.Decoder, v2016 bool) (any, error) { - tok, err := dec.Token() +func decodeToken(dec *jsontext.Decoder, v2016 bool) (any, error) { + tok, err := dec.ReadToken() if err != nil { return nil, errBadJSON } - switch t := tok.(type) { - case json.Delim: - if t == '{' { - return decodeObject(dec, v2016) - } - + switch tok.Kind() { + case '{': + return decodeObject(dec, v2016) + case '[': return decodeArray(dec, v2016) - case json.Number: - return sqlNumber(t.String(), v2016), nil + case '0': + return sqlNumber(tok.String(), v2016), nil + case '"': + return tok.String(), nil + case 't', 'f': + return tok.Bool(), nil default: - return t, nil + var null any + + return null, nil } } -func decodeObject(dec *json.Decoder, v2016 bool) (any, error) { +func decodeObject(dec *jsontext.Decoder, v2016 bool) (any, error) { obj := newSQLObject() - for dec.More() { - kt, err := dec.Token() - - key, ok := kt.(string) - if err != nil || !ok { + for dec.PeekKind() != '}' { + kt, err := dec.ReadToken() + if err != nil || kt.Kind() != '"' { return nil, errBadJSON } + key := kt.String() + v, verr := decodeToken(dec, v2016) if verr != nil { return nil, verr @@ -131,17 +137,17 @@ func decodeObject(dec *json.Decoder, v2016 bool) (any, error) { obj.set(key, v) } - if _, err := dec.Token(); err != nil { + if _, err := dec.ReadToken(); err != nil { return nil, errBadJSON } return obj, nil } -func decodeArray(dec *json.Decoder, v2016 bool) (any, error) { +func decodeArray(dec *jsontext.Decoder, v2016 bool) (any, error) { arr := []any{} - for dec.More() { + for dec.PeekKind() != ']' { v, err := decodeToken(dec, v2016) if err != nil { return nil, err @@ -150,7 +156,7 @@ func decodeArray(dec *json.Decoder, v2016 bool) (any, error) { arr = append(arr, v) } - if _, err := dec.Token(); err != nil { + if _, err := dec.ReadToken(); err != nil { return nil, errBadJSON } @@ -163,7 +169,7 @@ func writeJSONValue(buf *bytes.Buffer, v any) { case nil: buf.WriteString(jsonNull) case bool, string: - b, _ := json.Marshal(t) + b, _ := json.Marshal(t, jsonx.V1()) buf.Write(b) case int64: buf.WriteString(strconv.FormatInt(t, 10)) @@ -174,7 +180,7 @@ func writeJSONValue(buf *bytes.Buffer, v any) { case *sqlObject: writeJSONObject(buf, t) case sqlRaw: - b, _ := json.Marshal(string(t)) + b, _ := json.Marshal(string(t), jsonx.V1()) buf.Write(b) default: buf.WriteString(jsonNull) @@ -212,7 +218,7 @@ func writeJSONObject(buf *bytes.Buffer, o *sqlObject) { first = false - kb, _ := json.Marshal(k) + kb, _ := json.Marshal(k, jsonx.V1()) buf.Write(kb) buf.WriteByte(':') writeJSONValue(buf, v) diff --git a/services/iot/things_test.go b/services/iot/things_test.go index b2fa7b2de8..3ec6255e3c 100644 --- a/services/iot/things_test.go +++ b/services/iot/things_test.go @@ -1,7 +1,7 @@ package iot_test import ( - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iot" ) @@ -705,8 +706,8 @@ func TestUpdateThing_MergeFalse_ReplacesAttributes(t *testing.T) { require.NoError(t, err) var bodyAttr iot.AttributePayload - raw, _ := json.Marshal(tt.updateBody["attributePayload"]) - require.NoError(t, json.Unmarshal(raw, &bodyAttr)) + raw, _ := json.Marshal(tt.updateBody["attributePayload"], jsonx.V1()) + require.NoError(t, json.Unmarshal(raw, &bodyAttr, jsonx.V1())) err = b.UpdateThing(&iot.UpdateThingInput{ ThingName: "merge-test", diff --git a/services/iot/topic_rules.go b/services/iot/topic_rules.go index af4c0ca34d..b6563239e9 100644 --- a/services/iot/topic_rules.go +++ b/services/iot/topic_rules.go @@ -1,7 +1,7 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -26,9 +26,9 @@ func cloneRuleAction(a RuleAction) RuleAction { out.SNS = &cp } if len(a.Other) > 0 { - out.Other = make(map[string]json.RawMessage, len(a.Other)) + out.Other = make(map[string]jsontext.Value, len(a.Other)) for k, v := range a.Other { - out.Other[k] = append(json.RawMessage(nil), v...) + out.Other[k] = append(jsontext.Value(nil), v...) } } diff --git a/services/iot/types.go b/services/iot/types.go index dfbec94c99..7ac37530b2 100644 --- a/services/iot/types.go +++ b/services/iot/types.go @@ -3,9 +3,12 @@ package iot import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Thing represents an AWS IoT Thing. @@ -54,15 +57,15 @@ type RuleAction struct { Lambda *LambdaAction `json:"lambda,omitempty"` SNS *SNSAction `json:"sns,omitempty"` // Other holds action types with no typed model (s3, dynamoDB, ...), kept verbatim. - Other map[string]json.RawMessage `json:"-"` + Other map[string]jsontext.Value `json:"-"` } const typedRuleActionKeys = 3 // UnmarshalJSON decodes the typed actions and keeps every other key verbatim. func (a *RuleAction) UnmarshalJSON(data []byte) error { - var raw map[string]json.RawMessage - if err := json.Unmarshal(data, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return err } *a = RuleAction{} @@ -73,14 +76,14 @@ func (a *RuleAction) UnmarshalJSON(data []byte) error { var err error switch k { case "sqs": - err = json.Unmarshal(v, &a.SQS) + err = json.Unmarshal(v, &a.SQS, jsonx.V1()) case "lambda": - err = json.Unmarshal(v, &a.Lambda) + err = json.Unmarshal(v, &a.Lambda, jsonx.V1()) case "sns": - err = json.Unmarshal(v, &a.SNS) + err = json.Unmarshal(v, &a.SNS, jsonx.V1()) default: if a.Other == nil { - a.Other = map[string]json.RawMessage{} + a.Other = map[string]jsontext.Value{} } a.Other[k] = v } @@ -106,10 +109,10 @@ func (a RuleAction) MarshalJSON() ([]byte, error) { out["sns"] = a.SNS } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } -func castRaw(in map[string]json.RawMessage) map[string]any { +func castRaw(in map[string]jsontext.Value) map[string]any { out := make(map[string]any, len(in)) for k, v := range in { out[k] = v diff --git a/services/iotanalytics/handler_channels.go b/services/iotanalytics/handler_channels.go index 256e18006c..2ac6b4881a 100644 --- a/services/iotanalytics/handler_channels.go +++ b/services/iotanalytics/handler_channels.go @@ -1,16 +1,18 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateChannel(c *echo.Context, body []byte) error { var req createChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -114,7 +116,7 @@ func (h *Handler) handleUpdateChannel(c *echo.Context, name string, body []byte) var req updateChannelRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/iotanalytics/handler_channels_test.go b/services/iotanalytics/handler_channels_test.go index 09fb7bd4b0..147fece4f6 100644 --- a/services/iotanalytics/handler_channels_test.go +++ b/services/iotanalytics/handler_channels_test.go @@ -1,13 +1,15 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAndDescribeChannel(t *testing.T) { @@ -85,7 +87,7 @@ func TestHandler_ListChannels(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - err := json.Unmarshal(rec.Body.Bytes(), &resp) + err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) require.NoError(t, err) summaries, ok := resp["channelSummaries"].([]any) @@ -270,7 +272,7 @@ func TestHandler_SampleChannelData_WithMessages(t *testing.T) { require.Equal(t, http.StatusOK, sampleRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sampleRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sampleRec.Body.Bytes(), &resp, jsonx.V1())) payloads, ok := resp["payloads"].([]any) require.True(t, ok) assert.Len(t, payloads, 2) @@ -394,7 +396,7 @@ func TestHandler_DescribeChannel_NewFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "describe response must contain field %q", field) } @@ -435,7 +437,7 @@ func TestHandler_CreateChannel_RetentionPeriodInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasRP := resp["retentionPeriod"] assert.Equal(t, tt.wantRetention, hasRP) }) @@ -484,7 +486,7 @@ func TestHandler_DescribeChannel_IncludeStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasStats := resp["statistics"] assert.Equal(t, tt.wantStatistics, hasStats) }) @@ -508,7 +510,7 @@ func TestHandler_ListChannels_ChannelStorage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["channelSummaries"].([]any) require.Len(t, summaries, 1) summary, _ := summaries[0].(map[string]any) diff --git a/services/iotanalytics/handler_datasets.go b/services/iotanalytics/handler_datasets.go index a2a53967d1..7376eeb4dc 100644 --- a/services/iotanalytics/handler_datasets.go +++ b/services/iotanalytics/handler_datasets.go @@ -1,12 +1,14 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseQueryDateTime parses a scheduledBefore/scheduledOnOrAfter query parameter into epoch @@ -61,7 +63,7 @@ func filterDatasetContentsBySchedule(contents []*DatasetContent, c *echo.Context func (h *Handler) handleCreateDataset(c *echo.Context, body []byte) error { var req createDatasetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -190,7 +192,7 @@ func (h *Handler) handleUpdateDataset(c *echo.Context, name string, body []byte) var req updateDatasetRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -222,7 +224,7 @@ func (h *Handler) handleCreateDatasetContent(c *echo.Context, datasetName string var req createDatasetContentRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/iotanalytics/handler_datasets_test.go b/services/iotanalytics/handler_datasets_test.go index 44fe78cca5..ade737561a 100644 --- a/services/iotanalytics/handler_datasets_test.go +++ b/services/iotanalytics/handler_datasets_test.go @@ -1,7 +1,7 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAndDescribeDataset(t *testing.T) { @@ -101,7 +103,7 @@ func TestHandler_DatasetContentLifecycle(t *testing.T) { if tt.wantList == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["datasetContentSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -140,7 +142,7 @@ func TestHandler_CreateDatasetContent_ExplicitVersionID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-custom-version", resp["versionId"]) getRec := doRequest(t, h, http.MethodGet, "/datasets/explicit_ver_ds/content?versionId=my-custom-version", nil) @@ -189,7 +191,7 @@ func TestHandler_GetDatasetContent_MagicVersionStrings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) status, _ := resp["status"].(map[string]any) assert.Equal(t, "SUCCEEDED", status["state"]) @@ -214,7 +216,7 @@ func TestHandler_DeleteDatasetContent_OmittedVersionDeletesOnlyLatest(t *testing if i == 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) firstVersion, _ = resp["versionId"].(string) require.NotEmpty(t, firstVersion) } @@ -227,7 +229,7 @@ func TestHandler_DeleteDatasetContent_OmittedVersionDeletesOnlyLatest(t *testing require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, _ := listResp["datasetContentSummaries"].([]any) require.Len(t, summaries, 2, "omitted versionId must delete exactly one version") @@ -259,7 +261,7 @@ func TestHandler_ListDatasetContents_PaginationAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) vid, _ := resp["versionId"].(string) require.NotEmpty(t, vid) wantVersions[vid] = true @@ -273,7 +275,7 @@ func TestHandler_ListDatasetContents_PaginationAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["datasetContentSummaries"].([]any) for _, s := range summaries { @@ -315,7 +317,7 @@ func TestHandler_ListDatasetContents_ScheduleTime(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["datasetContentSummaries"].([]any) require.Len(t, summaries, 1) @@ -360,7 +362,7 @@ func TestHandler_ListDatasetContents_ScheduledFilters(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["datasetContentSummaries"].([]any) assert.Len(t, summaries, tt.wantLen) @@ -422,7 +424,7 @@ func TestHandler_Datasets(t *testing.T) { listRec := doRequest(t, h, http.MethodGet, "/datasets", nil) assert.Equal(t, tt.wantStatus, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["datasetSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -478,7 +480,7 @@ func TestHandler_DatasetContent_GetVersionSpecific(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) versionID, ok := createResp["versionId"].(string) require.True(t, ok) require.NotEmpty(t, versionID) @@ -542,7 +544,7 @@ func TestHandler_DescribeDataset_NewFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "describe response must contain field %q", field) } @@ -566,7 +568,7 @@ func TestHandler_GetDatasetContent_VersionAndEntries(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasVersionID := resp["versionId"] assert.False(t, hasVersionID, "GetDatasetContent must not return versionId -- AWS has no such member") _, hasStatus := resp["status"] @@ -608,7 +610,7 @@ func TestHandler_DeleteDatasetContent_RequiresVersionId(t *testing.T) { deletePath := tt.path if deletePath == "" { var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) vid, _ := cr["versionId"].(string) require.NotEmpty(t, vid) deletePath = "/datasets/delcontds/content?versionId=" + vid @@ -635,7 +637,7 @@ func TestHandler_ListDatasetContents_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["nextToken"], "nextToken must be set when results are truncated") summaries, _ := resp["datasetContentSummaries"].([]any) assert.Len(t, summaries, 2) diff --git a/services/iotanalytics/handler_datastores.go b/services/iotanalytics/handler_datastores.go index bdc65b22ae..c8712dee56 100644 --- a/services/iotanalytics/handler_datastores.go +++ b/services/iotanalytics/handler_datastores.go @@ -1,15 +1,17 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateDatastore(c *echo.Context, body []byte) error { var req createDatastoreRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -135,7 +137,7 @@ func (h *Handler) handleUpdateDatastore(c *echo.Context, name string, body []byt var req updateDatastoreRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/iotanalytics/handler_datastores_test.go b/services/iotanalytics/handler_datastores_test.go index 4a9c9e205f..f0f66f40be 100644 --- a/services/iotanalytics/handler_datastores_test.go +++ b/services/iotanalytics/handler_datastores_test.go @@ -1,12 +1,14 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAndDescribeDatastore(t *testing.T) { @@ -125,7 +127,7 @@ func TestHandler_Datastores(t *testing.T) { listRec := doRequest(t, h, http.MethodGet, "/datastores", nil) assert.Equal(t, tt.wantStatus, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["datastoreSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -207,7 +209,7 @@ func TestHandler_DescribeDatastore_NewFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "describe response must contain field %q", field) } @@ -248,7 +250,7 @@ func TestHandler_CreateDatastore_RetentionPeriodInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasRP := resp["retentionPeriod"] assert.Equal(t, tt.wantRetention, hasRP) }) @@ -292,7 +294,7 @@ func TestHandler_DescribeDatastore_IncludeStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasStats := resp["statistics"] assert.Equal(t, tt.wantStatistics, hasStats) }) @@ -316,7 +318,7 @@ func TestHandler_ListDatastores_DatastoreStorage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["datastoreSummaries"].([]any) require.Len(t, summaries, 1) summary, _ := summaries[0].(map[string]any) diff --git a/services/iotanalytics/handler_logging.go b/services/iotanalytics/handler_logging.go index c10d9bd8d6..376cf5801b 100644 --- a/services/iotanalytics/handler_logging.go +++ b/services/iotanalytics/handler_logging.go @@ -1,10 +1,12 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeLoggingOptions(c *echo.Context) error { @@ -24,7 +26,7 @@ func (h *Handler) handleDescribeLoggingOptions(c *echo.Context) error { func (h *Handler) handlePutLoggingOptions(c *echo.Context, body []byte) error { var req putLoggingOptionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/iotanalytics/handler_logging_test.go b/services/iotanalytics/handler_logging_test.go index 46508535ff..402b97ec90 100644 --- a/services/iotanalytics/handler_logging_test.go +++ b/services/iotanalytics/handler_logging_test.go @@ -1,12 +1,14 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_LoggingOptions(t *testing.T) { @@ -64,7 +66,7 @@ func TestHandler_LoggingOptions(t *testing.T) { if tt.wantDescribe == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) opts, ok := resp["loggingOptions"].(map[string]any) require.True(t, ok) assert.Equal(t, "ERROR", opts["level"]) diff --git a/services/iotanalytics/handler_messages.go b/services/iotanalytics/handler_messages.go index e9da65197c..5be56842c3 100644 --- a/services/iotanalytics/handler_messages.go +++ b/services/iotanalytics/handler_messages.go @@ -1,16 +1,18 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleBatchPutMessage(c *echo.Context, body []byte) error { var req batchPutMessageRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/iotanalytics/handler_messages_test.go b/services/iotanalytics/handler_messages_test.go index 2b532ff521..9b5ada8821 100644 --- a/services/iotanalytics/handler_messages_test.go +++ b/services/iotanalytics/handler_messages_test.go @@ -1,13 +1,15 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_BatchPutMessage(t *testing.T) { @@ -67,7 +69,7 @@ func TestHandler_BatchPutMessage(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) entries, _ := resp["batchPutMessageErrorEntries"].([]any) assert.Len(t, entries, tt.wantErrors) } @@ -149,7 +151,7 @@ func TestHandler_BatchPutMessage_NoChannelNameInErrorEntry(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) entries, _ := resp["batchPutMessageErrorEntries"].([]any) require.Len(t, entries, 1) entry, _ := entries[0].(map[string]any) diff --git a/services/iotanalytics/handler_pipelines.go b/services/iotanalytics/handler_pipelines.go index 5897b777a0..ddb13bf253 100644 --- a/services/iotanalytics/handler_pipelines.go +++ b/services/iotanalytics/handler_pipelines.go @@ -1,16 +1,18 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreatePipeline(c *echo.Context, body []byte) error { var req createPipelineRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -97,7 +99,7 @@ func (h *Handler) handleUpdatePipeline(c *echo.Context, name string, body []byte var req updatePipelineRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -126,7 +128,7 @@ func (h *Handler) handleStartPipelineReprocessing(c *echo.Context, pipelineName var req startPipelineReprocessingRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -162,7 +164,7 @@ func (h *Handler) handleCancelPipelineReprocessing(c *echo.Context, resource str func (h *Handler) handleRunPipelineActivity(c *echo.Context, body []byte) error { var req runPipelineActivityRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/iotanalytics/handler_pipelines_test.go b/services/iotanalytics/handler_pipelines_test.go index 4a99b42814..0e98f62387 100644 --- a/services/iotanalytics/handler_pipelines_test.go +++ b/services/iotanalytics/handler_pipelines_test.go @@ -1,12 +1,14 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAndDescribePipeline(t *testing.T) { @@ -105,7 +107,7 @@ func TestHandler_StartAndCancelPipelineReprocessing(t *testing.T) { if tt.wantStart == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &resp, jsonx.V1())) reprocessingID, ok := resp["reprocessingId"].(string) require.True(t, ok) assert.NotEmpty(t, reprocessingID) @@ -169,7 +171,7 @@ func TestHandler_RunPipelineActivity(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) payloads, _ := resp["payloads"].([]any) assert.Len(t, payloads, tt.wantLen) } @@ -233,7 +235,7 @@ func TestHandler_Pipelines(t *testing.T) { listRec := doRequest(t, h, http.MethodGet, "/pipelines", nil) assert.Equal(t, tt.wantStatus, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["pipelineSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -350,7 +352,7 @@ func TestHandler_DescribePipeline_NewFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field, "describe response must contain field %q", field) } @@ -452,7 +454,7 @@ func TestHandler_ReprocessingSummaries_Sorted(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &resp, jsonx.V1())) ids[i], _ = resp["reprocessingId"].(string) require.NotEmpty(t, ids[i]) } @@ -462,7 +464,7 @@ func TestHandler_ReprocessingSummaries_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) pipeline, ok := resp["pipeline"].(map[string]any) require.True(t, ok) summaries, ok := pipeline["reprocessingSummaries"].([]any) @@ -510,7 +512,7 @@ func TestHandler_PipelineReprocessingSummary_NoStartEndTimeLeak(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) pl, _ := resp["pipeline"].(map[string]any) summaries, _ := pl["reprocessingSummaries"].([]any) require.Len(t, summaries, 1) diff --git a/services/iotanalytics/handler_sdk_route_table_test.go b/services/iotanalytics/handler_sdk_route_table_test.go index ca841ecf3e..944ad8cf44 100644 --- a/services/iotanalytics/handler_sdk_route_table_test.go +++ b/services/iotanalytics/handler_sdk_route_table_test.go @@ -1,7 +1,7 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sdkRouteCases is the authoritative method+path for every real IoT @@ -113,7 +115,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var resp struct { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEqual(t, "not found", resp.Message, "method=%s path=%s op=%s: dispatched to the unmatched-route default", tc.method, tc.path, tc.op) }) diff --git a/services/iotanalytics/handler_tags.go b/services/iotanalytics/handler_tags.go index 4009a59beb..5db478f222 100644 --- a/services/iotanalytics/handler_tags.go +++ b/services/iotanalytics/handler_tags.go @@ -1,10 +1,12 @@ package iotanalytics import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTagsForResource(c *echo.Context) error { @@ -38,7 +40,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { } var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/iotanalytics/handler_tags_test.go b/services/iotanalytics/handler_tags_test.go index cc2fedb9b6..a4366d8936 100644 --- a/services/iotanalytics/handler_tags_test.go +++ b/services/iotanalytics/handler_tags_test.go @@ -1,13 +1,15 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_TagOperations covers ListTagsForResource/TagResource/UntagResource. @@ -63,7 +65,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn, _ := createResp["channelArn"].(string) require.NotEmpty(t, arn) @@ -152,7 +154,7 @@ func TestHandler_CreateResource_InvalidTagsRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errResp["__type"]) okRec := doRequest(t, h, http.MethodPost, tt.path, tt.body(validTags)) @@ -191,7 +193,7 @@ func TestHandler_TagResource_Returns204(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["channelArn"].(string) require.NotEmpty(t, arn) @@ -252,7 +254,7 @@ func TestHandler_TagValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["channelArn"].(string) require.NotEmpty(t, arn) @@ -306,7 +308,7 @@ func TestHandler_ListTagsForResource_EmptyNotError(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn, _ := createResp[tt.arnKey].(string) require.NotEmpty(t, arn) @@ -314,7 +316,7 @@ func TestHandler_ListTagsForResource_EmptyNotError(t *testing.T) { assert.Equal(t, http.StatusOK, tagRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp, jsonx.V1())) tags, ok := tagResp["tags"].([]any) require.True(t, ok, "tags field must be array") assert.Empty(t, tags, "newly created resource must have empty tag array") diff --git a/services/iotanalytics/handler_test.go b/services/iotanalytics/handler_test.go index 0f0b1dbc52..5ab9ab69ab 100644 --- a/services/iotanalytics/handler_test.go +++ b/services/iotanalytics/handler_test.go @@ -2,7 +2,7 @@ package iotanalytics_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotanalytics" ) @@ -47,7 +48,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -321,7 +322,7 @@ func TestHandler_AlreadyExistsErrorType(t *testing.T) { require.Equal(t, http.StatusConflict, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceAlreadyExistsException", resp["__type"]) }) } @@ -387,7 +388,7 @@ func TestHandler_ErrorResponseFormat(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"], "error response must have __type field") assert.NotEmpty(t, resp["message"], "error response must have message field") }) @@ -626,7 +627,7 @@ func TestHandler_Pagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp[summaryKey].([]any) require.True(t, ok) assert.Len(t, summaries, tt.wantLen) @@ -658,7 +659,7 @@ func TestHandler_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) summaries1, ok := resp1["channelSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries1, 2) @@ -671,7 +672,7 @@ func TestHandler_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) summaries2, ok := resp2["channelSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries2, 1, "page 2 should have the remaining 1 channel") diff --git a/services/iotanalytics/persistence.go b/services/iotanalytics/persistence.go index 8f03b63400..e6919698f2 100644 --- a/services/iotanalytics/persistence.go +++ b/services/iotanalytics/persistence.go @@ -2,7 +2,7 @@ package iotanalytics import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -42,7 +42,7 @@ const iotanalyticsSnapshotVersion = 2 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` ChannelMessages map[string][]ChannelMessage `json:"channelMessages"` DatasetContents map[string][]*DatasetContent `json:"datasetContents"` diff --git a/services/iotanalytics/pipeline_expr_test.go b/services/iotanalytics/pipeline_expr_test.go index 795cf6ad4a..89022c7885 100644 --- a/services/iotanalytics/pipeline_expr_test.go +++ b/services/iotanalytics/pipeline_expr_test.go @@ -1,12 +1,13 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotanalytics" ) @@ -246,7 +247,7 @@ func TestInMemoryBackend_RunPipelineActivity_Math(t *testing.T) { } var decoded map[string]any - require.NoError(t, json.Unmarshal(out[0], &decoded)) + require.NoError(t, json.Unmarshal(out[0], &decoded, jsonx.V1())) assert.InDelta(t, tt.wantValue, decoded[tt.attribute], 1e-9) }) } diff --git a/services/iotanalytics/pipeline_lambda_iot_test.go b/services/iotanalytics/pipeline_lambda_iot_test.go index 63d4a9d439..9037db1c84 100644 --- a/services/iotanalytics/pipeline_lambda_iot_test.go +++ b/services/iotanalytics/pipeline_lambda_iot_test.go @@ -2,13 +2,14 @@ package iotanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotanalytics" ) @@ -43,7 +44,7 @@ func echoAddFieldLambda(calls *[]string) *fakeLambdaInvoker { calls: calls, invoke: func(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { var msgs []map[string]any - if err := json.Unmarshal(payload, &msgs); err != nil { + if err := json.Unmarshal(payload, &msgs, jsonx.V1()); err != nil { return nil, 0, err } @@ -51,7 +52,7 @@ func echoAddFieldLambda(calls *[]string) *fakeLambdaInvoker { m["seen"] = true } - out, err := json.Marshal(msgs) + out, err := json.Marshal(msgs, jsonx.V1()) return out, 200, err }, @@ -105,7 +106,7 @@ func TestInMemoryBackend_RunPipelineActivity_Lambda(t *testing.T) { require.Len(t, out, 1) var decoded map[string]any - require.NoError(t, json.Unmarshal(out[0], &decoded)) + require.NoError(t, json.Unmarshal(out[0], &decoded, jsonx.V1())) assert.Equal(t, true, decoded["seen"]) assert.InDelta(t, 1.0, decoded["x"], 1e-9) }) @@ -130,11 +131,11 @@ func TestInMemoryBackend_RunPipelineActivity_Lambda(t *testing.T) { require.Len(t, calls, 2, "3 payloads at batchSize=2 must invoke twice (2 then 1)") var firstBatch []map[string]any - require.NoError(t, json.Unmarshal([]byte(calls[0]), &firstBatch)) + require.NoError(t, json.Unmarshal([]byte(calls[0]), &firstBatch, jsonx.V1())) assert.Len(t, firstBatch, 2) var secondBatch []map[string]any - require.NoError(t, json.Unmarshal([]byte(calls[1]), &secondBatch)) + require.NoError(t, json.Unmarshal([]byte(calls[1]), &secondBatch, jsonx.V1())) assert.Len(t, secondBatch, 1) }) @@ -218,7 +219,7 @@ func TestInMemoryBackend_RunPipelineActivity_DeviceRegistryEnrich(t *testing.T) require.Len(t, out, 1) var decoded map[string]any - require.NoError(t, json.Unmarshal(out[0], &decoded)) + require.NoError(t, json.Unmarshal(out[0], &decoded, jsonx.V1())) registry, ok := decoded["registry"].(map[string]any) require.True(t, ok) @@ -270,7 +271,7 @@ func TestInMemoryBackend_RunPipelineActivity_DeviceShadowEnrich(t *testing.T) { require.Len(t, out, 1) var decoded map[string]any - require.NoError(t, json.Unmarshal(out[0], &decoded)) + require.NoError(t, json.Unmarshal(out[0], &decoded, jsonx.V1())) shadow, ok := decoded["shadow"].(map[string]any) require.True(t, ok) diff --git a/services/iotanalytics/pipelines.go b/services/iotanalytics/pipelines.go index e4fbc43467..dccf1d6074 100644 --- a/services/iotanalytics/pipelines.go +++ b/services/iotanalytics/pipelines.go @@ -3,13 +3,15 @@ package iotanalytics import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // clonePipelineActivities deep-copies a slice of PipelineActivity. @@ -371,7 +373,7 @@ func (b *InMemoryBackend) invokeLambdaBatch(ctx context.Context, lambdaName stri return nil } - reqBody, err := json.Marshal(msgs) + reqBody, err := json.Marshal(msgs, jsonx.V1()) if err != nil { return fmt.Errorf("%w: marshal lambda batch for %q: %w", ErrPipelineActivityFailed, lambdaName, err) } @@ -382,7 +384,7 @@ func (b *InMemoryBackend) invokeLambdaBatch(ctx context.Context, lambdaName stri } var results []map[string]any - if jsonErr := json.Unmarshal(respBody, &results); jsonErr != nil || len(results) != len(msgs) { + if jsonErr := json.Unmarshal(respBody, &results, jsonx.V1()); jsonErr != nil || len(results) != len(msgs) { return fmt.Errorf( "%w: lambda activity %q did not return a JSON object array of the same length", ErrPipelineActivityFailed, lambdaName, @@ -464,7 +466,7 @@ func enrichPayloads(attribute string, data map[string]any, payloads [][]byte) [] // decodeMessage attempts to unmarshal a message payload as a JSON object. func decodeMessage(payload []byte) (map[string]any, bool) { var m map[string]any - if err := json.Unmarshal(payload, &m); err != nil { + if err := json.Unmarshal(payload, &m, jsonx.V1()); err != nil { return nil, false } @@ -475,7 +477,7 @@ func decodeMessage(payload []byte) (map[string]any, bool) { // marshaling somehow fails (m came from a successful Unmarshal, so this is unreachable in // practice, but encodeMessage must never panic or drop data on error). func encodeMessage(m map[string]any, fallback []byte) []byte { - b, err := json.Marshal(m) + b, err := json.Marshal(m, jsonx.V1()) if err != nil { return fallback } diff --git a/services/iotanalytics/pipelines_test.go b/services/iotanalytics/pipelines_test.go index 05cd8cd9b4..78e24be74d 100644 --- a/services/iotanalytics/pipelines_test.go +++ b/services/iotanalytics/pipelines_test.go @@ -2,12 +2,13 @@ package iotanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotanalytics" ) @@ -230,7 +231,7 @@ func TestInMemoryBackend_RunPipelineActivity_AttributeActivities(t *testing.T) { } var decoded map[string]any - require.NoError(t, json.Unmarshal(out[0], &decoded)) + require.NoError(t, json.Unmarshal(out[0], &decoded, jsonx.V1())) assert.Len(t, decoded, len(tt.wantKeys)) for k, v := range tt.wantKeys { diff --git a/services/iotanalytics/wire_shape_sdk_roundtrip_test.go b/services/iotanalytics/wire_shape_sdk_roundtrip_test.go index b0ff62716e..462c973a08 100644 --- a/services/iotanalytics/wire_shape_sdk_roundtrip_test.go +++ b/services/iotanalytics/wire_shape_sdk_roundtrip_test.go @@ -1,7 +1,7 @@ package iotanalytics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotanalytics" ) @@ -226,7 +227,7 @@ func TestListSummaries_NoFabricatedARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp[tt.summariesK].([]any) require.True(t, ok) @@ -273,7 +274,7 @@ func TestDatastore_IotSiteWiseCustomerManagedS3Storage_NoRoleArn(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) datastore, ok := resp["datastore"].(map[string]any) require.True(t, ok) diff --git a/services/iotdataplane/connections_test.go b/services/iotdataplane/connections_test.go index 1b0b74ba1f..0aee54e023 100644 --- a/services/iotdataplane/connections_test.go +++ b/services/iotdataplane/connections_test.go @@ -2,7 +2,7 @@ package iotdataplane_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -209,7 +210,7 @@ func Test_ListConnections_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) conns := resp["connections"].([]any) assert.Empty(t, conns) } @@ -257,7 +258,7 @@ func Test_ListConnections_ShowsRegistered(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) conns := resp["connections"].([]any) assert.Len(t, conns, 2) } @@ -323,7 +324,7 @@ func Test_AdminConnectionsPath_BasicFlow(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/_admin/connections", nil) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["connections"].([]any), 1) // Delete. @@ -393,7 +394,7 @@ func Test_Connection_Register_DuplicateShape(t *testing.T) { require.Equal(t, http.StatusConflict, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ConflictException", resp["error"]) } func Test_Connection_EmptyClientID_Rejected(t *testing.T) { @@ -414,7 +415,7 @@ func Test_Connection_DollarPrefix_Rejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["error"]) } func Test_Connection_DeleteUnknown_NotFound_DollarStillRejected(t *testing.T) { @@ -457,7 +458,7 @@ func Test_DeleteConnection_UnknownClient_HTTPShape(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["error"]) }) } @@ -568,7 +569,7 @@ func TestHandler_GetConnection_WireShape(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.clientID, resp["clientId"]) assert.Equal(t, true, resp["connected"]) assert.NotZero(t, resp["connectedSince"]) @@ -661,7 +662,7 @@ func TestHandler_ListSubscriptions_WireShape(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) subs, ok := resp["subscriptions"].([]any) require.True(t, ok) assert.Len(t, subs, len(tt.brokerSubs)) @@ -753,7 +754,7 @@ func TestHandler_ListSubscriptions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) subs, ok := resp["subscriptions"].([]any) require.True(t, ok) @@ -985,7 +986,7 @@ func TestHandler_SendDirectMessage_WireShape(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "OK", resp["message"]) assert.NotEmpty(t, resp["traceId"]) @@ -1081,7 +1082,7 @@ func Test_GetConnection_AfterDelete(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, false, resp["connected"]) assert.Equal(t, "SERVER_INITIATED_DISCONNECT", resp["disconnectReason"]) assert.NotZero(t, resp["disconnectedSince"]) diff --git a/services/iotdataplane/export_test.go b/services/iotdataplane/export_test.go index 0dab9f5829..ddbca34063 100644 --- a/services/iotdataplane/export_test.go +++ b/services/iotdataplane/export_test.go @@ -1,9 +1,11 @@ package iotdataplane -import "encoding/json" +import ( + "encoding/json/jsontext" +) // MergeStateFields exposes mergeStateFields for white-box testing. -func MergeStateFields(base, patch map[string]json.RawMessage) map[string]json.RawMessage { +func MergeStateFields(base, patch map[string]jsontext.Value) map[string]jsontext.Value { return mergeStateFields(base, patch) } @@ -80,7 +82,7 @@ func ForceSetShadowVersion(b *InMemoryBackend, thingName, shadowName string, ver } // GetShadowDesired returns the desired state map for white-box testing. -func GetShadowDesired(b *InMemoryBackend, thingName, shadowName string) map[string]json.RawMessage { +func GetShadowDesired(b *InMemoryBackend, thingName, shadowName string) map[string]jsontext.Value { b.mu.RLock("GetShadowDesired") defer b.mu.RUnlock() @@ -93,7 +95,7 @@ func GetShadowDesired(b *InMemoryBackend, thingName, shadowName string) map[stri } // GetShadowReported returns the reported state map for white-box testing. -func GetShadowReported(b *InMemoryBackend, thingName, shadowName string) map[string]json.RawMessage { +func GetShadowReported(b *InMemoryBackend, thingName, shadowName string) map[string]jsontext.Value { b.mu.RLock("GetShadowReported") defer b.mu.RUnlock() diff --git a/services/iotdataplane/handler_publish.go b/services/iotdataplane/handler_publish.go index 9d6747495b..d4dee28cf0 100644 --- a/services/iotdataplane/handler_publish.go +++ b/services/iotdataplane/handler_publish.go @@ -1,7 +1,8 @@ package iotdataplane import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -39,12 +41,12 @@ func unwrapPublishPayload(body []byte, contentType string) []byte { } var wrapper struct { - Payload *json.RawMessage `json:"payload"` + Payload *jsontext.Value `json:"payload"` } - if jsonErr := json.Unmarshal(body, &wrapper); jsonErr == nil && wrapper.Payload != nil { + if jsonErr := json.Unmarshal(body, &wrapper, jsonx.V1()); jsonErr == nil && wrapper.Payload != nil { var payloadStr string - if unmarshalErr := json.Unmarshal(*wrapper.Payload, &payloadStr); unmarshalErr == nil { + if unmarshalErr := json.Unmarshal(*wrapper.Payload, &payloadStr, jsonx.V1()); unmarshalErr == nil { return []byte(payloadStr) } } diff --git a/services/iotdataplane/handler_sdk_route_table_test.go b/services/iotdataplane/handler_sdk_route_table_test.go index 7f8385d37f..3a695d2f08 100644 --- a/services/iotdataplane/handler_sdk_route_table_test.go +++ b/services/iotdataplane/handler_sdk_route_table_test.go @@ -1,7 +1,7 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sdkRouteCases is the authoritative method+path for every real IoT Data @@ -96,7 +98,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var decoded struct { Error string `json:"error"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &decoded, jsonx.V1())) assert.NotEqual(t, "not found", decoded.Error, "method=%s path=%s op=%s: dispatched to the unmatched-route default", tc.method, tc.path, tc.op) }) diff --git a/services/iotdataplane/handler_test.go b/services/iotdataplane/handler_test.go index 77639ec0aa..270972c7c7 100644 --- a/services/iotdataplane/handler_test.go +++ b/services/iotdataplane/handler_test.go @@ -2,7 +2,7 @@ package iotdataplane_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -609,7 +610,7 @@ func Test_ErrorShapes_AllTypes(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code, "unexpected status for %s %s", tt.method, tt.path) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantError, resp["error"], "unexpected error type for %s %s", tt.method, tt.path) _, hasMsg := resp["message"] @@ -629,7 +630,7 @@ func Test_VersionConflict_ErrorShape(t *testing.T) { require.Equal(t, http.StatusConflict, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ConflictException", resp["error"]) assert.NotContains(t, resp, "code", "a numeric code breaks the SDK's string-typed body decode") } diff --git a/services/iotdataplane/models.go b/services/iotdataplane/models.go index e90c08b904..d598d57729 100644 --- a/services/iotdataplane/models.go +++ b/services/iotdataplane/models.go @@ -1,7 +1,7 @@ package iotdataplane import ( - "encoding/json" + "encoding/json/jsontext" "regexp" "time" ) @@ -57,10 +57,10 @@ var _ StorageBackend = (*InMemoryBackend)(nil) // never JSON-marshaled directly; shadowEntrySnap (persistence.go) is its serialisable form. type shadowEntry struct { updatedAt time.Time - desired map[string]json.RawMessage // nil = not set - reported map[string]json.RawMessage // nil = not set - metaDesired map[string]int64 // field → epoch seconds of last update - metaReported map[string]int64 // field → epoch seconds of last update + desired map[string]jsontext.Value // nil = not set + reported map[string]jsontext.Value // nil = not set + metaDesired map[string]int64 // field → epoch seconds of last update + metaReported map[string]int64 // field → epoch seconds of last update thingName string shadowName string version int diff --git a/services/iotdataplane/persistence.go b/services/iotdataplane/persistence.go index c8e70f0571..6bcba90ca0 100644 --- a/services/iotdataplane/persistence.go +++ b/services/iotdataplane/persistence.go @@ -2,7 +2,7 @@ package iotdataplane import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "maps" @@ -32,14 +32,14 @@ const iotdataplaneSnapshotVersion = 1 // unexported identity fields (see store_setup.go) -- shadowEntry itself // carries no exported fields. type shadowEntrySnap struct { - UpdatedAt time.Time `json:"updatedAt"` - Desired map[string]json.RawMessage `json:"desired,omitempty"` - Reported map[string]json.RawMessage `json:"reported,omitempty"` - MetaDesired map[string]int64 `json:"metaDesired,omitempty"` - MetaReported map[string]int64 `json:"metaReported,omitempty"` - ThingName string `json:"thingName"` - ShadowName string `json:"shadowName"` - Version int `json:"version"` + UpdatedAt time.Time `json:"updatedAt"` + Desired map[string]jsontext.Value `json:"desired,omitempty"` + Reported map[string]jsontext.Value `json:"reported,omitempty"` + MetaDesired map[string]int64 `json:"metaDesired,omitempty"` + MetaReported map[string]int64 `json:"metaReported,omitempty"` + ThingName string `json:"thingName"` + ShadowName string `json:"shadowName"` + Version int `json:"version"` // Deleted round-trips the tombstone flag (see shadowEntry.deleted) so a // restored snapshot preserves delete-then-recreate version continuity. // Omitted (defaults to false) for pre-existing snapshots, which is the @@ -80,14 +80,14 @@ func newDirtyDTORegistry() ( } // copyRawMessages returns a deep copy of a map[string]json.RawMessage. -func copyRawMessages(src map[string]json.RawMessage) map[string]json.RawMessage { +func copyRawMessages(src map[string]jsontext.Value) map[string]jsontext.Value { if src == nil { return nil } - dst := make(map[string]json.RawMessage, len(src)) + dst := make(map[string]jsontext.Value, len(src)) for k, v := range src { - cp := make(json.RawMessage, len(v)) + cp := make(jsontext.Value, len(v)) copy(cp, v) dst[k] = cp } @@ -147,8 +147,8 @@ func snapToEntry(es *shadowEntrySnap) *shadowEntry { // guards against decoding a snapshot from an incompatible (older or newer) // build of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises backend state to JSON. @@ -236,7 +236,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreDirtyTablesLocked restores the "dirty" tables (shadows, // connections) from tables via the ephemeral DTO registry, converting each // DTO back to its live type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, shadowDTOs, connDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/iotdataplane/persistence_test.go b/services/iotdataplane/persistence_test.go index ccf80ea9b2..5e83db3757 100644 --- a/services/iotdataplane/persistence_test.go +++ b/services/iotdataplane/persistence_test.go @@ -1,13 +1,14 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -377,7 +378,7 @@ func Test_Persistence_ShadowWithMetadata(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) desired := state["desired"].(map[string]any) @@ -412,7 +413,7 @@ func Test_Persistence_NullWipeSurvivesRoundTrip(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] diff --git a/services/iotdataplane/publish.go b/services/iotdataplane/publish.go index 6eba6a8703..f19ddf593e 100644 --- a/services/iotdataplane/publish.go +++ b/services/iotdataplane/publish.go @@ -2,11 +2,13 @@ package iotdataplane import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // payloadFormatIndicatorUnspecifiedBytes and payloadFormatIndicatorUTF8Data @@ -108,7 +110,7 @@ func parseUserProperties(raw []byte) ([]MQTT5UserProperty, error) { } var entries []map[string]string - if err := json.Unmarshal(raw, &entries); err != nil { + if err := json.Unmarshal(raw, &entries, jsonx.V1()); err != nil { return nil, fmt.Errorf( "%w: userProperties must be a JSON array of single-key objects", ErrValidation, diff --git a/services/iotdataplane/retained_messages_test.go b/services/iotdataplane/retained_messages_test.go index 5208022651..927627ca26 100644 --- a/services/iotdataplane/retained_messages_test.go +++ b/services/iotdataplane/retained_messages_test.go @@ -2,7 +2,7 @@ package iotdataplane_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -212,7 +213,7 @@ func Test_ListRetainedMessages_Pagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) topics1 := page1["retainedTopics"].([]any) assert.Len(t, topics1, 2) @@ -225,7 +226,7 @@ func Test_ListRetainedMessages_Pagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) topics2 := page2["retainedTopics"].([]any) assert.Len(t, topics2, 2) } @@ -237,7 +238,7 @@ func Test_ListRetainedMessages_NonNilWhenEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) topics, ok := resp["retainedTopics"] require.True(t, ok) @@ -318,7 +319,7 @@ func Test_ListRetainedMessages_PageSizeParam(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) topics := resp["retainedTopics"].([]any) assert.Len(t, topics, tt.wantPageCount, "query: %s", tt.query) }) @@ -339,7 +340,7 @@ func Test_ListRetainedMessages_PaginationOffByOneFixed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) topics1 := page1["retainedTopics"].([]any) require.Len(t, topics1, 2) @@ -354,7 +355,7 @@ func Test_ListRetainedMessages_PaginationOffByOneFixed(t *testing.T) { // Page 2: cursor=c/3 → page starts at c/3 (nextToken IS the first item of the page). rec = doRequest(t, h, http.MethodGet, "/retainedMessage?pageSize=2&nextToken="+nextToken, nil) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) topics2 := page2["retainedTopics"].([]any) require.Len(t, topics2, 2) @@ -373,7 +374,7 @@ func Test_ListRetainedMessages_SummaryIncludesQos(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) topics := resp["retainedTopics"].([]any) require.Len(t, topics, 1) @@ -401,7 +402,7 @@ func Test_GetRetainedMessage_StillHasQos(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "qos", "GetRetainedMessage full response must include qos") } @@ -433,7 +434,7 @@ func Test_GetRetainedMessage_UserPropertiesField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Contains(t, resp, "userProperties") if tt.wantNull { @@ -489,7 +490,7 @@ func Test_RetainedMessage_GetNonexistent_404Shape(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["error"]) } func Test_RetainedMessage_Lifecycle(t *testing.T) { @@ -550,7 +551,7 @@ func Test_ListRetainedMessages_MaxResultsAlias(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) topics := resp["retainedTopics"].([]any) assert.Len(t, topics, 3) diff --git a/services/iotdataplane/shadows.go b/services/iotdataplane/shadows.go index c17825ed6c..49773de1bf 100644 --- a/services/iotdataplane/shadows.go +++ b/services/iotdataplane/shadows.go @@ -1,7 +1,8 @@ package iotdataplane import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -9,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validateThingName checks that a thing name meets AWS IoT naming rules. @@ -83,8 +85,8 @@ func validateShadowDocument(doc []byte) error { return fmt.Errorf("%w: The payload exceeds the maximum size allowed", ErrRequestTooLarge) } - var obj map[string]json.RawMessage - if err := json.Unmarshal(doc, &obj); err != nil || obj == nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(doc, &obj, jsonx.V1()); err != nil || obj == nil { return fmt.Errorf("%w: Invalid JSON", ErrValidation) } @@ -92,16 +94,16 @@ func validateShadowDocument(doc []byte) error { } // isJSONNull reports whether v is the JSON null literal. -func isJSONNull(v json.RawMessage) bool { +func isJSONNull(v jsontext.Value) bool { var x any - return json.Unmarshal(v, &x) == nil && x == nil + return json.Unmarshal(v, &x, jsonx.V1()) == nil && x == nil } // mergeStateFields deep-merges patch into base: null deletes a key, nested // objects merge recursively, other values replace. base and patch are unchanged. -func mergeStateFields(base, patch map[string]json.RawMessage) map[string]json.RawMessage { - result := make(map[string]json.RawMessage, len(base)) +func mergeStateFields(base, patch map[string]jsontext.Value) map[string]jsontext.Value { + result := make(map[string]jsontext.Value, len(base)) maps.Copy(result, base) for k, v := range patch { @@ -116,7 +118,7 @@ func mergeStateFields(base, patch map[string]json.RawMessage) map[string]json.Ra return result } -func mergeJSONValue(existing, patch json.RawMessage) json.RawMessage { +func mergeJSONValue(existing, patch jsontext.Value) jsontext.Value { patchObj, ok := decodeJSONObject(patch) if !ok { return patch @@ -127,7 +129,7 @@ func mergeJSONValue(existing, patch json.RawMessage) json.RawMessage { existingObj = nil } - merged, err := json.Marshal(mergeStateFields(existingObj, patchObj)) + merged, err := json.Marshal(mergeStateFields(existingObj, patchObj), jsonx.V1()) if err != nil { return patch } @@ -135,9 +137,9 @@ func mergeJSONValue(existing, patch json.RawMessage) json.RawMessage { return merged } -func decodeJSONObject(raw json.RawMessage) (map[string]json.RawMessage, bool) { - var obj map[string]json.RawMessage - if len(raw) == 0 || json.Unmarshal(raw, &obj) != nil || obj == nil { +func decodeJSONObject(raw jsontext.Value) (map[string]jsontext.Value, bool) { + var obj map[string]jsontext.Value + if len(raw) == 0 || json.Unmarshal(raw, &obj, jsonx.V1()) != nil || obj == nil { return nil, false } @@ -146,7 +148,7 @@ func decodeJSONObject(raw json.RawMessage) (map[string]json.RawMessage, bool) { // updateMetaFields returns a copy of meta with timestamps updated for keys present in patch. // Null-deleted keys are removed from the returned meta map. -func updateMetaFields(meta map[string]int64, patch map[string]json.RawMessage, ts int64) map[string]int64 { +func updateMetaFields(meta map[string]int64, patch map[string]jsontext.Value, ts int64) map[string]int64 { result := make(map[string]int64, len(meta)+len(patch)) maps.Copy(result, meta) @@ -163,8 +165,8 @@ func updateMetaFields(meta map[string]int64, patch map[string]json.RawMessage, t // computeDelta returns the fields where desired differs from reported, recursing // into nested objects so only the differing members appear. nil means no delta. -func computeDelta(desired, reported map[string]json.RawMessage) map[string]json.RawMessage { - delta := make(map[string]json.RawMessage) +func computeDelta(desired, reported map[string]jsontext.Value) map[string]jsontext.Value { + delta := make(map[string]jsontext.Value) for k, dv := range desired { rv, ok := reported[k] @@ -179,7 +181,7 @@ func computeDelta(desired, reported map[string]json.RawMessage) map[string]json. if dIsObj && rIsObj { if sub := computeDelta(dObj, rObj); sub != nil { - if raw, err := json.Marshal(sub); err == nil { + if raw, err := json.Marshal(sub, jsonx.V1()); err == nil { delta[k] = raw } } @@ -199,14 +201,14 @@ func computeDelta(desired, reported map[string]json.RawMessage) map[string]json. return delta } -func jsonRawEqual(a, b json.RawMessage) bool { +func jsonRawEqual(a, b jsontext.Value) bool { var av, bv any - if json.Unmarshal(a, &av) != nil || json.Unmarshal(b, &bv) != nil { + if json.Unmarshal(a, &av, jsonx.V1()) != nil || json.Unmarshal(b, &bv, jsonx.V1()) != nil { return string(a) == string(b) } - ab, errA := json.Marshal(av) - bb, errB := json.Marshal(bv) + ab, errA := json.Marshal(av, jsonx.V1()) + bb, errB := json.Marshal(bv, jsonx.V1()) return errA == nil && errB == nil && string(ab) == string(bb) } @@ -272,7 +274,7 @@ func buildShadowResponse(entry *shadowEntry, clientToken string) ([]byte, error) resp["clientToken"] = clientToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // sortedKeys returns a sorted copy of the keys of a map[string]V. @@ -303,8 +305,8 @@ func (b *InMemoryBackend) GetThingShadow(thingName, shadowName string) ([]byte, type shadowUpdateInput struct { Version *int ClientToken string - StateDesired json.RawMessage - StateReported json.RawMessage + StateDesired jsontext.Value + StateReported jsontext.Value } // parseShadowUpdateDoc validates and parses an UpdateThingShadow request body. @@ -312,12 +314,12 @@ type shadowUpdateInput struct { func parseShadowUpdateDoc(document []byte) (*shadowUpdateInput, error) { // Outer document uses RawMessage for State so we can detect absent vs null. var outer struct { - Version json.RawMessage `json:"version,omitempty"` - ClientToken string `json:"clientToken,omitempty"` - State json.RawMessage `json:"state"` + Version jsontext.Value `json:"version,omitempty"` + ClientToken string `json:"clientToken,omitempty"` + State jsontext.Value `json:"state"` } - if err := json.Unmarshal(document, &outer); err != nil { + if err := json.Unmarshal(document, &outer, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: Invalid JSON", ErrValidation) } @@ -325,7 +327,7 @@ func parseShadowUpdateDoc(document []byte) (*shadowUpdateInput, error) { if len(outer.Version) > 0 && !isJSONNull(outer.Version) { var v int - if err := json.Unmarshal(outer.Version, &v); err != nil { + if err := json.Unmarshal(outer.Version, &v, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: Invalid version", ErrValidation) } @@ -345,11 +347,11 @@ func parseShadowUpdateDoc(document []byte) (*shadowUpdateInput, error) { } var stateDoc struct { - Desired json.RawMessage `json:"desired"` - Reported json.RawMessage `json:"reported"` + Desired jsontext.Value `json:"desired"` + Reported jsontext.Value `json:"reported"` } - if err := json.Unmarshal(outer.State, &stateDoc); err != nil { + if err := json.Unmarshal(outer.State, &stateDoc, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: State node must be an object", ErrValidation) } @@ -389,9 +391,9 @@ func jsonValueDepth(v any) int { // validateShadowStateDepth checks that a state.desired/state.reported section // does not exceed AWS IoT's documented maximum JSON nesting depth (see // maxShadowStateDepth). raw must already be known non-empty and non-null. -func validateShadowStateDepth(raw json.RawMessage, sectionName string) error { +func validateShadowStateDepth(raw jsontext.Value, sectionName string) error { var v any - if err := json.Unmarshal(raw, &v); err != nil { + if err := json.Unmarshal(raw, &v, jsonx.V1()); err != nil { return fmt.Errorf("%w: %s node must be an object", ErrValidation, sectionLabel(sectionName)) } @@ -406,12 +408,12 @@ func validateShadowStateDepth(raw json.RawMessage, sectionName string) error { // applyShadowStateSection merges a raw state section into existing state. // raw absent (nil) → keep existing; raw null → clear; raw object → merge patch. func applyShadowStateSection( - existing map[string]json.RawMessage, + existing map[string]jsontext.Value, existingMeta map[string]int64, - raw json.RawMessage, + raw jsontext.Value, sectionName string, ts int64, -) (map[string]json.RawMessage, map[string]int64, error) { +) (map[string]jsontext.Value, map[string]int64, error) { if len(raw) == 0 { return existing, existingMeta, nil } @@ -424,8 +426,8 @@ func applyShadowStateSection( return nil, nil, err } - var patch map[string]json.RawMessage - if err := json.Unmarshal(raw, &patch); err != nil { + var patch map[string]jsontext.Value + if err := json.Unmarshal(raw, &patch, jsonx.V1()); err != nil { return nil, nil, fmt.Errorf("%w: %s node must be an object", ErrValidation, sectionLabel(sectionName)) } @@ -464,7 +466,7 @@ func (b *InMemoryBackend) UpdateThingShadow(thingName, shadowName string, docume now := time.Now() ts := now.Unix() - var existingDesired, existingReported map[string]json.RawMessage + var existingDesired, existingReported map[string]jsontext.Value var existingMetaDesired, existingMetaReported map[string]int64 if current != nil { @@ -561,7 +563,7 @@ func (b *InMemoryBackend) DeleteThingShadow(thingName, shadowName string) ([]byt payload, err := json.Marshal(map[string]any{ "version": entry.version, keyTimestamp: entry.updatedAt.Unix(), - }) + }, jsonx.V1()) if err != nil { return nil, fmt.Errorf("iotdataplane: marshal delete response: %w", err) } @@ -635,12 +637,12 @@ func (b *InMemoryBackend) AddShadowInternal(thingName, shadowName string, docume // Best-effort parse of state.desired / state.reported from the seeded document. var doc struct { State struct { - Desired map[string]json.RawMessage `json:"desired"` - Reported map[string]json.RawMessage `json:"reported"` + Desired map[string]jsontext.Value `json:"desired"` + Reported map[string]jsontext.Value `json:"reported"` } `json:"state"` } - if json.Unmarshal(document, &doc) == nil { + if json.Unmarshal(document, &doc, jsonx.V1()) == nil { if doc.State.Desired != nil { entry.desired = doc.State.Desired } diff --git a/services/iotdataplane/shadows_merge_test.go b/services/iotdataplane/shadows_merge_test.go index c838557587..4e83e86bf1 100644 --- a/services/iotdataplane/shadows_merge_test.go +++ b/services/iotdataplane/shadows_merge_test.go @@ -1,13 +1,15 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -83,7 +85,7 @@ func TestBackend_ShadowVersioning(t *testing.T) { require.NoError(t, err) var result map[string]any - require.NoError(t, json.Unmarshal(resp, &result)) + require.NoError(t, json.Unmarshal(resp, &result, jsonx.V1())) gotVersion, ok := result["version"].(float64) require.True(t, ok, "response should contain numeric version field") @@ -247,7 +249,7 @@ func Test_ShadowVersion_OverflowProtection(t *testing.T) { require.NoError(t, err) var result map[string]any - require.NoError(t, json.Unmarshal(resp, &result)) + require.NoError(t, json.Unmarshal(resp, &result, jsonx.V1())) versionFloat, ok := result["version"].(float64) require.True(t, ok, "version must be a number") @@ -270,7 +272,7 @@ func Test_ShadowMerge_DesiredPartialUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) desired := state["desired"].(map[string]any) @@ -292,7 +294,7 @@ func Test_ShadowMerge_NullDeletion(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev2/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) desired := state["desired"].(map[string]any) @@ -315,7 +317,7 @@ func Test_ShadowMerge_ReportedIndependent(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev3/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) desired := state["desired"].(map[string]any) @@ -331,12 +333,12 @@ func Test_ShadowMerge_VersionIncrements(t *testing.T) { rec1 := doRequest(t, h, http.MethodPost, "/things/dev-ver/shadow", []byte(`{"state":{"desired":{"k":"v1"}}}`)) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) rec2 := doRequest(t, h, http.MethodPost, "/things/dev-ver/shadow", []byte(`{"state":{"desired":{"k":"v2"}}}`)) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) v1 := r1["version"].(float64) v2 := r2["version"].(float64) @@ -355,7 +357,7 @@ func Test_ShadowDelta_ComputedOnGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) delta, hasDelta := state["delta"] @@ -377,7 +379,7 @@ func Test_ShadowDelta_AbsentWhenEqual(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev-nodelta/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) _, hasDelta := state["delta"] @@ -400,7 +402,7 @@ func Test_ShadowDelta_UpdatedAfterReported(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev-delta2/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) _, hasDelta := state["delta"] @@ -417,7 +419,7 @@ func Test_ShadowMetadata_PresentAfterUpdate(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev-meta/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta, hasMeta := resp["metadata"] require.True(t, hasMeta, "metadata must be present after update") @@ -440,7 +442,7 @@ func Test_ShadowMetadata_UnchangedFieldTimestampPreserved(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/things/dev-meta2/shadow", nil) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1, jsonx.V1())) ts1 := resp1["metadata"].(map[string]any)["desired"].(map[string]any)["a"].(map[string]any)["timestamp"].(float64) // Update only b. @@ -450,7 +452,7 @@ func Test_ShadowMetadata_UnchangedFieldTimestampPreserved(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/things/dev-meta2/shadow", nil) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2, jsonx.V1())) ts2 := resp2["metadata"].(map[string]any)["desired"].(map[string]any)["a"].(map[string]any)["timestamp"].(float64) assert.InDelta(t, ts1, ts2, 0, "timestamp for unmodified field must not change") @@ -486,7 +488,7 @@ func Test_ClientToken_Echoed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) token, hasToken := resp["clientToken"] if tt.wantPresent { @@ -545,9 +547,9 @@ func Test_MergeStateFields(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - var base, patch map[string]json.RawMessage - require.NoError(t, json.Unmarshal([]byte(tt.base), &base)) - require.NoError(t, json.Unmarshal([]byte(tt.patch), &patch)) + var base, patch map[string]jsontext.Value + require.NoError(t, json.Unmarshal([]byte(tt.base), &base, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(tt.patch), &patch, jsonx.V1())) result := iotdataplane.MergeStateFields(base, patch) diff --git a/services/iotdataplane/shadows_pagination_test.go b/services/iotdataplane/shadows_pagination_test.go index 2191c43f4b..5105d40ed8 100644 --- a/services/iotdataplane/shadows_pagination_test.go +++ b/services/iotdataplane/shadows_pagination_test.go @@ -1,7 +1,7 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -31,7 +32,7 @@ func Test_ListNamedShadows_ExcludesClassicShadow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["results"].([]any) require.True(t, ok, "results must be an array") @@ -85,7 +86,7 @@ func Test_ListNamedShadows_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { _, ok := resp[field] @@ -119,7 +120,7 @@ func Test_ListNamedShadows_SortedAlphabetically(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["results"].([]any) require.True(t, ok) @@ -144,7 +145,7 @@ func Test_ListNamedShadows_IncludesTimestamp(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "results") assert.Contains(t, resp, "timestamp") } @@ -171,7 +172,7 @@ func Test_ListThingsWithShadows_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) things := resp["things"].([]any) assert.Empty(t, things) } @@ -188,7 +189,7 @@ func Test_ListThingsWithShadows_Multiple(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) things := resp["things"].([]any) assert.Len(t, things, 3) // Must be sorted. @@ -231,7 +232,7 @@ func Test_ListThingsWithShadows_PageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) things := resp["things"].([]any) assert.Len(t, things, 10) assert.Contains(t, resp, "nextToken") @@ -251,7 +252,7 @@ func Test_ListNamedShadows_PageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["results"].([]any) assert.Len(t, results, 10) assert.Contains(t, resp, "nextToken") @@ -270,7 +271,7 @@ func Test_ListThingsWithShadows_PaginationOffByOneFixed(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/api/things/shadow/ListThingsWithShadows?pageSize=2", nil) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) things1 := page1["things"].([]any) require.Len(t, things1, 2) @@ -287,7 +288,7 @@ func Test_ListThingsWithShadows_PaginationOffByOneFixed(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/api/things/shadow/ListThingsWithShadows?pageSize=2&nextToken="+nextToken, nil) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) things2 := page2["things"].([]any) require.Len(t, things2, 2) @@ -305,7 +306,7 @@ func Test_ListThingsWithShadows_IncludesTimestamp(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "things") assert.Contains(t, resp, "timestamp") @@ -329,7 +330,7 @@ func Test_ListThingsWithShadows_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) things1 := page1["things"].([]any) assert.Len(t, things1, 2) nextToken := page1["nextToken"].(string) @@ -339,7 +340,7 @@ func Test_ListThingsWithShadows_Pagination(t *testing.T) { paginatedURL := "/api/things/shadow/ListThingsWithShadows?pageSize=2&nextToken=" + nextToken rec2 := doRequest(t, h, http.MethodGet, paginatedURL, nil) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) things2 := page2["things"].([]any) assert.Len(t, things2, 2) diff --git a/services/iotdataplane/shadows_state_test.go b/services/iotdataplane/shadows_state_test.go index 14c980e0ec..497038f2c7 100644 --- a/services/iotdataplane/shadows_state_test.go +++ b/services/iotdataplane/shadows_state_test.go @@ -1,13 +1,14 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -29,7 +30,7 @@ func Test_ShadowDesiredNull_WipesDesired(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] @@ -51,7 +52,7 @@ func Test_ShadowDesiredNull_LeavesReportedIntact(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] @@ -78,7 +79,7 @@ func Test_ShadowReportedNull_WipesReported(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasReported := state["reported"] @@ -105,7 +106,7 @@ func Test_ShadowBothNull_WipesBoth(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] @@ -133,7 +134,7 @@ func Test_ShadowDesiredNull_ThenResetDesired(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) desired := state["desired"].(map[string]any) @@ -150,12 +151,12 @@ func Test_ShadowDesiredNull_VersionStillIncrements(t *testing.T) { resp1, err := b.UpdateThingShadow("dev", "", []byte(`{"state":{"desired":{"k":"v"}}}`)) require.NoError(t, err) var r1 map[string]any - require.NoError(t, json.Unmarshal(resp1, &r1)) + require.NoError(t, json.Unmarshal(resp1, &r1, jsonx.V1())) resp2, err := b.UpdateThingShadow("dev", "", []byte(`{"state":{"desired":null}}`)) require.NoError(t, err) var r2 map[string]any - require.NoError(t, json.Unmarshal(resp2, &r2)) + require.NoError(t, json.Unmarshal(resp2, &r2, jsonx.V1())) v1 := int(r1["version"].(float64)) v2 := int(r2["version"].(float64)) @@ -175,7 +176,7 @@ func Test_ShadowDesiredNull_ViaHTTP(t *testing.T) { // Confirm desired absent in GET. rec = doRequest(t, h, http.MethodGet, "/things/dev/shadow", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) state := resp["state"].(map[string]any) _, hasDesired := state["desired"] @@ -193,7 +194,7 @@ func Test_ShadowResponse_OnlyDesiredSet_ReportedOmitted(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] @@ -213,7 +214,7 @@ func Test_ShadowResponse_OnlyReportedSet_DesiredOmitted(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasReported := state["reported"] @@ -233,7 +234,7 @@ func Test_ShadowResponse_BothSet_BothPresent(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDesired := state["desired"] @@ -256,7 +257,7 @@ func Test_ShadowResponse_EmptyStateSection_StateObjectPresent(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) // "state" key must still exist (as empty object {}). _, hasState := doc["state"] @@ -285,7 +286,7 @@ func Test_ShadowMetadata_ClearedOnDesiredNull(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) meta, hasMeta := doc["metadata"].(map[string]any) if hasMeta { @@ -313,7 +314,7 @@ func Test_ShadowDelta_AfterDesiredWipe_NoDelta(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) _, hasDelta := state["delta"] @@ -332,7 +333,7 @@ func Test_ShadowUpdate_EmptyDesiredPatch_NoOpForKeys(t *testing.T) { require.NoError(t, err) var r2 map[string]any - require.NoError(t, json.Unmarshal(resp2, &r2)) + require.NoError(t, json.Unmarshal(resp2, &r2, jsonx.V1())) assert.InDelta(t, float64(2), r2["version"], 0) state := r2["state"].(map[string]any) @@ -361,7 +362,7 @@ func Test_ShadowUpdate_MultiplePatchesAccumulate(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) desired := state["desired"].(map[string]any) diff --git a/services/iotdataplane/shadows_test.go b/services/iotdataplane/shadows_test.go index d0449acecc..08df3c6220 100644 --- a/services/iotdataplane/shadows_test.go +++ b/services/iotdataplane/shadows_test.go @@ -1,7 +1,7 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -22,7 +23,7 @@ func TestHandler_ShadowCRUD(t *testing.T) { "desired": map[string]any{"color": "red"}, }, } - docBytes, err := json.Marshal(shadowDoc) + docBytes, err := json.Marshal(shadowDoc, jsonx.V1()) require.NoError(t, err) // Step 1: shadow does not exist yet. @@ -133,7 +134,7 @@ func TestHandler_ShadowResponseContainsVersionAndTimestamp(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "version") assert.Contains(t, resp, "timestamp") @@ -142,7 +143,7 @@ func TestHandler_ShadowResponseContainsVersionAndTimestamp(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Contains(t, getResp, "version") assert.Contains(t, getResp, "timestamp") } @@ -174,7 +175,7 @@ func updateShadow(t *testing.T, h *iotdataplane.Handler, thingName, shadowName s require.Equal(t, http.StatusOK, rec.Code, "UpdateThingShadow: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -194,7 +195,7 @@ func getShadow(t *testing.T, h *iotdataplane.Handler, thingName, shadowName stri var resp map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) } return resp, rec.Code @@ -315,7 +316,7 @@ func Test_DeleteThingShadow_ResponseOmitsState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasState := resp["state"] assert.False(t, hasState, "delete response must NOT include state (empty response state document)") @@ -428,7 +429,7 @@ func Test_DeleteThingShadow_ReturnsPayload(t *testing.T) { // Response must be a JSON object with version and timestamp (AWS contract). var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "version") assert.Contains(t, resp, "timestamp") } @@ -608,7 +609,7 @@ func Test_CrossThing_ShadowIsolation(t *testing.T) { require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) desired := state["desired"].(map[string]any) assert.Equal(t, "blue", desired["color"]) @@ -631,7 +632,7 @@ func Test_ClassicVsNamedShadow_Isolation(t *testing.T) { resp, err := b.GetThingShadow("dev", "named-one") require.NoError(t, err) var doc map[string]any - require.NoError(t, json.Unmarshal(resp, &doc)) + require.NoError(t, json.Unmarshal(resp, &doc, jsonx.V1())) state := doc["state"].(map[string]any) desired := state["desired"].(map[string]any) assert.Equal(t, "yes", desired["named"]) @@ -659,8 +660,8 @@ func Test_NamedShadow_IndependentVersions(t *testing.T) { require.NoError(t, err) var alpha, beta map[string]any - require.NoError(t, json.Unmarshal(alphaResp, &alpha)) - require.NoError(t, json.Unmarshal(betaResp, &beta)) + require.NoError(t, json.Unmarshal(alphaResp, &alpha, jsonx.V1())) + require.NoError(t, json.Unmarshal(betaResp, &beta, jsonx.V1())) assert.InDelta(t, float64(3), alpha["version"], 0, "alpha must be at version 3") assert.InDelta(t, float64(1), beta["version"], 0, "beta must be at version 1") diff --git a/services/iotdataplane/shadows_validation_test.go b/services/iotdataplane/shadows_validation_test.go index 7cf29ccc31..3793a41185 100644 --- a/services/iotdataplane/shadows_validation_test.go +++ b/services/iotdataplane/shadows_validation_test.go @@ -1,7 +1,7 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotdataplane" ) @@ -50,7 +51,7 @@ func TestBackend_ShadowUpdate_ObjectDocumentSucceeds(t *testing.T) { require.NoError(t, err) var result map[string]any - require.NoError(t, json.Unmarshal(resp, &result), "response must be valid JSON") + require.NoError(t, json.Unmarshal(resp, &result, jsonx.V1()), "response must be valid JSON") assert.Contains(t, result, "version", "response must contain version") assert.Contains(t, result, "timestamp", "response must contain timestamp") } @@ -102,7 +103,7 @@ func Test_UpdateThingShadow_StateRequired(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["error"], "error type must be InvalidRequestException") } @@ -157,7 +158,7 @@ func Test_VersionConflict_RejectedWithCorrectError(t *testing.T) { if tt.wantErrorType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrorType, resp["error"], "error type must be ConflictException") } @@ -421,7 +422,7 @@ func Test_ThingName_ValidationOnDelete(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "error") } func Test_ThingName_ValidationOnListNamedShadows(t *testing.T) { @@ -493,7 +494,7 @@ func Test_ClientToken_TooLong_ViaHTTP(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["error"]) } func Test_ClientToken_Exactly64Chars_Accepted(t *testing.T) { @@ -507,7 +508,7 @@ func Test_ClientToken_Exactly64Chars_Accepted(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, exact, resp["clientToken"]) } func Test_ShadowUpdate_StateRequired(t *testing.T) { @@ -584,7 +585,7 @@ func Test_ShadowUpdate_StateRequired_ErrorShape(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["error"]) assert.Contains(t, resp["message"], "state") } diff --git a/services/iotdataplane/value_semantics_test.go b/services/iotdataplane/value_semantics_test.go index 4fb1e694a8..4cec508776 100644 --- a/services/iotdataplane/value_semantics_test.go +++ b/services/iotdataplane/value_semantics_test.go @@ -1,13 +1,15 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" iotdataplanesdk "github.com/aws/aws-sdk-go-v2/service/iotdataplane" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestShadow_NestedUpdatesMergeAndDeltaIsMinimal(t *testing.T) { @@ -66,7 +68,7 @@ func TestShadow_NestedUpdatesMergeAndDeltaIsMinimal(t *testing.T) { var doc struct { State map[string]any `json:"state"` } - require.NoError(t, json.Unmarshal(got.Payload, &doc)) + require.NoError(t, json.Unmarshal(got.Payload, &doc, jsonx.V1())) if tt.wantDesired != "" { assert.JSONEq(t, tt.wantDesired, mustJSON(t, doc.State["desired"])) @@ -86,7 +88,7 @@ func TestShadow_NestedUpdatesMergeAndDeltaIsMinimal(t *testing.T) { func mustJSON(t *testing.T, v any) string { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/iotdataplane/whitebox_test.go b/services/iotdataplane/whitebox_test.go index 2b517ea9d5..6ae6042f7a 100644 --- a/services/iotdataplane/whitebox_test.go +++ b/services/iotdataplane/whitebox_test.go @@ -2,7 +2,7 @@ package iotdataplane import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body []byte) *httptest.ResponseRecorder { @@ -91,6 +93,6 @@ func Test_ShadowStateDepth_ViaHTTP(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["error"]) } diff --git a/services/iotdataplane/wire_sdk_roundtrip_test.go b/services/iotdataplane/wire_sdk_roundtrip_test.go index 4eba4a5657..f143d70d93 100644 --- a/services/iotdataplane/wire_sdk_roundtrip_test.go +++ b/services/iotdataplane/wire_sdk_roundtrip_test.go @@ -1,7 +1,7 @@ package iotdataplane_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/iotdataplane" @@ -112,7 +113,7 @@ func TestShadowLifecycle_SDKRoundTrip(t *testing.T) { Version int64 `json:"version"` Timestamp int64 `json:"timestamp"` } - require.NoError(t, json.Unmarshal(deleted.Payload, &deleteBody)) + require.NoError(t, json.Unmarshal(deleted.Payload, &deleteBody, jsonx.V1())) _, err = client.GetThingShadow(t.Context(), &iotdataplanesdk.GetThingShadowInput{ ThingName: aws.String(thingName), diff --git a/services/iotwireless/handler.go b/services/iotwireless/handler.go index 4e3fa6a71b..df1af1d7c7 100644 --- a/services/iotwireless/handler.go +++ b/services/iotwireless/handler.go @@ -1,7 +1,8 @@ package iotwireless import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -975,7 +977,10 @@ func writeError(c *echo.Context, status int, message string) error { c.Response().Header().Set("X-Amzn-Errortype", errType) c.Response().WriteHeader(status) - _ = json.NewEncoder(c.Response()).Encode(errorResponse{Type: errType, Message: message}) + _ = json.MarshalEncode( + jsontext.NewEncoder(c.Response(), jsonx.V1()), + errorResponse{Type: errType, Message: message}, + ) return nil } @@ -985,7 +990,7 @@ func writeJSON(c *echo.Context, status int, v any) error { c.Response().Header().Set("Content-Type", "application/json") c.Response().WriteHeader(status) - _ = json.NewEncoder(c.Response()).Encode(v) + _ = json.MarshalEncode(jsontext.NewEncoder(c.Response(), jsonx.V1()), v) return nil } diff --git a/services/iotwireless/handler_certificates.go b/services/iotwireless/handler_certificates.go index c87b08617c..32ddf21a8b 100644 --- a/services/iotwireless/handler_certificates.go +++ b/services/iotwireless/handler_certificates.go @@ -1,12 +1,13 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -124,7 +125,7 @@ type startSingleWirelessDeviceImportTaskResponse struct { func (h *Handler) associateWirelessGatewayWithCertificate(c *echo.Context, gatewayID string, body []byte) error { var req associateWirelessGatewayWithCertificateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -168,7 +169,7 @@ func (h *Handler) startWirelessDeviceImportTask(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) task, err := h.Backend.StartWirelessDeviceImportTask( h.AccountID, h.DefaultRegion, req.DestinationName, req.Positioning, req.Sidewalk.toModel(), @@ -202,7 +203,7 @@ func (h *Handler) startSingleWirelessDeviceImportTask(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) details := SingleImportDetails{DeviceName: req.DeviceName, Positioning: req.Positioning} if req.Sidewalk != nil { @@ -293,7 +294,7 @@ func (h *Handler) updateWirelessDeviceImportTask(c *echo.Context, id string) err } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateWirelessDeviceImportTask(id, req.Sidewalk.toModel()); err != nil { return handleError(c, err) diff --git a/services/iotwireless/handler_certificates_test.go b/services/iotwireless/handler_certificates_test.go index 52f472d9bb..17fb29d617 100644 --- a/services/iotwireless/handler_certificates_test.go +++ b/services/iotwireless/handler_certificates_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AssociateWirelessGatewayWithCertificate(t *testing.T) { @@ -46,7 +48,7 @@ func TestHandler_AssociateWirelessGatewayWithCertificate(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) gwID = createResp["Id"].(string) } @@ -56,7 +58,7 @@ func TestHandler_AssociateWirelessGatewayWithCertificate(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.iotCertificateID, resp["IotCertificateId"]) } }) @@ -73,7 +75,7 @@ func TestHandler_GatewayCertificateLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) gwID := createResp["Id"].(string) // Associate certificate @@ -86,7 +88,7 @@ func TestHandler_GatewayCertificateLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var certResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &certResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &certResp, jsonx.V1())) assert.Equal(t, "cert-123", certResp["IotCertificateId"]) // Disassociate certificate @@ -107,7 +109,7 @@ func TestHandler_ListDevicesForWirelessDeviceImportTask_ByID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -115,7 +117,7 @@ func TestHandler_ListDevicesForWirelessDeviceImportTask_ByID(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Equal(t, "dest-import", listResp["DestinationName"]) rec = doIoTWRequest(t, h, http.MethodGet, "/wireless_device_import_task?id=does-not-exist", "") @@ -159,7 +161,7 @@ func TestHandler_StartWirelessDeviceImportTask(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["Arn"].(string) id, _ := resp["Id"].(string) @@ -207,7 +209,7 @@ func TestHandler_GetWirelessDeviceImportTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskID = createResp["Id"].(string) } @@ -216,7 +218,7 @@ func TestHandler_GetWirelessDeviceImportTask(t *testing.T) { if tt.wantFound { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.setupDest, resp["DestinationName"]) assert.Equal(t, "Initialized", resp["Status"]) } @@ -256,7 +258,7 @@ func TestHandler_DeleteWirelessDeviceImportTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskID = createResp["Id"].(string) } @@ -310,7 +312,7 @@ func TestHandler_UpdateWirelessDeviceImportTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskID := createResp["Id"].(string) rec = doIoTWRequest(t, h, http.MethodPatch, "/wireless_device_import_task/"+taskID, tt.updateBody) @@ -321,7 +323,7 @@ func TestHandler_UpdateWirelessDeviceImportTask(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "dest-old", getResp["DestinationName"]) if tt.wantFileList == nil { @@ -363,7 +365,7 @@ func TestHandler_ListWirelessDeviceImportTasks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["WirelessDeviceImportTaskList"].([]any) require.True(t, ok, "WirelessDeviceImportTaskList should be array") @@ -401,7 +403,7 @@ func TestHandler_StartSingleWirelessDeviceImportTask(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["Arn"].(string) devID, _ := resp["WirelessDeviceId"].(string) @@ -420,7 +422,7 @@ func TestHandler_ListDevicesForWirelessDeviceImportTask_NoIDReturnsEmpty(t *test require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["ImportedWirelessDeviceList"].([]any) require.True(t, ok, "ImportedWirelessDeviceList should be array") diff --git a/services/iotwireless/handler_destinations.go b/services/iotwireless/handler_destinations.go index 582fd9afd2..04886b3dee 100644 --- a/services/iotwireless/handler_destinations.go +++ b/services/iotwireless/handler_destinations.go @@ -1,11 +1,12 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -36,7 +37,7 @@ type listDestinationsResponse struct { func (h *Handler) createDestination(c *echo.Context, body []byte) error { var req createDestinationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -114,7 +115,7 @@ func (h *Handler) updateDestination(c *echo.Context, name string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateDestination( h.AccountID, h.DefaultRegion, name, diff --git a/services/iotwireless/handler_destinations_test.go b/services/iotwireless/handler_destinations_test.go index 3194fba3ef..f4eb1ec4b0 100644 --- a/services/iotwireless/handler_destinations_test.go +++ b/services/iotwireless/handler_destinations_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateGetListDeleteDestination(t *testing.T) { @@ -40,7 +42,7 @@ func TestHandler_CreateGetListDeleteDestination(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, tt.destName, createResp["Name"]) // Get @@ -48,7 +50,7 @@ func TestHandler_CreateGetListDeleteDestination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.destName, getResp["Name"]) assert.Equal(t, tt.expression, getResp["Expression"]) @@ -57,7 +59,7 @@ func TestHandler_CreateGetListDeleteDestination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) dests, ok := listResp["DestinationList"].([]any) require.True(t, ok) assert.Len(t, dests, 1) @@ -103,6 +105,6 @@ func TestHandler_UpdateDestination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "rule/updated", getResp["Expression"]) } diff --git a/services/iotwireless/handler_event_configurations.go b/services/iotwireless/handler_event_configurations.go index 24308f0d35..46a3a4669d 100644 --- a/services/iotwireless/handler_event_configurations.go +++ b/services/iotwireless/handler_event_configurations.go @@ -1,10 +1,12 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type eventConfigDocResponse struct { @@ -56,7 +58,7 @@ type listEventConfigurationsResponse struct { func eventConfigDocFromBody(body []byte) *EventConfigDoc { var doc EventConfigDoc - _ = json.Unmarshal(body, &doc) + _ = json.Unmarshal(body, &doc, jsonx.V1()) return &doc } diff --git a/services/iotwireless/handler_event_configurations_test.go b/services/iotwireless/handler_event_configurations_test.go index 92d0e22e2d..8eec2f19dd 100644 --- a/services/iotwireless/handler_event_configurations_test.go +++ b/services/iotwireless/handler_event_configurations_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_EventConfigurations(t *testing.T) { @@ -19,7 +21,7 @@ func TestHandler_EventConfigurations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var defaultResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defaultResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defaultResp, jsonx.V1())) assert.NotContains(t, defaultResp, "DeviceRegistrationState") // Update event config by resource types (PATCH, not POST -- iotwireless@v1.59.4 @@ -32,7 +34,7 @@ func TestHandler_EventConfigurations(t *testing.T) { // fabricated always-empty response. rec = doIoTWRequest(t, h, http.MethodGet, "/event-configurations-resource-types", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defaultResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defaultResp, jsonx.V1())) drs, ok := defaultResp["DeviceRegistrationState"].(map[string]any) require.True(t, ok) sidewalk, ok := drs["Sidewalk"].(map[string]any) @@ -44,7 +46,7 @@ func TestHandler_EventConfigurations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok := listResp["EventConfigurationsList"].([]any) require.True(t, ok) assert.Empty(t, configs) @@ -54,7 +56,7 @@ func TestHandler_EventConfigurations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, getResp, "Join") // Update resource event configuration @@ -66,7 +68,7 @@ func TestHandler_EventConfigurations(t *testing.T) { // Get resource event configuration must now reflect the stored config. rec = doIoTWRequest(t, h, http.MethodGet, "/event-configurations/some-resource", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) join, ok := getResp["Join"].(map[string]any) require.True(t, ok) loRaWAN, ok := join["LoRaWAN"].(map[string]any) @@ -82,7 +84,7 @@ func TestHandler_EventConfigurations(t *testing.T) { "", ) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok = listResp["EventConfigurationsList"].([]any) require.True(t, ok) require.Len(t, configs, 1) @@ -124,7 +126,7 @@ func TestHandler_EventConfigurationByResourceTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["DeviceRegistrationState"] assert.True(t, ok, "persisted event config must be returned") } @@ -172,7 +174,7 @@ func TestHandler_ResourceEventConfiguration(t *testing.T) { // field (it echoes only the event-type configuration); confirm the // stored per-resource event config round-trips instead. var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp[tt.wantField] assert.True(t, ok, "persisted event config field %q must be returned", tt.wantField) }) @@ -189,7 +191,7 @@ func TestHandler_ListEventConfigurations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var pre map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pre)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pre, jsonx.V1())) assert.Empty(t, pre["EventConfigurationsList"]) // Update config for two resources. @@ -204,7 +206,7 @@ func TestHandler_ListEventConfigurations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var post map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &post)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &post, jsonx.V1())) list, ok := post["EventConfigurationsList"].([]any) require.True(t, ok) assert.Len(t, list, 2) @@ -265,7 +267,7 @@ func TestHandler_ListEventConfigurations_FilterByResourceType(t *testing.T) { Identifier string `json:"Identifier"` } `json:"EventConfigurationsList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids := make([]string, 0, len(resp.EventConfigurationsList)) for _, e := range resp.EventConfigurationsList { diff --git a/services/iotwireless/handler_fuota_tasks.go b/services/iotwireless/handler_fuota_tasks.go index 83ac62874c..67c8bfc896 100644 --- a/services/iotwireless/handler_fuota_tasks.go +++ b/services/iotwireless/handler_fuota_tasks.go @@ -1,13 +1,14 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -84,7 +85,7 @@ type listMulticastGroupsByFuotaTaskResponse struct { func (h *Handler) createFuotaTask(c *echo.Context, body []byte) error { var req createFuotaTaskRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -166,7 +167,7 @@ func (h *Handler) deleteFuotaTask(c *echo.Context, id string) error { func (h *Handler) associateMulticastGroupWithFuotaTask(c *echo.Context, fuotaTaskID string, body []byte) error { var req associateMulticastGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -181,7 +182,7 @@ func (h *Handler) associateMulticastGroupWithFuotaTask(c *echo.Context, fuotaTas func (h *Handler) associateWirelessDeviceWithFuotaTask(c *echo.Context, fuotaTaskID string, body []byte) error { var req associateWirelessDeviceWithFuotaRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -208,7 +209,7 @@ func (h *Handler) updateFuotaTask(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateFuotaTask( h.AccountID, h.DefaultRegion, id, req.Name, req.Description, @@ -230,7 +231,7 @@ func (h *Handler) startFuotaTask(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) var startTime *time.Time diff --git a/services/iotwireless/handler_fuota_tasks_test.go b/services/iotwireless/handler_fuota_tasks_test.go index 9b76d35e47..942ae0605a 100644 --- a/services/iotwireless/handler_fuota_tasks_test.go +++ b/services/iotwireless/handler_fuota_tasks_test.go @@ -1,13 +1,16 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_FuotaTask_LoRaWANRoundTrip verifies the LoRaWANFuotaTask @@ -27,7 +30,7 @@ func TestHandler_FuotaTask_LoRaWANRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -35,7 +38,7 @@ func TestHandler_FuotaTask_LoRaWANRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok := getResp["LoRaWAN"].(map[string]any) require.True(t, ok) assert.Equal(t, "US915", loRaWAN["RfRegion"]) @@ -48,7 +51,7 @@ func TestHandler_FuotaTask_LoRaWANRoundTrip(t *testing.T) { rec = doIoTWRequest(t, h, http.MethodGet, "/fuota-tasks/"+id, "") require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok = getResp["LoRaWAN"].(map[string]any) require.True(t, ok) assert.Equal(t, "EU868", loRaWAN["RfRegion"]) @@ -114,7 +117,7 @@ func TestHandler_UpdateFuotaTask_Fields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -125,7 +128,7 @@ func TestHandler_UpdateFuotaTask_Fields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.wantValue, getResp[tt.wantField]) }) } @@ -163,7 +166,7 @@ func TestHandler_StartFuotaTask_StartTime(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -174,7 +177,7 @@ func TestHandler_StartFuotaTask_StartTime(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, hasLoRaWAN := getResp["LoRaWAN"].(map[string]any) if tt.wantStartTime == "" { @@ -225,7 +228,7 @@ func TestHandler_CreateFuotaTask(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.NotEmpty(t, resp["Arn"]) }) @@ -310,7 +313,7 @@ func TestHandler_ListMulticastGroupsByFuotaTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ftResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ftResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ftResp, jsonx.V1())) ftID := ftResp["Id"].(string) // Create a multicast group @@ -318,7 +321,7 @@ func TestHandler_ListMulticastGroupsByFuotaTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var mgResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mgResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mgResp, jsonx.V1())) mgID := mgResp["Id"].(string) // Associate multicast group with FUOTA task; AssociateMulticastGroupWithFuotaTask @@ -332,7 +335,7 @@ func TestHandler_ListMulticastGroupsByFuotaTask(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) groups, ok := listResp["MulticastGroupList"].([]any) require.True(t, ok) assert.Len(t, groups, 1) @@ -343,7 +346,7 @@ func TestHandler_ListMulticastGroupsByFuotaTask(t *testing.T) { // List again should return empty rec = doIoTWRequest(t, h, http.MethodGet, "/fuota-tasks/"+ftID+"/multicast-groups", "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) groups = listResp["MulticastGroupList"].([]any) assert.Empty(t, groups) } @@ -364,7 +367,7 @@ func TestHandler_FuotaTaskUpdate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Update @@ -377,7 +380,7 @@ func TestHandler_FuotaTaskUpdate(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "ft1-updated", getResp["Name"]) } @@ -397,7 +400,7 @@ func TestHandler_StartFuotaTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Start the task @@ -421,7 +424,7 @@ func TestHandler_DisassociateWirelessDeviceFromFuotaTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) ftID := createResp["Id"].(string) // Create a device @@ -435,7 +438,7 @@ func TestHandler_DisassociateWirelessDeviceFromFuotaTask(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var devResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp, jsonx.V1())) devID := devResp["Id"].(string) // Associate device with FUOTA task; AssociateWirelessDeviceWithFuotaTask @@ -482,7 +485,7 @@ func TestHandler_FuotaTask_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) require.NotEmpty(t, id) @@ -491,7 +494,7 @@ func TestHandler_FuotaTask_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.taskName, getResp["Name"]) assert.Equal(t, id, getResp["Id"]) @@ -500,7 +503,7 @@ func TestHandler_FuotaTask_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list, ok := listResp["FuotaTaskList"].([]any) require.True(t, ok) assert.Len(t, list, 1) @@ -543,7 +546,7 @@ func TestHandler_FuotaTasks_FullLifecycle(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) fuotaID, _ := createResp["Id"].(string) require.NotEmpty(t, fuotaID, "CreateFuotaTask must return an Id") diff --git a/services/iotwireless/handler_log_levels.go b/services/iotwireless/handler_log_levels.go index 91ea8602da..4e64bc0f5d 100644 --- a/services/iotwireless/handler_log_levels.go +++ b/services/iotwireless/handler_log_levels.go @@ -1,10 +1,12 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // getResourceLogLevelResponse mirrors GetResourceLogLevelOutput, which @@ -52,7 +54,7 @@ func (h *Handler) updateLogLevelsByResourceTypes(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) cfg := LogLevelsConfig{ DefaultLogLevel: req.DefaultLogLevel, @@ -95,7 +97,7 @@ func (h *Handler) putResourceLogLevel(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.PutResourceLogLevel(id, req.LogLevel); err != nil { return handleError(c, err) diff --git a/services/iotwireless/handler_log_levels_test.go b/services/iotwireless/handler_log_levels_test.go index 839d6fdd8f..8522edb3ed 100644 --- a/services/iotwireless/handler_log_levels_test.go +++ b/services/iotwireless/handler_log_levels_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_LogLevels(t *testing.T) { @@ -19,7 +21,7 @@ func TestHandler_LogLevels(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "INFO", getResp["DefaultLogLevel"]) // Update log levels @@ -28,7 +30,7 @@ func TestHandler_LogLevels(t *testing.T) { // Verify updated rec = doIoTWRequest(t, h, http.MethodGet, "/log-levels", "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "DEBUG", getResp["DefaultLogLevel"]) // Put resource log level @@ -45,7 +47,7 @@ func TestHandler_LogLevels(t *testing.T) { rec = doIoTWRequest(t, h, http.MethodGet, "/log-levels/my-device", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "ERROR", getResp["LogLevel"]) // Reset resource log level @@ -54,7 +56,7 @@ func TestHandler_LogLevels(t *testing.T) { // After reset, should return INFO default rec = doIoTWRequest(t, h, http.MethodGet, "/log-levels/my-device", "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "INFO", getResp["LogLevel"]) // Reset all resource log levels @@ -91,7 +93,7 @@ func TestHandler_LogLevels_OptionListsRoundTrip(t *testing.T) { WirelessDeviceLogOptions []map[string]any `json:"WirelessDeviceLogOptions"` WirelessGatewayLogOptions []map[string]any `json:"WirelessGatewayLogOptions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ERROR", resp.DefaultLogLevel) require.Len(t, resp.WirelessDeviceLogOptions, 1) diff --git a/services/iotwireless/handler_metrics.go b/services/iotwireless/handler_metrics.go index bd2fe2b0ab..c6cf13a281 100644 --- a/services/iotwireless/handler_metrics.go +++ b/services/iotwireless/handler_metrics.go @@ -1,10 +1,12 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const stubServiceType = "CUPS" @@ -65,7 +67,7 @@ func (h *Handler) updateMetricConfiguration(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateMetricConfigurationStatus(req.SummaryMetric.Status); err != nil { return handleError(c, err) @@ -117,7 +119,7 @@ func (h *Handler) getMetrics(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) results := make([]summaryMetricQueryResultResponse, 0, len(req.SummaryMetricQueries)) for _, q := range req.SummaryMetricQueries { diff --git a/services/iotwireless/handler_metrics_test.go b/services/iotwireless/handler_metrics_test.go index 8473561201..38e0d776ba 100644 --- a/services/iotwireless/handler_metrics_test.go +++ b/services/iotwireless/handler_metrics_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetMetricConfiguration(t *testing.T) { @@ -19,7 +21,7 @@ func TestHandler_GetMetricConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) summaryMetric, ok := getResp["SummaryMetric"].(map[string]any) require.True(t, ok) assert.Equal(t, "Enabled", summaryMetric["Status"]) @@ -31,7 +33,7 @@ func TestHandler_GetMetricConfiguration(t *testing.T) { rec = doIoTWRequest(t, h, http.MethodGet, "/metric-configuration", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) summaryMetric, ok = getResp["SummaryMetric"].(map[string]any) require.True(t, ok) assert.Equal(t, "Disabled", summaryMetric["Status"]) @@ -52,7 +54,7 @@ func TestHandler_GetMetrics_MapsQueriesToResults(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["SummaryMetricQueryResults"].([]any) require.True(t, ok) require.Len(t, results, 2) @@ -71,7 +73,7 @@ func TestHandler_GetServiceEndpoint_ExactURLsAndValidation(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CUPS", resp["ServiceType"]) assert.Equal(t, "https://cups.lorawan.us-east-1.amazonaws.com", resp["ServiceEndpoint"]) @@ -80,7 +82,7 @@ func TestHandler_GetServiceEndpoint_ExactURLsAndValidation(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var lnsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lnsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lnsResp, jsonx.V1())) assert.Equal(t, "LNS", lnsResp["ServiceType"]) assert.Equal(t, "https://lns.lorawan.us-east-1.amazonaws.com", lnsResp["ServiceEndpoint"]) @@ -126,7 +128,7 @@ func TestHandler_GetMetrics_ReturnsEmptyResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["SummaryMetricQueryResults"].([]any) require.True(t, ok) @@ -168,7 +170,7 @@ func TestHandler_MetricConfiguration_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp[tt.wantKV] assert.True(t, ok, "expected key %q in response", tt.wantKV) }) @@ -214,7 +216,7 @@ func TestHandler_GetServiceEndpoint_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantServiceType, resp["ServiceType"]) endpoint, _ := resp["ServiceEndpoint"].(string) assert.Contains(t, endpoint, tt.wantSubstr) diff --git a/services/iotwireless/handler_multicast_groups.go b/services/iotwireless/handler_multicast_groups.go index e025bdb73e..c156629de7 100644 --- a/services/iotwireless/handler_multicast_groups.go +++ b/services/iotwireless/handler_multicast_groups.go @@ -1,7 +1,8 @@ package iotwireless import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "time" @@ -9,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -59,7 +61,7 @@ func (h *Handler) createMulticastGroup(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) mg, err := h.Backend.CreateMulticastGroup( h.AccountID, @@ -141,7 +143,7 @@ func (h *Handler) updateMulticastGroup(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateMulticastGroup( h.AccountID, h.DefaultRegion, id, req.Name, req.Description, req.LoRaWAN, @@ -214,11 +216,11 @@ func (h *Handler) startMulticastGroupSession(c *echo.Context, id string) error { // would, not answered with a fabricated success. func (h *Handler) sendDataToMulticastGroup(c *echo.Context, _ string) error { var req struct { - PayloadData string `json:"PayloadData"` - WirelessMetadata json.RawMessage `json:"WirelessMetadata"` + PayloadData string `json:"PayloadData"` + WirelessMetadata jsontext.Value `json:"WirelessMetadata"` } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.PayloadData == "" { return writeError(c, http.StatusBadRequest, "ValidationException: PayloadData is required") @@ -236,7 +238,7 @@ func (h *Handler) associateWirelessDeviceWithMulticastGroup( c *echo.Context, multicastGroupID string, body []byte, ) error { var req associateWirelessDeviceWithMulticastRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/iotwireless/handler_multicast_groups_test.go b/services/iotwireless/handler_multicast_groups_test.go index 49e0b43419..6914de8b6a 100644 --- a/services/iotwireless/handler_multicast_groups_test.go +++ b/services/iotwireless/handler_multicast_groups_test.go @@ -1,13 +1,16 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AssociateWirelessDeviceWithMulticastGroup(t *testing.T) { @@ -62,7 +65,7 @@ func TestHandler_MulticastGroup_LoRaWANRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -70,7 +73,7 @@ func TestHandler_MulticastGroup_LoRaWANRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok := getResp["LoRaWAN"].(map[string]any) require.True(t, ok) assert.Equal(t, "US915", loRaWAN["RfRegion"]) @@ -92,7 +95,7 @@ func TestHandler_MulticastGroup_LoRaWANRoundTrip(t *testing.T) { rec = doIoTWRequest(t, h, http.MethodGet, "/multicast-groups/"+id, "") require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok = getResp["LoRaWAN"].(map[string]any) require.True(t, ok) assert.InDelta(t, float64(1), loRaWAN["NumberOfDevicesInGroup"], 0.001) @@ -104,7 +107,7 @@ func TestHandler_MulticastGroup_LoRaWANRoundTrip(t *testing.T) { rec = doIoTWRequest(t, h, http.MethodGet, "/multicast-groups/"+id, "") require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok = getResp["LoRaWAN"].(map[string]any) require.True(t, ok) assert.Equal(t, "EU868", loRaWAN["RfRegion"]) @@ -132,7 +135,7 @@ func TestHandler_CancelMulticastGroupSession(t *testing.T) { if tt.create { rec := doIoTWRequest(t, h, http.MethodPost, "/multicast-groups", `{"Name":"mg"}`) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ = resp["Id"].(string) } @@ -153,7 +156,7 @@ func TestHandler_MulticastGroupCRUD(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, ok := createResp["Id"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -166,7 +169,7 @@ func TestHandler_MulticastGroupCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "mg1", getResp["Name"]) assert.Equal(t, id, getResp["Id"]) @@ -175,7 +178,7 @@ func TestHandler_MulticastGroupCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) groups, ok := listResp["MulticastGroupList"].([]any) require.True(t, ok) assert.Len(t, groups, 1) @@ -186,7 +189,7 @@ func TestHandler_MulticastGroupCRUD(t *testing.T) { // Verify update rec = doIoTWRequest(t, h, http.MethodGet, "/multicast-groups/"+id, "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "mg1-updated", getResp["Name"]) // Delete @@ -208,7 +211,7 @@ func TestHandler_MulticastGroupSession(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Getting the session before one has been started must 404, matching real @@ -225,7 +228,7 @@ func TestHandler_MulticastGroupSession(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var sessionResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sessionResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sessionResp, jsonx.V1())) _, hasLoRaWAN := sessionResp["LoRaWAN"] assert.True(t, hasLoRaWAN) } @@ -240,7 +243,7 @@ func TestHandler_DisassociateWirelessDeviceFromMulticastGroup(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var mgResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mgResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mgResp, jsonx.V1())) mgID := mgResp["Id"].(string) // Create wireless device @@ -254,7 +257,7 @@ func TestHandler_DisassociateWirelessDeviceFromMulticastGroup(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var devResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp, jsonx.V1())) devID := devResp["Id"].(string) // Associate device with multicast group; AssociateWirelessDeviceWithMulticastGroup @@ -284,7 +287,7 @@ func TestHandler_SendDataToMulticastGroup_UniqueMessageID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) mgID := createResp["Id"].(string) seen := make(map[string]bool) @@ -296,7 +299,7 @@ func TestHandler_SendDataToMulticastGroup_UniqueMessageID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) msgID, _ := resp["MessageId"].(string) assert.NotEmpty(t, msgID) @@ -334,7 +337,7 @@ func TestHandler_SendDataToMulticastGroup_RequiresBody(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) mgID, _ := createResp["Id"].(string) require.NotEmpty(t, mgID) @@ -375,7 +378,7 @@ func TestHandler_MulticastGroup_BulkOps(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) mgID := createResp["Id"].(string) path := "/multicast-groups/" + mgID + "/bulk" @@ -397,7 +400,7 @@ func TestHandler_MulticastGroups_FullLifecycle(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) mgID, _ := createResp["Id"].(string) require.NotEmpty(t, mgID) diff --git a/services/iotwireless/handler_network_analyzer.go b/services/iotwireless/handler_network_analyzer.go index 7dab9b41f5..ab7e043e87 100644 --- a/services/iotwireless/handler_network_analyzer.go +++ b/services/iotwireless/handler_network_analyzer.go @@ -1,11 +1,12 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -46,7 +47,7 @@ func (h *Handler) createNetworkAnalyzerConfiguration(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) nc, err := h.Backend.CreateNetworkAnalyzerConfig( h.AccountID, h.DefaultRegion, @@ -125,7 +126,7 @@ func (h *Handler) updateNetworkAnalyzerConfiguration(c *echo.Context, name strin } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateNetworkAnalyzerConfig( h.AccountID, h.DefaultRegion, name, diff --git a/services/iotwireless/handler_network_analyzer_test.go b/services/iotwireless/handler_network_analyzer_test.go index 689e29244a..47d8fe5c65 100644 --- a/services/iotwireless/handler_network_analyzer_test.go +++ b/services/iotwireless/handler_network_analyzer_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_NetworkAnalyzerCRUD(t *testing.T) { @@ -20,7 +22,7 @@ func TestHandler_NetworkAnalyzerCRUD(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) name, _ := createResp["Name"].(string) assert.Equal(t, "na1", name) @@ -29,7 +31,7 @@ func TestHandler_NetworkAnalyzerCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "na1", getResp["Name"]) assert.Equal(t, "test config", getResp["Description"]) @@ -38,7 +40,7 @@ func TestHandler_NetworkAnalyzerCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok := listResp["NetworkAnalyzerConfigurationList"].([]any) require.True(t, ok) assert.Len(t, configs, 1) @@ -50,7 +52,7 @@ func TestHandler_NetworkAnalyzerCRUD(t *testing.T) { // Verify update rec = doIoTWRequest(t, h, http.MethodGet, "/network-analyzer-configurations/na1", "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "updated", getResp["Description"]) // Delete diff --git a/services/iotwireless/handler_partner_accounts.go b/services/iotwireless/handler_partner_accounts.go index 57371546c7..2ac6d00b98 100644 --- a/services/iotwireless/handler_partner_accounts.go +++ b/services/iotwireless/handler_partner_accounts.go @@ -2,12 +2,13 @@ package iotwireless import ( "cmp" - "encoding/json" + "encoding/json/v2" "net/http" "slices" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -47,7 +48,7 @@ type listPartnerAccountsResponse struct { func (h *Handler) associateAwsAccountWithPartnerAccount(c *echo.Context, body []byte) error { var req associatePartnerAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/iotwireless/handler_partner_accounts_test.go b/services/iotwireless/handler_partner_accounts_test.go index c1e21d25cb..e372eaa804 100644 --- a/services/iotwireless/handler_partner_accounts_test.go +++ b/services/iotwireless/handler_partner_accounts_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AssociateAwsAccountWithPartnerAccount(t *testing.T) { @@ -42,7 +44,7 @@ func TestHandler_AssociateAwsAccountWithPartnerAccount(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) sidewalk, ok := resp["Sidewalk"].(map[string]any) require.True(t, ok) @@ -63,7 +65,7 @@ func TestHandler_PartnerAccounts(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &assocResp, jsonx.V1())) assert.NotEmpty(t, assocResp["Arn"]) // Get partner account @@ -71,7 +73,7 @@ func TestHandler_PartnerAccounts(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, true, getResp["AccountLinked"]) sidewalk, ok := getResp["Sidewalk"].(map[string]any) require.True(t, ok, "AccountLinked accounts must include Sidewalk info") @@ -84,7 +86,7 @@ func TestHandler_PartnerAccounts(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var unlinkedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &unlinkedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &unlinkedResp, jsonx.V1())) assert.Equal(t, false, unlinkedResp["AccountLinked"]) // List partner accounts @@ -92,7 +94,7 @@ func TestHandler_PartnerAccounts(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sidewalkList, ok := listResp["Sidewalk"].([]any) require.True(t, ok) require.Len( diff --git a/services/iotwireless/handler_positioning.go b/services/iotwireless/handler_positioning.go index fddad4332e..857837ada2 100644 --- a/services/iotwireless/handler_positioning.go +++ b/services/iotwireless/handler_positioning.go @@ -3,13 +3,15 @@ package iotwireless import ( "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net" "net/http" "net/netip" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // accuracyResponse mirrors types.Accuracy: a struct of two float fields, not @@ -99,7 +101,7 @@ func (h *Handler) updatePosition(c *echo.Context, id string) error { var req map[string]any body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) _ = h.Backend.UpdatePosition(id, req) return stubNoContent(c) @@ -126,7 +128,7 @@ func (h *Handler) putPositionConfiguration(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.PutPositionConfiguration(id, resourceType, req.Destination, req.Solvers); err != nil { return handleError(c, err) @@ -172,7 +174,7 @@ type getPositionEstimateRequest struct { func (h *Handler) getPositionEstimate(c *echo.Context) error { var req getPositionEstimateRequest - _ = json.Unmarshal(readStubBody(c), &req) + _ = json.Unmarshal(readStubBody(c), &req, jsonx.V1()) if err := validatePositionEstimate(&req); err != nil { return handleError(c, err) diff --git a/services/iotwireless/handler_positioning_test.go b/services/iotwireless/handler_positioning_test.go index 1e33ae91cb..5334b18ca5 100644 --- a/services/iotwireless/handler_positioning_test.go +++ b/services/iotwireless/handler_positioning_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Position(t *testing.T) { @@ -19,7 +21,7 @@ func TestHandler_Position(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) pos, ok := getResp["Position"].([]any) require.True(t, ok) assert.Empty(t, pos) @@ -39,7 +41,7 @@ func TestHandler_Position(t *testing.T) { // coordinates, not a fabricated empty response. rec = doIoTWRequest(t, h, http.MethodGet, "/positions/resource-123", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) pos, ok = getResp["Position"].([]any) require.True(t, ok) assert.Equal(t, []any{47.6, -122.3, 100.0}, pos) @@ -57,7 +59,7 @@ func TestHandler_Position(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getCfgResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfgResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfgResp, jsonx.V1())) assert.NotContains(t, getCfgResp, "Destination") // Put position configuration with a real ResourceType and Destination. @@ -69,7 +71,7 @@ func TestHandler_Position(t *testing.T) { // Get position configuration must now reflect the stored destination. rec = doIoTWRequest(t, h, http.MethodGet, "/position-configurations/resource-123", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfgResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfgResp, jsonx.V1())) assert.Equal(t, "my-position-dest", getCfgResp["Destination"]) solvers, ok := getCfgResp["Solvers"].(map[string]any) require.True(t, ok) @@ -91,7 +93,7 @@ func TestHandler_Position(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok := listResp["PositionConfigurationList"].([]any) require.True(t, ok) require.Len(t, configs, 1) @@ -106,7 +108,7 @@ func TestHandler_Position(t *testing.T) { "", ) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok = listResp["PositionConfigurationList"].([]any) require.True(t, ok) assert.Empty(t, configs) @@ -228,7 +230,7 @@ func TestHandler_PositionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp[tt.wantKey] assert.True(t, ok, "expected key %q in position config response", tt.wantKey) @@ -237,7 +239,7 @@ func TestHandler_PositionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) cfgs, ok := listResp["PositionConfigurationList"].([]any) require.True(t, ok) require.Len(t, cfgs, 1) diff --git a/services/iotwireless/handler_profiles.go b/services/iotwireless/handler_profiles.go index b8248e35a3..0438b521a3 100644 --- a/services/iotwireless/handler_profiles.go +++ b/services/iotwireless/handler_profiles.go @@ -7,11 +7,12 @@ package iotwireless // grouped in one cohesive file instead. import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -54,7 +55,7 @@ type listDeviceProfilesResponse struct { func (h *Handler) createDeviceProfile(c *echo.Context, body []byte) error { var req createDeviceProfileRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -147,7 +148,7 @@ type listServiceProfilesResponse struct { func (h *Handler) createServiceProfile(c *echo.Context, body []byte) error { var req createServiceProfileRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/iotwireless/handler_profiles_test.go b/services/iotwireless/handler_profiles_test.go index c1889a8749..39451d1063 100644 --- a/services/iotwireless/handler_profiles_test.go +++ b/services/iotwireless/handler_profiles_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateDeviceProfile(t *testing.T) { @@ -39,7 +41,7 @@ func TestHandler_CreateDeviceProfile(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.NotEmpty(t, resp["Arn"]) }) @@ -71,7 +73,7 @@ func TestHandler_DeviceProfile_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) require.NotEmpty(t, id) @@ -80,7 +82,7 @@ func TestHandler_DeviceProfile_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.profileName, getResp["Name"]) assert.Equal(t, id, getResp["Id"]) @@ -89,7 +91,7 @@ func TestHandler_DeviceProfile_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) list, ok := listResp["DeviceProfileList"].([]any) require.True(t, ok) assert.Len(t, list, 1) @@ -121,7 +123,7 @@ func TestHandler_ServiceProfile_LoRaWANGetShape(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -129,7 +131,7 @@ func TestHandler_ServiceProfile_LoRaWANGetShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) loRaWAN, ok := getResp["LoRaWAN"].(map[string]any) require.True(t, ok, "LoRaWAN must be present on Get") assert.InDelta(t, float64(15), loRaWAN["DrMax"], 0.001) @@ -153,7 +155,7 @@ func TestHandler_DeviceProfile_SidewalkCreateShape(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) @@ -161,7 +163,7 @@ func TestHandler_DeviceProfile_SidewalkCreateShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) sidewalk, ok := getResp["Sidewalk"].(map[string]any) require.True(t, ok, "an empty Sidewalk request object must still mark the profile as Sidewalk on Get") assert.Empty(t, sidewalk, "AWS-assigned Sidewalk fields must not be fabricated") @@ -205,7 +207,7 @@ func TestHandler_ListDeviceProfiles_FilterByType(t *testing.T) { Name string `json:"Name"` } `json:"DeviceProfileList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := make([]string, 0, len(resp.DeviceProfileList)) for _, dp := range resp.DeviceProfileList { @@ -253,7 +255,7 @@ func TestHandler_CreateGetListDeleteServiceProfile(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, ok := createResp["Id"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -263,7 +265,7 @@ func TestHandler_CreateGetListDeleteServiceProfile(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.profileName, getResp["Name"]) // List @@ -271,7 +273,7 @@ func TestHandler_CreateGetListDeleteServiceProfile(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) profiles, ok := listResp["ServiceProfileList"].([]any) require.True(t, ok) assert.Len(t, profiles, 1) diff --git a/services/iotwireless/handler_tags.go b/services/iotwireless/handler_tags.go index 901f81a2c7..66abb03e09 100644 --- a/services/iotwireless/handler_tags.go +++ b/services/iotwireless/handler_tags.go @@ -1,12 +1,13 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -46,7 +47,7 @@ func (h *Handler) tagResource(c *echo.Context, resourceArn string, body []byte) } var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } diff --git a/services/iotwireless/handler_tags_test.go b/services/iotwireless/handler_tags_test.go index d86c12658d..1f3bb61064 100644 --- a/services/iotwireless/handler_tags_test.go +++ b/services/iotwireless/handler_tags_test.go @@ -1,7 +1,7 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListTagsTagUntagResource(t *testing.T) { @@ -51,7 +53,7 @@ func TestHandler_ListTagsTagUntagResource(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["Arn"].(string) require.NotEmpty(t, arn) @@ -85,7 +87,7 @@ func TestHandler_ListTagsTagUntagResource(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tagList, ok := tagsResp["Tags"].([]any) require.True(t, ok) diff --git a/services/iotwireless/handler_test.go b/services/iotwireless/handler_test.go index 2d8b687e8d..d95a6cdfa6 100644 --- a/services/iotwireless/handler_test.go +++ b/services/iotwireless/handler_test.go @@ -1,7 +1,7 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -325,7 +326,7 @@ func TestHandler_Reset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["WirelessDeviceList"].([]any) require.True(t, ok) @@ -411,7 +412,7 @@ func TestHandler_ListEmpty_NonNil(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp[tt.listKey].([]any) require.True(t, ok, "key %q should be a JSON array, got %T", tt.listKey, resp[tt.listKey]) @@ -482,7 +483,7 @@ func Test_RouteMatcher_TagOperations(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) resourceArn := created["Arn"].(string) require.NotEmpty(t, resourceArn) @@ -503,7 +504,7 @@ func Test_RouteMatcher_TagOperations(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listed, jsonx.V1())) require.Len(t, listed.Tags, 1) assert.Equal(t, "env", listed.Tags[0].Key) assert.Equal(t, "prod", listed.Tags[0].Value) @@ -531,7 +532,7 @@ func Test_RouteMatcher_AssociateAwsAccountWithPartnerAccount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) sidewalk, ok := resp["Sidewalk"].(map[string]any) @@ -545,7 +546,7 @@ func Test_RouteMatcher_AssociateAwsAccountWithPartnerAccount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, true, getResp["AccountLinked"]) } @@ -594,7 +595,7 @@ func Test_ErrorResponse_SetsAmznErrortypeHeader(t *testing.T) { assert.Equal(t, tt.wantErrType, rec.Header().Get("X-Amzn-Errortype")) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantErrType, body["__type"]) assert.NotEmpty(t, body["Message"]) }) diff --git a/services/iotwireless/handler_wireless_devices.go b/services/iotwireless/handler_wireless_devices.go index 99677f6bdd..bf982a4242 100644 --- a/services/iotwireless/handler_wireless_devices.go +++ b/services/iotwireless/handler_wireless_devices.go @@ -1,13 +1,14 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -100,7 +101,7 @@ type testWirelessDeviceResponse struct { func (h *Handler) createWirelessDevice(c *echo.Context, body []byte) error { var req createWirelessDeviceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -194,7 +195,7 @@ func (h *Handler) deleteWirelessDevice(c *echo.Context, id string) error { func (h *Handler) associateWirelessDeviceWithThing(c *echo.Context, wirelessDeviceID string, body []byte) error { var req associateWirelessDeviceWithThingRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -219,7 +220,7 @@ func (h *Handler) updateWirelessDevice(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateWirelessDevice( h.AccountID, h.DefaultRegion, id, @@ -283,7 +284,7 @@ func (h *Handler) sendDataToWirelessDevice(c *echo.Context, wirelessDeviceID str } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) messageID := uuid.NewString() diff --git a/services/iotwireless/handler_wireless_devices_filter_test.go b/services/iotwireless/handler_wireless_devices_filter_test.go index e0777de97d..69e2611d48 100644 --- a/services/iotwireless/handler_wireless_devices_filter_test.go +++ b/services/iotwireless/handler_wireless_devices_filter_test.go @@ -1,13 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -25,7 +26,7 @@ func listWirelessDevicesNames(t *testing.T, h *iotwireless.Handler, rawQuery str Name string `json:"Name"` } `json:"WirelessDeviceList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := make([]string, 0, len(resp.WirelessDeviceList)) for _, d := range resp.WirelessDeviceList { diff --git a/services/iotwireless/handler_wireless_devices_test.go b/services/iotwireless/handler_wireless_devices_test.go index 9216384928..27a826e1a7 100644 --- a/services/iotwireless/handler_wireless_devices_test.go +++ b/services/iotwireless/handler_wireless_devices_test.go @@ -1,13 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -41,7 +42,7 @@ func TestHandler_CreateGetListDeleteWirelessDevice(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, ok := createResp["Id"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -51,7 +52,7 @@ func TestHandler_CreateGetListDeleteWirelessDevice(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.deviceName, getResp["Name"]) // List @@ -59,7 +60,7 @@ func TestHandler_CreateGetListDeleteWirelessDevice(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) devices, ok := listResp["WirelessDeviceList"].([]any) require.True(t, ok) assert.Len(t, devices, 1) @@ -133,7 +134,7 @@ func TestHandler_AssociateWirelessDeviceWithThing(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) devID = createResp["Id"].(string) } @@ -155,7 +156,7 @@ func TestHandler_UpdateWirelessDevice(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Update @@ -168,7 +169,7 @@ func TestHandler_UpdateWirelessDevice(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "dev1-updated", getResp["Name"]) } @@ -188,7 +189,7 @@ func TestHandler_DeregisterWirelessDevice(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Deregister (should delete the device) @@ -216,7 +217,7 @@ func TestHandler_DisassociateWirelessDeviceFromThing(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) devID := createResp["Id"].(string) // Associate with thing @@ -239,14 +240,14 @@ func TestHandler_GetWirelessDeviceStatistics(t *testing.T) { require.Equal(t, http.StatusCreated, createResp.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) devID := created["Id"].(string) rec := doIoTWRequest(t, h, http.MethodGet, "/wireless-devices/"+devID+"/statistics", "") assert.Equal(t, http.StatusOK, rec.Code) var stats map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stats)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stats, jsonx.V1())) assert.Equal(t, devID, stats["WirelessDeviceId"]) } @@ -269,7 +270,7 @@ func TestHandler_SendDataToWirelessDevice(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["MessageId"]) } @@ -283,14 +284,14 @@ func TestHandler_TestWirelessDevice(t *testing.T) { require.Equal(t, http.StatusCreated, createResp.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) devID := created["Id"].(string) rec := doIoTWRequest(t, h, http.MethodPost, "/wireless-devices/"+devID+"/test", `{}`) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PASS", resp["Result"]) } @@ -319,7 +320,7 @@ func TestHandler_QueuedMessages_SendListDelete(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var devResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &devResp, jsonx.V1())) devID := devResp["Id"].(string) // List queued messages (empty) @@ -327,7 +328,7 @@ func TestHandler_QueuedMessages_SendListDelete(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) msgs, ok := listResp["DownlinkQueueMessagesList"].([]any) require.True(t, ok) assert.Empty(t, msgs) @@ -339,14 +340,14 @@ func TestHandler_QueuedMessages_SendListDelete(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sendResp, jsonx.V1())) sentMessageID, _ := sendResp["MessageId"].(string) require.NotEmpty(t, sentMessageID) // List queued messages must now reflect the sent message. rec = doIoTWRequest(t, h, http.MethodGet, "/wireless-devices/"+devID+"/data", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) msgs, ok = listResp["DownlinkQueueMessagesList"].([]any) require.True(t, ok) require.Len(t, msgs, 1) @@ -359,7 +360,7 @@ func TestHandler_QueuedMessages_SendListDelete(t *testing.T) { // After deletion, the queue must be empty again. rec = doIoTWRequest(t, h, http.MethodGet, "/wireless-devices/"+devID+"/data", "") assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) msgs, ok = listResp["DownlinkQueueMessagesList"].([]any) require.True(t, ok) assert.Empty(t, msgs) @@ -381,7 +382,7 @@ func TestHandler_SendDataToWirelessDevice_UniqueMessageID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) msgID, _ := resp["MessageId"].(string) assert.NotEmpty(t, msgID, "MessageId should not be empty") @@ -399,7 +400,7 @@ func setupWirelessDevice(t *testing.T, h *iotwireless.Handler, name, devType, de require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ := resp["Id"].(string) require.NotEmpty(t, id) @@ -418,7 +419,7 @@ func TestHandler_QueuedMessages_MultipleSends(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) devID, ok := createResp["Id"].(string) require.True(t, ok) @@ -427,7 +428,7 @@ func TestHandler_QueuedMessages_MultipleSends(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var pre map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pre)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pre, jsonx.V1())) assert.Empty(t, pre["DownlinkQueueMessagesList"]) // Send two messages (POST /wireless-devices/{id}/data). @@ -438,7 +439,7 @@ func TestHandler_QueuedMessages_MultipleSends(t *testing.T) { require.Equal(t, http.StatusCreated, r.Code) var sr map[string]any - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &sr)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &sr, jsonx.V1())) assert.NotEmpty(t, sr["MessageId"], "SendData must return a MessageId") } @@ -447,7 +448,7 @@ func TestHandler_QueuedMessages_MultipleSends(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var post map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &post)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &post, jsonx.V1())) msgs, ok := post["DownlinkQueueMessagesList"].([]any) require.True(t, ok) assert.Len(t, msgs, 2, "two enqueued messages must appear in list") @@ -472,7 +473,7 @@ func Test_GetWirelessDevice_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) id := created["Id"].(string) // Before association, ThingArn/ThingName must be absent. @@ -480,7 +481,7 @@ func Test_GetWirelessDevice_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var before map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &before, jsonx.V1())) assert.Empty(t, before["ThingArn"]) assert.Empty(t, before["ThingName"]) @@ -493,7 +494,7 @@ func Test_GetWirelessDevice_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var after map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &after, jsonx.V1())) assert.Equal(t, thingArn, after["ThingArn"]) assert.Equal(t, "my-thing", after["ThingName"]) @@ -504,7 +505,7 @@ func Test_GetWirelessDevice_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var afterDisassoc map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &afterDisassoc)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &afterDisassoc, jsonx.V1())) assert.Empty(t, afterDisassoc["ThingArn"]) assert.Empty(t, afterDisassoc["ThingName"]) } diff --git a/services/iotwireless/handler_wireless_devices_wireshape_test.go b/services/iotwireless/handler_wireless_devices_wireshape_test.go index b872399a17..6519dd787f 100644 --- a/services/iotwireless/handler_wireless_devices_wireshape_test.go +++ b/services/iotwireless/handler_wireless_devices_wireshape_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_CreateGetWirelessDevice_LoRaWANSidewalkWireShape drives a real @@ -35,7 +37,7 @@ func TestHandler_CreateGetWirelessDevice_LoRaWANSidewalkWireShape(t *testing.T) var createResp struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec = doIoTWRequest(t, h, http.MethodGet, "/wireless-devices/"+createResp.ID, "") require.Equal(t, http.StatusOK, rec.Code) @@ -57,7 +59,7 @@ func TestHandler_CreateGetWirelessDevice_LoRaWANSidewalkWireShape(t *testing.T) } `json:"AbpV1_0_x"` } `json:"LoRaWAN"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "dp-1", got.LoRaWAN.DeviceProfileID) assert.Equal(t, "addr-1", got.LoRaWAN.AbpV1_0X.DevAddr) @@ -94,7 +96,7 @@ func TestHandler_NetworkAnalyzerConfig_TraceContentWireShape(t *testing.T) { var got struct { TraceContent traceContent `json:"TraceContent"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "INFO", got.TraceContent.LogLevel) assert.Equal(t, "ENABLED", got.TraceContent.MulticastFrameInfo) assert.Empty(t, got.TraceContent.WirelessDeviceFrameInfo) @@ -109,7 +111,7 @@ func TestHandler_NetworkAnalyzerConfig_TraceContentWireShape(t *testing.T) { var got2 struct { TraceContent traceContent `json:"TraceContent"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got2, jsonx.V1())) assert.Empty(t, got2.TraceContent.LogLevel, "update replaces TraceContent wholesale") assert.Equal(t, "ENABLED", got2.TraceContent.WirelessDeviceFrameInfo) } @@ -137,7 +139,7 @@ func TestHandler_ListWirelessDevices_EntryShape(t *testing.T) { var got struct { WirelessDeviceList []map[string]any `json:"WirelessDeviceList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) require.Len(t, got.WirelessDeviceList, 1) entry := got.WirelessDeviceList[0] diff --git a/services/iotwireless/handler_wireless_gateway_tasks.go b/services/iotwireless/handler_wireless_gateway_tasks.go index 7d5e5e1802..b7674f2c7e 100644 --- a/services/iotwireless/handler_wireless_gateway_tasks.go +++ b/services/iotwireless/handler_wireless_gateway_tasks.go @@ -1,11 +1,13 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createWirelessGatewayTaskResponse struct { @@ -57,7 +59,7 @@ func (h *Handler) createWirelessGatewayTask(c *echo.Context, gatewayID string) e } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) task, err := h.Backend.CreateWirelessGatewayTask(gatewayID, req.WirelessGatewayTaskDefinitionID) if err != nil { @@ -103,7 +105,7 @@ func (h *Handler) createWirelessGatewayTaskDefinition(c *echo.Context) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) def, err := h.Backend.CreateWirelessGatewayTaskDefinition( h.AccountID, diff --git a/services/iotwireless/handler_wireless_gateway_tasks_test.go b/services/iotwireless/handler_wireless_gateway_tasks_test.go index 1238329c32..b3eec2db46 100644 --- a/services/iotwireless/handler_wireless_gateway_tasks_test.go +++ b/services/iotwireless/handler_wireless_gateway_tasks_test.go @@ -1,13 +1,15 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GatewayTaskLifecycle(t *testing.T) { @@ -20,7 +22,7 @@ func TestHandler_GatewayTaskLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var gwResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gwResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &gwResp, jsonx.V1())) gwID := gwResp["Id"].(string) // Create task definition @@ -29,7 +31,7 @@ func TestHandler_GatewayTaskLifecycle(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var defResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &defResp, jsonx.V1())) defID := defResp["Id"].(string) assert.NotEmpty(t, defID) @@ -39,7 +41,7 @@ func TestHandler_GatewayTaskLifecycle(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var taskResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &taskResp, jsonx.V1())) assert.Equal(t, "PENDING", taskResp["Status"]) // Get task @@ -47,7 +49,7 @@ func TestHandler_GatewayTaskLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getTaskResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getTaskResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getTaskResp, jsonx.V1())) assert.Equal(t, "PENDING", getTaskResp["Status"]) // List task definitions @@ -68,7 +70,7 @@ func TestHandler_GatewayTaskLifecycle(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var notFoundResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ¬FoundResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ¬FoundResp, jsonx.V1())) msg, _ := notFoundResp["Message"].(string) assert.NotContains(t, msg, "ResourceNotFoundException") assert.Contains(t, msg, "task") @@ -130,7 +132,7 @@ func TestHandler_ListWirelessGatewayTaskDefinitions_ReturnsRealData(t *testing.T require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, _ := createResp["Id"].(string) require.NotEmpty(t, id) createdIDs = append(createdIDs, id) @@ -140,7 +142,7 @@ func TestHandler_ListWirelessGatewayTaskDefinitions_ReturnsRealData(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) defs, ok := resp["TaskDefinitions"].([]any) require.True(t, ok, "TaskDefinitions should be array") @@ -199,7 +201,7 @@ func TestHandler_GatewayTaskDefinitionCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) arn := createResp["Arn"].(string) require.NotEmpty(t, id) @@ -210,7 +212,7 @@ func TestHandler_GatewayTaskDefinitionCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.defName, getResp["Name"]) // Delete. @@ -222,7 +224,7 @@ func TestHandler_GatewayTaskDefinitionCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) defs := listResp["TaskDefinitions"].([]any) assert.Empty(t, defs) }) @@ -252,7 +254,7 @@ func TestGetWirelessGatewayTaskDefinition_NotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) msg, _ := resp["Message"].(string) assert.NotContains(t, msg, "ResourceNotFoundException") @@ -276,7 +278,7 @@ func TestGetWirelessGatewayTaskDefinition_Found(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id, _ := created["Id"].(string) require.NotEmpty(t, id) @@ -284,7 +286,7 @@ func TestGetWirelessGatewayTaskDefinition_Found(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "real-taskdef", got["Name"]) assert.Equal(t, true, got["AutoCreateTasks"]) assert.NotEmpty(t, got["Arn"]) diff --git a/services/iotwireless/handler_wireless_gateways.go b/services/iotwireless/handler_wireless_gateways.go index 3fae05c554..eab16d533c 100644 --- a/services/iotwireless/handler_wireless_gateways.go +++ b/services/iotwireless/handler_wireless_gateways.go @@ -1,12 +1,13 @@ package iotwireless import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -51,7 +52,7 @@ type getWirelessGatewayStatisticsResponse struct { func (h *Handler) createWirelessGateway(c *echo.Context, body []byte) error { var req createWirelessGatewayRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -117,7 +118,7 @@ func (h *Handler) deleteWirelessGateway(c *echo.Context, id string) error { func (h *Handler) associateWirelessGatewayWithThing(c *echo.Context, gatewayID string, body []byte) error { var req associateWirelessGatewayWithThingRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "invalid request body") } @@ -141,7 +142,7 @@ func (h *Handler) updateWirelessGateway(c *echo.Context, id string) error { } body := readStubBody(c) - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if err := h.Backend.UpdateWirelessGateway( h.AccountID, h.DefaultRegion, id, req.Name, req.Description, diff --git a/services/iotwireless/handler_wireless_gateways_test.go b/services/iotwireless/handler_wireless_gateways_test.go index 4d7d5e41ea..ddfe6ef589 100644 --- a/services/iotwireless/handler_wireless_gateways_test.go +++ b/services/iotwireless/handler_wireless_gateways_test.go @@ -1,12 +1,15 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateGetListDeleteWirelessGateway(t *testing.T) { @@ -45,7 +48,7 @@ func TestHandler_CreateGetListDeleteWirelessGateway(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id, ok := createResp["Id"].(string) require.True(t, ok) assert.NotEmpty(t, id) @@ -55,7 +58,7 @@ func TestHandler_CreateGetListDeleteWirelessGateway(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.gatewayName, getResp["Name"]) // List @@ -63,7 +66,7 @@ func TestHandler_CreateGetListDeleteWirelessGateway(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) gateways, ok := listResp["WirelessGatewayList"].([]any) require.True(t, ok) assert.Len(t, gateways, 1) @@ -116,7 +119,7 @@ func TestHandler_AssociateWirelessGatewayWithThing(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) gwID = createResp["Id"].(string) } @@ -143,7 +146,7 @@ func TestHandler_UpdateWirelessGateway(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) // Update @@ -161,7 +164,7 @@ func TestHandler_UpdateWirelessGateway(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "gw1-updated", getResp["Name"]) } @@ -175,7 +178,7 @@ func TestHandler_DisassociateWirelessGatewayFromThing(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) gwID := createResp["Id"].(string) // Associate with thing @@ -198,7 +201,7 @@ func TestHandler_GetWirelessGatewayStatistics(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) gwID := createResp["Id"].(string) // Get statistics @@ -206,7 +209,7 @@ func TestHandler_GetWirelessGatewayStatistics(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var statsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &statsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &statsResp, jsonx.V1())) assert.Equal(t, "Connected", statsResp["ConnectionStatus"]) assert.Equal(t, gwID, statsResp["WirelessGatewayId"]) } @@ -229,14 +232,14 @@ func TestHandler_GetWirelessGatewayFirmwareInformation(t *testing.T) { require.Equal(t, http.StatusCreated, createResp.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) gwID := created["Id"].(string) rec := doIoTWRequest(t, h, http.MethodGet, "/wireless-gateways/"+gwID+"/firmware-information", "") assert.Equal(t, http.StatusOK, rec.Code) var info map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &info)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &info, jsonx.V1())) loRaWAN, ok := info["LoRaWAN"].(map[string]any) require.True(t, ok) currentVersion, ok := loRaWAN["CurrentVersion"].(map[string]any) @@ -264,7 +267,7 @@ func TestHandler_GatewayFirmwareInformation(t *testing.T) { require.Equal(t, http.StatusCreated, gwRec.Code) var gwResp map[string]any - require.NoError(t, json.Unmarshal(gwRec.Body.Bytes(), &gwResp)) + require.NoError(t, json.Unmarshal(gwRec.Body.Bytes(), &gwResp, jsonx.V1())) gwID, ok := gwResp["Id"].(string) require.True(t, ok) @@ -274,7 +277,7 @@ func TestHandler_GatewayFirmwareInformation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) loRaWAN, ok := resp["LoRaWAN"].(map[string]any) require.True(t, ok, "response must have LoRaWAN field") _, ok = loRaWAN["CurrentVersion"] @@ -292,7 +295,7 @@ func Test_GetWirelessGateway_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) id := created["Id"].(string) thingArn := "arn:aws:iot:us-east-1:000000000000:thing/gw-thing" @@ -304,7 +307,7 @@ func Test_GetWirelessGateway_ReflectsThingAssociation(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var after map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &after, jsonx.V1())) assert.Equal(t, thingArn, after["ThingArn"]) assert.Equal(t, "gw-thing", after["ThingName"]) } @@ -321,7 +324,7 @@ func TestHandler_WirelessGatewayAndDestinationUpdates(t *testing.T) { require.True(t, rec.Code >= 200 && rec.Code < 300) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) gwID, _ := createResp["Id"].(string) require.NotEmpty(t, gwID, "CreateWirelessGateway must return an Id") diff --git a/services/iotwireless/idempotency.go b/services/iotwireless/idempotency.go index 9d6d70a2fc..1f5d063aa0 100644 --- a/services/iotwireless/idempotency.go +++ b/services/iotwireless/idempotency.go @@ -3,13 +3,15 @@ package iotwireless import ( "bytes" "crypto/sha256" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/url" "sync" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxIdempotencyEntries = 1024 @@ -98,7 +100,7 @@ func (w *captureWriter) WriteHeader(status int) { // other body member. func requestTokenAndParams(body []byte) (string, [sha256.Size]byte, bool) { var members map[string]any - if err := json.Unmarshal(body, &members); err != nil { + if err := json.Unmarshal(body, &members, jsonx.V1()); err != nil { return "", [sha256.Size]byte{}, false } @@ -108,7 +110,7 @@ func requestTokenAndParams(body []byte) (string, [sha256.Size]byte, bool) { } delete(members, "ClientRequestToken") - canonical, err := json.Marshal(members) + canonical, err := json.Marshal(members, jsonx.V1()) if err != nil { return "", [sha256.Size]byte{}, false } diff --git a/services/iotwireless/idempotency_persistence_test.go b/services/iotwireless/idempotency_persistence_test.go index 2b38476260..7c70c7f27e 100644 --- a/services/iotwireless/idempotency_persistence_test.go +++ b/services/iotwireless/idempotency_persistence_test.go @@ -1,13 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -42,7 +43,7 @@ func TestClientRequestTokenSurvivesRestore(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var first map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first, jsonx.V1())) snap := h.Backend.(*iotwireless.InMemoryBackend).Snapshot(t.Context()) require.NotEmpty(t, snap) @@ -55,7 +56,7 @@ func TestClientRequestTokenSurvivesRestore(t *testing.T) { if tt.wantSameID { var again map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &again)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &again, jsonx.V1())) assert.Equal(t, first["Id"], again["Id"]) } }) diff --git a/services/iotwireless/import_task_single_test.go b/services/iotwireless/import_task_single_test.go index e1e006d21e..7e94f03c0b 100644 --- a/services/iotwireless/import_task_single_test.go +++ b/services/iotwireless/import_task_single_test.go @@ -1,13 +1,15 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSingleImportTaskRoundTrip(t *testing.T) { @@ -44,7 +46,7 @@ func TestSingleImportTaskRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var start map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) id, _ := start["Id"].(string) arn, _ := start["Arn"].(string) @@ -53,7 +55,7 @@ func TestSingleImportTaskRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "d1", got["DestinationName"]) assert.Equal(t, tt.wantPositioning, orEmpty(got["Positioning"])) @@ -71,7 +73,7 @@ func TestSingleImportTaskRoundTrip(t *testing.T) { } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp, jsonx.V1())) if tt.wantTagValue == "" { assert.Empty(t, tagResp.Tags) diff --git a/services/iotwireless/multi_region_test.go b/services/iotwireless/multi_region_test.go index 0976e756e6..9a2bfda197 100644 --- a/services/iotwireless/multi_region_test.go +++ b/services/iotwireless/multi_region_test.go @@ -2,7 +2,8 @@ package iotwireless_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -180,8 +182,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/iotwireless/multicast_bulk_test.go b/services/iotwireless/multicast_bulk_test.go index 32cb47192a..e690e00082 100644 --- a/services/iotwireless/multicast_bulk_test.go +++ b/services/iotwireless/multicast_bulk_test.go @@ -1,12 +1,13 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -86,7 +87,7 @@ func TestHandler_StartBulkAssociate_MutatesState(t *testing.T) { var created struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec = doIoTWRequest(t, h, "POST", "/wireless-devices", `{"Name":"d1","Type":"LoRaWAN"}`) require.Equal(t, 201, rec.Code) diff --git a/services/iotwireless/pagination_test.go b/services/iotwireless/pagination_test.go index db1b13b0fa..bbd3eb97af 100644 --- a/services/iotwireless/pagination_test.go +++ b/services/iotwireless/pagination_test.go @@ -1,12 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListWirelessDevices_Pagination locks in real cursor @@ -47,7 +49,7 @@ func TestHandler_ListWirelessDevices_Pagination(t *testing.T) { require.Equal(t, 200, rec.Code) var resp listResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.LessOrEqual(t, len(resp.WirelessDeviceList), 2, "page size must respect maxResults") for _, d := range resp.WirelessDeviceList { diff --git a/services/iotwireless/persistence.go b/services/iotwireless/persistence.go index 037e563fec..67b5e39aa9 100644 --- a/services/iotwireless/persistence.go +++ b/services/iotwireless/persistence.go @@ -2,11 +2,13 @@ package iotwireless import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -229,7 +231,7 @@ func newDirtyDTORegistry() ( // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourceTags map[string]map[string]string `json:"resourceTags,omitempty"` PartnerAccounts map[string]string `json:"partnerAccounts,omitempty"` FuotaTaskMulticast map[string]map[string]bool `json:"fuotaTaskMulticast,omitempty"` @@ -296,7 +298,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Idempotency: idemEntries, } - data, err := json.Marshal(snap) //nolint:musttag // nested types lack tags + data, err := json.Marshal(snap, jsonx.V1()) //nolint:musttag // nested types lack tags if err != nil { logger.Load(ctx).WarnContext(ctx, "iotwireless: failed to marshal snapshot", "error", err) @@ -309,7 +311,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { // snapshotDirtyTablesLocked builds the ephemeral DTO registry from the 8 // account/region-scoped tables and returns its SnapshotAll() output. Must be // called with b.mu held for reading. -func (b *InMemoryBackend) snapshotDirtyTablesLocked() (map[string]json.RawMessage, error) { +func (b *InMemoryBackend) snapshotDirtyTablesLocked() (map[string]jsontext.Value, error) { dtoReg, deviceDTOs, gatewayDTOs, serviceProfileDTOs, destinationDTOs, deviceProfileDTOs, fuotaTaskDTOs, multicastGroupDTOs, networkAnalyzerConfigDTOs := newDirtyDTORegistry() @@ -473,7 +475,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // ephemeral DTO registry, converting each DTO back to its live type by // re-populating the AccountID/Region fields the live type excludes from // JSON. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, deviceDTOs, gatewayDTOs, serviceProfileDTOs, destinationDTOs, deviceProfileDTOs, fuotaTaskDTOs, multicastGroupDTOs, networkAnalyzerConfigDTOs := newDirtyDTORegistry() diff --git a/services/iotwireless/wireless_gateway_tasks_test.go b/services/iotwireless/wireless_gateway_tasks_test.go index 1025fc4bff..7aff86bd25 100644 --- a/services/iotwireless/wireless_gateway_tasks_test.go +++ b/services/iotwireless/wireless_gateway_tasks_test.go @@ -1,13 +1,14 @@ package iotwireless_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iotwireless" ) @@ -115,7 +116,7 @@ func TestHandler_ListWirelessGatewayTaskDefinitions_EntryShape(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) entries, ok := resp["TaskDefinitions"].([]any) require.True(t, ok) diff --git a/services/kafka/handler.go b/services/kafka/handler.go index 9207105890..f57fbfc811 100644 --- a/services/kafka/handler.go +++ b/services/kafka/handler.go @@ -3,7 +3,7 @@ package kafka import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -653,7 +654,7 @@ func decodeJSONBody(body []byte, v any) error { return nil } - return json.Unmarshal(body, v) + return json.Unmarshal(body, v, jsonx.V1()) } // ---------------------------------------- @@ -666,7 +667,7 @@ const defaultPageSize = 100 func encodeKafkaPageToken(offset int) string { data, _ := json.Marshal(struct { O int `json:"o"` - }{O: offset}) + }{O: offset}, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(data) } @@ -689,7 +690,7 @@ func decodeKafkaPageToken(token string) int { O int `json:"o"` } - err = json.Unmarshal(data, &t) + err = json.Unmarshal(data, &t, jsonx.V1()) if err != nil || t.O < 0 { return 0 } diff --git a/services/kafka/handler_channels.go b/services/kafka/handler_channels.go index 114bcda87d..891f34bbfb 100644 --- a/services/kafka/handler_channels.go +++ b/services/kafka/handler_channels.go @@ -2,11 +2,13 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // splitChannelResource splits the handler's internal "clusterArn|channelArn" @@ -53,7 +55,7 @@ func (h *Handler) handleCreateChannel( body []byte, ) error { var in createChannelInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "BadRequestException", "invalid request body: "+err.Error()) } @@ -219,7 +221,7 @@ func (h *Handler) handleUpdateChannel( } var in updateChannelInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "BadRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kafka/handler_channels_test.go b/services/kafka/handler_channels_test.go index d9d2e62426..767831b74b 100644 --- a/services/kafka/handler_channels_test.go +++ b/services/kafka/handler_channels_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -278,7 +279,7 @@ func TestKafka_ListChannelsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) channels1, _ := resp1["channels"].([]any) assert.Len(t, channels1, 3) @@ -292,7 +293,7 @@ func TestKafka_ListChannelsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) channels2, _ := resp2["channels"].([]any) assert.Len(t, channels2, 2) assert.Empty(t, resp2["nextToken"]) diff --git a/services/kafka/handler_cluster_operations_test.go b/services/kafka/handler_cluster_operations_test.go index c84eba36fb..b72cfc4ec9 100644 --- a/services/kafka/handler_cluster_operations_test.go +++ b/services/kafka/handler_cluster_operations_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -44,7 +45,7 @@ func TestKafka_DescribeClusterOperation(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) op := backend.AddClusterOperationInternal(clusterArn, "UPDATE_BROKER_COUNT") @@ -63,7 +64,7 @@ func TestKafka_DescribeClusterOperation(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) opInfo, ok := resp["clusterOperationInfo"].(map[string]any) require.True(t, ok) @@ -145,7 +146,7 @@ func TestClusterOperationTracking_V1(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) opList, ok := listResp["clusterOperationInfoList"].([]any) require.True(t, ok) assert.GreaterOrEqual(t, len(opList), 2, "should have at least 2 operations") @@ -167,7 +168,7 @@ func TestClusterOperationTracking_V1(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) opInfo, infoOK := descResp["clusterOperationInfo"].(map[string]any) require.True(t, infoOK) assert.Equal(t, opArn, opInfo["operationArn"]) @@ -195,7 +196,7 @@ func TestClusterOperationTracking_V2(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) opList, ok := listResp["clusterOperationInfoList"].([]any) require.True(t, ok) require.NotEmpty(t, opList) @@ -205,7 +206,7 @@ func TestClusterOperationTracking_V2(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) opInfo, ok := descResp["clusterOperationInfo"].(map[string]any) require.True(t, ok) assert.Equal(t, opArn, opInfo["operationArn"]) @@ -242,7 +243,7 @@ func TestListClusterOperationsV2_OmitsDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) opList, ok := listResp["clusterOperationInfoList"].([]any) require.True(t, ok) require.NotEmpty(t, opList) diff --git a/services/kafka/handler_cluster_policy.go b/services/kafka/handler_cluster_policy.go index 8c22076d55..253d60166c 100644 --- a/services/kafka/handler_cluster_policy.go +++ b/services/kafka/handler_cluster_policy.go @@ -2,10 +2,12 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDeleteClusterPolicy( @@ -54,7 +56,7 @@ func (h *Handler) handlePutClusterPolicy( body []byte, ) error { var in putClusterPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_cluster_policy_test.go b/services/kafka/handler_cluster_policy_test.go index c78902031f..58ddcf8898 100644 --- a/services/kafka/handler_cluster_policy_test.go +++ b/services/kafka/handler_cluster_policy_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -45,7 +46,7 @@ func TestKafka_DeleteClusterPolicy(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) var clusterArn string if tt.useRealArn { diff --git a/services/kafka/handler_cluster_updates.go b/services/kafka/handler_cluster_updates.go index 14b0951e7a..15e429de47 100644 --- a/services/kafka/handler_cluster_updates.go +++ b/services/kafka/handler_cluster_updates.go @@ -2,10 +2,12 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type rebootBrokerInput struct { @@ -23,7 +25,7 @@ func (h *Handler) handleRebootBroker( body []byte, ) error { var in rebootBrokerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -116,7 +118,7 @@ func (h *Handler) handleUpdateBrokerCount( body []byte, ) error { var in updateBrokerCountInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -147,7 +149,7 @@ func (h *Handler) handleUpdateBrokerStorage( body []byte, ) error { var in updateBrokerStorageInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -183,7 +185,7 @@ func (h *Handler) handleUpdateBrokerType( body []byte, ) error { var in updateBrokerTypeInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -214,7 +216,7 @@ func (h *Handler) handleUpdateClusterConfiguration( body []byte, ) error { var in updateClusterConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -249,7 +251,7 @@ func (h *Handler) handleUpdateClusterKafkaVersion( body []byte, ) error { var in updateClusterKafkaVersionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -361,7 +363,7 @@ func (h *Handler) handleUpdateRebalancing( body []byte, ) error { var in updateRebalancingInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_cluster_updates_test.go b/services/kafka/handler_cluster_updates_test.go index 95bf2799d1..c1d0ea8b83 100644 --- a/services/kafka/handler_cluster_updates_test.go +++ b/services/kafka/handler_cluster_updates_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -164,7 +165,7 @@ func TestUpdateOpsRequireCurrentVersion(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "BadRequestException", errResp["__type"], "wrong version must produce BadRequestException") } @@ -285,7 +286,7 @@ func TestUpdateBrokerCount_Persists(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo, ok := descResp["clusterInfo"].(map[string]any) require.True(t, ok) provisioned, ok := clusterInfo["provisioned"].(map[string]any) @@ -323,7 +324,7 @@ func TestUpdateBrokerStorage_Persists(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo, _ := descResp["clusterInfo"].(map[string]any) provisioned, _ := clusterInfo["provisioned"].(map[string]any) bng, _ := provisioned["brokerNodeGroupInfo"].(map[string]any) @@ -357,7 +358,7 @@ func TestUpdateBrokerType_Persists(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo, _ := descResp["clusterInfo"].(map[string]any) provisioned, _ := clusterInfo["provisioned"].(map[string]any) bng, _ := provisioned["brokerNodeGroupInfo"].(map[string]any) @@ -389,7 +390,7 @@ func TestUpdateClusterKafkaVersion_Persists(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo, _ := descResp["clusterInfo"].(map[string]any) provisioned, _ := clusterInfo["provisioned"].(map[string]any) assert.Equal( @@ -608,7 +609,7 @@ func TestUpdateClusterConfiguration_V2Path(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo, _ := descResp["clusterInfo"].(map[string]any) provisioned, _ := clusterInfo["provisioned"].(map[string]any) assert.NotContains(t, provisioned, "configurationInfo", diff --git a/services/kafka/handler_clusters.go b/services/kafka/handler_clusters.go index 80a9844d5a..663ed3da9e 100644 --- a/services/kafka/handler_clusters.go +++ b/services/kafka/handler_clusters.go @@ -2,13 +2,15 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createClusterInput is CreateClusterInput (api_op_CreateCluster.go, @@ -233,7 +235,7 @@ type createClusterV2Output struct { func (h *Handler) handleCreateCluster(ctx context.Context, c *echo.Context, body []byte) error { var in createClusterInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -264,7 +266,7 @@ func (h *Handler) handleCreateCluster(ctx context.Context, c *echo.Context, body func (h *Handler) handleCreateClusterV2(ctx context.Context, c *echo.Context, body []byte) error { var in createClusterV2Input - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_clusters_fields_test.go b/services/kafka/handler_clusters_fields_test.go index 4ff7c37be6..9e51d41ce5 100644 --- a/services/kafka/handler_clusters_fields_test.go +++ b/services/kafka/handler_clusters_fields_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -240,7 +241,7 @@ func TestServerlessCluster_HTTP(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["clusterType"]) } }) @@ -266,7 +267,7 @@ func TestDescribeClusterV2_ServerlessArm(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo, ok := resp["clusterInfo"].(map[string]any) require.True(t, ok) @@ -287,7 +288,7 @@ func TestDescribeClusterV2_ProvisionedArm(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo, ok := resp["clusterInfo"].(map[string]any) require.True(t, ok) @@ -392,7 +393,7 @@ func TestEncryptionInfo_InV1Response(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo := resp["clusterInfo"].(map[string]any) encInfo, ok := clInfo["encryptionInfo"].(map[string]any) @@ -428,7 +429,7 @@ func TestEncryptionInfo_InV2Response(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo := resp["clusterInfo"].(map[string]any) provisioned, ok := clInfo["provisioned"].(map[string]any) diff --git a/services/kafka/handler_clusters_shapes_test.go b/services/kafka/handler_clusters_shapes_test.go index e12fc8cdd8..1903a276fc 100644 --- a/services/kafka/handler_clusters_shapes_test.go +++ b/services/kafka/handler_clusters_shapes_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -184,7 +185,7 @@ func TestListClustersV2_ClusterType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterList := resp["clusterInfoList"].([]any) require.Len(t, clusterList, 2) @@ -271,7 +272,7 @@ func TestListClustersV2_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterList, _ := resp["clusterInfoList"].([]any) @@ -301,7 +302,7 @@ func TestListClusters_NameFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterList, _ := resp["clusterInfoList"].([]any) @@ -328,7 +329,7 @@ func TestListClustersV2_ServerlessHasNoProvisionedArm(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterList := resp["clusterInfoList"].([]any) require.Len(t, clusterList, 1) @@ -411,7 +412,7 @@ func TestOpenMonitoring_InV2Response(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo := resp["clusterInfo"].(map[string]any) provisioned := clInfo["provisioned"].(map[string]any) @@ -593,7 +594,7 @@ func TestCreateCluster_V1_HTTP_AuthModes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["clusterArn"]) }) } @@ -695,7 +696,7 @@ func TestGetBootstrapBrokers_Variants(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["bootstrapBrokerString"], "default ClientBroker is TLS: no plaintext listener") assert.NotEmpty(t, resp["bootstrapBrokerStringTls"], "TLS broker string present for the default mode") @@ -754,7 +755,7 @@ func TestGetBootstrapBrokers_ScramPublic(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["bootstrapBrokerStringSaslScram"]) assert.NotEmpty(t, resp["bootstrapBrokerStringPublicTls"]) @@ -773,7 +774,7 @@ func TestZookeeperConnectString(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo := resp["clusterInfo"].(map[string]any) zkStr, ok := clInfo["zookeeperConnectString"].(string) @@ -810,7 +811,7 @@ func TestDescribeCluster_V1_IncludesNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clInfo := resp["clusterInfo"].(map[string]any) assert.Equal(t, kafka.EnhancedMonitoringPerBroker, clInfo["enhancedMonitoring"]) diff --git a/services/kafka/handler_clusters_test.go b/services/kafka/handler_clusters_test.go index 25d03dbb46..db05354409 100644 --- a/services/kafka/handler_clusters_test.go +++ b/services/kafka/handler_clusters_test.go @@ -3,7 +3,7 @@ package kafka_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -60,7 +61,7 @@ func TestKafka_CreateCluster(t *testing.T) { var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -78,7 +79,7 @@ func TestKafka_CreateCluster(t *testing.T) { if tt.wantFields != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for k, v := range tt.wantFields { assert.Equal(t, v, resp[k]) @@ -149,7 +150,7 @@ func TestKafka_ListClusters(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["clusterInfoList"].([]any) require.True(t, ok) @@ -211,7 +212,7 @@ func TestKafka_DescribeAndDeleteCluster(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) var clusterArn string if tt.useRealArn { @@ -276,7 +277,7 @@ func TestKafka_GetBootstrapBrokers(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) var clusterArn string if tt.useRealArn { @@ -293,7 +294,7 @@ func TestKafka_GetBootstrapBrokers(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["bootstrapBrokerString"], "default ClientBroker is TLS: no plaintext listener") assert.Len(t, strings.Split(resp["bootstrapBrokerStringTls"].(string), ","), 3) } @@ -340,7 +341,7 @@ func TestKafka_CreateClusterV2(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "v2-cluster", resp["clusterName"]) assert.Equal(t, "PROVISIONED", resp["clusterType"]) assert.NotEmpty(t, resp["clusterArn"]) @@ -380,7 +381,7 @@ func TestKafka_DescribeClusterV2(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) var clusterArn string if tt.useRealArn { @@ -395,7 +396,7 @@ func TestKafka_DescribeClusterV2(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterInfo, ok := resp["clusterInfo"].(map[string]any) require.True(t, ok) @@ -456,7 +457,7 @@ func TestKafka_ListClustersV2(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, ok := resp["clusterInfoList"].([]any) require.True(t, ok) @@ -582,7 +583,7 @@ func TestListClustersPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) list1, ok := resp1["clusterInfoList"].([]any) require.True(t, ok, "clusterInfoList must be an array") @@ -601,7 +602,7 @@ func TestListClustersPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) list2, ok2 := resp2["clusterInfoList"].([]any) require.True(t, ok2) @@ -638,7 +639,7 @@ func TestListClusters_NegativeOffsetToken(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["clusterInfoList"].([]any) require.True(t, ok, "clusterInfoList must be an array") @@ -662,7 +663,7 @@ func TestListClustersV2Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) list1 := resp1["clusterInfoList"].([]any) assert.Len(t, list1, 2) @@ -675,7 +676,7 @@ func TestListClustersV2Pagination(t *testing.T) { var tok struct { O int `json:"o"` } - require.NoError(t, json.Unmarshal(decoded, &tok)) + require.NoError(t, json.Unmarshal(decoded, &tok, jsonx.V1())) assert.Equal(t, 2, tok.O) path2 := "/api/v2/clusters?maxResults=2&nextToken=" + url.QueryEscape(nextToken) @@ -683,7 +684,7 @@ func TestListClustersV2Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) list2 := resp2["clusterInfoList"].([]any) assert.Len(t, list2, 2) assert.Empty(t, resp2["nextToken"]) @@ -727,7 +728,7 @@ func TestClusterCreatingToActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn = createResp["clusterArn"].(string) } else { rec := doKafkaRequest(t, h, http.MethodPost, "/v1/clusters", map[string]any{ @@ -742,7 +743,7 @@ func TestClusterCreatingToActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn = createResp["clusterArn"].(string) assert.Equal(t, kafka.ClusterStateCreating, createResp["state"]) } @@ -755,7 +756,7 @@ func TestClusterCreatingToActive(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusterInfo := descResp["clusterInfo"].(map[string]any) assert.Equal(t, kafka.ClusterStateActive, clusterInfo["state"]) }) @@ -779,7 +780,7 @@ func TestInvalidNextTokenFallsBackToStart(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list := resp["clusterInfoList"].([]any) assert.Len(t, list, 3) } @@ -803,7 +804,7 @@ func TestCreateClusterV2HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "v2-cluster", resp["clusterName"]) assert.Equal(t, "PROVISIONED", resp["clusterType"]) } diff --git a/services/kafka/handler_configurations.go b/services/kafka/handler_configurations.go index a01c8f512b..71e4ccc8b0 100644 --- a/services/kafka/handler_configurations.go +++ b/services/kafka/handler_configurations.go @@ -2,12 +2,14 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createConfigurationInput struct { @@ -54,7 +56,7 @@ func (h *Handler) handleCreateConfiguration( body []byte, ) error { var in createConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -231,7 +233,7 @@ func (h *Handler) handleUpdateConfiguration( body []byte, ) error { var in updateConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_configurations_test.go b/services/kafka/handler_configurations_test.go index 4618d610a1..b27c39e458 100644 --- a/services/kafka/handler_configurations_test.go +++ b/services/kafka/handler_configurations_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -56,7 +57,7 @@ func TestKafka_CreateAndDescribeConfiguration(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-config", resp["name"]) assert.NotEmpty(t, resp["arn"]) } @@ -102,7 +103,7 @@ func TestKafka_ListConfigurations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs, ok := resp["configurations"].([]any) require.True(t, ok) @@ -144,7 +145,7 @@ func TestKafka_DescribeAndDeleteConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) var cfgArn string if tt.useRealArn { @@ -209,7 +210,7 @@ func TestCreateConfigurationResponseIncludesStateAndRevision(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["arn"], "arn must be present") assert.NotEmpty(t, resp["name"], "name must be present") @@ -269,7 +270,7 @@ func TestListConfigurationsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs := resp["configurations"].([]any) assert.Len(t, configs, tt.wantPage1) @@ -301,7 +302,7 @@ func TestConfigRevision_DescribeAndList(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.InDelta(t, float64(1), descResp["revision"], 0) // ListConfigurationRevisions. @@ -310,7 +311,7 @@ func TestConfigRevision_DescribeAndList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) revisions, _ := listResp["revisions"].([]any) assert.NotEmpty(t, revisions, "should have at least one revision") } @@ -330,7 +331,7 @@ func TestConfigRevision_UpdateConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, configArn, updateResp["arn"]) assert.Equal(t, "cfg-update-test", updateResp["name"]) } diff --git a/services/kafka/handler_nodes_test.go b/services/kafka/handler_nodes_test.go index 1b599896a7..442b5d11b0 100644 --- a/services/kafka/handler_nodes_test.go +++ b/services/kafka/handler_nodes_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -110,7 +111,7 @@ func TestListKafkaVersions_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["kafkaVersions"].([]any) require.True(t, ok) diff --git a/services/kafka/handler_replicators.go b/services/kafka/handler_replicators.go index 8f1687cbfd..913c41434f 100644 --- a/services/kafka/handler_replicators.go +++ b/services/kafka/handler_replicators.go @@ -2,12 +2,14 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // amazonMskClusterDTO mirrors types.AmazonMskCluster. @@ -338,7 +340,7 @@ type createReplicatorOutput struct { func (h *Handler) handleCreateReplicator(ctx context.Context, c *echo.Context, body []byte) error { var in createReplicatorInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -599,7 +601,7 @@ func (h *Handler) handleUpdateReplicationInfo( body []byte, ) error { var in updateReplicationInfoInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_replicators_test.go b/services/kafka/handler_replicators_test.go index 828b4ada3c..6be668964f 100644 --- a/services/kafka/handler_replicators_test.go +++ b/services/kafka/handler_replicators_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -48,7 +49,7 @@ func TestKafka_CreateReplicator(t *testing.T) { var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -66,7 +67,7 @@ func TestKafka_CreateReplicator(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-replicator", resp["replicatorName"]) assert.NotEmpty(t, resp["replicatorArn"]) assert.Equal(t, kafka.ReplicatorStateRunning, resp["replicatorState"]) @@ -97,7 +98,7 @@ func TestKafka_DeleteReplicator(t *testing.T) { bodyBytes, _ := json.Marshal(map[string]any{ "replicatorName": "my-replicator", "serviceExecutionRoleArn": "arn:aws:iam::000000000000:role/my-role", - }) + }, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/replication/v1/replicators", bytes.NewReader(bodyBytes)) req.Header.Set("Content-Type", "application/json") rec := httptest.NewRecorder() @@ -107,7 +108,7 @@ func TestKafka_DeleteReplicator(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) var replicatorArn string if tt.useRealArn { @@ -172,7 +173,7 @@ func TestListReplicatorsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) reps := resp["replicators"].([]any) assert.Len(t, reps, 2) @@ -186,7 +187,7 @@ func TestListReplicatorsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) reps2 := resp2["replicators"].([]any) assert.Len(t, reps2, 1) assert.Empty(t, resp2["nextToken"]) @@ -341,7 +342,7 @@ func TestReplicator_UpdateReplicationInfo(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code, updateRec.Body.String()) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, replicatorArn, updateResp["replicatorArn"]) assert.NotEmpty(t, updateResp["replicatorState"]) } diff --git a/services/kafka/handler_scram_secrets.go b/services/kafka/handler_scram_secrets.go index 94118f7c09..b60a996776 100644 --- a/services/kafka/handler_scram_secrets.go +++ b/services/kafka/handler_scram_secrets.go @@ -2,10 +2,12 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type scramSecretInput struct { @@ -24,7 +26,7 @@ func (h *Handler) handleBatchAssociateScramSecret( body []byte, ) error { var in scramSecretInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -48,7 +50,7 @@ func (h *Handler) handleBatchDisassociateScramSecret( body []byte, ) error { var in scramSecretInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_scram_secrets_test.go b/services/kafka/handler_scram_secrets_test.go index 611898c9b5..5c04a56063 100644 --- a/services/kafka/handler_scram_secrets_test.go +++ b/services/kafka/handler_scram_secrets_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestKafka_BatchAssociateScramSecret(t *testing.T) { @@ -53,14 +55,14 @@ func TestKafka_BatchAssociateScramSecret(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) encodedArn := url.PathEscape(clusterArn) var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -82,7 +84,7 @@ func TestKafka_BatchAssociateScramSecret(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "unprocessedScramSecrets") } }) @@ -117,14 +119,14 @@ func TestKafka_BatchDisassociateScramSecret(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) encodedArn := url.PathEscape(clusterArn) secretArn := "arn:aws:secretsmanager:us-east-1:000000000000:secret/my-secret" // Associate first - bodyBytes, _ := json.Marshal(map[string]any{"secretArnList": []string{secretArn}}) + bodyBytes, _ := json.Marshal(map[string]any{"secretArnList": []string{secretArn}}, jsonx.V1()) e := echo.New() req := httptest.NewRequest( http.MethodPost, @@ -139,7 +141,7 @@ func TestKafka_BatchDisassociateScramSecret(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) // Disassociate - bodyBytes2, _ := json.Marshal(map[string]any{"secretArnList": []string{secretArn}}) + bodyBytes2, _ := json.Marshal(map[string]any{"secretArnList": []string{secretArn}}, jsonx.V1()) req2 := httptest.NewRequest( http.MethodPatch, "/v1/clusters/"+encodedArn+"/scram-secrets", @@ -188,7 +190,7 @@ func TestScramSecret_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) unprocessed, _ := assocResp["unprocessedScramSecrets"].([]any) assert.Empty(t, unprocessed, "no secrets should be unprocessed") @@ -198,7 +200,7 @@ func TestScramSecret_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) secretList, _ := listResp["secretArnList"].([]any) require.Len(t, secretList, 1) assert.Equal(t, secretArn, secretList[0]) @@ -210,7 +212,7 @@ func TestScramSecret_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, disassocRec.Code) var disassocResp map[string]any - require.NoError(t, json.Unmarshal(disassocRec.Body.Bytes(), &disassocResp)) + require.NoError(t, json.Unmarshal(disassocRec.Body.Bytes(), &disassocResp, jsonx.V1())) unprocessed2, _ := disassocResp["unprocessedScramSecrets"].([]any) assert.Empty(t, unprocessed2, "no secrets should be unprocessed after disassociate") @@ -220,7 +222,7 @@ func TestScramSecret_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2, jsonx.V1())) secretList2, _ := listResp2["secretArnList"].([]any) assert.Empty(t, secretList2, "list should be empty after disassociate") } @@ -248,7 +250,7 @@ func TestScramSecret_AssociateMultiple(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) secretList, _ := listResp["secretArnList"].([]any) assert.Len(t, secretList, 3) } @@ -292,7 +294,7 @@ func TestBatchAssociateThenDisassociate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) clusterArn := cr["clusterArn"].(string) encoded := url.PathEscape(clusterArn) diff --git a/services/kafka/handler_tags.go b/services/kafka/handler_tags.go index f562abdbf4..acfd4d29ef 100644 --- a/services/kafka/handler_tags.go +++ b/services/kafka/handler_tags.go @@ -2,11 +2,13 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listTagsOutput struct { @@ -37,7 +39,7 @@ func (h *Handler) handleTagResource( body []byte, ) error { var in tagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_tags_test.go b/services/kafka/handler_tags_test.go index 50cabf4b2f..fdf6d0f9f4 100644 --- a/services/kafka/handler_tags_test.go +++ b/services/kafka/handler_tags_test.go @@ -1,7 +1,7 @@ package kafka_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestKafka_TagOperations(t *testing.T) { @@ -43,7 +45,7 @@ func TestKafka_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) encodedArn := url.PathEscape(clusterArn) tagPath := "/v1/tags/" + encodedArn @@ -98,7 +100,7 @@ func TestTag_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) assert.Equal(t, "infra", tags["team"]) @@ -119,7 +121,7 @@ func TestTag_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp2, jsonx.V1())) tags2, _ := listResp2["tags"].(map[string]any) assert.Equal(t, "test", tags2["env"]) _, hasTeam := tags2["team"] @@ -138,7 +140,7 @@ func TestTag_ListEmpty(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) assert.Empty(t, tags, "freshly created cluster should have no tags") } diff --git a/services/kafka/handler_test.go b/services/kafka/handler_test.go index 703e4b3934..1fda0d39e2 100644 --- a/services/kafka/handler_test.go +++ b/services/kafka/handler_test.go @@ -2,7 +2,7 @@ package kafka_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -39,7 +40,7 @@ func doKafkaRequest(t *testing.T, h *kafka.Handler, method, path string, body an if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -68,7 +69,7 @@ func decodeJSONResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -88,7 +89,7 @@ func doKafkaRequestJSON( var resp map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) } return resp, rec.Code diff --git a/services/kafka/handler_topics.go b/services/kafka/handler_topics.go index 3ebf1f8085..1b26b1a699 100644 --- a/services/kafka/handler_topics.go +++ b/services/kafka/handler_topics.go @@ -2,11 +2,13 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createTopicInput mirrors aws-sdk-go-v2/service/kafka's CreateTopicInput @@ -34,7 +36,7 @@ func (h *Handler) handleCreateTopic( body []byte, ) error { var in createTopicInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -275,7 +277,7 @@ func (h *Handler) handleUpdateTopic( } var in updateTopicInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_topics_test.go b/services/kafka/handler_topics_test.go index 9f8c3d9256..e26f6e14c5 100644 --- a/services/kafka/handler_topics_test.go +++ b/services/kafka/handler_topics_test.go @@ -3,7 +3,7 @@ package kafka_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestKafka_CreateTopic(t *testing.T) { @@ -57,14 +59,14 @@ func TestKafka_CreateTopic(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) encodedArn := url.PathEscape(clusterArn) var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -86,7 +88,7 @@ func TestKafka_CreateTopic(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-topic", resp["topicName"]) } }) @@ -123,14 +125,14 @@ func TestKafka_DeleteTopic(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) encodedArn := url.PathEscape(clusterArn) // Create topic e := echo.New() topicBody, _ := json.Marshal( - map[string]any{"topicName": "my-topic", "replicationFactor": 1, "partitionCount": 3}, + map[string]any{"topicName": "my-topic", "replicationFactor": 1, "partitionCount": 3}, jsonx.V1(), ) reqCreate := httptest.NewRequest( http.MethodPost, @@ -236,7 +238,7 @@ func TestListTopicsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) topics1 := resp1["topics"].([]any) assert.Len(t, topics1, 3) @@ -253,7 +255,7 @@ func TestListTopicsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) topics2 := resp2["topics"].([]any) assert.Len(t, topics2, 2) assert.Empty(t, resp2["nextToken"]) diff --git a/services/kafka/handler_vpc_connections.go b/services/kafka/handler_vpc_connections.go index 47e824e445..cb7d381f17 100644 --- a/services/kafka/handler_vpc_connections.go +++ b/services/kafka/handler_vpc_connections.go @@ -2,10 +2,12 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createVpcConnectionInput struct { @@ -37,7 +39,7 @@ func (h *Handler) handleCreateVpcConnection( body []byte, ) error { var in createVpcConnectionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, @@ -208,7 +210,7 @@ func (h *Handler) handleRejectClientVpcConnection( body []byte, ) error { var in rejectClientVpcConnectionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError( c, http.StatusBadRequest, diff --git a/services/kafka/handler_vpc_connections_test.go b/services/kafka/handler_vpc_connections_test.go index aced96d301..67add0f2c8 100644 --- a/services/kafka/handler_vpc_connections_test.go +++ b/services/kafka/handler_vpc_connections_test.go @@ -3,7 +3,7 @@ package kafka_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -58,7 +59,7 @@ func TestKafka_CreateVpcConnection(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) body := tt.body @@ -69,7 +70,7 @@ func TestKafka_CreateVpcConnection(t *testing.T) { var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -87,7 +88,7 @@ func TestKafka_CreateVpcConnection(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["vpcConnectionArn"]) assert.Equal(t, kafka.VpcConnectionStateAvailable, resp["state"]) } @@ -126,7 +127,7 @@ func TestKafka_DeleteVpcConnection(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["clusterArn"].(string) // Create VPC connection @@ -135,7 +136,7 @@ func TestKafka_DeleteVpcConnection(t *testing.T) { "targetClusterArn": clusterArn, "vpcId": "vpc-12345", "authentication": "SASL_IAM", - }) + }, jsonx.V1()) reqVpc := httptest.NewRequest(http.MethodPost, "/v1/vpc-connection", bytes.NewReader(vpcBody)) reqVpc.Header.Set("Content-Type", "application/json") recVpc := httptest.NewRecorder() @@ -144,7 +145,7 @@ func TestKafka_DeleteVpcConnection(t *testing.T) { require.Equal(t, http.StatusOK, recVpc.Code) var vpcResp map[string]any - require.NoError(t, json.Unmarshal(recVpc.Body.Bytes(), &vpcResp)) + require.NoError(t, json.Unmarshal(recVpc.Body.Bytes(), &vpcResp, jsonx.V1())) var vpcConnectionArn string if tt.useRealArn { @@ -213,7 +214,7 @@ func TestVpcConnection_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) vpcConnArn, _ := createResp["vpcConnectionArn"].(string) require.NotEmpty(t, vpcConnArn) // Real CreateVpcConnectionOutput has no targetClusterArn field (unlike @@ -230,7 +231,7 @@ func TestVpcConnection_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, vpcConnArn, descResp["vpcConnectionArn"]) assert.Equal(t, clusterArn, descResp["targetClusterArn"]) @@ -241,7 +242,7 @@ func TestVpcConnection_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) conns, _ := listResp["vpcConnections"].([]any) require.Len(t, conns, 1) @@ -275,7 +276,7 @@ func TestVpcConnection_ListClientVpcConnections(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) // Real ListClientVpcConnectionsOutput carries its array under the // distinct "clientVpcConnections" key (not "vpcConnections", which is // ListVpcConnections' key -- a different operation with a different @@ -303,7 +304,7 @@ func TestVpcConnection_RejectClientVpcConnection(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) vpcConnArn, _ := createResp["vpcConnectionArn"].(string) encodedCluster := url.PathEscape(clusterArn) diff --git a/services/kafka/iam_auth.go b/services/kafka/iam_auth.go index aa725d3bf6..f23ac86ca7 100644 --- a/services/kafka/iam_auth.go +++ b/services/kafka/iam_auth.go @@ -4,13 +4,14 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "net/url" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" "github.com/blackbirdworks/gopherstack/services/sts" ) @@ -83,7 +84,7 @@ type iamPayload struct { // parseIAMPayload decodes the JSON sent by the aws-msk-iam-auth clients (version 2020_10_22). func parseIAMPayload(raw []byte) (*iamPayload, error) { var kv map[string]string - if err := json.Unmarshal(raw, &kv); err != nil { + if err := json.Unmarshal(raw, &kv, jsonx.V1()); err != nil { return nil, errIAMMalformed } diff --git a/services/kafka/persistence.go b/services/kafka/persistence.go index 01abe28bd1..ff1e7a18d5 100644 --- a/services/kafka/persistence.go +++ b/services/kafka/persistence.go @@ -2,7 +2,7 @@ package kafka import ( "context" - "encoding/json" + "encoding/json/jsontext" "maps" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -32,13 +32,13 @@ const kafkaSnapshotVersion = 1 // ScramSecrets and ClusterPolicies persist the two fields left as plain maps // (their values are not *T, so they don't fit store.Table) alongside Tables. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - ScramSecrets map[string][]string `json:"scramSecrets"` - ClusterPolicies map[string]string `json:"clusterPolicies"` - PolicyVersions map[string]string `json:"clusterPolicyVersions,omitempty"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + ScramSecrets map[string][]string `json:"scramSecrets"` + ClusterPolicies map[string]string `json:"clusterPolicies"` + PolicyVersions map[string]string `json:"clusterPolicyVersions,omitempty"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/kafka/routes_test.go b/services/kafka/routes_test.go index 58d837a681..74a4519d5b 100644 --- a/services/kafka/routes_test.go +++ b/services/kafka/routes_test.go @@ -1,7 +1,7 @@ package kafka_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kafka" ) @@ -333,7 +334,7 @@ func TestUpdateOpsLiveUnderV1ClustersPath(t *testing.T) { tt.method, tt.suffix, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["clusterOperationArn"]) // The old (wrong) /api/v2 path must no longer resolve to the same op -- @@ -363,7 +364,7 @@ func TestRejectClientVpcConnectionRealPath(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) vpcConnArn, _ := createResp["vpcConnectionArn"].(string) require.NotEmpty(t, vpcConnArn) @@ -399,7 +400,7 @@ func TestListVpcConnectionsPluralPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) conns, _ := resp["vpcConnections"].([]any) assert.Len(t, conns, 1) @@ -425,7 +426,7 @@ func TestGetCompatibleKafkaVersionsTopLevelPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, _ := resp["compatibleKafkaVersions"].([]any) assert.NotEmpty(t, versions) @@ -477,7 +478,7 @@ func TestUpdateReplicationInfoStripsSuffix(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, replicatorArn, resp["replicatorArn"], "the resolved replicator ARN must not include the /replication-info suffix") } diff --git a/services/kafka/scram_sync.go b/services/kafka/scram_sync.go index 5f13e55f9e..c23cd2e1c7 100644 --- a/services/kafka/scram_sync.go +++ b/services/kafka/scram_sync.go @@ -5,7 +5,7 @@ import ( "crypto/pbkdf2" "crypto/rand" "crypto/sha512" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +14,7 @@ import ( "github.com/twmb/franz-go/pkg/kgo" "github.com/twmb/franz-go/pkg/kmsg" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -249,8 +250,13 @@ func ParseScramSecret(secretString string) (ScramCredential, error) { Password *string `json:"password"` } - if err := json.Unmarshal([]byte(secretString), &v); err != nil || v.Username == nil || v.Password == nil || - *v.Username == "" || *v.Password == "" { + if err := json.Unmarshal( + []byte(secretString), + &v, + jsonx.V1(), + ); err != nil || v.Username == nil || v.Password == nil || + *v.Username == "" || + *v.Password == "" { return ScramCredential{}, errScramSecretShape } diff --git a/services/kafkaconnect/handler.go b/services/kafkaconnect/handler.go index 4df86a8156..72b7305bff 100644 --- a/services/kafkaconnect/handler.go +++ b/services/kafkaconnect/handler.go @@ -1,7 +1,7 @@ package kafkaconnect import ( - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -225,7 +226,7 @@ func decodeBody[T any](body []byte, out *T) error { return nil } - return json.Unmarshal(body, out) + return json.Unmarshal(body, out, jsonx.V1()) } // writeJSON writes a 200 JSON response. diff --git a/services/kafkaconnect/multi_region_test.go b/services/kafkaconnect/multi_region_test.go index d8dd0439c2..c36be1f356 100644 --- a/services/kafkaconnect/multi_region_test.go +++ b/services/kafkaconnect/multi_region_test.go @@ -2,7 +2,8 @@ package kafkaconnect_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/kafkaconnect" ) @@ -185,8 +187,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/kafkaconnect/persistence.go b/services/kafkaconnect/persistence.go index 2554cc270a..3f05a3021c 100644 --- a/services/kafkaconnect/persistence.go +++ b/services/kafkaconnect/persistence.go @@ -2,7 +2,7 @@ package kafkaconnect import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -30,8 +30,8 @@ const kafkaConnectSnapshotVersion = 1 // workerConfigurations, connectorOperations -- see store_setup.go), produced // by b.registry.SnapshotAll(). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes backend state to JSON. diff --git a/services/kafkaconnect/worker_engine.go b/services/kafkaconnect/worker_engine.go index 860bb50c0b..21af36e50d 100644 --- a/services/kafkaconnect/worker_engine.go +++ b/services/kafkaconnect/worker_engine.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -22,6 +22,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" ) @@ -620,7 +621,7 @@ func (e *workerEngine) call(ctx context.Context, method, url string, body any) ( var rdr io.Reader if body != nil { - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) if err != nil { return nil, 0, fmt.Errorf("encode request: %w", err) } @@ -670,7 +671,7 @@ func (e *workerEngine) readStatus(ctx context.Context, base, name string) (strin } var st connectStatus - if err = json.Unmarshal(data, &st); err != nil { + if err = json.Unmarshal(data, &st, jsonx.V1()); err != nil { return "", "", fmt.Errorf("decode status: %w", err) } diff --git a/services/kinesis/account_settings_test.go b/services/kinesis/account_settings_test.go index 5c214b55ad..410186cb7c 100644 --- a/services/kinesis/account_settings_test.go +++ b/services/kinesis/account_settings_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -104,7 +105,7 @@ func TestDescribeLimits_DynamicOpenShardCount(t *testing.T) { ShardLimit int `json:"ShardLimit"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before, jsonx.V1())) assert.Equal(t, 500, before.ShardLimit) // Create a stream with 3 shards. @@ -117,7 +118,7 @@ func TestDescribeLimits_DynamicOpenShardCount(t *testing.T) { OpenShardCount int `json:"OpenShardCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after, jsonx.V1())) assert.Equal(t, before.OpenShardCount+3, after.OpenShardCount) } @@ -142,7 +143,7 @@ func TestDescribeLimits(t *testing.T) { OnDemandStreamCountLimit int `json:"OnDemandStreamCountLimit"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 500, resp.ShardLimit) assert.Equal(t, 0, resp.OpenShardCount) assert.Equal(t, 0, resp.OnDemandStreamCount) @@ -194,7 +195,7 @@ func TestDescribeAccountSettings(t *testing.T) { } `json:"MinimumThroughputBillingCommitment"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DISABLED", resp.MinimumThroughputBillingCommitment.Status) assert.Zero(t, resp.MinimumThroughputBillingCommitment.StartedAt) assert.Zero(t, resp.MinimumThroughputBillingCommitment.EndedAt) @@ -256,7 +257,7 @@ func TestHandleDescribeLimits(t *testing.T) { OpenShardCount int `json:"OpenShardCount"` ShardLimit int `json:"ShardLimit"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 0, resp.OpenShardCount) assert.Equal(t, 500, resp.ShardLimit) } diff --git a/services/kinesis/cbor_test.go b/services/kinesis/cbor_test.go index b9b879bf7a..142758295d 100644 --- a/services/kinesis/cbor_test.go +++ b/services/kinesis/cbor_test.go @@ -3,7 +3,7 @@ package kinesis_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -191,7 +192,7 @@ func TestKinesisCBOR_GetRecords(t *testing.T) { "ShardId": "shardId-000000000000", "ShardIteratorType": "TRIM_HORIZON", } - iterBytes, _ := json.Marshal(iterBody) + iterBytes, _ := json.Marshal(iterBody, jsonx.V1()) iterReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(iterBytes)) iterReq.Header.Set("Content-Type", "application/x-amz-json-1.1") iterReq.Header.Set("X-Amz-Target", kinesisPrefix+"GetShardIterator") @@ -203,7 +204,7 @@ func TestKinesisCBOR_GetRecords(t *testing.T) { require.Equal(t, http.StatusOK, iterRec.Code) var iterResp map[string]any - require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp, jsonx.V1())) shardIter, ok := iterResp["ShardIterator"].(string) require.True(t, ok, "must have ShardIterator") @@ -253,7 +254,7 @@ func TestKinesisCBOR_DataRoundTrip(t *testing.T) { "Data": b64Data, "PartitionKey": "pk1", } - b, _ := json.Marshal(jsonPut) + b, _ := json.Marshal(jsonPut, jsonx.V1()) putReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(b)) putReq.Header.Set("Content-Type", "application/x-amz-json-1.1") putReq.Header.Set("X-Amz-Target", kinesisPrefix+"PutRecord") @@ -276,7 +277,7 @@ func TestKinesisCBOR_DataRoundTrip(t *testing.T) { iterC := e.NewContext(iterReq, iterRec) require.NoError(t, h.Handler()(iterC)) var iterResp map[string]any - require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp, jsonx.V1())) shardIter := iterResp["ShardIterator"].(string) // Read via CBOR. @@ -376,7 +377,7 @@ func TestKinesisCBOR_JSONAndCBORCoexist(t *testing.T) { "Data": b64, "PartitionKey": "pk2", } - rawJSON, _ := json.Marshal(putJSON) + rawJSON, _ := json.Marshal(putJSON, jsonx.V1()) req2 := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(rawJSON)) req2.Header.Set("Content-Type", "application/x-amz-json-1.1") req2.Header.Set("X-Amz-Target", kinesisPrefix+"PutRecord") @@ -398,7 +399,7 @@ func TestKinesisCBOR_JSONAndCBORCoexist(t *testing.T) { iterC := e.NewContext(iterReq, iterRec) require.NoError(t, h.Handler()(iterC)) var iterResp map[string]any - require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp, jsonx.V1())) shardIter := iterResp["ShardIterator"].(string) getReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(mustMarshalBytes(t, map[string]any{ @@ -413,7 +414,7 @@ func TestKinesisCBOR_JSONAndCBORCoexist(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) recs := getResp["Records"].([]any) assert.GreaterOrEqual(t, len(recs), 2, "both records must be visible via JSON") }) @@ -421,7 +422,7 @@ func TestKinesisCBOR_JSONAndCBORCoexist(t *testing.T) { func mustMarshalBytes(t *testing.T, v any) []byte { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return b diff --git a/services/kinesis/channel_delivery.go b/services/kinesis/channel_delivery.go index 559a10e044..6244cc75f6 100644 --- a/services/kinesis/channel_delivery.go +++ b/services/kinesis/channel_delivery.go @@ -4,7 +4,8 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "regexp" @@ -18,6 +19,7 @@ import ( "github.com/google/uuid" "github.com/klauspost/compress/zstd" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -159,7 +161,7 @@ func validateChannelRecord(formatType string, data []byte) string { return "record is not valid UTF-8 for RecordFormatType STRING" } case recordFormatTypeJSON: - if !json.Valid(data) { + if !jsontext.Value(data).IsValid(jsonx.V1()) { return "record is not valid JSON for RecordFormatType JSON" } } @@ -399,7 +401,7 @@ func (b *InMemoryBackend) writeChannelDeadLetterQueue( ShardID string `json:"shardID"` SequenceNumber string `json:"sequenceNumber"` ErrorMessage string `json:"errorMessage"` - }{f.streamARN, f.shardID, f.sequenceNumber, f.errorMessage}) + }{f.streamARN, f.shardID, f.sequenceNumber, f.errorMessage}, jsonx.V1()) if err != nil { continue } diff --git a/services/kinesis/consumer_wire_shape_test.go b/services/kinesis/consumer_wire_shape_test.go index ee1168b29a..65edd5a578 100644 --- a/services/kinesis/consumer_wire_shape_test.go +++ b/services/kinesis/consumer_wire_shape_test.go @@ -1,12 +1,14 @@ package kinesis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestConsumerWireShape_StreamARN locks in that StreamARN only appears on @@ -36,7 +38,7 @@ func TestConsumerWireShape_StreamARN(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(setupRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(setupRec.Body.Bytes(), &descResp, jsonx.V1())) streamARN := descResp.StreamDescription.StreamARN require.NotEmpty(t, streamARN) @@ -82,7 +84,7 @@ func TestConsumerWireShape_StreamARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) consumerObj := raw[tc.wrapperKey] var obj map[string]any diff --git a/services/kinesis/consumers_test.go b/services/kinesis/consumers_test.go index 1c9f2e296c..7264950757 100644 --- a/services/kinesis/consumers_test.go +++ b/services/kinesis/consumers_test.go @@ -3,7 +3,7 @@ package kinesis_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -34,7 +35,7 @@ func subscribeAndCollect(t *testing.T, h *kinesis.Handler, consumerARN, shardID "StartingPosition": map[string]any{ "Type": "TRIM_HORIZON", }, - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) @@ -62,7 +63,7 @@ func getFirstShardID(t *testing.T, h *kinesis.Handler, streamName string) string } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.StreamDescription.Shards) return resp.StreamDescription.Shards[0].ShardID @@ -82,7 +83,7 @@ func registerConsumerAndGetARN(t *testing.T, h *kinesis.Handler, streamARN, cons ConsumerARN string `json:"ConsumerARN"` } `json:"Consumer"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp.Consumer.ConsumerARN } @@ -220,7 +221,7 @@ func TestRegisterStreamConsumer_InvalidName(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) }) } @@ -349,7 +350,7 @@ func TestListStreamConsumers_MaxResultsPagination(t *testing.T) { ConsumerName string `json:"ConsumerName"` } `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Consumers, 2) assert.NotEmpty(t, page1.NextToken) @@ -367,7 +368,7 @@ func TestListStreamConsumers_MaxResultsPagination(t *testing.T) { ConsumerName string `json:"ConsumerName"` } `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Consumers, 2) assert.NotEmpty(t, page2.NextToken) @@ -385,7 +386,7 @@ func TestListStreamConsumers_MaxResultsPagination(t *testing.T) { ConsumerName string `json:"ConsumerName"` } `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page3)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page3, jsonx.V1())) assert.Len(t, page3.Consumers, 1) assert.Empty(t, page3.NextToken) @@ -430,7 +431,7 @@ func TestListStreamConsumers_NoMaxResults_ReturnsAll(t *testing.T) { ConsumerName string `json:"ConsumerName"` } `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Consumers, 3) assert.Empty(t, resp.NextToken) } @@ -741,7 +742,7 @@ func createStreamAndGetARN(t *testing.T, h *kinesis.Handler, streamName string) StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.NotEmpty(t, descResp.StreamDescription.StreamARN) return descResp.StreamDescription.StreamARN @@ -785,7 +786,7 @@ func TestConsumerLifecycle(t *testing.T) { // only types.ConsumerDescription (returned by DescribeStreamConsumer) // does. A raw map catches a StreamARN key resurfacing on this response. var regRespRaw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®RespRaw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®RespRaw, jsonx.V1())) consumerRaw, ok := regRespRaw["Consumer"].(map[string]any) require.True(t, ok) _, hasStreamARN := consumerRaw["StreamARN"] @@ -799,7 +800,7 @@ func TestConsumerLifecycle(t *testing.T) { ConsumerStatus string `json:"ConsumerStatus"` } `json:"Consumer"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) assert.Equal(t, tt.consumerName, regResp.Consumer.ConsumerName) assert.Equal(t, tt.expectedStatus, regResp.Consumer.ConsumerStatus) assert.NotEmpty(t, regResp.Consumer.ConsumerARN) @@ -819,7 +820,7 @@ func TestConsumerLifecycle(t *testing.T) { ConsumerARN string `json:"ConsumerARN"` } `json:"ConsumerDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.consumerName, descResp.ConsumerDescription.ConsumerName) assert.Equal(t, consumerARN, descResp.ConsumerDescription.ConsumerARN) @@ -841,7 +842,7 @@ func TestConsumerLifecycle(t *testing.T) { ConsumerName string `json:"ConsumerName"` } `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Consumers, 1) assert.Equal(t, tt.consumerName, listResp.Consumers[0].ConsumerName) @@ -860,7 +861,7 @@ func TestConsumerLifecycle(t *testing.T) { var listResp2 struct { Consumers []any `json:"Consumers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp2, jsonx.V1())) assert.Empty(t, listResp2.Consumers) }) } @@ -921,7 +922,7 @@ func TestConsumerErrors(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) @@ -951,7 +952,7 @@ func TestRegisterConsumerDuplicate(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceInUseException", errResp.Type) } @@ -975,7 +976,7 @@ func TestSubscribeToShard(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -998,7 +999,7 @@ func TestSubscribeToShard(t *testing.T) { ConsumerARN string `json:"ConsumerARN"` } `json:"Consumer"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) consumerARN := regResp.Consumer.ConsumerARN // SubscribeToShard. @@ -1009,7 +1010,7 @@ func TestSubscribeToShard(t *testing.T) { "StartingPosition": map[string]any{ "Type": "TRIM_HORIZON", }, - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) diff --git a/services/kinesis/errors_test.go b/services/kinesis/errors_test.go index 4e597f0649..8eb75acd3c 100644 --- a/services/kinesis/errors_test.go +++ b/services/kinesis/errors_test.go @@ -1,12 +1,14 @@ package kinesis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestErrValidation verifies ErrValidation is returned for invalid stream name. @@ -39,7 +41,7 @@ func TestErrValidation(t *testing.T) { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp.Type) }) } diff --git a/services/kinesis/handler.go b/services/kinesis/handler.go index 573b7493ef..459b8de3f2 100644 --- a/services/kinesis/handler.go +++ b/services/kinesis/handler.go @@ -2,7 +2,7 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -269,7 +270,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var req extractStreamNameInput - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "" } @@ -378,7 +379,7 @@ func (h *Handler) kinesisRoute(ctx context.Context, r *http.Request, action stri return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // handleError writes a Kinesis error response using the standard error details mapping. diff --git a/services/kinesis/handler_account_settings.go b/services/kinesis/handler_account_settings.go index 0e40ec97bd..96960de77a 100644 --- a/services/kinesis/handler_account_settings.go +++ b/services/kinesis/handler_account_settings.go @@ -2,10 +2,11 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // describeLimitsOutput mirrors kinesis@v1.46.4 DescribeLimitsOutput @@ -106,7 +107,7 @@ func (h *Handler) handleUpdateAccountSettings( body []byte, ) (any, error) { var req jsonUpdateAccountSettingsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -137,7 +138,7 @@ func (h *Handler) handleUpdateMaxRecordSize( body []byte, ) (any, error) { var req jsonUpdateMaxRecordSizeReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_channels.go b/services/kinesis/handler_channels.go index 2640be03ad..65d8f9f085 100644 --- a/services/kinesis/handler_channels.go +++ b/services/kinesis/handler_channels.go @@ -2,10 +2,11 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- wire types (field names verified against kinesis@v1.53.0 serializers.go/deserializers.go) --- @@ -419,7 +420,7 @@ func channelSummaryToJSON(c *Channel) jsonChannelSummary { func (h *Handler) handleCreateChannel(ctx context.Context, _ *http.Request, body []byte) (any, error) { var req jsonCreateChannelReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -447,7 +448,7 @@ func (h *Handler) handleCreateChannel(ctx context.Context, _ *http.Request, body func (h *Handler) handleDeleteChannel(ctx context.Context, _ *http.Request, body []byte) (any, error) { var req jsonChannelARNReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -460,7 +461,7 @@ func (h *Handler) handleDeleteChannel(ctx context.Context, _ *http.Request, body func (h *Handler) handleDescribeChannel(ctx context.Context, _ *http.Request, body []byte) (any, error) { var req jsonChannelARNReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -483,7 +484,7 @@ func channelStreamFiltersFromJSON(filters []jsonStreamFilter) []ChannelStreamFil func (h *Handler) handleListChannels(ctx context.Context, _ *http.Request, body []byte) (any, error) { var req jsonListChannelsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -511,7 +512,7 @@ func (h *Handler) handleListChannels(ctx context.Context, _ *http.Request, body func (h *Handler) handleUpdateChannel(ctx context.Context, _ *http.Request, body []byte) (any, error) { var req jsonUpdateChannelReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_consumers.go b/services/kinesis/handler_consumers.go index 302c04e6f3..0976f694bd 100644 --- a/services/kinesis/handler_consumers.go +++ b/services/kinesis/handler_consumers.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "hash/crc32" "math" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -124,7 +125,7 @@ func (h *Handler) handleRegisterStreamConsumer( body []byte, ) (any, error) { var req jsonRegisterStreamConsumerReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -146,7 +147,7 @@ func (h *Handler) handleDescribeStreamConsumer( body []byte, ) (any, error) { var req jsonDescribeStreamConsumerReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -168,7 +169,7 @@ func (h *Handler) handleListStreamConsumers( body []byte, ) (any, error) { var req jsonListStreamConsumersReq - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) out, err := h.Backend.ListStreamConsumers(ctx, &ListStreamConsumersInput{ StreamARN: req.StreamARN, @@ -193,7 +194,7 @@ func (h *Handler) handleDeregisterStreamConsumer( body []byte, ) (any, error) { var req jsonDeregisterStreamConsumerReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -351,7 +352,7 @@ func (h *Handler) parseSubscribeToShardRequest( return req, StartingPosition{}, false, h.handleError(ctx, c, "SubscribeToShard", readErr) } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return req, StartingPosition{}, false, h.handleError(ctx, c, "SubscribeToShard", ErrInvalidArgument) } @@ -552,7 +553,7 @@ func (h *Handler) pollSubscribeToShardTick( Records: records, ContinuationSequenceNumber: out.Event.ContinuationSequenceNumber, MillisBehindLatest: out.Event.MillisBehindLatest, - }) + }, jsonx.V1()) if marshalErr != nil { return nil, false, marshalErr } diff --git a/services/kinesis/handler_monitoring.go b/services/kinesis/handler_monitoring.go index 73159c0dad..7f9c7a705b 100644 --- a/services/kinesis/handler_monitoring.go +++ b/services/kinesis/handler_monitoring.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonEnhancedMonitoringReq struct { @@ -25,7 +27,7 @@ func (h *Handler) handleEnableEnhancedMonitoring( body []byte, ) (any, error) { var req jsonEnhancedMonitoringReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -53,7 +55,7 @@ func (h *Handler) handleDisableEnhancedMonitoring( body []byte, ) (any, error) { var req jsonEnhancedMonitoringReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_records.go b/services/kinesis/handler_records.go index 6da6d760c0..fd408d7121 100644 --- a/services/kinesis/handler_records.go +++ b/services/kinesis/handler_records.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonPutRecordReq struct { @@ -91,7 +93,7 @@ func (h *Handler) handlePutRecord( body []byte, ) (any, error) { var req jsonPutRecordReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -128,7 +130,7 @@ func (h *Handler) handlePutRecords( body []byte, ) (any, error) { var req jsonPutRecordsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -168,7 +170,7 @@ func (h *Handler) handleGetRecords( body []byte, ) (any, error) { var req jsonGetRecordsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_resharding.go b/services/kinesis/handler_resharding.go index f7a22fe398..dec2a2f878 100644 --- a/services/kinesis/handler_resharding.go +++ b/services/kinesis/handler_resharding.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonMergeShardsReq struct { @@ -40,7 +42,7 @@ func (h *Handler) handleMergeShards( body []byte, ) (any, error) { var req jsonMergeShardsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -62,7 +64,7 @@ func (h *Handler) handleSplitShard( body []byte, ) (any, error) { var req jsonSplitShardReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -84,7 +86,7 @@ func (h *Handler) handleUpdateShardCount( body []byte, ) (any, error) { var req jsonUpdateShardCountReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_resource_policy.go b/services/kinesis/handler_resource_policy.go index 378f0cfdf6..85e7aa011f 100644 --- a/services/kinesis/handler_resource_policy.go +++ b/services/kinesis/handler_resource_policy.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonResourceARNReq struct { @@ -25,7 +27,7 @@ func (h *Handler) handlePutResourcePolicy( body []byte, ) (any, error) { var req jsonPutResourcePolicyReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -45,7 +47,7 @@ func (h *Handler) handleGetResourcePolicy( body []byte, ) (any, error) { var req jsonResourceARNReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -65,7 +67,7 @@ func (h *Handler) handleDeleteResourcePolicy( body []byte, ) (any, error) { var req jsonResourceARNReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_shard_iterators.go b/services/kinesis/handler_shard_iterators.go index 7199843a64..0790a77d3b 100644 --- a/services/kinesis/handler_shard_iterators.go +++ b/services/kinesis/handler_shard_iterators.go @@ -2,9 +2,11 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonGetShardIteratorReq struct { @@ -27,7 +29,7 @@ func (h *Handler) handleGetShardIterator( body []byte, ) (any, error) { var req jsonGetShardIteratorReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_shards.go b/services/kinesis/handler_shards.go index 8d589ee07e..abbef6a97b 100644 --- a/services/kinesis/handler_shards.go +++ b/services/kinesis/handler_shards.go @@ -2,9 +2,11 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonShardFilter struct { @@ -67,7 +69,7 @@ func (h *Handler) handleListShards( body []byte, ) (any, error) { var req jsonListShardsReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_stream_encryption.go b/services/kinesis/handler_stream_encryption.go index a2fb0977f1..86445110f3 100644 --- a/services/kinesis/handler_stream_encryption.go +++ b/services/kinesis/handler_stream_encryption.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonEncryptionReq struct { @@ -19,7 +21,7 @@ func (h *Handler) handleStartStreamEncryption( body []byte, ) (any, error) { var req jsonEncryptionReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -41,7 +43,7 @@ func (h *Handler) handleStopStreamEncryption( body []byte, ) (any, error) { var req jsonEncryptionReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_stream_modes.go b/services/kinesis/handler_stream_modes.go index a84e903a35..4e46606446 100644 --- a/services/kinesis/handler_stream_modes.go +++ b/services/kinesis/handler_stream_modes.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // jsonUpdateStreamWarmThroughputReq mirrors UpdateStreamWarmThroughputInput @@ -35,7 +37,7 @@ func (h *Handler) handleUpdateStreamMode(ctx context.Context, _ *http.Request, b WarmThroughputMiBps *int `json:"WarmThroughputMiBps"` StreamARN string `json:"StreamARN"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } if req.StreamModeDetails == nil { @@ -55,7 +57,7 @@ func (h *Handler) handleUpdateStreamWarmThroughput( body []byte, ) (any, error) { var req jsonUpdateStreamWarmThroughputReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_stream_retention.go b/services/kinesis/handler_stream_retention.go index fb358338a9..a897b65d22 100644 --- a/services/kinesis/handler_stream_retention.go +++ b/services/kinesis/handler_stream_retention.go @@ -2,8 +2,10 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonRetentionPeriodReq struct { @@ -18,7 +20,7 @@ func (h *Handler) handleIncreaseStreamRetentionPeriod( body []byte, ) (any, error) { var req jsonRetentionPeriodReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -40,7 +42,7 @@ func (h *Handler) handleDecreaseStreamRetentionPeriod( body []byte, ) (any, error) { var req jsonRetentionPeriodReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_streams.go b/services/kinesis/handler_streams.go index 903e7f3552..4f41b2814b 100644 --- a/services/kinesis/handler_streams.go +++ b/services/kinesis/handler_streams.go @@ -2,10 +2,11 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -109,7 +110,7 @@ func (h *Handler) handleCreateStream( body []byte, ) (any, error) { var req jsonCreateStreamReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -181,7 +182,7 @@ func (h *Handler) handleDeleteStream( body []byte, ) (any, error) { var req jsonDeleteStreamReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -224,7 +225,7 @@ func (h *Handler) handleDescribeStream( body []byte, ) (any, error) { var req jsonDescribeStreamReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -282,7 +283,7 @@ func (h *Handler) handleDescribeStreamSummary( body []byte, ) (any, error) { var req jsonDescribeStreamReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -343,7 +344,7 @@ func (h *Handler) handleListStreams( body []byte, ) (any, error) { var req jsonListStreamsReq - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) out, err := h.Backend.ListStreams(ctx, &ListStreamsInput{ Limit: req.Limit, diff --git a/services/kinesis/handler_tags.go b/services/kinesis/handler_tags.go index 009b54534e..e2b38c0c62 100644 --- a/services/kinesis/handler_tags.go +++ b/services/kinesis/handler_tags.go @@ -3,12 +3,13 @@ package kinesis import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "slices" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -77,7 +78,7 @@ func (h *Handler) handleAddTagsToStream( body []byte, ) (any, error) { var req handleAddTagsToStreamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -124,7 +125,7 @@ func (h *Handler) handleRemoveTagsFromStream( body []byte, ) (any, error) { var req handleRemoveTagsFromStreamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -151,7 +152,7 @@ func (h *Handler) handleListTagsForStream( body []byte, ) (any, error) { var req listTagsForStreamReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -205,7 +206,7 @@ func (h *Handler) handleTagResource( body []byte, ) (any, error) { var req jsonTagResourceReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -243,7 +244,7 @@ func (h *Handler) handleUntagResource( body []byte, ) (any, error) { var req jsonUntagResourceReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } @@ -263,7 +264,7 @@ func (h *Handler) handleListTagsForResource( body []byte, ) (any, error) { var req jsonResourceARNReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrInvalidArgument } diff --git a/services/kinesis/handler_test.go b/services/kinesis/handler_test.go index 5c1334b8ce..639c6bd532 100644 --- a/services/kinesis/handler_test.go +++ b/services/kinesis/handler_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "crypto/md5" - "encoding/json" + "encoding/json/v2" "math/big" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -57,7 +58,7 @@ func doRequest(t *testing.T, h *kinesis.Handler, action string, body any) *httpt var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -159,7 +160,7 @@ func doParityRequest(t *testing.T, h *kinesis.Handler, action string, body any) var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -255,7 +256,7 @@ func TestKinesisHandler_ErrorResponses(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) @@ -312,7 +313,7 @@ func TestExtractResource(t *testing.T) { e := echo.New() // Valid body - body, _ := json.Marshal(map[string]string{"StreamName": "my-stream"}) + body, _ := json.Marshal(map[string]string{"StreamName": "my-stream"}, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") c := e.NewContext(req, httptest.NewRecorder()) diff --git a/services/kinesis/inspect_test.go b/services/kinesis/inspect_test.go index 7af71a8125..88eff6fbe3 100644 --- a/services/kinesis/inspect_test.go +++ b/services/kinesis/inspect_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -79,7 +80,7 @@ func (e *inspectEnv) get(t *testing.T, path string, out any) int { require.NoError(t, err) if out != nil && resp.StatusCode == http.StatusOK { - require.NoError(t, json.Unmarshal(body, out)) + require.NoError(t, json.Unmarshal(body, out, jsonx.V1())) } return resp.StatusCode diff --git a/services/kinesis/monitoring_test.go b/services/kinesis/monitoring_test.go index 3526c21a7e..527209fb73 100644 --- a/services/kinesis/monitoring_test.go +++ b/services/kinesis/monitoring_test.go @@ -1,12 +1,14 @@ package kinesis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEnhancedMonitoring(t *testing.T) { @@ -33,7 +35,7 @@ func TestEnhancedMonitoring(t *testing.T) { CurrentShardLevelMetrics []string `json:"CurrentShardLevelMetrics"` DesiredShardLevelMetrics []string `json:"DesiredShardLevelMetrics"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &enableResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &enableResp, jsonx.V1())) assert.Equal(t, streamName, enableResp.StreamName) assert.Empty(t, enableResp.CurrentShardLevelMetrics) assert.ElementsMatch(t, []string{"IncomingBytes", "OutgoingRecords"}, enableResp.DesiredShardLevelMetrics) @@ -50,7 +52,7 @@ func TestEnhancedMonitoring(t *testing.T) { CurrentShardLevelMetrics []string `json:"CurrentShardLevelMetrics"` DesiredShardLevelMetrics []string `json:"DesiredShardLevelMetrics"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &disableResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &disableResp, jsonx.V1())) assert.ElementsMatch(t, []string{"IncomingBytes", "OutgoingRecords"}, disableResp.CurrentShardLevelMetrics) assert.Equal(t, []string{"OutgoingRecords"}, disableResp.DesiredShardLevelMetrics) } @@ -91,7 +93,7 @@ func TestEnhancedMonitoring_StreamARN(t *testing.T) { var resp struct { StreamARN string `json:"StreamARN"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.StreamARN) assert.Contains(t, resp.StreamARN, streamName) }) diff --git a/services/kinesis/page_token.go b/services/kinesis/page_token.go index 3c38066e01..ef18ce197b 100644 --- a/services/kinesis/page_token.go +++ b/services/kinesis/page_token.go @@ -2,8 +2,10 @@ package kinesis import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // pageTokenLifetime is the documented lifetime of ListShards and @@ -34,7 +36,7 @@ func encodePageToken(kind string, stream *Stream, cursor string, now time.Time) Cursor: cursor, IssuedAt: now.UnixNano(), Created: stream.CreatedAt.UnixNano(), - }) + }, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(raw) } @@ -48,7 +50,7 @@ func decodePageToken(kind, token string, now time.Time) (pageToken, error) { } var pt pageToken - if err = json.Unmarshal(raw, &pt); err != nil || pt.Kind != kind || pt.Stream == "" { + if err = json.Unmarshal(raw, &pt, jsonx.V1()); err != nil || pt.Kind != kind || pt.Stream == "" { return pageToken{}, ErrInvalidArgument } diff --git a/services/kinesis/persistence.go b/services/kinesis/persistence.go index d1466392c5..11ef9137b7 100644 --- a/services/kinesis/persistence.go +++ b/services/kinesis/persistence.go @@ -2,11 +2,13 @@ package kinesis import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -38,7 +40,7 @@ const kinesisSnapshotVersion = 1 // persisted the same way it always was. type backendSnapshot struct { MinimumThroughputBillingCommitment MinimumThroughputBillingCommitmentOutput `json:"minimumThroughputBillingCommitment"` - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourcePolicies map[string]map[string]string `json:"resourcePolicies,omitempty"` ChannelBuffers map[string]channelBufferSnapshot `json:"channelBuffers,omitempty"` AccountID string `json:"accountID"` @@ -122,7 +124,7 @@ func (stream *Stream) MarshalJSON() ([]byte, error) { stream.mu.RLock("Snapshot") defer stream.mu.RUnlock() - return json.Marshal((*streamAlias)(stream)) + return json.Marshal((*streamAlias)(stream), jsonx.V1()) } // Snapshot serialises the backend state to JSON. @@ -150,7 +152,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { MinimumThroughputBillingCommitment: b.minimumThroughputBillingCommitment, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "kinesis: snapshot serialization failed", "error", err) diff --git a/services/kinesis/persistence_roundtrip_test.go b/services/kinesis/persistence_roundtrip_test.go index 42ba51fd65..9a3315c401 100644 --- a/services/kinesis/persistence_roundtrip_test.go +++ b/services/kinesis/persistence_roundtrip_test.go @@ -2,13 +2,16 @@ package kinesis //nolint:testpackage // reuses ctxRegion (isolation_test.go) for import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "testing/synctest" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestInMemoryBackend_FullStateSnapshotRestoreRoundTrip exercises every kind @@ -185,12 +188,12 @@ func TestInMemoryBackend_Restore_IncompatibleVersion_ResetsEmpty(t *testing.T) { // Corrupt just the version field to simulate a snapshot from an // incompatible (older/newer) build. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &raw)) - bumped, err := json.Marshal(kinesisSnapshotVersion + 1) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) + bumped, err := json.Marshal(kinesisSnapshotVersion+1, jsonx.V1()) require.NoError(t, err) raw["version"] = bumped - mutated, err := json.Marshal(raw) + mutated, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) fresh := NewInMemoryBackendWithConfig("000000000000", "us-east-1") diff --git a/services/kinesis/persistence_test.go b/services/kinesis/persistence_test.go index 138f736761..7ae48b5f0f 100644 --- a/services/kinesis/persistence_test.go +++ b/services/kinesis/persistence_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -318,7 +319,7 @@ func TestTags_SurvivePersistenceRestore(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) found := false for _, kv := range resp.Tags { diff --git a/services/kinesis/records_get_test.go b/services/kinesis/records_get_test.go index 596fb9a82c..e0e93e0352 100644 --- a/services/kinesis/records_get_test.go +++ b/services/kinesis/records_get_test.go @@ -3,7 +3,7 @@ package kinesis_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -48,7 +49,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.NotEmpty(t, descResp.StreamDescription.Shards) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -75,7 +76,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { var putResp struct { FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assert.Equal(t, 0, putResp.FailedRecordCount) rec = doRequest(t, h, "GetShardIterator", map[string]any{ @@ -88,7 +89,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp, jsonx.V1())) require.NotEmpty(t, iterResp.ShardIterator) rec = doRequest(t, h, "GetRecords", map[string]any{ @@ -101,7 +102,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { PartitionKey string `json:"PartitionKey"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Len( t, getResp.Records, @@ -134,7 +135,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.NotEmpty(t, descResp.StreamDescription.Shards) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -166,7 +167,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp, jsonx.V1())) require.NotEmpty(t, iterResp.ShardIterator) rec = doRequest(t, h, "GetRecords", map[string]any{ @@ -179,7 +180,7 @@ func TestGetRecords_SizeCap_ExcludesPartitionKey(t *testing.T) { Data []byte `json:"Data"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.LessOrEqual(t, len(getResp.Records), 2, "data cap (10 MiB) should stop GetRecords before the 3rd 4-MiB record") }, @@ -367,7 +368,7 @@ func TestPutAndGetRecords(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.NotEmpty(t, descResp.StreamDescription.Shards) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -383,7 +384,7 @@ func TestPutAndGetRecords(t *testing.T) { ShardID string `json:"ShardId"` SequenceNumber string `json:"SequenceNumber"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assert.NotEmpty(t, putResp.ShardID) assert.NotEmpty(t, putResp.SequenceNumber) firstSeq := putResp.SequenceNumber @@ -405,7 +406,7 @@ func TestPutAndGetRecords(t *testing.T) { } `json:"Records"` FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp, jsonx.V1())) assert.Equal(t, 0, batchResp.FailedRecordCount) assert.Len(t, batchResp.Records, 2) @@ -420,7 +421,7 @@ func TestPutAndGetRecords(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp, jsonx.V1())) assert.NotEmpty(t, iterResp.ShardIterator) // GetRecords @@ -438,7 +439,7 @@ func TestPutAndGetRecords(t *testing.T) { Data []byte `json:"Data"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Len(t, getResp.Records, 3) // 1 + 2 batch assert.NotEmpty(t, getResp.NextShardIterator) @@ -454,7 +455,7 @@ func TestPutAndGetRecords(t *testing.T) { var atSeqIterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &atSeqIterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &atSeqIterResp, jsonx.V1())) rec = doRequest(t, h, "GetRecords", map[string]any{ "ShardIterator": atSeqIterResp.ShardIterator, @@ -467,7 +468,7 @@ func TestPutAndGetRecords(t *testing.T) { SequenceNumber string `json:"SequenceNumber"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &atSeqResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &atSeqResp, jsonx.V1())) // AT_SEQUENCE_NUMBER starts at the given record (inclusive) require.NotEmpty(t, atSeqResp.Records) assert.Equal(t, firstSeq, atSeqResp.Records[0].SequenceNumber) @@ -484,7 +485,7 @@ func TestPutAndGetRecords(t *testing.T) { var afterIterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterIterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterIterResp, jsonx.V1())) rec = doRequest(t, h, "GetRecords", map[string]any{ "ShardIterator": afterIterResp.ShardIterator, @@ -497,7 +498,7 @@ func TestPutAndGetRecords(t *testing.T) { SequenceNumber string `json:"SequenceNumber"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterSeqResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterSeqResp, jsonx.V1())) // AFTER_SEQUENCE_NUMBER skips the given record assert.Len(t, afterSeqResp.Records, 2) @@ -512,7 +513,7 @@ func TestPutAndGetRecords(t *testing.T) { var latestIterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &latestIterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &latestIterResp, jsonx.V1())) rec = doRequest(t, h, "GetRecords", map[string]any{ "ShardIterator": latestIterResp.ShardIterator, @@ -522,7 +523,7 @@ func TestPutAndGetRecords(t *testing.T) { var latestResp struct { Records []any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &latestResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &latestResp, jsonx.V1())) assert.Empty(t, latestResp.Records) // No new records since iterator was created }) } @@ -554,7 +555,7 @@ func TestSequenceNumberOrdering(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) shardID := descResp.StreamDescription.Shards[0].ShardID // Put 5 records @@ -570,7 +571,7 @@ func TestSequenceNumberOrdering(t *testing.T) { var putResp struct { SequenceNumber string `json:"SequenceNumber"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) seqNums[i] = putResp.SequenceNumber } @@ -591,7 +592,7 @@ func TestSequenceNumberOrdering(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp, jsonx.V1())) rec = doRequest(t, h, "GetRecords", map[string]any{ "ShardIterator": iterResp.ShardIterator, @@ -604,7 +605,7 @@ func TestSequenceNumberOrdering(t *testing.T) { SequenceNumber string `json:"SequenceNumber"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) require.Len(t, getResp.Records, 5) for i, r := range getResp.Records { @@ -1153,7 +1154,7 @@ func TestGetRecords_MillisBehindLatest_ViaHandler(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(iterRec.Body.Bytes(), &iterResp, jsonx.V1())) // Fetch 1 record (leaving 2 behind). rec = doRequest(t, h, "GetRecords", map[string]any{ @@ -1166,7 +1167,7 @@ func TestGetRecords_MillisBehindLatest_ViaHandler(t *testing.T) { Records []any `json:"Records"` MillisBehindLatest int64 `json:"MillisBehindLatest"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Len(t, getResp.Records, 1) // Should be behind the last record, not just the next one. assert.GreaterOrEqual(t, getResp.MillisBehindLatest, int64(0)) diff --git a/services/kinesis/records_test.go b/services/kinesis/records_test.go index 62092defba..9cde186913 100644 --- a/services/kinesis/records_test.go +++ b/services/kinesis/records_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "math/big" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -73,7 +74,7 @@ func TestPutRecord_ByARN(t *testing.T) { ShardID string `json:"ShardId"` SequenceNumber string `json:"SequenceNumber"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.ShardID) assert.NotEmpty(t, resp.SequenceNumber) }) @@ -133,7 +134,7 @@ func TestPutRecords_ByARN(t *testing.T) { } `json:"Records"` FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 0, resp.FailedRecordCount) assert.Len(t, resp.Records, 2) }) @@ -257,7 +258,7 @@ func TestPutRecordsNotFound(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp.Type) } @@ -288,7 +289,7 @@ func TestMultipleShardRouting(t *testing.T) { var putResp struct { ShardID string `json:"ShardId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) shardIDs[putResp.ShardID] = true } @@ -343,7 +344,7 @@ func TestPutRecords_OversizeRecordReturnsValidationException(t *testing.T) { } `json:"Records"` FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 1, resp.FailedRecordCount) require.Len(t, resp.Records, 2) @@ -386,7 +387,7 @@ func TestPutRecords_ThrottledRecordReturnsProvisionedThroughputException(t *test } `json:"Records"` FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 1, resp.FailedRecordCount) assert.Equal(t, "ProvisionedThroughputExceededException", resp.Records[0].ErrorCode) @@ -422,7 +423,7 @@ func TestPutRecords_AllValidRecordsSucceed(t *testing.T) { } `json:"Records"` FailedRecordCount int `json:"FailedRecordCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 0, resp.FailedRecordCount) for _, r := range resp.Records { assert.Empty(t, r.ErrorCode) diff --git a/services/kinesis/resharding_shard_count_test.go b/services/kinesis/resharding_shard_count_test.go index 90c205befb..af8b9c98ac 100644 --- a/services/kinesis/resharding_shard_count_test.go +++ b/services/kinesis/resharding_shard_count_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -70,7 +71,7 @@ func TestUpdateShardCount(t *testing.T) { CurrentShardCount int `json:"CurrentShardCount"` TargetShardCount int `json:"TargetShardCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, streamName, resp.StreamName) assert.Equal(t, tt.wantCurrentCount, resp.CurrentShardCount) assert.Equal(t, tt.wantTargetCount, resp.TargetShardCount) @@ -82,7 +83,7 @@ func TestUpdateShardCount(t *testing.T) { var shardsResp struct { Shards []any `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shardsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shardsResp, jsonx.V1())) assert.Len(t, shardsResp.Shards, tt.targetShards) }) }) @@ -296,7 +297,7 @@ func TestUpdateShardCount_ViaHandler_OpenShardsOnly(t *testing.T) { CurrentShardCount int `json:"CurrentShardCount"` TargetShardCount int `json:"TargetShardCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, 2, updateResp.CurrentShardCount) assert.Equal(t, 4, updateResp.TargetShardCount) @@ -307,7 +308,7 @@ func TestUpdateShardCount_ViaHandler_OpenShardsOnly(t *testing.T) { var listResp struct { Shards []any `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Shards, 4) }) } diff --git a/services/kinesis/resharding_test.go b/services/kinesis/resharding_test.go index 05e132e016..4668eef711 100644 --- a/services/kinesis/resharding_test.go +++ b/services/kinesis/resharding_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "math/big" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -193,7 +194,7 @@ func TestScalingCap_HandlerValidationException(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp.Type) assert.NotEmpty(t, resp.Message) } @@ -494,7 +495,7 @@ func TestMergeShards_ARNSupport(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 2) streamARN := descResp.StreamDescription.StreamARN @@ -539,7 +540,7 @@ func TestSplitShard_ARNSupport(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) rec = doRequest(t, h, "SplitShard", map[string]any{ @@ -574,7 +575,7 @@ func TestMergeShards_OnDemandRejected(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) }) } @@ -602,7 +603,7 @@ func TestSplitShard_OnDemandRejected(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) }) } @@ -659,7 +660,7 @@ func TestMergeShards(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 2) shard0 := descResp.StreamDescription.Shards[0].ShardID @@ -690,7 +691,7 @@ func TestMergeShards(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp2, jsonx.V1())) assert.Len(t, descResp2.StreamDescription.Shards, 3) }) } @@ -725,7 +726,7 @@ func TestMergeAndSplitShardIDs(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &d)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &d, jsonx.V1())) return d.StreamDescription.Shards } @@ -739,7 +740,7 @@ func TestMergeAndSplitShardIDs(t *testing.T) { Shards []shardEntry `json:"Shards"` } - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &d)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &d, jsonx.V1())) return d.Shards } @@ -850,7 +851,7 @@ func TestMergeShards_Errors(t *testing.T) { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) @@ -884,7 +885,7 @@ func TestSplitShard(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -903,7 +904,7 @@ func TestSplitShard(t *testing.T) { // After splitting 1 → 2, expect 3 total: 1 closed parent + 2 open children. rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "split-stream"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Len(t, descResp.StreamDescription.Shards, 3) }) } @@ -961,7 +962,7 @@ func TestSplitShard_Errors(t *testing.T) { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.errType, errResp.Type) } }) diff --git a/services/kinesis/resource_policy_test.go b/services/kinesis/resource_policy_test.go index 9de4ed1341..aa5bed2fe8 100644 --- a/services/kinesis/resource_policy_test.go +++ b/services/kinesis/resource_policy_test.go @@ -1,13 +1,14 @@ package kinesis_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -78,7 +79,7 @@ func TestResourcePolicyLifecycle(t *testing.T) { Policy string `json:"Policy"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp, jsonx.V1())) assert.Equal(t, tt.policy, policyResp.Policy) // DeleteResourcePolicy. @@ -110,6 +111,6 @@ func TestDeleteResourcePolicy_NotFound(t *testing.T) { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type) } diff --git a/services/kinesis/ring_buffer.go b/services/kinesis/ring_buffer.go index 3457ae6d7e..0b290e299d 100644 --- a/services/kinesis/ring_buffer.go +++ b/services/kinesis/ring_buffer.go @@ -1,9 +1,11 @@ package kinesis import ( - "encoding/json" + "encoding/json/v2" "sort" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // shardRecords is a bounded ring buffer for Kinesis shard records. @@ -82,7 +84,7 @@ func (r *shardRecords) MarshalJSON() ([]byte, error) { out[i] = r.at(i) } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } // UnmarshalJSON restores the ring buffer from a JSON array. @@ -90,7 +92,7 @@ func (r *shardRecords) MarshalJSON() ([]byte, error) { // Any previously held pointers are cleared to allow GC. func (r *shardRecords) UnmarshalJSON(data []byte) error { var records []*Record - if err := json.Unmarshal(data, &records); err != nil { + if err := json.Unmarshal(data, &records, jsonx.V1()); err != nil { return err } diff --git a/services/kinesis/shard_iterators.go b/services/kinesis/shard_iterators.go index 9530fd71a5..a23b4c5408 100644 --- a/services/kinesis/shard_iterators.go +++ b/services/kinesis/shard_iterators.go @@ -3,13 +3,15 @@ package kinesis import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // iteratorToken encodes a shard iterator as a base64 JSON token. func encodeIterator(it *ShardIterator) (string, error) { - data, err := json.Marshal(it) + data, err := json.Marshal(it, jsonx.V1()) if err != nil { return "", err } @@ -25,7 +27,7 @@ func decodeIterator(token string, now time.Time) (*ShardIterator, error) { } var it ShardIterator - if err = json.Unmarshal(data, &it); err != nil { + if err = json.Unmarshal(data, &it, jsonx.V1()); err != nil { return nil, ErrShardIteratorExpired } diff --git a/services/kinesis/shard_iterators_test.go b/services/kinesis/shard_iterators_test.go index 4c6cc159a2..1ad01efb86 100644 --- a/services/kinesis/shard_iterators_test.go +++ b/services/kinesis/shard_iterators_test.go @@ -3,7 +3,7 @@ package kinesis_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -60,7 +61,7 @@ func TestGetShardIterator_ByARN(t *testing.T) { var resp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.ShardIterator) }) } @@ -203,7 +204,7 @@ func TestGetShardIteratorBadIteratorType(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) shardID := descResp.StreamDescription.Shards[0].ShardID rec = doRequest(t, h, "GetShardIterator", map[string]any{ @@ -264,7 +265,7 @@ func testGetShardIteratorAtTimestamp(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -288,7 +289,7 @@ func testGetShardIteratorAtTimestamp(t *testing.T) { var iterResp struct { ShardIterator string `json:"ShardIterator"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &iterResp, jsonx.V1())) assert.NotEmpty(t, iterResp.ShardIterator) // GetRecords should return the record. @@ -302,7 +303,7 @@ func testGetShardIteratorAtTimestamp(t *testing.T) { Data []byte `json:"Data"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Len(t, getResp.Records, 1) assert.Equal(t, []byte("hello"), getResp.Records[0].Data) } @@ -328,7 +329,7 @@ func TestGetShardIterator_AtTimestampRequiresTimestamp(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) shardID := descResp.StreamDescription.Shards[0].ShardID rec = doRequest(t, h, "GetShardIterator", map[string]any{ @@ -342,7 +343,7 @@ func TestGetShardIterator_AtTimestampRequiresTimestamp(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", errResp.Type) } @@ -423,7 +424,7 @@ func testGetRecordsNextShardIteratorHasExpiry(t *testing.T) { require.NoError(t, err) var next kinesis.ShardIterator - require.NoError(t, json.Unmarshal(raw, &next)) + require.NoError(t, json.Unmarshal(raw, &next, jsonx.V1())) assert.False(t, next.CreatedAt.IsZero(), "NextShardIterator must carry a CreatedAt so ExpiredIteratorException can ever fire on a chained token") diff --git a/services/kinesis/shards_test.go b/services/kinesis/shards_test.go index e201c65f92..a0fdfe8a23 100644 --- a/services/kinesis/shards_test.go +++ b/services/kinesis/shards_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -31,7 +32,7 @@ func TestListShards_NextTokenStreamNameMutuallyExclusive(t *testing.T) { var page1 struct { NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) require.NotEmpty(t, page1.NextToken, "expected NextToken for pagination") tests := []struct { @@ -65,7 +66,7 @@ func TestListShards_NextTokenStreamNameMutuallyExclusive(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", errResp.Type) }) } @@ -90,7 +91,7 @@ func TestListShards_NextTokenAlone_Succeeds(t *testing.T) { ShardID string `json:"ShardId"` } `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) require.NotEmpty(t, page1.NextToken) // Use NextToken alone (no StreamName) — should succeed because the token embeds stream context. @@ -105,7 +106,7 @@ func TestListShards_NextTokenAlone_Succeeds(t *testing.T) { ShardID string `json:"ShardId"` } `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) assert.NotEmpty(t, page2.Shards) } @@ -538,7 +539,7 @@ func TestListShards(t *testing.T) { ShardID string `json:"ShardId"` } `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listShardsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listShardsResp, jsonx.V1())) assert.Len(t, listShardsResp.Shards, 3) } @@ -639,7 +640,7 @@ func TestListShards_MaxResults_ViaHandler(t *testing.T) { NextToken string `json:"NextToken"` Shards []any `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Shards, 2) assert.NotEmpty(t, resp.NextToken) @@ -654,7 +655,7 @@ func TestListShards_MaxResults_ViaHandler(t *testing.T) { NextToken string `json:"NextToken"` Shards []any `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2.Shards, 2) assert.Empty(t, resp2.NextToken, "no more pages") } @@ -927,7 +928,7 @@ func TestListShards_ShardFilterType_TimestampRequired(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", errResp.Type) }) } diff --git a/services/kinesis/stream_encryption_test.go b/services/kinesis/stream_encryption_test.go index 1b0078cc38..064c3b7c78 100644 --- a/services/kinesis/stream_encryption_test.go +++ b/services/kinesis/stream_encryption_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -44,7 +45,7 @@ func testStartEncryptionARNSupport(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) rec = doRequest(t, h, "StartStreamEncryption", map[string]any{ "StreamARN": descResp.StreamDescription.StreamARN, @@ -85,7 +86,7 @@ func TestStopEncryption_ResetsFields(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "NONE", resp.StreamDescription.EncryptionType) } @@ -208,7 +209,7 @@ func TestStreamEncryption_Errors(t *testing.T) { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(got.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) } }) diff --git a/services/kinesis/stream_modes_test.go b/services/kinesis/stream_modes_test.go index 480835ddef..6ec18ac82d 100644 --- a/services/kinesis/stream_modes_test.go +++ b/services/kinesis/stream_modes_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -155,7 +156,7 @@ func TestUpdateStreamMode_Valid(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) rec3 := doRequest(t, h, "UpdateStreamMode", map[string]any{ "StreamARN": descResp.StreamDescription.StreamARN, @@ -174,7 +175,7 @@ func TestUpdateStreamMode_Valid(t *testing.T) { } `json:"StreamModeDetails"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &verifyResp)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &verifyResp, jsonx.V1())) require.NotNil(t, verifyResp.StreamDescription.StreamModeDetails) assert.Equal(t, tt.wantMode, verifyResp.StreamDescription.StreamModeDetails.StreamMode) }) diff --git a/services/kinesis/stream_retention_test.go b/services/kinesis/stream_retention_test.go index 2bf83bc98b..b782d71602 100644 --- a/services/kinesis/stream_retention_test.go +++ b/services/kinesis/stream_retention_test.go @@ -2,13 +2,14 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -199,7 +200,7 @@ func TestHandleIncreaseStreamRetentionPeriod(t *testing.T) { RetentionPeriodHours int `json:"RetentionPeriodHours"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, 48, descResp.StreamDescription.RetentionPeriodHours) } @@ -231,7 +232,7 @@ func TestHandleDecreaseStreamRetentionPeriod(t *testing.T) { RetentionPeriodHours int `json:"RetentionPeriodHours"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, 24, descResp.StreamDescription.RetentionPeriodHours) } diff --git a/services/kinesis/streams_describe_test.go b/services/kinesis/streams_describe_test.go index f589540cf9..ce54fe9c13 100644 --- a/services/kinesis/streams_describe_test.go +++ b/services/kinesis/streams_describe_test.go @@ -2,7 +2,8 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -55,7 +57,7 @@ func TestDescribeStream_ByARN(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "arn-describe-stream", resp.StreamDescription.StreamName) assert.Equal(t, desc.StreamARN, resp.StreamDescription.StreamARN) }) @@ -100,7 +102,7 @@ func TestDescribeStreamSummary_ByARN(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescriptionSummary"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "arn-summary-stream", resp.StreamDescriptionSummary.StreamName) assert.Equal(t, desc.StreamARN, resp.StreamDescriptionSummary.StreamARN) }) @@ -142,7 +144,7 @@ func TestDescribeStream_EncryptionFields(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "KMS", resp.StreamDescription.EncryptionType) assert.Equal(t, "alias/my-key-id", resp.StreamDescription.KeyID) }) @@ -181,7 +183,7 @@ func TestDescribeStreamSummary_EncryptionFields(t *testing.T) { } `json:"StreamDescriptionSummary"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "KMS", resp.StreamDescriptionSummary.EncryptionType) assert.Equal(t, "alias/summary-key-id", resp.StreamDescriptionSummary.KeyID) }) @@ -208,7 +210,10 @@ func TestDescribeStreamSummary_OpenShardCountAndConsumerCount(t *testing.T) { } `json:"StreamDescription"` } - require.NoError(t, json.NewDecoder(strings.NewReader(descRec.Body.String())).Decode(&descResp)) + require.NoError( + t, + json.UnmarshalDecode(jsontext.NewDecoder(strings.NewReader(descRec.Body.String())), &descResp, jsonx.V1()), + ) regRec := doParityRequest(t, h, "RegisterStreamConsumer", map[string]any{ "StreamARN": descResp.StreamDescription.StreamARN, @@ -228,7 +233,10 @@ func TestDescribeStreamSummary_OpenShardCountAndConsumerCount(t *testing.T) { } `json:"StreamDescriptionSummary"` } - require.NoError(t, json.NewDecoder(strings.NewReader(sumRec.Body.String())).Decode(&sumResp)) + require.NoError( + t, + json.UnmarshalDecode(jsontext.NewDecoder(strings.NewReader(sumRec.Body.String())), &sumResp, jsonx.V1()), + ) assert.Equal(t, 3, sumResp.StreamDescriptionSummary.OpenShardCount) assert.Equal(t, 1, sumResp.StreamDescriptionSummary.ConsumerCount) @@ -269,7 +277,7 @@ func TestDescribeStream_StreamCreationTimestamp(t *testing.T) { StreamCreationTimestamp float64 `json:"StreamCreationTimestamp"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.GreaterOrEqual(t, int64(resp.StreamDescription.StreamCreationTimestamp), before) }) } @@ -309,7 +317,7 @@ func TestDescribeStream_StreamModeDetails(t *testing.T) { } `json:"StreamModeDetails"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.StreamDescription.StreamModeDetails) assert.Equal(t, tt.wantMode, resp.StreamDescription.StreamModeDetails.StreamMode) }) @@ -366,7 +374,7 @@ func TestDescribeStreamSummary_OpenShardCount_AfterMerge(t *testing.T) { ShardID string `json:"ShardId"` } `json:"Shards"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &shardsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &shardsResp, jsonx.V1())) require.Len(t, shardsResp.Shards, 2) rec3 := doRequest(t, h, "MergeShards", map[string]any{ @@ -387,7 +395,7 @@ func TestDescribeStreamSummary_OpenShardCount_AfterMerge(t *testing.T) { OpenShardCount int `json:"OpenShardCount"` } `json:"StreamDescriptionSummary"` } - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &summaryResp)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &summaryResp, jsonx.V1())) assert.Equal(t, tt.wantOpenShards, summaryResp.StreamDescriptionSummary.OpenShardCount) }) }) @@ -426,7 +434,7 @@ func TestDescribeStream_EncryptionTypeDefault(t *testing.T) { EncryptionType string `json:"EncryptionType"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantEncryption, resp.StreamDescription.EncryptionType) }) } @@ -454,7 +462,7 @@ func TestDescribeStream_IncludesClosedShardsAfterMerge(t *testing.T) { } rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-closed-merge"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) s0 := descResp.StreamDescription.Shards[0].ShardID s1 := descResp.StreamDescription.Shards[1].ShardID @@ -468,7 +476,7 @@ func TestDescribeStream_IncludesClosedShardsAfterMerge(t *testing.T) { // After merge: 2 closed parents + 1 open merged = 3 total. rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-closed-merge"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Len(t, descResp.StreamDescription.Shards, 3) }) } @@ -495,7 +503,7 @@ func TestDescribeStream_IncludesClosedShardsAfterSplit(t *testing.T) { } rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-closed-split"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) shardID := descResp.StreamDescription.Shards[0].ShardID const splitKey = "170141183460469231731687303715884105728" @@ -509,7 +517,7 @@ func TestDescribeStream_IncludesClosedShardsAfterSplit(t *testing.T) { // After split: 1 closed parent + 2 open children = 3 total. rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-closed-split"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Len(t, descResp.StreamDescription.Shards, 3) }) } @@ -537,7 +545,7 @@ func TestDescribeStream_OpenShardNoEndingSequenceNumber(t *testing.T) { } rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-open-shard"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) // Open shards have an empty EndingSequenceNumber. assert.Empty(t, descResp.StreamDescription.Shards[0].SequenceNumberRange.EndingSequenceNumber) @@ -585,7 +593,7 @@ func TestDescribeStream_OpenShardWithRecordsNoEndingSeq(t *testing.T) { } rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "open-shard-with-records"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) shard := descResp.StreamDescription.Shards[0] @@ -625,7 +633,7 @@ func TestDescribeStream_UpdateShardCount_IncludesOldClosedShards(t *testing.T) { } rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "describe-usc-stream"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Len(t, descResp.StreamDescription.Shards, 5, "3 closed + 2 open = 5") }) } @@ -734,7 +742,7 @@ func TestDescribeStream_ClosedShardHasEndingSequenceNumber(t *testing.T) { rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "closing-seqnum-stream"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 1) shardID := descResp.StreamDescription.Shards[0].ShardID @@ -750,7 +758,7 @@ func TestDescribeStream_ClosedShardHasEndingSequenceNumber(t *testing.T) { // Re-describe: closed shard should have a non-empty EndingSequenceNumber. rec = doRequest(t, h, "DescribeStream", map[string]any{"StreamName": "closing-seqnum-stream"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.StreamDescription.Shards, 3) closedCount := 0 diff --git a/services/kinesis/streams_test.go b/services/kinesis/streams_test.go index 23f7df41ed..683e8aaca6 100644 --- a/services/kinesis/streams_test.go +++ b/services/kinesis/streams_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -72,7 +73,7 @@ func TestCreateStream_ShardCount_Validation(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp.Type) } }) @@ -160,7 +161,7 @@ func TestCreateStream_OnDemand_ShardCountZero(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.StreamDescription.StreamModeDetails) assert.Equal(t, tt.wantMode, resp.StreamDescription.StreamModeDetails.StreamMode) @@ -423,7 +424,7 @@ func TestCreateStream_DefaultsToProvisioned(t *testing.T) { } `json:"StreamModeDetails"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.StreamDescription.StreamModeDetails) assert.Equal(t, tt.wantMode, resp.StreamDescription.StreamModeDetails.StreamMode) }) @@ -476,7 +477,7 @@ func TestCreateStream_WithOnDemand(t *testing.T) { } `json:"StreamModeDetails"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.StreamDescription.StreamModeDetails) assert.Equal(t, tt.wantMode, resp.StreamDescription.StreamModeDetails.StreamMode) }) @@ -524,7 +525,7 @@ func TestCreateStream_WithTags(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) rec3 := doRequest(t, h, "ListTagsForResource", map[string]any{ "ResourceARN": descResp.StreamDescription.StreamARN, @@ -537,7 +538,7 @@ func TestCreateStream_WithTags(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsResp, jsonx.V1())) found := false for _, kv := range tagsResp.Tags { @@ -572,7 +573,7 @@ func TestStreamLifecycle(t *testing.T) { var listResp struct { StreamNames []string `json:"StreamNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Contains(t, listResp.StreamNames, "my-stream") // DescribeStream @@ -590,7 +591,7 @@ func TestStreamLifecycle(t *testing.T) { } `json:"Shards"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-stream", descResp.StreamDescription.StreamName) assert.Equal(t, "ACTIVE", descResp.StreamDescription.StreamStatus) assert.Len(t, descResp.StreamDescription.Shards, 2) @@ -607,7 +608,7 @@ func TestStreamLifecycle(t *testing.T) { OpenShardCount int `json:"OpenShardCount"` } `json:"StreamDescriptionSummary"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sumResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sumResp, jsonx.V1())) assert.Equal(t, "my-stream", sumResp.StreamDescriptionSummary.StreamName) assert.Equal(t, 2, sumResp.StreamDescriptionSummary.OpenShardCount) @@ -645,7 +646,7 @@ func TestCreateStreamAlreadyExists(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceInUseException", errResp.Type) } @@ -673,7 +674,7 @@ func TestHandleListStreamsEmpty(t *testing.T) { var resp struct { StreamNames []string `json:"StreamNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp.StreamNames) assert.Empty(t, resp.StreamNames) } @@ -730,7 +731,7 @@ func TestCreateStream_OnDemandLimit_ViaHandler(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "LimitExceededException", errResp.Type) } diff --git a/services/kinesis/tags_test.go b/services/kinesis/tags_test.go index 2afce221b4..7895d5d9c5 100644 --- a/services/kinesis/tags_test.go +++ b/services/kinesis/tags_test.go @@ -2,7 +2,7 @@ package kinesis_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesis" ) @@ -88,7 +89,7 @@ func TestListTagsForResource_SortedOutput(t *testing.T) { } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Tags, 3) assert.Equal(t, "apple", resp.Tags[0].Key) assert.Equal(t, "a", resp.Tags[0].Value) @@ -113,7 +114,7 @@ func TestAddTagsToStream_KeyTooLong(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) } @@ -133,7 +134,7 @@ func TestAddTagsToStream_EmptyKey(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) } @@ -154,7 +155,7 @@ func TestAddTagsToStream_ValueTooLong(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) } @@ -188,7 +189,7 @@ func TestAddTagsToStream_StreamNotFound(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp.Type) } @@ -213,7 +214,7 @@ func TestTagResource_KeyTooLong(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) } @@ -238,7 +239,7 @@ func TestTagResource_ValueTooLong(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", resp.Type) } @@ -321,7 +322,7 @@ func TestRemoveTagsFromStream_StreamNotFound(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp.Type) } @@ -338,7 +339,7 @@ func TestListTagsForStream_StreamNotFound(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp.Type) } @@ -372,7 +373,7 @@ func TestListTagsForStream_LimitRespected(t *testing.T) { } `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Tags, 5) assert.True(t, resp.HasMoreTags) } @@ -406,7 +407,7 @@ func TestListTagsForStream_LimitDefault(t *testing.T) { } `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Tags, 10) assert.True(t, resp.HasMoreTags) } @@ -455,7 +456,7 @@ func TestListTagsForResource(t *testing.T) { } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp.Tags) } }) @@ -494,7 +495,7 @@ func TestHandleAddTagsToStream(t *testing.T) { } `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.False(t, listResp.HasMoreTags) assert.Len(t, listResp.Tags, 2) @@ -543,7 +544,7 @@ func TestHandleRemoveTagsFromStream(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Tags, 1) assert.Equal(t, "team", listResp.Tags[0].Key) } @@ -567,7 +568,7 @@ func TestHandleListTagsForStreamEmpty(t *testing.T) { } `json:"Tags"` HasMoreTags bool `json:"HasMoreTags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.Tags) assert.False(t, listResp.HasMoreTags) } @@ -616,7 +617,7 @@ func TestListTagsForResource_TagsFromCreate(t *testing.T) { StreamARN string `json:"StreamARN"` } `json:"StreamDescription"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) rec3 := doRequest(t, h, "ListTagsForResource", map[string]any{ "ResourceARN": descResp.StreamDescription.StreamARN, @@ -629,7 +630,7 @@ func TestListTagsForResource_TagsFromCreate(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsResp, jsonx.V1())) found := false for _, kv := range tagsResp.Tags { diff --git a/services/kinesisanalytics/application_cloudwatch_test.go b/services/kinesisanalytics/application_cloudwatch_test.go index 8155d308a2..b961cfe8f7 100644 --- a/services/kinesisanalytics/application_cloudwatch_test.go +++ b/services/kinesisanalytics/application_cloudwatch_test.go @@ -2,13 +2,14 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -237,7 +238,7 @@ func TestAddCWLRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) detail := resp["ApplicationDetail"].(map[string]any) cwlList := detail["CloudWatchLoggingOptionDescriptions"].([]any) assert.Len(t, cwlList, 1) diff --git a/services/kinesisanalytics/application_inputs_test.go b/services/kinesisanalytics/application_inputs_test.go index 9201033487..e8ff51a3a3 100644 --- a/services/kinesisanalytics/application_inputs_test.go +++ b/services/kinesisanalytics/application_inputs_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -541,7 +542,7 @@ func TestHandler_DiscoverInputSchema(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrCode, resp["__type"]) }) } diff --git a/services/kinesisanalytics/application_outputs_test.go b/services/kinesisanalytics/application_outputs_test.go index 7d2501c1f6..2f2eb4cec3 100644 --- a/services/kinesisanalytics/application_outputs_test.go +++ b/services/kinesisanalytics/application_outputs_test.go @@ -2,13 +2,14 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -237,7 +238,7 @@ func TestAddOutputRoundTrip(t *testing.T) { rec2 := doRequest(t, h, "DescribeApplication", map[string]any{"ApplicationName": app.ApplicationName}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) detail := resp["ApplicationDetail"].(map[string]any) outList := detail["OutputDescriptions"].([]any) assert.Len(t, outList, 1) diff --git a/services/kinesisanalytics/application_reference_data_test.go b/services/kinesisanalytics/application_reference_data_test.go index c4e56ca60e..e646325571 100644 --- a/services/kinesisanalytics/application_reference_data_test.go +++ b/services/kinesisanalytics/application_reference_data_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -256,7 +257,7 @@ func TestAddRefDataSourceRoundTrip(t *testing.T) { rec2 := doRequest(t, h, "DescribeApplication", map[string]any{"ApplicationName": app.ApplicationName}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) detail := resp["ApplicationDetail"].(map[string]any) refList := detail["ReferenceDataSourceDescriptions"].([]any) assert.Len(t, refList, 1) diff --git a/services/kinesisanalytics/application_update_test.go b/services/kinesisanalytics/application_update_test.go index 84a3ac8482..45bbe33219 100644 --- a/services/kinesisanalytics/application_update_test.go +++ b/services/kinesisanalytics/application_update_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -248,7 +249,7 @@ func TestHandler_UpdateApplication_NestedWireShapes(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp, jsonx.V1())) detail := resp["ApplicationDetail"].(map[string]any) inList := detail["InputDescriptions"].([]any) @@ -353,7 +354,7 @@ func TestUpdateApplication_ReturnsApplicationDetail(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) detail, ok := resp["ApplicationDetail"].(map[string]any) require.True(t, ok, "UpdateApplication response must contain ApplicationDetail, got: %s", rec.Body.String()) @@ -384,7 +385,7 @@ func TestUpdateApplication_CodeVisible(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) detail, ok := resp["ApplicationDetail"].(map[string]any) require.True(t, ok) @@ -424,6 +425,6 @@ func TestUpdateApplication_ConcurrentModificationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConcurrentModificationException", errResp["__type"]) } diff --git a/services/kinesisanalytics/applications_handler_test.go b/services/kinesisanalytics/applications_handler_test.go index 53eb5774fa..2f69d0f93f 100644 --- a/services/kinesisanalytics/applications_handler_test.go +++ b/services/kinesisanalytics/applications_handler_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -46,7 +47,7 @@ func TestHandler_CreateApplication(t *testing.T) { if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) } }) @@ -160,7 +161,7 @@ func TestDeleteApplication_TimestampMismatch_ConcurrentModificationException(t * assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ConcurrentModificationException", resp["__type"], "timestamp mismatch must return ConcurrentModificationException, not LimitExceededException") } @@ -225,7 +226,7 @@ func TestHandler_ListApplications(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["ApplicationSummaries"].([]any) assert.Len(t, summaries, tt.wantCount) diff --git a/services/kinesisanalytics/applications_test.go b/services/kinesisanalytics/applications_test.go index 6c0e5e768c..db175091db 100644 --- a/services/kinesisanalytics/applications_test.go +++ b/services/kinesisanalytics/applications_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -605,7 +606,7 @@ func TestResourceAlreadyExists_Returns400(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceInUseException", errResp["__type"]) } @@ -620,6 +621,6 @@ func TestErrValidationMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidArgumentException", errResp["__type"]) } diff --git a/services/kinesisanalytics/discover_schema.go b/services/kinesisanalytics/discover_schema.go index 7645c90d91..7b1a3cc33e 100644 --- a/services/kinesisanalytics/discover_schema.go +++ b/services/kinesisanalytics/discover_schema.go @@ -3,7 +3,8 @@ package kinesisanalytics import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "sort" @@ -11,6 +12,8 @@ import ( "strings" sdk_s3 "github.com/aws/aws-sdk-go-v2/service/s3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -208,7 +211,7 @@ func sampleJSONLines(body []byte, limit int) []string { for _, line := range lines { trimmed := bytes.TrimSpace(line) - if len(trimmed) == 0 || !json.Valid(trimmed) { + if len(trimmed) == 0 || !jsontext.Value(trimmed).IsValid(jsonx.V1()) { continue } @@ -266,11 +269,10 @@ func decodeSampleRecords(raw []string) []map[string]any { records := make([]map[string]any, 0, len(raw)) for _, r := range raw { - dec := json.NewDecoder(strings.NewReader(r)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(r)) var m map[string]any - if err := dec.Decode(&m); err != nil { + if err := json.UnmarshalDecode(dec, &m, jsonx.V1(), jsonx.UseNumber()); err != nil { continue } @@ -318,7 +320,7 @@ func inferColumnType(records []map[string]any, key string) string { switch val := v.(type) { case bool: sawBool = true - case json.Number: + case jsonx.Number: if _, err := strconv.ParseInt(val.String(), 10, 64); err == nil { sawInt = true } else { @@ -330,7 +332,7 @@ func inferColumnType(records []map[string]any, key string) string { default: sawOther = true - if b, err := json.Marshal(val); err == nil { + if b, err := json.Marshal(val, jsonx.V1()); err == nil { maxLen = max(maxLen, len(b)) } } @@ -357,12 +359,12 @@ func stringifyValue(v any) string { return "" case string: return val - case json.Number: + case jsonx.Number: return val.String() case bool: return strconv.FormatBool(val) default: - b, err := json.Marshal(val) + b, err := json.Marshal(val, jsonx.V1()) if err != nil { return "" } diff --git a/services/kinesisanalytics/discover_schema_test.go b/services/kinesisanalytics/discover_schema_test.go index 649f378b6d..7d4dfaef16 100644 --- a/services/kinesisanalytics/discover_schema_test.go +++ b/services/kinesisanalytics/discover_schema_test.go @@ -3,7 +3,7 @@ package kinesisanalytics_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -80,7 +81,7 @@ func discoverSchemaBody(t *testing.T, rec *httptest.ResponseRecorder) map[string t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/kinesisanalytics/handler.go b/services/kinesisanalytics/handler.go index 7ae78c3732..0afdd6a3ae 100644 --- a/services/kinesisanalytics/handler.go +++ b/services/kinesisanalytics/handler.go @@ -2,7 +2,7 @@ package kinesisanalytics import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -163,7 +164,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req applicationNameInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.ApplicationName } @@ -198,12 +199,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError var code string var status int @@ -234,8 +233,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err status = http.StatusBadRequest code = errLimitExceededException case errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): status = http.StatusBadRequest code = errInvalidArgumentException case errors.Is(err, errApplicationName), diff --git a/services/kinesisanalytics/handler_test.go b/services/kinesisanalytics/handler_test.go index b56a6d26ee..638e9b8e04 100644 --- a/services/kinesisanalytics/handler_test.go +++ b/services/kinesisanalytics/handler_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -49,7 +50,7 @@ func doRequest(t *testing.T, h *kinesisanalytics.Handler, action string, body an if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -273,7 +274,7 @@ func TestErrorTypes(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) }) } diff --git a/services/kinesisanalytics/persistence.go b/services/kinesisanalytics/persistence.go index cf28ab3a45..b8784282e7 100644 --- a/services/kinesisanalytics/persistence.go +++ b/services/kinesisanalytics/persistence.go @@ -2,9 +2,11 @@ package kinesisanalytics import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" @@ -28,11 +30,11 @@ const kinesisanalyticsSnapshotVersion = 1 // Application is persisted directly (no DTO) because every field, including // the additive Region, already round-trips through encoding/json. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - NextID int64 `json:"next_id"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + NextID int64 `json:"next_id"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -56,7 +58,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NextID: b.nextID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "kinesisanalytics: failed to marshal snapshot", "error", err) diff --git a/services/kinesisanalytics/persistence_test.go b/services/kinesisanalytics/persistence_test.go index 242c92e5f7..1ddfaadd79 100644 --- a/services/kinesisanalytics/persistence_test.go +++ b/services/kinesisanalytics/persistence_test.go @@ -2,11 +2,14 @@ package kinesisanalytics //nolint:testpackage // needs kaCtxRegion and the unexp import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestInMemoryBackend_FullStateSnapshotRestoreRoundTrip exercises every kind @@ -158,12 +161,12 @@ func TestInMemoryBackend_Restore_IncompatibleVersion_ResetsEmpty(t *testing.T) { // Corrupt just the version field to simulate a snapshot from an // incompatible (older/newer) build. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &raw)) - bumped, err := json.Marshal(kinesisanalyticsSnapshotVersion + 1) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) + bumped, err := json.Marshal(kinesisanalyticsSnapshotVersion+1, jsonx.V1()) require.NoError(t, err) raw["version"] = bumped - mutated, err := json.Marshal(raw) + mutated, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) fresh := NewInMemoryBackend("us-east-1", "000000000000") diff --git a/services/kinesisanalytics/tags_test.go b/services/kinesisanalytics/tags_test.go index c3a4bc057f..beb6eff1ff 100644 --- a/services/kinesisanalytics/tags_test.go +++ b/services/kinesisanalytics/tags_test.go @@ -2,7 +2,7 @@ package kinesisanalytics_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalytics" ) @@ -434,7 +435,7 @@ func TestSortedListTagsForResource(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Tags, 3) assert.Equal(t, "a", resp.Tags[0].Key) diff --git a/services/kinesisanalyticsv2/application_update_test.go b/services/kinesisanalyticsv2/application_update_test.go index f653515151..344cca1e75 100644 --- a/services/kinesisanalyticsv2/application_update_test.go +++ b/services/kinesisanalyticsv2/application_update_test.go @@ -2,13 +2,14 @@ package kinesisanalyticsv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "math" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -520,7 +521,7 @@ func appCreateEpochSeconds(t *testing.T, b *kinesisanalyticsv2.InMemoryBackend, } `json:"ApplicationDetail"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.ApplicationDetail.CreateTimestamp } diff --git a/services/kinesisanalyticsv2/flink_engine_test.go b/services/kinesisanalyticsv2/flink_engine_test.go index 80029494aa..986f747412 100644 --- a/services/kinesisanalyticsv2/flink_engine_test.go +++ b/services/kinesisanalyticsv2/flink_engine_test.go @@ -2,7 +2,8 @@ package kinesisanalyticsv2_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "mime" "mime/multipart" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -127,7 +129,7 @@ func (f *fakeFlinkREST) Do(req *http.Request) (*http.Response, error) { case strings.HasSuffix(p, "/run"): var body map[string]any - _ = json.NewDecoder(req.Body).Decode(&body) + _ = json.UnmarshalDecode(jsontext.NewDecoder(req.Body), &body, jsonx.V1()) f.runs = append(f.runs, body) return jsonResp(`{"jobid":"job1"}`), nil diff --git a/services/kinesisanalyticsv2/flink_rest.go b/services/kinesisanalyticsv2/flink_rest.go index fde5d06424..322bba6ae1 100644 --- a/services/kinesisanalyticsv2/flink_rest.go +++ b/services/kinesisanalyticsv2/flink_rest.go @@ -3,7 +3,7 @@ package kinesisanalyticsv2 import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -11,6 +11,8 @@ import ( "net/http" "net/textproto" "path" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const flinkMaxBody = 1 << 20 @@ -89,7 +91,7 @@ func (c flinkREST) send(ctx context.Context, method, p, contentType string, body return nil } - if err = json.Unmarshal(raw, out); err != nil { + if err = json.Unmarshal(raw, out, jsonx.V1()); err != nil { return fmt.Errorf("decode flink response: %w", err) } @@ -100,7 +102,7 @@ func (c flinkREST) json(ctx context.Context, method, p string, in, out any) erro var body io.Reader if in != nil { - raw, err := json.Marshal(in) + raw, err := json.Marshal(in, jsonx.V1()) if err != nil { return fmt.Errorf("encode flink request: %w", err) } diff --git a/services/kinesisanalyticsv2/flink_run.go b/services/kinesisanalyticsv2/flink_run.go index c4bf340f35..c39ae593e9 100644 --- a/services/kinesisanalyticsv2/flink_run.go +++ b/services/kinesisanalyticsv2/flink_run.go @@ -2,7 +2,7 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "os" @@ -12,6 +12,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" ) @@ -77,7 +78,7 @@ func (e *flinkEngine) stage(in flinkLaunch) (string, error) { props = []PropertyGroup{} } - raw, err := json.Marshal(props) + raw, err := json.Marshal(props, jsonx.V1()) if err == nil { err = os.WriteFile(filepath.Join(dir, "application_properties.json"), raw, flinkFileMode) } diff --git a/services/kinesisanalyticsv2/handler.go b/services/kinesisanalyticsv2/handler.go index 579e647fd6..e09653af34 100644 --- a/services/kinesisanalyticsv2/handler.go +++ b/services/kinesisanalyticsv2/handler.go @@ -2,7 +2,7 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -131,7 +132,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ApplicationName string `json:"ApplicationName"` } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } diff --git a/services/kinesisanalyticsv2/handler_application_config.go b/services/kinesisanalyticsv2/handler_application_config.go index 1813036a99..42ddc6fd51 100644 --- a/services/kinesisanalyticsv2/handler_application_config.go +++ b/services/kinesisanalyticsv2/handler_application_config.go @@ -2,10 +2,12 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type cwlOptionInput struct { @@ -218,7 +220,7 @@ type deleteApplicationVpcConfigOutput struct { func (h *Handler) handleAddApplicationCloudWatchLoggingOption(ctx context.Context, c *echo.Context, body []byte) error { var in addApplicationCWLOptionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -258,7 +260,7 @@ func (h *Handler) handleAddApplicationInput( body []byte, ) error { var in addApplicationInputInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -288,7 +290,7 @@ func (h *Handler) handleAddApplicationInputProcessingConfiguration( ctx context.Context, c *echo.Context, body []byte, ) error { var in addInputProcessingConfigInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -337,7 +339,7 @@ func (h *Handler) handleAddApplicationOutput( body []byte, ) error { var in addApplicationOutputInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -368,7 +370,7 @@ func (h *Handler) handleAddApplicationOutput( //nolint:dupl // add input/reference-data-source handlers share structure but are semantically distinct operations func (h *Handler) handleAddApplicationReferenceDataSource(ctx context.Context, c *echo.Context, body []byte) error { var in addApplicationRefDataSourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -398,7 +400,7 @@ func (h *Handler) handleAddApplicationReferenceDataSource(ctx context.Context, c func (h *Handler) handleAddApplicationVpcConfiguration(ctx context.Context, c *echo.Context, body []byte) error { var in addApplicationVpcConfigInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -439,7 +441,7 @@ func (h *Handler) handleDeleteApplicationCloudWatchLoggingOption( ctx context.Context, c *echo.Context, body []byte, ) error { var in deleteApplicationCWLOptionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -467,7 +469,7 @@ func (h *Handler) handleDeleteApplicationInputProcessingConfiguration( ctx context.Context, c *echo.Context, body []byte, ) error { var in deleteInputProcessingConfigInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -490,7 +492,7 @@ func (h *Handler) handleDeleteApplicationInputProcessingConfiguration( func (h *Handler) handleDeleteApplicationOutput(ctx context.Context, c *echo.Context, body []byte) error { var in deleteApplicationOutputInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -513,7 +515,7 @@ func (h *Handler) handleDeleteApplicationOutput(ctx context.Context, c *echo.Con func (h *Handler) handleDeleteApplicationReferenceDataSource(ctx context.Context, c *echo.Context, body []byte) error { var in deleteApplicationRefDataSourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -536,7 +538,7 @@ func (h *Handler) handleDeleteApplicationReferenceDataSource(ctx context.Context func (h *Handler) handleDeleteApplicationVpcConfiguration(ctx context.Context, c *echo.Context, body []byte) error { var in deleteApplicationVpcConfigInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_application_config_delete_test.go b/services/kinesisanalyticsv2/handler_application_config_delete_test.go index 9dcbd09aa4..aec4dc83e6 100644 --- a/services/kinesisanalyticsv2/handler_application_config_delete_test.go +++ b/services/kinesisanalyticsv2/handler_application_config_delete_test.go @@ -1,13 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -28,7 +29,7 @@ func TestKAV2_DeleteApplicationCloudWatchLoggingOption(t *testing.T) { }) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descs := out["CloudWatchLoggingOptionDescriptions"].([]any) desc := descs[0].(map[string]any) @@ -77,7 +78,7 @@ func TestKAV2_DeleteApplicationCloudWatchLoggingOption(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descs, ok := out["CloudWatchLoggingOptionDescriptions"].([]any) require.True(t, ok) assert.Len(t, descs, tt.wantCWLCount) @@ -125,7 +126,7 @@ func TestKAV2_DeleteApplicationInputProcessingConfiguration(t *testing.T) { }) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) inputs := out["InputDescriptions"].([]any) input := inputs[0].(map[string]any) inputID := input["InputId"].(string) @@ -226,7 +227,7 @@ func TestKAV2_DeleteApplicationOutput(t *testing.T) { }) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) outputs := out["OutputDescriptions"].([]any) output := outputs[0].(map[string]any) @@ -287,7 +288,7 @@ func TestKAV2_DeleteApplicationOutput(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["ApplicationARN"]) } }) diff --git a/services/kinesisanalyticsv2/handler_application_config_test.go b/services/kinesisanalyticsv2/handler_application_config_test.go index ffc3374611..d105543cf0 100644 --- a/services/kinesisanalyticsv2/handler_application_config_test.go +++ b/services/kinesisanalyticsv2/handler_application_config_test.go @@ -1,13 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -73,7 +74,7 @@ func TestKAV2_AddApplicationCloudWatchLoggingOption(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) descriptions, ok := out["CloudWatchLoggingOptionDescriptions"].([]any) require.True(t, ok) assert.Len(t, descriptions, tt.wantCWLLen) @@ -146,7 +147,7 @@ func TestKAV2_AddApplicationInput(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) inputs, ok := out["InputDescriptions"].([]any) require.True(t, ok) assert.Len(t, inputs, tt.wantInputs) @@ -196,7 +197,7 @@ func TestKAV2_AddApplicationInputProcessingConfiguration(t *testing.T) { }) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) inputs := out["InputDescriptions"].([]any) input := inputs[0].(map[string]any) @@ -328,7 +329,7 @@ func TestKAV2_AddApplicationOutput(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) outputs, ok := out["OutputDescriptions"].([]any) require.True(t, ok) assert.Len(t, outputs, tt.wantOutputs) @@ -422,7 +423,7 @@ func TestKAV2_AddApplicationReferenceDataSource(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) refs, ok := out["ReferenceDataSourceDescriptions"].([]any) require.True(t, ok) assert.Len(t, refs, tt.wantRefs) @@ -512,7 +513,7 @@ func TestKAV2_AddApplicationVpcConfiguration(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["VpcConfigurationDescription"]) vpcDesc, ok := out["VpcConfigurationDescription"].(map[string]any) require.True(t, ok) @@ -545,7 +546,7 @@ func TestKAV2_VpcConfiguration_NonNilSlices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) vpcDesc, ok := out["VpcConfigurationDescription"].(map[string]any) require.True(t, ok) @@ -612,7 +613,7 @@ func TestKAV2_AddOps_VersionBump(t *testing.T) { respBody := tt.setupAdd(h, appName) var out map[string]any - require.NoError(t, json.Unmarshal(respBody, &out)) + require.NoError(t, json.Unmarshal(respBody, &out, jsonx.V1())) versionID, ok := out["ApplicationVersionId"].(float64) require.True(t, ok) assert.InEpsilon(t, 2.0, versionID, 1e-9) diff --git a/services/kinesisanalyticsv2/handler_application_presigned_url.go b/services/kinesisanalyticsv2/handler_application_presigned_url.go index 47c768cc48..66a4855264 100644 --- a/services/kinesisanalyticsv2/handler_application_presigned_url.go +++ b/services/kinesisanalyticsv2/handler_application_presigned_url.go @@ -2,10 +2,12 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createPresignedURLInput struct { @@ -20,7 +22,7 @@ type createPresignedURLOutput struct { func (h *Handler) handleCreateApplicationPresignedURL(ctx context.Context, c *echo.Context, body []byte) error { var in createPresignedURLInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_application_presigned_url_test.go b/services/kinesisanalyticsv2/handler_application_presigned_url_test.go index 3ca738d99f..ac003d620f 100644 --- a/services/kinesisanalyticsv2/handler_application_presigned_url_test.go +++ b/services/kinesisanalyticsv2/handler_application_presigned_url_test.go @@ -1,13 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -59,7 +60,7 @@ func TestKAV2_CreateApplicationPresignedUrl(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) url, ok := out["AuthorizedUrl"].(string) require.True(t, ok) assert.Contains(t, url, "FLINK_DASHBOARD_URL") diff --git a/services/kinesisanalyticsv2/handler_application_snapshots.go b/services/kinesisanalyticsv2/handler_application_snapshots.go index 128de02e0b..a808178339 100644 --- a/services/kinesisanalyticsv2/handler_application_snapshots.go +++ b/services/kinesisanalyticsv2/handler_application_snapshots.go @@ -2,10 +2,12 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createSnapshotInput struct { @@ -34,14 +36,14 @@ type listSnapshotsOutput struct { } type deleteSnapshotInput struct { - ApplicationName string `json:"ApplicationName"` - SnapshotName string `json:"SnapshotName"` - SnapshotCreationTimestamp json.Number `json:"SnapshotCreationTimestamp,omitempty"` + ApplicationName string `json:"ApplicationName"` + SnapshotName string `json:"SnapshotName"` + SnapshotCreationTimestamp jsonx.Number `json:"SnapshotCreationTimestamp,omitempty"` } func (h *Handler) handleCreateApplicationSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var in createSnapshotInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -57,7 +59,7 @@ func (h *Handler) handleCreateApplicationSnapshot(ctx context.Context, c *echo.C func (h *Handler) handleDescribeApplicationSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var in describeSnapshotInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -71,7 +73,7 @@ func (h *Handler) handleDescribeApplicationSnapshot(ctx context.Context, c *echo func (h *Handler) handleListApplicationSnapshots(ctx context.Context, c *echo.Context, body []byte) error { var in listSnapshotsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -90,7 +92,7 @@ func (h *Handler) handleListApplicationSnapshots(ctx context.Context, c *echo.Co func (h *Handler) handleDeleteApplicationSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var in deleteSnapshotInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_application_snapshots_test.go b/services/kinesisanalyticsv2/handler_application_snapshots_test.go index cea70f4004..bf059c3bd7 100644 --- a/services/kinesisanalyticsv2/handler_application_snapshots_test.go +++ b/services/kinesisanalyticsv2/handler_application_snapshots_test.go @@ -1,12 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestKAV2_SnapshotLifecycle(t *testing.T) { @@ -38,7 +40,7 @@ func TestKAV2_SnapshotLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) snaps, ok := listOut["SnapshotSummaries"].([]any) require.True(t, ok) assert.Len(t, snaps, 1) diff --git a/services/kinesisanalyticsv2/handler_application_update.go b/services/kinesisanalyticsv2/handler_application_update.go index 4105dab3a6..5e38724265 100644 --- a/services/kinesisanalyticsv2/handler_application_update.go +++ b/services/kinesisanalyticsv2/handler_application_update.go @@ -2,10 +2,12 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // runConfigurationInput mirrors real AWS's RunConfiguration (StartApplication) @@ -219,7 +221,7 @@ type updateApplicationOutput struct { func (h *Handler) handleUpdateApplication(ctx context.Context, c *echo.Context, body []byte) error { var in updateApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_application_update_test.go b/services/kinesisanalyticsv2/handler_application_update_test.go index 1316c51b10..f8c17a07f1 100644 --- a/services/kinesisanalyticsv2/handler_application_update_test.go +++ b/services/kinesisanalyticsv2/handler_application_update_test.go @@ -1,12 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestKAV2_CreateApplication_ExtendedInlineConfiguration verifies that @@ -57,7 +59,7 @@ func TestKAV2_CreateApplication_ExtendedInlineConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) appConfig := detail["ApplicationConfigurationDescription"].(map[string]any) @@ -110,7 +112,7 @@ func TestKAV2_UpdateApplication_ConditionalTokenWireRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) token, ok := createOut["ApplicationDetail"].(map[string]any)["ConditionalToken"].(string) require.True(t, ok, "expected ConditionalToken in CreateApplication response") require.NotEmpty(t, token) @@ -123,7 +125,7 @@ func TestKAV2_UpdateApplication_ConditionalTokenWireRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) assert.Equal(t, "FLINK-1_19", updateOut["ApplicationDetail"].(map[string]any)["RuntimeEnvironment"]) // A second call reusing the now-stale token must fail. @@ -159,14 +161,14 @@ func TestKAV2_StartApplication_RunConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut["OperationId"]) descRec := doKAV2Request(t, h, "DescribeApplication", map[string]any{"ApplicationName": "start-runcfg-wire-app"}) require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) appConfig := descOut["ApplicationDetail"].(map[string]any)["ApplicationConfigurationDescription"].(map[string]any) runConfig := appConfig["RunConfigurationDescription"].(map[string]any) restoreConfig := runConfig["ApplicationRestoreConfigurationDescription"].(map[string]any) @@ -236,7 +238,7 @@ func TestKAV2_AddDeleteVpcAndCWLOption_WireIncludesOperationID(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) detail := descOut["ApplicationDetail"].(map[string]any) cwlOptions := detail["CloudWatchLoggingOptionDescriptions"].([]any) cwlID := cwlOptions[0].(map[string]any)["CloudWatchLoggingOptionId"].(string) @@ -262,7 +264,7 @@ func assertHasOperationID(t *testing.T, body []byte) { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) opID, ok := out["OperationId"].(string) require.True(t, ok, "expected OperationId in response") assert.NotEmpty(t, opID) @@ -298,7 +300,7 @@ func TestKAV2_StartApplication_SqlRunConfigurations(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) createAppConfig := createOut["ApplicationDetail"].(map[string]any)["ApplicationConfigurationDescription"].(map[string]any) //nolint:lll // test readability createSQLConfig := createAppConfig["SqlApplicationConfigurationDescription"].(map[string]any) inputID := createSQLConfig["InputDescriptions"].([]any)[0].(map[string]any)["InputId"].(string) @@ -322,7 +324,7 @@ func TestKAV2_StartApplication_SqlRunConfigurations(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) appConfig := descOut["ApplicationDetail"].(map[string]any)["ApplicationConfigurationDescription"].(map[string]any) sqlConfig := appConfig["SqlApplicationConfigurationDescription"].(map[string]any) input := sqlConfig["InputDescriptions"].([]any)[0].(map[string]any) @@ -452,7 +454,7 @@ func TestKAV2_DiscoverInputSchema(t *testing.T) { } var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) inputSchema := out["InputSchema"].(map[string]any) assert.Len(t, inputSchema["RecordColumns"], 3) }) @@ -510,7 +512,7 @@ func TestKAV2_CreateApplication_ZeppelinConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) appConfig := detail["ApplicationConfigurationDescription"].(map[string]any) zepDesc := appConfig["ZeppelinApplicationConfigurationDescription"].(map[string]any) @@ -576,7 +578,7 @@ func TestKAV2_UpdateApplication_ZeppelinConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) appConfig := descOut["ApplicationDetail"].(map[string]any)["ApplicationConfigurationDescription"].(map[string]any) zepDesc := appConfig["ZeppelinApplicationConfigurationDescription"].(map[string]any) diff --git a/services/kinesisanalyticsv2/handler_application_versions.go b/services/kinesisanalyticsv2/handler_application_versions.go index a3a1e436c8..1a94ad0774 100644 --- a/services/kinesisanalyticsv2/handler_application_versions.go +++ b/services/kinesisanalyticsv2/handler_application_versions.go @@ -2,12 +2,13 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type describeApplicationOperationInput struct { @@ -93,7 +94,7 @@ type rollbackApplicationOutput struct { func (h *Handler) handleDescribeApplicationOperation(ctx context.Context, c *echo.Context, body []byte) error { var in describeApplicationOperationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -114,7 +115,7 @@ func (h *Handler) handleDescribeApplicationOperation(ctx context.Context, c *ech func (h *Handler) handleListApplicationOperations(ctx context.Context, c *echo.Context, body []byte) error { var in listApplicationOperationsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -144,7 +145,7 @@ func (h *Handler) handleListApplicationOperations(ctx context.Context, c *echo.C func (h *Handler) handleDescribeApplicationVersion(ctx context.Context, c *echo.Context, body []byte) error { var in describeApplicationVersionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -160,7 +161,7 @@ func (h *Handler) handleDescribeApplicationVersion(ctx context.Context, c *echo. func (h *Handler) handleListApplicationVersions(ctx context.Context, c *echo.Context, body []byte) error { var in listApplicationVersionsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -185,7 +186,7 @@ func (h *Handler) handleListApplicationVersions(ctx context.Context, c *echo.Con func (h *Handler) handleRollbackApplication(ctx context.Context, c *echo.Context, body []byte) error { var in rollbackApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_application_versions_test.go b/services/kinesisanalyticsv2/handler_application_versions_test.go index 6312718009..f9707e57ce 100644 --- a/services/kinesisanalyticsv2/handler_application_versions_test.go +++ b/services/kinesisanalyticsv2/handler_application_versions_test.go @@ -1,12 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestKAV2_ApplicationOperationsLifecycle exercises @@ -29,7 +31,7 @@ func TestKAV2_ApplicationOperationsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) opID, ok := startOut["OperationId"].(string) require.True(t, ok) require.NotEmpty(t, opID) @@ -41,7 +43,7 @@ func TestKAV2_ApplicationOperationsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) details, ok := descOut["ApplicationOperationInfoDetails"].(map[string]any) require.True(t, ok) assert.Equal(t, "StartApplication", details["Operation"]) @@ -55,7 +57,7 @@ func TestKAV2_ApplicationOperationsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) items, ok := listOut["ApplicationOperationInfoList"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -103,7 +105,7 @@ func TestKAV2_RollbackApplication(t *testing.T) { require.Equal(t, http.StatusOK, rollbackRec.Code) var rollbackOut map[string]any - require.NoError(t, json.Unmarshal(rollbackRec.Body.Bytes(), &rollbackOut)) + require.NoError(t, json.Unmarshal(rollbackRec.Body.Bytes(), &rollbackOut, jsonx.V1())) assert.NotEmpty(t, rollbackOut["OperationId"]) detail, ok := rollbackOut["ApplicationDetail"].(map[string]any) diff --git a/services/kinesisanalyticsv2/handler_applications.go b/services/kinesisanalyticsv2/handler_applications.go index 45dd23c4fc..8ef6638125 100644 --- a/services/kinesisanalyticsv2/handler_applications.go +++ b/services/kinesisanalyticsv2/handler_applications.go @@ -2,13 +2,14 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maintenanceWindowDuration = 8 * time.Hour @@ -227,8 +228,8 @@ type listApplicationsOutput struct { } type deleteApplicationInput struct { - ApplicationName string `json:"ApplicationName"` - CreateTimestamp json.Number `json:"CreateTimestamp,omitempty"` + ApplicationName string `json:"ApplicationName"` + CreateTimestamp jsonx.Number `json:"CreateTimestamp,omitempty"` } type startApplicationInput struct { @@ -313,7 +314,7 @@ type discoverInputSchemaOutput struct { func (h *Handler) handleCreateApplication(ctx context.Context, c *echo.Context, body []byte) error { var in createApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -575,7 +576,7 @@ func buildZeppelinConfigDesc(in *zeppelinApplicationConfigInput) *ZeppelinApplic func (h *Handler) handleDescribeApplication(ctx context.Context, c *echo.Context, body []byte) error { var in describeApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -591,7 +592,7 @@ func (h *Handler) handleDescribeApplication(ctx context.Context, c *echo.Context func (h *Handler) handleListApplications(ctx context.Context, c *echo.Context, body []byte) error { var in listApplicationsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -612,7 +613,7 @@ func (h *Handler) handleListApplications(ctx context.Context, c *echo.Context, b // DeleteApplication validates against. Returns nil (skip the check) when the // field is absent or unparseable, matching the pre-existing "leniency, never // causes a false accept/reject" note in PARITY.md. -func deleteTimestampSeconds(n json.Number) *float64 { +func deleteTimestampSeconds(n jsonx.Number) *float64 { if n == "" { return nil } @@ -627,7 +628,7 @@ func deleteTimestampSeconds(n json.Number) *float64 { func (h *Handler) handleDeleteApplication(ctx context.Context, c *echo.Context, body []byte) error { var in deleteApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -641,7 +642,7 @@ func (h *Handler) handleDeleteApplication(ctx context.Context, c *echo.Context, func (h *Handler) handleStartApplication(ctx context.Context, c *echo.Context, body []byte) error { var in startApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -662,7 +663,7 @@ func (h *Handler) handleStartApplication(ctx context.Context, c *echo.Context, b func (h *Handler) handleStopApplication(ctx context.Context, c *echo.Context, body []byte) error { var in startStopApplicationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -690,7 +691,7 @@ func (h *Handler) handleUpdateApplicationMaintenanceConfiguration( ctx context.Context, c *echo.Context, body []byte, ) error { var in updateMaintenanceConfigInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -711,7 +712,7 @@ func (h *Handler) handleUpdateApplicationMaintenanceConfiguration( func (h *Handler) handleDiscoverInputSchema(ctx context.Context, c *echo.Context, body []byte) error { var in discoverInputSchemaInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_applications_test.go b/services/kinesisanalyticsv2/handler_applications_test.go index 21840becdb..3542784ecb 100644 --- a/services/kinesisanalyticsv2/handler_applications_test.go +++ b/services/kinesisanalyticsv2/handler_applications_test.go @@ -1,7 +1,7 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -16,7 +17,7 @@ func assertErrorType(t *testing.T, body []byte, wantType string) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, wantType, resp["__type"]) } @@ -24,7 +25,7 @@ func assertAppStatus(t *testing.T, body []byte, wantStatus string) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) detail, ok := resp["ApplicationDetail"].(map[string]any) require.True(t, ok, "response missing ApplicationDetail") @@ -76,7 +77,7 @@ func TestKAV2_CreateApplication(t *testing.T) { if tt.wantStatus == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail, ok := out["ApplicationDetail"].(map[string]any) require.True(t, ok) @@ -184,7 +185,7 @@ func TestKAV2_CreateApplication_InlineConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) // Inline config must not bump the version past 1 -- real AWS keeps a @@ -222,7 +223,7 @@ func TestKAV2_NonNilSlices_InDetailOutput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) // Tags should be present (may be empty but not nil) @@ -292,7 +293,7 @@ func TestKAV2_ListApplications(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, ok := out["ApplicationSummaries"].([]any) require.True(t, ok) @@ -341,7 +342,7 @@ func TestKAV2_StartStopApplication(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) assert.Equal(t, "RUNNING", detail["ApplicationStatus"]) @@ -369,14 +370,14 @@ func TestKAV2_StartStopUpdate_ReturnOperationId(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) assert.NotEmpty(t, startOut["OperationId"]) stopRec := doKAV2Request(t, h, "StopApplication", map[string]any{"ApplicationName": "opid-app"}) require.Equal(t, http.StatusOK, stopRec.Code) var stopOut map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopOut)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopOut, jsonx.V1())) assert.NotEmpty(t, stopOut["OperationId"]) updateRec := doKAV2Request(t, h, "UpdateApplication", map[string]any{ @@ -387,7 +388,7 @@ func TestKAV2_StartStopUpdate_ReturnOperationId(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) assert.NotEmpty(t, updateOut["OperationId"]) } @@ -466,7 +467,7 @@ func TestKAV2_UpdateApplication(t *testing.T) { if tt.wantRole != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) detail := out["ApplicationDetail"].(map[string]any) assert.Equal(t, tt.wantRole, detail["ServiceExecutionRole"]) } diff --git a/services/kinesisanalyticsv2/handler_tags.go b/services/kinesisanalyticsv2/handler_tags.go index ac3e4eb4ae..16fca54a7f 100644 --- a/services/kinesisanalyticsv2/handler_tags.go +++ b/services/kinesisanalyticsv2/handler_tags.go @@ -2,10 +2,12 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceInput struct { @@ -28,7 +30,7 @@ type listTagsOutput struct { func (h *Handler) handleTagResource(ctx context.Context, c *echo.Context, body []byte) error { var in tagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -41,7 +43,7 @@ func (h *Handler) handleTagResource(ctx context.Context, c *echo.Context, body [ func (h *Handler) handleUntagResource(ctx context.Context, c *echo.Context, body []byte) error { var in untagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } @@ -54,7 +56,7 @@ func (h *Handler) handleUntagResource(ctx context.Context, c *echo.Context, body func (h *Handler) handleListTagsForResource(ctx context.Context, c *echo.Context, body []byte) error { var in listTagsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body: "+err.Error()) } diff --git a/services/kinesisanalyticsv2/handler_tags_test.go b/services/kinesisanalyticsv2/handler_tags_test.go index ae6c329917..a01ed56d2e 100644 --- a/services/kinesisanalyticsv2/handler_tags_test.go +++ b/services/kinesisanalyticsv2/handler_tags_test.go @@ -1,12 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestKAV2_TaggingOperations(t *testing.T) { @@ -24,7 +26,7 @@ func TestKAV2_TaggingOperations(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) detail := createOut["ApplicationDetail"].(map[string]any) appARN := detail["ApplicationARN"].(string) @@ -36,7 +38,7 @@ func TestKAV2_TaggingOperations(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tags, ok := listOut["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 1) @@ -62,7 +64,7 @@ func TestKAV2_TaggingOperations(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listOut2, jsonx.V1())) tags2, ok := listOut2["Tags"].([]any) require.True(t, ok) assert.Len(t, tags2, 1) diff --git a/services/kinesisanalyticsv2/handler_test.go b/services/kinesisanalyticsv2/handler_test.go index 65928d1933..aea291aae1 100644 --- a/services/kinesisanalyticsv2/handler_test.go +++ b/services/kinesisanalyticsv2/handler_test.go @@ -2,7 +2,7 @@ package kinesisanalyticsv2_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kinesisanalyticsv2" ) @@ -34,7 +35,7 @@ func doKAV2Request(t *testing.T, h *kinesisanalyticsv2.Handler, op string, body if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) return doRawKAV2Request(t, h, op, bodyBytes) diff --git a/services/kinesisanalyticsv2/persistence.go b/services/kinesisanalyticsv2/persistence.go index f0b5d54854..bd92e73056 100644 --- a/services/kinesisanalyticsv2/persistence.go +++ b/services/kinesisanalyticsv2/persistence.go @@ -2,7 +2,7 @@ package kinesisanalyticsv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -239,7 +239,7 @@ func fromPersistedSnap(p *persistedSnapshot) *Snapshot { // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` // FlinkStopSaves keeps each application's stop-with-savepoint location for RESTORE_FROM_LATEST_SNAPSHOT. FlinkStopSaves map[string]persistedStopSave `json:"flink_stop_saves,omitempty"` NextID int64 `json:"next_id"` diff --git a/services/kinesisanalyticsv2/wire_field_fixes_test.go b/services/kinesisanalyticsv2/wire_field_fixes_test.go index c783448136..e46dc5bdaa 100644 --- a/services/kinesisanalyticsv2/wire_field_fixes_test.go +++ b/services/kinesisanalyticsv2/wire_field_fixes_test.go @@ -1,12 +1,14 @@ package kinesisanalyticsv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestKAV2_UpdateApplication_ApplicationDescription_NotARealField proves @@ -43,7 +45,7 @@ func TestKAV2_UpdateApplication_ApplicationDescription_NotARealField(t *testing. require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) detail, ok := updateOut["ApplicationDetail"].(map[string]any) require.True(t, ok) assert.Equal(t, "original", detail["ApplicationDescription"], @@ -53,7 +55,7 @@ func TestKAV2_UpdateApplication_ApplicationDescription_NotARealField(t *testing. require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) descDetail, ok := descOut["ApplicationDetail"].(map[string]any) require.True(t, ok) assert.Equal(t, "original", descDetail["ApplicationDescription"]) diff --git a/services/kinesisvideo/handler.go b/services/kinesisvideo/handler.go index cfc39c381b..36490c3185 100644 --- a/services/kinesisvideo/handler.go +++ b/services/kinesisvideo/handler.go @@ -1,7 +1,7 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -249,7 +250,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } diff --git a/services/kinesisvideo/handler_configs.go b/services/kinesisvideo/handler_configs.go index 85011a8ac4..e03729a8d3 100644 --- a/services/kinesisvideo/handler_configs.go +++ b/services/kinesisvideo/handler_configs.go @@ -1,10 +1,12 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildConfigOps() map[string]handlerFunc { @@ -18,7 +20,7 @@ func (h *Handler) buildConfigOps() map[string]handlerFunc { func (h *Handler) handleDescribeImageGenerationConfiguration(c *echo.Context, body []byte) error { var req describeImageGenerationConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -34,7 +36,7 @@ func (h *Handler) handleDescribeImageGenerationConfiguration(c *echo.Context, bo func (h *Handler) handleUpdateImageGenerationConfiguration(c *echo.Context, body []byte) error { var req updateImageGenerationConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -49,7 +51,7 @@ func (h *Handler) handleUpdateImageGenerationConfiguration(c *echo.Context, body func (h *Handler) handleDescribeNotificationConfiguration(c *echo.Context, body []byte) error { var req describeNotificationConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -65,7 +67,7 @@ func (h *Handler) handleDescribeNotificationConfiguration(c *echo.Context, body func (h *Handler) handleUpdateNotificationConfiguration(c *echo.Context, body []byte) error { var req updateNotificationConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/handler_edge.go b/services/kinesisvideo/handler_edge.go index c902a64cec..839a155ec6 100644 --- a/services/kinesisvideo/handler_edge.go +++ b/services/kinesisvideo/handler_edge.go @@ -1,10 +1,12 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildEdgeOps() map[string]handlerFunc { @@ -18,7 +20,7 @@ func (h *Handler) buildEdgeOps() map[string]handlerFunc { func (h *Handler) handleStartEdgeConfigurationUpdate(c *echo.Context, body []byte) error { var req edgeStreamRequest - if err := json.Unmarshal(body, &req); err != nil || req.EdgeConfig == nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil || req.EdgeConfig == nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -32,7 +34,7 @@ func (h *Handler) handleStartEdgeConfigurationUpdate(c *echo.Context, body []byt func (h *Handler) handleDescribeEdgeConfiguration(c *echo.Context, body []byte) error { var req edgeStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -46,7 +48,7 @@ func (h *Handler) handleDescribeEdgeConfiguration(c *echo.Context, body []byte) func (h *Handler) handleDeleteEdgeConfiguration(c *echo.Context, body []byte) error { var req edgeStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -59,7 +61,7 @@ func (h *Handler) handleDeleteEdgeConfiguration(c *echo.Context, body []byte) er func (h *Handler) handleListEdgeAgentConfigurations(c *echo.Context, body []byte) error { var req listEdgeAgentConfigurationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/handler_signaling.go b/services/kinesisvideo/handler_signaling.go index 07b7344086..ac46d293cc 100644 --- a/services/kinesisvideo/handler_signaling.go +++ b/services/kinesisvideo/handler_signaling.go @@ -1,10 +1,12 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildSignalingOps() map[string]handlerFunc { @@ -19,7 +21,7 @@ func (h *Handler) buildSignalingOps() map[string]handlerFunc { func (h *Handler) handleCreateSignalingChannel(c *echo.Context, body []byte) error { var req createSignalingChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -48,7 +50,7 @@ func (h *Handler) handleCreateSignalingChannel(c *echo.Context, body []byte) err func (h *Handler) handleDescribeSignalingChannel(c *echo.Context, body []byte) error { var req describeSignalingChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -62,7 +64,7 @@ func (h *Handler) handleDescribeSignalingChannel(c *echo.Context, body []byte) e func (h *Handler) handleListSignalingChannels(c *echo.Context, body []byte) error { var req listSignalingChannelsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -89,7 +91,7 @@ func (h *Handler) handleListSignalingChannels(c *echo.Context, body []byte) erro func (h *Handler) handleUpdateSignalingChannel(c *echo.Context, body []byte) error { var req updateSignalingChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -117,7 +119,7 @@ func (h *Handler) handleUpdateSignalingChannel(c *echo.Context, body []byte) err func (h *Handler) handleDeleteSignalingChannel(c *echo.Context, body []byte) error { var req deleteSignalingChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/handler_storage.go b/services/kinesisvideo/handler_storage.go index c14b2eed3d..cb307e5515 100644 --- a/services/kinesisvideo/handler_storage.go +++ b/services/kinesisvideo/handler_storage.go @@ -1,10 +1,12 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildStorageOps() map[string]handlerFunc { @@ -19,7 +21,7 @@ func (h *Handler) buildStorageOps() map[string]handlerFunc { func (h *Handler) handleDescribeStreamStorageConfiguration(c *echo.Context, body []byte) error { var req streamStorageConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -37,7 +39,7 @@ func (h *Handler) handleDescribeStreamStorageConfiguration(c *echo.Context, body func (h *Handler) handleUpdateStreamStorageConfiguration(c *echo.Context, body []byte) error { var req streamStorageConfigRequest - if err := json.Unmarshal(body, &req); err != nil || req.StreamStorageConfiguration == nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil || req.StreamStorageConfiguration == nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -52,7 +54,7 @@ func (h *Handler) handleUpdateStreamStorageConfiguration(c *echo.Context, body [ func (h *Handler) handleDescribeMediaStorageConfiguration(c *echo.Context, body []byte) error { var req mediaStorageConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -71,7 +73,12 @@ func (h *Handler) handleDescribeMediaStorageConfiguration(c *echo.Context, body func (h *Handler) handleUpdateMediaStorageConfiguration(c *echo.Context, body []byte) error { var req mediaStorageConfigRequest - if err := json.Unmarshal(body, &req); err != nil || req.MediaStorageConfiguration == nil || req.ChannelARN == "" { + if err := json.Unmarshal( + body, + &req, + jsonx.V1(), + ); err != nil || req.MediaStorageConfiguration == nil || + req.ChannelARN == "" { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -89,7 +96,7 @@ func (h *Handler) handleUpdateMediaStorageConfiguration(c *echo.Context, body [] func (h *Handler) handleGetSignalingChannelEndpoint(c *echo.Context, body []byte) error { var req getSignalingChannelEndpointRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/handler_streams.go b/services/kinesisvideo/handler_streams.go index 6dfd939883..32d36770df 100644 --- a/services/kinesisvideo/handler_streams.go +++ b/services/kinesisvideo/handler_streams.go @@ -1,12 +1,13 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildStreamOps() map[string]handlerFunc { @@ -23,7 +24,7 @@ func (h *Handler) buildStreamOps() map[string]handlerFunc { func (h *Handler) handleCreateStream(c *echo.Context, body []byte) error { var req createStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -49,7 +50,7 @@ func (h *Handler) handleCreateStream(c *echo.Context, body []byte) error { func (h *Handler) handleDescribeStream(c *echo.Context, body []byte) error { var req describeStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -63,7 +64,7 @@ func (h *Handler) handleDescribeStream(c *echo.Context, body []byte) error { func (h *Handler) handleListStreams(c *echo.Context, body []byte) error { var req listStreamsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -90,7 +91,7 @@ func (h *Handler) handleListStreams(c *echo.Context, body []byte) error { func (h *Handler) handleUpdateStream(c *echo.Context, body []byte) error { var req updateStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -113,7 +114,7 @@ func (h *Handler) handleUpdateStream(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteStream(c *echo.Context, body []byte) error { var req deleteStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -130,7 +131,7 @@ func (h *Handler) handleDeleteStream(c *echo.Context, body []byte) error { func (h *Handler) handleUpdateDataRetention(c *echo.Context, body []byte) error { var req updateDataRetentionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -154,7 +155,7 @@ func (h *Handler) handleUpdateDataRetention(c *echo.Context, body []byte) error func (h *Handler) handleGetDataEndpoint(c *echo.Context, body []byte) error { var req getDataEndpointRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/handler_tags.go b/services/kinesisvideo/handler_tags.go index 7ca8bf6d15..1991b15159 100644 --- a/services/kinesisvideo/handler_tags.go +++ b/services/kinesisvideo/handler_tags.go @@ -1,10 +1,12 @@ package kinesisvideo import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) buildTagOps() map[string]handlerFunc { @@ -20,7 +22,7 @@ func (h *Handler) buildTagOps() map[string]handlerFunc { func (h *Handler) handleTagStream(c *echo.Context, body []byte) error { var req tagStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -33,7 +35,7 @@ func (h *Handler) handleTagStream(c *echo.Context, body []byte) error { func (h *Handler) handleUntagStream(c *echo.Context, body []byte) error { var req untagStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -46,7 +48,7 @@ func (h *Handler) handleUntagStream(c *echo.Context, body []byte) error { func (h *Handler) handleListTagsForStream(c *echo.Context, body []byte) error { var req listTagsForStreamRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -60,7 +62,7 @@ func (h *Handler) handleListTagsForStream(c *echo.Context, body []byte) error { func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -82,7 +84,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } @@ -99,7 +101,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { func (h *Handler) handleListTagsForResource(c *echo.Context, body []byte) error { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidArgumentException", "invalid request body") } diff --git a/services/kinesisvideo/multi_region_test.go b/services/kinesisvideo/multi_region_test.go index 15609ee2b9..ba9f68a039 100644 --- a/services/kinesisvideo/multi_region_test.go +++ b/services/kinesisvideo/multi_region_test.go @@ -2,7 +2,8 @@ package kinesisvideo_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/kinesisvideo" ) @@ -175,8 +177,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/kinesisvideo/persistence.go b/services/kinesisvideo/persistence.go index a80dab1c03..b31210ac69 100644 --- a/services/kinesisvideo/persistence.go +++ b/services/kinesisvideo/persistence.go @@ -2,7 +2,7 @@ package kinesisvideo import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" @@ -29,8 +29,8 @@ const kinesisvideoSnapshotVersion = 1 // one JSON-encoded array per registered table name (streams, channels -- see // store_setup.go), produced by b.registry.SnapshotAll(). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes backend state to JSON. diff --git a/services/kms/aliases_test.go b/services/kms/aliases_test.go index c9042ddcc2..f5ed225276 100644 --- a/services/kms/aliases_test.go +++ b/services/kms/aliases_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "strings" @@ -631,7 +632,7 @@ func TestCreateAlias_InvalidName_WireErrorType(t *testing.T) { var body struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidAliasNameException", body.Type) assert.NotEqual(t, "ValidationException", body.Type) } diff --git a/services/kms/custom_key_stores_test.go b/services/kms/custom_key_stores_test.go index 3f2baa09b8..0c69147653 100644 --- a/services/kms/custom_key_stores_test.go +++ b/services/kms/custom_key_stores_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -558,7 +559,7 @@ func TestCustomKeyStore_StateGuards_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) connectBody := `{"CustomKeyStoreId":"` + createOut.CustomKeyStoreID + `"}` require.Equal(t, http.StatusOK, doKMSRequest(t, h, "ConnectCustomKeyStore", connectBody).Code) @@ -567,7 +568,7 @@ func TestCustomKeyStore_StateGuards_WireErrorType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "CustomKeyStoreInvalidStateException", errResp.Type) }) @@ -580,14 +581,14 @@ func TestCustomKeyStore_StateGuards_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) disconnectBody := `{"CustomKeyStoreId":"` + createOut.CustomKeyStoreID + `"}` rec := doKMSRequest(t, h, "DisconnectCustomKeyStore", disconnectBody) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "CustomKeyStoreInvalidStateException", errResp.Type) }) @@ -600,7 +601,7 @@ func TestCustomKeyStore_StateGuards_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) idBody := `{"CustomKeyStoreId":"` + createOut.CustomKeyStoreID + `"}` require.Equal(t, http.StatusOK, doKMSRequest(t, h, "ConnectCustomKeyStore", idBody).Code) @@ -609,7 +610,7 @@ func TestCustomKeyStore_StateGuards_WireErrorType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "CustomKeyStoreInvalidStateException", errResp.Type) }) } @@ -629,7 +630,7 @@ func TestDeleteCustomKeyStore_HasKeys_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) idBody := `{"CustomKeyStoreId":"` + createOut.CustomKeyStoreID + `"}` require.Equal(t, http.StatusOK, doKMSRequest(t, h, "ConnectCustomKeyStore", idBody).Code) @@ -643,7 +644,7 @@ func TestDeleteCustomKeyStore_HasKeys_WireErrorType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "CustomKeyStoreHasCMKsException", errResp.Type) } @@ -662,7 +663,7 @@ func TestEncrypt_DisconnectedCustomKeyStore_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) idBody := `{"CustomKeyStoreId":"` + createOut.CustomKeyStoreID + `"}` require.Equal(t, http.StatusOK, doKMSRequest(t, h, "ConnectCustomKeyStore", idBody).Code) @@ -672,7 +673,7 @@ func TestEncrypt_DisconnectedCustomKeyStore_WireErrorType(t *testing.T) { require.Equal(t, http.StatusOK, createKeyRec.Code) var createKeyOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createKeyRec.Body.Bytes(), &createKeyOut)) + require.NoError(t, json.Unmarshal(createKeyRec.Body.Bytes(), &createKeyOut, jsonx.V1())) require.Equal(t, http.StatusOK, doKMSRequest(t, h, "DisconnectCustomKeyStore", idBody).Code) @@ -681,6 +682,6 @@ func TestEncrypt_DisconnectedCustomKeyStore_WireErrorType(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) } diff --git a/services/kms/describe_key_grant_tokens_test.go b/services/kms/describe_key_grant_tokens_test.go index 42e3cf0d5d..3881e0af5a 100644 --- a/services/kms/describe_key_grant_tokens_test.go +++ b/services/kms/describe_key_grant_tokens_test.go @@ -16,12 +16,13 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -31,7 +32,7 @@ func TestDescribeKey_GrantTokens_WireField(t *testing.T) { // The field must deserialize from the AWS wire name "GrantTokens". var input kms.DescribeKeyInput require.NoError(t, json.Unmarshal( - []byte(`{"KeyId":"k-123","GrantTokens":["tok-a","tok-b"]}`), &input)) + []byte(`{"KeyId":"k-123","GrantTokens":["tok-a","tok-b"]}`), &input, jsonx.V1())) assert.Equal(t, "k-123", input.KeyID) assert.Equal(t, []string{"tok-a", "tok-b"}, input.GrantTokens) } diff --git a/services/kms/errtarget_findings_test.go b/services/kms/errtarget_findings_test.go index fb0f0d9f3d..0bc62aded8 100644 --- a/services/kms/errtarget_findings_test.go +++ b/services/kms/errtarget_findings_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -34,7 +35,7 @@ func TestCancelKeyDeletion_DisabledKey_NotDisabledException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) desc, err := h.Backend.DescribeKey(context.Background(), &kms.DescribeKeyInput{KeyID: keyID}) @@ -73,7 +74,7 @@ func TestDecrypt_DisabledKey_StillDisabledException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "DisabledException", errResp.Type) } @@ -119,7 +120,7 @@ func TestImportKeyMaterial_DisabledKey_NotDisabledException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) require.NoError(t, h.Backend.EnableKey(context.Background(), &kms.EnableKeyInput{KeyID: keyID})) @@ -169,7 +170,7 @@ func TestVerifyMac_Mismatch_IsInvalidMac_NotInvalidSignature(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidMacException", errResp.Type) } @@ -211,6 +212,6 @@ func TestDecrypt_ExpiredImportedMaterial_KMSInvalidStateException(t *testing.T) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) } diff --git a/services/kms/grant_authz.go b/services/kms/grant_authz.go index 511503e250..19a8533290 100644 --- a/services/kms/grant_authz.go +++ b/services/kms/grant_authz.go @@ -2,13 +2,15 @@ package kms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strings" gopherarn "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -162,16 +164,16 @@ func statementCoversAction(s *policyStatement, action string) bool { func keyPolicyAllows(policy string, p *awsmeta.Principal, action string) bool { var doc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if json.Unmarshal([]byte(policy), &doc) != nil { + if json.Unmarshal([]byte(policy), &doc, jsonx.V1()) != nil { return false } var stmts []policyStatement - if json.Unmarshal(doc.Statement, &stmts) != nil { + if json.Unmarshal(doc.Statement, &stmts, jsonx.V1()) != nil { var one policyStatement - if json.Unmarshal(doc.Statement, &one) != nil { + if json.Unmarshal(doc.Statement, &one, jsonx.V1()) != nil { return false } diff --git a/services/kms/handler.go b/services/kms/handler.go index 12296e1dd3..b149104cab 100644 --- a/services/kms/handler.go +++ b/services/kms/handler.go @@ -2,7 +2,7 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -215,7 +216,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -262,7 +263,7 @@ func (h *Handler) buildDispatchTable() map[string]kmsActionFn { func unmarshalAction[T any](fn func(context.Context, *T) (any, error)) kmsActionFn { return func(ctx context.Context, b []byte) (any, error) { var input T - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -300,7 +301,7 @@ func (h *Handler) dispatch(ctx context.Context, r *http.Request, action string, return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a structured error response for a KMS operation failure. @@ -389,7 +390,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin payload, _ := json.Marshal(ErrorResponse{ Type: errorType, Message: errorMessage(reqErr), - }) + }, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/kms/handler_alias_rotation.go b/services/kms/handler_alias_rotation.go index 97a503ee54..0222fa60bc 100644 --- a/services/kms/handler_alias_rotation.go +++ b/services/kms/handler_alias_rotation.go @@ -2,7 +2,9 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildAliasRotationActions returns dispatch entries for alias management and key rotation. @@ -10,7 +12,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { return map[string]kmsActionFn{ "CreateAlias": func(ctx context.Context, b []byte) (any, error) { var input CreateAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -18,7 +20,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "UpdateAlias": func(ctx context.Context, b []byte) (any, error) { var input UpdateAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -26,7 +28,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "DeleteAlias": func(ctx context.Context, b []byte) (any, error) { var input DeleteAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -34,7 +36,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "ListAliases": func(ctx context.Context, b []byte) (any, error) { var input ListAliasesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -42,7 +44,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "EnableKeyRotation": func(ctx context.Context, b []byte) (any, error) { var input EnableKeyRotationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -50,7 +52,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "DisableKeyRotation": func(ctx context.Context, b []byte) (any, error) { var input DisableKeyRotationInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -58,7 +60,7 @@ func (h *Handler) buildAliasRotationActions() map[string]kmsActionFn { }, "GetKeyRotationStatus": func(ctx context.Context, b []byte) (any, error) { var input GetKeyRotationStatusInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_alias_rotation_test.go b/services/kms/handler_alias_rotation_test.go index f3de8b48df..cc7dd8349b 100644 --- a/services/kms/handler_alias_rotation_test.go +++ b/services/kms/handler_alias_rotation_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "strings" @@ -39,7 +40,7 @@ func TestHandler_ListAliases_FilterByKeyID_ViaHTTP(t *testing.T) { AliasName string `json:"AliasName"` } `json:"Aliases"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.Aliases) for _, a := range resp.Aliases { assert.Equal(t, "alias/filter-test", a.AliasName) @@ -61,7 +62,7 @@ func TestHandler_RotateKeyOnDemand_ViaHTTP(t *testing.T) { var resp struct { KeyID string `json:"KeyId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, keyID, resp.KeyID) } @@ -86,7 +87,7 @@ func TestHandler_EnableKeyRotation_ViaHTTP(t *testing.T) { KeyRotationEnabled bool `json:"KeyRotationEnabled"` RotationPeriodInDays int32 `json:"RotationPeriodInDays"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &status)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &status, jsonx.V1())) assert.True(t, status.KeyRotationEnabled) assert.Equal(t, int32(90), status.RotationPeriodInDays) } @@ -107,14 +108,14 @@ func TestKMSHandlerAliasOperations(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq, createRec))) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut.KeyMetadata.KeyID // CreateAlias aliasBody, _ := json.Marshal(map[string]string{ "AliasName": "alias/test-alias", "TargetKeyId": keyID, - }) + }, jsonx.V1()) aliasReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(aliasBody))) aliasReq.Header.Set("X-Amz-Target", "TrentService.CreateAlias") aliasRec := httptest.NewRecorder() @@ -128,11 +129,11 @@ func TestKMSHandlerAliasOperations(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(listReq, listRec))) var listOut kms.ListAliasesOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.Aliases, 1) // DeleteAlias - deleteBody, _ := json.Marshal(map[string]string{"AliasName": "alias/test-alias"}) + deleteBody, _ := json.Marshal(map[string]string{"AliasName": "alias/test-alias"}, jsonx.V1()) deleteReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(deleteBody))) deleteReq.Header.Set("X-Amz-Target", "TrentService.DeleteAlias") deleteRec := httptest.NewRecorder() @@ -156,11 +157,11 @@ func TestKMSHandlerKeyRotation(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq, createRec))) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut.KeyMetadata.KeyID // GetKeyRotationStatus - statusBody, _ := json.Marshal(map[string]string{"KeyID": keyID}) + statusBody, _ := json.Marshal(map[string]string{"KeyID": keyID}, jsonx.V1()) statusReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(statusBody))) statusReq.Header.Set("X-Amz-Target", "TrentService.GetKeyRotationStatus") @@ -168,11 +169,11 @@ func TestKMSHandlerKeyRotation(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(statusReq, statusRec))) var statusOut kms.GetKeyRotationStatusOutput - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusOut)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusOut, jsonx.V1())) assert.False(t, statusOut.KeyRotationEnabled) // EnableKeyRotation - enableBody, _ := json.Marshal(map[string]string{"KeyID": keyID}) + enableBody, _ := json.Marshal(map[string]string{"KeyID": keyID}, jsonx.V1()) enableReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(enableBody))) enableReq.Header.Set("X-Amz-Target", "TrentService.EnableKeyRotation") enableRec := httptest.NewRecorder() @@ -180,7 +181,7 @@ func TestKMSHandlerKeyRotation(t *testing.T) { assert.Equal(t, http.StatusOK, enableRec.Code) // DisableKeyRotation - disableBody, _ := json.Marshal(map[string]string{"KeyID": keyID}) + disableBody, _ := json.Marshal(map[string]string{"KeyID": keyID}, jsonx.V1()) disableReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(disableBody))) disableReq.Header.Set("X-Amz-Target", "TrentService.DisableKeyRotation") disableRec := httptest.NewRecorder() @@ -293,7 +294,7 @@ func TestKMSHandlerErrorCases(t *testing.T) { assert.Equal(t, tt.expectedStatus, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.expectedErrTyp, errResp.Type) }) } @@ -321,7 +322,7 @@ func TestKMSListAliasesFiltered(t *testing.T) { ) // Filter by key1 - body, _ := json.Marshal(map[string]string{"KeyId": key1.KeyMetadata.KeyID}) + body, _ := json.Marshal(map[string]string{"KeyId": key1.KeyMetadata.KeyID}, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(body))) req.Header.Set("X-Amz-Target", "TrentService.ListAliases") rec := httptest.NewRecorder() @@ -329,7 +330,7 @@ func TestKMSListAliasesFiltered(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out kms.ListAliasesOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Aliases, 1) assert.Equal(t, "alias/key1", out.Aliases[0].AliasName) } @@ -354,7 +355,7 @@ func TestKMSUpdateAlias_Handler(t *testing.T) { body, err := json.Marshal(kms.UpdateAliasInput{ AliasName: "alias/handler-update-test", TargetKeyID: k2.KeyMetadata.KeyID, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doKMSHTTPRequest(t, h, "UpdateAlias", string(body)) @@ -377,7 +378,7 @@ func TestHandlerCreateAliasWhitespaceRejected(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) rec := sendKMSOp(t, h, "CreateAlias", `{"AliasName":"alias/my bad alias","TargetKeyId":"`+keyID+`"}`) @@ -394,7 +395,7 @@ func TestHandlerListKeyRotationsViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) sendKMSOp(t, h, "RotateKeyOnDemand", `{"KeyId":"`+keyID+`"}`) @@ -403,7 +404,7 @@ func TestHandlerListKeyRotationsViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) rotations := out["Rotations"].([]any) require.NotEmpty(t, rotations) diff --git a/services/kms/handler_crypto.go b/services/kms/handler_crypto.go index 5229e6a679..4180a76991 100644 --- a/services/kms/handler_crypto.go +++ b/services/kms/handler_crypto.go @@ -2,7 +2,9 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildCryptoActions returns dispatch entries for encrypt, decrypt, sign, verify, and data-key operations. @@ -10,7 +12,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { return map[string]kmsActionFn{ opEncrypt: func(ctx context.Context, b []byte) (any, error) { var input EncryptInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -18,7 +20,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opDecrypt: func(ctx context.Context, b []byte) (any, error) { var input DecryptInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -26,7 +28,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opGenerateDataKey: func(ctx context.Context, b []byte) (any, error) { var input GenerateDataKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -34,7 +36,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opGenerateDataKeyWithoutPlaintext: func(ctx context.Context, b []byte) (any, error) { var input GenerateDataKeyWithoutPlaintextInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -42,7 +44,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, "ReEncrypt": func(ctx context.Context, b []byte) (any, error) { var input ReEncryptInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -50,7 +52,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opSign: func(ctx context.Context, b []byte) (any, error) { var input SignInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -58,7 +60,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opVerify: func(ctx context.Context, b []byte) (any, error) { var input VerifyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -66,7 +68,7 @@ func (h *Handler) buildCryptoActions() map[string]kmsActionFn { }, opGetPublicKey: func(ctx context.Context, b []byte) (any, error) { var input GetPublicKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_crypto_test.go b/services/kms/handler_crypto_test.go index 1cde50a4dc..e323e5b71b 100644 --- a/services/kms/handler_crypto_test.go +++ b/services/kms/handler_crypto_test.go @@ -1,7 +1,7 @@ package kms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "encoding/base64" @@ -32,7 +33,7 @@ func TestKMSHandlerEncryptDecrypt(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq, createRec))) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut.KeyMetadata.KeyID @@ -40,7 +41,7 @@ func TestKMSHandlerEncryptDecrypt(t *testing.T) { encBody, _ := json.Marshal(map[string]any{ "KeyID": keyID, "Plaintext": []byte("my-secret"), - }) + }, jsonx.V1()) encReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(encBody))) encReq.Header.Set("X-Amz-Target", "TrentService.Encrypt") encRec := httptest.NewRecorder() @@ -48,10 +49,10 @@ func TestKMSHandlerEncryptDecrypt(t *testing.T) { assert.Equal(t, http.StatusOK, encRec.Code) var encOut kms.EncryptOutput - require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut)) + require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut, jsonx.V1())) // Decrypt - decBody, _ := json.Marshal(map[string]any{"CiphertextBlob": encOut.CiphertextBlob}) + decBody, _ := json.Marshal(map[string]any{"CiphertextBlob": encOut.CiphertextBlob}, jsonx.V1()) decReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(decBody))) decReq.Header.Set("X-Amz-Target", "TrentService.Decrypt") decRec := httptest.NewRecorder() @@ -59,7 +60,7 @@ func TestKMSHandlerEncryptDecrypt(t *testing.T) { assert.Equal(t, http.StatusOK, decRec.Code) var decOut kms.DecryptOutput - require.NoError(t, json.Unmarshal(decRec.Body.Bytes(), &decOut)) + require.NoError(t, json.Unmarshal(decRec.Body.Bytes(), &decOut, jsonx.V1())) assert.Equal(t, []byte("my-secret"), decOut.Plaintext) } @@ -79,7 +80,7 @@ func TestKMSHandlerReEncrypt(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq1, createRec1))) var out1 kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(createRec1.Body.Bytes(), &out1, jsonx.V1())) createReq2 := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(`{}`)) createReq2.Header.Set("X-Amz-Target", "TrentService.CreateKey") @@ -87,26 +88,26 @@ func TestKMSHandlerReEncrypt(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq2, createRec2))) var out2 kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(createRec2.Body.Bytes(), &out2, jsonx.V1())) // Encrypt with key1 encBody, _ := json.Marshal(map[string]any{ "KeyId": out1.KeyMetadata.KeyID, "Plaintext": []byte("reencrypt-me"), - }) + }, jsonx.V1()) encReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(encBody))) encReq.Header.Set("X-Amz-Target", "TrentService.Encrypt") encRec := httptest.NewRecorder() require.NoError(t, h.Handler()(e.NewContext(encReq, encRec))) var encOut kms.EncryptOutput - require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut)) + require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut, jsonx.V1())) // ReEncrypt with key2 reEncBody, _ := json.Marshal(map[string]any{ "CiphertextBlob": encOut.CiphertextBlob, "DestinationKeyId": out2.KeyMetadata.KeyID, - }) + }, jsonx.V1()) reEncReq := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(reEncBody))) reEncReq.Header.Set("X-Amz-Target", "TrentService.ReEncrypt") reEncRec := httptest.NewRecorder() @@ -114,7 +115,7 @@ func TestKMSHandlerReEncrypt(t *testing.T) { assert.Equal(t, http.StatusOK, reEncRec.Code) var reEncOut kms.ReEncryptOutput - require.NoError(t, json.Unmarshal(reEncRec.Body.Bytes(), &reEncOut)) + require.NoError(t, json.Unmarshal(reEncRec.Body.Bytes(), &reEncOut, jsonx.V1())) assert.Equal(t, out2.KeyMetadata.Arn, reEncOut.KeyID) } @@ -140,7 +141,7 @@ func TestKMSHandlerInternalError(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidCiphertextException", errResp.Type) } @@ -154,12 +155,12 @@ func TestKMSHandlerSignVerify(t *testing.T) { createBody, _ := json.Marshal(map[string]any{ "KeyUsage": kms.KeyUsageSignVerify, "KeySpec": "RSA_2048", - }) + }, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "CreateKey", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) keyMeta, ok := createResp["KeyMetadata"].(map[string]any) require.True(t, ok) keyID, ok := keyMeta["KeyId"].(string) @@ -171,12 +172,12 @@ func TestKMSHandlerSignVerify(t *testing.T) { "Message": message, "MessageType": "RAW", "SigningAlgorithm": "RSASSA_PSS_SHA_256", - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "Sign", string(signBody)) require.Equal(t, http.StatusOK, rec.Code) var signResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &signResp, jsonx.V1())) sigRaw, ok := signResp["Signature"] require.True(t, ok) assert.NotEmpty(t, sigRaw) @@ -188,12 +189,12 @@ func TestKMSHandlerSignVerify(t *testing.T) { "MessageType": "RAW", "Signature": sigRaw, "SigningAlgorithm": "RSASSA_PSS_SHA_256", - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "Verify", string(verifyBody)) require.Equal(t, http.StatusOK, rec.Code) var verifyResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verifyResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verifyResp, jsonx.V1())) assert.True(t, verifyResp["SignatureValid"].(bool)) } @@ -206,21 +207,21 @@ func TestKMSHandlerGetPublicKey(t *testing.T) { createBody, _ := json.Marshal(map[string]any{ "KeyUsage": kms.KeyUsageSignVerify, "KeySpec": "ECC_NIST_P256", - }) + }, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "CreateKey", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) keyMeta := createResp["KeyMetadata"].(map[string]any) keyID := keyMeta["KeyId"].(string) - getKeyBody, _ := json.Marshal(map[string]any{"KeyId": keyID}) + getKeyBody, _ := json.Marshal(map[string]any{"KeyId": keyID}, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "GetPublicKey", string(getKeyBody)) require.Equal(t, http.StatusOK, rec.Code) var pubResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pubResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pubResp, jsonx.V1())) assert.NotEmpty(t, pubResp["PublicKey"]) assert.Equal(t, "ECC_NIST_P256", pubResp["KeySpec"]) } @@ -234,12 +235,12 @@ func TestKMSHandlerInvalidSignatureError(t *testing.T) { createBody, _ := json.Marshal(map[string]any{ "KeyUsage": kms.KeyUsageSignVerify, "KeySpec": "RSA_2048", - }) + }, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "CreateKey", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) keyMeta := createResp["KeyMetadata"].(map[string]any) keyID := keyMeta["KeyId"].(string) @@ -250,13 +251,13 @@ func TestKMSHandlerInvalidSignatureError(t *testing.T) { "MessageType": "RAW", "Signature": badSig, "SigningAlgorithm": "RSASSA_PSS_SHA_256", - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "Verify", string(verifyBody)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidSignatureException", errResp["__type"]) } @@ -270,7 +271,7 @@ func TestHandlerEncryptReturnsAlgorithm(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) plaintext := base64.StdEncoding.EncodeToString([]byte("test-plaintext")) @@ -278,6 +279,6 @@ func TestHandlerEncryptReturnsAlgorithm(t *testing.T) { require.Equal(t, http.StatusOK, encRec.Code) var encOut map[string]any - require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut)) + require.NoError(t, json.Unmarshal(encRec.Body.Bytes(), &encOut, jsonx.V1())) assert.Equal(t, "SYMMETRIC_DEFAULT", encOut["EncryptionAlgorithm"]) } diff --git a/services/kms/handler_custom_key_stores.go b/services/kms/handler_custom_key_stores.go index b82bb73e6f..c043e2ba79 100644 --- a/services/kms/handler_custom_key_stores.go +++ b/services/kms/handler_custom_key_stores.go @@ -2,7 +2,9 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildCustomKeyStoreActions returns dispatch entries for custom key store and ECDH operations. @@ -10,7 +12,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { return map[string]kmsActionFn{ "CreateCustomKeyStore": func(ctx context.Context, b []byte) (any, error) { var input CreateCustomKeyStoreInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -18,7 +20,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { }, "DeleteCustomKeyStore": func(ctx context.Context, b []byte) (any, error) { var input DeleteCustomKeyStoreInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -26,7 +28,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { }, "DescribeCustomKeyStores": func(ctx context.Context, b []byte) (any, error) { var input DescribeCustomKeyStoresInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -34,7 +36,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { }, "ConnectCustomKeyStore": func(ctx context.Context, b []byte) (any, error) { var input ConnectCustomKeyStoreInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -42,7 +44,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { }, "DisconnectCustomKeyStore": func(ctx context.Context, b []byte) (any, error) { var input DisconnectCustomKeyStoreInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -50,7 +52,7 @@ func (h *Handler) buildCustomKeyStoreActions() map[string]kmsActionFn { }, opDeriveSharedSecret: func(ctx context.Context, b []byte) (any, error) { var input DeriveSharedSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_custom_key_stores_test.go b/services/kms/handler_custom_key_stores_test.go index a570c0b2b0..96c22eba16 100644 --- a/services/kms/handler_custom_key_stores_test.go +++ b/services/kms/handler_custom_key_stores_test.go @@ -3,7 +3,7 @@ package kms_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -31,7 +32,7 @@ func TestHandler_XKS_CreateDescribeViaHTTP(t *testing.T) { var createResp struct { CustomKeyStoreID string `json:"CustomKeyStoreId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotEmpty(t, createResp.CustomKeyStoreID) // Describe the XKS store @@ -45,7 +46,7 @@ func TestHandler_XKS_CreateDescribeViaHTTP(t *testing.T) { ConnectionState string `json:"ConnectionState"` } `json:"CustomKeyStores"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) require.Len(t, descResp.CustomKeyStores, 1) assert.Equal(t, "EXTERNAL_KEY_STORE", descResp.CustomKeyStores[0].CustomKeyStoreType) assert.Equal(t, kms.ConnectionStateDisconnected, descResp.CustomKeyStores[0].ConnectionState) @@ -129,7 +130,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.CustomKeyStoreID) }, }, @@ -150,7 +151,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.DescribeCustomKeyStoresOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.CustomKeyStores, 1) }, }, @@ -199,7 +200,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.GenerateRandomOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Plaintext, 32) }, }, @@ -223,7 +224,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.GenerateMacOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.Mac) }, }, @@ -241,7 +242,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.GenerateDataKeyPairOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.PublicKey) assert.NotEmpty(t, out.PrivateKeyPlaintext) }, @@ -260,7 +261,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.GenerateDataKeyPairWithoutPlaintextOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.PublicKey) assert.NotEmpty(t, out.PrivateKeyCiphertextBlob) }, @@ -282,7 +283,7 @@ func TestHandlerDispatchesCustomKeyStoreAndCryptoOps(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.DeriveSharedSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.SharedSecret) }, }, @@ -349,7 +350,7 @@ func TestHandlerResetClearsCustomKeyStores(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out kms.DescribeCustomKeyStoresOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.CustomKeyStores) } @@ -365,21 +366,21 @@ func TestCustomKeyStoreHandler_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut kms.CreateCustomKeyStoreOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) storeID := createOut.CustomKeyStoreID // Connect via HTTP. - connectBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}) + connectBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}, jsonx.V1()) rec = postKMSOp(t, h, "ConnectCustomKeyStore", string(connectBody)) require.Equal(t, http.StatusOK, rec.Code) // Describe via HTTP – should be CONNECTED. - descBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}) + descBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}, jsonx.V1()) rec = postKMSOp(t, h, "DescribeCustomKeyStores", string(descBody)) require.Equal(t, http.StatusOK, rec.Code) var descOut kms.DescribeCustomKeyStoresOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descOut, jsonx.V1())) require.Len(t, descOut.CustomKeyStores, 1) assert.Equal(t, kms.ConnectionStateConnected, descOut.CustomKeyStores[0].ConnectionState) @@ -388,7 +389,7 @@ func TestCustomKeyStoreHandler_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) // Delete via HTTP. - deleteBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}) + deleteBody, _ := json.Marshal(map[string]string{"CustomKeyStoreId": storeID}, jsonx.V1()) rec = postKMSOp(t, h, "DeleteCustomKeyStore", string(deleteBody)) require.Equal(t, http.StatusOK, rec.Code) } diff --git a/services/kms/handler_generate_and_mac.go b/services/kms/handler_generate_and_mac.go index 4908a92a5f..b596e2a7e7 100644 --- a/services/kms/handler_generate_and_mac.go +++ b/services/kms/handler_generate_and_mac.go @@ -2,7 +2,9 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildGenerateAndMacActions returns dispatch entries for data key pair, MAC, and random operations. @@ -10,7 +12,7 @@ func (h *Handler) buildGenerateAndMacActions() map[string]kmsActionFn { return map[string]kmsActionFn{ opGenerateDataKeyPair: func(ctx context.Context, b []byte) (any, error) { var input GenerateDataKeyPairInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -18,7 +20,7 @@ func (h *Handler) buildGenerateAndMacActions() map[string]kmsActionFn { }, opGenerateDataKeyPairWithoutPlaintext: func(ctx context.Context, b []byte) (any, error) { var input GenerateDataKeyPairWithoutPlaintextInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -26,7 +28,7 @@ func (h *Handler) buildGenerateAndMacActions() map[string]kmsActionFn { }, opGenerateMac: func(ctx context.Context, b []byte) (any, error) { var input GenerateMacInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -34,7 +36,7 @@ func (h *Handler) buildGenerateAndMacActions() map[string]kmsActionFn { }, "GenerateRandom": func(ctx context.Context, b []byte) (any, error) { var input GenerateRandomInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -42,7 +44,7 @@ func (h *Handler) buildGenerateAndMacActions() map[string]kmsActionFn { }, opVerifyMac: func(ctx context.Context, b []byte) (any, error) { var input VerifyMacInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_generate_and_mac_test.go b/services/kms/handler_generate_and_mac_test.go index fa11021028..423ce7d907 100644 --- a/services/kms/handler_generate_and_mac_test.go +++ b/services/kms/handler_generate_and_mac_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "strings" @@ -38,12 +39,12 @@ func TestVerifyMac_Handler(t *testing.T) { "MacAlgorithm": "HMAC_SHA_256", "Message": msg, "Mac": macOut.Mac, - }) + }, jsonx.V1()) rec := sendKMSOp(t, h, "VerifyMac", string(bodyBytes)) require.Equal(t, http.StatusOK, rec.Code) var verOut kms.VerifyMacOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verOut, jsonx.V1())) assert.True(t, verOut.MacValid) } @@ -63,10 +64,10 @@ func TestKMSHandlerGenerateDataKey(t *testing.T) { require.NoError(t, h.Handler()(e.NewContext(createReq, createRec))) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut.KeyMetadata.KeyID - body, _ := json.Marshal(map[string]string{"KeyID": keyID, "KeySpec": "AES_256"}) + body, _ := json.Marshal(map[string]string{"KeyID": keyID, "KeySpec": "AES_256"}, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(body))) req.Header.Set("X-Amz-Target", "TrentService.GenerateDataKey") rec := httptest.NewRecorder() @@ -74,7 +75,7 @@ func TestKMSHandlerGenerateDataKey(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out kms.GenerateDataKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Plaintext, 32) assert.NotEmpty(t, out.CiphertextBlob) } @@ -90,11 +91,11 @@ func TestKMSGenerateDataKeyWithoutPlaintext(t *testing.T) { require.NoError(t, err) keyID := keyOut.KeyMetadata.KeyID - body, _ := json.Marshal(map[string]string{"KeyId": keyID, "KeySpec": "AES_256"}) + body, _ := json.Marshal(map[string]string{"KeyId": keyID, "KeySpec": "AES_256"}, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "GenerateDataKeyWithoutPlaintext", string(body)) assert.Equal(t, http.StatusOK, rec.Code) var out kms.GenerateDataKeyWithoutPlaintextOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.CiphertextBlob) assert.Equal(t, keyOut.KeyMetadata.Arn, out.KeyID) } @@ -129,7 +130,7 @@ func TestKMS_InvalidKeySpec_Returns400UnsupportedOperationException(t *testing.T body, err := json.Marshal(map[string]string{ "KeyId": wrapKeyID, "KeyPairSpec": "BOGUS_SPEC", - }) + }, jsonx.V1()) require.NoError(t, err) return "TrentService.GenerateDataKeyPair", string(body) @@ -165,7 +166,7 @@ func TestKMS_InvalidKeySpec_Returns400UnsupportedOperationException(t *testing.T assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnsupportedOperationException", errResp.Type) }) } diff --git a/services/kms/handler_grants_policies.go b/services/kms/handler_grants_policies.go index 528f8b5531..b88bf70a7c 100644 --- a/services/kms/handler_grants_policies.go +++ b/services/kms/handler_grants_policies.go @@ -2,8 +2,10 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildGrantPolicyActions returns dispatch entries for grant and key policy operations. @@ -11,7 +13,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { return map[string]kmsActionFn{ opCreateGrant: func(ctx context.Context, b []byte) (any, error) { var input CreateGrantInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -19,7 +21,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { }, "ListGrants": func(ctx context.Context, b []byte) (any, error) { var input ListGrantsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -27,7 +29,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { }, "RevokeGrant": func(ctx context.Context, b []byte) (any, error) { var input RevokeGrantInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -35,7 +37,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { }, opRetireGrant: func(ctx context.Context, b []byte) (any, error) { var input RetireGrantInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -43,7 +45,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { }, "ListRetirableGrants": func(ctx context.Context, b []byte) (any, error) { var input ListRetirableGrantsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -59,7 +61,7 @@ func (h *Handler) buildGrantPolicyActions() map[string]kmsActionFn { // function's cognitive complexity under the gocognit limit. func (h *Handler) handlePutKeyPolicy(ctx context.Context, b []byte) (any, error) { var input PutKeyPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -85,7 +87,7 @@ func (h *Handler) handlePutKeyPolicy(ctx context.Context, b []byte) (any, error) func (h *Handler) handleGetKeyPolicy(ctx context.Context, b []byte) (any, error) { var input GetKeyPolicyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_grants_policies_test.go b/services/kms/handler_grants_policies_test.go index 3823cc5ef2..69f1f5f2dc 100644 --- a/services/kms/handler_grants_policies_test.go +++ b/services/kms/handler_grants_policies_test.go @@ -2,7 +2,8 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -34,7 +36,7 @@ func TestHandler_CreateGrant_WithRetiringPrincipal_ViaHTTP(t *testing.T) { GrantID string `json:"GrantId"` GrantToken string `json:"GrantToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.GrantID) assert.NotEmpty(t, resp.GrantToken) } @@ -57,25 +59,25 @@ func TestHandler_CreateGrant_NameTooLong_ViaHTTP(t *testing.T) { "GranteePrincipal": "arn:aws:iam::123456789012:role/grantee", "Operations": []string{"Encrypt"}, "Name": strings.Repeat("x", 257), - }) + }, jsonx.V1()) require.NoError(t, err) rec := b2postKMSOp(t, h, "CreateGrant", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "LimitExceededException", errResp.Type) assert.NotEqual(t, "ValidationException", errResp.Type) - listBody, err := json.Marshal(map[string]string{"KeyId": keyID}) + listBody, err := json.Marshal(map[string]string{"KeyId": keyID}, jsonx.V1()) require.NoError(t, err) listRec := b2postKMSOp(t, h, "ListGrants", string(listBody)) assert.Equal(t, http.StatusOK, listRec.Code) var listOut kms.ListGrantsOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut.Grants, "rejected CreateGrant must not create a grant") } @@ -102,14 +104,14 @@ func TestHandler_PutKeyPolicy_InvalidPolicyName_ViaHTTP(t *testing.T) { "KeyId": keyID, "PolicyName": "custom", "Policy": `{"Version":"2012-10-17","Statement":[]}`, - }) + }, jsonx.V1()) require.NoError(t, err) rec := b2postKMSOp(t, h, "PutKeyPolicy", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnsupportedOperationException", errResp.Type) assert.NotEqual(t, "ValidationException", errResp.Type) @@ -141,7 +143,7 @@ func TestKMSGrantOperations(t *testing.T) { rec := doKMSHTTPRequest(t, h, "CreateGrant", createBody) assert.Equal(t, http.StatusOK, rec.Code) var createOut kms.CreateGrantOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut.GrantID) assert.NotEmpty(t, createOut.GrantToken) @@ -150,7 +152,7 @@ func TestKMSGrantOperations(t *testing.T) { rec = doKMSHTTPRequest(t, h, "ListGrants", listBody) assert.Equal(t, http.StatusOK, rec.Code) var listOut kms.ListGrantsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Grants, 1) assert.Equal(t, createOut.GrantID, listOut.Grants[0].GrantID) @@ -161,7 +163,7 @@ func TestKMSGrantOperations(t *testing.T) { // ListGrants after revoke — should be empty rec = doKMSHTTPRequest(t, h, "ListGrants", listBody) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut.Grants) } @@ -181,15 +183,15 @@ func TestKMSKeyPolicy(t *testing.T) { "KeyId": keyID, "PolicyName": "default", "Policy": policy, - }) + }, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "PutKeyPolicy", string(putBody)) assert.Equal(t, http.StatusOK, rec.Code) - getBody, _ := json.Marshal(map[string]string{"KeyId": keyID, "PolicyName": "default"}) + getBody, _ := json.Marshal(map[string]string{"KeyId": keyID, "PolicyName": "default"}, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "GetKeyPolicy", string(getBody)) assert.Equal(t, http.StatusOK, rec.Code) var getOut kms.GetKeyPolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, policy, getOut.Policy) } @@ -211,30 +213,30 @@ func TestKMSRetireGrant(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createOut kms.CreateGrantOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) grantToken := createOut.GrantToken // ListRetirableGrants for the retiring principal listBody, _ := json.Marshal(map[string]string{ "RetiringPrincipal": "arn:aws:iam::000000000000:role/retire-role", - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "ListRetirableGrants", string(listBody)) assert.Equal(t, http.StatusOK, rec.Code) var listOut kms.ListGrantsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Grants, 1) assert.Equal(t, createOut.GrantID, listOut.Grants[0].GrantID) // RetireGrant using grant token - retireBody, _ := json.Marshal(map[string]string{"GrantToken": grantToken}) + retireBody, _ := json.Marshal(map[string]string{"GrantToken": grantToken}, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "RetireGrant", string(retireBody)) assert.Equal(t, http.StatusOK, rec.Code) // ListGrants should now be empty listGrantsBody := `{"KeyId":"` + keyID + `"}` rec = doKMSHTTPRequest(t, h, "ListGrants", listGrantsBody) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut.Grants) } @@ -285,9 +287,9 @@ func TestListGrants_RawBody_NoGrantTokenLeak(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw struct { - Grants []map[string]json.RawMessage `json:"Grants"` + Grants []map[string]jsontext.Value `json:"Grants"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.Grants, 1) _, hasToken := raw.Grants[0]["GrantToken"] diff --git a/services/kms/handler_keys.go b/services/kms/handler_keys.go index 93a444e868..d55b652387 100644 --- a/services/kms/handler_keys.go +++ b/services/kms/handler_keys.go @@ -2,8 +2,9 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -57,7 +58,7 @@ func (h *Handler) buildKeyLifecycleActions() map[string]kmsActionFn { // backend whenever the caller supplied a malformed tag. func (h *Handler) createKeyAction(ctx context.Context, b []byte) (any, error) { var input CreateKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_keys_test.go b/services/kms/handler_keys_test.go index 02e4071552..62ff825d9b 100644 --- a/services/kms/handler_keys_test.go +++ b/services/kms/handler_keys_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "log/slog" @@ -30,14 +31,14 @@ func TestHandler_CreateKey_DescriptionTooLong_ViaHTTP(t *testing.T) { b := h.Backend.(*kms.InMemoryBackend) longDescription := strings.Repeat("x", 8193) - body, err := json.Marshal(map[string]string{"Description": longDescription}) + body, err := json.Marshal(map[string]string{"Description": longDescription}, jsonx.V1()) require.NoError(t, err) rec := b2postKMSOp(t, h, "CreateKey", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "LimitExceededException", errResp.Type) assert.NotEqual(t, "ValidationException", errResp.Type) @@ -62,7 +63,7 @@ func TestHandler_CreateKey_KeySpecKeyUsageMismatch_ViaHTTP(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnsupportedOperationException", errResp.Type) assert.NotEqual(t, "InvalidKeyUsageException", errResp.Type) @@ -91,7 +92,7 @@ func TestHandler_CreateKey_HMACMultiRegion_ViaHTTP(t *testing.T) { MultiRegion bool `json:"MultiRegion"` } `json:"KeyMetadata"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "HMAC_256", out.KeyMetadata.KeySpec) assert.Equal(t, "GENERATE_VERIFY_MAC", out.KeyMetadata.KeyUsage) assert.True(t, out.KeyMetadata.MultiRegion) @@ -112,7 +113,7 @@ func TestHandler_ScheduleKeyDeletion_ViaHTTP(t *testing.T) { var resp struct { KeyState string `json:"KeyState"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingDeletion, resp.KeyState) } @@ -137,7 +138,7 @@ func TestHandler_CancelKeyDeletion_ViaHTTP(t *testing.T) { var resp struct { KeyID string `json:"KeyId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, keyID, resp.KeyID) desc, err := b.DescribeKey(context.Background(), &kms.DescribeKeyInput{KeyID: keyID}) @@ -180,7 +181,7 @@ func TestKMSHandler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.KeyMetadata.KeyID) }, }, @@ -192,7 +193,7 @@ func TestKMSHandler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnknownOperationException", errResp.Type) }, }, @@ -210,7 +211,7 @@ func TestKMSHandler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.Contains(t, ops, "CreateKey") }, }, @@ -222,7 +223,7 @@ func TestKMSHandler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "NotFoundException", errResp.Type) }, }, @@ -240,7 +241,7 @@ func TestKMSHandler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out kms.ListKeysOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Keys, 1) }, }, @@ -394,7 +395,7 @@ func TestKMSHandlerDisableEnableKey(t *testing.T) { rec = doKMSReqLocal(t, h, "ScheduleKeyDeletion", `{"KeyId":"`+keyID+`","PendingWindowInDays":7}`) assert.Equal(t, http.StatusOK, rec.Code) var schedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingDeletion, schedResp["KeyState"]) rec = doKMSReqLocal(t, h, "CancelKeyDeletion", body) @@ -411,7 +412,7 @@ func TestHandlerCancelKeyDeletionReturnsBody(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) sendKMSOp(t, h, "ScheduleKeyDeletion", `{"KeyId":"`+keyID+`","PendingWindowInDays":7}`) @@ -420,7 +421,7 @@ func TestHandlerCancelKeyDeletionReturnsBody(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, keyID, out["KeyId"]) assert.NotContains(t, out, "KeyState", "real CancelKeyDeletionOutput has only KeyId") } @@ -435,7 +436,7 @@ func TestHandlerUpdateKeyDescriptionMaxLengthRejected(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) longDesc := strings.Repeat("x", 8193) diff --git a/services/kms/handler_replication_maintenance.go b/services/kms/handler_replication_maintenance.go index 8f99e45d6a..fcd42a629a 100644 --- a/services/kms/handler_replication_maintenance.go +++ b/services/kms/handler_replication_maintenance.go @@ -2,8 +2,10 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // replicateKeyAction handles ReplicateKey dispatch, including tag validation and @@ -13,7 +15,7 @@ import ( // leaving a real, untagged replica key behind. func (h *Handler) replicateKeyAction(ctx context.Context, b []byte) (any, error) { var input ReplicateKeyInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -66,7 +68,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn return map[string]kmsActionFn{ "GetParametersForImport": func(ctx context.Context, b []byte) (any, error) { var input GetParametersForImportInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -74,7 +76,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn }, "ListKeyPolicies": func(ctx context.Context, b []byte) (any, error) { var input ListKeyPoliciesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -82,7 +84,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn }, "ListKeyRotations": func(ctx context.Context, b []byte) (any, error) { var input ListKeyRotationsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -91,7 +93,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn "ReplicateKey": h.replicateKeyAction, "RotateKeyOnDemand": func(ctx context.Context, b []byte) (any, error) { var input RotateKeyOnDemandInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -99,7 +101,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn }, "UpdateCustomKeyStore": func(ctx context.Context, b []byte) (any, error) { var input UpdateCustomKeyStoreInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -107,7 +109,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn }, "UpdateKeyDescription": func(ctx context.Context, b []byte) (any, error) { var input UpdateKeyDescriptionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -115,7 +117,7 @@ func (h *Handler) buildReplicationAndMaintenanceActions() map[string]kmsActionFn }, "UpdatePrimaryRegion": func(ctx context.Context, b []byte) (any, error) { var input UpdatePrimaryRegionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_replication_maintenance_test.go b/services/kms/handler_replication_maintenance_test.go index f593d5af48..1573e0d151 100644 --- a/services/kms/handler_replication_maintenance_test.go +++ b/services/kms/handler_replication_maintenance_test.go @@ -3,7 +3,7 @@ package kms_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "strings" @@ -47,7 +48,7 @@ func TestHandler_GetParametersForImport_ViaHTTP(t *testing.T) { KeyID string `json:"KeyId"` ParametersValidTo float64 `json:"ParametersValidTo"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, keyID, resp.KeyID) assert.Greater(t, resp.ParametersValidTo, float64(0)) } @@ -98,7 +99,7 @@ func TestHandler_ImportKeyMaterial_WireFieldName_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut kms.DescribeKeyOutput - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, kms.KeyStateEnabled, descOut.KeyMetadata.KeyState) } @@ -110,7 +111,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { h := kms.NewHandler(kms.NewInMemoryBackend()) // Create EXTERNAL-origin key. - createBody, err := json.Marshal(kms.CreateKeyInput{Origin: kms.KeyOriginExternal}) + createBody, err := json.Marshal(kms.CreateKeyInput{Origin: kms.KeyOriginExternal}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(createBody)) req.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -123,7 +124,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingImport, createOut.KeyMetadata.KeyState) // Import key material. @@ -135,7 +136,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { importBody, err := json.Marshal(kms.ImportKeyMaterialInput{ KeyID: createOut.KeyMetadata.KeyID, KeyMaterial: mat, - }) + }, jsonx.V1()) require.NoError(t, err) importReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(importBody)) importReq.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -147,7 +148,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { assert.Equal(t, http.StatusOK, importRec.Code) // Describe should show Enabled. - descBody, err := json.Marshal(kms.DescribeKeyInput{KeyID: createOut.KeyMetadata.KeyID}) + descBody, err := json.Marshal(kms.DescribeKeyInput{KeyID: createOut.KeyMetadata.KeyID}, jsonx.V1()) require.NoError(t, err) descReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(descBody)) descReq.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -159,11 +160,11 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut kms.DescribeKeyOutput - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, kms.KeyStateEnabled, descOut.KeyMetadata.KeyState) // DeleteImportedKeyMaterial. - delBody, err := json.Marshal(kms.DeleteImportedKeyMaterialInput{KeyID: createOut.KeyMetadata.KeyID}) + delBody, err := json.Marshal(kms.DeleteImportedKeyMaterialInput{KeyID: createOut.KeyMetadata.KeyID}, jsonx.V1()) require.NoError(t, err) delReq := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(delBody)) delReq.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -175,7 +176,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { assert.Equal(t, http.StatusOK, delRec.Code) // Key should be back to PendingImport. - descBody2, err := json.Marshal(kms.DescribeKeyInput{KeyID: createOut.KeyMetadata.KeyID}) + descBody2, err := json.Marshal(kms.DescribeKeyInput{KeyID: createOut.KeyMetadata.KeyID}, jsonx.V1()) require.NoError(t, err) descReq2 := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(descBody2)) descReq2.Header.Set("Content-Type", "application/x-amz-json-1.1") @@ -187,7 +188,7 @@ func TestKMSHandlerImportKeyMaterial(t *testing.T) { require.Equal(t, http.StatusOK, descRec2.Code) var descOut2 kms.DescribeKeyOutput - require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(descRec2.Body.Bytes(), &descOut2, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingImport, descOut2.KeyMetadata.KeyState) } @@ -270,7 +271,7 @@ func TestKMSHandlerNewMaintenanceOps(t *testing.T) { } var payload map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload, jsonx.V1())) _, ok := payload[tt.wantField] assert.True(t, ok) }) @@ -316,7 +317,7 @@ func TestKMS_ErrorClassification_MissingTableEntries(t *testing.T) { ValidTo: pastTS, })) - body, err := json.Marshal(kms.EncryptInput{KeyID: keyID, Plaintext: []byte("test")}) + body, err := json.Marshal(kms.EncryptInput{KeyID: keyID, Plaintext: []byte("test")}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(body))) @@ -327,7 +328,7 @@ func TestKMS_ErrorClassification_MissingTableEntries(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) }) @@ -349,7 +350,7 @@ func TestKMS_ErrorClassification_MissingTableEntries(t *testing.T) { e := echo.New() h := kms.NewHandler(restored) - body, err := json.Marshal(kms.EncryptInput{KeyID: keyID, Plaintext: []byte("test")}) + body, err := json.Marshal(kms.EncryptInput{KeyID: keyID, Plaintext: []byte("test")}, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(body))) @@ -360,7 +361,7 @@ func TestKMS_ErrorClassification_MissingTableEntries(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KeyUnavailableException", errResp.Type) }) } @@ -376,7 +377,7 @@ func TestHandlerReplicateKeyRequiresMultiRegion(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) rec := sendKMSOp(t, h, "ReplicateKey", `{"KeyId":"`+keyID+`","ReplicaRegion":"us-west-2"}`) @@ -393,7 +394,7 @@ func TestHandlerReplicateKeyCopiesTags(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) tagRec := sendKMSOp(t, h, "TagResource", `{"KeyId":"`+keyID+`","Tags":[{"TagKey":"env","TagValue":"prod"}]}`) @@ -403,14 +404,14 @@ func TestHandlerReplicateKeyCopiesTags(t *testing.T) { require.Equal(t, http.StatusOK, repRec.Code) var repOut map[string]any - require.NoError(t, json.Unmarshal(repRec.Body.Bytes(), &repOut)) + require.NoError(t, json.Unmarshal(repRec.Body.Bytes(), &repOut, jsonx.V1())) replicaID := repOut["ReplicaKeyMetadata"].(map[string]any)["KeyId"].(string) tagListRec := sendKMSOp(t, h, "ListResourceTags", `{"KeyId":"`+replicaID+`"}`) require.Equal(t, http.StatusOK, tagListRec.Code) var tagListOut map[string]any - require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut)) + require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut, jsonx.V1())) tags := tagListOut["Tags"].([]any) require.NotEmpty(t, tags) @@ -435,7 +436,7 @@ func TestHandlerUpdatePrimaryRegionViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) // Replicate to eu-central-1 first — UpdatePrimaryRegion requires an actual replica. @@ -456,7 +457,7 @@ func TestHandlerReplicateKeyWithInputTags(t *testing.T) { require.Equal(t, http.StatusOK, keyRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(keyRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) // Replicate with explicit tags that should overlay the source tags. @@ -465,14 +466,14 @@ func TestHandlerReplicateKeyWithInputTags(t *testing.T) { require.Equal(t, http.StatusOK, repRec.Code) var repOut map[string]any - require.NoError(t, json.Unmarshal(repRec.Body.Bytes(), &repOut)) + require.NoError(t, json.Unmarshal(repRec.Body.Bytes(), &repOut, jsonx.V1())) replicaID := repOut["ReplicaKeyMetadata"].(map[string]any)["KeyId"].(string) tagListRec := sendKMSOp(t, h, "ListResourceTags", `{"KeyId":"`+replicaID+`"}`) require.Equal(t, http.StatusOK, tagListRec.Code) var tagListOut map[string]any - require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut)) + require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut, jsonx.V1())) tags := tagListOut["Tags"].([]any) keys := make(map[string]string) diff --git a/services/kms/handler_tags.go b/services/kms/handler_tags.go index 713fd4aae2..a0e06cf602 100644 --- a/services/kms/handler_tags.go +++ b/services/kms/handler_tags.go @@ -2,12 +2,13 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -147,7 +148,7 @@ func (h *Handler) getTags(resourceID string) map[string]string { // listResourceTags handles the ListResourceTags operation. func (h *Handler) listResourceTags(ctx context.Context, b []byte) (any, error) { var input listResourceTagsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -202,7 +203,7 @@ func paginateTagList(tagList []kmsTagEntry, marker string, limit *int32) *listRe // tagResource handles the TagResource operation, validating key existence and tag count. func (h *Handler) tagResource(ctx context.Context, b []byte) (any, error) { var input tagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -291,7 +292,7 @@ func (h *Handler) validateTagCount(keyID string, newTags map[string]string) erro // untagResource handles the UntagResource operation. func (h *Handler) untagResource(ctx context.Context, b []byte) (any, error) { var input untagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/kms/handler_tags_persistence_test.go b/services/kms/handler_tags_persistence_test.go index a303e274d8..16668aa475 100644 --- a/services/kms/handler_tags_persistence_test.go +++ b/services/kms/handler_tags_persistence_test.go @@ -16,12 +16,13 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -95,7 +96,7 @@ func TestHandlerRestore_LegacyBackendOnlySnapshot(t *testing.T) { require.NotEmpty(t, legacy) var probe map[string]any - require.NoError(t, json.Unmarshal(legacy, &probe)) + require.NoError(t, json.Unmarshal(legacy, &probe, jsonx.V1())) _, hasHandlerFormat := probe["handlerFormat"] require.False(t, hasHandlerFormat, "precondition: a raw backend snapshot has no handlerFormat marker") diff --git a/services/kms/handler_tags_test.go b/services/kms/handler_tags_test.go index be7596b6c7..3585a15dd1 100644 --- a/services/kms/handler_tags_test.go +++ b/services/kms/handler_tags_test.go @@ -3,7 +3,7 @@ package kms_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "strings" @@ -29,7 +30,7 @@ func TestTagResource_PendingDeletion_Rejected(t *testing.T) { body, err := json.Marshal(map[string]any{ "KeyId": keyID, "Tags": []map[string]string{{"TagKey": "env", "TagValue": "test"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doKMSRequest(t, h, "TagResource", string(body)) @@ -38,7 +39,7 @@ func TestTagResource_PendingDeletion_Rejected(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) } @@ -69,7 +70,7 @@ func TestTagResource_EnabledAndDisabled_Accepted(t *testing.T) { body, merr := json.Marshal(map[string]any{ "KeyId": keyID, "Tags": []map[string]string{{"TagKey": "env", "TagValue": "test"}}, - }) + }, jsonx.V1()) require.NoError(t, merr) rec := doKMSRequest(t, h, "TagResource", string(body)) @@ -90,7 +91,7 @@ func TestUntagResource_PendingDeletion_Rejected(t *testing.T) { body, err := json.Marshal(map[string]any{ "KeyId": keyID, "TagKeys": []string{"env"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := doKMSRequest(t, h, "UntagResource", string(body)) @@ -99,7 +100,7 @@ func TestUntagResource_PendingDeletion_Rejected(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "KMSInvalidStateException", errResp.Type) } @@ -130,7 +131,7 @@ func TestUntagResource_EnabledAndDisabled_Accepted(t *testing.T) { body, merr := json.Marshal(map[string]any{ "KeyId": keyID, "TagKeys": []string{"nonexistent-key"}, - }) + }, jsonx.V1()) require.NoError(t, merr) rec := doKMSRequest(t, h, "UntagResource", string(body)) @@ -219,7 +220,7 @@ func TestTagResource_AndListResourceTags_Roundtrip(t *testing.T) { TagValue string `json:"TagValue"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp, jsonx.V1())) assert.Len(t, tagsResp.Tags, 2) } @@ -248,7 +249,7 @@ func TestUntagResource_RemovesSpecifiedTags(t *testing.T) { TagKey string `json:"TagKey"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp, jsonx.V1())) keys := make([]string, 0, len(tagsResp.Tags)) for _, t := range tagsResp.Tags { keys = append(keys, t.TagKey) @@ -318,7 +319,7 @@ func TestListResourceTags_Pagination(t *testing.T) { Tags []any `json:"Tags"` Truncated bool `json:"Truncated"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Tags, 3) assert.True(t, resp.Truncated) } @@ -353,12 +354,12 @@ func TestKMSTagOperations(t *testing.T) { keyID := keyOut.KeyMetadata.KeyID // ListResourceTags on a key with no tags - listBody, _ := json.Marshal(map[string]string{"KeyId": keyID}) + listBody, _ := json.Marshal(map[string]string{"KeyId": keyID}, jsonx.V1()) rec := doKMSHTTPRequest(t, h, "ListResourceTags", string(listBody)) assert.Equal(t, http.StatusOK, rec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) assert.Empty(t, listOut["Tags"]) assert.Equal(t, false, listOut["Truncated"]) @@ -369,7 +370,7 @@ func TestKMSTagOperations(t *testing.T) { {"TagKey": "env", "TagValue": "prod"}, {"TagKey": "team", "TagValue": "backend"}, }, - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "TagResource", string(tagBody)) assert.Equal(t, http.StatusOK, rec.Code) @@ -377,7 +378,7 @@ func TestKMSTagOperations(t *testing.T) { rec = doKMSHTTPRequest(t, h, "ListResourceTags", string(listBody)) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) tags, ok := listOut["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 2) @@ -386,13 +387,13 @@ func TestKMSTagOperations(t *testing.T) { untagBody, _ := json.Marshal(map[string]any{ "KeyId": keyID, "TagKeys": []string{"team"}, - }) + }, jsonx.V1()) rec = doKMSHTTPRequest(t, h, "UntagResource", string(untagBody)) assert.Equal(t, http.StatusOK, rec.Code) // ListResourceTags should now return 1 tag rec = doKMSHTTPRequest(t, h, "ListResourceTags", string(listBody)) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) tags, ok = listOut["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 1) @@ -536,7 +537,7 @@ func TestKMSHandlerListResourceTagsPagination(t *testing.T) { Tags []any `json:"Tags"` Truncated bool `json:"Truncated"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Tags, tt.wantCount) assert.Equal(t, tt.wantTruncated, out.Truncated) @@ -590,7 +591,7 @@ func TestHandlerTagResourceMaxTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) // Build a tag list with 51 unique entries. @@ -622,14 +623,14 @@ func TestHandlerCreateKeyWithTagsApplied(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut["KeyMetadata"].(map[string]any)["KeyId"].(string) tagListRec := sendKMSOp(t, h, "ListResourceTags", `{"KeyId":"`+keyID+`"}`) require.Equal(t, http.StatusOK, tagListRec.Code) var tagListOut map[string]any - require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut)) + require.NoError(t, json.Unmarshal(tagListRec.Body.Bytes(), &tagListOut, jsonx.V1())) tags := tagListOut["Tags"].([]any) require.NotEmpty(t, tags) diff --git a/services/kms/handler_test.go b/services/kms/handler_test.go index 7cbb043b55..71a13bc5a1 100644 --- a/services/kms/handler_test.go +++ b/services/kms/handler_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -68,7 +69,10 @@ func TestErrValidation_Mapping(t *testing.T) { if err != nil { return `{}` } - body, _ := json.Marshal(map[string]any{"KeyId": key.KeyMetadata.KeyID, "PendingWindowInDays": 3}) + body, _ := json.Marshal( + map[string]any{"KeyId": key.KeyMetadata.KeyID, "PendingWindowInDays": 3}, + jsonx.V1(), + ) return string(body) }, diff --git a/services/kms/helpers_test.go b/services/kms/helpers_test.go index 3deba98564..da3bd5b120 100644 --- a/services/kms/helpers_test.go +++ b/services/kms/helpers_test.go @@ -3,7 +3,7 @@ package kms_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" "log/slog" @@ -284,7 +285,7 @@ func buildBodyFromResourceID(operation, resourceID string) string { switch operation { case "ConnectCustomKeyStore", "DeleteCustomKeyStore", "DisconnectCustomKeyStore": - body, _ := json.Marshal(map[string]string{"CustomKeyStoreId": resourceID}) + body, _ := json.Marshal(map[string]string{"CustomKeyStoreId": resourceID}, jsonx.V1()) return string(body) case "GenerateMac": @@ -292,21 +293,21 @@ func buildBodyFromResourceID(operation, resourceID string) string { "KeyId": resourceID, "MacAlgorithm": "HMAC_SHA_256", "Message": []byte("test message"), - }) + }, jsonx.V1()) return string(body) case "GenerateDataKeyPair": body, _ := json.Marshal(map[string]any{ "KeyId": resourceID, "KeyPairSpec": "ECC_NIST_P256", - }) + }, jsonx.V1()) return string(body) case "GenerateDataKeyPairWithoutPlaintext": body, _ := json.Marshal(map[string]any{ "KeyId": resourceID, "KeyPairSpec": "ECC_NIST_P256", - }) + }, jsonx.V1()) return string(body) case "DeriveSharedSecret": @@ -323,7 +324,7 @@ func buildBodyFromResourceID(operation, resourceID string) string { "KeyId": resourceID, "KeyAgreementAlgorithm": "ECDH", "PublicKey": pubOut.PublicKey, - }) + }, jsonx.V1()) return string(body) } diff --git a/services/kms/import_error_wiring_test.go b/services/kms/import_error_wiring_test.go index 64e34ff480..566f48bd2c 100644 --- a/services/kms/import_error_wiring_test.go +++ b/services/kms/import_error_wiring_test.go @@ -3,13 +3,14 @@ package kms_test import ( "context" "crypto/rand" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -46,7 +47,7 @@ func TestImportKeyMaterial_RSAUnwrapFailure_IsInvalidCiphertext(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidCiphertextException", errResp.Type) assert.NotEqual(t, "InvalidKeyUsageException", errResp.Type) @@ -81,7 +82,7 @@ func TestImportKeyMaterial_AsymmetricKeySpec_IsUnsupportedOperation(t *testing.T require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnsupportedOperationException", errResp.Type) assert.NotEqual(t, "InvalidKeyUsageException", errResp.Type) @@ -111,7 +112,7 @@ func TestImportKeyMaterial_EmptyMaterial_IsIncorrectKeyMaterial(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "IncorrectKeyMaterialException", errResp.Type) assert.NotEqual(t, "InvalidKeyUsageException", errResp.Type) assert.NotEqual(t, "ValidationException", errResp.Type) @@ -139,7 +140,7 @@ func TestImportKeyMaterial_WrongLength_IsIncorrectKeyMaterial(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "IncorrectKeyMaterialException", errResp.Type) assert.NotEqual(t, "InvalidKeyUsageException", errResp.Type) @@ -175,7 +176,7 @@ func TestDecrypt_WrongKeyUsage_StillInvalidKeyUsageException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidKeyUsageException", errResp.Type) } @@ -198,6 +199,6 @@ func TestVerifyMac_WrongKeyUsage_StillInvalidKeyUsageException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidKeyUsageException", errResp.Type) } diff --git a/services/kms/incorrect_key_test.go b/services/kms/incorrect_key_test.go index 968981f0ac..bde6d5fcd6 100644 --- a/services/kms/incorrect_key_test.go +++ b/services/kms/incorrect_key_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -179,7 +180,7 @@ func TestIncorrectKeyExceptionWireType(t *testing.T) { body, err := json.Marshal(map[string]any{ "CiphertextBlob": encOut.CiphertextBlob, "KeyId": otherKey.KeyMetadata.KeyID, - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(body))) @@ -194,6 +195,6 @@ func TestIncorrectKeyExceptionWireType(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "IncorrectKeyException", resp.Type) } diff --git a/services/kms/isolation_test.go b/services/kms/isolation_test.go index 7d8fd839d5..f1385351fe 100644 --- a/services/kms/isolation_test.go +++ b/services/kms/isolation_test.go @@ -4,7 +4,7 @@ package kms_test // keys and aliases created in one region are not visible in another. import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -48,14 +49,14 @@ func TestRegionIsolation_AliasInTwoRegions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var east1Key kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1Key)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1Key, jsonx.V1())) east1KeyID := east1Key.KeyMetadata.KeyID // Create alias "alias/my-key" in us-east-1. aliasBody, _ := json.Marshal(map[string]string{ "AliasName": "alias/my-key", "TargetKeyId": east1KeyID, - }) + }, jsonx.V1()) rec = kmsCall(t, h, e, "CreateAlias", "us-east-1", string(aliasBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -64,14 +65,14 @@ func TestRegionIsolation_AliasInTwoRegions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var west2Key kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &west2Key)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &west2Key, jsonx.V1())) west2KeyID := west2Key.KeyMetadata.KeyID // Create same alias "alias/my-key" in us-west-2 — should succeed (different region). aliasBody2, _ := json.Marshal(map[string]string{ "AliasName": "alias/my-key", "TargetKeyId": west2KeyID, - }) + }, jsonx.V1()) rec = kmsCall(t, h, e, "CreateAlias", "us-west-2", string(aliasBody2)) assert.Equal(t, http.StatusOK, rec.Code, "same alias name should succeed in a different region") } @@ -102,7 +103,7 @@ func TestRegionIsolation_ListKeys_RegionScoped(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var east1List kms.ListKeysOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1List)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1List, jsonx.V1())) assert.Len(t, east1List.Keys, 3, "us-east-1 should have 3 keys") // ListKeys in us-west-2 should return only 2 keys. @@ -110,7 +111,7 @@ func TestRegionIsolation_ListKeys_RegionScoped(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var west2List kms.ListKeysOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &west2List)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &west2List, jsonx.V1())) assert.Len(t, west2List.Keys, 2, "us-west-2 should have 2 keys") } @@ -129,18 +130,18 @@ func TestRegionIsolation_DescribeKey_CrossRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var east1Key kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1Key)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &east1Key, jsonx.V1())) east1KeyARN := east1Key.KeyMetadata.Arn aliasBody, _ := json.Marshal(map[string]string{ "AliasName": "alias/region-test-key", "TargetKeyId": east1Key.KeyMetadata.KeyID, - }) + }, jsonx.V1()) rec = kmsCall(t, h, e, "CreateAlias", "us-east-1", string(aliasBody)) require.Equal(t, http.StatusOK, rec.Code) // DescribeKey via alias in us-east-1 should succeed. - descBody, _ := json.Marshal(map[string]string{"KeyId": "alias/region-test-key"}) + descBody, _ := json.Marshal(map[string]string{"KeyId": "alias/region-test-key"}, jsonx.V1()) rec = kmsCall(t, h, e, "DescribeKey", "us-east-1", string(descBody)) assert.Equal(t, http.StatusOK, rec.Code, "DescribeKey in same region via alias should succeed") @@ -149,7 +150,7 @@ func TestRegionIsolation_DescribeKey_CrossRegion(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "DescribeKey via alias from wrong region should fail") // DescribeKey via ARN from us-west-2 should succeed — ARN encodes the region. - arnBody, _ := json.Marshal(map[string]string{"KeyId": east1KeyARN}) + arnBody, _ := json.Marshal(map[string]string{"KeyId": east1KeyARN}, jsonx.V1()) rec = kmsCall(t, h, e, "DescribeKey", "us-west-2", string(arnBody)) assert.Equal(t, http.StatusOK, rec.Code, "DescribeKey via ARN should succeed from any region") } @@ -168,12 +169,12 @@ func TestRegionIsolation_AliasNotVisible_CrossRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var keyOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &keyOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &keyOut, jsonx.V1())) aliasBody, _ := json.Marshal(map[string]string{ "AliasName": "alias/east-only", "TargetKeyId": keyOut.KeyMetadata.KeyID, - }) + }, jsonx.V1()) rec = kmsCall(t, h, e, "CreateAlias", "us-east-1", string(aliasBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -182,7 +183,7 @@ func TestRegionIsolation_AliasNotVisible_CrossRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var aliasList kms.ListAliasesOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aliasList)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aliasList, jsonx.V1())) for _, a := range aliasList.Aliases { assert.NotEqual(t, "alias/east-only", a.AliasName, diff --git a/services/kms/key_policies.go b/services/kms/key_policies.go index 7fd86737d4..8630b24c58 100644 --- a/services/kms/key_policies.go +++ b/services/kms/key_policies.go @@ -2,11 +2,12 @@ package kms import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" gopherarn "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutKeyPolicy stores a key policy for a KMS key. @@ -61,7 +62,7 @@ func validKeyPolicyDoc(s string) bool { Statement any `json:"Statement"` Version string `json:"Version"` } - if err := json.Unmarshal([]byte(s), &policyDoc); err != nil { + if err := json.Unmarshal([]byte(s), &policyDoc, jsonx.V1()); err != nil { return false } diff --git a/services/kms/mac_algorithm_wiring_test.go b/services/kms/mac_algorithm_wiring_test.go index bdb0eae4bb..4a6dc75c40 100644 --- a/services/kms/mac_algorithm_wiring_test.go +++ b/services/kms/mac_algorithm_wiring_test.go @@ -2,13 +2,14 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -38,7 +39,7 @@ func TestGenerateMac_WrongAlgorithm_WireType_IsInvalidKeyUsage(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidKeyUsageException", errResp.Type) } @@ -64,6 +65,6 @@ func TestVerifyMac_WrongAlgorithm_WireType_IsInvalidKeyUsage(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp kms.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidKeyUsageException", errResp.Type) } diff --git a/services/kms/persistence.go b/services/kms/persistence.go index 18b81f94b0..84b34eb244 100644 --- a/services/kms/persistence.go +++ b/services/kms/persistence.go @@ -2,10 +2,12 @@ package kms import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -33,7 +35,7 @@ const kmsSnapshotVersion = 1 // keyMaterialsStore/keyMaterialHistoryStore in backend.go), so neither can be // expressed as a store.Table. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Policies map[string]map[string]string `json:"policies"` KeyMaterials map[string]map[string]serializedKeyMaterial `json:"key_materials,omitempty"` KeyMaterialHistory map[string]map[string][]serializedKeyMaterial `json:"key_material_history,omitempty"` @@ -262,7 +264,7 @@ func warnMissingKeyMaterials( // have no registered table for RestoreAll to find -- store.Registry.RestoreAll // only restores tables already known to the registry, silently ignoring any // snapshot entry whose name isn't registered. -func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]json.RawMessage) { +func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]jsontext.Value) { for name := range tables { kind, region, ok := strings.Cut(name, ":") if !ok { @@ -375,7 +377,7 @@ const handlerSnapshotFormat = 1 // `tags` attribute of `aws_kms_key` after a restart. type handlerSnapshot struct { Tags map[string]map[string]string `json:"tags,omitempty"` - Backend json.RawMessage `json:"backend,omitempty"` + Backend jsontext.Value `json:"backend,omitempty"` HandlerFormat int `json:"handlerFormat"` } @@ -469,7 +471,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { Tags: h.snapshotTags(), } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "kms: handler snapshot marshal failed", "error", err) @@ -489,7 +491,7 @@ func (h *Handler) Restore(ctx context.Context, data []byte) error { HandlerFormat int `json:"handlerFormat"` } - if err := json.Unmarshal(data, &peek); err != nil { + if err := json.Unmarshal(data, &peek, jsonx.V1()); err != nil { return fmt.Errorf("kms: restore handler snapshot: %w", err) } @@ -500,7 +502,7 @@ func (h *Handler) Restore(ctx context.Context, data []byte) error { } var snap handlerSnapshot - if err := json.Unmarshal(data, &snap); err != nil { + if err := json.Unmarshal(data, &snap, jsonx.V1()); err != nil { return fmt.Errorf("kms: restore handler snapshot: %w", err) } diff --git a/services/kms/realism_validation_test.go b/services/kms/realism_validation_test.go index 18807bdb38..17ed64270b 100644 --- a/services/kms/realism_validation_test.go +++ b/services/kms/realism_validation_test.go @@ -2,13 +2,15 @@ package kms_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func kmsErr(t *testing.T, body []byte) (string, string) { @@ -19,7 +21,7 @@ func kmsErr(t *testing.T, body []byte) (string, string) { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &e)) + require.NoError(t, json.Unmarshal(body, &e, jsonx.V1())) return e.Type, e.Message } @@ -98,7 +100,10 @@ func TestKMSWire_ErrorRealism(t *testing.T) { } `json:"KeyMetadata"` } - require.NoError(t, json.Unmarshal(doKMSRequest(t, h, "CreateKey", createBody).Body.Bytes(), &created)) + require.NoError( + t, + json.Unmarshal(doKMSRequest(t, h, "CreateKey", createBody).Body.Bytes(), &created, jsonx.V1()), + ) keyID := created.KeyMetadata.KeyID rec := doKMSRequest(t, h, tt.action, tt.body(keyID)) diff --git a/services/kms/replicate_key_policy_test.go b/services/kms/replicate_key_policy_test.go index 16fd765643..ba6c5e9d34 100644 --- a/services/kms/replicate_key_policy_test.go +++ b/services/kms/replicate_key_policy_test.go @@ -21,7 +21,7 @@ package kms_test // regional endpoint would. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -29,6 +29,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -74,7 +75,7 @@ func Test_ReplicateKey_InlinePolicy(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) primaryID := createOut.KeyMetadata.KeyID replicateBody := `{"KeyId":"` + primaryID + `","ReplicaRegion":"us-west-2","Policy":` + @@ -89,7 +90,7 @@ func Test_ReplicateKey_InlinePolicy(t *testing.T) { require.Equal(t, http.StatusOK, replicateRec.Code, replicateRec.Body.String()) var replicateOut kms.ReplicateKeyOutput - require.NoError(t, json.Unmarshal(replicateRec.Body.Bytes(), &replicateOut)) + require.NoError(t, json.Unmarshal(replicateRec.Body.Bytes(), &replicateOut, jsonx.V1())) replicaID := replicateOut.ReplicaKeyMetadata.KeyID require.NotEmpty(t, replicaID) @@ -99,7 +100,7 @@ func Test_ReplicateKey_InlinePolicy(t *testing.T) { require.Equal(t, http.StatusOK, polRec.Code, polRec.Body.String()) var polOut kms.GetKeyPolicyOutput - require.NoError(t, json.Unmarshal(polRec.Body.Bytes(), &polOut)) + require.NoError(t, json.Unmarshal(polRec.Body.Bytes(), &polOut, jsonx.V1())) assert.Equal(t, "default", polOut.PolicyName) if tc.wantPolicy != "" { @@ -116,7 +117,7 @@ func Test_ReplicateKey_InlinePolicy(t *testing.T) { require.Equal(t, http.StatusOK, primaryPolRec.Code) var primaryPolOut kms.GetKeyPolicyOutput - require.NoError(t, json.Unmarshal(primaryPolRec.Body.Bytes(), &primaryPolOut)) + require.NoError(t, json.Unmarshal(primaryPolRec.Body.Bytes(), &primaryPolOut, jsonx.V1())) assert.NotEqual(t, customPolicy, primaryPolOut.Policy) }) } diff --git a/services/kms/terraform_lifecycle_test.go b/services/kms/terraform_lifecycle_test.go index 7875c7ca3b..bf8a68b6ac 100644 --- a/services/kms/terraform_lifecycle_test.go +++ b/services/kms/terraform_lifecycle_test.go @@ -20,7 +20,7 @@ package kms_test // regression (e.g. "KeyId" vs "KeyID") would also be caught, not just a Go-side one. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -65,7 +66,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createOut kms.CreateKeyOutput - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) keyID := createOut.KeyMetadata.KeyID require.NotEmpty(t, keyID) @@ -86,7 +87,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { "repeated DescribeKey must be byte-identical -- any diff here is perpetual terraform plan drift") var desc1 kms.DescribeKeyOutput - require.NoError(t, json.Unmarshal(descRec1.Body.Bytes(), &desc1)) + require.NoError(t, json.Unmarshal(descRec1.Body.Bytes(), &desc1, jsonx.V1())) assert.Equal(t, "terraform-managed key", desc1.KeyMetadata.Description) assert.Equal(t, "SYMMETRIC_DEFAULT", desc1.KeyMetadata.KeySpec) assert.Equal(t, "SYMMETRIC_DEFAULT", desc1.KeyMetadata.CustomerMasterKeySpec, @@ -107,7 +108,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { "that made aws_kms_key poll to a 10-minute timeout") var polOut kms.GetKeyPolicyOutput - require.NoError(t, json.Unmarshal(polRec1.Body.Bytes(), &polOut)) + require.NoError(t, json.Unmarshal(polRec1.Body.Bytes(), &polOut, jsonx.V1())) assert.JSONEq(t, policy, polOut.Policy, "GetKeyPolicy must return exactly the policy supplied to CreateKey") // --- ListResourceTags: must return exactly the tags supplied to CreateKey. --- @@ -119,7 +120,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { "repeated ListResourceTags must be byte-identical") var tagsOut tagsWireOutput - require.NoError(t, json.Unmarshal(tagsRec1.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(tagsRec1.Body.Bytes(), &tagsOut, jsonx.V1())) gotTags := make(map[string]string, len(tagsOut.Tags)) for _, tg := range tagsOut.Tags { @@ -136,7 +137,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { assert.JSONEq(t, rotRec1.Body.String(), rotRec2.Body.String()) var rotOut kms.GetKeyRotationStatusOutput - require.NoError(t, json.Unmarshal(rotRec1.Body.Bytes(), &rotOut)) + require.NoError(t, json.Unmarshal(rotRec1.Body.Bytes(), &rotOut, jsonx.V1())) assert.False(t, rotOut.KeyRotationEnabled, "key rotation must default to disabled") // --- CreateAlias -> ListAliases must show it, resolving TargetKeyId correctly. --- @@ -149,7 +150,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { require.Equal(t, http.StatusOK, listAliasesRec.Code) var aliasesOut kms.ListAliasesOutput - require.NoError(t, json.Unmarshal(listAliasesRec.Body.Bytes(), &aliasesOut)) + require.NoError(t, json.Unmarshal(listAliasesRec.Body.Bytes(), &aliasesOut, jsonx.V1())) require.Len(t, aliasesOut.Aliases, 1) assert.Equal(t, "alias/tf-lifecycle-test", aliasesOut.Aliases[0].AliasName) assert.Equal(t, keyID, aliasesOut.Aliases[0].TargetKeyID) @@ -162,7 +163,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { require.Equal(t, http.StatusOK, scheduleRec.Code, scheduleRec.Body.String()) var scheduleOut kms.ScheduleKeyDeletionOutput - require.NoError(t, json.Unmarshal(scheduleRec.Body.Bytes(), &scheduleOut)) + require.NoError(t, json.Unmarshal(scheduleRec.Body.Bytes(), &scheduleOut, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingDeletion, scheduleOut.KeyState) assert.Positive(t, scheduleOut.DeletionDate) assert.Equal(t, 7, scheduleOut.PendingWindowInDays) @@ -171,7 +172,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { require.Equal(t, http.StatusOK, finalDescRec.Code) var finalDesc kms.DescribeKeyOutput - require.NoError(t, json.Unmarshal(finalDescRec.Body.Bytes(), &finalDesc)) + require.NoError(t, json.Unmarshal(finalDescRec.Body.Bytes(), &finalDesc, jsonx.V1())) assert.Equal(t, kms.KeyStatePendingDeletion, finalDesc.KeyMetadata.KeyState) assert.Positive(t, finalDesc.KeyMetadata.DeletionDate) assert.Equal(t, 7, finalDesc.KeyMetadata.PendingDeletionWindowInDays) @@ -181,7 +182,7 @@ func TestTerraformLifecycle_KMSKey(t *testing.T) { // strconvQuote JSON-quotes s (equivalent to strconv.Quote for the ASCII/simple policy // strings this test uses, without pulling in strconv just for one call site). func strconvQuote(s string) string { - b, err := json.Marshal(s) + b, err := json.Marshal(s, jsonx.V1()) if err != nil { panic(err) } diff --git a/services/kms/undeclared_members_test.go b/services/kms/undeclared_members_test.go index bc197e250d..fcb04dbb27 100644 --- a/services/kms/undeclared_members_test.go +++ b/services/kms/undeclared_members_test.go @@ -1,7 +1,7 @@ package kms_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/kms/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_KeyMetadataOmitsUndeclaredMembers(t *testing.T) { @@ -32,14 +34,14 @@ func TestHandler_KeyMetadataOmitsUndeclaredMembers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out["KeyMetadata"], "PrimaryRegion") assert.NotContains(t, out["KeyMetadata"], "MultiRegionKeyType") id := out["KeyMetadata"]["KeyId"].(string) rec = sendKMSOp(t, h, "DescribeKey", `{"KeyId":"`+id+`"}`) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out["KeyMetadata"], "PrimaryRegion") assert.NotContains(t, out["KeyMetadata"], "MultiRegionKeyType") }) diff --git a/services/kms/validation.go b/services/kms/validation.go index fd84aaaac4..2e6f0f18e4 100644 --- a/services/kms/validation.go +++ b/services/kms/validation.go @@ -1,12 +1,14 @@ package kms import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "regexp" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var keyIDShapeRe = regexp.MustCompile( @@ -21,7 +23,7 @@ func validateListMarker(action string, body []byte) error { Marker string `json:"Marker"` } - if json.Unmarshal(body, &in) == nil && in.Marker != "" { + if json.Unmarshal(body, &in, jsonx.V1()) == nil && in.Marker != "" { if n, err := strconv.Atoi(in.Marker); err != nil || n < 0 { return fmt.Errorf("%w: invalid marker", ErrInvalidMarker) } diff --git a/services/kms/wire_error_types_test.go b/services/kms/wire_error_types_test.go index 2486b168f9..16f4394f30 100644 --- a/services/kms/wire_error_types_test.go +++ b/services/kms/wire_error_types_test.go @@ -2,7 +2,7 @@ package kms_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/kms" ) @@ -226,7 +227,7 @@ func TestWireErrorTypes_NotValidationException(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp.Type) assert.NotEqual(t, "ValidationException", resp.Type) }) @@ -351,7 +352,7 @@ func TestWireErrorTypes_MalformedKeyIDArn(t *testing.T) { var resp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp.Type) }) } @@ -360,7 +361,7 @@ func TestWireErrorTypes_MalformedKeyIDArn(t *testing.T) { func mustJSON(t *testing.T, v any) string { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/lakeformation/handler_credentials.go b/services/lakeformation/handler_credentials.go index 22ee1dab04..19d8a26d4f 100644 --- a/services/lakeformation/handler_credentials.go +++ b/services/lakeformation/handler_credentials.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAssumeDecoratedRoleWithSAML(_ context.Context, c *echo.Context, body []byte) error { var in assumeDecoratedRoleWithSAMLInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -40,7 +42,7 @@ func (h *Handler) handleGetDataLakePrincipal(ctx context.Context, c *echo.Contex func (h *Handler) handleGetTemporaryDataLocationCredentials(_ context.Context, c *echo.Context, body []byte) error { var in getTemporaryDataLocationCredentialsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } // GetTemporaryDataLocationCredentialsInput (lakeformation@v1.50.4 @@ -60,7 +62,7 @@ func (h *Handler) handleGetTemporaryDataLocationCredentials(_ context.Context, c func (h *Handler) handleGetTemporaryGluePartitionCredentials(_ context.Context, c *echo.Context, body []byte) error { var in getTemporaryGluePartitionCredentialsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } if strings.TrimSpace(in.TableArn) == "" { @@ -78,7 +80,7 @@ func (h *Handler) handleGetTemporaryGluePartitionCredentials(_ context.Context, func (h *Handler) handleGetTemporaryGlueTableCredentials(_ context.Context, c *echo.Context, body []byte) error { var in getTemporaryGlueTableCredentialsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } if strings.TrimSpace(in.TableArn) == "" { diff --git a/services/lakeformation/handler_credentials_test.go b/services/lakeformation/handler_credentials_test.go index d49a94c033..10c1118bdb 100644 --- a/services/lakeformation/handler_credentials_test.go +++ b/services/lakeformation/handler_credentials_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -61,7 +62,7 @@ func TestHandler_AssumeDecoratedRoleWithSAML(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, resp, field) assert.NotEmpty(t, resp[field]) @@ -85,7 +86,7 @@ func TestAssumeDecoratedRoleWithSAML_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["AccessKeyId"]) assert.NotEmpty(t, out["SecretAccessKey"]) assert.NotEmpty(t, out["SessionToken"]) diff --git a/services/lakeformation/handler_data_cells_filter.go b/services/lakeformation/handler_data_cells_filter.go index f9d0054a1e..be4fbe754e 100644 --- a/services/lakeformation/handler_data_cells_filter.go +++ b/services/lakeformation/handler_data_cells_filter.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateDataCellsFilter(_ context.Context, c *echo.Context, body []byte) error { var in createDataCellsFilterInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -32,7 +34,7 @@ func (h *Handler) handleCreateDataCellsFilter(_ context.Context, c *echo.Context func (h *Handler) handleDeleteDataCellsFilter(_ context.Context, c *echo.Context, body []byte) error { var in deleteDataCellsFilterInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -46,7 +48,7 @@ func (h *Handler) handleDeleteDataCellsFilter(_ context.Context, c *echo.Context func (h *Handler) handleListDataCellsFilter(_ context.Context, c *echo.Context, body []byte) error { var in listDataCellsFilterInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -79,7 +81,7 @@ func (h *Handler) handleListDataCellsFilter(_ context.Context, c *echo.Context, func (h *Handler) handleGetDataCellsFilter(_ context.Context, c *echo.Context, body []byte) error { var in getDataCellsFilterInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } f, err := h.Backend.GetDataCellsFilter(in.TableCatalogID, in.DatabaseName, in.TableName, in.Name) @@ -92,7 +94,7 @@ func (h *Handler) handleGetDataCellsFilter(_ context.Context, c *echo.Context, b func (h *Handler) handleUpdateDataCellsFilter(_ context.Context, c *echo.Context, body []byte) error { var in updateDataCellsFilterInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } if in.TableData == nil { diff --git a/services/lakeformation/handler_data_lake_settings.go b/services/lakeformation/handler_data_lake_settings.go index 712d6626dd..4497fd47af 100644 --- a/services/lakeformation/handler_data_lake_settings.go +++ b/services/lakeformation/handler_data_lake_settings.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetDataLakeSettings(_ context.Context, c *echo.Context, body []byte) error { var in getDataLakeSettingsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -26,7 +28,7 @@ func (h *Handler) handleGetDataLakeSettings(_ context.Context, c *echo.Context, func (h *Handler) handlePutDataLakeSettings(_ context.Context, c *echo.Context, body []byte) error { var in putDataLakeSettingsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } diff --git a/services/lakeformation/handler_data_lake_settings_test.go b/services/lakeformation/handler_data_lake_settings_test.go index 327f9d0c18..22ba6412b9 100644 --- a/services/lakeformation/handler_data_lake_settings_test.go +++ b/services/lakeformation/handler_data_lake_settings_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -41,7 +42,7 @@ func TestHandler_GetDataLakeSettings(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "DataLakeSettings") }) } diff --git a/services/lakeformation/handler_lake_formation_identity_center.go b/services/lakeformation/handler_lake_formation_identity_center.go index 6e541e9f8e..9b5d4670d2 100644 --- a/services/lakeformation/handler_lake_formation_identity_center.go +++ b/services/lakeformation/handler_lake_formation_identity_center.go @@ -2,10 +2,12 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateLakeFormationIdentityCenterConfiguration( @@ -14,7 +16,7 @@ func (h *Handler) handleCreateLakeFormationIdentityCenterConfiguration( body []byte, ) error { var in createLakeFormationIdentityCenterConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -42,7 +44,7 @@ func (h *Handler) handleDeleteLakeFormationIdentityCenterConfiguration( ) error { var in deleteLakeFormationIdentityCenterConfigurationInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -62,7 +64,7 @@ func (h *Handler) handleDescribeLakeFormationIdentityCenterConfiguration( ) error { var in describeLakeFormationIdentityCenterConfigurationInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -90,7 +92,7 @@ func (h *Handler) handleUpdateLakeFormationIdentityCenterConfiguration( ) error { var in updateLakeFormationIdentityCenterConfigurationInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } diff --git a/services/lakeformation/handler_lake_formation_identity_center_test.go b/services/lakeformation/handler_lake_formation_identity_center_test.go index d5c4948083..afffbce80f 100644 --- a/services/lakeformation/handler_lake_formation_identity_center_test.go +++ b/services/lakeformation/handler_lake_formation_identity_center_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -52,7 +53,7 @@ func TestHandler_CreateLakeFormationIdentityCenterConfiguration(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ApplicationArn") } }) @@ -72,7 +73,7 @@ func TestIdentityCenterConfiguration_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["ApplicationArn"]) assert.Contains(t, out["ApplicationArn"].(string), "arn:aws:sso") } diff --git a/services/lakeformation/handler_lf_tag_expression.go b/services/lakeformation/handler_lf_tag_expression.go index be036532c0..35e819a55d 100644 --- a/services/lakeformation/handler_lf_tag_expression.go +++ b/services/lakeformation/handler_lf_tag_expression.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateLFTagExpression(_ context.Context, c *echo.Context, body []byte) error { var in createLFTagExpressionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -32,7 +34,7 @@ func (h *Handler) handleCreateLFTagExpression(_ context.Context, c *echo.Context func (h *Handler) handleDeleteLFTagExpression(_ context.Context, c *echo.Context, body []byte) error { var in deleteLFTagExpressionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -50,7 +52,7 @@ func (h *Handler) handleDeleteLFTagExpression(_ context.Context, c *echo.Context func (h *Handler) handleListLFTagExpressions(_ context.Context, c *echo.Context, body []byte) error { var in listLFTagExpressionsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -65,7 +67,7 @@ func (h *Handler) handleListLFTagExpressions(_ context.Context, c *echo.Context, func (h *Handler) handleGetLFTagExpression(_ context.Context, c *echo.Context, body []byte) error { var in getLFTagExpressionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } expr, err := h.Backend.GetLFTagExpression(in.Name, in.CatalogID) @@ -83,7 +85,7 @@ func (h *Handler) handleGetLFTagExpression(_ context.Context, c *echo.Context, b func (h *Handler) handleUpdateLFTagExpression(_ context.Context, c *echo.Context, body []byte) error { var in updateLFTagExpressionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } if strings.TrimSpace(in.Name) == "" { diff --git a/services/lakeformation/handler_lf_tags.go b/services/lakeformation/handler_lf_tags.go index da7605c1d8..5aae9acc0a 100644 --- a/services/lakeformation/handler_lf_tags.go +++ b/services/lakeformation/handler_lf_tags.go @@ -2,15 +2,17 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateLFTag(_ context.Context, c *echo.Context, body []byte) error { var in createLFTagInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -23,7 +25,7 @@ func (h *Handler) handleCreateLFTag(_ context.Context, c *echo.Context, body []b func (h *Handler) handleDeleteLFTag(_ context.Context, c *echo.Context, body []byte) error { var in deleteLFTagInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -36,7 +38,7 @@ func (h *Handler) handleDeleteLFTag(_ context.Context, c *echo.Context, body []b func (h *Handler) handleGetLFTag(_ context.Context, c *echo.Context, body []byte) error { var in getLFTagInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -54,7 +56,7 @@ func (h *Handler) handleGetLFTag(_ context.Context, c *echo.Context, body []byte func (h *Handler) handleUpdateLFTag(_ context.Context, c *echo.Context, body []byte) error { var in updateLFTagInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -68,7 +70,7 @@ func (h *Handler) handleUpdateLFTag(_ context.Context, c *echo.Context, body []b func (h *Handler) handleListLFTags(_ context.Context, c *echo.Context, body []byte) error { var in listLFTagsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -104,7 +106,7 @@ func (h *Handler) checkAddRemoveLFTagsInput(c *echo.Context, resource *Resource, func (h *Handler) handleAddLFTagsToResource(_ context.Context, c *echo.Context, body []byte) error { var in addLFTagsToResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -122,7 +124,7 @@ func (h *Handler) handleAddLFTagsToResource(_ context.Context, c *echo.Context, func (h *Handler) handleRemoveLFTagsFromResource(_ context.Context, c *echo.Context, body []byte) error { var in removeLFTagsFromResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -140,7 +142,7 @@ func (h *Handler) handleRemoveLFTagsFromResource(_ context.Context, c *echo.Cont func (h *Handler) handleGetResourceLFTags(_ context.Context, c *echo.Context, body []byte) error { var in getResourceLFTagsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -174,7 +176,7 @@ func (h *Handler) handleGetResourceLFTags(_ context.Context, c *echo.Context, bo func (h *Handler) handleSearchDatabasesByLFTags(_ context.Context, c *echo.Context, body []byte) error { var in searchDatabasesByLFTagsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -190,7 +192,7 @@ func (h *Handler) handleSearchDatabasesByLFTags(_ context.Context, c *echo.Conte func (h *Handler) handleSearchTablesByLFTags(_ context.Context, c *echo.Context, body []byte) error { var in searchTablesByLFTagsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } diff --git a/services/lakeformation/handler_lf_tags_test.go b/services/lakeformation/handler_lf_tags_test.go index 1535d03534..56a3d89600 100644 --- a/services/lakeformation/handler_lf_tags_test.go +++ b/services/lakeformation/handler_lf_tags_test.go @@ -1,7 +1,7 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -49,7 +50,7 @@ func TestHandler_LFTagLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.tagKey, getResp["TagKey"]) // Update @@ -64,7 +65,7 @@ func TestHandler_LFTagLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["LFTags"].([]any) assert.Len(t, tags, 1) @@ -142,7 +143,7 @@ func TestHandler_AddLFTagsToResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["Failures"].([]any) assert.Len(t, failures, tt.wantFails) } @@ -234,7 +235,7 @@ func TestCreateLFTag_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "team", out["TagKey"]) } @@ -279,7 +280,7 @@ func TestListLFTags_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags := out["LFTags"].([]any) require.Len(t, tags, 3) @@ -306,7 +307,7 @@ func TestAddLFTagsToResource_PartialFailure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) failures := out["Failures"].([]any) assert.Len(t, failures, 1, "only nonexistent tag should fail") assert.Equal(t, "nonexistent", failures[0].(map[string]any)["LFTag"].(map[string]any)["TagKey"]) @@ -335,7 +336,7 @@ func TestUpdateLFTag_AddAndRemove(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) vals := out["TagValues"].([]any) strs := make([]string, len(vals)) @@ -368,7 +369,7 @@ func TestAddLFTagsToResource_TableResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["Failures"]) } diff --git a/services/lakeformation/handler_opt_ins.go b/services/lakeformation/handler_opt_ins.go index 2524c95a0a..d1e658aad2 100644 --- a/services/lakeformation/handler_opt_ins.go +++ b/services/lakeformation/handler_opt_ins.go @@ -2,15 +2,17 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateLakeFormationOptIn(_ context.Context, c *echo.Context, body []byte) error { var in createLakeFormationOptInInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -31,7 +33,7 @@ func (h *Handler) handleCreateLakeFormationOptIn(_ context.Context, c *echo.Cont func (h *Handler) handleDeleteLakeFormationOptIn(_ context.Context, c *echo.Context, body []byte) error { var in deleteLakeFormationOptInInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -53,7 +55,7 @@ func (h *Handler) handleDeleteLakeFormationOptIn(_ context.Context, c *echo.Cont func (h *Handler) handleListLakeFormationOptIns(_ context.Context, c *echo.Context, body []byte) error { var in listLakeFormationOptInsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } diff --git a/services/lakeformation/handler_permissions.go b/services/lakeformation/handler_permissions.go index bc3e691a5c..39cf7aed98 100644 --- a/services/lakeformation/handler_permissions.go +++ b/services/lakeformation/handler_permissions.go @@ -3,16 +3,18 @@ package lakeformation import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGrantPermissions(ctx context.Context, c *echo.Context, body []byte) error { var in grantPermissionsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -33,7 +35,7 @@ func (h *Handler) handleGrantPermissions(ctx context.Context, c *echo.Context, b func (h *Handler) handleRevokePermissions(ctx context.Context, c *echo.Context, body []byte) error { var in revokePermissionsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -55,7 +57,7 @@ func (h *Handler) handleRevokePermissions(ctx context.Context, c *echo.Context, func (h *Handler) handleListPermissions(_ context.Context, c *echo.Context, body []byte) error { var in listPermissionsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -85,7 +87,7 @@ func (h *Handler) handleListPermissions(_ context.Context, c *echo.Context, body func (h *Handler) handleBatchGrantPermissions(ctx context.Context, c *echo.Context, body []byte) error { var in batchGrantPermissionsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -99,7 +101,7 @@ func (h *Handler) handleBatchGrantPermissions(ctx context.Context, c *echo.Conte func (h *Handler) handleBatchRevokePermissions(ctx context.Context, c *echo.Context, body []byte) error { var in batchRevokePermissionsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -139,7 +141,7 @@ func (h *Handler) runBatchPermissions( func (h *Handler) handleGetEffectivePermissionsForPath(_ context.Context, c *echo.Context, body []byte) error { var in getEffectivePermissionsForPathInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } diff --git a/services/lakeformation/handler_permissions_test.go b/services/lakeformation/handler_permissions_test.go index d44d964d48..29b05f52c5 100644 --- a/services/lakeformation/handler_permissions_test.go +++ b/services/lakeformation/handler_permissions_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -45,7 +46,7 @@ func TestHandler_GrantRevokeListPermissions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) perms, _ := listResp["PrincipalResourcePermissions"].([]any) assert.Len(t, perms, 1) @@ -82,7 +83,7 @@ func TestHandler_BatchGrantRevokePermissions(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["Failures"].([]any) assert.Empty(t, failures) @@ -104,7 +105,7 @@ func TestBatchGrantPermissions_EmptyEntries(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["Failures"]) } @@ -126,7 +127,7 @@ func TestGrantAndListPermissions(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) perms := out["PrincipalResourcePermissions"].([]any) assert.Len(t, perms, 1) } diff --git a/services/lakeformation/handler_resources.go b/services/lakeformation/handler_resources.go index 1287564074..401ebe278a 100644 --- a/services/lakeformation/handler_resources.go +++ b/services/lakeformation/handler_resources.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleRegisterResource(_ context.Context, c *echo.Context, body []byte) error { var in registerResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -46,7 +48,7 @@ func (h *Handler) handleRegisterResource(_ context.Context, c *echo.Context, bod func (h *Handler) handleDeregisterResource(_ context.Context, c *echo.Context, body []byte) error { var in deregisterResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -59,7 +61,7 @@ func (h *Handler) handleDeregisterResource(_ context.Context, c *echo.Context, b func (h *Handler) handleDescribeResource(_ context.Context, c *echo.Context, body []byte) error { var in describeResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -74,7 +76,7 @@ func (h *Handler) handleDescribeResource(_ context.Context, c *echo.Context, bod func (h *Handler) handleListResources(_ context.Context, c *echo.Context, body []byte) error { var in listResourcesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -94,7 +96,7 @@ func (h *Handler) handleListResources(_ context.Context, c *echo.Context, body [ func (h *Handler) handleUpdateResource(_ context.Context, c *echo.Context, body []byte) error { var in updateResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } diff --git a/services/lakeformation/handler_resources_test.go b/services/lakeformation/handler_resources_test.go index 0fe4e21965..2f5e058ced 100644 --- a/services/lakeformation/handler_resources_test.go +++ b/services/lakeformation/handler_resources_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -49,7 +50,7 @@ func TestHandler_RegisterDeregisterDescribeResource(t *testing.T) { assert.Equal(t, tt.wantDescStatus, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) ri, ok := descResp["ResourceInfo"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.resourceArn, ri["ResourceArn"]) @@ -123,7 +124,7 @@ func TestHandler_ListResources(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, _ := resp["ResourceInfoList"].([]any) assert.Len(t, list, tt.wantCount) }) @@ -157,7 +158,7 @@ func TestListResources_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list := out["ResourceInfoList"].([]any) require.Len(t, list, 3) diff --git a/services/lakeformation/handler_table_storage.go b/services/lakeformation/handler_table_storage.go index b6cf74e6a8..c80c080dc9 100644 --- a/services/lakeformation/handler_table_storage.go +++ b/services/lakeformation/handler_table_storage.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetTableObjects(_ context.Context, c *echo.Context, body []byte) error { var in getTableObjectsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -25,7 +27,7 @@ func (h *Handler) handleGetTableObjects(_ context.Context, c *echo.Context, body func (h *Handler) handleListTableStorageOptimizers(_ context.Context, c *echo.Context, body []byte) error { var in listTableStorageOptimizersInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } opts, next := h.Backend.ListTableStorageOptimizers( @@ -38,7 +40,7 @@ func (h *Handler) handleListTableStorageOptimizers(_ context.Context, c *echo.Co func (h *Handler) handleUpdateTableObjects(_ context.Context, c *echo.Context, body []byte) error { var in updateTableObjectsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -53,7 +55,7 @@ func (h *Handler) handleUpdateTableObjects(_ context.Context, c *echo.Context, b func (h *Handler) handleUpdateTableStorageOptimizer(_ context.Context, c *echo.Context, body []byte) error { var in updateTableStorageOptimizerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } result := h.Backend.UpdateTableStorageOptimizer( diff --git a/services/lakeformation/handler_test.go b/services/lakeformation/handler_test.go index 7f31381a3c..0294685251 100644 --- a/services/lakeformation/handler_test.go +++ b/services/lakeformation/handler_test.go @@ -2,7 +2,8 @@ package lakeformation_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -62,7 +64,7 @@ func newTestContext(t *testing.T, path string, body any) (*echo.Context, *httpte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -91,7 +93,7 @@ func postJSON(t *testing.T, h *lakeformation.Handler, path string, body any) *ht // jsonDecode is a helper to decode a response body into a map. func jsonDecode(r io.Reader, v any) error { - return json.NewDecoder(r).Decode(v) + return json.UnmarshalDecode(jsontext.NewDecoder(r), v, jsonx.V1()) } func TestHandler_UnknownOperation(t *testing.T) { @@ -515,7 +517,7 @@ func TestErrValidationMapping(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidInputException", resp["__type"]) }) } diff --git a/services/lakeformation/handler_transactions.go b/services/lakeformation/handler_transactions.go index 31cfa87fd1..ff3a2d1f32 100644 --- a/services/lakeformation/handler_transactions.go +++ b/services/lakeformation/handler_transactions.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCancelTransaction(_ context.Context, c *echo.Context, body []byte) error { var in cancelTransactionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -28,7 +30,7 @@ func (h *Handler) handleCancelTransaction(_ context.Context, c *echo.Context, bo func (h *Handler) handleCommitTransaction(_ context.Context, c *echo.Context, body []byte) error { var in commitTransactionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -47,7 +49,7 @@ func (h *Handler) handleCommitTransaction(_ context.Context, c *echo.Context, bo func (h *Handler) handleStartTransaction(_ context.Context, c *echo.Context, body []byte) error { var in startTransactionInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -59,7 +61,7 @@ func (h *Handler) handleStartTransaction(_ context.Context, c *echo.Context, bod func (h *Handler) handleDescribeTransaction(_ context.Context, c *echo.Context, body []byte) error { var in describeTransactionInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -78,7 +80,7 @@ func (h *Handler) handleDescribeTransaction(_ context.Context, c *echo.Context, func (h *Handler) handleListTransactions(_ context.Context, c *echo.Context, body []byte) error { var in listTransactionsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } @@ -93,7 +95,7 @@ func (h *Handler) handleListTransactions(_ context.Context, c *echo.Context, bod func (h *Handler) handleDeleteObjectsOnCancel(_ context.Context, c *echo.Context, body []byte) error { var in deleteObjectsOnCancelInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } @@ -119,7 +121,7 @@ func (h *Handler) handleDeleteObjectsOnCancel(_ context.Context, c *echo.Context func (h *Handler) handleExtendTransaction(_ context.Context, c *echo.Context, body []byte) error { var in extendTransactionInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } } diff --git a/services/lakeformation/handler_transactions_test.go b/services/lakeformation/handler_transactions_test.go index 0afd7d991d..a2b2355754 100644 --- a/services/lakeformation/handler_transactions_test.go +++ b/services/lakeformation/handler_transactions_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -122,7 +123,7 @@ func TestHandler_CommitTransaction(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantStatus2 != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantStatus2, resp["TransactionStatus"]) } }) @@ -198,7 +199,7 @@ func TestCommitTransaction_ReturnsStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "COMMITTED", out["TransactionStatus"]) } diff --git a/services/lakeformation/handler_work_units.go b/services/lakeformation/handler_work_units.go index 527ff73670..b95b35c684 100644 --- a/services/lakeformation/handler_work_units.go +++ b/services/lakeformation/handler_work_units.go @@ -2,16 +2,18 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetQueryState(_ context.Context, c *echo.Context, body []byte) error { var in getQueryStateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } state, err := h.Backend.GetQueryState(in.QueryID) @@ -24,7 +26,7 @@ func (h *Handler) handleGetQueryState(_ context.Context, c *echo.Context, body [ func (h *Handler) handleGetQueryStatistics(_ context.Context, c *echo.Context, body []byte) error { var in getQueryStatisticsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } exec, plan, err := h.Backend.GetQueryStatistics(in.QueryID) @@ -37,7 +39,7 @@ func (h *Handler) handleGetQueryStatistics(_ context.Context, c *echo.Context, b func (h *Handler) handleGetWorkUnitResults(_ context.Context, c *echo.Context, body []byte) error { var in getWorkUnitResultsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } result, err := h.Backend.GetWorkUnitResults(in.QueryID, in.WorkUnitID, in.WorkUnitToken) @@ -50,7 +52,7 @@ func (h *Handler) handleGetWorkUnitResults(_ context.Context, c *echo.Context, b func (h *Handler) handleGetWorkUnits(_ context.Context, c *echo.Context, body []byte) error { var in getWorkUnitsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } ranges, nextToken, err := h.Backend.GetWorkUnits(in.QueryID) @@ -63,7 +65,7 @@ func (h *Handler) handleGetWorkUnits(_ context.Context, c *echo.Context, body [] func (h *Handler) handleStartQueryPlanning(_ context.Context, c *echo.Context, body []byte) error { var in startQueryPlanningInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidInputException", err.Error()) } if strings.TrimSpace(in.QueryString) == "" { diff --git a/services/lakeformation/handler_work_units_test.go b/services/lakeformation/handler_work_units_test.go index 310c8bc7d0..96afc053b0 100644 --- a/services/lakeformation/handler_work_units_test.go +++ b/services/lakeformation/handler_work_units_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -24,7 +25,7 @@ func TestStartQueryPlanning_RequiresDatabaseName(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out["message"].(string), "DatabaseName") } diff --git a/services/lakeformation/multi_region_test.go b/services/lakeformation/multi_region_test.go index 8957d9bcac..a0798d3308 100644 --- a/services/lakeformation/multi_region_test.go +++ b/services/lakeformation/multi_region_test.go @@ -2,7 +2,8 @@ package lakeformation_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -176,8 +178,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/lakeformation/pagination_validation.go b/services/lakeformation/pagination_validation.go index 165b9547dc..039afba684 100644 --- a/services/lakeformation/pagination_validation.go +++ b/services/lakeformation/pagination_validation.go @@ -1,10 +1,12 @@ package lakeformation import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -22,11 +24,11 @@ func validatePagination(op string, body []byte) error { NextToken string `json:"NextToken"` } - if !json.Valid(body) { + if !jsontext.Value(body).IsValid(jsonx.V1()) { return nil } - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) if in.MaxResults != nil && (*in.MaxResults < 1 || *in.MaxResults > maxListResults) { return fmt.Errorf("MaxResults must be between 1 and %d: %w", maxListResults, ErrValidation) diff --git a/services/lakeformation/persistence.go b/services/lakeformation/persistence.go index a6575a115d..bc2d6fd285 100644 --- a/services/lakeformation/persistence.go +++ b/services/lakeformation/persistence.go @@ -2,10 +2,12 @@ package lakeformation import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -94,7 +96,7 @@ func newTransactionDTORegistry() (*store.Registry, *store.Table[transactionSnaps // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourceLFTags map[string][]LFTagPair `json:"resourceLFTags"` Queries map[string]string `json:"queries,omitempty"` TableStorageOptimizers map[string][]StorageOptimizer `json:"tableStorageOptimizers,omitempty"` @@ -186,7 +188,7 @@ func (b *InMemoryBackend) Snapshot() ([]byte, error) { // Marshal failure is returned to the caller (the Persistable wrapper logs // it via the context-aware logger); do not log through slog.Default() here. - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { return nil, fmt.Errorf("lakeformation: marshal snapshot: %w", err) } @@ -278,7 +280,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreTransactionsLocked restores the "dirty" transactions table from // tables via the ephemeral DTO registry, converting each DTO back to its // live type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreTransactionsLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreTransactionsLocked(tables map[string]jsontext.Value) error { dtoReg, txDTOs := newTransactionDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/lakeformation/persistence_test.go b/services/lakeformation/persistence_test.go index 21ee862a49..288414d41e 100644 --- a/services/lakeformation/persistence_test.go +++ b/services/lakeformation/persistence_test.go @@ -1,13 +1,14 @@ package lakeformation_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/services/lakeformation" ) @@ -350,7 +351,7 @@ func TestPersistence_IncludesQueriesAndOptimizers(t *testing.T) { // Verify queries survived restore (GetQueryState should work) var qOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &qOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &qOut, jsonx.V1())) queryID := qOut["QueryId"].(string) state, err := b2.GetQueryState(queryID) diff --git a/services/lambda/account_settings_test.go b/services/lambda/account_settings_test.go index 8afa095077..961e1b89f1 100644 --- a/services/lambda/account_settings_test.go +++ b/services/lambda/account_settings_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -25,7 +27,7 @@ func TestAccountUsage_FunctionCount_Increments(t *testing.T) { require.Equal(t, http.StatusOK, rec0.Code) var s0 lambda.AccountSettingsOutput - require.NoError(t, json.NewDecoder(rec0.Body).Decode(&s0)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec0.Body), &s0, jsonx.V1())) require.NotNil(t, s0.AccountUsage) assert.Equal(t, 0, s0.AccountUsage.FunctionCount) @@ -36,7 +38,7 @@ func TestAccountUsage_FunctionCount_Increments(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var s2 lambda.AccountSettingsOutput - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&s2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &s2, jsonx.V1())) require.NotNil(t, s2.AccountUsage) assert.Equal(t, 2, s2.AccountUsage.FunctionCount) } @@ -50,7 +52,7 @@ func TestAccountUsage_AccountLimit_Fields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var s lambda.AccountSettingsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&s)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &s, jsonx.V1())) require.NotNil(t, s.AccountLimit) assert.Positive(t, s.AccountLimit.TotalCodeSize) assert.Positive(t, s.AccountLimit.ConcurrentExecutions) @@ -110,7 +112,7 @@ func TestGetAccountSettings_UnreservedConcurrency(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) limit, ok := out["AccountLimit"].(map[string]any) require.True(t, ok, "AccountLimit must be present") @@ -133,7 +135,7 @@ func TestGetAccountSettings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.AccountSettingsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.AccountLimit) assert.Positive(t, out.AccountLimit.ConcurrentExecutions) assert.Positive(t, out.AccountLimit.TotalCodeSize) @@ -152,6 +154,6 @@ func TestGetAccountSettings_FunctionCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.AccountSettingsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, 2, out.AccountUsage.FunctionCount) } diff --git a/services/lambda/async_destinations.go b/services/lambda/async_destinations.go index b80c23d773..f4bddfecd9 100644 --- a/services/lambda/async_destinations.go +++ b/services/lambda/async_destinations.go @@ -3,9 +3,11 @@ package lambda import ( "cmp" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -50,8 +52,8 @@ type asyncOutcome struct { // asyncDestinationRecord is the JSON invocation record AWS Lambda delivers to // OnSuccess/OnFailure destinations. type asyncDestinationRecord struct { - RequestPayload json.RawMessage `json:"requestPayload,omitempty"` - ResponsePayload json.RawMessage `json:"responsePayload,omitempty"` + RequestPayload jsontext.Value `json:"requestPayload,omitempty"` + ResponsePayload jsontext.Value `json:"responsePayload,omitempty"` Timestamp string `json:"timestamp"` Version string `json:"version"` RequestContext asyncRequestContext `json:"requestContext"` @@ -100,7 +102,7 @@ func (b *InMemoryBackend) dispatchAsyncOutcome(ctx context.Context, out asyncOut return } - body, marshalErr := json.Marshal(buildAsyncDestinationRecord(out, functionArn)) + body, marshalErr := json.Marshal(buildAsyncDestinationRecord(out, functionArn), jsonx.V1()) if marshalErr != nil { log.WarnContext(ctx, "lambda: failed to marshal destination record", "function", out.functionName, "error", marshalErr) @@ -197,18 +199,18 @@ func buildAsyncDestinationRecord(out asyncOutcome, functionArn string) asyncDest // rawJSONOrNull returns b as raw JSON when it is valid JSON, otherwise a JSON // string containing the raw bytes so the record always marshals cleanly. -func rawJSONOrNull(b []byte) json.RawMessage { +func rawJSONOrNull(b []byte) jsontext.Value { if len(b) == 0 { - return json.RawMessage("null") + return jsontext.Value("null") } - if json.Valid(b) { - return json.RawMessage(b) + if jsontext.Value(b).IsValid(jsonx.V1()) { + return jsontext.Value(b) } - quoted, err := json.Marshal(string(b)) + quoted, err := json.Marshal(string(b), jsonx.V1()) if err != nil { - return json.RawMessage("null") + return jsontext.Value("null") } return quoted diff --git a/services/lambda/capacity_providers_test.go b/services/lambda/capacity_providers_test.go index e92eff569a..5e4b04234b 100644 --- a/services/lambda/capacity_providers_test.go +++ b/services/lambda/capacity_providers_test.go @@ -2,7 +2,8 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/lambda" @@ -231,7 +233,7 @@ func TestCapacityProvider_StateTransitionAndTags(t *testing.T) { CapacityProviderArn string `json:"CapacityProviderArn"` } `json:"CapacityProvider"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec = callInMemoryHandler(t, h, http.MethodGet, "/2025-11-30/capacity-providers/tagged", "") require.Equal(t, http.StatusOK, rec.Code) @@ -544,7 +546,7 @@ func TestCapacityProvider_GetDeleteUpdateList(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut lambda.UpdateCapacityProviderOutput - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&updateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &updateOut, jsonx.V1())) require.NotNil(t, updateOut.CapacityProvider) require.NotNil(t, updateOut.CapacityProvider.CapacityProviderScalingConfig) require.NotNil(t, updateOut.CapacityProvider.CapacityProviderScalingConfig.MaxVCpuCount) @@ -555,7 +557,7 @@ func TestCapacityProvider_GetDeleteUpdateList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListCapacityProvidersOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.CapacityProviders, 1) // Delete — real AWS returns 200 with the deleted provider's state, not 204 @@ -564,7 +566,7 @@ func TestCapacityProvider_GetDeleteUpdateList(t *testing.T) { require.Equal(t, http.StatusOK, delRec.Code) var deleteOut lambda.DeleteCapacityProviderOutput - require.NoError(t, json.NewDecoder(delRec.Body).Decode(&deleteOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(delRec.Body), &deleteOut, jsonx.V1())) require.NotNil(t, deleteOut.CapacityProvider) assert.True(t, strings.HasSuffix(deleteOut.CapacityProvider.CapacityProviderArn, "capacity-provider:test-cp")) @@ -573,7 +575,7 @@ func TestCapacityProvider_GetDeleteUpdateList(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var listOut2 lambda.ListCapacityProvidersOutput - require.NoError(t, json.NewDecoder(listRec2.Body).Decode(&listOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec2.Body), &listOut2, jsonx.V1())) assert.Empty(t, listOut2.CapacityProviders) } @@ -626,7 +628,7 @@ func TestListFunctionVersionsByCapacityProvider(t *testing.T) { var out struct { FunctionVersions []any `json:"FunctionVersions"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Empty(t, out.FunctionVersions) } }) @@ -667,7 +669,7 @@ func TestCapacityProvider_TelemetryConfig(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createOut lambda.CreateCapacityProviderOutput - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) require.NotNil(t, createOut.CapacityProvider.TelemetryConfig) require.NotNil(t, createOut.CapacityProvider.TelemetryConfig.LoggingConfig) assert.Equal(t, "WARN", createOut.CapacityProvider.TelemetryConfig.LoggingConfig.SystemLogLevel) @@ -678,7 +680,7 @@ func TestCapacityProvider_TelemetryConfig(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut lambda.UpdateCapacityProviderOutput - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&updateOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &updateOut, jsonx.V1())) require.NotNil(t, updateOut.CapacityProvider.TelemetryConfig) require.NotNil(t, updateOut.CapacityProvider.TelemetryConfig.LoggingConfig) assert.Equal(t, "DEBUG", updateOut.CapacityProvider.TelemetryConfig.LoggingConfig.SystemLogLevel) diff --git a/services/lambda/code_signing_test.go b/services/lambda/code_signing_test.go index ddef6bae16..e6da21bc3a 100644 --- a/services/lambda/code_signing_test.go +++ b/services/lambda/code_signing_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -48,7 +50,7 @@ func TestCodeSigningConfig_Lifecycle(t *testing.T) { if tt.wantStatus == http.StatusCreated { var out lambda.CreateCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.CodeSigningConfig) assert.NotEmpty(t, out.CodeSigningConfig.CodeSigningConfigArn) assert.Equal(t, tt.wantDesc, out.CodeSigningConfig.Description) @@ -73,7 +75,7 @@ func TestCodeSigningConfig_GetDeleteUpdate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut lambda.CreateCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) cscARN := createOut.CodeSigningConfig.CodeSigningConfigArn // Get @@ -97,7 +99,7 @@ func TestCodeSigningConfig_GetDeleteUpdate(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListCodeSigningConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.CodeSigningConfigs, 1) // Delete @@ -128,7 +130,7 @@ func TestFunctionCodeSigningConfig(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createOut lambda.CreateCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createOut, jsonx.V1())) cscARN := createOut.CodeSigningConfig.CodeSigningConfigArn // Put function code signing config @@ -138,7 +140,7 @@ func TestFunctionCodeSigningConfig(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putOut lambda.PutFunctionCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&putOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &putOut, jsonx.V1())) assert.Equal(t, cscARN, putOut.CodeSigningConfigArn) assert.Equal(t, "csc-test-fn", putOut.FunctionName) @@ -148,7 +150,7 @@ func TestFunctionCodeSigningConfig(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut lambda.GetFunctionCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, cscARN, getOut.CodeSigningConfigArn) // List functions by code signing config @@ -157,7 +159,7 @@ func TestFunctionCodeSigningConfig(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListFunctionsByCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.NotEmpty(t, listOut.FunctionArns) // Delete function code signing config @@ -171,7 +173,7 @@ func TestFunctionCodeSigningConfig(t *testing.T) { assert.Equal(t, http.StatusOK, getRec2.Code) var getOut2 lambda.GetFunctionCodeSigningConfigOutput - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&getOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &getOut2, jsonx.V1())) assert.Empty(t, getOut2.CodeSigningConfigArn) } @@ -234,7 +236,7 @@ func TestCodeSigning(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cscOut lambda.CreateCodeSigningConfigOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cscOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cscOut, jsonx.V1())) require.NotNil(t, cscOut.CodeSigningConfig) cscArn := cscOut.CodeSigningConfig.CodeSigningConfigArn assert.NotEmpty(t, cscArn) @@ -251,7 +253,7 @@ func TestCodeSigning(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listOut lambda.ListCodeSigningConfigsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.CodeSigningConfigs, 1) // UpdateCodeSigningConfig. @@ -280,7 +282,7 @@ func TestCodeSigning(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getCSCOut lambda.GetFunctionCodeSigningConfigOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCSCOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCSCOut, jsonx.V1())) assert.Equal(t, cscArn, getCSCOut.CodeSigningConfigArn) assert.Equal(t, "csc-fn", getCSCOut.FunctionName) diff --git a/services/lambda/concurrency_test.go b/services/lambda/concurrency_test.go index 4956b11798..c577ac50e9 100644 --- a/services/lambda/concurrency_test.go +++ b/services/lambda/concurrency_test.go @@ -1,13 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -110,7 +112,7 @@ func TestPutFunctionConcurrency(t *testing.T) { } var out lambda.FunctionConcurrency - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantReserved, out.ReservedConcurrentExecutions) }) } @@ -199,14 +201,14 @@ func TestGetFunctionConcurrency(t *testing.T) { if tt.wantAbsent { var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.NotContains(t, raw, "ReservedConcurrentExecutions") return } var out lambda.FunctionConcurrency - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantReserved, out.ReservedConcurrentExecutions) }) } @@ -448,7 +450,7 @@ func TestGetFunction_ReservedConcurrentExecutions(t *testing.T) { var out struct { Configuration *lambda.FunctionConfiguration `json:"Configuration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Configuration) if tt.wantReserved == nil { @@ -550,7 +552,7 @@ func TestConcurrency_PutGetDelete(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var conc lambda.FunctionConcurrency - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&conc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &conc, jsonx.V1())) assert.Equal(t, 50, conc.ReservedConcurrentExecutions) // Get @@ -559,7 +561,7 @@ func TestConcurrency_PutGetDelete(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getConc lambda.FunctionConcurrency - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getConc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getConc, jsonx.V1())) assert.Equal(t, 50, getConc.ReservedConcurrentExecutions) // Delete @@ -575,7 +577,7 @@ func TestConcurrency_PutGetDelete(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var raw map[string]any - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&raw)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &raw, jsonx.V1())) assert.NotContains(t, raw, "ReservedConcurrentExecutions") } diff --git a/services/lambda/ddb_esm_test.go b/services/lambda/ddb_esm_test.go index fd0ec94a3b..9c6921b85f 100644 --- a/services/lambda/ddb_esm_test.go +++ b/services/lambda/ddb_esm_test.go @@ -2,13 +2,14 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -260,7 +261,7 @@ func TestLambda_DDB_Poller_InvokesLambdaWithRecords(t *testing.T) { AWSRegion string `json:"awsRegion"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payloads[0], &event)) + require.NoError(t, json.Unmarshal(payloads[0], &event, jsonx.V1())) require.Len(t, event.Records, 2) assert.Equal(t, "event-1", event.Records[0].EventID) diff --git a/services/lambda/delete_function_cleanup_test.go b/services/lambda/delete_function_cleanup_test.go index 1edf60ebad..dc79dab4b1 100644 --- a/services/lambda/delete_function_cleanup_test.go +++ b/services/lambda/delete_function_cleanup_test.go @@ -1,13 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -61,7 +63,7 @@ func TestDeleteFunction_ClearsSideState(t *testing.T) { require.Equal(t, http.StatusOK, aliasListRec.Code) var aliasOut lambda.ListAliasesOutput - require.NoError(t, json.NewDecoder(aliasListRec.Body).Decode(&aliasOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(aliasListRec.Body), &aliasOut, jsonx.V1())) assert.Empty(t, aliasOut.Aliases, "recreated function must not inherit the deleted function's aliases") @@ -70,7 +72,7 @@ func TestDeleteFunction_ClearsSideState(t *testing.T) { require.Equal(t, http.StatusOK, concGetRec.Code) var concOut map[string]any - require.NoError(t, json.NewDecoder(concGetRec.Body).Decode(&concOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(concGetRec.Body), &concOut, jsonx.V1())) assert.NotContains(t, concOut, "ReservedConcurrentExecutions", "recreated function must not inherit the deleted function's reserved concurrency") } diff --git a/services/lambda/dispatch_test.go b/services/lambda/dispatch_test.go index be3fc2493b..1f6713c3e2 100644 --- a/services/lambda/dispatch_test.go +++ b/services/lambda/dispatch_test.go @@ -1,13 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -223,7 +225,7 @@ func TestListFunctionURLConfigs_All(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListFunctionURLConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.FunctionURLConfigs, 2) } @@ -250,7 +252,7 @@ func TestHandlerReset_ClearsState(t *testing.T) { require.Equal(t, http.StatusOK, listCSC.Code) var listOut lambda.ListCodeSigningConfigsOutput - require.NoError(t, json.NewDecoder(listCSC.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listCSC.Body), &listOut, jsonx.V1())) require.NotEmpty(t, listOut.CodeSigningConfigs) // Reset @@ -261,7 +263,7 @@ func TestHandlerReset_ClearsState(t *testing.T) { require.Equal(t, http.StatusOK, listCSC2.Code) var listOut2 lambda.ListCodeSigningConfigsOutput - require.NoError(t, json.NewDecoder(listCSC2.Body).Decode(&listOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listCSC2.Body), &listOut2, jsonx.V1())) assert.Empty(t, listOut2.CodeSigningConfigs) // Verify capacity providers are cleared @@ -269,6 +271,6 @@ func TestHandlerReset_ClearsState(t *testing.T) { require.Equal(t, http.StatusOK, listCP.Code) var listOutCP lambda.ListCapacityProvidersOutput - require.NoError(t, json.NewDecoder(listCP.Body).Decode(&listOutCP)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listCP.Body), &listOutCP, jsonx.V1())) assert.Empty(t, listOutCP.CapacityProviders) } diff --git a/services/lambda/durable_execution_test.go b/services/lambda/durable_execution_test.go index cc2801c685..7954a01139 100644 --- a/services/lambda/durable_execution_test.go +++ b/services/lambda/durable_execution_test.go @@ -1,7 +1,7 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -49,7 +50,7 @@ func TestDurableExecution_GetHistory(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetDurableExecutionHistoryOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Events, 3) assert.Equal(t, "ExecutionStarted", out.Events[0].EventType) assert.Equal(t, "StepStarted", out.Events[1].EventType) @@ -81,7 +82,7 @@ func TestDurableExecution_GetState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetDurableExecutionStateOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Operations, 1) assert.Equal(t, "execution", out.Operations[0].ID) assert.Equal(t, lambda.DurableOperationTypeExecution, out.Operations[0].Type) @@ -111,7 +112,7 @@ func TestDurableExecution_Stop(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var stopOut lambda.StopDurableExecutionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopOut, jsonx.V1())) assert.Positive(t, stopOut.StopTimestamp) rec = callInMemoryHandler(t, h, http.MethodGet, durableExecURL(""), "{}") @@ -212,7 +213,7 @@ func TestDurableExecution_ListByFunction(t *testing.T) { assert.Contains(t, rec.Body.String(), "DurableExecutions") var out lambda.ListDurableExecutionsByFunctionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Neither exec-1 nor exec-2 is associated with "some-func": checkpoint-only // auto-creation has no function-association entry point (see // durableExecutionStore's doc comment) — the correctly wired, correctly @@ -275,7 +276,7 @@ func TestDurableExecution_WireShapeFields(t *testing.T) { rec := callInMemoryHandler(t, h, http.MethodGet, durableExecURL(""), "{}") var out lambda.GetDurableExecutionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, durableExecARN, out.DurableExecutionArn) assert.Equal(t, "test-exec-1", out.DurableExecutionName) assert.NotEqual(t, out.DurableExecutionArn, out.DurableExecutionName) @@ -306,7 +307,7 @@ func TestDurableExecution_WireShapeFields(t *testing.T) { rec := callInMemoryHandler(t, h, http.MethodGet, durableExecURL("")+"?IncludeExecutionData=false", "{}") var out lambda.GetDurableExecutionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.ExecutionDataIncluded) assert.False(t, *out.ExecutionDataIncluded) assert.Nil(t, out.InputPayload) @@ -323,7 +324,7 @@ func TestDurableExecution_WireShapeFields(t *testing.T) { rec := callInMemoryHandler(t, h, http.MethodGet, durableExecURL(""), "{}") var out lambda.GetDurableExecutionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.ExecutionDataIncluded) assert.True(t, *out.ExecutionDataIncluded) }, @@ -346,7 +347,7 @@ func TestDurableExecution_WireShapeFields(t *testing.T) { check: func(t *testing.T, _ *lambda.Handler) { t.Helper() - b, err := json.Marshal(lambda.DurableExecutionStatusTimedOut) + b, err := json.Marshal(lambda.DurableExecutionStatusTimedOut, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, `"TIMED_OUT"`, string(b)) }, @@ -400,7 +401,7 @@ func TestDurableExecution_CheckpointUpdatesOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var checkpointOut lambda.CheckpointDurableExecutionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &checkpointOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &checkpointOut, jsonx.V1())) require.NotNil(t, checkpointOut.NewExecutionState) require.Len(t, checkpointOut.NewExecutionState.Operations, 1) assert.Equal(t, opID, checkpointOut.NewExecutionState.Operations[0].ID) @@ -411,7 +412,7 @@ func TestDurableExecution_CheckpointUpdatesOperations(t *testing.T) { histRec := callInMemoryHandler(t, h, http.MethodGet, durableExecURL("/history"), "{}") var histOut lambda.GetDurableExecutionHistoryOutput - require.NoError(t, json.Unmarshal(histRec.Body.Bytes(), &histOut)) + require.NoError(t, json.Unmarshal(histRec.Body.Bytes(), &histOut, jsonx.V1())) eventTypes := make([]string, 0, len(histOut.Events)) for _, ev := range histOut.Events { @@ -422,7 +423,7 @@ func TestDurableExecution_CheckpointUpdatesOperations(t *testing.T) { stateRec := callInMemoryHandler(t, h, http.MethodGet, durableExecURL("/state"), "{}") var stateOut lambda.GetDurableExecutionStateOutput - require.NoError(t, json.Unmarshal(stateRec.Body.Bytes(), &stateOut)) + require.NoError(t, json.Unmarshal(stateRec.Body.Bytes(), &stateOut, jsonx.V1())) require.Len(t, stateOut.Operations, 2) // implicit root EXECUTION + this one var found bool @@ -506,7 +507,7 @@ func TestDurableExecution_ListByFunctionQueryParams(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListDurableExecutionsByFunctionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) }) } } @@ -562,7 +563,7 @@ func TestDurableExecution_StopVariants(t *testing.T) { if tt.name == "with_custom_error" { var out lambda.GetDurableExecutionOutput - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Error) require.NotNil(t, out.Error.ErrorMessage) assert.Equal(t, "cancelled by operator", *out.Error.ErrorMessage) diff --git a/services/lambda/esm_config_test.go b/services/lambda/esm_config_test.go index a36ae4362f..419d6edf70 100644 --- a/services/lambda/esm_config_test.go +++ b/services/lambda/esm_config_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -33,7 +35,7 @@ func TestESM_HTTPLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) uuid := created["UUID"].(string) // List by function name @@ -78,7 +80,7 @@ func TestESM_BatchWindow(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(60), out["MaximumBatchingWindowInSeconds"], 0) } @@ -98,7 +100,7 @@ func TestESM_TumblingWindow(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(300), out["TumblingWindowInSeconds"], 0) } @@ -117,7 +119,7 @@ func TestESM_FilterCriteria(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) fc, ok := out["FilterCriteria"].(map[string]any) require.True(t, ok) filters := fc["Filters"].([]any) @@ -140,7 +142,7 @@ func TestESM_BisectBatchOnError(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, true, out["BisectBatchOnFunctionError"]) } @@ -160,7 +162,7 @@ func TestESM_MaximumRecordAge(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(3600), out["MaximumRecordAgeInSeconds"], 0) } @@ -180,7 +182,7 @@ func TestESM_ParallelizationFactor(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(5), out["ParallelizationFactor"], 0) } @@ -200,7 +202,7 @@ func TestESM_DestinationConfig(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) dc, ok := out["DestinationConfig"].(map[string]any) require.True(t, ok) onFail := dc["OnFailure"].(map[string]any) @@ -222,7 +224,7 @@ func TestESM_UpdateBatchWindow(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) uuid := created["UUID"].(string) updRec := callInMemoryHandler(t, h, http.MethodPut, @@ -231,7 +233,7 @@ func TestESM_UpdateBatchWindow(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updated map[string]any - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updated)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updated, jsonx.V1())) assert.InDelta(t, float64(30), updated["MaximumBatchingWindowInSeconds"], 0) } @@ -253,7 +255,7 @@ func TestESM_SQS_FullOptions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(10), out["BatchSize"], 0) assert.InDelta(t, float64(5), out["MaximumBatchingWindowInSeconds"], 0) assert.NotNil(t, out["FilterCriteria"]) @@ -279,7 +281,7 @@ func TestESM_DDB_FullOptions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(50), out["BatchSize"], 0) assert.Equal(t, true, out["BisectBatchOnFunctionError"]) assert.InDelta(t, float64(3), out["MaximumRetryAttempts"], 0) @@ -307,7 +309,7 @@ func TestESM_Kinesis_AllWindowOptions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(200), out["BatchSize"], 0) assert.InDelta(t, float64(120), out["MaximumBatchingWindowInSeconds"], 0) assert.InDelta(t, float64(60), out["TumblingWindowInSeconds"], 0) @@ -336,7 +338,7 @@ func TestESM_ListByFunction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) mappings := out["EventSourceMappings"].([]any) assert.Len(t, mappings, 3) } @@ -353,7 +355,7 @@ func TestESM_EnableDisable(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) uuid := created["UUID"].(string) // Disable @@ -365,7 +367,7 @@ func TestESM_EnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updOut map[string]any - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updOut, jsonx.V1())) assert.Equal(t, "Disabled", updOut["State"]) // Re-enable @@ -375,7 +377,7 @@ func TestESM_EnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, enableRec.Code) var enableOut map[string]any - require.NoError(t, json.NewDecoder(enableRec.Body).Decode(&enableOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(enableRec.Body), &enableOut, jsonx.V1())) assert.Equal(t, "Enabled", enableOut["State"]) } @@ -391,7 +393,7 @@ func TestESM_DeleteReturnsMapping(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) uuid := created["UUID"].(string) delRec := callInMemoryHandler(t, h, http.MethodDelete, @@ -399,7 +401,7 @@ func TestESM_DeleteReturnsMapping(t *testing.T) { require.Equal(t, http.StatusOK, delRec.Code) var delOut map[string]any - require.NoError(t, json.NewDecoder(delRec.Body).Decode(&delOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(delRec.Body), &delOut, jsonx.V1())) assert.Equal(t, uuid, delOut["UUID"]) // Get after delete → 404 @@ -425,7 +427,7 @@ func TestESM_MSK_Topics_And_ConsumerGroup(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) topics, _ := out["Topics"].([]any) require.Len(t, topics, 1) @@ -452,7 +454,7 @@ func TestESM_MSK_Get_PreservesConfig(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) id, _ := created["UUID"].(string) require.NotEmpty(t, id) @@ -460,7 +462,7 @@ func TestESM_MSK_Get_PreservesConfig(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &got, jsonx.V1())) topics, _ := got["Topics"].([]any) require.Len(t, topics, 1) @@ -494,7 +496,7 @@ func TestESM_SelfManagedKafka_Create(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) topics, _ := out["Topics"].([]any) require.Len(t, topics, 1) @@ -533,7 +535,7 @@ func TestESM_SelfManagedKafka_UpdateSourceAccessConfigs(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) id := created["UUID"].(string) updateBody := `{ @@ -546,7 +548,7 @@ func TestESM_SelfManagedKafka_UpdateSourceAccessConfigs(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(updateRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updateRec.Body), &out, jsonx.V1())) sacs, _ := out["SourceAccessConfigurations"].([]any) assert.Len(t, sacs, 2) @@ -570,7 +572,7 @@ func TestESM_AmazonMQ_Queues(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queues, _ := out["Queues"].([]any) require.Len(t, queues, 1) @@ -600,7 +602,7 @@ func TestESM_DocumentDB_Create(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) docdb, _ := out["DocumentDBEventSourceConfig"].(map[string]any) require.NotNil(t, docdb) @@ -627,14 +629,14 @@ func TestESM_DocumentDB_Get_PreservesConfig(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) id := created["UUID"].(string) getRec := callInMemoryHandler(t, h, http.MethodGet, "/2015-03-31/event-source-mappings/"+id, "") require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &got, jsonx.V1())) docdb, _ := got["DocumentDBEventSourceConfig"].(map[string]any) require.NotNil(t, docdb) @@ -657,7 +659,7 @@ func TestESM_DocumentDB_NoCollectionName_Omitted(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) docdb, _ := out["DocumentDBEventSourceConfig"].(map[string]any) require.NotNil(t, docdb) @@ -713,7 +715,7 @@ func TestSourceAccessConfiguration_TypeAndURI(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) sacs, _ := out["SourceAccessConfigurations"].([]any) require.Len(t, sacs, 1) @@ -779,7 +781,7 @@ func TestListESM_EventSourceArnFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) esms, _ := out["EventSourceMappings"].([]any) assert.Len(t, esms, tc.wantCount, "EventSourceMappings count mismatch for filter=%q", tc.filter) diff --git a/services/lambda/esm_failure.go b/services/lambda/esm_failure.go index 4a944f7fba..c1f9f0e447 100644 --- a/services/lambda/esm_failure.go +++ b/services/lambda/esm_failure.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "slices" @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -211,7 +212,7 @@ func logDeliveryFailure(ctx context.Context, uuidStr, dest string, err error) { } func marshalFailure(rec failureRecord) ([]byte, error) { - body, err := json.Marshal(rec) + body, err := json.Marshal(rec, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal failure record: %w", err) } diff --git a/services/lambda/esm_failure_internal_test.go b/services/lambda/esm_failure_internal_test.go index 5ed0c92b51..c31639d2c3 100644 --- a/services/lambda/esm_failure_internal_test.go +++ b/services/lambda/esm_failure_internal_test.go @@ -2,7 +2,8 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" "sync" @@ -12,6 +13,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type deliveredMsg struct { @@ -130,10 +133,10 @@ func newFailureHarness( defer mu.Unlock() var ev struct { - Records []json.RawMessage `json:"Records"` + Records []jsontext.Value `json:"Records"` } - require.NoError(t, json.Unmarshal(payload, &ev)) + require.NoError(t, json.Unmarshal(payload, &ev, jsonx.V1())) *h.calls = append(*h.calls, len(ev.Records)) if failOn(string(payload)) { @@ -321,7 +324,7 @@ func TestStreamRetryAndOnFailureDestination(t *testing.T) { } `json:"requestContext"` } - require.NoError(t, json.Unmarshal(body, &rec)) + require.NoError(t, json.Unmarshal(body, &rec, jsonx.V1())) assert.Equal(t, "RetryAttemptsExhausted", rec.RequestContext.Condition) assert.Equal(t, testFnARN, rec.RequestContext.FunctionArn) assert.Equal(t, tt.wantInvokeCnt, rec.RequestContext.Count) @@ -470,7 +473,7 @@ func TestKafkaRetryExhaustionDestinations(t *testing.T) { } `json:"KafkaBatchInfo"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.Equal(t, "RetryAttemptsExhausted", out.RequestContext.Condition) assert.Equal(t, "0", out.KafkaBatchInfo.RecordInfo.Offset) assert.Equal(t, 1, out.KafkaBatchInfo.BatchSize) @@ -642,7 +645,7 @@ func TestESMSystemLogLevels(t *testing.T) { Processor string `json:"eventProcessorId"` } - require.NoError(t, json.Unmarshal([]byte(line), &rec)) + require.NoError(t, json.Unmarshal([]byte(line), &rec, jsonx.V1())) assert.Equal(t, "u-3/0", rec.Processor) got = append(got, rec.EventType) @@ -781,7 +784,7 @@ func TestDynamoDBStreamOnFailureDestination(t *testing.T) { } `json:"requestContext"` } - require.NoError(t, json.Unmarshal(del.msgs[0].body, &out)) + require.NoError(t, json.Unmarshal(del.msgs[0].body, &out, jsonx.V1())) assert.Equal(t, "800000000003126276362", out.Info.Start) assert.Equal(t, "2019-11-14T00:13:19Z", out.Info.First) assert.Equal(t, streamARN, out.Info.StreamArn) @@ -807,7 +810,7 @@ func TestESMMaximumRetryAttemptsWire(t *testing.T) { t.Parallel() m := &EventSourceMapping{FunctionARN: testFnARN, MaximumRetryAttempts: tt.in} - body, err := json.Marshal(toJSONESMResponse(m)) + body, err := json.Marshal(toJSONESMResponse(m), jsonx.V1()) require.NoError(t, err) if tt.want == "" { diff --git a/services/lambda/esm_kafka_failure.go b/services/lambda/esm_kafka_failure.go index 7ce353dd11..4cf13e0a6e 100644 --- a/services/lambda/esm_kafka_failure.go +++ b/services/lambda/esm_kafka_failure.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "strconv" @@ -117,7 +117,7 @@ func (p *EventSourcePoller) deliverKafkaFailure( switch { case strings.HasPrefix(dest, kafkaDestinationPrefix): - rec.Payload = json.RawMessage(event) + rec.Payload = jsontext.Value(event) body, mErr := marshalFailure(rec) if mErr != nil { return mErr diff --git a/services/lambda/esm_logging.go b/services/lambda/esm_logging.go index 8bec9b6bab..95a45512ef 100644 --- a/services/lambda/esm_logging.go +++ b/services/lambda/esm_logging.go @@ -2,11 +2,12 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "maps" "strconv" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -97,7 +98,7 @@ func (l esmLogger) emit(ctx context.Context, at, eventType string, extra map[str maps.Copy(rec, extra) - body, err := json.Marshal(rec) + body, err := json.Marshal(rec, jsonx.V1()) if err != nil { return } diff --git a/services/lambda/esm_partial_batch_test.go b/services/lambda/esm_partial_batch_test.go index 446428065b..032eab635f 100644 --- a/services/lambda/esm_partial_batch_test.go +++ b/services/lambda/esm_partial_batch_test.go @@ -2,13 +2,14 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -204,7 +205,7 @@ func TestLambda_ESM_FunctionResponseTypes_StoredAndRetrieved(t *testing.T) { } func mustMarshal(v any) []byte { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { panic(err) } diff --git a/services/lambda/esm_stream_retry.go b/services/lambda/esm_stream_retry.go index 8330cc8f28..9b8a38ae00 100644 --- a/services/lambda/esm_stream_retry.go +++ b/services/lambda/esm_stream_retry.go @@ -3,13 +3,15 @@ package lambda import ( "cmp" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "time" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -18,7 +20,7 @@ type streamEvent struct { arrival time.Time seq string key string - raw json.RawMessage + raw jsontext.Value } // streamBatch is a batch awaiting a successful invocation. @@ -39,14 +41,14 @@ type streamShardRef struct { } func streamEventPayload(events []streamEvent) ([]byte, error) { - raws := make([]json.RawMessage, len(events)) + raws := make([]jsontext.Value, len(events)) for i, e := range events { raws[i] = e.raw } return json.Marshal(struct { - Records []json.RawMessage `json:"Records"` - }{Records: raws}) + Records []jsontext.Value `json:"Records"` + }{Records: raws}, jsonx.V1()) } func (p *EventSourcePoller) frontStreamBatch(key string) *streamBatch { diff --git a/services/lambda/esm_stream_window.go b/services/lambda/esm_stream_window.go index 13374b33d2..0c3531d931 100644 --- a/services/lambda/esm_stream_window.go +++ b/services/lambda/esm_stream_window.go @@ -3,7 +3,8 @@ package lambda import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "hash/fnv" "math" @@ -12,6 +13,8 @@ import ( "strings" "sync" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -30,7 +33,7 @@ var ( type tumblingWindow struct { start time.Time end time.Time - state json.RawMessage + state jsontext.Value finalQueued bool } @@ -289,13 +292,13 @@ type windowRange struct { } type windowedPayload struct { - State json.RawMessage `json:"state"` - Window windowRange `json:"window"` - ShardID string `json:"shardId"` - EventSourceARN string `json:"eventSourceARN"` - Records []json.RawMessage `json:"Records"` - IsFinalInvokeForWindow bool `json:"isFinalInvokeForWindow"` - IsWindowTerminatedEarly bool `json:"isWindowTerminatedEarly"` + State jsontext.Value `json:"state"` + Window windowRange `json:"window"` + ShardID string `json:"shardId"` + EventSourceARN string `json:"eventSourceARN"` + Records []jsontext.Value `json:"Records"` + IsFinalInvokeForWindow bool `json:"isFinalInvokeForWindow"` + IsWindowTerminatedEarly bool `json:"isWindowTerminatedEarly"` } func (p *EventSourcePoller) streamBatchPayload( @@ -310,10 +313,10 @@ func (p *EventSourcePoller) streamBatchPayload( p.mu.RUnlock() if len(state) == 0 { - state = json.RawMessage(emptyJSONObject) + state = jsontext.Value(emptyJSONObject) } - raws := make([]json.RawMessage, len(b.events)) + raws := make([]jsontext.Value, len(b.events)) for i, e := range b.events { raws[i] = e.raw } @@ -329,21 +332,21 @@ func (p *EventSourcePoller) streamBatchPayload( EventSourceARN: m.EventSourceARN, IsFinalInvokeForWindow: b.final, IsWindowTerminatedEarly: b.early, - }) + }, jsonx.V1()) } // windowResponseState extracts the required state property of a tumbling-window response. -func windowResponseState(body []byte) (json.RawMessage, bool) { +func windowResponseState(body []byte) (jsontext.Value, bool) { var resp struct { - State *json.RawMessage `json:"state"` + State *jsontext.Value `json:"state"` } - if err := json.Unmarshal(body, &resp); err != nil || resp.State == nil { + if err := json.Unmarshal(body, &resp, jsonx.V1()); err != nil || resp.State == nil { return nil, false } if bytes.Equal(bytes.TrimSpace(*resp.State), []byte("null")) { - return json.RawMessage(emptyJSONObject), true + return jsontext.Value(emptyJSONObject), true } return *resp.State, true @@ -358,7 +361,8 @@ func batchFailureIndex(body []byte, events []streamEvent) int { } `json:"batchItemFailures"` } - if len(bytes.TrimSpace(body)) == 0 || json.Unmarshal(body, &resp) != nil || len(resp.BatchItemFailures) == 0 { + if len(bytes.TrimSpace(body)) == 0 || json.Unmarshal(body, &resp, jsonx.V1()) != nil || + len(resp.BatchItemFailures) == 0 { return -1 } diff --git a/services/lambda/esm_stream_window_internal_test.go b/services/lambda/esm_stream_window_internal_test.go index cec3b22455..cc816d27b3 100644 --- a/services/lambda/esm_stream_window_internal_test.go +++ b/services/lambda/esm_stream_window_internal_test.go @@ -2,7 +2,8 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" "sync" @@ -11,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type scriptedKinesisReader struct { @@ -39,13 +42,13 @@ func (r *scriptedKinesisReader) GetRecords(string, int) ([]KinesisRecord, string } type streamCall struct { - Window *windowRange `json:"window"` - State map[string]any `json:"state"` - ShardID string `json:"shardId"` - EventSourceARN string `json:"eventSourceARN"` - Records []json.RawMessage `json:"Records"` - IsFinalInvokeForWindow bool `json:"isFinalInvokeForWindow"` - IsWindowTerminatedEarly bool `json:"isWindowTerminatedEarly"` + Window *windowRange `json:"window"` + State map[string]any `json:"state"` + ShardID string `json:"shardId"` + EventSourceARN string `json:"eventSourceARN"` + Records []jsontext.Value `json:"Records"` + IsFinalInvokeForWindow bool `json:"isFinalInvokeForWindow"` + IsWindowTerminatedEarly bool `json:"isWindowTerminatedEarly"` } func (c streamCall) seqs(t *testing.T) []string { @@ -60,7 +63,7 @@ func (c streamCall) seqs(t *testing.T) []string { } `json:"kinesis"` } - require.NoError(t, json.Unmarshal(r, &rec)) + require.NoError(t, json.Unmarshal(r, &rec, jsonx.V1())) out = append(out, rec.Kinesis.Seq) } @@ -104,7 +107,7 @@ func newStreamHarness( h.p.streamInvoker = func(_ context.Context, _ string, payload []byte) invokeOutcome { var c streamCall - require.NoError(t, json.Unmarshal(payload, &c)) + require.NoError(t, json.Unmarshal(payload, &c, jsonx.V1())) h.mu.Lock() h.calls = append(h.calls, c) @@ -229,7 +232,7 @@ func TestStreamParallelizationFactor(t *testing.T) { } `json:"kinesis"` } - require.NoError(t, json.Unmarshal(r, &rec)) + require.NoError(t, json.Unmarshal(r, &rec, jsonx.V1())) l := laneIndex(rec.Kinesis.PK, tt.factor) if laneOf >= 0 { @@ -360,7 +363,7 @@ func TestStreamTumblingWindow(t *testing.T) { assert.Equal(t, testKinesisARN, c.EventSourceARN) require.NotNil(t, c.Window) - state, err := json.Marshal(c.State) + state, err := json.Marshal(c.State, jsonx.V1()) require.NoError(t, err) assert.JSONEq(t, w.state, string(state), "call %d", i) } @@ -676,7 +679,7 @@ func TestStreamDynamoDBParallelizationKeepsItemOrder(t *testing.T) { } `json:"Records"` } - require.NoError(t, json.Unmarshal(payload, &ev)) + require.NoError(t, json.Unmarshal(payload, &ev, jsonx.V1())) got := make([]string, 0, len(ev.Records)) for _, r := range ev.Records { diff --git a/services/lambda/esm_test.go b/services/lambda/esm_test.go index 13062ac39a..ffa10c8e5e 100644 --- a/services/lambda/esm_test.go +++ b/services/lambda/esm_test.go @@ -2,7 +2,7 @@ package lambda_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -37,7 +38,7 @@ func doESMRequest(t *testing.T, h *lambda.Handler, method, path string, body any var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -87,7 +88,7 @@ func TestLambda_ESM_FilterCriteria_RoundTrip(t *testing.T) { } `json:"Filters"` } `json:"FilterCriteria"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) require.NotEmpty(t, createResp.UUID) require.Len(t, createResp.FilterCriteria.Filters, 1) assert.JSONEq(t, `{"data":{"orderType":["premium"]}}`, createResp.FilterCriteria.Filters[0].Pattern) @@ -113,7 +114,7 @@ func TestLambda_ESM_FilterCriteria_RoundTrip(t *testing.T) { } `json:"Filters"` } `json:"FilterCriteria"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) require.Len(t, getResp.FilterCriteria.Filters, 1) assert.JSONEq(t, `{"data":{"orderType":["standard"]}}`, getResp.FilterCriteria.Filters[0].Pattern) } @@ -144,7 +145,7 @@ func TestLambda_ESM_CRUD(t *testing.T) { State string `json:"State"` BatchSize int `json:"BatchSize"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotEmpty(t, createResp.UUID) assert.Equal(t, streamARN, createResp.EventSourceARN) assert.Equal(t, "Enabled", createResp.State) @@ -160,7 +161,7 @@ func TestLambda_ESM_CRUD(t *testing.T) { UUID string `json:"UUID"` State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, esmUUID, getResp.UUID) // ListEventSourceMappings @@ -172,7 +173,7 @@ func TestLambda_ESM_CRUD(t *testing.T) { UUID string `json:"UUID"` } `json:"EventSourceMappings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.EventSourceMappings, 1) assert.Equal(t, esmUUID, listResp.EventSourceMappings[0].UUID) @@ -204,7 +205,7 @@ func TestLambda_ESM_CreateDisabled(t *testing.T) { var resp struct { State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Disabled", resp.State) } @@ -226,7 +227,7 @@ func TestLambda_ESM_CreateNilEnabled(t *testing.T) { var resp struct { State string `json:"State"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Enabled", resp.State) } @@ -256,7 +257,7 @@ func TestLambda_ESM_ListByFunctionName(t *testing.T) { var allResp struct { EventSourceMappings []any `json:"EventSourceMappings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &allResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &allResp, jsonx.V1())) assert.Len(t, allResp.EventSourceMappings, 2) // List for function-a only @@ -268,7 +269,7 @@ func TestLambda_ESM_ListByFunctionName(t *testing.T) { FunctionARN string `json:"FunctionArn"` } `json:"EventSourceMappings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtResp, jsonx.V1())) assert.Len(t, filtResp.EventSourceMappings, 1) assert.Contains(t, filtResp.EventSourceMappings[0].FunctionARN, "function-a") } diff --git a/services/lambda/esm_tuning_validation_test.go b/services/lambda/esm_tuning_validation_test.go index 408e4ce3f2..723acdf96b 100644 --- a/services/lambda/esm_tuning_validation_test.go +++ b/services/lambda/esm_tuning_validation_test.go @@ -1,12 +1,14 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestESM_TuningValidation(t *testing.T) { @@ -124,7 +126,7 @@ func TestESM_UpdateTuningValidation(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) uuid, _ := created["UUID"].(string) diff --git a/services/lambda/event_filter.go b/services/lambda/event_filter.go index 063b34bf40..9b5927c447 100644 --- a/services/lambda/event_filter.go +++ b/services/lambda/event_filter.go @@ -2,10 +2,13 @@ package lambda import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // eventFilterMatches reports whether the given event source record satisfies the @@ -29,8 +32,8 @@ func eventFilterMatches(fc *FilterCriteria, record map[string]any) bool { continue } - var pattern map[string]json.RawMessage - if err := json.Unmarshal([]byte(f.Pattern), &pattern); err != nil { + var pattern map[string]jsontext.Value + if err := json.Unmarshal([]byte(f.Pattern), &pattern, jsonx.V1()); err != nil { continue } @@ -47,7 +50,7 @@ func eventFilterMatches(fc *FilterCriteria, record map[string]any) bool { // the "$or" combinator documented for "Or (multiple fields)": its value is an // array of sibling pattern fragments evaluated against the same value, and the // object matches only if at least one fragment does. -func patternMatchesObject(pattern map[string]json.RawMessage, value map[string]any) bool { +func patternMatchesObject(pattern map[string]jsontext.Value, value map[string]any) bool { for key, rawRule := range pattern { if key == "$or" { if !orClauseMatches(rawRule, value) { @@ -69,15 +72,15 @@ func patternMatchesObject(pattern map[string]json.RawMessage, value map[string]a // orClauseMatches evaluates a "$or" array of sibling pattern-fragment objects // against value, matching if any fragment matches. -func orClauseMatches(rawRule json.RawMessage, value map[string]any) bool { - var branches []json.RawMessage - if err := json.Unmarshal(rawRule, &branches); err != nil { +func orClauseMatches(rawRule jsontext.Value, value map[string]any) bool { + var branches []jsontext.Value + if err := json.Unmarshal(rawRule, &branches, jsonx.V1()); err != nil { return false } for _, branch := range branches { - var branchPattern map[string]json.RawMessage - if err := json.Unmarshal(branch, &branchPattern); err != nil { + var branchPattern map[string]jsontext.Value + if err := json.Unmarshal(branch, &branchPattern, jsonx.V1()); err != nil { continue } @@ -91,7 +94,7 @@ func orClauseMatches(rawRule json.RawMessage, value map[string]any) bool { // fieldMatchesRule evaluates a single pattern field. rawRule is either a nested // pattern object (recurse) or a JSON array of match rules (any of which may match). -func fieldMatchesRule(rawRule json.RawMessage, fieldVal any, present bool) bool { +func fieldMatchesRule(rawRule jsontext.Value, fieldVal any, present bool) bool { trimmed := strings.TrimSpace(string(rawRule)) // Nested object pattern: recurse into the sub-document. @@ -101,8 +104,8 @@ func fieldMatchesRule(rawRule json.RawMessage, fieldVal any, present bool) bool return false } - var subPattern map[string]json.RawMessage - if err := json.Unmarshal(rawRule, &subPattern); err != nil { + var subPattern map[string]jsontext.Value + if err := json.Unmarshal(rawRule, &subPattern, jsonx.V1()); err != nil { return false } @@ -110,8 +113,8 @@ func fieldMatchesRule(rawRule json.RawMessage, fieldVal any, present bool) bool } // Rule array: the field matches if any element in the array matches. - var rules []json.RawMessage - if err := json.Unmarshal(rawRule, &rules); err != nil { + var rules []jsontext.Value + if err := json.Unmarshal(rawRule, &rules, jsonx.V1()); err != nil { return false } @@ -126,7 +129,7 @@ func fieldMatchesRule(rawRule json.RawMessage, fieldVal any, present bool) bool // ruleMatchesValue evaluates one rule element against the field value. A rule is // either a scalar (exact match) or an operator object like {"prefix":"x"}. -func ruleMatchesValue(rule json.RawMessage, fieldVal any, present bool) bool { +func ruleMatchesValue(rule jsontext.Value, fieldVal any, present bool) bool { trimmed := strings.TrimSpace(string(rule)) if strings.HasPrefix(trimmed, "{") { @@ -137,13 +140,13 @@ func ruleMatchesValue(rule json.RawMessage, fieldVal any, present bool) bool { } // scalarMatches performs an exact comparison between a scalar rule and the field. -func scalarMatches(rule json.RawMessage, fieldVal any, present bool) bool { +func scalarMatches(rule jsontext.Value, fieldVal any, present bool) bool { if !present { return false } var ruleVal any - if err := json.Unmarshal(rule, &ruleVal); err != nil { + if err := json.Unmarshal(rule, &ruleVal, jsonx.V1()); err != nil { return false } @@ -169,9 +172,9 @@ func scalarMatches(rule json.RawMessage, fieldVal any, present bool) bool { // operatorMatches evaluates an operator rule object such as {"prefix":"x"}, // {"exists":true}, {"anything-but":[...]}, or {"numeric":[">",5]}. -func operatorMatches(rule json.RawMessage, fieldVal any, present bool) bool { - var op map[string]json.RawMessage - if err := json.Unmarshal(rule, &op); err != nil { +func operatorMatches(rule jsontext.Value, fieldVal any, present bool) bool { + var op map[string]jsontext.Value + if err := json.Unmarshal(rule, &op, jsonx.V1()); err != nil { return false } @@ -185,7 +188,7 @@ func operatorMatches(rule json.RawMessage, fieldVal any, present bool) bool { } // singleOperatorMatches dispatches one named operator. -func singleOperatorMatches(name string, arg json.RawMessage, fieldVal any, present bool) bool { +func singleOperatorMatches(name string, arg jsontext.Value, fieldVal any, present bool) bool { switch name { case "exists": return existsMatches(arg, fieldVal, present) @@ -209,9 +212,9 @@ func singleOperatorMatches(name string, arg json.RawMessage, fieldVal any, prese // match intermediate nodes" -- a field present as a nested object is an // intermediate node, not a leaf, so it never satisfies exists regardless of // the requested polarity. -func existsMatches(arg json.RawMessage, fieldVal any, present bool) bool { +func existsMatches(arg jsontext.Value, fieldVal any, present bool) bool { var want bool - if err := json.Unmarshal(arg, &want); err != nil { + if err := json.Unmarshal(arg, &want, jsonx.V1()); err != nil { return false } @@ -222,13 +225,13 @@ func existsMatches(arg json.RawMessage, fieldVal any, present bool) bool { return want == present } -func affixMatches(arg json.RawMessage, fieldVal any, present bool, fn func(string, string) bool) bool { +func affixMatches(arg jsontext.Value, fieldVal any, present bool, fn func(string, string) bool) bool { if !present { return false } var want string - if err := json.Unmarshal(arg, &want); err != nil { + if err := json.Unmarshal(arg, &want, jsonx.V1()); err != nil { return false } @@ -237,13 +240,13 @@ func affixMatches(arg json.RawMessage, fieldVal any, present bool, fn func(strin return ok && fn(fv, want) } -func equalsIgnoreCaseMatches(arg json.RawMessage, fieldVal any, present bool) bool { +func equalsIgnoreCaseMatches(arg jsontext.Value, fieldVal any, present bool) bool { if !present { return false } var want string - if err := json.Unmarshal(arg, &want); err != nil { + if err := json.Unmarshal(arg, &want, jsonx.V1()); err != nil { return false } @@ -254,7 +257,7 @@ func equalsIgnoreCaseMatches(arg json.RawMessage, fieldVal any, present bool) bo // anythingButMatches matches when the field is present and NOT equal to any of // the listed values. The argument may be a scalar or an array of scalars. -func anythingButMatches(arg json.RawMessage, fieldVal any, present bool) bool { +func anythingButMatches(arg jsontext.Value, fieldVal any, present bool) bool { if !present { return false } @@ -264,8 +267,8 @@ func anythingButMatches(arg json.RawMessage, fieldVal any, present bool) bool { return !scalarMatches(arg, fieldVal, present) } - var values []json.RawMessage - if err := json.Unmarshal(arg, &values); err != nil { + var values []jsontext.Value + if err := json.Unmarshal(arg, &values, jsonx.V1()); err != nil { return false } @@ -279,7 +282,7 @@ func anythingButMatches(arg json.RawMessage, fieldVal any, present bool) bool { } // numericMatches evaluates a numeric rule like ["=",1] or [">",0,"<=",10]. -func numericMatches(arg json.RawMessage, fieldVal any, present bool) bool { +func numericMatches(arg jsontext.Value, fieldVal any, present bool) bool { if !present { return false } @@ -289,19 +292,19 @@ func numericMatches(arg json.RawMessage, fieldVal any, present bool) bool { return false } - var tokens []json.RawMessage - if err := json.Unmarshal(arg, &tokens); err != nil { + var tokens []jsontext.Value + if err := json.Unmarshal(arg, &tokens, jsonx.V1()); err != nil { return false } for i := 0; i+1 < len(tokens); i += 2 { var operator string - if err := json.Unmarshal(tokens[i], &operator); err != nil { + if err := json.Unmarshal(tokens[i], &operator, jsonx.V1()); err != nil { return false } var operand float64 - if err := json.Unmarshal(tokens[i+1], &operand); err != nil { + if err := json.Unmarshal(tokens[i+1], &operand, jsonx.V1()); err != nil { return false } @@ -339,7 +342,7 @@ func toFloat(v any) (float64, bool) { switch n := v.(type) { case float64: return n, true - case json.Number: + case jsonx.Number: f, err := n.Float64() return f, err == nil @@ -440,7 +443,7 @@ func parseJSONObjectBytes(b []byte) (map[string]any, bool) { } var obj map[string]any - if err := json.Unmarshal(b, &obj); err != nil { + if err := json.Unmarshal(b, &obj, jsonx.V1()); err != nil { return nil, false } diff --git a/services/lambda/event_invoke_config_test.go b/services/lambda/event_invoke_config_test.go index 2f669779b9..6f96052867 100644 --- a/services/lambda/event_invoke_config_test.go +++ b/services/lambda/event_invoke_config_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -150,7 +152,7 @@ func TestPutFunctionEventInvokeConfig(t *testing.T) { if tt.wantRetries != nil || tt.wantAge != nil { var cfg lambda.FunctionEventInvokeConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) if tt.wantRetries != nil { require.NotNil(t, cfg.MaximumRetryAttempts) @@ -186,7 +188,7 @@ func TestFunctionEventInvokeConfig_LastModifiedIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) lastModified, ok := raw["LastModified"] require.True(t, ok, "response must include LastModified") @@ -358,7 +360,7 @@ func TestUpdateFunctionEventInvokeConfig(t *testing.T) { if tt.wantRetries != nil { var cfg lambda.FunctionEventInvokeConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) require.NotNil(t, cfg.MaximumRetryAttempts) assert.Equal(t, *tt.wantRetries, *cfg.MaximumRetryAttempts) } @@ -518,7 +520,7 @@ func TestListFunctionEventInvokeConfigs(t *testing.T) { } var out lambda.ListFunctionEventInvokeConfigsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.FunctionEventInvokeConfigs, tt.wantCount) }) } @@ -709,7 +711,7 @@ func TestEventInvokeConfig_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var cfg lambda.FunctionEventInvokeConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &cfg, jsonx.V1())) require.NotNil(t, cfg.MaximumRetryAttempts) assert.Equal(t, maxRetry, *cfg.MaximumRetryAttempts) require.NotNil(t, cfg.MaximumEventAgeInSeconds) @@ -721,7 +723,7 @@ func TestEventInvokeConfig_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getCfg lambda.FunctionEventInvokeConfig - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getCfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getCfg, jsonx.V1())) assert.Equal(t, maxRetry, *getCfg.MaximumRetryAttempts) // Update config @@ -736,7 +738,7 @@ func TestEventInvokeConfig_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListFunctionEventInvokeConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.NotEmpty(t, listOut.FunctionEventInvokeConfigs) // Delete config @@ -767,7 +769,7 @@ func TestEventInvokeConfig_WithDestinations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cfg lambda.FunctionEventInvokeConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) require.NotNil(t, cfg.DestinationConfig) require.NotNil(t, cfg.DestinationConfig.OnSuccess) assert.Contains(t, cfg.DestinationConfig.OnSuccess.Destination, "success-q") @@ -802,7 +804,7 @@ func TestFunctionDestinations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.FunctionEventInvokeConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.DestinationConfig) require.NotNil(t, out.DestinationConfig.OnSuccess) require.NotNil(t, out.DestinationConfig.OnFailure) diff --git a/services/lambda/event_source_poller.go b/services/lambda/event_source_poller.go index 2b0763b355..ee36106443 100644 --- a/services/lambda/event_source_poller.go +++ b/services/lambda/event_source_poller.go @@ -3,7 +3,7 @@ package lambda import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" @@ -11,6 +11,7 @@ import ( "time" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -641,7 +642,7 @@ func (p *EventSourcePoller) invokeLambda( InvokeIdentityArn: m.FunctionARN, AWSRegion: p.lambdaBackend.region, EventSourceARN: m.EventSourceARN, - }) + }, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "event source poller: failed to marshal event", "error", err) @@ -863,7 +864,7 @@ func (p *EventSourcePoller) invokeLambdaForDDB( NewImage: r.NewImage, OldImage: r.OldImage, }, - }) + }, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "event source poller: failed to marshal DDB event", "error", err) @@ -876,7 +877,7 @@ func (p *EventSourcePoller) invokeLambdaForDDB( arrival = time.Time{} } - keyJSON, _ := json.Marshal(r.Keys) + keyJSON, _ := json.Marshal(r.Keys, jsonx.V1()) events = append(events, streamEvent{arrival: arrival, seq: r.SequenceNumber, key: string(keyJSON), raw: raw}) } @@ -1068,7 +1069,7 @@ func buildSQSEventPayload(region, esmARN string, msgs []*SQSMessage) ([]byte, er } } - payload, err := json.Marshal(sqsEvent{Records: records}) + payload, err := json.Marshal(sqsEvent{Records: records}, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal sqs event: %w", err) } @@ -1161,7 +1162,12 @@ func filterByBatchItemFailures(reportFailures bool, respBody []byte, msgs []*SQS } var failures batchItemFailures - if jsonErr := json.Unmarshal(respBody, &failures); jsonErr != nil || len(failures.BatchItemFailures) == 0 { + if jsonErr := json.Unmarshal( + respBody, + &failures, + jsonx.V1(), + ); jsonErr != nil || + len(failures.BatchItemFailures) == 0 { return nil } diff --git a/services/lambda/event_source_poller_test.go b/services/lambda/event_source_poller_test.go index 3a8ef8defc..4a9865edf3 100644 --- a/services/lambda/event_source_poller_test.go +++ b/services/lambda/event_source_poller_test.go @@ -2,7 +2,7 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -248,7 +249,7 @@ func TestLambda_BuildSQSEventPayload(t *testing.T) { EventSourceARN string `json:"eventSourceARN"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) require.Len(t, event.Records, 1) rec := event.Records[0] diff --git a/services/lambda/extensions_api.go b/services/lambda/extensions_api.go index 906d1c3610..598fec872e 100644 --- a/services/lambda/extensions_api.go +++ b/services/lambda/extensions_api.go @@ -2,7 +2,8 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -197,7 +199,7 @@ type registerResponse struct { func writeExtError(w http.ResponseWriter, status int, typ, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(extensionError{Type: typ, Message: msg}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), extensionError{Type: typ, Message: msg}) } // register adds an extension; it returns the response, identifier or an HTTP failure. @@ -290,7 +292,7 @@ func (r *extensionRegistry) fanoutInvoke(reqID string, deadline time.Time, fnARN body["tracing"] = map[string]string{"type": "X-Amzn-Trace-Id", "value": trace} } - raw, _ := json.Marshal(body) + raw, _ := json.Marshal(body, jsonx.V1()) wait := &invokeWait{pending: map[string]struct{}{}, done: make(chan struct{}), deadline: deadline} for id, ext := range r.exts { @@ -433,7 +435,7 @@ func (r *extensionRegistry) shutdown(ctx context.Context, reason string) { deadline := time.Now().Add(r.shutdownTimeout) raw, _ := json.Marshal(map[string]any{ jsonKeyEventType: extEventShutdown, "shutdownReason": reason, "deadlineMs": deadline.UnixMilli(), - }) + }, jsonx.V1()) var taken []chan struct{} @@ -488,7 +490,7 @@ func (s *runtimeServer) handleExtensionRegister(w http.ResponseWriter, r *http.R body, _ := io.ReadAll(http.MaxBytesReader(w, r.Body, maxExtensionBodyBytes)) if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { writeExtError(w, http.StatusBadRequest, "Extension.InvalidRequestBody", "malformed registration body") return @@ -512,7 +514,7 @@ func (s *runtimeServer) handleExtensionRegister(w http.ResponseWriter, r *http.R w.Header().Set(headerExtensionID, id) w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(resp) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), resp) } // handleExtensionNext serves GET /2020-01-01/extension/event/next (long poll). diff --git a/services/lambda/extensions_api_internal_test.go b/services/lambda/extensions_api_internal_test.go index 428d36c629..ee6799a254 100644 --- a/services/lambda/extensions_api_internal_test.go +++ b/services/lambda/extensions_api_internal_test.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -82,7 +83,7 @@ func (h *extHarness) do( func (h *extHarness) register(t *testing.T, name string, events ...string) string { t.Helper() - b, err := json.Marshal(map[string]any{"events": events}) + b, err := json.Marshal(map[string]any{"events": events}, jsonx.V1()) require.NoError(t, err) status, hdr, body := h.do(t, http.MethodPost, "/2020-01-01/extension/register", @@ -177,7 +178,7 @@ func TestExtensionRegister(t *testing.T) { if tt.wantStatus != http.StatusOK { var e extensionError - require.NoError(t, json.Unmarshal([]byte(body), &e)) + require.NoError(t, json.Unmarshal([]byte(body), &e, jsonx.V1())) assert.Equal(t, tt.wantType, e.Type) return @@ -187,7 +188,7 @@ func TestExtensionRegister(t *testing.T) { var resp map[string]string - require.NoError(t, json.Unmarshal([]byte(body), &resp)) + require.NoError(t, json.Unmarshal([]byte(body), &resp, jsonx.V1())) assert.Equal(t, "ext-fn", resp["functionName"]) assert.Equal(t, "$LATEST", resp["functionVersion"]) assert.Equal(t, "index.handler", resp["handler"]) @@ -250,7 +251,7 @@ func TestExtensionInvokeFanout(t *testing.T) { var ev map[string]any - require.NoError(t, json.Unmarshal([]byte(<-otherEv), &ev)) + require.NoError(t, json.Unmarshal([]byte(<-otherEv), &ev, jsonx.V1())) assert.Equal(t, "INVOKE", ev["eventType"]) assert.Equal(t, reqID, ev["requestId"]) assert.Equal(t, extTestFnARN, ev["invokedFunctionArn"]) @@ -337,7 +338,7 @@ func TestExtensionShutdown(t *testing.T) { var got map[string]any - require.NoError(t, json.Unmarshal([]byte(<-ev), &got)) + require.NoError(t, json.Unmarshal([]byte(<-ev), &got, jsonx.V1())) assert.Equal(t, "SHUTDOWN", got["eventType"]) assert.Equal(t, tt.wantReason, got["shutdownReason"]) assert.Positive(t, got["deadlineMs"]) diff --git a/services/lambda/fis.go b/services/lambda/fis.go index 3558dc44fb..6dd891fe95 100644 --- a/services/lambda/fis.go +++ b/services/lambda/fis.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "math/rand/v2" "net/http" @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -338,7 +339,7 @@ func (b *InMemoryBackend) applyFISFaultToInvocation( errPayload, _ := json.Marshal(map[string]string{ "errorMessage": faultErr.Error(), "errorType": "FISFaultInjection", - }) + }, jsonx.V1()) return errPayload, http.StatusOK, nil } diff --git a/services/lambda/function_fields_test.go b/services/lambda/function_fields_test.go index 46b7c2e995..aafbeab50b 100644 --- a/services/lambda/function_fields_test.go +++ b/services/lambda/function_fields_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -42,7 +44,7 @@ func TestVpcConfig_Ipv6AllowedForDualStack_Create(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) vpc, _ := out["VpcConfig"].(map[string]any) require.NotNil(t, vpc) @@ -63,7 +65,7 @@ func TestVpcConfig_Ipv6AllowedForDualStack_Update(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) vpc, _ := out["VpcConfig"].(map[string]any) require.NotNil(t, vpc) assert.Equal(t, true, vpc["Ipv6AllowedForDualStack"]) @@ -87,7 +89,7 @@ func TestVpcConfig_Ipv6AllowedForDualStack_NotSet_Omitted(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) vpc, _ := out["VpcConfig"].(map[string]any) require.NotNil(t, vpc) // omitempty: nil pointer → field absent in JSON @@ -118,7 +120,7 @@ func TestVpcConfig_Ipv6AllowedForDualStack_GetConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out, jsonx.V1())) vpc, _ := out["VpcConfig"].(map[string]any) require.NotNil(t, vpc) assert.Equal(t, true, vpc["Ipv6AllowedForDualStack"]) @@ -142,7 +144,7 @@ func TestVpcConfig_CreateAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var created lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &created, jsonx.V1())) require.NotNil(t, created.VpcConfig) assert.Equal(t, []string{"subnet-abc"}, created.VpcConfig.SubnetIDs) assert.Equal(t, []string{"sg-xyz"}, created.VpcConfig.SecurityGroupIDs) @@ -151,10 +153,10 @@ func TestVpcConfig_CreateAndGet(t *testing.T) { rec2 := auditGetFunction(t, h, "vpc-fn") require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out)) + var out map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out, jsonx.V1())) var cfg lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(out["Configuration"], &cfg)) + require.NoError(t, json.Unmarshal(out["Configuration"], &cfg, jsonx.V1())) require.NotNil(t, cfg.VpcConfig) assert.Equal(t, []string{"subnet-abc"}, cfg.VpcConfig.SubnetIDs) } @@ -171,7 +173,7 @@ func TestVpcConfig_UpdateAndGet(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, rec2.Body.String()) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.VpcConfig) assert.Equal(t, []string{"subnet-new"}, fn.VpcConfig.SubnetIDs) } @@ -186,7 +188,7 @@ func TestTracingConfig_CreateDefault(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) // Default TracingConfig is PassThrough require.NotNil(t, fn.TracingConfig) assert.Equal(t, "PassThrough", fn.TracingConfig.Mode) @@ -208,7 +210,7 @@ func TestTracingConfig_CreateActive(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.TracingConfig) assert.Equal(t, "Active", fn.TracingConfig.Mode) } @@ -224,7 +226,7 @@ func TestTracingConfig_Update(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.TracingConfig) assert.Equal(t, "Active", fn.TracingConfig.Mode) } @@ -249,7 +251,7 @@ func TestFileSystemConfigs_CreateAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.Len(t, fn.FileSystemConfigs, 1) assert.Equal(t, "arn:aws:elasticfilesystem:us-east-1:000000000000:access-point/fsap-abc", fn.FileSystemConfigs[0].Arn) @@ -270,7 +272,7 @@ func TestFileSystemConfigs_Update(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.Len(t, fn.FileSystemConfigs, 1) assert.Equal(t, "/mnt/new", fn.FileSystemConfigs[0].LocalMountPath) } @@ -293,7 +295,7 @@ func TestDeadLetterConfig_CreateAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.DeadLetterConfig) assert.Equal(t, "arn:aws:sqs:us-east-1:123:my-dlq", fn.DeadLetterConfig.TargetArn) } @@ -310,7 +312,7 @@ func TestDeadLetterConfig_Update(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.DeadLetterConfig) assert.Equal(t, "arn:aws:sns:us-east-1:123:my-topic", fn.DeadLetterConfig.TargetArn) } @@ -339,7 +341,7 @@ func TestDurableConfig_CreateAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.DurableConfig) require.NotNil(t, fn.DurableConfig.ExecutionTimeout) assert.Equal(t, int32(3600), *fn.DurableConfig.ExecutionTimeout) @@ -360,7 +362,7 @@ func TestDurableConfig_Update(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.DurableConfig) require.NotNil(t, fn.DurableConfig.ExecutionTimeout) assert.Equal(t, int32(7200), *fn.DurableConfig.ExecutionTimeout) @@ -386,7 +388,7 @@ func TestDurableConfig_PublishedVersionCarriesConfig(t *testing.T) { require.Equal(t, http.StatusCreated, pubRec.Code) var ver lambda.FunctionVersion - require.NoError(t, json.NewDecoder(pubRec.Body).Decode(&ver)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pubRec.Body), &ver, jsonx.V1())) require.NotNil(t, ver.DurableConfig) require.NotNil(t, ver.DurableConfig.ExecutionTimeout) assert.Equal(t, int32(1800), *ver.DurableConfig.ExecutionTimeout) @@ -631,7 +633,7 @@ func TestEphemeralStorage_DefaultOn_Create(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.EphemeralStorage) assert.Equal(t, int32(512), fn.EphemeralStorage.Size) } @@ -673,7 +675,7 @@ func TestEphemeralStorage_Create(t *testing.T) { if tc.wantCode == http.StatusCreated { var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.EphemeralStorage) assert.Equal(t, int32(tc.size), fn.EphemeralStorage.Size) } @@ -716,7 +718,7 @@ func TestEphemeralStorage_Update(t *testing.T) { if tc.wantCode == http.StatusOK { var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.EphemeralStorage) assert.Equal(t, int32(tc.size), fn.EphemeralStorage.Size) } @@ -742,7 +744,7 @@ func TestImageConfig_Persisted_Create(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.ImageConfigResponse) require.NotNil(t, fn.ImageConfigResponse.ImageConfig) assert.Equal(t, []string{"serve"}, fn.ImageConfigResponse.ImageConfig.Command) @@ -768,10 +770,10 @@ func TestImageConfig_InGetFunction(t *testing.T) { rec2 := auditGetFunction(t, h, "imgcfg-get-fn") require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out)) + var out map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out, jsonx.V1())) var cfg lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(out["Configuration"], &cfg)) + require.NoError(t, json.Unmarshal(out["Configuration"], &cfg, jsonx.V1())) require.NotNil(t, cfg.ImageConfigResponse) require.NotNil(t, cfg.ImageConfigResponse.ImageConfig) assert.Equal(t, []string{"run"}, cfg.ImageConfigResponse.ImageConfig.Command) @@ -785,7 +787,7 @@ func TestImageConfig_NotSetForZip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Nil(t, fn.ImageConfigResponse) } @@ -928,7 +930,7 @@ func TestAllNewFields_PersistInGetConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.VpcConfig) assert.Equal(t, []string{"subnet-1"}, fn.VpcConfig.SubnetIDs) @@ -1049,14 +1051,14 @@ func TestVpcConfig_JSONShape(t *testing.T) { rec := auditCreateFunction(t, h, body) require.Equal(t, http.StatusCreated, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.NewDecoder(rec.Body).Decode(&raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &raw, jsonx.V1())) vpcRaw, ok := raw["VpcConfig"] require.True(t, ok, "VpcConfig key missing from response") - var vpc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(vpcRaw, &vpc)) + var vpc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(vpcRaw, &vpc, jsonx.V1())) assert.Contains(t, vpc, "SubnetIds") assert.Contains(t, vpc, "SecurityGroupIds") } @@ -1068,8 +1070,8 @@ func TestTracingConfig_JSONShape(t *testing.T) { rec := auditCreateFunction(t, h, baseImageFn("tracing-shape-fn")) require.Equal(t, http.StatusCreated, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.NewDecoder(rec.Body).Decode(&raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &raw, jsonx.V1())) _, ok := raw["TracingConfig"] assert.True(t, ok, "TracingConfig key missing from response") @@ -1104,7 +1106,7 @@ func TestMultipleFields_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) // VpcConfig updated require.NotNil(t, fn.VpcConfig) @@ -1153,7 +1155,7 @@ func TestGetFunctionConfiguration_IncludesNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &fn, jsonx.V1())) require.NotNil(t, fn.VpcConfig) assert.Equal(t, []string{"subnet-gc"}, fn.VpcConfig.SubnetIDs) @@ -1192,10 +1194,10 @@ func TestListFunctions_IncludesNewFields(t *testing.T) { require.NoError(t, h.Handler()(c)) require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out)) + var out map[string]jsontext.Value + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out, jsonx.V1())) var fns []lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(out["Functions"], &fns)) + require.NoError(t, json.Unmarshal(out["Functions"], &fns, jsonx.V1())) require.Len(t, fns, 1) require.NotNil(t, fns[0].VpcConfig) assert.Equal(t, []string{"subnet-list"}, fns[0].VpcConfig.SubnetIDs) diff --git a/services/lambda/function_settings_test.go b/services/lambda/function_settings_test.go index 9f83f62afc..e00c840113 100644 --- a/services/lambda/function_settings_test.go +++ b/services/lambda/function_settings_test.go @@ -2,7 +2,8 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -61,7 +63,7 @@ func TestFunctionScalingConfig_PutGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetFunctionScalingConfigOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.AppliedFunctionScalingConfig) require.NotNil(t, out.AppliedFunctionScalingConfig.MaxExecutionEnvironments) assert.Equal(t, int32(maxEnv), *out.AppliedFunctionScalingConfig.MaxExecutionEnvironments) @@ -96,7 +98,7 @@ func TestFunctionScalingConfig_DistinctPerQualifier(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetFunctionScalingConfigOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.AppliedFunctionScalingConfig) require.NotNil(t, out.AppliedFunctionScalingConfig.MaxExecutionEnvironments) @@ -147,7 +149,7 @@ func TestRuntimeManagementConfig_GetDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cfg lambda.RuntimeManagementConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.Equal(t, "Auto", cfg.UpdateRuntimeOn) } @@ -163,7 +165,7 @@ func TestRuntimeManagementConfig_Put(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var cfg lambda.RuntimeManagementConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &cfg, jsonx.V1())) assert.Equal(t, "FunctionUpdate", cfg.UpdateRuntimeOn) } @@ -180,7 +182,7 @@ func TestRuntimeManagementConfig_PutManualWithARN(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var cfg lambda.RuntimeManagementConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &cfg, jsonx.V1())) assert.Equal(t, "Manual", cfg.UpdateRuntimeOn) assert.Equal(t, rva, cfg.RuntimeVersionArn) } @@ -196,7 +198,7 @@ func TestRuntimeManagementConfig_FunctionARNInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cfg lambda.RuntimeManagementConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.Contains(t, cfg.FunctionArn, "rmc-arn-fn") } @@ -215,7 +217,7 @@ func TestRecursionConfig_GetDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var cfg lambda.FunctionRecursionConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.Equal(t, "Terminate", cfg.RecursiveLoop) } @@ -231,7 +233,7 @@ func TestRecursionConfig_Put_Allow(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var cfg lambda.FunctionRecursionConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &cfg, jsonx.V1())) assert.Equal(t, "Allow", cfg.RecursiveLoop) } @@ -251,7 +253,7 @@ func TestRecursionConfig_Put_Terminate(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var cfg lambda.FunctionRecursionConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &cfg, jsonx.V1())) assert.Equal(t, "Terminate", cfg.RecursiveLoop) } diff --git a/services/lambda/function_tenancy_capacity_test.go b/services/lambda/function_tenancy_capacity_test.go index fab249dfca..c29a7c0878 100644 --- a/services/lambda/function_tenancy_capacity_test.go +++ b/services/lambda/function_tenancy_capacity_test.go @@ -1,12 +1,14 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateFunction_TenancyAndCapacityProviderConfig(t *testing.T) { @@ -52,7 +54,7 @@ func TestCreateFunction_TenancyAndCapacityProviderConfig(t *testing.T) { } var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, "PER_TENANT", created["TenancyConfig"].(map[string]any)["TenantIsolationMode"]) rec = callInMemoryHandler(t, h, http.MethodPost, "/2015-03-31/functions/tenant-fn/versions", `{}`) @@ -68,7 +70,7 @@ func TestCreateFunction_TenancyAndCapacityProviderConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) cp, _ := got["CapacityProviderConfig"].(map[string]any) require.NotNil(t, cp, "published version keeps the capacity provider config") diff --git a/services/lambda/function_url_host_test.go b/services/lambda/function_url_host_test.go index 2c21d7be27..5f046fa60c 100644 --- a/services/lambda/function_url_host_test.go +++ b/services/lambda/function_url_host_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -298,7 +299,7 @@ func TestFunctionURLHost_EventShape(t *testing.T) { Cookies []string `json:"cookies"` IsBase64 bool `json:"isBase64Encoded"` } - require.NoError(t, json.Unmarshal(<-env.events, &ev)) + require.NoError(t, json.Unmarshal(<-env.events, &ev, jsonx.V1())) assert.Equal(t, "2.0", ev.Version) assert.Equal(t, "/a%20b/c", ev.RawPath) @@ -373,7 +374,7 @@ func TestFunctionURLHost_IAMAuthorizerContext(t *testing.T) { } `json:"authorizer"` } `json:"requestContext"` } - require.NoError(t, json.Unmarshal(<-env.events, &ev)) + require.NoError(t, json.Unmarshal(<-env.events, &ev, jsonx.V1())) assert.Equal(t, "AKIDEXAMPLE", ev.RequestContext.Authorizer.IAM.AccessKey) assert.Equal(t, "000000000000", ev.RequestContext.Authorizer.IAM.AccountID) } @@ -501,7 +502,7 @@ func TestFunctionURLConfig_Validation(t *testing.T) { if tt.want == http.StatusCreated { var cfg lambda.FunctionURLConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) assert.Regexp(t, `^https://[0-9a-f]{32}\.lambda-url\.us-east-1\.on\.aws/$`, cfg.FunctionURL) up := callHandler(t, h, http.MethodPut, "/2021-10-31/functions/val-fn/url", `{"InvokeMode":"X"}`, nil) diff --git a/services/lambda/function_url_http.go b/services/lambda/function_url_http.go index b7e91f8ea6..c6d6935582 100644 --- a/services/lambda/function_url_http.go +++ b/services/lambda/function_url_http.go @@ -3,7 +3,7 @@ package lambda import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -20,6 +20,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -275,7 +276,7 @@ func writeFunctionURLError(w http.ResponseWriter, status int, message string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) - body, _ := json.Marshal(map[string]string{"Message": message}) + body, _ := json.Marshal(map[string]string{"Message": message}, jsonx.V1()) _, _ = w.Write(body) } @@ -448,7 +449,7 @@ func (b *InMemoryBackend) buildURLEvent(r *http.Request, meta urlRequestMeta) ([ event.Body, event.IsBase64Encoded = encodeURLBody(bodyBytes, r.Header.Get("Content-Type")) - return json.Marshal(event) + return json.Marshal(event, jsonx.V1()) } func urlIAMAuthorizer(r *http.Request, accountID string) *lambdaURLAuthorizer { @@ -590,7 +591,7 @@ func writeFunctionURLResult(w http.ResponseWriter, result []byte, streaming bool if streaming { if prelude, rest, ok := bytes.Cut(result, []byte(functionURLStreamSep)); ok && - json.Unmarshal(prelude, &resp) == nil { + json.Unmarshal(prelude, &resp, jsonx.V1()) == nil { writeURLResponseHead(w, &resp) writeFlushed(w, rest) @@ -598,7 +599,7 @@ func writeFunctionURLResult(w http.ResponseWriter, result []byte, streaming bool } } - if json.Unmarshal(result, &resp) != nil || resp.StatusCode == 0 { + if json.Unmarshal(result, &resp, jsonx.V1()) != nil || resp.StatusCode == 0 { w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusOK) diff --git a/services/lambda/function_urls_test.go b/services/lambda/function_urls_test.go index bdf9ac83ae..1f20db4ee4 100644 --- a/services/lambda/function_urls_test.go +++ b/services/lambda/function_urls_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -78,7 +80,7 @@ func TestFunctionURL_CORS(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) require.NotNil(t, cfg.Cors) assert.Equal(t, []string{"https://example.com"}, cfg.Cors.AllowOrigins) assert.Equal(t, 300, cfg.Cors.MaxAge) @@ -96,7 +98,7 @@ func TestFunctionURL_InvokeMode(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.Equal(t, "RESPONSE_STREAM", cfg.InvokeMode) } @@ -112,7 +114,7 @@ func TestFunctionURL_AWSIAMAuth(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.Equal(t, "AWS_IAM", cfg.AuthType) } @@ -128,7 +130,7 @@ func TestFunctionURL_FunctionURLIsSet(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(rec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &cfg, jsonx.V1())) assert.NotEmpty(t, cfg.FunctionURL) } @@ -177,7 +179,7 @@ func TestUpdateFunctionURLConfig_CORS(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &cfg, jsonx.V1())) assert.Equal(t, tt.wantAuthType, cfg.AuthType) @@ -213,7 +215,7 @@ func TestFunctionURL_CorsAllowOrigins_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) cors, _ := out["Cors"].(map[string]any) require.NotNil(t, cors) origins, _ := cors["AllowOrigins"].([]any) @@ -235,7 +237,7 @@ func TestFunctionURLConfig_2021(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &cfg, jsonx.V1())) assert.Equal(t, "NONE", cfg.AuthType) // Get via 2021 path @@ -249,7 +251,7 @@ func TestFunctionURLConfig_2021(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListFunctionURLConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.FunctionURLConfigs, 1) // Update via 2021 path @@ -291,7 +293,7 @@ func TestFunctionURLConfig_2021_ListEmpty(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListFunctionURLConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Empty(t, listOut.FunctionURLConfigs) } @@ -381,7 +383,7 @@ func TestLambda_FunctionURL_EventPayloadEnrichment(t *testing.T) { Headers map[string]string `json:"headers"` Cookies []string `json:"cookies"` } - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) assert.ElementsMatch(t, []string{"session=abc", "theme=dark"}, event.Cookies) assert.Equal(t, "bar", event.QueryStringParameters["foo"]) diff --git a/services/lambda/functions_test.go b/services/lambda/functions_test.go index 849ccd9aaa..1a92663ad5 100644 --- a/services/lambda/functions_test.go +++ b/services/lambda/functions_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -80,7 +82,7 @@ func TestUpdateConfig_EnvVars(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.Environment) assert.Equal(t, "val", fn.Environment.Variables["KEY"]) assert.Equal(t, "bar", fn.Environment.Variables["FOO"]) @@ -98,7 +100,7 @@ func TestUpdateConfig_TimeoutAndMemory(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) assert.Equal(t, 30, fn.Timeout) assert.Equal(t, 512, fn.MemorySize) } @@ -115,7 +117,7 @@ func TestUpdateConfig_VPC(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.VpcConfig) assert.Equal(t, []string{"subnet-abc"}, fn.VpcConfig.SubnetIDs) assert.Equal(t, []string{"sg-xyz"}, fn.VpcConfig.SecurityGroupIDs) @@ -133,7 +135,7 @@ func TestUpdateConfig_DLQ(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.DeadLetterConfig) assert.Equal(t, "arn:aws:sqs:us-east-1:000000000000:dlq", fn.DeadLetterConfig.TargetArn) } @@ -150,7 +152,7 @@ func TestUpdateConfig_Tracing(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.TracingConfig) assert.Equal(t, "Active", fn.TracingConfig.Mode) } @@ -168,7 +170,7 @@ func TestUpdateConfig_FileSystem(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.Len(t, fn.FileSystemConfigs, 1) assert.Equal(t, "/mnt/data", fn.FileSystemConfigs[0].LocalMountPath) } @@ -186,7 +188,7 @@ func TestUpdateConfig_Layers(t *testing.T) { require.Equal(t, http.StatusCreated, pubRec.Code) var layerOut lambda.PublishLayerVersionOutput - require.NoError(t, json.NewDecoder(pubRec.Body).Decode(&layerOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pubRec.Body), &layerOut, jsonx.V1())) layerARN := layerOut.LayerVersionArn // Update function to use layer @@ -196,7 +198,7 @@ func TestUpdateConfig_Layers(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &fn, jsonx.V1())) require.Len(t, fn.Layers, 1) assert.Contains(t, fn.Layers[0].Arn, "my-layer") } @@ -239,7 +241,7 @@ func TestGetFunctionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, 15, fn.Timeout) assert.Equal(t, 256, fn.MemorySize) } @@ -259,7 +261,7 @@ func TestArchitectures_CreateArm64(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.Equal(t, []string{"arm64"}, fn.Architectures) } @@ -274,7 +276,7 @@ func TestArchitectures_CreateX86(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, []string{"x86_64"}, fn.Architectures) } @@ -290,7 +292,7 @@ func TestArchitectures_UpdateCode(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, []string{"arm64"}, fn.Architectures) } @@ -305,7 +307,7 @@ func TestArchitectures_DefaultIsX86(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetFunctionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) // may be empty or x86_64 — just confirm it doesn't return arm64 for _, arch := range out.Configuration.Architectures { assert.NotEqual(t, "arm64", arch) @@ -328,7 +330,7 @@ func TestSnapStart_CreateWithPublishedVersions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.SnapStart) assert.Equal(t, "PublishedVersions", fn.SnapStart.ApplyOn) assert.Equal(t, "On", fn.SnapStart.OptimizationStatus) @@ -345,7 +347,7 @@ func TestSnapStart_CreateWithNone(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.SnapStart) assert.Equal(t, "None", fn.SnapStart.ApplyOn) assert.Equal(t, "Off", fn.SnapStart.OptimizationStatus) @@ -363,7 +365,7 @@ func TestSnapStart_UpdateFunctionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.SnapStart) assert.Equal(t, "PublishedVersions", fn.SnapStart.ApplyOn) assert.Equal(t, "On", fn.SnapStart.OptimizationStatus) @@ -384,7 +386,7 @@ func TestSnapStart_DisableViaUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) require.NotNil(t, fn.SnapStart) assert.Equal(t, "None", fn.SnapStart.ApplyOn) assert.Equal(t, "Off", fn.SnapStart.OptimizationStatus) @@ -403,7 +405,7 @@ func TestSnapStart_GetFunctionReflectsState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetFunctionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.Configuration.SnapStart) assert.Equal(t, "PublishedVersions", out.Configuration.SnapStart.ApplyOn) } @@ -423,7 +425,7 @@ func TestFunctionState_ActiveOnCreate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.GetFunctionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, lambda.FunctionStateActive, out.Configuration.State) } @@ -445,7 +447,7 @@ func TestFunctionState_ListedFunctionsHaveState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListFunctionsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) for _, fn := range out.Functions { assert.NotEmpty(t, string(fn.State), "function %s has empty State", fn.FunctionName) } @@ -462,7 +464,7 @@ func TestFunctionState_VersionHasState(t *testing.T) { require.Equal(t, http.StatusCreated, pubRec.Code) var v lambda.FunctionVersion - require.NoError(t, json.NewDecoder(pubRec.Body).Decode(&v)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pubRec.Body), &v, jsonx.V1())) assert.NotEmpty(t, string(v.State)) } @@ -488,7 +490,7 @@ func TestCreateFunction_AllFields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, "full-fn", fn.FunctionName) assert.Equal(t, 1024, fn.MemorySize) assert.Equal(t, 60, fn.Timeout) @@ -590,7 +592,7 @@ func TestUpdateFunctionCode_Publish(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, tt.wantVersion, fn.Version, "UpdateFunctionCode Publish=%v: Version must be %q", tt.publish, tt.wantVersion) @@ -647,7 +649,7 @@ func TestCreateFunction_Tags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out lambda.GetFunctionOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) for k, v := range tt.wantTags { assert.Equal(t, v, out.Tags[k], @@ -706,7 +708,7 @@ func TestCreateFunction_MemorySizeNotDivisibleBy64(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterValueException", errResp["__type"], "error type must be InvalidParameterValueException, not ServiceException") } @@ -737,7 +739,7 @@ func TestSnapStart_GetConfiguration_OptimizationStatus(t *testing.T) { require.Equal(t, http.StatusOK, cfgRec.Code) var cfg map[string]any - require.NoError(t, json.NewDecoder(cfgRec.Body).Decode(&cfg)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cfgRec.Body), &cfg, jsonx.V1())) snap, _ := cfg["SnapStart"].(map[string]any) require.NotNil(t, snap) assert.Equal(t, "PublishedVersions", snap["ApplyOn"]) @@ -834,7 +836,7 @@ func TestListFunctions_FunctionVersionAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) fns, _ := out["Functions"].([]any) assert.GreaterOrEqual(t, len(fns), tc.wantMinCount, "FunctionVersion=ALL must include $LATEST and all published versions") @@ -876,7 +878,7 @@ func TestUpdateFunctionCodeArchitectures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) require.Equal(t, []string{"arm64"}, fn.Architectures) // GetFunctionConfiguration returns the stored architectures. @@ -885,7 +887,7 @@ func TestUpdateFunctionCodeArchitectures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn2 lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn2, jsonx.V1())) assert.Equal(t, []string{"arm64"}, fn2.Architectures) } diff --git a/services/lambda/get_function_qualifier_test.go b/services/lambda/get_function_qualifier_test.go index efb0ea5636..b91f0de193 100644 --- a/services/lambda/get_function_qualifier_test.go +++ b/services/lambda/get_function_qualifier_test.go @@ -2,7 +2,7 @@ package lambda_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -21,7 +22,7 @@ func doFnRequest(t *testing.T, h *lambda.Handler, method, path string, body any) var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -148,7 +149,7 @@ func TestLambda_GetFunction_ByQualifier(t *testing.T) { Version string `json:"Version"` } `json:"Configuration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Equal(t, tc.wantVersion, out.Configuration.Version) require.Contains(t, out.Configuration.FunctionArn, tc.wantArnSfx) }) @@ -172,7 +173,7 @@ func TestLambda_GetFunctionConfiguration_ByQualifier(t *testing.T) { FunctionArn string `json:"FunctionArn"` Version string `json:"Version"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) require.Equal(t, "1", cfg.Version) require.Contains(t, cfg.FunctionArn, ":function:cfgfn:1") } diff --git a/services/lambda/handler_capacity_providers.go b/services/lambda/handler_capacity_providers.go index f8d487f860..d4b7a7422e 100644 --- a/services/lambda/handler_capacity_providers.go +++ b/services/lambda/handler_capacity_providers.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Capacity provider handlers --- @@ -66,7 +67,7 @@ func (h *Handler) handleCreateCapacityProvider(c *echo.Context, bk *InMemoryBack var input CreateCapacityProviderInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -153,7 +154,7 @@ func (h *Handler) handleUpdateCapacityProvider(c *echo.Context, bk *InMemoryBack var input UpdateCapacityProviderInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_code_signing.go b/services/lambda/handler_code_signing.go index 1e3707f632..e7c1d70d1f 100644 --- a/services/lambda/handler_code_signing.go +++ b/services/lambda/handler_code_signing.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handle2020FunctionRoute handles routes under /2020-06-30/functions/{name}/... @@ -72,7 +73,7 @@ func (h *Handler) handlePutFunctionCodeSigningConfig(c *echo.Context, bk *InMemo } var input PutFunctionCodeSigningConfigInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } @@ -173,7 +174,7 @@ func (h *Handler) handleCreateCodeSigningConfig(c *echo.Context, bk *InMemoryBac var input CreateCodeSigningConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -234,7 +235,7 @@ func (h *Handler) handleUpdateCodeSigningConfig(c *echo.Context, bk *InMemoryBac var input UpdateCodeSigningConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_concurrency.go b/services/lambda/handler_concurrency.go index 9524e8c347..717df6b429 100644 --- a/services/lambda/handler_concurrency.go +++ b/services/lambda/handler_concurrency.go @@ -1,13 +1,15 @@ package lambda import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const opListProvisionedConcurrencyConfigs = "ListProvisionedConcurrencyConfigs" @@ -29,8 +31,8 @@ func (h *Handler) handlePutFunctionConcurrency(c *echo.Context, name string) err "ReservedConcurrentExecutions is required") } - var raw map[string]json.RawMessage - if unmarshalErr := json.Unmarshal(body, &raw); unmarshalErr != nil { + var raw map[string]jsontext.Value + if unmarshalErr := json.Unmarshal(body, &raw, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } @@ -40,7 +42,7 @@ func (h *Handler) handlePutFunctionConcurrency(c *echo.Context, name string) err } var input PutFunctionConcurrencyInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } @@ -131,7 +133,7 @@ func (h *Handler) handlePutProvisionedConcurrencyConfig(c *echo.Context, name st } var input PutProvisionedConcurrencyConfigInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } diff --git a/services/lambda/handler_durable_execution.go b/services/lambda/handler_durable_execution.go index 2c43335034..67e45bb4f0 100644 --- a/services/lambda/handler_durable_execution.go +++ b/services/lambda/handler_durable_execution.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -284,7 +285,7 @@ func replayClosedDurableExecution(ex *DurableExecution, invType string) ([]byte, msg = ptrconv.String(ex.Error.ErrorMessage) } - payload, _ := json.Marshal(map[string]string{"errorMessage": msg}) + payload, _ := json.Marshal(map[string]string{"errorMessage": msg}, jsonx.V1()) return payload, "Unhandled", http.StatusOK } @@ -300,7 +301,7 @@ func (h *Handler) handleCheckpointDurableExecution(c *echo.Context, path string) var body CheckpointDurableExecutionInput if raw, err := httputils.ReadBody(c.Request()); err == nil && len(raw) > 0 { - _ = json.Unmarshal(raw, &body) + _ = json.Unmarshal(raw, &body, jsonx.V1()) } return c.JSON(http.StatusOK, store.checkpoint(arn, body.Updates)) @@ -430,7 +431,7 @@ func (h *Handler) handleStopDurableExecution(c *echo.Context) error { // struct here silently dropped every real client's Error every time. var parsedErr ErrorObject if raw, err := httputils.ReadBody(c.Request()); err == nil && len(raw) > 0 { - _ = json.Unmarshal(raw, &parsedErr) + _ = json.Unmarshal(raw, &parsedErr, jsonx.V1()) } var errObj *ErrorObject @@ -479,7 +480,7 @@ func (h *Handler) handleSendDurableExecutionCallbackFailure(c *echo.Context) err // the request's top-level JSON body, not {"Error": {...}}. var parsedErr ErrorObject if raw, err := httputils.ReadBody(c.Request()); err == nil && len(raw) > 0 { - _ = json.Unmarshal(raw, &parsedErr) + _ = json.Unmarshal(raw, &parsedErr, jsonx.V1()) } var errObj *ErrorObject diff --git a/services/lambda/handler_event_invoke_config.go b/services/lambda/handler_event_invoke_config.go index 14f5745016..50517ae11c 100644 --- a/services/lambda/handler_event_invoke_config.go +++ b/services/lambda/handler_event_invoke_config.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handlePutFunctionEventInvokeConfig handles PUT /2015-03-31/functions/{name}/event-invoke-config. @@ -25,7 +26,7 @@ func (h *Handler) handlePutFunctionEventInvokeConfig(c *echo.Context, name strin var input PutFunctionEventInvokeConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -67,7 +68,7 @@ func (h *Handler) handleUpdateFunctionEventInvokeConfig(c *echo.Context, name st var input PutFunctionEventInvokeConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_event_source_mappings.go b/services/lambda/handler_event_source_mappings.go index 51030ca6d7..88cbd51d14 100644 --- a/services/lambda/handler_event_source_mappings.go +++ b/services/lambda/handler_event_source_mappings.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleESMRoute dispatches event-source-mapping REST API requests. @@ -74,7 +75,7 @@ func (h *Handler) handleCreateESM(c *echo.Context) error { var req handleCreateESMInput - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } @@ -216,7 +217,7 @@ func (h *Handler) handleUpdateESM(c *echo.Context, id string) error { } var req handleUpdateESMInput - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } diff --git a/services/lambda/handler_function_settings.go b/services/lambda/handler_function_settings.go index 477b49004a..066c4e3332 100644 --- a/services/lambda/handler_function_settings.go +++ b/services/lambda/handler_function_settings.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleRuntimeMgmtRoute handles /2021-07-20/functions/{name}/runtime-management-config routes. @@ -51,7 +52,7 @@ func (h *Handler) handleRuntimeMgmtRoute(c *echo.Context, path, method string) e var input PutRuntimeManagementConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -112,7 +113,7 @@ func (h *Handler) handleRecursionConfigRoute(c *echo.Context, path, method strin var input PutFunctionRecursionConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -179,7 +180,7 @@ func (h *Handler) handleScalingConfigRoute(c *echo.Context, path, method string) var input PutFunctionScalingConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_function_urls.go b/services/lambda/handler_function_urls.go index 1e29d68538..339f9cda4b 100644 --- a/services/lambda/handler_function_urls.go +++ b/services/lambda/handler_function_urls.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateFunctionURLConfig(c *echo.Context, name string) error { @@ -24,7 +25,7 @@ func (h *Handler) handleCreateFunctionURLConfig(c *echo.Context, name string) er var input CreateFunctionURLConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -173,7 +174,7 @@ func (h *Handler) handleUpdateFunctionURLConfig(c *echo.Context, name string) er var input UpdateFunctionURLConfigInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_function_urls_test.go b/services/lambda/handler_function_urls_test.go index 1e32de7aea..472adf2075 100644 --- a/services/lambda/handler_function_urls_test.go +++ b/services/lambda/handler_function_urls_test.go @@ -1,7 +1,7 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -62,7 +63,7 @@ func TestFunctionUrl_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cfg lambda.FunctionURLConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) assert.NotEmpty(t, cfg.FunctionURL) assert.Equal(t, "NONE", cfg.AuthType) assert.NotEmpty(t, cfg.FunctionArn) @@ -72,7 +73,7 @@ func TestFunctionUrl_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getCfg lambda.FunctionURLConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getCfg, jsonx.V1())) assert.Equal(t, cfg.FunctionURL, getCfg.FunctionURL) rec = callHandler(t, h, http.MethodDelete, "/2015-03-31/functions/"+tt.funcName+"/url", "", nil) diff --git a/services/lambda/handler_functions.go b/services/lambda/handler_functions.go index a5bd895e69..8fe2739bad 100644 --- a/services/lambda/handler_functions.go +++ b/services/lambda/handler_functions.go @@ -4,7 +4,7 @@ import ( "context" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -371,7 +372,7 @@ func (h *Handler) handleCreateFunction(c *echo.Context) error { } var input CreateFunctionInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid request body") } @@ -589,7 +590,7 @@ func (h *Handler) handleUpdateFunctionCode(c *echo.Context, name string) error { } var input UpdateFunctionCodeInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid request body") } @@ -765,7 +766,7 @@ func (h *Handler) handleUpdateFunctionConfiguration(c *echo.Context, name string } var input UpdateFunctionConfigurationInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid request body") } diff --git a/services/lambda/handler_invocation.go b/services/lambda/handler_invocation.go index 4bbb2aa1e2..5945ecd57e 100644 --- a/services/lambda/handler_invocation.go +++ b/services/lambda/handler_invocation.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/binary" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "hash/crc32" "math" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // errInvalidInvocationType and errInvalidLogType are returned unwritten by @@ -129,7 +131,7 @@ func writeInvokeResult(c *echo.Context, result []byte, functionError string, sta } func rejectNonJSONPayload(h *Handler, c *echo.Context, body []byte) bool { - if len(body) == 0 || json.Valid(body) { + if len(body) == 0 || jsontext.Value(body).IsValid(jsonx.V1()) { return false } @@ -326,10 +328,10 @@ func isLambdaFunctionErrorPayload(result []byte) bool { } var probe struct { - ErrorMessage *json.RawMessage `json:"errorMessage"` - ErrorType *json.RawMessage `json:"errorType"` + ErrorMessage *jsontext.Value `json:"errorMessage"` + ErrorType *jsontext.Value `json:"errorType"` } - if err := json.Unmarshal(trimmed, &probe); err != nil { + if err := json.Unmarshal(trimmed, &probe, jsonx.V1()); err != nil { return false } diff --git a/services/lambda/handler_layers.go b/services/lambda/handler_layers.go index 0e2104e4ac..42fec6da16 100644 --- a/services/lambda/handler_layers.go +++ b/services/lambda/handler_layers.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleLayersRoute dispatches Lambda Layers REST API requests. @@ -149,7 +150,7 @@ func (h *Handler) handlePublishLayerVersion(c *echo.Context, bk *InMemoryBackend var input PublishLayerVersionInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -233,7 +234,7 @@ func (h *Handler) handleAddLayerVersionPermission( var input AddLayerVersionPermissionInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } diff --git a/services/lambda/handler_permissions.go b/services/lambda/handler_permissions.go index ffad594aaa..f0c36c0dd3 100644 --- a/services/lambda/handler_permissions.go +++ b/services/lambda/handler_permissions.go @@ -1,13 +1,14 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- AddPermission handler --- @@ -25,7 +26,7 @@ func (h *Handler) handleAddPermission(c *echo.Context, name string) error { } var input AddPermissionInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } diff --git a/services/lambda/handler_resource_policy.go b/services/lambda/handler_resource_policy.go index 442ef00dd5..70317f2706 100644 --- a/services/lambda/handler_resource_policy.go +++ b/services/lambda/handler_resource_policy.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resourcePolicyBody is PutResourcePolicy's real request body shape @@ -60,7 +61,7 @@ func (h *Handler) handlePutResourcePolicy(c *echo.Context, b *InMemoryBackend, r } var input resourcePolicyBody - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } diff --git a/services/lambda/handler_runtime_test.go b/services/lambda/handler_runtime_test.go index 487665403d..84ee5c501d 100644 --- a/services/lambda/handler_runtime_test.go +++ b/services/lambda/handler_runtime_test.go @@ -2,7 +2,7 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/container" "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/image" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" gophercontainer "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" @@ -500,7 +501,7 @@ func assertLambdaError(t *testing.T, rec *httptest.ResponseRecorder, errType str t.Helper() var lambdaErr lambda.Error - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lambdaErr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lambdaErr, jsonx.V1())) assert.Equal(t, errType, lambdaErr.Type) } diff --git a/services/lambda/handler_tags.go b/services/lambda/handler_tags.go index 5082eb4077..725d7052fb 100644 --- a/services/lambda/handler_tags.go +++ b/services/lambda/handler_tags.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -102,7 +103,7 @@ func (h *Handler) handleTagsRoute(c *echo.Context, method string) error { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "failed to read body") } var input lambdaTagsInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid body") } var kv map[string]string diff --git a/services/lambda/handler_tags_iam_test.go b/services/lambda/handler_tags_iam_test.go index b5c9f9cfea..3fc64525f4 100644 --- a/services/lambda/handler_tags_iam_test.go +++ b/services/lambda/handler_tags_iam_test.go @@ -1,7 +1,7 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -154,7 +155,7 @@ func TestHandler_TagsRoute(t *testing.T) { if tt.wantTagsNotNil || len(tt.wantTagValues) > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantTagsNotNil { assert.NotNil(t, resp["Tags"]) } @@ -173,7 +174,7 @@ func TestHandler_TagsRoute(t *testing.T) { if len(tt.verifyTagValues) > 0 || len(tt.verifyTagAbsent) > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].(map[string]any) require.True(t, ok) for k, v := range tt.verifyTagValues { diff --git a/services/lambda/handler_test.go b/services/lambda/handler_test.go index 8bb26ea9fe..1923715af0 100644 --- a/services/lambda/handler_test.go +++ b/services/lambda/handler_test.go @@ -2,7 +2,7 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -294,7 +295,7 @@ func TestCreateFunction(t *testing.T) { } var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) assert.Equal(t, tt.wantFunctionName, fn.FunctionName) if tt.wantFunctionArn != "" { assert.Equal(t, tt.wantFunctionArn, fn.FunctionArn) @@ -375,7 +376,7 @@ func TestGetFunction(t *testing.T) { if tt.wantCode == http.StatusOK { var out lambda.GetFunctionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Configuration) assert.Equal(t, tt.funcName, out.Configuration.FunctionName) require.NotNil(t, out.Code) @@ -421,7 +422,7 @@ func TestListFunctions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListFunctionsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Functions, tt.wantCount) }) } @@ -544,7 +545,7 @@ func TestUpdateFunctionCode(t *testing.T) { if tt.wantImageURI != "" { var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) assert.Equal(t, tt.wantImageURI, fn.ImageURI) assert.NotEmpty(t, fn.RevisionID) if tt.wantLastUpdateStatus != "" { @@ -645,7 +646,7 @@ func TestUpdateFunctionConfiguration(t *testing.T) { } var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) if tt.wantDescription != "" { assert.Equal(t, tt.wantDescription, fn.Description) } diff --git a/services/lambda/handler_versions_aliases.go b/services/lambda/handler_versions_aliases.go index edac4b399c..31a5b1013f 100644 --- a/services/lambda/handler_versions_aliases.go +++ b/services/lambda/handler_versions_aliases.go @@ -1,7 +1,7 @@ package lambda import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -83,7 +84,7 @@ func (h *Handler) handlePublishVersion(c *echo.Context, name string) error { var input publishVersionInput if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } } @@ -160,7 +161,7 @@ func (h *Handler) handleCreateAlias(c *echo.Context, name string) error { } var input CreateAliasInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } @@ -264,7 +265,7 @@ func (h *Handler) handleUpdateAlias(c *echo.Context, name, aliasName string) err } var input UpdateAliasInput - if unmarshalErr := json.Unmarshal(body, &input); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &input, jsonx.V1()); unmarshalErr != nil { return h.writeError(c, http.StatusBadRequest, "InvalidParameterValueException", "invalid JSON") } diff --git a/services/lambda/handler_versions_aliases_test.go b/services/lambda/handler_versions_aliases_test.go index acdcbc5f65..2a37e76891 100644 --- a/services/lambda/handler_versions_aliases_test.go +++ b/services/lambda/handler_versions_aliases_test.go @@ -1,13 +1,14 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -69,7 +70,7 @@ func TestPublishVersion(t *testing.T) { if tt.wantVersion != "" { var ver lambda.FunctionVersion - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ver)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ver, jsonx.V1())) assert.Equal(t, tt.wantVersion, ver.Version) assert.Equal(t, tt.wantDesc, ver.Description) assert.Equal(t, tt.funcName, ver.FunctionName) @@ -134,7 +135,7 @@ func TestListVersionsByFunction(t *testing.T) { if tt.wantCount > 0 { var out lambda.ListVersionsByFunctionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Versions, tt.wantCount) for i, v := range tt.wantVersions { assert.Equal(t, v, out.Versions[i].Version) @@ -238,7 +239,7 @@ func TestCreateAlias(t *testing.T) { if tt.wantName != "" { var alias lambda.FunctionAlias - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias, jsonx.V1())) assert.Equal(t, tt.wantName, alias.Name) assert.Equal(t, tt.wantVersion, alias.FunctionVersion) } @@ -312,7 +313,7 @@ func TestGetAlias(t *testing.T) { if tt.wantName != "" { var alias lambda.FunctionAlias - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias, jsonx.V1())) assert.Equal(t, tt.wantName, alias.Name) } }) @@ -378,7 +379,7 @@ func TestListAliases(t *testing.T) { if tt.wantCount > 0 { var out lambda.ListAliasesOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Aliases, tt.wantCount) } }) @@ -456,7 +457,7 @@ func TestUpdateAlias(t *testing.T) { if tt.wantVersion != "" { var alias lambda.FunctionAlias - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias, jsonx.V1())) assert.Equal(t, tt.wantVersion, alias.FunctionVersion) } }) diff --git a/services/lambda/invocation_test.go b/services/lambda/invocation_test.go index 75f6953721..9880c7aaff 100644 --- a/services/lambda/invocation_test.go +++ b/services/lambda/invocation_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -598,14 +599,14 @@ func TestHandleInvokeAsync_Returns202Immediately(t *testing.T) { if tt.wantStatus == http.StatusAccepted { var body map[string]int - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, http.StatusAccepted, body["Status"], "InvokeAsync body must contain {\"Status\":202}") } if tt.wantErrType != "" { var errBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Contains(t, errBody["__type"], tt.wantErrType) } }) diff --git a/services/lambda/kafka_event.go b/services/lambda/kafka_event.go index 8537ab7b34..eb5a1f4e69 100644 --- a/services/lambda/kafka_event.go +++ b/services/lambda/kafka_event.go @@ -2,11 +2,13 @@ package lambda import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "strconv" "strings" "time" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -101,7 +103,7 @@ func buildKafkaEventPayload(eventSource, eventSourceARN, bootstrap string, recs }) } - return json.Marshal(ev) + return json.Marshal(ev, jsonx.V1()) } // kafkaFilterView is the record shape FilterCriteria is matched against; only "value" is a data key. diff --git a/services/lambda/kafka_event_internal_test.go b/services/lambda/kafka_event_internal_test.go index e247ff7fdf..e5320a0961 100644 --- a/services/lambda/kafka_event_internal_test.go +++ b/services/lambda/kafka_event_internal_test.go @@ -2,12 +2,14 @@ package lambda import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func kafkaTestRecord(topic string, partition int32, offset int64, value string) KafkaRecord { @@ -63,7 +65,7 @@ func TestBuildKafkaEventPayload(t *testing.T) { var ev map[string]any - require.NoError(t, json.Unmarshal(raw, &ev)) + require.NoError(t, json.Unmarshal(raw, &ev, jsonx.V1())) assert.Equal(t, tt.source, ev["eventSource"]) assert.Equal(t, "b1:9092,b2:9092", ev["bootstrapServers"]) diff --git a/services/lambda/kafka_integration_internal_test.go b/services/lambda/kafka_integration_internal_test.go index d612bf3d87..086f42a6b2 100644 --- a/services/lambda/kafka_integration_internal_test.go +++ b/services/lambda/kafka_integration_internal_test.go @@ -3,7 +3,7 @@ package lambda import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net" "net/netip" "strconv" @@ -17,6 +17,8 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "github.com/twmb/franz-go/pkg/kgo" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -89,7 +91,7 @@ func awaitDelivery(t *testing.T, ch <-chan []byte) map[string]any { case raw := <-ch: var ev map[string]any - require.NoError(t, json.Unmarshal(raw, &ev)) + require.NoError(t, json.Unmarshal(raw, &ev, jsonx.V1())) return ev case <-time.After(kafkaDeliveryTimeout): diff --git a/services/lambda/kafka_msk_internal_test.go b/services/lambda/kafka_msk_internal_test.go index 785655c4db..74e9d8d5ac 100644 --- a/services/lambda/kafka_msk_internal_test.go +++ b/services/lambda/kafka_msk_internal_test.go @@ -2,12 +2,14 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const mskTestARN = "arn:aws:kafka:us-east-1:000000000000:cluster/c/uuid" @@ -82,7 +84,7 @@ func TestMSKESMFollowsClusterBroker(t *testing.T) { var ev map[string]any - require.NoError(t, json.Unmarshal(<-deliveries, &ev)) + require.NoError(t, json.Unmarshal(<-deliveries, &ev, jsonx.V1())) assert.Equal(t, "aws:kafka", ev["eventSource"]) assert.Equal(t, mskTestARN, ev["eventSourceArn"]) assert.Equal(t, "127.0.0.1:19092", ev["bootstrapServers"]) diff --git a/services/lambda/kafka_worker_internal_test.go b/services/lambda/kafka_worker_internal_test.go index e2e447af5d..290a5e692c 100644 --- a/services/lambda/kafka_worker_internal_test.go +++ b/services/lambda/kafka_worker_internal_test.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync" "sync/atomic" @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errKafkaTestFunction = errors.New("boom") @@ -202,7 +204,7 @@ func TestKafkaWorkerBatching(t *testing.T) { Records map[string][]struct{} `json:"records"` } - require.NoError(t, json.Unmarshal(payload, &ev)) + require.NoError(t, json.Unmarshal(payload, &ev, jsonx.V1())) n := 0 for _, rs := range ev.Records { diff --git a/services/lambda/layer_permissions_test.go b/services/lambda/layer_permissions_test.go index f7cee14828..1a4df24183 100644 --- a/services/lambda/layer_permissions_test.go +++ b/services/lambda/layer_permissions_test.go @@ -1,13 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -166,7 +168,7 @@ func TestLayer_Policy_AddAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, addRec.Code) var addOut lambda.AddLayerVersionPermissionOutput - require.NoError(t, json.NewDecoder(addRec.Body).Decode(&addOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(addRec.Body), &addOut, jsonx.V1())) assert.NotEmpty(t, addOut.Statement) assert.NotEmpty(t, addOut.RevisionID) @@ -175,7 +177,7 @@ func TestLayer_Policy_AddAndGet(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var pol lambda.LayerVersionPolicy - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&pol)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &pol, jsonx.V1())) assert.NotEmpty(t, pol.Policy) } @@ -222,7 +224,7 @@ func TestLayerVersionPermission_RevisionId(t *testing.T) { require.Equal(t, http.StatusCreated, addRec.Code) var addOut lambda.AddLayerVersionPermissionOutput - require.NoError(t, json.NewDecoder(addRec.Body).Decode(&addOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(addRec.Body), &addOut, jsonx.V1())) rev1 := addOut.RevisionID require.NotEmpty(t, rev1) @@ -234,7 +236,7 @@ func TestLayerVersionPermission_RevisionId(t *testing.T) { getRec := callInMemoryHandler(t, h, http.MethodGet, policyPath, "") var pol lambda.LayerVersionPolicy - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&pol)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &pol, jsonx.V1())) assert.NotContains(t, pol.Policy, "s2") // Stale RevisionId on Remove is rejected and leaves the statement in place. @@ -244,7 +246,7 @@ func TestLayerVersionPermission_RevisionId(t *testing.T) { getRec2 := callInMemoryHandler(t, h, http.MethodGet, policyPath, "") var pol2 lambda.LayerVersionPolicy - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&pol2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &pol2, jsonx.V1())) assert.Contains(t, pol2.Policy, "s1") // The correct RevisionId succeeds. diff --git a/services/lambda/layers.go b/services/lambda/layers.go index c574aeced3..e1cd08b96e 100644 --- a/services/lambda/layers.go +++ b/services/lambda/layers.go @@ -3,7 +3,7 @@ package lambda import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -346,7 +347,7 @@ func (b *InMemoryBackend) AddLayerVersionPermission( stmts[input.StatementID] = stmt - stmtJSON, marshalErr := json.Marshal(stmt) + stmtJSON, marshalErr := json.Marshal(stmt, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } @@ -454,7 +455,7 @@ func buildLayerPolicy(stmts map[string]*LayerVersionStatement) (string, error) { Statement: statements, } - data, err := json.Marshal(doc) + data, err := json.Marshal(doc, jsonx.V1()) if err != nil { return "", err } diff --git a/services/lambda/layers_http_test.go b/services/lambda/layers_http_test.go index 65c537e760..4f0b987f9c 100644 --- a/services/lambda/layers_http_test.go +++ b/services/lambda/layers_http_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -50,7 +52,7 @@ func TestLayer_PublishAndGet(t *testing.T) { require.Equal(t, http.StatusCreated, pubRec.Code) var pub lambda.PublishLayerVersionOutput - require.NoError(t, json.NewDecoder(pubRec.Body).Decode(&pub)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pubRec.Body), &pub, jsonx.V1())) assert.Equal(t, int64(1), pub.Version) assert.Equal(t, "v1", pub.Description) assert.Equal(t, []string{"python3.12", "python3.11"}, pub.CompatibleRuntimes) @@ -63,7 +65,7 @@ func TestLayer_PublishAndGet(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got lambda.GetLayerVersionOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &got, jsonx.V1())) assert.Equal(t, int64(1), got.Version) } @@ -79,7 +81,7 @@ func TestLayer_MultipleVersions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var pub lambda.PublishLayerVersionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&pub)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &pub, jsonx.V1())) assert.Equal(t, int64(i+1), pub.Version) } } @@ -99,7 +101,7 @@ func TestLayer_ListVersions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListLayerVersionsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.LayerVersions, 2) } @@ -134,7 +136,7 @@ func TestLayer_ListLayers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListLayersOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.Layers), 2) } @@ -149,14 +151,14 @@ func TestLayer_GetVersionByArn(t *testing.T) { require.Equal(t, http.StatusCreated, pubRec.Code) var pub lambda.PublishLayerVersionOutput - require.NoError(t, json.NewDecoder(pubRec.Body).Decode(&pub)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pubRec.Body), &pub, jsonx.V1())) rec := callInMemoryHandler(t, h, http.MethodGet, "/2018-10-31/layers?find=LayerVersion&Arn="+pub.LayerVersionArn, "") require.Equal(t, http.StatusOK, rec.Code) var got lambda.GetLayerVersionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &got, jsonx.V1())) assert.Equal(t, pub.LayerVersionArn, got.LayerVersionArn) } @@ -229,7 +231,7 @@ func TestListLayers_CompatibleRuntimeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) layers, _ := out["Layers"].([]any) assert.Len(t, layers, tc.wantCount, "layer count mismatch for runtime=%q", tc.compatibleRuntime) }) diff --git a/services/lambda/layers_test.go b/services/lambda/layers_test.go index 73ad3303c8..3c67b61683 100644 --- a/services/lambda/layers_test.go +++ b/services/lambda/layers_test.go @@ -3,7 +3,7 @@ package lambda_test import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -591,7 +592,7 @@ func TestCreateFunctionWithLayers(t *testing.T) { "Layers": tt.layers, } - bodyBytes, _ := json.Marshal(bodyMap) + bodyBytes, _ := json.Marshal(bodyMap, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/2015-03-31/functions", strings.NewReader(string(bodyBytes))) req.Header.Set("Content-Type", "application/json") rec := httptest.NewRecorder() diff --git a/services/lambda/list_functions_master_region_test.go b/services/lambda/list_functions_master_region_test.go index 83ab63e7ad..390b4c8eb4 100644 --- a/services/lambda/list_functions_master_region_test.go +++ b/services/lambda/list_functions_master_region_test.go @@ -1,12 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListFunctions_MasterRegion(t *testing.T) { @@ -50,9 +53,9 @@ func TestListFunctions_MasterRegion(t *testing.T) { } var out struct { - Functions []json.RawMessage `json:"Functions"` + Functions []jsontext.Value `json:"Functions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Functions, tt.wantCount) }) } diff --git a/services/lambda/mq_event.go b/services/lambda/mq_event.go index 519b5d4586..6a2455f5f5 100644 --- a/services/lambda/mq_event.go +++ b/services/lambda/mq_event.go @@ -2,10 +2,12 @@ package lambda import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "strconv" "time" "unicode/utf8" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Event shapes follow https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html. @@ -113,10 +115,10 @@ func strPtr(s string) *string { // buildMQEventPayload shapes msgs into the documented aws:mq or aws:rmq event. func buildMQEventPayload(eventSource, eventSourceARN, vhost string, msgs []mqMessage) ([]byte, error) { if eventSource == mqEventSourceRabbitMQ { - return json.Marshal(buildRabbitMQEvent(eventSourceARN, vhost, msgs)) + return json.Marshal(buildRabbitMQEvent(eventSourceARN, vhost, msgs), jsonx.V1()) } - return json.Marshal(buildActiveMQEvent(eventSourceARN, msgs)) + return json.Marshal(buildActiveMQEvent(eventSourceARN, msgs), jsonx.V1()) } func buildActiveMQEvent(eventSourceARN string, msgs []mqMessage) activeMQEvent { diff --git a/services/lambda/mq_event_internal_test.go b/services/lambda/mq_event_internal_test.go index f4ef964725..07e5106a92 100644 --- a/services/lambda/mq_event_internal_test.go +++ b/services/lambda/mq_event_internal_test.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync" "testing" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -244,7 +246,7 @@ func TestMQESMPollsRealBrokerOnly(t *testing.T) { var ev map[string]any - require.NoError(t, json.Unmarshal(<-deliveries, &ev)) + require.NoError(t, json.Unmarshal(<-deliveries, &ev, jsonx.V1())) assert.Equal(t, "aws:rmq", ev["eventSource"]) assert.Equal(t, mqTestBrokerARN, ev["eventSourceArn"]) assert.Contains(t, ev["rmqMessagesByQueue"], "q::/") diff --git a/services/lambda/mq_worker.go b/services/lambda/mq_worker.go index e113c567da..8cd85afb81 100644 --- a/services/lambda/mq_worker.go +++ b/services/lambda/mq_worker.go @@ -2,11 +2,12 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "reflect" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -169,7 +170,7 @@ func (p *EventSourcePoller) mqCredentials( } raw, err := secrets.SecretString(ctx, secretARN) - if err != nil || json.Unmarshal([]byte(raw), &creds) != nil { + if err != nil || json.Unmarshal([]byte(raw), &creds, jsonx.V1()) != nil { return creds, false } diff --git a/services/lambda/mq_worker_internal_test.go b/services/lambda/mq_worker_internal_test.go index 412554a10e..097c8bcbf2 100644 --- a/services/lambda/mq_worker_internal_test.go +++ b/services/lambda/mq_worker_internal_test.go @@ -2,7 +2,7 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync" "sync/atomic" @@ -12,6 +12,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errMQTestFunction = errors.New("boom") @@ -203,7 +205,7 @@ func TestMQWorkerBatching(t *testing.T) { Messages []struct{} `json:"messages"` } - require.NoError(t, json.Unmarshal(payload, &ev)) + require.NoError(t, json.Unmarshal(payload, &ev, jsonx.V1())) sizes = append(sizes, len(ev.Messages)) diff --git a/services/lambda/multi_region_test.go b/services/lambda/multi_region_test.go index 48b3c9615b..9147477dd5 100644 --- a/services/lambda/multi_region_test.go +++ b/services/lambda/multi_region_test.go @@ -3,7 +3,8 @@ package lambda_test import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -48,7 +50,7 @@ func regionCall(t *testing.T, h *lambda.Handler, region, method, path string, bo var buf bytes.Buffer if body != nil { - require.NoError(t, json.NewEncoder(&buf).Encode(body)) + require.NoError(t, json.MarshalEncode(jsontext.NewEncoder(&buf, jsonx.V1()), body)) } req := httptest.NewRequest(method, path, &buf).WithContext(regionCtx(region)) @@ -77,7 +79,7 @@ func createRegionFunction(t *testing.T, h *lambda.Handler, region, name string) FunctionArn string `json:"FunctionArn"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out.FunctionArn } @@ -95,7 +97,7 @@ func regionFunctionNames(t *testing.T, h *lambda.Handler, region string) []strin } `json:"Functions"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) names := make([]string, 0, len(out.Functions)) @@ -316,9 +318,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.remote, hasRegions) diff --git a/services/lambda/permissions.go b/services/lambda/permissions.go index f3e1efe019..a92e01a18c 100644 --- a/services/lambda/permissions.go +++ b/services/lambda/permissions.go @@ -4,13 +4,15 @@ import ( "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "strconv" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AddPermission adds a permission statement to a function's resource-based policy. @@ -271,10 +273,9 @@ func buildPermissionStatementJSON(p *FunctionPermission, resourceArn string) str var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) + enc := jsontext.NewEncoder(&buf, jsonx.V1(), jsontext.EscapeForHTML(false)) - if err := enc.Encode(stmt); err != nil { + if err := json.MarshalEncode(enc, stmt); err != nil { return "" } diff --git a/services/lambda/permissions_test.go b/services/lambda/permissions_test.go index 7cac66ff08..9994e43bf0 100644 --- a/services/lambda/permissions_test.go +++ b/services/lambda/permissions_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -29,7 +31,7 @@ func TestPermission_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, addRec.Code) var addOut lambda.AddPermissionOutput - require.NoError(t, json.NewDecoder(addRec.Body).Decode(&addOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(addRec.Body), &addOut, jsonx.V1())) require.NotNil(t, addOut.Statement) assert.NotEmpty(t, *addOut.Statement) @@ -44,7 +46,7 @@ func TestPermission_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var pol lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&pol)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &pol, jsonx.V1())) require.NotNil(t, pol.Policy) assert.Contains(t, *pol.Policy, "AllowS3") assert.Contains(t, *pol.Policy, "AllowSNS") @@ -63,7 +65,7 @@ func TestPermission_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var pol2 lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&pol2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &pol2, jsonx.V1())) assert.NotContains(t, *pol2.Policy, "AllowS3") assert.Contains(t, *pol2.Policy, "AllowSNS") } @@ -129,7 +131,7 @@ func TestPermission_SourceArn(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var addOut lambda.AddPermissionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&addOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &addOut, jsonx.V1())) require.NotNil(t, addOut.Statement) assert.NotEmpty(t, *addOut.Statement) // Statement must include the StatementId @@ -274,7 +276,7 @@ func TestPolicyJSON_SourceArnCondition(t *testing.T) { require.NotEmpty(t, policyStr) var policy map[string]any - require.NoError(t, json.Unmarshal([]byte(policyStr), &policy)) + require.NoError(t, json.Unmarshal([]byte(policyStr), &policy, jsonx.V1())) stmts, _ := policy["Statement"].([]any) require.Len(t, stmts, 1) stmt := stmts[0].(map[string]any) @@ -368,7 +370,7 @@ func TestAddPermission(t *testing.T) { if tt.wantStatus == http.StatusCreated { var out lambda.AddPermissionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.Statement) assert.NotEmpty(t, *out.Statement) } @@ -416,7 +418,7 @@ func TestAddPermission_FunctionUrlConditions(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out lambda.AddPermissionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.Statement) assert.Contains(t, *out.Statement, `"StringEquals":{"lambda:FunctionUrlAuthType":"NONE"}`) assert.Contains(t, *out.Statement, `"Bool":{"lambda:InvokedViaFunctionUrl":"true"}`) @@ -425,7 +427,7 @@ func TestAddPermission_FunctionUrlConditions(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var pol lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&pol)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &pol, jsonx.V1())) require.NotNil(t, pol.Policy) assert.Contains(t, *pol.Policy, "lambda:FunctionUrlAuthType") assert.Contains(t, *pol.Policy, "lambda:InvokedViaFunctionUrl") @@ -453,7 +455,7 @@ func TestAddPermission_RevisionId(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var pol lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&pol)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &pol, jsonx.V1())) require.NotNil(t, pol.RevisionID) rev1 := *pol.RevisionID assert.NotEmpty(t, rev1) @@ -466,7 +468,7 @@ func TestAddPermission_RevisionId(t *testing.T) { getRec2 := callInMemoryHandler(t, h, http.MethodGet, policyPath, "") var pol2 lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec2.Body).Decode(&pol2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec2.Body), &pol2, jsonx.V1())) assert.Equal(t, rev1, *pol2.RevisionID, "rejected AddPermission must not change the revision") assert.NotContains(t, *pol2.Policy, "s2") @@ -478,7 +480,7 @@ func TestAddPermission_RevisionId(t *testing.T) { getRec3 := callInMemoryHandler(t, h, http.MethodGet, policyPath, "") var pol3 lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec3.Body).Decode(&pol3)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec3.Body), &pol3, jsonx.V1())) rev3 := *pol3.RevisionID assert.NotEqual(t, rev1, rev3, "a real mutation must change the revision") @@ -489,7 +491,7 @@ func TestAddPermission_RevisionId(t *testing.T) { getRec4 := callInMemoryHandler(t, h, http.MethodGet, policyPath, "") var pol4 lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec4.Body).Decode(&pol4)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec4.Body), &pol4, jsonx.V1())) assert.Contains(t, *pol4.Policy, "s1", "rejected RemovePermission must not delete the statement") // RemovePermission with the correct RevisionId succeeds. @@ -519,7 +521,7 @@ func TestPermission_PolicyJSONEscapesValues(t *testing.T) { reqBody, err := json.Marshal(map[string]string{ "StatementId": tt.sid, "Action": "lambda:InvokeFunction", "Principal": "s3.amazonaws.com", "SourceArn": tt.sourceArn, - }) + }, jsonx.V1()) require.NoError(t, err) addRec := callInMemoryHandler(t, h, http.MethodPost, "/2015-03-31/functions/fn/policy", string(reqBody)) @@ -529,7 +531,7 @@ func TestPermission_PolicyJSONEscapesValues(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out lambda.GetPolicyOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) require.NotNil(t, out.Policy) type statement struct { @@ -540,7 +542,7 @@ func TestPermission_PolicyJSONEscapesValues(t *testing.T) { var doc struct { Statement []statement `json:"Statement"` } - require.NoError(t, json.Unmarshal([]byte(*out.Policy), &doc)) + require.NoError(t, json.Unmarshal([]byte(*out.Policy), &doc, jsonx.V1())) require.Len(t, doc.Statement, 1) assert.Equal(t, tt.sid, doc.Statement[0].Sid) assert.Equal(t, tt.sourceArn, doc.Statement[0].Condition["ArnLike"]["AWS:SourceArn"]) diff --git a/services/lambda/persistence.go b/services/lambda/persistence.go index 74141f40dc..b79df07bdc 100644 --- a/services/lambda/persistence.go +++ b/services/lambda/persistence.go @@ -2,10 +2,12 @@ package lambda import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -160,7 +162,7 @@ type backendSnapshot struct { // b.ephemeralRegistry (codeSigningConfigs, // provisionedConcurrencies) are deliberately NOT included here -- they // were never persisted before this refactor and must stay that way. - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` // The fields below have no pure, self-contained identity (see // store_setup.go's exclusion list) so they cannot become store.Tables, but // they WERE persisted before this refactor and must remain so. @@ -258,7 +260,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "persistence: snapshot marshal failed", "service", "lambda", "error", err) @@ -382,7 +384,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreFunctionsFromDTO restores b.functions from its "functions" DTO // entry in tables (gopherstack-rluhj; b.functions is not on b.registry, see // store_setup.go's package doc and functionConfigurationSnapshot above). -func (b *InMemoryBackend) restoreFunctionsFromDTO(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreFunctionsFromDTO(tables map[string]jsontext.Value) error { funcDTOReg := store.NewRegistry() funcDTOs := store.Register(funcDTOReg, "functions", store.New(functionConfigurationSnapshotKey)) @@ -403,7 +405,7 @@ func (b *InMemoryBackend) restoreFunctionsFromDTO(tables map[string]json.RawMess // restorePermissionsFromDTO restores b.permissions from its "permissions" // DTO entry in tables (b.permissions is not on b.registry, see // store_setup.go's package doc). -func (b *InMemoryBackend) restorePermissionsFromDTO(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restorePermissionsFromDTO(tables map[string]jsontext.Value) error { permDTOReg := store.NewRegistry() permDTOs := store.Register(permDTOReg, "permissions", store.New(permissionSnapshotKey)) diff --git a/services/lambda/provisioned_concurrency_test.go b/services/lambda/provisioned_concurrency_test.go index f53503851f..584dfa3d4b 100644 --- a/services/lambda/provisioned_concurrency_test.go +++ b/services/lambda/provisioned_concurrency_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -139,7 +141,7 @@ func TestPutProvisionedConcurrencyConfig(t *testing.T) { } var out lambda.ProvisionedConcurrencyConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantRequested, out.RequestedProvisionedConcurrentExecutions) assert.Equal(t, tt.wantRequested, out.AllocatedProvisionedConcurrentExecutions) assert.Equal(t, "READY", out.Status) @@ -233,7 +235,7 @@ func TestGetProvisionedConcurrencyConfig(t *testing.T) { } var out lambda.ProvisionedConcurrencyConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantRequested, out.RequestedProvisionedConcurrentExecutions) assert.Equal(t, "READY", out.Status) }) @@ -407,7 +409,7 @@ func TestListProvisionedConcurrencyConfigs(t *testing.T) { } var out lambda.ListProvisionedConcurrencyConfigsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.ProvisionedConcurrencyConfigs, tt.wantCount) }) } @@ -469,7 +471,7 @@ func TestProvisionedConcurrency_Lifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, putRec.Code) var pc lambda.ProvisionedConcurrencyConfig - require.NoError(t, json.NewDecoder(putRec.Body).Decode(&pc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putRec.Body), &pc, jsonx.V1())) assert.Equal(t, 5, pc.RequestedProvisionedConcurrentExecutions) assert.Equal(t, "READY", pc.Status) @@ -479,7 +481,7 @@ func TestProvisionedConcurrency_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getPC lambda.ProvisionedConcurrencyConfig - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getPC)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getPC, jsonx.V1())) assert.Equal(t, 5, getPC.RequestedProvisionedConcurrentExecutions) // List @@ -488,7 +490,7 @@ func TestProvisionedConcurrency_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListProvisionedConcurrencyConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.ProvisionedConcurrencyConfigs, 1) // Delete @@ -500,7 +502,7 @@ func TestProvisionedConcurrency_Lifecycle(t *testing.T) { listRec2 := callInMemoryHandler(t, h, http.MethodGet, "/2019-09-30/functions/pc-fn/provisioned-concurrency", "") var listOut2 lambda.ListProvisionedConcurrencyConfigsOutput - require.NoError(t, json.NewDecoder(listRec2.Body).Decode(&listOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec2.Body), &listOut2, jsonx.V1())) assert.Empty(t, listOut2.ProvisionedConcurrencyConfigs) } @@ -549,7 +551,7 @@ func TestProvisionedConcurrency_StatusReady(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.InDelta(t, float64(5), out["RequestedProvisionedConcurrentExecutions"], 0) assert.InDelta(t, float64(5), out["AllocatedProvisionedConcurrentExecutions"], 0) assert.InDelta(t, float64(5), out["AvailableProvisionedConcurrentExecutions"], 0) @@ -587,7 +589,7 @@ func TestProvisionedConcurrency_List_IncludesAllQualifiers(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out lambda.ListProvisionedConcurrencyConfigsOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.ProvisionedConcurrencyConfigs, 2) } @@ -658,7 +660,7 @@ func TestProvisionedConcurrency_FullCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var pcOut lambda.ProvisionedConcurrencyConfig - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pcOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pcOut, jsonx.V1())) assert.Equal(t, 5, pcOut.RequestedProvisionedConcurrentExecutions) assert.Equal(t, "READY", pcOut.Status) @@ -673,7 +675,7 @@ func TestProvisionedConcurrency_FullCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listOut lambda.ListProvisionedConcurrencyConfigsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.ProvisionedConcurrencyConfigs, 1) // DeleteProvisionedConcurrencyConfig. diff --git a/services/lambda/publish_latest_published_test.go b/services/lambda/publish_latest_published_test.go index 0e787f689f..c243a051e3 100644 --- a/services/lambda/publish_latest_published_test.go +++ b/services/lambda/publish_latest_published_test.go @@ -1,7 +1,7 @@ package lambda_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPublishVersion_PublishTo(t *testing.T) { @@ -44,13 +46,13 @@ func TestPublishVersion_PublishTo(t *testing.T) { } var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantVer, got["Version"]) assert.Contains(t, got["FunctionArn"], ":"+tt.wantVer) rec = callInMemoryHandler(t, h, http.MethodPost, "/2015-03-31/functions/pub-fn/versions", tt.body) require.Equal(t, http.StatusCreated, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) if tt.wantVer == "$LATEST.PUBLISHED" { assert.Equal(t, tt.wantVer, got["Version"], "republish keeps the single version") diff --git a/services/lambda/snapstart_extra_test.go b/services/lambda/snapstart_extra_test.go index 8a1baa6f02..ff80310a03 100644 --- a/services/lambda/snapstart_extra_test.go +++ b/services/lambda/snapstart_extra_test.go @@ -1,13 +1,15 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -62,7 +64,7 @@ func TestSnapStart_ReportedOnPublishedVersion(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ver lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ver)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ver, jsonx.V1())) require.NotNil(t, ver.SnapStart) assert.Equal(t, "PublishedVersions", ver.SnapStart.ApplyOn) assert.Equal(t, "On", ver.SnapStart.OptimizationStatus) @@ -85,6 +87,6 @@ func TestSnapStart_OmittedWhenUnset(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var ver lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ver)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ver, jsonx.V1())) assert.Nil(t, ver.SnapStart) } diff --git a/services/lambda/store_test.go b/services/lambda/store_test.go index b9fa96403c..1ae5fbbaf3 100644 --- a/services/lambda/store_test.go +++ b/services/lambda/store_test.go @@ -3,7 +3,7 @@ package lambda_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -596,7 +597,7 @@ func TestBuildURLEventPayload(t *testing.T) { require.NoError(t, err) var event map[string]any - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) if tt.wantVersion != "" { assert.Equal(t, tt.wantVersion, event["version"]) diff --git a/services/lambda/tags_test.go b/services/lambda/tags_test.go index a10b54ac09..91903620ca 100644 --- a/services/lambda/tags_test.go +++ b/services/lambda/tags_test.go @@ -2,13 +2,15 @@ package lambda_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -26,7 +28,7 @@ func TestTags_TagAndListAndUntag(t *testing.T) { getRec := callInMemoryHandler(t, h, http.MethodGet, "/2015-03-31/functions/tags-fn", "") var out lambda.GetFunctionOutput - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) fnARN := out.Configuration.FunctionArn // Tag @@ -41,7 +43,7 @@ func TestTags_TagAndListAndUntag(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsOut map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&tagsOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -57,7 +59,7 @@ func TestTags_TagAndListAndUntag(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var tagsOut2 map[string]any - require.NoError(t, json.NewDecoder(listRec2.Body).Decode(&tagsOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec2.Body), &tagsOut2, jsonx.V1())) tags2, _ := tagsOut2["Tags"].(map[string]any) _, hasEnv := tags2["env"] assert.False(t, hasEnv) @@ -85,7 +87,7 @@ func TestGetFunction_ReturnsTopLevelTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) rawTags, ok := out["Tags"].(map[string]any) require.True(t, ok, "GetFunctionOutput must have a top-level Tags field, got: %v", out["Tags"]) @@ -103,7 +105,7 @@ func TestTags_CreateFunctionWithTags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) // Tags may be in the function config or accessible separately _ = fn } @@ -142,7 +144,7 @@ func TestTaggedFunctions_CreationTags(t *testing.T) { h, _ := newInMemoryHandler(t) - tagsJSON, err := json.Marshal(tt.tags) + tagsJSON, err := json.Marshal(tt.tags, jsonx.V1()) require.NoError(t, err) body := `{"FunctionName":"` + tt.fnName + `","PackageType":"Image","Code":{"ImageUri":"x"},` + diff --git a/services/lambda/test_helpers_test.go b/services/lambda/test_helpers_test.go index 5550ebb40e..4a05416224 100644 --- a/services/lambda/test_helpers_test.go +++ b/services/lambda/test_helpers_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "fmt" "hash/crc32" "io" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -163,7 +164,7 @@ func lambdaParseBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]an t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/lambda/versions_aliases_test.go b/services/lambda/versions_aliases_test.go index adc5a70e20..debae34d6b 100644 --- a/services/lambda/versions_aliases_test.go +++ b/services/lambda/versions_aliases_test.go @@ -1,7 +1,8 @@ package lambda_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -83,7 +85,7 @@ func TestPublishVersion_Basic(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var v lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&v)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &v, jsonx.V1())) assert.Equal(t, "1", v.Version) assert.Equal(t, "ver-fn", v.FunctionName) assert.NotEmpty(t, v.FunctionArn) @@ -101,7 +103,7 @@ func TestPublishVersion_Increments(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var v lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&v)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &v, jsonx.V1())) assert.Equal(t, strconv.Itoa(i), v.Version) } } @@ -117,7 +119,7 @@ func TestPublishVersion_WithDescription(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var v lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&v)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &v, jsonx.V1())) assert.Equal(t, "my-snapshot", v.Description) assert.Equal(t, "1", v.Version) } @@ -143,7 +145,7 @@ func TestListVersionsByFunction_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListVersionsByFunctionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) // $LATEST is always present require.NotEmpty(t, out.Versions) assert.Equal(t, "$LATEST", out.Versions[0].Version) @@ -163,7 +165,7 @@ func TestListVersionsByFunction_AfterPublish(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out lambda.ListVersionsByFunctionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) // $LATEST + 2 numbered versions assert.GreaterOrEqual(t, len(out.Versions), 2) @@ -196,7 +198,7 @@ func TestPublishVersion_Publish_CreateFunction(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, "1", fn.Version) } @@ -211,7 +213,7 @@ func TestFunctionVersion_ARNFormat(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var v lambda.FunctionVersion - require.NoError(t, json.NewDecoder(rec.Body).Decode(&v)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &v, jsonx.V1())) // versioned ARN should end with :1 assert.True(t, strings.HasSuffix(v.FunctionArn, ":1"), "expected ARN to end with :1, got %s", v.FunctionArn) } @@ -235,7 +237,7 @@ func TestAlias_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var alias lambda.FunctionAlias - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&alias)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &alias, jsonx.V1())) assert.Equal(t, "live", alias.Name) assert.Equal(t, "1", alias.FunctionVersion) assert.Equal(t, "prod alias", alias.Description) @@ -247,7 +249,7 @@ func TestAlias_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getAlias lambda.FunctionAlias - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getAlias)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getAlias, jsonx.V1())) assert.Equal(t, "live", getAlias.Name) // List aliases @@ -256,7 +258,7 @@ func TestAlias_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listOut lambda.ListAliasesOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.Aliases, 1) // Delete alias @@ -284,7 +286,7 @@ func TestAlias_RoutingConfig_WeightedTraffic(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var alias lambda.FunctionAlias - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&alias)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &alias, jsonx.V1())) require.NotNil(t, alias.RoutingConfig) assert.InDelta(t, 0.1, alias.RoutingConfig.AdditionalVersionWeights["2"], 0.001) } @@ -308,7 +310,7 @@ func TestAlias_Update(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updated lambda.FunctionAlias - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updated)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updated, jsonx.V1())) assert.Equal(t, "2", updated.FunctionVersion) assert.Equal(t, "now v2", updated.Description) } @@ -331,7 +333,7 @@ func TestAlias_UpdateRoutingConfig(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updated lambda.FunctionAlias - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&updated)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &updated, jsonx.V1())) require.NotNil(t, updated.RoutingConfig) assert.InDelta(t, 0.2, updated.RoutingConfig.AdditionalVersionWeights["2"], 0.001) } @@ -388,14 +390,14 @@ func TestAlias_RevisionID_Changes(t *testing.T) { `{"Name":"rev","FunctionVersion":"1"}`) require.Equal(t, http.StatusCreated, createRec.Code) var a1 lambda.FunctionAlias - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&a1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &a1, jsonx.V1())) updRec := callInMemoryHandler(t, h, http.MethodPut, "/2015-03-31/functions/alias-rev-fn/aliases/rev", `{"FunctionVersion":"2"}`) require.Equal(t, http.StatusOK, updRec.Code) var a2 lambda.FunctionAlias - require.NoError(t, json.NewDecoder(updRec.Body).Decode(&a2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(updRec.Body), &a2, jsonx.V1())) assert.NotEqual(t, a1.RevisionID, a2.RevisionID) } @@ -418,7 +420,7 @@ func TestAlias_RevisionID_Precondition(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var a1 lambda.FunctionAlias - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&a1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &a1, jsonx.V1())) staleRec := callInMemoryHandler(t, h, http.MethodPut, "/2015-03-31/functions/alias-precond-fn/aliases/pc", @@ -428,7 +430,7 @@ func TestAlias_RevisionID_Precondition(t *testing.T) { getRec := callInMemoryHandler(t, h, http.MethodGet, "/2015-03-31/functions/alias-precond-fn/aliases/pc", "") var got lambda.FunctionAlias - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &got, jsonx.V1())) assert.Equal(t, "1", got.FunctionVersion, "rejected update must not change the alias") okRec := callInMemoryHandler(t, h, http.MethodPut, @@ -459,7 +461,7 @@ func TestPublishVersion_RevisionID_Precondition(t *testing.T) { listRec := callInMemoryHandler(t, h, http.MethodGet, "/2015-03-31/functions/publish-precond-fn/versions", "") var list lambda.ListVersionsByFunctionOutput - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&list)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &list, jsonx.V1())) assert.Len(t, list.Versions, 1, "rejected publish must not create a numbered version ($LATEST only)") okRec := callInMemoryHandler(t, h, http.MethodPost, @@ -502,7 +504,7 @@ func TestVersion_AlwaysLatestInCreateFunction(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, tt.wantVersion, fn.Version, "CreateFunction response must include Version=%q", tt.wantVersion) }) @@ -541,7 +543,7 @@ func TestVersion_AlwaysLatestInGetFunctionConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, "$LATEST", fn.Version, "GetFunctionConfiguration must always return Version=$LATEST for live code") }) @@ -578,7 +580,7 @@ func TestVersion_LiveFunctionStaysLatestAfterPublish(t *testing.T) { `{"ImageUri":"x:v2","Publish":true}`) require.Equal(t, http.StatusOK, rec.Code) var upd lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&upd)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &upd, jsonx.V1())) assert.Equal(t, "1", upd.Version, "UpdateFunctionCode Publish=true response must show numbered version") }, @@ -599,7 +601,7 @@ func TestVersion_LiveFunctionStaysLatestAfterPublish(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fn)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fn, jsonx.V1())) assert.Equal(t, "$LATEST", fn.Version, "GetFunctionConfiguration after publish must still return Version=$LATEST") }) @@ -636,7 +638,7 @@ func TestAliasRouting(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var alias lambda.FunctionAlias - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alias, jsonx.V1())) assert.Equal(t, "prod", alias.Name) assert.Equal(t, v1.Version, alias.FunctionVersion) @@ -651,7 +653,7 @@ func TestAliasRouting(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listOut lambda.ListAliasesOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Aliases, 1) // UpdateAlias — point to v2 with weighted routing 10% to v1. @@ -664,7 +666,7 @@ func TestAliasRouting(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated lambda.FunctionAlias - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, v2.Version, updated.FunctionVersion) require.NotNil(t, updated.RoutingConfig) assert.InDelta(t, 0.1, updated.RoutingConfig.AdditionalVersionWeights[v1.Version], 0.001) diff --git a/services/lambda/zip_handler_test.go b/services/lambda/zip_handler_test.go index a4631874ca..f027588474 100644 --- a/services/lambda/zip_handler_test.go +++ b/services/lambda/zip_handler_test.go @@ -3,13 +3,14 @@ package lambda_test import ( "archive/zip" "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lambda" ) @@ -150,7 +151,7 @@ func TestZipHandler_CreateFunction(t *testing.T) { h, _ := newHandler(t) - body, err := json.Marshal(tt.input) + body, err := json.Marshal(tt.input, jsonx.V1()) require.NoError(t, err) rec := callHandler(t, h, http.MethodPost, "/2015-03-31/functions", string(body), nil) @@ -162,7 +163,7 @@ func TestZipHandler_CreateFunction(t *testing.T) { } var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) if tt.wantFnName != "" { assert.Equal(t, tt.wantFnName, fn.FunctionName) @@ -192,7 +193,7 @@ func TestZipHandler_UpdateFunctionCode(t *testing.T) { zipBody := func() string { zipBytes := makeTestZip(t, `def handler(event, context): return "updated"`) - b, err := json.Marshal(map[string]any{"ZipFile": zipBytes}) + b, err := json.Marshal(map[string]any{"ZipFile": zipBytes}, jsonx.V1()) require.NoError(t, err) return string(b) @@ -244,7 +245,7 @@ func TestZipHandler_UpdateFunctionCode(t *testing.T) { if tt.wantRevisionID { var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) assert.NotEmpty(t, fn.RevisionID) } }) @@ -292,7 +293,7 @@ func TestZipHandler_UpdateFunctionConfiguration(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var fn lambda.FunctionConfiguration - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &fn, jsonx.V1())) assert.Equal(t, tt.wantRuntime, fn.Runtime) assert.Equal(t, tt.wantHandler, fn.Handler) }) @@ -348,7 +349,7 @@ func TestZipHandler_BuildCodeLocation(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var out lambda.GetFunctionOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.Code) if tt.wantImageURI != "" { diff --git a/services/lightsail/error_envelope_test.go b/services/lightsail/error_envelope_test.go index 57df4b49cc..0b0810ffc0 100644 --- a/services/lightsail/error_envelope_test.go +++ b/services/lightsail/error_envelope_test.go @@ -2,7 +2,7 @@ package lightsail_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/lightsail" @@ -53,7 +54,7 @@ func TestErrorEnvelope_NotFoundDecodesToTypedError(t *testing.T) { require.Equal(t, http.StatusBadRequest, rawStatus) var envelope map[string]any - require.NoError(t, json.Unmarshal(rawBody, &envelope)) + require.NoError(t, json.Unmarshal(rawBody, &envelope, jsonx.V1())) require.Equal(t, "NotFoundException", envelope["__type"], "raw response must carry the JSON body key __type the SDK's getProtocolErrorInfo reads") msg, ok := envelope["message"] diff --git a/services/lightsail/handler.go b/services/lightsail/handler.go index e0d3052076..ff51a6b0cb 100644 --- a/services/lightsail/handler.go +++ b/services/lightsail/handler.go @@ -2,7 +2,8 @@ package lightsail import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -197,8 +199,8 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } - var m map[string]json.RawMessage - if unmarshalErr := json.Unmarshal(body, &m); unmarshalErr != nil { + var m map[string]jsontext.Value + if unmarshalErr := json.Unmarshal(body, &m, jsonx.V1()); unmarshalErr != nil { return "" } @@ -210,11 +212,11 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ) } -func extractFirstResourceByKeys(body map[string]json.RawMessage, keys ...string) string { +func extractFirstResourceByKeys(body map[string]jsontext.Value, keys ...string) string { for _, key := range keys { if raw, ok := body[key]; ok { var v string - if err := json.Unmarshal(raw, &v); err == nil && v != "" { + if err := json.Unmarshal(raw, &v, jsonx.V1()); err == nil && v != "" { return v } } @@ -292,7 +294,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin } body := map[string]string{"__type": errType, "message": err.Error()} - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.1") @@ -306,7 +308,7 @@ func decodeBody[T any](body []byte) (*T, error) { var v T if len(body) > 0 { - if err := json.Unmarshal(body, &v); err != nil { + if err := json.Unmarshal(body, &v, jsonx.V1()); err != nil { return nil, validationError("malformed request body: " + err.Error()) } } @@ -318,7 +320,7 @@ func decodeBody[T any](body []byte) (*T, error) { // exception (marshaling our own well-typed wire structs should never // fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, serviceError("lightsail: marshal response: " + err.Error()) } diff --git a/services/lightsail/multi_region_test.go b/services/lightsail/multi_region_test.go index b8107c369f..615a342aed 100644 --- a/services/lightsail/multi_region_test.go +++ b/services/lightsail/multi_region_test.go @@ -1,7 +1,7 @@ package lightsail_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lightsail" ) @@ -37,7 +38,7 @@ func lightsailCall(t *testing.T, h *lightsail.Handler, region, op, body string) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/lightsail/persistence.go b/services/lightsail/persistence.go index ddd806cc0f..a0d9bebfd5 100644 --- a/services/lightsail/persistence.go +++ b/services/lightsail/persistence.go @@ -2,7 +2,7 @@ package lightsail import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -18,14 +18,14 @@ const lightsailSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Lightsail backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - DefaultKeyPair *KeyPair `json:"defaultKeyPair,omitempty"` - Partner *PartnerProfile `json:"partner,omitempty"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` - NextAccessKeySeq int `json:"nextAccessKeySeq"` - VpcPeered bool `json:"vpcPeered"` + Tables map[string]jsontext.Value `json:"tables"` + DefaultKeyPair *KeyPair `json:"defaultKeyPair,omitempty"` + Partner *PartnerProfile `json:"partner,omitempty"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` + NextAccessKeySeq int `json:"nextAccessKeySeq"` + VpcPeered bool `json:"vpcPeered"` } // Snapshot serialises the backend state to JSON. diff --git a/services/lightsail/sdk_roundtrip_field_fixes_test.go b/services/lightsail/sdk_roundtrip_field_fixes_test.go index eeba85eb37..f20fa02f69 100644 --- a/services/lightsail/sdk_roundtrip_field_fixes_test.go +++ b/services/lightsail/sdk_roundtrip_field_fixes_test.go @@ -1,7 +1,8 @@ package lightsail_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "time" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/lightsail" ) @@ -160,22 +162,22 @@ func testGetRelationalDatabaseEventsDuration(t *testing.T) { func backdateOldestEvent(t *testing.T, backend *lightsail.InMemoryBackend, dbName string, when time.Time) { t.Helper() - type snapshot = map[string]json.RawMessage + type snapshot = map[string]jsontext.Value raw := backend.Snapshot(t.Context()) require.NotEmpty(t, raw) var snap snapshot - require.NoError(t, json.Unmarshal(raw, &snap)) + require.NoError(t, json.Unmarshal(raw, &snap, jsonx.V1())) var tables snapshot - require.NoError(t, json.Unmarshal(snap["tables"], &tables)) + require.NoError(t, json.Unmarshal(snap["tables"], &tables, jsonx.V1())) // Decoded as untyped maps, not lightsail.RelationalDatabase, so this // edit doesn't need (and musttag doesn't demand) a json tag on an // internal persistence struct that intentionally has none. var dbs []map[string]any - require.NoError(t, json.Unmarshal(tables["databases"], &dbs)) + require.NoError(t, json.Unmarshal(tables["databases"], &dbs, jsonx.V1())) require.Len(t, dbs, 1) require.Equal(t, dbName, dbs[0]["Name"]) @@ -187,15 +189,15 @@ func backdateOldestEvent(t *testing.T, backend *lightsail.InMemoryBackend, dbNam require.True(t, ok) event["CreatedAt"] = when.Format(time.RFC3339Nano) - newDBs, err := json.Marshal(dbs) + newDBs, err := json.Marshal(dbs, jsonx.V1()) require.NoError(t, err) tables["databases"] = newDBs - newTables, err := json.Marshal(tables) + newTables, err := json.Marshal(tables, jsonx.V1()) require.NoError(t, err) snap["tables"] = newTables - newSnap, err := json.Marshal(snap) + newSnap, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) require.NoError(t, backend.Restore(t.Context(), newSnap)) From c1ee91f17540a47c354a1380bbc8ff65ed671af2 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 12:37:03 -0600 Subject: [PATCH 06/11] refactor(json): lint fixes for services a-l (dupl scope, whitespace, gosec, unconvert) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- services/acm/handler_acme_domain_validations.go | 1 + services/acm/handler_acme_eab.go | 1 + services/apigateway/handler_authorizers.go | 1 + services/apigateway/handler_base_path_mappings.go | 1 + services/apigateway/handler_documentation.go | 1 + services/apigateway/handler_request_validators.go | 1 + services/apigateway/handler_schema_models.go | 1 + services/applicationautoscaling/handler.go | 1 - services/apprunner/handler.go | 1 - services/appstream/handler.go | 2 ++ services/appstream/handler_appblock.go | 2 ++ services/appstream/handler_application.go | 2 ++ services/appstream/handler_image.go | 1 + services/azurefunctions/kudu.go | 2 +- services/bedrockagent/handler_helpers.go | 1 - services/ce/handler.go | 1 - services/cloudcontrol/handler.go | 1 - services/codebuild/handler.go | 1 - services/codestarconnections/handler.go | 1 - services/datasync/handler.go | 1 - services/directoryservice/handler_directories.go | 1 + services/directoryservice/handler_snapshots.go | 1 + services/ecs/handler.go | 1 - services/firehose/handler.go | 1 - services/gcpeventarc/delivery.go | 2 +- services/gcpresourcemanager/v1.go | 2 +- services/inspector2/handler_findings.go | 1 + services/inspector2/handler_sbom.go | 1 + services/iotwireless/persistence.go | 2 +- services/kinesisanalytics/handler.go | 1 - services/kinesisvideo/handler_signaling.go | 1 + services/kinesisvideo/handler_streams.go | 1 + 32 files changed, 24 insertions(+), 15 deletions(-) diff --git a/services/acm/handler_acme_domain_validations.go b/services/acm/handler_acme_domain_validations.go index ab1e415633..95a6bf3747 100644 --- a/services/acm/handler_acme_domain_validations.go +++ b/services/acm/handler_acme_domain_validations.go @@ -205,6 +205,7 @@ type listAcmeDomainValidationsOutput struct { AcmeDomainValidations []acmeDomainValidationWire `json:"AcmeDomainValidations"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) jsonListAcmeDomainValidations(ctx context.Context, body []byte) (any, error) { var input listAcmeDomainValidationsInput if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { diff --git a/services/acm/handler_acme_eab.go b/services/acm/handler_acme_eab.go index a214d5d3be..79fe1c47d4 100644 --- a/services/acm/handler_acme_eab.go +++ b/services/acm/handler_acme_eab.go @@ -169,6 +169,7 @@ type listAcmeEABsOutput struct { ExternalAccountBindings []acmeEABWire `json:"ExternalAccountBindings"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) jsonListAcmeExternalAccountBindings(ctx context.Context, body []byte) (any, error) { var input listAcmeEABsInput if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { diff --git a/services/apigateway/handler_authorizers.go b/services/apigateway/handler_authorizers.go index 222e02a6d1..3ed1a9ad02 100644 --- a/services/apigateway/handler_authorizers.go +++ b/services/apigateway/handler_authorizers.go @@ -107,6 +107,7 @@ func (h *Handler) getAuthorizerAction(b []byte) (int, any, error) { return http.StatusOK, auth, nil } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) getAuthorizersAction(b []byte) (int, any, error) { var input getAuthorizersInput if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { diff --git a/services/apigateway/handler_base_path_mappings.go b/services/apigateway/handler_base_path_mappings.go index 8568bee45b..ca4997c1a9 100644 --- a/services/apigateway/handler_base_path_mappings.go +++ b/services/apigateway/handler_base_path_mappings.go @@ -77,6 +77,7 @@ func (h *Handler) getBasePathMappingAction(b []byte) (int, any, error) { return http.StatusOK, bpm, nil } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) getBasePathMappingsAction(b []byte) (int, any, error) { var input getBasePathMappingsInput if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { diff --git a/services/apigateway/handler_documentation.go b/services/apigateway/handler_documentation.go index dd9e095431..61dec97d11 100644 --- a/services/apigateway/handler_documentation.go +++ b/services/apigateway/handler_documentation.go @@ -282,6 +282,7 @@ func (h *Handler) getDocumentationVersionAction(b []byte) (int, any, error) { return http.StatusOK, v, nil } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) getDocumentationVersionsAction(b []byte) (int, any, error) { var input getDocumentationVersionsInput if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { diff --git a/services/apigateway/handler_request_validators.go b/services/apigateway/handler_request_validators.go index 1535211901..bd034fb8c3 100644 --- a/services/apigateway/handler_request_validators.go +++ b/services/apigateway/handler_request_validators.go @@ -77,6 +77,7 @@ func (h *Handler) getRequestValidatorAction(b []byte) (int, any, error) { return http.StatusOK, rv, nil } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) getRequestValidatorsAction(b []byte) (int, any, error) { var input getRequestValidatorsInput if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { diff --git a/services/apigateway/handler_schema_models.go b/services/apigateway/handler_schema_models.go index de70de7318..b653b09b29 100644 --- a/services/apigateway/handler_schema_models.go +++ b/services/apigateway/handler_schema_models.go @@ -74,6 +74,7 @@ func (h *Handler) getModelAction(b []byte) (int, any, error) { return http.StatusOK, m, nil } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) getModelsAction(b []byte) (int, any, error) { var input getModelsInput if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { diff --git a/services/applicationautoscaling/handler.go b/services/applicationautoscaling/handler.go index a43b97bae2..fe95936868 100644 --- a/services/applicationautoscaling/handler.go +++ b/services/applicationautoscaling/handler.go @@ -235,7 +235,6 @@ func clientMessage(err error) string { } func (h *Handler) writeAPIError(_ context.Context, c *echo.Context, _ string, err error, msg string) error { - resourceName := "" if rn, ok := errors.AsType[resourceNamer](err); ok { resourceName = rn.ResourceName() diff --git a/services/apprunner/handler.go b/services/apprunner/handler.go index b029f1de20..a2a4d03c47 100644 --- a/services/apprunner/handler.go +++ b/services/apprunner/handler.go @@ -197,7 +197,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - switch { case errors.Is(err, awserr.ErrNotFound): return c.JSON(http.StatusBadRequest, map[string]string{ diff --git a/services/appstream/handler.go b/services/appstream/handler.go index a5608ebbaf..2109579589 100644 --- a/services/appstream/handler.go +++ b/services/appstream/handler.go @@ -699,6 +699,7 @@ type describeStacksInput struct { Names []string `json:"Names"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeStacks(_ context.Context, body []byte) (any, error) { var req describeStacksInput if len(body) > 0 { @@ -926,6 +927,7 @@ type describeFleetsInput struct { Names []string `json:"Names"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeFleets(_ context.Context, body []byte) (any, error) { var req describeFleetsInput if len(body) > 0 { diff --git a/services/appstream/handler_appblock.go b/services/appstream/handler_appblock.go index 3ef409d084..e64b2b5919 100644 --- a/services/appstream/handler_appblock.go +++ b/services/appstream/handler_appblock.go @@ -96,6 +96,7 @@ type describeAppBlocksInput struct { Arns []string `json:"Arns"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeAppBlocks(_ context.Context, body []byte) (any, error) { var req describeAppBlocksInput if len(body) > 0 { @@ -194,6 +195,7 @@ type describeAppBlockBuildersInput struct { Names []string `json:"Names"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeAppBlockBuilders(_ context.Context, body []byte) (any, error) { var req describeAppBlockBuildersInput if len(body) > 0 { diff --git a/services/appstream/handler_application.go b/services/appstream/handler_application.go index bcecf9a833..c5fabec8c6 100644 --- a/services/appstream/handler_application.go +++ b/services/appstream/handler_application.go @@ -85,6 +85,7 @@ type describeApplicationsInput struct { Arns []string `json:"Arns"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeApplications(_ context.Context, body []byte) (any, error) { var req describeApplicationsInput if len(body) > 0 { @@ -524,6 +525,7 @@ type describeDirectoryConfigsInput struct { DirectoryNames []string `json:"DirectoryNames"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeDirectoryConfigs(_ context.Context, body []byte) (any, error) { var req describeDirectoryConfigsInput if len(body) > 0 { diff --git a/services/appstream/handler_image.go b/services/appstream/handler_image.go index 86243005c7..ba3efa717d 100644 --- a/services/appstream/handler_image.go +++ b/services/appstream/handler_image.go @@ -333,6 +333,7 @@ type describeImageBuildersInput struct { Names []string `json:"Names"` } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) opDescribeImageBuilders(_ context.Context, body []byte) (any, error) { var req describeImageBuildersInput if len(body) > 0 { diff --git a/services/azurefunctions/kudu.go b/services/azurefunctions/kudu.go index 097a9a3514..8b64e1da45 100644 --- a/services/azurefunctions/kudu.go +++ b/services/azurefunctions/kudu.go @@ -85,7 +85,7 @@ func writeJSON(w http.ResponseWriter, status int, v any) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(status) - _, _ = w.Write(raw) + _, _ = w.Write(raw) // #nosec G705 } // authorized accepts the app's publishing credentials as Basic auth, or any Bearer token (Kudu trusts the diff --git a/services/bedrockagent/handler_helpers.go b/services/bedrockagent/handler_helpers.go index 71775bc35e..462edaa5e7 100644 --- a/services/bedrockagent/handler_helpers.go +++ b/services/bedrockagent/handler_helpers.go @@ -21,7 +21,6 @@ import ( var wireCodePrefix = regexp.MustCompile(`^(?:[A-Za-z]+Exception: )+`) func handleErr(c *echo.Context, err error) error { - var code string var status int diff --git a/services/ce/handler.go b/services/ce/handler.go index 1cde01e271..9ee3720c0c 100644 --- a/services/ce/handler.go +++ b/services/ce/handler.go @@ -201,7 +201,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - switch { case errors.Is(err, ErrUnknownMonitor): payload, _ := json.Marshal(service.JSONErrorResponse{ diff --git a/services/cloudcontrol/handler.go b/services/cloudcontrol/handler.go index 8e7ae80914..36877139ad 100644 --- a/services/cloudcontrol/handler.go +++ b/services/cloudcontrol/handler.go @@ -143,7 +143,6 @@ func marshalError(errType, message string) []byte { // exceptions (e.g. ConcurrentModificationException, ServiceInternalErrorException) use 500. // See e.g. https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_GetResource.html#API_GetResource_Errors func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - switch { case errors.Is(err, ErrClientTokenConflict): return ccError(c, http.StatusBadRequest, "ClientTokenConflictException", err, diff --git a/services/codebuild/handler.go b/services/codebuild/handler.go index 538213da2e..485fe18ce3 100644 --- a/services/codebuild/handler.go +++ b/services/codebuild/handler.go @@ -273,7 +273,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - respond := func(errType string) error { payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errType, diff --git a/services/codestarconnections/handler.go b/services/codestarconnections/handler.go index e3efeb72e4..ac1cb18e65 100644 --- a/services/codestarconnections/handler.go +++ b/services/codestarconnections/handler.go @@ -236,7 +236,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b const codestarContentType = "application/x-amz-json-1.0" func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var errType string var statusCode int diff --git a/services/datasync/handler.go b/services/datasync/handler.go index 02e10e3940..15a61d4265 100644 --- a/services/datasync/handler.go +++ b/services/datasync/handler.go @@ -231,7 +231,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - switch { // ErrNotFound/ErrAlreadyExists deliberately map to the SAME wire code as // ErrInvalidParameter below: every one of datasync's 53 diff --git a/services/directoryservice/handler_directories.go b/services/directoryservice/handler_directories.go index d4d10e7c01..0afadb6ba3 100644 --- a/services/directoryservice/handler_directories.go +++ b/services/directoryservice/handler_directories.go @@ -154,6 +154,7 @@ func (h *Handler) handleCreateMicrosoftAD(c *echo.Context) error { }) } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleDeleteDirectory(c *echo.Context) error { body, err := httputils.ReadBody(c.Request()) if err != nil { diff --git a/services/directoryservice/handler_snapshots.go b/services/directoryservice/handler_snapshots.go index a89c3d1a5b..bd52126636 100644 --- a/services/directoryservice/handler_snapshots.go +++ b/services/directoryservice/handler_snapshots.go @@ -39,6 +39,7 @@ func (h *Handler) handleCreateSnapshot(c *echo.Context) error { }) } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleDeleteSnapshot(c *echo.Context) error { body, err := httputils.ReadBody(c.Request()) if err != nil { diff --git a/services/ecs/handler.go b/services/ecs/handler.go index a761d2d3d4..c50b27c852 100644 --- a/services/ecs/handler.go +++ b/services/ecs/handler.go @@ -369,7 +369,6 @@ func (h *Handler) Reset() { } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - switch { case errors.Is(err, awserr.ErrNotFound): code := errorCode(err) diff --git a/services/firehose/handler.go b/services/firehose/handler.go index 099c821b0f..0172096361 100644 --- a/services/firehose/handler.go +++ b/services/firehose/handler.go @@ -200,7 +200,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - respond := func(status int, errType string) error { msg := strings.TrimPrefix(err.Error(), errType+": ") diff --git a/services/gcpeventarc/delivery.go b/services/gcpeventarc/delivery.go index 2eea1a3e79..9ebb6d54af 100644 --- a/services/gcpeventarc/delivery.go +++ b/services/gcpeventarc/delivery.go @@ -180,7 +180,7 @@ type structuredEvent struct { func workflowArgument(ev cloudEvent) ([]byte, error) { data := jsontext.Value(ev.body) - if !jsontext.Value(data).IsValid(jsonx.V1()) { + if !data.IsValid(jsonx.V1()) { quoted, err := json.Marshal(string(ev.body), jsonx.V1()) if err != nil { return nil, err diff --git a/services/gcpresourcemanager/v1.go b/services/gcpresourcemanager/v1.go index 3ec478d845..05efa055c2 100644 --- a/services/gcpresourcemanager/v1.go +++ b/services/gcpresourcemanager/v1.go @@ -155,7 +155,7 @@ func writeV1JSON(w http.ResponseWriter, code int, v any) { func writeV1Raw(w http.ResponseWriter, code int, raw []byte) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(code) - _, _ = w.Write(raw) + _, _ = w.Write(raw) // #nosec G705 } func writeV1Proto(w http.ResponseWriter, m proto.Message) { diff --git a/services/inspector2/handler_findings.go b/services/inspector2/handler_findings.go index afe56d49b7..52bbba360b 100644 --- a/services/inspector2/handler_findings.go +++ b/services/inspector2/handler_findings.go @@ -174,6 +174,7 @@ func resourceToWire(r FindingResource) map[string]any { return res } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleCreateFindingsReport(c *echo.Context) error { body, err := httputils.ReadBody(c.Request()) if err != nil { diff --git a/services/inspector2/handler_sbom.go b/services/inspector2/handler_sbom.go index a44d611ba9..1ec38d2ee4 100644 --- a/services/inspector2/handler_sbom.go +++ b/services/inspector2/handler_sbom.go @@ -20,6 +20,7 @@ const ( pathSbomExportGet = "/sbomexport/get" ) +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleCreateSbomExport(c *echo.Context) error { body, err := httputils.ReadBody(c.Request()) if err != nil { diff --git a/services/iotwireless/persistence.go b/services/iotwireless/persistence.go index 67b5e39aa9..f79d017b71 100644 --- a/services/iotwireless/persistence.go +++ b/services/iotwireless/persistence.go @@ -298,7 +298,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Idempotency: idemEntries, } - data, err := json.Marshal(snap, jsonx.V1()) //nolint:musttag // nested types lack tags + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "iotwireless: failed to marshal snapshot", "error", err) diff --git a/services/kinesisanalytics/handler.go b/services/kinesisanalytics/handler.go index 0afdd6a3ae..162971e23a 100644 --- a/services/kinesisanalytics/handler.go +++ b/services/kinesisanalytics/handler.go @@ -203,7 +203,6 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var code string var status int diff --git a/services/kinesisvideo/handler_signaling.go b/services/kinesisvideo/handler_signaling.go index ac46d293cc..a9d5587384 100644 --- a/services/kinesisvideo/handler_signaling.go +++ b/services/kinesisvideo/handler_signaling.go @@ -62,6 +62,7 @@ func (h *Handler) handleDescribeSignalingChannel(c *echo.Context, body []byte) e return h.writeJSON(c, describeSignalingChannelResponse{ChannelInfo: channelInfoFromChannel(ch)}) } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleListSignalingChannels(c *echo.Context, body []byte) error { var req listSignalingChannelsRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { diff --git a/services/kinesisvideo/handler_streams.go b/services/kinesisvideo/handler_streams.go index 32d36770df..c533f93233 100644 --- a/services/kinesisvideo/handler_streams.go +++ b/services/kinesisvideo/handler_streams.go @@ -62,6 +62,7 @@ func (h *Handler) handleDescribeStream(c *echo.Context, body []byte) error { return h.writeJSON(c, describeStreamResponse{StreamInfo: streamInfoFromStream(s)}) } +//nolint:dupl // structurally similar JSON-protocol handlers func (h *Handler) handleListStreams(c *echo.Context, body []byte) error { var req listStreamsRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { From e07b0db5802393906b92913f2a12346ef2ef4dc6 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 12:53:26 -0600 Subject: [PATCH 07/11] refactor(json): move services m-z, test, cmd, dashboard and demo to encoding/json/v2; add v1-import guard Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- cmd/acceptguard/report.go | 10 +- cmd/bdaudit/issues.go | 6 +- cmd/bdaudit/report.go | 10 +- cmd/bodyclass/report.go | 10 +- cmd/cfnattrgen/main.go | 19 +- cmd/cfnattrgen/regen_test.go | 6 +- cmd/cfnpropgen/main.go | 21 +- cmd/clientcoverage/main.go | 9 +- cmd/enumcheck/report.go | 10 +- cmd/errcodeaudit/report.go | 10 +- cmd/errtargetaudit/report.go | 10 +- cmd/opcensus/main.go | 10 +- cmd/overwidecandidates/main.go | 10 +- cmd/parityfmtcheck/report.go | 7 +- cmd/parityfmtcheck/report_test.go | 6 +- cmd/paritylint/report.go | 7 +- cmd/pgoload/stepfunctions.go | 6 +- cmd/reqfielddiff/main.go | 10 +- cmd/reqfieldscan/main.go | 10 +- cmd/requiredoutputfields/main.go | 10 +- cmd/retypesgen/main.go | 11 +- cmd/routecollisions/main.go | 10 +- cmd/sfnschemagen/main.go | 5 +- cmd/sqdocsgen/main.go | 6 +- cmd/staleclaims/report.go | 10 +- cmd/stampaudit/report.go | 10 +- cmd/structfielddiff/main.go | 9 +- cmd/xmlitemwrap/report.go | 10 +- cmd/zeroguard/report.go | 10 +- dashboard/azureaks_proxy_test.go | 7 +- dashboard/azureapim_proxy.go | 10 +- dashboard/azureapim_proxy_test.go | 13 +- dashboard/azurearm_inproc_proxy.go | 8 +- dashboard/azureflexdb_proxy.go | 10 +- dashboard/azureinproc_proxy_test.go | 5 +- dashboard/azurekeyvault_proxy.go | 14 +- dashboard/azuremonitor_proxy_test.go | 5 +- dashboard/cloud_json.go | 9 +- dashboard/gcpapigateway_proxy.go | 7 +- dashboard/gcpapigateway_proxy_test.go | 13 +- dashboard/gcpbigtable_proxy.go | 5 +- dashboard/gcpfunctions_proxy.go | 5 +- dashboard/gcpidentitytoolkit_proxy.go | 8 +- dashboard/gcpidentitytoolkit_views.go | 14 +- dashboard/gcpresourcemanager_proxy_test.go | 7 +- dashboard/oci_inproc_proxy.go | 17 +- dashboard/ociapigateway_proxy_test.go | 11 +- dashboard/ociartifacts_proxy.go | 19 +- dashboard/ociartifacts_proxy_test.go | 17 +- dashboard/ocicontainerengine_proxy.go | 9 +- dashboard/ocicontainerengine_proxy_test.go | 7 +- dashboard/ocicontainerinstances_proxy.go | 9 +- dashboard/ocicontainerinstances_proxy_test.go | 19 +- dashboard/ocicore_proxy.go | 8 +- dashboard/ocievents_proxy.go | 8 +- dashboard/ocifunctions_proxy.go | 7 +- dashboard/ocifunctions_proxy_test.go | 5 +- dashboard/ociloadbalancer_proxy.go | 11 +- dashboard/ociloadbalancer_proxy_test.go | 13 +- dashboard/ocilogging_proxy.go | 10 +- dashboard/ocilogging_proxy_test.go | 7 +- dashboard/ocimonitoring_proxy.go | 8 +- dashboard/ocimonitoring_proxy_test.go | 5 +- dashboard/ocimysql_proxy.go | 6 +- dashboard/ocimysql_proxy_test.go | 5 +- dashboard/ocinosql_proxy.go | 17 +- dashboard/region_test.go | 5 +- dashboard/ui.go | 24 +- dashboard/ui_test.go | 9 +- demo/wire.go | 7 +- .../azure-keyvault-app/azure-keyvault-app | Bin 0 -> 11110770 bytes examples/azure-keyvault-app/main.go | 2 +- .../azure-servicebus-cosmos-worker | Bin 0 -> 11416407 bytes .../azure-servicebus-cosmos-worker/feed.go | 2 +- .../servicebus.go | 2 +- .../azure-servicebus-cosmos-worker/worker.go | 2 +- examples/extensions/hello/main.go | 9 +- examples/gcp-run-pubsub-push/service/main.go | 6 +- pkgs/jsonx/jsonx.go | 16 + .../testdata/snapshot_inventory.json | 398 +++++++++--------- services/macie2/handler_administrator_test.go | 13 +- services/macie2/handler_allow_lists.go | 7 +- services/macie2/handler_allow_lists_test.go | 23 +- .../macie2/handler_automated_discovery.go | 8 +- .../handler_automated_discovery_test.go | 9 +- services/macie2/handler_buckets.go | 10 +- services/macie2/handler_buckets_test.go | 17 +- .../macie2/handler_classification_jobs.go | 13 +- .../handler_classification_jobs_test.go | 53 +-- .../macie2/handler_custom_data_identifiers.go | 13 +- .../handler_custom_data_identifiers_test.go | 31 +- services/macie2/handler_enablement.go | 7 +- services/macie2/handler_enablement_test.go | 17 +- services/macie2/handler_findings.go | 13 +- services/macie2/handler_findings_filters.go | 7 +- .../macie2/handler_findings_filters_test.go | 15 +- services/macie2/handler_findings_test.go | 21 +- services/macie2/handler_members.go | 15 +- services/macie2/handler_members_test.go | 29 +- services/macie2/handler_organization.go | 7 +- services/macie2/handler_organization_test.go | 13 +- services/macie2/handler_resource_profiles.go | 8 +- .../macie2/handler_resource_profiles_test.go | 11 +- .../macie2/handler_reveal_configuration.go | 5 +- .../handler_reveal_configuration_test.go | 11 +- .../macie2/handler_sensitivity_inspection.go | 5 +- .../handler_sensitivity_inspection_test.go | 13 +- services/macie2/handler_tags.go | 6 +- services/macie2/handler_tags_test.go | 19 +- services/macie2/handler_test.go | 5 +- services/macie2/handler_usage.go | 6 +- services/macie2/handler_usage_test.go | 9 +- services/macie2/list_filter_params_test.go | 21 +- services/macie2/multi_region_test.go | 8 +- services/macie2/pagination_tie_test.go | 25 +- services/macie2/persistence.go | 4 +- services/macie2/tag_leak_test.go | 13 +- services/managedblockchain/accessors_test.go | 34 +- .../framework_attributes_test.go | 16 +- .../managedblockchain/handler_accessors.go | 6 +- services/managedblockchain/handler_members.go | 8 +- .../managedblockchain/handler_networks.go | 6 +- services/managedblockchain/handler_nodes.go | 8 +- .../managedblockchain/handler_proposals.go | 8 +- .../handler_sdk_route_table_test.go | 5 +- services/managedblockchain/handler_tags.go | 6 +- services/managedblockchain/handler_test.go | 8 +- .../input_validation_test.go | 10 +- .../managedblockchain/invitations_test.go | 12 +- services/managedblockchain/members_test.go | 21 +- .../managedblockchain/multi_region_test.go | 8 +- services/managedblockchain/networks_test.go | 25 +- services/managedblockchain/nodes_test.go | 28 +- services/managedblockchain/pagination_test.go | 16 +- services/managedblockchain/persistence.go | 8 +- .../managedblockchain/persistence_test.go | 7 +- services/managedblockchain/proposals_test.go | 56 +-- .../proposals_voting_test.go | 55 +-- services/managedblockchain/store_test.go | 10 +- services/managedblockchain/tags_test.go | 13 +- .../marketplaceentitlementservice/cbor.go | 20 +- .../marketplaceentitlementservice/handler.go | 7 +- .../persistence.go | 10 +- services/marketplacemetering/customers.go | 8 +- .../marketplacemetering/customers_test.go | 5 +- services/marketplacemetering/handler.go | 5 +- services/marketplacemetering/persistence.go | 10 +- services/marketplacemetering/register.go | 7 +- services/mediaconvert/endpoints_test.go | 10 +- services/mediaconvert/handler_certificates.go | 6 +- services/mediaconvert/handler_endpoints.go | 6 +- .../mediaconvert/handler_job_templates.go | 7 +- services/mediaconvert/handler_jobs.go | 7 +- services/mediaconvert/handler_jobs_query.go | 6 +- services/mediaconvert/handler_policy.go | 6 +- services/mediaconvert/handler_presets.go | 7 +- services/mediaconvert/handler_probe.go | 6 +- services/mediaconvert/handler_queues.go | 7 +- .../mediaconvert/handler_resource_shares.go | 6 +- services/mediaconvert/handler_tags.go | 8 +- services/mediaconvert/handler_test.go | 12 +- services/mediaconvert/janitor_test.go | 8 +- services/mediaconvert/job_templates_test.go | 14 +- services/mediaconvert/jobs_test.go | 34 +- services/mediaconvert/multi_region_test.go | 8 +- services/mediaconvert/persistence.go | 10 +- services/mediaconvert/policy_test.go | 10 +- services/mediaconvert/presets_test.go | 10 +- services/mediaconvert/queues_test.go | 32 +- services/mediaconvert/resource_shares.go | 6 +- services/mediaconvert/resource_shares_test.go | 8 +- services/mediaconvert/search_test.go | 8 +- services/mediaconvert/tags_test.go | 8 +- services/mediaconvert/versions_test.go | 6 +- services/medialive/handler.go | 6 +- services/medialive/handler_batch_test.go | 14 +- services/medialive/handler_channels_test.go | 23 +- ...handler_cloudwatch_alarm_templates_test.go | 20 +- services/medialive/handler_cluster_test.go | 31 +- services/medialive/handler_error_type_test.go | 5 +- ...andler_event_bridge_rule_templates_test.go | 14 +- .../handler_input_security_groups_test.go | 13 +- .../medialive/handler_inputdevice_test.go | 15 +- services/medialive/handler_inputs_test.go | 13 +- services/medialive/handler_multiplex_test.go | 35 +- .../medialive/handler_reservations_test.go | 13 +- services/medialive/handler_schedules_test.go | 6 +- .../medialive/handler_signal_maps_test.go | 14 +- services/medialive/handler_tags_test.go | 16 +- services/medialive/handler_test.go | 11 +- .../medialive/list_summary_shapes_test.go | 6 +- services/medialive/multi_region_test.go | 8 +- services/medialive/persistence.go | 4 +- services/medialive/whitebox_test.go | 8 +- services/mediapackage/handler.go | 11 +- .../mediapackage/handler_channels_test.go | 29 +- .../mediapackage/handler_harvest_jobs_test.go | 23 +- .../handler_origin_endpoints_test.go | 25 +- services/mediapackage/handler_tags_test.go | 10 +- services/mediapackage/handler_test.go | 11 +- services/mediapackage/multi_region_test.go | 8 +- services/mediapackage/persistence.go | 4 +- services/mediastore/containers.go | 5 +- services/mediastore/handler.go | 47 ++- services/mediastore/handler_tags_test.go | 6 +- services/mediastore/handler_test.go | 9 +- services/mediastore/lifecycle_policy.go | 6 +- services/mediastoredata/handler_test.go | 27 +- services/mediatailor/handler.go | 11 +- services/mediatailor/handler_alerts_test.go | 6 +- .../handler_channel_policy_test.go | 6 +- services/mediatailor/handler_channels_test.go | 35 +- .../mediatailor/handler_functions_test.go | 12 +- .../mediatailor/handler_live_sources_test.go | 13 +- services/mediatailor/handler_logs_test.go | 14 +- .../handler_playback_configurations_test.go | 31 +- .../handler_prefetch_schedules_test.go | 22 +- services/mediatailor/handler_programs_test.go | 12 +- .../handler_source_locations_test.go | 21 +- services/mediatailor/handler_tags_test.go | 16 +- services/mediatailor/handler_test.go | 21 +- .../mediatailor/handler_vod_sources_test.go | 19 +- services/mediatailor/multi_region_test.go | 8 +- services/mediatailor/persistence.go | 4 +- services/mediatailor/wire_field_fixes_test.go | 11 +- services/memorydb/acls_test.go | 5 +- services/memorydb/dataplane_test.go | 5 +- services/memorydb/errcode_test.go | 8 +- services/memorydb/events.go | 5 +- services/memorydb/events_test.go | 7 +- services/memorydb/handler.go | 5 +- services/memorydb/handler_acls.go | 12 +- services/memorydb/handler_acls_test.go | 9 +- services/memorydb/handler_clusters.go | 17 +- .../handler_clusters_lifecycle_test.go | 21 +- services/memorydb/handler_clusters_test.go | 27 +- services/memorydb/handler_engine_versions.go | 6 +- .../memorydb/handler_engine_versions_test.go | 14 +- services/memorydb/handler_events.go | 5 +- services/memorydb/handler_events_test.go | 19 +- ...er_multi_region_cluster_membership_test.go | 18 +- .../memorydb/handler_multi_region_clusters.go | 18 +- .../handler_multi_region_clusters_test.go | 29 +- services/memorydb/handler_parameter_groups.go | 16 +- .../memorydb/handler_parameter_groups_test.go | 13 +- services/memorydb/handler_reserved_nodes.go | 10 +- .../memorydb/handler_reserved_nodes_test.go | 25 +- services/memorydb/handler_service_updates.go | 5 +- .../memorydb/handler_service_updates_test.go | 19 +- services/memorydb/handler_shards_test.go | 21 +- services/memorydb/handler_snapshots.go | 14 +- services/memorydb/handler_snapshots_test.go | 21 +- services/memorydb/handler_subnet_groups.go | 11 +- .../memorydb/handler_subnet_groups_test.go | 5 +- services/memorydb/handler_tags.go | 10 +- services/memorydb/handler_tags_test.go | 31 +- services/memorydb/handler_test.go | 31 +- services/memorydb/handler_users.go | 12 +- services/memorydb/handler_users_test.go | 11 +- services/memorydb/lifecycle_test.go | 13 +- services/memorydb/models_events.go | 17 +- services/memorydb/parameter_groups_test.go | 5 +- services/memorydb/persistence.go | 8 +- services/memorydb/persistence_test.go | 7 +- services/memorydb/shard_detail_test.go | 5 +- services/memorydb/snapshots_test.go | 7 +- services/memorydb/tags_test.go | 7 +- services/mgn/handler.go | 11 +- services/mgn/multi_region_test.go | 8 +- services/mgn/persistence.go | 12 +- services/mgn/s3import_launch.go | 10 +- services/mgn/wire_field_fixes_test.go | 8 +- services/mq/broker_pagination_test.go | 28 +- services/mq/configurations_test.go | 16 +- services/mq/handler_brokers.go | 9 +- services/mq/handler_configurations.go | 7 +- services/mq/handler_tags.go | 6 +- services/mq/handler_test.go | 7 +- services/mq/handler_users.go | 7 +- services/mq/models.go | 6 +- services/mq/multi_region_test.go | 10 +- services/mq/persistence.go | 8 +- services/mq/user_summary_wire_test.go | 5 +- services/mwaa/airflow_access.go | 12 +- services/mwaa/airflow_auth.go | 9 +- services/mwaa/airflow_auth_test.go | 9 +- services/mwaa/airflow_engine_test.go | 9 +- services/mwaa/airflow_sync.go | 5 +- services/mwaa/environments_validation_test.go | 5 +- services/mwaa/export_test.go | 6 +- services/mwaa/handler.go | 5 +- services/mwaa/handler_cli_token_test.go | 13 +- services/mwaa/handler_environments_test.go | 39 +- services/mwaa/handler_metrics.go | 5 +- services/mwaa/handler_metrics_test.go | 6 +- services/mwaa/handler_rest_api.go | 5 +- services/mwaa/handler_rest_api_test.go | 6 +- services/mwaa/handler_tags.go | 5 +- services/mwaa/handler_tags_test.go | 22 +- services/mwaa/handler_test.go | 5 +- services/mwaa/handler_web_login_token_test.go | 11 +- services/mwaa/persistence.go | 6 +- services/mwaa/tags_test.go | 5 +- services/mwaa/web_login_identity_test.go | 5 +- services/neptune/engine_probe.go | 8 +- services/neptune/gremlin/frame.go | 8 +- services/neptune/gremlin/graphson.go | 16 +- services/neptune/gremlin/server.go | 23 +- services/neptune/gremlin/server_test.go | 10 +- services/neptune/gremlin_ws_proxy_test.go | 7 +- services/neptune/handler_test.go | 5 +- services/neptune/iam_auth.go | 7 +- services/neptune/iam_dataplane_test.go | 9 +- services/neptune/opencypher/graph_test.go | 7 +- services/neptune/opencypher/persist.go | 14 +- services/neptune/opencypher/value.go | 16 +- services/neptune/opencypher_front.go | 16 +- services/neptune/opencypher_front_test.go | 5 +- .../opencypher_queries_internal_test.go | 5 +- services/neptune/persistence.go | 14 +- services/networkfirewall/handler.go | 12 +- services/networkfirewall/ordering_test.go | 21 +- services/networkfirewall/persistence.go | 6 +- services/networkfirewall/resource_policy.go | 10 +- .../networkmanager/corenetworkpolicydiff.go | 35 +- services/networkmanager/corenetworks.go | 7 +- services/networkmanager/handler.go | 9 +- services/networkmanager/introspection.go | 5 +- services/networkmanager/persistence.go | 12 +- services/networkmanager/resourcepolicy.go | 8 +- services/networkmanager/validate.go | 5 +- services/networkmonitor/handler.go | 36 +- .../networkmonitor/handler_monitors_test.go | 23 +- .../networkmonitor/handler_probes_test.go | 17 +- services/networkmonitor/handler_tags_test.go | 10 +- services/networkmonitor/handler_test.go | 9 +- services/networkmonitor/persistence.go | 8 +- services/oam/persistence.go | 12 +- services/oam/policy.go | 20 +- services/oam/realclient_links_test.go | 7 +- services/ociapigateway/auth.go | 14 +- services/ociapigateway/auth_test.go | 14 +- services/ociapigateway/certificates.go | 16 +- services/ociapigateway/dataplane.go | 8 +- services/ociapigateway/dataplane_test.go | 5 +- services/ociapigateway/deployments.go | 22 +- services/ociapigateway/gateways.go | 46 +- services/ociapigateway/handler.go | 18 +- services/ociapigateway/helpers_test.go | 5 +- services/ociapigateway/models.go | 92 ++-- services/ociapigateway/spec.go | 49 ++- services/ociartifacts/dataplane.go | 9 +- services/ociartifacts/handler.go | 18 +- services/ociartifacts/helpers_test.go | 5 +- services/ociartifacts/registry.go | 5 +- services/ociartifacts/registry_test.go | 7 +- services/ocicontainerengine/handler.go | 14 +- services/ocicontainerengine/helpers_test.go | 5 +- services/ocicontainerengine/models.go | 34 +- services/ocicontainerengine/nodepools.go | 24 +- services/ocicontainerinstances/handler.go | 18 +- services/ocicontainerinstances/instances.go | 9 +- services/ocicontainerinstances/models.go | 6 +- services/ocicontainerinstances/validate.go | 8 +- services/ocicontainerinstances/volumes.go | 9 +- services/ocicontainerinstances/wire.go | 10 +- services/ocicore/handler.go | 14 +- services/ocicore/instance.go | 9 +- services/ocievents/condition.go | 19 +- services/ocievents/delivery_test.go | 9 +- services/ocievents/emit.go | 8 +- services/ocievents/handler.go | 18 +- services/ocievents/rules_test.go | 6 +- services/ocifunctions/docker_test.go | 5 +- services/ocifunctions/fake_runtime_test.go | 10 +- services/ocifunctions/funcs.go | 10 +- services/ocifunctions/handler.go | 14 +- services/ocifunctions/invoke_test.go | 5 +- services/ocifunctions/models.go | 6 +- services/ocifunctions/persistence_test.go | 7 +- services/ociidentity/handler.go | 14 +- services/ociidentity/handler_test.go | 12 +- services/ociloadbalancer/handler.go | 18 +- services/ociloadbalancer/store.go | 7 +- services/ocilogging/agents.go | 14 +- services/ocilogging/handler.go | 14 +- services/ocilogging/ingest.go | 6 +- services/ocilogging/models.go | 32 +- services/ocilogging/persistence_test.go | 5 +- services/ocilogging/query.go | 5 +- services/ocilogging/search.go | 5 +- services/ocimonitoring/alarms.go | 96 ++--- services/ocimonitoring/alarms_test.go | 10 +- services/ocimonitoring/eval.go | 8 +- services/ocimonitoring/handler.go | 14 +- services/ocimonitoring/models.go | 4 +- services/ocimonitoring/persistence_test.go | 5 +- services/ocimysql/channels.go | 16 +- services/ocimysql/dbsystems.go | 68 +-- services/ocimysql/handler.go | 14 +- services/ocimysql/lifecycle.go | 50 +-- services/ocimysql/models.go | 128 +++--- services/ocinosql/alter.go | 12 +- services/ocinosql/ddl.go | 28 +- services/ocinosql/handler.go | 18 +- services/ocinosql/limits.go | 5 +- services/ocinosql/models.go | 8 +- services/ocinosql/rows.go | 34 +- services/ocinosql/sqlexec.go | 4 +- services/ocinosql/sqlparse.go | 7 +- services/ocinosql/tables.go | 5 +- services/ocinosql/values.go | 33 +- services/ocinotifications/handler.go | 14 +- services/ocinotifications/publish.go | 9 +- services/ocinotifications/subs.go | 5 +- services/ociobjectstorage/auth_test.go | 10 +- services/ociobjectstorage/handler.go | 12 +- services/ociobjectstorage/ops.go | 6 +- services/ociqueue/handler.go | 14 +- services/ociqueue/helpers_test.go | 5 +- services/ociqueue/queues.go | 36 +- services/ocistreaming/cursors.go | 8 +- services/ocistreaming/handler.go | 14 +- services/ocistreaming/service_test.go | 8 +- services/ocivault/handler.go | 14 +- services/ocivault/handler_test.go | 12 +- services/ocivault/models.go | 4 +- services/ocivault/seal.go | 6 +- services/ocivault/secrets.go | 45 +- services/ocivault/secrets_test.go | 5 +- services/ocivault/secretwire.go | 4 +- services/omics/delete_precondition_test.go | 22 +- services/omics/handler.go | 5 +- .../omics/handler_annotation_stores_test.go | 27 +- services/omics/handler_configurations_test.go | 10 +- services/omics/handler_read_sets_test.go | 45 +- services/omics/handler_readjson_test.go | 11 +- .../omics/handler_reference_stores_test.go | 33 +- services/omics/handler_runs_test.go | 65 +-- .../omics/handler_sequence_stores_test.go | 18 +- services/omics/handler_shares_test.go | 13 +- services/omics/handler_tags_test.go | 8 +- services/omics/handler_test.go | 5 +- services/omics/handler_variant_stores_test.go | 17 +- services/omics/handler_workflows_test.go | 32 +- services/omics/lifecycle_poll_test.go | 40 +- services/omics/list_summary_shapes_test.go | 39 +- services/omics/multi_region_test.go | 8 +- .../omics/pagination_query_params_test.go | 14 +- services/omics/persistence.go | 4 +- services/omics/run_options_test.go | 6 +- services/omics/runbatch_route_test.go | 16 +- services/omics/s3_source.go | 8 +- services/omics/wire_field_additions_test.go | 13 +- services/opensearch/access_policy.go | 5 +- services/opensearch/bulk_test.go | 5 +- services/opensearch/data_sources.go | 10 +- services/opensearch/documents_handler_test.go | 5 +- services/opensearch/domains_test.go | 4 +- services/opensearch/handler.go | 9 +- services/opensearch/handler_advanced.go | 5 +- services/opensearch/handler_advanced_test.go | 24 +- services/opensearch/handler_applications.go | 9 +- .../opensearch/handler_applications_test.go | 38 +- services/opensearch/handler_bulk.go | 26 +- services/opensearch/handler_capabilities.go | 5 +- .../handler_data_source_attachments.go | 7 +- services/opensearch/handler_data_sources.go | 60 +-- .../opensearch/handler_data_sources_test.go | 38 +- services/opensearch/handler_domain_config.go | 5 +- .../opensearch/handler_domain_config_test.go | 28 +- .../handler_domain_maintenance_test.go | 13 +- services/opensearch/handler_domain_options.go | 10 +- .../opensearch/handler_domain_options_test.go | 27 +- .../opensearch/handler_domain_status_test.go | 22 +- services/opensearch/handler_domains.go | 13 +- services/opensearch/handler_domains_test.go | 26 +- .../opensearch/handler_inbound_connections.go | 5 +- .../handler_inbound_connections_test.go | 16 +- services/opensearch/handler_indices.go | 13 +- services/opensearch/handler_insights.go | 9 +- services/opensearch/handler_migrations.go | 5 +- .../handler_outbound_connections.go | 5 +- .../handler_outbound_connections_test.go | 13 +- services/opensearch/handler_packages.go | 15 +- services/opensearch/handler_packages_test.go | 22 +- .../opensearch/handler_reserved_instances.go | 5 +- .../handler_reserved_instances_test.go | 15 +- .../opensearch/handler_scheduled_actions.go | 5 +- .../handler_scheduled_actions_test.go | 10 +- services/opensearch/handler_serverless.go | 17 +- .../opensearch/handler_serverless_jsonrpc.go | 14 +- .../handler_serverless_real_client_test.go | 5 +- .../opensearch/handler_serverless_test.go | 82 ++-- services/opensearch/handler_tags.go | 7 +- services/opensearch/handler_tags_test.go | 12 +- services/opensearch/handler_test.go | 5 +- services/opensearch/handler_vpc_endpoints.go | 11 +- .../opensearch/handler_vpc_endpoints_test.go | 22 +- services/opensearch/interfaces.go | 10 +- services/opensearch/lifecycle_policies.go | 6 +- services/opensearch/models.go | 24 +- services/opensearch/multi_region_test.go | 10 +- services/opensearch/persistence.go | 14 +- services/opensearch/persistence_test.go | 10 +- services/opensearch/store_test.go | 6 +- services/opensearch/wire_field_fixes_test.go | 11 +- services/opsworks/handler.go | 12 +- services/opsworks/handler_agent_versions.go | 6 +- services/opsworks/handler_apps.go | 12 +- services/opsworks/handler_commands.go | 6 +- services/opsworks/handler_deployments.go | 8 +- services/opsworks/handler_ecs_clusters.go | 9 +- services/opsworks/handler_elastic_ips.go | 16 +- .../handler_elastic_load_balancers.go | 10 +- services/opsworks/handler_instances.go | 29 +- services/opsworks/handler_layers.go | 16 +- .../opsworks/handler_load_based_scaling.go | 8 +- services/opsworks/handler_rds_db_instances.go | 12 +- services/opsworks/handler_service_errors.go | 8 +- services/opsworks/handler_stacks.go | 24 +- services/opsworks/handler_tags.go | 10 +- services/opsworks/handler_test.go | 7 +- .../opsworks/handler_time_based_scaling.go | 8 +- .../opsworks/handler_users_permissions.go | 20 +- services/opsworks/handler_volumes.go | 16 +- services/opsworks/interfaces.go | 10 +- services/opsworks/layers.go | 4 +- services/opsworks/models.go | 6 +- services/opsworks/multi_region_test.go | 8 +- services/opsworks/persistence.go | 4 +- services/opsworks/whitebox_test.go | 8 +- .../organizations/account_provisioning.go | 6 +- services/organizations/default_policy_test.go | 19 +- .../delegated_administrators_test.go | 10 +- services/organizations/effective_policy.go | 8 +- .../organizations/effective_policy_test.go | 12 +- services/organizations/handler.go | 5 +- services/organizations/handler_accounts.go | 23 +- .../organizations/handler_accounts_test.go | 34 +- .../handler_delegated_administrators.go | 11 +- .../organizations/handler_effective_policy.go | 7 +- services/organizations/handler_handshakes.go | 29 +- .../organizations/handler_handshakes_test.go | 20 +- .../organizations/handler_organization.go | 6 +- .../handler_organizational_units.go | 19 +- .../handler_organizational_units_test.go | 25 +- .../organizations/handler_pagination_test.go | 36 +- services/organizations/handler_policies.go | 17 +- .../handler_policy_attachments.go | 11 +- .../organizations/handler_resource_policy.go | 6 +- services/organizations/handler_roots.go | 5 +- .../organizations/handler_service_access.go | 9 +- services/organizations/handler_tags.go | 9 +- services/organizations/handler_test.go | 12 +- services/organizations/organization_test.go | 10 +- .../pagination_sort_totality_test.go | 5 +- services/organizations/paths_test.go | 15 +- services/organizations/persistence.go | 10 +- services/organizations/persistence_test.go | 5 +- services/organizations/policies.go | 6 +- services/organizations/policies_test.go | 20 +- .../organizations/policy_attachments_test.go | 6 +- .../organizations/resource_policy_test.go | 8 +- services/organizations/roots_test.go | 7 +- services/organizations/scp_test.go | 12 +- services/organizations/service_access_test.go | 7 +- services/organizations/tags_test.go | 12 +- .../capacity_ledger_delete_cleanup_test.go | 9 +- services/outposts/handler.go | 9 +- services/outposts/multi_region_test.go | 8 +- services/outposts/persistence.go | 10 +- services/personalize/handler.go | 18 +- services/personalize/handler_test.go | 7 +- services/personalize/multi_region_test.go | 8 +- services/personalize/persistence.go | 4 +- services/personalize/validate.go | 6 +- .../pinpoint/applications_settings_test.go | 51 +-- services/pinpoint/apps_test.go | 35 +- services/pinpoint/attributes_test.go | 8 +- services/pinpoint/campaigns_fields_test.go | 54 +-- services/pinpoint/campaigns_test.go | 51 +-- .../pinpoint/channel_credential_echo_test.go | 7 +- services/pinpoint/channels_test.go | 34 +- services/pinpoint/channels_types_test.go | 44 +- services/pinpoint/endpoints_test.go | 38 +- services/pinpoint/error_envelope_test.go | 5 +- services/pinpoint/event_streams_test.go | 12 +- services/pinpoint/events_test.go | 10 +- services/pinpoint/export_import_jobs_test.go | 29 +- services/pinpoint/handler.go | 5 +- .../pinpoint/handler_applications_settings.go | 5 +- services/pinpoint/handler_apps.go | 5 +- services/pinpoint/handler_attributes.go | 5 +- services/pinpoint/handler_channels.go | 17 +- services/pinpoint/handler_endpoints.go | 7 +- services/pinpoint/handler_event_streams.go | 5 +- services/pinpoint/handler_events.go | 5 +- .../pinpoint/handler_export_import_jobs.go | 7 +- services/pinpoint/handler_journeys.go | 7 +- services/pinpoint/handler_messages.go | 11 +- .../handler_recommender_configurations.go | 7 +- services/pinpoint/handler_segments.go | 5 +- services/pinpoint/handler_tags.go | 5 +- services/pinpoint/handler_templates.go | 25 +- .../handler_templates_rejection_test.go | 6 +- services/pinpoint/handler_test.go | 12 +- services/pinpoint/journeys_activities_test.go | 52 +-- services/pinpoint/journeys_test.go | 43 +- services/pinpoint/messages_test.go | 41 +- services/pinpoint/multi_region_test.go | 8 +- services/pinpoint/payload_size.go | 9 +- services/pinpoint/payload_size_test.go | 9 +- services/pinpoint/persistence.go | 38 +- .../recommender_configurations_test.go | 26 +- services/pinpoint/segments_test.go | 72 ++-- services/pinpoint/store.go | 8 +- services/pinpoint/tags_test.go | 27 +- services/pinpoint/template_versions.go | 23 +- services/pinpoint/template_versions_test.go | 6 +- .../templates_create_new_version_test.go | 8 +- services/pinpoint/templates_email_test.go | 28 +- services/pinpoint/templates_push_test.go | 22 +- services/pinpoint/templates_test.go | 44 +- services/pinpoint/wire_field_fixes_test.go | 8 +- services/pipes/enrichment_test.go | 5 +- services/pipes/errsweep_wire_shape_test.go | 5 +- services/pipes/filter.go | 78 ++-- services/pipes/filter_validation.go | 6 +- services/pipes/handler.go | 40 +- services/pipes/handler_test.go | 37 +- services/pipes/persistence.go | 14 +- services/pipes/pipe_lifecycle_test.go | 5 +- services/pipes/pipes_test.go | 9 +- services/pipes/runner.go | 5 +- services/pipes/runner_targets_test.go | 17 +- services/pipes/runner_test.go | 7 +- services/pipes/runner_timestream.go | 12 +- services/pipes/sources_poll.go | 9 +- services/pipes/sources_test.go | 7 +- services/pipes/tags_test.go | 6 +- services/pipes/targets_test.go | 11 +- services/pipes/wire_key_case_restore_test.go | 5 +- services/pipes/wire_time.go | 8 +- services/pipes/wire_time_test.go | 5 +- services/polly/handler.go | 9 +- services/polly/handler_test.go | 7 +- services/polly/multi_region_test.go | 8 +- services/polly/persistence.go | 10 +- services/polly/speech_test.go | 13 +- services/polly/throttle_test.go | 7 +- services/pricing/catalog.go | 6 +- services/pricing/handler.go | 5 +- services/pricing/pricelists.go | 6 +- services/pricing/pricing_more_test.go | 7 +- services/pricing/pricing_test.go | 7 +- services/pricing/savingsplans.go | 6 +- services/quicksight/dataset_security.go | 8 +- services/quicksight/error_envelope_test.go | 5 +- services/quicksight/handler_paths.go | 8 +- services/quicksight/handler_test.go | 7 +- services/quicksight/models.go | 4 +- services/quicksight/multi_region_test.go | 8 +- services/ram/errsweep_wire_shape_test.go | 5 +- services/ram/handler.go | 15 +- services/ram/handler_permission_versions.go | 17 +- .../ram/handler_permission_versions_test.go | 9 +- services/ram/handler_permissions.go | 21 +- services/ram/handler_permissions_test.go | 56 +-- services/ram/handler_principals.go | 8 +- services/ram/handler_principals_test.go | 15 +- services/ram/handler_resource_shares.go | 21 +- services/ram/handler_resource_shares_test.go | 62 +-- services/ram/handler_resources.go | 23 +- services/ram/handler_resources_test.go | 38 +- services/ram/handler_share_associations.go | 16 +- .../ram/handler_share_associations_test.go | 22 +- services/ram/handler_share_invitations.go | 16 +- .../ram/handler_share_invitations_test.go | 11 +- services/ram/handler_share_permissions.go | 28 +- .../ram/handler_share_permissions_test.go | 39 +- services/ram/handler_tags.go | 12 +- services/ram/handler_tags_test.go | 9 +- services/ram/handler_test.go | 16 +- services/ram/idempotent_ops.go | 5 +- services/ram/multi_region_test.go | 8 +- services/ram/permission_version_shape_test.go | 5 +- services/ram/persistence.go | 8 +- services/ram/policy_shares.go | 5 +- services/rds/engine_dumpstore.go | 11 +- services/rds/engine_pgext_docker_test.go | 6 +- services/rds/master_secret.go | 5 +- services/rds/persistence.go | 16 +- services/rds/persistence_test.go | 12 +- .../rdsdata/column_origin_realclient_test.go | 7 +- services/rdsdata/errsweep_wire_shape_test.go | 5 +- services/rdsdata/handler.go | 45 +- services/rdsdata/handler_test.go | 7 +- services/rdsdata/real_docker_test.go | 5 +- services/rdsdata/real_engine.go | 5 +- services/rdsdata/real_handler_test.go | 8 +- services/rdsdata/sql_test.go | 7 +- services/rdsdata/statements_test.go | 37 +- services/rdsdata/transactions_test.go | 37 +- services/rdsdata/typehints.go | 6 +- services/redshift/handler_serverless.go | 136 +++--- .../handler_serverless_custom_domains.go | 14 +- .../handler_serverless_custom_domains_test.go | 27 +- .../handler_serverless_endpoint_access.go | 16 +- ...handler_serverless_endpoint_access_test.go | 21 +- .../redshift/handler_serverless_gaps_test.go | 28 +- .../handler_serverless_idc_token_test.go | 13 +- .../handler_serverless_lakehouse_test.go | 19 +- .../redshift/handler_serverless_recovery.go | 10 +- .../handler_serverless_recovery_test.go | 16 +- .../handler_serverless_resource_policy.go | 10 +- ...handler_serverless_resource_policy_test.go | 13 +- .../redshift/handler_serverless_restore.go | 8 +- .../handler_serverless_restore_test.go | 17 +- ...handler_serverless_snapshot_copy_config.go | 12 +- ...er_serverless_snapshot_copy_config_test.go | 17 +- .../handler_serverless_table_restore.go | 12 +- .../handler_serverless_table_restore_test.go | 15 +- .../redshift/handler_serverless_tagging.go | 10 +- .../handler_serverless_tagging_test.go | 27 +- services/redshift/handler_serverless_test.go | 26 +- .../handler_serverless_tracks_test.go | 13 +- ...handler_serverless_update_snapshot_test.go | 9 +- services/redshift/multi_region_test.go | 8 +- services/redshift/persistence.go | 8 +- services/redshift/persistence_test.go | 14 +- services/redshift/schedule.go | 5 +- services/redshift/serverless.go | 22 +- services/redshift/serverless_index_test.go | 6 +- .../redshift/serverless_scheduled_actions.go | 14 +- services/redshiftdata/engine.go | 6 +- services/redshiftdata/engine_pgx.go | 8 +- services/redshiftdata/engine_result.go | 8 +- services/redshiftdata/handler.go | 16 +- services/redshiftdata/handler_databases.go | 12 +- .../redshiftdata/handler_databases_test.go | 32 +- services/redshiftdata/handler_sessions.go | 8 +- services/redshiftdata/handler_statements.go | 36 +- .../handler_statements_lifecycle_test.go | 53 +-- .../handler_statements_semantics_test.go | 54 +-- .../redshiftdata/handler_statements_test.go | 45 +- .../handler_statements_validation_test.go | 31 +- services/redshiftdata/handler_tables.go | 12 +- services/redshiftdata/handler_tables_test.go | 22 +- services/redshiftdata/handler_test.go | 9 +- services/redshiftdata/idempotency_test.go | 18 +- services/redshiftdata/persistence.go | 5 +- services/redshiftdata/persistence_test.go | 8 +- services/redshiftdata/s3_copy.go | 17 +- services/redshiftdata/s3_unload.go | 9 +- .../redshiftdata/session_keepalive_test.go | 6 +- .../redshiftdata/wire_sdk_roundtrip_test.go | 10 +- services/rekognition/datasets.go | 31 +- services/rekognition/handler.go | 5 +- .../handler_async_video_fields_test.go | 24 +- .../rekognition/handler_celebrities_test.go | 14 +- .../rekognition/handler_collections_test.go | 34 +- .../rekognition/handler_custom_labels_test.go | 6 +- services/rekognition/handler_datasets_test.go | 58 +-- .../rekognition/handler_face_liveness_test.go | 18 +- services/rekognition/handler_faces_test.go | 76 ++-- services/rekognition/handler_labels_test.go | 11 +- .../handler_media_analysis_test.go | 24 +- .../rekognition/handler_moderation_test.go | 16 +- .../rekognition/handler_project_versions.go | 6 +- .../handler_project_versions_test.go | 57 +-- services/rekognition/handler_projects_test.go | 31 +- .../handler_stream_processors_test.go | 38 +- services/rekognition/handler_tags_test.go | 31 +- services/rekognition/handler_test.go | 7 +- .../handler_text_detection_test.go | 12 +- services/rekognition/handler_users_test.go | 20 +- services/rekognition/job_notification.go | 5 +- services/rekognition/job_notification_test.go | 9 +- services/rekognition/multi_region_test.go | 8 +- .../rekognition/omission_defaults_test.go | 8 +- services/rekognition/persistence.go | 4 +- services/rekognition/persistence_test.go | 25 +- services/rekognition/realism_test.go | 5 +- services/rekognition/s3_object_test.go | 11 +- services/resiliencehub/handler.go | 9 +- services/resiliencehub/multi_region_test.go | 8 +- services/resiliencehub/persistence.go | 10 +- services/resourceexplorer2/catalog.go | 5 +- services/resourceexplorer2/persistence.go | 6 +- .../resourceexplorer2/types_catalog_test.go | 6 +- services/resourcegroups/groups.go | 8 +- services/resourcegroups/handler.go | 16 +- .../handler_groups_config_test.go | 9 +- .../resourcegroups/handler_groups_test.go | 11 +- .../handler_groups_validation_test.go | 11 +- services/resourcegroups/handler_query_test.go | 9 +- .../resourcegroups/handler_resources_test.go | 23 +- services/resourcegroups/handler_tags.go | 9 +- services/resourcegroups/handler_tags_test.go | 11 +- .../resourcegroups/handler_tagsync_test.go | 19 +- services/resourcegroups/handler_test.go | 9 +- .../handler_untag_rejection_test.go | 9 +- services/resourcegroups/persistence.go | 6 +- services/resourcegroups/persistence_test.go | 8 +- services/resourcegroups/query.go | 6 +- services/resourcegroups/query_validation.go | 8 +- services/resourcegroups/source.go | 7 +- .../resourcegroupstaggingapi/compliance.go | 5 +- .../compliance_test.go | 7 +- .../get_resources_test.go | 18 +- services/resourcegroupstaggingapi/handler.go | 12 +- .../resourcegroupstaggingapi/handler_test.go | 12 +- .../resourcegroupstaggingapi/persistence.go | 12 +- .../resourcegroupstaggingapi/report_test.go | 7 +- services/rolesanywhere/handler.go | 5 +- .../handler_attribute_mappings.go | 6 +- .../handler_attribute_mappings_test.go | 8 +- services/rolesanywhere/handler_crls.go | 8 +- services/rolesanywhere/handler_crls_test.go | 10 +- .../handler_notification_settings.go | 8 +- .../handler_notification_settings_test.go | 12 +- .../handler_pagination_restart_test.go | 10 +- services/rolesanywhere/handler_profiles.go | 8 +- .../rolesanywhere/handler_profiles_test.go | 22 +- services/rolesanywhere/handler_tags.go | 8 +- services/rolesanywhere/handler_tags_test.go | 13 +- services/rolesanywhere/handler_test.go | 29 +- .../rolesanywhere/handler_trust_anchors.go | 8 +- .../handler_trust_anchors_test.go | 18 +- services/rolesanywhere/persistence.go | 6 +- services/rolesanywhere/persistence_test.go | 8 +- services/route53/persistence.go | 10 +- services/route53recoverycluster/misc_test.go | 5 +- services/route53recoverycluster/ops.go | 7 +- .../route53recoverycontrolconfig/misc_test.go | 5 +- .../persistence.go | 8 +- .../route53recoveryreadiness/misc_test.go | 5 +- .../route53recoveryreadiness/persistence.go | 6 +- services/route53resolver/configs_test.go | 15 +- services/route53resolver/dns_querylog.go | 5 +- .../dns_resolver_log_destinations_test.go | 7 +- .../route53resolver/dns_resolver_log_test.go | 5 +- .../firewall_domain_lists_test.go | 17 +- .../firewall_rule_groups_test.go | 41 +- .../route53resolver/firewall_rules_test.go | 43 +- services/route53resolver/handler.go | 14 +- .../handler_error_type_internal_test.go | 5 +- .../route53resolver/handler_firewall_rules.go | 8 +- services/route53resolver/handler_test.go | 10 +- .../route53resolver/outpost_resolvers_test.go | 12 +- services/route53resolver/persistence.go | 8 +- services/route53resolver/persistence_test.go | 7 +- .../query_log_associations_test.go | 21 +- .../route53resolver/query_log_configs_test.go | 19 +- .../resolver_endpoints_test.go | 79 ++-- .../route53resolver/resolver_rules_test.go | 29 +- .../route53resolver/rule_associations_test.go | 17 +- services/route53resolver/store_test.go | 13 +- services/route53resolver/tags_test.go | 18 +- services/rum/events.go | 12 +- services/rum/metrics.go | 5 +- services/rum/pattern.go | 5 +- services/rum/pattern_test.go | 7 +- services/rum/persistence.go | 12 +- services/rum/policies.go | 8 +- services/rum/realclient_helpers_test.go | 5 +- services/s3/authz.go | 5 +- services/s3/bucket_ops_acl_policy.go | 8 +- services/s3/bucket_policy_validation.go | 32 +- services/s3/express_session.go | 6 +- services/s3/golden_perf_test.go | 12 +- services/s3/notification.go | 7 +- services/s3/object_lambda.go | 5 +- services/s3/object_lambda_features_test.go | 5 +- services/s3/object_lambda_head_list.go | 7 +- services/s3/object_lambda_head_list_test.go | 5 +- services/s3/object_lambda_test.go | 5 +- services/s3/persistence.go | 18 +- ...lient_bucket_config_and_object_ops_test.go | 5 +- services/s3/select_csv.go | 6 +- services/s3/select_json.go | 10 +- services/s3control/handler_access_points.go | 6 +- services/s3control/persistence.go | 10 +- services/s3files/file_systems.go | 8 +- services/s3files/handler.go | 5 +- services/s3files/persistence.go | 10 +- services/s3tables/handler.go | 5 +- services/s3tables/handler_namespaces.go | 11 +- services/s3tables/handler_namespaces_test.go | 6 +- services/s3tables/handler_replication.go | 17 +- .../handler_table_bucket_config_test.go | 7 +- services/s3tables/handler_table_buckets.go | 35 +- .../handler_table_maintenance_test.go | 9 +- services/s3tables/handler_tables.go | 33 +- services/s3tables/handler_tables_test.go | 6 +- services/s3tables/handler_tags.go | 7 +- services/s3tables/handler_test.go | 8 +- services/s3tables/metadata_writer.go | 9 +- services/s3tables/multi_region_test.go | 8 +- services/s3tables/persistence.go | 6 +- services/s3tables/validation.go | 6 +- services/s3vectors/buckets.go | 5 +- services/s3vectors/models.go | 8 +- services/s3vectors/persistence.go | 6 +- services/s3vectors/vectors.go | 7 +- services/sagemaker/ai_benchmark_jobs.go | 26 +- services/sagemaker/ai_recommendation_jobs.go | 44 +- services/sagemaker/ai_workload_configs.go | 20 +- services/sagemaker/algorithms.go | 8 +- services/sagemaker/app_image_configs.go | 32 +- services/sagemaker/apps.go | 8 +- services/sagemaker/automl.go | 26 +- services/sagemaker/automl_search.go | 10 +- services/sagemaker/automl_v2.go | 15 +- services/sagemaker/code_repositories.go | 7 +- services/sagemaker/compilation_jobs.go | 18 +- services/sagemaker/device_fleets.go | 11 +- services/sagemaker/domains.go | 26 +- services/sagemaker/edge_deployment.go | 18 +- services/sagemaker/endpoint_configs.go | 8 +- services/sagemaker/endpoints.go | 8 +- services/sagemaker/engine_async_test.go | 5 +- services/sagemaker/engine_files.go | 15 +- services/sagemaker/engine_invoke.go | 5 +- services/sagemaker/engine_jobs_test.go | 13 +- services/sagemaker/engine_training.go | 5 +- services/sagemaker/flow_definitions.go | 7 +- services/sagemaker/handler.go | 24 +- .../sagemaker/handler_ai_benchmark_jobs.go | 37 +- .../handler_ai_recommendation_jobs.go | 45 +- .../sagemaker/handler_ai_workload_configs.go | 27 +- services/sagemaker/handler_algorithms.go | 36 +- services/sagemaker/handler_algorithms_test.go | 17 +- .../sagemaker/handler_app_image_configs.go | 39 +- .../handler_app_image_configs_test.go | 14 +- services/sagemaker/handler_apps.go | 34 +- services/sagemaker/handler_apps_test.go | 20 +- services/sagemaker/handler_automl.go | 23 +- services/sagemaker/handler_automl_search.go | 24 +- .../sagemaker/handler_automl_search_test.go | 20 +- services/sagemaker/handler_automl_test.go | 24 +- services/sagemaker/handler_automl_v2.go | 15 +- services/sagemaker/handler_automl_v2_test.go | 8 +- services/sagemaker/handler_cluster.go | 70 +-- services/sagemaker/handler_cluster_test.go | 53 +-- .../sagemaker/handler_code_repositories.go | 22 +- .../handler_code_repositories_test.go | 14 +- .../sagemaker/handler_compilation_jobs.go | 23 +- .../handler_compilation_jobs_test.go | 25 +- services/sagemaker/handler_device_fleets.go | 36 +- .../sagemaker/handler_device_fleets_test.go | 20 +- services/sagemaker/handler_domains.go | 70 +-- services/sagemaker/handler_domains_test.go | 16 +- services/sagemaker/handler_edge_deployment.go | 39 +- .../sagemaker/handler_edge_deployment_test.go | 21 +- .../sagemaker/handler_edge_packaging_jobs.go | 18 +- .../handler_edge_packaging_jobs_test.go | 36 +- .../sagemaker/handler_endpoint_configs.go | 26 +- .../handler_endpoint_configs_test.go | 21 +- services/sagemaker/handler_endpoints.go | 46 +- services/sagemaker/handler_endpoints_test.go | 28 +- services/sagemaker/handler_experiments.go | 23 +- .../sagemaker/handler_experiments_test.go | 20 +- services/sagemaker/handler_feature_groups.go | 21 +- .../handler_feature_groups_stores_test.go | 8 +- .../sagemaker/handler_feature_groups_test.go | 18 +- .../sagemaker/handler_feature_metadata.go | 12 +- .../handler_feature_metadata_test.go | 9 +- .../sagemaker/handler_flow_definitions.go | 16 +- .../handler_flow_definitions_test.go | 12 +- services/sagemaker/handler_hp_tuning_jobs.go | 40 +- .../sagemaker/handler_hp_tuning_jobs_test.go | 21 +- services/sagemaker/handler_hub.go | 57 +-- services/sagemaker/handler_hub_test.go | 32 +- services/sagemaker/handler_human_task_ui.go | 16 +- .../sagemaker/handler_human_task_ui_test.go | 12 +- .../sagemaker/handler_hyperpod_scheduling.go | 40 +- services/sagemaker/handler_images.go | 44 +- services/sagemaker/handler_images_test.go | 26 +- .../sagemaker/handler_inference_components.go | 29 +- .../handler_inference_components_test.go | 26 +- .../handler_inference_experiments.go | 30 +- .../handler_inference_experiments_test.go | 18 +- .../handler_inference_recommendations_jobs.go | 39 +- ...ler_inference_recommendations_jobs_test.go | 30 +- services/sagemaker/handler_jobs.go | 28 +- services/sagemaker/handler_labeling.go | 30 +- services/sagemaker/handler_labeling_test.go | 56 +-- services/sagemaker/handler_lineage.go | 87 ++-- services/sagemaker/handler_lineage_test.go | 71 ++-- .../handler_list_notebook_filters_test.go | 6 +- services/sagemaker/handler_mlflow.go | 56 +-- services/sagemaker/handler_mlflow_test.go | 36 +- services/sagemaker/handler_model_cards.go | 26 +- .../sagemaker/handler_model_cards_test.go | 18 +- services/sagemaker/handler_model_packages.go | 79 ++-- .../sagemaker/handler_model_packages_test.go | 31 +- .../sagemaker/handler_modelcard_export.go | 12 +- .../handler_modelcard_export_test.go | 10 +- .../sagemaker/handler_modelmonitor_test.go | 37 +- services/sagemaker/handler_models.go | 17 +- services/sagemaker/handler_models_test.go | 19 +- services/sagemaker/handler_monitoring.go | 20 +- .../handler_monitoring_job_definitions.go | 53 +-- ...handler_monitoring_job_definitions_test.go | 16 +- .../sagemaker/handler_monitoring_schedules.go | 26 +- .../handler_monitoring_schedules_test.go | 14 +- .../sagemaker/handler_notebook_instances.go | 45 +- .../handler_notebook_instances_test.go | 10 +- .../sagemaker/handler_optimization_jobs.go | 27 +- .../handler_optimization_jobs_test.go | 20 +- services/sagemaker/handler_partner_apps.go | 33 +- .../sagemaker/handler_partner_apps_test.go | 28 +- .../sagemaker/handler_pipeline_versions.go | 18 +- .../handler_pipeline_versions_test.go | 22 +- services/sagemaker/handler_pipelines.go | 59 +-- services/sagemaker/handler_pipelines_test.go | 37 +- .../handler_pipelines_versionid_test.go | 10 +- .../sagemaker/handler_presigned_session.go | 18 +- .../handler_presigned_session_test.go | 12 +- services/sagemaker/handler_processing_jobs.go | 19 +- .../sagemaker/handler_processing_jobs_test.go | 8 +- services/sagemaker/handler_projects.go | 33 +- services/sagemaker/handler_projects_test.go | 16 +- services/sagemaker/handler_servicecatalog.go | 8 +- .../sagemaker/handler_servicecatalog_test.go | 8 +- services/sagemaker/handler_spaces.go | 45 +- services/sagemaker/handler_spaces_test.go | 20 +- .../handler_studio_lifecycle_configs.go | 16 +- .../handler_studio_lifecycle_configs_test.go | 14 +- services/sagemaker/handler_tags.go | 13 +- services/sagemaker/handler_tags_test.go | 12 +- services/sagemaker/handler_test.go | 11 +- services/sagemaker/handler_training_jobs.go | 40 +- .../sagemaker/handler_training_jobs_test.go | 8 +- services/sagemaker/handler_training_plan.go | 26 +- .../sagemaker/handler_training_plan_test.go | 26 +- services/sagemaker/handler_training_plans.go | 12 +- .../sagemaker/handler_training_plans_test.go | 8 +- services/sagemaker/handler_transform_jobs.go | 17 +- .../sagemaker/handler_transform_jobs_test.go | 25 +- .../sagemaker/handler_trial_components.go | 25 +- .../handler_trial_components_test.go | 22 +- services/sagemaker/handler_trials.go | 23 +- services/sagemaker/handler_trials_test.go | 16 +- services/sagemaker/handler_user_profiles.go | 40 +- .../sagemaker/handler_user_profiles_test.go | 24 +- services/sagemaker/handler_workforces.go | 24 +- services/sagemaker/handler_workforces_test.go | 16 +- services/sagemaker/handler_workteams.go | 24 +- services/sagemaker/handler_workteams_test.go | 16 +- services/sagemaker/hp_tuning_jobs.go | 32 +- services/sagemaker/human_task_ui.go | 7 +- services/sagemaker/hyperpod_scheduling.go | 11 +- services/sagemaker/images.go | 11 +- services/sagemaker/inference_components.go | 16 +- services/sagemaker/inference_experiments.go | 7 +- .../inference_recommendations_jobs.go | 26 +- services/sagemaker/interfaces.go | 4 +- services/sagemaker/jobs.go | 11 +- .../sagemaker/list_summary_shapes_test.go | 8 +- services/sagemaker/mlflow.go | 7 +- services/sagemaker/model_cards.go | 22 +- services/sagemaker/model_packages.go | 48 ++- services/sagemaker/models.go | 73 ++-- .../sagemaker/monitoring_job_definitions.go | 28 +- services/sagemaker/monitoring_schedules.go | 16 +- services/sagemaker/notebook_url_test.go | 5 +- services/sagemaker/optimization_jobs.go | 34 +- services/sagemaker/partner_apps.go | 10 +- services/sagemaker/persistence.go | 14 +- services/sagemaker/persistence_test.go | 19 +- services/sagemaker/pipeline_executions.go | 6 +- services/sagemaker/projects.go | 20 +- services/sagemaker/projects_update.go | 23 +- services/sagemaker/request_realism_test.go | 14 +- services/sagemaker/request_validation.go | 5 +- services/sagemaker/shape_validation.go | 27 +- services/sagemaker/spaces.go | 28 +- .../sagemaker/studio_lifecycle_configs.go | 7 +- services/sagemaker/training_jobs.go | 4 +- services/sagemaker/training_plan.go | 11 +- services/sagemaker/training_plans.go | 15 +- services/sagemaker/user_profiles.go | 10 +- .../sagemaker/variant_weight_default_test.go | 7 +- .../wire_field_fixes_respsweep2_test.go | 18 +- .../wire_field_fixes_respsweep_test.go | 8 +- .../endpoint_validation_test.go | 5 +- services/sagemakerruntime/handler.go | 5 +- services/sagemakerruntime/handler_test.go | 7 +- .../invoke_endpoint_async_test.go | 8 +- .../sagemakerruntime/invoke_errors_test.go | 7 +- .../sagemakerruntime/multi_region_test.go | 8 +- services/sagemakerruntime/persistence.go | 14 +- services/scheduler/handler.go | 53 ++- .../handler_error_type_internal_test.go | 5 +- services/scheduler/handler_test.go | 7 +- services/scheduler/idempotency_test.go | 14 +- services/scheduler/persistence.go | 12 +- services/scheduler/runner.go | 5 +- services/scheduler/schedule_groups_test.go | 58 +-- services/scheduler/schedules_list_test.go | 62 +-- services/scheduler/schedules_rest_test.go | 23 +- services/scheduler/schedules_target_test.go | 121 +++--- services/scheduler/schedules_test.go | 66 +-- services/scheduler/tags_test.go | 43 +- services/scheduler/whitebox_test.go | 6 +- .../batchgetsecretvalue_test.go | 15 +- .../secretsmanager/cancelrotatesecret_test.go | 5 +- services/secretsmanager/createsecret_test.go | 25 +- services/secretsmanager/deletesecret_test.go | 9 +- .../secretsmanager/describesecret_test.go | 9 +- services/secretsmanager/explicit_empty.go | 15 +- .../secretsmanager/getrandompassword_test.go | 13 +- .../secretsmanager/getsecretvalue_test.go | 15 +- services/secretsmanager/handler.go | 11 +- .../secretsmanager/handler_dispatch_test.go | 17 +- .../secretsmanager/handler_random_password.go | 6 +- services/secretsmanager/handler_rotation.go | 9 +- services/secretsmanager/handler_secrets.go | 19 +- services/secretsmanager/handler_tags.go | 7 +- services/secretsmanager/listsecrets_test.go | 17 +- .../listsecretversionids_test.go | 7 +- services/secretsmanager/persistence.go | 4 +- .../secretsmanager/putsecretvalue_test.go | 7 +- .../replica_write_guard_test.go | 5 +- services/secretsmanager/replication_test.go | 15 +- services/secretsmanager/resource_policy.go | 35 +- .../secretsmanager/resource_policy_test.go | 17 +- services/secretsmanager/rotatesecret_test.go | 17 +- .../secretsmanager/secret_versions_test.go | 9 +- services/secretsmanager/updatesecret_test.go | 11 +- .../updatesecretversionstage_test.go | 9 +- services/securityhub/action_targets_test.go | 11 +- services/securityhub/aggregators_v2_test.go | 16 +- .../securityhub/analytics_filters_test.go | 5 +- services/securityhub/automation_rules_test.go | 35 +- .../configuration_policies_test.go | 15 +- services/securityhub/connectors_v2_test.go | 9 +- services/securityhub/controls_test.go | 9 +- services/securityhub/exportjobs_v2.go | 8 +- .../securityhub/finding_aggregators_test.go | 5 +- services/securityhub/findings.go | 7 +- services/securityhub/findings_test.go | 29 +- services/securityhub/findings_v2_test.go | 19 +- services/securityhub/handler.go | 11 +- .../handler_malformed_body_test.go | 5 +- services/securityhub/handler_test.go | 5 +- services/securityhub/hub_test.go | 15 +- services/securityhub/insights_test.go | 17 +- services/securityhub/invitations_test.go | 7 +- .../members_only_associated_test.go | 8 +- services/securityhub/members_test.go | 10 +- services/securityhub/multi_region_test.go | 5 +- services/securityhub/organizations_test.go | 6 +- services/securityhub/persistence_test.go | 10 +- services/securityhub/products_test.go | 13 +- services/securityhub/resources_v2_test.go | 5 +- services/securityhub/standards_test.go | 43 +- services/securityhub/store.go | 8 +- services/securityhub/tags_test.go | 8 +- .../ticket_v2_client_token_test.go | 10 +- services/serverlessrepo/handler.go | 18 +- .../handler_application_dependencies.go | 6 +- .../handler_application_dependencies_test.go | 19 +- .../handler_application_policy.go | 9 +- .../handler_application_policy_test.go | 25 +- .../handler_application_versions.go | 9 +- .../handler_application_versions_test.go | 35 +- .../serverlessrepo/handler_applications.go | 17 +- .../handler_applications_list_test.go | 17 +- .../handler_applications_test.go | 41 +- .../handler_applications_validation_test.go | 12 +- .../serverlessrepo/handler_cloud_formation.go | 13 +- .../handler_cloud_formation_test.go | 41 +- .../handler_pagination_restart_test.go | 15 +- services/serverlessrepo/handler_test.go | 15 +- services/serverlessrepo/multi_region_test.go | 8 +- services/serverlessrepo/persistence.go | 10 +- .../serverlessrepo/wire_sdk_roundtrip_test.go | 5 +- services/servicecatalog/constraints.go | 6 +- services/servicecatalog/handler.go | 5 +- services/servicecatalog/helpers_test.go | 7 +- services/servicecatalog/persistence.go | 6 +- services/servicecatalog/rules.go | 12 +- services/servicecatalog/serviceactions.go | 6 +- services/servicecatalog/util.go | 5 +- services/servicediscovery/discovery_test.go | 57 +-- .../servicediscovery/dns_registrar_test.go | 17 +- services/servicediscovery/handler.go | 14 +- .../servicediscovery/handler_discovery.go | 12 +- .../servicediscovery/handler_instances.go | 25 +- .../handler_list_summary_test.go | 6 +- .../servicediscovery/handler_namespaces.go | 37 +- .../servicediscovery/handler_operations.go | 9 +- services/servicediscovery/handler_services.go | 29 +- services/servicediscovery/handler_tags.go | 11 +- services/servicediscovery/handler_test.go | 13 +- .../servicediscovery/input_realism_test.go | 8 +- services/servicediscovery/instances_test.go | 67 +-- .../servicediscovery/multi_region_test.go | 5 +- services/servicediscovery/namespaces_test.go | 55 +-- services/servicediscovery/operations_test.go | 25 +- services/servicediscovery/persistence.go | 8 +- services/servicediscovery/persistence_test.go | 7 +- services/servicediscovery/services_test.go | 61 +-- services/servicediscovery/tags_test.go | 22 +- services/servicequotas/autonotify.go | 5 +- services/servicequotas/catalog.go | 8 +- services/servicequotas/docs_catalog_test.go | 8 +- services/servicequotas/handler.go | 5 +- services/servicequotas/persistence.go | 12 +- services/ses/deep_flows_sdk_test.go | 7 +- services/ses/email_sending.go | 6 +- services/ses/identities.go | 5 +- services/ses/inbound_actions.go | 9 +- services/ses/inbound_auth_test.go | 6 +- services/ses/inbound_dsn_kms_test.go | 5 +- services/ses/inbound_kms.go | 6 +- services/ses/inbound_spf_test.go | 5 +- services/ses/inbound_test.go | 7 +- services/ses/multi_region_test.go | 8 +- services/ses/notifications.go | 6 +- services/ses/persistence.go | 10 +- services/ses/templates.go | 5 +- services/sesv2/account_test.go | 6 +- services/sesv2/configuration_sets_test.go | 21 +- services/sesv2/deep_flows_sdk_test.go | 7 +- services/sesv2/deliverability_test.go | 11 +- services/sesv2/email_identities_test.go | 37 +- services/sesv2/email_templates.go | 5 +- services/sesv2/email_templates_test.go | 5 +- services/sesv2/event_publishing.go | 8 +- services/sesv2/export_jobs_test.go | 11 +- services/sesv2/handler_account.go | 15 +- services/sesv2/handler_configuration_sets.go | 19 +- services/sesv2/handler_contact_lists.go | 9 +- services/sesv2/handler_contacts.go | 11 +- ...ler_custom_verification_email_templates.go | 9 +- services/sesv2/handler_dedicated_ip_pools.go | 9 +- services/sesv2/handler_dedicated_ips.go | 9 +- services/sesv2/handler_deliverability.go | 11 +- services/sesv2/handler_email_identities.go | 19 +- services/sesv2/handler_email_templates.go | 11 +- services/sesv2/handler_event_destinations.go | 9 +- services/sesv2/handler_export_jobs.go | 11 +- .../sesv2/handler_identity_certificates.go | 7 +- services/sesv2/handler_import_jobs.go | 7 +- services/sesv2/handler_message_insights.go | 6 +- .../sesv2/handler_multi_region_endpoints.go | 7 +- services/sesv2/handler_page_size.go | 7 +- services/sesv2/handler_send_email.go | 11 +- services/sesv2/handler_suppression.go | 7 +- services/sesv2/handler_tags.go | 7 +- services/sesv2/handler_tenants.go | 7 +- services/sesv2/handler_test.go | 9 +- .../sesv2/handler_update_configuration_set.go | 7 +- services/sesv2/handler_vdm.go | 9 +- services/sesv2/import_jobs_test.go | 10 +- services/sesv2/message_insights_test.go | 7 +- services/sesv2/multi_region_test.go | 5 +- services/sesv2/persistence.go | 8 +- services/sesv2/realism_test.go | 6 +- services/sesv2/send_email_test.go | 5 +- services/sesv2/smtp_relay_test.go | 7 +- services/sesv2/store_test.go | 10 +- services/sesv2/whitebox_test.go | 6 +- services/shield/errors_test.go | 5 +- services/shield/handler.go | 14 +- ...er_application_layer_automatic_response.go | 10 +- services/shield/handler_attacks.go | 18 +- services/shield/handler_attacks_test.go | 47 ++- services/shield/handler_drt.go | 12 +- services/shield/handler_drt_test.go | 5 +- services/shield/handler_emergency_contacts.go | 10 +- services/shield/handler_health_checks.go | 8 +- services/shield/handler_protection_groups.go | 25 +- .../shield/handler_protection_groups_test.go | 17 +- services/shield/handler_protections.go | 19 +- services/shield/handler_protections_test.go | 33 +- services/shield/handler_subscription.go | 9 +- services/shield/handler_subscription_test.go | 21 +- services/shield/handler_tags.go | 11 +- services/shield/handler_test.go | 7 +- services/shield/persistence.go | 20 +- services/shield/request_validation_test.go | 8 +- services/signin/handler.go | 5 +- services/signin/persistence.go | 12 +- services/signin/tokens.go | 7 +- services/sns/archive.go | 5 +- services/sns/archive_test.go | 9 +- services/sns/confirmation.go | 6 +- services/sns/delivery.go | 11 +- services/sns/delivery_test.go | 5 +- services/sns/filter_match.go | 109 ++--- services/sns/filter_match_test.go | 13 +- services/sns/filter_policy.go | 63 +-- services/sns/golden_perf_mixed_test.go | 5 +- services/sns/golden_perf_test.go | 8 +- services/sns/handler_test.go | 5 +- services/sns/lambda_firehose_delivery.go | 14 +- services/sns/lambda_firehose_delivery_test.go | 15 +- .../sns/message_structure_protocols_test.go | 11 +- services/sns/metrics.go | 10 +- services/sns/models.go | 4 +- services/sns/persistence.go | 4 +- services/sns/platform_endpoints.go | 5 +- services/sns/publish.go | 7 +- services/sns/publish_test.go | 9 +- services/sns/realism_sdk_test.go | 5 +- services/sns/signing_channels_test.go | 5 +- services/sns/signing_test.go | 5 +- services/sns/subscription_attributes_test.go | 7 +- services/sns/topic_attributes.go | 25 +- services/sqs/bench_protocol_test.go | 15 +- services/sqs/checksums_test.go | 7 +- services/sqs/dead_letter.go | 13 +- services/sqs/dead_letter_test.go | 29 +- services/sqs/errsweep_wire_shape_test.go | 5 +- services/sqs/fifo_test.go | 18 +- services/sqs/handler.go | 9 +- services/sqs/handler_dead_letter.go | 6 +- services/sqs/handler_dead_letter_test.go | 7 +- services/sqs/handler_message_move_tasks.go | 10 +- services/sqs/handler_message_visibility.go | 8 +- .../sqs/handler_message_visibility_test.go | 16 +- services/sqs/handler_messages.go | 14 +- services/sqs/handler_messages_test.go | 35 +- services/sqs/handler_permissions.go | 8 +- services/sqs/handler_queue_attributes.go | 8 +- services/sqs/handler_queues.go | 13 +- services/sqs/handler_queues_test.go | 9 +- services/sqs/handler_tags.go | 9 +- services/sqs/handler_tags_test.go | 6 +- services/sqs/handler_test.go | 9 +- services/sqs/message_move_tasks.go | 5 +- services/sqs/message_move_tasks_test.go | 5 +- services/sqs/message_visibility_test.go | 7 +- services/sqs/messages_test.go | 5 +- services/sqs/permissions.go | 5 +- services/sqs/permissions_test.go | 11 +- services/sqs/persistence.go | 24 +- services/sqs/queue_attributes.go | 6 +- services/sqs/queues_test.go | 5 +- services/sqs/sns_delivery.go | 7 +- services/sqs/sns_delivery_test.go | 9 +- services/sqs/sns_envelope_test.go | 5 +- services/ssm/activations_test.go | 20 +- services/ssm/agent_messages.go | 15 +- services/ssm/agent_messages_test.go | 11 +- services/ssm/associations_test.go | 15 +- services/ssm/automation_exec.go | 6 +- services/ssm/automations_test.go | 30 +- services/ssm/client_token_bound_test.go | 8 +- services/ssm/cloud_connector_test.go | 15 +- services/ssm/command_run_doc.go | 6 +- services/ssm/commands_test.go | 30 +- services/ssm/document_metadata_test.go | 19 +- services/ssm/document_parameters.go | 8 +- services/ssm/document_permissions_test.go | 14 +- services/ssm/document_test.go | 16 +- services/ssm/documents.go | 5 +- services/ssm/epoch_seconds_wire_shape_test.go | 21 +- services/ssm/handler.go | 15 +- services/ssm/handler_agent.go | 13 +- services/ssm/handler_parameters_test.go | 10 +- services/ssm/handler_test.go | 9 +- services/ssm/idempotency.go | 10 +- services/ssm/inventory_test.go | 17 +- services/ssm/janitor.go | 5 +- .../ssm/maintenance_window_execution_test.go | 7 +- .../ssm/maintenance_window_lifecycle_test.go | 17 +- .../ssm/maintenance_window_targets_test.go | 27 +- services/ssm/maintenance_window_test.go | 9 +- services/ssm/ops_items_test.go | 39 +- services/ssm/ops_metadata_test.go | 21 +- services/ssm/parameter_encryption_test.go | 11 +- services/ssm/parameter_labels_test.go | 11 +- .../ssm/parameter_policy_notifications.go | 8 +- services/ssm/parameters_handler_test.go | 17 +- services/ssm/parameters_test.go | 7 +- .../ssm/patch_baseline_approval_rules_test.go | 7 +- .../ssm/patch_baselines_lifecycle_test.go | 29 +- services/ssm/patch_baselines_test.go | 19 +- services/ssm/persistence.go | 10 +- services/ssm/public_parameters.go | 5 +- services/ssm/public_parameters_sdk_test.go | 7 +- services/ssm/resource_policies_test.go | 13 +- services/ssm/secret_references.go | 5 +- services/ssm/service_settings_test.go | 13 +- services/ssm/sessions_test.go | 11 +- services/ssm/ssmmessages_port_test.go | 9 +- services/ssm/ssmmessages_server.go | 17 +- services/ssm/ssmmessages_test.go | 14 +- services/ssm/tags_test.go | 17 +- services/ssoadmin/application_auth_methods.go | 14 +- services/ssoadmin/application_grants.go | 14 +- services/ssoadmin/handler.go | 15 +- .../ssoadmin/handler_account_assignments.go | 16 +- .../handler_application_access_scopes.go | 12 +- .../handler_application_assignments.go | 22 +- .../handler_application_auth_methods.go | 19 +- .../handler_application_auth_methods_test.go | 9 +- .../ssoadmin/handler_application_grants.go | 17 +- services/ssoadmin/handler_applications.go | 18 +- services/ssoadmin/handler_inline_policies.go | 10 +- .../handler_instance_access_control.go | 12 +- services/ssoadmin/handler_instances.go | 14 +- services/ssoadmin/handler_managed_policies.go | 12 +- services/ssoadmin/handler_permission_sets.go | 22 +- .../ssoadmin/handler_permissions_boundary.go | 10 +- services/ssoadmin/handler_regions.go | 12 +- services/ssoadmin/handler_tags.go | 10 +- services/ssoadmin/handler_test.go | 9 +- .../ssoadmin/handler_trusted_token_issuers.go | 14 +- services/ssoadmin/interfaces.go | 10 +- services/ssoadmin/models.go | 10 +- services/ssoadmin/multi_region_test.go | 8 +- services/ssoadmin/persistence.go | 18 +- services/ssoadmin/store.go | 14 +- services/ssooidc/handler.go | 5 +- services/ssooidc/persistence.go | 6 +- services/stepfunctions/aliases_test.go | 9 +- .../stepfunctions/asl/distributed_scope.go | 8 +- services/stepfunctions/asl/executor.go | 38 +- services/stepfunctions/asl/executor_test.go | 5 +- services/stepfunctions/asl/intrinsics.go | 10 +- .../stepfunctions/asl/item_reader_parquet.go | 7 +- services/stepfunctions/asl/jsonata.go | 8 +- services/stepfunctions/asl/jsonata_exec.go | 9 +- .../stepfunctions/asl/jsonata_validate.go | 23 +- services/stepfunctions/asl/mock.go | 15 +- services/stepfunctions/asl/parser.go | 117 ++--- services/stepfunctions/asl/result_writer.go | 11 +- services/stepfunctions/asl/sdk_integration.go | 15 +- services/stepfunctions/asl/variables.go | 6 +- services/stepfunctions/distributed_map.go | 5 +- services/stepfunctions/eks_integration.go | 11 +- .../stepfunctions/error_path_sweep_test.go | 11 +- services/stepfunctions/execution_history.go | 5 +- .../stepfunctions/execution_history_test.go | 5 +- services/stepfunctions/executions.go | 10 +- services/stepfunctions/handler.go | 21 +- services/stepfunctions/handler_activities.go | 24 +- .../stepfunctions/handler_activities_test.go | 55 +-- services/stepfunctions/handler_aliases.go | 14 +- services/stepfunctions/handler_executions.go | 20 +- .../stepfunctions/handler_executions_test.go | 21 +- services/stepfunctions/handler_map_runs.go | 10 +- .../handler_state_machine_versions.go | 10 +- .../stepfunctions/handler_state_machines.go | 12 +- .../handler_state_machines_test.go | 93 ++-- services/stepfunctions/handler_tags.go | 10 +- services/stepfunctions/handler_test.go | 37 +- .../handler_tracing_logging_test.go | 18 +- services/stepfunctions/handler_util.go | 48 ++- services/stepfunctions/handler_util_test.go | 22 +- services/stepfunctions/http_task.go | 11 +- services/stepfunctions/http_trace.go | 6 +- services/stepfunctions/integrations.go | 7 +- .../stepfunctions/item_reader_parquet_test.go | 5 +- .../item_reader_s3_resource_test.go | 13 +- .../jsonata_distributed_map_test.go | 5 +- .../list_executions_golden_test.go | 5 +- services/stepfunctions/map_runs_test.go | 47 ++- services/stepfunctions/overwide_list_test.go | 61 +-- services/stepfunctions/persistence.go | 18 +- services/stepfunctions/result_writer_test.go | 56 +-- services/stepfunctions/s3_item_reader_test.go | 5 +- services/stepfunctions/sdk_convert.go | 6 +- services/stepfunctions/sdk_integration.go | 5 +- services/stepfunctions/sdk_sync.go | 9 +- services/stepfunctions/sdkwire/call_test.go | 7 +- services/stepfunctions/sdkwire/legacy.go | 6 +- .../sdkwire/parity_whitebox_test.go | 6 +- .../stepfunctions/sdkwire/schemair/encode.go | 8 +- .../sdkwire/schemair/schemair.go | 13 +- .../state_machine_versions_test.go | 15 +- services/stepfunctions/tags_test.go | 48 ++- services/sts/persistence.go | 5 +- services/sts/token_validation.go | 8 +- services/sts/token_validation_test.go | 7 +- services/sts/trust_policy.go | 56 +-- services/sts/validation.go | 8 +- services/sts/web_identity.go | 6 +- services/sts/web_identity_irsa_test.go | 11 +- services/sts/web_identity_test.go | 9 +- services/sts/web_identity_verify.go | 6 +- services/support/cases.go | 8 +- services/support/cases_test.go | 5 +- services/support/handler.go | 14 +- services/support/handler_test.go | 7 +- services/support/persistence.go | 10 +- services/support/whitebox_test.go | 8 +- services/swf/decision_lifecycle_test.go | 5 +- services/swf/decision_orchestration_test.go | 5 +- services/swf/handler.go | 12 +- services/swf/handler_activity_types_test.go | 5 +- services/swf/handler_test.go | 11 +- services/swf/handler_workflow_types_test.go | 6 +- services/swf/lambda_tasks.go | 6 +- services/swf/models.go | 19 +- services/swf/multi_region_test.go | 8 +- services/swf/persistence.go | 6 +- services/swf/persistence_test.go | 5 +- services/textract/handler.go | 14 +- .../textract/handler_adapter_versions_test.go | 59 +-- services/textract/handler_adapters_test.go | 49 +-- .../handler_analyze_document_config_test.go | 11 +- .../handler_document_analysis_test.go | 57 +-- .../handler_document_detection_test.go | 40 +- .../textract/handler_expense_analysis_test.go | 33 +- services/textract/handler_id_analysis_test.go | 20 +- .../textract/handler_lending_analysis_test.go | 45 +- services/textract/handler_tags_test.go | 25 +- services/textract/handler_test.go | 15 +- services/textract/job_output_test.go | 5 +- services/textract/persistence.go | 4 +- services/textract/persistence_test.go | 19 +- services/textract/realism_test.go | 6 +- services/textract/s3_object_test.go | 13 +- services/textract/s3_output.go | 5 +- .../docker_engine_ops_test.go | 4 +- .../timestreaminfluxdb/engine_ops_test.go | 5 +- services/timestreaminfluxdb/engine_params.go | 23 +- services/timestreaminfluxdb/handler.go | 5 +- services/timestreaminfluxdb/handler_other.go | 4 +- services/timestreaminfluxdb/models.go | 4 +- .../timestreaminfluxdb/parametergroups.go | 4 +- services/timestreaminfluxdb/persistence.go | 10 +- services/timestreaminfluxdb/secrets.go | 5 +- services/timestreaminfluxdb/validate.go | 25 +- services/timestreaminfluxdb/wire.go | 12 +- .../column_info_marshal_test.go | 8 +- services/timestreamquery/handler.go | 9 +- .../handler_account_settings.go | 14 +- .../handler_query_execution.go | 12 +- .../handler_scheduled_queries.go | 22 +- services/timestreamquery/handler_tags.go | 16 +- services/timestreamquery/handler_test.go | 9 +- services/timestreamquery/persistence.go | 8 +- .../timestreamquery/query_execution_test.go | 5 +- .../timestreamquery/scheduled_queries_test.go | 7 +- services/timestreamquery/ts_meta.go | 6 +- services/timestreamwrite/handler.go | 11 +- .../handler_batch_load_tasks_test.go | 53 +-- .../timestreamwrite/handler_databases_test.go | 48 ++- .../timestreamwrite/handler_endpoints_test.go | 12 +- .../handler_internal_error_test.go | 6 +- .../timestreamwrite/handler_records_test.go | 35 +- .../timestreamwrite/handler_tables_test.go | 67 +-- services/timestreamwrite/handler_tags_test.go | 22 +- services/timestreamwrite/handler_test.go | 5 +- services/timestreamwrite/multi_region_test.go | 8 +- .../partition_key_enforcement_test.go | 6 +- services/timestreamwrite/persistence.go | 8 +- services/transcribe/call_analytics_test.go | 29 +- services/transcribe/handler.go | 12 +- services/transcribe/handler_test.go | 20 +- services/transcribe/language_models_test.go | 18 +- services/transcribe/medical_scribe_test.go | 10 +- .../medical_transcription_jobs_test.go | 16 +- .../transcribe/medical_vocabularies_test.go | 11 +- services/transcribe/multi_region_test.go | 8 +- services/transcribe/persistence.go | 10 +- services/transcribe/realism_test.go | 5 +- services/transcribe/s3_output_test.go | 10 +- services/transcribe/tags_test.go | 7 +- services/transcribe/transcript_synthesis.go | 6 +- .../transcribe/transcription_jobs_test.go | 15 +- services/transcribe/vocabularies_test.go | 11 +- .../transcribe/vocabulary_filters_test.go | 9 +- services/transfer/handler.go | 14 +- services/transfer/handler_access_test.go | 15 +- services/transfer/handler_agreements_test.go | 25 +- .../transfer/handler_certificates_test.go | 27 +- services/transfer/handler_connectors_test.go | 55 +-- services/transfer/handler_host_keys_test.go | 20 +- services/transfer/handler_profiles_test.go | 28 +- .../handler_security_policies_test.go | 12 +- .../transfer/handler_servers_fields_test.go | 52 +-- services/transfer/handler_servers_test.go | 39 +- services/transfer/handler_ssh_keys_test.go | 10 +- services/transfer/handler_tags_test.go | 25 +- services/transfer/handler_test.go | 5 +- services/transfer/handler_users_test.go | 36 +- services/transfer/handler_web_apps_test.go | 40 +- services/transfer/handler_workflows_test.go | 24 +- services/transfer/multi_region_test.go | 5 +- services/transfer/paging.go | 5 +- services/transfer/persistence.go | 4 +- services/transfer/realism_test.go | 6 +- services/transfer/resource_id_shape_test.go | 14 +- services/transfer/sftp_apigw.go | 5 +- services/transfer/sftp_server.go | 13 +- services/transfer/undeclared_members_test.go | 6 +- services/transfer/wire_field_fixes_test.go | 9 +- services/translate/handler.go | 9 +- services/translate/handler_languages_test.go | 6 +- .../translate/handler_parallel_data_test.go | 11 +- services/translate/handler_tags_test.go | 12 +- services/translate/handler_test.go | 7 +- .../handler_text_translation_jobs_test.go | 15 +- services/translate/multi_region_test.go | 8 +- services/translate/persistence.go | 4 +- .../verifiedpermissions/cedar_attributes.go | 55 +-- services/verifiedpermissions/handler.go | 12 +- .../handler_authorization.go | 6 +- .../handler_authorization_test.go | 46 +- .../handler_identity_sources_test.go | 30 +- .../handler_policies_test.go | 67 +-- .../handler_policy_stores_test.go | 53 +-- .../handler_policy_templates_test.go | 12 +- .../handler_schema_test.go | 9 +- .../verifiedpermissions/handler_tags_test.go | 39 +- services/verifiedpermissions/handler_test.go | 20 +- .../verifiedpermissions/idempotency_test.go | 12 +- .../verifiedpermissions/multi_region_test.go | 8 +- services/verifiedpermissions/oidc_jwks.go | 5 +- .../omission_defaults_test.go | 18 +- services/verifiedpermissions/persistence.go | 6 +- services/verifiedpermissions/policy_scope.go | 8 +- .../policy_template_item_shape_test.go | 6 +- .../verifiedpermissions/policy_validation.go | 13 +- services/verifiedpermissions/schema.go | 10 +- services/vpclattice/handler.go | 6 +- services/vpclattice/handler_test.go | 9 +- services/vpclattice/multi_region_test.go | 5 +- services/vpclattice/persistence.go | 4 +- services/vpclattice/whitebox_test.go | 8 +- services/waf/byte_match_sets_test.go | 13 +- services/waf/change_token_test.go | 17 +- services/waf/geo_match_sets_test.go | 13 +- services/waf/handler.go | 9 +- services/waf/handler_test.go | 9 +- services/waf/ip_sets_test.go | 17 +- services/waf/logging_configuration_test.go | 12 +- services/waf/non_empty_entity_test.go | 5 +- services/waf/pagination_test.go | 5 +- services/waf/permission_policy_test.go | 6 +- services/waf/persistence.go | 4 +- services/waf/rate_based_rules_test.go | 13 +- .../realclient_match_sets_and_rules_test.go | 5 +- services/waf/regex_match_sets_test.go | 11 +- services/waf/regex_pattern_sets_test.go | 13 +- services/waf/request_validation_test.go | 8 +- services/waf/rule_groups_test.go | 15 +- services/waf/rules_test.go | 13 +- services/waf/sampled_requests_test.go | 8 +- services/waf/size_constraint_sets_test.go | 11 +- services/waf/sql_injection_match_sets_test.go | 11 +- services/waf/tag_leak_test.go | 9 +- services/waf/tags_test.go | 16 +- services/waf/web_acls_test.go | 25 +- services/waf/xss_match_sets_test.go | 11 +- services/wafv2/capacity_test.go | 7 +- services/wafv2/export_test.go | 8 +- services/wafv2/handler.go | 19 +- services/wafv2/handler_api_keys.go | 17 +- services/wafv2/handler_api_keys_test.go | 12 +- services/wafv2/handler_ip_sets.go | 17 +- services/wafv2/handler_ip_sets_test.go | 23 +- services/wafv2/handler_logging_config.go | 34 +- services/wafv2/handler_logging_config_test.go | 26 +- .../wafv2/handler_managed_rule_catalog.go | 38 +- .../handler_managed_rule_catalog_test.go | 34 +- services/wafv2/handler_managed_rule_sets.go | 19 +- .../wafv2/handler_managed_rule_sets_test.go | 34 +- services/wafv2/handler_permission_policies.go | 11 +- .../wafv2/handler_permission_policies_test.go | 13 +- services/wafv2/handler_rate_based_rules.go | 16 +- .../wafv2/handler_rate_based_rules_test.go | 25 +- services/wafv2/handler_regex_pattern_sets.go | 46 +- .../wafv2/handler_regex_pattern_sets_test.go | 19 +- .../wafv2/handler_resource_associations.go | 14 +- .../handler_resource_associations_test.go | 19 +- services/wafv2/handler_revenue_statistics.go | 20 +- services/wafv2/handler_rule_groups.go | 40 +- services/wafv2/handler_rule_groups_test.go | 39 +- services/wafv2/handler_tags.go | 11 +- services/wafv2/handler_tags_test.go | 23 +- services/wafv2/handler_test.go | 25 +- services/wafv2/handler_web_acls.go | 76 ++-- services/wafv2/handler_web_acls_test.go | 77 ++-- services/wafv2/interfaces.go | 24 +- services/wafv2/list_summary_shapes_test.go | 10 +- services/wafv2/logging_config.go | 23 +- services/wafv2/models.go | 28 +- services/wafv2/multi_region_test.go | 5 +- services/wafv2/persistence.go | 20 +- services/wafv2/realism_test.go | 8 +- services/wafv2/rule_groups.go | 16 +- services/wafv2/store.go | 18 +- services/wafv2/web_acls.go | 38 +- services/workmail/handler.go | 7 +- .../workmail/handler_access_control_test.go | 5 +- .../workmail/handler_availability_config.go | 25 +- .../workmail/handler_impersonation_test.go | 5 +- .../handler_mobile_device_access_test.go | 10 +- services/workmail/handler_test.go | 7 +- services/workmail/lifecycle.go | 8 +- services/workmail/persistence.go | 6 +- services/workspaces/bundles_test.go | 23 +- services/workspaces/directories_test.go | 19 +- services/workspaces/directory_registration.go | 5 +- services/workspaces/handler.go | 5 +- services/workspaces/handler_test.go | 43 +- services/workspaces/images_test.go | 19 +- services/workspaces/multi_region_test.go | 8 +- services/workspaces/persistence.go | 4 +- services/workspaces/pools_test.go | 6 +- services/workspaces/tags_test.go | 17 +- services/workspaces/workspace_properties.go | 6 +- .../workspaces/workspace_properties_test.go | 6 +- .../workspaces/workspaces_lifecycle_test.go | 35 +- services/workspaces/workspaces_test.go | 53 +-- .../workspaces/workspaces_validation_test.go | 26 +- services/xray/handler.go | 10 +- services/xray/handler_encryption_config.go | 10 +- .../xray/handler_encryption_config_test.go | 20 +- services/xray/handler_groups.go | 23 +- services/xray/handler_groups_test.go | 39 +- services/xray/handler_indexing_rules.go | 11 +- services/xray/handler_indexing_rules_test.go | 18 +- services/xray/handler_insights.go | 19 +- services/xray/handler_insights_test.go | 41 +- services/xray/handler_resource_policies.go | 15 +- .../xray/handler_resource_policies_test.go | 25 +- services/xray/handler_sampling_rules.go | 19 +- services/xray/handler_sampling_rules_test.go | 29 +- services/xray/handler_sampling_statistics.go | 11 +- .../xray/handler_sampling_statistics_test.go | 33 +- services/xray/handler_service_graph.go | 15 +- services/xray/handler_service_graph_test.go | 36 +- services/xray/handler_tags.go | 15 +- services/xray/handler_tags_test.go | 19 +- services/xray/handler_telemetry.go | 8 +- services/xray/handler_telemetry_test.go | 8 +- services/xray/handler_test.go | 7 +- services/xray/handler_trace_retrieval.go | 21 +- services/xray/handler_trace_retrieval_test.go | 25 +- .../xray/handler_trace_segment_destination.go | 10 +- services/xray/handler_trace_segments.go | 8 +- services/xray/handler_trace_segments_test.go | 22 +- services/xray/handler_traces.go | 13 +- services/xray/handler_traces_test.go | 53 +-- services/xray/helpers_test.go | 9 +- services/xray/multi_region_test.go | 5 +- services/xray/persistence.go | 7 +- services/xray/policy_lockout.go | 39 +- services/xray/policy_lockout_test.go | 7 +- services/xray/resource_policies.go | 9 +- services/xray/service_graph_histogram_test.go | 6 +- services/xray/trace_segments.go | 8 +- services/xray/whitebox_test.go | 8 +- .../hardcoded_arn_partition_guard_test.go | 6 +- test/guards/jsonv1_import_guard_test.go | 110 +++++ test/guards/sdk_source_test.go | 11 +- test/integration/acm_test.go | 10 +- test/integration/apigateway_test.go | 8 +- test/integration/appsync_test.go | 7 +- test/integration/awsconfig_test.go | 5 +- test/integration/azurearm_test.go | 8 +- test/integration/azureservicebus_test.go | 5 +- test/integration/chaos_test.go | 7 +- test/integration/cloudwatchlogs_test.go | 6 +- test/integration/cognito_test.go | 5 +- test/integration/cosmosdb_test.go | 14 +- test/integration/ecrpublic_test.go | 8 +- test/integration/eks_irsa_test.go | 10 +- test/integration/elasticsearch_test.go | 8 +- test/integration/firehose_delivery_test.go | 9 +- test/integration/firehose_test.go | 5 +- test/integration/fis_test.go | 22 +- test/integration/gcp_iam_test.go | 6 +- test/integration/glacier_test.go | 5 +- test/integration/iot_test.go | 14 +- test/integration/lambda_esm_test.go | 5 +- test/integration/lambda_new_ops_test.go | 43 +- test/integration/lambda_test.go | 7 +- test/integration/lambda_url_test.go | 11 +- test/integration/lambda_zip_test.go | 23 +- test/integration/opensearch_test.go | 8 +- test/integration/pipes_sqs_lambda_test.go | 5 +- test/integration/pipes_test.go | 5 +- test/integration/ram_test.go | 13 +- test/integration/rdsdata_test.go | 9 +- test/integration/redshiftdata_test.go | 15 +- test/integration/resourcegroups_test.go | 5 +- .../resourcegroupstaggingapi_test.go | 7 +- test/integration/route53resolver_test.go | 13 +- test/integration/s3_eventbridge_test.go | 31 +- test/integration/s3_notification_test.go | 37 +- test/integration/scheduler_test.go | 5 +- .../secretsmanager_rotation_test.go | 5 +- test/integration/servicediscovery_test.go | 33 +- test/integration/sesv2_test.go | 19 +- test/integration/sns_roundtrip_test.go | 10 +- test/integration/sns_sqs_cross_test.go | 8 +- test/integration/stepfunctions_asl_test.go | 6 +- test/integration/swf_test.go | 5 +- test/integration/verifiedpermissions_test.go | 15 +- test/internal/tofu/download.go | 7 +- test/terraform/azure/cosmosdb_test.go | 10 +- test/terraform/azure/eventgrid_test.go | 7 +- test/terraform/azure/servicebus_test.go | 5 +- test/terraform/terraform_test.go | 22 +- 1808 files changed, 15676 insertions(+), 12768 deletions(-) create mode 100755 examples/azure-keyvault-app/azure-keyvault-app create mode 100755 examples/azure-servicebus-cosmos-worker/azure-servicebus-cosmos-worker create mode 100644 test/guards/jsonv1_import_guard_test.go diff --git a/cmd/acceptguard/report.go b/cmd/acceptguard/report.go index c82d902d5f..2b6c6e50d4 100644 --- a/cmd/acceptguard/report.go +++ b/cmd/acceptguard/report.go @@ -1,9 +1,12 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func writeJSON(path string, findings []finding) error { @@ -13,10 +16,9 @@ func writeJSON(path string, findings []finding) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(findings) + return json.MarshalEncode(enc, findings) } func printReport(findings []finding) { diff --git a/cmd/bdaudit/issues.go b/cmd/bdaudit/issues.go index 90a478ad36..fd1108e3cc 100644 --- a/cmd/bdaudit/issues.go +++ b/cmd/bdaudit/issues.go @@ -2,10 +2,12 @@ package main import ( "bufio" - "encoding/json" + "encoding/json/v2" "fmt" "os" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const statusClosed = "closed" @@ -61,7 +63,7 @@ func loadIssues(path string) (map[string]issue, error) { } var iss issue - if unmarshalErr := json.Unmarshal([]byte(text), &iss); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal([]byte(text), &iss, jsonx.V1()); unmarshalErr != nil { return nil, fmt.Errorf("%s:%d: %w", path, line, unmarshalErr) } if iss.ID == "" { diff --git a/cmd/bdaudit/report.go b/cmd/bdaudit/report.go index 416fab8122..4a11afecde 100644 --- a/cmd/bdaudit/report.go +++ b/cmd/bdaudit/report.go @@ -1,11 +1,14 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "os" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type report struct { @@ -23,10 +26,9 @@ func writeJSONReport(path string, rep report) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(rep); encErr != nil { + if encErr := json.MarshalEncode(enc, rep); encErr != nil { return fmt.Errorf("encode json: %w", encErr) } diff --git a/cmd/bodyclass/report.go b/cmd/bodyclass/report.go index b188fb33f1..5af8390219 100644 --- a/cmd/bodyclass/report.go +++ b/cmd/bodyclass/report.go @@ -1,10 +1,13 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type serviceReport struct { @@ -68,10 +71,9 @@ func writeJSON(path string, results []serviceReport) { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(results); encErr != nil { + if encErr := json.MarshalEncode(enc, results); encErr != nil { fatal(encErr) } diff --git a/cmd/cfnattrgen/main.go b/cmd/cfnattrgen/main.go index a4635c83b2..0742bd56f5 100644 --- a/cmd/cfnattrgen/main.go +++ b/cmd/cfnattrgen/main.go @@ -26,7 +26,8 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "go/ast" @@ -37,10 +38,12 @@ import ( "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type resourceTypeSpec struct { - Attributes map[string]json.RawMessage `json:"Attributes"` + Attributes map[string]jsontext.Value `json:"Attributes"` } type resourceSpec struct { @@ -158,15 +161,15 @@ func runTrimSpec(specPath, outPath string) error { continue } - attrs := make(map[string]json.RawMessage, len(rt.Attributes)) + attrs := make(map[string]jsontext.Value, len(rt.Attributes)) for attr := range rt.Attributes { - attrs[attr] = json.RawMessage("{}") + attrs[attr] = jsontext.Value("{}") } trimmed.ResourceTypes[name] = resourceTypeSpec{Attributes: attrs} } - out, err := json.MarshalIndent(trimmed, "", " ") + out, err := json.Marshal(trimmed, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return fmt.Errorf("marshal trimmed spec: %w", err) } @@ -187,7 +190,7 @@ func loadSpec(path string) (*resourceSpec, error) { } var spec resourceSpec - if unmarshalErr := json.Unmarshal(data, &spec); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &spec, jsonx.V1()); unmarshalErr != nil { return nil, unmarshalErr } @@ -295,7 +298,7 @@ func buildTable(spec *resourceSpec, supportedTypes map[string]struct{}) map[stri } func renderJSON(table map[string][]string) ([]byte, error) { - out, err := json.MarshalIndent(table, "", " ") + out, err := json.Marshal(table, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return nil, err } @@ -359,7 +362,7 @@ func buildServices(spec *resourceSpec, literals map[string]struct{}) []string { const minTypeNameParts = 3 func renderServices(services []string) ([]byte, error) { - out, err := json.MarshalIndent(services, "", " ") + out, err := json.Marshal(services, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return nil, err } diff --git a/cmd/cfnattrgen/regen_test.go b/cmd/cfnattrgen/regen_test.go index 34f33b3e74..8d788dc1b8 100644 --- a/cmd/cfnattrgen/regen_test.go +++ b/cmd/cfnattrgen/regen_test.go @@ -1,12 +1,14 @@ package main import ( - "encoding/json" + "encoding/json/v2" "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -90,7 +92,7 @@ func TestRenderJSON_Deterministic(t *testing.T) { assert.Equal(t, first, second) var roundTrip map[string][]string - require.NoError(t, json.Unmarshal(first, &roundTrip)) + require.NoError(t, json.Unmarshal(first, &roundTrip, jsonx.V1())) assert.Equal(t, table, roundTrip) } diff --git a/cmd/cfnpropgen/main.go b/cmd/cfnpropgen/main.go index 59e8584569..fc0546e135 100644 --- a/cmd/cfnpropgen/main.go +++ b/cmd/cfnpropgen/main.go @@ -8,11 +8,14 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "os" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type propertySpec struct { @@ -53,7 +56,7 @@ func readJSON(path string, v any) error { return err } - return json.Unmarshal(data, v) + return json.Unmarshal(data, v, jsonx.V1()) } func run(specPath, typesPath, outPath, reqPath string) error { @@ -67,7 +70,12 @@ func run(specPath, typesPath, outPath, reqPath string) error { return fmt.Errorf("load types: %w", err) } - out, err := json.MarshalIndent(buildSchemas(&spec, types), "", " ") + out, err := json.Marshal( + buildSchemas(&spec, types), + jsonx.V1(), + jsontext.Multiline(true), + jsontext.WithIndent(" "), + ) if err != nil { return fmt.Errorf("render: %w", err) } @@ -80,7 +88,12 @@ func run(specPath, typesPath, outPath, reqPath string) error { return nil } - req, err := json.MarshalIndent(buildRequired(&spec, types), "", " ") + req, err := json.Marshal( + buildRequired(&spec, types), + jsonx.V1(), + jsontext.Multiline(true), + jsontext.WithIndent(" "), + ) if err != nil { return fmt.Errorf("render required: %w", err) } diff --git a/cmd/clientcoverage/main.go b/cmd/clientcoverage/main.go index aa8c7d7863..479738cd11 100644 --- a/cmd/clientcoverage/main.go +++ b/cmd/clientcoverage/main.go @@ -36,7 +36,8 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "go/ast" @@ -49,6 +50,8 @@ import ( "regexp" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -650,7 +653,7 @@ func loadOpcensus(path string) ([]opService, error) { } var services []opService - if unmarshalErr := json.Unmarshal(data, &services); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &services, jsonx.V1()); unmarshalErr != nil { return nil, fmt.Errorf("parse %s: %w", path, unmarshalErr) } @@ -692,7 +695,7 @@ func main() { rpt := buildReport(services, result) if *jsonPath != "" { - data, marshalErr := json.MarshalIndent(rpt, "", " ") + data, marshalErr := json.Marshal(rpt, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if marshalErr != nil { fmt.Fprintln(os.Stderr, "marshal report:", marshalErr) os.Exit(1) diff --git a/cmd/enumcheck/report.go b/cmd/enumcheck/report.go index aaad7c39e6..7d692353fb 100644 --- a/cmd/enumcheck/report.go +++ b/cmd/enumcheck/report.go @@ -1,9 +1,12 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func writeJSON(path string, findings []finding) error { @@ -12,10 +15,9 @@ func writeJSON(path string, findings []finding) error { return err } - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(findings); encErr != nil { + if encErr := json.MarshalEncode(enc, findings); encErr != nil { _ = f.Close() return encErr diff --git a/cmd/errcodeaudit/report.go b/cmd/errcodeaudit/report.go index 8d564cd3c2..ea37dc3a9e 100644 --- a/cmd/errcodeaudit/report.go +++ b/cmd/errcodeaudit/report.go @@ -1,9 +1,12 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func writeJSON(path string, findings []finding) error { @@ -13,10 +16,9 @@ func writeJSON(path string, findings []finding) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(findings) + return json.MarshalEncode(enc, findings) } func printReport(findings []finding) { diff --git a/cmd/errtargetaudit/report.go b/cmd/errtargetaudit/report.go index 6d8f01b33a..6e072770b2 100644 --- a/cmd/errtargetaudit/report.go +++ b/cmd/errtargetaudit/report.go @@ -1,11 +1,14 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // lowResolutionThreshold gates the implausible-resolution guard -- @@ -211,10 +214,9 @@ func writeJSON(path string, scans []serviceScan) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(scans) + return json.MarshalEncode(enc, scans) } func printServiceScan(sr serviceScan) { diff --git a/cmd/opcensus/main.go b/cmd/opcensus/main.go index 5e76a6ee15..aa2d4350c4 100644 --- a/cmd/opcensus/main.go +++ b/cmd/opcensus/main.go @@ -40,7 +40,8 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "go/ast" @@ -52,6 +53,8 @@ import ( "slices" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -210,9 +213,8 @@ func writeJSON(path string, results []serviceResult) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") - if encErr := enc.Encode(results); encErr != nil { + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) + if encErr := json.MarshalEncode(enc, results); encErr != nil { return fmt.Errorf("encode json: %w", encErr) } diff --git a/cmd/overwidecandidates/main.go b/cmd/overwidecandidates/main.go index e3bc546c5e..75ae2aab5a 100644 --- a/cmd/overwidecandidates/main.go +++ b/cmd/overwidecandidates/main.go @@ -26,7 +26,8 @@ package main import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "flag" "fmt" @@ -37,6 +38,8 @@ import ( "slices" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dirModuleOverride maps services/ to its aws-sdk-go-v2/service module @@ -370,10 +373,9 @@ func writeJSON(path string, results map[string]serviceResult) { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(results); encErr != nil { + if encErr := json.MarshalEncode(enc, results); encErr != nil { fmt.Fprintln(os.Stderr, "error:", encErr) } diff --git a/cmd/parityfmtcheck/report.go b/cmd/parityfmtcheck/report.go index c9c4127bd8..cdf6b66522 100644 --- a/cmd/parityfmtcheck/report.go +++ b/cmd/parityfmtcheck/report.go @@ -1,10 +1,13 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const jsonFileMode = 0o644 @@ -28,7 +31,7 @@ func writeJSON(path string, results []result) error { }) } - data, err := json.MarshalIndent(out, "", " ") + data, err := json.Marshal(out, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return fmt.Errorf("marshal results: %w", err) } diff --git a/cmd/parityfmtcheck/report_test.go b/cmd/parityfmtcheck/report_test.go index 4fdf65d14a..aa62f38eb9 100644 --- a/cmd/parityfmtcheck/report_test.go +++ b/cmd/parityfmtcheck/report_test.go @@ -2,13 +2,15 @@ package main import ( "bytes" - "encoding/json" + "encoding/json/v2" "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPrintReport(t *testing.T) { @@ -68,7 +70,7 @@ func TestWriteJSON(t *testing.T) { require.NoError(t, err) var got []jsonResult - require.NoError(t, json.Unmarshal(data, &got)) + require.NoError(t, json.Unmarshal(data, &got, jsonx.V1())) require.Len(t, got, 2) assert.Equal(t, "dlm", got[0].Service) diff --git a/cmd/paritylint/report.go b/cmd/paritylint/report.go index d1684e217f..0873068351 100644 --- a/cmd/paritylint/report.go +++ b/cmd/paritylint/report.go @@ -1,10 +1,13 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func printReport(w io.Writer, findings []finding) { @@ -35,7 +38,7 @@ func printReport(w io.Writer, findings []finding) { } func writeJSON(path string, findings []finding) error { - data, err := json.MarshalIndent(findings, "", " ") + data, err := json.Marshal(findings, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { return err } diff --git a/cmd/pgoload/stepfunctions.go b/cmd/pgoload/stepfunctions.go index 44a7b242f7..ee4e8e1e0b 100644 --- a/cmd/pgoload/stepfunctions.go +++ b/cmd/pgoload/stepfunctions.go @@ -2,7 +2,7 @@ package main import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "log/slog" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/sfn" sfntypes "github.com/aws/aws-sdk-go-v2/service/sfn/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const sfnStateMachineName = "pgoload-sm" @@ -30,7 +32,7 @@ func sfnDefinition() string { "States": map[string]any{ sfnPassState: map[string]any{"Type": "Pass", "End": true}, }, - }) + }, jsonx.V1()) return string(def) } diff --git a/cmd/reqfielddiff/main.go b/cmd/reqfielddiff/main.go index 2eab5a822f..8d1c0fd1a2 100644 --- a/cmd/reqfielddiff/main.go +++ b/cmd/reqfielddiff/main.go @@ -420,7 +420,8 @@ package main import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "os" @@ -428,6 +429,8 @@ import ( "path/filepath" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -586,8 +589,7 @@ func writeJSON(path string, reports []serviceReport) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(reports) + return json.MarshalEncode(enc, reports) } diff --git a/cmd/reqfieldscan/main.go b/cmd/reqfieldscan/main.go index 4ff94473bb..aaa25c397b 100644 --- a/cmd/reqfieldscan/main.go +++ b/cmd/reqfieldscan/main.go @@ -206,7 +206,8 @@ package main import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "os" @@ -214,6 +215,8 @@ import ( "path/filepath" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -335,8 +338,7 @@ func writeJSON(path string, reports []serviceReport) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(reports) + return json.MarshalEncode(enc, reports) } diff --git a/cmd/requiredoutputfields/main.go b/cmd/requiredoutputfields/main.go index fe90fbfb32..f912c4e4b3 100644 --- a/cmd/requiredoutputfields/main.go +++ b/cmd/requiredoutputfields/main.go @@ -23,7 +23,8 @@ package main import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "os" @@ -33,6 +34,8 @@ import ( "slices" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dirModuleOverride maps services/ to its aws-sdk-go-v2/service module @@ -395,10 +398,9 @@ func writeJSON(path string, results map[string]serviceResult) { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(results); encErr != nil { + if encErr := json.MarshalEncode(enc, results); encErr != nil { fmt.Fprintln(os.Stderr, "error:", encErr) } diff --git a/cmd/retypesgen/main.go b/cmd/retypesgen/main.go index 098d93e5a4..85dd0cc4b9 100644 --- a/cmd/retypesgen/main.go +++ b/cmd/retypesgen/main.go @@ -3,7 +3,8 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "flag" "fmt" @@ -16,6 +17,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const fetchTimeout = time.Minute @@ -88,7 +90,12 @@ func run(out string) (int, error) { types := parse(string(b)) - data, err := json.MarshalIndent(catalog{Source: source, Types: types}, "", " ") + data, err := json.Marshal( + catalog{Source: source, Types: types}, + jsonx.V1(), + jsontext.Multiline(true), + jsontext.WithIndent(" "), + ) if err != nil { return 0, err } diff --git a/cmd/routecollisions/main.go b/cmd/routecollisions/main.go index 7ae9f2918e..0847cd3198 100644 --- a/cmd/routecollisions/main.go +++ b/cmd/routecollisions/main.go @@ -39,7 +39,8 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "flag" "fmt" "go/ast" @@ -50,6 +51,8 @@ import ( "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const cliGoPath = "internal/app/cli.go" @@ -169,10 +172,9 @@ func writeJSONReport(path string, results []svcInfo) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(results) + return json.MarshalEncode(enc, results) } func listServiceDirs(servicesDir string) ([]string, error) { diff --git a/cmd/sfnschemagen/main.go b/cmd/sfnschemagen/main.go index 2394fd94ea..4b6191583e 100644 --- a/cmd/sfnschemagen/main.go +++ b/cmd/sfnschemagen/main.go @@ -8,7 +8,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "fmt" "go/format" "log" @@ -20,6 +20,7 @@ import ( "sort" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire/ir" ) @@ -208,7 +209,7 @@ func queryVersion(dir string) string { } func writeModel(key string, model *ir.Model) { - raw, err := json.Marshal(model) + raw, err := json.Marshal(model, jsonx.V1()) if err != nil { log.Fatal(err) } diff --git a/cmd/sqdocsgen/main.go b/cmd/sqdocsgen/main.go index a29490a8d8..2086d692eb 100644 --- a/cmd/sqdocsgen/main.go +++ b/cmd/sqdocsgen/main.go @@ -6,7 +6,8 @@ package main import ( "bytes" "compress/gzip" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "flag" "fmt" @@ -18,6 +19,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const fetchTimeout = time.Minute @@ -208,7 +210,7 @@ func main() { slices.SortFunc(svcs, func(a, b service) int { return strings.Compare(a.Code, b.Code) }) - b, err := json.MarshalIndent(svcs, "", " ") + b, err := json.Marshal(svcs, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/cmd/staleclaims/report.go b/cmd/staleclaims/report.go index 0dfc74f075..b040237b38 100644 --- a/cmd/staleclaims/report.go +++ b/cmd/staleclaims/report.go @@ -1,10 +1,13 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const disclaimer = `NOTE ON READING THIS REPORT @@ -59,10 +62,9 @@ func writeJSON(path string, findings []finding) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(findings); encErr != nil { + if encErr := json.MarshalEncode(enc, findings); encErr != nil { return fmt.Errorf("encode json: %w", encErr) } diff --git a/cmd/stampaudit/report.go b/cmd/stampaudit/report.go index 2d8bdca390..877d9b4a9a 100644 --- a/cmd/stampaudit/report.go +++ b/cmd/stampaudit/report.go @@ -1,10 +1,13 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -130,10 +133,9 @@ func writeJSON(path string, results []result) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(out); encErr != nil { + if encErr := json.MarshalEncode(enc, out); encErr != nil { return fmt.Errorf("encode json: %w", encErr) } diff --git a/cmd/structfielddiff/main.go b/cmd/structfielddiff/main.go index 56f3b0bfba..b20830bfdd 100644 --- a/cmd/structfielddiff/main.go +++ b/cmd/structfielddiff/main.go @@ -38,7 +38,8 @@ package main import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "flag" "fmt" @@ -50,6 +51,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/cmd/internal/sdkshape" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dirModuleOverride maps services/ to its aws-sdk-go-v2/service module @@ -261,10 +263,9 @@ func writeJSON(path string, dumps []opDump) { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(dumps); encErr != nil { + if encErr := json.MarshalEncode(enc, dumps); encErr != nil { fatal(encErr) } diff --git a/cmd/xmlitemwrap/report.go b/cmd/xmlitemwrap/report.go index b14492b0af..c978689606 100644 --- a/cmd/xmlitemwrap/report.go +++ b/cmd/xmlitemwrap/report.go @@ -1,9 +1,12 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func writeJSON(path string, findings []finding) error { @@ -13,10 +16,9 @@ func writeJSON(path string, findings []finding) error { } defer f.Close() - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - return enc.Encode(findings) + return json.MarshalEncode(enc, findings) } func printReport(findings []finding) { diff --git a/cmd/zeroguard/report.go b/cmd/zeroguard/report.go index 68ce9764d5..aaa85ea99f 100644 --- a/cmd/zeroguard/report.go +++ b/cmd/zeroguard/report.go @@ -1,9 +1,12 @@ package main import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func writeJSON(path string, findings []finding) error { @@ -12,10 +15,9 @@ func writeJSON(path string, findings []finding) error { return err } - enc := json.NewEncoder(f) - enc.SetIndent("", " ") + enc := jsontext.NewEncoder(f, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) - if encErr := enc.Encode(findings); encErr != nil { + if encErr := json.MarshalEncode(enc, findings); encErr != nil { _ = f.Close() return encErr diff --git a/dashboard/azureaks_proxy_test.go b/dashboard/azureaks_proxy_test.go index 19ad9faac0..8ebfa6a889 100644 --- a/dashboard/azureaks_proxy_test.go +++ b/dashboard/azureaks_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -120,13 +121,13 @@ func TestAzureAKSProxy(t *testing.T) { require.NoError(t, h.Handler()(echo.NewContext(httptest.NewRequest(http.MethodGet, pool, nil), rec))) var doc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1())) props, ok := doc["properties"].(map[string]any) require.True(t, ok) props["count"] = 5 - body, err := json.Marshal(map[string]any{"properties": props}) + body, err := json.Marshal(map[string]any{"properties": props}, jsonx.V1()) require.NoError(t, err) runGCPSteps(t, h, []gcpStep{ diff --git a/dashboard/azureapim_proxy.go b/dashboard/azureapim_proxy.go index e2cd376069..a8c83b5223 100644 --- a/dashboard/azureapim_proxy.go +++ b/dashboard/azureapim_proxy.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "crypto/tls" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -253,14 +255,14 @@ func (t *apimTry) subscriptionKey(ctx context.Context, svc, sub string) (string, Properties map[string]any `json:"properties"` } - if json.Unmarshal(rec.Body.Bytes(), &doc) != nil || doc.Properties["state"] != apimPxActive { + if json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1()) != nil || doc.Properties["state"] != apimPxActive { return "", http.StatusConflict, "Subscription is not active" } rec = t.arm(ctx, http.MethodPost, base+"/listSecrets") var keys map[string]any - if rec.Code != http.StatusOK || json.Unmarshal(rec.Body.Bytes(), &keys) != nil { + if rec.Code != http.StatusOK || json.Unmarshal(rec.Body.Bytes(), &keys, jsonx.V1()) != nil { return "", http.StatusConflict, "Subscription key is unavailable" } @@ -298,7 +300,7 @@ func (t *apimTry) apiInfo(ctx context.Context, svc, api string) apimAPIInfo { } `json:"properties"` } - if rec.Code != http.StatusOK || json.Unmarshal(rec.Body.Bytes(), &doc) != nil { + if rec.Code != http.StatusOK || json.Unmarshal(rec.Body.Bytes(), &doc, jsonx.V1()) != nil { return def } diff --git a/dashboard/azureapim_proxy_test.go b/dashboard/azureapim_proxy_test.go index 4f0d2a1a71..9c6022ddeb 100644 --- a/dashboard/azureapim_proxy_test.go +++ b/dashboard/azureapim_proxy_test.go @@ -2,7 +2,8 @@ package dashboard_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -56,7 +58,10 @@ func newAPIMDashboard(t *testing.T) *apimEnv { be := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Echo-Key", r.Header.Get("Ocp-Apim-Subscription-Key")) - _ = json.NewEncoder(w).Encode(map[string]any{"path": r.URL.Path, "header": r.Header, "query": r.URL.RawQuery}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]any{"path": r.URL.Path, "header": r.Header, "query": r.URL.RawQuery}, + ) })) t.Cleanup(be.Close) @@ -99,7 +104,7 @@ func newAPIMDashboard(t *testing.T) *apimEnv { Secondary string `json:"secondaryKey"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &keys)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &keys, jsonx.V1())) require.NotEmpty(t, keys.Primary) dash := echo.New() @@ -222,7 +227,7 @@ func TestAzureAPIMTryIt(t *testing.T) { var o out if rec.Code == http.StatusOK { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &o)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &o, jsonx.V1())) } return rec, o diff --git a/dashboard/azurearm_inproc_proxy.go b/dashboard/azurearm_inproc_proxy.go index 6b036ebd61..a591e35a02 100644 --- a/dashboard/azurearm_inproc_proxy.go +++ b/dashboard/azurearm_inproc_proxy.go @@ -2,7 +2,7 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +11,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -152,7 +154,7 @@ func armProxyRelay(c *echo.Context, rec *httptest.ResponseRecorder, view func(an // armScrubBody applies the optional view and the generic scrub to a JSON body; anything else is returned as is. func armScrubBody(body []byte, view func(any)) []byte { var doc any - if json.Unmarshal(body, &doc) != nil { + if json.Unmarshal(body, &doc, jsonx.V1()) != nil { return body } @@ -162,7 +164,7 @@ func armScrubBody(body []byte, view func(any)) []byte { armScrub(doc) - if out, err := json.Marshal(doc); err == nil { + if out, err := json.Marshal(doc, jsonx.V1()); err == nil { return out } diff --git a/dashboard/azureflexdb_proxy.go b/dashboard/azureflexdb_proxy.go index 47a6b191df..17e3ea7f09 100644 --- a/dashboard/azureflexdb_proxy.go +++ b/dashboard/azureflexdb_proxy.go @@ -1,12 +1,14 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/netip" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -115,7 +117,7 @@ func flexProxyBody(method string, p []string, in []byte) ([]byte, bool) { return nil, false } - b, err := json.Marshal(map[string]any{"properties": props}) + b, err := json.Marshal(map[string]any{"properties": props}, jsonx.V1()) return b, err == nil } @@ -129,7 +131,7 @@ type flexPropsIn struct { func flexDatabaseProps(in []byte) map[string]any { var req flexPropsIn - if json.Unmarshal(in, &req) != nil { + if json.Unmarshal(in, &req, jsonx.V1()) != nil { return nil } @@ -153,7 +155,7 @@ func flexDatabaseProps(in []byte) map[string]any { func flexFirewallProps(in []byte) map[string]any { var req flexPropsIn - if json.Unmarshal(in, &req) != nil { + if json.Unmarshal(in, &req, jsonx.V1()) != nil { return nil } diff --git a/dashboard/azureinproc_proxy_test.go b/dashboard/azureinproc_proxy_test.go index c1faf8b550..6cef6221f2 100644 --- a/dashboard/azureinproc_proxy_test.go +++ b/dashboard/azureinproc_proxy_test.go @@ -2,7 +2,7 @@ package dashboard_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/dashboard" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/azurearm" ) @@ -110,7 +111,7 @@ func jsonField(t *testing.T, raw []byte, path ...any) string { t.Helper() var doc any - require.NoError(t, json.Unmarshal(raw, &doc)) + require.NoError(t, json.Unmarshal(raw, &doc, jsonx.V1())) for _, p := range path { switch k := p.(type) { diff --git a/dashboard/azurekeyvault_proxy.go b/dashboard/azurekeyvault_proxy.go index 700a5d4876..ddfa9f5971 100644 --- a/dashboard/azurekeyvault_proxy.go +++ b/dashboard/azurekeyvault_proxy.go @@ -2,7 +2,8 @@ package dashboard import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "regexp" "slices" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" azurekeyvaultbackend "github.com/blackbirdworks/gopherstack/services/azurekeyvault" ) @@ -74,7 +76,7 @@ func azureKeyVaultInternalToken() string { claims, _ := json.Marshal(map[string]any{ "iss": "gopherstack-dashboard", "exp": time.Now().Add(azureKeyVaultTokenTTL).Unix(), - }) + }, jsonx.V1()) return header + "." + enc.EncodeToString(claims) + "." } @@ -88,8 +90,12 @@ func (h *DashboardHandler) azureKeyVaultCreateVault(c *echo.Context) error { Name string `json:"name"` } - if err := json.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, azureKeyVaultMaxBodyBytes)). - Decode(&in); err != nil || !azureKeyVaultNameRe.MatchString(in.Name) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, azureKeyVaultMaxBodyBytes)), + &in, + jsonx.V1(), + ); err != nil || + !azureKeyVaultNameRe.MatchString(in.Name) { return c.JSON(http.StatusBadRequest, map[string]string{ "error": "vault name must be 3-24 characters: letters, digits and hyphens, starting with a letter", }) diff --git a/dashboard/azuremonitor_proxy_test.go b/dashboard/azuremonitor_proxy_test.go index ae486bfc51..28c87568be 100644 --- a/dashboard/azuremonitor_proxy_test.go +++ b/dashboard/azuremonitor_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/azuremonitor" ) @@ -148,7 +149,7 @@ func TestAzureMonitorProxy(t *testing.T) { } `json:"innererror"` } `json:"error"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "BadArgumentError", body.Error.Code) assert.Equal(t, "SemanticError", body.Error.Innererror.Code) assert.NotEmpty(t, body.Error.Innererror.Innererror.Message) diff --git a/dashboard/cloud_json.go b/dashboard/cloud_json.go index eb8055b440..fb753f34d3 100644 --- a/dashboard/cloud_json.go +++ b/dashboard/cloud_json.go @@ -1,10 +1,13 @@ package dashboard import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -33,8 +36,8 @@ func cloudUnavailable(c *echo.Context, name string) error { // cloudJSONDecode reads a size-bounded JSON body into v; on failure it has already replied. func cloudJSONDecode(c *echo.Context, v any) bool { - dec := json.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, cloudJSONMaxBody)) - if err := dec.Decode(v); err != nil { + dec := jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, cloudJSONMaxBody)) + if err := json.UnmarshalDecode(dec, v, jsonx.V1()); err != nil { _ = cloudJSONFail(c, http.StatusBadRequest, cloudStatusBadArg, "invalid request body") return false diff --git a/dashboard/gcpapigateway_proxy.go b/dashboard/gcpapigateway_proxy.go index 42cfd4d2f6..275b00128b 100644 --- a/dashboard/gcpapigateway_proxy.go +++ b/dashboard/gcpapigateway_proxy.go @@ -2,7 +2,7 @@ package dashboard import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -17,6 +17,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpapigateway" ) @@ -194,7 +195,7 @@ func (a *gcpAPIGWProxy) tryIt(ctx context.Context, r gcpRESTCall) (proto.Message bad := status.Error(codes.InvalidArgument, "invalid API Gateway try-it request") var in gcpAPIGWTryIn - if len(r.body) > gcpAPIGWMaxBody || json.Unmarshal(r.body, &in) != nil { + if len(r.body) > gcpAPIGWMaxBody || json.Unmarshal(r.body, &in, jsonx.V1()) != nil { return nil, bad } @@ -257,7 +258,7 @@ func gcpAPIGWTryTarget(project, location, gateway string, in gcpAPIGWTryIn) (str // structOf converts a JSON-compatible value into the protobuf Struct the REST proxy renders. func structOf(v any) (proto.Message, error) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, status.Error(codes.Internal, "unreadable response") } diff --git a/dashboard/gcpapigateway_proxy_test.go b/dashboard/gcpapigateway_proxy_test.go index 4aeeb4659f..673c5f69a6 100644 --- a/dashboard/gcpapigateway_proxy_test.go +++ b/dashboard/gcpapigateway_proxy_test.go @@ -2,7 +2,8 @@ package dashboard_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpapigateway" ) @@ -42,7 +44,10 @@ func newAPIGatewayDashboard(t *testing.T) *dashboard.DashboardHandler { be := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("X-Echo-Query", r.URL.RawQuery) - _ = json.NewEncoder(w).Encode(map[string]string{"path": r.URL.Path, "query": r.URL.RawQuery}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{"path": r.URL.Path, "query": r.URL.RawQuery}, + ) })) t.Cleanup(be.Close) @@ -124,7 +129,7 @@ func TestGCPAPIGatewayProxy(t *testing.T) { } `json:"openapiDocuments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cfg, jsonx.V1())) require.Len(t, cfg.Docs, 1) raw, err := base64.StdEncoding.DecodeString(cfg.Docs[0].Document.Contents) @@ -211,7 +216,7 @@ func TestGCPAPIGatewayTryIt(t *testing.T) { var o out if rec.Code == http.StatusOK { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &o)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &o, jsonx.V1())) } return rec, o diff --git a/dashboard/gcpbigtable_proxy.go b/dashboard/gcpbigtable_proxy.go index 4eb2ddca46..9f647a052c 100644 --- a/dashboard/gcpbigtable_proxy.go +++ b/dashboard/gcpbigtable_proxy.go @@ -2,7 +2,7 @@ package dashboard import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "cloud.google.com/go/bigtable/admin/apiv2/adminpb" @@ -13,6 +13,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" gcpbigtablebackend "github.com/blackbirdworks/gopherstack/services/gcpbigtable" ) @@ -171,7 +172,7 @@ func (a *gcpBigtableAPI) readRows(r gcpRESTCall, table string) (proto.Message, e } var v any - if uErr := json.Unmarshal(b, &v); uErr != nil { + if uErr := json.Unmarshal(b, &v, jsonx.V1()); uErr != nil { return nil, status.Error(codes.Internal, uErr.Error()) } diff --git a/dashboard/gcpfunctions_proxy.go b/dashboard/gcpfunctions_proxy.go index b73380fcbe..c4278c8558 100644 --- a/dashboard/gcpfunctions_proxy.go +++ b/dashboard/gcpfunctions_proxy.go @@ -3,7 +3,7 @@ package dashboard import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "cloud.google.com/go/functions/apiv2/functionspb" @@ -12,6 +12,7 @@ import ( "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpfunctions" ) @@ -139,7 +140,7 @@ type invokeInput struct { func (a *gcpFunctionsAPI) invoke(ctx context.Context, name string, raw []byte) (proto.Message, error) { var in invokeInput - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, status.Error(codes.InvalidArgument, "invalid request body: "+err.Error()) } diff --git a/dashboard/gcpidentitytoolkit_proxy.go b/dashboard/gcpidentitytoolkit_proxy.go index a9d25ddcab..5e9e96b23e 100644 --- a/dashboard/gcpidentitytoolkit_proxy.go +++ b/dashboard/gcpidentitytoolkit_proxy.go @@ -2,7 +2,7 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,8 @@ import ( "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -147,7 +149,7 @@ func (p *gcpIDPRequest) call(method, path, rawQuery string, body any) (*httptest var payload []byte if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) if err != nil { return nil, err //nolint:wrapcheck // surfaced as a 400 by the caller } @@ -262,7 +264,7 @@ func (p *gcpIDPRequest) userAction(uid, action string) error { return ociInvalid(p.c, "claims must be a JSON object") } - raw, err := json.Marshal(in.Claims) + raw, err := json.Marshal(in.Claims, jsonx.V1()) if err != nil || len(raw) > gcpIDPMaxClaims { return ociInvalid(p.c, "claims must be a JSON object under 1000 bytes") } diff --git a/dashboard/gcpidentitytoolkit_views.go b/dashboard/gcpidentitytoolkit_views.go index 796dc2625a..6f56f26885 100644 --- a/dashboard/gcpidentitytoolkit_views.go +++ b/dashboard/gcpidentitytoolkit_views.go @@ -1,9 +1,11 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type idpProvider struct { @@ -45,7 +47,7 @@ func idpUsersView(raw []byte) (any, error) { Users []idpUserWire `json:"userInfo"` } - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // surfaced as a 502 by the caller } @@ -73,7 +75,7 @@ func idpLocalIDView(raw []byte) (any, error) { LocalID string `json:"localId"` } - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // surfaced as a 502 by the caller } @@ -92,7 +94,7 @@ func idpOOBView(raw []byte) (any, error) { } `json:"oobCodes"` } - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // surfaced as a 502 by the caller } @@ -123,7 +125,7 @@ func idpTenantsView(raw []byte) (any, error) { } `json:"tenants"` } - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // surfaced as a 502 by the caller } @@ -164,7 +166,7 @@ func idpConfigView(raw []byte) (any, error) { } `json:"signIn"` } - if err := json.Unmarshal(raw, &in); err != nil { + if err := json.Unmarshal(raw, &in, jsonx.V1()); err != nil { return nil, err //nolint:wrapcheck // surfaced as a 502 by the caller } diff --git a/dashboard/gcpresourcemanager_proxy_test.go b/dashboard/gcpresourcemanager_proxy_test.go index 7471e3cd87..19a7196dca 100644 --- a/dashboard/gcpresourcemanager_proxy_test.go +++ b/dashboard/gcpresourcemanager_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/dashboard" "github.com/blackbirdworks/gopherstack/pkgs/gcpenforce" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/gcpresourcemanager" ) @@ -106,7 +107,7 @@ func TestGCPResourceManagerProxy(t *testing.T) { Etag string `json:"etag"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pol)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pol, jsonx.V1())) add := `{"role":"roles/viewer","member":"user:a@example.com","etag":"` + pol.Etag + `"}` @@ -122,7 +123,7 @@ func TestGCPResourceManagerProxy(t *testing.T) { Etag string `json:"etag"` } - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &cur)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &cur, jsonx.V1())) del := `{"role":"roles/viewer","member":"user:a@example.com","etag":"` + cur.Etag + `"}` runGCPSteps(t, h, []gcpStep{ diff --git a/dashboard/oci_inproc_proxy.go b/dashboard/oci_inproc_proxy.go index c6f96ed0c0..d5c6200e33 100644 --- a/dashboard/oci_inproc_proxy.go +++ b/dashboard/oci_inproc_proxy.go @@ -2,7 +2,8 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -10,6 +11,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -57,12 +60,20 @@ func ociDispatch(c *echo.Context, inner *echo.Echo, apiPath string, body []byte) func ociDecodeBody(c *echo.Context, v any) bool { r := c.Request() - return json.NewDecoder(http.MaxBytesReader(c.Response(), r.Body, ociInprocMaxBody)).Decode(v) == nil + return json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(c.Response(), r.Body, ociInprocMaxBody)), + v, + jsonx.V1(), + ) == nil } // ociDecodeBodyN is ociDecodeBody with an explicit size cap. func ociDecodeBodyN(c *echo.Context, v any, limit int64) bool { - return json.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, limit)).Decode(v) == nil + return json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, limit)), + v, + jsonx.V1(), + ) == nil } // ociInvalid answers 400 for a request outside the proxy's allow-list. diff --git a/dashboard/ociapigateway_proxy_test.go b/dashboard/ociapigateway_proxy_test.go index 8e546a6a4a..d56148759a 100644 --- a/dashboard/ociapigateway_proxy_test.go +++ b/dashboard/ociapigateway_proxy_test.go @@ -6,7 +6,7 @@ import ( "crypto/rand" "crypto/x509" "crypto/x509/pkix" - "encoding/json" + "encoding/json/v2" "encoding/pem" "math/big" "net/http" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ociapigateway" ) @@ -63,7 +64,7 @@ func newGatewayDashboard(t *testing.T) (*dashboard.DashboardHandler, string, str e.Any("/*", ops.Trusted()) post := func(path string, body map[string]any) []byte { - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rec := httptest.NewRecorder() @@ -79,7 +80,7 @@ func newGatewayDashboard(t *testing.T) (*dashboard.DashboardHandler, string, str require.NoError(t, json.Unmarshal(post("/20190501/gateways", map[string]any{ "compartmentId": gwComp, "endpointType": "PUBLIC", "displayName": "edge", "subnetId": "ocid1.subnet.oc1..s", - }), &gw)) + }), &gw, jsonx.V1())) var dep struct { ID string `json:"id"` @@ -91,7 +92,7 @@ func newGatewayDashboard(t *testing.T) (*dashboard.DashboardHandler, string, str "path": "/hello", "methods": []string{"GET"}, "backend": map[string]any{"type": "STOCK_RESPONSE_BACKEND", "status": 200, "body": "hi there"}, }}}, - }), &dep)) + }), &dep, jsonx.V1())) certPEM, keyPEM := gwCert(t) post("/20190501/certificates", map[string]any{ @@ -166,7 +167,7 @@ func TestOCIAPIGatewayProxy(t *testing.T) { Status int `json:"status"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, 200, out.Status) assert.Equal(t, "hi there", out.Body) assert.Equal(t, "utf8", out.Encoding) diff --git a/dashboard/ociartifacts_proxy.go b/dashboard/ociartifacts_proxy.go index 778c1bf188..d127b0fac0 100644 --- a/dashboard/ociartifacts_proxy.go +++ b/dashboard/ociartifacts_proxy.go @@ -2,7 +2,8 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -13,6 +14,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -306,7 +309,7 @@ func (in *ociArtReadmeIn) build() (map[string]any, bool) { } func ociArtMarshal(v map[string]any) ([]byte, bool) { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) return b, err == nil } @@ -383,7 +386,11 @@ func ociArtRestoreBody(c *echo.Context) ([]byte, bool) { Version *string `json:"version"` } - err := json.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, ociInprocMaxBody)).Decode(&in) + err := json.UnmarshalDecode( + jsontext.NewDecoder(http.MaxBytesReader(c.Response(), c.Request().Body, ociInprocMaxBody)), + &in, + jsonx.V1(), + ) if err != nil && !errors.Is(err, io.EOF) { return nil, false } @@ -442,7 +449,7 @@ func ociArtScrubSignatures(raw []byte) []byte { Items []map[string]any `json:"items"` } - if json.Unmarshal(raw, &env) != nil { + if json.Unmarshal(raw, &env, jsonx.V1()) != nil { return []byte("{}") } @@ -455,7 +462,7 @@ func ociArtScrubSignatures(raw []byte) []byte { env.Items = []map[string]any{} } - out, err := json.Marshal(env) + out, err := json.Marshal(env, jsonx.V1()) if err != nil { return []byte("{}") } @@ -476,7 +483,7 @@ func ociArtDownload(c *echo.Context, inner *echo.Echo, contentPath string) error Size int64 `json:"sizeInBytes"` } - _ = json.Unmarshal(meta.Body.Bytes(), &art) + _ = json.Unmarshal(meta.Body.Bytes(), &art, jsonx.V1()) if art.Size > ociArtMaxDownload { return cloudJSONFail(c, http.StatusRequestEntityTooLarge, "PayloadTooLarge", diff --git a/dashboard/ociartifacts_proxy_test.go b/dashboard/ociartifacts_proxy_test.go index 8bfe628fe5..af15e1e844 100644 --- a/dashboard/ociartifacts_proxy_test.go +++ b/dashboard/ociartifacts_proxy_test.go @@ -2,7 +2,7 @@ package dashboard_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/ociartifacts" @@ -88,7 +89,7 @@ func newArtDashboard(t *testing.T) artFixture { } `json:"items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &list, jsonx.V1())) require.Len(t, list.Items, 1) f.imageID = list.Items[0].ID @@ -105,7 +106,7 @@ func artTenancy(t *testing.T, f artFixture) string { Compartments []string `json:"compartments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Compartments) return out.Compartments[0] @@ -161,7 +162,7 @@ func TestOCIArtifactsProxyRepositoryActions(t *testing.T) { Immutable bool `json:"isImmutable"` } - require.NoError(t, json.Unmarshal(create.Body.Bytes(), &repo)) + require.NoError(t, json.Unmarshal(create.Body.Bytes(), &repo, jsonx.V1())) assert.NotEqual(t, "forged", repo.ID) assert.NotEqual(t, "forged", repo.CreatedBy) assert.Empty(t, repo.Tags) @@ -172,7 +173,7 @@ func TestOCIArtifactsProxyRepositoryActions(t *testing.T) { upd := artDo(t, f.h, http.MethodPut, artAPI+"/containerRepositories/"+repo.ID, `{"isImmutable":true,"isPublic":false,"freeformTags":{"forged":"yes"},"compartmentId":"x"}`) require.Equal(t, http.StatusOK, upd.Code, upd.Body.String()) - require.NoError(t, json.Unmarshal(upd.Body.Bytes(), &repo)) + require.NoError(t, json.Unmarshal(upd.Body.Bytes(), &repo, jsonx.V1())) assert.True(t, repo.Immutable) assert.False(t, repo.Public) assert.Empty(t, repo.Tags) @@ -222,7 +223,7 @@ func TestOCIArtifactsProxySignaturesAreScrubbed(t *testing.T) { "compartmentId": tenancy, "imageId": f.imageID, "kmsKeyId": "ocid1.key.oc1..kmskey0001", "kmsKeyVersionId": "ocid1.keyversion.oc1..ver", "message": enc([]byte(artMsg)), "signature": enc([]byte(artSig)), "signingAlgorithm": "SHA_256_RSA_PKCS_PSS", - }) + }, jsonx.V1()) require.NoError(t, err) made := f.direct(t, http.MethodPost, "/20160918/container/imageSignatures", string(body)) @@ -254,7 +255,7 @@ func TestOCIArtifactsProxyGenericLifecycleAndDownload(t *testing.T) { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(made.Body.Bytes(), &repo)) + require.NoError(t, json.Unmarshal(made.Body.Bytes(), &repo, jsonx.V1())) assert.NotEqual(t, "forged", repo.ID) put := f.direct(t, http.MethodPut, @@ -273,7 +274,7 @@ func TestOCIArtifactsProxyGenericLifecycleAndDownload(t *testing.T) { } `json:"items"` } - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &arts)) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &arts, jsonx.V1())) require.Len(t, arts.Items, 1) assert.NotEmpty(t, arts.Items[0].Sha256) diff --git a/dashboard/ocicontainerengine_proxy.go b/dashboard/ocicontainerengine_proxy.go index 8986db70ac..e71c32ae48 100644 --- a/dashboard/ocicontainerengine_proxy.go +++ b/dashboard/ocicontainerengine_proxy.go @@ -2,7 +2,8 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +12,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -131,7 +134,7 @@ func ociOKEResizeBody(in io.Reader) ([]byte, bool) { Quantity *int `json:"quantityPerSubnet"` } - if err := json.NewDecoder(in).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(in), &req, jsonx.V1()); err != nil { return nil, false } @@ -146,7 +149,7 @@ func ociOKEResizeBody(in io.Reader) ([]byte, bool) { return nil, false } - body, err := json.Marshal(out) + body, err := json.Marshal(out, jsonx.V1()) return body, err == nil } diff --git a/dashboard/ocicontainerengine_proxy_test.go b/dashboard/ocicontainerengine_proxy_test.go index ff1f28aa91..edf7683712 100644 --- a/dashboard/ocicontainerengine_proxy_test.go +++ b/dashboard/ocicontainerengine_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocicontainerengine" ) @@ -50,7 +51,7 @@ func newOKEDashboard(t *testing.T) (*dashboard.DashboardHandler, string, string) } require.NoError(t, json.Unmarshal(okeSeed(t, e, http.MethodGet, - "/20180222/clusters?compartmentId="+okeComp, ""), &clusters)) + "/20180222/clusters?compartmentId="+okeComp, ""), &clusters, jsonx.V1())) require.Len(t, clusters, 1) okeSeed(t, e, http.MethodPost, "/20180222/nodePools", @@ -66,7 +67,7 @@ func newOKEDashboard(t *testing.T) (*dashboard.DashboardHandler, string, string) } require.NoError(t, json.Unmarshal(okeSeed(t, e, http.MethodGet, - "/20180222/nodePools?compartmentId="+okeComp, ""), &pools)) + "/20180222/nodePools?compartmentId="+okeComp, ""), &pools, jsonx.V1())) require.Len(t, pools, 1) return dashboard.NewHandler(dashboard.Config{OCIContainerEngineOps: ops}), clusters[0].ID, pools[0].ID diff --git a/dashboard/ocicontainerinstances_proxy.go b/dashboard/ocicontainerinstances_proxy.go index 95cb0e859d..323a703670 100644 --- a/dashboard/ocicontainerinstances_proxy.go +++ b/dashboard/ocicontainerinstances_proxy.go @@ -3,7 +3,7 @@ package dashboard import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" idbackend "github.com/blackbirdworks/gopherstack/services/ociidentity" ) @@ -445,13 +446,13 @@ func ociCIScrubJSON(raw []byte) []byte { } var doc any - if json.Unmarshal(raw, &doc) != nil { + if json.Unmarshal(raw, &doc, jsonx.V1()) != nil { return []byte("{}") } ociCIScrub(doc) - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return []byte("{}") } @@ -610,7 +611,7 @@ func (h *DashboardHandler) ociCISubnets(c *echo.Context) error { } var subnets []map[string]any - if json.Unmarshal(rec.Body.Bytes(), &subnets) != nil { + if json.Unmarshal(rec.Body.Bytes(), &subnets, jsonx.V1()) != nil { return c.JSON(http.StatusOK, map[string]any{ociCIKeyItems: []any{}}) } diff --git a/dashboard/ocicontainerinstances_proxy_test.go b/dashboard/ocicontainerinstances_proxy_test.go index 19ad734e66..70eff49427 100644 --- a/dashboard/ocicontainerinstances_proxy_test.go +++ b/dashboard/ocicontainerinstances_proxy_test.go @@ -3,7 +3,7 @@ package dashboard_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/dashboard" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocicontainerinstances" "github.com/blackbirdworks/gopherstack/services/ocicore" "github.com/blackbirdworks/gopherstack/services/ociidentity" @@ -114,7 +115,7 @@ func (f ciFixture) settle(t *testing.T, id, state string) { State string `json:"lifecycleState"` } - return json.Unmarshal(rec.Body.Bytes(), &got) == nil && got.State == state + return json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1()) == nil && got.State == state }, 10*time.Second, 5*time.Millisecond) } @@ -141,7 +142,7 @@ func ciCreateDirect(t *testing.T, f ciFixture) string { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inst)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inst, jsonx.V1())) f.settle(t, inst.ID, "ACTIVE") return inst.ID @@ -164,7 +165,7 @@ func TestOCIContainerInstancesProxyScrubbing(t *testing.T) { rec := f.proxy(t, http.MethodGet, ciAPI+"/containers?compartmentId="+ciComp+"&containerInstanceId="+id, "") require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrList)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrList, jsonx.V1())) require.Len(t, ctrList.Items, 1) rawCtr := f.direct(t, http.MethodGet, "/20210415/containers/"+ctrList.Items[0].ID, "") @@ -240,7 +241,7 @@ func TestOCIContainerInstancesProxyCreateRebuild(t *testing.T) { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inst)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inst, jsonx.V1())) raw := f.direct(t, http.MethodGet, "/20210415/containerInstances/"+inst.ID, "").Body.String() for _, dropped := range []string{"mallory", "securityContext", "EMPTYDIR", "registryEndpoint", "runAsUser"} { @@ -410,7 +411,7 @@ func TestOCIContainerInstancesProxyLogsStateEngine(t *testing.T) { } rec := f.proxy(t, http.MethodGet, ciAPI+"/containers?compartmentId="+ciComp+"&containerInstanceId="+id, "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrs)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrs, jsonx.V1())) require.Len(t, ctrs.Items, 1) rec = f.proxy(t, http.MethodPost, ciAPI+"/containers/"+ctrs.Items[0].ID+"/actions/retrieveLogs", "") @@ -442,7 +443,7 @@ func TestOCIContainerInstancesProxyLogsDockerEngine(t *testing.T) { } rec := f.proxy(t, http.MethodGet, ciAPI+"/containers?compartmentId="+ciComp+"&containerInstanceId="+id, "") - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrs)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ctrs, jsonx.V1())) require.Len(t, ctrs.Items, 1) rec = f.proxy(t, http.MethodPost, ciAPI+"/containers/"+ctrs.Items[0].ID+"/actions/retrieveLogs", "") @@ -496,14 +497,14 @@ func TestOCIContainerInstancesProxySubnets(t *testing.T) { ) require.Nil(t, aerr) - vcnJSON, err := json.Marshal(vcn) + vcnJSON, err := json.Marshal(vcn, jsonx.V1()) require.NoError(t, err) var v struct { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(vcnJSON, &v)) + require.NoError(t, json.Unmarshal(vcnJSON, &v, jsonx.V1())) _, _, aerr = be.CreateSubnet(ocicore.CreateSubnetIn{ CompartmentID: ciComp, VcnID: v.ID, DisplayName: "sub-a", CidrBlock: "10.0.1.0/24", diff --git a/dashboard/ocicore_proxy.go b/dashboard/ocicore_proxy.go index 0436952892..192944e5bd 100644 --- a/dashboard/ocicore_proxy.go +++ b/dashboard/ocicore_proxy.go @@ -1,7 +1,7 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -9,6 +9,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -93,10 +95,10 @@ func ociCoreRelay(c *echo.Context, rec *httptest.ResponseRecorder) error { if rec.Code < http.StatusMultipleChoices && len(body) > 0 { var doc any - if err := json.Unmarshal(body, &doc); err == nil { + if err := json.Unmarshal(body, &doc, jsonx.V1()); err == nil { ociCoreScrub(doc) - if out, merr := json.Marshal(doc); merr == nil { + if out, merr := json.Marshal(doc, jsonx.V1()); merr == nil { body = out } } diff --git a/dashboard/ocievents_proxy.go b/dashboard/ocievents_proxy.go index 6e08fcb14a..292d9b9516 100644 --- a/dashboard/ocievents_proxy.go +++ b/dashboard/ocievents_proxy.go @@ -1,12 +1,14 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -161,7 +163,7 @@ func ociEventsCreateBody(c *echo.Context) ([]byte, bool) { out["description"] = in.Description } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } @@ -175,7 +177,7 @@ func ociEventsToggleBody(c *echo.Context) ([]byte, bool) { return nil, false } - b, err := json.Marshal(map[string]any{ociEventsEnabledKey: *in.IsEnabled}) + b, err := json.Marshal(map[string]any{ociEventsEnabledKey: *in.IsEnabled}, jsonx.V1()) return b, err == nil } diff --git a/dashboard/ocifunctions_proxy.go b/dashboard/ocifunctions_proxy.go index 334beef992..9528584260 100644 --- a/dashboard/ocifunctions_proxy.go +++ b/dashboard/ocifunctions_proxy.go @@ -2,7 +2,7 @@ package dashboard import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net" "net/http" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" fnbackend "github.com/blackbirdworks/gopherstack/services/ocifunctions" ) @@ -72,13 +73,13 @@ func (h *DashboardHandler) registerOCIFunctionsRoutes() { // maskedConfig renders a wire value as JSON with secret-looking config values replaced. func maskedConfig(v any) (map[string]any, error) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, err } out := map[string]any{} - if err = json.Unmarshal(raw, &out); err != nil { + if err = json.Unmarshal(raw, &out, jsonx.V1()); err != nil { return nil, err } diff --git a/dashboard/ocifunctions_proxy_test.go b/dashboard/ocifunctions_proxy_test.go index 99f0327c39..1085089838 100644 --- a/dashboard/ocifunctions_proxy_test.go +++ b/dashboard/ocifunctions_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocifunctions" ) @@ -36,7 +37,7 @@ func ociFnCall( require.NoError(t, h.Handler()(echo.NewContext(req, rec))) out := map[string]any{} - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) return rec, out } diff --git a/dashboard/ociloadbalancer_proxy.go b/dashboard/ociloadbalancer_proxy.go index 4dc6e13ad8..24fff74adb 100644 --- a/dashboard/ociloadbalancer_proxy.go +++ b/dashboard/ociloadbalancer_proxy.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "crypto/x509" - "encoding/json" + "encoding/json/v2" "encoding/pem" "io" "maps" @@ -19,6 +19,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ociloadbalancer" ) @@ -241,7 +242,7 @@ func ociLBCreateBody(c *echo.Context) ([]byte, bool) { }} } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } @@ -311,7 +312,7 @@ func ociLBBackendBody(c *echo.Context, update bool) ([]byte, bool) { return nil, false } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } @@ -320,7 +321,7 @@ func ociLBBackendBody(c *echo.Context, update bool) ([]byte, bool) { // subjects and validity; PEM text never reaches the browser. func ociLBScrubCerts(raw []byte) []byte { var v any - if json.Unmarshal(raw, &v) != nil { + if json.Unmarshal(raw, &v, jsonx.V1()) != nil { return raw } @@ -337,7 +338,7 @@ func ociLBScrubCerts(raw []byte) []byte { } } - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return []byte("{}") } diff --git a/dashboard/ociloadbalancer_proxy_test.go b/dashboard/ociloadbalancer_proxy_test.go index cd91f7903a..1e409f5829 100644 --- a/dashboard/ociloadbalancer_proxy_test.go +++ b/dashboard/ociloadbalancer_proxy_test.go @@ -6,7 +6,7 @@ import ( "crypto/rand" "crypto/x509" "crypto/x509/pkix" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "math/big" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ociloadbalancer" ) @@ -123,7 +124,7 @@ func newLBDashboard(t *testing.T) lbFixture { "sslConfiguration": map[string]any{"certificateName": "tls"}, }, }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := httptest.NewRecorder() @@ -139,7 +140,7 @@ func newLBDashboard(t *testing.T) lbFixture { ID string `json:"id"` } - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &items), list.Body.String()) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &items, jsonx.V1()), list.Body.String()) require.Len(t, items, 1) f.id = items[0].ID @@ -287,7 +288,7 @@ func TestOCILoadBalancerProxyActions(t *testing.T) { } `json:"backendSets"` } - require.NoError(t, json.Unmarshal(lbDo(t, f.h, http.MethodGet, lb, "").Body.Bytes(), &detail)) + require.NoError(t, json.Unmarshal(lbDo(t, f.h, http.MethodGet, lb, "").Body.Bytes(), &detail, jsonx.V1())) var found bool @@ -320,7 +321,7 @@ func TestOCILoadBalancerProxyActions(t *testing.T) { DeleteProtected bool `json:"isDeleteProtectionEnabled"` } - require.NoError(t, json.Unmarshal(list.Body.Bytes(), &items), list.Body.String()) + require.NoError(t, json.Unmarshal(list.Body.Bytes(), &items, jsonx.V1()), list.Body.String()) require.Len(t, items, 1) assert.Equal(t, "flexible", items[0].Shape) assert.False(t, items[0].DeleteProtected) @@ -349,7 +350,7 @@ func TestOCILoadBalancerProxyTryItRoundRobin(t *testing.T) { Status int `json:"status"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, 200, out.Status) assert.NotContains(t, out.Headers, "Connection") assert.NotContains(t, out.Body, "evil.example") diff --git a/dashboard/ocilogging_proxy.go b/dashboard/ocilogging_proxy.go index 4810406047..655593c604 100644 --- a/dashboard/ocilogging_proxy.go +++ b/dashboard/ocilogging_proxy.go @@ -1,13 +1,15 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" "github.com/google/uuid" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -95,7 +97,7 @@ func ociLoggingToggle(c *echo.Context, parts []string, raw string) (string, []by return "", nil, false } - b, err := json.Marshal(map[string]any{"isEnabled": *in.Enabled}) + b, err := json.Marshal(map[string]any{"isEnabled": *in.Enabled}, jsonx.V1()) return ociLoggingMgmt + raw, b, err == nil } @@ -140,7 +142,7 @@ func ociLoggingSearchRequest(c *echo.Context) (string, []byte, bool) { b, err := json.Marshal(map[string]any{ "timeStart": in.TimeStart, "timeEnd": in.TimeEnd, "searchQuery": in.SearchQuery, "isReturnFieldInfo": true, - }) + }, jsonx.V1()) return ociLoggingSearch, b, err == nil } @@ -161,7 +163,7 @@ func ociLoggingPushRequest(c *echo.Context, logID string) (string, []byte, bool) "source": "dashboard", "type": "dashboard.test", "defaultlogentrytime": now, "entries": []any{map[string]any{"data": in.Data, "id": uuid.NewString(), "time": now}}, }}, - }) + }, jsonx.V1()) return ociLoggingIngest + "/logs/" + logID + "/actions/push", b, err == nil } diff --git a/dashboard/ocilogging_proxy_test.go b/dashboard/ocilogging_proxy_test.go index 730f221f06..b6d29eb996 100644 --- a/dashboard/ocilogging_proxy_test.go +++ b/dashboard/ocilogging_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocilogging" ) @@ -49,7 +50,7 @@ func newLoggingDashboard(t *testing.T) (*dashboard.DashboardHandler, string, str } require.NoError(t, json.Unmarshal(logSeed(t, e, http.MethodGet, - "/20200531/logGroups?compartmentId="+logComp, ""), &groups)) + "/20200531/logGroups?compartmentId="+logComp, ""), &groups, jsonx.V1())) require.Len(t, groups, 1) logSeed(t, e, http.MethodPost, "/20200531/logGroups/"+groups[0].ID+"/logs", @@ -60,7 +61,7 @@ func newLoggingDashboard(t *testing.T) (*dashboard.DashboardHandler, string, str } require.NoError(t, json.Unmarshal(logSeed(t, e, http.MethodGet, - "/20200531/logGroups/"+groups[0].ID+"/logs", ""), &logs)) + "/20200531/logGroups/"+groups[0].ID+"/logs", ""), &logs, jsonx.V1())) require.Len(t, logs, 1) return dashboard.NewHandler(dashboard.Config{OCILoggingOps: ops}), groups[0].ID, logs[0].ID diff --git a/dashboard/ocimonitoring_proxy.go b/dashboard/ocimonitoring_proxy.go index 101a08faf2..44c441c88e 100644 --- a/dashboard/ocimonitoring_proxy.go +++ b/dashboard/ocimonitoring_proxy.go @@ -1,12 +1,14 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -91,7 +93,7 @@ func ociMonitoringListBody(c *echo.Context) ([]byte, bool) { b, err := json.Marshal(map[string]any{ ociNamespaceKey: in.Namespace, "name": in.Name, "resourceGroup": in.ResourceGroup, - }) + }, jsonx.V1()) return b, err == nil } @@ -110,7 +112,7 @@ func ociMonitoringSummarizeBody(c *echo.Context) ([]byte, bool) { return nil, false } - b, err := json.Marshal(in) + b, err := json.Marshal(in, jsonx.V1()) return b, err == nil } diff --git a/dashboard/ocimonitoring_proxy_test.go b/dashboard/ocimonitoring_proxy_test.go index d05bef329b..696c8c5a9c 100644 --- a/dashboard/ocimonitoring_proxy_test.go +++ b/dashboard/ocimonitoring_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocimonitoring" ) @@ -59,7 +60,7 @@ func newMonitoringDashboard(t *testing.T) (*dashboard.DashboardHandler, string) } require.NoError(t, json.Unmarshal(monSeed(t, e, http.MethodGet, - "/20180401/alarms?compartmentId="+monComp, ""), &alarms)) + "/20180401/alarms?compartmentId="+monComp, ""), &alarms, jsonx.V1())) require.Len(t, alarms, 1) return dashboard.NewHandler(dashboard.Config{OCIMonitoringOps: ops}), alarms[0].ID diff --git a/dashboard/ocimysql_proxy.go b/dashboard/ocimysql_proxy.go index 549ad8f913..2f1d816300 100644 --- a/dashboard/ocimysql_proxy.go +++ b/dashboard/ocimysql_proxy.go @@ -1,12 +1,14 @@ package dashboard import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -102,7 +104,7 @@ func ociMySQLBody(c *echo.Context, method string, parts []string) ([]byte, bool) out["displayName"] = in.DisplayName } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } diff --git a/dashboard/ocimysql_proxy_test.go b/dashboard/ocimysql_proxy_test.go index 3b9b6ce1f8..d390012fe9 100644 --- a/dashboard/ocimysql_proxy_test.go +++ b/dashboard/ocimysql_proxy_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ocimysql" ) @@ -50,7 +51,7 @@ func newMySQLDashboard(t *testing.T) (*dashboard.DashboardHandler, string) { } require.NoError(t, json.Unmarshal(mysqlSeed(t, e, http.MethodGet, - "/20190415/dbSystems?compartmentId="+mysqlComp, ""), &systems)) + "/20190415/dbSystems?compartmentId="+mysqlComp, ""), &systems, jsonx.V1())) require.Len(t, systems, 1) return dashboard.NewHandler(dashboard.Config{OCIMySQLOps: ops}), systems[0].ID diff --git a/dashboard/ocinosql_proxy.go b/dashboard/ocinosql_proxy.go index 43197493d6..760f5af674 100644 --- a/dashboard/ocinosql_proxy.go +++ b/dashboard/ocinosql_proxy.go @@ -2,11 +2,14 @@ package dashboard import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -135,16 +138,16 @@ func ociNoSQLCreateBody(c *echo.Context) ([]byte, bool) { b, err := json.Marshal(map[string]any{ ociKeyCompartment: in.CompartmentID, ociKeyName: in.Name, "ddlStatement": in.DDL, "tableLimits": limits, - }) + }, jsonx.V1()) return b, err == nil } func ociNoSQLRowBody(c *echo.Context) ([]byte, bool) { var in struct { - CompartmentID string `json:"compartmentId"` - Option string `json:"option"` - Value json.RawMessage `json:"value"` + CompartmentID string `json:"compartmentId"` + Option string `json:"option"` + Value jsontext.Value `json:"value"` } if !ociDecodeBody(c, &in) || in.CompartmentID == "" || !bytes.HasPrefix(bytes.TrimSpace(in.Value), []byte("{")) { @@ -160,7 +163,7 @@ func ociNoSQLRowBody(c *echo.Context) ([]byte, bool) { out["option"] = in.Option } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } @@ -182,7 +185,7 @@ func ociNoSQLQueryBody(c *echo.Context) ([]byte, bool) { out["consistency"] = in.Consistency } - b, err := json.Marshal(out) + b, err := json.Marshal(out, jsonx.V1()) return b, err == nil } diff --git a/dashboard/region_test.go b/dashboard/region_test.go index c8b9122648..a2cd4d4c4a 100644 --- a/dashboard/region_test.go +++ b/dashboard/region_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/appconfigdata" ) @@ -30,7 +31,7 @@ func profileCount(t *testing.T, h *dashboard.DashboardHandler, query string) int Profiles []any `json:"profiles"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return len(out.Profiles) } diff --git a/dashboard/ui.go b/dashboard/ui.go index 21a764e3a4..2f213152f0 100644 --- a/dashboard/ui.go +++ b/dashboard/ui.go @@ -3,7 +3,8 @@ package dashboard import ( "context" "embed" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "html" "io" @@ -29,6 +30,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/chaos" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/portalloc" "github.com/blackbirdworks/gopherstack/pkgs/service" acmbackend "github.com/blackbirdworks/gopherstack/services/acm" @@ -846,7 +848,7 @@ func (h *DashboardHandler) logEmbeddedSPABuildStamp() { } var stamp spaBuildStamp - if jsonErr := json.Unmarshal(data, &stamp); jsonErr != nil { + if jsonErr := json.Unmarshal(data, &stamp, jsonx.V1()); jsonErr != nil { h.Logger.Warn("embedded dashboard SPA build-stamp.json is malformed", "error", jsonErr) return @@ -1087,7 +1089,7 @@ func (h *DashboardHandler) registerCodeStarConnectionsMutationRoutes() { ProviderType string `json:"providerType"` HostArn string `json:"hostArn"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1130,7 +1132,7 @@ func (h *DashboardHandler) registerCodeStarConnectionsMutationRoutes() { ProviderType string `json:"providerType"` ProviderEndpoint string `json:"providerEndpoint"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1178,7 +1180,7 @@ func (h *DashboardHandler) registerCognitoUserPoolRoutes() { var req struct { Name string `json:"name"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1239,7 +1241,7 @@ func (h *DashboardHandler) registerCognitoUserPoolClientRoutes() { var req struct { ClientName string `json:"clientName"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1304,7 +1306,7 @@ func (h *DashboardHandler) registerCognitoUserRoutes() { Username string `json:"username"` TempPassword string `json:"tempPassword"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1356,7 +1358,7 @@ func (h *DashboardHandler) registerCognitoUserLifecycleRoutes() { var req struct { Enabled bool `json:"enabled"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1409,7 +1411,7 @@ func (h *DashboardHandler) registerCognitoGroupRoutes() { GroupName string `json:"groupName"` Description string `json:"description"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1461,7 +1463,7 @@ func (h *DashboardHandler) registerCognitoUserPoolConfigRoutes() { var req struct { MfaConfiguration string `json:"mfaConfiguration"` } - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{keyError: err.Error()}) } @@ -1677,7 +1679,7 @@ func (h *DashboardHandler) registerAppConfigDataProfileRoutes() { } var req setProfileRequest - if err := json.NewDecoder(c.Request().Body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &req, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, map[string]string{keyMessage: "invalid request body"}, diff --git a/dashboard/ui_test.go b/dashboard/ui_test.go index 21027f50b3..119b78fbf5 100644 --- a/dashboard/ui_test.go +++ b/dashboard/ui_test.go @@ -1,7 +1,7 @@ package dashboard_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "regexp" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/dashboard" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -72,7 +73,7 @@ func TestSystemSettings_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "123456789012", body["accountID"]) assert.Equal(t, "eu-west-1", body["region"]) @@ -134,7 +135,7 @@ func TestSystemSettings_NoSecretShapedKeys(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) secretLike := regexp.MustCompile(`(?i)secret|password|token|credential|accesskey`) for key := range body { @@ -184,7 +185,7 @@ func TestSystemRegions(t *testing.T) { var body struct { Regions []string `json:"regions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) for _, want := range tt.wantContains { assert.Contains(t, body.Regions, want) diff --git a/demo/wire.go b/demo/wire.go index ff1e4d9338..ad726732fd 100644 --- a/demo/wire.go +++ b/demo/wire.go @@ -2,12 +2,13 @@ package demo import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire" ) @@ -35,13 +36,13 @@ func NewWireCaller(key string, handler http.Handler, creds aws.CredentialsProvid } func (c *wireCaller) Call(ctx context.Context, op string, params any) (map[string]any, error) { - b, err := json.Marshal(params) + b, err := json.Marshal(params, jsonx.V1()) if err != nil { return nil, err } var in map[string]any - if err = json.Unmarshal(b, &in); err != nil { + if err = json.Unmarshal(b, &in, jsonx.V1()); err != nil { return nil, err } diff --git a/examples/azure-keyvault-app/azure-keyvault-app b/examples/azure-keyvault-app/azure-keyvault-app new file mode 100755 index 0000000000000000000000000000000000000000..369aba431c7d92e235856b248376f0989c028618 GIT binary patch literal 11110770 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⋙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

u2_ySN7rz}XgK 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

}Oursqk@j?stZ;!J@G}Uru zITB>Q)MbC7Gy7wm*>6+!`NW%(^>ZVXY-YOTOJi`zlYzt3{tsee*oD5NwUXno=szgO zTuwx?$^88@+tzsZ_%juM8u6{yz;|>kjmgKEixjZPoWD;bqiN0$C4%<|@AHE9Jl^L7 z@44n~SHUG(j7eUBzifr8tKHS+9*60FRT7EHEye$X_#)HKaiS0Qk6#eP7nq%H{JnT{ zXY1_v4B|aA%H=;?t2Fhr>%Xgl_=qWX@zMSBpBcpGrRsm7j{M@60euAVxwd}uDVQ>c zxMsFpcRi#txb-2VpSMR_fqd)pbVv!A%?CHY7lgS?Q}SYJ%KH2phwb1Gx#3yz8W8aR zqG;LH9+G}$wlW8)fQVh^oceQA*(ZJebw@PxKle>c>k(LCwK0Td_i+|kQwjHGYp?C> z`+4(o&ascd1$xA?uCR}sD|sOQ9wK&ukMgWD_%=W1mMs=n?m+V3?-JyS9PWyAACcfg ztDDE?YlAYv`1#`N4i`P%f+A5Pg4U`>-T4;oX(Tk0KSMTL8A|?qBB%)#Zr2eZ`q-&; zK~}|kjx|AZIT8ELZXfqUC2z5%{9`*jt%y?U%l7h$HOh)mn_eKlZ9G%QZ{wIP*$m4G zwD3)%{M5#)u!*$Umz|FC5|cjJNj&V3H(Ak1>@E*>cgH64`m;g*%XGD_&HQ|WbWi4P z$He|&KDtb;K=FT8dgq?Ol3>qZ!$J294kux^Jp&WHI=$OID4N62F+YNK3Pn3lj!DrD z`j4F{;#r5C#lhqU=;sY`rQ`=n`aunbW51I6NnN$~UV7lmq($=(dO%z<6O{K0-kmyP zgHm0{6ozphcpw3*L;S;??D-ih#LCk$($iiQM`q5k+HiXaHIJ{UMVu>)bi9fC4K95u zU3VvpJYx--iXY6khat;YL8nc8k@ImYL%G4)oqj7kQZjAmWkQ@>gE9evdU~BE)C`(! z<&QxJlbX8F;O5t{43*UQfq;Ixjv_HZ;krCoz4}=nZ|$P4?e?AhW@esDOlD@&|LnhS zyz?}m-kGQ`E6LE%z?FzL+@Y8}7N3`$>UtrslTe@|;uFa~SsY(B5bPy(SR9YyJ;}^l zo(ZyO;X2utVE;ObW#?a|7OMTg^RLJ>>Ff+L=8}Jjmc4F+HF*zEL7)6NHF>A=sXtpu z8@3we8CZb*`hqXU&mdRnr+nE;^OU?>rFqe^|LLqW&&;z$+e)iDD}7c4PwcGpVLtU| ztML_g8kN#VvYWW+c_f`#osy2lI!NMJQ%C)M52Q^zR(p_L8zQldUi&8u2>kL-Lr1-* z^)rFD?(a6$S?^sGzyId`Q7@G$Q@z&rH3XxyWN`kHE1|Mh^eSR6#jbIHAjS@Lw|$gg z6Q$!Vwpy;A^l@cub7kQk)mGWjqWf*DVv6ZADO6Ru@{ZwM87t`+m$xcDpg;Gr-aC@} zSW5RzKCd#`TvRcq@7Y!Hi#o7hs{2z_>6*y}D=JR!IEkRIlfP4{!|_5>G-trsI*S?4 zINdAU2WX$O`)ykF^C3UD1?a5YqjFDI!gg)|{rC01ctHJ6{@eO*R@LM6b3H!^hKa_< zKeL(t+|GjDAGzmLIWq0(z3;Ea?LPKQA-M7J36IwvR)*D z^;;tarC_X|+AFR0dJbbDphYkV+H%+NDy%?~C$Q<(FmFtC1^WoAi?_0VkrYkIOdQ0s zZm%g>5#fkCbJFb0v0RRuUKcEz0CK0albYL2g@gLN`V`csc0z3xW+wV<0I_9+tz4}8 zP3D`z@2x4=+2Jd0dO5%^9#fVk&@Tkl*WcDF4fO-)04FVG3{coPT-cr6XMZ>=Q*feR z{-H(h@@62<736aXaOib_Zu$LwfZnt}ppHMj*To;vHdL2@)$mW_l&16Pg&PBWenGKY zyxG-w8}Yq7aV@OTR&&{$GzZmrgxYiBwH(FUlnO1<1)!Viryi14cfPu5w166CPv?!4 zxpuiTbiuOqx=pxnA_bbBtZVE$!um*ijs~9~T-1I89H#n*%j&0w(76Y811s3o%u2h< zZp=1oV{@(U8ZG?V(=Bql?E0Ffxs0OIBHfSzHH=oTjT4KuPJF17%5?jBq>6=9u)m|^ z`2WaLpKyI*##&8t(x#YM$YW=vPho$XB@1>_N+jh74z`ZSwUmMon%VX9V% z{9pJEJwLsed3<7_##*{g9Zt2J8I7)&5!@#|tDm2B^q5I$9nG`72#3H{-AS_dstQqz zygMb^TN!b)AEphEJK-zUYcVQ@s_cH8B zI%+TWUL}eCj;=aph1dJd%Gf)Vh1}1(>s3HXs|r`WiOZSV<0{$BZvLdq>%A#a8RJ+_ zQ(I;Dxigs+R;rZ8t72=bVr#IPjqQ@@EWe#lb-lR$DevMhxnc-wJ)d5e@l09ChVV>v zpCi;kh%)!}FVTUHe~BHzBEYtG(AO(6)8$Uhl7Td|XrV#+L;)yG*M^JeSw+ zOP5MB9xD2JVw%QPX7a4~C12Nnl|H4Pf_rxc4;h=N-H;?Un#_eC*yz5e6Rpim zk#w6f?`G(C;a+bJ{{>z6 zhf(DmDf!nQmdk_9!K2w6{L0?E=6oEr4G%wOZLHM`!B*j45j|ViIw4v6Hg~=>njTvN z{0m^m;%bEcfQ8zyC8UCzzrura3S2dw?8yz|_8M_?(;Oo^YU6PKu>`Lcf927CX4Lh^ zd&FZ42`Y~+--$<`K9j#!S-N-9Ezz<+?_ot)djyw{w^YU6F^91?h1N>Wd@5sWE{q-3 zf?;{`mt4I(sVrLdOP9FH&xbJIG27T+=}KG`JBsVER@*bkngn#^xvVqjS9?DBb%dge z_(_=GJc$I$?P(U14u2e3vGRx1X}{VbCt}w&WL#OZ~nc@n5*q z$^M)q9elDc4(by2nz5e}VAeNTbjT?H zi~T#4wE2B(kV4y9C$N{ji{G@mD#}cMOAXBW;!SmT=uiO_3-#r}{a-4xmgQT{rzCgl z=lzQP3&EuR1&?I8i-*ku@p2oH^*RsypY2vLQZ78fw<)njaMVx6-l2PK%Cf8UK#yd< zLc@7D)4!g)=>pBrw-nPeG{`-Ua*rW;M4M1HX1!~aaAoK?g0x^D%O?cIy`Hfwn-_hj zz6YeoGt%Rcp0QA-GW(%*3hkR6&&al+yZIz^nL;x%ZIH^5cG2pWo`72L)_TCWON~ND zKhINtAOjZpSrM}PIcM`bHo^A7$vPt_(T(oT`t#}x5LlIu7y#S1l7|uBlb*>g zv4|ZYS=`ls<`%1`9uR9XZH{eJo(y-%pg4#BkDMNx__Z#+;C|xS1ak3L5pOQ15JvS~ z&k|#O5e&bCkzn&Lc%1f~2IEb&X#c0qS8aC2(-%^wZDhlzkEk*1Q)*0ODYlr$oO$_{ z&C}KrKB>H3kJ7<&Kbep=rKEK5ES{5#Ag$Y$f^gP(y{j-O_b<*&hKkp7oK>>nR4qb^ zig&lJqepG~O9x-5{HK-<9-;hrLCPsTcz$IqP$3h@Kal)*<?(o)Lo4 zmJVLYS9sQ5Vql1?`6$Gz$-CiM+ighBLP9)$z?OvnP=b)?zKq&XbYIW9Tn>dlML=5J zVW_l^SE|@U3V<%&UM0GimtU_>tn}vCU@OYFlf^>!12(WRzh2K+M!w|Vs~$aYOEDe_ zv%w%=N1@{?1Cxbe2c}{|hqE0gLDafcIx1mj#_%H7jU4wxk4RUVCH>V(-mpq|gnC)! zW-^}5W1FBm=Y)qx{pVcyoiRbiPln!*pin1x7p{)BbOk_af!}#FodNPo+Pgt;(PAK2TTr))mf3 z%&+~qd6rNkA7W_yZsA5GGvGyLGhdO=OIHW6+NqW<>%bbcIPu*mwa2MBPjuIOx}*&S zQ0qS||L&?+lNj}G=Hcp`nWxNw<(Ynu z1OksVkJ3D_1DDo1?Held{TP(^@8l~|yw{6;;WdAZFS%V)+-{+c*rd04&D;A{#aSU_ zATXdn*u^3e#SUU6gD!mT2Fp6|_lu#zr^h;S53ZvYH8W|Y^ccZ%v6gN2F~1C;wfX^# zBQ%0`ok(n}EHW*eZhjcpC7;z;;qzY^!TBC@)kdo{{E`6t8}q9r{Sw!enAug}m9)(|9o-ykk|00Bmx9!4$M15XkoH-IRQr13M4;cq)}WIbDMb zM|}Iv!MomBUOFoGeHmPD8lLqL)JlpwmBR1)4t#d~ohYGudJVAaNLo0mV?D&IX-tPI zdN*wEz?_(_XQ=`ocs@d1kqee6_TId+(58Hgl zL^%{KLe@qyTGG<0#u>xsrfH?~iAblqf?dgz5u1~l$hDS#RpPjA(&}=n zGg^Lbar>6xjhkz?SH+LoH!^(<^k3PqFD;L`Fsj`kgzI+_!{?3}(`EmSG|jo=nW_x1 zy!x^c2HC6bTf_Y^FvtkUi@&VRs)*m*b9m{e;hEVs-PQS#%J_NAwak?XvjxnHh9jOI zt%o@9ukFkEp>%RITHX=w)eEWFTdmIK2xjfL`mcJ{;+`{-R{zx@b?8@{axHI%lRk5$ z?0;Ud6Ie0lffwYF*UlfRBl(z3o2dfhS@rv+H52wr+UgFa;YO6iW+;$%71MeJ<13-> z3Fe_qf5bmKQKfD4&hxZw3DR-@*JvL?-09asVgj#QE>eHT<8BI_7>A81fb2QC-AfG zq*?Rw&tyOj^>pK-X2^cPsqAy9UmUh=2Ui2kv_f|Kt(!YC-NC~!enJnz4M$5b%jF>K0J2$?db=0YvO{aP* zXDPM*IHt0&Su)xkj1)3@4j=Jaef}Z8o+N_9`d6@W8t9t9S}`BFN#MemJ71tyn}lXh zup>VanLF&X&nD{dPk81L$l35of7k>6oR~J&3*WrLe%;HL=PzC?=-b~596`N>^QV?C zs=_BW+l11V?zqWnOIxHZ-HEQXKlv(kat(3~SAC5NC|xR`74kZKaYE;_^Ho@7SYD+l zjBI0%DL(O2V8dc=CKIbw_2$-> z-GtoWj`gii9&HXQ0fTC_gM#tJl!C%Gzy}h0?-ljRou0fcn3UI=y%A+{?q*gr*jNqm z0{?kDVQ|7{_vAz4=Xb- z{%W&K$)DgwsWPG#&1vEIX&|$H@pCp!zBE{mp25KSbiPLUf%Mb51Zm2!hi^^!9_FL< z?_^~DpgS6u^IBiFZCh7QdXG|eyXjgpUnfq)SJlAU1ZkTOidwF)T-G|J)Wn%nG4Q2km77J^ZwtP znK-!Tm!O?cM(~Dy$-Vu@2C6gv1fcb013DYHKAB@)9D4B140m;At5BqVEKxs>J^P>y zEct(L;D2l%ilm@@{|~)rdfx}93V3A#ah93G{NrcA=RLx^N@&F{qI(EkYgcYYUcrV}L7Co*12h zGP0vT0GV04Ili?MMhq=e?xM!6b%VOp@7^&Ru_ylgY#8|L=j_f>-;EmU6lWK+FHv)v zso}hZbq?a!ujRWjWjBWiQ)8}@IWNE!xLnK)!LjLc_kku#Do7o%Wy%Qs1kIaf0uI<- zVfV|L+)UlG!Oj~Py2R|8sQ?biABd(WN6UtPAZ~@L1prIt+D8g^(|#-514mVtoDr<7rK`Xbap>!hP<-CDU0I~ZSlOV|`a|}JFypSQSF^hX zh?rDuwt0*Vay68Z$7kyw;F+C7)$PTuFRu=0%Po%j{RN%o<6H{CIwOmB^zHmgb=>jx z1eR(czHF7SlT2tNTT@4-=|3W{$5}@z^WmTE@&{{HGw>cRo4CJQo!wuZ{ML_F1TYlX zB~+X;EPuxT@YfxF*6;p0(US68R4lP3PkJ`epsBx+M}?m?iASPx<*Y|6Y^1_Z5kcIa zQ`>iBY}d%xLyAeFd;cQAy*oo~W(Zs#C-cz}Dz-s6OLt9FuIZ&!vCv@z;oc(5qav1- ztuHC|Fd=eFK@01)4Yc>mHGvrxCpt8ly?q+Xg!tgsiL=-6yp~DruQH6&OeG%CZMV^h zO0DGot1=c+Mz;vp{;fZie)iytM-b`oH@+MG@NIE9rKQ!DbQ?HXLur);PNxh+6A(&m z<$0?7g%#>>1eWA!0F?F07mf;L5urmW7UwHxbdsBV%@(g3%l?pTGRdbNd2hW%P`L5u zw38)P1%!&+bhq{{sR`7fkbC|SzSu2zp2XJvw@y~PPw}O{j;yCui2uB5^3qpeAAIKw zFJ?az9NT!rrXtGEx{ZVsYIpHbaonRQ{Jh3EwHeE~RHek$@H%)DuN|RF__a#G=_ho@ z%K+M$!i!}nEwn!8)t$i@wD?IQt2unNC1{Hak^6af2ji>twtw3>^iMbcoAB{3S$bJI zZ}?P_yH?z}JpDuh*uyVx?;DO5ktE>)SiJw8!*gF{Oc{t{j@skok)yE|At?G)&q=wh ztk2RC(XV=i8(-lK6QJ-+`QfQTM^w5r+;|2Ft9(zlZ`5V*f_Xr7=13eX_!q;*?p;fb z+_8~6p=?M|A4AG;}Sik~Q^<|3CuvU-UI%ZbAp)IODIcvknBWZb*1hVj&5z zLpnJeeGwjB70=o}ZhTsKc+r4c40P~1&qC?E^us3+iC-XddUCM2`+6yJ98%=J zz@|hNGAcaoL}VC|J>4wxyxU}+cUzHuB5cXhO1Pi%!&rr~`4J1#)ata_GM42`fA6v7 znsVm&!HDtDpV^vC(WxqfDh{kVKn9}h8?TDm0|0RnB16G5_`hAy+%9Nt7c{p=^i%Dv zT&5jgyHWQR3sH6fB%QRZ?U~m4Hn1^2N549>?ofhLPU8~JJygtIkHeyd+UnhM%bof& zhc*L2JoLu7tiA1d&?~tID+Q8yV~vf?J(gI`%(EMKW)R)Rm%00O8$F?pXsL~9|DYgV zb(x!qH?2$g$#B)YcLOQ=DQZ_K^bVsh@!}5$tGjvbbnF%Mw~a9;Z>0O8cjS9%b#F_A z6>V4f=N6RPu1_Ayb)eQ+CmNzENS}oox}#NfeMkC{yi|aiqKK6LA+5XY#!GZ+Zd&d4 zx~o@?k@g=|jHtwm|G`3K4h;)uuI^M>&~={6o0sbSkGzBAeTyycRNfS<<@F_L;YNHm zW0T?_OBL~}gB3BaTM?2!S~Hc?zcNogRl_Pmy@|uK^KMgJjn4TZtG~?zv!*j^?jRiG zyw7(kxjF52KG@H=UC^n3gjcv$?=}^D_1Fr(M|o+}_)z#OU%b|{Y~Rs+*K7R1_d$t@s?-Fz#tb~|Tg5W7c7Hxp|vd5xc&T^$c> zCtV&$YSrXKfW7S23(6^i)Njx>7i6jPJUT3Y=1T0q057L)5@iZ)~)~9|D}^}@YawP z$cNQ3y@6)3>TfUTX)Qc(G1{x#l3i_Y0(%7~8nvhxEm?S+B%KNM)3P~pAngk3>hMhI z9qjr5bq>^xfxRid0q%vI6OlfoXlB#&3Ms>s`9yEbTD0jswYxN0_X}wBvC)F+b%OM0 z)Ud(aizXB){X_*s6opZq%2_p?Ah|vD&y9FvxYC3Tx!B&Wyyglr+DtaROB=l%t|R#= z-1v;3>uA*!DfRjZb1uz4UemcuoJyI~3oz^Dee(CPXTnDuws`EF!C+=^Mnr-c71R9i zBC-kP}{p44EuN?rip#SvV5$UMHQS!>Oi6eHE{30MmD*30oMsSZ`a<5onn z)43Toc-5K&^G5eu8NV&v!jJ#u>7Q28-sVp-Dtyd|<9*Ne{M$?Lpm;|HFOiXB){lrE zb);8%Wx*6?1ub(_pcyk+;9I<@O9(5nMvlqH?TXnha;ykzUTW-4QEF{&>+7lIPCzx8 z^=0c*wn<|8PcBdwg0JX-iVfFNr6FUX6Y8>Qh9OO}N zdU^QX<_h*Ok8HgO)uS-%scULPPn5Yr#(5xtvA|wL{Yy@#cM3Vv5|c86$^W>Dxml-U zpu&V-n+ogS*dzM#Xar9L#h*8ev9BUJJTt*??;MGFENCuUPT$oPn3En>^|q${VMvX+ zY7t7FO3w$uLO=vX*50+uXW@AwVU|wAZbCIB^#vv%RryoHFKY!q{?@LJd;Jk{I>^#Iy5ISL`*c)aYnE1MXl8!hgX@_Pr~gJqJpK ztvQO26@o2*!sb}G;OD1ki5LYVR!yS;GHC!}x{WSuGvo0yVLKA_jKXXiqRU6)7*n)o ze)GTZD=t@2AMM|nxpn|q5{64N-cn;}n8p%A$!?}3PpFui^C|Wx!vAnqSE=yByAP+O z$qYz1L40`Tc=pQ77hmBYq=%(+ zQb_h1C?q_SyDeq1{nj?9WG)t;u9wsYt^KY1Ylp0u1tgo>x=?bMNc}(KK<#V&9rh6v zy(ETwVokel{NDZo#mm#Xv;S6~W_D9BAwTH+SeN`zR9|-bTbBR++Hx87H>{DKu>C71 z4ssgi-)ng??6Ck9y?To`A;PPF+3`0KAV0`%sS z8~$YPFMgH~3xz4palw7zZwXan$LFB$JMI-R{eo=bbT?|yL9Re=_71T5>Mr!Nj%$*- zFrQy0ku3F}nTC9a(wI$mrTq!}rpX~r%HSLMa@uA`ec4_*8)e$2kF9IAghss zaX{A>R^GAWGa^#T1{)nHs#O81x^;nNLJ3<%Jfk1d1BN}0TTFWp@{Wf-y&L+^r5)zR;}4*J_Q{3ZOcj;g zdMHKhPygBBS@_3J$scGz_LGanLYc$=kY7*Xvi+?B-#BQV)y6m1bYVEsOIjRQZtu!? zb%dbgUzq}vy)p4vx1%!J#C58BGw*DvDqS{t89J=ANgt1l4`6xMU-;FGi7^)(U($rc zjiGc9Bwc#Mlw9P`s?y6dC(|EoRhTEOGT*zA?io=wLHv;ut1vG zC146ec@jqo%!Rji$F%@q3@Db`3tAIUZ8y~0SGRsSwTu7M2>;_$IwF~-9bDZB_3DB- zJn4c%G2Y|whC;EgrYkVjprNa3hj;Zy9}Zp}LHjG)o6aFwcqS{bH2S9`xs>I6WwYs7 z9)151L;~*RUB5$C4u@66)>Yv(`&ZaP*l;WyDzP4x%^p2c;n5@KcD5U%Y&)grrIFltV2y+Dkfjw_OiYsi9tf52zLjXMS5i`C#CP6WP+n9VEv z$kkY5>~RM>@-PqoY6|`Wsw0g(fc{u+iyY8{xacQ`I016`((?Abk;YARtfu}8XkMZ( zR5ZwjlI;0@Zyfctc=3#4g+`?06ZGc6EK6aqTN`Rg#9DtywxFp>q&e9$C#xU+o7&F| zCb<6#X~-YhO6m;TaB6fOqa1=yGg=)a1n0pC@%1VHi4bRZ@c_}^Af!rx4i2GowR^?xmTiMWDf3)?D zgcd&f)j8ql*9;>_7J>BQNU}d^JRB#DXm=yWBQPa@QXhx8d9E<$a9BzCO(87!Q zlxuA=ot%lbicDnniy-ElOD@O!u1BS$1vajMFTI8A-{SDRoj}7o1vzhCA00g>QJ!9!E`EuNpLb@;?ceS@jS93Q|R3EIEVwf}_9_6PB)_Ph9bXLPpz z5Bs;@#c$oy*?!{9>#o+Dza|v*IJmIFKFeeCv_9jZOZO240oW+6Sy~DE>@aZxv{jyR zd>#*N`XPW>o#3tCp>1OJ=6~2xrHJn(i8@vRmlO5xxrNndnR_Sw2bN*=E3Fqfo4Rhp zH`rfn2hf0rfO}`MsEJErqIPuZ?NjF)q+qk-z)N4vK;}}FZWlIwMu_!n%C^)F5JNR0x}H*5MdhdvAX z&kr&&t!VzCM@isK(1Z&ede`Ztnh+Xe`z4Yq){$#||D-MYi$Ne3t(^3$`<{38=bGn! zZzGdAM9KqBKtDlzjk(9g-(EyKQ%VrOB#5sz{eElnpHN7=Mw-jNAc*(OPIm9;)%p9E zKaF@Z8MqP}PkD2_G3X>P`+eqxTPQ*D!Sr)6jF`_SDoRvpeY4f5(WK61?vT*E`PZ%q zgduF2LY0^Sfm-=@5Je}?lXAx_R64HKIt&0AXfA#q<6COKBW2oop#$;re+0x1e#Ae_ z#-N5g;WRNfGUluvbx3!t?-5&c8YDR55iie_-T^5sb?8GXj`*m0b#{#xf3Tiv?Q*Pm zH;b6>QvM(Z)TNmKWfkW)s=^x-8eKk4`o@)+Ug@6jtU`5iLq{6JZDNjBx@mH6wU6tY zCmtf%C@uLHu}mofYV*wNPuQk<8lR})(#!yr8n(@ld=gNTm%ayMVPUbv-0QMD)gFvn zvrQwPKIx*&w;V4ReOf@7;y+7*RQUgKocQLiC_p?R=>H(T#EgPI%skaX?RI3rG>W(d zvhHY;<0?NbmDgNPHrsz!5o2~g&QCEtX{u~~t62(AjBr+?j`ytO#Tt-}><(dpJ(dXY zk(EwA`(G(c^r2)EQZWv{G#)zI?}UIk|CWRElGZm4Jk1brjqLiedtSCPZ-TyvmTl&v zhw2YEj(39-Q3+3pg&X_{S99Tc8&iJx*>|xIXxQ6Ef+;6R-`<=&)@xWQp`fuxBCs!r z?n5vbq%z{%J} z5zPJJMX%VYpFCO74-Q$r{aRV(ch3BlJ|d0#>Uy?i4h$5V zZu>z9p+_tIV4kr3duHm(6!S(;UwR>y*rx!nqrX8%+0d;g5PBk^rVjz~tl|Eg{Pr6n zf}VtyvZmZ8;|j|{b0*pMOYv~f<>+jR=O4Ax^QV=_zN4eI)$=bv1JP9bzT_2zP>rxI zxzjU8BG(~z;)+Mh2M#b<0drf1h%5*Rq)%LoIO+3oUBS-yfQwVN)?X#b1}IkNEuQ)@ zCNt+Tozes=|6Y=!LIE)p1@w2>o8KW*Ak97dZbPQm*w&HVT7ty>r;%KEsQ9=SYJa-S*GucCNJF-qV_c zE#E%AeJkgjV(xlzip7;9KzM^mqagl=q#JCga02;Ws-M=DcC@zX|fay{B{ z$jETT>I-}K?O7SeSwiWiNny8g>q%Vp#MMdWhZ^S9Hn(b==~gvh&b+Lf@hrA17cqTq z3Q#4cl>OiNUmOR41bvuSUv|MF%Si?k7$Ee>| zhwH2v)75(@SHduwv%Jz0-@_uQ3#bB{me>2?pn9bDeHEc_J zAF_+zBcz2FO}s0z_H!@%>TWnhVG9RoD#B4j5sY6#PjIzixj%FvOpM}99<_{RQBfId zqaxNDEv_Ec@6o-mmPzEQjGx8A=B`M^+;9bz&ODZ|wn*mbww~Q9(rb$vd%F7G#Qhjm z*&`$IoGWoi8-B6x2rr$}4yh|8qdF8Wd^6fmPDuhp#93=}7n{7HN=y^I%4#v%1TRCA z5q=T1r!mQWfk8}dhO225r6w>%>YEmSoAw_@)$qyN&uq(^OuS&u6& z-uFSjclfcL6U+TRu{F(mk8W-ql>Sch-can#=53+EH8Z!~F@bXGm3GYT0Pokfzvq?i zoP046KXQdU*VcRBiW%CANSBh03Rldi)|VX_49vW4_n*;THV@80_#O4KvwesCNlP42ZrKl8MC!Ggg zR|j}qC%mo^URSfHI-IlxN;_t2Fwu=~-$(~d{w@)R1ckJ(Z#$-+#gbT?V{mBt?2G9$ z6J*WA3d7A0``BG|I5E}uV6;rGwU=YA0e=n8>IJQKwLinpj=fp9&gN${5?9+Fb@WE) zacyQtBqIpB0F`?t-6^MPTqCNt=-xiR}~s%DT*s@{ANE zITnALHW`>$k$-YRvKF)$p{7bY54SD}e^g$=zcs&fW9<$JwtpLoeHF>Om!fIGF}h>M z?ngQ6VTqPx_WSt;{lF^NuCgPy3kTdxmMwJD4OuMt)~w)1O)SFPSrM3DHwYPs*0ip~ z^Aie{e~1l6L!HSL0YvHjm}30Of_O&nGMp!;y`-P;17C#5HA%E%YOY+k*yLV(f^vey9!*|q( z-6)&8F$P#_t~vMm?%fNNRE(MTk#C)Q^@NPf|(}!57)1cy6vr4bNYO1=K5cYW1SavQrL!PE9`5S-$J3 zE;_vpZ;UDmt&Aq*5&Jd5!Qb2kf41*slxEguwk{xylXd?0>4i)33s=WBuG>+#5lwPU z>7;^5eO|679*1zrtqou6)qaOB_yQ4Qa78>L9CXF-W12aOS9Fn|frFHaJ((RVOWP;D z7eDJTvc_7Fh^FPaTd3ya%rF>`om6J(0qZ}?0NNkJ#K>smQ z$WwEo?XZ+uKZc&3bb)c4NVz2$N2i%-S8`9nzu~yt30WULg)37IBlp#(pY<7^qKIrSh8`v7UHf@ut}B@1XV1V`HC*-Qg;bAh z4mWMnaT%RzUfGahyEG;qI!RRz{9kMNj43}MTepGJd~$QYGC1U(u748nT?MQo08k(# zbKJE7eiQ%Q{Q$owe}LZt3MjFaKld2+-Dc1O)E*E0^GSBip1oaL3>EqCNWt;|3Ct4g z_H6PQ`ufSkLQ~dhzXJ`;tvxk1@P~HpI^3o1T3rWEtIf}gU0$GVt@nFkpFbEku~@rr z!20bq>1<42)(t{no;Um4A|xh=NhaU%&>!APF@x5_Xs4R#)>orLGKb4-J>{T8B>I^= zJw-dV&slO7`85U35Ns{AKY%+6vkMc`XxYOHA+0)VFj0`ih|c0_ks8rM-{Ko@?nJrUu>E7$2JzPZ)X}QyOCIJGXI*Wa*jo;Z*PyS?^^$tZVJzu zWplB^Vs{bAa}s&{v+idbH8APuUm>o}|53WcJ`a6)euWUm|4|j9c-GAMvh}cbNk^4) zg`Xyd@_0sxz{;Znfg_cv3hJyrQAz>ar!AWCv%-&1ElFaVnsI~N1v+c#-3z>ZtrP zvT;I%33oMaRNGK?df;h1c4^JB%k28ioT-n~^waNh762#e?GU~7;3r^LQ?5=8jW-Su z?>WD5eSW<=pFJg|1aJ6sj}V5fRl|V`LhM0Us)c6`B`u4!s_?5TDx-T?tjS?dReZ!b z7+U}4vhisbgkKzR?(pKR!)FaFuiuBW{CT#-6+`5%K`TYA5!pcs)`x4M->UT06?6Mk z#&)rSEZ2#TwB<`H+rMP3SXaq9@sz6cpK1LUEt~(Gwto7uAy)5oG;WwmV0ps_DtKi0 z*)8m!NdwDfussg3!F;6!NW*e930Behf>uAM8 z8AT(ZlyD>Va!}X9t`^qn;b*xd=M@J|`fN3_zAOqa5PgLk9q~E?dbC4h%fa68@QY23 zzNebvlJ8MD@I zk05x5XMbQ}46cjFoI5*3prSb<&kvzx;Y~u=vLQT(1=>{T|+!Am&YCqQxLG zSbt7CBqde2Rn?lBV60kcHPL$2H}|Z%3vhPk^>cn#Vzofp_6;<(()ysO^%}mGx+ol7 zLj*e7FQlWD$|ieAusz$@L))-{jwoe|fGY_U%iNWEuOcfNSJY)_3^t~RU)*4oYpByW zAh$b_40Gsb*U0eV=Bjk)2>+m^8z1Q)J5Bb7_w zr}{(nwx;qG_pXn(Ni99x+x)Lte(u6Au4QM6t5>@@!I0u+Hf3~EG=He_bV+<1$5oc z_O~z{YAFxr_Nnq0xZ&AzWNd)$4UKpMS5+RfYWensUo<&~=67H(mKsU)A|On;Qxj}N zDlbo_OxBIz7k6Ik`Dd;3{6j>gpK3wH_-Eba^cxG3mZnjU5M&8@{O69KQx*?0E3y$q z?`c8|tTvG)ZF{LNc|USiwbbvxU{gJVhau4XtGufASCtbIWll4&Rlz+bl*8F4K z{PQUM(RNb9rwI`&qw*2^bk`@3WnXro{dR|NWKh(^w{#H6P3&o?r3%KVyv%8`vuWaWB$CwK za+Fd9#>Po)Il2mZ^dP9p@GD%b3A)SeDt-C6tJ<5CpvFtbr^mA!V7b|DQ$ol5Wan(< za~bBVcGdb{Qm5pLi2NdX11+7_R36i&FmL(x#b4Nv(SpA^nRQX@#FaSZtn2`iwbJk1 zy_>GY?sivI_?5Ng_E5m`bAQwR!A0>C*Fn}JY4{RH*N0R_zlw|;xSmnH{JICeSSv#j z$Y>xdmcBXr zk)rQd($V*k0mBw%QY1d|uOe|*i*DWQCy3dI@YnIyjqt}p zNV(!8c~T88n*@TR89_RWw0N9-z_mT&){{j9YqUcCxl%`S^$As(uqj#b{VRckYsZ{OD5jC3Z> z;vLiC_1=@rQ_hUFb`N9u_U86g@^$46T<;yTPPvY0`G$*No$oDSFUk$kUf>}Zq7fax ziN9h`>me$AnHgLGy~}&TiwCCw*XsF-vhZ>viG`$)E=xt%Mzui_3|gzJ0^c&-tOCkWYg%v76?7|P70YqV=_t$K#u zO8_KLZRYwmYRQo)^NE2$)HrjCi+Us#W#{jET*e7zl#6|+E4G4O-x|cTf2-ZN^cFoQ z@HEG`^sVovc9s{C)I0-Z=6na=(3d!b;aF~lcK6+KXtLnXO3{O7j(ux5yaYp_RO)Mly}C?wy_{&EcyW# z`Pg4mRCFVe<_24Lg|L;fm5{0=fYW>&wIzPJKGnEkL46k1Ij+c;2Bcs;GKjUX-soaq z=#1Taw^}0epo?78TOS3KW%(bmW+U~rHp9Z;j~e(0VaHx*?ax}b9%vD4>m3?}@ob=f z_SuVfEFa=WYZDb%86TQ0o-|dK;u%~xB6Gjgp(-~$uB!?!S$AQ4zy?gj>k1@xRGZH~ zMK8o@hQ{>*hB44pAYKiaf~Ss*t;4c>WMQ)m%by$>+c2_lX;ta^DG#fF36d3%U1jXT zc#6nG&C)G#SOITNNg?LfEJ_%OXQ^9ZTn}5AE#opbeduP#ykK?|T9_U8PjuX0G)-D_ zVU1V;Dsj-WAZp4~ttnhcR+!Mb$LhJPHTpb<>-2_5rdkP8_RL6o|w1 z$aQNC`^!yS(o`|&2#@t1Ys%)S$`#DRiDfUrgwxDr<2AX`&px|~>Glp0brJn@)efoJ z0+V-;Shz)^_h`u#^k%u;{u#;skCnA5)7wyNnU(4WH46LWA%eT1S&6Y280YoGYM^xI zq^CjZ?`V$%-Ywz6f8lj!Z)ywF$3&n}b8M7d`?;6ZY+?&bNh~ZxRh%Y*Xi3OXu6# z&bQ6Hu@U&b9wL(1gc{X!(NRM=$$HZEDTnE6=OFv__T)ms-id_oU%__lZf@mB!T3e^ z>eT>=Z>N59GT}0q3bF;ti~gczi+_R22SV!#lci{H?L+EpB*qKF-o4ej1bUB$7|(Yu z^as3Ij>YxL83m{#^_M{DHgfhuMSOC8Wvu)I-hqUvF{sW!-b=6hHoZ4Jt9YxWuW1}Q zOXgTf-rS=1-fVSkFxT@+PurQ~Qp<+J@I`EY@YugXeIwoemp!OOGw9Rz%4@^pUgQA48EuT|%8 zcAe6>h>$A0$h4f_eTWC0kXlJde_qu3dTP|W@$&$E5R9J!b#{rLNpEu|%~=5F(iP4+ z8061+gjRTdLgPV~@%YZQ4R2(@Ao*zoFx3g$zo*_NeK27kw@%ec6azuee{hZssiia1 zS=&Bm6Qu8A0_!_-_iH+X8m?-0tDn-Z?!2YSFRzjGU)Yp#O%%Al)Np7H-q%={XSl*# z`~7%Ewi1Sqx7P=)$`up1#xjK0kI;Kfi=y#(Ntp9^$>k_3@Qw*T-l7qM_69{KkZ~H5 znCXL3_0lm}*V^)2J`QDD7iV92g>C4{zB0%tOY}ow8-h$rS$5iksb2WPr2()l;q0{z zrfXK?UTJz01_}Y0PshX3>;~=B(%ITuQ)inmD}p|49kHJ>#P#34lxP(F6y{?6=m&E) zD`Mf=41o5yeBpO&6Lzg%mGFc)@2f8u(R7&8H|X9KZr2LH$3ACq6G;Nd@i;0DlpVSe zaTHWGClBwIPZ6Vt@cgOc@Ge`E;L^45EK4dgcQbE?pM{&P632ZL!Vz2SVs6*0OZMc8 z@J9&u{DqFfkZTq$Q~<;y-sw-R(N#h-ci+(`RTM7kV(rn7({-<0@AfW0Yw+e(1D>x~ z7lc7C*@K&rTw$e~34e#iY#_|bgIQGPp)v@AbXiSzEDiR5a4&UdE=jIlE5uJO4>S1_TRO$(2>b!j+2$|eH|t*(>49rMH^1L$GfhclGB=W8ahHDh zOc#InE(%5RPBSBjH^WsGoM38dJTrDj^KMbjJL1P2i*(+rd9POo@Ls^X9jv_PaVN@D zQJZJ(o8pQaZT{@I?VXt^cD8kfi>fitxv1+>QI7vD3F5gQ*2VuxtB0=h0}Fz9YL;fv zt)KI>j@>rRw*0-}~{fFATuM4Cl_V@By`o(SPd-gL?(ylBpm@PUq1i8=N~R{PAkH_@hUpSkKTcEsc%J&((_Z}D^XJi(6c z`r2>#IbXOp>*n?_v$hRM)a|IlPN4F0=Sf;GuEM+=9sIG_d=%*gc{sM#qA#M-Yy0@U z>7BlezCl5DS4j6?F5HQJ6$*3aiyh~|JN$`h9cyA+EB(nu{;PJAdZjk0%VT>Q+O<*{d!}h2XvCT+)7m6A(TOV_5+Tr)hZupIsbN*owPs&-&FtQ|OrEfa?A@TnS?%Q_I7Y=i#&**ByYiqh zEBL_d;8HDh;oD_2Wu<0^N-npeM~wNgR*_A$m{Cwda`1kM_WPhZ$RJe%{5w7o0~2j& z$fD{w)f}AauYDW!t|r4};h#Q9@cytg*Y%h-je_16s7$J~qn&#P-TG+yNZ}RVF2RJu zdG+Tdf2O#5FyYvysa=!5!wC2-6kz$^f}5;k$!@K5h2aY^LLo5MwB)H|m_`P3^EVUA z7il_nJxWZ6&?BoQcx2-%qU^Al#r8oI_&EY@W?8%QA#jl zxgVsG)9W6YkGyG7-w2d67wa>wZJqvYP_!_i*fpjg?pE*QwG>7H9E6Q7QH#?!Y*PTl zDgR@#f8L>TI+L=ApoGz~HfYV>NdJPxUVnCXL7i=vP`A;4e{2^Q@e24+S~%`STwa(IOx)-1MjlPAxTXocV zf0fpLU*Zpwrv=o1G3KL%X7>UVP_$KfH@EEp&IqeiGZ zu!|~@l2(ZG=UBWybZKB3Ro{vCsI`9AZ{T0qlBh|X(Y*!T?`IXa?phx_@Bp9C_B&j* zIu8C|IuQS7ptDCa7hz{C+c~oR0j2BH8a)Mne=rN{=M;Sphf#Y>=c~^J6sb z(2=vJp0t%kVS$4G_{lf9g=_!5lJ2ls6t(_Or}`tX-}(n-q-Y2Ph8s~^F@iKIz;2|z z?8B%VU+X!AbhM=_Gh?&Ec*L%CtdkJN5EO@iQ5Ijor2(a;i#6?eNbM}i@36nsDVM5EKjN+|H zoKVAENOfg3N3m+W(luWAf;GA)9=C5HO(I@t^F(GsPP}w#v&_&GV99ujwCs~nnx`S{ zCkpK2fg(K$w|McR`cTor5`C7wJ8_eiqlMz!gvyKS7O!v(CTFrfq)mLB<8eI%=R&a2vFRgxtF(Aa{Wx z_rTx!1t6l0Bd(HDFtL!U7`+ECR^C$oLCo~GSm@>(tx!H+yCIo0+pLdwKL9>y+d|tXRvm+Iyw0j@o4b*Vy%;?NO>yxDc6=+B!g1)&@@!lugXp!K zZ16n4q23mDkIF>g3!Q$5R@PUPGdQk5*|XV8XYrk#^;9n#+=9%hHG7km|4mx6FO9y> zntg}Y8?}fHMZ;IqLW=%{%tIuE&t6O+fZ`L*t&l8Q+tf9J9M#ai)9}#sYhSSQ|et2tk;-(4qbdb zp8e#5r&!_oh*$z`Lhe6W_r zN3oo-2cKzYL2P|zBhi=BNX>uG-P6^`6ypV`^A z)j_=4ru@X4`{*n4oGa<1OFLU9{;=S^&Y|B{lp6ZSb@rcY-xFQ!%k{?4plx~T&^-)$ zK~Lk3VFKulK?E22*tOe>U9Hj;xmdwNd+=@+xTfU>3v$UHQ=N5WH;~N^$DIB@(%u9< z%If<6pGXG65@%3?0YL|i8e9WnOVr2&L7st$#-%ojwy6t^ZT%W00V-4zCoJPQHnz5| z-*4&iZPnUV{aOTRYXZpX!cvjN6&0Uxv@9-&RP%p-?tPv~2xxu%{l)a*5@NE9bGrn7b8)yVha`fJS#9m|Yy7C!G$h?Qr07!yR% zwKvnRbUzLV$GE?53zvz5fx;UMs)x?d4@Tee)l>VK3&jh+LH22gl`Go7HOFTPe{rku zl4tM|oM&FbOS_~u+VlfuAUpql3HChxf{6?RbZ9nHhCT56Ts|0R?58U^!bW=}ZMjq6 z9ycL~m)h=F@^E`AvXM%v3n1HzKmLBeJ)Qu6iHg6N!k(6jS=+O z1^^Ufl{4Jo7Cid$@(XITa)y&w)C7?S8c#@6Y?&ocL52|?@Q)a8Iz#TqO>Xm<0`pXW z`E`7v;t!?>!cDV2x~p;}=GqeaYIzv7{A~^lC!&1c+u}1Ecfm4tDA$i(|9J#(Out@6ZXSBfE8%yq?C2wg+2ZwwN z0H>1X&Hv3gD9U^&vdJ8mGwt7)qaFBBsoEb;`&!jYn`R6NG>kI`mx`B1hp>%in@Z&Y ze#81TyMYzW^YzTXRIAkj&allA2-yBu+p&b?uZ(HO(*)ls{@d4O<~fAbsF_9;OtowA?8O&3+lm7mK>?^V9Wgq5=mORBkpB1&c8vH0|G~=SE_cTyF?u5O`Ga}>S_V@NW6$W19n966@&oR1 z2R4z9K20?bUnvYkr5~qN_kmhFQh*r^yB|0`I1*t~@=Pa;;m7pkGQ5no-f|)x#{!{V zuSGs~%9sA6kF%n(j`joDUe0iahKvb?!|lTR4Z>;=i?K0Pv!ya5pE_hpYsXsULY}5t zq71@6k)gpk`27y@obZxpD+`5DZr%a&K@;WtF9&u~m*}+VDeIl)7sxHk?W+#ySc@ujwl)GnE(sUT zfN&Q|AJDOmfp7da3(`NPvdn0?{j>6+;UuW%dI$eoyE8Hi>`JYt?Ph0`aeDjKZCNt; z57H^-Z_(#_PsfQRv#32=Hd5iD_xNfyrFndX-M~oPOON-N z$Q=jcul3&ehLt-))yuEsWMaD{BcR~J(4V+aW_Sl%uypWYC0>Ix$Mb*dd9-v19Fdb$ zcZWVqATj$U+_>ZdxQ6l>|?gN); zeF^q63hBbn=R)B4=a`?N9s0@J0;r*ui>X2#i&!jZqhamWDxVI1@VLMCd*m9sV2zfO zCi20RCjIbFNY{er-tMJGZTeQ5{+8l59h2CQ3i&3E%=_vB6!fjL-7brcdU{{pIESd7P)OwE9Nt+2;HauEp50Tky&c@sDYm zVP;H<-4%p86cH4d0amo7;>_s>j;+`vxqFWlkSz&pJ| zZ?hP``wC(FZc}U1(<2xKOJAYc_nUT%%@9`}11>kGZ)3z>W ze7D7NRp41Ec&7I>%(#@#s-ea`J_`ux;L+ZPs9R(|9J&Y!U8QFLjv95no@(@j(wb?$ zkPLP2AEW~pf13`VlICAim*gI|&w!t*)mlaAVTU0cCZDih4exxxKyR>ZaeK+`8Jtq& zSvVc3vW`0nMfsPYbi^m_#<@y0TKy+WXkITH_p2lwjhc$gNVvxXsE=(Y=oTH7!8ZbKyBLeZ!D;uH}I!bOtQetWsg&eWq&-m>x>o< zZ1zZK&79?X@^uk9 zy*c=^*4eW*vqxy5Y-sjj)aERj?)@_*axYy<82*%LGsTP{gb+p3ze5!TL{MIItM|_o z&%Jahp3#CT{cSijd%h}J)N!l*pDB`i=~5(nDcK{9Cy^DMs{XTC{gpX${} zi|GNJ>beLm(+kYuR^2%(e_uj68U`i4+@9^pl{idSrvR zoxuqu%+HY(4U9QelFuzVbP`E4Sd@r`D34pau2D^$tBoLTJnE2qP@81-d`VGVn zbcdrj13e9u)Fx-x@>YUDOdsS7-|Gxp%kxSuo*TZz$=iTX$)y2s;iJqVhQ!-eL;L9(6BQWdc3~Oniy7tqFfG=TU*Ul zV{Dxu?V^+_$ootMsz=)buk*Qq&#`26v~pfeoL1fVqnbpys4w$0)FKl1=Yza{gcjt4 zV&-4wEVw}ze%k#}{B_zly}m`doQZ;rLk0w6AUO!D z@8bhv=`hFYvv+rITkmR_IhS_0dAcE=U(ENZ{$TYdkP6*$0t;^M4jiU9C-wom7W@hxvRG{wtbYZw8^5eEQi3L@cZuU`h<7!%0;Fou5D zK9jC<%(Bw-Ckj^f+-7c%9^=WUJDHyNw@4e4r~P#VYMAmeM1ttZza~-HZm*~;STB1W zPi|V=K^L`mlJnaLMsC(XYfLt|eTTOfF#0C=`oOpLk>y&X68ZrewcoafUM0>iDR5jWz zzGBTHQb;clES`mcuFEZnG~$%+nR*I4MW|_rc&~`O1o3aM?0N0mFzbQS{7*sF+%VHa zwuocs7X0T(^{$&t;!YWOz@#@9868NWw*Lyn>CKVO{tx0~m;N&g9kJ@_FT;cvb;w@d zF_^mm3@YeQ4i&opuSDJ(78UzsAKa%^vpX(AiF<^64<9UCp#=>kB|7+JE<35dAf2CA zm5z4A5bN#bd;{ZoD{v#c)eov-^$f*V8vniWy;BQV&M14c!chtH4`HHpf6Jflco%viZf3v%$Tza!LGM@L zcs4C_b3GyfOWWd3=xP9I_Ilu0hbx6(*a{3duBQs4|74aVov5rG-l&C*npt}>vlUDs z%lF$%#hjJU;qx%EhrO?X%NFD)?2#+DOT2rIrPzEOc<%|-7PN|Fb-1KJ_*uhJnc`$_ zydtB7%_iYO@lBwR>8F)D`3=3MB&!ceI{Bfe3i38jNunSROu^20NMm1u;uj>|{GydR zu>92n%YX=PpnIQV*45cM$E|hMbq;F%@J%*e%{ekxVmR_?~y-T=7Rl(e5t3{i# z>Bn{J@Nm;%b#qnTLA&|H1k;iKdDZV`p5IOP+i{aL`7eGSweuI@bRzdJwoA+d7Dvy zlWp6SaiLRJ;L-g3-PpyP@RaeGH+V(mewhvtzP`JXlZ2u07c@zs%XSN0(8({_=lz{5Me4AAhI3I5hV$^;z<-Q(jZx1t(5d7Zds$83HRIdjePnIyxC&5W&xN zntvSrH-#E6X5LEtZ@_91jqoLqJ;gGJTdC*$Viz=Se#tMxsA|O1D9y4n|q9@UyJIB$_VfgEz8`y%C=&m z!D;2m{tDy%@=yDCx@1DScPj@FTKn#R7e(lnkWvN-#?%OR?LW2TZK)mKnq zl9B+DDvJ%@ML5C1k<^X($%ertt&H&CQl|r*kJ&2NIN1GVzD);z`xG=d93U-!-iNc9 zP2aWu#dD&PV)$QSSE3X&#hE{JBH7}1E!BDWjWV|gmM9!jL9Jb1$H>cJ-Clhe?XH3q zwh$Yui9AvWfV0^qyD=CTEVCxRiE=<=z`>dHsJ?7MBhv0gpw}^ttQ#|n4FT)UDswQZ z0by~t3H_o=!8pH5BX-;C(8~Y_nioaMnOwatgX>Ahs&(%rw&iuKP7Qr)bbVmYX1YFL z&lWMT?BOt(emd?0+0xemVpGlgdMlWeRwVlxTHOL`-+^g5a`Hn{nB3tqylWjdZMvi|%nP{=c6L2ZNKjTk6 zwjZIEMli~G`NFXP2n_wQV|WXW;w{^Yhm&}~hj{7{7>kbP*=VAO@5{zUA&Xx%PIXxB zsUbizo0IZ&QwM>1NIZSU2jA57%(`*89Ui__n?CJdEcqJg-F>2uhyTn&o#f})cdqZm zZ&~@!g7`0jIj*wybTzXZU6< zuI?y~s4@ADxq``eG&Q;jL?$z)?&fn%Qo##IA2Q>+bzTxXQ0#v;^@#x#kRBM(>+2ZpQX+ zI=Huq){Z4N@mZeA7vLwn!!*LY)O`NJy| z^!P)Wi)Sd){?m@ekD-N~XF%@l8Xc=8O%+abZwz>o!p;L?C;dR}Nl_S;#tnPxY+*Y+ z>Tvi1qWl1UFRHPcHILYz_NW*|qFMU#4|N}hONm>sFiFM6BoKZdFke-BN1LXXQ!x)< zXWdDk-xvdSj(nACyFRHC$Oc7t=qv{nCzHwGcku$y;T9F(_!g!c-6a{@e|!mZ{a05w zBJi^ss0;rf<68wW0aA7#o0kovXmt6o{oSjI{?1pn4xAfP^1J77^=t4k9uYx|t##Dtfn7{-VA&uoCwLz~F3r~p8pk>So<7vMe$xF8fMsWMNHMBMu|P2~MQzKd^~ zK~v~2=+dv9V*YKHuSa_u8s>ZNGyewRNqy5Ioi7v}gVpS#?hQN}G0#2jc#O$yjUSNy z2eA!++I>2Zp917Ci_dtr`s)fHYic}gd2kz_@|5r9KN;Yc^4=Zz9e>RaWX>^sh>X7` z2l~6QUobwX1~bQzVCd4F+tZ^*;+xFu!YsNE4(}SDX;*u+8E%@9A80r?HK`^QNLPQM z@hxB1I6Uoi7&bAf#`1|n;VRbFmyqJzlS}q{0=(#O$Ye0xbMJl9pD|`RaowN?p4t9n zetZzJ$w6xA=M=Vh{`x9kJQL)&!<;Atn~#pH4gD%=&g_G;EcBzxzqQ8T|~k9 zR<0;(+MCyKM5?-m`CeSUp6k|ZVbiGK6ki&`xZFYs_gQ*l0t}-#`$nRo>T)LI zEkj9d_@i_Ocr7eFq?^}5YwIF<$Gj?fKXH#~Kr{%*Yf=;fVu5ZwdS{;+|D* z_;36KpBio-XASZLxwK#k{I$ZQ$6&6OKmUMq>MC*DZOZgN`JBDlrbOI7km4S5R-W`* zUj43o%FV)Z;uB&>Ej<*T3jMFHCeBgQfe)6xu)+KERjT;eiA5rWKx0v2(N2Di2Pmgf z`iEw}%9~c_P4MnfWef{zE1yJnCFz@BDXgdr%OH|8ESC7zqQ~B5h_835=m$KR)gA0e zz!4D+XvD{ab=18cYldj17(MKe+-kzOtUQfT3mK0a%4MU5#71m|ztDQujK5OG?R%&u zfikLfsk?=fOWlr^QbX$88pbc&TE4QOSE9WKm#}R#1>}zX!HwY3YA~>`Jmybcw+xaH zzb(it&oLFn2b=+^+4z7l^e1MXHouS67jKA5%MwrfsC+ty%1@l~k)hdr$c(O#p7wH9 z&gK*OqAQy~dpE0g{Y)xo(C2#W{EGec1t$CxRPc3Px zXp7e~QaxcutFpt~tA8zDK~iN?R?rk23-PSl6k1?Q`tr9#yW42n!A(NCKPPojghdu> z4g%OpY(sAOL#pX+liGPyu207c$tV0HsZV$w<{i;F=cJxchg+4bhl3tq6kI+ao$#e@ zj>OZqHvt4uw14=TAvi_OTR>OzUV3iBWJfXvChoyIH0$Yq%14>&GwHc zxA@hYIO0TFyu&0BOE=W=C&2R0|C-%O7QrZ%sw{~4?riM5Sp2F|R~J{MepnYvJiGJ! z^x2VCFD~lz6Jp7i&=U5DH7`>D-O84Hwp`{0+j~?~dcXj4QQcuwzzw$fC0_P;-nPob zJGtQA{r9{AaEFa++0bx(Wz&zt!G=Kuqqbd%VFMxZs(O<-4f5h0naht&ZDXlA$$^#2 zD+lGp743VU`^04$JQ%4E>N{wdfsZpkM%$3$nQc&RJbiXSwr3S#;EyIC>#BxfRpmb} zn0ka@IHb`XANu2at>fk$W)||+Ec65`Zd1J08hHptun%V^#!^!e$A%!VgbxN6{-<99 z7)6w=aZ)X&n`VzOPD=*%g?RaAH$7 z(9Z;**UH4({)NeofT6&QZZ3TCHba;a<*8!kPPOhFisitY>wSiE}Mj+z`I>WzPb>;LfZHOpaJ7xB&Y2Pt=zZ?k@tZ|<5Crr5a zbiWvy5jH?)w7jAXP`?oz7^yM319Vts`~Htova@~Ps0|MNTihni8Sw)#0osm5+b{7ZZYaw8CGxgP+hlusJj7{|WT{DsB;sTPE39{%&Ueog$J^$aY0pRnoI zv_*}j`}s9J%^2{Cb8xKSOGmQ5`ypoEjFkS`BmEwd(kKZujZ&+A)4>;CmSV*QA9fft zo6MknvZvdi8RniNicXv~ULr#lL$<2%TUNjBLp^wZsPiq<|C#>I0`4v(0+bJPoXNdr zS=aCby8qFzFb(FsT7&9fGx_kJC8L>m>>LVjxk5UaEoR6Q71Pg`)PAy^r7J3#{i;RU z`pwu1wdpMS76p{Mk9#;PUv{F9cipfq$b*qF^Sv0e>0o-}mtgS8Pred^3x#U;FGazC zefrbyU(A>AJ?|?(9Zzx1cCSR|Kt0hb#Qna_@Lj(qcL9}zuoxcY_Op!? z-%TS0D*FIQg0D98RGa&+G6Ukm9i$eK3V)jE6&>QPvx)Eg+$(C~pX{YG-`m_jlf@k_ z7{^%<{(K=YM%2#fz(_1-Ej6sZy|lIoKMwZkZ`oxywBT%3x{0iGdFQd}^*-?Apuauk_?ye=O4 z%Zu?I6N{TFUW!8P>R+hkLp99cR4YPmX;Z}_B{lXQ(Z)i{`NMCxm;FNWyDuMD>5%N6 zXh<2mTE~pW)fbz625iK#R+@;zW*#$5;j*%dV7qSKXuB`a*Uo)Gmk=7TG(UvK*N#== zgXzQZrQjwiu9+xFj0=;tW^XpQ+XNu3l}&q_8V}QmtmV}gxw3u7=dBty&)&46#5YLH zA>0-kr0=dRw3DAa;WraO{`AV~Vz@A?mOVr?i<%L^?#;YuvkRjG@MW9cD>0dJji6`x6pZGEv zyS+*o|AWA9WbDij1>P7ccKZRI`|kUI8d|_vYOxn$fEf02SE-qtx5_|n*^BtY*3<3$ zt#?P9V$$DzkaTI9?fhKqrPsOrZF>2$q=$3q50K9EkGQ*;vF`OJ@@JlH=#ZnCyGIJB z>AyDY?Bs7Y!zNYIeu5yk zFQ}i)UU78jsc4xhE^~jQfbg{1e^U9}b;x+L1b zuUo$oE3~##KEmFs&In9Bs#!%*NyDG9oeKA*?p=(p`EQj|_6_cGcsoi73o zxo6eF>R?{KXh+sNnjOS2w@hVGtKSAH*%jFJYo?Z+X{2P2azi%5vz-};|E%;&O{-|S zB_TSY1%Z~84c_^bt;d;4FVlh}HMe`B3LIxD)c7s7>0@*0eUu(Npu+ZsJ~}3IbYf?o z_Pg^~%ryVePY!XX+d8()r44ps=;yT#weuDIGk@J*GMw(?JgJJKD8uH=o@HQ@Mnsc+ zfqZVr)E^vfajcXI6!&P&ubKNkM-xe}TE)2fX|(JBXM5(Y0(FkQR4YfV$#J;e?LZs; zM0k!4ld(2)n6}F4;3Fm8G*Y^I1c248A?eY)})C_f9*6?TzY1`(KMl;%@(|4VZ{aVMLVlDd`~1S3}30pQae#o6#bl3z7I|C z>kQvu-Om3Jh-hjMzj*f6TMwmB^h+&_4gDo7SyZ0bt~&(-VP zaCcuK(f71bhPLTo*nJ$)Ui%rVOk`t|ocWMrQ_PtGIzbMv6H2GcwbC=y z69|rYbvh#&&l?+#4_|?=W^B*qs^k)!Z+gVq_l~I=wvs#9;+%4k()W2GjEdRqNyY?- zXch?8x`T~wO^c_8Z_Wys0Z_vXmKw*KOIS3*DFp?kNu$y5g!S?{KizLh zRXSE2Yi{eoIB;!Iyu3XginqscKW)(!(uObUK88|Vym)k6P6cmrreLLezUSjW)1Dw4 zQIA>n$Y)xWk8i07vEq%}f1S~7+`xz(w_&~Z8#ncvMST{c*!MGCM^J4QtMW+Z`~$|) zj^AJDpGV(R0R$p#vwnfw#sTgxWwxOjzT2^a9VUJpW`Eas0a+n+L-Jq}@>c>^^#YFK zlkI~sF#j5kwiHJ9!Y+s7%?K2T+DlQ^6?m6J<3C~sC4D(aybKQrosSgqr|LZTIxPic zvE4rgBd{e~ce?BKH**T;-;Y>r|K@elCnK%-+ogXE*I1B=^tjT!!y}Fe#(FNJ#D3?0 z@W=;mHD;~gmkZzwy4uhEw#h@a+5YYy{paOPW_sgsCSjSIriYy56wh8Y{V)_4sd;5o zV%GO{q>WfbIqYWQl; zzJodRjurz>;jZE6Hm=@k=yut*>-G@7Hp>2Z^R%mA)6Xd}-S57gz5Dxs;h`i}#7xDf zr|8%dvFJ&Y!u<^Tu7AL(YfY4;SlX5g*pc~plwk5C#7W${^VxTV-Y~ixLf}y%)S9}G ztHp0DDc{)e9v?z?w`YpX>|h~smu>fljH8D857|M+Zw@Va^a;)QT$h1_u0?S-GYoKx zABXdA8LUwxV3Hv)h`F-B8@OyK)Keh7zt-*Pr~5oX6Tr?BctN6K?+82Tntf)ea$adc z-_wV_H8Z(8#q9_Fb3U|#eHznj(F`FdUR(A^{yQQ^8GUn01^r4?pO*D^5MZN*8VH4-`1}Xx`nQ9gZ6i6S1(>kZox86bj*DkIm;L^`8BP zAymqrqw)M!(q2RuL4g>0ske6^xp6u6hslz=VBKCwS- z>P_^MJ0IrN-{93hzl8d?q7cc|f2D#Ch)Uew-Ic3<@3#L`f2Bv88m~#Jw5NcE77w)@ z634TiHo2BQe9~{}Ots|RO(S0he`wB60Lg0uDT?87-}Y9lGP}qtIy_FQTby;=gh6!J z%b+|MM~Yu>ff;G30nUrvbF-74T#S_*M~HRqeV$uDnfsy2H-w_HWHt%F~eT{uU#1g&+8V8yjf8p7^9NuG`OToD4r!P2Wi19yHz<0QYbBh6H>= zX=`!m`_>$GQ|ZF@emla3d}4pHguy0XsesMht5)r#Zdbcb>V8K*M&>oTRJ=>@cV9(3 z&+<*oD+Et>6BH^*i$Y375-gRNS>~i}Glf(4t2@}=RU>sht*`OqZKi?b6H0_7w7=B@ z$ex^yai^DHG8MAxo@08R!tM zx)okWJ3&_&N0U*}$jGvSEbg|CbLnLSH(mTGOQ)B9kJ6WPrq57%m-0VV`fobZ+q$LS zp!C~1(+hsEfB6fPepP3BwbF|_;X6&~V>{FDReGc|J*4zwI@90imcHXQ(huoOFD1rl z*YYnaecMO5{s(@vfBIjPzN9m~zFYaZO8-q~`oeDMHz@tK&h%>4-=%*SDE%rweRzSKKLQsOz2#v2&ce3i4BjLZkb<8FJ$TKi%$BghqO|y^WX`wMKr8` z9EM&UO7u0n!)lIYvldu#kZbL@t$-vwO4h1rs@Q|v!esye!u{$ey7%2II}<6L6&iIT zA>X~)QeLDVCg`m;NDb$%lWQbDx%-+_np=Q6m1Uj5QStim6p!OatQt3`&)3pC`i&~~ zgx7Kx$Wrs_gn1Y)r+8Xxd5+VoIxeBAH{bE1k;SSXIIR~>cjCK+xEz`j1PSrf{8lhm zHT&&pBV*;Sa5Oz0n($Uta!1whcTif!lb`O4haUg4@>GWIem0hTJwE)c@hu<3L*w^l z|F88Q0meZau*VGklOJ(ly)a(>W@yfQkS%suHXe7wlZ7KkSB!$62PD7c5NTXmNz@_` z<+A#cx_EL!NEcvp%KHH3J23qcDjnC!g*1P~9HuNKmUGo4zW+>tvgbQCC+Q*$Y!y^do|Ji9= zF3PNRANNMOwsWNaf2l>)bhrB$zC?X$22%0@7!JF=3BcH8LE4hjwePnucrUsiw#_<^ z9)V`SFzM#^7nA=vOOCS&3h|~VBLhcR?%{k9(pGSRImAZYC zNRI+Lq*!XyE?rQ+mv9Fx=`rhx7Ek{n0IFhpAp2)y?QRd;6wj%`D^Ky0 zc$9-)K69gd+4LS&$v5K3AL%|=Z4aU58gnyj951?uOn?4XGM`^r#A}VSS*&B3h+Lf& z`4Q36b1I)8_2X%l%R^K!eGdyMv2R9%L5+c!4gERXTaOPbqHGtV}0JCa$KMsT7y zYS~rM-RtE&e{>6T+&1SsoZ@-*vM?=_sESSImjNQAjfBdmMT1;YxnK_*##8h;PCPLU zTxKzRKws+3HGx_WMw2rl^H&Lr)RH{J^WLi!5qtg7_1a&UJ9lIwnc84%B%zkys6{3s zf{y121sFRG7}Tct$?b3A;YUbQ9}~qM3%u84GKzar-O8C_Gk2I9-aA=J=i>2|k+l!T zDg5?I`wG31teThE>18B-w|*BjCH1^cg?> z0*ugXSnvP^BO?le@3H^DR>=ZBpu|nC>$c0X%rK#VK%E^SI|tOzAFS^Ry9T%{ zc&qWRiMg20KMF217^m+~H5^lC>IiOows2xwegbVhPs^nVq z{L^Ap9K5V--X_MT^;MT&pGdMIaa854jHm9k9I*#iF{^sN_QNkoYg6{u z=no7TT#nV&K2`J7JxYX?zYc|Ycw-nw4jk+Z#~e#sxlG~2^pHbi!#M@FHlAEJj$2ny zw9b*sw8XT>Os9ML(RECxk2amo@jnl~P+~r1CZ^FNRTNhf5yD*(}tqWg9di&jdX*Lbv<32ITp(C7rU#d0@g znD3TcQ+Fw&gZ;ukf6=_JiIP(lqj8-{OWtRGO#X#Rb8BReg%uWf_03a#tYYYBj3KjS z-C9+Oun$u~i~U)2)>>|aQ#Db_XOm{uxi|U;m@_AUM6aikKQg)QTpm&Ki=ILf9(0B>NmPRYj3Z!+R z)jhtadSF)xchR+!U>UjBR5dp0B<0sWv0CiXuE*}QKFaT9VL1{!PI_!~3ig-p@rbIh zsw+U;_H=4I^)q2W_sAbp1;RNA&_uCNB0xXSPu;y`t1G*VRy}Y;4e>E?gPt}&gvM=dY>o07r zp_bi7G>dCJHZaLI2y&%_*A4g;A^t7i&Hhh{QWO$iH#^(iR-k^W5;|KG_sc_qY<7ws zJq_pGakmeR47l)ft#^qdjTdR_<#D;H(mv4I-zymQZLn55k(s=5) zl}C}D_;*J`4gS}-#E*-oPPv9M@l?h2{8Z(A9?N^as{H+_N3ku6muF(33D4t##JxW2 z;;G*mI${TvJ+A8uCxALr`gVEg#DhPQp_U_{0Dpc$({p<9K5pI>CBzfG1UDRa#lCJU z99YT6qOK*~6BwM-U88l_p#8lH6`FyL=2+(+%sc%%nqYb{(Xjs2#(M8;W$)8$@_U$P z!iYFPZ!J6aG5=ME+HqFNH{HVDvrod(_W2{et5KQkFqPmzhns}9$pnouzU0+77TRu6 zoY{)DK*@y0Y0VzPVGrC|a^H%x;ikPrROt5DJa;6od59&vYpy~V3e%-6+T1?f*m-A@>rjQP1n^`GO zQhU8QNYAWwba*=&1?Te-r;h z;m^=?r4xFp67TnRXbgL$!H;{ENe4IdChDXvs0%&y?UDF+u6BA{fCzskL$mLtk4mO`99L6Ckv|x9wuB}lN;`SP z=*zNZp?cqEWa$PcHDC+Uc2aj&g}umY=}~>0^a8WpN6h8`+B2Y-TLQkf=k=Wh>}#WS z@Wh=?#ZEp?$7L{|>`j4wd4Zh;7CM-wXhc(YUM=Fhq3Yh0A)u&d! zqg{&?B9}D@)Yev`5R{HB6};v!cv*XD zcy79vVmIOY(ggegsaEIogtBsi1T)WZ((?*bd3s?PKkgCQaEi!?ct%DPcUC;8O3hPc zaZW#TGJZgDEZM4e@!7f&ZH9g_AJa%I)g)MB!`nG7iek1cBjt!$*R*^xwV}T_gPAT| zR!Tq86&GGGB0z*IxXt8;4JUu{N*Lq~NPmWjYlu)s>wW}27vH7Np2Q+GHMjf;3>lB8 z*j>o%Rk0a{_xr#bii;)J0ki=wJz!8*_~lb}w&6t!4ICFsENg#*6RTc0_`c1i5vB+C zGbZheu)FNTpexG-KgqJ5_-ZynxUeev!hBJS4surL+id+O6g5pYVo5L{@f&8Dz9f`QR2UNNu}z3t*(k+ zV6)8mK3VWr47lUT;>~X=wh<`aZ<3yFDUoGS+|ejOBFwPqxh$6SaJnRhU?IA$H+Qwj zI0v57g?$BTy5im{f8c&YlqVqGH<=MyaHkysGq=pZz0GGczb5}wNve)zqRdP{x0mtw zKz*utF*=sc4;zxwkeq2CTR4zTSojzBpqb+WZ;0RtIE*BZ3%P2-=%s4i&(5z-NT|Lq=mRS(t&!(S0pusMKC0jQv1cy_`i;G#Q?L1Ke@eh)3>_yK$C_>|V!pG@m= zBIf^LC8s&tyxP=}N$oMVf67fGIY>;pdl4Pbwm=G@^FAkCJ_ud!N7mBL)#+W)Wz{X4 z;5NAhz1xFb-*3vXuJ;|`51K(Tr9$m^Zok-=BWJe@gF4|ldj#1-PhDJV0-H`jf}VXI z94a-nru;Dly$a3#rWjW0VostO`Kwjjns?av8E?&J@#vzG&<(5YJM7}oAr2l&><|}A zjrxLYCR(Q#X%>ymz$#V*>5IAHA@Qz%kb6nxp1pfs-dP#JB6BXM`P*2eKQ*g}!ek93 zOqN+iqLDMR1F`3ZX8(i+rX*(8qF)Tn{;p|lGIXOsmktPBM>_b{v6|Xz+^x6MSLmY- z(UC=}OCG|N60gV0_9WSO{S#4t+`5!k1o?+jTz4(Ai>lqT*~*>SGD)2WCKP9nknm{^ zS?pILLfsdt?&qjmG*Dyr58@xV+2P27lETUbQTePK7ZtH!(}q~1bNY1AXlTQFs*^I> z1K`7D{nlHLaw>x z<~1R=t3|5Qo%sp`nGSyAIv68832zBvKMF!Y0pU z4oXS>0*B$KY}tqK$stsRe&9%mMgZ2j>o7r(=)_43l4$wQK7A!U;y(VFNng`QI$<2V z^sS_a%+baXpPKYtV!~a{KY8WL-2OH_K9+Q7#w-7TmtN}bf(yAnVm)=|S}+%!L7$H$ zr#tOOrq7H1j}PC}him!JO)7C8|N8+`m-T0IH-^`3{-U}?s~ZhdDafh;PZ$NPwvNa8 zDJ!D2oRW)Pg=876Qzi<`n6W&14bpP7OkyWj>zR*Ha#Sk^ly$XeXHEew29`gZO@BT9 z%4kdq6CA!VX7Ee2PKE31>m&qkw{`*z}n;{n%XjN4#|JeAr}O-DwQC zdzS?=b|*EdcV77)>^IWxn#Em5xi#~^S1@PB+Twpb)pg<@WF!7FksC)jiJ1j~##8vg zz4CY`1-`(wIh8WZy*ml%o)xM!$`#YT06|?7{dm^ zU8(!df-YK-V&|lZ;72%xQ&)!;#1!_9)0%X<%)NY<)?(IHd7}6rjg$>>V9FJ=_rHar$A6uea)L+NNx;g}@c?gRNkSJAyrJKh;u$pMPVo z>@@SNoo%&~{4TR-u#-gFOmv*0$M3V=LpY``rjq@)T;7f=l(?G&83dfAkO!Xw7hZ?n{N2-2Aw+JAI(c1CO{>t#mKn;*rL;J<L!3L{ zc$8kg8#z>WB?q+A6F5K-#lGQ_M97lFRzndlW$7g2I~bDa!1;_F$}A|%zlU@R!~XO= zUoq@m>@Q3+tXEU**elBU(V|ha{q8pQ+x@YR?OD(0M{=XTXZOKJ|6oQ=4G@5K4(sb$o_LJ`wNPUHpw3cNG>(qG2(RikVHj6ubYthF>|x;({8?A zyOx^lH?2TAwUl79W$u&MkIeU~BnB@ou2pUx!m%WgkW`9?NGv%Mbpg@{^AyNtMx5lu zrB0HFy;NB}VwGEk8CKWa{TW0gDxLsXwjQVr4F;-5Y)x)s5wmh^^+xeXe_}-nS0mwMVMw2ru8x*Pvyc_r^>JI^%0-gXbjJn zE6*jI`S(0qDmzw=OBx5PgAJxXPour!isOVaUZRkoyqP$ z-$ftO{QDV;6(nBrjGQVblEQB8A5&3y2pA#FGjK3p4;9YalK>*8E`gwtx>% zssLZAlAq{i$AmFB+rI+duHQ%c(0BQ^&5T>uO;uziqES?Xy+*}aINCCU~77#cQyj}Y?VH`WEX>8#&3E%zTf z(w14WS;)TQZDO^_3+h9%z2tC z*k}40-+yy%iwNn1*Z*1({G&5X)`IS55`!~L>muZ{1qgbfThOp#v&L09W zWl=WimYoK;e!VF>uxUn^`#mu9l-CqD44@9yZz?*halKNeJ*O2KX3;kQe@}L@ zG&e}p$W9)X8JLq-yKT=r`F$vS%ah;BR12ho7T5NFo$db>wsucyHBmadNv#q0v`6ja z05XI@a1{ktQqzVJNuYN3&)Yre1l?;+SPf@;gM~7&7;J4{LLwU9W>rz z(fIoGqQ)(Hnf6a@+3*u>%^V5Ec&Ic3=Zh%cM?^W|r(Z3iu)oU5r^^}6|92Us)V)~T zk(m+snvB7mK|J3~x;H*$(*67$l`mZOiCG-d{ItSM|EgEc>zg0Zo>|rADpiZa?^SZM zX0t`0`D-QG-)bJ_#Q!sV@qa+mt>FR@)pUpoiI2$sW+(7ZeV_KifnwjMncp#Kx{%f* zf7*|;I0CaK@cgv$*e=^kvnI)D#ywwRm%&g0P?Yy$=coBLjgH<$d=M905;O+d? z*o?dw$tOMZYF-zij}AOTxK;0p^gm4APsGxtwM`Wx$QWptCiGZdJX{sIGv8AGzaCvF zG;?We#hm%Hq<>6-k9OREd&>HTP?bErZ=288%q035XRalSULZAdHm{a`+!r_7B`lt1-K$G7|v%I+%U4vRq zh`Eq-x8z;Q8(GG^j7GEfXv4M;kHhOp#t_sL}p znJ0P!09;a1w$3aiH|ox>q*RNtqjEa5_60C{mnPcV6FYo@Rs}dfm{pQ^_nXDjrqw*%s*GE z5IB*N=uc)Ez68qM3pJ)JQODTo&0p#FW!-;O%}Ax~r6F(+W4~pTi-T(X{g(S*5Bqbi z#9N8&_&(Sgnuyua1;Y3u~x_+*)FVSjyOlj5X zzF~T}@eRFB+oF)Gv0^sOtIUZlW}&cUvnP&gE(6DlXS3&A#s1MekF_#YbsgB zdM#*}6I-0}yV^*b&JFZ;t<(d)NOwt=o!(FS^YXido#_jCcta0|^5E*>_h$dV8@jK+ z^hbF3l!s}*Hb;a9_V9PhlP}GU-eZ68NAJ9x9A(F^jgsE{wEW%3pDmCXQ$IRls|lp< zwx0QKL&~EuZiQswY|o6r0P^Cbw3@JbDsEkA&t8lS(D)4z0t+5)01Jz$-=7+*tJp%% z?!`=ISl|XaCQBaAHb#N=5m@O%kB`(zgjS9sG!8PAa|4i5PKn0ZPI`i;YQ%z*J};+s z^o4MD#qal9;))NlF8Ex^_J3Aq{{h6X2X;JW8ui%4;4OI7FqsKEc%Im1nUH0sZ|~&O z5r&ywQBn-w$rq6@2_$e+5nScIthh=;Pewn2kdzL7d@6%;98GF|EWX4aA0rRDefNVM z{rpz|PbVz=-|f*kexU_mw8M|zfH!CF(A-lfo2P?hSsd#Wxv_Cxh!uYC71gf=@D|Gqt7}hpT&> zxl%5rgV!pp*mmG?fqGKm%?89|;cpD&g$eVM>p+7^O$Sdl9bkVjSrzv(6-SHR!V8QM zlsLA2`r@qyJF^VLh2!}VcCOcJs_=aCldF7;NhOXdjkt$UG4_>5VU5e9#d(?E@?c;V zobENY+P|uTlL~J!1(SupH}w_HH9xs(XPDGdTKX zd%9jzg#*k_t}bHglbQ}T^6NfCUDCh{idkoqGI>z-*n|Mn)Jn)8xFLk z+4;E~`ttbeXn;5Z$;C-mkHNdMreqJ95*gq4=$#kl@;mLvN33eio+IwfqOs8j%P%y|o{v6C zQPV7tp~S+D&gldzox{1E}$47%mR&g#9*+y?YE1Q2X-*pvq7Wh;P8l? zstM$|noWCrhq;eI~#T-qv%f@B{rM3;$)`Ubb(W_`wAsU9>{)bNiT@ z|H!jDM=U^^8GApQM84Tu8$U9^xKf1=+2TolTC=}#@B1G%O_zMhGHc;~uoM0=0`py< z3NXqIvs&lWw^2G3oyo^VfrzvjA3A^3;vdOQG9VR`;(kaNyoL5G;?Nc2v(-D{OAgH(@MgzV+Pq173<)*f!0Q& zd>qZ(OtluPrM|SJDLy)-*qwa5Sv-_$tC-1gWGRVG(x9}4ql-WvJ zh@QpnKKceXKkicy7NMK>g%1Ru1*%v!c>*Pb?l#7CV$tDIpg-F`2VrPn|CbIf{U ze_m|MuiirWp(@`;Q|O9roY> zD~KGVBN-)9W+Z3V!f#kdlI9NZ<~OZlB0Cs4gc>JB z9Zh_iQl5#|IL=pdQu<|tQSr_hY-i1gGElYR_Xu*7caQLJJ;TGblX{|wHX&{}Z?(Pa z7{^G~2k(@26F#4Lo6Y)UFMt1H8VlIdDx@jnaF4@4t99y0HE}Vgu~euF$$Ld`a_jaw_6vW+w3lFE^|Q0=)aSS@1JLxe=r^EfhS(6B zo-Wf{LqF{D;egwE8zJcXw%V5-3GJZdsAUHZFJj8PKBmplPA$ZsR4(oAkit4h)#wdH8Rp4w23*X1oo7vdB4> z@3@y==?SR)Roxx`RCT!1ae&59PU`V{HTp-I7XLMkEY~SZVp$D6Pb^`p^a8up(4A6o zN<0FKBA?Wmgk~)0B3FO>VZ+&RqH2H}w|9meop;30 znH)sOT;YLZYNdYdaKfDxch(v&UlB@NCuLr9heqJ0N6*krQ*1x(7xOp6L zv!_mC$@Pe`#8irxFA23oMOprFFYVt4vmJzOA-2U+HMI%^Kc8kYFvb9(;Nbm~K=+Su^5 zvE){cn#I!9_-$|DQuZEB`)6a~!&VbZ=rHbzigm2v@O+Dbm{X{YeMYR$98PKJZ`g^q zG{aG1#5am3x4J(x_Fe<3Z8!&*2UO-_a^>NaM7s`jiKk?PF@giXrZXsa5N0NTyHTj+Y92H* zsyXz1KZnoGPYqeVZ0v9Mys1C$#nTnz`8X*xZbgB(fy0L<&4*d~fUUT7Qo3JMy_pe9 z?2A?n+FCX2)v95yRHd)vs5G9#oCG{iXTMN_r_U&-sIf2`Q*?Lu6e*yV1}-L-0tVEh z?_}m6oiqVG@fltTrO#y25j9|S>9VnV_x!smeMw24o>s#}iE*3w6bRa?hP77>TTxa1 zeCW1&Dd*$As(f$gw%hoifDRnu;UwC;D@snN8vc3J@V)V5Cbs9*So^!gll`1{vY$gQ zr*h80-F~FdY!+O57Z;#!EQqK2ZPYn|nyT_8Q%~kV_d4P~loQ2nQZj#?5m_>d%qt%# zEWonr_~YX?Vm5W__2-BBGlf5fX>k5u@0aq&KOz=mfoOm4SYQ6LA;YG|nLaN=Ht@7i zW%C=N8-UHDe3>O2GqsxNs8-fNIigK!Hd$iIAjx;QSuB^9U%kl_Eai|uG!Q5NKly7p zVjL^qaO-=Sdb;7Zlg|A@{B;-P3O&k`?ys0nOR;4Bnz-&6g+kkSS3^za*RYcP=`dEl zmYbb4kjZvBQRwwA#<{5ouE!kZU{Qd3v}xJ5PE74@YT57a&N$6>ku~EIq$QU3+kPxO z8~OFf9BBP{>b@WvNlsCChq)IK5z+8uNeW?cBXi!(xbh9lG~n0f?}@tpia+nP{CN%2 z%Pf-3@0-QiW58m8^VMraKCwcdU+Yrqe*DK-l4tnr$#k##(iqdIF1Cnna5XN}nfF2r zsi6H|17pc83NO$xCIA-r%c&}^)q1Z`q+4qYsO4XTTK-0TRh$K3g);#RB4W%(iy?wW zmhc9qHcw70eY-hpgs(cU(VQ@92g;yZY#W?&wHk!=mIzBzcr?^CSOS-hdhR({-P7iP z0f5jN5Vvr~7b0tg$f*1A2n|t7NfU7CGegB^?T;Q{s8p=ZJHK9LPUOWod@a~Jf&Yg} z`m(YGPobTy-%GSBq+lu3yxnk4`pGumN`?aT{Qn4O{Gfok9~0S7#8IYhM${8Akj?CV_yMfQhn3M`B&9@0!K@vb zp?aeTbS99F?F7lp3r61Y$L(OCA)1An-?igsK|9k*_U=zlRF6D5n_+>0&PHstMAmBf zKqvC5?dS68790>O@sI+UZve5!U-x1Cv?H@C_w+7L-8qFj^3DVKgYJL-lE5k+ld$@S zTNocteh#-#^&;NA3BS2%q1`e7UeWgJrI=XHPMAQ22LIZez<{TYa=hq-y``5=n0T&c z-|l`k37)dmm?sFd%%QVb73-4y#z&Pkz!| zhDX3R&RsbxR?uFDj_=z8(lL8&i5f!O)FLt;-PU zzm=8Nk$LRnd$ugQ>hV3>;^~uP=ci`5VNSXAoFW(pym)@Z$mB>{~K-skhmP-gb1)(a8bu1-<7MPfS4VWn35K6y{q#jC~&&ffA zl2^2`<<_LO>_!zAAJgXGQ}b(YNmU%GT1`!j5-2%K*OJaBgNM^484m5I`n|Yp$*w(n zkv52EVCvXO7KI-{+=>rdsspS!&CH8F%`+F%`Q=XfZc}+{$3`!K>7W(`hBNyGN%*Rb z&~t$Zu_4BPYT{`TT&G-2SHx!Z&vE)U=PnI@=;`faruH)Vvxmo!EZhH8gnj_fOpv{e zPWjT%oQDu`bcVH`$!;RiWpT}yFRy`ntGy<5+1Q8oyp6y*g&onmp@htfw*J1##!?gs zpvZ3j*NL_PTNcu^o}BUYcac9I-h~8sqL)tetZ`KLfK5LumwqDY?s35Dl}8i=^2yiH z{$Xmrk15|`=Meh?%DWpOX?K^+nYoOdVRCx#oxy6+o;gv{Cd=Ii+P3J}ezr)_pFpjU zm}%#;``GXNrS$haNdn-+{%2@rKk;YAvTd0?FFV6_GX;IBjEBatPxHsp<8|HyIJ#EU zz5o2EO1|V1y!dClJR6#Gr)XC;nyGq7?)Ij=6|2QqX1~mHM1#Huc(=hP%sW9PjD%7o zf!cKC-7(r;B|jtHq1KaXNy;@-d!ck?#`j^yoakjmied{IMgIlqfZr{(V9ij*BX}~Z zLrtL2=~(IB+-5R7+J_8=K9VK_a+WP`lgEWghD~$+(MzuJ#t%rTzjvFrm4qL&VMqK}!RyPq($Zhs(kAEhf)cXkfkeb4g21J`}QR`wx=4RhFS3h|Y^bg^9b zRGa?#5YlD%AbqiyK2NaUsm79O?00G>H>^$4;5tlySGh_p48!lGmSTOF?$u#ZPlOh+tM8+Z`e=s&8K`m*^8Imzc8bz zdg~IZ9!ehVKlUxNfU1mpKJ$PK{~u@P0v}a%?f)4_U_jyw5+n%dpizTbO%ydzQzsDg z3?vxTD!y72MQp7`NJ13Fzyx6!$BtI5*8cmq@7CU4U#)_VHUY{@t2}xUi`NHQJ>yu* zqcuEQ^Z)+#J|{1*xA&h9%$zyy&_b=A1C54)`qMf<@YsgyxwC+W@E~9^Rywa`@Pf3X?~a?zwvj73NETX_$wwX zO=-?psKcv=7>$;jW3Oe^y7C=TY<*SUqpyMd7|1FerKZPxj8V!*u zTx5I)R`H675_Hv4hSv%?u*zmVW+++nRd%z? zODpyH%l&?uho7XoP3kqBFpYP%sUN)2{Gjd%rxWTE0MR<>q();)c-vz>V1xOC#5=lV zg>81N4k-o;WIM|4oIPP6E`Ei0KwR2dX`npi8ChV^*u z(WBt!QZq(tf@=-_aT{C{wyQ;!K^fIzsja@dA$Q(yD45QlGlj_yGc0#a8!xDa_>!Y6 zGixg)joneeeZoug`11jf&~192kNZ`N?W4yJtBXq!PtFHSM81&R;TG7I+MB6O42bpF ztFFX-+H$W4t|U#QZRzJ+FCF?4UmBv8PPDZgb1^v$vL4BG( z@mM-#?L_^RAeepYnP8WRGVEfjz@1SS({4?dLZrmq>>aRv~C=wEI*SXH*DyCF|$NZ1O? zB8b%~W#QCRbz5^)D@KhhNe^%!Tkg(TqAG7* zQ{KFKONPmTS+eHOZfSm zo^)%T(s}2UZ8!Y=$R6|UC}PH)#ZmXqH+cHxY>tJ&lGfAMR_)Wz{3qt`F`j$Sn%z!( z*y|*-x>S^X;9%!7yFNs0Ky7b*sQ)6$f-a36um@rF;Cemv%60!++H%awBE9m@m^NRp zZ1|6-pARP<@#rfi`eG@?@8Dn1m#4_@p;Vrn9*;h`$rPXA5u1Vks2=dI6R1ku8)pg; zJs$_d@;U!gsC=x2B0o4G#BNo{T|G1>;15ZE*xZa=p(p*FhdaUD^yW@9A(j~3(u2E# ze0bf#eOWt9efbxJf{yq&wj4bO#hv>d@!+dj#w=2o`|J0XaN>s|7K`36G;cW`BNl_w zphbzPhK^>1RNp3T3`;QKh6iSdRW%?((9+ytQ`Y8jjEvyw7;qB%(b0+yqw#bh-gy@@ zNOZMdM08dG{r78$$ft<@Y=?}>cdM$CHriB|ouFSNQkNmOjBj7_x;qzkDNh#vm}(ym z(1Y&AqwMvt0Jx7JIQfc^8X)v9@W4ET0XNVeg8^3eTjE~I-Zs0mix!W6*r&x&T~9-K z>Pv~Nug!wHFQr*hT+&U7hU!?4@B!qGhS3J*A+zV5JJbk@M#e-2K+ueu=!DtfR#x+L zLw4Wn?;2Sss+LnpAUAdOg!Ybir>0LiIv(6oW!R_QfD@hUm^bZ&iZ_XnN+jg~@1SJ{PrnYMU8GGu#=p%Ntbt zj+2~02&fymv*%Y20%Kox(6`lpOPk{HFN^}3%CrQ+^qG})vpKmGIScGNo$n@jiOk_6 z(p03UBK$QE!#@Y4Y0Y zl_7GViU9SdCTmu51K^f5x0(G(xb+$!2H;n^Lo?=xQf+cdDC-D})<-3s|MBO@VaKbD z`-*)OT#Aj+?EkkndiZC)fD%53km#-Nz0G6pcS=bCcyhUoOUtWHfVo>k-7YJ& z=^@CG!%vwi?fvKtax_>Ue+e)e`)6(Xl+k+i7d!#hW8a9U@?Q6dX63#PZWg$6D+m2C z7y9l7Z{l%aE&s&n+m8PS0sCr$x%gOx?W?JH=dMD_Uu!Gg2`{Rl=NL6*!7td}h6zT# z9;utRhNR~2c=Mw4=yz(t8TrfQZKb@?-CGdXF8&MgfmJ?zN)f@BWWM??3-#!vR6C$|z{GBb?O4d#%^|1AKG65(?V?4d|$PkL(qS{p6hSfV>?D(uE zxI^EYfzld`E48V@4fYBZqifda&0pO5JJgI_Q!`fFUfTHDv6uuP2L_Lj^kM&+v9BS0 zm(~PV){OlV%fK5f1CYc9?%CkvhU?DqEb4Gu(`!3p-IGNZ5_G|gw0n}`SRGRLX@Ir( z-=w!Q>P$HCE`-Tz4UTClo;@X%7rrP}6Aob{y5)BOn7G$#BX$)6M_UWamRcNpq=Vn4n@b4Yh&J9t zam1jpK_MLDWB1mKeZ6*ZXZW78>0>-Sgstft%pU-_;Zz@EJ#6hUc1xKns#j)2AbtrXZjX9)&m2<^!EH*7~MGceh@ z|FXfNk2doBE3R{eD%Mtr+NaAOBtpgTHvKN;h75CdjwRZVX>gg`b1nHM@o!=D*}r4- zbP_~j%&c->z%J_kMjub<{xx)YJwK}?DQm&tX&>kG!TSWoHL}A!!_37C>3lV7KNXrUScUC(2f@0jyET# zhj8>G4y~;RZ^!O3VaqSvfJv@laBao9x%mX}%njh97R_FwIfSOis$D!`vMW}IbnA?K zhDHt!p*zsA2Y$%kVH2y|o9j?TYOxbP`pjvVy#5pHC&DQ&9)ks@q;qjl||v>H!>*c^~|c3t~~1u z(EM;ss=g0r76slOcI)50t-RRrjcB-I`N6Fx4owQN1xBLl79=Z-#@62wxY z?n0J)^^als4oznBnho{V??jru>d9tNO;>5AtWEo;DAG};%)4jOZMfXd5|`dikT8_T zcSPTb%5~gc7|*2i=7^W)prEfv-MdqJ{V8 z3p=IcM{^nVg>>9LdP+VyPNkH@!4HN?+1x#7|PwQO0V@1biX=lf7E!$4{$s88IZ_T=o;Uvb@c3e(}`}OrKjO~Bn;pXD#Bx0TEs$X2YNj%hR?whwk(C8;b&2*&60@|Jf^E$hDP}mbOCXdjhU3{ls_wk) zbe$z~UXK+wxYBckMJo3_-U_KlQ`KCXx^xrz&3@+Mr7i;na(usw(#8F1*;6qOt9;!% zO3%@&GVu;w0)3>;2I#!a-p&ld=<4jp^a9VUznv&E1YR~y@?im3A-9ph66OGgr}OAi z%`6nI3HyQfPD&s{v!Co%a)8M(R^bsE^K@;gWdg_+m?NX^NdwfN&Z*Gc3?%X+tvzLw z5Iot2tzbZgy@TC;fZTgQ?)^fw^bo=y$0c6Y+5vmNW5K|{7V=_$cnrKh9Vg^t2MvBo}ZYIiodwU9ad%T4rg$Tohi&0D96 zq&TbCHD_nyBO*3j6!aE}T`UrQMeN-schb~OM2-^^jPzJOGM@fLuAu%J-!&Q|U)v!u zv1Ul&R!+_V%D%%2w?1G7{W-&bT~9rSr)A8J(5ZMWyhvoL6HMc{xUi6cUmW6yPQ#ak z>mZdZhlq>8}cJTi?fA&yffC^5shT= zuL0_H%pN8*aK)}6xPn3yw)=|%TpH(orjK2GSky3LfDu-(zg+KOi4g{@v_fQjUm~zj z1sQJcf~y5-o4{}oAR9&rKf;OsL#iZzA=|Wma|ZU3VD1XNDBR`^dY1<69c$!bg(;oL z3Obn@UfzDqDz&A{=-BCjl5-DRy<<;D-Zr+{O#Vp>!%2o&-(@?5;zs1_OxAWagqt}~2Fo>*ODGV*!PE?WpQeM-eyUwPEsq?mBe_Pzy z2;H>Dav!j7fNQ+8HXd9@^k~|8`E{nXGajzqh}{nD=FVK3UNlSvkGRZfm-J(R>&tWV zP(58J?iw&!NxMC4fb*=EN z*EYjwku9F6C)f?vu2CJiq49JxdR!#0eg63s+7Bmw?N0~2=eQ?@Hc9O{VJ3$19%}vMS0Wr5| z^@LR&XoEHhK5_)iw1t`c>k zR4QIeAA5r^sPx==b{^^a&%w9gyf5*azU@SVmM+*##8mg8-|ASZ4q$lkj#$d-N-RYo zd0e~<$zv3g=>Er$UW*9+RoC?FZuVxt*t3JCe`k9AWASr{WQX}BkC0I8`r2sb6-C>a{bzL5pJa1B5E<$*x2xF2lFv#xBc4xN2vVxIy5`@{_$4oz`ITdx0#!nT9wb6Ad>Z6T2)X5U1 zyDv)7?st?+;zZ#5r0(7oKk4-<`?BT(RS5r8O;(f1aoZ!r zEVKoH7P&j+7k3C*wG*LSgHZs`@Keh4y9da*TLv9}@j zg`>tl_1DO%2J~O2KKDyrZDL&lvaRj>gKC5CaBks$nriST`;oX7?QWoR#Gd+H-jP z0pO+bXZ`rL0CO5jwu>31hhN6;o#CekhaYSw3eelYK7<=+V6M*RBhqZjzVOQ@o_K;= z@lfA?JT_f;@wiP8_z+5d5BkPbhQz|A#lZ3Op8&@jzGb)xegW>4Jc4yY+%h^r4xS_K z@5ODzAM%v@d4AcJ+)pki(94D0i-6(J-}L(qC4((ryuk* zl%3z*mp-i5{Iu|00ug(CtannGchR%>@{8{LohFeowR|V9Q)iy~tJ?yJHT|5KgwKS2 zD>}l9CMf+290JXubfG?BLBdn$UTXNye+bO6yR`sN?t)gen?9~iPwrP`rm2?83$dt- zy)Zo_UOjF@O+{OH$#$|PR`!F#aZv6)^-o^c#(tGtizkqk=Z)uu`wNK{qIknUwj+FS z`=JUZ_V*7bv}!0-$J5()VEL9NCO!N?7#B+>c!0(t^)3vCT*H*MQpzK{{ zk?IB4;MOxjO0x-g1^L?Dy1HK=o28hO`mW9QjLr9g^05gOc9#*FCA*qTUK3`0R6DoU zCU>co8=Zuy9;2U8c-uB>Q+2W0BxeMdsY*^O2E&U!p_aH}aikV`&6##OUyG-22e)_Q z52FYdi5($K{HFO$F4vecS_}xG)t>f%QOp_s?PP*N%Kg2 z^&`6Oj|utr$AI}Uga0vu|5$b1ujr#rA2}5N@YTPMVUaPu*yj-VO%2U(BcQo^GV&Jb zca10AoOe1Z=;K?T1<1hPz3SqF=*L>g78#|W#lKhRwugT+q?ztGz-xjx;4I(snkiEoCiR+AEH&)T#?z_Ajsu(1ZE>qt#gOgK1jQuw)8N$v#HA-S=7TZema&CJ&npCk~$z9ORFR7>84;pg%~ zTDG|!k^OO1%ia-$YZaBPUUtz6nn2=~-!qpN7xcm*mzV8RT@$?JA zRjql3H>RGc7qR~CwCi7PzJ5&8&G`O=>Ji?Y$sa{n4SzT>@mtVB2stk ziYK2^A>C2KVr?GNdF9UU{9;boTA3}RBX}d;@vc`4uX2;usn|bTKU)Si==eY1NtJXpf9@OzHxJ@`3^ z%5NYovc5c|HmP;`npkPjSxfc2fVXJfP7hx-U+cR%Lyzk8R3zez)*v|Z&Hh@w^@xUjW~NspGDM;Z!E0G8(&?Y^>9tBEa=RvZ2r-00c}tFbJ{*$vF|RnsdYFg;>ks@ zw6|!R-=T}}&Z-4rx05Zok2g^QLLs0JZH@vXCTPs@-<9ZAU(~gKj#umoFYzHcLtt`D z_z=xh%vf{f8S=V~P2}DuD8YQVT(xb%$w2v^XJE@@lR`OG8x;YprADup{M;*ag;!_> zLoubD)Kas~bgoaDhc8%T*#FFezjD)@`&rj@bM6#oMO_G)Gp(Nel z)EMgIds7cllx?>%raPG+^zNT^0Ev`RvkB;UgiXNd2}wtU{6Nm^M|5rG8BT7TX5L&- z7QVb~w-Y|8J$(6keZR6h{MB~lF5MlT-fwq!Xg?=7Ih1pHltNlh#J0V;Kuw~UT!Myqolcc=ZUx0nz+JB6m3?%H?o7g$ zbr0uX#t&_p;LSau>=7VS4{Q|15vHREqsMymuIV#>v-8G)TdLOyFZ}Sz5KcO$sQE|t z_7B)4$Ne?Jr zdITbU*=Ca)GZ~61T&TA{qh!Bus|c7Uj#+7^T+4kI2w^QE67!6oU|Cz0aZA`)9e#S5 z%2$OSTnYV8B0z7I5FpB`YUIC6<^|+XV25nI6H#01q*TU} z{5DKVn#b^BOue1H>=$mW;+HS~WykZwN#Vn>JJY$*)($C@_o?4jZ9;1K!~X&VcAF5r zyC=I3?q-`0M%%81!p@J5b9wW_Kv@z*9QA_zY)u96%-l29^$T#b+v1N5Y{^e8HUjCc705ojD~yG-?8Z7YyU{&%8T$iJrc_60Y=jU$OoNm!YDx0*frqq>@Q!Ay z;7YP<*=70OH zUc>7_mSZO#8s6EG9x|wb?_6(ehLx3Q8WDAzHiU!t_jD zr8vwPc_h$64e9faW+RLkk;xJCa}#FPnsHKtg%(UCvSrBGgso&<)2*DQm4>z^HF|J7 zxQG4?4so<(&f!iF$L@XehC)C3{c>%3LJ%WQ?$>c15VX=mj>gG5JrVx_Tng?QLy*Y1 zWAKm0hMX5qoyReR4yWSvrvJv~e$6VjKM4Dmeho48B0l=;04@HkV%S~yW0wnjs*HYZ zl-5#IzyuI7&QrI`r(F6#U8s|?E;b%kn+&OG=#}d`!HcFFl%@ScZbUin@E*R9L6kcz zMi)r~ooXoKR^$D1ifV#uYAUuiX|rY=SZtMAUpC$~%p4&~<%N2r$bZY`ac_qoxD9+{ zw2U#8aDR7otk;|k?>T2(lgEP{|7NyV-uS2Y@DWUpALax%XefiI`*l=VM3GLuj?W5h zI9kJF+77plrMTLjEtXPlHXAP2ei1=ZOXdPZKI1e#2go!7na{)be2ieJyYkvU0y+(6 z1Bg4Ru;O#>yjhbQ;^pU6*=GtvT$37%min$^!iir}E{?^XiN+T%D5tzwZN>WtTdQ(~ zB$yXO{p#93O=@L-F7397%lZc%2re2tV%|lmn+G!wJHz+H)G_9)HhFUy zy_(G1SHeqLk=k+F6cV_DQ!#tbuN}Lw7I_)J1-Vj?RD%?Y`N*qvJX!2G+Yj02{kUYI+WBvNK=_=v?pH2Z-OX=zCNMh0-61DIiZd zh3=saW3b&3I zZxhIF0n2-W3^Fos%N}8RjGX6%C@_+o@NK-h95Ki6KFkNSQQQ(NkL>q-%OgQr7E$tu zC~*=DFHvP$^oS4zf9J(N47syeby#Fiz@fuhHt=vk|8MO3Mz}Ocu3ReXr0xhQc&nmX zFM5^=gv6#v;n9(Xc9Q#u|J?->tbK-%FmU_m1pc5wWfAqb)$;tCVQru8)C8}?2TCr@?r~RI|FuzkyGQC{s6K}1W1v3z@iB}2{}nucrjK3v z_(UHc>0<{Uq;J>rR(;&YDunEF=Fy&J*{rYbi+2jxXan5anoauG+E_h7O;*op#DmAY z^q4!%rvIdO`h3#eCR=slL#iG}QTGNI3@poMhi27vpE|cEPt<%DWwHnUo%2mnz;vy_ zsY@al)I$phsVif-U5zK&)i}jvGs%f~XL9B

~>?UBbUrj;5@GiA1LDIXZex>>Pl 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�sEW26`M++YVJ%Y*&Zd$65K9UQApAY`51~G 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%0D$E$A!gzmq=~4b9(1u;_&>p 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Ƕ`Rrpm479?e0FGgb^Q&v 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≀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�vK4_#Z2n0lJZs3JxoeNQj;K{!-Gw7Zc^mK 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�jyo9 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

D#%<) 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

mh|5 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𝔶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 z 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

+>129*m}`4IE|n$b(&=NZ`rj@lvIO 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 z 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 z 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%0AU7l=*vtZ_n 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%0A$$V*mY3!JR^Vf2 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 L}^MTPS~RmiKzwuFrQ2wjyEgGqFQlqjnJF% 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%0AEsVwI)jy7lr~^$jli8Klj*W*%U7nD zmDEi%t7-Lr;{k$}L<&!jx;3Uas%o`tiQYR<7mV%J3s$nasHogRrzMkXAk{HQ8_qh_ zjHW9rQ+y_YRkU6AMECpWdOEsmS;I^>soHJo9P&j)pR8`Jo1^11?a14`--%3^p60FV z>Qe?xR&4ERSWWj~y_uDxJ3J>L+H6a1Czc0wQIZl5vN}%3 z^I_f=V<3?KvhXaHwfN|S=9)Kaf!SJ#D;4Nwi)D%Yv}w)Ckg~PI#K@jJ&Z&V0T-mOZ z3^YIC&dMpen@9Qft!6RV5DVJ$by5}%9Yo6&W_PjA=SN!x?uq4&fc09N`e$fKAC=eu^I6l?G)5hAwbb*lvBx=R?9zI0%%?-!HMT1Zj z^1OI$Lju!+BIs0DvfZ7yW^*!Q8Q041NlvBKTai=8ZWVPGPfi81TQtG*#XkMNoAs*d z-SYJzcY`i4hdAxX3r#sb`_*w5bbtQKAUn7|^t5UZyDIOBIlK3_L{1Z7nb$dqRX#O( zWqDUtctbX$!^PEFZG~557fR^bi7zM(fh)XdSM(@T{n2cSlR0c2>iRbTp+TdAZaowp zqqhLt^yueVv3iF)O1a_Bn^>nUe zN`#+iHQ&*KAEdXGu*(cR;R=66)-1eNkn^aY$2{DwBV}(@?gl(Z)BizzcYGM^1-J?c z^$4{;?uUzC)d>CiN&c{fn|3K77K#2JpAFa;m>W@=p3Xbc2@LtcNdTicG6CjVJH*Sv z6&^T4&0hb4e*H+p_>_nF$EQano(!)>N~G$A1tXN675|~S>}vgZI4(wMB5uSPHSM=!_MyZbMGc)ec?C)cCr z`@7F~uZ!2OUyh6G=cB!s2gUH^%h%5*glMCYKgrmd)4i5QS{QkKS{&$q8L{k(m}=u-O>QB zT2JA!$G=Cn#puqE26u1cza_;b-rTt_98xca%c?LH1c_KF_V!-vqA`V6D$3#AMa5Nt zWOy%t@Le3?^!2XziU+shYz_;KBJ>t-6Z45?^WrYADy}*!TI045`9NR;Kujj%S@>NT>!vlWvAv5Q0GjHT-ct1>KJ^ zh)O^id)RRs!LaKSWcrs^;d?OOvwk_sn(wTwJ_?8|w8Y{VF(Bc5O!5elnoHi3d83@1_-LB_% z1)PJ#NBp|Dna+>so7MApxrCE!k4!n*wc?js#2&zG<=Pw!pjdIts%XA1i~I6(!RXC2 zNVF4C#YBpew~beb(MR=+$2*%Z95RMuCW8F>>)O{*3jA*yz#|F+NC0A7s)E)C&|t%{ z5J=NMeewP!7TUNod}qv8j!deM(yQ-&vJPSd^}}kdn<2(=SVm0O)=s9CnmWlE5~b3i z0gh^k;nT?TLzaZ!?&T^Z!3COJ5E3lSa)_JARH|uaz=pEU4XJ8%R@%L1x0u0q_4krA zcQhbY6W)(&t~6ZmtsOBQbC|~!MR~*Ho-CPdh(b{11H$#EBUKSw$m#Ga3qiZ;ic&SS zOhc=NA*_bQ0>X9s+%mJBo z9T`{^!{z9fInt`V)VL!#Rm-}jn*$#4V@C=)jt9h*f|^>jTkz!(DP=rE+i=Jm!`2N+ zt#>r>I!w`bh@ivEkir{8Lf@=zTXpN0Zt0*tL-Q+_DhjGi-_$$ZEMr~kdg3OFSDPj= zT1;*0#YI7L%<{?ol;7HI#guSqsk?mir(nFEq3+3imAOI>XMNak@p(FGyBeC_ijvWW zqgy+sl5B4sD=D>wR6|}o=r!b)3^olj4zAs8u`>vUof&jL{K{)p`vuZrl%@9rG~8t- zHY^<2DJ|r*cwm2Pzogq*cw)MmuBM;ctyK=Wh_#%N>~AzI;nMnXLGC84P%WV$cG&J5 zim7IYh0m!uW{-mob#Guz}){Pyq z!=@s!12*>Z39&bXd&v2H3{)L2GDRJI+2v zIV&jLMay1ByQgkguNyXR0*MhWG7!bwV{f#41_cLFc^F78g<6~}nMY2P^eId`@mYc$ z9~2p!!9n_7517P#PT~2rB$*)bHf@N)BanHgD`E|Ifjw4WwVRIVQn*b6p9%P)D%Ruj zVhE+GmUK2Z(siXKs1};XlO0svmNN;xXF|0h!eu)9rZhB;Q5+5mY*1LF$83n9@R(W> zxOV{8^w!Opkb!Ix;+?xux6M}-3u?P&r`1s=tl9LD_{U>BtvR>ZbyTY64iWR zFLqgchFBIz5)*)fyjyk|48D6!o=+xZE2hI(qD5>!?l}k{YH0EZ0mGmmz#4-}M65;) zr&>NuItJgj$jM`w{OhLx<4p8H+NZ5UL8X(HrGcN)NbMf{_%tYqs&N(OAHP9ce8hW zNLUC+mcs-Ljz*?EQX1JrmVombmBUd3WrR)5lqP&i-g5nLY5c899e>iOnlf9dl zC+BaQYEzK?F)$?H+`ce@5)##-CrH?Kmq6%|eUE%+yy(UFJUEh_!NYwcy5SvMdgzdC zF6`vzHr7%shS66{F!L2g6R)oMof_o{E$T|})zs>fIkur6LPZSZayhji7+S&x2v{lc z0oDwKX<)M~sl9Bwr!=+G?Ga{V`f>l|%h88oDR{j``vEU%1kpe`m>%w!W|QHKh`N z44$>j`~4VA-4?^e_n)%O8MVKuFF|EQ5ritLwv$AVo|dYiRyz49a#HT%9{t50{@8o< z>IuRZZl8^oBP4z0jmi1V(Q(Bo_FTEoii$4E#hQ*_QSn-=qfrHAHFdrpkyjENkNPJk zCoU~?i$)vn(Xd(#Z|3D}8kP#Kbot2C8r)7Nt8~?{N!nm=kV^Mg%3}JR{n_aiQEyxc z(j?l7NFwS~HQ)E#uO7mXaLudmyG7+U;c#bgvhTGM6kRQ+3;0#Ji8<+y?rrXwD)hUc(v&f(3uL_)gpv?AY;_eHTdoZ*fvXY))6 z5}oIcX@2CogNS(Czaa0j9g-}pnC~tN9FIxBvT&nvKAGN-1C{AT78XZ2hylQli^&iH z>-o+BQo-1PhjqybD#0�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®M2{A$O!T9n|sNAPyx{oAG(N> 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

1+wu$6n~SzBZk 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%0A+qDL7=cOGRN8*OwwdATsI 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

t_-6Zk3d+n#C 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

*D?-e8?GNG6;0-W3V-OV-FsS){rO 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

UcLYNwUjl0<`4$gTiY&w^#&{Z&C`yz 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

ayAY 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

|7yK25(;ECurK<$T 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

    pQf{wcxwLo0l6_^sahOTLJo-?uyG^lNSX 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

    W+tI*4+#}TDKIc>TkXY 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 =PxMZB>xx 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 ?#(%iB*{ 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

    (cLN|i)^oaew` z{{^Bg$h8wbdJ8cNz$Zn&4v%g9DzwTe8qE)nyvzzKhu0{df}OVMJ}*b2byt}HdQUwS zq@P~PCo!$6dQ=gs1KpD>yMEq-LiBn=&EW@k>!>`YrCEpL^pYr*lhN}399!C5AXTVe z4>-1g-%FZl7ZWt25YK+OcqL?5EASx)y#cTGt1ddLbY|fie8Sq5$iba|_#Hw8iyqNm zApPMRL631<#V>4W5v5^9PftH}nR+ei&$x5(_tA92K*;*<DvB_#so4G8-5E)iE3$xplhsGf1FLnV?06;5q^dYkH-m zHE@kP@hScSCxZ{{K6l;oT|58ROW*o@X0kpT*I*YUY-DI~sOUjGV3X$cLaD{cM`T9c zVHZ?DNV1gMttp834`sjI=EJe8WmJ1v0$&S=(<@r3k$80sME)&<^kthk>POy@8FZo0 zL~p4(5Lx9@v)Qm`nk zTFp8KkU+yOOSR`nKUFS6k%%aInbQKS!wL;E6f(p)K%wI3-ZhNW7#G+v`c)nDbt&p6 zdc!C>?&kr}vRW|SN=tZZt6+zYeE7sNz}KWwJ!bZPU7U_=HA^LW* zFKp~jOfI+cO6mgpfyjVe_~ft14a*fRaW2V%&uYOUGxEarq5pmj(N8QP-e?22K3_

    f`;xf|2B!5Fvz0nPLR5vS|D{k-4!^^4F~E&wU#5 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%0D$Xu;y`sEkeo^4mZ!`R4 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 z

    uYC9&6j(}TN1ToM{(OS)q&vOvgfn-8CI{6ir#M+@fE)u6DK@%a307>N{amj>D6 zUcsZD(~kSy+o#*%OMwD!`he)b|S=bQ!;54mfNu=*`{t|b%@6z zf5E{n)uBQwzIF2%FGw|l2BDO@A2gg~ClA02JcaUK#s7(Hz)jXw!oC0Y7fHS@S`COy znMVAC3#SX)@>%H$J|d3#WPJ`Ip@$k>hg-Drr!Ixzo+l1*MdK}Y+5|>dk3oMuKGOF# zbYiWS)gL!R#hZPCd&U2xlW~$acX!mKjU1Pu6cYEh2(@KoAy%-zYNld-x9Hr@#@>>E zNb$(J5$P}Jh_xOX?WUgyu>AHgBV~+H2Je}_0S+kGPbD*+_BmFETRFwY0DzLm1-9=0 z{Yq|W9_rHx34$*NQ?^6_aq~yOr?t%%CC+ZMrTlVd1R?u}ehTErBgcS}4E~j+tD{j? zLM$n%{OWvT&n!t}vxLWv>3_4%t@}BSbPd3q4;tu=XQB||vNgj-RZ)FK&3Kb`%{gIR zx=dDi1VgT4r5=1qpP%Q+3im#hzXJQ%D3CMGK~7x~?A-k3h@N0a>5cMRR}5k?;2|La z_HL;=cJl<;fhdZ2vYQY`h}MY`PcoAdX@Q%FgWDNO;eU7>&@L9Chr#Upwiztw<$BXR zNty5W&|yw@7<}o6=KWal6b0DvCN+I>`?twTCn!o~Al#U=X>cwuc`$R<_wjysAmDZ8 z7O2zbktMo2Nx(85f}{iyrNB$=B|?c<=<-qslI*l_8~}KT?qc7r-mc;U(?H9U7JliG z6&ug8^e1l0Saq20Hw{8TY4`4z*mzP8=D*}}KNb~5RxcCmTCz`xwjG2*ZHfq1UcuIH zt=)Xq#LeL!LDSDk&1-1A(}msp$+6$HY~X+xFxB>iL%=T`F5;^RUj8Ot*c43wAfjsu zhTL|bPTIL%GS*VDr?y38jBdjWYI=Yeq+H6+^$}`~wNF;Gf-emiQ?a#+^!}kQJ!m{d zwWWZ|szC_LIQbhq+an<61j-gt^gdg;8>KxYD{@k|?1d9ckG@RjN6m_6gzS3q48Eb0 zt%Oq!+rYe^8eIE8N?=j8Jklu?t`R+ zT*ns+-a&pHEA&W!wQTk$bWL~ftW@4V0MQ?U+q3ClH6;XRNhhM07-kv_e)w$ObMD(c4XHhx4`qrvG5^!%65w1#7mDGzmoe5=QZ zhb($YB>SlG+kl7anIWf$KE;jA?{;p0s8K*ouGsfm9h~FqC<8DXRDzMH=lY!0z%NG` zL@IT^4Qdg9UH++t7$RbLW`MDUQnheSwLfp5py6KA+cMV7lnz*3*7nEuYW7H?ytYsi zNh3H#87s@LQlNbxfL?}upi&j?y;x-c&{GR!h}I}HmnHf1D>l&4hLV9R@h4dfcpGlt zuj)3&a=agLn!|e8WvhCqhVl*RO|#{TId6-_LCF720o#BiE_d`cHfR0jJwd zZ0`A&-az3jvNgQr$SygYz1Kl5c)I_&bddmVUp2{GedwuLWDVvt4d!6dCaaE_{vsE- zBVsLHWkd4THQz8mr`YrZW2= zAbs}%mILsHFD+<%fi=}HNyk@~1*xicM|a7Q!@8wtk6omc_tZ;5f_tAh$0{d`*R=dg zo%mD5UGnKrwxH?tOW**Mdb?Qu`!_iv#5jnehDZSG^uUCubFF!oA)fYE5~q<+ z005WX4b7yjrW|1GysF+&)7!rTUVYE)AyB`FGAa|?x=5~Vz?SNSoe<6{ zs0|a1cG^f!k(mBn2VU=tKQp_{iE^6<>EcJ;V$&7#hQ0RuO#*`STm(#?>|pEqq#kAL z2k6iBRM;KL=p7+3j&~~ZcN^@;N4!Xam!6pkXdRbO1&=&b#|7j@cZ+toUDVjXpcXul z$d*HplROf^D_|#{7r5L>z|$AR6H`O=z`ae*`R}gNHGazI)A>KYjcjFpD?Fh~bm7kh2tZUg9XBIE;m%_ zAZQadM-@)ZFXA1g%3h7J^yZ4iVm z*;~qo$%g)p=arxbc;Gi2iOB_Ae3xy*3pnGiqNX3(I-YyexNDvRB1eodQUI)qoqcR{ z`wQQP;vd>kC|XSYI7&BczfQrozc^+YJlK{zXC0l++boo%tye0x1$EE{%{jx*wsm~v zVL|@qkmK|9gYV&kn{M>vop2~;2{DyTI+Egfc2wzS2yWIF)HMwCer@@+(MJ7d|FD(J z7I_NAF{>Jxza+#B1FFR;4;G5(BEkiTYZ9~*q;o3PigUA@yUvp>A)u7`xAu=G?@iyH z%u~)K;PlDtL(V02+j&W|*RaNvm-gyUb!6*Ja`07zZ$m#?;i}*@v$zOXi*jJqXczQ~ z1YQYavR7%#J^DV%km!X`)Xn-wfm8mM%xSnu$2z=LVy zh`{xl^0IO)h%Z6%o<6uQD{=$D-7t{?_D$VQ`JHd9PWL4{tatRi44-$b%n+SjECbq& zOYcaOm4g4Ov?13JyvMe>tZXK1fB&p}6iZQ=*bI;V!>4xebtrc3E$tKjDj#7z0C@x5 z4&|j-2K1O4VvF{eYm3Ht>p4A2#_w_SnrucmpdHo>!(*IqrI;n+vCeZu-~*!f{foxL z29l5Hv<|D4SuH@y=r2G@BRXYyko7@$dnHQA?OI27gY!5uU4uVEyQ`n72X$?b9_<8) zqWhBRXrtT#F%2QTH52)n+8{gbn80SO$@{j^lebfHr@YCg&wekqFL?Jl9qRt_Db$Gc zM-kDsG*x!BS@vxdU-R=3YIE?CTZcOGba8#Uv!r4PTqRk2!V4r+{iza=`=b~T5+@kP#v-x-TcNmzsE#F0C z8@Tv^@r#U4RX3m`v9*rMe-~DjoIr{p5~WA?Bvj}@YJCF-&TMm=z^n9iAC4F&rxLnw z$gl3byI!$J_diPs6Mh!L1t_{J-O|)er=-ROpUnSOV+F<#4_!Q zZ}vaTF=ow03ysA^bM>)?cI~+v(!BjcEvbFq0%Mf+BFYwRMF-EU_`fajau$-EREcXn zNnYE&1xBvz73vNV#e2z|q)m3DOJrFsRWx^{^Xi|S2k@t#AT z5t8c7{HN$hrCO!>jiStm+-c%lBK3+%-On51ygjnY!uDt1d?TWb0kBG=qGBWCtoS6Y zk+}4D%fNWt=J=*}+eGPZUuM!JbIHmwMF)J<8v&USB*78*%DvrBT++5Jo{4x%AbXy& zC7Aj-yLiu3a0F137l6Fo>(1gmDwz>wXUWPPNuLU!MHDUR)X%#>ZP>kX)g6M00YHIN z)sED5nJ96MI8kdPsoi+2K{1|iyk+{Bg*DK%Cq#TZT;(JvKk4k4f!Bx-HQjo8jBgR_ zShI3H_MI(#V3$~?&Nk77|w76`(*;-@8 zD5ty7Tda0q=W74ts$A!;)LvfvEOoJ0t5~^!l4-*NuSdXGo!DP>?r22S?!d&NY!H?x<|ls|YH)=J+G{_?TaI^5QPpO9tl zR9W|vTc&Gw?okRK(vT^Fm-wyJvq;t=X&oqeN(xkRYuj=;*0)R(ZUb+&mv#yJvbGZOJ}3*C!>s}BrRBg7Vi1o;kU%*ilz+i`_vta0_QH<20kn-R2DQW*>j0$&?JWNc(-6>(Qr ztlf6DT;DwuGR5w9qW6=|Y8UE{Bd;9Wd92~i|lLr7n+uYDW` z|MVJ@Cdc=E6y+wS0gg0&nTmRH#Ql!{+DWQo1#<_griP3)IkoAr1V7$2Og^#!6&`9b z5B$wnhKA1lTaS<0#!nbZ(^Qv2yxSOoF?WCdbW^+xiPMB1`f~J|JiI~2>c94PfNWZ& zhmzI*V!hHD{QL{#HS2}63K{*~Z;Cr)l_RT)>90f~YQ@?m7+>bIOS)v=7S>M(Y#XgS zTP*ogdR01j!;zkLy#i%yJii3KmymAPog<+>AbqkDYg#X$K2QiHh}{EX+D}5eb1bey z{|K!NZrPyUxg1WmwI&}Q>FRa0hTsyw~6*gPDA2_%* zs(7Oubmp>*$g|XoS@A%Gww0g^HxdpshnoIJB^WedRlb658 zPB~A+BDJ07H!a@r@9VqiFMqT7(m_LHC%4lPfK zELA&gHDhWUo*m{}F7sk(_uaP~;dDTi9N~!MSZWt^eGjd?Mx{>R@|TvUAVkbwgzwPa zLk$pUQR(L)(#A#f+F>I^q+?2LH`6r~vxm4iU+@jDhrdKkisc|wt3dHt4wcEVWN)7? z>aZ-1`V5!f8aa?VN#rOde2D$R^){+?JwNYqo3s+^DOt5 z_!Iob`29mmADX8Bo*_?D`XXo_!Ou0!6!f$zdIwnq8ZYA~mri{XXk+g3$NkIylfb)zGA4AnLCg51OpkfiT9I{Bv4X7sMww5ltzpp(o7LWliTKeU0;bZi~dj z+qyBot$T9p?CD{`2S|s0$1y9w*D9?VWc^ee-yT4SGP_*bdHX89qy%H{Vba$1q#2Hd zqkqi?$HxXC&88EOlDp#6Z|t1w9wF1c9+5>8>6P2J?-jd}<0^8L#QUw>_`Dq5V@*eS zq)~V%6o>|gwXV3fB9i-GzIfGtUydBf5aZM@&WN^V`1(-I9f22SQ8e8R#m>OaSmu2W zAGT$>S}=7&2!)7Y1r#z1%hZV-MWvSg2+UlK95=ivS=~gL5pa6ZH&Lg*P^s$#3oxlu zYo`6@AFThieZoUXw`12kE^Aocl z<9vc!`*Q6yDzyfIfr;ti0;rYT8Tj}jIE(F*HUDLwP!z>=*?I;Knj+Q)FEMY)plLX_ ztatFA<;a^OrM_K!FvVo9Hdu+6k8i=oZD4&n$bKUkLG#PzqGzj6*rQybioEag)OmJ~ zz94AxX>marn2$!K__rJJ-nzDiq2CXocS`OLVRr3g=(4Ck_J?puzh!(`aXXKUHI`Wa1P%O70fo_%?o47fq(8Gm;J|K?`>8Egt+f*UH+y;43z zY!40xF(9g!vl$$Yf~hnH#C<+*{=tzJ{bp}D{tQz*0*k;}F-P)m+$n5{KM7JR2u7&XvSe&&HsR(3yFpEjNXSHvOF{n`PnO#C6E=&i*_q%pD-43+& z1XCxFWgo`o#)l<_>Z=(4<9h+xtH6g1rU!c-Lx!BgS{iI5C|fFtRMApN3IFC6_jFBy zn}*Pi+^wQT{9_+s0+00}v2Dcg{txdSPQ0MqDVCqa{>p8*B?-DWNPMXaBkHg4gyTM| zt;lWzy-^%kywQMWRn0&+NC`q5j|0YQNh9$66W8;JH^+l)s%%s%rHX zMPL1PX&MU&xst}NYL6Iy_M-*_(&*C@yL$^(nc&!0o%5Lu+dSBX9cpaU&2Dxxb7tnuuAjl3sssIA1-1gjdC#;dgW@eL?V{}v5~sKR3z9!8 z&gVptnJ1avL9h`}k7VncOmDmehVHA}MU??$XgXEzKHcc=S}!%?3r>oV?Jy>YfpIF5 z)e^6BqPRpmCmKfCyIHOM z^NVnXu3ulFnCL{yT%dk8aV*_&elm_upMF8X|AN zRvBO~htQ!on;5M80cQ%-FH2uw3?ObsovN-+Gzw-&MbcTlfVB#}&R!7XHC_w8ANi?! zy|ymm5q>%XVL5+>`iJD(aAM(W-D6-7H}mjxd%w|UK;Xi_qp$^Z!9y|meo*jf{&j1R zur1Pyl!+CSIKt8jJps@fVr>ujvv&c1C2?kVj3kZ@u@p>r5#pkx-!uP@by#PG9E0V+ zC~#LFb0*J>x(Q)*8s8~-K;z+0<7Ua;J?Pn}AoGP&*wp_@-|;)jWqF1!oT|Y7+Cle0 z7o$uEWyG)Kd}8~&%mD39G$SJOPh}nd_Jg?Q&EZ6G+coc?*Pe8gAC$%;+wYp|ixD&i z*P46#btU}BdnP~&Zm=m)=x3)-hTuR&VA~cCiH{VtHDx6iD9wi`Om8SAvm z-!c$2D?}B5f6()#Wgss&U|!ZbOarDHl`XYH>U>)OUJ|ut$)xP4g!?A*6xhC+1mu`| z-EE+l*-}t$OHW;h@MAIZnCUYTqmO zKGMxzBVnLt{}NCWeGfJGj>DGAGrE(-Edaxi8#{_g0@Mz znc`3g9J=_ej;Io;3UikcOXlm-k8cI_&n|vuF?LA{d7k+vlZuk?7P|Ofxn_uQ4$1H= zQ&%jSSO23^Y?e_ojdS&|H+`7aq?gWnG4mmI1kLH)1oN;N=A@C+=C1;|IC^sm7}HNF zskd~g4SS@$wbWn2r|RfpZE~+6_LBC98U|8{)pIi4BT+eE) ztxj+}TndQD45yxW`N9kymmTCTFHNmIw*iIfc+3s7M_MBo_;M?Z`)=8kLvTcY{tN#it z0(Tfhl4yDnSG?zs3a}M$@<*GC=F>_2Cyc)Yu(I|B=7A%7|H`}f>-MgpCzolA#yr7; ztsZ<*tQ^vhcg%*$^@trt2n=f^I~@Z7Qgu)MAH#kYFaEjMJukTBPRqlZU;Lr)LdSqh zIK~{nZTZKXAY{gbWd;;D&6~+BP`sZ!g>2$e^#pz5uWB%gU%#rbM<{0ED>qTK0^U9~ zA0_+{-}mC&D-qv*LcjjkXRxl|&Q{PB1}^)of`oGM^D~k zTw$3E{$mFm_X^evx)PwSyv6*7)GsZ+yiZMl4OW(4KBgwX1*>IUrQ|wFqy6UE(Gi6B zmQ@>y>G$^6c-!>*&~D!4Z}j#gc(10>!n;NqOosGZgl8LM_CrY|$^(Hyr?PsFVuCT;W6zycTXB&@2x@2mLVzAs=Ya^}pLc)Je_-h)wcJuy0kHLAKd9fDvtfp{I!lKyRQiAro zB>%71&BQiosh-_#Gf+UeGy<0Lbe(y}AFLYR#Kcch#2ttHI0q*mJaLl@>O_=pcLSFY zpzhbHWyRD#+RHtPYPu`ZZeD@o#j6|D!i?|vk{xR>QvP@Cs2_C1;~YSG;p2rK=`pT^ z&!Yj4yu1CJqQ_0Cksc<=@pz^mJP7Zn2hq4<%Ua4BJ49l4jN!@JIUjerp4VV(SWy^_ zweJJfCp#8vMe~#8YJ~VZcg~lqo)bf}8Y&XxML1cE>U|g5jOlko8vlhcFnerUmK3z0 zcX(hZ-A1BHmwM(#ip|(nJM~Hfc8yspi`I*(4TZQ@0EBN$xJ!Ej5`pm&!;i$>`;`sG zYZ+`}HwFjW&ei@x6A4yQTg=)EHbhH4@$%lAm+0`u^719PPF&m0vtJDMSWz2h8s7-J zn$q@vXxNGUYj^PF3;49lnxis0!N8K`s~g5Z_MI3)>_qb%i8q@00^abNOTt5yn0aWk z=^ZY)xbet-u!wxM(gX2@neihu`*FAMWXMEyb2+>u78F|i%{cHuxViUb4jq&z5Hdp* zI?X~v?x~Bo(?A}Ol`X>M3?1L~6^tJT8Sg?4UvHQ#9$#F7wrc|5%aO05uC^b;+1RnoEpPF?M6;0I@CuAn`)YM*r7Etg8 zX1rup3pT{*B}(aVO0VL}I%5WJH{1n^)9Vta;f$G@hR+FJ4&6T#GU`(i`m;E=PkGJu z?{1ZJoDHKTwDQQN9TpmHI6|1`%2d=A$Qb-o1Lw7CkwWKXfk``S=QUKHYnt)?DVZ+l z6s0f+l5O;sQIM~CIciAb?xkc56Z^kRvmk3wE%~Ok!-<#cSBxJzd8=)Y{4ol@YbA8c z)Vqd2dPjb(W$UosZ7`*!J&HJ8)`&R}g%$ftCobe9w}Cj7qPbF&Q_jV2U$fB1uBZGR;;Y9xVS=Av>&d%8YznNxp7(kNM>-u)jxL#-aL!A8!5>33=ZjZ~xH(0hmY$^QBcv@bZ@Crlc?MqK`a zcf8#JP_FO6b+QUG{wLWLm?pnBzZ}=wQ6VmL>V-Cq?lhYR+viF8CGPL9*V0u5QqgND zB@v=Lm{NM12JRlfRr}`cU|G>!mD!g_On{K3NG)x!CqCoVS+3k$^3Db;X|M=Hwp;$m zoz<_9yVid0sMJEC#CHJ(y;n`vigAT(@61}ieC-!)2(6_^J=9gAaWt>Q{cBF63-bUrq@oSdFtx?SL7Jim#FF+cU^Xfos;L-5T9hN)>{EGPL&~bY@n@6y> zm9po&Y!^A5c;Z&3?rq2?u!GVebH3jbXzyO;9)P&4epNRuip~u%V9f)-!qv9F9D{N{ zf>tgCn7nm(E3p?e?9^gAW+O$NXv`T6rI3?~LsHD-^Hr`J1te;D{w)#f? z($};+qI>Rwu5sdHFo6KKWf;vK`$Hy9QUQv}@Pe zx=^8b*x+a^zt*|&lyH*G{hd+=RcwZj+74NC&^j;DmGscz-}&evXjl$-)qkO1 z>LSQ<-}c%_(fU=L(iwTeP;btS^({fl$pUu_r^eWonLc0&L);v~Dk;X&W`H}RM*!Jw z{$ij+LRpIIOMFzY!O#oR(lKo-eh* z=^l-n|Msw}Xr2f3nwg(K9B2kIWQnWAnD#L{hxn|kUys4#f~Hjcph>U53UpNC>loD^ zbOF#9GRZFM;r(;kb9%L@A5xLkuEVR{o@TD(LQFeRHynQR;6XONNwz zuTFxkl(Pw}pS2ie%QX{^P9TxaUi9d5AR$FA{M~0?3{=tEib1`=wnPFRF zHsI5J$p{=?K|R8>GUHsBCdwgQs8S zt~dq5Z<{-e1A=;6>V64O13`GK2O+RQ72121n`6AT#B~%jRNA!5kPb9Ly!5xK! z?>E;=7W_y}0U}g77%^4fk%GWK^3G4=^hafL1dLlvP}r3)bB~-cX_P`!IijJ~+B7`v zw~iAWMB!9GQ+Ge2Gj}A9*)qgCOedJROVh-@!lz-^Xz;?&E|0asB{LT!8G%G*cr@xx%`YvX5i_*L1E*q3F(j#*eWuzc{2gAZHgl z(N_j+|*9#^I_PtH4rEqkL1#m1LSzhc-IsfrA zQiK#LVP(%3jXHQwj+@>9(nvBTryptTzB~aYg4GC{cP$;|Zex9`(C!DtW7o7@a$aT< zZk0zD0o;SSn)J+M+uFXGPnz2gdps%vOzOBx@ha%UZ@p+sN@w13B30n6ScrHcLg^#& zGxr)FTblfPCm{juQX>U-p1M#dj&mbAq=dIKs0DvLnzDuj=xeql(eqMs@_wTdeYc)LZ0f+$*c%b0>ZDi zAipGmukuQplLGtw!$Z_%<%xt%rrse6^#nacaLDO|5J{8eMSryjQHD|~3{hYX@DtvV zdbsvfp1r%$23R!xA&^;lAgP?39T^FUtOv(?Kmp0$1RTq} z*Ir)pL=*3ZB{i@Hjh-ppPc|&Koyo%23 zT5ANAq;gMZ$Tg21-ppO;MjclyfTMU;Ldk=LD?r8Qw8MsJF*Ks8OKvn>6R;!py*D|8 zmZwR)|5Fb{u`P_6?AzTIXmWLu$H`_X{&gn7G5R&e&K#9|UH3a4cl6b~gGL;Qz1!qp zfrJJy#1cD zKQ;ibkOeX>{zNX6!5+=rf{EJVHRgay{`vxqcDuvOG2QlCn14K5uc+$FwIO!g9<sunV!2aDx2ZLLr8sTbbJeQ0g@WLFc_!tzzNGxIB6D)BUNEF1g;C@<=O{ zcNGy|h@yRosk-eAaIO0)lQO+;pEhbzMGbX}4FlfyOD4Wj#HWA+4`{P9K(-jXM6tq> z%#TK*w2~U_3V0*EAa}JQ8|_}0U8@e5|K(VI#oF<Z!1{Zcyh8;!n(|e>>)i*h^@^WAcVo|91T)%|#uxBxU5UbMgP${VK zL)<4YSlLhX)jR5!;ISM+d@Ed+@Nvu#@5T&F6R_y7P58L;6#7Pe7;3a+Wf%E5SR270 z7saPcBvVcP@aJ!>{fbFi_YI31ZR*K|jGz^B~rvmr)qkY8UG;&U;V=61fl>KAJB%(nxG_&biiAu7iB{s z``A!DFoyH~s{P&bEC`Ak(^3k2A&zuAYts00pqoEGASW0rR3Pes zK8a<+OhCqtGCJ6Tf8a3NP?sjW4TzCn2v)?1$cDmSH@LgOLm|^K1dLg$oF^sA#x1~% z06Zq7X~@txhJdeI7r#R<4ZO&^`No5+HsJf^jqnewPp#Zn2w+xz(+nLtb@*gVd!>ea zkseSw4>x#2ine~2vc)7aIY{q}oQA^5&*q}T)9kV8H>td)A2wE6yFUaC{KV-^E-BAJ zhdH4+H5CJR7t9w~e~WsWK!^eGu$k%f{7%Bqu{xUf=%jIaXn}`QdcGhY-E_YB?C~Y3 zYl5lcGKx6=w~0^dH|c;%J#3`e#rgY7PCaaZUu%qL6xNEk0EeN2=rX&4JbFTCwZLqt z@P+_wV;cm0D>v{I&+onJsT#K1e-&wcU2MAHID@UU{;>23{W@Y5&4|lx$42E12(g{< zz|A`i4UsVq|=j$;5if$(X}y6}*y;RSXH)?GOX~dL(_c6@5#k97sz~|UW_KvUteKsZRdK^ zQZ;Fp`RW;pDJ72KAaDjBj!Xk^wPeb(-50QHeAG*c+68sN$r9aYd>dtERiJsP9Y2sg; z0{g+9c&cwrtRZ~tLCy3;A>eifA0a^KlR(^tyZ>z;tbS*!Q<$Ys%{-w@1Pp`qJnC+x zSz-UlN=p5X%qZeuj}O1>(K9IhlHD%|>0Uu?AdhT*tJ}()L1R5A{BHTERJ}M#FN{K@ z>B=rO7uj9dHFow@+!^`kf7Q%?Q_E)gWO=CsxO5i+R)AmzLZyV?UBgP(T5THt>w9nsPE9g((;c78QKBURo7(J z)rEHl0vKo4Zs-Q&Poi+3Lf(m^$mU8cUs(W5s3 zFfxC@6?#Byhu-a*MS`auzePg0UjMgw?x>4*HeJ`3r<-+{*t7f#T{jkcqRgYe5L`m0 zQ;;aN=D)jQ4XYn^_aJ~^5%V!mkXbn=j!S?6G495j`#-jH`>99EO`e{HmO&S1mZBNw zNyi$YEz(5tX?D>C*FoY!Pa2#wlx=WMmxQyP2_(s6CT?Jf*wS0ZzWZNslCE#0e+xa) zw+UZ76PTnfBH$-%Wy7U}p&KVC$!?8u+UouOE}fVy%DAT2%;ja^N&=3M9m=dZXYcn> zoGNNa!FstktO$UZN<@TE3YA0sV))1u$_n4h8$w^(v$hDLR`-3raA$ThS zzm-_Qm;+Z*=UWwH<5Tt{)#Z&VVTGzWW^&tAAdvwwhd{niq?YZ)H81?Recq0;5V$J`k>9WeY| z;ePmf`4(2-V2pW1bz%mX<6PJxyVsLi?LgziLNNYooR+M%6O9wA590~9DD@!#le!ge z941@|<(H{P8(ePocfjQN8iGXJ>ut#HOfN6jx`cpP*VYca9VfD6Lvx0>w*M-F#%KI+ zs)x16uvHIZkaNudQUVID-SeO?-Cc9PST;2Ww(UCJeEa(k>ys; zJo#790tnnVJosYUAtMHndf0!f6?s3D#|eZs(JrP5XeI+PBtm zeT0v1GYkLJovIlOGa5j-63S8n0lF;S0qe<(63L$%`?y;GiiyvJ|1)3S`hU!dHIh(s z0AYd$V1vfamCo&dqI&jF;9WNa8s5lH{jk98OX64w??J|@bt&e*X|JudKbH00zn>LJ zI$`MdrEZZv^5M^)dK+<-nps4H!sr+_f{vs8v^4}t^*}Ln+GIi3YT*zA&R@bb| z$RgIyV6~vFG2*f}v0Axg10t#L2a6BoB88;?ZulaT`z^~+Har`r!H(-?{dG41tn$Tq zB90s(oSQo_AT3WRI)6ICQIXFgZK!Kjld2jx0T140DL9D`0b9I=3q|qtFTaz=xW zpOwHUuH5w!=;op5rXw`{>&znaMM_}K*M454MT^#}hqwNYCG=s&@Lq|YD;HspRHUtP z1i>PNpV82gsL^E6XkJ)Jot{|vZ3*CS!$_ZNlzn;WiKJ=~SNmbvnzds?*sPbzPNZcnWkXbN_gww%?yMYlP`^4Ny3R8T9n^)PO zHOctRNs3N%RA7<4Bvf+@^Unx3?&)B0iJ&_hs-0kuZ3Ix#esdwhcnq`_k=(K=h1gIG z)%+I(5D5d3lqNCiKGgDTp1pq&$B2cj(zM1#z~Z48m;DhWQ17Ix z&8pa+bDRV#&ZR0sa-hpc6hF>LKfOkM$H0Jjd4@Hc8FReDZe*$A(BPKB?f%!vI#`Hh z!+~QAnX(VXHKlMuP|`Ri;bJes>>aR2uXwx(HgpP%ZJ2?@89Id_q;76^iE;g{n(WgV z4531y${8qG)!;OZL&ll(Y?$?O`j8$!TzT-xZ9T5*n(qwirQL#h0jjmO~ zSc8wU(Z=m~04`x9(1jeFjQywrY*cYFjYwTyK}hmU48g5eH{9;H$!ShHx#JV+i-Agg zgPetgGyE)WW3J6!BmR_Dh-lmr+u;Ym>MtmU1{m3|fY}hov7ji>-QA>K&t1Hw%TWPG z7qJ%QFB+w#C_|fL{=2`bq*>CVq%4hVGg2F2Y!ZI%zucEnq-|KoicSD4)@LSg4Rq-j zDR5mPKkQA06YsrL$_%is;~!C-VL@IdKg`ILT1y1n?OOH=kY33@WzK@v$d1ax0>3d@ z@H;aOuX)j?!;@%d3QFW=;lp}Ew^-Z(jS4~kf>C(7mNZGYGT~j$nF_44rl>Ue56c6H zjaYq+DoN+tJ*oDwjsnA=LnrOti%3*~89C8%$%u~ogDKJpWxUQ|A&b`JL-!6D`8=e7 zJayy|e|wTq)GXxhUe1$${llX-rW)EB+G^Vv^8+Vqe$dF>YM(Q9jtShbqW99Ucw^_n z;kg1X&A*(~Viqr|0v$P|IN>)1zWO?EMIE1i>NS}gh2|)sdAE<>cY+b};tD?@z!VhKqn9J~hv@u>}YbjJ0x%Ah& z&-(KbAVZM)ENC+qGhr<-!$7eSE~{QnjdC4mbuQCUg8LK|G)hrWbaT4~Fg! zZ_3?|(;6}OGlqc@9$M0IRRwyXr(z++uKz0iKGTSc~*nBDtBQ@qrf8=p1nB$O+gB zTjs*p08ZpDmsY~-9j5u}{Ywnhs~x(v>Yo@T!hd%L8+^I_Jwds9c|2`K49j&`Go>q_ zV3`~8vkY+d%IVukmFh%J?XDdjsH}OXM0lkC=Oc@H&{5tN2rbx{$~F;99^?<)zBiS8%#UBx{lPK=_h!|#SdB8Jc{ zZ@}Mxr)Mx?n4EJ?kgLX}&)KV>EVYm)9PrWH75*da{4I9Z@uE-O-qH~<(;cjF?Kx9( zo65{4-x@I^fExV0E#`>xjH>Q89vUXxAc+$ntrlOEFWk_nc+YB&2%7hy9JHuJ(1)gu z7l5SKGbN!rr=a~3ZI~N2E9iZn@q#iyrcihU4X(%#H$P3_Wj@~@;q_w)6C!>!qTjLV z%OVrxNL3tIE{-GZB%S*M34R?d{d`M)6*!tQMRq;Rne?%yf?xuWgj_*MD`)2Y3(qhd z8q;^0dK3Tjt{69$oYw@!2Hg#bjW@{N&4YFtpat{@^!9fYiUsKljzj*uj-d>Nghl9h zb99XLb!Yx#UK8uMH?MlmMOqUOfw=b%Oo)pmJ;U7}c@K2BT9j)wmC49lU`F}qYY?M+ z0wL0951Jfmvb#9ntVX$>_5$oz2~IK$u2!=H<4 z-U~HKjNTJ&ExI$@RB)|Ze;gPx@nqc6M7KhC?BU^$&UhzC&#|H9Aj=c)Ivs%vcc+y{P+ zLv4gqRSE#)+Jc4wsOMzA$C*51M|6TrK$d{4eceGUi`YS8BwE?$09=mnaLf(c;hk`s} zOJhRx%4LMACc{at>Ck~s6`kJCRebAOf{levf1CS9kJw`Y_LCs*2f?}bFz7AI7)U4@ zgqogxV?xh_@oWc8&+ajy-#PylH+@}Ck&Ajq9ry?{`ZVx{1UxDz^Hvd_E@Uw=byYYOBod0Yr@^j+d-S87t?!(>Ud+)2@!Zfj$ z8dL8AKexcVoykwm6Zym7t}yqi{m86Ix417#1Ishxau61P)s12b`4fZ(@YOzt-lLMz9x14P@Du7$k7qS0p8!(Hb8ge40pL?YGi+;pL~LR&dY^G`g@2 zG2>ezDO8xWIMtY-I{Xvr+_NNz7ikP-ui1wZu)sjLJVPlCn8heH{C?AWILPIJ4mdS_ZI>?X^7l*+5 zI8cljO^V-kN{VFuK^dMGy#CQm+<$`|y1=iVdHk>Z7=}@2qhJ-xYy5*?QCFsYAY*MT z_lt_5d)dY%XhS3+q_=cRLTojQsP`=x!cNa}QexFGm6eBT!)S6+Rdt1>KaoUgzP zejl`N>_CRibz7G;@Z{407u&^a*O3q}mP4+}HUYzYznY=&o>!+CkvHxJbmo=o^6mod zpnP`H)rv<%0$Sdt8^jK;f?VfFJ$eSmQV((eDO>P*h9O=8eAzNyIp*~NX;)3>>jEf#*IvT6L5g%c26phXZhkYyHb>6UCQoch z+WUR4B$vaAVojuJ7ehgL3Y_2qXMCqM7h|$KC}u&)|I+^?twiHveYY?|B3^M$s?mhJ zjyz;!F{8(W_cdZ$2ID!PpC^ySG1bdgs~Se7Mn@&^kt!CAM&DqskV@ULd7G5T&5^w zn$?{~U)XogYKiMHHI1&NxG8U9WOujW}tp*u8H z*<=U!DG~ReKIK2Fp`|+q)C6T^$4Ev~q(Nph_AH$ayyv0tiYDMlF{@JFbdmcl*_k_@ z8<4)P$M4?XWU8WB3~j_son@A?9UDNH6frd5AwA8z*nuJ5Q7J#P ztJL+ViNWwYX?fiIY_rr}KD5yr!3Z4x+KuJA?ALdE;}=~2kKgFCoN|J9(e)rq68x+_NUX%gHi15(FV3H*;6 z#fEVcQMw*))>s0o@5)qzM0=;adyEI37qV1yo-8hiGx%|$!y`kgFH;zZR`QM9@rrR8 z5{P6ka5{7Y+K@(cc4jMQFgU==Duu-9&&rh5SGAy(?N~?c@r(+9;CjI>yx??Ip&UenT^q zV4QHOo`suMHexpl;6#m|jWsl`7ZVZZ4KmWw2p|+O|DBEYY1lpeX&i<+sGN3)9C4kI z3;n-z9Ov`F{C-SZW_T-wfV=(`^G6}JJx<}9-wl(F-rhm;x3;W4o7k403=8;nY+1Qh zF+od2eui7Fu%T-8z)`6n-h!4t7QL(BM@# z7WB3!d6?!es$foc75bm>LB;GLnezXY));fisVNI}{7~L3$(w$55bm@MBOZu5J7^Pu?*Ru1%o!vyou!U4kUf#1Vo(AFLaIOaMNHa z?ACtdyL@1*;1>s^u=l|41=z>`b zO!2A6e>ww+IE%tJMN@j4Sime%`P7G#;tdf!h?f^%*h2{S>Y#r-GxFuB-%{Y2Osc$38m9-m~Pf_ zW=JnzNEKYQY5Lk*sYp8uVJU8I(7lm#(ZqvIJX2nv-7kUJSJ|#sQK)}|B50{ySModv zV^{a@`DorU7jR%~m;Fa_a|S{Iu}deaKH(EG2z{iOee-=kLrQV^^DPPFm_2RF)Wbxt zpB=}u+(<2P<(M0fP%NLcHB@D;#4!zzjua$b7RpFl1v3nPw09w{PA}8!)LB9nQQc-5 z*}88kXpf&Cat_$cLUX(Mv38E**=Lk~S9ceJBT<&mDupu@Q9Tjkml)0PPNU%whVwjF zF;_I3HOoCi0Y7al+pcV_;KKW1?imzc_vpm+l*jsaZO56v8jSbnlS-Jbt1#`2;srTE z2!=;zADm8e1Sg?0XH*k`SC94BKFD(v-|66XSH>X=1TU{EK!vH?%x8VZy8&$RD+f8q zcy1-&-8#IW6{GvIv2uW`TrT;}CLvl7m~GO%KArLWl4}r5U%{}IodhLipg(2t9;M9= zL3-K;>UeI5aA0xs3( zGMZxdK+EA8t_=M}B0(Noa-ANc&ySKZv9L$fDTswJjZ)D;#znSzNpJh}uYDT*Au|=z zs9nXZJa<>Dbfk$5DpF;Jo2wt>=R#_~z|FgftNzQrzd&yv5-#1!(Aqz^6MyO}*Dn}N zyT)9bwo;D->(46{A#tfNRIAVcMXr z^k?>;Gf1lo3m(zTA=s{}TO{|4U8wP)RLFg{19E=ywjgghRPz>45bUsV4T=TFE~=WE z_OMJ7Ri{^`jf?xTJc`H( z$RFIoQ#>AGs~{^Kes8v;jsa{+?{H z^T~^I#oDGMh@{h)+|#=;PRC!3PC@lb#qIDqH2XWDraBYsn$BipK;Q7^EU!j&Dk+f>He@TDHQ?BHVUY@8j>ZBjVL(1-W$RQ{{onn(>^FA(XUFZ}re#F}XW8!QjT%Rj z(5=a`aaTpyU8zW|vf1KV?V&lOmZ2tjrWwBZAO*MPR|~Hty)*_2PEw=2x4WSaU|zbwvHXKul2K&l!+56uX(cZ9c)aiC}#1>}$Q zp5|2k{iOCoHC{S_OuALmjB$Tj_|nOr=Oyu76|1a0TT5W!T-hgYB>1Z`nDVEVp;zDl z#PjauIA&qRq~5l&aCHx1OrZ&ES)_)!9`)n}VX_{)S2w!&s#>0lyU=oD=j^WnN+o(! z7-g(5Zx)(K!N!k`)*Z*SL8^1+3MS%4xq{L5MwyYg0#kz={_liJc_^+5>OQnI;|7mI z^z2*c_a6oxtT7>@ZpOxuP;L}uhc1MsD0gOkA)WXLG^pJ3Reb;@+>;@V#wNm|A+Pq z-rzV@Lt64k5`-M=`S%i7xSkLpv;)98;@ra?mso9Da}V@ZWaEr>`cgDUeGeNw^JCN+ z80Ib%LIukGY{FdSNhZ<=)4-`T4J9Ad51*POyl(4npx`~q_hHEFPwEFW+*_STF-!2yAloO|7%w_5h)dj`cfZeCZ z(2uxio{|k;tXtF3yC?dqx?H(mAv@gcumQz(!ETjtCr%!EV3jCftc*)(2rn!Xf!THs zetGIIOG^eqd^ZCn!36{xWUT}>rU>>cX9IxTml#;CINjRTb` z6u3+sGcN)+Y*gdi+6^tj^z2@(jbb~DO*ZFvC=1srH%Uz+sx(6B*m6o+4$KLCZ~Gj< z1ANxLqR9z;YHh&HdMZj?*^p#9>d@!`j?i-nP1d3ccNaNe`$jzMdEXH#jmvCPGjX>q?Myh^NK})IXLM6GOfq8+s zpk4m+Qd_R{LN*||CF3fu^isO(b=SH-e+v33WdSV6gGmyjBkrNxsPxrA+_%zlD7DT7 z#%Vr_=VW`GnIhX@*gqby(dT*_pm?qGUs71;r{?bCO5rew>c7XvCT^ z-~(r|>;)Zlm9{b|%FgSM1Hr@ufr{f=qDsKM1loqa?@B}g;HtJRkV>O>&oI>_Gqa`w z1J%-9t}NmNT?#EE~J+4{+BO2vvcXe8^?*wZ?77N;3XSM{09$SJ zRW^-Ti@w`Wbo*En)TK&_S9(*QvY!go6nBw-hLfFx9EF%Vq!C1S2h&(cW6{{VlDAF! z%aR>^nWnrHnMRT^5ciH8`YyjJvJ%>-v^>gAp#Ej(rVj@OOlt<1zCcDL#4l%%UC{Rj2rvA z>v=~~1Y%4{z~cJ&-0Bb}GUq)cHL_CVmC_6_?7n-SaRdzOC5ADPrM_Seh;WZ*6Doj^ z3%wwUeM)u*59wD3fk3(lQ*RL$Hgz{5@Wh=>4~*6^oMvB6$<4+LW>)8-HlX;mX6$q1im78pWF<5$M|J` zF^b?oxV|Epxfw~Ak)Cqj1>Hy%oi0ThK?i1k5oYY$FK}3UEnT@8xCR`3LL&K>9ZdYz zbCAUjK1>4#nt?HcoOqYKg>kDivN6Hgofk6g;reQ;;&MBr5ovPSULsiF6jp8knVO}>F!3lrC++14(XJV20^;>8@_+$w-Y-v z_uLcDeeRiae_tZMhhH4EKd;xuRlv$-pcb!?C+umBT`1(Gc{G%fBjD=9Xtg=5h^95Z z*`9Jd{y-r^b)v9-_Vd!{weN%&u)L)n$qp3)a8MKc(9LQXpB^ahT6m$CND^a@yhtDQ z{|f=@#|3pNk?Bf7WKU~yFs-{>=mO0ZqE1=PNHjLbk*eCB31;n3PJS|c%UY&w#zCc@ z%lN)doX41F496$zJ>vg10N|*BSCe@h>B0@4qDJXr(u9TSQB zg(QXX@q{fLfoTmjW#XP-|KSJ2@s?Xy`Xf9VRo2{O)#M_2wnNbTno<2b{`S zq)|Zr>ES^qR(I$0lklCHw*6Y6`vGa|4vPf;wL6PfZ%J zy%%*)%{Su3!+w8H-M?zo@F6snWOeV(*v&;o-H$snob~q~U2FUo>>#sRkxZqS)njcv z=aChlse>nd4Wc)LL6DvF3RHO`X$yf67pW?`1}xHxZ#zBqATKYvp@MlFdM`RT z+<6=!)DY$9?a&3BoWCQRDo@{a+@!2Wv;i1<`t^X*0n4*u+p_{~tw9-<|1)EiIem5Q zd-U&bET<@Fe3fa#Mh8Nbr`p~8>6a^UE4GrS zKY^hZQ=SJukR#K$XBAOf5^~n(K|^$;Z_KxHWC?9>e4gCWGaFKc>?l`&Xj*Oa2HS-Y zlCcN8aPvYNN#H-taKR2CTe>w_nljBLnaEE?)b_lg&*rO0mnKK_S-_-$xhb((W89fu z%@I3||DrMpCG+>FU+t<#7J_`$v<`q;XE~=~TUFB?5kif6&i(8`U0yT3Q%w@H#%qz2 z*_4DSI2rDQ9gKBt^N}iV=L6aa(~0wHqOev{aRX6POgLyR57=e;zea8CaY=BC4X%G> zoC7dY+V{`c3#@ihRtz-ba3hUT3%Ud$-y-2Rb?a5|f7I_$uW|?OLg)Ec_V&DS2kBMruX#eMvq20u9X(WuU_i2ZT?^&>aJyV+Kmwp*XD7^Gqy{8;+6ZV{Ep}}r z=v67F3YZZ2{v4U609G?|OvrF=<%M*?QzMR@9~PQV0DL08A4zsq@~JW=0-9sarAL8Y zu3~d113Xx1!-3&_;~E`R9z)Nmk_lf{mcy%Cp3gz*g>}M~vp=`447$QjJx#i|dzWOk zniRZ?7<$yoImeqZ8gclzWNh~btJLTm{;QAAdU0VP-Iot;@MSZr2k)NAoG;jeqJ6Q0 zWyF5ciG0;$j;9#~ZFI=3Bn0lZZoa?vp8ejj0PYu@{5#s4NTf)Y2Nz{=4L1PPK65;h z2JgWS00yq!foerzT3MbnIn0ss^eB8_w0VXnVi@SgwTJjC^-EkF<2HXaaCV`Z^8r+5 zE@66UQYxbpekB;$52+?wwu;R;+ly}#)77z@&={|WMbkL&YGzc!;$NP}&|R=r+Z zD;X!^iPv0=s>4L(R(iIws=X`gRDlEH-;h;PNJ#Z}!4>A$5oUiMTDoNFqatY5s9leq zQOD~sQkOvmvOzF){`gCDA?;>?)1<*_IA%qhy)9x%S6TBjk~1#xPelYJ&p_#oWn(0{ zpcGtK0vt{7_`lyjX(-FLgkVd??q|kq10&sfhOKiYp5cR}?JAnCWN;Me*}+Z#C}Q)& z9kYu^Ii+(u29v6x&nQ6hcX{9Dt2`4qM5_N$|y0@)Y?c+6Auh`a}Cq z(38nc(+RRcZ#>EbwC#9b87##RK9w9DH$!Z#;si;v@K8bciKxctq_6CJ1C;&#`RvY2 zgLh4^wS^d!XA7h#n5K!lej+y0cKR|&Lg}g!ziJ7!)(a_71ocXXl(BwhJz%3A2)ZHY z-4%}F&PxKz$fcSXC*ib1t^|!AbM?=n@544TFQ<^lAE2{@a>m*+&1INIE6R8LCT|V@ z6X{Q>wy-`;4t8(iU)rnRYekC5>EZlZfJ0sXHc7354CnXFRGg*+fF9kCw?aRGdZl7T z_4lt%W#O#?J3&A`NEJ?p0D{{Vfo8%A{o7 zsZtGSoL^@{bvm2J1ZwqpNt#UER}mi?RDd3&&rT8nBuLd-jT}iMG2n_3+1yDz`FBp| zN1a%rx~_}>z3%#6&CtG|ysqJ7uDfz~y?1tLAtxLmpf>h^+B99wJ%+Qm)FT;~bcwlW zX(>2g0|yQP%0NDVH)!+iB||5mHN`iU&lUvsdxQ7L|6R;fX6OD>1ZQp9qyZ7aEYJi( z)l7ka<+2WdF{he)POs1VC_Ko2%#SSu>xW|IpjNLcQ+dP!`}cNWvLR|x0j!h^fU8X1 z`))1?;dmFW3wmMQ`kks8>WLG0 z46m?8#AvhR#m@W)LTAvU&VaEZ9Mw4pqr@OV>R?Jf|I&LPLrsB*%0fgL(6dPf`P({p z{WBV3doyCQcGK)$bvHj8BY$X{i1jot{KSSeJoU8*4LDW*UtC;bVO7MK<#=D>_TZEu za+qHt59O~S?l~MQTHA38c0?2}`ggVu>>yQoY_$2nKrLn+XV^kN=+_ic<$Gq+$bYHk%x zJ9S;>NVa@vAheW(1-1660o$UM@yg>^$rlXk=7I@RA9nd1mVjY^d@!YB`rEHUuW`pM z9K<-`+cRrB8#B~^4&E5=8%G5dK^3UXnL@ue<$l~r3Pd2lRrE9& zYbu~S(eGeg*;Q}HO>t3W1LP_B%-F$}0`T`v--x(J==bc z&z0XTp`8+cn}lA`ywAB9h5?r*hw;bSkBgjS=~{o%egY%niUeLAwAUJWQlPQMgwO+D zfGVkBm4?<(6r-{xanD0P!ImK&$m>1#Jkq9SvJu@d(SiGUJD9A*UmAa}V*?pRR+^** z?385eK>3z!=f207#RU(-QpqIhmsv)QtIzCK$m-!pKR|Ax$^cz*Y8|obmq80emaOuA zc4Z)|apnI%ypIwhoq@q@Q_)*lE-5C73m}FkX+pv&LOaZ^RY0*NI7)X4>cu0SdRNte zrkoVpy=yH4!c6%mP>5>6QuMkffQmeeaM0GBXB(EOg=f!EP^M3TtAmQ|l=Bqf zY2kk9T~3KaW7StB{Td5mr;&pQAx#6;P`tUP2DI7~!!*#IH!s?hoE3;sa*8w`6If8| zLa{gAF9ED4i_b`sFL>P+vUFQ@c7}jd9SQ-__&)*MnMU`_5_Cr+ z8od|O|z>g<-|eto6C6&a0?b^05av1$O|3{uX_5T}(O^szL-6 zvp&CcAc8`&G`qJymH^7kje>*5q5+?%s$REcT2`K<#uaya;_d#kJn8iLhTN7pwS^vRBOqWTv;nVLh3*!-&sw6RQCaObFG0#uqBnN%fNpxzt+Cz{FwRy4s zvaiHGrG)0ZuS6eZ(7-XIfNV<@yNj#n@d}zJ(J`gZlnz-5NuE|<+2M;HQ#|;QJe{7p z$-C+7!P~%yW*Ly2cGZsML5+#XxS=SsUUl&<=lzKuoJ9KNL{g z2g*L@wqK;QM|_zqd>s(5qVuI`)kWRFguZoIsi-{}0LufS)8{tnlq-Vl^*e;auo?@q zYJ9Qar`--g6z{@6?7UPm_>WBkH~lXRSRQLd@@nKsux8}|A36hB3FS0d&wbfcSexyF zcM}$mF)v;$PS4Mj+bv$KNZ;J2L`a-5NyL>rJm?~n_L=IH{!c)=LF;i-x~-8_pM~(P zD{1{ibw`J>bJA)JYA4uY=cM@*6t6PBSfrNF};iNG;aDlzrM^$Cs_ z#rUFki9t$_o98cfj9uzN3|?mEp*H7(cIQlXFyJ>1YT~aZzb|C)`w;FAl0uXSK%RiV=1R==Snlh5GfJ$UPlI< zV9Z1IdjPgKSiV0@TbQ>xdZ?LggQtx=ux6b+xl)?pdV4&k#!?sbWcp;yR(J z*zAMaLs^1IFH8zB-whNJ!3}{Q@|sFvAI_Z)L8~Egi?w9w<0r~{wdl*2R7gJ0?_s(F zr%OUGBz3Qnm1cfnPL50JNi!YG5(U8ppBJ0zn?u)SNH4~>kH9VSHH{nD}^ilNOxe9 z%Qf{{4zV_7JS^HJmrLCcf78~%M1&&{DBctLwj2n1fv9KRHe`{ZcA;2k6kzQ|-%~Q>sm;hlrZ5M=5Gj3Rg^%Hf|>lDZa=EqdC;)5Op0D=1VUA#R57p zk3Akvnk)jj_bIipeFA^U6LN>!TO8Vh4>9{pKAGjh!$#9U+-*5~?h`!r>W{YJgE6}4 z$raFv=_Sg9L&Eo4;%YHiX)XyWb5ETekZBx@<@Y%({AJFElcCbR4Sz&6_8T)PpBi(V z+g_R+e$x8)(E^+v9+la<*lFgFa8PfI*=LxuLz-v#2!n+qonUd2v+p9E_3h?gwcb^h zu|aEuoxR(-2|>@bHL#%@@M?9cZ5x3}x#ksI0U`E4IgttJCM1N7I~_ys8$; zvE2%BbD6O2RbGi7Uxdt8+Y_*O<8*8>#P%NrUir>VXjF@T`u-I*0*fULk~SarJkWX5 zNQV-gN)4gdrAc6wA;w*XADEmHX2jyy(C@yl%x*4CpZfA47mw0|6h6UUj@lY`?8Q5N z)8Yv0-6}ctcs$OS=mA~tDGY^zF|6`oI& zO=MeXO)*$JVQ!T>L%iHDU^Hn4Q5%oqY@j z@ETRb@)*1?Hw|72_WAdy3BixJvY_B=b5gNX>Twqb9Rrofc2NF_hWuD6;3;W|ZG4F=;F&z$ zx)J<~5L|uv+mr$e-X?tX3A;Ox-s^x7GF+n6r-Qa?FN2L1i}`t9bZGJkSmm%4lhYl= z5(h05`Hd8uY`RQYI#MFp`aUqlvu(jA(0a$V<-?k23dSVxAwHh~!|IeE!$E@h_1}QP zrKjrjnVxc>L)8Cz+NC=;iK>TY^S}H3eZ}N_mT#j@Oi7)p=#}vFZY~BMLa>36J6=R3 ziok6w=c}AmQDNd3&zZ83&68aEkpvOaWudp|DUJo8I!zflGg9SIRHt__IDxokXfz^5 zuaGRp_2q+4!~UDtXnLuCOmwUy%C|35*SlxR1j{eC4pXNll_uBWy(z&h2E3rQu1n7-eP9?7G5`}u<#0*DqNZknZa(A*& z`?GRuONHBPybG_P9&uoz@+X$M6}R%|zzW<&y|}?)6t{S^06VQK+VIGUAy4UAX-4EM ze2zQv@j_4dP(48zU~^kR`=or?j+Ya!A=PXE=_0aR)09#}IZ#(29FAw$dGbBG~v2sFGD9bLK-%4)9NJiVb zjS-mi(nl#_kXrs*OE@AwB?sGR%)-s~HcO1m*AlBofbwhGQ-FFhe257OcGM`Yw-fVj z$>RyBA+PqSqTme%JyDlpus}@^W%&=N*`z7NmPa9fM1hD4*@3J-A0e5-Sil*#$z?4T@%YGsltj z_tF${wkpN$Nk{nbj-4+sazvo#^a40`DAmn_93+*T44%Z|B=TUPdQ4$_zyFW1US9%? zF=b9ADHg9zYU#Mmu)--d-g-<-?WaTi@{3mol;d)TCbYf=PxTZFYc6Fu#4 zl)3uu_Gefzm9K?>QiL1ph)7Y|={44Y-(!}CEhkk~#OEMRDzKCn=TgE|(&RvFD^7mM z->pL_c^9FPtj^F$htjpdlF_J(y6Q2^z>Cgv{+Ls7PP1^lS_D}?=HEB z5|xI2Oh`%Lw!rDo~Q~o%c3Ns-fnB zo@#GA6L>S1k#?u}_5tY9xntFembx7kx)U#OEb(z_M z{!W2N8=WR?;Lk$lE&jS0ZBceVx7d3b@by2;v=#GH3CZX2E9bYOF5pmH-ee|2Z0Z9b zgm_2lYPm zg6QYUtTu{d-q4}tqA?H|V8ZE0LWJNW-{U8N9|_8d;%A+adbY{GNkuJH+}J)rD;Cy&C`NIe3!aD_Opo&N)PER_=y z{D2^0cPt_ACJ7G>D!7w?`Ybp4tpd?}3~IbC?UzKHmti{g_u}AAmLIz{z>T@oLsg}J zSBU&0QbiQjlej&B`v~vco+k(l+BhLtZf;B)huE}E*EI5KS&lY2^^vECsH^zg>74cP zE%CWnyq_=vf5|8~-8IFx`gJKMbWX~x47YLL{yN!S<^8laeAq2`+ph3w%-({Xg;s>; zlOzAld!{|DShs1wrf=v#gF;>LaV#oz$WTKXSp|-qywRPV%5{9~d&Oy*=x#$gC{@Ch z9L+@?4y>LAWLl*NDyJ1$8d_;e0-MwJWEm>xfMvom+!_MRHZ=a*aZp-8E zY^cnh^ zVhe5JR+Wwx<4m+X0TMzL%ej+Vi(a(-88Z1%pYO6cMs5iijy}l=uyPxJ-p!JbsAec! zAKk{&loMcJGPaT^AI15rMU@l07D`Ta(hUDpkxlvAA**?7D&tbNSd#J%~)Wf*)?J%o8k$Gxh!ilvha@eIpD^J%pp*QYD9npbn z?;XmAKdG4?B>pX07CUuP^D~rKNR(+{-)pg_01Z=A9^5i}*2AwnlGYKGH<-9U;$vAW z`W!cO=xzL*)g2ne`u>#4J|K&VQ}-yeeG$8E5!0vEJcl+d%dR!#qVmcmq$HO%t*?Tb zuz9v#P<*a)Oix>Vq~=H-!ZiAqUl`mv(Gv$rCTijoYy{oyiG8}ttn6~mi7As%MXa(_ z!PjYt!YskbrK`a%f;w6F1;EB;6hOTi9(z}r4nw13D?_S8i3(u;8{8a~E4a7!zJERTSskHFlemZuA|RDKmUqFvr-!IO~|?IM7iTECzOKlaN?YhaMtPPb+b?AD`() z-k`w*ta<4pk;m*-?gb=Q7z3sSDqI$N(GX=pEa`K%f7Fp57|+l&PJ774>>N1ECuPFV zGcxh;|`^9i_@}5x&?ypeIYr7e!5!O6R7Lw%%L`H5+7v zxH#20zOCkAXEbA^pi|zke7+lIgfPwg9qk(#u%ts1i`~57JtG>E{X}#4K2y;Pdx)9h zTgx1<39rTZ%>IvBw-V|47duR6c=LCuKiV!fOOOAJBMgqEhqNsdyrK|Cv#tdatF8qM z{7-|zmd^mQY?`$8>Xmu~*Q*vq^cbVy1v_^5H%E8GF--;`1N}^`EJW&Ru+ze9Q`gv@FeVft(yYxZJirL2 z0D1m#hgEJ~X+#<56Cj0EY41W0ji1P-T}<$MB`gc-R?AI>tpaFpbNj2os z?i}7G7Fr_ip9fQqIW&Bq9dV}$_OQd_9LYUCjG2y8>edDOxC077L+o2ZKsb$TjrEzq zS2(z@sYcGxqW{rQTsuUxyJ`ak%Xoy6D2Sx=2FjLY6M)>a=#ACK&0#nq(8z-Q_a`3Quj0@ocPVu^$#A$%n>D!h-V)(#IoKm9(=aZ6FmIY zqzuqL7nB|WQ9MWFb(UXM;ow9D4tK05MdU-0%zB?qA&fTPnrF0G>YUb9@fX5)1XeeG zvn^Az;35m-y3CqEad7o-Wr2;!Tr(CDR@M`^bUg*oQZROMaL$U?H5m+ zE7$?wVw4DUW&*xmfF2{`h=Q#t2E!!+P>5@sEt09JuI*QaxEYP&-uxk7&*^%&|C5tz z(qX3+}4sw|d-owkpqQFB>cMCDV%MABVy#&jZ3Ibx?)hqypj#OcfUIDFAl z_MPfhV^|A$kG{WD4|!k0zfr8oFEYtnGwqsq;{2Hnm~F$^vOG(&VJSJ@Q5lNzmu|<` z#(w1M(wAypV8R5i>{ZgK$tySAH;iZ3fG{Jy;2h&?``7^Ig61CK{oN$M2Ugbhp8;Po zSE2BgxAdCF*`Ij`4suf>EO}O*!ntl4iM&zgGL7zCht%R6Uv(#fB z<3uD$pWvxwIxBU5B3HM;0ggu z`lHz+_B^w43s)qtCB0;Vg_ehieqY0f=6Q~-LlULw5(Cp^Wc>zL9}O23$bU}8d1e=* z;OjC_*zX@6Q3QF(*Rk)8e1dHq+Y5=t0<}n*-=MsYSZh|qwC^)2i+9AH56jdvZd$wX zI`evO)p|wV5*b_nd3)RJmyU>8kwI=#DlqJktj#oyA}bE%{fs1bNKe#;nP~P)RwU~- z`klj(u#%|yHJi25K2;izzbt@Tcy4A<8NKCbWN!REXidq{Sw~+0Ni&GCGShZkkv7}R zu^;%nQ3skr&$J@feMTP0A;Vw4Z;IA1c!Q2G$uk}|sfe72#~*Gi0wvUl6-5wkf25fb zv+HkqasF5n(Z(p{GzXd99MN17v;SuPxJ&hbT5GTzf?-gI&O?SmjZ+1d{!WfDd zZie?&%zi3ySGe;IMb_4>qeKhq5hiw2)ai&RZMFsv2em)Fo^@pAjE1*NE;Y=H%e;9k7+`G=wF&9Z$nitd?!jR?}!UzLFe4P!7hS3RDe)u-}s{* zk}Mj4;J#K6OCfz1Z6`y!XQ?hieJ7}^Sup}9$*s)sw-sC7AR0=j z$jD;mt+s_NPi^8iS5A#X{*%^rS{YryGs6rj11^p(C5UI;#XC0y$I8vyF38ZH*vwHU zgwyAGAhtySHKq>x!)X*fI+X_+s#om_(i#hf)IXja0xE zgd0vYUuEEMd>&nR417B|1jSQ7OGMEU0sqPMxd%d4M}iAnte8#KrQd*y@8gsf!IMC& znB&%gVkGD#K5AIxIc)dU7vRu6QIZFtkuqc(Gc(v2OA)byroA6IGfHlls26Fs)X0M@ zE`X*Xl_*h+lW=-vUGhc_$j3HiXgqi3#<5{*Vh1TDB}Cqub2G4T&?%)_P(OQHukfz6 zGe7Uozgc!J&D-}AzPvR@G0|QUQ@QLU^Vi!M6Xq?JAVGWbpmu)IBfB9?k>Aa{p{9?6xFXM3*z$vo4ZyYg?>zwnAJ|)QGt_O1Q(ad zqO3PlsOhr62gne5xR!jl#>?-#~Dvxe4 zM}<68L_ws9`Tk6sm|IB1L48V-!W%EN{W{do`+VZpu)wT*Mb5mbM98K+7Xu+~h|1(v ztU(1=F&^%K5@p&R0q%hE{b>)3V!9e`8!FUkY z^KICx`S&SC>`6bKu}ti1NXeyCc17aHl$KnM3rHxOl^D|bC^)`dy-GTYCKD*L#Oz_` zv>LsoQLG!sJsXtFIz1W}VNDtSl_feR;Gv)Xx z+(UH)Y*Qs*3i9_^sLaMe3ds0vxe4O^ZQ|2xpSsx~m!&HA=_=(SM%>S(yUZdPgv)1* zmjoAAL>8j4;*NnCro#xk7eutXwjYqO7p%$s^=}9^h5HQfF1S}>#i}N>Q-}e)*sh8j z)s{Qk(NCaq37bLM+F&SZS{#XmIqh^X@p9} zJ0_K-U0P7}?#}jrZR9rZnqXqql%PHtPHbItlNjP+%6vm0>oYPlfu)4u?+EyWv}d#f z$rsMR$ADFCq^)DkV>Xqu>HowegU^)8XMyw=c#Q&pzXHe0pBv zo{r86lJTNxiowCFK;M1$fNCN_vpR%1A;*8d44ixnNOFI-63yeS9dq?7Cpl;1+Pb1G zKIq_*%5mF7$mPL$NB8AVy*U50e8eZ_z(?w1y#pB;(TdoeUfO>6vn|47>mAc)k&^vS zN<&0+%!XEAKsnBH=49PsE!c2Tu1x~8TjTi!4tH0fpoDxw(nXGKV!*HyEeEh&OvSpn zV@~MDQb`B(=>4-Kr`{WQ#pL0OR~%d6tR>i}t6~6C+G}&(Pi;>MUX9Zw7w(!eKTI+|Zv|&?>_G zU%db@4u^Rqn3oHjJ(jae=dt&@sQfO9!?MIDvhIg}y1*@Ry0y)}L{BSBDWW@he~}5v+&_c#%w*3C zilT%qhL)&(_+LftMaZh>>cr@KQ9Ac!tw&fomD50B+;|bgt_qjnkszZc;7tZpHx5zS znn@E&G{0jMk$NuSEu}}?*1LVzfT{32D$J{g3}}D`+-ybMy;Dn8c$0x(U|v)S&D)wa z-B%l+D0Ne&BSKm9MtKNM61wlm?76(~5_qXI`9v;_OiF zgnYU7Si%Wz89ZEeZA&F4dJ#@#PneQQtq=c(;;=q*j-7vqH7gtaBO^Bk3x=FOv{^%rh8XfXxa)$LAFQ25@a5VmCH<8=ri3!MTVF>oLzw zHLBdZ;6iS4oj!>`m83fmd^1)TYMNZRhv#-r4!Q8@sF_MQHCJEsj&b(E>|wxWk6?mX zyv{g!k7I!068rsp-Mj|?gBM9ZYr}HNW?v&WYUj>sP^2_^)FIH<19!V_NWATMhx9gGR$=^m;>AAJWj_&{Su=c}Q)fRq)4+&|U z{LNFX@uN=vnp)bdzuzSA%@3NR;2_Z`2*j&D>j-vJ*eFXSm+n zphx4oQU1M~=WzNB%;C4LRF1$@iOyiI=DWb+xzuzAkEK<;SmjAgipQ^qvz!$yz@vJr zpPP4^65gEr_wx<+XhyH!eI{uLkCM*{T+W7<3RV@%=FzoRVPo$40QO);f^~ zWFn>PcMn>#mh+K+v3wONK;7*Uc_5@wHI@B{F`h?)y27DO;H-iYzDRx3l zMQadi_y2Xyq*yvRxmo*=s$7kuc?~YA-1K_}?yFR1m?^taj{ZH{xMT~aVl90Bp?}ki zx4pZ&IWqvuC!X^>Ujm*va9MvpaNF8;#FQT6{%c|NV943Bj2(SqXLl3hYt6vN?oQOd z?rV}mMo;@MS|A3R>KSYPN{u}g->PGLYTmNOPoLhcwz|hE_PDjQ)Sxb$>L8>{Uj6Pb zZ>cBcYslb9aW;!C?Y|4tmvJ@jpj*L&iyT}0?_Xc6ai+NjPm|7@f1enINN%rLB`*ak zxDArUL;}BbKv2)vtK1mKC<&2AViBBC^hmqO2I|qIXFvoX&p{4ZA`B&lKgBdJ+NY%X zjO&ksUHGIqD&X}?iZ>-CGaiv{Eq=`(aK~!H9hZreki$0>3K%`}OAyuGdz{fAk96hq z3H4E?&U_*H#w0WZPqrP50pXA!Vd%}Xv?}TUy`uN8O)UAJ*0MqF$aOhEZa@@JI;_#6 zdHLbU{5MKl%3ok{It-mwlB!)_P|LdTOZC~Qo)n*M|KoxIyktOR%)b*)x{8biK=KhL zXDApW203iQ`Mw<=6|*dEy<5qhoBHIRXLzovzBnv<{>=FPx0l%i2W86qwtAdNze$1i8Mn(gcSkuVLIM}Gq-!_EU(n9V>G zR;u%z;Z8JPw6xx{nRixvWL7tHG_T(iE}yB3DwrORYx02S_|iSMoR02lf4(SoE|ter z&hQ-Z&xv)O-N$m3EYjR*bLS@ZfXdDu08}ylOy+Xw4u0-v^EfcSqALcL94GCn)}F=s zeVowj`6p={(|rgyflg4m)0mIZ(PcnU!9hp&Q;{Jl8SL+mICA_g^errbD$3JYJQO&eB{lcPs(Hlo z(PVEI3N>o}NyW4TO|BNb54tR^Or%;3Vll0;^qF3{2Kj%?w*KLd;H)Enc(^eRtc}A= z!Iv4v8KJIq`(^a}mZ!Qm`Ri~?iw!fXK92LB`^^_iQmPvdszAg>_Du$tv(+VbHr=m{ zbqK|$_(PtyhL2s^;S|Lgz|o>|`h;r^C<$-h>K3TwP)d@gLPMF$=?$8mU5XH&ZlXD@ z-DgntMycN4MTZL9S0nLM4;`RV{;^jQQ}3Hy9?9Rgj?NN|lT@=2V+fcIaLWd%E^p`Y=_*@u_hp^oI3aB9_9P6yjN?LeiQqFv6ps+ zw}duvE!6PaUvS+hA}p zDJlz6Z1(mh+^WhHv-4<6O;W}}{F}eZQ`$dnT57m_|KFOm)Y5x@MD8kfwVx7Gw%v2C z$Q@+M0;gGtNeQlhCj4Xu=&nO=UHyxeL{_QL`4!WKY#fCiwX?sBuJ$ zV93_EU#lEJH;uz z?&9e~oQHwZEiK`Fn*76$+H zA3wFeYeqW(AEsTD@`cWY8)`CthRl9t75&k>DTx-8E*_?g;<4`^17FLohO(CYdDZ+Q z*)2iA@ZOMfUZhxe91k#~a7Rka?tXZT%i_`B>QJn|qK!s6xH+mO;=gg?OA zX=`sAh@olUI`GG`#lr;W4SEuQ-TDrE2ei6HI>mM$S*JI`?kTG7Db*eXW3<5mzYV_X z;NN_Es1x&L@z#Iy9`P2X`}kjhY57}5IN$WGdqx|sM6ASF*&Y)s9Dyfl`5?bW#rxJZ ziS}I8xl>Z(2%L*i+PXq``Hl(B6~RQ)GkEz(OwKfGAX{)c2{Fp4SL7I=-Nh13&-DhE zSKm(qxf(=O45-#tnXbWRFeQjf(c3glR+^w-vjHWD{FNY=p?5rhC5qbTd+!++*$;U` z$Mh-QRR7w3SYEjFuC{Buac!-7Prr2`b1p5k`K9X{0mWy=H2E;}m~7gZe^lDP&VoJT z#JYoZQ#0UyQ-zG_{>uDUrxjpTE~w=b!%TjYW?Coz>+EuNg;Onut`6F8xS@~Cj)hK6E=%X*-Ke#-KTnTXj6_w&rhz#=Z7?Kc8*naA$2 zD0lc~Id(B95BNdB8<|T;8Yy!{c~A|pM}(dv;BG_wn#e@Rogcvig^2Wo<4n(Rl7HVJ z5eY{WvKUg}8l#$kUj5d*G?Kjru!f(;Y06htE%jxCkP*0E2q7u~?;v8kCEzsAO(=D} zk!}crpzas%po{L42FRiz7eDD;VJ#nCZ&0vn`d$=_8ld%lXcLhc9ng*=Z}A14qCCAf zlEd$ySmDeqQlStWt@nU1kloy0cdK@>STp#SEoU^2vkIzfwG^1{%%T+#Rk(gs{k<9x z;<10vce+53+^(dN!pp!u_-)-Aepe7Fk!aU=!&+ZxVk+}9%S%kAB)H6&gHLLMwl_`? z>Dqzf&4(iC4zf4bfCW5l-;9?!htMI|h{RSG87$&T6HwGJ*qu=!e~BT&y_Wj-GwvHK zhj9a4vzo9Wln_0U?4f`e5zTE6>-TRhlFk?*_n4lzCRfPtx2LR~XyDP4lh38VL~+dN z+l_}(KtQo>sPw5BR2R=#l3>en!Slpl_?UK}f!#-YL!r*ST(2=;Y*vC;?4r$ZE#o0N z=zL=c8UEg(4s?N^iWst=;N6oO2wYr*SnS?TICn=XdDHSK`9ykyR+75Jxnxv(v#Fj# zicO^3psaj@{WY18=$t?mT(l)Id;Avp#4zF8c3!D+5t`dBj?w{{%lAX4Y~!&v#$(ql zNL!f_F_;BFq#@dUO+~u}+l|176knjiEicOU$S)OB$fP3%;H`+pnm(7tLQwXw$5I~{ zYsP8Px&WUrCIY#$qj)nhP80lLS@vrJRqk*E4)U~AAVuOj+m2Vuqa#~aQ0bg$t4EJ} zJBJD1Q!Y5|MVd{t4{V;ZpZ2m<)s4Oz)Q(=*^BB88N-z8zRgMO(%wa&cGWv$~?JlwY zD3_2YO{_(N{TEHzbWNGKWpLh-X&U&x^a~IehQFywBYs{{wvqW*c?ziW10C zV8;`l3BFWl1 zY(!qI=}H2bH?J6P$JGtFOxlSpm$K!u|7iO|P}ZL%X)A*;#O9W&e5v^1pRBUz`S>=l z18a5-8BWL~Fkm!FsWnHW6SYT=&9&Y`Y7{X(pZbF8qFwmTJ5dgmhifjA&aSIK@o;C5lqgC3sdE^1<;|HMC=l_CIapMm6r9wUdfw|++xia>bsH_DY zB@V?6xR8XTCIhhHqoJRYAz@#mVG=*;x)c}hjRI8c!+plfW?McHvoH_bxyQ8;)6Xv^ zGFpD2=-odJd<9Bfey8YtvW7LP>(y2syXudI+3Q8>**}RWee2mFWxj@LP{h~mZXP!%;`2e z^4=%tC3faS!JZlaT+0lE*fl>OiPj-gPH)HfbS5;U=B2{=5E4EunkDjv5c26;%f_Ff zYgU6 z#1&I&cgrOqIoW&9~WJY`H4e=70IBW8|jJ9uEOZ*BLyDm7>t~| zB&@}4Lu51@YtipWL@QHJ|3uFIvC2)d*#&mB(N5k~Jx*~tGj#yEp!DbwomnlEOVZ{M zUW)9>5gj2T-Xb$a+F6-uy$N%+lr46nb`DTkyO_Fw$=G>E+pxrhNbzU!btDy_wv>8xmYBj{c1iezLq#ZPh3nyf~j zdig#X^v(>1q#f;H?=vl~IY$2)Sc_`a>;NC(sxI5(ny8A9BVG|GcR}_rhc+KD7d~=_ zc}2sgeClB~7(a+UhBfk4#zXw1x_Ts@yAe%v_Gb_#dK^Vh4G;=@(eSqZ9pDX>!||x+ zNly^4&N9)yhpneA2f>S0y`59gl9$#Usd;s70)9^Q1ikCZMF<;$!l*;=7Bz*VsbOkx z{IGqK;PD0&1>TFR!2wLsA6e6ed>3dc(eANJKB^8w~CDt%8DTya|UPMkzy# zuE`Ky4CCqXj@ERD-yeS}Ujh^If*MAaXQus@J52nIQWn}~fU-U);5hnGOYu}o?zlwUd2AS2&1JplQ*v3nw0*H)* zxf~c#fHI`1CtY!D(O%vCfc15SjR9?Z2-s#>ns9atM5u;lcvH9ms}_Lu_S+-9zw9XT z9y|-o<&|o*7-bYVL#_;htgo#5^4UgXeMEpl+V2)&UHKFTsCyej@-)6QNgy27qzOmU z{^9m{Mr#06H(p(*3CFs5h_*SB`&Nf?7dY_H<39nKEG;!DHrxpHXX+Ra_`+`T! zQw{BI;D>rq{+7eEx5A+w0>^7`j|?AR%8{IrclC^NV)cH1VQ}OMq=CqS@F}Z?ihJ|@ zIq(Sc+!@=W@u<$K?SDyG-(3wxe-24|d}WZDPDQ#U7J`Og#DOH|Ao zX(T5y<`Zc4v}tpWDF6jbQ^M1xBs2L2-0xuQ`EEqDrZqd* z>rydeKyA+x$|4hAvjC3w^ylt1ll=ELb1lIOEsEI}!vYjZteR)+l6=d+!g^+qsopjkFh%I_Mm(Tx%5k*_5P z5`uSDv)51pS{}kz#z^sA{mSFHQvnhn6S&>%FD%H`%@9=kd8<0@k017(4*B`fH8#ff z&aC=k5BDzBa5UI-A3E9M6_%T4Lp+?I~uOrOpZOc;NdZkym zshS*Os5@@QU1`jCQ(u&|b$(vCPjI@5JguSFF)+ZdKFr8jAoLGxKw$3`LvI=%EGzew zfTGn4LvE9X7n1BJQFJ@!A+ojom>p|w(Ytc*jLaRzcu9lg@su8XQ9wWUYu=0hVgp{^ zIn@mIONS02wy$f*^#siq5Vq#wdWE{YU0c`CS38bO8!lzsAS_KjR-d{%hmQX;tJISL zRXP6nTc=?tfejIN4C7mo5IJ43@H37M$Bu0wQ!DOp@K;Ib2fU;XIiTl^`3y4nMU}}e z@uj|yC+CeYdoiB^M^lfbmagiJ0crkf(^_h2!07)8a86>Yse8B#zw~2tt-JbH3dpYT zN!%5wD_c~?f!`|&YbNK%&nN4weg9^~Ss@${LgJ0?Lc{=^jdKcCRn7lLYd7yk00Y*u zFIo;P*IejGvUUl=uFrpY{D4QIFKKBrSZTtX0Q2zG5JVaW83U32<5Ef~zAn~m>s_UY zlk@eJ0k2iT-Ougk*^B0|Uh`?R&OrMYrhY5!$i+7v^t5>lhkQQK8k9ut`;6dH7T~+P3fX3n+)j$kxIz=*s1=G*$m5FQ~aGZ4MU(&Z8c#9~hsNKH*gmvF35&n7JVR|3H%aCFzb z_P17?wx9JdidHE99F_-~c0~_Lo6gkLi$pGS?UuJ?{>7tv#K`Er5c&J%F9{6fry$#9 z5p+8LPG$F4Lyoa2r_XsfSR$1}L3FcW{^Uv7AEKAVYRsVhNfI~eBU?;Yr$NVEkw#;^ z%ByN)tiG7No>TB?&OGiy_yN{aqwqYt{C|@tyLm>crQgcgHjfP1o;7Ko8yztrho)U? zF!`K7w8s&uZ#K~HCuH55yGY5IxzG%rt6lOtsY-Li++}_d{Z-~sE9(S&4moeIeV+9N zjU?-0HNT6zfvR?)Bmkr4hy!$_ydKNqFbAE64g@;3?7vGerWo;)DS%WtRD80(K5fyg za4^X>OiI<9!GN00Adw;XtPHYpat1BH&-XB(fGs&z2WcgvRXGSBT47<`(WioEH82<@ z1KtQ11FInwuJmvV6N|6m2e9KM51f?&|EZap0q@^m#XPXulyg8Hc(ZOs`7kIFLE`p~ z76Y4V)U_Ol1Peb{0LKD~fm$<-r1PLM%!uqZ6HAOZ6ay%fgH(%(U4~NKhSW3qImH)N z{eT5_Y(_I)PaxjG2k^Cg20RYxK-)s>Buq4y?g-nX-6C<3q5+8%v@}O&%u@SsaZ_h`V+tf$|m1eYmo?r(fqRmHv@q?qEySFiKF)3?;xCf6@H`%UHoaA> z(Lir3{_S_V!H=@iO!07Z$$8 z0ei`U!NIz4{{~E~H3W`F7woPGOd72l^R`YMmg2RtZzGPwFP|$()CD2lU>0|W>By(N^Om*R`->n? zk5g}vk{m{%7FB`Rz#TGJ9JF}b#5X_<5y^LfA`UC3je@&b1PFp-PPif_o7lIv2W0T5 zUGp9>N-qLjQE^QopwWK=&R^Dn;||)_Ml3YB2PPX76ri-7zfe#%^NPJ_rTh9+NW0Rd zcbI)--dIw>QcUr%*JeRq;3Od-&q})xXk=pis3z>w2jJqpyueVELNC7~L34jCoEJSX zuqvu3_>*&tjDzgc2&sq2$%hg2W0Bj4+TFM}5B?29l5|Z!_^4#cMd9dK;^>+5=y*f1 zH`IvRNJkK4IPQ#^=p`)(LTFGB5x2+EuA?`JwrQV_yB{H^*(wTMCDZb9uuLMBRgyztms-07hXg zb+lp=yp2JGN0_4uYrtQnk#yhV5Sg%xMEF}PAA5Fa$1|;3r)R~c@0um)nl|wq_RA@Z)Q5>C%)$lEq z!}`|dF;sty-3yLE$6H0QgtmvsM)KCmM5kuv z?=5dH1NL!;BhGwsa@L7QJLP&KaB>sW zw62!9;?|CdOx!GceDmJuAes}!?+ey~)&jWuYFr6>^I}!?(@|UeeuKgm)&RV$O)QVX z_m1XoM)(eHmf8ZNu4aVSly1%Md8DRJt-{Tz*R+Xh>)IN9juwQy1+o2G0B()ho-(b2 zSbPe1jn0(^&EN`>WC7%@vR)rY9X(uT4pobY%KFv=0&p{Ai=;*+>k>7dz}3fS?WIY* zH9yfZ>^}^`qQ14R=PcJ@z&11%ugwBRb>Qe4I`Oy+Ub-!9n%Z?h^f?S3*aF?4#caVk zJP&?{gi5xJ*b~^T+G5%s5&4|1KjAJ?fp|y8@=@d7Ti<>r*qk~hyY$jPqi@E8w|D=MaFrwWx zgj^9}*y>rDDwPnc7%^2#qpwB`VJW(skTP_So3KgsHy)mW?8b+phm#dkDMdhuKPQ&) z*?Zo!{Dt0qL4`5Y?;y9E3mh1D`kTpRR#6G!vJwKWrVxhSK~*EPADAo4_C^e%L-zBTHXOQ1QP<7V_VF#1ss05`?5j`KkWY5vEIz)g=8gY6raf zrw$Z8Y03Ot-trZa zh8Jh<9dOcFVgyxUrkySXa+MWv0{*GWFfEUsb)9u%xxq|7)=&EnfUL31o*WP86V|(W zDAVA*dKo_BF|u3Z4%Rxx;4>r17&khAG zJ%#y2z`d}2c6u8`u$GzC7^SZ+3ZFT#V?NC~SMlR0mu#dhW1h)?jdE|XJ}4#OzISZ% zV<@qSXfq4c04BVIcyrzNQ|w7nBp)VTe*OC!Y4#1#SpjADhUx1hhV+~V3rxkFt3kLw z{sCkLbdN zb=*Yuo_q6`+U8w%U(EOj&r>b7N!$HINgcb!9cf5TEUN-30NdJOMK>2BX+9W`10Loj z3J@~U=GP)a{9|jP3(SQf9(7ID^FFb}lY0|_9jaiz554=YEow~LukE)UXmUSL7HsZU zKhqjf>wo_hDDNvCQw7$Aip7ol0TSCEon;2?Yu!zy}1YL8E=Etj? zrsJss`1$%6;cru-k;2ca?W~_LHJ|3O-zF(9aMZh5mHP{q*O@0z9G|_Zkio{qBET9& zzgWtbZPtG^)u}o(_P?!@#}M-i>FPFVrd`uliBYqtQms^wWKsx}j}lrtZ^LcrEO#dw z)tUQra)|@BqrkE>tCxCq*nEdS;uFiR+WC)#`0wpOz)-xj*6S1GZFb9#JmV)&Z=m=} z08ZvbUyiW9#J}OtDbd~k>e`sOqeR|of=Tl+v5S#PYpB#9yZ;Zito&vruvO$H02m6skrk_b)wZn2I1%rWIr zY`1k~<1P^zyAGlZJ7`Hv{JeE~2mU>XtkS_`GNQ{lyYJTCD7Fwv`frVQkQqF>AWbsA z)*5Z(Og_Dh%6hg%O+4TWqQ(E)F3Y)fFt*?vw&sD!h1Wy}^myumI;~ER03jI|ifL?2 zx#LxsxG2+1|CVf{n=*yBDZ%br%$PzF{}vPW>X61Hh&@S?oJxH+o;njd4OEmXCQ*ZD zvBZD>9RpqB=&46gu7W=(K};xnqI!0zJp_6c)_tg8UhwJ3{_ffe^>E?}svLqs2rQ3! zzH$W-%EBM2&SUE_Q`b}%GfE}HoFZFri1y-sfJ3Xm|NOPC*VnTRT)jozz{{==xx6%w zJrUn?ihRC|6iO=eXAKE-ORbvKyY3PO4oFoOoYCkXxu4}9Ei=y(PB@FEhQ;8}GilM8 znmOSI5AMtfHa@zxW6_co>Ze4EPtkZZ9mY#i-)>T-5i$R{U3i2WGB%~c)d1J^4NI7GjrZC7MS$PHkuyZwdhH~Y9y(-i2VXZTBh)1&xB2vL|Z}_N zQmTwZ#<%8#nMGLoU$D%-h{IiTIj&?uDkaD!t~ef6oG{eu#0whl@u^jaZ3N&VAD7o4Dlqm>ljA>iJ|2ckvOzh)`Ckn^!G=_{o_$RF73{ z_>Aa`K`gh-lj-cbbXH~GwyAho>Wi;Z9(d~uqE?2gA?1N{1D^`N zP&*`zhLUp6l{lBFOap-5QfDyzMl1_=Z{LkkzyBzqyDE2XC1AkrA_9RX2tY*dO7=;I zHIEhEHcH*U$sJy^VbMv#<=VHDPyEdu`Kzn`fZRCT-$>QmU$}Fa>hRCjX2UA&#s4QX z6eLAVJ}2BQCd{PShRvOuhE2zY5G3d1=eO;p^#;RQsj+$9VdSla@=cXJgbav~Sio-p z2Y!5v!_bT!|HjS7_E0i&MilG!uB@NH;#fO)3xVjR97jrR{PjI0J-sw7`YWB5e?uES zO8iQ_n0tn)@a1TD`_AWA^FcoUFfj9Q8K-FagaJj}D>3D7(QSEJ3pz`0%!3SMHtYh@ z`9D@{{wf_08f9HCJ1Q<;zUa;h>D|fFMB_@K_)csiLeaQL+TM6BIPEso6h+(f6xj%CNtTmW85it`s!6p|lDmnk{_3uRK}T zD@)Eatgr5yM6TDT3?*iI`9rpZm+I4jxFLYjzFUgvu@B>VPLiZB6NyQ;#H=I(=BjS) zZkPObbPy!l8E@yeVK1&xk>)TPn3}SswdoT%51)E9AC_=c5L=Su7~UnpS2vzBCxMKG zd@w$9=H^4d!A8pfV3TproGZAtf9^rrl3=jx0B-NS;Zm2E2NW|a^pu!Zjvm&zxf|DW zHE11!-gG_Cz$lDYbaYk~Ui+kSPj@?g>Ey<1-2l1LgagC5+s%2KdsE6^IVY+$2Q-rt z8&~zA)%4uDjeV^Y`Iq_eaSe}8i+*}~K7doSZ0|o&>+A{l`6d*M)I5JO7UAZ@wtCdy zQL6JQCx7c2b-v?X$osjj^F*jqMqp+GtI`doYh|Y4f~8(_^vIFBVHu?d03vHbe4$m9 zPng}!K$dsf#p`VuK}`G1J~>ZM2Y*38GLNKLAlR?ZHF~x232GVf89~Ey5b2WTQ1%&t z!RrO}8NuK->c^J;;cs&U0#aItZ>MWrwfvz2ey}KVCp)es%*Yc;j`pwbjT|p54hVfY zt-0=48snDt*9uVGrjSN1Vj6wwK^{84HeK!3?j3p5QWyKrokxB4pgU1eN2F#s2(R2S zEFvDtOoMV|(--X_7mRI9YG2ZF5ulO#mKd7s+Jn3W<58~rilwk;fkuAWyE(7;x;`S=jpj+ z#fvmb@|jsE+3b_04~}2GI?ASx9NUH75AQqM_3KBBU$k9bu72i-g)0&r=3fYxQdFsR zYyeNT>p>H1m+|UC4=(6`7l8gid{?W&do;)-uX6`=jcl%Ao4ftN}7>g=G{+*;4cmWG^wisPu~1Ne#br zZubb$aimxnL3*rnYyq;>q63JF5E{$9^AN*iUSXu{Iu$I<;3P@eHKY_Hm zOeYi2y722**SS8(;RF?mJ>!=j;JmJxGq1^mL>bN5;!bjsvj(tMe0;oFA%AC zg*Ilo`rItD2H*M9P(x(mx4FP6v`x22FQ>saIz%*9eVa(oElh7_qloYWyh!^sW76rU z#pL4W4TErw-1d!&!7pc#7@zGlNAf&c&&L4d52hj-ldvcq4(XD?y0u}%dUO1aR__%G4#=bk zJlD$2X)T~rpUAFKn%TkXeOo{Pq5h-@WPh#)UBqKuG9LaG)Fu0a6~y1Y1yQe)sPRKZ!Sef9~Z69cYpEM9>bG#mu24nb2 z6UmqB-`+E6(i~R3I2-1dE|+_e(d?P;@ydxw(V;R2mQnFy4skm9Vu zl8fPSs(Enejx-*JtiXfkvw_Zq?XCC(+2mS$_RW}dn(683xs&*QGhwAL-;gWjHqwmXgR>zTw|qYU*U!Z z1$xZtchYVEDKx?_N{+}lYzB!-qfx0tycbOy)&Y*BsZKvvJ?E+fmX@!^@N0L%QIidE z*auI)4!l6b(sPX}d4?JB^?_!>ySb`yNr8m;7xG@ug%4>BOnMqGkJeyq(i?WqH9QY* z9sy;ZY*VdQ@?NuHYU1PQRg5~jp0 z)px5*T)xi{rPNbFN=kRVBlL8AbrVXR7-3I)Z&VRpTuI-3YY^%6g!d8o^lnoK{yMc7 z->T6}8L%L<(1H1Vp?0NAvETJ=Q%LL378)LvYmL=aT6ID|wx+~@g>@}35lMFXq}!1C zrce^=2kW7A;IVxwkAOCDv~R4EZ^{hEq+K@IA~!DKfR5gGsXf$d=0m}{s{Q*<*IU@y zws?O%RWtb+`A1B;lFk1{K;Sg1^vacH;v!i*%7CB+DBf(wWIzzFAs0ejzczS8+b@q% zayGJEKN#7UtOq%fqH8@Q>t3hBPJpha-BqjC$Ic5L;>ij`Z%ce(1L9B6A=;5TFfTv< zn?wAh=uErm0yX130cC+QP>CK0*5TzH-?_nqh1Po;o1c0N zn72k;V4?x`J%MjMg2S0SK26AiJY#3Vb7D)$oL}>)HvY|#zq#q-mC;kc?Z>ajWklz) z5wmav+>muT2$|J-OB4y~C9CleY(uzz#=S!3W6c3K-sQ}=nVcDp?4~MXxy_A8I(EoI zf9LX@Q&TRKMC<4NOKUTQnjq~zBrcy8`mZ>t-~B)4*a8#7K$P}F+X(vHw5_maNnR=p z!-sw0dRC>_Dr}@TnH>ma8{4+V8X^{Z=Ak#FpqX?g9m$+~PQr8(o6yZKmEpr*=0(>R z`B=YLZ7Q_5c*?Pzm6O%vfm7&~0wp0EY#z0RWdr>TXE3k{jG!GI+S{9&U?5Vu8mYVH zfc$lvtky>AF-Exao2C;cLFp8QLmXY*U0aaw(V)DGCW9wrC*77_ol5Tk0{A&N8KJ9` zY`Z9t5qm-ydW^GKuW;L1=_%mWPhkC*cQUy3%>yC4T1DvSe$4GivduBkE*b1)DfE1J zP>%IQpjuOa8DJj>d!2TfUSBh%u2z#|Fi!8=)Avq!;pdj)F$R#AQIf;oC2LTCU^ODE z8iJ8_<+eDLY8SU%Be;DEb0S}pF#;JwN7MpCqv}v+W2iAvzq~$m>1Uy0IF3=e?JT_6 zY#_WxvrX9R)F}sd@6Q>S&gol8UbEDn|Mm!;cAV9gP17b?z+!(QF9^6fS4=xYDaTYi zcUVHI&MICltUS~rVh#@r#S?yel)jB%B8ZplH%&K|Rr>06HyKt0k+E9GjkMBNV?cGg zn=+~Fo7J<}Y#Wj-v~8ureC?ebi3qH*4rerNEwGUSyp!%RpzedjD!lfWJTe!6AaVS9!3eMvZv!I!r+ovKhZ2Q#77zDW2in}x!3D|hl+Da_wk=0%QUAx03-@$LG$cIl}0|t1U)_nFmmB7 zKe)E5F-brw|ILTkM8tU~VG$5!@sDTv>!<8%EjAdA)X@v|!Sf4K?-H`Omt-Upfn(A? z1>1w@jpdgV#%zVK2I7wrklC1=tT}@sch75v{!RC%u7p0IN3vxi-(AAto;PDhex?+~{|Xd8(y>=`V!%p351wCG?P(V6y3Z#Ax2 z&rUo7mo&xA?bs#D2%o38?A=ougu7!SSntO*@sDo(O0ok}@bif^s3{Kq(-;BhZydZ4 zXSH$-nJ(Ae<>qgx8JH@-% z&3ux7aJjEw37*1*uPY2V`nd6KQd0f$Q_$jVe^BWw^&E}fFTx!U1bABiqmO8xYoEjv zn5q=MfOwZkvEJoOnL4B_PwOI$RA?D9EN`qd1ng>S|sTu z-QsL&Wsh)=?MB+^H=Rh|(x!K$Z=9=Ke~{=?((-jV!Vgph);f#LUDiLNcw+UK46fIkySTn5^}ICN#-=&t6}!icTCEVp zA%+?HG>CAHUZu>%-rIr#{a&OP`G8l{dU=Ibz zL|pT&BCsHIM1M>-t=aFWfI}r8|CW4XF0(z2wODQL5|g|lQemDwcdwycR(%4}hd1bz z3$D4xhOJw+?Lp{YvP(DKD2Dk2(&?pTbqFZqjl~X&UwJ?v84q1Pli{u({Q`tCKlt~v zM5pg=C`!k30b3X}U}<@NEIL`&ov3#1RiyWy_sKvz94eXzSM6_S`^t#$Dvq99eqt>& zcj2Se75`$oBnwkowDR3PJLukKg=n1Wr;=)3PWy5m_h!87E65yZ`7RsIrc9Fsrr6nMEgmw~pFk9?vb$ z$Fes}^16yjv2+ZDz&YrEMpZW-;JFlAS+izh-_Kf&H6tbw@l8 zfOl>0DdjISn!xz~i0gUp5)o3X6t=4jQe~})ZY)18^XOPQIgUtv^T)iDaH@-18~Ha0 z@7gFjjd!1vUP&E81HF@3pqpprG}V){C}df13Q;>L{I0L83w2NRy=R~S;r2@jUqf@$ zDETuH*5{Z-^N|XgV8s!oHL4Pw5_BfFKuL#PcGgImzft?BeF5T#m-Yx_-O=I8hPN|$ zvusNa2l0+YI{4)BuMBcYis;^DWD!X>?0Vm8-(`*)G@Odr&!a91LM}P>&l9c-95-b) z^ZD-FW!0-Ny4=CPa;`R9LSb#H^-EAI$+a!#I}H|Gr^jzJ2q*Y;Iff}Zj}J${p|=Lw zso-j-#9Dm&S*yjoKlfk8kG`Kif$<^9z`_~Z%A_&s!$S}4f?ZqC@IPPO&f;fExBND0 zNE~2Cfz9f`y6B=Ixz^BFoJSR!NhcWw=EG_-&e;?HlS$Nb`tc*|#7_0LWlu=s;}_AD zWNWrdN==b`ZGl^X0O~Jk2h#7z1U-#xmu>JKlM+u7Z^<{Kd64f0K8kE=u(BA@)MxuL zAjIKuN$-<_NE^-{oI96w6}dK-R$(R6ceR=o(KU?aSRE?Wbt0StoO^Xu*H1t-{gb^W z`!7hkfU-aFUMM|0{F9RNu)DZ9k5ma}$B-4DXp-p-^GHxA}>%wQ^iUG+)d$?mNi zsKd7Dl<8gcUXa;J&^)K>5wb!-t>`SqU-hR+6()JI5LI=3i|IM6QoD*Zi1}xeki5lY zH^;0amD2?2eiFg?st>gL?ny2#yizpvi@1r>&!wvHPvh1g|IRkwXIr$?eCdzQ%S2gn z3mH7DpQsz(a|Q-}kzYf<7Cew9rHu$0vzVe^(-ga+8lNxKGaeQ2xD?$Tqxj$lV~~Gc zpDBPGg%15S%HLMtevHPnu9VuB=;JDVzI^eD1#zo zCpqpCf9WUmZ;>xC@w{pgSx)r&JZhp=SmX$)xnK2U*wMB0(|8|aWTn5I;%inu4WX0W zoh7caQ6IqGTVil4Etlb)j*vESa7w~{&z$=M+h|1qB(8obrwmwLUB^I|(u4WtVnZC? zw^;0@580e2%vt%sfaNF@><$t<~i(`B3nEH^Owp;u58IL z%sJ;q2tRcCnQv4tpFiisYm|#G7%m{v#l-$4gjcH35hg?s-X-?1rYaA}l{aLZYk*6z zXPUoFAP@Z#P$?oGhjlWfG8uuyFaTqnY;8fM)LWyOO>itcR>9+>nUQgfR(}ek+@I9C z(V_G;Bt3&dG8hhyIW+|7z{3P^auKT>4+=?C{v z2$Zu?BY|ZiOFF;m>jb!r_qDO{6(VLAfU6X}Awv@^<;{c^peJL0UM#H{IMivL24hNO zEl~{YL|?AA|H{i2jMIY6kD_Y>Q~g;!Z# zM1s~JBG(f8{!9stxRh=zwnj>?BUYCz7KT&B-an#20I#FhT@ci-lDPLWd{4s4+V$G= z1o=mG@AZ)&K7EeTob}8cDL?{hzTC%T*L1^&O0D)l;tRv@{qGf8_9{um4bk5u2oImb zj+`mE6*MsO4w1Z_JC*vT@``^U%EamHbM=&SG;T_fBTpt2iN|1Rmgi+xlS;_TD^`=r zX{k?_kZN%0Pge-4$(v6{;gwlyXiXM;U4qUjN;fR|AfZJ(UHUz9LppHLse)8GqP==>G<1!_UpJNx!x5}Hs>W>R5eR}rSA zdkT*&QD%oOI=Ikv-qk5UX8d7^^E6m3pZ2D7UH2Y@a2!r#Dd`u~S25nHZ&-nr>q`5s z;8#;7p3VDih<2Aye)SF#s~)e45Go6M*gqLQbJccVf~JYFh^7F;>pPaq=kVW)B2dn6 zN+sBr6!`u7t?CpaMLr(TNI&*}v(Mx3PQuC;b0D%;O@PmG_s2ut}1c7p)9bH(T zaA48o!u%c8(YU~e#iYfWT;gM2rys{KrZAr)H zym86k|Bv=&#w;>|)wx-C%;;8pWV0r}0IP+BWl|b3o3qRcC%=nL)X#3~S;UwWssVS_ zTrYe6-^=8oFPx(9_So->qs774%mxo;Co1O2smWu$w{S(K>o{-Un#%uP8^Ys90H_z9# zkkW6>p=z{S7%`GMj`_fuh=y=?`h7j{mr;S&gWo!ND|Yy?Ms&F0h6h!y=ES#Z4D|GzI6 z@Cjvt&g^>pjoAe!j`w#VQqr#i?r+u>o81o?TEsuS4?m(shmH)(mU%tceXr<0aKWU( zHw+pwy?JhytVM}qkxMhNr6!0Q#NEQ_+o*%t<5lv567iL2fCl_8p*& z#}Le@czfb?8n4TH>B7!=MWjl!JN@1#kB2of&G2>>g@{bONrFmz_9&03H7f1!aTfVB zvwrscuu+#Sl0hCmf3H3)LLi&T|G*BtqJPH=lZNXP;_X7SXf;Z}kz$0wLNS3uieAmX zzBk&76kv2+duHlCaf~eN*#8L`q4wRsZh2k(zpiS<2)#e(mDfq#wZPL)G+UWyr9+fD z{VU=Q!Ft3OUF_t}-y|Et+L8bN%bbPA-D)6bsn`9d32t%ciWieY>z=Rt>&k{~j)Q8= zbxh>G9qkMV6Y|A__LsK_a>>EA&#NTG)F3q`MZ)h8F8)gc=egQlw7+xB3S^doWLJOS z(JiUM14qnXC8XZw_@>XWdCXSo zQDjvS^g;|N!zu7l)_lyXn!=~O|ET*$%Jy~gN$M@?Pcp7zrit9{-du;Z$QR59b3Jdt zEVRxOB>dFH1J$w3mrMA;s;@`Tq{(!wUoqXX1Y1v|Yx zUZavN4{pY2$q~2NjWD-P=#Wrm##{eAGv*w^luMMH)LW6ky*67=xLL8uoB+@4B-6JH zs0L&Gi$Kpe<#*9KRl?NWsy3sI|$7&nTk`gOIN|TQ;A5 zR+qA7Ke|-z68w!2veDAuwX~j%!uDhP%6w$Q5Jre3(oeA(rp|hvOC8pjiK};!T;rwI zyBgMLKW^&@G{5pQ(*_AfjYG%v5Fv7T5w4!bVe~+>NpvgqHsP4s?_S?SHecHgX^I{k zry`dn%y{Il5rJne$ZPCx=)OzyV9jworDf|9;Lxs}u8G2gia|ZmJ+_l`dBn7%05cFSVsJ41 zD&6AxVR~BvZnP;)uwq*3i~SmaG=7C_(S`j28KoAB&EzoFXysdvM>aaDaXv`s@Z}2y z4@*tdF^h5kIQM)$wbGaRCMR^IYdy1SduLxeK1%wY6z+8lBjiS@z>g*txoZvlRV+>H z76>t6v0}(W&IV0>vDM#>WZ|$@0wHX!eOpgk_UR3^$&d+Krjn=T~4S_X|BXtDO1p-It3rB-v z`lQ^2m0q?3s|)wzMgq13a11)>f!7D4b5TX26f0JJqN0G5_NEWie#fSq5D*4!x{&PP z?CINNleqI$?5&y>AZM{4W7C&~^y>yY%4+2LgEiOOZaXl^AWL4ZaHiV0h?wCcP z?Re6C$boJ^XX?j=uyi&XI@QLN*5*E9n4kTzUNx~Lwcp)n#)EulyZs&4n#!8t_A`?M zfkEV{(wq%x3kmp-50+9*{OG2s+vL1(QNiZKnulfPpzBw1vTzcgbdANh#j`ro zG+&+BtRJU*G@Pd`R?IAQ9YG8ic^=TmpQv1DU6x=`3ct}qFv~wec=Wr23`@HB4zk=* zJ^lQcs_dMU0#D%89DsEH`&ou+a_h6}QMHT$BSeIUuyceil|rKrSY<3L_m3>xO##xh zbGqf1>*}O6?RT}y(C$kDDV{ydY$<=3=R>}CnT{bl$Y6FC2MfF9q}8lJZQHgQyGi3FX&T$Moj10fG`7F{eSc-|y}ixe zV&<7=W^ddh#wxYCln*7b8~^ghX>;8@b)ynxuiaZ9v{;Ie9a>L_P&4bWs~xBYYGJ^W zaBwsxzT?%u5L(!tAtm*i#e3}&P>YUepsVUelydPlWgaxvM5qS*X=im z_%k2XZ7-)?G~xixp(HY5k95qD%YqE8b`N^w{J1Yh%!yT}8c3|t4GP({9`qWs5)e!* z#tqtBuID<4G7W~xepm@>>vq|g?2oGh*N5BxN;(aTDPle8x^UbtWAA=EXLCayRp`eU zQ%`kwLJcVRQHyl^wcd@acfMF{d~!Duc5uw$s&>6PC`q<#k|Vg*@*`i|KSLk>mmPdd zdd(*QRQ>&AQ<0V+pX0>HYq|H z7{N5%l8|eM!_wWvzo5<&_@~@YI&2ha#B9a`E38-dIMssbJjMo=(?gsl=~>7*T!*z! z7Hr*J?jt|4-lQlQqS?J?cq!t!VYYPIu_)&xAZm^X(K(V_EsR7fM)@zZnd)6F_I9o4 z90Ra}kV=l^7MA4*cs@}f1QzZOU4r$|4gX*h@(?*9Ak7_JsPw1ELN8Y7$G8V~X2|t; zQVy+=C49YjQd`QZ*m;h+UF2kNG~mxQI$v$%VkC$8$N#0`Z~E1#<3KzEw;X=YAMCee zrxW@jqnmp;?n1O{)(8&2DV?9G0aH3}9OC$cWX1DTJ$OBuh~v2ntv`@V=QL1Fz5mYK zMu3Zag-Ci`gd37CE8!tNe1UK7t98}cTXsbA`^L&2|9cKk66WWX>@$gHt?Q~T(b(D?1*z%9N^tx^;HWJ0h-#Ufy{ zUlyMbU40;}Ve(Pyt;%fPZfs{&4fkW`Z81_cVWk`Uq;~;2v~3u!Qdm_}KmiCR+L`Cw9=eXT7(`dqAwr!#~Lzj<#lh%iheG>r@I z;_qwq9y#1shv?V3DQ#(cQum~M5GzMH43^&gFBq=BYju7ZEQ#UIf%#bJOc^uKPGi7Jv;s-V z1VFcaf*7Eo6C#i+Xn2v5{YeQRZpBs1lyYCj_KpVla9OYPT*A zAPqgBnr=Cx$bDM(gD}xT-?ZuJ(TeF0F``m(9%?hY%hNWCMLTJ1pAa zljb@-Y_;~gl&;;5+h9Jmh5$r>V4M2q)va=@DwkOp%y_32PgK*0|f zZGv$+HdXw}p#M#N@R7odrmV#l-Gfw5DZ?=hiGFEu#`d|MXU%oPW5t-^vhMEV+hLG^ zR2jJ3b2-EUhr7`_k6K2rbfhE^9k~^Rflcu_d(%ZBO?HkAO;#c(-Fa z!ChC$wXlVT7s#qW%=oV{rRz8?Rt*FFuN$q*sudoXcwi-N$5Fz`Y+YOH;mS?55?T`H zLi2Rdd~_Z^v4I`D4i`JyGXcINW}5DGXFqsBgf6~6od?u^>?Y|%7?9D9`)VxG_ym;YBUQoDE z5i3HzqN!9V)iz{E5i_1ka>}o8AU3#61RAx6Xw010C9Ef+%DBJ_# zd!S!%DNn7Oqi5DT-^rrSaXiRYRsP+w6mXor*9jN2_UK_F` zZZH<%56Y&oS?pm3_PH}uSO8evro+7Pp{YDE!b?46f8X6AsxCre$=rBsBu+r_> zmg(Id!%d*ls^dk~C|zqmSl`o=JhjdT1c$9v8%#yUb!5o&B}Icz_L-BRw^(nFLtjeT zLEW}Jk-E}~d^&Ix0mKtKwy6wt=7|nw9-xW0f(q>GSpm?mAx{tV_?x!b78_3Rv4Sc# zi+C_P54F3ypt4_4^)}e>M32~vx=jt1Q~$&#bk{#|?bb*Q?(ty)yd47{qg*W* zO*W&Jo5Xv6BbC^8t=U@lLD})-ok9$)E%|xE;ST{)2Zl32qYR3y{< zwx~7yP$H_{u#N3&vUJ$KEta)-vaKtrpN!LEZi?c=fuVvj;-qaSEJi`};iA|AvOT3g zixm|kDTABOmGZnNpr=9fsjS*LSqOSd9>xR(FEz zCgkLU)|E5YX8z(eEExVxu`;-SJo(PD;Y$l!8*2zJs%>o>qc%^u4eOWlmW(qgEdMgy?YCswqE7c+s`Ikpl zK5O;;OFzvrcfW2QLBv@eV`3S21TlBxxBI4efh7hU3dd=0i52F!KG@@33l+lc#7FtC zGG^kZ*B#YiM-@{6#?=d0DnomgvtJq3BIR=((-H4~X;c5K@CdHfZMZo6IZt)Xt-@Iq z>h7llc~h$(^mrC2gk{12m|A$TPg6BZ@>h8FzzfTWoT#OM;l$1Q9q^qcLcC`D@aBQV zxR73bP^SNw0<3SNy%wzm0kV$%`Ln<(*Nl^PhB&?Y!wMR!yl>>$JMG~##P2ncGFrkX z38WLfdUt^>Dm;PXBeBz(Sj>_(Wi~$$0M^ue!Q2-0RWL z$F(U0Rzuh6(;pJQXSiRf`j|(b7sYg$k=*rk_i`fYYu@>1*}eJ1=Lom2 z=f7QMMF;+)kb4XohUz`?Kredr&m%{ZMniyoQ0WR@-n?OFSpwu-jw z9p2#%+fnm?N`0DC{h@Kuw*0G)AAa+e?N6f&qOS^m6YbMXH>|1vXUH~og}mc()wbd% zsoe85ENFt`yTfv1lyIZ&RGl`XmysEpIi+}@+L9$o!a+^FtC(d=Y!HP~9* z=px&%ISaJsb;*Z2^- z_zJd|hP&YnHTTnKMeCdp4J_+aYhE07dlEB4pM0`lMSL6(4LZvdBLp`D;A5f)vs`ax zC-U7%Auc`mmtwY8k7;w~r}&oxueoGYM{hK73E7Bp&{rmH?`4LCfA}fi7W=V^W(bY^ z_%}Xg!mQt(xFJ#o5$2xUgihlyQdqHz{^TMSfW2|ie=@)X8s>)I#DrNRLI*l3h@R-V zfA1pbag=U;tl~j~;a60e3gn0*hN}1{-)#73hnMS@^VRK86MX32nrfO(&Q$X1aeDUr z@>qH=`v^|5vzanZema706T9EbN*FHz%Kn3k{`Jb_>NR0bNnklS{KilSz9-!6H9v(qKHS8nsLk;w9UeB(y z%|Ah|sX76~gE+U5sSyq>GTFCs% zbi;uwo@uZs9JN5+2?i0ceoLqzy))r(!dP0{Y;VR05Q#Z&SOH86F|b@C6Q=p9l9`PoxaX8<_o~##x(t-OV z+s2ng_Di6lw#TsrbNyRj22(G|sbCD|!avbRto&VH8*Epdb__%$*Vyg%q)5~j!m9Ky z%C*QcD_yf=?&a%d&a$lAAoaHVMqZ0{qw{9Y#Q$=hBayrKvtB3%QLj=9l?Uf?IufbZ zm@*oVjTVDdhCYeccggqG`@&Ujjy{Rs0s~onPTpWMF>F5>DCkE+(JhmH^IJ7Y1F75Y z1JDlFQ<`wF4SP3vhRy8Ff-A{GsMXM`Gaocicn@3P1B_W~fvd?w|1{ywyN{*+zN*`- zKQG%5jTtkKyP_KoX`-Y+?}uPzUVvdY5ZrW?YQ2}Gyg<nbnY@B4s`n5(s@wSUu?2zYr?WIpYN!u~zDxIHm(->hXFLK_>8`P3t_+HF!P4FR+$ItpjOxF<) z1!f>{eO4)J0DgcV0-^j8M+4QcS23%Qh<{yVj(vM4wLc*{THWz$(NS=OE}*Y_1G~O8 zo*MsArzF9|!F#6FL6SY{e~Q4#zfI~(p;Uy@A$+Sh2XK{b5=2o4UAK>n-#yGs8uVGg zy7o5TKW`ZO>@PxvC$ndZ;O+o(grd&0maOc zL^p*?-EKNhg`@P|H)#f+)pI(8YyAz*Q_>u$-S`<=B(28-#vkPz3d2%|`j2g%Ca`3|VrRIJ*QqFoGL*;M*yG6nqb zk)!a(T`FMnw}SCl(_GLZI6=K-L`d2!H89U7Lgnkagw4RUoGN_f16VvSARsRtWd1A+ zzwz^8$l1z(Cti%66hkJ1HNah(IjF)b3Cv{;we~&^H|B0;4XwyiHw2b)#<~CZx05q2 z7k1?Gp~%@9%vuaa*J=G$ zFS8RK6hThdd|&i!CKqnT@V~o(zH^a#3N{MhW8*+OxZ63)ADfCr*YSrK@j6eVY&=js zFut?PgkW^GhV#ioZ>Nup&~XnjmrLs1fn-ksIZq#5r;o`?W0wioTc5hJPw(G)A6*9@ z74Bajp|=7x`~qdixlZXgW1nbe`7gS=1WlKD+4nm6?50y88=@?8F8RU5Ur{pwOfT82=@FMr|ehQRi zaaQU@g}3%Gbm*Vo6DW#7r#CFDbp15>9l%&`Da6x$mcktvz5{Z8^%q7FL8As$cO!7; z9;P6OdVCS0(mcBhxRi$}U^;NL4c5T6wFWHIKuji>Y;b^QfInaPvz`0j&2meyO4}>> z{}u)-aBY5*A#?`DkPplq0WWzN^@b%xr9c;X)72m~H7Y12({C}uWu!~$92n|a4;lD# zUEjGDKbgE3!3?yLn@Lp_XZLj;awsbQT)Dk`)?jHchQfzGibc+z_Yvg~tAdGwZ|X)J z>sdpU;6n%V|DTU(YGC4zlda{rnUoItkrCBTcY=n}O8k`-@y=n2zz#zBt@&`@oPyts z2ZQ&Pr<#yOo0s92w$HienqX)Yx-aoGP>=Q$JqBFUQ&z(tygnqJKjSKMUL}tfiikfE#l# zulFCok}Q5XHwSv@_UYA6a7v8^JN_h8$Z&NtTFWxozz}>a&Gjz*Q87f&cdCSoJW*dMiz3l?<0+kpRwkpNw0}3q>1+-;4OJG zf&}~hixAw&mJCgJbB!<58^THV_W)0?GFXe6P$iI_L{Z2a(oagruLN8&AOi^@=#k?K z6Wza+KY7aNc(Dx{yd`SkA5_RfNCT_8%`p5T*=xW}`)JHEWYxJ@`KAxgbW`lS&|GvrQT(X(Se8O;$wZaj%a%?*qo)Nze*1qi&?pS|I5F!!d!q?GAH%h$ zy?M~{<1Uxy!qTS29m_4o?RAV!NpG;^ah~f}7LYB+&A3WMA6&?5RaDx43Q%%{Aj2J) zcPQcFU#cO&?z;IJzj=!`YmH37(N_B>@xI{9*2iYcvYI6qX5OgR*r2DKI+ke z0{#;5F?gaO$-KlDJ9wcJH50D1@OIfcQJn;Cd=qzHc`XjP`dyStrA<3R(*FmAvp6WZ zZL=UUA(uU=;pf+T)(G&)-UH#Jzu#t0d4v_IQruf3D1Xtnr{Kg|Vz@i_tiuor+hlk{ z_H?#mltBNukeDCqpkpaHnJeJwao5EtAvapXf-0l@B!=VzD5U{dy~7~;H8jhf135!$ z<~b@Iy=)(x`#|DeEl%dk^TB0(GgZ*@{)%n zc1q&30W=7e)Q2IfjqshYuryq|P`{0VRXU_#_KNQb)p-Ix?_kU>=#h8gCpNLQEP82< zGs}|Pp*IVXL8G0bX(}I8{MXwidk?%+lr}2*_}*l}X7?2S2<`LP^1rT`V&Q}5iUVsL z6~Bl)+w~l39g^V0u@y-dlE{AEU!6-!drccJ)SH>{O8r8EOz9c*b8eQ}m|XK=i~#u$s-uf>obP<}t`!&pUq& zV>xFQl`C*kFQ0nhz&phXun3Kg?tsM6N(crDA%;1mK)$(Z#c3gWNXm|`OXr*gTnm&f z=>m-)G8bI2Y}wyeerpHFC827=o}%KrqQH<3DJtbyu34n#_(3IQ!eAY-?B!Rm(S0s| zJ?j2(gGA{)yQqekmL~jZm2WrGOC~SP-L}3zv1blKmscUB?5HBqb-OZ~n_(Opo~V(@ z=FUUNl%ACJkAzm+*Xp3m{Ml~`#{-H;j#Ah(4G%_wR-)r2{u(h{^5T8u+*O8a{%V0OD3 z+*2CR>Q`ME=D6nEvE4SmC(YLxJ5WGtmZVc0+o~N=0_2!b8d@m@(`(CWt_E&^HFrI< zP=xw7wKQ$Wp1IFh)|Ex(0mMLgUj@J+-_a+W(3sc;{dDJyYu1?`s!yLloG$F~MX`}D zz{nz(qs)Ne9X$za-0VeOS5zMpw^_Ycjc%p-7RZZC9vJK6p+=bA6wiV`dW#A4XFRK; zn#Z14I_VT_(HZxL1*ZUsbb|vkk4anZx1}gY!ZcKGzER~8nFQV7yNj5DVjpoBueTn= zy8f2H+`i;`mKHE4dp7!hd@#$6LXxu`$_CeRmZVlZB_7qW0IsysP4dJqA{n;i76-IY zAWc$!Riy3H-_CHD_GzsCUmAGnC%0x8X_Wlatk?0G2!tpy!^CW%Xomib_=7I22zIvz z2g8q=kFujRA>xP_!yl&hSW24IVbaqG1HUxThg3oCFC!lZ!+zIwtGV@(uFYg5s3ELu z>UBr7zT8yrgh!icPB(v*$OtW(@%o_=%^R>V^JK`4CpjQN#tqrR{zNTMXCxn%k@uK5 zR?u927>u;Ghv>A_sE><+ly7*)t-@_2fSRieQ6amef8ovIgC~M525~m5I5Ln&n2f7I zYI%`KS+KS5YryPYH-T#TAb^3!XZph0;@mS=8c?t=Gy3HOP^( z0q1Hde>gHIH#&mOus+T!);R@pXPw)xY6h8`Uj)BME$nmlyr5Vl(r?cddOQDS>L|3M zJ|--{3erZQQbIyWadSefUZM#SPzsA`v-d(k8i!@TgvQ7>L@1hk9f*$Is*MB2w+ZtPE4&y&tUm{y- zq|q^J(!blMm<#s;r@YwX-q7lN7FO3Ci4tm%XY+dPuIQ4(USo-v#PX;Q1a)RVC^5t! zP8%LZx1+m_f8TjFs9}O+H=KcPxdhksVHrt9oF1-B=JDC}XZK4r9O#(si!O{h4^40C z*;R%r6Wj&MeRtOj51-aQyiG>TJ>UmbP8ML%8M!z@YZEtf&gCQ4L0?#5uJ9|x;n0Hkuf!PDA6*9(`Rq0#=yhUa|DBL9#^btw+C$}o><6IveM5oo1?#(ui z-&$BP;o7+wVm$2OUlnR#L%INg{HEXMXzEP{cxc)~4%S@rZ_o)9%61^fFO(DSW0Scz zvl`lv>k;Lf{R0Pf5DLz;O+xkHr3g(@iT&8%2bZHIqcOF+0VDpGsh$K1y{GUJZ#T=$vaU7Slr8eE$jpPZWVLO3NU9%1~iJ-RwbEym=DQZVNSlPKB zl3R^a)MYZTqn|&wAxC??ZG-b(6Ghsn;-8B0-2fh~lJpxaO+JrZuyse^$W^0C$b8!& z7j>NX+xJ!#iV*`U7BA8|i{9G|4$yD|I7mf>UiYZyun@N-6SJk*G*43pc@A1=occzZ zj3gH`M(?s7Y5d4xD(N%SNBW*{ySFd{$4)oG+UtXK>W+M(j7gPlUDp10=;2SDT{#$) zaTcZDI;CwMgR`{pO7c8f4&3DJQ5!|4H|+02qXa2#8{?R{D37fjJsX1$Ad^E^S$y!y z@}qs8s>(Q=^?Bhf*`%^KD~iVgQgMFNFPhB#h6HY~Y;vc0X4JYY(S_dOm&Rs*K3cg! zG*11r6^p{pZHm7!(Zw&Jcz2bB@vqNN8*W7CF-$ctYlm)ybSx*A-BYCIrtM=cR~R14UJ)T(sS7188o(+y+a8+- zTr1jh$O7V#jqm8~G9dIQqG)}cTR?B1mecFxt*I91d{svz9orGm`d$rsRCSq4OQ{+j zw~Iu&iiUh48f*#+Z4pZkip>5`IcBgYCL16gM~Jz5vXKte&w_U*p=qew9j3npLiD4z zO#07&L47n6Y$|Qr6GEA$XB1U79>Fsl<^6PmXIRXSN+KLMRjhrQzmez=|3!LfDvoU8 zzAO06+i^hGMlz55PvdNQ7=KhS!x51u4EM1N9%Kn}>WYfS;cVapPfK)_>@o^a)4KIr z80V0R6k8+cz)xH7cx|s2v$b1nSs3Jftqgcb6h$X-&DiyXu&JGAj)%5g+D%Sq2|>@+ z@UOUWddr3}D6a_mQ`juiFz*&B>=3{1W&Lt?_L`H$X2P~pXD%rLTF?xE;V4`n_I!6b zQYVVFIQJEBF?7wRhOrBE+Y~X?5)P8t^lW#U0cfN&1eh6=QE7)Xwb-b_btyngzDBS4NVTI_`yfT%pE~!#sYp zCW>{Oecez<op9ljg=j!e&o&f5oDl5KJk+hF(O)O<_gW?-gaW2i;ihrl*?}s zviIkAK?%ABcde!^Tl(Dz>$IKfxXbSg;F(()!I{L@t(v^z9jK0l!|tHK*joIuJ(q}9 zy|fnscGdj=#YeP5q#%tMtw6$UMhF37upw}UN__}_tQ!s0tez;R^IVZqM=_DEQ za0M`6e}(tNo-y4P++plna#jc38}zefj(4zcUbLevUs!(A?4Ch)e}%y~8(r6rR>)h# zEy&*)Ka(6*WF|IYHXDGvID-crT+>(M6V}uBPQ(QRPY5?tsf%LU z_cyx8NPvK|cpr&mIYsF;`Af5tnaAq=tz(z)6r13c$nz+F$M^wLQeoP*9XcbV)7 zMW4NYiTGBHyeoj9#B7LK@)Ly@dzVVotiJG}yJnlSC8e?f2G@4_K+^9bs7fGZp6}|T z_)HW=wU|I|F02WEB0NxxRQ3Gr)Bxc7Tu#fp`yYiQLK+i;TI$Y_oe13$L~L-S`k3`| z;Z||nznN^5?*riILk^_A_nre&nQ(O$l~>_B?wPTYL#rlN9~j9iU@p(_y8R=Qtu;Jp7Ag#7E$kn<3wyqiy!) z`}DAU!HStl+g;A2d;AdX2T7> zAe7PVoCe`7@gI9K!UB01k*k_$&d`iAmX)KLNLZ)esYx8(ZZG>ZPP4YK0~k?`l}fd2 zb2VJY65@7WkuS!C?lW}vyZ%D8Cx;ljBvPqR7(aeTb}gS#a(KRgJ^m-{p8sb-`jA_X zHN6#7a~Cko#%A3iY{;8#B2bREZ}y)#a~foPa-&CL`?NmDiTrUd1g)+8?JNrhMiOO< z=cy=g&|QY^ZbH}Qkr!y=B-kNKN58Oc;s6U>_qU|wkoBxYV zw+i7Bt=vHNL5*!-dK#xqHP;%QoUi<=L z=EIHtfUu>dP~JWpgTr2C8g2~j11}r*x9(HBXiKFRwA9z*w*Jrlya*>Y-CqH_e9REc z<$Yg=+1L^*n<7Ncgx>xzO`cx(E8MwX4yNoJyOQ-7Ol#z=l2XQzodh%#vV+|F zYpfiQ6J=u@0IZcb&R)J%OT0;~&~r#gcl8vthFRo`h{F7QR#HYhIWdmO{5(!XvOAH6FdfI^Ty%PiWz;p9lQ(+Wq)#A4VbO{9xg-*3}C z2%M;a-chx#@GakIm5SgqurLFpbv0aRTFg{fY>u6~0|#bP4>VmT zA2oDHXTNpk2o84=CA(#nt8Q?pG5r)@2D^~{Ncf{(PGY-Ukb6HapKeS7-C5L|eiXLsP{0qDv)b$+c+I;I; z4lCW{fw{wTUb{5cFei$6qPw0zLCt04 z^k&knQNtv#tMyCnD|ZoF8bIit$cI|o%wB0omzJ7nj#dCAp_FToGl#?R}G>C}FL zRiW|4Hbg2MSCWDs!^3-C;`B^||EZGoCVxh`MlI3%(1r;%-;RJ7ZiCSW;lGm@&dP`r zX^2ssLI6Ru{p>ag+pGyLY^%yV|X`G7l|+y<@X zz+tsV4cGy-_6vA zCaTm9F_a0ej}C4bgIvWg0B7&@PQFwF{o-E)NCpTP{=9koh5?b*XxuJiOzc&Mz(LoR z!pESdB|~W1#YAJMn8ck3@3s?H6Kyw}UNdo&^iEmnJ3bN2=0Gze2BCNu(;xc-wEVOA zUvR(j5JT%{kuE^S^H5UH>!gGjpUi^)Y(EAg=Q|!>4TA_^tdL!tsvfdB?W#Y!BB72X zm^{#{*Vm`$UwvNa@wc?hYwP(}f5ya!O0M8rRT7nHc;_WCADQLv0j)jkSxZai3Smd6 zX!hYRLE$!$n-bWv-oGhVY0Y3$Zs#eKzCv`tI9{EabR(-;0PRZ3n^KK&^*-O^Ny#m1 z^1wTxGr~vgrYrL#(Kt8invO}8V<#&T*eUI>Glj}q?h3-aY;*~%$&Sx59i z2s>_ks@e3PUwim(o0R3f033=B+fJt1{%Ad_OMsmmwb-eT_DV;*n<+ZND1ne7PL)(D z>yP%6CS_~UU003t{7xWWj7Ht-SX%Z)MY`Eu8N&UEaG^|;NhxQDF6L}B@>v#%?9dsD zFG3p#aZg3kUcZ+KpUbJ&2T2#K_B=3-5*(xO7m?UbpZ-wBoglHrhS&Q2T@BdcF0F&9 zm_m$fs$M3)+>tt#=|sFOD5vaBJL!dFcJ;M$vRFj*UYqw#|R9 z$R*f?cdkc?vSQJ0ysE>O@3fh3^%RB@n&^RMwZrDKHKbr*}^a*Sa3mGbI7j9JTI~xuh|bIpK%(l z!(P#Iyn;#GZ1$59hid z^>A@S7sX!kJg$W2cRkmVue++5X9a-wEDCjJ7gZ zA9_p7!26x$I7sua*XqxRu*Bc2)*;q~wv?G0z9X3=OS6*CI)+dc@(Fquyo5($7?E&} znw(o~?CPOx`V}LTwn;{NfKa=3?g2w!qM07~#hwTCj|>4e{-)m=eAOSde)MnHz3hz?jZ5&j>;zFEh<;e*v%Z_f|s77t=wQ8uz;svM72Y#V3?-il`<13;iPVMNh?uu z2WjRKWKSgBw7^)~*n=Fd7KqnSHw+p$|1HIC385+QSBRbWAOiMJrKpVf zp~FbWLf{x#W!hBoilXMFTAt3$Cv2@zx<#5b27Oh8b6jq7A`d|}oDGuVmrhj1=5*GL zn&{kvs`JSVq_*_3bY%p4!inbb@Fuy3QvN0SP+iWEe}oSUBv)>xN|d|=7Tg3k@HJ#Z z^rg_I$74^uQ#dQaZ}ML!k(rZ9dffSN^bqidMd2EiXJ0KbT4THr)-INojXXr@bBt7y!c>k+WqW4l2A8Sp zHB(NADI+wMJ9~4}<}WTP7dC^;#H;x&y%5IY1tEMylM0G*bEQc}d`HIN!x;2EA$7Y4 zYW6D+j3z?Rv1-?9pT2S=>q*EF>e@)u3H1I-m79MuWizq?Y&5;gGK%$5EaK>oXf2Gk z8El7}fx(0Dm!z-W>?j{a%Os@+RMRD4`#4;r7I#KL$v-N#+Q}yfw|R~?wJuL7(KK}7 zC5HC`nD{JV$n<&n+?i5WHJFMF9fJ08k_?sD*Dc4zJzFf^_WoFv&gFjH$u|4W6Efx< zZ~bJVeFyf+3{`eym1j$&nm0xewQt^GhK?y|DFEY+aJQx~Ds-QE^G%xijGonwbiz zMOek66R(@n1d>ya*LG?4plQ9YOSL*$C#Rn_qY-%Q zQM$kg9X->Y`F08dORe*)9B=MXm0ousZ`Aw_2`<@~-xS_cr&M#K=Qk`)3{DYYP4U<5 ziZJ40PJ4M1#1-JHgDO_jqx#Vegj>m-n-3QgTs5ioP+6Nu_r2rq$n{wGIa@imD`40W z=!}G7W!7E-PE)GzYHN(nngLTjUhjEpxl%6JWXk##ABiMMK~;ygGK?NY%hDri@|JSp zcULY3{~BYJ;sk1^3y5|y7camVV!caArM`JY?24Go%3l*$xB~>|e}+}nLo`v~g*ln-jH^XXnn(d=B}VyTH_qJ^+p+AB;lq>N^ZH2m z!h|ZU3Hh&HlYVYSITyax0Nuv^c`I7ITXN`yKXxg3UI#<6P!jGuX&W9A>M=?L{MJcc zH6^2`S!>~5ATnk^N-WB|_!}w`)SUa0uJNPhnE7Emon;?FN46CEGYO|TO%M%Be<4~l zWXn}O(kdU`dhdpw>C?W1Oj}hSlV=9S@k;}f+@-u%wTmFRCpKv`jZim)6c4ZCrt+2zG_>V4aGWZh<{pVOTTd7Eyp6VLN zZmhfCc(`~kOo1sThwDupIk)L7S_bH+CR{s5#)s z#ig`<4eKoJMNOh$W~AOAND4nO05W zoMAp>+gq#qm_dn^s{_s?r<3yM9Kvij?$ZujF~2n`-=k?VE@aOX9BY z&oXQ8B4S6^7_%D4uPO2WmdhA-pvu#)0wGQM4T0#f9MR8j!mMgq2vO4ug%4dW?n%}1ySs+SUW1<Uoz08&__pCqT_WQG-~PZe2SA4Re1N`B~$eQvJNJq@^+{FDEx z*r675EHwe{O(F+5#qW(OV91+^da305V>X*nM>cgbF^qMRU9I0jX$%&Jujui2e^+hV zmgd`6de(a=PB^!$P0Fc$N8&F_9UWkOMzsp?Fi0^ljDpeU{#;TlFP_HXYB0+g$D0C7w$1SP zqz z$MUc1k`^8T0zcC1qJPT?`K^}bD%L!mQ>YLcO%5GnoOc3g^nAZ!E4>8f$a6y+NfJox z5yT61*a9Jq859fPQ!U@gWI7fvZVHWnbNAIo;dh7qUVF6EDzZJtFm!GR??bN%FW_Bt?POZufD;PO|>&RY}5DY^PDfRdtq)THM6~eqgxmq5SUT+iqntiID zUBwE$@VeTzV?D7TI(-~1l3g?CKg=;1{fiUeB<>=B_aaPxd`FzGt8@jpe0IB9WJt>m zaVRsMz zl!odk`VFcObaZo@D~vJivS;p2&84Hbo2;jfau##Y!Q8;b^<%aP*4PFo6($?_YpZ_C z7U1=ir!7G3^~dkH_;Xvn_)WQaYv0kL3u_>OYTaNMgv*@a?lhYovgpzisQE>2I z$aSdtZF?OJWa8|n8iIt+3-D5RVqPkLetcOygj^&Y{s_}^Lg7LlunkMPgw`WgqM5wXjYCzBo z#2OuMYikZTo*WdDb?PD@gy9gpE*Z#S^Eb0b3>e011S+$LT-VZd3HU}6hx_ykSem(D z<+}A87=Nm6utr1mvxy6Rmeg=Pi>F!czMMW+8DsL#U3oj8-oET7YvvE())==}l#?3t z%4nQmU_R$J=UhrD6ILcIx{H*%N3mM!Y&K1f{Bp`r-w%r}T=2W(o};;meQ7CE+_f_8 zrq!B*$CS0TP3V#9$4g&CjUSihVZ6dgLbH5nh-X&iJ{CX52?L?M-u9&>ovChr&wl?a zXZQ71E_WJX9g07Nh;yE3*72X$`xgD*Rr_AX0$KNm1d+6DTTSy2xa-DpmTUan;DO-+ zJp$Ux3B+-Pj~PE&wF;8gcici919kQg9x&4EyAUeIWcRE5HzREL<-d`93e55bNrvrq zu#QyHvIj0jC@f1geiUEbsyb_M58LvafXpJyTVjrz{jNaxZ$T|;*f4Jp;eKt2^< z(`j4`KbupJaKiy<_4jVap_79w->mLtJaU@QPqRaZ!Sz>n)@m!e)UjYv#*=}KC20^z zBn&n$Vl~i8Rp>+Fh>*>@GzB;wll}D{t~t$7eKq$uZ|RMKZG06Kwp| z`eltS3TZ3|1b}c!r`Nb-?&CV2SvS3@@%V1BO?d+R&KX+sVjtH>&g2pwN9waQ#OlZ` z1)djiatfipf&`3H5}>G3A-oyGd46bupMsAAr)ua8-e5IiT4BqZBNH?vGl?VNoR2#l;`snCTAYi zEsh^sxrtT7*zuzzXM0DvPdm(TYbVcD7P_IW2Fg2uO;RheIn=F~w!JkwjCJSWiUtS^ z1JLAfn9;&&Ljh7nLQ)Avu^GsV<22B!OioN63{Sj|R3!NA zFZ%^Jbls+}xbpHIO>sZqR5HoVSxzp*Q&0RZpQf3($aa;p48CSAk6gF-RIB>lnj20# z8h*wq+?#^5Wcl$wnyxY|s^@Jlut-WSCEXz1-Q6YK-Q6i2OLvDzgVNms(j}=hNOw2B z=l8#^_uJXobDqhk@0l^SX4^vj8E zl}h}22seU9m5}zei2oaWj2#EXSjmZ19Pf)>Z-QklX)-|a5 z+Q_5xGpsg(LdpbF+w!s@Vk&@p#PBOCtY1+~XalA|uEp$R#6GJHhAZ+POXcc^ksP%9 z*!>`+llRZa0=lgYd}Ty{4l zJ;)h_usL6Tp$2UD1C(!L?vt3wCm03JL9fBByqbGNzH2lllH9 zY{L`TTv5bxe5sdw?!bg>#c@pOm`WSX-J0`TPvxocT1^oJ-c9_7n?|T-pSj-!3vc47 z;Rf#RwMAwUXA)*?g-yvX>3<0Qg%=y9-eH*0BiTi|qqV@M?{#r5w?jHVFH1qJ7VBZ* zHY96cYN&qsc=6E+%maxG{<~%y?<>S`vRTY*Pq64iC5XV+Fufrl=}iHc3~_i8s!`1Li)kJajv%PLNT+28MP5`8{!OqP0)9vrp!m22=XVX3w* zMc5tFLBAID<-a#eKgSKU>*T=JcwfHFf`4b&0^CX1dCaAA7gx+M?ix&@Hdr8W5|k9M zGjS)4>U7lKaNGHyGx`xZVA-4CU{;60l$C=%+AaCH2qCf5;dlSQFim-ee*NM_!%kvw z(6gF)zNldX#Yw=ujOA8G$<8%+<6nZdjE)2ysDVl+z;G>1`2A#WPA;t4GWHhslz3%{G60Tg|@FyODZ4 zuHwHQwW1T#-hQs&qx7<*GRkDD!Sa4@+`_=Ezuk4awNs!HYag#d(h8hfP?NZJB{AF2 zF-)Dm@^EZO@uP>QqO{K4kA{_bx?FrH19=sGDEj8y9kjwXppYj+9%~!vA7y3I*R)GoAQULTsmM3x9(pVG>&&| zurVrR{V=A{>icFH=K#W$Vad|zlBwutsL9H27LywJFoq#c~ zfzd9p5ic)aVb5>Rpz5O+bG)!UtDl(uHJwwp!(KpYhFaHjhIx|Y)hytH->NYM@p^Sw z`4U&(Rku7H%k0H4f1qzgeo`NNe?lE zOvTU-F25bOFp6P!Z?|d+&)?^w(+24LqELX(bB4pgNTI3$sZXvz6 z-p)BY7<2uc8PY@gZ>ml?Z=<&+5r^*pp^`2bM{ICjS|?CXTiX*rds!+iZjn-G!lh8( z?|S-X`co`l_?&cf?hYbnr)Tp37z|JJ&OIo3^FvbG>eJ2Ywbk%@gCCTb3d`e@Y@bW& zUkR}1UjKzn=PetNT*UhH+JDza=;=QuO*C%JutvsUs0iT@PDVY&;Ud0SQ;B|gx0ScI z`!AW1Xo)%6(Q3+CN|!cqDqU?E1-rmjKWgU>e5LeO{T(ZSU!E|wG;<04@+MExWMou` zefrLMU-DGmt@x8yjPH0AEjnS$ykOm>`6Wy&%(FwV%#28M(ZKk4G2i2MHl3NV(0p5f zLyGo@STnAkpB-^q}?>Pz6A{_YgV6zMdMm;EUsIEk%4$d+gPdfY1e=~p#% zW6+8|L^M54R-)?ce91ZX?!Nb*5=~iuy`g8@N_WS4WXDrag>~l}h%~u`u-Ay7>-D$s z>?v@HiP8dsD7K1@@W#zU2!VynMd$-YeJLA*k^eOUJ@Qqzq;9s@3u}5)ydyCQORb4- zYU{qi${pSx<^vr7V=#5jVQLlB;9@;DTRBvCXmflK zSGTsIM%V-uVZI){z!IMO>EfY;6P+_KASo1KEMBGbAS8i=bg;stWY+3^Hmk4_G?yB-O;bwYQDDNO+?>J$7 z(^1)Fwn=UFs_9Q^GYGK~6&?IltQUtI-E?KGbb*?|NZ_}5IK9m864Z!Rw?5LdW>$5d zU$$UM{Dd!FymY%SWDtn*lTOJv-U}^1jVN}rs^fAe;UJiK^8h>N$c|k%F5=m}>%Yo{ zI|Y25SWD&1P3#sfE&Xd?(RGd_qFNFXHZq0Jc*bUk;`z5}12+g> zhnH{Zu;HU((2OPhxU4cm?&6KQ_R;qTz<)L)E~5d>6Q{?IomY7T*zW(9iI`LIo}?{GK^t` zwoo>Lls|@XSEwDkVoY0quZ@w+3JcS|KscWg?W$#9E{bhSfyD1`COPVFKZu`M?v146 zE?EP&9EPyF2j3ABRA@OWYCH`CX9s5J_Q!RQ^Q+@ocZsC>LJLHK2`e3)^Yk;{%fS|X zTaf7ow$Z8zsa}+E#~5aZb*hgx!F;p1PfWXRvCYeiPT0VzZCIycUo!vWdx<|5=%(z2 z#uGQ#?3wqeLPyVk>cWp{4ugQ%|F8ZM>CxCAKPAIst9D^1j8GOuGe}WIu-dQ`&*)q7 zP#mnAxLIPUMLwMV@J^+U<(%Oadh*?ET5yctkxke{%?QJO;WlMaIc@S0N9)LIeLua- zT=sN$S@0WVobg)fi$B#ptXdBKK_>y5?vTRv)m17YKPtOM&=}gbf40sqor@@(pxoio z?0lpnN8(5fdk=}x-2z9nt0P+hrWmJ>5!q&H!{&s{1IG(W>-M*aIyuuqq&Kp!-!gR$ zs&?fw@E5DFT5(Me= zm{$4x_A2)cL$G;YK8F#D3r&@2N5Nr@4&MNw8^c^!t4HDQ+PNCZZ_G^nW+_)13bcQV zQbWBBxcmHzJmXk^Gx^@7t8SoGRmfCI)il$&7KPTYt7?!*jYt6(|0XIp;(Yqku{@)q z?5KD4PXIy+#gWtglW!-HQOM*dUV-YFu)>HaiFP;!3Bq(sPc>)k^-o zu!}2XdciNY#GM*IZLzNfU*+xg(BJfG6sYr-PW)3P=N^hOPW^Rr=V`BmO%^L3=}9cb zCRA(vLg>ZE0J%}rdoZ>Ig>N6g^Ai~H1o&Z9CNNAhYfiTk&**v&>3*;;M2;NABg91r zjQF|!h3Hv5OE#D5eeCqnpfA-lxSG7eXVK4l2)%Jp8!4S6wfTDkkWVpjOjG#`f3is3 z7VZ0*9x5A_NPXse#gL3m8dHXER~Rs-6?ddK^DXMcctR&t{$2 z)WYzj;*tp7t`$JNE1Z(g$j}%6S=<6(+Z2rXq?ddL+n+Z3n?BRQd8(EP4Y%rr=7=Ww zPF#t-f}zpj0xeMh_+FHCX(&Smdq4? z8&@+Qrbwb{n1r40-#Zlw&-WL({v5>>m1$xQd2qRc$_Bm@o-(a|B4qs2(PyZr@z3`7 zZ-rW#O&{LLS_|jiwNGo?;a};_ z{_lw~5y$8IG%j&W-D+vTav`qANB;R}&=0i9YRHi)shM=R<8NWSR{9jRowHtx@aj)n zqQ3k8cyj)=##?Q7H9WJpPE%zKz5*8Wc)PXss-02l#I+HQh0M_}d$*9c&lW|vk6GVN zc}qeCdxOLa)c1 zZD2mwpe(G6%xQZ(*lQ~dlL!2>>T_Z^h$^ z+6~MYAJV_<@AU|rwU}oxfABi`t!943{n($slW5o_FW!p4&mv_}XU>UXZ#m!di=|6Vdk5_Z!n|so97E<6+zO?W0Ni^kv+WVW zAn&1D2Oc~@3wdvhO5Y-H?RQmH@GQB~h|DZm2G^N5$m_t~4UnU(TGOB5AVUI&Qf9f; z1z=lFYg)Rm@*S`@8}L&5Hbyf)4dCc!y@GveTZ{7cJAC}#CiXt64`w1-k9tZ#Wx-wB zk7VX#i~}A4c$^%IfYi00;Jj8Oq?K>=_*dX&64`HIB*Xc=&WXBW ztc~tst3Td2Rre_~_y-Zpa{&V_Sx6mLp}g1aPGFUS7qWz6EyfMj=l_CN=+PBG3e@O3 zrwA@-qiii)?Z=Vf03o+(ip^A9Mk62ff6!E|7nu#%89{Y~Y~5prNY-n=%qhIRax}%8 z@6i=&bjS<;;SXz7z6-N{Jt{z7y%T?@3+Jq;Jhk3|zU#Y+XC(o)wy~BEH?cDwXJ||o zG{zLxq9a+pZY%WZWv!q{8Z^+O_r`NQ=u=4v>p$9x%1FY>kz;vV(f`&5YzANbax;%n?;O`As2?d>s=+ zEKBE|vEVU;uWRZ!)WH+B)K=N6u!b8H;`fADv%KF188Hii%hJ4_jC$Kk18l^8U&>^# z?*AKJ_8*qf^!T@PE|3bga;G?5Z)oabX8+JGhaJ>A!#uv5X_Z`vnWPTnL?7c~*k2l8fgZM56n)BT*hsw`=JZ;)*tG(WBv<gtR-!nxg}+JG%c8s_Qh%Dy&N=u>-&}rMU2Vtg-_(IcYzSnx zGj@@^4i~;k^sckq9?kFLya~Hy8cho?U8XZ{XHOlQDXoS))gnX;B0@ZWl((?Qf3#2g zZJF^X zyVzTPG*6R!G3Px#-`e}c)ua0kqI?HovDITXw-avCs)rAcMo~NrLzc^q!r^jKo*p1x zxbAMg$X@NEaXus0beh)hIZMu~lBb)5T>4{6B01?tH@tRdE{{b4B%U(5>pM>rXCYd% z^|@J}+>aGh&_1;H8&y`S3PUw>I*I$>z7=!VKAx8oC*s^U#Dj#fmum7KC|ZhhK4&!} zTuPnrB7_kg3l9hE<)jS5D-J z{(>);t_~kuTsKq+v5g4E>62B6&98)%@aAils$1Z|YJvW-)>VCivZat%iKWT5ZYj6I z{~{e=75tvogR~hmbOd+Cg2EQ?E2%FBZIu*_EzeOl$zanNemCfh>Q3XMlq>lK4M-_b z>FYxedB{3h{B~<3SdOP$?L|TD8|jcsV-1y&mbz~ARt{rq@1t66vMw&IlrD8c4Z_Vb zC-i5$g>Ea)6RBmhFKUF9>1bD-#dddL9X7VYH@>1@|ABcABIMNat&LERPvS4`zZXrjxx2H zbc*LA=?_B_(qN=BPAI&%y7Gr1y49MrBkVakEpCdL@^UqYIGeYQq$bvQv&OiPe+Rp^ z5CK9=s!wHV;cX?+_Zp;jsZJ;*=A2p#KS+PC3jVevkF+~Pe>>Q_lm?H&ziFxRA~E6c zbt-cNSnHXWH%Y^^{$wfRdVAv8C=q^QW${8?q?13)1w}G+t!~NdMt^ZNhqdQt&0|S& zc6P`RG+>Km{zSq*Wa7v;{yoVuQRBbylp!3C{#%c=(GvG&7+skO?h6 zV(aC_EKwA*f?vH*Q)6@37W>4|uwRkmkk@J1!;a8`9_x*c8Fop;m}u9BoDJ>Pbb+(%{Jl=TJQnD1}b= ztTmEcV_OM>dP8x@gP*`|wc8OE%*l}ACBfYFDJf_(35i&CP^=B|+E(*tt=E!fd zzYd#j(h7W`IYh~gU%nHq8%304Tk+KC%Kn+4o=iyrH`7trx*N)olrzZd#Lzo*VzlI= z=rcti*||$D-*xWIU2p1mRzB+?5S>0atygz2; zu6UIdswli~d&<_}`-Y7N(Yx++$$xfw$=it|+hIP10Oe>$@gf4a3mAaT7gOxYar(;fVew4;-1(z{JQ8cxcAULU z>e42hU^}VG!%d3mByij&1I)nmM%jL^{!K$GhX{ujR3v8P!8On9J&1Jpw7t(o1sj&B zkB2gHVdWKj;Hwhi@+>FR8977?#5{CpT(0I}Bi{GDMD67hq9OvT!ffg<`T}QhP+iL* zMB6d}#dRW6`BH`4g*F(DP44S2df7{TP;QzsCJzOLuO`1#Aq`mE0}knhpq#c;gEtog z45iIS)6ku30=hYP38e-b7# zk@9vcB^eO2@1?pDi|i{jLAi`7 zPV;(q5nHUY24sXvU%4Wgd9ZZg@=&Aj*V~f&K2D{;_Fg2e{^r55vHfK49Z<$?W}|cNS^ku zlGWuGHh$cZdaes=>YAv#mxg6B8RsUV7tY%j`cW^d-WR3f`>S0xWjbM6mUr;tIUby| zw0mIEYJEAGio9;h*%l*;@=%w_vF490W|lCAorEWtnDQkDUY_3nr`)V7c!r>l{Ku03 zy%7P7AjsrC4C%Kr6v2tYWFQZ6$R7AJ?8%LG=qnFqa5^9TJ6V&xuqRhqsi<5Z^XM!6 zw0=EvHm@ZOc>y?lnTVmEvw$wT&$VNuQ8((PH>-E$BrRQt)NH2nu9>{3X`|Y1q1= zpa^%wfQ}k4MT-XrIM2CB_l96j;!@4Jn_eW5y)@np2~Y-4f#fTlCW};^X+XzWVwWLc zZuN|GvCH3xWVn6E@M?~FFIk<03apx#xNk8ZwS12VA7Yr5S~eGRk>=egL6fHg&P~A7 z`}?plu+s%)?EaI+9^;_XTUP{mv4(B4=)Q&Hzbd{PGUvgj%9}1aaC1M!&DlFmb6VyQ zc$lk$7;|jxo7O|Q5K&`KjfZBQtzfIs@p1KW&G3CVLKY5Pd0+eLmVd}cT04=~z3UcE zJ@Z2eSs<2$iyZ2?=L$Q=h2?UhD*7FYPwIb<6bavoQPCO)=AP|7}t<t+pDI0oK6PwuiC68KT8mp0XG z)6uH?EeR_D5h=Dk{7iFFR0bv=<^;1Z8L>#-q!AR92;xyN`3BNkb%OPlGpPspttlVf zu;l-G@4v@TpqR)rOsQgOLeMh${n4$)>=q`|9FR?qt+_Cse0SZo1V7i6lk&_^@PTtL zgz7D<|Eg#b!rRcdeIP_*o9M^~*vNszAb!m~#Ps|WtOwkdZtiSj*?-@PU4fnm%UOsX z;c7|#?pK;K=(M6KRX7M1e{PpS~-3@T@V- z4B6*6^DU0Cc^c&by|~^U6Gw&1$P=ttGyjQj6OuKHE@3a6e8hz9yoa+ zrU7eTHn#&p8#3hYyU^5d*VtFhJBEeBI<;M&(k1bqIlR44{^zpVB>zr5uORF2hF6fg zwLf(uee@M8u*Jl$f#qO$n!VDSi2$%z2V8L$P)phZ<54rW`a50C9+tT!Qw!^>cRp4T zFmqF5m>EVQhzx6f8dsyGX26lz{vhZC!&Ja6d2O|A?G)&R5VF^}v)|?ty;UZF$eB53 zK2qboAy(85XY0fB{V(FcjyHx)840`NJ~3D?ZIPEq+bw)66?n6dDJ!ASckx63X`WOD zMz4w!Gbp}M*r|U}0I840O8te2SWAb+)`$lF1_v0V4Y{N`w$$xR0sHpTjzs)5!6`DW z?cm}xb&!@6whE@8`!2qO0|)G6!QQ>qqu+D)9q5lS-%l5Jpy=W`Ic^8ln~U39!O3X=(~@+7TARRkecZKymQ_kgshCkWZ&UiIN3GK=nv6;&d6Z$po`eqRLd zy45{r7dacwwdaJbp zmggJ`g120oe(G^zdG#5_USZ`83?#Hq)eJu444Pb8{sVF0gZQPXjOwq zV`D3fy5D$Tdqy#{>KnodNpU9BQT^ux%e0J4`)GZRa7Hup63MiAYeM7uPd`%oj7HU% z=)Fw{XP!onqe=gYH@2t}!FwCHfVK*tN$lq|pl5+p3I)AmN-5{R#Unkrpc8I9sV|&Y zwo)o?Y7;%V!9stFvsgbIAe($C_V!jg0p2ii?xZVAd{+Q=QI^BsEq-`$3Jo{I8;a;e zS|-99`ZL>?3W{7%;6E%D{iTZs5AvFox=fgOZT+#m2JyFGlLDJCtwBt)eTil_Tr>;- zdW;K7u8Ocyl7(kwHeTqM1i}RGIYF#>N6u~Z{Hqe6I$tMfBfB^>hQv(+{~m*i$Wb|eIT!ayHd^p8fo;7&2^DyFqk|Fk;b7yvZ7WWrBV z=kPb%4}w*BJVS`kPml`igZO5x^cI&I5vw3t%`pGR52Anp?p2hRCg>z~D+FE?{h+G+ z-$3u*j|AiD>t>#j*I8Y{DOHN{efi8WxUOLG-hw|+l<(h#?{#;$%*AlYu4Ux&8TAi* z=TZ4U$r83@d~~S}MIoh|b`t3D8TCx2FP%|aYsQ#Z`O3x0oFhrp#@mN_8Gae zu)T7L+r6R8x(h{FbP%Eg|qVd?8$$t#IZxfZHnP4m*j7SR9=Zfq&+x z+}Gkqmof4q)+UYmHBv|)w`G>mp@YtW|351rM?nRy?D|K6t+I(HIJD1057+GAPadFp zPP3!{T@{#%UH6Ryy722=V=+o&XBP}xu!Fd6pxUxvmCk9OpdP?Bwv$L$a|TnQ7`caO z?{H_f8_17-vK7Ov{N%!4%@b9)HWhL7%{Fy&hpiw@fN2u_kT3&q3agA8(LT{J@34wF zh-os4#rMzMo>lMNH2$U>XuP7}Z!scQ=BwVS&en&+H}qU=(1|^|R9O9wD1^$XE{HK# z<}%&2AcB0^+wbl_b4p?&h&%)Fs=6 zUrKDB>~4c3V`G`2_3Y!eV*u}H{9GL5ab9;X8L6!hUXr-{1PikqZv>^rdI${_+ACeA zgAbI$e)6a9puz|?^iVrV>qAx(m+h$ZLc!YK&j+n7rkX7Zu$&r1gmasp6W zUxe27E(z~W7MDX;(tgpxyh!ryY+JyQyM$u!hM*9Q!#@Qh8La*Z z&p8|d2Qj=2fJ6TVZ?T_<4ZuiIN#oHk`wTn?lmSd2f<1xslj{vx;VZ6Ls4LmtDqG|p z6JnES#+nltR);`eXLP1oYCezh?$w##gb8u}sJ>V%=trrK9){?vM@^P{z-05Jy%?F_ zW;Ht<+R%XH*)s3qn?vY%Q?w!z<4!OwOaN9Y>zI^lLqwilz=F6kQ;tI9 zvG{#)>~@GNMN7g^oe$5@Km)$8O_>kfpV0~9;R8MrD5?I)<-^bC=q#5WveNOl*YD31 zug~^ak5bXf$y}SoEFE<0r3clp=+ZlYXbZD^ORj$+bV7a=cGu#NMgAS)j+=SIfkg|b9xnN`~n~d9M3bA zPXl^AJ`%9tmuMJw6^bgad{FostJ7FbxbvmWuq=qMdiqxNWj}~dRrPg#A#!VC?g`q#U{{1Xmbqr=B}r zuhuxTxKn$LS4bki-V2-nRhH!<0u$@4;X&m5Ge4*|*Nk7g{il8L@I?t2H4#qWB2E2? zDtOejizSyx8({qFv&0+A)JNR;t7m&puGGgCu{2`EY(WaIZ31$4xjZv2gGfRhENxsf zy3WErJA{l2@s_2GcFB>rBQ{I<_`R2BbNiDYDDt+TJ|<`e4y%#hcke`_+U+yI*nmFE zK|Y(MtYt2&oGW?e^nPt8B*iM_L?n{{LThnzDtZ@Zui(WZrf=Re=oSG%d0VN^NHrlQ zG)Zc!KSIxe(d~>!z?vftvY0JrA{#m^X7RHZ!~kzrHIJD_W>RR1!}ZB`K}bfk(Oaez z*kn_}Qm6bL?Z~k{Emf|~9UpE>@daszpY041WVntU(lV)XX)L+Q10J5!V)Tqd31h8J zWi!b9xC=6bm0SC=QF?tJUyra-w#>nu zkm_l)RU9<7xR~W*<~O?DpS|T7M5c6$h@ZG&Ui3}Gc?VUi7WC#N|K8uO1S}`o(XUtP z5Kje9<2IGUO}RvyR!SF@K5p6px*=aW>EP-Q$NORTb}@?@KC+%Q8fk7N_Qw#x$y15; zUvD1U_IJvkk!;8iyE_|S0r|1ab3dm}@w$va zY#=pWeu75+P!yzCf3*Tr^A}NKLz1J67isdsVxU;qynjLxws|9bWN9{X?jwQh<;s&x_$P+rHAG)}3lgl*dB55JeOjkZj)yBSN#=7gQ(x<@zDl)4(U3$G)gQRg zo+8r3=VheatyJ^+!C{|KMX1+n3Lhat^ z5i!pUw$j)GjYG~CZG@lc0Gy;k{tzql&EynH)M;AG3OHI&%$cYj;HAmvtDQWCN_vyU zXRZK=mJr-?rcHr6M}-8|G#VgJ(E3dG!$*yNVdaT#iY7bAH-8D&^)wKIFsn_!@Sb#t z6jM-hn}l?Te2~8M$%jgxuDwa>lS1fCiwlAga8$%V5^0q=CeH^FrZ(~(= zxJ}UL=%Xap7ncpiZMhu5Ro(JnOm1idZd5+vtgUU;TkT=6_1I)-Z{iLjv z6L!Jma7U{jdZTJuJf>1&W>o?s9FD1iD9BhqeJO^KG7bTA+h3MS4Tx(>JHnRB(uho# zZ$Kd#p>A)&GfU_g6_hj=4z)NFeS>nJ-GrucL3zPh05mgdtxZ=Kd$J{^u7{qPU^)yX?b?^y=gDY>=X^M>^;^0z0T8=Lc!8R zBm41QEh}^yr5}O%GgJTPRvOvmEV z5u(H~H~5GY8-|I{I!!|cAFY)sn4-)R)1qa~$m9PpbATB-Xi_kZ!Q<|8OrRoZ?oU91Dw$8FS~CWAOH zis_6YAS=Z+uq|V^G`;8g$NhzybbWyQw+bnReDUxecS@j`2pab6DKQgbq3y3#O^ z12t6B;Qhu}dRHrxSi>}$W%Ud@-@+k#kpp#?v(g@^IZi*+!kH%Ro7?b8*r|bNbqhFW z!+Mxo9Z;FWD_C^`?^M$uFkzq*nkPy)IwMDgq#0X~RFUJiq-~K;c}Iww_`+rKwlJVF zD*m{W0$pZ2r(VA_m?PMwz61IX>VJWp)s4Qf(>bi?RK=C~s6Egq31$?wl!580k zKE@Ua*EL@u#=o$8`*bO6MK50oFRDG1gW?f*02$zMoSY3wogq5724W5hj!5%I6r%1$ z!xH8ALCy+ArB9A`MMb0LV3Rcj)c_r^4#;C}gGdx}dM*%-PB^{(1xp{Q$2)VdR_kOT5~tmD4SdfqVw1<}$|E02q_A{f5RvGmHYO{oDD3jL zAgFX|uqjB7s_8~U(I@Ud?|?HG+yyRD!P+uz2V9GL6)gKwiWCo#jlzUGYqOM3OBcu6 zuJ8fjZdGY$a2E|`N(e?IFM04Bq?C314q}8CR|{WJ$4Mwv^_5{c(T!>=tg;?`zCF}X zXBy)PB+NnUBysU_xgPjXxCNDqeEE5af+kddkVobxVpmK9U(iZ308^I^{92<0B2{xP ze5@IX9K$5E|GG(Det3A75BClGXyZgMt3vGg>qH5FnhOOpny_kcoUE%1y zUUzMU+bjecx#{4}!tDucu!)lhd_H67H}zTT2l}4CP*LN}@`oLy&~Tg}=rXO+A|chW zKeVS$W%faCboND#Lcx}tuLn{pI04gISRBu2**Wqwk*fZ1jhS%Ae(cnL2_3!U-uGEm znbmMR!T!NfNHr@)p>KtrD>8RMixA5F8H2V?B68OSNZs_gu)pb|G!#CWJDg+E>dEZO#2sI+-RQ*=xbU@iHBbK==`iU=RXyfVC2Bz7#a>``p;9L=mk`D zevP4hyrmV5@W#S&Npzgp)|TFjo%JXimI{ia4b~s}MH|-k2B!SnH1Xv;flP>Z8a2b zi>P1*Gdakx$u;0In4qkvO{C*yeOQxOs`5p5we2>~5Sl}LcR?Sd6%M17rO(BXrizDB zRBBR+bz~;Cr~y7|7!A%K$D^Svq)=T_e#fcif2kuzQ1}N|ND5SuOAD8St?%2I`v?i? zP>{tK&#+X%toYJ_<>i93QUDEq_b(aqL<3lGcOp_pcY9MsOuLr)&~YEWY3qa0O65ej z!Y^Odt6)by)rgU49NP6Kmm}5$7@}Bs)ml9~(8JoZP9s?Sm-Bd`cW=)6eas8T*~*lJ z&Zc_00lhd!$1Z8U>?N4KygnI`#xB!8)O0HFQ8j%-%#b&HsJ6Mz~ATYr@2- zLaGVzzufRonK%x!JSu%k`;L2KFH`g;NH7!X$f~Kss z)6W)Au?sRZZqOfuCU#Y@Z3uWvKYijj@y`(*ABvLyr53qSKr`dEc8De-tYPGz_~nh` zMNyA+?HF+rrN=&KhXZU^YbH8AsQur9&9z3Hw;d8K=4iO$Wof1OL(3nSZ7X=FUmzJf z9w{pfq1qw8{fI z{=Sf0RRtF=M1AW{C_30H8gK(sp$x#*F7&hHvK?n%ksSDsL4o<||>CaCs5 z`xmfxqpw}AB_5Hzi)48a|=L+hPS4%Q8W zpv$FxqxD-NlhTu^R7t3uK1gVO()^w@e3-(&#egsVby6}J*?|U#)mkl9MXeo=1`+Hh z(PxR^WeSVz=P3wa=`@B+KSoq35lM#51o`^Zp^?beDfUy zq;_G~KALnKA!Bja2RU%4@d7b%*blz=WXv40mrVQ&rGBPK6ko7IgaP!132o!fTiPAJ zQFXM51s=(UDFx0@-d89WDDUe)r|yL;Ev!8T?=X6a5Fw_ga`Z1jX=Pf-&(()6_*&1D z`-|Q^oubsXrbVRBGlYe$MQzwH3`pvN^l*Q9a_WR->pQSv1h7gDcyV+nr_78H)g2Bc zlQ43n)YfAP_dX)2d!*LiW{&7tS_M{mE#6Pol=EYPP9hnhOO}glY<|Ox(Cd7}n=@U= z-`{#)1LQO2c76EFGL&Cv@0g3|q}xo);>>OV$Y5{`8;`JafBtliMr8~eFyv?c8KSHI z^6}@6c?agEbKYUU%mB?+nTV;ZusV2V4A~Q7J0D{&pe8!mnc!h9{I@Pzpm-DxzuHGx zKt0pNJnUWopf$m&khxcQ6dE~Z4o@}3dpt(oM@E?AT&b<(+jaa@PO4bgr)5ScLLsGW zR*ux{9Up8zkI|K5%xsi}numV^;vyu~bJLxQ-y^S}XiKH}cf2s)RFM$z#*PGm$g?@b z9<)r__yCX>rrov{;hEmvpHN*T)legDpX?}HLDrke2xa}}KkN?9S;J*r7suIu+2#wC z>|`>D)|8?v1AJ$Q_d*+waN^wj9y2wamkZU<~lnzfC)qN#+PTKWd zEE-qbF2cF)98*VYSj^(_5;oHCDN{ z8NXL6S$izsZtoA`*%p)#&1F1oGeE`qd9zX8Bi{!%#vXno7n44d4SKNl!GoO)6EO$= zE%U~N8KLxM?3HQ`-vQQET0E*eIgf682JNPL|7lPf1m291zZLPATN1nHP zNyzQr!8Bxf!y0;MgupD0eflCzIE-R21N!52hTT7cQJ9@>FHzf^ zolz-FSE}!`(0Tm)@$_~JuO^ef*YWAx@z;20Jm$ad$=CA7Bp~s$toyYGxGNe(d=2r_ zXQo?(i4#jPPsvxo%KTJ&@74J;#gZUO>H*M{%euwG;Xm~a=eF+O?}CPurRYx)$);<> zNDeLgNq-&r0;q_mfWae)^z3d%Ro~E!k+VZjeEgqtPC-V}8fm{w5f~jb>CouQELW@ z*-v0o^fe-4vYowRA1FQ^1h?n4K8zgIx4Xa-R;cTNH|d!#D%ZLhbzTKS7O+7D{N8b< z!`D{TpP{50^S=UYmVnPH_mMcGOx-W0H3FxI&D$OXLptm}6!~`X)#VHPbcxrm8dRtU zRv)-1k!+mWHr6hj>*Myv|0C(D1ET7lHY|vAu7n_6OLs`Wba!_n-CYY(3n&dzE{zJ( z2qF!lGy)RR9V(p?-{JTD<8pT|cy~_B%ro;mN9ScKAN0fHZ?lU-kn<=#j&)GdVdl}|%tkJo8iN?+>W_0G60#CW_XBiHXQx$Lj_DGs{nyaX8l4sm~x z29RwEXk3%MH<3rj{gg~e8qxJGgY>9cKE~yFq2*$Ir}Y22`sD8hqqfeiqX2d*dya$d zJS`wSq>x&_h0^7?b+peArN?XT zKH4`ik27_`7p?bjj;qd$ztfMIWLsGNM|qR{>?~%131Q=hs+tk^w$bWc)wxa?C|xab z6FQ;3os514Lb%=|GE9MvvylkL2=ihC9dM@W>{m5<)by;m%5mF4E z%w2_udRYO=s(0DZ#aK$|#fbSm zp_Oq)OMfgjjPe)4!%ylOg5Q5aWOC0HN8dNSMtnU?XwuHj_{CABb~-hMsOXH_hjsLv zcBMFcN9Gc82Wn|gsr6JqVW(wYmKut$baafY{gF<~_P$?pqp@2`L|)!XjR7(JNR5F& z>IJ;4Lgbrpf#uETx{BW+G`(ux*C?`yg+GRF+%o@KgfOdID(*Xm5IccFbp2!@MHh$n zU-I4$5?E6=6gO%E|8@AKE~ZNt2=w~?RVWmB%l_@-hSqTA`!QxLbsw0)8Kad6SHHJ$ z8G-VDab^g02`plZZ)LO7>BxTeR_INd3|GIwcO&J~9y0_Q_zd90{YgW#PPRWI z6RW4yl@8?N;9XnhKGt}OhmJd$cFd`bH<1ow4Q)v%Dm$&VxFsP8+$ejx{Pw&OwJ$s0 z@RgClv-axC9@S=m%~my-$jO~1Yw~=C{O1MzxVP(@SW0%Me=fLUE!bdpk8={~^K2!9 zKX+!9OR_?9i%6E)RY#5{RyHTFFEEs$YRj>qgZ5Jez)HdYw|QZ6Z8;z8DXFiYYN^ z8u*6iFX-Bl?Mkhv=*SbfI;bNL3q$V;d~bBcO=c|)%qp_*i^^)i=dJ9CEivf%m)v_M z(ev4jD|=@2!T=|8c^}Jq@?F}FfAF=)N%E*g1i|Q!=~_|Th)>cqjvW)^*>X=WMsf=`ne`+Y5}P?JJE7X02ZtD7hpw;{fPTZO1}N!qUQ5l{e%e zm19{bxyxH#zTgR8HAlkTc)?VNCc`3bSQP507l$$|eF;|Hkm~;4X33~!$&K3RTfs65 z;EXjBH60I}`7cVyE6=o{puh6;AVwOh~bQ=+G)8|MI_joA|BXS0ZgJF> z5j)aei0NG<6@fxOeiXg(pa#tPivZcJfe#CP+WySH*zd#pA@0E78;` z{av~Eb?nK>b*_NpzRTc`bKR2fkJh_yyi~igBw5_%l&;8Yn|0WAWduyruN#J$7VKqM zn4^hWXI=O_hvdrFhJ$q4L$o>v|>#+WwD_(H!bs zv!NXd+YBeESWeNjK9EiE4Uvq=@R!-5CVl)<{B7}f*A*fZhV@gHV_5w^!kuR)u-G#? zrC`ao5Ukr{Sos+pit6`@7FmZJiVA|kik#&*X_{2cy7vUAc{!RzW2D^s$qd(Np@_vW z%u~TD=&EF&UU70po$1usq@B;jEU^BtvO>o!0R+7t2#VFDWcS-^iUE7prPCTzLI5 z`&hUXxwzHsRQBA!=vp?>W^;^pT~<}3FXgWOs_9Nv^_~smeh7rh)*{Dvon)8eI!51l zcIt7ZRx*povS0LjI;o_+ZeIxxrH=(AbOO~7DE_BvQ z6>OH4UXu9@!&am>xAmbs^P`FhHJlX$JPXIzaMHuMqiFj-L9zcV>24TnHs|GIf7TFI z>N=t&$W$eF+I*7kkT+nv4PHpoDwLVneFCZFyn=pU@*FLu8Likk!j|b#yn?=~A!N+| zUUAs*AIiC#WWOYA{foRIhK^biiZxcKBdSZD#!+EuMC}fDneK3COyt!MSVzA3HpSp5 ziVI)LT2#hOn|y>PZGW*LCNVX&Qr-EJsF$zMV9o9SrHqHr_TL!}D^7j}L#mCQDy%*(qgUU+?l>V9|cttIdJidiTy;LwNip|Sq# z82XUiC<+s<*mr=$^wMzTarGTy*#}zOoxtN?sT5Z z4|Jd_!*-!P6Jw+APL_6jeoSzGbB!3-C%`WaY_IY4b++8yK@BS_dF=IUiCXDsi;9S9 zT`z1_8Zi-uby|l8D?eo#SH;k&+EYbxKUJ#hxMyz>8c981E9Q$2Pb3GX zfh7&j(|NsB%tH#TL!^2T_+DNU)tT|#Tq?Nj)UE_dLHw%Xb1CqOpCe#Dte!YO zSTEpq_?1l&x}@HN^*YbfpUFqhU=ojR=q?;TMVC$y6YW!rMOMDHL=v503VkrGWm#v*wK6^hHgNf)JT`e=6^{#*O-y5c*E`v?$H3f{WmjAnEML}45@Z+(mS$%0Rk)G zGvRe-_vp$FMWsj(%ZEn;dzqYWvxEtGmplH;iyoWD09HNS*F?_Mz3;|#kWq+$G`)bO zkoRp*eAG-iD_o{65|5_u?A*OJAU2womde-Ep0)fO?i{gu{o`&+HcnIdXA|D3dI;2Y zM{`59w}7#>4&K35U}G6ES-HsMsX~4heODh-xXE`wB{yN2d#i$W+b;tp`$w`z%E72%>8G^*J&P2T??hH{IAq2{rEV>9+fonMU! z9JJIjs_rq>`7K$LMBd719|l)<^lb|V&zf=7NQ~T7rKV-Z9u0~i;v;)v5rQkj!r&E9 zh-PO-uoSI(@APqXErhp8WAH#@q}Fx@BzI&}?ZnEi7c{eI6!d(7TmAXL%$gVfVA>eG zCoWvIDTyXm&rv&Hat&I}@&KoN@_8Xg5WNc#>pDq`7}P;Ni(JI+dWBnDnRPiBdmRwX zx^~ywIfz$$sTFMPC)>Vig$TKq?b2w0bz~4Lq*o49a%Eav;C6N6B3#O(#ZYXOd#-R1 z6?eTAd!O*iwYIUFng!IHMRVxq!`*w`0X)Lv`$c%O>~I#m)pm-an0##T~sTtP~!5)adHr%(mo4h0l9= zFN<7~AR8AK`6{n*MS$8hPf#A{$pvB~hGck)ForG^rU@$x_T=f$zt2HErr`c;Fnjdx zR{WSp`AUyy{pV*&fc`$NYAXUUIFrtipD<{Z_P=2{&RG0R3355xd%E%8MiITZ4&7Jx zgcEYqY1dVqGGLw^jYVJ*OAc1FT;Ykzf7!=_)Y3)6=9Q;~mkI6H^-O7oDWB?Vqw!fVfTplf8Lxx-_FylEYe399^K{aBRVPWFjyyySq1+h{T9iI zndHV-@%GW%FV^QzZ1aG*Qg(VbUPPaJ{$y{EH_|d?q_ho~qokAY5Mm%oxO;$LROHgfPZ0KK|Og=U0h*YLK7& zbc-PG_svssp@_%XLoPGv@^b3>D)F9w#wnkCz#$J_*NJ;X;c*l~{C#@w+dk|G(om_^M*9n6h(6U{A*sb&NR>E_FHtmBnMXxK)-KdBb{rL@TaXtdD zperfQEP|kC%giVtrIBkCZ~ShOgFitKluOLxmK?~I6F10h69lpGDWT=vgkRxh!pplG zGUEA8b?1w_iC<_FiM^5qCbqdcq$L^WkH@=QSwiQ}fBf1)es^@M=`?pqkJOx}^2l?0 zsX1^d@TVMX-3uNk#`6roC2D)*iJ`lln_1=Do}aP9v%pp_CK_qLpYw>OT^(t^zUo3o zG1{q)?D&?<{>k|HFGzQGl5`e({6LMlot7)QvlTV+(PZ+gQQE?)N{5yS1?1JEU%Ib& zdd-C(ezW4OZ`OP_)?O&)$b2F~(P9}{|AlpuQTfj1yEsxR(v%qR)u@}_q_=MJ-Qt5; zATO5Z8c^dM3*s|MMp^b-Psx5$A<>MD`3+YWk?s5pjXG0r{~v~Bx*5l((G<{3ogONA zsdSmT1?FGp79ZX1Nc|TPA1e&2cCUS%qjv{aMONqS5xc+aZ%B6AgnSellW0`$zZ(p- z4P^k5sVZW3$^J%3^5Vecfk8>Bi`i&Kr46V|1Qj{d;f8Y{w(=M}OKj)K7J11aQVBv& z4z*RwukSN~LHx@JD``g4X;Ah9ufj%;t+CI!Z+0lC2sjv?eoc8JbD(p)9YGPPV!|#vThO(#E&iEgHvq zi=iU%3kVo7>N4f3^#?}DifS!@z!*}*Nw}m+4)XZPgFPSni`rgIa{<}NUszrFkDw>p ziJsT$6LC5?@CkT;S@`@2; z;eWt&X^4+_4CrY**ToXx&eHCPSKX9p&u5s_!D_^>TgJqTIoL19L5Yst(!FG<_rR|_^y9xJ8>tlI}IkKOV+n* z9|h)g8U-54LfMQHD>&&Q1Dhy>~e_Mftr);SEunm6{hDqT%C76aCpe$z^1q+r}|uGB+EDI-)3m8sCfQL#VKX^jI%O}lQmOxmV0w4$yx^p z30H9ebXBDPoaR36_!FI_ny~4QW#6$!u~ye-oVx^Ebr}qo>7!Pp85Jj4rv&Z(sjG6& z;nzJq5j4~aePA>Xb)UnZTUo2CKJD+^)^P-{&(<;d1w4r>gK$brei#*of6#3#UByA= zB*U=<-hOLzXVn_@{{6oU-NrNnqtRWcMjq!2KQ)oQm8}=yVn02--=|BT*l2<`YQKLs z{bBJc15ohZ$AkvX4(j4R$3lj;5q^QKwCDIaQb_t8)4*Hm36*fye&tl&a&SPd(JueH zxf`6(@CkHcgiE~(7kRsuri*clN5Qv~=aAFe%bDgElmy0M?Fg5DC!MKQOyOZ1bYext z#hKunykH!#17fMDy<3ODM%B(ZFhehg!*3VQwMv!D4_iv1I_Qr_YGm?tl1h;`EDd`J ztl#^Mo?xnEBzgy4!oE^bhp+kH3iRUcy}eBEV`}&bdZr>InqHKPir@4_XO9Ja{My+0 zH6=wExoKnI3Zy;e)O-SSx+A6;I8Uxut=S@WyoeQfIQ=mitYn$tS;=X$VAEO}VbqFF zypyQh_Rgx|!g0>bR&68hVk?AF7=(%JpHee0eb3sND(y8WF z=*RgEmBB5wL-NSGW+m~j#6xXiWT;c7WU@&Z)rX>*lDi080?WP!_vj^o)@^Xf=MT0q z8grW#r{sn@z_PyS-dy-Zo{zI_I|Is#ek3S+vWf6M+SmbkJOWKl(xWp)a8v|_ye)t* zvqBMMj69qMAl#dn;*5)9S@fnqtNP^%JNrMBp z)iw>K_X*Quc3SzqL#wL<7xylz!O(_`gLOI8r(}-JrCv8X3RMGC)L;A0YHR|#bU!d9 zuWN=#?(>@d5V@IGeebGYkn@G985l*0rQEDW ziBTd4rDNjCY*NLh(gN{Y>l!EJPHv1wvrs}Zd|vVOWOwBQpZzaePpV6wXm|%>R)B@g z#zkdAJ^*}9{+8XFZ0VD=iU*o&W%j4ix1z`IvZcdUUZS1sZ zK-Maop~e}Mc!=llDOL3~obZDCo61<*=Pt=J;C@Q!)kmTFxy}iC%>D-=7ipu%n%+WUR*R-pl z82ysqH)vE|S)a*iy-o8~mU!5#toa8BI__syi#Q$FJBL=Sy(D}Bjm)^IY+CmCql3NL zL53E9S1BmYvGtgD9-k*JuK$c)rv1GIK$HGF2F4HkWMLfNE!2g($0Ie%Ytwbs+l$KO zg{P=x?19m+@(l&TNf~$9nsS1MIfbJN*3I&VfIsxnYb;tGMkXXv1AF><{0loZ6x2)G z1M<07SW~~U6&{_%iJPC0plIcBZ}#?HED*chOaT8>;dhZ3=@#==^v`x9#Z>k_XakE5 z%3XfNo^SS>W&8`dp%h354_L*PeP9NjoIB-6_*|TNLREBNI_v zS3`UqdYSa%On#`<{Kq8IqS=pz{pe@I$Ux~IlzaOC#o>AkkPt_$g{L<&S*P`r=`$6& zl*8I=w({$9`pd53Z7uA%k4K2C4R68V{fTaRI`;7z1PO~#4&ZYsKKkD^%Ygr(Dg)sp zv!%F4%|nXP-{?dDFGJV8zilAplYk=(dtZ?%_+90CQvZT7}` zL)VEF0pI9Rri8Om6J&-RwY{>K+r5zC54+C=$K=Euu?XYBu}YS2BFj)xUs2k+T^IphRJbO$+^ACkL^_T9Lq~8b;2t!Vh9B z-sS|~60gp(H)QcWOz|cTeq{Zgji+OtmtPK$dEw#scir;* z8xz+WCVm~oaFqGn7hTDokLGrP+vxQ+Gsi2LiRz46Z|LRn` zjmk&UB%3NO2l&uppI5*8mj+YYbJ82Y> zS+LFl;;mzTRc(*afRyC|eh=@4c6F!~-MM1({_kje7I11u<*g4w%6PTPg&4 zp07ZTa>6)Z;#GXKXtq0A<6S1k?QL*ZpoRTU2lK;QmYBu7i-@)p>*2)4Q5yQcH}JNT zZt=+iDbE1OG{X;mcU{T%zJ+toBUaqk|K4P_os5WsDLuIkpd`^ChZ?CE8g{C;0qtTe zN47C8B2nLuKt7fkv`{d)R%31_@01F~v5YN17hF+zVHe-T>kC44uMVBiKzJ>M6L`%%iqqkGw;JxB#RlGk#Ig~NzDLPkY_c6#C>cSEiX!Ouh^Er;gZAH3m6`&mqN*XDfP@w;e6j~E z4?~53YKzMB81_|(=9YfpYC?KcPu%F*8^(_u##(Nw0PQD|!7JMN1c4PZEJzWYHG{kBzAvyX84Xyl}#jd`8 zFMl-iY1GYZEuE_S90N?j8YoD3a{KxxtTZQPR;>?7%TVA-`e zvcjKRGl7uXtQYuP=TyE+?@+62N+{=PyW zobUDtzK-WAgqIdE46jhCAPp20`?U)tJy}ta9V}667qRrLQzR4pmh1hmpQ>yK&653i z?emlwIB6(>AlXHyij}hLgE!gLqQEhY8!R{Pwr~7ia%o!s(Ww%6lS}8y)>4EeQ)Cn5 zk~eMLAFGP2i-t-hN2aKnxVTwp3dE^>_zVvKx7Qd?`a02@v-*|5u8ke>-<=l>p)&Rg z%Ql-zUv%bax>^*rz889}VeMKw81jA8zGsX56gQ3N@Ja@<7ookws;cWxLB%jdxa#M3 z6S^0_dHCf91Q9QHG8BND8Gfn&4CBIZxAhIYFDyI{GWX%y{eO9QUyO!4AtSGnlR+q( z7I$*DRiFS|@hP)si8Yg-qB<1a8v! zzT9Jev9dU~$SF`AnkDT0lEMLxMQghTv6pv#e9F`-zpU4cJ^tmgNgL!E;UZw9Nft(* z^peqit-E@0+;;M$ai1lnG; zpPIfdCxes}tA5s?<);(KVcx{pv{ehMYiQM(B!gUG+aT~M6dyznFG{FjrCTr3E`N+Bhc_^VD zVAZg5>>>s*5W4Il;+4F5xS)F`Z**HqJNt!q^2rZll|aNCqced+-ZmGQaN zW69xwV@iBS!l4XdIbL>#ZCt}+TQ7FS)Ten>YaWBHRPxTS{e4n_o3IBS(NN|+Ynd=A zt3K3)kX4^L=(Y7WE93(utNv2hTRH(m*WSj;t90Dy5~U1h9TQCk;rJ(m(f`e2%hx@R z?!vYoP>vmQe)2Z`$MRuFoldJMtN>z_UX0o1x;8*RmdqDH6GS3~8dPWSLKG(PWe&pt zhDCp3!GB^=c%{M!{-r1xvGgYupj0oe+7s3>kCkxx)N1DL(F~s+R78Lz`(`UoFlQSr zeA^~3NvQvBw10_+h?n9XV*>XpWJ8B3{djs zcJ1L@!#$LZ zt!dry9C!VNnH4LIx>XZU&7u_p*xkoEMSswd<=jXyJ15*&pW`vG30P!ONz7KZaay6B z3a6K%*T;0wh}X>H!uUm61B6G__hbnX9Qf)>qOmAdp_u(NeCq>pQi3nn;JoP9t#nY$ zBswdyI4xEe`O#jr&LGzQ6I;wv2U(Z}rEH4lvKAtPcjG>SckRCFo}D`6v-Ow&l~F~8 zvTTxpnrhP4V=w*zIW^u~;ei$MhF{dx3*&>3qdZ|I@sC+asTb9W8BN<1{;%oAfBe4L zJh#7@*dOFYuiDf?T-W2LL)!42NnGV^xzZouqxl(1mskG9yu#F!SV`&& zPdUHlrq(K($o>owGT@#J^v*aCYB`lVcG=JCf8KB-IW7DR4~<=>g|uz)tkJq z#VVc;^_4qOMAs^(qEmU{g3`%~5Zplv*LHWZhkJ0qr#F4YqPw`wt|-6e4dUPj5gA5m zy)|Vgm_f!L2DE<7>)3&17E1R~Z6#xlaK0U;h$ARd%FJx3+EI8u5UIf5!9(V^=5CLxrKL59$uVN zhTV=L;mLzDUOhYvl{OC|JDB0Wk1ypK*vSMq5x(a1t3~wxqmd;cLGWq8O+OAH9~;wu zD*qt))|8>BMg;#H!Py7ti&H*@8<1A9(MJYXF$X=@TI~NNu@;&A&2%&>G-bIlU>iNl(x68X6U!*x zevTB3EYrIWVeLOwMz=bP)jrMaLd{JPNU~XHgw)2xX``1_J`*T9;6W^=V|JMUJkIEG zBL+_av+r0brY8O6vdoVGkAqFGP3v^NYy|!)3BQ5lYSx_<@q_kJ-lNt~ z0uV^32J?7mi&{vz36E|4?)R|zVoPjIu6zy&V+rHn<4e2U?*T3$$HR7z7Z(?0N!%|N z*AvxG!r9I^6=`6HaT%LQp zzaUrPeLqWuPh-SAb( z2E)Kgiisl@fuuDxtaEgN=CD_2Z#VQW-N@z3t9n3NY&OmKwJO13&?+Li~H8&j}s!8NB_4@L#2Y8sc8DY z*Z(SVg4HsD3~(e&H0Z_;s5Opeq3^WfU^+$H6@-kwlo}I`pjm6b7k0-l|6W8FJC*IJ zF6JpWHmkVq2DQv66mt6(f+*6(^c^BZ(ChBT@YU!Amur1?7=Ddju?y*VdGPxzz*FQV zP!S7O+)9&lxlVgA5Cuz}8b*Rn77QHjB;A0(%j6=Ekqeg@;#A$cV=*)ujOF{cPchkv6ZR z{!fiPf6M!hZ?pO9n;g%0I(N2IYW8%0QAY8fIcRyragq4a*bL^Wk*>=j zwLPmRePpHn^8$wzLnA%Jzoh*8xsiBse8)MK@#mzZA1_juKkc%m8XxbRCZ-i~?%t&p z(){zN{^?Qr+??wU`Zka*BG0?Qwf5|)rjU9=@n@DML+w_n*q_~JCs7!lwH*w@T0+T@ zBjg&^*=HhpmdgV9Hva@5VcVVv#0!x9VV~$V1fsgO)$4E(OFpp=9~=q|$ep7L9n?h1 zH#dCrJWhOpZW3u3b|#W!7W!59e&Zc=uYC)eh(16KTRecw2}zTf;XPmhRg{xFR0xF& zkMgcTay+KVqQyUmQeB=a^)mppQ|4))2!0R}K)iKTd1LV*d{p{@DeifCd~u4=7WDb4 z5RE^p7__WWFjDFbklKtm<~RSl>)>(0B31NgBrgr#c}Z9Idv|LfrgIjoQrQX;d>j|7 z!n#SUsVF{ap9+y^R5ROA0i1F*78D%33UZeA@Z?>xSl!__8pwOTe4FpSkOHVqRRLE( zv|}c!8%nMmVqgR-u~1v?yIqNp+~Qj{Xr$R>wdK z9Hy|}LGxt)7Fku)>wg^EG6saV9LI-Z`#;>Hsax^zzU?y#bc4>+d9VnF8`a+YWEY&a zqZEmjmN3R}f+IPdtTM}X#CtC(wy183^_(+f?CrH~3=ACc@3Q-bI3A#Cdw%Dp=t_A# zMaOZs6YFd~<@3??wavyrDyiOj`&dygsGRCAM=5?ose(@dQ5ltHwhDtjzEKW_8WBP-xx>H(O-6!__3zWDdhrk5=D=I zp9pjyu0#_?$tCbvfAAHd%mA*(izGe#L>rmicha9m33ZJQHH_Np6 z=zO`m&_X2hCs3_6yAv|!5!Sq>(x~%chD&;h$g}onbBUH?zS?_(Zbd*)B0>vqJ;Dl$ z(+(A%G@H#&6D9r1!iZOL>FvNNjD8ZT0DA1l>m1Y*7YCp0#=9LM$d8+kdS#`C8EcMf#*wF{@BJ7fYMc;%(7;ahT9^xpxA7LEg;LNL8oNHOQTcp;E53Z z*bj!U`EYZdwEtNdJNDh30>WUu)b@4~tH{>Ww5|6*BkAiXp9JF$EH!HDIO@uZTWD+h z2v@&BEr4SKSJ9EkiTdwbdGXaaV-WVJPQA#)<#Zr%lJOYd+S|d!IMj{?*=*Sy`d(l1 zO<7X1_!wowrdJWz!6TXvsYXA5zg|9^#RBy|mL>V+KvLQ1iY}n3Vlm$3pSjGDqmC3> zKzGvky+Thg2K;xMZ~{$Jf7{;PByNQxiL_e-*4lXQz{6#>1BrB)0}1lV6%bP{Rzfnl z!3|E-{C^$;@zX$0eE4%a5}<3qH^b_J58qOj;jK^@qeGdB$-87>Fnu~m3DOdrEkfzV zFIeOGm99WfpsKJp`f%bu1VWv@)Zjz#%zuc0Ey73%6D2P#2qk*0FoY_zOBt1Ftt&AG z%3}XY^?jj*($Ojvq!u*>YB@;NM!92)4bvE-8)qTY$$t&?R~}sWC4FF`bfhYmxXeUI z+9hZ)TM`4cYe2!rip_RT8*-HF*pFAztY>U>Ra;nQznpIDsHjBcgdm((j1Z5$~l zrURfNB`>M7tC7g9mkq_a-Cu{u`Eu6!N2FCzKC*rneBFn5!*C88uzh*?2w~HNh6BAb zF@JX@_Z!l2EBPfu8pkTN9-s$}IuK5FE0O10kCIV3bT69*bs&O%{K!XUOI9nHk*i(! zn}8(rUgwA%uN$SAy)DA#vNS_l^*hc}I6feuxZ^ycY~zV!2@W>MRs5{ z5Wt5Hndq|x>pXw-#&pPA@N8WO>Vay&`nXbOp15o5;en*s0i1}prSNs_?G^Porw>*Y zwMUox35pauC}#a^-I{sx_KI0j;Pq=Ms?ayvf&N@@(k>qG$g=mXsll(9!J}Y~GOcy@ z&(-tECKRS=@Y->qo|Nfw%;7Fztw<+TEjWJ{NsSy~E1l)oeId7Osl;phu{E?hCCR6s z>}|~b2zGd{{VYV`aW>As%;nN2q(nfGlr$BTdJ2571QZQ>xAy-I3)MyeB_~g(kK&K$ zsjn=0BA8cIE#?F`SU{KK%`nX3S3r>4eZDHPgPq=s={|`}__egeCyH^1QNLw%O9(Yw zrFjZFP0%cGKZs~O)5~jYlmVsd8o#V10B4-I3*+jGR$A#Y9Wau7P0&3PMre4i;|V3m z$|OZ&S7nt%*?#?aQ4CZoU+_g6k4F?%&dz+X`5T08@}8YNWvTygg|g5<Y1Xh^RB|OnhhBU)i7L0oeARH%QOC#ql zz@u;9BJm)NqR=@)k6O zCl8;0Uh?FTUw?Fr)nCnb@012TD3VSzm4I4Z1heA1qS{;ygtf=T{bwnia*BvMc9H^e z^xat|+-#s_3dM>BsuN1*cerne11mI^M%tqHv*Q3IlGn&feYQ6RQx52lhzrSOj?N+U z|1~a&b;+VQum*=>$TN=#4#-a!K^mUi<|NXGpu)p{$n&~_m!I;y)~Ku8=Xk{}x6ibD zm}A_Y$`!RUyr&3qsn6^aW`Ag7cHrXqbJ~KwqV@TOgHoy?<0c3OdKrdxeY^@?7ZE{e~_DOYS@tO zB#S=VGF!3cd(z2BXM3gGMTl@NxXAZ{p7-ieIm6yLhiXWEUDY4p0s znzq6JQlYOo>6Lb#rxnl8ckt@kE=OwXx=`sb_r6Ed(O!h!FE>-$Qk(D^j3H{ zFmJm*mgpfb82fpYJIWkim0kuC!3zb`*4F4DVY5ou9L!2NJZZ(>K`y?_0Q+mCmQw4< zD4*Dmjst)_CcCpX-SohS-tgY;_L0m8^$k6yb09w&l zwW_=gj?!i*f7_zNA#IZoTV8mU!&tXbS=S30&pOx1vicNll_|{Hzz=ir3~m=M^K3FV z3ZNrxN6(j@9voRZ?)*NTH5(1>rP*2W^7W<=(#+zH>>Vspco>j!n2OE&NqfeBQQ@xE zsmqC-TyFg--^Nn!Eh0>q!0{5Tk}v9qclpF;dqCOR>8Lqse{v9;*t}W#(7uADrew%v ztWQVMw!EL|Q37@6>dAF9D#w=Q*2LQPM+pu;=*y;FpmN@ce~X}6v=7`ccQm2ukbL36 zGx6t)(x|5b9EPE(wOIFL+^ku;HemeqBv3Wyu>qjO3-*);P5lQQyHU2{Se#g=b1SY6 zy}u*1R(Ce^#z5%N@rm|t1cY;P*K4Ip$NQ!AfDPnq$t`lrI~X^K0qD+$*5^p8`h5l$ zOp4^AoXnBefiGR2Zaa7MZRCD!ty0CLIpzMxYO%l^DwP%a=b7?E1f?f`q?eqOL>j#< z7W@v(t|}(<>*-V|Wj0}C*zb~B)t^V`91hTalsA45)VALx17Yyb{&_nLGpS$|v;@H5Pv`~T*9rDOjMACOBhZXt{XTB6qysu9KDX3}aqfzq&j7t1C`WD|e8 zzf8p$@Yk+ptIM75SyiHe{nGP(i=2sL7;GgkJ0(SV%NBZm_pY9IGAddXt5MG*YXF`& z2!7YyQ~?>JtBa;UxXcc+kbm~xHm|rdL9f^~C&T!HWayA(?J&4SG&+_>3a0;tbl5}z zdHo5^1f`Shz|6*|eOUa9n5UR0PNYXaTG9arLp?PE(_#B1VP_l~kc4GcT2Xuul@IMm z`k$!$=f#_%r|oTtkfAGaO&WP#)2&P83Cm~lUSr;nMIl6SuXohTFWS%=P8OvcJ_Nmw zD5}vefO6|Ez2uff5%eLVGCg!X-<6N*(!qH=_ZOg zYp#Jf^sf_Gn#8mMBJKlrPnZb-x$#oYc{GB4+X|z9?oSsd3Nu3Zj|NvZ%dd!SdJmug zz$jXtQdyC7A8$mPV2WbJ6a@8+OA*T4X**%HF#rft zRj^4j_x;B0Kw%tP=o*M&M`4Vyq^mH<`o0|DhoYt4`Mr_$#UuDMzTRX8ye(ac2FP|M}h-&=68R59}jiKPuR8fCD{_+?X zQDaCLRJ$pP^+oZlGfv0MLzNtjMEK@y1u5$C_;7u@^Fqz z)%V;K>Z$c~yowGY|DC>8)NL_5Zjk`xC^^J)Zi}EHb6Bs{f(oQ|Oi}lD8r60s zwOFjpwMtYehHd47#dF#dj}m3&-HZ#O)K|!l!p~w4x3o8DO3l3&gJJekUxx-r$8!vtymkf!k`5ZWgAp zb-r@zf!UOA49h$D#D{6`bLYi`+LiUHsD;tzMm=34sR(7Z#~*5Fryau^wVzw6_%+82 zOaL#jM>Cb=UOy-=mu9FDzx)wqwzj@oWtWajsFYi!EfFk-D3KTQyF&%gEPbKF*e)CvXSN z?u8sMY@j+RQ_Mi91~hB)*P<~wEqLYl7dnuWo>mTO@`BNIgA04SR5?VtpzFl$34F^R z1EQh%ROLaj=KLe^voqhj-%BhXFsJ;*P)D|VzvSc_;dEHaBQg9TCfHg1W=;;>nfmDU zXVn=$-*8cbkR})9cS0TX;5WKEYAv0@{g@F#%z$L)RUMR|hFQroxooE?7sYkR3BjQA z^(*=9`UJH916G&!fKDg}prv2u*FirRkhI1fwnC{%HCx<_IYWBcEN-?-U>^t9*lkW{ zd7%e2%;S_vMIvpv(v8=b=3w2tw<#9lcAwV|*t=f7&9og7IP5s4Ci;6V-LfD3KWnt) z(oSsRq8}L!1CjoewQv(4X3~|A1J0(d48-x#DsJlp4_u4L?3_b4}}BJWI}A-NP%>Egfm&^TquxfcAWnnXGHV{YP$8_+s7GQQL7>S8=D%!M=_xp70 z{aeOGfG2ajPLAz8GvJ9`{e6fq)+ zEuVFWdHx}9P*}j>a0n8Xmo*>nl03!s8v^2WW(Pl4>T!kkeei)Ti>rbP;!iSrlwn<7 zu4xZT?AH7$AOM0<3SOp!648y~VA@CS+qXYnxCIz<#DhN0%Iiu*`n`F~fKSf4z4_hgw0gS75Jz%HY%z(M7 ztB+QQIY|`h3yU?PBTdI)qXzWOj=uRu1BHL*`;Yr12z1nLk2+J{UmH}S9~?!iZ;Ct+ z`2BrvdT2(dBNA?>if01Z?2t zMXBl+DDNOGejUiZ>2fqd4Mk-YMNG8$A|T^QMJKfg@QXeBfW~)+JYbOM46vjZnn zGO=@jZ=0uLl;yYz%dyVHW1zAk(@~Je7yzN$w9i*4;VZ5inh+nKrP89kA00yI!bZQO zuDP-d9M`pN&dw4PPuW=HsroPkl4{Wc-P8Vrg9x}3?M9?ex+?1#M{$nl;jEHsqlS2u z8jif5G51nFgUaF32A8$UVgkQ^lwuX3=QEn#`(Aio6C-TI6T5Zn?jOG@RV{e0pI$;+ z+zisLa6b8Ph3Wr;>XRlQ9o-`Zg)XdTlyfMS+);#6e%b{<5hn2xX^3$ofP_2c0QHjy zTEM=`@ay?E*B=qVixIynH(|OPM6f%;aP61TSNVWLv_HZ?09O-`)+Bq8L@OpLiqEOjoQW-)(o zE@4L`E(5p zD1dA;pkT8Wa`?DUjBkiWdwDY#7 z{JkbZbxatES2*eB!UeVfx!;{kSDkg2KL)o>uU_G%Ftj7X=B0HDEvPy5JjmLs_-B7R zMpsV4S)p~;HbzTzs8DoRKor(#l>{We%D@{|G5!y<#hOl<=-L3T+27!wdI-WV zIyrf>4wPs^pX*}OuVw|hRGS8Yxdp`n;B2!1YeumiKvGEzzQ1=w;&h~{@p+a+X94C~ z$opvk&YR`EzOXA9e24=2-DQTX)r47wbqCUodN-1-i&?Bi`W&DSk2?c*`<;smGB$4= zepDky-+`K;&Z($cX~D#s! zzb3k<^KPgS&VQ4(u#^O?VFCK&QJ9%FyqiM1`;W(K%xN*c_yeDb*%Zi2Je704Ca1oOFFn3{vJ&hd|I8REyat`OaP=D9M7!e6N_kD9p)B zj~06#S`;ERy7USrzkuy0Z6;?5SDiq$Qi}p ze)X)B2i1@kaT4C&EWR`%1*^NRAN_NQs5+3#mKh+%KaO4Hvy}L9^!><&K4kr2E!UHl z1`rA}9aBQgIWa&mMhw5BqB5Paca|K(Il`Tz&a;(gi2Rj+Xrjw5=z{i8d(q|{fNF=w zR4h^BuZxb@qjOwCYXGsd=lD})7rZb9hXw!~!0Qt6&V`9v{|umynP?=gUclK9P5p;) zymV_z5)gqz#7g<2TkFM-#TVEU2GH-r2JM-yB-)Vd)4`k@x`B90Bs*|SjfmU;`-40SIuSCM8FlPP@B2JK(qGm3x>=YbI@z!}s_=cb?kn2AN}4>TUn z8`Rsj+@Lw(zu^H9fM6%k1kmM~YOon_cp|^4^4%5w4Kf@n$?a{7|qSGhg(&d?_*VJ ziesm&4#$n-JK!i%*a@An9L{V8APIVTFpE^$F*e-W2JPPRBFje+Jfrkw`XXQotPvhZ z@_CM}_#p2Z8?9vi1xWH>V77V@cLzSABKN%OVN7kjQZ7Pymr+4)(}$l>!hE$PDtEghS8!ENGd?UK1-WBn zXN3F>aS+Cx)T%`zpCtz)p`;9Tb|<)}@m;ApX;440{4h-`D&M-+z@p1plZtPU`D1Z_ z7v+-hGRyt4j~C_m1V84~PQ*rAB76VDy$X;ZUkZW%E@TxSVf_}J{QWC7+O?%Y0q3yC9DQmm z@mT>arA-tEiLcXBvSE~u-yxjVx0)NQFN(-ILiBatfM_$+Q$)mBN?pX&%~;wA$B!+Q zbe}fCKd%@7kZ)D)VeKphtzlA4$Md;<{rKA2Znk^xkN}$?5fgwaxd?`Z~ zgPj38;?zHSM_1RVrBVOA8nc{Qbw%04r(PB$B)3kOe4YHL(kEi7nvrvid|mUe7?0V) zyWjbaK?r*m8_Z4pp>tassBrNF+^p}IFdql+1(0vdsq$cESW>?NM0Zd0@L<_{B`BRcz;=9l45(ka_w`Et^CAZ|HBr*m&7 zSqQy9fUa?-ehwwf^JAxvzx7wJu!Tlo%5IAzYI3$Zode&uI{KCN@s2(K$axL3&Q4b2+Io|n$YCNN9H8l_dl60@5 zC9qqc5WrQ~D)x!VI>s0@U+69Vq3VJ$sZ}~?4kQu;Rj7#UBBMB`u{!MUR~6$J_pg1N zC3FH(%Pv)-O;MoT0t-{P>KSQQ07$L+XB$DkUU&Y6TvFEglz)gGp0L61#9UhQ^?yHH z@YLPny?KjZmyVuq{L<|adaA(7!gGdkMebV!Lg~l>ZXp3VvTPK;+D)(w=3!oE1sd)z z!TrK4rAo1zNL!e1oiw_Bws{|bP@#w*(bLd7lIy|C`$`t~a3=WDksIh~$hJL6WEO#h zVGY?Ai>b(o0wmCgyfY6QMF@{xa=ZEZxUodnH*E3fb7Q^fWWXqejYZev5j$~z!XqS~ zBG>5G;Gh@`{!0eBiKZ96diV~Y?*jKLL&UJw5h+E|n|sISBn$2r254cLeywL&<_(m> z{Zi-!bacVSf()`N2l3Z~TQueV+oE!?Dm&7~Ui{1K5vJzaV?5-| zjM3)5d%fPn>}BlCITK0XA+LA1Ez4x_*q6;A{%{{!=T&g_Mwvn`thTlv}#CXm|r5q}G<4ht%QSi`7kMy(*kKEL&1n{{A992Eifsm=?Pc5^Ob>?b9aR1&5( z+S8VrmK&{%Wm%)}uhDKOd zEJ)Lkc~7!fB6F5MRi)Kjdnq6Bzlmq#bsc1H`TmzqF>6uQP4PQ zf{*r;WfHw0PEs5#HLzpl*`^rySE%!wqyyQ*8*{)*r~kpL1~-bfWH@Rl1R5Z zGDl>qdTEZhAE!_fQAsX+$ej*CSfx>0(Ul=cIrPAGk_u$Dh@FH+-{5h)QPYp->C(i~eWa7rz}UQ4 zM*}fK?k9?`U>jdJBDxNJ@tt{be0+0i4lb52i4dX;HB!C#m`E2@4u3t6NSC6CL1~{Q zU)vc4|8mMpIic(LJz3;FZ_G#H`(yuk#HUh4bU{Y%H)UX43*^KJ0#9<}r}ehP2q^V4 z+b*r$KeYZHKh-FuM&a{FJXNoEz<=|x<7AB0#9q$wv8##Lwd{$^V=u#u1C&a< z3}$$N*c6(UuGe zNJDs35Q&h2j$D+mn)%Q5y0(-c_7iSy2Z8@{enl!nyv#cnSlS#d z%|h^3xN(>v%2zc2f^d0J?m}%~%W<&XG+mR@sqQQhNR;S%Pn6gakQudD%@2V_FpyI9 z>v2%2SC_5#WS_~(0R)2jb*H&G6O^_rJxv(4nrP+*%UV4R?02}Rl1||ze{-+6-xce7 zx%5w&cTtkEb)z5PMRlg7kD+-5RQqL_wkAWw=T5M6n%xT=_liy}SG!UhbefF{tiMtY zkTf27%#!Ie!=cVs>H#UoSOE-bhtakUjz!uJNU(lU(c|BN%r~!V^dNj+yi2GR#i~QL zaQFsfCt2Yc1Aq#!bCU%?K(0_xtbk!ACRaWaM7FlMCCsu>-)JE9ihxjFCWK`td38*} zvg;WWgFZ|Qha3m02!XV|4@8e|v`=UEw9!=ogaJlw2@00=>~saj-`n)3VPM*~81u-R zQ6ym6Gk3^!>i$-=Bay90Yk*;455x~Txq5@hPXmDV&E;=JajPd9{9FPyi$0 zSVQ5j(IWd^PX^Pr8e1rYL_DDqA6bg*@~T{x%zUi!QELBQv@C{46jwU8?26Xcan9Rj zf!f%M?tULrJ~e~IVPfN@b&hH*`C>1365$r`y~O;#W+-?`m*O95Bi&v_%@54P2PaQ* z`QZ{3aj)d^DT#T0yUV*>TZXfNH22`emR=b*6s1JIFQihb zzI|{mefk>o3HEu<334%fAdoLYki!yJ_WD5&qD~X8SE|Bv9lxX$%4BFAL>IT;Sl{L^ z>LhtrjbV0@YCq_{fNE(6w>XuY@iVE>{UuZ;hJ<+3j#JHG@Ca^~L-R^^L_N9rQ^RCz z$4ZILeKF@gUDrRHR1#afoVnPOAQD@BZAR7$CrBky{BEpLM2>6o=&0=$H?26)OZ+F#GBy_!YSZL)W_5ovp|K>?JEWug z^w4x0?QoLG+VduLVl*Z*S~qj?bDyBpA?^LoUYoelB&W_qsy1-BJV#Eg@7n;PPrf$z zMD9)x@wPpfLzix2;s$2M&DCf!((9%AsgChEPkBLB<)`=_gLQWlGNWF{>1b2U`X3|m zAKj|pn`hZFj^_EpuIS)oP?ZS74eKE$1=m{SHwGAe0G}%uEbf&u>?UItV zl6_S242Xj?4=!J)S$y{}I4iMPx`!x|DjSYc+>&n(O#3>n7(|mbKt2)rAsBMVSJF)R zJ@kB129nQ?!msgiE#GHH**BrekB9pO@AS^^1~Bhl_~`nRq=53%OL5V-aZ~c-8SqcKpbS zr)RjvdXl4TtHeAvFB%Abtip7*(p|e&R#fB^#QHaYX;h8rTx#J1_3^{yz$<3tX1P~o z1quPXe1BHEpVNFmW!(4}nR$&(-wjTrS@L*h9Rj4~XSx)b)Hl=1fd2e=oF;O{4iNxe zBq6+OtIPzOAH_KGwjcAo6SJCs-Tfm!n|H~=iSgK&7)Np&k=J_RgbxeaFIV@<6G>|~ z%kFdhtj2paQt(#eG(lgkBVR~4dma72!xqkx{t?G6+&+%ioKsF4XLKj^%`$-_zQz>i zoIMcJ1QlPJyCsTZeON;@SA4B^?3Ksk-pq2xvacaaxW%mLoBtLA-{FtV+Q5ss{Bo>+ zBYO0Q)4;>E%!5!UyhZS~4+cXpt??Xw{PtQhB8OaD(+K1n%#D?4xXKfsp9h@=CPzQe zdvDu94h=&gX#I`-XkJAu-SV|Du+@gNN1rji!-_P2*tREe^H+JJ#MLlif|8eOBZT>^ zpQwSPJoQzdU$0v^45`tPREq-#&|esH|JAtj5!)`_!c|+9RznRBDeeTUeygp9jf|qN zwc-!G?Mwc=W|4KBeYVS7a!F2tI+a?V>q71|(jVs!|3ut0ljGOv?(4h>RBW8-UQLfM zR^L#tTaLd?rTWY3Fvfot%`ML1k3YxTd(!iDs5)uPwXepZSEPZ%%rTp(G+(={-Iy(yDAtRD zsLz_~YkI%b2=Cukq0Q8JVF8GfvFF#&Dk@NXj}v@=I=Gwcnh`^q_yWZwZ{*|G5H^a+ z#xC$Jl@skzV^)?lo>9b4mnE{lVRkQv`);=0cWY<;%~YVOujP=Q8y}tepL7)!DPx#` zwVgT{z6EN0xna8I6gaYEFgfI@se5nF`;en1R~DL-CP1vE|Im{)x|<9;1%9Z{0A4bZ z8ZG^I0Q>+INIrKc;xx)XM8PP#C&NFrWc?B)pNT?}fLC>`FBA*K%?@=_Iub%@_+6Qx zkW~8BaWZ1YwC|;Vl z0B_i7-QzRHMe6wo&#Y0z0Bz+frjwtQ1>c34E6eE8ZsPTM#x>~V5EIO|0Pp1o_Mob| zz=u@w4H$H`yh8Rb{jmIfZImiU$E@1bUJHt_5kYp`Mdo3}fz;isJg*jAnn z1+&tTqKR)FNUPNu;8K@IB-^+*ScCoDiE#vr#-Rhe2yL?C&s7~;{h4;q`VMjhljkRF zr=9BvXZVmUAe;>f#AB@uL8`#^uk?y|ofL{YRT$1F%#bTKLGX(B65lW>7U3bPWT*o9 z7;#c#X7sYsS|q_Yh4cvetWk(mueyZ`DN(ZY87f_AUGk$u9Rn;0bE~|m&pq#}iCdvpIA2DS=x(rW^Um|1eBC&M~Z7$*a%6omo5JGZO zV(MvaQuS?+>u43CVMKZvkgl>0KK5js!htv2$l45UF1v7+0^`-gej zXe*wA^i0+Ekkt|ZT+cc{DTWG&EFQp&tHiPX!}vugrh5(^_7s9MxlP9cTs_!8qVG6CYwFW$>k=Qv}P-eUOSjESe?+SH~SqovQgW= z)LROph-QIlJtp^gEGrn*lX0`Zlm!j!*09+W1(%RtA=j;DfU<#M4dpb*-ERsz(orKd>IbH&;$GKrdEOtn@WV z-8A{2sr}@L%-{)yTim}Cq9&dED&`e+Fbcgh9s)mE1$hYBLO&J`i*fp${^B!*PlEjx zO@qa6Gi2dcJM>Ml-**K7?1adU5F=Cwd>03}6JmkuUosed_J%q=N#P#t>SxE4iB>hI zh!bf{^?+%3EPXD9RPtn5=452}qQ+eE$~=u zeK6q3-YH*j!rNFBioyOhUEDca`EJo)?k-uzuTD{zIivB`QX5ZV)*l<@p+*TCnE>xk!MY6pfR#uo@YBbL$X$ z_;q}&acMF7`Y9uO;qdzva15xOca3c|sRyI8{sxn{A~$+=xK(XPE|pvKa46(EY=au+ z6ZqoXHHP446ZD=|krU-REXhikLrCqyQBTgS}VPxA7I>h8H0u&en#_A@BSobS_c4;xwZI$HfN^S-n?=#2QnCuLwAv7a9wwS{?#5~g$RQj5 zxe2VUhPysGMJ@Hdp-Dg6zD<=D=Y(&m6z)gVIbik{(;4qIG2*_|SKPme=NiWy0_U{= zD+jE7M3r{K`zp{RdWci+?V`{m7gHwuYxGD@kL+gJs;gJ=59x+tvnmHF(iU*bu{Gdm z+&Xa=#aXID{pZyzETkuQ!ge$0-asV93Edf|YJT03d1h9Niqio-(C$R{kFTF(zs`Z; zvF1i1&W1appGHu5MRc$nPRp7kWXow4gi>ttOt#mTLJ0FsQqfWOwz;tW;awv5%Ebf7 zJH9$IxL&=ZYiyS~NZ}k3acPT7Zx>g2HPHoLQp52OJQ5R+t8LX&eEAN!JluK}b=)pW zzgpBXIAfbE!+X5`R?Yr&DOUs%#|9_Cw-gM3n!`}5x53?qM&S$dgx_zH?`&~jsLUN2 z?zTQz_W$IrKO7A8C-7#TSUy^A%Uv}ZFZ|flQy#1Yq(i-4FN~o`8V>F>e z0OPfOq?7Wfz`s*d6M*wXJaq0|a-@ zzq+WV{T*KKT`T287*hBfdhjVKd&NKT{!BngNK^B!@Mxa#SB2vuqPu799LCbm!E}~i zr{2Hg<`ho|G;j&nO@loSz4TV~IIU6NHs*Y}{^)A{f{b%Pz5VAT+Zwg0SFC*p(S^aV z^`+*CV(r`s`T;SqFlXEA8H!o%^F@F7nelgv58(H#QmjD z*Wt5b7ps1XD{bk`9}LyB-Q12{Ezt%6UF}2W%|Mj^QR{_bM~99u>L^*qu;X8h>SkOo zo=!GFOJ9*g%lvNEfA&*Y_P)L%d)B-jz9LFtnoEZ0f9;)^@A;!NmysUr7Z!(6$o=|y zN4Nf^m4pVPuwGbbqnd!Ws|SuUEpS=CDusI&!;uBlcb+~FP(1R|!NhcGc(4a5q}LoG&?gIqguzPk1I0|IsIbxI}8nt+TL^?mN#LYK%Vx` zColP?@N{I?A;8SvM8Pq#Vo>NQe8Gf`{@F_lh*VMERBo{p?{#co3@J4?es*G7v(CQB zZy8G?^z!Y8w*^)^mQDIuMc1@-Wa>}rV_aptoQEzuTnghdg1x)rx3OvTF?baiQW_Yy z*BFi~WoPM#fI4?>vnuUqgpWDxUw&GKz{^>wGLWjoorOIQZo748|ytGe% zQ14aD+u8*hS2I0o_2+QbjJ{=7Letep{o=@T^y$=?U>^uXB1!pe26e`rFh(Z?FWd z{ABD+{?#9{;v9zS_p+3{jG7P+Q#C{&5)FthaFccu$*1)kG{){2!C@J$6m*%QQ2R}W zhP%5ouabY+WZYE!x234Ddwq=&h1WBXO(bEzL8!ly-3;#>*Bxh(HTQuey73;kFVFAX z1V3sTFvx>s==@$C{cRWl&_T+Z;Mu3pJeXvymuG+CvhbR^_lDm-0ZqP&))P|1I(8%0rECs}2n2$8s(V!!`O1 z#eu+nKyPSn`W5ZRyr9|1LNCs3!)WS?EXFjW7DA@8cx3@GEbq zbHeODgxv$O(C#Kg%0V=$igkJj9W&a^Lux=jRl*#X3d8hpz>&7$OoA8+K%;8mgt~#a zR$}iHLnzjRNqA#Ra&{~icFoO)Hp>)teN`46cK{8qqfo7MD%1p=ZjFUBe!O!sW8=>> z8{1#WJwLas?BC0%Nmsb9#_NrO|DbpUJNFHt_3)TBEHc;2#KW;*Qw7i1(X?Dpv7_lb z+J-K8rGH0I(X09IcQZ#*u3Rh<2Q2IO#3izd4==IQg7=Y!N9;pRFwX2M%%)8qPrc*4 z-a!ouWTPXfk~J)~cdn5+%g`%b=WLp`gE1cryGf$4z4|!~>if7e_K&vvI~+h&dt6YC zjpSESrYiaUtqvgP&bE)va5b#8Wy-yOm>?G6RC*JmrWy?(s>a3xm&3~=0XxBQg=ypQ z3)`I7&wKR`II=6P2H@<(CCEiglIMPeNe{!yL$b+KY5ulV!S;2v&g2!-_BB5u%9ww_ zx_G`@bQC8RC~tlso>2-sS@sCRB)SVXhjZR>C4#1^Ap>Hr1JsR_wz>8bOhiE(#~5GAW;dmx_z z$&_;ejp<& zqdW`~_6%EkjXQ}Yp!CJE$9jTQQ|N%-LQXzwg)50Am1oQ&W5OhqiVwzo+$1!&XpHz-`NhW zU+VsGr+hGCeTixV)y#P2iHjFVU=C#PW=P#CD>@jZ*Afd+XhLe-tYC_U@SwTubAon5kdHn8*UknXmA!mMfBlw3ZJ3U$^lN<#$E ztseuEtJeIig_mm2Bv*Hb6d0>UjpR7;MqX(Vu+2zLFs3+~OUr@2=J-PM`wV;#Fc|)t zb#ECLX!rdV%spV$OAM)%?l5EtqleA0!@QWF8rgjZ-@@np@*I3wD*$pd^0BJWn2Yp< z(VujLT509U|01sp&hUkK`chyw_&M^?7iP}c1aC9jq3y83Exol5-t!EHr5%l;VTB={ z-yUzXu@mIl%M$EF08}UG%se~bZFY8oc60mS(|uvaPWs?CJ4L$#bK6nM(2O04+zgpT zn}N$po$$G}D@JWtKK4+6C2;h)*^>r&iNW~vO!3~IS;%8Hcc3zUcTQe(*pLI~L=jIn zsBASvxk(G$Q4E)VD;TuX?u+iYPJ_Pe7RuIn@SzKf$en1tdeo)cb-eQ_bgk{HFwTtG z6SO{7lSrHk8ePKP-Cr1IX&i9*lc`-oiMMZVM5V+>G6rUv#*pL>J+!PeBBKIFTXumH z^i4KT1!w~{;DB2MFW05!=GhS7L$8Pv1a~>~{7se0+!q-Qv^m=x)U9Q#oP1z`*CAgPcY`$r=c?r!e$UpC|AR$p$Aa| zTmlGI%?A_PfhJ6cGTJq{a*y~{e=12#m-0S8FC=dKA(kLKmErC-f@llVFc~B3%UX;M zgwpTZfy^iQ)9un;6+C;CW^_Zo;w-Fz;O&LCxp309`&D<~3o^|dAE~h>k)qcngx2*_ z(-9)4Xht^*1;3{-_}L9_a~=xhD$U$0w#+bp=4pR$g0}x?(8#q(mon2Gb#S0?zaI#( z6VivkTzCIWzkAe&@Ww+5!9$vO{@VlfN#or%Q$m9m?&8Wi_lGH%b?)tl0$Db1hVsBc zk4=VS`3sU7qY^0IZwCrr7Hx)dz}@q7ztxb$4rHP|!7roH;!Y4L-kY~GP047Cx%VN2 zqr#^xhhgoA1nofeA$SrtIEm96k0bs{W4<9>@l@^)8;fbM;h#?!l46Xmq#Mb%G30G&~=Ho zkT_7;%3aK34~4ys;%kJuviAtP)qfE2q1T9MmAfQ6!VgK0-iFnIG@0O%SWU^QUypy9 zI{W=m13D@mF2+j?;hVJjLoB(igC5vENJ#30^ta^SW$y)b06Lg0YL|eZ2-Nct2fmAs z^2D?`|SWZR{^(ane!luG;xtI;>t4EXk5LvyjGtNBU^1F}V z+MSoa6+H{$UF{i@a3CwbfW>#2DvA4?r;ad^$!9a{&WV30ybR zuANV~Q3yB~KvJe?zhCNOq-m>lmZXTjk|AwNcrx1L^%TJ3M}Ey75+I+d(cAaOgF

      EZ~U+Kv#ebAsNirvMFaVuS`sK_@O)&P<0rEWr0lXMX8W;1zqI z_)YM4Gmp!db8O8bFNa0h`V(F9{cA)ZjQ}Ae;`c`y$`nEj=h9t? z3YMrCU>Pf*0JaSe`d4<$Ctej-aj^TcBKV|lT@ug|Qz$@HVSJFDO<2(p=`}z=E@_aW-cc(5L~IfB!4NdoEWfGg z(HK$a^su2S6&LlM)IO=4I^uB%UK7q_cY?qg$nyfm(TN-l^db(lSXq2a+MT&B@-=9{Hi4SQa#)wlG{FfZ*?(fxKI-PmHwZJh;ymq zuf6LUaREXuljXmHX{Gw&fmi z=%Lh!NuTlrtH}FGHOFVWhc_M(337df@5NSB!rhI+2=$Fc6i$gH9kWPx3zeZjs3yc= zNtDF&lY&XG`%WniT=bE|d^MeE?e(*y%zsjWyc+lsx(QtEq(In?)5LFNmmZe3%fuS_ zOdu)h%~%=X^T#)##T*ajJLD&vFdAI#U$X8CD(xCfIA`no(E4y1J3VJxF9g}zF6t0f z(R}m7*+SR@kA%}^mqCtrrC$dM3aa|f+g8}Zh%?J1vTGU&YEu%qb zev^%Ynbs55<&o&N)3%&7m=-9!UtGd;?z=IR9YcrLG;Sx-qN!$}-Gv{aL4(k$x3QEE zmw%*t`Pu`2AI>#-i$R(!u?FpABEff)U_DZe%2VHeC)K;Ag68SWB0Zxg-C+$`AGTK! z)((&-efS3Itug}*SL33~#vu%43yL!DHe@@kKLxv;M!+!$M39*^&g|J2mlMa)6A|E; z5vEn85S2zK{r$!;bnXXTkr(nc%b8?xa;HLB(C5BoZRoAzpTgir`tIq-J-oSIf_|Bd zF8N+xeK3ay?gpv}WAggG_<{@M&>a%In)c|8xxbch1mRomCm;b3!%gbGZ=uAk1y*{gOuAWyL0SP>LZnKyeWzuBeddt zPMO*X4Sd*d4*fs_P0D3~wdHwq*v5T}FofS;-Hp2!Q1jWm@$TUzjS1Dw=CyeISuXwI z5y2oMfNo%&&qVJ5SMMX(R)g{*4YYpqG3-jZHWu)>;-y$16mo3>;3KsDcMm8>k|qXy zG>20~l6)S9?i9Hi9D;hWRO2@+{op=D_JZ*Z-#f=RlJib7Z&=xi&^jGyPU9{jx6?X!*nw>J+_-&gfWuOV>|s ze{74XKiy^>lPL>5eozv#tsY+}9+1BLLz!4H&uri|xsf#W$BG%bEX9h2aF4qTxg~5* z_0jO4z8n=z84?aBc@W}{+Tes=FJ93hw-MrA-T2*}zO@ClOBnTvE<6LnSHs`SoYkz= z(aIfn{w(8f&2v(;q1ztZY7`xE9U!MYc_4T}m)QN?QU6anfi?0*y_dW9xJruQL%lnA zM58Zvfw>VZUz=cOVbZZFa|IhDdZTOJoajMG7sI@F+ob>UbXXL~w}WJEZ18+68tJ5j zcoJCu$xp{`%s*+gLUimlXxkrjGTk7dtFlL|prNBeRJq*X|MS~lmeorbKa4TVKJE3+ zi!d7Kwy(`e<|lA!5xbvJ0ptrw39*HE-7L3jzdA5e9dhvo z%g_|zs~MM3$Ao|6#agfv!dVUH3n5)51LC^rxR4v*Squ(P8qg%ZDW)E~heZ8b3za`g z-1#E5K9eT3KYZ^*xVy#Qo1X|89=(KLR76~x{~SmcW{c3L-F_s;XbG`E4G2H5gFx&? zc)Kjot@9!)F`ZWy0#*}m=`j(;I`5j+%_qEm&se}#cjTkmz^{k1HiqG~G;1jI7NQaN zw_E%z5XkojZ~NUd%g#-;@v9EkIhzM5$*N z^*T%vmemOjOd7=iC2aFy>gHfV?7TW5pdHV{#(AW1bWt=2S_t8<*)mVzfjv>LWYK!{ zN`bVQ*VuDd3Q0cF+^5+1;m|^&`1~{YY&@ag`BJ^Bg*L#BpsI8s-Eu@1w4+Ob@D=B1 z$}==S%bmX-e_UsemlTQuL9M{1{!F?Ttj3>_YY>Wj33oEeuLX{_IcqBfP0GhWIFH*W zYA=$32v9xBJaqSecH~%ByN+>Fy3E=D&J5e|bGbF;l;qgYgEOX)d`d_yP(9MLF_Tym zsnTAGNG&O6-wNiVH#3P2BrxN0c86`y^$0^!Qfzs-S!y+=PRI-Rn3cM0x@9HK+83#*a~Z*3VlPBHpZ925caQ3eMmg zKi2k`qsB~)sJUMn?^YwCAY128dr(`X*y z4J@c>@N%qiHW=l{N1^#4N1ZIfgN6}+(O^zO*oXNsi~x+QSEoFs*HKcfP8&v8RpXv>`$B9q);HN_p0_=gCZt9YJawF#N8ofOCV1k ze6ueIC}VN&j$N}6X#L64kTo;h-%5zQ)$)IiJ_^xb&Yk;7_D&hFScOTIcrLre`i|r4)n}vh^yfm@zCt(KHl;c^ZX(4TyxVk?Xmsx-5hR4bAr`g z$Y{YJYi2f7V;=wK6k`?n-&~rZ{aEv2USUvV%3Bp#NXd5umQ|yS5ArH3(f6nY_GXI z8qSFaC@-}Gmr307%jS63w;NXPBb4Mg1>T-5eo6w*x5l0WCm1$Whd6elOJ3+0Zb3m) z*qe+RdBZwkMGeof=s-S{dbAoWz&&#;<5OF9UW&dTZ9~g$sdJYHw97L^n=&JPLb0zw zM`8_W+Me&z&thBQ@y7QZF=4<%-?^9Tq-r&B{iO)NH#8ejkZKhLnHf=EtK6K2do4A7 zNOm=hQ5oK%IX&F+;b1xpsIXV#Cou&I1Z>8yR+RUaHz4K!PF94hxbq^__%9c zWnOJr=gc;k*xjImWblna2kgHY3ZoPSb4}2t2B&Xt&@pS#9)8!aas7NPU{{N>>Ao?L zp84}hQAq3dd2Km-+amFP-i2`(d!|99F-aX_%!v6&!uKvF{yQxWJ}q#kmWID{Z+YtK zj{hP7xlX5y0lM%|{c9}xed-C6S($!7j2^mu$aD*I9j|*3aQk;E<|;-P(r~IQ`%-~P zt3%OZQf_wWU^B079o2zfCnv0CgVY6>hWhCC(t&rXe;ZcAWbr_H&(6A+x)|6)z-TDM zgIgnPC0+i^O{Yq#H)Df}U<#~`b|YXag`NMR@|4MV8qO5pbm&l*3!6_)-jxIA#P?Mt z^&yqi9vyW~;vA2mh;085>urN=)F*j@b9*w^y79R+>$!Dou^3?;vHt9S%DV)?Xi)Oe z>5*>dK4Qi2VpkG+z(5c&8NXU54a*b##sFI;YawW@#T2av6YX1g+0@Z;kji7+vrYv( zrKV+8y&>jP^|P52WBg9jI;5ZFy#MB7@|}s-T3jd!)xk|ch6q){=B>0{tJ-R@FFGZ1 z-WMK!b|d#GfA-0S8Z3`w^(YIQ;Hh#E(1%Y5pU;9XF&*V72tUGQbX?( zD}M8a!be@pU?n9|#CMkMu>P2Kc1)d<&E*jZ_H`7q{U+z0Hr>vrc#mzgLCuBW>BN~s zUBkyR(v}CVVFstbN@3yZZ}jUL2tgqu*w2*MQF;bV_h;_lc|cZ~HBQ)HC*clO`fxog ze3691vxyfmS_jVZp<9a`%xPbmsMZGmRAtZNJzlBZhFiB%t%1KgPIZZ}xFEZ|QbWf) zpCNfp-gD9_=>Y^q-TgLBJBjQX>#`fh5W_#^&I}|$*j4Gn$KPM1dUkJJRJoh~jGRB5 zqi`)SPv&P-(fEDD9s(Qvg89gVXW!}tWsks?>A0EsO@|puYYe*hFgP&0b5-4d@%*#L z)z2NPl~5K02JDF2A-Gkme-W*>;NBJ2X998I3ea;}jt{+P2wSZk^&bBBn=(-5(8M^s z=q}sUMirQd;G8=( zq>aW~gE`jw!m7({J21xPh!1G9Ux71{VXKe{*g%N!}$jrsOt^Z94!qveUC90nUO( z1m?v6QCX%jlx{l$*fn>#&;nQsd;W2nkc-gXZx93MpnA!(dUa0eq1;UJiiKWfv{R=| zjB8^zuD0C^XR^xx{4SNOqqmfy^4Ci9&m7(v96PI4=7`S|`*5Ym6JdS3#KyufjBOR) z46&ECdm`tkGUYMZJp5Al7VklHEK#0X`v zjlLzSFB*-p1px8~2+%kaJU)~~)mfC zP9ub|1}QApN(G(=$L;k^VNFGb*h<)yabu}mRCl5cWM#r%1lI2 zoVA|Z)}p${F!|aGi<|-7;s+LD`xeSqa^bc?*D$8!;HFUeckgjmO`CfbhM#`JNPj$v zwEC@|`;ho8*u76EsZkN!di%~W6b}p4fxQwq1fdF1o%rkP=gcGTlW_mCT~V$9LX7rW z?TuLm7<&{RL|gIrjo}FDl~!YfAlajVQHPzJDsT=1F|sFpIFccznPck7I=gNM?@j;y z=S!p_Wv2%;B|nm?>9Q($yJ*=M3%U93eeXh+uTK(6*^SIT)HH&Hbe#?|yV(P1fg1ek z1cu4e@f+lJ$QUPUS2K58QsiB`T6Z`1QXwyoH}}$L3k>CxOS`Y*pSN#=?_FIPahHNo zy^uChfTm$>1DXcj5X0Vlx6Tuue*?fOz1<{Nt=p*ECV9hnwLp5KsL&@e1Lnci9KJx4 zDFgqpBY|0Nb3RgA_@j?uk5J7b1aPJ|wbYk*c+w`qPz*5b{*sC}xJ#1VSF(W|G`_`L ze+eXwAK55`!?>Pn z{)Rn0JZ}L~ez7@ugUHQwqo52X>kE1Vb~e$e#G*zsfuWjW{;;3rxDh53M0popJ%FYW7-3)X9~u07R<5SU583?KC&2lU ztFSmCDfH{|sjUls7U!3;JfP`6&ND9_3`DsZ`^`w|CWe{k0h`~PnLR6IDOLCTP=34` z1=;32a+E{)YCc8*>$2l+tY}?J-t`umnVcW&y~Q_NMuuDteMSZRMg~~+`aGZpr{DJT zlU|KIM00oL4@L#UA#>JlTD-_W5L$w6^h3_UExP4Xv&EP9_qfy+`^)9(+1mY3E7Jz; zvow~O(K=$JNh)zS&hEUFN==djL+u&+N){ zFU7s_Sv$6nwrV_jGvYtOTInosi2Rkk0$Vrc2x9%+51%395*InBkf1q`F&_L&^?-QN z>c#hpj z`bt*|O(&ksU;v|ux(PxFpL~YIn5VYscQ_!NWDh^>2=@CL%g3E9x;L<#Oq)WN3Nex@ z$UJ<-M?NA@DFc{}%pQk6 zC}l0N_aF9GzdgHN_|EHIj1H2qy7D!SHv27?tc_&4!0pekY>MEZ1%7GFtCVv8W4Z{R z&2!SxP#txTm8@wdtZ8JMp;!r^2O-N^13gFs-hrD-f(fB3)50TYJeU!w8~aPVC}H7^ zB!_*ysJ*#YkSN15*Km4PKR{O2BhQ$V8b%J}kHvBa+SE`@`$&$FC8@z0eVI42JeIq= z%b=IS0DYN&*Fac_Itfo+9S7T~`Mj|QxY}ko3$!Scm`DW(@pJ;~b<-7bA0Cw$z|#5^ zI=y5vPW_sPaE#!V9APEqWz)hbVA0{e0Ay^pNK00mUp*XZopvFA{Q|q5#%WJ+DY+=XyD_M5upyNDLq&(4IMy!}( ztNEhCvr}F{U&PySL{_OD?;|r9y?@MjHA?7GG{D|byb&`(B}9z@*RF5h^QJ zSDO323}%q4WNlk~xNd0g^n6^ec125|1F@M(C)g#bHxMRV1W)C~0pqBUo~v9>L1WOP zl+oZ&+C9ZbkZJI#iFDnZB8Bn+Bk4!0+1~_tbM+(DbwBG4at8jQc$dsRzX+!C^D5cz zv?zC6B|xOt#O%C|tk_a3n3d8Uq)1%G(YWB!Tvx8xGSVHK4mSppOkIWQt56teTHlo^X)u9D_b^8L z@c8o~jRVL@LRgGJlC6*~hr_CsT=Q_=uH7m`YLnQ5emfbDmWK{!32R8v0z4vr*z?sG; zs;{t%{5X$N45!rBV8s1CD)fJXx$VaytLek6WV>e;Z{zikbyuH8;UZfl7AbbXc1P|| z2_pD6;t!iRPs?!?Yxb%wz;^EwscjqI&+PL3*fH$6sZMTWmtv6?Ss8zxcI?J!Bh_6j z=!S=$W_bf-nq3VENx238V3$-Z+l{1dAu*)uc&(59$(;~9OQEF|(TI{y0yf@1GLiR@S58u{ncewQI?(!XeXB?%CYmO}d z{}Te--v`ws#Ryt=N2e>!W(l9(2ezy=)JGswxS z#a3!VS!n&&-`L|FnYc&z!BMJ)l%>3gCmD>9F^8>s8)gWdTvs3N`a~1nv|P<3pax%_ zcMX(#q;KmHRRqyyce-ZxDA)7sYG$Dm+Hy1RY#!hOfl@UgFJs8Bpvz>8t#K2ubm|Lo zYI+~$XCB0z%4$e52_#{vI{#1f4Q0mHCZt#ObnM+S1=X=@j`b8J!^t#FVb{z;ZnhV! ziv7&U*Y&gD3xE)HWc(>Pow*21(aj=udkk?Z|}pwk^4zL$F!-X&#T82 zQ!)*$i`^6-WPB34ocpfTymrFSoXB_jV@o%ml#R^SCw7~lnDa#a)HI_I_VSpIC*vDH zwtlALEh|mi=8Ue_Y2wdsde3AxFV{bJelX>Ru#Xl|O5$D7)*7j`s81}v*ENOEpPuCa zAwVr977bcKmRBSg{cd!!^-FZC=CH4qD2t4h*>@99$@`Sd9p)i}rmq(dsFOOO3#^Z1 zM87!KAqF{|zcBz;M9*r+!38=U4R-)UF9+CH68|NbB(v;w{|dLwa&U6sfoxxN&&t-8 zUxBraI;G33Tj18$b7#R%wSh%nLW+D3^8?6El&V5nEO0-D8>2o6_Y%D~U{kQmf_}<3 zRhK7|=p6UtD36V5!TJ2Zp!Iy^H(fk=iu_{co>v>beFnxMYf!xF zD|hx}>1#8a#9f%Ysie1K9{PF-Xv*bz+~oC{;w)-WX^#9))3Cg*fvJrXc_cBBZ)CHVU(-g3ESxewL_ z6!MD>Yiv+Oo1@sm>sbn0E5pRATd1BIxY8oJY9KVpn=_ z?f{`1sS#Ka;ESGMptoj5I^1XViljuY1%{ylz_J!*>n%e4WQw&zg=wnxG3TrSHS0Op zL;2(St^^F(coZcz$M`r&p_RaTj6|T0m4J~V#eQ8UN`F8nR2J7KcJNYN8lb(-WVC{G zE1Y8~EgA@@FGOsIfkal=v+TpaMmeV_N7C}-ANN|7_qZ+oN~h{P;*OpW!6Y+$uPh^g zQGggpD?kr6D>{eZ#(i-mQg#;}Du<7co*j8H;ds~u2) zA`qN%B)!ZibsG8OB%sdQuS_p3iD+|r`Ivt1LjcV{lHQ9r_3xip$of7qqjLhDJYzCQ z`Qxt%Hk*(h57`L@SVE))Hvxdz)wXD)M6Ar30ZB;R1V{R2OowlJqv*p!)bMAiU9E?Yp4{G)GQ(EL$3Dxq;t|?MrY6);QY~nUH zikQc+1LEXbY4@2atQHBk-+m9}*pS0s>BW@1QXuUT-q}~T5%|i|&G&ZnDfKm(wx_j% zC6{Lx?`fBXw%(u+{GFLYJN#@`;9|vSJO2@w%<`Sk&~}pCxKy8+bk&kzdS#l%-1^F; z{1M-1h+liy0Ii)wc7lPaQih^~>jc>HPn8o>12T^?nzVvY0a;K--3`bY57*WvIO{aU z=uKF4$B|R4vN1^&$RBSss^-L}b0;5W{R7Zo2?V^eb{fu(kC=V;_I~oi z1#C7f(4{L2x=a)hv&4jUTz414Da23yazdz#D2Z{+bGQXkbjK?)x9W<)3F-3yp;5lb zu^J9iUdgMO{EGpjIYrNccPL4*+GKNwt~=i=7XM2z6F2O@>(s0snc(`Op1Tf)&BM%o znhHCOL(B@riH6F<^kPX)Nsu^$Tz1(|7{C!NjD_*a-XIz$EGi;3ovmw-fH`{E*NB|DIxacMl;oj2g{IxD2EU&HyHTvu;)y=cV8*4cS<%KYp70k) zRw!}CL{nlnA;wbDV7@o*`73c*9|lQe7Q1K)gD3)j#=;=2%u}vHesXhXVzvTRj!iP$ zS)0s(jbD-1b0eSzrotfgI^&9AX2-IS271tCk}RZDLx#IUVW(R2vRF6RgG!4W>i0fX zm-I*;&!jbX*u<}Q&=+U!Vt8h443p*T0cYQE#2k;okR1)}^_3BCXoe^1qQa5Ik>Dk?VajB4p24a@~yOR!84ZHSAv2W-~-PJurZH{7F zMZ>*Vh(S8fCQWBZ^MuW3v{Jw!Aq*r1ZkR^!CSz1Xs_}@c9P46WohkJ%vYZud9+4UZ zuXvk_A&f};y|Otr40C@H8J5iE-+ud6iJgI332;@ifJfbvq;0~rhfU{^ ztTf-smyN+khp0U|-YH*aIYFhFUX(k41Sgab3tX?MkvE63iTJoMk~IYc`L#;9qpZ!0 z?NZnAuS$z2VZt^=qh*S4S*1g|?>}osp=w&O%d%Jqab%r+*5D^w?hGCO`r8j?y|r|i z{k=d1LsB?YeIzaC*De;$kdac*fG{mamPt?Y6l1moqSkiQNEJuO=tIu7tz7DB!35yw zAtTS=ub*4O{HJs33=+_JG02j6S5Ci=c=Mh?K%GHgLbCxjB7*)20}C}i)=!DzDP+34 zz&cs_E@5A%b@DaY(}>~1+Lbjf?eQiV24P1jLXiKrpdHrUXY-WqL9*)0#?%s<5l2QeQSMTR>Nkw zr@n8tY{S@jhd?Ez#)M2h#>9nZKF^><S zZRHuDBHfe>X&f5pMQIdh%8l1+GGEhWW@T=}aTpz-<@MIy4lBa(5)AHx*#&~~b~Pp* zPZ3MJOsQ0Cj3SM-nUh}`Bio)8hJN8R4)SA9QOicnv;_d+WR8s)@~V~*c5Whp_@#hN zVBun0A$10+kYVk|3x)YNi@xVc;Xi$Jjj>*53A*2qhL{vV)B5X<-U?H+e2R*ldZC0N zYrhM%7YZkN#vpG^69WlT=zVqF&AjN1L9Aro!A!s3VebI1X^OzpV8snPXE_$73a7^E zN8vjdrkc4*P&$@Py37u)xUK@oqqbT1mwuT;8N|olqOK44@77p+m=+DC97$A7M2 z2;LBCElPKK!7TswNFasmQ{Sw>)waO)-tL*P1i4xE-)Ngay!g&dxJql2MFa_rvTJHa zz7uHXyHG)3jnNP76@Z`pUloKoM(BNP1+avgo~@lcW_v8XXo=7#3d8Bqn^K)xN(q{j z4Qa`uhYnqcx6WefuT_06ncOY=`wu(}sNtjK3VzSMh3zsYn>~uNgF-#?hW||d{^aY# zf_aEQ5O&y@Jg}tT7V(}O4%;om(z6+ca(n*{n@T@XIG9wciZfR6 z8m=X$<>OoKc<(vz+y2960i@upUIt%74O(~a{mg)1W1vpnasX29P_n5|`i4I=7}lZv z;g9zQi12&4eZEKk4J&Rqi|2yB=6yKf(TJD9SWv>!p8{)XPNwuSiErPLKmCXZ~(L z+}E{2*9%~Gxgaj#4WU}*LafAi2V(`$r^^UEXVs$^X*dIov!&^FQij@4|5uBV(G)|SaL2>1YO z7^4Ip)^XhUw(=famNf))aFclGgjjqBm~S#o0auFBb+*5RkImV8iDBOazo0Slr^0zgc)>UKP?oS+Dz*qOEp3^m- zS-qjLRg%EU%%C}7?cp4G4YhW#E)YWj3!o^p4Ba*Pc6lc9@Y z-Dg{3jtCJDm5aWyoUh=$n%YH|QwcIT>?XL6H4=hLNqC`=`g?!#=;I><=WKS0;>fIz zA#TLJ8F9R#;0#~v;y8|=K;VspmBMWZ4(LqX$aV`dVhd2i^;Noj+XL1t9RWip2ig5U z&+vg|b^nR$=OkXmF+*(0I<8-Iev0B}PiCe9u2ZhSBHz34Br-1zB%=8WSu-!n#-@uB zCMUZ;S4PyZ!UUQ=2MezQUA(?9hF4ImzL3bu(W*(GLvJSN3~b&=W7>}j2`~?Mfa+T? z?33b%s2aSAq)g$O{r;T}LKoS<7$>bnE?{xUn!Mg#gDULsfL0+cuNyK~i~6Y${aval z+h8g$WTU3TlWJBY@tBrlZM6(_e%q%ULXG z9};ANkIB6m+Y?_W!&Na{iuidh{3Pd~>OHwnGj6BGZpMlldi9x(9`FFOXDB+hg+fxM z4>=N0pRF*KMMokT0EUD?#F6~HdG9@Y2EJj$8lf|)y>7sj)?z)HF2;z~z1b{914rxn zu6KZ0z|~y2Qk#+{-%jtf0dsXOZfD&l@mjPgLN(dRV>~8NB7D&p^a)u~FHjsIu9WmI zJMeIsaQD#zmf5MFK~RecgbM&12rJVAmiuOK$uCk6q%fqf*(Vj%0 zDrr)ge!!#-T&c@koM*VgiBz;%?o4Y?rTBUpimivHuhJ-8Vi)+&5^HU!399ZRY4tCG zHo*L0@}0mae8_pp13QmmfL}3`vMZwy^|_DD#(@1+U}a8ruPExF98d55%YSYFbx3n0 zJ~AzcoY1UfV*vPbmTv4^$dJ<~`LE^jT0E_w&Ld>e2JiZPji0;BwA18DR?>x($O8TA zk%)Vs(^+NhqD$`5rf&6_sDqgt&H4>r&n>8>FErHwP2bD5<1QTsGYgh3T^AYQe)LLlKrJO!&zEmUk?mDI1-BpU63Qa;nuvjL z)jCvm5ZjhwN!^`?mv3hZWf<$*fZF*~g14?fG8Myg)Ly)KdBwM*)rvTGfDScK+6wMx zfl-7SiRKV&1&uJ;Q&Hxz5Eks|$zS4Vmfs_!3MQ(=Pe*KwkbeT#+12{E^;3^J zwBGzX=Efu=QljQGMkU&)9Zq96k|j13CGA4W5W+WqnF%?&i-K&eKB616|A=j=L|YFc z0uS;(pz|%uG-a%`gJuxU-YwME$OU)(F#S(IzFt z3lsHUab}w%z0nOd5Gzd_b{b0{zlp$fT1A*w{LI37Q*QH5N#9;RMyeDrlW&h3f%2_M zrMy*d)IMeyHWce>C4U2CXzi)@{_bxgw5=xBEEh%>(-z(;yc{F_N}3o+x<6Wl?)u~> z=~6r$p|a;Y^3#ZB4>pbURX`6#`)bnw2*!~3XvDisEI1#Z!lkCyO%kl&ZZRqB;H4Um?~$--tdMu!ro0O z33gKrg-(SGW^8JO@N&gZywbpI9UylRn_ZW63&e`1cw==6WQnG@VV!=~R;zSlLgpSx zQ0OA%#?Wr1*lCmIZXY#GyW!k4^fgKtqe$07P$_$3WtUkg`){lA<}ll1 zo|Q7KfP>CuGrsx93?=s~v%vc^XR(NM@Ze}6*5ZnF_L^mP`H-{p_9wn90MSmyFn5u@ z9vy8-Y=T9442dqi{OU#OQV?B=w!0Q>c|Hod=_bQ{(GhqXnbjFDOiKNo3z3F}CbmD+ zq6;y7jkY!Iv0sD0uc2j}pSQT-#WY!Iu|4={`De|89ps+&CN2vrP`k0<|L_6I*Q3VN zBl01o5I{iriCY>$nIC&?XcRQ}Fl-rHJ*=w!f&36dFPUYj`G+gR&!YF8$JdWeQ@`c_ zP+y|P6XcehaipFdy!q}zN-*&7FN6P*9UMDFDo>u{!vO{q$-qCYT1kH5o!=!889~&o z7=uZNR9KHwPggR#K19^5=ffYij8&`|u=n-!-FAZDV|sL8$Q0I`C4K_0FoM*=lo5Pww5fC0gXpQ!%5Xhad+^NI$zX8;zANXS=kK@@)x38#|K?puaxO& z9-rl$vSGB0Hta`cm!`xOHl|!n)6bA{XG2g?FI868&Qh{)slL&GGC-}K*Nj<{y?l5E zAaTH@Q}?jWA*w|?W`Yd!qEKf+6j{;zp%gMOUd~C2eotC@i``Y_B~G9TLc#=WWo9ar z?L(X@zT`J@A0e3}EKWPv`D}EjNgtK|L-hE5VXeBS3Mq+2(T@~*_E{{F~4w zl5|S|Cz6-OtmiH628pOA$x(5xtshd3=tR0vurAyRqApL;Pc4hwBIVWqPWjVc0+sWi z#7{tGnKEFz8b=1ed#ph|J@Pu23tu02#sG>|cFGrJm^ZFgfr104=&8kByc6+e&2Aa5 zj{&LLX)ZDDr4Kn}1>gY?!F`v3!9oZ(dMBHv_vPm#;IlznkG|YkLbAl&N0wLo2MgA& zlBq+$2t)a~Hvfc<0c;}W388d35A$E-+Au-K(Ut`VK;E=$Sy z=J=mo*g&@CkPz+uNyYN}K>8FK1y_KaP^LZVCx$X>U{#x+5#M^M)#u@_T_b5q1C3F! z#92yvjzs4S%r>dUiN3wt(@Qe#8|()k#V&{dse>IQm6tRo?uRA7#y}$FQ1d(nhhz3o z%jPcEbE25Q->2!<4PF0>CsF71IoDEkNP-FXveaF_+V9^%KLqqJ?JSf4CmH=u8Llg4 zc#m9l6Q%NnEV?s6Th%`xPgYGeyK%gx$s;m1N&4(2yf(t3tijWIWV=T&jb?Z<8^?NN zHK|j+fnUgrTzJ*-6OANmxwef7xN`?h_dNMif%b%Uqc2ne+RSoU$^O|98sIVF@*7y0_m_Mrup2 zp}`2iiC1*>dkgcN&Fvp(4!tc=daM^ zhuTmS8@gAkx^>aG@`udconW@krhb3@Dcwf>`5?uAS(b|4Am zG5^DJgE0qhZYpsO(Emo7GRcY*Xs^s^3QQ~0l(f}TWvLR9jVy$;Y`zX1{bu}>0T{Rt z(3c+f*nJ!~8oA8ax!3yI%ibDrm2q?Ipcu(n>!DR^riI;JSC7T%2N*?ML+gDi7Ockt z2Vh;IU*jS+05 zAJ5HSAyXY2$KMryZMByA-lgpkndC8GD zHa%IA8@5q}B~+Fn1_tsslhO-F|Z37pVo?6l<7{l()=E^X_72H~gqCiQ8t z8J}I7p&#IWb)rsSDue z2dIm?QgXhTEvuGL9Oze9K^7%iEOho1jsDWDoaMua&r)127T1K7!ioSQB}QLB(*B2E zM)>*O-{_~1ztQ>5y+YRuKjPpVJGlRpjB4%*V{BFQ;rlghN?i6!Po}Bx^Fjt&H;_!F zf;@^^>7OYm-(A6|5h-c<4sZacHn0G6kSH5i4>77Lq#dq41Ln=YH@@@RF#PGiEb==F zHB_TlJyrU%VYAaBuIn(DX&t-^Y_0RlR;d(nQ0tyoy<_-|U!$yh?mZJ8tqSpMYGI&d z(8c&Sx`uQ|ahKrQx6gOc2tY(I+5DPyt{b!b;L4Tn(Di8XBtQW{s3jh1!4lpGy(V+R zeE@_&>gf?E4j+|li^!jTanxgZ!WTu%wTt47fibEwYEu3EyKn^i^sw4($H}KBA z`(Wz3asPj=&m-^$x{|Kwemqy!7u|v+?49*@5n@K#T~u?Zje2VYn(LYf4R)-pl$WWemHdV6JF@jlXP4(he|u_1K(K9($pA8)3l=4*$0oDnmWFNGA1}uXfIar31S$G z`ea$v*;@?}*6E-N@wnybdUiYSI@)x@$PP8^CU)f?d8?+kMs%3}(}-Ld+H-oK&hY69 zwPlL!Zo-Uad&y;vb^NH0GcZ&M;hDN;v2d%`bOe|(>P9_Zk8NM|1+pup)4GKlmZ&zf z&1PflQC;1Hw@+RhsY{uX_T;6pT%3;5zqqppw1LY$^Pi9EgJNvGMOHz(UP{=@y-Pm; ztR4P=1`s$|H_F?!PnAqHALT%l@2^4lKZ1^zTaEUs5BxlRFwEtYhXJR|k3=F!R*9Dt#7(-T!93I}U$f@|EEp%4~1G=U_g&~?JLcD37g9or5yRX3; zKwoauVwnj%<3H>#Zmsw(JW5(y-!^$ipOCJN)icr?G?F-sQ*nv$NGY|sD&2u_jr|`- zl+*RH&i#7hb+-@4?rA#ikuoEQXfEXB+nz_#*Qb&wuT&R&lb$iu++*7S!d1}v(4SxYdo(ICQx2lvw-Nr#ACGzH z`p&3X2?hUQ->(6DLe{1P$Y(w{U@aSvUSORv#LpklT_XgkW>Lrb7~AH!;dOK|c@fkafOkExFTZHLci^IkcUt#fQ%rVL^3P!=CzLj~ z1@2KhZDwjOizsrnB>@GwkDO!;ZF7>Bjeshx`cp}5J%SOKd&gj^Wh%&i-|v&GpwkTw zle2|>l1z6znDGZNz(r{~yMJKH0}7=cltTU4UxslQ0F=PVD5Z9D^+m(}^WtKFM+hc}GZ>CJj(GkGDTET9;-sfJ}%jj{UgTO-% z%h_e7;@KXL{z`kJQ((*11uT;w=W6ft@t@1RTWEG>=Euv9yJHPr`~2RnBlEk)@1N~h zI&`3hKYc`iHCwQgnw_ijaU}Q5SEg)U0L0(R4^`?XvVYVlNXxA~O%=26%xOA^HbR=t z1UL&&dKx6~|50ss%7)L{6v!J+-0+vivLboIXCCARO5S~5?SnU^R=Svd z>j5i$rR0-7ubtGp5`*#UfNmAnU<&OjPMw4<*at>y6~Zc+oRl(wk7Y+hi8z9ZtXwy* zV*0Ihw7r!fLBvfK*oU6(8swH^RFTeaQ&AKr(Kr>=vQb!K-*!Rq3nKOFm+kZddMG1mcE14BsEP(x>H7i+~(a?q`(!Y z)}}7-eGAK=d9H1&-VfWxz=nR}#XxB3X0jF3cK7u|S^YnY6~X9Tf-qHPsD7-4~ zncQCmhKGlB*VU)0{%nP{FLxKOQs>S$$>oIEV8-*n@kR z{t|Mc9YRHrrSL^&3W%AUZOUkv->I1B62G}-lgx!sJ^RRP%s$e`6n>`~<)K<{WmzOZ zlLd@*@AleK-irl!mSzB4wU1=4LV^5?f_TM;MExI9+A_>DHaL%k0vV_${rQg$jSJo! zYzk=`QRTe-NIPfQReSkbb6m5A&eMM{UyJ5;W_}!s1LVu)4JuNBjhrD&Eu{6|W^tj$3Xe4$DQuv6EDcGJ7Tmxc{WaO$5cHCqF+WN*RlQ zCocCfbMc03#GGI{eq>A#QR{?KO?!I067xF(~@SLA}AuB48ar=GP6HL$=amiokY<(C?@2p zCMw2LMtEtyOZ;J>FIg}@+s1oX+!Ox}YFDt3v{>#IeSW8(z)5J(`!_#%zloirU1#X9 zY@s=EPQ-3D0`q}oAhh%MG8f_G^+C`><69Q%6eDN`{m`g>x?3&1$v3)-{?K^!yM#L< zIG_>;yB6;^Zbv^Ki1w37wvUM0yNQLB0VJgSkhMQB`}haI6A87Fu}7E@59r2rnEjsb zIVFR?q#vOyyF4Ac=BY|(@73MLjN9e{zy<;nv1>Q3UG)fn@F*eoJMtb*ok};w24QX!aZ;g%Ozd^*3loP!y+yf0LYb8<4@aiz7F1_ ztFRPjfDMJ0@&duF6JK~*t%PhDDksR)2tG=xpZmkoI6g9nvJ zX7lvr!ly-ipgxrr>o22ykOGqC_g{Ky>4A(B{Aw!^3%uGT4y zpS6W)$nbWgwrX!in(X{iDAfImy_my)c54e##LQJ(6wgBym%dX~%YWOl-}LvfL+_e}><`v@Ma8liA*$tDZg#vtSfvY67#klu3;Cil>JZ?yJ2iN>T{ z6S@64?|dk9z7G%86V}r@FyN}K5*fCP(6SgBxx6V~edF;l@6$_w20#%@S|+Vo%oCNo z#WHQTfM_y0h|Q+_>$kzzHnJ=jDluDcv+rq}AXuI7HNpmv6BCW@yh_U67>!5b{1TU&}YC$maEwb4aWiDUP!N{e}Qsy9>P(jQc>QypLiYc zO#B2z9-gpYD*pgipNN2X!e~fFLR5CFO*8od9mvlgS~r{3Mn8EE9jKeBvZ#3+!$|ue zC}OXh>9Y=u-h>9b_hir4+k!W@i3lH&6>;a9Ed zx1eFjMui}HW7QRD_hzJBr3i?H^=RwBOaC|~LhMhV#T*St#f(kFE{c2*xw&bm(2m5< zIB7)M1S8JqhW~vU9m$k*uVo`|d}Qomhyo89j#IS!ONkXQ#_hCJXgWZZX9rgCw-0OL zD(6kJ()it>!LvN@N?(VbXWyzP25OSX>P05LW={c@J7cJjwy68~sfj*pT?}zeS0&nE z=5z8||H!}xC?!n}0nxR5`t#~2aMoK>@RSUFQ!;4|RW6l7XWAGp4fV59un#G>m-Yi` z;fTtbG*2jN=&I3ISFv?wlJxXiDjOz#u(QT<96#_g<^3@OiEt(%a!|#y$fW5J>_L^% zo0jy{#cDIP^V_DdnW6feFU>1Gez247gZOIMCHY{6#XNPR*dW8twH|j=)Pr+HuJ`ry zw#@boeN)5|>SC`0lY8isb_LRSL$>E=^1F>ul9O)bxqwMv{gmdWYil%8MOr%==*q}< zElt31Uf!LeDIR>vCP74Fdx!79@EoHk1z)9RS`H{Dul#E>92tY z-)RvUi-nq1Hsr7Ziv)lDeCS)suosj$1Bq#Zv{hOG9`#EQNZHFpzBll|?v>nO71&Y& zK6$Rk45KBj)x8NkxY>OPo{dn;bUzmjEDIj?=Lfu-|Hsl*0JYI|ZJ>E6DNvl^UMTMF zP~3{UySo&Z;8u#eySrPk7I$}w7k4TA%Qyc_W_CB(tlWE#pYxoNa(4ilB?WORl^yHDPEopYJ<9}iRwA~CiKFWLV!$s1lAL>lXeE# zLT}F2cezwM$*KxKj~&C=p#Io@C`P1yYMlBQGejJ5MpMtL zCj;jGgN~k+3kzLrP09s+S$gCZf;I6UBCG0chgF69bZQQ(%7p<7U9>RQk%}+VhHU=i zj~u!MD`gW5315`;25yhUO67HYe>9*p*T=LQ`?SRF_TM{b5alLV-dXrq^Y!x|@uMs~ zW|`V~HFhPZD(oJ6bRHhkKPPccGKXz7#Pvz0sx``%KK6@(6!5;Ob)MMDKR=OriL0n} zc4(*0uNX__xGet;bj)|4E@W0D)L;zYY$tpzvV|X9oEg?Qx-+c zNAjkqPvE^#+8@EMK&@)nWEfiZ0+Ts187ALXCO@37DHlIqQuNJ?oq`+*z`Dve%F#e3#{&w+ z>WMQC{B-SCLkT|FDWYTb0oTVqP&0sfey$xYSeK!3&eS_s90BW&6U^QvNL~AE=+(pP zFZa+G0>m`GT{2yi7$T7SmK%00h1TpE60!gFN%@hn5bAJkD00~&0J$9AD+X#Y4%(KL zghsdm&uR&4Bueq_Bu(G{Rs2};AUQi2|9089X9ThLdPAy%pNL4^Mg(?~8YB=-|B^_n zb{^b>odne30c?Qz7A?@aQE%hsC4BnVT8Fn2|QSg<)UjPjAgPCek=Amyw=EG|K-_bi_Q}aDOEB6^* zjcP`FCch)mgUc_Z4|f8Pt=LPcnTuHTpYGSBqn-&3gT-8k?lXckdd-gr$r`>5=|yE} zb+5>P9kW@6r`!jmGL-1f0gA*sJ0^EG5*y!yl^L;tx~l9SqnJTe!M0{qu4fE3Ph!&JmVX^=lUpZzJ;?d@i1sePbKX#z%dF22jqZ6y=#` zGbY19<7Y@;Ng4dnehtC)4xI%_go7jpAsms zNVzI2IY+Ga?)3L36#vXP-ruE#_>voIjs>V@yahw`9zf+vIOW5wuWGwny%5@p;kvZn zXULQt4=uXM7-g1}ezOTuOOUcTnq@UvN9{Ou5g;)fc;$-y&H$J0;Hie_eOkW-Hb8Qn zr2#`-N8B8W?YHoEL-huJQIoZ@9YdE`op@7qkNm^k?hZ)(#7Z1fC$C48n5xIs8p%69 zFjnC zFxCEGteZdArWFAV8IA%s9=P1ki?PIX1#>x-ud6=; z3a5VE=z*jgQ$5kQ5kR|Yx#W7EOQWzTY(b#xtt&%mic!QGIxPI9FQPwT3Fk5HO(Kgg zC^?T#H3IR5)k_FJ0fDYeGH&vacVfp`c*LoVS|y;u>}S;!V;EZj7NN&6_)TXyYy@-` zG;e5@5<|(2L=pyn7RfIxeN^n4!5ynqs%{eR3lQl8^b-V4Ve#X?XzHQ`>9?ivh|$#k zV%DFbWfqZLvk5-!pLf)Bq-y#LhKogLa*p}0ag_53bzZQSJTPD3JZy6rgO9A_g2GYk z%PyawMRJzmUK!c*Qh-D7h2T63KuNQHKO=9tsHmF&M9T|P^L+@Jo}ZZ4_uu#`$xEH+ zR!LbgwJu@gyQf+qRNHd@xh;5l`eVfMm2#$?&HMUJGo-AQQEZM6u4@sS^IijRB1Yl_uwVW=LLO%~PP46PL^a8(tCg^e(@jFs|(WuYCVjaXoA#;rhi;xaS+ zNQ41_9Fq$&k;=+BC_uQ;{FC&og)|V!39{mRS`J@HM_)BWD(!r-raHABc205E2<~k( zCKIu8)$L~vcxuVsH1-OePXgAt!A%6LgxI&)$Q92{JHFkk;oH6C5Go{_s(=5a!i&?7 zoZqEe1M=CUp1KzUD4OvfYXtOd0Sjq|T{X_lkIh3(%Ye`};rQHh^WF8`sRP69to-rm z*XANn%i!Ay?;T5SPpdO=W)ol*;6eziGvm(sXMrDm6~E6oRNX$D%0HJGd`41@it#ybs(xiq3jsUewl=)3p0UrtaLuku|0Bna1Ss>C znJJ`mC+rQyM$g=Iv72Vg0+<-ipV}<0;Hq&osDBM4-f$bG^PHY1Bsti z89w^9fULMrsFw(G_ZvK0`0!_CPd)>qn8I z&he>k7TeOKj>V)74w~`erQuYr_S29AF&6%Bo|u9*!pqvf(Pyf!lJ*oh(d zYy-ITa_cz{UklfI?k_bgZ&HqUEZvz;OzA6cyET?OU+W6l%_3;EmN7=DXijhk@4_nU z7@6l>r`JuEv)YC^>I)mArDe<`^xB5aShGtS0|Olb~_S*p9!VS^NS9wMu1)3bLb=RigBJ>zz}_T60RV>CwliaE_6&Rapw1a8w!VrHWbH zu=Pe|%UN8pk+u%nK-(2CejZOyYE1D>IA>w-D8ytIM`ji`XBKx4D=#QW8gm!cs!r)E z^YRwa*rkab{CZ}zdg-%$*|B|LwRwree3h$5c*i|K#hIpVhUVLRRnc%|({S}y@jIaR z*K3Tca}EO?Z1U2Wu^xeyhQCvN^x^fBHU2=gsbI$Jy)EYdA0I+`^~H9(8xs6Fbh?EV;+Ew2BKk2OHAy z6fG0AEOm?i?T7ezq&?u%l%W#$b^?F%Ld!0-XxBvbgc+?U{r`!N~PVpXtKbA{-T5l5P~I( z_rVy1X<~w7M5^!qT_rHF7ftz3q{nrZ-X!GVOhx_eEL`|1rA<}DP7d_P;-T`h6n9`R zF$LPZy|6tbe3fE_(?MBa*_7}5Mq_#0pJfJ87pDhMRmGdR|FLS6;FngT=c(^q06qROKzCNu7RO1PsA6!tK7z_IMj8=+dz zFkF*c9Ep2(=fEXO%a;a9hYg@Q`RrN-IZYQ>EwxM4YoxKj!o15nU*hgr} zwO2M(T`V+0y;9sV1sqQe%Pb~6eq0RTZLnec4S}G}Q5)iIC3@zMw$EvrN3MqzDc8e% zB9N=IS@|{Xt=ZRJYr>$nrn8pUrs$k7C&l><7l>3boKzl4orZ{9(g4jZqz(O*nMqq1icV2Kao5)k=Gw+QR>OGt*OdnkP9==Q#m86*utsZ29PU=+hC*Rq+HW%);I> zJf6c|NUtP9pT=~k;)5@(KM+6cSp5A#st3s&7YnnWt8awW}}&wwXA8 z2MBi(_=IeFiVHijWFdbQ5ujaN{!sc^RW>TUNi^@VzMzJ2Y2sNf0yu(R(E*|OUX{Y@ z?(EMktUei@JDP#zK7^*TNdJNPWgKqGje7`BQ=&B;fmf6DPTG_oxqg@tRfA#OvGbV; z=bk`^iNO_|ox(c7OpTQ%Nf5ApAFrQ}KuGhl=W@nXKg0!HGUry|$|5I3y=Ce3HI&Df zD0w1)i(}9XgKZo=>@1ai(Tc2~9!d5%RGyKe0FOOb2rvTV%4Ea^#X4 z7Y(K|j#7^L#27SX$}OG~^dgN?{`HJ8*c+!z5HKI=+fP|RsI)Ya!FE@c!A>3o(VbQ$ zfe63+!wTDWgox88#^y)nCz7QtoJ~l1jp6^QVagPcn?1Q|1`=05zL6^coyImtHBD^H z4pcHWPbmQJGaHLn?w`nxStBk)U?}u+tN|%(QjqHrN#Uo_% zRaYrze=X6(W&XPB;YYA#C!TO{iT{tU+nsCwdmsT<%w&eM)5E_PzJU6!o|JCa`5U+S zcW(2tz}S9rna`>R6W7klIXdmxh}^Zo6a81?4~PfK>z!+F7RCumE^RcEX95v{zGlR$ zDsISfCBpB!G1Arbh*{impeS6tW)fMe+)KMwO`*xCa!+l(%#^lW6^dN6GWU4V-1SrY1JpnZac%IcnQ4W^p$;@vfL8gHR*5QBzLb}n z;R~z%4VrvykbM7ouwrRrDb=*u^e~TB^$UQnjBp*h0Zis#w{ctN%LPE?bFa46MKc`} zZGL>^sQ^?bwgliM&U~e0vp7QxCVxZl5gg=w&+Y2>=PrcY7QiUhey$ZoM|n**2+{(; z25#>Q2hed}ffR!jYyfi2XtEo8%0{fl1JE0Q%?@&ZU*ROXLdv|qG3CDac0SDzP@*TO z4wJaz&h^%F^qv!7a0~t`vAPjwX?_?w8*3&x0fkS5b0dV|3;!&6-OD&_wzQssKh5cV z(}vRC$$McY59yP%@UF(j(CZl?d{e3B&gH1O^21YDkN&3$qA+8Zw0e-S|o zk(~HVM}T8{N9B3iD7=Xgebe*F%$2S!)EMZDdlU&;;1gSA#^)yls2Ayb+~&s}+W$Ra zha`;7%@MAHdrviu@)mGfPG^;Cgi#YJRL|P#)s2r4R zv?(1-3b|X?4f!&zmOA8x6P_Lh-aE!BHJy|n9g*L?}#tMLEuqUlj2I=OM z#Fv#Qmz8`Yr60nj{3ey=SCl?3D$TRN%5WDJt}+MIL^C5cmNU|3$x)%*vKqzRTFh|( zL%ok4;~YbbKI%92d38O+peaM9r5RbcDNBaSubc?+6wSKrcGvB@fxM za%A=t#qK9Ca&3T?)$H~p{8a6YocwE_epysfaycK6HDB7cCEClpty;z|BHf0?BCT_; z>LJ+(wlDjxbtw5~Dr{@|RC5~crSJ=9u7N9c%H){ip=)K|v1v0hmv4A_cRT5M&X&?0 zu9D?vJ%eD>_5Qp60k?4rfUQLaZd-@|>MfCn==a+gFhuunmTsF`=Tpd@1)p4Lc9CQ1hBgCrNx}Q|n^WDbgH2xhtXXR6hzl?n^{#2k}7_*n_ zyx`x8^uHC=%&_MCN^v)Yg9J00j4PVu9ltf-$@XXx`^^xg{81x`7(!!Nj~XxZWZLrx zTxCn2e05v%^*CiakjvslHszYg6z}})TwH384#VxtVaOIwN8&tZ1BIg}_x))2!Ry#W zgFk_trs@`Tgnz(CD&Z;np^k=L7mj_xg}=Ru7~h8m&p-GQTy2ha&O99&f{7v z^%?%cZOhQ>7#bh}^Hy=ho$Sy-&z#3Y{sCi5a36iV`Lj?}s!U5F8ZY{ou`@W2u(yLN z`CB1jZ^3s++sVuRlnNK)D$Qo30nyke@m_iut+ELaJ*V&1SEu#^uU&c|o5rJnu-A2i z(5mk043L2e&4Al9wd)q`*$a4(1~-uU6>n68<}bt}&muRFJB=O#O~S!?%;v|fL?Bk4 z-AsNiJb8D<tdAB$j38m_IqWgR81 zYi7a_RWK-aUC|4iuG4hZcQK3i@pBO5BfnCIOKd3FmGi`&Z)Yy^2O(eOeut3Sqy5w# zBY(cfKE&eQ$Xxb=y$W7}nA%_PtZp?UP`B2D{YSGT4xEbvv|;|FJX|4|ual*0jFZp$ zr2pWvCL(>X4Xk)#HoVUSthJiSH#5!Ro}<_Mk1^EP9)kqHKA}|o*6~xqW6!p;?y`>$ zYLmpW%;Y{s-f;;aLGr|+`lcJ`rAi#!a*(zzdqd6bF@D--E8v(QzGNaFns7X(Fbya1 zvePs}z)qy)=4ftCb&*RXku^ebsuN@cM)!W0&kN09e{U;+EzJFFo0OA%j2GYZAFHMU zTm37LKaBer44rbzhsi0f_9xf(?u&HTaU>(6imo%=!0#?ZTjlQHy~OVj!!z`scQl;cRB>*1KiPNK7MY+wb}BRtq-)H=RZep@m8@aq(S)D_ z)!IOwks66;=u^bHF|2MF=Lb93^Lj%7_ibVjfSkE_dYXFKF~>S-?ov2Eh+`6s=_Gy< z`)6(pI5es{?5o|Z@Q4;dR26Denai$VC7zQzGHaKCvZ|J|cY(YHKo9Q+IE})RtSA4? z@oTp_z03c;*#JqxCf+$swr_`SgVJw}Cx+e^ydRKQ{8Wzg=7*RNtTAsa#;MgJ{~$mj zbek#E(i4^#^6~wpU8Y{4^~NfSV$0-7R!21>k)2;a zB2(}C6KPY?o{+wectC00j{~>L76HI6tf#2bJN!DJ3jm4o%0XO|K+e=o^$34H%i|Ny zwdfi`uwuhf8Ibe)9&|Nl2YE+)ej`{cK=Kc&aM_rioOnG#C$X+7d{-YU%2MP6qheOZ%iiPb zJu|r(4{53*Z`@B-g_x`I3kL~V>Gglu>5y*|Z7~4CnjWvB)5f)BcNVIQIMlK3q$Gu{ zkCiy#rrwf?a~}bOGVJvR*%7@aZAl;G{7pj`cl<22&C|dad5~aKs`9$7%9prLb0?>H zB4D<^x39*3yZiF#+Fl)>UC);OGt;c0#YRQ&+?Ur0+^yw{AS+q?2J-%E`gvR|?)`d*Oj&0Gz_kOIE^1Re`V1ZPh`VDY|nwp6@5!u@YcU!mLddX|@tkUJW|U=W@Q%6ht&&L;II*pCxIPMi!r z^Tcq(EqN0ayS3x?xUqC31;3x+XTT3SNp6GjGhl9(?n7DVe$;D|7QTYnB}&w(GI&kb zn}Ta~z`AYv{TvCfv8-BrbmLTRqu9OtVrrRi>7+VL9#OZBF2b%`dLD4GiVkIDSjXl$ z+qTX1^h~rRmGN4~E}Ii*BE4^^f)wK`D3H&_`7h!l4yW&M=C1sw)uP0kq9M0pQ>Nzh zXPZo-Dii2R_r+XSj`v5(@;VmBRAqxkkJ2O^GrQ`vTf0V47fNoi=cI1A$52et2{^oT zx)hhE96uX$H+hO{BJp$!;>TK>pKI8uzXc5;wyg%7R*vyAI4IM=#^h98^lAp!jNcWA zmphPrVo{ho*v}xy=Xn)JKiesVlp^7j;}u`Ro2IK&Ma+37mfe3z>{j-#kjnhIzn)JJmT4_VlN9_b@#*qok z4sYPX)wR-$6Z{N6j@0Z8Mj+~?vz`EP&~e&7GMFKD*xe_iwzYx9Z_%L#ui60yBq>L+ zUy$dgP;3&AN`(gx(cENRFfxcpjDi1XRs_h>xs^*uo5Fd*!#T$yR=8mh;3s^q+avn4 z=-ug1&H1BjxH>P5FH^3fctqz}FKy2T<$9U{slm9KcRApCdfUA~g;sDc=2Wuun$a#W zD-CPAV1RBEYpKi+D zi*mA5dMQ0luqP^QBQP`q9AHmMwcmQh%~B3JvI+mb1#{fB^z2i@`fD&p8?dwSfelK` zy!oSub81i?o-S@ce0Orc6tyxV@VR}&nX>o$4Gv0i18{GKbP(1;`7|HxCL})&?ZjC@ z22n+ZT-5BrFzD#VO%tDF zW%>nZ(^BEnrS}${V<-G-&AW`q-1SX(G?PMxAKJl6FA$_%L(tHEh)v}PkOu`yE5x{FYSI7}kH_cCJUMGz z&Pci84=2<4dzvHuCm+t^I^x}Rk3D*^94}nNqfx{Xs?vTDOlJrfd|YGw71Q7{_h~#A zczd|RGFFw+szZ=sQ$|hj=W+6#Z71laOQ0|491^wUi6a4Pyrhl^Il`oE8hFi9@D0#n`VKzHKk z=ybi^RPIm-HgNE+4QME39<}*FT;soe5hCd(Q0numLScs9N#R}JYFK~wO(CS`pF%9E zrlQtHsxOgow&mtuMgNrd;ydk1dPM(-t|L{}Cay&yz(C<*uz=z|FC4r3DzvKs0oKd4VbcyW`Ig0Cacp8gehM_FN>C0O%w;NB5pV91V6Sb zZ}Lx7&+36+r!x0nM8~0s;E(Wsn{o0H!GtUbgP(#S4oEv62f1>X9=|ewD5zo86X74^ zDu^ngDudilpcvKcXz*L#^5>GK@T^> zg5YUYtWq5=lk{C1)HO;H_DLNztsXs@PP`Zk;))A_IMO0~1~#~~2=7_%kBO?C10vYN zF7!mS<&(=|J-su9nYymfUw)AYsZKq~PP4x7Kq5!b+zInyk|#+uMfqVKOensCUro-f z>3VV6F4~d}CK5#Za2ZLHsXfaP(fM(h&AMUfI%5N4!-9Yu+h^>3j-yJ;;2Rhu%CW&OuogN-c0p7t zrkDaX+5&6h*q<}1W=axAj*$zDcq_>&Yl!>@3b=iQ4Vc;6$6nYux@1j8cAX?CgAEN@#76q~oTt7x*^1memH=WF@b(ZEYhLT$E3mMEh9>=eprTayy)X|9COT4o{GI)p639$30IG1PPNc(X0h6`e8eb? z8ydVPk6&!HLD){af7SF!R_PIMeyDfW*Qh7m39f6P(VC#?-#NuKgeJ6nP%UWg)G3JV z{QHL;msG7ln|sHfMu|kLpq*GL%_*);mtM)Ih^rvNgvn@*ELeBR%*&pHeP)#7AKKpn zTD4tg(aJPsj#(zASZko1=L5yvY;MKevoT>^1m`s)he0pr zjwaVKnlH2JdOe=jcCA9Tg1r~LqE-ZJ4EBtCCsbVG0tLboP=@29DYuSIs)JI7>SkBO z1gVU9-@vTI5Z(Fop~bCBKpP;M{(&Peqr6I6(Ygz#Qj?QTBrh7=_=LlI`FtrU{Z$RU z%MjzF39nBbJ>&t58cYi=UP{7JGk%hW>Ie#ZH~w_kB1OiBHHjQ15q7qc1btH?^v_WR zwJT4Z)Z#^}p-Df3!UoF`nwbr<=REwda-sUB!|^G9y!d~lE%9JVUU|snJ92G*5c?)C zyz9c^&yOkjE@bgzx8;!f%YleP*ojFnO#h+|G)P``L)6wt7P9GLmGa&o{+i zbr%hak>MxK>KlVPeh&sW(LujAjikVAX)+8lt-KO{p4+E-xIAP?vs4_GkD=z(q=|$f zoj0MB@e%Xi^q49YMhO|Uq5F}F{0=lkH8t8)8t^0Bv? zgYQ^qX2f~2V^{S>ZJA7Sc@&0pia5q(`-hw^srD?8`MzC4U#OI$@Bc>`N8(Rs&=#zS z5fhe#DUBVxcPB4M#7x_s^ZU0`8|yA9Xu56y2K4wzLx$uPk|*30NvKG zq7r@u3Jnv%8AxBL2n+`WKam`es`r0Av!bE}Re=y+&RBN&{+(O3xBgn@wqL=pzy|sP~{=WB>`LtV?x~;@8OD-xrviAFBfhN#aN`LgL8tuo*od#Z|CF|{G#=vCpHeHWx0DarU`WST^{_n6IBCg16rCH4@zF#4i%MZDwH*RIF<3y=!T*{NT$`%UQCcVRWUpn zdZ#tmZ?=-&rl?TZ4#q3679Mq9H||?8$K^;Z{kvQtwf-H>){XDQ+_zI+((PjG?B<^5 zh6ajb3DN=i!jG>|*r!tBiBL5O+=?WmE)?{P-q~AC%bugO|DykL;Ztz&ewVGr*U*h; zKwO=R+iYoM_9G>sjbdltw?$*(LEkJ{;9AzjT#$VPM0w0`H_EJyo7m=I3@B`s6vByD z{y|fD<_nI9M>{!e-VhCRC7ONq-8UU&U!;k?-*CJMS8iKT@7OWs%~4kg!Kl`1Xd$ed z24e-ZoO_*d_&9eAHBemkK^TTg!bBUDPu?|3$j+9sj)!_GF;9H{D-_t zL8b6@A&#;0Z1N_k&xBxbF$=;!9yMI5)d2hjf{&9fO;0F_?XM&!0(m>C|JxRlQ_I*I zrzR&B-b!Iq4U_&g6H<_vJ|rmH<~3ArN{tD+=AJ-mTbR!1Rmt(HoHhzL;~C~0%Ksfn z2p+#Cne0@PF6=oW4P*tmRJ)F7@Mh$ef1K)61C*C6L^Kz{4_3gs{ELK!UeDApU)*_; z6S$^3@Kg?#(AX7j-1fA}rk(L#KlxaSTp&8DM_YlC6EL_yjh}#x=uOy$r$fc+`$6pP z9iGQ4sy~s4=ovAbU&uDqQ`MJ^!L5qhxF59afqgEL%IH~B84R1az|UkA>yAIe@1Rp# znv|q<>KNl}^WTVtloMx_jDEMxAh0X50Xc3N((ApG`>K~OWxwBZFXat8U;)X?_KXC% z6Pi=BX?rfP>J6#JCkHq&f>GUMC_C+;hp&GU_b%F3%nFOPztB%5SUzd96(b(lr*hB7 z7;Y_!b-yG5<5F9@ebFBoJVXW2b2tWWc}-Zc$-e6Ff?P@4I{e( z2^|(>BZ{;lWjN%Twd~l&3s%rfw7_3_aw(Yfu@?hY&>*xxnnk|B*H}I(Up|rhZp3Y; zcE>2smBjUS;8VEHD5m1IYJ2fQdTt2G@j9<8ERoHzhU65(>*%p&ScT{#{JFo#{M`LD zM<1(aMcA7Wk)2G0rr(;q{5DZ+_6-|L>SJ+h|0Jb9S6iBp9OgZ5q%<$rzfQ6L_E&ok zg()JsDJYmc<6qlbO4t22ya$NEn_QJU!^>aOX8yCu17_i#EDx_tnm+s+mfBX%$i{pW zPIQpw)<-U3R!LeHSPR!BiqUR?NPyL(LocgVdQNr#_R1);tKf+q!P|0`e` zyu?ikQJ|lfMrqe0cyb+Fq*tf=cBpI7edCPW^k@kW>35ji;SBnvL7{MG*KBr3eg?A;>rwUR1Ti!}tGr%#gO0iTydUSTYII$Pe9B0(NFxr= zrHTW1Dk3$1;WSUAYs1E+FL!DEcu-vwYX{hSNh_V~+QPx{Mo|8T`|!}jXHqpG8$B71 zxC=zK9jF#Gu_Vvl;l+lf>kGx~cvsVBy_;eoRQ(yGNT=c{D|6q5Cff?ao4WkY0Sh@F zPS&W-%j_(1ihM^ky-k@A{>n<}u2H zlg@xy*}qfr(TzJhHi0{Rq3i=HENLZUnHHf`yz7kS!{on+mOu!$gt-{WPI>Sb2RtI~ z3^x>G7R@nCBkV{53=4Wf=ExYFbd0RHyHG|gfv`J7+5fAv^B zSDQXD+YTSRFE?Zj?=>s-GZAeY(%s=`(p!K;M z{7_kIAS?Wrdqs}yzvA*92vn&CHUDixLeCL*Vrzu1HAT6e!r(voUnI3i--ov9D1(>t z@pNFiYH+xZ!JZ%0MUcn4wZM4`o=~|A{v|S+G%bgTeCcT}>9X63|27xMiA}btv3=Pt z;jz9f>|YpK+$SxU+g0lDx2W2+GEK!$a!*M)v{tZjDG?~skUOg+d-kP# zmRwp_TKV*1{BQ4--*&tug42F7L)gsU8z3ag0lmQGZHS}x~MWcZx=>XHt^l@2S z2aUa(hg!eK0>%I$H)tMP6YaMU6YGQ^FUTZfXJ5FBdTo>ZiG24~)$OAywXanV@hybB zNbs`m@IzB{3z=blEp4N55|zpJd#zr$N7b1OfgJtDa|+(ae%aOP{uFf}-|Z5^LqGmu$bTPF^=7a*F34}D8ldnnMdfgE)!11k zL+b>AqllDK>|Q#$AEQ}e=$)8Oh2ng$-6JbxDZ#<$_ePla5i8bB2xf+gH}P0-w$5Nr zuDL`X)k#mV1@V7u3ifEDQ25ltvCmdk9P`RYF|)Wr+V zo}Y?29UftdN6OVNVl!?5!znMnSHUG+ZBb+ZtNHzUN~)Pe)2tT!SqHWK>Fyxo=;u}* zHGa7>nr+-PO0^2A3=b7iL>NRi;|))dZXGBxHSypCTW%V9hvrO1FG-CiFnfwWMyl)m zs$FjunOT!_o)q&Eu@NgqKOgi8;ZQXKrm$`+CUW!&8I^qZKKiu*1?HgIn?CHfk4_-S zU-nzJi|0az3XZ_gg=d=%`%mhs4J71HBH@)`5EE$7?c&<22 z1ARD`f@j6Rw@!Oz;^>_|GPC0wF&Cu33Xl+LU(IDfEP@6Ns zo(yJhB>6m-I@`Zj`)Xl*!c!GWUkUU(_Lo0 z81+l;`I9K=vvkq4E820JtL{zO(r1h0AD>{-#C%s%Z?qxyO_T5*95CKJL!YMXQ3r-B8 zx!Ipw@iRk>Et_GJepQJ5+*_nBMynWj{edvKyv5y99?9xNMR&WaXR~Ck2v=pEYB^Cj zoo;9>a?j!z?5Yd(fUglN#rAim(a=gZT81zu)5^4W9pUK&f@c~pz>LUbENg}Sum+aw ze2y}zy;32OCyk7zKP|4)iljTLnk0~Cti?&%f-q#G9e1a|j?jk;NE}?@qLkC7lB1O8 z7phB6;iniCqU%D#l&*0ZbE8fg#DgdQ8hfZlI_w6^Cbwhw7EfWT+M7!{i^JL0J@?=) zUpEl4=D~A|j!~`Dp0ftdd~!(d!R65>t+}i}aFHsEJK*R<`{Wx>Efb)QQn=$TU5dGQ zjVnA6UPL269%g(DmT2Yj`+0Ha3FXX2Lnm4i;`)c1t2l$)e;l%bbK;L>^v4_epS+(r z`|UWD&STUM7aM`!mUp!`pcBX7*JLAY{@A7U4E5j>`Y3EuFV5mr+rAF2Cc%3!a_Y%{ zEDbQdsX#Ep|J;M9^lXCfsU^e&rhV4jENg@uX8XP1mYA83Vq6!&XCGSWM>EywyU&Mn zhkWX(Q8|*x_ug3uFC@Bi+5xKZp>Y4P+>)}#Zpxy-2f!WY8Nu4?HT?Wg@c=X)_icGj zPLx2cwjp_r9r@SFPOZG`?I{SAh_wcmT~>5*qa(S1bv)5GhHI+UM9Sa_sodEDYocCU zaI4aoLlG51OxHoW1nR$M5T{J00XyYA7^rg`L=rT#A^NBPc}VjyHPbasHNJ{_Y#Eql zcUlb?5RcAFM$dd-qoZO+6Q<>gmauAYs|&kH71UMTvw_Jl4L{C1E2H z43l%Q5HI{liQb)`Hi8xUV@L9*X8gEvuml-$2HfitKG38X4c*M1L}d@H{}LH8rPD^F zX1oC(I3KJs#PQ&Wj0}r32jl4d&XCCbx&bel1NE;i0%}t<#8d~ivr>Fm97+frE7(y~ zbbpXslPuW?hS^$^TpY%HS2@@N05&s#O5p3$Nv|pgV;&$t4$x0vCcmaff93fl8HqWa zzCe1DDbF>|lB6BYSd78r61VYpMUw0HteBedjJQZF1Ejzf|4`g_heOw{ddS|>TbOZt z%Co#|npLOJ+$1sP7@e?d{1;E^TJR=PDg&p3c-vVS1IS$d7Y1`a_evY;^*0^{sXN|P zF<0(R)100q2F#Nz25FR9%!V1|dJ)nYVoPhc{%j@5%Bli2OY>H?Zp~;4#;vL@R9Taat?VEsMBk zR)y+;K^{HjJG7ysE%0&?{~S=4Fj215gfYX3mgY>Y{{zo8+-jDyXzDm>66#SA_H8oL zfQ_Ck>R3L^nb(f7bX{n%U(Bi+t4WRVzrxmlq{0C>W#hD81+#xl3x9_y#W&F%V3q#v zD4`s&`%?1#my78(y6qGI+0)SPztPVN#QW&}BSe4aTVGjRAMQS(j?i;46_4j4xGo5= z=q@idj)HeGHrniLf0jkISm-ONKFlgQx5-tPV@zI{1PgtykR=RVsCyUP9zql{uQ+V- zdPL6&^AULa|FM6ZD&%U@(88S5s!zX+e6Y!VaLUgi6PPKL)oXTzh<_q*J4VUn+rFQemo2KSgYjqxV5ol;Z!AcV8UT!p@`GM}gO4u;~f?|L0l7-Yp*id}Zj^xR3$kN?-<($vj@YJIV(*yw7_0$WfE z**iQfSc|F)<$gfxmh5-4}&9I8V?hi%>HUC0d&Ocfp8dp=C%5V{a{=yg~@KK0e&EbD9M*FB638 z;J1$yGExX6Vj;iZ07fg+ONpS}g>^dbW`!P3^97+zn>Ho$xBfFzp%+EdgmjR;Y<-{B z`BR9UCqlp#7ToKJ)Z{;eY+x{_;x|3^sF6K6$cCB`Iuuo{yHha`-irpPT-W>`M^_mT z#TJEWK^jCra!Kj#2I&%z?(UY5junya4(aX&X;`|1C8WE%(>J_dFt9Om=gzt3d~t3R zZNVk6qU%FY7jeY`Uf``)Tx%JprtTNU$sAe`8x}XERv}*Yj_x*yBM9&HjwuPDZ0u5q zGc-b7m`ZLe;K==$DeArDBp6_bxI)2Wz#f6^e13#vC-2<9|LNVcCNWmSyDcl^)6cp3 zvZi_L^Sx^=3jqj2S?Eutd_@avt+Zmwu6ae@cYW=a zg~2AJCadoiFrzhAN~z!Zk^u7Mcbc+Qx!kX@nsxDkdsxH!++9RRF6?*KUZ zfC=I5#f>3@-YA9c+7$#3_v4bTQUDDsQDHZ!X^B`HeOVb7dB2WbH=YWdUHb>RUX_zCqzHoRTI2Lr@q9r zpD(i>c&BoIGDv^L0l1IV(CD~yYCpEe+otRMG6@*8>Kz+kgd!Sk#;a*b2<$VPB-f4& z5Q$;pX-J ze(EM1e<~#gzqaVs`?a}!jM+I)1EJMsl~=xNGl6E1@WX3vm70691f8I67!G+Rai*q{ z^a(DOSi67jE~)eyj4+B-Jejznppp_4=GbyJtpw&43?A{pLCSMNA%CwQyQ4o#5UJ!L zb=}LJWPnwcm{u?P$5onIc4SHAlHO_U59Ap4$cqFki?e&oBCxrE+11H4Nj9>Mm)ij~ zEnw48+oUlqK%C#sBNp)!>%~h>a?!=;`MI61I_sq@*NLxMxP%APog{gu?AY&Wj@^B3 zhz`u0MrsmziZ0*@pDgErbs@IyThr#=OsD9vZU1@g7X+KWaqV~BS^8D;y5oR5htc1b zBj2XfzR0O`%tR&Z(d zHO*cQu*t!fLelk_nU(yA`6MplFG4nb^Xm?i+qe0Rdq#y8!V#cZw=|7ncu!TyC}C|K z#_C+2?tRoEc;zTM{Q3FxUqx@u^#BBaY6ZcWRmSOAGZ$GZM0GGwSC3sH)o|goD!flDBCt1^s$(MuR@g`@njEo)vw@X3|`yM zmGJ3Nj@ytyEiqFiCUq6KQ{iY*>b^Lw?RAGuu_);%H6m~P1nkp8J>S?-inA|hMmH64R-+UqeDhIDTds+Aag&>E>8~oo3~YI=RdJ&+hcURJ zK*JMn!M-px$LM2BSnRC6Ue2l(=YoizY0e0omtjyAXsq!5?KF6!Z4%y>yK*s6l41iaC*73 z$p|ZlM3FhI3OxGn_a=EhNI-l4KE#Pus+K1!Tph|gZ2_Zw;zuA+4tzz#u{;2gr?SR9 zmqkN)RTNUDlV=LLhnC)&rwo*s^yo<)*?zxkN~s2;JnBU1P=leqC=e2A@GRZg1?1?PyCwnkpGT*Irw$Csx~qbt-lc2GGL zRM~urub@i=?q7fUxZ{otDS_#8BM76wxqVPZ#dntJ}3I zL#cQuJ-K{03yfJ;ke|)b!}8ywur4X)Te8|E??-Ins3NYt3sZ7lOM740wE@3A!+&b~ z0*|=Fw;~l{9-F`G4{)DR0#XvioP;Zeui9$0E?-o_g@yt|68a621MCUGyQwC>#&~1J zJc~p?>tB#SdHyqnWE|F*x=XR@{EHiD;S6Gs;{tA(R(1{b@Rl)7j(6;o+8_~#wg7!P zdXu#m7Ny;U9?sx_veQ*!$eC$GBs1#Q(<4S!|{v!DfYo z?CT`dT(#16^nS?gI(tDFh$-Ttvfy!VqhLO2h-AdBe)qe~(zFWw4Z`ddZI{Yjy0 z(^!V(z`d=cexjO{ey{J1GxctB!sQ-J*fbMcNyEsgtZ(n8FWbAf;0OpyhFthGOxTf)2cM&4wbDx1406 zF}(wZ7kQXfm}_mg{_4P@e|7@{_0`ajFL`%o2Gh;WC9ntsP0F^D(@*odnarpeB;*rFadODJ&8(8pNN#Gd4Lpi-uq>4Q_dAz+ z1%=w19qa>d^^j9@LWd7BR>XtgoA#N%s%M436Rr$ZqenbIiy-?~#eRJ!6w4D_*eTg% z-&*j!C&ez)K^-d460(B^7jG-*tMaQ`)PPx`()sezU63bcZPfjH5YSjEJPc6^gNpOy zgAJU$OXL%dLA65cFBT-6uT7~IA!*(e>patcdMprJZATX=&dl*X13MC4+C(s7&$Gt- z`q3Up@L=-O&y!rt=d*b8C^Kt;RL>qx&n-L(O1wOBCk7SOC=2Kd29;0 z1Thu5F@kC>*>5&j^48di7b;)ml)em01Knc1=;>yK!JHwC6*>7*1g@!Z{8}cEhhJBs zg9_+o=^%xg@ws|&lCHE5zx`_qAvG?rdt&8f=U0+}6K}9_)bwAt6)wuk8Rf;~g@i&I zxPajQ9xa#m#JVzcB)nvHX!Kq>hp)FQ+C-tHD@+VQC{%4@KOD{wog%bN9L!w)!WSEZ zL-E8OI%7P%X31F(JIQ^bwwRaw^JaQ#q7E{Yq;GH-b05dBaq$`za%P!3Y4N7Z+gmdH zQO5`oUfwGkzAGmFu?RmPrhVCm;4nb=ao&@~qv6OJ@x^AKxfZB#f@$g2~p z!%!dG#+oUH1U6LfXoW{>UreUny1^uJEyObvd>lIQdDS$K1mDltQq~de$?(sxyf3SX zbbZ6OL1X4Uzg($AT1gKyBiHv+J^nTSGxpq>)a@JyVg3dAt;6&{7c%t%IQS_yvF+wfu!#ce5b(Z6hVjY>5L4! zaZ>@#Ucf>n#)@{Je(DdQb0Mg5puP*iifGhD(GS6j6JC-FFm|9uBNY!owxj;6hRz>= zhmm)xA-;|k#Ad=^+ztFNW-x|giT4~;fHy#3Ftsj9TL>2UtR1!BP~!RY+)((kZ#hn|e|XNw5B@anZ&N58VG(-oT8`h+^0YQN!+IB7>I^&= zWF)}qiXKvmaz`f(NXKL)P=5NbH2-093}5^9)g#G!ILG17&Gr@H4`+(tv-!_i)FKSW zwM@aEC%-^XwZBife4NNzjU#B0KsHU4F6afsBX>q0r6m-sOLGnK&wv%ICBjpz#zk8D zp1KS;QXf4q{60k&7AumlfsT8EHF(jgYx!NE{yP5+aG&XSbWrC%J=<8niZ-fVMH?|W z7aNR|$}26;J|DaH(Iw;KLvVm)gDY^hN&~pJpUh*b6B`ILQFGa4K3Y;LMs!LaqKK>t zV};c_1b)-dccTfv^E%Dd0Z@f>li&FL=PMJ`dN>mdz_K)O$|E7QIZGK`AsB1ulr+A^LE&j4yn(Zj#VPhhhP(T z@~Dd){~M}VaGtK74?6HsLyv~_WHk0gT0b$KYI;*|ss5q{`H3dp!&(Vblpk?jsEOyd zNOpBs)72`aM*mN_^r;hUdF<&zAa;v*ZU78F(+_OohHU7sH^H7F07s^)x>JrOo@vPi z?1wH?GV-Q3cV#lh&6>rHEw2@!5=uP?8HsCUtj{vjhf_@s*tHPg$E4&{&4T{&#$u+& z-7`%5X)^UEqCN^-J?JH?hBqmBV&(D8IgkYRhopW1Ap8AR7+Ps)vA||aAjU(P8MJrv zq7m5NiyUPMoPwp-lf#y6rz5tOPz22R!)&W(Vt7IoVXE$-$t5dX-yaNc(>#(dXI?J6 z@h+=)&pHP9xfgk(4Fi0e1qJqIY(9Y8V}Nmckx~A+lV^O8l4%~3xHBaXo4LeN%~tQO z8?l3IlJBmsa&a7g9!{B5l4|Qz9VQ=m-<;>He zTmK0M*Z1H6jzUW*CLCzRPQ$~BQyRW}=2%8<&V6$=# z-)ZSuMry73utHT$)Kea1Q+tk1UFmETSrdwL_%+?es4h>POIHJW0vE)wcMf0I@PreH zi>Sh*zTaHB2-xMCw4h_L>K-KlX2~^rS*j}ng2E<#4dt~zLgKe@DweKmU9t(3oD}>u zByv*$Dx!y%T>tyqaS!zhFFMUL7pB*FI=w#i)?gq2S{fwOivk&P0Q>dILeFDM-2_c| z=g#BS^#-VW>G)%^EG=xgD2L>W3C3&mJem1(hlzMrKZXIr+~*o*((dwGBm|dSn1y<2 zI3O~urZB@}V+cp^8lf0# z)*$&Oslk_Shb7i3hvFWW2_^vdm}Ms#&(nVMy=NNKISN8dPA6~|XPosIio zPbr#jM|owOf0C5%zKAUI;7J6F(qRu?l){0T`bK2@(bOIqx6>y>>ts=ND0?U?1a3-T zO|H4I#u{nF?l22{)Gnh?@+Yc-I*k7g)Ce(I{zkOUTgOjY1!Yn2g0CP|%eVXu_9r-` zRkY9KR>N%qy(bkR8GH9sZvkj*1$pA$RLsUn+7XGc4dG+7K1prHq`qhGCDAdoH;}JD zWhyPHs<9ept%lUDTLxlE4fk*AjQmA(ZyNlO_2u&QiY1frnk<~vi8iPpSc=-SuZI@YYpq48APAWiZWI@6iwlr`9^&*d zUr4hasLMm{*^?mXdhju4dzt$&>F}=G=^B(DMM3rTKms|Mf(q?af`C1&8Q6zm#Aykq zDgQ3Wm)Swq86uxDUihN3jFB>-^@n5CP)2K3q1P0~4-kf+qGSW_`>HFG!WI_8Y6mht z|0v$m{2knocXy#;%>k8V>>L89-DyP4_l{qw%eszO{Eu`$zXKkF@%6T8T|2{bkv0#5r66(=-(AU1Po2gCC zORC^bn=JMq3#vUO$piGszQ{!jH2%5~T)xPW(zrO>w;(~jw3zBD%$$BJ@t$*GFpm^& z-y{ZDUhnF9nC4X0;93x2@$zl;It^)>jY!o@D}muR52313>dFhqSBe>b1KN~g!>es(P8F(0Jejf6SO(%`E-yLBGKig(U014O3l!}_gQu`prUZoSQzYW6{ zcN@i|HK*8ZdQ0pqX!;6~vSRYy?0eU&)s6Q>Ny*^Q+dzM5-04Qn=RHng<$ zLQ8Yl+Db-_xXW0xy7{f+X9j$V(}pV?v7<1{?o#%v&i5f>E#>O>Qt|{Kyy{{PSu0-A zQ(Kku5?&h04toaRk}i8wgY=&ES1fW8_zWvQ@&&$?6g+KYu18kK_yaLLiO zuP{IKRV<>YrP+GQW57#oxQh?4<)8R5*;IC;tOfNKpW%2#g1(?zB`j&Mxly~aY+NCt z=PF?szbX1>aVH#N_=lWyL5UZ#-;s9y*S#l(4GeZ)M45)f(9cfjjgvqlgFxU!)4QM^ zzVYb9f9#e=UqZKszt$Mjn}yW*Sjd-GYs9!zKa~}Y-Y2!;FPt9}1m)?VqI(g*Z*d@; zMpARX2r+T~Ml=dQ+=x8}BQYgFk+gCC+SAsPjT~@0F7TkcdF+DDd8r=#~E8t1}5y~p2%jkN9^ZBNOMaclVI)x+2gXrP2bxl{Y>3xD6 z^=zt>!`I;CwgXNJ$U0<`GKzHIf@8A+G%GB%+@^6Q1A8MMsR8j*9 z*35+%Lb<+nh<6DqF?Bww0(nd%1RKCpEpsy<38=gS*u+)!lV)3*u|6J6M#QkW&+a`x z^c)e*d>S)9^F}QXk6rWiQvf2bR6QnL1kYWnKIF?g@@)EWbRK z9aR(Op>EU#$FPFRXNBTre^QodBOBwmJ(D$^FFBsgSs=$O15I#ML93g>BbLpZV?Euu z51VC?uv!<^fS3%C*hKU@+-MSvEm;pH<0e{v#gNNl%D%n+0?q88ZwNlj?_9mLMBpLO z`Hrw`A3|xBIX4*v77rpt+o%9Ar7=`llFMw{oOMJPM?yd>u);t^%Es*S(&qf*DGC3} z92t*M#yL(O>f3AIZ{yCWl3# z22^{$IWBVllhr8oVIJWjKX&0e9Gu3l6r)TLE9E|ME!S$UXS*pA*WVq}4=zmGud5}Y z)1MVx3*Q9h=m2ST^7jkGAY!B9-;EueF<8fcLu^odk9ZAaCKpYAYv?eZnSwx5(c&#s zA)5vGoKzOZ%{SJL0>!@!c|!B2z{*+;*Z@Oe)kF3jobMrx3u7EblV7t#$=OgxV00CG zUgmeLdL$1k9QBv{+7X^y+qLmc9Lv%BW;eL**vBAZ-E@E&5fltu+j|K@T8{n!_(c9H z#DrJll8UdR9+;K0_349pz9u zW<-EtQg;pN|BHV+`4i!x{bLlIfB~u<8M0?h|3gUb*q@9AQJ^3Z9b?%LAQ<{MM&u+( z>W@Y}>(S7|4by6i)7f^j#}>HQNsd>)BJp_M9C6i*eV-R?R0jPre5JPaT;DK&cpx?O zXnXvA!I;iTUn1+n8DhJ|NpG~^PgPqjI#z}0jFK)^`&;M0H+jTw>jxq|44A5rKx`-rFdPkf$wxM$joP?=;WfgtitUStwQ13u=_I&^ z6$TZG%m}5F0&%*&Z6yH+3j*cgT>Vysg?x2^segf(AD!E;MQobz{a!WX7B%Rk8>a#g zRX^gt+cmEBAsJl~WyOIg9rA|LujnYcdOek_Fg7hv;cGGM*1&g=^ZJr@F2-LVzuo5@UV|3b3JGL@}SWtQX%bI|f(GwaE{Z zi}roZTk@(*)0ju<62AUElcdp=0nCK36^L=Muu*CS20Yk349NK>LcW)ih^6f%O)GUv%)}^j(K+VaWt% z@o>KxU_HJgJJv=p=!naOu4Tz!0r^{W3VFwVQM;%9v~#r z5XeG{)8{LI?3+6EIsE(%qo>0v^@p=?@;!LwsuUr6WOKma5V1`o1l%R4?hkq2;aYqe&1^RAP48+}{@-Dan%iOSegcxJPSAuk$s~Z z(I|kdNXuaj*|Gu_?uhdiYG$pDWBED6`|L9;VKWEGCz|x3dI3hPXAi8Wj1_a)wANsl z(0^#4t>5_|LeUaQ=l$`0rX=2p1o_&5nu)X$z02J@D_ayFxW|g0I>zh)!=6Suo{$p(Rg zXT3Mz2dClJXD|vM6YF=h*Ohq9d=*lS>8-uIu%mg2h?}iIu}|a${iX zuSE;|KCj)f$@JTJ*bK@F=ef_gR=ayeI_{#kh|Z}%j<(06&4gb0Ich9wKOV)4K%znf zTASy|J^(aw-)B(+tXbmsTUNxEDoA>uO&5=z?x88X@g}rAhsbpFm#^)|P3BmByDkx` z&ZCCPI~7+Wf7~WKQD#(~4~sScZ!cbUDJra=q+;Sz=rwz?Plmc{NTBmQC zcyi#_bx{mwp9$ee2IqGGBGED#t64Z7eHXMDl~kj(WB&TmDK9zBB<+GWMG!BJuFYhy z79AUnA_&Ih39Dzb{F=B-g%ix`@m8$-3^%QD<}<3OVGzHVcOW*tE(qX+!B8X>q{4cP|vy-`H2XWMS$@9|yWyoIznnTAUx2+K;<7u%ME zzbWn%t7}%)PnYsdKXobDX7;-iXXBjusvJq5slW5($vaKj6EO$}N`>DRHlMkm<;4cLA#mflOdS{10}E1J zFs`*Jb>|dC8}~Oy|Ci(--pQ{@Y#)35B5UB&ycWL5dJP4fbQWBuJh6W_rx*KjM6R&) zcF$D)!HgC*#F92==SvW;woJ;h>NNv!t--j+P0G|%Tv?(4=UWKk?Ij4JpWJcYv!%mw zPvx>0OUgs12N&M~Up(716N6?HgT7If31*5A8AZ}=We>rh-;mqA@S4_l;OVF#ttqCc zXedd%(9xAE2oO%Z^~Yen=1&Kb^U1F^Gwo4qMruAEpKp(NHSxb)80}g@m>R`^bm?X1 zN&`>F@td}ax?5Ad=$@pe&5xwJS^luG7s~W!Xoet?W_+}R(d3hCnxacQ21ewz zN<6PmOvRiJ0M9gzfyVnM$&&a!Egp@cNCs%1$E;ulD`A)R>|XiIM^}0=Oet|*OL;A8 z>7o*ZW!r~oN)o4WAj_Hbr|&*L8v&ZCyu|UD7U2+2xPs`-LGKl)VK#uCEkt@@u8rUy zBghPeI5=4hly;eN0iG2RXE!4sw$7|L_!F=(l&A@E*n6VmWJlAd$7FzhzjoP)FS!g` z$KcZnc*ar$j?!}{R*CQXW%5@Xr6uH8)7g>QP$2f}rO7$@TmTm6XhbNWil9=U6<*vvpmkmg$UhC~BO0df*w5bo1UPYHA=C0=i_sN@kJ(ZIcjXb)iIKInY3JVv z*BkfM3zuF)!{R0&;QiCuS@^n)6t$k-nl=FGFL)oUMX>$!!A7;ER@Vdw0(=t@7EA|) zZ}fAj_bsM3CT#Ah;i463_qsomb43tB0o_%7hSKD8;{Ca01F$ZfD$?@0GuVzNOeo%D zj3?(>Y7D>zc2A>VjSM6ISityECdSA>=`*%Z2_@%7qj(zJKP@F(#h{2tRSKBb20F%u zc52Ai7Hfs-4x{)xpWNG^&~1ZTfVV4-plA|2i#LGXx507yU~u#>3f?pdMSI5QXFPOF zSgm40-(eI(S@h`<6c1LT5~R@eZ7^6fVHm%RkYfbJvJjU%DFK(%MAXmC)Ru3(lF(=S zS){6%BZ0D~xGr_lDdgzcJsCI4S5ksKpaTk0O2XA~X*F~^_uyN9*5vd-S<3>ayJKf? zAfuprV6S9|4NLlG@0!sR4%|>>1q9!A{=T+MWZe{ZFE`3g+?++UAhv2;AhL2(uGeXPa*$Se5hd3|#1%ZF25ZPM zkq3podl|6(V_8{PHGI~<)@$)`(Pta+$;!S=X9yE|kJE+u$9(ev-_WLO7xiu%dagE0 z!d)=6aB#o}u7jrQW8aw|b?-aFTT)*?5rX@O$;KBBc#o>zeQhrE)qX47UWl#pb_F^e z%&Q6TRz}NcS&RSr{~AVAMa$34NgLq@8mM2#8uk*@hks@dj$yUIH~xnfl+qmj`BI$= z^f+QMv#Q9;6-@pch&-L8QpVt(Us*QE|>|9|7q|3rz&lOhO^X6_rhtbQ0%8mT!YBT_UH~ zNQ>+o8I2v4cr@_5pCy)mh>#NsshKb2WPzR*_%kxs=02ox2q8b|yb@6Tsp@30kLvDK z#}+sl0FeyWAri-@=GNUoK0Ex8E6Prp=UJ;PahOGvGh9j_J67`>V1>Supr3K25sL=v zmC!KHur9ktWDX5zi*YZcevsbXdr`sslI|56-VEgW2JP6KPAK$?RO&pd-Ae~Bz% z0G)i-#gC4){SB<5aHovE`IR)shX!^-k8~XsNw3s+=0yDN8%+t(&1H(j>RtcsfhM&4 zYr-wsa{$|G^GXxM3av$hvoCb1s@5`wxxaEo%Om+?m!uPvu1lSQP4Uk|k43Pc8q zP1O3JeC`w>UfGFisS>eQ>Q_?fr1Np@G2fgQy1grNZ&=Z(t|@o&ZdlnP3CfXJWgkWGFkpBc_xrmzB5WLk@J z`SQ-8+NQsXo>}rPs#IGiG*1HIUzR&w(n6$QGHPx5?F{}dbElgj&$^2X6h3JXRN2$c zWR6Y2V2;tKs~r;t9yTu6!F@Wx5~ms2n*PUAbrHcjWYEvSHO%pDdm$b>#WI^|&!(LpOeZGE{=2OR4F6nnLqd&Zc$#?+Bjlba3zpLMZaaG`r4 zTbjE>f3f|Y%o+*hFQZ@Ev#Siqrk0vm2Dr2HWSNxCbSGzSvC(02#?80QhEhekyLy^g zUvIKj%XR0ykbU@!h^R`5BmaC8X+2%WF%hFoqfX_^}Kg+;_OfaGzwB1fT@*1Y=* zRNDL#AYQww5y!EKIKIsSsi+?YyW}bCvMnwcuu;1PyMrl|?5=gAPpoO*R4tN5MwO;U zr`a#hGK$wBot0>sRy@FPu1*+F2+^_uaLu&A9FP+P>AMkLrkW&?m?#8PhfGiN>5rbJ zW-tTow*~sbmcj5DmDNPj9=PSM=BGsDJ`!_I5 zZ6#jUf)IM@f&0=M0LvBW?}2NOD$i>31?%r9H9?aGmT-#vTzy^AF&yzb%8BlO)fj+_ z%?t*SOC4D>@XG{=T9s(&Zo0hF!&rtDzc+IU(ghlk<(Dz=eH+U1jtji?6n#hFRk}P( zpC?NW9&SXX_O-XaW>ICO(@3&7EZM-XREH<)%q}@4b0Vcgx%Yhu8T5(7_-d*JMdOh- z@M=&=Vd*vvpyQ49@uIilXvKY(g!^bZk+0oJum&(nqYs_$P^ICz-AP70;6PPGmKFZC zul2Jkb_wRt0&&1hps?Ce0@T z)~?tY6IM{i!$g}$9KGoQKqiy;0eZW+o+e#y$=!FV=h$X6XZ+$ z(VlQq*|4r80H@jGd&$e)axPd(|7f$W+t_6|JD0e~7{%~xqWw^`BPrjhm1yw((Di-Y z)<2cyLxtOdL7uLx>!>^Rkk|yj%)m%ZMp(ECq| zc=i3`TK%x5uW9KJeje+eK!BYBh-@UY~ z(mbo(^HeQ*j?PREw~YfJBtP*-|7!ARsmYlIFb5kzK)YWtlUN$0!^bTkoT}_pZdV|N zX=dVC0mPYzdxS2PKXSpOXePh=M$(i6Ov!fbD-%uYOy{5W7;kmC9}$0OrAgmaK)LFc zWct~LaEsQ5BO8my^@+St zO(8J}58;-mRFhO&9vv5C!Jjmp?d+w>)ZlR1zi-{}Ns-L>j>y@zl?}GXGlZoCF;-nH z1#)LN%l?)gxo8)cOk~Wm??Q)yA-FmNnqEMN%Yp1~$Tfr{wM66?_vcVibwIw@X#dgX z)jUqg#wZ$5M(#84dk12uQvL_j|6vL7P%z!bsdM(v%&xv)1#lO-S_9TbVf`wuof}DH zQFFuP5x^^>PP}V?B z7*uHKNmpI`x~NhUuy(hNj{eg?nKwwp7EtGF>V7>ye-xpvGQ`JP<9!T45(@QeaJ6&S zGY|zz2DSK+fxreJqbaUoy+KxN=Sej7t4ahGSEogBxW3Z2;_Sd;OASP_=-(wdpa8WG zBE?TL=^wVNb(tt#;nzF9=bvEnn11s6d=H{71v(>LD5}3nJioq&q)(;Ec`cW5R{^SA zM~+*D;eu>!t^NWLKehW&)iJAW+Il?#4}t~3;F$55f3xhr3Bj|dD8QIv`EVTAG8W?E z=XxJE=Z$Bvozx(?LgWbso9`PWfjhI6KHR@m2=Q1(!6jJfYy_l=>+RnWLZ9)#gp6id z_M0Y%-R-RW1-gU815gb`3+f`;84ZR@#f&UfUB)rWBd^P}#CuSPa)o`yI3>b+Db1Z# zRwFO_Ja_z_uJ8F_k3_D;e=PMoI+}qA#-+<(y`(<&<+_ZV3CgB48y05h-yiD81F-P3`8feK&%ABWh>7X7EOvL&wJ zoW>$~w!y%a@e{7Dv3_O6t1!4EQVMz-mgI|8@sm=El_&8(wKU$L{C zuYZi=V^K*PB!6L%`^4I#n8r~`<-VL?NMWS?Y0_8hsG|f>`SXV(M-}Oe1b#HL$Qu}I z;8}>R4TUjYmarO!@Vnvm33($|IXzq`nrtwOr_UbvaCYjbJ})CQ;NM!?s#B_!%hs9I zlSX5ca{Jt-Z+`e(eC_ro3l$DLp>?v$GvM!^kMBz0QCGZAiDsd*-;0lgEydx}GiJlZ z9(zu^WS21x66_4sO4LS6ajpZTG+Lt(X8zs~d9ASs3kI=tZCN@iv4HCMea&S%VstD6 z!%v|H+5__Q6Kl9U{Ujx1mNd@#{e&#*(iYdpin)c+X9A|ODoi(6FBW$mJk(E)nCqF6 z>c0~(*L6BKqEkSfBjF>nDA1XwiAV*UlMa!EO#_;zc8}44`A_HH zj>Be??o3mkUwjY|BaMvm!}0r8#z`|aGTbNk5g^`Mgy+TItvXn{OTqxi*RG>%$vdm| zl(k>n7tAW-hgnVt%Z~Q$l3ficYgY4sRPQ~zBAM3`pyCys=tmf+v*+C7V^&7EZyH~u zU^QdwKDQ=9Z(SXY{MD47%}_Cbv2C3vcQ?m`a>#)^f-k-3nF9L{l3wCUWFElF0bJ^p zRo;Phf5q#18PYFEV`oUbtU@@vbm90NSQt{e_CZbJXbTc4Q&Pc8a_#ElIQWfIK$ibi z5y1U48e2Z(=L=fmZYsB{1Fbt6n^dyY8%&-G_iu9A?5ouo6p+rAD=wz=I!91_Jj#~F z^vct&@vKu$@o{k|L7Jues3w2yZ46)365|~n*p9gyIQ}`9%*O)`cn;^6*^OzyF*e&e zhZnUrTmd}GyZ8XFi$&?c!1TVF@u%W;;j%^Rad89qi&?J$bMHh`>2xn;Mu$_`T}$Yh zJrTMRj5Go{WD8q~!v|t-VokaZw4@X>)t94I`<3^BP)lWZ-H}E`_;`MvG@LQLH_|7{lR?a3aQ)C70un@ z4N&|@CqZVZni^N0gJP#0b<8f>N*vipo3tCL*Lwu8C!@*A3nB5!e) z!-UM zbJaIY8CV-T8whbnn^5JnZ^5#g>u;d7ArVCATN@BqeY&(<&gxG<&4e$D$5_X=I6k9~ ze~zV!+QGQ;--eRLd|ujv4dH_aSLOF03z`nf^h@%9%$yOhYF*hDc@>bAW<(bizWD-w zZ2$O~t4qbh%8MVe5({`v7FEM~uaQ(a%v~kPbXy8POf?E{7Oifgo3--8E}jgsU^iED zw)U*J|M);4^fH6xz7lIl@%dRkDDPKhVMma;Yy;VIJNTcEtPFoc za>|Zok{`WPU0r}vl&gPhZ#5dN;A4TF>Hx5p?Bdw6rpThaT$`{*DdnZG$E#4|LO$pu zUhR7a`{pr=thHk;4mHean9VNx_ zxY;GyWW?GID&Al*qp?gNnQiqOs=>285!42;emWrhRPyEGk_9CyeN`jSMc_oC|P1bT-}$m2PWNKMYI1W4yo; zHd(4V;l%Jn_U@z-1>oI3DMLISVQIqRYsbxy7N+2s5isrPYu_)wd-m46NrUA!PP3eZs4}L9m3wW?2>_Mhmiyy9J2rN&C>xZIrld!+cynM2F0!{(o ze>%+7-;296tc+hFwpWHO{BO@G~ph_2uHPdZ2{AbeC)srp#)+`uzl}0{L@^DJn6yrYIRw^ z+(roPyunf8fK2kEKyR@N8KZAFcmE&FIDY3Qz4Is>j=s37U&@jDO(&G09`8;L_(N)< ztKEUO$NGXdM^I2EPAH%1Gh)sTgnL@Hr?QTi3sc`sbiQ0a9eSc5U1qCE3m#Al_GtZa z19+({KWPB=MJ!GECl&r}`mM?Cx9KM{nrA`PbZ=}I#|7S65pmRy-CIh(cl&jx8{#LEfK{g_KhB<9!~(P`T~Q@ z0^1M7BUSgK&Y)vnTf{}@^S6zgAGF#3$@HudMC!msn~^>qhyn=#0h#;=-dTc2X?cKU zCvGR4pFg1Gzg*OmzRFb6x{nI^2dkw9pL_bX2h#i%pb8tcbSjH)`_AKy@1zO+?a=}1 zX5Bjkvj*+}W4x;T^d~=-MZjmmWQXO1vr_>8L&zwO=Pag!mCZ{pb(0VHys3})*sAnZ zpf)PmX{0S|%m0@&#NsBU8Q%-{oZ#i(a2xt*_QJ!2-IraFIeE#u<*gg_?BiXm4T;39S*RrHeI{e@Z;5)y z@^uG#T_jINo>$Fa1K_sbDSc7$^D@woBjEgTg~{dtd2=O_NPgTCMUBwUU~0k?zAtJv zspdD?VeyNfP?5jNo$lt@X4{bHBrq8{mxbTWE9pXsZKs#hvPeHoEdvjNf5m6Z*4T1Z z_hrD79AHY_UGu1q4p_tNJ$C1hnr*3_n|x#XlU6g&I)%Uw3@BKDw2YRp`p_ZI2zh-y z@rivzn(?n@N8o|h&tD}+3Vc%rEU>)1aGTY9q~dD;u)Y|CNXJ{VE|uz*@1V2r($ zDRB9Lb>gL5vo%@%l&D^m;!+)Rh~9+RYrpwFNMF;YP7bMQdv#hE$^wNAac3J)*vK+K zFW-v{Z}_*w&5-M4bMg8$)vzR2JD6X2N?Uf7v_%3FE-vw%A^LuajSq?Op}k72f157Q z21Bny0C+Sj6RB<={gT5nv}A`Dh&U!hPTy-2g8%(4`kVXp2GJXNg7xXNEi%{}xky9R zuBr$qV1v3fPomPhIv%oI;+x&MXhc23wcR@3Yyh1tNyATkqk+Y`-v6|;&VVT~)wa+= zQX!)Lx~^0ey;EBI>z&Z+z*bW63cX-h4C2QANF(r523(Jga>r2-%|*cF=xXTW!#|d+ zZT83ZepxnC!Mw*kSIe2&}>k=`ifIDkoxXjWgUFn=GOW~nnR0ky(t9Q z7wj1+%hg4IC;a?1TBQxOyFIK48N&X9e%FL!Vb5o9-WSScc|Vd8>Vbk(Nzs@7actA0 zY3Sln|G1q-YC(x-gM8Gx9)BptYulUaG~RmQpSQvs{Za zD^AbZqlJB(A(_HebGt=#B0~mYq)F15%B{Ki<$X0vD7*FPR9SBJTq~(R=jQEU62bXH z&|nj18-*z1a+`Vyi2knKHjzFrNNvu-XSqSnhy$?kdcjkx>5E0QRuwA*ywzAi?zVj} zMGkK*ZK^)u0~T0UJTXk5*-z6mc62hwzk8A4q=UC6oZ+cZNngEkoBj4ekr1{Ld6T|$ zhllfM4f@pxlIa4Q&)j%uZOlchZoJD?BP}sSyUjiJdDDM-Z?}_?ms--yq`mL5UX6~G zG*n0wB%_~+rUBww{&puBSv0!J3$61Mpf*mR2+#cC#xuSl15rX{d4|$us!9}Nj2L=*O8Gg#)jg5vUY|HLnbtPbkp{tr@2dFr1>mPzh&)>K>t!Dud ztZZ&jt@4%&u*6-p@&Me=$Oky$Xs4AmZ(v?yRDrstBF^8MuiV-qd;NaIUr9HlI7|QJ zo2*hKH{(Bxg(F~c(2nU*7yP#41WtPQHZK;7;Y2+aE56l*sxQnN;1HK;lGe2P>@?)L zqst@vzm&JleO)~NqXW0bJJ>@{rE&Au_Np|->pG_IMHGYnL+0DZT_O_LX=at~d-lH6RRRl70LpBL9tndNT&#hpSY}GUdu>32irg zfhnClivyh6hVL*!f&QA+bD(OQ@-mQbx6NW-8DVLj01dUy=lO$7Z{DPhKB!x?w?(bZ zcPseEE7Z+m;|OdtJtpYmyTK9{35W9athE*{Mj0O>2W%E%;?*&^0YH?Uo-}c2ZRyFG z4&Vf@F22`<3K@dVdijG+xZ5k0Qgm<4z6Y2Jb+esGs28%AxU^r_#GNMPl4>i%5X%eC z{CWd#P(^4%V!JayoqThcXZ(psWJ}lNc5we_7PCqzx*tG_w$Vgn7b z0xYteSGYW2V$FB_vMvFwxa^*GboPNBoxyG1{?q)9ld zku1gc$zOMXQERX@z##6-W{vtOwUqv)J{yLuh0gdu`ojsrXAAW=?3b0YEaCFXhss+1 zc!uiJN*duIg;vMO5gUZj@sV013d+e?s=KHZ3g_r z$D+%+9RF!aNWgH|1vImUe!kuO=&Rb>eE{G5h=OS_R^c506AG`0LYL8Yu|jpM4Hwr} z2lzzZlM4>{Xe^h#r)P2Y+HHqS!mQt;_sKW$l))LSiU!CCih3sVC9K;1b_qBeM^eRA zz{j;KHzr<^*sESYKyVcci0NKaEJcp^(`MI;DNQz65AX5 z4OylIx&cTCM~%Bh{v-rf66N~>3uHFO^!e>;x|tun`4{X@Wz5~%*^CKXQ#Cj-#W!1p zBY09oV~=ap>ckhq@CKPO?>qC35A)R(x~3%*z`)p%Tyya4L;K4=K4Y-n3l^-RFjros z0eB5vp<(Hoe_t>D5$LJ+%5d2dINSd?y2_|Hnk5=sJ`!wkcXxMpcL>4VA;CR3i@UqK zOK=vKAR$PCLvVM8H@rU_W|_0}_SRIF+0gV9^MMxaZNPrELZY++qrwdWV&<`G$Q&b3jFdo(!-xD4KwROcNl=b!#zr zwqcT`jg`%FT?(Mn^PG39J5XHkmm+ZJs_G2YecHIr>^QVML{zS;$>OZnh;|~|tJUy5 zTOPgBavQsA{b0gxR$W*1m;k4!_C*H>{Hi1B!hlaIJ+N7DXvhwxY)^gHCBYhsTZx>$sgR4Vgc8Q3S@r=_Vjge>AB;9eN z0Vh(lAbVorHNAs=`l5;cTDu@Sz;nq~*-z-`9Q`<0W*gnLtNSKZx&fy?D-F%l*UH${ zOaD!;d6ML-zt$oLUs{y+^WVZpJmL0Q;D8)`y3X7&b_zqSu>)$k&v*=nXz-xlT(%x$ zoGX%O;l3f_+Sw9#f9=V?c(@AEXj>Mgtj|13fKZHo2#kv=&EKMAJJWQKQbjX+@r`mLhXg$DM!BIM%*7FIUhbZDkAy<2zNm zIbSZd7U~)e^s6L3W!dt!o*--|USsSK6KemWb-4LbXs3MuwcD?3jg8(OXrOz@t<`6Y zUNNvFto0x7XSM1|0JslLtl_tUE1m4O5-JulHhJM`@E%0|CErT0`xKQ~TZ2`v43X)OxGcqKE`gj zLeNGA0+jX6V8t_V9Rz+Z$BQh^|HcZ+JF0B)N9!HiNhwO-(EV+=&9%VyW4ICITiL1P zG#L8L?fv9bBNWnGn!NO{utOn~lVzk9UFnFc&w=V)IXW1N1C1w z1q?wGLbf-ig(b&Xx#`8*X0q=Z^PA9w9Y0D zNi{ly@3eooxm19i;r)mDPgDbBO&DFnX{I*|=a(#w`s4Wo&_f9ke!t-pPF2p9;mucj zcS?IQUPpx#G0T@D0H7?`8oIHcRwP1TJ|_Wc#y&$xN_9|1Qlk%>@Jg>%VBy z4+c2)iQYg6z|e+vea|#Ph4JkQ8+xN1(r#BgKW;(o$(LhZIew%y-M*6J>=|{ONFFkR z$69U(fgo-!Gr_76lLm$lpQNU6ffYIWOC&;st$Op%eLek9aqxE}8zpRM| zw(tEX9*!Fjk=8@%8mGWBO^UL4z2Ob?gU)|c{H>5Y*L#Cuc=sWeIUPv+w=&lwj6r1oSc`xu%Uu2+VzAyS|hc} z{nZtaI{`#kTE{LuP@Ti_gq4FekFhR zs7UPUNQrlT@`U*47riXV=&%8{d8?0v6n9MF*>=h1wxE65)*+Y4Zy1ziG2IyTD=zm_Jd;xODIIk0pbLd@lu6A8~U9LkO=o+>KZe0zZ=XC?C z&9marCnqZ2y7d5ro+RqmuMGWOZbk&_^8$Kg^;UMj&*?vo@Nz%j{W=$^-|S5bdvjpu zZ=h5P&J89pM|Cl&`fH3Uv(%?8RB>FJ(zxoBx}J8>7^gb5^IBjC0hZjU@PO80LRT^6 z7m&%%$y8hG&fc?ioqD+VV~xSF?oZH;?+lvU;G<4nPkyz7u%dsXN%eFv`|s+3#o5T-muQ_ z4_2DP`sHtD@nVQ8=^52x_*G;OaKj#YQCN2)a_@@I7_r1!puf-ZwihozvOSpkv_sun zomf@CzkCKLuBjTzqy2Y_CcOE}p*Qait=3(EI3O$oUoI^Tmu5-&{KM<~OQy!oX4Mmq zki$s7dJwUTSJ(aND-dn3DtQJ4C_oCuiezJzxIL!my4FUkv60EG zX$NXIh2-%5y7q4Bsnr0}B%+yMvFi$8OSh*SU{^_ie2yCV5Ks{F{HlL^56pv9Y9p$1 zq~QJa>pf-3?h*kSn2X%dgx&AgxN5+q@d9u;Fvqp;?`!x5h1i^{eidOp&|fXd5AS%{L)^iJ(Dm-BD=Mo_z){4xruv``4 zE~gK*vKcFO4c$8bscl$N8z!n^yv3yH^&IE*4?I6|S9f&Hy{gOnM4ZB*oT2Oq^0DCu z4(J-)>tbl@ZZz$B6)=_Fz5jy4{JKKlpO=Vp9SQ$#kG zW0yg9XHR;DAC6E9;S*^0I=0$fLFQHnA|{5oP;Y3TYoVO~r{Ns@s34TaB*HctZ}<`L zSl`)`!M~<~P(2n!>W@VKSwyfA5r0svs%7drP`!Gl#KLr#u5_`HhI!|PS#ru&fXcg* zD1^S_eZ5EU-z8^ORB8o~#XfB4%J>M#VygzwhyndT;s`oR!F>u`fgNrc`*Y+D z@r=BC)-mp&GlXfg&8y;b8F%$#zf_Bl?`jx(9`qjB>-j*9rp z#YDC8G&1==zCis)5K-b4l7i<#q3T6!A`u4Uj#UJ>Wmkwt9?~-TtBSfSeE`bE*^?$t zbcEw~IYdBV&t3glsosdaP$FSPViVE*SQObhDK` z$nziRrt(zYFVcgW;KA94820&_L$B0g7-Fp@RABT;hWuW|$3)?zb|Jx#5srDSW2jV0 zFDZtOxog7z7IRjyPp}%th|IObRs6b^mWOFgK$SOLQ(E>PProv^Y8|>XFggiyT|wvb7in9g({IezcjKS`(+jYvIqSeo z<#_IdKTK_G);>jp@WW@@8-q~DzR**+4R)pAjgvwy1;yd4vbAq(^^^nmzr{O8L-lg8 zT9QyU)6bsDuEABFC@hHJL^PjGqGg0rlE zzRkY?{0Km70^g3gP4=I};pFi;yi1X6?Og|A*fs)^P`b`t*ziMeNSQ|hz9c+rT#pJK zg*3Y1s#K*`%!V(qqCFSD=Jh)Ms z=lVU*s?ojxel?heE86L@lOWSkz`j$jEVFvBI1Iq(ibEWs0nrg>2AExLO|!{W;g4e< z+_GWHK zOI33^=WvV@+hu%ULL3(-kk)TT>Fa&+)O>c>Px|VZ4ji9ps}1v)a0f(b9+-pa zf)JO5i=fJD4f~X(z;l9uH%IF)r^?ov=muum>>DIIAE&_9B6SZ~8}brnw_@U*U~3P< zU??HX=)VStd0Ngjs|PylPR`A9qX7dZK-*@cBTHS(SjT>t-J6PX9|7r#0dXrKIE06{ z7tG+luXE}a!;m>y1ZH@|kjfWc_Ct1N>7Sd;y(%MFb|CwT)9 zWQ@UIf`CY7MsomAJ0@We7VHN$yu3W(Q>;XWb8+MD0kR{^_7b-s?=NEUqE2A27rZ~D znSj6*3bR3sh`s*b-%GB3MSbwsVHc!vyb-EmP2`my;adr-mb@6qt`J83GuukLtp0rt z%EuQU#158-3?$(6;armdLXAoJQJ@%jOdMpEViZiQ?Dn7^qS!_g#DoM0sIIL@1kQXy z|KvQoM~$n5ioUik!D`4aIl3Z&wl{~gem}pk^?G>N_^OhhPF)hB3PCUazV*rzM zy^MK6PQbqDzLQ3ATW`d@`AqNsU@!Xcm&^Z8qD$4ih23y>fl(MhY_?n$o(0%k&l&lA z!4-XZNPrZM(eWngQ02c#Ay}&?-LJF6?`nd2dS+F(Xp)^0A$Pi=!ZBO)g65g85qQWR z$P+4MlMPs!i@=*G+7!bo+h_taX+T)ziCAji=^u#x%l-?H$u{bQ7G0e*>-RgD2J}{e z!l?lM&eC!H8I?1Pz@Jgq<%Ie)&5r@&^k>%Q@3z#y=yS2DSjftM~g8k;yET?SN*N5=7lk2LWmGjxC0K_3+WfJ9gJ-x$YjbVTy`=6@kokpO_x^bnA+GJDXhG_rJfEk|b9dx>_V%mvSt zpyG1fVx0aN`5p+v8=zO{;*7fa-LJt@63c}rXmgoZRgF0m;6kEs=FC@i1X%5Qldr@t zhw`^@Qq-`mb1xSHx%*O$9RRK;f^|Q-oOCvFJ(Dik)J4-&u{fE(Qh+sFkqI;-AUJBz z1)N2UpPHH9$Rpw0cC=e&OUJOJIN?|)F&I|zB|@fgtJFUosZG0LZ!w+EY37G5lm9;85lhPz{)B;kyER6HJ6*VQ>x^~^8l^xmUWf)w1{5U{Y%Tb zf4p-@Qzs2I;0b$P1aAa~_O-(9$75}mdMqQ}(p;)gF1W-OKVATXIGq(_k&Y8^7w6V6 zJ8Gd``~&0r+8-iqqdvo50wn}NkUB;<75*BE`1*?=;xkQgHP%s7o`nruST%yZ% z=KMu)$iifYQK8E#DNsjWi}H-)yYU;xbs9Y z5Cce@uAjx-x)XeKBL%QmzZ&GIr%q`i9>NjL^j0h>OqR)@iORpO{&w1h1!SBV8%rv+ zefnmyZTvR^UC#Xl9EC&yaerRxcW3Mq7>}zsL{`+SJ7_oYg?QL>*`(l|k2B<}EGHcE z2`w8K61j*{g795K8UXwk>2LsEjSjdwe+UW?NkX>BblgY=U_LXqz;FbBD^NHco5z0p zOd0P@`u7im`RnQJ$%~Y`O+Ved24X1bg zv-WLLC$rjZ-yZ|6qcXH6Is_TXnsX`utmC=Y2BII4%*aCoAo9bL#UY{SkSYYe z%qqindCtXU1ShngHwR+SEcvdM96V#z-VyO$@i?kp2wqV0l+`ATfiLqhVMK_2C5^yA zq!Kzm4%Sg0z?x?B3fZmx3!wxcUNijF{HA=2*(x+$I12!yLo0E%9>xSBCVsusOmm0v zm&4O6F%u3>Z%9e*y-!;mJe%8#3Byf;*V2i0OGK$<;-|Oq(fd_x^N8MFAKrw%YE($% zla|3XaQy6Ey=rn0B85P7O$jVDluq_2nQ9$gvXj;6RIgN{ih!R(I5TrchMnwr$2a7`TsGJ9Mv_c{GZ9S5(*wzz4O-oX+fgTQY%NscUy z!N`w02maX#0CN01PXbnmnj&It?2hKo#R^%Fe~jt9(7_O;fMJbz;D2%~)PLA6(Zudx zH3r(VHD^X+MLrD$7;^|QrDOH0FWcq@qR4Bjd_$230Ji9Siq3#qhS(U8g~Ejc(u;|B zx31i3@n1eOvOci(H}F;ib26>pr)TzrR*cbW{#zZaA5TxLt`+`tw0logJqEXhGUhb3 zxn!8hRY+*++z9Ys>yKHXfVmt6)G*Z41mvPiU(s>Eh}_$N~x<+EW2&L)fasd6Y z=gG<%MeV!uSMyaJYMPSKDb4p6{R|w5SfKR4?pj?+RaSIJE_L~D8#KSC)P18;f_EgV zE*+=VOXzz$D;sEFLf{n}m;oN)xdO{hrtIJ)!<{cJqBD1!!?)YGMIvafRL@%-->&kyDT8O?KHS z^$}Q2af5IG4a1OM^@xakZw`jb8JTzpR9a%pRXE~P(eS}A?D5_Rl^7~&fe2=O-dlNf z>m6D_pd2tYwO8guuz|j+*Q|P%BT!E-b~tnLYuL3XZLK%Y7o+a!7|P_vrCd}k8+NQo zabPs7G)AnmbPptoE8}bn9bl37vYOU~zefvo)dXC4SYj8J`u^JvKWdU}`9*|^0Tg|< z|2tWKS1oAf6J~9F^g6M8`y1=#T2V+lb4T|?%@Q00{lF1eV|2arlP_aEp3^QA_rE4IB3nSSh zT{W$u#~FG)jF7rIC7&!DDF&Bw7D-dzCB0rbNSlzFl4G8dM)hRS1mcav?~;Cw7)&j& zy?bh+;>`+@9e`h+!mqUF$jRhLN1k*AMze78j}zq3KOCw7pfND@GSQBUZ7By3DsC6S zJ{YenS^=aFzc>t6kz0O%n1)T15`LVqwC!6s`icJjv1yP|lUL-#0RhYPZSq316<&x- z=-l!%{;dFT?B(XdB#Lyd~;=7g&IzB3rWy z@IT%j@mX@P42UOrk=7}U-HmFk#a;+IFbRM!2zc&FThFyB*z59j@$LBB$E(AFAVbwDARyEpIxon}jO3L&rT%_Fb&Gtgj3~ z7muEh#yUhKr#Kq>7jXOrzRJ=S78FDzw?4?m-`@V3NQL(ns~?v?*ZH-Io|z#9oJ(ro z$h4In$x*$CSCPgm?QB1-T_jP$xgj)y=zKf@@V^DxA=KU_0B;be1$=NBL5H;c0l-^d ztnCHAhRht}iX96{-UIe2Vv#K(>A8b@r;)~+_f)~1s0LW+=U8axy~}>KmW8fu!~*PK zW_rBS^61Wt5R3b`1k;-jdri?R>CrNHeeB+i(N?i&xh6C1prR9WNWR%DPNb1}W(l3N zIs#;Gq|z1co#kyFCX}ND`op|l#Q$B1E_1G~2NbPD2Z&6S5=MO*%Tfp0Hlo0=;5v{O z-wtlC?Jxf5P$l5CWD<&fGJnZ3H{2_WQ=gHle?2Cdr`o!tVoz~KO{h|E104oQvuA%% zZU$qrY2L1rz2l{YOf;yD;(g~!Mr)#F-J6V>;IVKlJ;FF z$HK1$8>s`Ndr%%JZ`fY>$6X@}D&KQ1DCfzsSwK?)m(k(R-ckBe5H$eh2&zMho#SiR z6Z0NjfdeljREgc?*N*`d{cR&m!nj>}M@-7LQ6AX73-#LH=4wem6tvny#w*SC*EEv* zl)%lk?S~v-fD^!LvHvP%{QYQCGxVuwc>RBB{XID%qS?7$RtIun$bUIo z+PMHJc#*#XyGdvW2vDsb9b7RR0C`nKHlVOj>_4F}rjicRo3i$%4>o#z;+L8(wlJR^ zb*hVGe2lK}(&M|(Z;||j_Sn?5N@ojG7e6PXzQuiB>e1oIez}PbfgTphFf}J31H{aX zU4_JXubIe9Hqap%PDn_hGKi^X5jO6uZzQ0f8tZIIj~>x~slpzKieAfAd!q~e38cD7 z)c`MtqnD&X2b?L!C%$f5EF!H&RZXThR^ZJ^(qdngcL7Mwx7_>2&wj(@ifRJm@MS)n z=s*`&#kHptI*Y9f;6MN@fuysd1hYEUd=*SAzFWU)OT3x7NT8i-GH}-=cWz^)#q*`9 z*UxCjd1amNbCVW5XIx~v_}fEnUoKDJ5QuhYgtc(xigubp(emE8r2WMF_th@zrfiAP zKvMO({BGZ)kVhlfpNeO}i3GF3pCzw&|I)Kr1fkSTis0-(enu*4sH^|3$_YpT?}OPomJyE(zlM-k`psNjVIbH-QdiM9`vZ zWe{PC%9E%L0X`7kE`MhvfVS(p*UQ#e?T9-cwgMh)MkiC;C&Y074FW5x08&c9&N$~C zgdREu|LC6QyH8O@vxDurV(l+7(1TqRAu4#PE0V`T;^)4lw~H*xl2JV&Ggjl{64lb~ zM&es>wof&yY7ndHq5bffQyHYVS6NwH*W~l@I9RqvT9c1a#}C&emhfj!Y+2GcB1U%MflXpcJzp_Gz z2JXz8$#!6Pejd2;i4q20(Edv`so+<7`e!QmYpv=vVX44-JC;qQh067TcjT|Ike0>n zmi$Tj4pN4geXG*q?=Fks0b6d~?f2&)qYUv)1hOU|Tv_-;5->e=O#Mx-UP#!K1>MQf zSVE?xJP=M3BnB&xwVG9L-qd;OD2{&6jX)#OjNbAfcvL%wg1860j_yV~iJx{U%AZ0E~=OZ6r0VN)oi5G?xJS{{B8gXo0J2O?W_ z;vmy?4%x?IY+I7WB1p7@kiXI?EVPz6sxM=E^5UUJw+PqqNY`zS=E;RxKV4Umz)MJ< z2YjQjVBuIETj$L)$z>LD|M1xZM)D(#psDTQmDt3c_0m zVoy!-_|(@1bsur~fD~jI&U+C$-wKr1?UID4E?F|=u?-O&`F;;8)#pme@~O+5U&uKR zJppy0+hDnQ2to;#9od#cF*dg@Pen}f6?)mULfK982j=$$4H(D|b^WUp^)-~Y(C^Hj z?D;HU*>HIAL(s9V!rzvu(Vv!rzy6bpITXy%7p6^I!%E_to?1$jN=y!sKAc9o=s!{P zSL%a)WJivkM22+1h2uCoMAkptU8oiu_*a*#b8M3A0@>VTO+T}02>Z4-#%7n+?w25N z__eUsP0eG(*2&Xd8<(O+!SWU*L;T-xB!#-Wx~FC_Vx>wzw>rJ?-+Bz(I&`_J=~KS- z__-N&3^Yhc{w3C=+=Cs1QX4}M1a{QSWMP`4enYQ_>DHG|wg8HGA5 zd@m7vqZW^J@C>z5Zacr3^<9{18P1BO9JG3m0*cPp=VSONxqH)&F^A$FOY^qEX;Y5X z12n&g{C*j!%OwDvsVDv(mr?84rMptM*Z7(`mVT_Z5RtBVqyAj+4_nqwg|4gK-2;Az zDwO59Y;AeRn*zU=zM%dl6@%w@io+E%oKpg}<_Qy*B$KE5rh=&*ubkS@bqSw8xI_Ln zwqs*4OrxvP^R1k~3)R^IX=qt~YpvrsFuYLWEPXF*Sh>iV{<)`PxYY)fmtDx}pC`S^ zhxNm0MNf`bRi~#NL;ZZLL;8^)Ok75LKiLlwO18e)8i$?zB+0@j>heYP2d8?!$07dO z6i7k2VvZ2gdxEs`o4Q>|NTngT0=!+f)IRxQ^~K#vl~Jv^`{<=86_7??`<81a4ECk! zb`lDHq5~_doeL9#O|@$M$sV-+YV4LQmGC}JEPNByWB(PDZlf}TA~2_9-}*`O?wNW) z19eid+M_wd?5$#yd127|>c2rfIA1N6y7cWyI^?IwHP{Y>xx*c-Z@MZPOGh_krighu zbx~Rp5F2En-%Q27eRb-L$Yhe{K;C^ZLpQ>sb2FQqp{FV`a^3!+gavc6p0}qICwX63 zsB?oKWm!xwt0xuM8sn~8L?8LZ)FQLHJrIU|3&YMsJ?l-gx~pCb*5v*f<*UIKTF=&w z$_*{6;OA`BJa{W2_S9k-QbF#~j9a`>x7XsAoM5<8Ki1~2l_mHz^w;>2PMO{-U?E9G z%P{)85ko|OPIw|jU=nhkvR^=5pv08$4NA!rAn(3V$64>9&pR+La@SCeK zS;ynT36RsP?-Vxr8@zSX6QGaSU3BhqL_p)Cx}t@h5fzY+_H;y`)st`iS=wT8rlKxe zTSphs;^sxBtiFLm>a7Q>bfchgUj}W2_5k7NDs-8ywDQX%*<<97%gE*qiJfcjhI#zN zO}Z)-^W5Z$--wxH*){8R@kLg6p?;1=&_ZZ^dH(^(#Oa;OZq9cBQ z!H>{SwMh7R0rjysDEb3Dx97p9krj4&b{FelU~^Mb)x4&yD!y8q!%+B84rQ{Z*i>o$ z7;X09QF|^%?r}7xbS$K$)nK`DJXYBF;QUkl!eZ@GG=kvnYnZkvky~E$U^V>UCij4H z+@dQ?Q%H;c#P2GmCIUjH%_Spg6Bae}2g7@h)@bp&jVE}oA;M?I&=*-F=x$7ZYu4Vt z0hd&9R5QKc2ROo?)9OodBG5tTaHyZqH4*Cbzh|r5sGb+X3pQ~K&G@sO>2e(@UX&E- z+}o&ic~X1)I1ftmqT8ht^T8h-flv8SI481_Wg4U2-22_7lV?c9ilQnGI&}Yz5pb;y zC3(kV46)IU9P=3mAA4`zt4fJJw|RAXExSXtaoG2e_kOEieaxJU+p?1Lg110U)SjxX z3HI07=L(p~!@Ip#e75Z_f83Us#xR^$xX5DPylv{LO*0MX?fpnC^S;{iG|mgxYA3C3 z5KfAdOkPYyy*`+}6q4yyT7R3?7%ODwDWLKERhvk$=2tI7bGJJB_!I?<0FpUqVhg{? zRsF|?nN$=^heGx8uSxDN8ZxC2=_|ej?T1Y}A}JT$fgz=EFndc1L@?BFWXz6fh3jvIZIQ=?)irhua2 zI<)2qHDb8%dy6G0Jztl5UefJ4C`+$CXUK~}Qj{j;h&EWjv0(N0i;XbD?iIfKMHG9w zXFVyKonRTZ46m3*GrtXSS^(koT!FW{HugQ3*=drUCv&Yc7xOSCul-Uj!!)u@bZCxS zm0M-;qVi}yk<{NmR8bLbPpeUu!HHsv7+oPFB#OZ3J$Lb=TjX(xW;2(^v`jB{K^o*W zC;z#C)@8DjNZ@FBalFcQXs}X9cCemm_I`i1s-oAinhU@|@e>3+fy9ZviQr2SY7ic# zKk;Q0CXJ|lQD?L(xy*vb{Mj8ia>50ZVRGDnT@K^XO)!q62(-rTIWxvZi z>-6e7EDO|V!G=;J-J{HAaqJ(^hdXnPXjRRmayH?tt>0eA=ZVzV(JV46Hm3bMSD>&H zxc^SG%kE`DOEOHJ9al@?zmI*4tS%V)7?f95ab(z^2f?SGsA>wkKS=B4{HTl=8hQy6Y=cPY+`oR-pJl?S35ixm6 zO69ORy*Xi5zA|eXcePh&(J^%BfR+14n39iASYOYhK;AScww%3z+iOv#j)J-$P>qV~ zjc{qFr6Qbi*6ckaZ9N}Ni$j~lepMI5ME@ZM|BC``u$&f`7o)Y|40XWA^Q)TSBnD}x}G@OT~^E11JjRE3Cz-c7hA-lN`tB6KjYFO+XLZP~0 zN?DDGf5Y%EklAM{TUzLn)3sAJ;U2HYNwYHzKC`U5x3`szPk_%FrvZ&qmEPy031 z*bm9!j!`EHhhlbdoPC+PY7a|T;m5A^)@Usit2kt1i314c@IR85e=?S$cz<*i;40Z_ zx}hgVnqw=?EhvCA2*OeBn|T>Wui_GBkW;^&$vn_%80yfCxV#btik%L;i7`AVF^R1H z=es#(t2YJ*J=!a4g8GSkW)7OxR`UvZutJ0%MO zb|plhx;-NyuPxQP7cqM{&RzbI5MlixGx6>JZ?t5=rFX;SlQzY`id=$w#WN=N!8UCw z!}W>uaN0I4bXqwfd4Q(9ZN#yAq&PV;Nc>}hUr|I2a)I=+$*+)W7m!bKZ1(W`t;5o; zgmt5ARP=|9;5)y za@xnFHnZk98fPLN6exgVRhL}7i=5QWK5qk2EDnoQ?17y8(n&DVwer0*>t_}X$}qMf z7xSxcrL?tQGa!a`&i`O0ukeiu@rk*eI0%mEcl%uW+%MOS#15QJ9`*?!wCM?O?T|Gk+;NBEr|-TBu}!0@T{`>HvZ zWlTLZ&FQXLW4UsT`WiOaLr(`Th5-XzFf0YkgLk!k7b_Mr0X$OKnB@*>Hj^7Ww{6#6 zkd}+GmcWU>hEL=!fMPexl&|){8L-YMc+CBZTw~g2+tTS!0~Y3~z4mVzY|G7*!6ixhJAA zPyBql1thG*I<&@ZC}grI#bs1JN+h3pal7q7@?(lavp8{Qd-;D}d=5*eV_w8>2N^)# z^sl}NYrE+#q2j2;Wt-Njb<(9gQ($bSMZ?@9Y$)g2ImiXGCFmv z5jnXF_YjCz%5bT&sXFPtibHCKEoEnR&#joslD%2Svl!1O{cyCzETj!VvRKfD;Fv=- znQIDU^S{u!?^l#{=|v;+qm;*jY6E6yIHUXOu~0g6*U8N7veIc^qr2n_o>toFmZ-m! z%yjblnXHfl(I`iq`abar_GqXM-91=@79xSj4)uj>_*8^8H7bzsF?j1+XuB+>$vQaX z2##!BflU(KkZi-3Wyo5}Gii`BKOhp)Y4FUBMn>3xT`7ywgeHT`I+?hvJ1|@Y`ea0# zZAgG?ImWQNL`+wKN%yc#FZFfWm?_=_`vE0D9&LcBNP#c5aw8f|H3NBySHX~NWZv5O zD=c9^jQE{#Ar+7d_Sn($VkS=)F}<&dxEmX3Y7v%K_) zen0~k)<`2bz(vjq@E42Em>)Un)Of`=U5zWKo@_qe8I{Sp3JgsB6XlKgFZF_h6R5#a zb>x^>H7;In1|f!1b+(-LV*yJK_sS7RE%AZowE#ZvzMH}BiZ=Q}#UkA`vk4(a^E&cq zjQaZrY&-&WEaSOv1-<_#sYSZusxY*D6P2(?x74g5!WKu>rKm78$}q^m{aB*bq*#;A zHS{qsmu;W;3nm1AHGc+%`3vTBT(@^HwEKiA^y-=0HjBxG01vHe-XFN`gMIZ+cOQ|3 z=4hC6ugidMSC5DGnt95VgX7$>EFbUi-(3frWd7qy{)f7jw8B$WJ*g_D;Z7gAuys|` zur|$|q)4@u5Yw@b$bkV}X@xnE>Ly&jJN0M(UXta4-Z{*9lQo( z7u~VoHNp@Im3b7L@0cMtFL{PMs=UgM-zE^UEF&8DwaR9Uw~0U{6MRYYLwlS%q)m-^C^9=pzO1f zavYf6hPc8pR^aW6%F$P3X5X+wXU#~4LiDkAJJ^2C@7#nd5;pZv=^ugQ3F-PknSiZd z>w|m?^0u_7ZV577bywb=?owHPU8dA-=3|c3(0w&dr-7R)`VqtB>k|c8vrYf9Xd+Bx zFn;mEci4CgwXCk>bTo7lxO5ptxi8v5*|viXt$j?^e7oj#Ue_SnC*nhlW(#aA^>`BbJ!x9SKtNh zpv>EFsX7;H_^9BoV?bda4%=i{P?Hw8CQt+zr}!@n{K=Qwcp`Fh$p%FQBMC>O*B3xF8(LFxrHI}GNRlzuB1SdB@sp+MbX25>?`o{|%uZ@t5dA$f_Ea~}Xiv!`vYvD}O%!MVJ3?c5Zk~G@> z7JQZf;P8oAm-J)Mgk;J9GnDBgKT5nyW+F0kExmu)ROQ`AX?A&BaZpq%E32kcKXVp; zug;BtU0@?0(=6q#yeH8LqlM-k6-W<*{GpJdo^ zuj6ex8gf^7$7f+tZXGEQT~Ynt&qAiY55$YfrW=Ss4Nx#sY$n>A zhxx(rE1@4MM`=tdK`3+QZ0VULIzK)`pnPr-UDPJc!kl%0Qve6$Rt|VW4&3Vpmph<6 zfX-f+7EqAR5oAmj_=cMjMK}DPBxiG^oJkym(6wV*V1;9Hs-6sb;=~6*WkQn;m$Pa7 z(m*juuUSNLSV45me->{jUt{x3PY|KuH{|fHe1|ef**%)JDsV3ci#dCj6~`3q4!+@y zG5OWDJ@=&ToNe*i2~{3v%0*CoOqX+fsWu_Qb&Z=2)ic-W2@_;pYKtSC@v}@z6~@_( zpL@W+4TgH2eF0ge0Gh__J|aU{aMNU652VP^$s%%<43riS^Bz-?P;T{(D7>G5OKoVU>^0P=s-j>`@w`8RpxH7T^W#?J{wVtMhU`lU< zK3oTLi`7r>rvRUyO(}t{(j(SaK~Y=`B_r*xq=bW?*<0fW5?9$~uPxpKv4zAg(+f5n zgItV0{9pFLVKj)rj*pG?ssHRZ%Vltn-DEKKp`K+w3s#ZkM5q$wTbBzOQaJeY4O zJwtiF^fBlt@b-|Q#4>JRji7wILW;7%weh!NWeSN}u#;@;7CX+1p_~!2_G<~*MnEs! z^Do`!Nz7*o^oVW?C|wf6jYjn^}SNd)U*pL3I z^`B{zu~*tz4FP0V+2dFtbAPCCs;AXK6h*SUv(0+*Htaa38r4$e7E1dSrP(Iac<3qP zQF{uGLkkWnjuRm(){v@&Gp+V8)h*Q+1YGfNt@=%~dTczizeU&hj9aEb4cpH;Ft32 zEuGCFiR6m2G$XZf5B1Owc*ZHpvxg|xhf97L{C!OZo?&8tF}!#E&H!z|l`qQq%sA6z{e9JHIQ$`?Co9CBw>&!|oh8?W<#MN!FbY>{L*2!dZOX`#FS z^952{&!R7R7R}8pT0*UK(HoVlLh8En3NCln2XgRrMd0X3*M2Tf z1uhwY=@?JWoML7lBBc}4AlM_MzKR;kiWI|HhTzUEdO#9vuIjL$%^{C{Ld`LCJ68$6 za#)LVg3UiE%wr4pxM#NThI5o*_g*lzf9)IR_ftp{-?SYr=Ew)Wk*s`sJ9Ay2S`0)Y z9|DT(HP&A<&`0Pg6-KY&v-@4sL?{L@rAhQ-k(Z+e6R28+p4(XH*=~@~oX%Sdjkd}_`@%w|H`?yc-%$=Eg z&pqdkr1ONBz1SU^>2ORc-kS6`1=Q!zUXJ!m;9bp~z!x3`&(2jTmy)&S;;09Iz#241 zI#alt@%W=sd_Iq{C(F^nm}>vF5$!v0<1vEY`Z;sxdW?YFWe#OOD2c1;9j_frT9C)>BcqqLk9#m(z7cM_4| zv7D5&Hc(-X>P(p)q11IQo3=CcRI(iMo=-G3X#rwJnNSH2uKonTHzT#2^r?g66Y_4Y zN=4M5f06~lJdf{rVYch6&JDo@h=Dx8j$chH-d}5=IHnwX+C#=x;8wu4mMvO8STJK= z>&XMBU@2+OEjt(m7Xb-!v1sul)Oql7+V{BCFg!Cam`uD$b#y1aaeZh9We`VHX|ylB zZGEUhh9ikzJn(ib+Qe}J8PgMLy6^iwB?I2gKf|SvJzOkYAD0Jvb|3x4c|#!u81At& z14x+C9L%`EZ+%ry9CZI+2LM7I0B+D{Z|UFh`85C@z6O5MdNc2Wml??}$DO=$&iv%c z_dK_E5#h_Sf*3}IwC^8Y0`rjiAMk~6f_bjd_1yQo+uGEYNP)RU==pbnmsb3X&;ts| zypj#Ve~~{ceec6A#bUT0#5ZLTYV`OnWp=;=ZdEphCQ{3atmDRvMz5q3Vp6RA81>=f zqnVrzq`34$`fw~0d4==elg;wvMN!e5EY?UdPIFq7oU3P^k~N|@;#42D;-^kF9;>c&@^NcHJV3Zm@WsJ zNUhuWtq>i{%e<{grhh#Th4gTm3pMLR-GLF*ti1Gg!+8q^>F9U+U_>=3^0izor-V}{ zk24erO?mq@ftk>xL6pmTJbzR_DU0YWdN<_z*1%ob4$SLkA*CW;sEgVJ83u~Ya#MK4PX7xcGB(9*6$rbD9c z03ph;bw%6=JUlk-*ohO=w=ee>!?geCKxGxVhK+e&_M-Y(6pdTA=PS-25je<&ik;w$SXfU$=EfUzu?KxoQl1FW3oI>j7y{3mI0H}DSW{1bt0epFL zZ#?$Wmfu$A6FEk%Q=G|{(~q>=bN>}Cc#=!@76(C6+MwNTRE0WUm@VQ86|jIpOmAi3 zdmll^P%Kyz%Q+5gEu<~kf8x+0PFpaRm2^~g`mhIL(|1zGa-T!t;0Xi$97pqY;X?iw zqN4(~$Cm!SqPX&bD~bjZ8N2}80yQAl=9_@fmWJd;u=rYKY1AfAEQ8cPv}Mwmh^MF0 z8dLQUplJ zoHgtIWU)Ef^P)H>e4sB%=4)t`(OS&SA9-@gb=_lpGTO+t@1|0SYKm{noM@7 z3iw*5G?_zq7kOk{(+ri#YwK%t)K9AF3=?+?a|!}7)6DH*Jr7?B9X;Dyq+?PXlYaK0 zX)b>xt+%gj?6}Ms;!rD=IHIj1yJfv1cpoWK5DdWeoani409Yq5Rw^+MAX7+d_He&{ zifd9XMnBKPP}GIgaf?GO39|?ecPJ`h@v|T>)Os&;o&hAF2i2=;cJBI~{=&HQb-Rtr zu;|SRo^eGI4ErFI`7B2hq0HnF0Y)S{&}}uVqj?#}CJGiQp(RJ=j=}!Of3q*u<-6zS zCfr^ge+(Ec7j?{GRh8@6UeI$fiV9@^*k{h5`yqiR!clw@Vg&2*<6uO^$PWf*MM@^Z zX9diM%+zzb-Jg0PP8$r~diaZms}-RKw}aXgbvwUCvLfq~J2F^ZN>!DkdHiMfCD|Vj)0Jm8ecx-Y zi_<9wjFv%>=euS<3KDw@EDuc`U7jlAWH%m~PGSfsDX`jFxl;%I!n3rpHpk;!9n34q zQ$%xE8GKO5wimL_?xi5sd>bd7gl`7C>#iepP{DJqxPNOoZ8AQY|D_11gEh1UXui6_ z=`T-a+5)HJpuW|bGtF60#?Ym?_p*mPXpao|9!B_&`dJg)=OUo6`SYR>LG(xVk)1SO z>Y%=zF|L5eZM$_HA8JXHQoUVv%g~6h>ihiRDtcau{tduA6g)Cri~TR(-CC%J2aO=y z_OcqbYXESmP*o?+TKR_$|Fx@JylmrTUV`;9nWn_#GM}CnnR>i#<>h@M&dVNb+$5YV zd#HitMihqIQejgYns~{5OilnVjAly1S^KyVBng=Zp72!?(s_cZjwWPu{#J_Uks9Pr zAR-lCwtK|g`9|ub+YfS2j_54U^V=2$qviUAoA@XARoAW)O5bDO%Su1y<@vpzb`X@} z7N1(R%z7&|^;$wyb4rwcSDpU8ND}gCkVKJGlw;*D6Vj6Ch5_+lEWWBYt$m+p(wN`1 zT6)WbEDgW&mVOM+d(@rge@M*N8GfvudQd?;CA!f^Jix`f-c7sRC8GTE{kpI2R1o7t zHzbG$Zt=&q!lOqfqz6M+`N`j0NDBqvnYNox>hr&tH`#zAU;*=0=S4zI0 z{A6?d`Q?jZci+H0IlS>mgYX`J|tgbPYIJ^GQ} zOGqCPo~tO_w8g5jX*}G$Z-09!J-(J*NGafUJ_| zL+WrFJIcI9{Lvgh$6v9I>`>erf`lPrXFw!h_GrE~L!f^5MaYJcR*2tZ9d7<5>KMnE z=IDwEX)V3_p&<|N(Hzb12pcJ_`D=RUtwim97x>)-9Yp4F)F?_o0)Al_8vK(E;`T6F zSomCC?KutX5WOgUOLn}D{oxWFA6z#i-0!Wu=cO2I-GqMPa!URiRMYo%T zi+lPaqv2y@$nlg6Kz$t7W0%8?ReNc?2uF0iD6NV6bi3?1tvfm~Z<6!}5|4jaM<}C< zwqRc75kl9=64Xa}NC|R%UruK0Uda;Vqk$iAs4{qD!kG3UIU+G1o!qw>vh_(wFB#qY z9*#J9b2=O(OlJBBM-*#9-RI*W>YuQG5!pHe#4G9Ba>WOCLBWzc5%jBw0tjw$@G5)g zUkd4Wn#uhYpUhaGv=LpU<>mEank9-TB26gTG0PycFN|E{o&vd9t{6kmmXt?H%S4Wi z|L}_l;e#-)M*i#1rt*;^R5?qRUq$)pt*X=%7HJo_jRBY@_&7 zK#nv3Yb*a2OZN;%<`E0(-eC&4h~OCz1(GMR@Si1Xk*~h&a3j(Qc>D?8ygS*HN+++d z?!7UEL{gir4aUIfmFTUW8a-E^HPj~h`o;Uk7%@O%-VFv~4xjue+l11M4TwGIUniR% z0?M^F;$+Kdvm2)l*FM$P@%EW{#J<>cF>y?I6ukg3z>Xz$hH$P;r>}ZS0M9t`?9GM9 zkdd1*J+M74gKx4B%kR;1b@wDg$@FvHJTT=j@f>wQ3*@9;Au9LrqtX60g{fEi=36vH z^L`>nboKXek-s^!qQ5 zf{&WQ(!9AJ1up=~PumL<$HEXHYx_QB?YGDOwKYihZ4ht|Q7oy7t*fH30#B2v2%|XYVhf44@bXS+<>Sj?Ny|ooH*f}(S!y!Y(UZp zxaqxJv+^e-!E3^?>SOT2%yjMz0pxLM)KSuHmn@Womd8TIjLoN1qWzI5{Vj#9o{X8* zg_K0SOz`$#SlZob_ltEsCwet6sltnAcDv>(vYpRrWTdvoB*EV6P6*AB8lSNR_bk+f zq~FA-GU_&2JgR=BY4k0%mF90OUBE~dsADX)#B7gD@Mft~-a|nkUGkkzKm5|fU4CLz z{Y%VWagoF}fEznq!V32Lz@Fvv>14e&`v7u$5C(N=-uvvzyJ9bFEmA^GQhAT_MoV}s zufhOLvJ$xTz&%a;GUI(QxsN@7MP7)G8F8k`=6Oks2Ypv%y0#!5SOkF9B$2VW1tiq< zv-9oDufJw#4`Yt3v8=lU>k7+vPw*G242gE3-@pF$bWbGC_0uG#(+h(2$+b_ z19s4TSv9r`xo?d=`?}Q~Hil9418G3c`oWUWF8K55)pX6fw2LJ=a4W9uzl+sg5VchZ z#;Ct~l%MN<%PQ&`g&MCm6Ft++qO@3odB-OMtIEl+cI|!CWks5=#h?>Hk)cXQ{y7P& zJ@8r1kVpWHswVJAK$%-oPLySjyni}YM7~yWin@^!n3T@_f`^H2Gi4~cS#$FiO6gPN zpDiZ`?>YU(-x3e$GUl`JVkQ&meYx5TQxDhEa(o0KDsT>Mc|rDh3&+@!)2Yvy<6e1S zJSE=#n707zW!Rg52aySWAd!JJ$f-S|Jw=dEpQ|L!+99T`E`nk?3BaA zM{BG4=@*Df!_lo9nXJd@kg?e13rT_6j7ASn(hM>mjwJUwR}JtFGQaRhqA|YbM%={m z&?iw9xbMM1z6TW2vmessmnqx<-l57ial;eGPzDb{buqgj`mGTkyc4LgFN#@u<--#! z|6#4#Vs}3Nxhyx+@iONq)Q0nKpm7R!W6)s7K-0JngE6v!~eqEvBlp+Z`K5lTBtll z3)uvKHg84C-`<-nE4T@Sicmta87MD2zL{vL+5k)Z)o(aRc&+yhI=f$zxJr-t@_7~I zYta#-)i{MbFGr+S(uC6*95mE^rT?aW*+M5){io+E9`d(TK?3iL{i23R&-P>wq8r0t zFFc~e$6`K8v4~gN*$6R~^s=j{P7d=3buCBzAb~_vo31^OKrV*WRO`5bw$2Qc)VR1$ zEZY9`y3aETRWL|#b>0VwK!_{%b`Xu@F%H@s(ror?1TUL*Ql485L7y=$)UnggqZ^rK zl_R2^fW!4Cl?ePzv!P*UlxcPA^UUf!ZMh<)$kYz98Ls+`ksD>sMf9ga=!ugp0Yr=B@ys%m_B)NT3F=jRC3Kd?5Y9f4`sDB zy#l(eVXz=Fh`SwF{?H}7TUfb5Ilu2v{B<{*<`2DOg4b1`b8Jk~LK<-F^Y_{SW+Hp~e#+D_HKX5#xTC_n|v~|ks12gDi72cHVGt=Wt z_f+RY{qqycmVkHt8_P={I>uFOea(an&=Oh4lrHA+Yqh8p5U)LPDsK4u|2syLZODWU z?mTNI-J|TCZ<3MwiqTEQz74SlM`W3()aq+0aP9^c)y zK;oxu8u>qO*=ha=AkznDHLlBtCjDlnN1*b98q0E|^Mj z>1VfRAo^Vi31pR7Uk^y_FfkvfaQQpP7U|>>F2CB4VnN=kNCnm@JKa$}Pf|1tsZp%Q zqX7(R%`JK%l96Qh3)h8BKo#W+zd&&gx@MT1Ok;4)Aag=a=~|8*3`NqF_R*Fd$^KQU z-$6TB%VAda@)@-Ah~;UMjny3{#*s%B%8kKQt_U$L0Z^SB>_l~C51rAfBd8}0GYz{> zev^PtlNN1JR*CnMW&rrEJHff;e)|lxFrh+rHm&-02{_(;`9$Co*VF3^qc{Fqa&1_V zud?5y(Hf9;lIXdo=6j2(xpzy#|Jnv_q5WJ-Y=@|@)ToD$(0M1M(#qA|vgTXh7nfE9 zyJ#mEw*hc{=(xDEaa(heN%2*)(5I|Di=lm|bPm6~=N60d?DTGIXxRc|TzP&q0e#n) zL39U~86sj60N3UYIN;lzVCKY;L7@3Ki42lY3H**cLssDV3N;Jln%K9JAkL zfv)B4wI@<1$64q zFF>by5u3GS2x7$N+Xk}m(mhEmfl7T}A$n6HJiaD7tQZ}C+rmPuq&4ERz9*Y@G`VAI z<9~SBy86mzm+AErL$3_+%XEF<@+-BZ2H%VT&Y^r}HD$lys6aNvcNJcW+dAf6l?w3N zs(gCh(w&)jaBJlVHC*^-wzD{3m0*vIvKrkI*?xKpp?Kw!zcZvV!$6$z;`p{hxqAMn z*LxXF-q{vyh)ya83v@d4@Fb=YPJK3%&Eu4^M1r$n$x{=xF<$~bCp;Z)Rj1<5v6yT_ zsfZVAo7QNj(=rkW$^yRij1Bn0vY2pJzgB&+p$bUaEfql~RA@@k*SNTUF&AAGQes?{ zDnrI0CQRJhpYwNhqhT@p#e_f5YE+yRA$23Szr+2?#Ao`SEHgy998uB4eC>YYToPsa zu5oDHaxKfzRh$nb9DHWB0*mRj0pDH1AV(}4-$^!pLl79V6vPi15>EM)7=B}t@ggB> zL}*>Q(V!QIvtF{!e12)w_Z|VV6>YGJYK01iyU1CNl8Qv=D|KN5PO_!1#0h#B-I%ye zE&k6^PCj7x6#qPamU91Z3GCBAdfR_fAAs+t520}*)siNrP*BkAOX%HRVEzVgJTAuK zNO2h%-LS&C$Ga7Zp>$dTQl-SOtX5%?swx;_<9X!CI~X#~GVN`Vhysm;o_i4(A+7%K z=T~J~CX5rwZO2wOUN>~EXGDWfUenE!V@q+S=yA_R`0;y0Yok<4;~^9Pg1ZFG3{4~mkS zB%hxoC2&oj#@>;L`2If4`2Lb?xv3)K1E>B6PMf-n??zp(LP~j8hMEt6ncBdzW>AS? zvMqlSX!s4`?4E~R4d9Uosr#qFWv4=myy``AdWCW^Wm}993g7-hI>kI!RkVNcs|A;b zmSD&C-dZ3`gU)>$yEW|eQO2y^md~L~_e=IPfW~5(r^~-U)l&8lTKTkYIl(;2<616Pi;LHE&RD0#gyqq3ACwA)*r7yKcYjl@tF55eua zp{SS$aBDUGR~;bMI9D>OA;@Go%me3bd<&J10Q>uV*Lbo*?pU0j_Hv-UT?(+66Boc@ zvLjGnZ{7do;_2SuME0QFelNrP-E)6bx;J;+(u4N!5r%}4R#4d#rm8h?(aO0gJ#`{h zl0Q}ZjFzMr*)O!G#7U}ob^HX!J_C}V5Y33oEb@w0sr>gVm>J6!pvTF{(()zMcZrk3 z>GG#MdkZh51h0K=h5yhDCn4Kt{0PZ~f(MpYm^~@LYwIr{(IrHH(WeFOoaebqN8H4m z76~&iDJRBW%ZP6Ljn6lfh)xt{20;~l-gaw*ACN*=XRX1ID32u7_6yVM^YsPm4E@cdCD@F8td*ByHRzqv_A{bW3ifwlM{# zd49E<4~$)gg{4xjKPnWspFW4}qw&QQ!GCH7^)M?GSg8gD7%CN%UgPx$c<2b1ksz7) z`nQjP>23lxM`ba#FSTAqR9jt^;33nL9>AxO>7ftPwzn{ew#u}w5CF-timCSC*Wz{zh(2ooN!(a~=tq)0%=)p%p1$*D^xPJ(Q zG4n=_0xQ{DA2%HL|5i~xl=iI2J`L47`dGd$ix=7tNJLSn`M>TSdMyRaCmA9iVpCIn z0n$6KP$$|u9l)tLzy}HUE%N!tKY6GQ68Dj}OJa8K?J*+oq1!GYk&;UY>Jhnp{zUj` zV%06KfWarO1vfv*JgnpBJdeSiJhuUeEinB%V38aVtJHG{jdB0zF)HE3J{NmQ5?O`i z<}~IK-eG*KYKU_ShIS8YnMxTV{>BU`-gn_}kJ|vtQSB5k0`>e+)*)%8PrHcotb`=B zdcgalw7HZn7HL<%E`$?}4Q(0l--kBNrC{*cxrLwoWch9@ouwi`;qs3@^?Z(O!n%d^ zy#e|sPdWwyCZGbQ`r9z6V+Wo6zw<`JA88`niwXEEPe=Zu3|d8tK4J4$<^)iln}Kdw zdBZa*R)}hE>C@3Knk@j%bW{zHrF2h#9t1!!fpdA^E&cvGPpE7$d0$orKwLe4lE?B& z1SA>XEhA3fgfjB(qDM87ZheYUu$Y|r@Q*vDSQpK{nU*nTL{0N~6DPwVF}*a<5r%Xp z?Iy0^E>AMC=LzEemV}b!k?cKCL+}oRpRFdVeUP(2SeE15%)d6(fFTWuax86Fa+df= zRW>q!{TEg8bjsZs7o#RI5%V@Y^xh%?`ASNm!2u-9B43B&;)DZw4HIeB_n$$0Y#tQ6 zh?%N;Pgy63WsX zr6yM^AW>Vl-PK^*oNfb>)Unu?1{?w%%S3*M`DY5JEIM_{I(6R|gF4(n0f+B8tNyab z{0E=CO>z=dn7ySfkCleSFe9GGIlY!}VwZ;(GvhEkEh}Pf&?Q3HB20n`TR0_7WUFx0 z-!D3a@T@#E5T-2uO2$tqRZYdls+a}x%2EPpA0m4`ro%w9|1|*_sGR8XPTOLQ4)tjyeBtDM2@ZN_yU1ymaV1&YWp4#q7;o@Z>JfIq^i5AbcR)HIen$cuN}R|(cn=2Yh7`;lwfb~I>*|EKOMuL9 zyGW<(m;?n@03l}@XNC9icP%!)v(b))%(sok^S63AidRY)FV%G2~E5jZ% zj++GNfGI3^35;f_FAvnd(uEB&P{E4QIDS`FCZSq!l;pB{l-0ZqGilZX5+Pl{i^vMd zIW@eN4BVhc&Mqlx)%&C*eb&+1kgOjmVDEaFn1}6);BC)_v3*XvBUX)mPkQ)XNG%L~ zZ6c?zv|0dv0D6>FDEqa~%x~_4+>(jH)z>7{?AzWig(r}sFh z!8zd+RdOZ9ofDDx&;}8DDY7mL3n@_!IqbD`jsM#|(sYl$NL-YlTL|jl}Q-h#2-iZ=M{~qsUiAKBr%8 zX0r;j&p=(~d-35v3ps*>ZOOznc5uGb+v|t+`;P*N&P0s$ms*3d?3*ZrLg5eFo0_)< z`11u`ztK}g`A925CSyKBU52A(PXNB2NcAY%ZEAgg5UP0D#k7^{R#qP*%xl(qf(HN{ z0(#ot>$#%Iw?6$W9YyoqQb4?CiJIAnZW~n7+2{5zvCG%VE8mc9Ke=W^u>Ac2T{ExW zgs$z80dQjNN3G2tvG6ipB(TRs&_+%oL|VSroufp$O(R-qYfWE9jY{=6+8sF4$wX_D zur}_8m@G>B31lZ3X1lTF@#Q(rFG7d*&VYP-VNk&z5JKfQHw6GY9{-3`9N)E*yD=3K zcrNP{8#oVx$4)Soq8ll<1BfIxZqe5J&68q_n-4nn^}|$4LvkK5Mc06aO11rW!tXxH zWy=H$R;HL&e)1M9HOZFtGm{lBfPfo!VZ_htL*JSwfLRkPU!lBX4m`o$S8|B{#pz-F zpJ`4BCi21{({(w-o4*uMTTHOdiov)zw*(VSX*$X5z!!#|%m*$-rd90P<2zV3&Of20 zv+cbnpE}ama*Bar3z?4`{=1iN12PN@4SNQn3gg(Bts-S zE06~={yG^ojq-`jqw)?@(hrm}+_JD1&Go75A9>bIc!K(S_87{B*rH1u6~-RP?+!LB zWSYRo9~({!a$Z@jd4Ks^(v{ zpQ=}l8S$G%SKm69%xON+f6?WBK}hQX#0Pg&!|+O^ox=(VL+nR~WDnR2K!Pv#=NY0L zRcxJ6@lBL24*GgIG`pu}Fm>)V(74TiUHEIizgDo%jVYA^SYdl->4(neh4TE7Z$8eY za_UPt(QM*iI&|j=)=zVlOauCiay*IyzU}bOE1U9wP%+02$YL7tO9#E-0V}XD0Oa5J zA9)g&xoHrbk`jQRQyhN)F6P@Odo8Ks;FY*}0h*+3-L{!>&I=vDqxH&TN1U=2POSDf zID>R=dMze*&QVOuS`|qbavDoa>{vGLMd*@sylHbIP_*kpfDN-l0>;L4m{^=~je-;sghIGe5AyU>Gj)=wJk z@f-lxg@EYW>Jv!zHsLwQD6l>NBL4Iu$;ct(Kl#li*TTRsn1FUq2mN(Bv(7Kufp_dm z`eIgF;FlAx2RT@ccp|=fG9?0D3D~B4%`p>}ZryD*T^+Zv3<3|^L@O|oKxIxI3?an0 z?|IVQK{k)XLvyrtwE=b~u?eXUTC|<5oS;W@R7uUzbFN)Lf;bMw`f#P2^qg2AJ{Msn$1SPDFU%qlut^}L+&?J z-i9U++j0Xp9)iPjS#6!j&>w5!@|yzZ6N67eAZIz|vT0hfCw=wcXSg`9Inn2fx9(0H z;tpsYn0Kj(5PQfSE_Y0J;ldqTkkbi0a>_FOr@^%&hd8Z&at3!kr*zQ{#mmOlF>#7qf^+F%W9(BU`BDQrswl%Bx&8Qp#K9WZ=orgaG3kn4OoLMN7=>T2yCWm)!dl|8O(~P`hOnPc5Y@G?C|Z;tnW29z8%S zTNCFYCsGF7GF>}Jg6Ro>GedDE6qFNa3FvaJwmd+$5#LO(eRu$#r5&?xr7w>qZdf%9 z#=-nHBDXkq6rh6_(FENedeBzn0)QsPOdR@Jv$C3yV5||Tzvn<-39|*C8L%o#pXf`5 zrhR95{o%8!(Q`2XfGTt3%hbv@R+0pT)ss!KS>now|NGb!c=0+)syaRVSJ%9hJ_J!O zTY=VIF4gt6N~#YTzN-x|^nW74$tHcGDX6}`#gVsxlrf?Yj5(Y5l!oCoRmo57kA%$w z&E&3(UGcO%r#_^>nyyGz>_1Em8F63qSMO`mJl?TXtQRZ4^i8Ie_ZYEAN=czWTH-XjUFdyXShvOU zX9iyZxW}6;Mb@dw#%Dovg!oVTh8HAaM3gp1JNuBl+`I)Wp@~`Ss6M|mC14cVIrJK- zWXj}WaV4_>Qsuc|~U48ORGSOew5YN*mL4CNDklzjD6bX_qS&Qm6 zA#ur4R|C&;^0CW`ALzJ$y^)6hc?#MnP=|1KbQ`s(z@xkZXnMR5v=2y}CT7XIsg}Hj zCS|A#v&kfl@uV;(kAOrsO+tOh#usurYnSl;?WtTdyDtJBm94{~5qIw-WRm5GS^$$2 z9R}1_?1oVtf3~l0Zr72g*w^t zgVbhVdgp1>l1-Z_&9@3Pa7}5{e@5v*!~3X%!bm8LzG>ytG+NUKVz9l@8=({EA&$tS za-(&WA)R`LS`>Xl=%Hi?`4~?@j4!>GdLCEO_Wrpc&dr`u`dxehzBAiDF+>IrJ-{X7 z8aTavfuAAVmHMI=(|9DO80?9|sPol+qoo8Iv+<1CoS z4ct*g|Lf%s$;t|BJoA3m#m+t|yvh4aER>`!u0$(^^BX*Hlgu&}>-rFZ z{v`5Dc2sS@1vmy0H=bg-x=OWji(FUNy@7t+lX*MaAs7{g_2}Et|S^2 zt9aC{T(rqIujc36F$VINya}Rvy2&5!u%8J8wg-)XIWGLn5}yE|`miGA+zqQwpN-C2 zdDaN_h8wqkx8z>%B$BP(+gCEFbWxpbqHDf5*^F=~%DbOV1aWFxy+XI-GJ6fI^_h{- zsp=;5sLiiWxRMd-`|8%;$ztX>Wpsx${yM{fyhB_WiiQ6iY*zxf8QWczz69NDtpHqj zYz|rp(+{-V9|e0B6LdwY)ZRVt1id(R;|>}kx3u8s9Lvk>dFcuVWGiPpK`U1&VwcAF z!n(aZhH%VJm_2?5#{M1On@>%cR)Eyh6)X5+JHhhXnq1T|8@bSDLu0f92VWrdd(1k{ zy6rBWB)t(2lmPTeH{f(#7%1O%4kVVr77!mKb8hfunAXlBJaA6x_XTs#dNu%fVs!}Rz8GM4oKOqNEq`<9v1v*5SDXZ zMt6@smd=E!buw6Cbhkgt|+zGpuzk5CWP< zV_f1Q`ZFK;QnV=&c<;nXHfMJ6{j+|BRm>BMvYjh}Lwdg(T`9#*^jA9pYziyauR6*% zSE4D_j_`dFw0Ve;YWaW%KAP2z_v%`1b8zMf@|FX`eJ#?lz zTm=*yv@+QUbo34DX}O**;2LddL(f%NK#9NJP!b!O*Kh)DJONQjQl@p=u}V8*3F=tW zdm_Ba+ZGzH;JIV9aLR&#c6;c6{GL7`6+i*IXdlTd@oZa+HA&*K)YM}#>&jW;>fk`rLDTKO;U*!$DnhR!D)@Vfp&b1gD5|HMvSgVJCH^S z@#`2t%V`Tl$%PCt3>1?>W(`c&fQx=qzC8Yh^JGsRQCx1ugHBx&f%+`X9Y&%48s2_F zi4n|B&Dxu5lImeG??1EiF=yM4Z+DDK@@m{QWVk)eA^r$`jJ#uKd!Dw+t8>eQ7Y{}5 z%T|-M^mYAmo`P8YX%|JmU(K;0-{e7lPP`g0@~GLI#~TH7fAjfFO}`QT{2oEgMxJRc za6uU<_Y2%5IAa^yZ{yNzUs~sgL)Y4C#FBZM6`I3NaZq;l>>SKrT>HE6Rg@iot&KBH zN^+D`zh7>$7hX{sGY7`=nJ(A+yE@(j$n(H@>FXsjuz$y(_tX>ZaI%)FrzC3H*kyhV zMrgS%2$NEr$L6sGR|HB2m(dSrG+l*@sGItR<@!%gxYj#;^JL z7ARcvkP`pP{hI(Iy0BGfjoRI#jsj>UHv>WXq;fT(N5nw{NJrb)0>TwscBo0d;Zz!6 zW(w^Y7j5iHOU~~Xo!>7^=NEa>{Q2`kW3A2|do8<^FSY88UdxRb^73D&erTp7LBK?= z+UB%*eK_de@7_qZzskTi`Wh{u7Vz!$;2EV5{M#pcXM^0|eNUEomH06AcowuLm?qVQ zbS^2xGYTg_>uaNJ|r-?J+e_kQOQ@}#kuaMQ{cX3Fo z&lx7(3ZcQSC9vWKGud7D3=?JG@O%a`s>eg`BCG_TRIB{shpT#^{!_tjARP^v;^%fw zYACRP=VdRxx6AX~sqo3DUB0Ou^gR}bx@cX=P0a@Z&r$|JJ?QLG^e5erFDvS;r|xyV z#9L4J%LEnm5Abll*9EiI2tA^(%4*iI^7gM(o|~VyRHye9?YoV|lddBIAfFAZ*HpS0 zM1yK3Uf1&ggWnOR{A01Gr7aW4x3`XIt|hc6w4Hqh$+*lDr~X5IDjm3hN)vg5q#zC? zP~oTa^c_8BYJapYUsv3De6=*2Cf2vN^q~H8FKcfDZmjX|dqpDDL@+{8Bh>8`0ET4< zx1_$n&Ug=yEW-il!F?U?vjCeb^{v!IKU)d;C~Aw)t+3=!eh}?M!7`Jd;v6kyz;Jnh z8-)k*`uXHvojGw7>Q81Bg-hzp>~R0u)tw<FTD3Vum1nx#{(#uB);VA-6#ZlX=rK{?%iNjteA(IaysKbppnBT^ z0^Qrx67dHYn;3m8g4~c{VN%{F*(fv4gF&oT1@2wpJ1SHx&>4#*y7r}|aP1n$Pj8)^ zxn)`+PzsH8qi4sZ*j=?Jvk=yWD^1d-wu@8Cm$MTL`^}kjG@*Zk%g zc>96%Z_bVq^!fU1ru1K7%sN0cdqOas&M}61HXh_AUzrthx{88ui`3lsU>_=aA zlRvUjrYh^U@^w?k%k4t0$^La$%B7}Y=P;QF&)~@byjp*s2Z^Z@PbEJamVwCSRa_}> zH72tbtix2`Y6l4sh1D}Uno4jZ>zY|yV$0G+v{^0Zo2m@ScGw6IMMkv#x#q8Y$)=dY zGmd$?bk%;*KpYooT-5%PK##2)H1{J6(4z-^VBVCzHlb6RI1cM&CQkU;fs9MrIyVVI zLw4$-J-u6c9do;CQA5t2bd+RI>^3Lrn<@UV(4Y{~95<>VP`WlQWMP-wRWo!nKvh>H zJK>vn@}T5Cw`UKM(doQ8%M3T;e4p>T)8o(%&@zsf<6W+l7M=-*i(dU>KQ=?J5@sOg zBmSZ-C;Qfj>R(?8cPJEWHdORj{*5fL3}>;l(`bz>6kh;FZ<1ymy~zkVQFrcY%w9V| zchovEh3%BN>@}d1vetl3augb9CGiGI zNo6DEvI*yqjWG?GBtjNc@v_GZC9sb$b!7$h!;j;H>gHc+pxs0#W_Gmx50p-r{trul zD^1WumirCu#uk_0lUaj>quHAdF~2`oE_m;&pj7|r7J<*_0ou~J&3N1aZyTmqAtwFp zj5s~9r$x&0d1y98;W+0S#ZTSJ9WOv}HvS6@{%y%j2^^{(fsqwQT(VA&a6pXY zbkttZ9~~KNKiNTeD1D!~URpcS*^OHc16 z>`xFuM{?!(AtvUezr@%V{6bu#M4K{7MPudj0$b0KlXjUBFUu{qo z3hIdVtS|B$XQkq7GIqS`_z0hw1qibZR&*0v$*Ju#p~D34=^BArQ3T5XoZ`2zm%O6e z(Qblo`1~5zws>Oaq)6P`%pz_xl5Flsdx*OV4}MS2`^!qCVi{q&0dlz5n1p&$Oqz+Y!~ZZ=BNKWwD7%%Q{(O@HnAyyaysk7?7iX==jlX!uRRwvvX`bz@-}j{b?=peUYWCJ}~m zxP~W4Ov~esxn{+e^}HzS)`%AXNjD4Fyh6|VfEIjXU>!x-p!=nZ@PtKm*Q(tYzH2~h z;CJ7p#@@HcjcSVflKsiA1 zPg8262fB@s#`M%hBf)$aZUV0v9^_p~F1`w-A6pWS|B*styoirzwTE6cu0#AdXiGsa zMe*;J91+vfn6qdQ4R>~iad6jvcDCgf)31$Mg_Jp!mn?X!PnB>1tIkXTIP6NxJj_@^ zAJ>YvfC?S^Op^Ds~;2klX zoi^~Z6_A>XS1OJ1m>5Ft=v{*V8Hv!@<-R9gJ_}2hr6+t!IfZ{rmzgErgqkhiU1q)O z%ez!*Nc}H!+1|r$zf_v_3TepgFY{B5STF7#I<%A(b0E#@gwh8c4+=q` zkz0RITW;v>V+!#_NfU`9UPzYJg>;h|wFh=Se3#<2KNQ5uF2!6+n!6f(-y2@dtmyt) zwEp8#w2@>V7P7fLs$%=JSNtz`mFFJ{Dxk*Bu?gUepSi}<`<<-mQRao6O!qXuYOo*d zHXO~T=t_G@EvDX=D18DK1RYO#KoSeKaL<^>tggY*t7AH8GV8XN%@-6GW@+MdZ+O>S zL&wRAdHrXa(8&_?@VddcK=CwaN-Xu%WYK>?w4Z{;2={P>se0`cP6{YJn@!guCsf%C z*fOW(BWriS$Y57+yCgrNvHT9KLOB=xWbMCJIE3YQ{ZERyXcJ>Wvg^8^bI3Y5jykCq zp@QC_CYL6GHfY-eIXS8Z!BJ)<%k16)rh;YO3t|y;R8L+{qGb3gAw8hilfd&;e<=T_ zC{*ZTUpyT~g7Zr{TG*1=RmQs|e?0#9oNi z)1wleQ1qFdi>qlz-R@0c#;~fcq`IIweUbAQLA!DGtHV(me|Xk~LH?@(lJILmXjb2k z7GRHu0WX_i53%IS=Hpfa1XEXH2}uc2smzlK*1&zpT`dp76Q@%t`kgr>`j_dN$_;Y{ z^HVyucY@T&{Uh#Kt6!>5-i-)OAF+@inUSOI5Ng)Iu2SRSJgdu`w>P`pht`okRU1WnFU-ihhN~&^wKw_r6ylg^z-!lZdgVChs;t?q%9v=x%<8Kl zd3i~3&J|h@v6i8sr(e-A*7#NKBjZ_ zBGT-t8HYE$to@RRc7DOsaA*K^m;{)3+nwpd0LY zcPKkmbh%m8nQpgTK*`c*=_n9n-L2T80bKu+FR}{_1;Q8y&pYWRXG=SB z|4ngXUZ7*3I5Gykn8^o{oI%0Sm&!B8s!1bUvUbP3_%@307#Z zhdJcvv(cJq3H*l+ZSuO|Buk13oat9_wd;2$wx>^9&iNUIib z7~QVpAGr=9UR<^T>MU@$sHT4OjY1HzPux5_?vD0jR+TMBpEX5lye_%cLSbW^RZ)xP zfBAi@2*wz#LdM!mu3ApEx$yWf*8p_~t?qp36LG45MilWd{BD>MQR3{?HDR<`Qz&Gq zrCTvO$#vrcTJY1Cps% zWoijUavoLuew3uhBq=T}V)m_NWW!OX@-p-xIJz#H8gJ<{Mw}h-Qk3*Untxf!)>r`h zAav(#*Ni7Ymn#Q0|ASom0%9>+ETlSh>2T!+24A|5B>Wv?{SiycOZ>IiWVm-Fj;qeU zQN`(-*Lvxq`L*t-ih%ab4<#Cn%U{|dViv1F?dniiV73Aln(JEnTLi)hBfhWO z<*7rGq1H`PU|w`KtW!JC^?fu(HcW`RbWyXJV4>?gi-vA-i!ZyAtav6Gx2a3R_XQB# z3Sd%^!xkSg7|EV8A@#-$eY=e&^jJCxUj4W@p`*0$?#}C+e&M0zag7DOs7Tmt`nw_X z%8u;D11O{{)5%l{GD=c@&ShFFlj;E3XHJ^PPzDzWPgx11r_fxnA>TFYnk%s zA8}Syvx6-#ZZgg&f~jy^B{zA=+3y+lVTyMVvqbgtw6Be>=2ng6S|#(-S7Q9u>HS_3 zD83HeXNj>iOUmItFubdn#ce9;_ha14^NUiIY@fZU-5XymY%yImNqx7&fOruC+wC*5 zd3N6p<=F&i5I+i;Iu<>vMYMn5U>TtBV=4h_xv8q(_?Ko-qPch3L(INSaD_x@$Zy**7-bA z)Uk+RaAmZj zdwriQYyQ~x52pdg#9q&K_MNxRpDUgYaMbKfCcxadv5VT z&1U|&)P+tIx{%8DvY}*iAc6lKgO?wc&YdY!2+^-DRU)$s5+U*P*ja5NEu(&A=5}!@ zXV$rJrlxA^Y<3EL&HIo$z|(^ssAv7b5yGGQ*j}*14$_uG?yNaKO*~NlprMsD?G`j3 zytWhYpOvl$2Qpr!`(hDBEHd$>-V-wt)G#lM|7wL$nY?5_6FS)%ONgTca+oQ95 zdYyJIys}Ajt0el52qLj!LjR?5}VkJ zbcw@us$uFsHO4cbdnQys9IbD#fD5&sLyw9o6`UJOx$ICrTVJCzkusN*oz4)E%iI@au}^x%XQB z15{H3l?ElcD$@J9#2&bKZp`<6nJ5vY+{L<=Mb8roNUI5x-IY`P#{P34gGz*NmZ0Uj z{CBUPs%$Ly0UMY3VVRvpQbB`NQyAfAp3VZAA5kXds;#E50iRY z>B0Ea{7c;L6`Q>EN;>K885By^cV_Q43==D9gih2Z>sq0L{5+~)-zOB9P7b+7 zU_~08EZTZm$nM^5?&FhI@FTf=#xGb5hoQTP;jYyGc6|FXL^op!%Ko>i=@hAoJt?Mr z=cZ}hsg5YXR8xIxk{ZGJEt}+rPDt~gs!>Ws0dnoz^v;jCyU~#0-vbKetosT5hzP?@+Tamr%NXEl})X5+ANX#u(Is@ zgp-zSTd#+hkXpw=ibSrpyGx%e&goG9mN)YJrc=_&`N&b!xDs&}zhj!Fal zK(!9fyD)YMuNELG%f7HQqX7aC$#OM2=r8W<3p(zql$x@+{}{&hnStC=Yj;rUG*t@Y zR)b8@d6c2%vD)EbJ|Ob7hA9nS2~A%mLGm%LPIc;%h)fn!W%+%9@`unsAmC?{jATx- zUs5uv=Xgn z5_9^jtOqu#|63O0);9UxYdDkoRuJmX0Jf*&Iq|u9B*BhFgnwlV!5tz$y?qU}2YOG8 z2cR+-YL*J8H7wpEfMCCv2|1x>{z^lpjSFy8@9?9Bar_hn9E2hYely<7^vle+q}rC0 z<-<+Ha0@+$LKyJHllJjZ&I(&`+_W&Yp_z@OE=;2kK86+T)2czST_Bt@=XcBhvo=Sl3u`{kHv$iI+@}1%{SK7Z z@#(1W$x@l{Tt_i@Z^4zUXU)&`C9~F?>oVkicQ3LCOE?iRc@^P%R|&-I?~79<@@O{N z`%s=f{r7{eHrjua+$U544Epk>@n-h4Dx4PP1i~hJSZ?v%T7&^K<;7x5>1EWSOnWp(`J-9jrezTG zx6gu=&0X2?z88B;Ozu2Z8ZaHP57ah|p1hK#088+*uW}Z1xM}%>1nwH4CGF}P>#jB) zy&wGj(P7pBRQB(7LXs_e=)6ZnVxHMGkk5)vRHoeN{?Jqd&X+aNX84rqgn=Y0anHWg z6K|AgUygrup|gtwJ;LBMb!!9kRnpKE`#KSA3h`Veuvcm>@pvmI?_hi^Ab;NZ=s)!E z|J73_nv6=BzR(VCw!l!P#!|8~Nny@aZ&`2$Qw$3cXWp*!w*qZCjQ6=LRHaAfyhV`L=NB-O(t3fL71`4kC$ z&&Lq)#Q~ZQ9d_*H)e@O(`qqy{1x*7*69){8@zdD$L_@z?s=1O@$$FqD->IU#cg+g} zCHG=FF2Eop0JuzOS|Hqw=yL%hgmV)Nz8Y7YKBK*VW3zuEB)LHKClEQz-l6B9au;R| z|BhK3{o$nCTgg_aj^iTBbKg*r2PU2+lkwFF+aBWaPNhnoEa0Zhubnpy2y*o}y+(=cQL(&rgL+}bfl`}A=o>;wimg?UyW zJOEXbKJ2XUOXRgY;JhppT0jY>> zY6Lvwtc4gz9jZb`;1*T+l>1k$UWrz_y9IuFxnp}@rmO)7l>_P3UEi`8 zkjROViS9sN)VQz9A##r|&Pc+Ot<*A^Tahxp?r$HV1kai zuiWKbiP|qP@daPs3FIrzR1sq~Pf<45!%@Y74dDu5Ihkcm0EI5?UI4nTojtTeY<@4d ziekPdm{vetEjEo=Njv|c(9I<##zl53tLRK2=H2|6_h(aBTWkR2d`PfkPUFq-Nd9wM z?vmTxtJ9n{M8!!u@|e;uImjP7NU4a82d2h6v%JRv(q6k?SmB3F2cOs8_oaV%8pyBd z9}gJ*Y5gX0yNLn#S<9J7XrD*kDB)Djc9UvMSg)wL)QvVzq{8j4=wvRv1TH-cuEu`@ zn@E6)dk=g*d$n4t3Vw)6GM{8jTMq#FN;m+%!#H?Qa*`~@V5<2_z|;0HrEf4sA2HJLz(Qdimu`=cJ(G8&`6ME~G1kJepm zvty*;Y34Xd1Z2BHouGKW$g1Ss*|Tl`O~q-=K|#hw^77d#>21XLv5nxUlfPXJWI1A* zH`dkrZQ}*7F`Ep>I3^=w$LZq1nA>01knIBc}F^Iueu(pjc?Nv;NJqcDYC-u`I;v9RVm{ zx9m(026}=azVn8={3+1Q2OA_;VJ;Lxe148)n_8M*;_LO(03KvJ(3Q;{z$H@JRmTj% z+4S9sMU~DjsPQe#0Wa6HnUwzuWL#*hl9B#aV$L?h|4ntl@lBbB)!gp7#37v}jFFyJ zyOObB&EZvIqtB+u-|&q3`xk_)Fr`){Yq9C@y_6?!zUl{2_LQ0}@Ts7E2E}3y>MJ27 zqf7RHW|_jWM=DWosOYLEWirt@a%3Us1O@0b%zcIpO*rqWO{yt1*So|#!GJHCk?xEh zwSDfIXN$|FSycE}pS{89gkB5eDeHR~E$h}&j$?8p5HBP}oi|9`w%LD-IA^(yspMRv zq>&K|-vW_!ZEz=&h%>feR~_NiUGQk2BgRtoMP!m<+bSr8-zY*`c=3!qWiGN;l{yr zKn$d2{mhu$0|6ndSC0VO^BI_GjlZ?1v>1kmKB&WvjFtUP75mo;!t*5Fme##DA+2{D zmPl{;N*u^f-Nv-3OZN?T6E9NH>3UZhGyB5Agc=N#E0A;5px0hwn)#A%s8}m;e`XP4 zX3er5Ngmqk4hV1Kz#j-9tcQ}@0kAv12Ljh-m@wc~4O;k48=M{St0ky}!?sPW%}8$z zOj$`iEj5t&D4+|Zh!B0>a?d{X+fIvg7I@C8nizC+W~2jG&KcG;p-_%s!EE*R6bQ$e;kJu2x zl7#fR?7$>-cz2Dz^IW3odYWj8I}qv6rH3(&egD{zq+5@ z&Ommf++Y0Et7x$`$?gYm8ypjSiYu}vI{jb#(5rOVU7NJ%CNDbP4OCWYbK`6;wAQll z=goMD335uc!qp}(<9BTPsGcN{0+fMjlyGYM^4ac!Vt`Jdy)-J+?*BbeFsYBc?AMk= zXJv4tQ|W2iMs^%vyf3Hh@Nu{;@=e(ygJ--WER54;0MEm+0E@R_K^d05F8-Hfzgb@4j`mTbO=a z;O=q=Lii>q&E};*9){&s+$3#mZrualK%X0IZt$qb{0-oEbq~o#VHe0W$y|RP=$*#q zP!kktUcoKtkZKplcm_%U*ySEsL0{pmhK$3`p!eTmHXC!p6CB@GCu27Uo>vapER!d^ z9RY@y2iLGJ{tKXj_+7u&%Gl9o=>rLi53M+)}k&a|}-R(%ibMiL4J0$*`$t z$isgpH?51uS(LD6d!+*qlx~87WJtz3Z>RUgjGK1R>03M_BJIE@e?*)-1p%Ao3yBpa zrr$t$9_RioNO2u|;}{`Yqfd4(OY7@!597iT$U3a1{wOjLyoJ3d{ui39&bD#j*J3zf-g(dXqlPL&>x6XN%kynAo@2h!jY)WCpF6y zKWv;!NJw`tH;CB@O>G^Rw!aQuGC`y0=8y=YY`@2UaNm`E3iROB)cg=W9v(~{1N zJlED--?;Y=%Gj$$%f@(9w#?5;j1AKRmw?@|-XAnqFYH*xU3|I3nY=KS$_B)2T13ue z)5gNebr^}eCXE^Ie@oF20}wVGBsgN3E%gW&Mun%SGauWXS&4WY5C!*1(YJ+|O^KLL zssXJkbaP3qE~)`={-EEffo8b_TtB1r&&B?wY6%(llV2^x#LN;=6f^4x5j#K+pG zX5#=Sh_yo=YH&YLSyQ25cf5yZ!wprs`6DLru#@MM5LLkW6CiTp+g{hLoA}qo)2H0e zhm>1)_XWpn1jlHkuG=PuGDN?&%rokjkHeCTD>ddoow`tm&JX^`q>I3@q;-}5#HrNo z0W^nno0L?L288R8<4fi-+hZkB_SoAn7CL-j5j6MG3Jakjre|+w|LOB8S3e0Enqy+{ z`Wjm_`zcg=uov+KTrblLzn1aHF}PX7+|(tIuhoX|)LZvA4h*PnRR2iOt9KfsVro<9 z+aWI$U8bglUk@e~074ph?yv!Me?Z#A0Eh8l48=HWlXy8ckh@EyUNiFsm0PG&q`saw z7_&>nsf}1%^%NCn6V|`vjwap^J>cEYS}udo-zf|mr_ZMGUCDo4vqZtM#E$r*cIca7 zWB0_A^$)HVGAUa2g91glv=);rk|>=e=+B>c{}HUozo|E?J&U^an1bB_v75Y_;|)Cg zZhTh@Wj8N1y$k(6UrzW#IK&T10Y7~AlRwy3OaHz)mge(MBBHBlLPOyM>4XEfk_`R( zia*ZPON#fAlo|(|zS=d+MC=QXw-*my(Io<^=qYmemAfDE4Vii;tFe^!8o?Ryb>&Wy3@Oq zIw0@gN7@}!a~1KAS1`W`g4}X2Eq_OQ^5by0S&On@dqck*SaPRD{Zp5J3|eV_)qfPPh;THa(Ax%Q;(lJfZ^=h7z5B4!I7h6$%F zgkv4TjIZkz&A#UF{pLfHs@I;yKlH-&F@J>l_HIUS!e}w(ZWM1-vh2h$ITru8=0>|L z*y>VkHK0H|cDvjacy0?=^2gMXk?|<3JHIrJG9Mdy(b!RA_>ej&UO8}l3iwrr%TNBU zGZ+I^JZiLkcZ?GH;lu`m4_RUV3|L#~`$8DE{(O2m4{byIEj2n>{+@gC&)O+!)|dY3 ztZ-I-dm##7RX$NIMgk!=&d`0srjOu5`rH{=o84;fRjlOOx zj}E%z`|B>%2fHfOnT+3vf<_z}w&s~#ta}5`in8|d_hPR2o7YqAoYXg_ju|>VN9d&6 zmTPMEPT>JdkN+0W%%?}KA3T%*?61~K9a3}yp*4ohQu zJygOfp%9)nC|{ZVbs`y-R;^!}PY3JL9TmFOTGTR0Qi5d*(mubS+8#7r4WManjW@Gc zRBct$ZfJ&nM&nF+X;{wH-xPUqh-b61e59Wwq?sg?ahGnZTC^*>2qR4-tiGuFbv85^BR+?m2i``)^y@O_qxp#s^ z9<@U@bl5rH?8Mt9L@V^>;DLF;s9ORg?Ahv@eZU^I0DNiqY6Em563A28q|_1eC@yJ6 zSq>o7x)`ynMc4F-cl9L3dGmMoH$ZWp<`BO(02^Djr;|Mf9TMlQC?g-DXYR2Eb2|xl zJh((8E4X)o)MOa`NU(viz-qSWd9m@ac&=ZM^a9$dEWH2gl%uCKGqWA>4dU+%Mfc0a ze|5@L7fn!>l6SLYIDc?3Y@yHaJoad!JW+gv%X@KA98XQ7PE&&ZGFwfVGWyw1bV$^T zIr(9Tx1Ep|`8UuQ4;Qp#rWTRv9DX;{1Y|nyHxljH<%LcT0qD0e%7)z&2rcbcG1AE5 z+jkgu{uX)WRO;AqLJ@9W3WFJWJb*k?Wa$K~z+j!zbKlwIt*Euj@Ul@CwjY!To@=$aRF;BOYjE#<=g1}dTsV=4p?Y~q3+~&f!gS!aItSNf&p#ESYYiXUKz-;`Z97ILYmyL1wsM@ipeh_6??`Ud-g=I>%^3^kYr&JVqp-nuNtynORt1K*dTRb`HZV1=07-B*A4M3 z_7AZrgXl1MewOwSia9ft@MycScpX{Ut6m*V>*Dz+zGq88@xur|ibL-Cfn%8tAM1c2 zvz(rCh=VBXwLPzCDkflQz}<Iyn>G{z1V=*RTk<@CCIpJQO`s+a_W%UlNXgrc@!35>lu!-y$6 zb7sb*>kUOFZX4V!lpB@%T$tIwq=jIW-?I8qHBn#dXsqJXVPwNQaiARhLXGp-okK#o z$tBpVgJT9{oJdEM*mV99+NcP(K2`UtAxaJos3=m_Q=ixnkNRSY6bJ-mShjK6683D$ zTsEib!pKYr3^^G=0gSq<_JZQMI45-?g1^+*N8~e5k5y=JUhkm_qc!@UVF?Xcmft&k zS}5}j-L4M=Z5|U1uAsrOz_7*)Ez!pWT5ov!!uFyLtIZRRK)u{> zqI^)DqVr@p`9SFb-Q%OmX3x7spM+zNDa+#+TQDPn;CDkL*+5x-h)B7;q&TXrnDp-P z@9V2B)SZ8gT1!+>vFxTojhaWQsO)U~35sqoAYvJ#%)W?WwpT>&m6UEArh4ySUZYYq zHlamjZm+S6$#KhYcWR!a`i*3ELSE&}!Rk!T^SM%TV76r;WTy)$kHRTKr2j$sQwN9g z2TCF#*O=|Oz!^!2e!q53SE3P9M`q&UZ&IpE@j?D`6-i1Y4p!?Ve})xQ84c*->hL{) zd;)=B0TEmSSG^l~Ol$Hr|$ z7$+wRf+X!|?H}eivVR_5K(}598~2pr{U*T#SBg{0rD;YS z5nMnJF^R}_Ak;9f>(?B)xEg15KtR!_3;a76fo=J8RVMH8?4-$rsN|h7lyI)xj3ZSq zEtCV{;-@ILV1gvZQk9+-;aJGodxW#SV0!%xnL6a2cB#epC?N9$bc^o%WwqoazDSN` zX%_||mC)=M3tBY+whRgePj>hiAZgX{iHCBo(!*D5k2qMz77>$JC3i*gm>=MgZ(Ou1 zFh?^{vbU{kxVGO47Et&)erj6>wlqT!rP1F-tIacW>?n$a7gV?6lKs(XSYC%->e|RQ zC*YUMBV$j^->Kh?$^_ZdmN_xMM=HQB6S{3dutN&&M^p!h8Z8bo1Jj3#kDuPFtjUW# zLrZgN|1gj{j>50HjimDIJbvcFIuI4m1q8|rkzhTt?Qu-Fuxt^O`#q|O2cyL)Ij$lr zI?}+InVkRTXwS%ZB|A4`=g<_!R)totBfR24-<-HaTtk8BIbU{!8IWNWH|7>vD8mYuzn zt0KMWRlB6Vv!-9h6B8qUgVH8`q=CvWC_icdEB*2r+y|e3v#*MM)MNZD5g|a)BpWru z0Ygs#K!(piMiH5a@ZqfYV6+u#x0Hl8N{EjT^^e1fB8>KknBz_qAsqfzPt!SJ2#~xQ zPp1`P_hSfmFcBe3{R8Q*p5C15q;!Pd_xx!!K zL=XK#(fW@kXh}Be_d&+J7_2{%U0x&4jY6X!&uK!j&ME}?=#8ICLFy|B~BPR z+wd+Rhn**Dt8+uME>I3vl#2~#Qh>p3B|2@|oNFX~J?OV32UR;t4FrJAS`KFqh;LUs z&lH=8@h$qe$WlH_E~2j&rOu=9qKMP^QWAbw`S`mjf zHoeZpHJvu4hv5u;sFPX58vIPDoh?pCB05KS@fd(5Uzbw&sEqI;fjk(X0H*+TTt~o? zq6{Ksd?-J{F<>Zk*9NWS-C392iQKqFd8!P&{#96YU+q4=&0NM<(nqjp{$bTzXEplj zy8m;}u06v%&u*CzR7n3(!OKIq6Wp$ zrZR#wK-DI+UL6F51Xkjm|8xNqkc$Ctu->meRHL(QW`IzlSTY#Uf>XB1xUy&c2h>()FYu~V70e(4dfAm^=taxhr`nUrg0<6% zeg`?!jD&mGx7OLUN|jTy>;hym`}9Tbj_2W(wOj8;*@gk-0>8>=HvP^G>5XvZz#joi zzJA)M?V8WjM@v!HHobga1i?U|cv;vkJbdmh@)FuMgXmj5)NsJ!bX-*H`X~T7wPUiO zyeypzIdZXY$Q%<)jn58(~3sn~uqU+kla^Q&0YV?u-KpU*Oc3KG8Zk75!` znFcU2t#Une!_5CC1WU`VfpK#`$o1pp=et*heYjdrCczGuo-VV+ByagftfHe)z9tt- zvBaSH?)6XWiNiiBPw?MmvS#q#XAR)zV4dfCFHnHY4;R;^NN>MZY`<7$U7*nQB+0E` ziZ%89&v8ug8nq`2xc*n9ADLUo&6klnmA^6WI8OpXcetP(#dO@nw6Cv_%odQ1G)$ns z32njwx}qL#aLG)2VRG&aocdi-=Ql_{ulzk5CUy^g-&Z^LVJ^}0#TYs#?+8lXIaD5e z3e}Z}$zG!WP6bfM^$HIJ#Ht_K>4V54dTZ4}q$HXE^!LD@rG>&2Tnl=SI-Cu98<_;?iXsXS&6Iqik7|CG29`73)no zM6sckOgX18B7m8HR1op%vgtJm+~Xj%CWrOwP^=2xwZ&|~%LIT<;0o&9x(@HF4t#<9 zoPNUm@k-c3#y6zG%$(*@;AoBnyV7Vv@+dX%anRW0{XToiT=W+wj?DSH;@P|6Ummt0 zzm=bo-0H2%J|&4xTN2-REBvVx^+ylJKAEQp1M_(HRJYTVJhXOe2}5k#4|OZmr6JE!D_~y{&WOx7e-+j1e;84w9X>9{ z#j>d3HNv@Fin^n(Q44@M_q;*#i+aF?i-*-tqdyn<8S*W;)+m*yI_?8QI&b6$SVwY| zEWuNz@=Z%l_1zcW*h-%7;=A6oJ-(@roDyL~4YIe9nF3kDA&5C`V{9Ju;$9;Q74Nl} z*Pl%e?Va-EBwN2zJW=`8Ni&Z}HV81*cm#aFh}-O>V8NkB^WbIKJs{_ z_Y&#!}fWdY>!Uw$;smJ#U24_MTZ4H=UABo^>Y-Io9be;v~Z zzIPLUr)TF0XPjDsw^*kfycbD?924z7sX7VK@puz{R|&ohr%cOewQiC%b#S*}$^A%Y z*IaUybT9B7LmG!bk@40>TN}vpw^H^v*4L@)n}WGO_^6ST=u(ln-qBe6VcfqcZ?f#L z@yVHCS;O8g5eF{e(KNkM97?!QjboAoHHpPgb#hy_>|)ch&!+yVc#m%)I|EDfa*iy1 zxPt-j+>w!Cdx0GM{Vu24=i-Ab{o)CXzYI11tb)6d_n6YRMpJeQpvFrzZ1U)# zFA>>&NUsVK7|)ygvv1#Kgw3$2>Qz7(O)l$*4(({lRoTv`*_!}94;Ct4FQ~Z)=9NKM zTWFl2akNHcx|VjNQkms@glV z5Byb)3&*9Ev$Q|tP}GuAc%X(bqOsO6MvS^pQDc@0daclOJJsA$H70leMtM{I8UFc3 z?I%jx!P^T&%|xR)G)afjY>|*15tJDn7US7MF(*FCoX+kRR{1P-i>}2!8OD@Jx6STH z)1W@~G@fuyz-}bI7uzynNTc@AY=gs8ijZ9ml&RyCnJ8zTnZm$k>c?$*LS3O;gY zpk>PZgC(E&C$rWao&QVQvKLuzTne(eP6HQVbbpovVYk3qnQoRuV$E}=N(onFj3T32 zmSkpu zA`+HLw_yldqY6*yojo~tCIw$Dr(Xq_u(pYMRiDsE%JZ#@czOrJ^@=?9xq%5Rr*H#_ z#_@j+DxYi+X6Q4<_HgAIWMS;+GkrDX3jK$=J+D@7tY`IuC0AkQ5Y_F_>e(UELjCJg znuk>AR6bAHC#{TQ^oe|rd(;vzUon(F$4WGd>W*)3g0joJwJE>b5K_C^hDNAWgV&~( z5F^=r-v~BgSTzPec(9nn!8iXSG+S+2RMWQ}1I9ubjV;m=1gbH5p(nBILGqVSKEqeD z9}LE4)LOe7DE%8{8yf^y$FhXRl=XB_Yl<>k&;$E@pXO!j>2_5RpESHRcaLX!>{QwM`QA~Q;et_#;)vx zoZaf0lbmPad+0~iF{DUA=uP;oV02=F(&o`#BdT~Tm-}%ZHVpR*)@mGKZJK(iuu40Px71}A=}L=ptwF(41Jdb6LA5c z+`}V}VYC-z1m5xXGG|m^?tKiTdki%=@|m29{$0FW1?PE=<}&dawd=vVB3mlzCaj+I z0ZjOl8h7RX6_p|8U+cTYB({wmp~ok{h_@%V({^q?{^`AL34FoA8OyLM8Ms?_TW0;a zukCK!L?Fg(OO9_eEfA@+h%qX={@xU-m;ueP;naejE zd$+W11bLlthl%?@Y?RuJzm3&qF3+p&SAxfQ{0KhS!`Ur)2Z!ktE_`u)*21oW`=zPJ z&hPQFqfenDWpV4%pmfxlEP_eYBjL(;W`5B6fc?H?p+>3UwdDfCGUsPEl(;x9J}jnG znK%qyhX_lyFa+V;k`}s>o8I5Xpv_Ab)ngSd*JkoAnM4{${5|~?L)pHkoiIG3gAZMf zWo1#c#?5%@tvJJJCCo3imUfHIV4}~1Aop8lmfZtP`3aH8d6rG<-I%ruN1k0UO5`)D z2tK7*TS~ff2bPKBPT2J;-T}0ha9;FCIYICwISB6jVnZ&D+ZfaoaROwUnRugs!vLh5 z%AE`hZ2r~rF+nag7vqK1HSaGKo7$KrGAt5H8^oV}G9+qYJ)!nAut%S0_Tro3t*D<# zZk@WZ?VkFEb)Oesxc_4z>>({>;8P!)oUc7g6pgaL?ZKAI)(u_9dUeB{hktqXEq|zb zy;I%d<~+;AxO-Mq18GpUiczm(c&=bDe3ICRijL9vEFiXHB5oQ(!M={6gMpt}DRB`p z!Y;n!E^eAj;d~*Vwrp5|HP>k%qqR$;jxm^+Vo$9Jz4;Lm0pqS9P_}iEJ~Zj=-r17U z|CBl-vWDyM{-jgA*Xc+rviQKuhwXy@+XZeS(X50MILkx1|4$ctl*wmL2I=2g1u(0? zsQ-1x6gJP9I)udH3+&xgce5jS5Hle&LVc36^k0L2QNHz~5ClBymiE{!9#$pPuVsRD zPW?_L@!{H?%^IguG$OA-HR>Rl_#0HWuMci){D};w%zugEul_=tj;XBGK{r`;V|?pq zNiliQ0-b+7m;q*Rx8I;EQUn(Ze^2)T+q%6+XOl=lNGY zAyb<=sghG!oq}(bhBk>ye+?=->>qxP9np1ZdS*ZWR1x4~O5_qNYNwc;!}x0w(ZL`w zmbNHegJos&r@c`~2Y7h7s*P0jL~ZilUyl*7!C1~Yat|DD! zHit%2lEj4V!~<$1@t*bY5U&e)xN6IMyXx?57V;~fZ8bM@s7Q7QO3VoXlCLFFt} zGijf!|5wQ6^V<9XiNga#h#CBgW;@~t`h)Y$wDBl`C6T;&K zT_}4)fp$GKz}*~6+YbnL#v3`dz^E90VqnmUrLQ-3UN7TFjgpdhEKY6v&a+-RVw!Xus%XkUK4D}0$ZCJV z_vGYRjE7o1D=H^`xPo}@9Wt9!p(q^U=w&L&(J=cmh>L{sQq%F56KM1Lql&Gnehc_` zl0~JFY}n8rf)(mbqBi(7_hOFLc-r7I`HK^TVImYx8h496QCWl0M^VhzNMtgWsl9~f zMmCNHVYtSLdFJTwWpYZfdxM4>-$M0s{5rf4X@(`^$6X%2xL(YO zNqE|CT}<0$L>BW=ktMpCBPJG@6L=kI=b$G2sff5!1;Ast$K%KUz=2!Kup?3*O61L< zSh(O1oID*ebwanuItP{eKW6vfEmGZy#@x5ZT0p51KPk>1!C!)7zgYs+Mqxc}Xrd-4>aL`W8>^|tCc6=aKQP{S;^WJMD^Wn ziAD(!_vdeCI*vF{rX~+@{GD45YLSC)zeWAKOcjD2Ya!z{oZav_;tT0?zScgBpJ-?=Ht)@?WVgB>bu zP3rKeHcTn%3QJMws_Li2|B|wzD^h-{d)+if@)Yz~sSVqr{i7o&K5LAu-8K!rkV~L9Q69pXc^y>rr=|1D4UrOG*zJR+<@v_X_XAQ5cmt z)m1qKaK~<4-J~uZKboaP4%ox8=3q%f5hyw6^wzVTB%izPFup57RHw<6>t@`C~2g$|R&f|_h43y+vJ0@c;nA(W%uq*#FVF?DI!fR_D} z;rQY9R3r$^UPqI>iO0qwHEwj???;EwH?S!XRCEZvSdBDtn&tr4zMRlRy_Pk;%KS@a zQMvjy(&L@76n=|-A1mB{T${EO?q85G8}0t7;90C~ns_AM19pRcs?;Ze@yi7V&ENdG zjna0}X(Y*hZ5anQn>g9gdR&?^B8YV_y>|94gg{3;vMRLckrIV(h#Gl5!mz!iw7 zmW8xLLf=M|VdqK_>k`t`9e))#=qsF(+b3-~hp}dimL;-}l_Ek^`t^U_2cN*?lJ)w0 z{w>!36bTZOcc-G!mXRizb#$f_x4uKC90Qaf4vqh?7rjeSSva=&8zD}#=QEzbcY_Y2 zJ0Gt40E`t5;Os{n6>TvCy)mbMx(K@S`>_)BdNS*rkh7l?r$4u_?FH-v^+(6JSf zr90~$04C&xKayghF|G%1rf``Nf}mt9Q{AAbw}|WLy*^bIXLkjJ)HKNis;^yf?*;pH zFwmr)^K;P6jQD+zFwv+HW)Olc_S6Jg;x@UUF0F#&?s1MnIL|v$<0=#nLQ}{!T)Z=} z!vCP@;n}YUjnbc|OBN)MEfx~yTN04}&|N12OHQv|S#~F!EK+^+p|D>U7w|M2xuo`aSHFjy@Sx36MHW$g{i|Il=eL#B z+rp8@jf~KHZA@DEUQFbmg+HS}8_294|G<=@+$6vISd>SiNrQTBbz@Aqd;+|a7%~7DJ{wIQ4)`_%5$T~dc;xDvMv9syU zwMu_QAuUjmY~xx5_Hp&16PkOm4jWLM^qV$hiZI5uY5BI@d`f5w?^~D2sW(~w*Be3i zQwUAfx)IuNmqlG@q4qGJxy{{?DS~bb`eJ?D3eidKM8d;0AB-+5xtXmpq4c6@nsPdO zR-*`Ea%wqWlc&JD^5iAVqRQU%DkT2pGxm3%uOMxWv3P46S6s~w8CbsP>6ZOF?7thn`w7ch62DspvPGyM$fB%kTo zyM469m&gfheV^_Io-T~gPTr0?X8b68%>0}fr2mi;Ko!0FtYmm8&DQ($%Yh^qxbFVZ zumH*T0v1+P7&wC}d7ka*L^He$T$wL)x6#p(WbzvwB=c-582ABe5PgrAkO=R!$1wV; zSN-xk2(8lJP~=c6%H-Sqy<8k=)HWR^-wUkx;q4KNe@Di){%j|=P zV+EVyN&%7$&DKmgX!9+a+PMC~yE1Ux3>d^YHA0W!;%lc{1d|Z^H($-7h^xl;_90ke z>Und9Elz5EaM}SK4J9T@deU<5u{b5psghY;e1vk$_p$e-)IKOKr8@)`j$r(+O?MFm zhOoVM7g48LLIv8asrjNO(m1$k8t&WJ#eS3x;p0ap{Q$kHa`(F4;PVEADr#nwpcDj} zi?0}G=Oo-tBgd6`CMSe?xul8G8Jl%(0I{fiP0i}1B3G%>*a|d%EQ_a~^*6OVo0G;t ze;w($OkWyC-d#S;@Lj%mu)L;%^@zWCXsJk1N=Eh=Qhp&X7r4Nb92=rO^MQThgnbH( zWrs$2%I5J%qohB>M7WcHj{D5dqM|3~lt5rTGmeu!IDL03umke=0v{N`p%s7E@o~Kr z(UE3Q%D5ZaBU9a9$i62dvXa4$x>R>V>*yoPZpIB&f9^PZN0;)a7@M$nrwXnz8(>f) zJtsvuEwE9-#w{DG>khx})$%@XTVY%dJF*(#EW_h|zaEH<{hkwh6VU~@Jc);k$qCu} z-p6NG?ubay6F_5zgv7;>MZk8M@hVXpk~xJ0bX->QP7H$LSQFf9lBi0T?>_CNsyn{F zo{25My9Jiqg<5R#a3|Ywa1F2 zZ0SL7(`jThwJ1W{91&5m`7z_L`9)%2y%Ms%OClXbnDEdTbFY28*{VK~@U2+|T#1I8 z{Gl0a0;OuODr1Ox#pt+uq~fDg!n{=mkir(n@j(wR9kquUl$69^6OqH!$TeYPv7t{0 zx;?4;R|u?M1_US*wu=km`LS&G(OPmB`Y|0?1DZd0BS&_E49VC8{zuYP2Sm|*?WJpx zZlt@rL+S2(=>|bkq(K^%?ha|BMLL&|29Z``>F(}t{C$5g%&8 zJ_gb`4&ZnRU*b&pKY6o>yc2s3>gOYJAsKKw*pC7C z_|j!03$g)UQI(^fFVP_+GqqzsYbRZ0G8V?>jG=@L%tJgguM&BWuH;=$zo!63LJ6E;@`pP4!4y;Psf(_x zfq8iQ>U?fTV^fy0hGJmqeFIp&59;8`TPK?O@LzztS-hqW7AT)0`V@Vbo}HHA?*D)X zI3YyM7f2@e-qoF{R*)!`GukR(XH4B)(o|>ay!%_r=k|-Mbcs5~!j9=5ov8>jBu>6U zu{%JZ5VMT8#MTLS`?V6VR%7?UAV3o5?Su#Y52T9Qep(|qmn)3jbr!@tPiV=`C(n(^ zUAg+)LvU{vQq7oH<)xz2@!v=OpO5KXqkpHcBP9{VE@yS)-^^t3aTdNSQ01zt3#sL9 zCoVMD);jisD2`hVT>Am-SK#A=C=wqT9_R@ zdY%2+|K{ld)w$xL4@39QlZiY}v@wwbpFjeZsu+iwi)AM}^>^jG2C}qSfP1C6d%X{y z2mKyX7CyktpESn|57jIwsM>0E8UBRqSZfsVTe2Yk?)@bZ;#t0M!>os z6T~&fpBGtEwL{~G_ZC;vpCtn`c|;nRGBg;2-ln#_y-AoezjqJ`;KIpzYthz;o80ZLOhGaSzI5BC?fAG8@Opv zA@)iArwX{SB$;@9KZ7}NQRbK0xZP4Cr?wN0E^R)kem*buG{Q;ja>y4}JlS+Px*Mi1 z2w?^$Lhs}xilE=UL{j*ze=>x~!;w>cPAS+}{DiDY5~wK*B-0ZW%!30R18{1DXL(0~ z)ayX9tYsXCym;UMZC&W2@t_41j9j%yOm)-#mT1P-^Db7VuHzy%xc=mz_~>c2-b0jD zkEppZDZ##eHV@hh_)AKud4IE3w#r-mBEEYVe$T@iPy9@Z;pE(*+HISWg|*g|Bv_-k)3A)MPzr{nVDrU}aT7;iwyXYGN*jHx$a^V)>@+Ob!Sg z<=OCNwjywaygV2Ds<%bP^CIk_bw>Wf6FO4fti}`?6ZLGwIru^Xh7FoRsvu`*4Rx1V zxj7bM^J(7=mHe6MRd@|8X%kZy+0y1{*^X^2CAn}M|Kp;h%w(|sS5G5}|Jm^-tpz8j z80ot$=f!3)x=;mh5Pz2EamRqKRq=Pe?~}1~fxlyQ!v_Vib8Zi3kHCg65rUrU<06`Q z4X?+Ck;YuPyK?LfH?P*!8omw|K3;)147Ln{Za`IQB$GqOh9CJ1uCiGAUz@XFsvxg1 z@M{P9dqP=g)j^bVz|&ORPO2a~mYC5o9smm&w-*;IxUT)mV*46}CLWkE zlUB~k7+|pvG$OdxDE+$4K1mqIgEvtMZmE+exmzs(7&=rTzd;VE=HA^IK$nDwuQA``HdT zXN_cJNbCDYw4n}3-o?%&gJ(n%lU}XUb>61|A#^@CI>C_Z`*EU2Hbayn- zg`aK+gj`k&_i8r!Z+^OH@MR8y?h9>YDqr&#d!~xLE%mgz?#&F7lcJ{yd&W}?!-T|Y zrOXNUPv?GF5r*>P_BkbCrt8~s8_;I5UR1=}5h74Z-hZo>vn5YLck_1+dQ#=>K!w*Wu)(5;wcY$UFRGRZXzrjhSk+0hHQ znngS8GDuEX)+6`%;up)vbR`>t=Z#&cAexpu*WCn-#CJWM+MSJAFg1`F_ahlFMimU2 z2i@`vHXDL(rZ}|8GY8EngR(X{&s;mtyC+{%{2hGWXZOV5R>iM;k_$$TaS%Xw-RBv^ zF8x5+^y-$i(Yyq%cvqga_#w%CRr8BFv|QTQyC zX`cUumJSx6+gMhY5=5^c!NRf(#Hn-n1c5Q)N5O>ovF@*`4D}(!#_RW(p6&A*DTswxx^F8NalIr1~W9%Qq_&tdGqEz7R~Kp&W$!M^pRcyDRqfKK+odpVr*3IMldwG1lIG6`FSJa_{QBpfH8PPok&0Ej%VK8~6IJI=B&6E?eBT$#h8))|;@+oZH+}?x?h73$7`Lj{{ z?6~aX%(K#(xwDA&b56*n*W81AX&xCrB3j;jZC#D#Kb{=$A|wN9)Vxlvn#Qc%?^)!= z0l*~Kns(?ucZk>O<*QA)2CB`H#7hu?cMsR2zJ18LGu3Mf`=MYv!pNdS$Y3N9x*GNgZ6s`SPuRS+`O7C{4TU|kNNCv1~ZFp zw3v5Qp6OS6u}HY5c~*R~RD_$g4?%b6vN6J7SWT_Q(V_~~L2u2?sy@?y6BgdE71oWu z`d(K^D5UdR?;cIEbg^Y6yS~CxF(4nWd%b^Nvz|TK>#^o3!xP`LW%%udnYiUzb9~Vd zIfGeWoBCja&oZ&v-!xdf5diMU&J&_>{+t2sBKGae?dms`nyj3a5U9PSx<6#^b`{h7 zYkRBv*VfhxNe|*`2U9jWKXr$CnO&~7rk)AHkdEz@9$9Io)y(2abBP)ilVm=#J+Fw% zeyF*QCw@>pKC2C_>Oi(0F?hEH4f#_n-<)I(kTQWBxoSu^szBwri}WB4XC1qnhaYIZ zDmnc?KwxkE=1yyXEx+G9X0Lmh9LQN;rviXqESS zu~IHd+fKHYBinNr-v*w?X2@9xs`xsI;6YN&!O4)rS}>zAMIEJVB$Q{!#p`0Omxcp={oS#HCf1R7iTX^A?ZEth}=gOUCaCvsa-s3r^ zQQmJn&E1yXe#RBKeNU>9BxQo-iQm$=$V(I6PJtUZHK3l3g&NI|5~ zl2i5YlhcXX9vxOKY+<@3`E83)r`k#aJz+!KWvA&GKRE0mNdxby;si@J4(I95owPNjU~y6p9l1ED3p zl(;<{Mgfx7zDu!UmSe)IEA;Qk*ihac@I;JuR%Xd+TfKYwIh7vDfa_wSxy zp2e8Ab$7^lJ_gQ+zPN^Qg6Dr2y9nWaB%1eR<9)sTfjoxS!*wR%!Ti&O+MBr7o%b%< z0bd)hFJMP&y!t)olGGX37hOnD7W%6#a-C$prDxn(*$3aI&1aK-=yHA@?ux`%vYKTO zN_{S_BP#2_3yboC8F6)2eMmET+1E*op8BojL*h@{UYIBzT@ow#Kyf2V@CWN zqkitG0P3zC%)iwq;Nim@xs3-U*Mf=^2PLHt{FS+_TfH;G9cvI>RP{pYKe>Ur)>9o| z?u}aNuI?E4D&a}0((9=+;T4n#0A1_p47hw|4%u|^9bZ#PNb%%U50`;-ttnC)@Ocjo z^O}&shpvU{+b#R2okJu!*#bwOya5q7?{I@WXD?!Lz!q3k2^8sq-8v6QTY%KJ;1VP&Qz}SI3_|iB5p(~rr#fpy^0VYEXot7 zExe6u#t?mO|L&Y`LrTw`qqz`rFOkZNzrW9wXUf*cY%jI?+SZWm8u5+eM>V zb|n$O1+-k&lm;9lc7eZ~U2ah4Ix1wm22tRgBdco+6%uesOe!HM^(plV2cI4PzFIcl z=wsz#)s|zx&@M^c^|Lb0}>=FzWYQi!6tTQPgX{#c#~ z$cj~4-B0-=I}V34Zv^Cve7$#Pd53(6nLE|nkV;cwtZys|rI%71COKtmqh2N|3xff~mfG56dZidXEBUwE}&-IiETf z0;>$(CvS<+>Q`2+?V}XZ-?b`D5*1K)hLIi|@jr89sC)nKN@DZ?L%jhnhzzx%Y(JnY z$sUnx>u5IZ9z1Vex4Hz^vPwiYD3eL=8T|0YlGe~0n7iI$5IcQCT2=r;A}`%v=x3L$ z#&mvjmQI#{++6pg7|6VQUTX@&AGiihawueU(Tax;DRc;3GR%v zAwtT#>sK}OH;dx%>D4HO5#cD??U-&zQy9?k+fPn#&VVR~f%1Us**+cARINplcz$r@ zZ9aq2y4Dz)6yU%fSq~gQIT*UZD=Bm)lTpB!A%|g2S;;&aw;f%;XL%jQW#S0*4>wNp zdgOo;2{pVWAJIF>?rzH>B`ZAW;n zBqVvdm{dbAOp}B9+9{$A)}uPv6cq%e!|6>}gdX38gpkz>46=k?pS_w-^tq&O%aAs0 z!U4}(e+jq#Q1oh}!Js!JE2uaQp=b zsVCeSS9%WcJH1*){o;~O8rlE+cWFx7T`f4cR|7CUz1L=8?_3~m7|D<0f&yPj<_#us z9Qy4X2L7;y;W!kP^VtMHr6wo9OE<)*WqrZKIxLTo{k04MDS$QLlMi*ms@Q z$p$3wyh24~(LzW2yXIrv`JcMvw=3;j%(Rcb#Uu3Yd4mjd{x-CLzi##ym@*AsK5I9W z8Mqj#D^%lr@p7W;3Tlm(4D;EltTGn6`YpLUP>jN*ZbEoL>G*5+&ANDwecOrAaH5D! zmH+L#pG!ml2)3v++p&GOSk}RB&5r*UTdrG8^Q-Y~L!5e0o@Eyc>m?eMaffQ#jaAO` zuS5JiLY^-LK6#dPH26zLE#2>vS~OOE_$#F~d#QdVEhPTIwI7b|#A{j+B`MGVRAaFPzN<^?n2o7rm-P7 zF|iZRv^tPJn20`UzYX+wh3 z*FO6GgQ{T&1hyF%S9n-!2cQlWXv8Yrq*7w=2XLA@RZ;IxJtT&l;%ZF|c4StBW@jm|NQ`mCa*0*zY-VDq0%^G!P(hHe7 zeRJ49*#x&*n{^7`7&2rk92tVlW@+>iD0=t)+i2|c=S~^i`6Ccw2N(M-jVp4bWz3px z+#>LEc+uqN5z%(SJ3D=*6Rq_+$6$GVEwRErE64NsQ!Sz9F@c~c&CG1pdrHUiKYgi1}b0x?05?NA?Uso8tr7JEs(>oR4w5 zYwZT1+gp~%Rq|LcyT(j5dU}A{;lx-U-sel{&)9m9&Q%ishl3)#|8}Rm)?LiFFHyur zG+6bNtZ!SVp&1y4dfDETbcMMD7QRQyNCnA z!K|q-H}{viE+kv==m~xhf{T1s`5qDh(Rfx%_5SrOTuOqmuIZ&qW<~U=?(Lj@pPpB3 z?bzdZtP1ⅇ1ktyX}2Z$Nz#+GWOefNe`R|M$p!!+weVpgh6)}++@ACAXEo%U^@Wr zxOTqR4G7KGB_!bPUQwR*h=lp~w?JI0@pLKBPwP-1}*TEDnMB@YPb9RTJvMG`1 z{M3Bax00~ZR8kCIRMq|>%Y5|~GaV(!rhZ?d&PYC-O5%n!bYeGFMs#x_H5onL4mg6O zLv_b0?fafkuR?eT;kkyINNG!{*RN-kgqEaQ|B5wqjz|ysDEG`_qD8YKFf;T#YCdr- zERK^}!Y4W~Z9Q5CZmvJ^@i&<;}%7{{w{V!5z@Os~>TdSe4OUa3e0^*^>EJ+l|8x_0-KRKzaHSG6hgb z+)TDrI;<5XFM)Ewt**b4u*J`#+jWltQvqAG4!BCEezKd`*TPzksY?9eqms90@8)so(v^N^gUsHJuwhuSUn}CMo8Bz+&;imOm zL_`A!+t&~2JS98FROd!(-v<0gb4tPA@d%cwDc{%rJ_2GI5={KHGsnfK(jWc;F$aIm z(Oy8`f_#*i2doSRQ_axoEGL$%d}f?VQ)jVR&>aig9o1z?F!~myvYq>900(|&_8%Ur zI|@5P@c0n4C?{>m9Lg_vbaj|%B>D)vT~FXqOw|OHK4bu#N@3&C4+3xp{B~|tnOdLw zE^_?`Jc+62e@KC8iKgu9jah8IU$g(AF0f^%L9034d;8s_X8Ivsx3d7p^soB)N<7(h zf$Ry3^j2fvXmU#W_JQ~kXDPE;a*Q3H!4LY;R7<2+-6CcW7pGCnLDBcwTD7e*SeKaz z8-lX0dcPOwe^oiAaW#1^P;69HREya}52LVU;8-5(CdLqKEGdtfD9;MMQ&XOA;Iz27 zZ1O~bvVg|$YF3M{=3HSGgB@D`dFr{*2X)UP=`2WMm$8X`tmI2tLZEojII_ z$Ib>vwwdPjuk%A#kwR1#Zt-5(z>C!@iyXJy0Oh4-XURsMr2$OsOI1>aqJ9#qS02vb zi5sXVGkT7)58jQs&1MugLg!TtK8NUX0>BslJr&`R&T}?Wky+#C==LDH;Jt+-6I{us z^Le$9A-Hknqvp;!r>dmWe*9CdrH}VgZYx}CDYbnV1TwljlmAgLG^BxkNAaT@0aR(W zp^OTbCRM)v-3%^+F6TuKUDsJ!8z4%7`ddV-dR?N1?cAdXVvx+@c9{S0LEq3<(MHWO zu8%(Txk<$nY%I0(Y@_mEair!mW>yzQ@$AJC%)hKrZLmT^X~$e<%^4*^(lemG)!H~n1%uw%<&Au(HKcB^{Q@}ZkV00{G(PviDk>1AlpyfY^Wt;rCC z{j~juN>uV7o4SWv&Zzl>eZ*^U>6UVa)J|=)HG)7w$FO=%sr6Z+M=LJsL<`_nc`vCo`Io^tws zbT{N*YDh=+C_lhE5xfO$Hgwfw`}1*_{*b*_Brma9|8A3dfI4M9fP)UlJHSdEWW*x4 z$v8Rrr$}Ply4^^+zf?u7E`OO>w40Zt;6(&!iT?0=rm4*?Gg}90KGIpEKg~dgjwj{8 z$+welmw!1mmWzq)xcz1@@YhR!e*A(pfaYGrs~o<|^;qMgp<*=JD|pA8ul3D^Yjep* zf5NTGK=7`GM^AM$AKOsBe>Zya1B5j_qogj-N@n(Sbu@F$uuuQKr^9+svBCr}x&w64 zU(L}tdET_H{z#L>KV@3>tp2)>hdx{xpODskebEeAS5kLJifg_2tM&9DduK@S(3O+!k{R14R{}L|GHP zrv>TW3K;y#=`(b`V&GspoLb2-7yoQ#_YBb7MxD_vb^qAi62)|+;nTeuyZr+kCU&CoPtSGXpLcFNBWxK_xo2_n z(It;`szrxUIsY@nX`ww5Ys=Z zzwmo?vVRrtc?Prvc)^G3pQ{yL7~Ul&KSzg{5i4s}^fgwlaK{%xd5{(N>WFt0q-Jd7 zgej^~J(%l`%kLESRhSg)l3Ma)Y8iT3v5|9HioZe9Ume-;bRy z1;7STBsYV5ZKEX-gPR9s@>dliCfNMl(bD&3+it;Yhr?x?UT#WOzj@N>{8ki0Rlu9C zX(*Txt4ib)=6f}OYPF2r$`vuhSsW4E)dZ+CPIv%)>Rt_igqUL>u82ge{P+49vxmb< z!K5Q6sxhx%`2pxMX+>e2hpG*pf=~chT>Y@NnzNB$^NoEiJ=Y`1y^NL?PqvfdA7&Uk z%`R39xZDbzU0XkYPn@B>PSb_=D5R}GIkhk*NN+f;V1INW&!g>bm6%4xrSC%Z^qIdU zW6TwNv9sRLe#zxyPgkn`iruY5P?c*fi~x{sT1$TQsHoZ-srXsHRlh3&rrI;{-|A-N z7l6|u;^#bzyS$hh$(38KEWO$pu9G34`Ck#VzLlvIKi;K} zXF6}m%SWtW_6?{*;29yN7l$3_)H|)OITC;-?S#FDs_-Xt?!fY%YBE>$AZqAK9lCeyBH-yI|@eSoKQsrK&@ap}BNP5l(`MgyS%G$#dPB)wCBIJc~N z>F2Q*X6asiE}Z`$HYA9(@y7M6rA}+>gt`@@H;~{>h#PbY8=GSZIaLqGWQUkT|F*_oW^{&f8UfhNaYh+UF_IEb^-Vp16a zo>XBRhb;=86Vsvm>#jR;H;iS_(GT?i&btlTUWM;7MndY;qjbKu4MzJsJDU`)DQ0r8 zCriEx`sMiUUH{)Pl9FUo=|2v4-oglypVBtiO9wvod``0*m}tnc{1JSdwzvuhhiNv{ z&;^{7X>Hz9hnvV*U%o=#L1G!PLLL2<6#EyKptF~~f+%JW>1QnMMT_9Bi=9QRb!CJO z4NIaosP=cX@g_ngc@ZCxZ+6i;3VK(AJdSqmM(aCz22LcY3fECKUw$#lN}+^C@6H~%a@2htl&GSHE@@fI*mI#{Fe^go|lPpBN$o#T>}1# zJiH`({A*ILixW&;^G=#BFeYbHGK3rXr5ycLJ9v#J{2~XchXSHQuAD$ zvzJ$m#PD-DLKQ7^1~jCC0Rk0VbU8Bg(X^1$(vWlDm)a_@pfvPA9rQqa^uQ?AJ58oL zAEXY&j^rgU9%gORYodx->U9fhbM{eX9dr!>30bFLC>kdZlsL-T;aO3`t&;<8L zeYwt(HjC@$AvYzY$)uc3vDj1aYqf?DE8^sm&?I`W$Mud7`&n0TquhEmju0~|W-dQ` z`Q&KMhFHi*gg6<&q+GCv9l2d`Z`*5`kfAEqVDHjb*UzZAa&EbA;memM+<4AIgB#7( zkBEd4hTLv2az6_Wjr8fznhfDjatF`Q$9t&2#DY9>%kHLog{xdA(aG(|cdL8%13YqV znRaL^KK-&m`eX=_-FTOQ^vj5q&3Obj0*R2^2Ndpz+Cq^HvkCdW?Fy)s3L2! z*$HsY6OPTtF6D|^rAV6>&PJ3XX4h`87mcAI@9i5BUy2I}RX_lUm~ix&YMF zO*;Y5R3T4lg!AgatOwm9&~xQo;xD<%E~j-!`J~|Du-|>$ct?wfRsTi=DO zk0gCC{b4FW08j(&X+zB~Eq_#&gltZr_g`k{C_lE1bknMwYldI=S4;T>N)M|3U9Bd} zwD1nBR@yU2`jv7X7EgfI4m;48Z50(BD98CUn97 zfKavV+BiXg5Ro}WnNn|rxmcrEZ-jJ&BG^)kM0nOtr-#++oHn`wzdhs4;)RjB2;2cG z6__v}T+->O08@$DB*zufc7e=PqY<9>jQ;jiTF=E5YTOViN1QCm*|fH7Nb)1XpF|37 zWQ+HB536nyRwGo3)#6H2$_@Smyv7}&$#){aP$4cjbvFS;60>X5)T(%IdpUfi2(U1Yc(LwjBa}NYnNT-wK_P z!IgBt%@TeW`mYa_${kadyZ%JWjoc90M4ZF}ZWHX@Kefi1dy1s?C^UHsUw-(nNId=d z4(N8-y*||OysEIPcIHWG)%s#1nDU)^$ff_X1?gj6*xwiaA;_$7PLsETzTReNLGgjIN}dCcdTJ?7C; zPd9g}@q}i8Hi{j{JHGVIwHZCv$1S%8-fm>VE!(OoxKV!n2uG-DL&y(t^5I`Gl=}1g z(Rb^6mvDxJ*<9bOl9waR6AP8&PcjF4u*7>P!HnC5Cut2F7d_su8)FMOH3b8ez5M;b zR%jvz=CxVnF)@7O2tWL9v-9fwCM8-DoY|5U;*&$)*EtdKW5)G#!s2`V7g4wDNJ!e$s$v{l`NT;h7Xu7PnI5_6}-{iN2$#ojjj(xLKo zn%;UF4%OL8vHmOTDkNLacY4TW5Q4V6$HyOHh+MOkPkx~D^l&mx`Y-Rz-ga_lcd<_sE>|u>d3AdnkgDkoPgl?=T zHHF#~hUhV31bwrP9=eG*;{Oa;6h&g%(dVIi%N@(?(3DdO43Dsuy7D{IeNk!B#d+=O z8f%#0A+zminlccNm_Ez8)>)zYuQ>xo2+~%;1On%vvmoGf)${mA`ThmO(;QO>Cgc`D zyWfSr&UkRCEu)b0OCy~{_}#D7!}z?9M(S?=wbelur)tU<^+tLxC5v0D@w*?Rp8Kbm z;`MkIC7)x9z9lPe?*#mQP^WAOIxOX?WsfB_mO+EV3(OSSR~X;1pBxLWnih9{9C$*=>4OvrL)gAvjvwN`>V>iL z)R`IfZ`l^EqEqktd#nW@+Ja^j`zhe|A8oprSC<%Laz~f2N>{t576sQ z&Y?5$VK^DJfoQOq_}u=-kib%-pPgddcKfqdtj0Ty)u<*;ANRXi(JLLRVtLcIRgsFdIr|LGsd0fft~1KYhXUA zsckWLI~WJ-mYvsBZT%e3VBm@y+g$k&Gsx%c)KKBclVM5p${M{iK>=BHBspsFW}*T9 zd3iILnvGE%2gxmeN%-%$R`Y1bD=G7N&=Eg$foIXrq?q{o{Gto>O@GL)S+TdXB$O2d zf0IzB>EE3WeOcm%R2C5rf zn?8`cRhI{xgV#6$5HiQ+c@~Q@X`B0N4aa(S+3CDxml`q`Z`tS;JJacX1zs}$no1NT zEwUaw5+ezu5M{U@8IHkF;c^DMjVi@}tv0 z_#8Z<;Vv>ENT8iUfEkYoKC$HMB&Z~QN!>gKmhFxAD}a@Jp!TDW`Vw@5hxFjn&&%DCn%mk7=GM-eh2PTzYyJ3;EHC z0&*V2b@qk=GVzFJ3U`)ka;x!lh9Zs76KUBPCX}VzAn$fW{kbtRq)wZDZ`~6N3#Wh- zqg$ag1RZ_#{_r;RnHNje{4E0I=GO`>@M|;YnFfBXmA%H!*Ub8OxQp!=NA!)4DbL;h zkR~88)w25+7{UG9R?dQuYP-}1L&o`%=>ce0P7Rm_n558{9Ly`+) zz^D9Rr>=Zx5(=0x^>&6 zVCLA)?8y)Q=X_F^z7~9zcY%yvgKr}Jw2yGm9ar?;xg|=fTHX*M;qNZ+E*cSN%&zvD zpBlV#J4Nm{tQolZ@JpfR%NQ3c<8-z3lj43O#b`AJPzb&i^US$oKtQsBtcO?pi-bq( z^Wqm*R@B>gPjb$m)XPBGURo7tP>p`=$^k03p`3-_mNyU5ll7}SFf|>IFiF}unY8RZ z;A~1Kb63Ow=YP83bDL#XoZRMM>f)eQGzA@DDI3j*F}x$3X}8qB3gd`{DcRV^KRgLg zqUpKYb0sL_&oRRW{=j)hV#_;&yd&{5+}W0TVXhJ4a^4=s+oG0-;!ZEv5(Hj#d4GD% zXZqLQVS6A>{79ni`b8FX71Ih_L22Y&j-GZ0aVBx;p3rN&66+54c7%`9Axpfd0IBWp zStuEalV)l?&?7!A4V%wM8;slH+j~nVhENad->?21PJCE|gEvC8sRoh-%*28B)x^Wl zp$W4Yi2RVX!RPrkm)IWe9dW8PUjv!~T%*pU_sv(-vIe6^euTJAi%d7j>@^Ac1Quzj zLL77=95o5=QMMX!s_54(bI+2Jg{aV4KJt9>FGDRaiT4wr4^Z`O7lYua60|~*#w+&GR3CP=HNoaK$SOBtV|SI_TRSMw}lZTfHhv8-rSoG{{9bGNHKk$ z^gb$LJ}364gF{U+`kS-5T1^!pD#~!CI-7z(AO{=6v;iGWdoFeE#;d$#0(?caEU*aT z_jv$Ty;`)!UsehiIwc)UMYza{=5IPmTVOI>8UShNx0*4LI^`Z>%JSs!j{uq*y=SRO z1;lb;#s)YLpZi<=_l4P~vC!L$!~0Ggw6YGjdGn6EVTzx}-`u#rLF5yBiziJhHt@#j z($Qh>H?SvBD2@!E>q`T$s2dD8tZtxU<5aXad!;6b7x}M~_I~mhLXRJ|MUH%c^pouRlUqMTJjFJK&EnfH|}8WKOjrgWbM3&k^M^Pk4b@lKfZ6B zUy^eCLs)tp@>@jyL%=6xt#t1#1T9njU?5Jv$`&%VEM-{zW|BmZLh+RenruhudC z6YZRzqs($zxE28d0a2zXJAknM(TmXeoY*^0#L5ozddwCcs-~0o@HxD==W<2I+~EKf z-rK(FJpXA01&sop>#t=&cOtA(XgyGNkrwU!d!`(vX$71&hDW01TK-K^FF{pa#15kzhYS4nu_qWEy$G3yxnoISnQ%vohA~y zqt;El*w|qw(cNHw@p94bJ6-)Ju(mQHA%}yl{002*$-%FyT{Xb%1bR+}B3l5BoH<#C z1+Eb~l8eIx-3u{7P;Bq+UtlNL%qz#@fH=A!^MLf829wenrpD*Wh`!uGa3T}@_>SDG zDA=*J_jG&#DBM)k+WzJG$73|yj<@e(J)c#m;d=(Qs_0g)n2Q}i=$*TSq zK2&fdVN|TM%180&Gl+GY$(7z`PcZ&W06B7u1YR#0fUFmqNz6vmtOrTooc%GkuL7GX zAKiwmf9xMlXyN7?hnKc=1bE}Q92peRF!7pVowgJp3*Dk3#Y3FcfPfEbP`Sq0wE(hw z_bS$+B1Bo3Vel<`|Mz$+qJNW3a~za#e2BwM&BH>=C%Wo5>o8V^cA9H-!8G{*OZhrd z7Bbc{A_{tgah>LN9XSF-&T}>nuwq^+G`wUgMC;?2t>RICj~vd*)0nCkqDlO^01DCI z7zJdXAozNl{o7A=ugj+6>n#NI*mDeivr_&T7v>pq#Da5Lj)yDuX^2{XhC=w(1FQke8>y^m)eU{InO2LOHY|v%gIc!h{SJ^ z#KmLKs$leN7boAfX7(ykHu3;}7iazI-^pG|BxxeuL&Lufn;kamSqG$DnDmI zh?$BL5`qhN0?g3n#yh2JS1d%bnHMyB3YO(D?lylnq;ZUdrbh!+8t~Km+sr#G_by^P zYhBCYeCZf0(8D{6r>w#{?`oW8$d<#z{ln|gvqy4Keu#^`U_b(nE2M((Ls%wMaR~}@ zl`rZ=1<1f|3vZC+>5h2%NJKNA`nvoRVR)e8sJp(VKTy!@Md()rzYt(4jgYTHZ;<_P zh)tKE=9HMoQ*YAwNY(dzqarskFD0h)Q+JMe$Nw^pV+>9J+kGNI^@z1U(B5bBGp5TM zyvGjnyI=LztrjC0eXy{pjH~3QUWTQM%A2rHX%!dGQoR=c#+GQ&*q8L`dC8w2lh&6+ z4Wwc?sAwhXl)aFopSg_5)aVXeQ>5NH|Ff+u)B0+sxwwo|ueMpf6;psBVrYJ-?kmCm z)D_{javXDwj=E|qh70Y7PW{VL=foJwz7e21B*v}pajO%7OxX%W{9G^E);`WlgXQ@WBtH3$Cs)hh)nOm;6)dc_Eg&!k8`U3_Yvav#3= z|26-vZl-WHr>4mod)mU)TlZ+v%_V0)Vcl#jK<;h0_xzbLl>D=q06~U3{;BmVZvk*v zLhx+01pQR?U-k@Pw@yJ>$}Slg$r4N4J}kCkJqVGuDJXf75yYU)kHKR&T(ijB^PJ+~ z11xz*mul?N%bu_V!}wSoJ-`E3Jr_lbSUm@jVBZ{ByM|pa>rF;E59H~%nYepkHYNW=rs>ljeF15TV+-r@2c6))syJLbW$=)@*6r6eS zRRtZaF$7uSnqxsAzR&*=-}S-MoB~K8VRg@eEN|e|9_({urb`-sYFXdbkQiWEy8efQ z;Q3&Z#wmnsDw-z^wi)0$|I>|Io^T*w)bs7_ja%iT*Rr4-kWh z3&{^WSoki6DqoZfeG%EfhCaKCN=Z`=0>$a9OxPHcc4u({H+WrX8ZY)2qOW<=yTuP* z@EC@3R-UP|i2XwB{vKr+kKSX$Q+s1zDAQoz)|G?bVLTX!oj{QCiRE)t^ump{lV;fn z?O9MhQcVCfD!$lIO%>4e@b5e7cjer@!s&9 zbz?BAu^yK)JlbI}Q>>2tf^~%Bs~_9IBsoiZE%qk`vz~9m@t6EadRy2_6oge=CBL*} zK3_;doPn<T7)bTc6>@#cT&VAPuj#`=_Uh7e9lLq+EPo6cq6u_#*fspC^lX0#-&u5M4F#8 zaYx;95Wf!6KRUnU5yZqYZS-TeNKr?U*Jn|T5~ zeTx@&_u}sE?heJ>-5rV?9E!Uh+})wL6?bj;W`@L;bg1tBr?{|}_01!wwFrRsCzlj|9u-sJZ`@>Qd>!v;KpCrCWU~*C}lQ|t>XJG8ioG4=*#Cw-A-fi3VNhw zys-S(|FT6s^9$SU(6o^A`?zFz@;I8ltZwYA@>vjl1D!-d_dY~O^$ct=aRm0b#vNe9 zQeFn8Hol~$OH~GHX$TCnaQtAJf^gsN{{j)>a^&>&I?L@y4kmqKU<)Sk=E`=+qV1Xw zQ`5okLRgf@L0_0fVOC3Sr4Rc2%4{VJemF?KwjbWZhU}b$cnArqQ{`w%B!#|yE4BN_ zUUK3#scY$5(0Gm5APQv@?wNnip%Kfe`gWMK;6KK3<7H@am9tMYiF_6FOBdDH? zaexYm*(~&)Is$=QjByBGL>I?)==XE~CrUvIS}Wdk?sUMUIfGedT|Iix4x*=0f`Io* zzq-1T+Xe{Q8CKV^WSYj~2Lm8iPy#9z+W=^i2q1_h_om|azUbV+kE{cy`uwVDIRGZ> zZxLuG0cq!7D$gd12Rb|GTi`bRu;nG2wp{^W@C?i;?AcpW`-Ni>*_m^d^AOQhWDQ9b z2g@8BuQ$YUN+Rax&IN!+*j#c{N|CqmH^5&Xt*&>LDH5!jEeI}kC0-=ZD5&rgx24A% zLl368lG(9Ji^J3q#^6+4f`8CsCOVr};4>Ug6m1}bHXc>~_>#6#eq)?t+8K{H3JVEK zui!|sepR{opnme)2r}IJu-cja@x})EQEwJ7z?eowKo3i!Fa#>$QFV#?(M3;@A`J4H zLzr)xN_34q&?Dz=7DLGIlLndmS(Tec1l_mzcdNV=2~c06t~-z+b=PvO>D&>vMl&4= zA+cONYAF{HreraDrl0R?DzozsqS?k#;kbZqS@g4v$N<}-RF%CSd^oP(&70yh#OB2i zkN^Y#GCg{dY&>zI>*oX`2yMw_f&;6-h(6MXA&=-0PocqUd47Yqfz(+*tV%;-VKJ)7 zSJFS6L1tOuC#^zbFuy_(^PxD6!4kj1&msGxmb;ME@0^^E8U(*)B;ptq5RTLPid5jG z{q>5=h6zuU<@XO35`R${yZncXZW=+sBIu$#s?PkGjM{K!u~!*yqr03zEco3{KEN8=S?uXy3b6Tp^NIL=CK43~|5C}<*D0u&0FHS*odOXHD1HZ#6O}4sZ*`YhZEvmq zE3+B!KG5~X*nQq))653dGdd0Kxv))#Q9rFBVF5(%dY4|>r zc3*;1@q7MH6ENx5AO65oB<2}Z4|yvVO=m!*q`fE0ZFV}#J;0R%V+ z?(0L!iG`|vE=3e{^@pIV5HExBKgJJK|CzAI=QS%$G{8DEqGeHqUi|ak@gz=dWgYgk znlF5WUhxTY8q_fuPjJ?j&)cbM?n(w1o78OeC`2RODIvEzNju@|w!)O0I3R8!u@y}T z$r?q6vO13gcc2PRKm?c}N@Uzj1kmMmfC@!)ms$z7v$R^#Xo!r9ul2&R$ft*tb_Gb~`5S{Lm-UrmY zuuj1@u~lQrmhrGUsnBI23uyt@WSmkSq-YEW^m5z_urv?lqN8-9)(bTwfrVAutkic< zr#}Y72RLz$X#_yeuVgJ-nd7-&_2}3e*>Fxs4mIN5T??YO5yY>Re`YKCn?I5ytnSdobl8%x6OIj*0A*S;k9pTrjCie+xIs*#5$p=SUSO_!suUg!VC1 zM+ZU;El<=#k{`F}g%!_!P_G`uuoX=Mk zH>;K9N>L2*(7wI`v_u^bJr!W_M(HCij9Yv_f*tcmuv|g!t94%a4kG+4bDES{MLvf# zi%7GGCq38-=Nut})ujL|g**slbUZjxNyvPfq((1dPPGf6q+>qeh(>^ghmB!rbSieQ zP+6n|lbe8}epG0|Eao?lmY+MY4J2uAdcN-v3p53_h7t&od3 z_x^{P`IK{tg5 z4C}>*KJab|iO`EZC^$YiGs=9a-QYbL$4U{vFW}Q;F0w7CUGbMVk_BQu#@DzsBZ>$G ziAy$;dp$V;EY*pRZ3Nc)H}Vod+~PPt-3fL~YY%w8QHL-@J==|=#Suy2s!kJ;*Fn{R z0HT>!9P7%R6OJv;l5=Q0t8t1R;j|OfU(#A7PtQy2IsYx;0LWiW^YS)$wwhl}s=Nma zp3H8wU2kvke&n7ZN)>JbbWOla8E@F@w%P%)q_A{uz=wjikTM-6cUd^v0y)C4jX(W< zVo5kU3Wj35Gn+JqEA1a&^D&VcFvKZEARsBwpF*Le{&V|x{@Ff1 zZHat1q4$}KU;K8wg#oa%0>RElb69v=+~Y=-nz7eMsNwALe6&Q~k>V^OMXw7gpoPj2 zSi1l&%1nHYSrp!3h};Y%l~-<&I4_-YkrBVB<+!iaPT}{`Gs{w!fU^Q1`Pb|H`d3?x z6N9KxpvKQRp#r`1uE1u=`Unm|--e!1>a*V0k&%&@RYe&k?GDXR;H4pN;6Hn3WN`PZ z)I0RZkH$opGNPv&j<9?s^pg)QtdSjdY4kS;HJM|9_O%W*Swozk*Z;rd*A&na;-U^0 zY_;qDzrR0+n`M3Gu4Gf?^0+FN-L%6JsxCMPTlCAm;c7MNmpzl$NX~tP;|=&$B5=G` z%-1VXuV87_0e^|LNKWQ_J!vm5(zf`Fy)H#vterYGH_dc9503V@>?13-q|En%z@num zZ3X*fGjLhUv21(C_9Fnju`f6X-*N)5vm_Fj>TP6F*(jCgwm1TqyDj^Wt&zp?p-MKx z&d(fG??u7Bj4J#^6F<$4fL(tj>Q!e-z!_uq-Rpj3pK{+Xo@f%Ot((!39cS1kRxZ59 zP|iPQtF~F82UWur)R#^bK{2jngGD1$gyrnDUx%Y=yN(v;G4jo1n393!;CDdj*-xmg zx;TzCQwmP>-ub~@0EE{&59QD9#xrH(@zvGsX9p3UZS#nX9c2(ULIF1XivwGE6ld=EN{-Quy7^kEAZ(x$`%tZ?E@V`;RI7=oUq){?Gpa7rfxg#b+|8o! zOzm8GyN2}A0k3UPTmCx*SXuOq#G>x+fir@EaUWFI*o0mCZ-pw)>>4e!T ziCQTjYwARIqoP?}PL=8vQ9vcSOPuDdW{Zw3y!edZyAtjjSqbxL^`c>>7Sr0=7%SpPrX7Av{( zCUy%-Bw`e{c%jLk>6%98*NbwsGq_val3 zycL@+pQ4JNz1F<2tCtxpvf&RkR)J>DfPag&>axsbl zM{*q3#P3X8EN0mxP7qJ5Lp>vdS4meVaOh&L5>I4M{9&y8-od?}j1=LY`VDD#%dV<0 zu1>r$rpvB8X&%P;qY{%45IK)j>;%RR9GD;Bf+-;+izB+7VH7JijqZ}y5IxRln(^uV zL><5?zWaaphX(gHT+jz>$DmKMANkJF2;UELuP1|FrOWbrE*3F@u_}v@b4Z^w<34Uja#> z{Id~SS$=36Jk_kEEG%~L{jqhLb!GmRMo=hgA*GhFq_a7t;w77X?8SBNAI2Ql(%c(T zF_Xx;YInI&(wLtn)ma)d#BPj&uv|?EZ6#Q+mDVdw9#Bx~V19n83xjM-xnvx#o(RMY z<$cEZk}{?x|8VCQ^;((ODb)QU;a)nOG&=^w{Xyy}3lCWVE3l2x8p=mj9S)g1m#A!% znfL@Wrz5z6n8oN5TWU;L=f{(yEtFpq1u>>I%S|xLO#W9-HGZ`I0-`uRR~k|NROZf| zFgvBl$^;t1LbHP)8k{9^l~TIxu{R3#|*OC2_X~{4(irXl9J?_cN(5R;QI94r@TJaH}ef*yWVQ=}s8aFZjovYjG)8u62O*5RPWKyS54JEl}7+uzOM#((*EsJso_6zI*t{Q0i~m?W&&X8@ZEwZva#bQ z0~fm1x13bGHGQ+XLyO%^*lsd0liFM1Ye<#6XoT_)9toqf*uFi|k%njl2vzb@Si8At z?%O zY_(9Fn!kWLTZTpKnNz;;01JmuyhI(nT~0FcInQo`HnDm`*SBAx4KNGS z%iox*u%3>SjdS7StDuOo6t2%`g5B@cusdZJN_S2`Ol=jc z6jSunKnZ&B3`GKU4AE0={^7$jB*gS9s*IPjeJhBsm1L)%)ILmRDMN*3ZWgQxjGBT! z?by4(s;5m05LtK2R=c&1jDRY(hOxaJCkb#%9C=K`wex3D8Jz;+Z=HqF&;Y&h3vfl( zlZbMvzD3>P(L;YcO}xR()vGyl*77Fy(0^vYk%0_u4eh#A=}No`C@BpWFB^=2%@lo+ z5d*O7U1DVFOWB}*VM6;-nwI&774!+=4s2=xfwRmJkoABOE``Mm_{nDjN!8#iH*VA@ z2gsk_9s<-JK}X@~LE{Tp(t0-tbROq}|IoevwG%yKC-EHPcp}91pvb+9V?iw(0zj-h zi~0}!IiEEyzLwc6VuA|&8PHRYUU`2eqj*@22u6i9VHMIEV|kCF#k)^YNkYrhLPfs? z3b;h2zJuQI!I5eT3mwGzWW``-t6y3S!UZxV#h&Q^_Aw5k62hyG<06#QT5H%;Kiff# z=JJUS4AUWSI`$rWNak3n>5bP*4Y?to@$y#T7wrDVgnn1W9r|1f2V^&IB#tYwhzWu= z9jC6*2jpWh+^|F1&rj%5G^|SK^#5Hk`QA|v*=yD2*+!fuSV?+N@Xb`@Ycb`;fpusj zi$77bm8WE|CUs;{^k`$Gxk{3Wq%GqvI?MaYM@{AfUeXpbz_@x>DLHN#!Q`T(>E??Q>D)@U@(qdd7RDplNdX6^x*+jAGd>q;%laHo2>d6Vow; z(V-T__3cUZ&}P1L`u_F7u^b#WqYFZ&cE&h5`Ly%d8M0ts16oQN**C<2{Is|dAx>}S zbA3DeM}@P{FBmt#%4@lXm0PbD#_fO{Pg0LVrvUl)+ZP}*z@8ZIM=&T-E5lfl0uMok zZ_4H))j}SqASlY2XKZ%*m=O8=$fNN42%;3YvN^%86c(6F^Qcl7>68oA?c@20Y_Wjn z+X`ThgzHY~u*V)bbsSr4RjS9AwZ;`w+;)f;;yYT0gtm+lZ3d;r8RzsTEIs~tdC=LUUsFfLE6m=jm+Xvi!Ym^ZHp_E;ppL& z8;C-|l_)LhSQ)Hm$Fe@pK2u1@l`q%H?*pMb0rc!9s{wqD*1oEM0ZJTks=t%A2q*2v ze}6*x^e!T!r|Zo3*iJZ|M1KX8B+YDyzlB5vsD*lndlaHa3_ zDC;ErxkuevLGq|v%0oG*&Wh>Z7nGFH3y#!wd*8_zOZFrq+8!k~Lgyh{{zGobJkFVA zCa@@C6i_fqk{JS8h`O z&89uji$d!G4Mf>Y+hZ{Q$F-m`0{xA@#Yi)f47oU_c~_j+8JSk=@&oO_L9j*U80OcZ zv-JWoJZ~_Kv8>zpq(6HfZsQGJ6k&@g~LUStBo@|Y%-CeGgC)%2KV7@h6heoF04dg7n% ziYj^bHeyX$d|GxQLj&3~ATtXy`#!8WWu zC*OFobh?G9j_kDPR#jZ4+`)Tjt}XF~`77?JJKrE+CU;^5OSlW3wyVq+!X$~+^py4T z78+XL)Azn5eX}=Z*O0k}YCh=frfj4Q^Q7*-Y&M&H?u2J5HwSdw{g$c{rOFg+TjHJB zf_X%7JHahMqgtIXE_**Z#bIs$p|@4uf?M<-W3N}(0EkkFtYC3poj@RsykpNO<+qJc z2f!5vfdR+QnsopRZdbto2xM427IXLGi{tf;>UB!QW9h=Ns6$WW!jX>2?&v?<$4&~39JfQU zMf0&<)f_3gDhfQ*fXXH!ndYr{G>$*eN5yO;PeU{+uIFc4fe`@J2D&$9THi-ZfB*>u z2-d~|Xk)18#1AnoyH3n8zjUO~(D`Ovi95;)FgYq6Eo!7818K!)3!{P{NMzDU^XBob z@R48!pqDVKbNhX|k0lV5M(Pc)wIiYL;jth$P)RMM4P$j#qr1FS#5`@DTvOZXDP*<) z?V6`6^vwk>tx}CODjIoQ9or9Nd6Io58!w*RR5-Mt+W-tDyvX{}d+=!WNx5h#7wseU zNCC`JK=NP&7$vqspUYpbN)KH$a@@aS z3PE|__V(k2qVeZPl-ZsFaR&nTe&?}*Ol&~@?562SRg~QYT&L%Yn*i_k-=^RNu43zY z!r4gv+N5+0_gk-L(J$UO7aPU0UK1u&+tO(&Y=^Cy&GbQ72vJ~$zIp@@4dZQ8AOG-u z<)i=E960N}12DqSzUFFY=T7fF5ZAmGcGswL_)HxB`9mA5`Y-mUV#(t5RRqJM(h z8cn%4D(NH`e*hCH`2sy-1#`a!*}1<43?mS^6^WURz<3k=6XOq;R_NHTB`q(`)?K=t zH3@U4lq5LU&|NBBo~AlNwSQdq|E}HFV9WcA;S+DbcBai=V0$VAr0*1MK-48JW|i!E zr2Zxj;rT+mxMMJRsxYtolhQL-?D{&doU24vK!Lf)Lw_LR^nmJGyel_oKD>bICdn&q z8*qnZIhW*qmj(;6=978cwu5cY)o98JUq8ouLz`yhTWNj)$qD@JDl zYRh#?Z_7Whwvgliqpl0ka7wAi8t$AJ*A?3?YB-L00=W0oD_~nbgl#zdUtzJ1tc`g1zph{=Vq)HRDM=0~S;mwvEO`QA z7N;seEW`16tgiP@EW;BfqJIkjG6wp-7nv1p1q|K=_8frR{@?=JmxgEU|622pB|C@x zRQQz!c27V63wwQ#Cu(LPuvw*M;TltE|8pvd5REkVSuG+wQy^!Nrcs71 zrdA+ZFD)4xT|_Ssp6qnu4XBjp}A@eSFMqi=An z*1%HrL%a+%5I*JkY985h+~&ruQIX-w{^DV|PhKuG7^ zmY0L)2V55r5vzGQ*O-Cw1h3blAQub>G#FsI>4>|(iwt|6X6wCRNnHly;} zBy;ma(y|DD4(#k-B~sSBfHpNvwm0q0U3c6Y7c$X5d1UNB#UVx63c2c&1xMcaf5^WV z)04{?4maT^-*BO;fGEKWoE?#XT$lS)1MIqJ@6FawQUj7`qsx3I>QBda%k0gRNT9EW z$sIdBAO2=~;FcE=M{Y$p`(%066)YT38K5FCH@1omXk|XbAenLPi+P_YWOVQfK&v(T zkG=5nytdo{(E%v<(X>uuxIh07FW#x^4Mw42-4jovqV`!iwE=r5)*}DBsO+0nh{t#; zbk^Z$+Forfo<4(Ha5BuLo5mdlD12W`71d3lhD!fFV@>jLlQZP`6PXYmDvf;$Hh3w$ z3upa0l8Eoxbg@JO11zutH`2GN6&|yf^r1#lGYJ?v-A{L7%v#3+TD}6Z7?u_gG_63* zV>$b1GWT*P#%(--KHA2_?R>7-_4R0ymz$i>HTNTro&i%Sn9?$@hvz!MS4N_6f52yy z_#FKNZ^`xENjpK|n*WyXwdKzm*p@pz3*EirMnXhhnFt=nRTuLBU~PBmMvwTLi&Qfj zMiq3jT4b70(s0+{smH*o#TE9J{{QXzy|SXEU^ZG45iu#r!pOHOF>krP2PFF=x#Kt$q>u z!EU`>Zt4pU8D}+Ki)}08rmx4Jx%O%jbuCJn-%Bm#S$OWkXt`&po81h9jY}MLYl7RF zFO+=~iVU3(cB}2t>~}pj-~at{zQ*vnn!0T2ZnN5K*?E4vE_=Ty(PmkiYM*NFiF!*}dX3ck-xBjW%rP5r<{g-f(4J4eEYPb`o&k*4>=yx<e);g zFKbVCp7V^P&G!tVRn|;O3ieKakC8YO&j89HkIN-hGOgv)T%Oen-Ih~ImWoQZe}z>0 zjFP1%hR)X5>KeO<#vPiq2CgY<>wEhinYCUf%ri7fR$l-)3YOZxTG}pX4&`Vx(jEY( zGB-7j%-u0DH9gOlWSpol;(@$)HuD^o>wPB+(~~xP+{5Djae+^Qp8-1ED zrUSGc@0sc57oEp$X|t_V-`y^A8EhvA0ch%-FtBO%@m1pS_maWNV=Kkcv94#z#C;-o z{jkeRUuMeT!|u`R#7_ zPk=u|mX$ zvs3qxC@M3kyzDwSA!xP3G;K-g@qDX5cRkhK=U+$m^(bu-Xk6dO7qNb=>MI$AYoBS* zpC-y_%&RTuDwR7c^=+}E^IlA3d8&<(JfPXSZ1|_coBW5_QZ=u3|Vd-`=}D zj-TS+a(a_|_JtQbndR;xY38`Ab1x;8;BwQ|t^%}k_DUI>LwDIO+r==3<;vF$CEw3~ zT14{de!ln;QQ`hAw^16DS#4KLGXO&mMcVHVo{D0-`>c6bYl*2XoTzZ2P+96PoSdLd z&JO^X{4$jCsm`)_@)C|DzGRisQh#Ow`Us!TKCyGC?mpt!o%$;$X(o#XvAhEMImV?z zWM&mV1%boAn6Gh%Zb=BZ) zVpyv!J27jaRLEH_oS^P65R?iX%tO_`m@Zb5aBZ#1|Mn9Hw9`w9TDe;ly(zU)Zpcw9@$cp1y>CyFilp z;{ExP=|<8I>qH!2h8Q{`i_Dtohw~{tT`KF)Przsv{qcs0UX)6fz(eYo@3W(G@qtIr zv!!L8Qk}3;GbMe%n~XR1=g-|suItg6{^6g_gZK2A`Et{l6k==et2$w24b1RqBg>OO zF8j8Lvg?b)TOUN+rQ8A`RY$h}U62&^flV#`fk$7R++!PLb4LPuS#`*}GN4F3IA7-= zaFc-4YED96^o|AfEf9@7er>UbPP4-XGO*i5&`~U?3D0%)0sC;14OZUH8d>8;dXcNl zD(^n^402BINcXUGW;S*}<7ZdqP2N%DWVv1>wq&C2fDU&9^dnz;OI(`uhd@5btr{#)u~a$(;9jq>f2 zH<(v=u}MbF!l;q?6`A?0DIn$5ksAuuN{_)|)`=EHSr=3`Y`yD8l3&~uFdmDk==fO& zY;BPtxZ6Y`y5|B?3ke!DT)trD&r3l(hW$j6vTQ%al}!uDz7#-2hXWmjlQ0Xwc!kdj zdrY$^JHua}OX2!e7=-UuIH__p2>$yIP407UV5ZUgit5l8f;ROp!x%`l8s6{L!C|Jq zX`C0b-~t}f_wa)c&y#Ck_=iKkaC{H4^S8Da9PnC*-R&FoGmeo%jdS@Ft~tXQ92whnvQ!usHHq^J*JdOWWD4K3$MxZRc97J zToQ*EP4$Mp3VY+R8Sl_w$Ms#wKLWKV$PF51%ts>F5i^Z?D8sYop#MBAM3}V$)pGn< zSgG?+Z5eHgU=_JIn(pQ4!oBvha&$liZ*0e(8V*0?S4l8w$VGdGNzH%- zgbI0mFk|z=?UDq@L}JLyVu}E}_@KVWPV?g-H+Y z6=L>yd_&ES?7WJ{2$dlg8jb4~r9R%fPB_!JOS~1lz`M%$YiRkq>kG;~$5q$anQ87< zr1r#BOzA9wHyI~!#3nwF&#Abb_XZ=;TdQe2#KSvscb^w-GF&AHsLvDoxCCC)zl-hr z4qH?Jb?q!_rT^=JeUX(uFAWwhw>~3Pkj-AhQG;XKqw|IbgghWFZCio`4r{h8$x&3( zDy8kD+wBbq<_o;}n-=hKMHm0(I=dBjiG@$Uhl8iIv#O0(LEsV9lR8{dlBzxyplK-Q zyF3(2cy9e0lShM?oxh{+#)Pk|VD7KF`$~rlo4eC+9+<*$C0eClxPa$bJHzQHWzi(m zX)c9@elbP^gLW{EZWsrIPEVKjg_1 zJ=9kWCR6Rz+%9umO|vk&W9fw%;7o&DByiC(^V9yPs2p+?&vV<76Tg<&+JeI0L0gov zIf`4pS%}kG4E2RL(Z&Au3LcaL1auF~r5%15>==6d_vKk^^ov|}J;P{GIg7j+o<`sc zB<0p$56{GH2h%D`D)MZLhzj@RTh?dEyZz&ZZJJt(egiG)jj;5F)}0P>WE6HIRV|u} z&B zr%`}WBm7WQaBx@#EHk?Y#!5|=UI{aS_}I|*pMED>#^IJqwYQr(4~E?N56QuX3@odCGfmxO{(Zb!UY!$Gw_;e(QFz!B6`ejkb%tEWPt15u!vF^=O6W)qDax z{z?wuD*HNMSKNbUl1DJvvhW2?yfWkQW!WN2uL7R{t%91QN+87&cDN3?liHN1qSvA> z)5gB;Tmfs*d5TTt3})dT>jL3FMQvN*3-#(KpQSVxxlE|Sg` zOc%<|06i-z62j|HQAi!>1rtpm0-{)C!?MCA5ir6efEjJox2pRCa^!d_7UeYvKd`=F zo%1v@kcSG6!sb+@Xemg-r8L~MCxdk+O8U2!!w*+Ng-G_NEDH^QiE{{HX!zlEM4UlV zu0BonPrSsuNndOWUma&&-(Qx<7e-ck{i@qLyd`FQ{B$VM_CmmoZixBt*{xvuNO(-EXJlZ~mDLQW;!mLvB_cj|; z?6`Dky$e(!HJrob!b~}TO^p@wM!TUT9&BQd=jVN8d!(H&)TCtRG)TIB#t0pYRae=g zD<}oGdlO;c&9SD&&BJu@R=2{49}3(*Z*SVOPmw%lL~K&WQvSP{+tU$kvnNEIIny?P z4CUiv5jLAFz(^QBZnJ`UkUA!yx3c}L{!^RdmR(uM&3JywBQ7j7iw-wU)nZFsF#IRK zm~vZlDjcGTtoAfsY5HTS9gAdqm;8;sQen)1FPVt z2Cr2+EKhYT+~P3X9jhA2-Xk)ZD(CEqlGmxn-N?5M-ROt73`o5s2h~;kkJMQuojU!5 zZ?DsmR#Nd(>rf*^s{$H&Q6?oFkmA|i2mgs>uQJVf{?~av(oUsLM|lF6u0&pPtd-kVyY%LDo@JEZr;vbah5K< zocx;2%i!F2cgwb3o+X6Gc~4AYeZ>HoW3fPS;8ZrHDbdobv;0>)Z1Gb#4-VOe*17HG z%({z=(`b8bGq@h{RT8dHZi%3wzP_8w1E+)FpfGjC`^2`t<<$06dwX%t)0qmLByks3 zl+Lg>+RIbe>e33eX@&)gVR5Uaran4vgD$iMW8u$M?r;g#6lWsdm(!u@GhfEN!7@s{ zi9f@+sWk=$ZdFxpzjxA4;*B;I8&ufE-ArgB%HxX|6`S3n8cf9%o9`YxiXb`MbXC&j z7Sn7_F6Snrgbi?X~6L;`&l80^Jxy_TW`e&A*aTgQm3wxbw8lXR9*sX%{^|R@S#j{&;!JeBi? z`$e6Sz&ZZcbabj}ZK6cc$GP)t)42lkUs~Z%S{Unc%3wWm=k`fXw-$xA)J<7bAzBOH zGxgemtp%}e%K0VeV6Dvl)bX}thZ34?3##h$L#1qPRGz4_=d9om3x|o`+@Iyuy_*vg&hp{4@Le*Eisa7Cn5+N0tS?^-NeE18LUl zC?gtI`eL`LCEbx4m=;^b+%-0+I8*kbMxONFF7r}cb3@E)L3pmwfeihe=e7Ui z&=r(26i6J)+n(>Ss)>N|Vmnpm6H8#l(yRnGKvWn(h0I#f;c8mChe$xkHu>c;b46y0FCdV-c2amK@Wq z&qYizP5zrh&`8~6>t_{J$nI*(b>6q(eN$ZB$=0uac3-;txw`k9aHqoA7>jdggtR-6 z^|MfYtV)Vr>qhKcIeVTn`0hFN4aY}s<}Ec&8D$7(45}ZmzXtoGnt!(I5x69# z?UJ)aUP;!)t1b^0te_B}t!Ls1OkcezE)p_V(GP@miRrz*#8&L?&&-yoh`Im`7e_Od zVS*?scAT_C!F}E)m2AP%DdorI&D%&u$U0$@BpI6&U) zYH-I$k(?{v7p$xhs%E`tREFCu;1ubDRu^h@VpP%{hYM(IPE_=`&p~Y%9OXxzs|poT z0tCEx{`VyqL!-OiH$MmxqK*664xJJB&I5j1xtWtg7J(S5$6B7ErV7BbDbw5${`pk{ zOVHZ-yK{~Nn0^*jun5zcX;4_s#wNrg_Uec~C!22-ReGInu*p`PRdXMzIG*L`!{a1N zLrC4gHcx=iw=@{f4wNZSK-9mM`E>H5&^D}eVI+9acu!0UZi;$9&d%aXLBHA=DS7I7 zeORxU6xecEOq`nwRZfmSqAG;aAw!X)!COsU9jv7LQ%rr~355&P8n3srvjmBAnc4rg(;j zLDy{%O*|sE8@rEa0R7K;Lh=n7>Zb1mMdnCruCA{wmM$ z&O?$Io24k~uC8rw{tS%CjbsmP-PO?oaSP^Vo!$XsE+Nc<-jb>A4=i%+{0}hR4l!y` zIzGa%P~+vPd7OTZi?V*NPIq2Hgf3*$0|@-~Wm^>~^0~I4D9w6x+r{zU358sRmsmO( z+}B>AR?T+3Mi#1D4&>54 z@#D3Rg0rFi2054Psc-X~(0yCyD`9m0_X?JJZV{nUYZA*-YCtc#d(+OWdap$>Jpr16 zQj=mW(p0@ZidyQmHw-g$7Gnvuhplb>XTSpF@YbYBru4 zt3;|NVSj|XJZ^woC4@z`v>G2*Y(|uiWlicrZ!MpjA1%l5V4)!PZ?e+IYTqLul8B4K z(X|27n${Rbe06VK^@V0yLuY8W(-^zmId|3O_zEd4Sx2P}d$rByi&P2yhX+C8_sZi8fdH)|Fdx6N+Q9`Sp^b#XcDvH zlat_aUE4sJagbSIeesdQsmGzKwet~0_7<}^@+4l%ko+(--$T#G_rH)MilHGCVyrIs z&1JS$zx_R81aP|-Jx)m6ak~c-W40vxCBH0w@s1_{Kd%1HW~acWg6w9Y3k_PR8-n^` znM+zHd#yRf|x}$0Y ztvRv@MPrXG;EoR5sDXaEUsJw$u{GG?upSo8)#XET0-8$PV+bsE0$APClGqVqHW}f@0yoa+S|K9Gt>ht*sK>-1?7}yP&78r zAc^OU@60Sl!4G&mYjy|?4k)Wv&bL^I@f=;=qKqB_T#mCC9M4}d6S_OHc^8sepGe&H z2B-Vub`JHIrz!*)EMPki3e!ndvi+166 z`f|O&`IwZf`{M&gU{Pg#W6sZ0)E6Z~*Jp);qpcqISegJ!bsUe^Oki!=Ezlin`>or! z&NwvQ4LX!r<<$1ih3(lI3ajtQBs$gJLA0)qD)EUKLVOOjn4N?55YWrH_6C8}7ahK} zmnF`qUt46SB}?x2_P^obL6dW7IwJ_E3)mKK{^eU+Jxe>h1rh$L-QE8BXTCynlb$i) zE}!LxX7?&XItQ~T&F#(>M^m|diF5BzEjeF9Eniose6kpfkPgdIP;^rL=U2F%`>R%> z_oV@2FMbcNBYe_Uj7F`;7t)#7u-1& z+0|i!46$>sf>t>KOmDKTtCVaBUw~+?--Kl2M5=$niW~UD%jof4vb#G%Bs^+5V==ua zh+{S|7;?~`9xafLG;`GcY6)KDN!Zph_&LW)a-&&rj4xCf<3vnrKqz+*Nc#&ATKVur z4jz?O2fPNW$51!VI;u7qW@hn&ygR+wNa?hLWd5Q zn*rfuL$b1X>;0t_OZ*271&P(g`zqrtR4VfJ_nH(6hk#EfBF9~(Cxq%tTn?y`qFMwr zP9O9)D@zqosHUF}lp;DPwF*rw#rJszdW2ndud>(oCz_g zsw-I{O9!IC8YGVtpBM#X0huLwcImxySPwp|LPscx|^_mIvI>e3glnqts5t$r{ z^wGxLTL_jExs}1s&sx=Z25ju8 zJJ%>|uLqQ+g{mPg<5V_NSCN37v--zp{`RpcZ&U{CP2PStn2IgW^{KOw;)fk~^BAQ0 ztzZb)3;n}0xtFATMhoxnlEZRDD#FdKQyM5u@|Zhj`lrtb$(_vJ!-#h&vcpQp`b3gF z7XB2S$cdxrsA*fGB$g}6nq@N0fALBLqt@BQuY7+LG)G+C{?4(hi*1NHi^6fRZvH^W ztG=XENd}*M6#W~^Iy2rNSi%CSa)ap9m)1EI7?32D&zY)3(APqEYFT#h0Y1<4o?If| z#gwGaMqCX&@!AhhHt0iWWfzA8rd3(7h}bU>poE_YaZJN8tpEc%B7~U!?=^6WtVbiit-;@GnM>i$5KfXgq+Qj_{V^K_}2wdHlv>- zeVb&$XlLF!I@IzO0ncZbErTc_9fEX@s;Xs6%4@~Xr9@vXi>KmD>zSRR{JZN+g*mO! zm{F++$@biG-reRu5e;_0NcL2iVOGBA^>QlBi|<#LQ3>{B@3D4^j7?1YHvA{h`3FmK z(+D8AfaZSe0|9A~-lla1sU-*4)@pgQQ$A?~Y3$P80D~(7kuGK#a7X>KiT}V6EUn&8~zUy~13B9DrzU7sB7J&r%=-yAeo4>4I^HS%2FbvEV!mS#k-eEe?7 z5VC@tIR}2R^xR7BQ}bQIL9x8~aH^4hfuz_;=6OvpQUZ1C%uTWgyhh#IvOg>83@**tK>_u?Zh^2 zQejV&ed$|l2rk5`>t>Y9fIknb2f5#5SH)^4OIUwq1xCq52L5=W=I*h^e0$g%gvJ#Zv7ekF> zQTG2x^lTdP8hd?9rnvNV;G-VFbv?28hV^Kk?X%>6K#8-%YGL7}-2}`Mj>50PN4RzI zCs2w+x>!CVcutu(h6eifzcA53qkdcaT)BIQa+3I(ONP^`Jga=NJXk*G|B2AUvyGL{ zzx*zc*A&T}4jxU?Bt6GJKcK@ym#U=2SL*4mI_Pr;Z+x@+Af!g9(f&H$ zmR1lBM$O8Jt-LntrB~B^=WVU`W_>|Ym}KTK6xyAf(i`15E2@Pg5qjO!WkzeA*Ke|X4G6Jm?r;oKbk?U4 zsr3^3p_q^wd}GKMD}3^j!Va^R_IPTtQ<5PHm2*(|>C?JB&FAs@q;@>XJo>YDS{znj zn^$X{h|5Y~6Gr|_L3+oJ>4CMgY72o#*BwP1; z;Rz0fUwo+4i&j6&g)qpr)AHd=kBW*NC(VzEARB!GqAsnaAeV+S#Z0EqkTo$EK2X`I ztS0|!s5~Oo5jOc=wB?xwYVIPj)ER7x5Z|RYk9CO#$U70N_Cw{a2gCZ}O#Cu}s4nUM z68x&|vUEqhB=%twudY!qqSLG|@vc}36+bXL`6%8trjkyXW+@U7HT`1yka+GQ=j z(i?!P(rFvNJm*qe3pPY1KeJcIjSh^F&W|^!o;Vfi3R}6VxD4|oUoys;d6Di*YH=zn zxEm$t=3uBQLIFCt?oa8u;KJ;=0)nI{RVjP`#|@EIC9rVVU9t7a1FJm%MVn=lIKkdp zeBWuH@-YZgQnxNWpdo9}m=pj;*tfd@!2!}sd~Oc?3Xo{(>x7yo?qwLLNbmY^>7X(43poj5+tim z9*BvwOq;|eI^BYGu^tO#cc$8c?BE8glB_EODBSMz`RVeCAeI8q{X~9BRFLGEKN^!I z;LRU;9l7?J=sj$Z9Y#N;-LH#1{(uioeBbBuZkZX5y8Un1Wh{NgV$s4II{I2Pv)8S8@OaKvxSkfCihXH%1Un1n{aqIA@#n1pn{r5%?kQ1< zYiKa$#0n5Cmv|R^SHBEB8bc|r>qk5rzsp}ljY){~I^Td(DH^`qeG>QodZa#m`BASK zN0N*Q)udC3!p&5W{Vg*i`R_MR6_3o=E)PPeZS_P+k;ys)&AH!ei+rtB8@~~#rv1`l zeYU7od3X5E)E!Pi)tm-{$<@7b(rEVHA0K0Ft6Q?i{Vb>sRk9mf zs?Oa7+QL>>_C-{ZBdEs+=_bBrTvmO!@P${Dik!us7=Ya;J}u0iFRMPK52uVdu3bVO zjDTPcT*)4r@w}A%@8y=>rOBR}ULPbcut;`czwcDkEIOm9VYN51d_L7?P1Ni75i-h$ zZKNn%GV`Q4QLIPj$a~$3^$;i+B-58Bl(Df0VU^ z+auC-UbdgsYmxT=*afe~-T+oK)tP%Tjq>d)OLA-MV#3ijS>uamJ()|txoWO3^+)f4 z4!zfN@i*^%Xw%fw;98tVhOr94x4R>aJ8bO;&=Zab}(=0FQ)bR3zfQ^Od6sG(l$ke** ziaN5))4mb6k|st^{fX7Su{CYhKY~YQ*+kocT7P1-V#i>WH-2&+K>evw9O%nx_Q&7Q zv|arD1%EBF!*O!ca@cF=ZeU3x5$B=%b&5`QUc)!{` zh{1y%OWPeAwmB_!(;~}3u|-WnDN2EPlDA=6={v4%m==hn(NzXtPLQ@p&d>9+?)r;a z7+msF)PJW_ghlZzO4TKfH&lXWA*1QBzZ@QCERd_>pZq7ecya)SORMGoSU?QKw~6ml zPrKs2p_(rfiZFS;++=@<<>(opKYy7UlYIMyN0$0f{)?@nRpZ9LaNtp3;flEY)RV~S z#}Sb(0ES;6hV(?~EJ;po==n98hD#cj0uag(m17Oz%>nBv?~-u(?iz^GZwT=R&CH zpopL>xSSR`H6RsBlX=agbLA#->i#$>C~%XLTfgi`za{(2c_z8~C+AXRC>J`K1j|kV z5_^RIT8}pBZ0hA5waYG6{pr4JJRzj}&PV>WmCL#;4S7x(yUP65+49A3tH9_>?+K6k zY_y~_Mg=Pooia@j*P-XBgxue_t~^-W#R|lY9MrHfz(Kzt3{r&B=*jS-hf*uotNdL zTC+Js5nTD@>6^_TS0emL@XFMu=`Y1CQHFDmXsxF&+|%es>X62_y%pV2_+wSMtlI0b zgBNbd_!l^9^xvk!blsxZqUP&DB4_HgGm(F{qJQ@v=^IovqA`bF($E!m?gZ#et`OdT z_T{3SRE8bF#1St{vjSk9h?t`eSZFp5u%x3--SBM7N7(zYCdHv8q|BlG%$rp@YC*V2}S&|p#zDRP~ujKD;{ z5*Y*9`q;b64S@$_YgP!opuOw(BV*R2>O|zEBW{+qV18M}IUdKwVma}5sDVGuso&&d`w_K7 zv?)`*1b3WrX;N-ZM_{hn{P*1&>AHN&?yx)XMMdv4>(Ad(2Jlja32*9{5{aUCb5J^_K*`Rw z(f<6)xZ%WeVso|u-!ErOTR^HGXL=!cq(sJw#`OsgULI{5sERd*2agU|7a=3M4CyUA1_x~6f7||( zqYDAocC!>tP3q(IrW*M~QSeAXkD{e)cMcQULtrFy=&ZKT2M+cHAc!HX;hAtFc7fI zk#?q%Oc{etk-g^>v{7mTIgPht3@D; zl(3Bn+$EY!JsLw54!4p{?P8Sti75Ck@gt3;j&92C+`|jaW*;A2+x=!n8!%9f_!6*N z8QvDsIGn0=Lr_i%K%7Ba9$xpobQ+ob+NegXiB9=TZS)hSKAbTH%84H<$QTR$mb?)u zPzr{6ogoe);1sr%QiT1KiETtTfP|kqE>=W~NqM%hKfSGvyt!?RBN!Nc%>P5JABXTk zZ8tR%>4X`7zJ&F~Zx@2pfBhBSW7EpP@~K6ei6Xzv4Z#zsqLuEX*Z%jHvfEy_1RgOgpBf`2J7kW z-|1(V!d~{Uo?O&d7mB}IZyXaHKC!${4=jOHa%*5H|1U@{=yZ_NRFpKGKE4dBlu`u4 zKOYrL=G&K(y$>isw(9svh|}32`KVl*8T|^loni8*Dz$r{c%{r6o??ivH1hEA? z>cz!}@s1H*B9RRFMrU!-%GN2!#boPTnOe8eubDBi9oSI3L%W>+3(h{HG;NrkxHax^ zLugULKY#gA0gRLD0h%x?7N6_Ts0RFPtFZuV5Ia>Kp>R(hwljRx4VbQIDuZ7OycPct zUiV(j>6M{>@SGxNpi*KIjk-QQZ(ptU7LvhOx;F6rJ?5PN+C8$|7P0c!ToWbDyAQ*v zErf}T(sLAuAL`L5F&Ptwoc1$alx~@Eb1F(`?zV*q0tm#c%pc%H!#TWp+pNVfp@Ttc zIBR8fU*=S1Nw+1Mw_hAA03v@h7jTTg}0pAUG&Kr~0=+;y$9MPFKL8E!1OeW|`?uB~B@{4a{gRL4SL#+k^=7l9)YqSF0W{$gH44J9r9p2T(I; zrIEAMr)1- zIT}_gJ_zSwr;;WY)7oxF{ZIB(9!9TYYt5K1NWAb<{d}J|MYswpCZ~8X=OLHOGZ{Ss zr(WI0e|1sCbz+Kv;1TXHra5)%RGUOY3lD$bqY33csE9&RZseIk{f=_dHR-Jf0F64j zia2LC0M?vg4H7tH58Vc-e@{b$asK)Q4Z14^(QaC8E81=`NbnNr$Bt=6dy+1ANn;wof9lnO)J2*@VqXzePphm!zCb9>ClhPkVB+*JxK9aPT4@|Bp?=e{a75jPm41`&Je`qhiGzX?W1|2?kTaxHcM5~q`fh&Mu7)e2ivc)~~ z*8B_))%`ZX+y73B&(gL*r=#-2q`%b>M9YKnK+&U5(Rdpq=8V8ruB!6>D!;vk%Uf+5+u_Z(0w+%G>2TOt z1ovZ2PYL`jzc)ED1=q^W;=n#+SxhPH#_~w41;*1pmN))MN)##%_yN}mJSXrVc*@#a zt}0F^1lQ}UIiLZxm2|RoghgUnRO5j}Mi@pqyK7GZ8cOrnN5$yhl4LPJaa*SJHVhj; zrQa4NAl)5l>kVTxc)0xfuc4ZM4NVq7whjgo*Roj!fqfhlxB7bbrW^hdbLpP8Wqp?+ zECRU&e#ZVq81cG-JwEh9#?fD7nf=JUfc=r+I?b=fsF*K4KcS(G`vzo_uNL~J?Ym9 z$-4t2Vx#N_gR*jm^z*|yd?BW`0ZdtdQg3liYr3nIW0VJj=a7s6%ru6V0u^uV0vCwM z$btv?2*VGj+?oQVk>oUAUD^bHzgp>MJZzrZ7;v>K3edqWCb zJaQ8VGw=ni7|X%Fq4fcoJH0xUc$GcLny+Pg@Z}vR=*S*y7qVT~SP};g@S1Br^@h>F zgle>6hEi#M1}=s^$eBrTM*Eym>M!`bpkI7ohiE3bTQloGSW`?E8~}003hM2mG-V3j zQw#VZRp-huTGItV z!iRu)3F9-7P&rCS0=n-eLUptso<@bf9$`je!x?^4))Sti#rnnFe?|}8c%HM8TGV9X znfu^FDL&y8(!;E5CnDGjTDdSmXV`nHhM zC;JSyLt&iEZ=Rr&yv#2n@jAi+;to~v1einkVy9)4V?ZNzdyJ1(0p7*9sAq<%%`V~7 zUu#$^G4tQ<1~3P#7_XHYL7DQ9Z4%0B@(*SWUp~FFPMztBrU_3V9ksz-;)fl1&nz7w zIaVGr;Ue91Y*==-k1{Q3Lsl(p*EFCo>6ic9yA0%H4xP12K>YY!Unro#zMJ1wj&_jT z`=s3QXROEx-N+bQRu&u_p7()G^CYu37y^wL<~w!q{Ng^k!tZ%q;KRLBA}P~TC0F^> zL|J6EQ+*H6hh)3Z*xNn3aAfRg`77^YzuSD)GlP=BJ^V#elmAij<%hv>2cS}V8+zXZ zYG643;HIxjjZ_93zjRj9HjY=F6YEO8Fmqix4>gOmzrGrLxxt zYx;G7z>!;K66YR2pFwl@8jSQhHXRa1$qGf6-{8d;eCR<}{@MNjGQLhT*Iqbo(-aL% z+TJT;hN^%diGBmM-Z3MS5v~qjo?4J$Yg|1e=z1@42~(lvZ%?v!ou=$sV_`et4LhZs zvb!VqxO9MgPjLKSzhPrvh#F!ic$WnSs?`MLe}T-+;X^z(sF94*#!MqkddrKHBu7;x z-eP|3L7ay#^$*}%v*8ex2`f)~EqPw&X&)+o-`eNweEfVE&5v@~ET#RJXqNw4%EHPK z>^u(i=bM}FHq({`s*Z4KTjc92fjt8aFnmH)g?d}~7G>5H{gUrWCKfZ{Td{B{Djyz0 zcddViuSwQByHC7|{k&XfM(TjyArtr>SG-m7KY`MAVQ4mTln>wQH5(p|4AETwp46fU z4>5NNA)f%6>$$4wgAudRyCKWQ2fZbt{Tnirt7q#j${GSUg06Hd{o-bUW& zl1nX>qjq9qvdm=3n@;?BU7Zf+{|cUg8_u9vy6=oYAzsYojW?oNWMZZ`>`IP!o@uoaUs~IBy)RneXy+E1L?dSqh3}i?)Gqn5tIKj9eTySNaTiNUVNnG_l*Dv`azL*0d2}%V%t@T1SU~D z<{`6ie{x;xW?P%ApbPRtXx&p+Z@VR>YjL;djPAbNF%!}!r+FCm18r^___5;(o%i{j zIH!8=i5NKCPp#5`r}4~;uK-(YN;oC<#L$nuzulV2U`6qsK1Ii)6h;l0XzVPa8of)@ zvbhx|SM0(t^Y7!-E>k(Oun@(__jJA{Xn%BerCszoncdhBzh&OJRO{>JY!Mc}m!Fvu z)Q~OHw1Az-dmNe;gC2(5Y3_{qf$%df3H^@K@{+yCf3|Bf7q#x+aAC_H`ndbuv6{-U zOJPv8tO-iKOYRP?uzM-!Nie@Jr>x-3KY#nD4+??7Htx%PSG0Gw6JLWm^uHJ~f71Nq zwvJj<4`b_-H_to}Ee1qT{eHzqVy~O+>hGSPY{AsP$A3)?>7x9+&z6eiYRR^5<@5{~ z#P|8~QC0vPF6815C~cHrL*zrjP8_dAI@eX*e%>>-mgMGb7Qiw#A^dnGIHgt>rsoUM z7nASDS#Z|fLOJ^i^l1OKE($S=Y$pzYhkl!2itpmh0||R&HfhuDo?Ly_(`pYlrF8!3 z=rxIXB__#7J2gWwbKhkhY^$F*aLi&J%v*fYmS+uV<&ftCNVd!sHU;IO#TOsoE98Jun&@EVL>zhJ<_y<1{G`#C{Jv zj3I)UYjoAJbgoDK@a3!I+dV&B?(xw1nKXh7_vsR&ww4rPh#=*48K1VdhNe;b=SG&K zDy9{{?|Jf&MziN6IC_6u9P6O0hi+Dr-iU(*YkGdM{vL@Jv}I$8uNyyC$jxS_M{%2I zyxq6BqYb{(|M^M-*xFo$ffklcMoR^^W-CNneLHfqEpWkn)^hUx+mpIMV8vbJMW?>( z#(zEl&mK^Ogsk(_ZsmWQR=|I=?jK6}F|AglfFZjH1FuOgPoq-CI%sW=nTYi=4Fg|3 zJKV_LU@c}`P%!ngcjRzl?Fg9Oqo9YD9~ED|X6&d`Hw__TEWB0lMtiaD5B@G(t;WP*F(@xE#hNYD zdxe4~?wU-(SRj~$RIUPc;d_IMgl5Qb9a`kd4`p_ZVDKp}^1ST?MBy9&GSloDD%N}N z8Fa?Fqdbqy)UWiRLDBu%+Z`)_573iih?B%Riu`K8xo+T|4KNN^NA#P43uLb&zg+6= z4jDbSan}hwr_$0M`leR?_0d?kzn|C9SuW6Qt4jZO?z)t*+tmSzj?0{C@{DD0b1G5P z^LEe=dF&mfVgvt zt9Hvas~zBw+L~E>L1`zHufbYoS_>fl2GuJ8tIM1BzMnPj8>l~MbekEXcvp2z65hOC zjS7swFF_fJ-1s#DpxZONF!z7gVsG0KwwyfXiM)fkyY0O7!6W||BZ5TIM5?K6Pk~6 z1Hfkk>Vj=#F7B^8g4i#Bke>s<2tXf0Pere0(Qc_AytQAO8=z!(j4RYtXeW^8i9T!s4sq>V5SUmXL@;vq z6Vj=nL(Cy9@g_r3vnb9Ay|D z&AiQM0^kFpmf-}v30$Ucs&W-`bSid0GL1Y9i|k(NO_zqzT=|iy6sJJXj<9l$zBL5d z#hCqK*W_Wy`z&5OwgdiE zZ|Isq(mjHQwyZ{>fzk}IJQS%HHNd9zHrvH#F^8|o)(Pn=H_k~CCnO9wj*i}ey<=BK z+SIprpM=L9Ks*cL<>2r2G}~h6@1zIy@()dC$+{b^Ph2)H^L>T%6-WQ~CyJnbk1r#` z*!hp6pN}TlP9xzBWn4hweHW#P_UqfQ29cIFYK?>DH3fKt>OiZMx*-Q$*!-{ zmf2`8-*s9RM2vWHPm(e)37g5qJij&b?kq;fp&C|CqVdA<%%pWphhfDA}(r_`TZsD6VH!!bJr?9;X*a$K0x(tg?O~_Gr`hf1JQ&&b-!KD!Y&#yu3UqV0w4j-n>H1 z2GjFiW{TX!8&j2GT%mJn6{yH+B$Q>IANqz?8Y``#Lp@v!5X-PH` zLCmnw2ASf<7$?-syI;($dKt!5%^aCh@;sO<8teq_3d#|I?vI6E(kF&b&d(g*It{X! zoxieYZNZH~yAmiocmIxSyDe^r-5Y=wmz zif;X^OQ_W*nyFcrpDCJS4bDetqbqebuC5OSP644i&BSSTpMAM0C+|bjD^r3wJ@LrX z6_uS4i=T^=#dJXS_WKwz4b(atYx$bor$kjc zilbq$?H|T1o+_4NWn`kuL(WZB$AF}QK-Eu!z1h83t)nCN#rc}_$;)P10UAmGU?QVa z9-)HwxP!X;WO7LbPa*GxV-e;e#t@{{G4B}xL;=MsiW<+%Q0B_M~{X3q~^&TzT|g()?Scx~1yTzsVhSn)F&0 z#Q;2L%adg9M?i~sUbIcNaxWIiAh57=M*#9GRKIhEKuxv}aSs!H5>y>C$6?Av2xg2Rp3FK>|V^EQ9vNomoKa4x4K(59z1DE-lj7+X0}7ISd&=g;}htE;QWV^zIDVcsT&RfsQ`SQ z*VFKVoI+LsU4Lg+Y-NfHoeDPT?5{3sv{~RLz#~VH7Clrl`&eUl)%jHzm|E3B$_VNj zEai+JN95%z^Q=Bd+pwdIOTmh-zD zSJovU8cx73so`sW1|6{a#F7-;-(V-^oeSboc55aNkV)OdtLFCg5vY8eOYJ(0Q3w0& zs-v(4MJ&CHcxl`$YKdRCzm^2pDH%66OmkPgU{z`+x5z=2%J#i$Njp&xpYHW5iUUlb zlKtESqE3CGD>$N~L1k_YfC+sq8U`*D>2t9>hBhT))){A{4f)4z@$-wJ->saug-UB| zM_{axjS8KGkH9F9O|k!%*47t(_BGuX9v!0?wb@p#pr4CZU6!yxq*?0NAA!8>6Pa4py3KcGD~|1p54NW7ra5sb!E zYYN=ifMbrC7UO0NfeRM)dkfjUA-j5!uK0J}@hG8jt&dY|(}_yz$zn!}@8)IC$`(+< zB1cR%E)*Lq;fEc%Oc!GtQ~(t9el&pB)UfHw6%ll;fzc31!6~0h+tEMM9ri&vad>HM zat|~4>9dZ}SqxBrDWD7uuEB?pH(1}2yot>MWTqZnRabV$&5s9GWAQP)_TIp7`O9VO zU^qo2;v>H^B6+#Pu;N@`hduN63tZyud9HWc{Jd=Ti*x8rTm)Z-dRB=iCZFH?onvI} zz;8N*MDi$>aY%YJX?4G%V1|0mbX|h!aEsT)NpWe;|CN(S#l;ppuktD%uG<^W_RLaP z`_bk`g>y7t=(OO1&b+2T+MCa6+O?5Ip*}Y%P+CY7h)7yYcLDZ&u13)cWBm??-xYm@ zwh}^5Kc9xiTO*~{0oj+#s-+F5r=N9W?e=Z}`)lFb??@Xtw<|D3*zevdv8AjIyVz%T zsQ(Ogb;954=XE0?!feg6R}~<0VjWQ=#av1~vGCQ1M|9XX`s65_^RP*rSM{~XSGX>9 z`l{kKMN^Ju#C&6>F|WRw2y=O^o(vF|909^6GRmm1JsWTIryL@rtlkYw(L{S=%Ny(C z!CWJ-o`0M6#=!e)HC3@-fjUoN6Z;rg>qNveC#MnMeZPn>Gg=W?{8APyzPz{0mVJTSNPrDIildXS?3Hi1FOCbm)fdGr8fv=r+tqN5+8xaEy-KQOIcc zbI+jKiF1x<|Mz}GZ%C++ZvV`jJ;hGwSDI+_hSyaQJ_ZKiMhqyI_u^=aN{Jc2B7x4f z{?3V()wB4T6aIOr!oF)cWI#Vhmt`H96F@z zo{@eTi4TVt z9MnB0kDaZM3y7H}L@D3775M;vfF|E)7?VA4=*R!HRb%2Vp2RSMH5}$mf4%i7l40of zvHMC7NIHUqe}+cyD$0%i0G{S*03UvA317 zibU*};SX^!7g^$dC>fU0voa?F#CQ zpUf+M7fJf0jQ%$!LgR?jj_5V8-as7YKI?R0Rx(HVn?x70vyWW_ zZFdDV$-GTFGB$VPF&XpBb95-duaOFuO?Oo!$2t)vlxx~`)usWs-JijW|Kit^z|@6`J)6z zwc(;(myOH#8L_+MCueRm(f*S|@%(SD%4-=J${vp5 z0wcbrvZ40cd}IBbPxF%`&vSy96A@(+SYIJ)a5nKRhlik(*q!HnMuN3Upf1SaOE^n@ zXZrTvVGeb!#nw2i`5K?4v5v0?wkO)G5xQK2Ie~VrS?Gk7LC-)|5?-dkqq~|}eQDr= z9j^fc{(7D{oXw;@F|Nt&x;$O|?N}SsxmHSUt3QjSb#mp>Q9z)9O?#k86@`?Q^Gl8k zyFm+zI*vuH%b@o{E_l$c$0)1wFYf>p#|C@RpoDy#7B>3K;i?a!y?135FnA|s8%sg` zPg(Xyq@J8**Ux9a(4-R(x#;XQ^B-iEsu z13vxA&+b}3inZ#eR~^CgH?!^AI^UgF^OD3*ABok~)3bh*XZTs53+TdwmoT2^VRaPP z>S03Pu0%mz#=g2Nzpha-kTSUZHtXTcZ}*;&!J0ruU&z46RPkmxRt>;V6>lyTEMMXK z`txtchuU@($q{pp(9>0+vjUJ`FaNBXyUDvwS*)AeCHq3>#&t!us??rGdLjp{^o51- z@KxPY5#moh`YFiO^GH^O2oQRzKa#Uj#1y%REfBkRM z#MYC|`X=W95fRz0bK0csdk?|j!mo`dAxcjydr9_-`LnJA^Y6eS{X#m#I7Qb^b;H)0 zvwVBZn;g7MUgQ|MFRCSfLeXC(pU&FNqCm}D7K%C|q(i$Iz<3&5$zgq$)y_#xN`?&k zFv-G!xxqr*Cy%D8;IWE{H7_a{f5qg1O_rl;L)4yFaF;1yY05$_#`{^NQ?pG~&XNV9 z*qLA8c^ub30xI+y4}fd_!X;o;YWi5I^|>O$;DPB=NX<(Mx}bwP0H=XfTKZO8k2ggL3;Lr zFX6bO7R`u_fne?;e>Bx7WtDVa4s6sLW0$BVl0keDv3A~BzJmX9Qb2I{j~zS~o94hP z0JtQ-S&pdn9!mG078L#*e4@zqtio_eZj~arHB}!dtu2Q!rP*JqE#X1>Q)Qf~D)*wSkF!<=7^)^+f<$(kIsH!3$F zky}574Z=Kn>5}{K<|5pYb6c%0x0IiUx67rOKg5-S zjt^wF93^I8o6OO+53qJU_SeTsaDGgYm_YGA5;?&`m8E7w|7~ngW~`R-q4M-TX1*Uk zCoge{`H$MtklVzhJ}UeoAyjOskcz~la@pbeKixmDDV1jKueEwlZYyn5XysW9C58>w zdBc%)&oPC}Y(zEb8Akd{VNzK>oUbaY2>r#+`~6?k+IRPt9kWujJwCW*`crZtAhm+p z2QK!?VDaRzyxuH=kwu%OvHx*{X8OS+!`!{i(2vI2ji z9w>-q^(2Bxuk;<(cgV|}sp)xs_+n(D<3eZqpwI{L&!=}$DsY9IJJq{oK<#07FO9ed zhWmxs(4VwRjM%Y1!dAC-8!p2@9+ZUZU%m05o9W&g_YajmpO(;D4aoV+Ncz=Q)KuP5N&!2W=;< zaLwuS?xFGM793~A?ctMVSoLRgYeWcS53JB&#FcYY?}NhY8e;S7o~`ekuV2JrTHMKV z#U6{rXVyhODUkR+J5LbH1oJ{JvY$yM&Tk1_63R5xf|(D=@>#AQ#Yt)`$ss9QQuCH< zDy7yxPXnhfM=L5d6shg2^^kuVcAE%?!=9yWCAZpYQeMOM(w39@iY@Vz1c_`dIM~;P z1gWZ5$O=CNp$z`|mCj1p7PX>= z_;z^@SKji?As>h>yTwNo8p{ILho|M}DDuP;ig5D^VXK2Wa%6khLQ zC)jdwPfF(>i>S_2TGg&-`WX_TQ%{mYr>IX&Y*q>cyr*EW>h}=4DWVVU>87(KBCH8q z9dDET>i9N%J^Iac^X~#C?dQQ?g8&uXe4m|jdR|+xea&ecQ7xwR{}puv%QSY*5fXL_ z_4xq#_k@Y>JC5Cw1ym6pZl`E7wcuQXNK&+LXLF_g{WLMGoSp|YQ4vpn!ns7rRS&JO zzBHn}Ql?7S=_R{BWfi~2=XS%Q333VU>j)7=p2-`yPM!#>ftj7wHx!R1TMDTOLEHOLyT?W2@+zEGlk6J(E~!T z>EqF4=YP7M9dU=k_-1UFH23j1G>POi<)+s5=K4@oNjj|`2B}}+qNNLQ+7$+i zL^KvEV*ACU_52)~@M9!VBzcRM`w9H_kYO~e{}vbuPih8Klk=SQ4B4T^0$#;})uL?R zDV^~kHKEXj64#S?w>294&PI7HthiOGG00g!#IqwuScxNc&7>sqS|1 z&;(u-jhnWa&%?P-`(5_a>8vI*^^D2n-z*zv<4~@c?(Q&X<0iZf)2ZLa-oTcYE|4$)Kq!WV z{1r1*h1B+!Q}*!|y#ALfzHPs!MNY9LaVvrStPE#uagI=H>|ql+VoY0^slHqSN&c&m z*86SPvgn@j5l`ZrOIUlb3h7_fRDrq3z*G~wv|kgdhRuOMEkf;1a0y?r|3X>Y5hG~z zl#706riO>0jhVx1lbq>8O;$kXpP90l35D<>`?JW9b7Zn|mUYUv*}71%SnhG13-W-N zFj&1$S6>yxJU?+-OfpZg!u|l)z}Cz|wIMU8oy~fuSnM29o@L=)tNm(P4^I zd>XSNPU|I(q4{#AMmPiHOis>6A7lM?oA*MGuU==ukLEFEX3YBkYNvCHD~pp^YpE$2 zNitffvh?I!xbSC?0>T}m%E~!|2QY7%`4jhaYkWk4is|YER0`Bx9=(|9%Nt>(|&#(6UVB1warhI1m@NY&R3*IsUTEsi6&R2c5>TLcM zhD^EcF;+tD-D>8$1u(ceohE_P5eH*aNpD3YIL|RvbH?=?O)NlPNphr_%l;-4s4$q@ zqBPO6K(_!HL}7dH$Fth2^R-i(bmm=NKct~OOeUMG_$;;=bs+9zpJICae*h#w+rFG$ z&JS4cUdy^#QPI7nzRy5ycFMP%P+A57Fe@;+XJkF3ADvZivaw1%Z6rkIl zB{+R?$;18664V|!le_fki!WV%S;n+gf5mdtJQqobW<>};K1@(Coz)ap78YH#5*Ixe z$)$=#SFOZ~-xJhK7X-dylfW6l0xMf{6|Y;>%sD=r`|l~!grFE-X8ph;kvc)s9OCQNjN<4bMl-r~gWr zT&n9g>bi?LY(`LRIck=An0H`5Vasw>UNu`?N;?eC$D+4bp^Qr@UzS_SSNkn$(wrxb z3sq-aO4}`+4z=2DN>eSY*V0rq4af8rRH zMcuWA@1dJN@itNFWT}Nq*l<~`8-tyB6CdNh7)yS7>2hAJ=ctxus-B1RozJibzUotG z-(WRblKmJBaKea1^7mmolVvAg*!*gQ7r$>zmhQAWi`{V z2E_T%NB^iWnZwSN)z%umhwSqNwQD9NP7=fI5|I_m%WWaQ0 zqsUr&2-4gG?&OmdpxOf_ABz=_L$7?kT&qUb)K){9TXUt5N-TH9*CB;?V-olnlmCrL z%MNH)%{dWeNQ9wTZv)v!{&sttIU6a3z2y8~|Ry*^5?ebV%y-z833hmYUQm>F1Gb*ZJc>qF7`!0C%GUAgRiD_1OCdD-G% zobRWq!$t}Ce%!J{Y?CjIh70#rL{mUgP{fQQ2Mkw+(XUQmq*ub3Ki3j?@llf$5cej7>d@ZI_P>S(ndv7#xaG$ znz<)=vCdgEXBseGiuKZXsW~t414%1azxRSwk%gr~VNHn!g*A~*U3@3W$LyCQiDpr@ z2w+|)mZ$dhtCnt3R|Jo0PwmT?YSu%A=pAaGOFiFqsf(H-gl(_RVM$jQZX#9O{St}T zE{o@0BdA@J;9aCBQx*s0x!W(`Q@U#YDh?LCE^;buAe&cReW^IY%IVp>>gvmaRA1RTnSW*b!E>9QY*30>}bXGYS`0M z(@Z21#+@NLI)P>^^6=BTck!}aXt7gY0YKaVd)+$7CVST(+?4RqMr0B)A}3Ubyq zbZnKF$+$?SVGUrr^rBn|RBuuZ-!m+YVu!?|;wIJbU8;JvgURxm0J|lTZF<9&mQpjc+cqp8cZLbc!T+M7JbG<X zyyM|_!Zx0f#Sv*ItHPt2OMU!FVw=9~_!mv*GkAu7B&FIjvYM^ar6?p0F!vJ=mf`yF zfurFj@yk(NYWZ!<`4ZguvbLjPyP&I<#(KAh9f>m+3)gjhN5d|`&s8<5`9ruz{NAJ* zzF}ptH*s`YB~Yzp?IwT7$AQF_g_S_Hsivvv;YflV{HgYh9Ch(b;<9&F0@dt=){Xtt z!m-3t4>581(t>SK98d7hQ@UuPt2o= z1?DlTX6~`3VnQ1P&VECj`U?wl^lPsXoL(H0M9BKU8w9n^aekPf$X*aHpS%4o!uhLi z7Wn;x1gJI*YXCJo)Uj!HcN69mL!;}bx-oATZ*&cd1i`^l{w(8Q^)B9^)OR%TR#G(! znQIN->-Jr&<40LN)8@asg94g8NL{Mq67JqEbyUmH2B?mYTzfA8s*i>v;eTZ;%#q(L8gU*UA^NGRV^Q+WSeuF3tT%$!aq3YqWA!|K>{q<5R*z$E zl-K@(iL-$-NNTP)p=mnTgsZZ0rsLY0p<|7RZk~~~R1@pYf0_NXQ%07J zQs~Z4s^kHaWiLbfpJhXv>7gKfo{@5_TV*WllH@lDP_5d!3L5eqJSu+KrtaW~AQ?KI5#v#gE#(+i7RRJl*b}xCY*<;m zDD@tVjOlhJgX7Xx9t>=4z{B+kUP2!>tStUj{BrnObN^=CB%XMVVOfTi#m)Q%#OkzZ zv+jF~_-)ZmDI?3{)tAIG$2Bb9wEsW${yt8wqDmOYPtQz}?jm%04Abcj5PIdsNkEvF zWHM32B$JnkBxHV>K(Y?wPeQ*XQ>RXy zb4nYA+Z*^^Y*<>+hJzyC@YtB|Qut`_y?M-c={BneJ{Ew8q<*6acQo)7TW}fMLk%B3 zF8IC0n9jz0mzLp>C|GRk_o+6#LDMQO^%;DkA>8I!o@&GJNqkZZ^=MANMIEnX`*65n z?E(Ujw1mt6lVZ<9!ly)UXhpk+nkI9-t33wa5mbb!aJ*sWwFHkg?l7EaaLy;ZB9z#s z8`i&wJXb3*9aCl+#uF&x=q9_$))|~^n91N)h@D)7YU8tw1R$xojQY&;sWuD~jW;7& zE_rMo^I>8E7Xf(6Hp_?iEw~HYSl&Yof4kxNaA3hdVJY44H=`7z!=VMdYs%YgZMcsQ zJse&zikq?H+66xQrx$z>Q%0%bS1i-kh6`|NLFz)8X4={?R2Sl+Mrm}nOEuO%Y&bBn z@E%-RL8_{zKd^B3&#^nW*z6nHFxwyXJDTL&$ z%z^`pxPZaeZ6C9A!z#k9i~S93@Ae5XV>QxYW{NW-;%9Af;HF}QFq$M3q>Zpp4;(e$2V?Jc~ z5SuRKcz@*`XvKe_;KI?qr;&tujH0wASQKB}EtH-i8N5gNOl!^NN&$u*e@OaCOM4{QCRxvIDs@|8@L1! zrXP7n_VD>+mRj6fxXCD9OjJB*LRz`}7(c={L9N7e-_V9--~x5|p2gw4aj$G!2$Z1- zf;PQv{CHH>s8(XoeH-#UhkvdA`WXZu=~9h3uB~bQnDn5wO}z})y?6$Z0;gl!CY0`3 zOr)^r*tVIk6rdVgbS6scwxM&Z)y5Z&@r_)hFiVFCk?2;eeJI5pXylyItyuefYM5}V zk^l!AJI*8=++t%s99;TrBLPSjx44YKp`{} zJnDHcbN!dj#@$Yya}N(ceJ&AJ-d4r&{(lu#VLBWc=7U(KW5_uAHEMB{^wHrbaHIA# zYFUgQ&d@=BQWQ}$JeU%xg44tCVZI|4wSM1ru=OVd#^7k_^|*}sOowTKlAj%ChRs}r z-#Tz$0SOtMx+b#I0h!Nxab;HSbM3+|>NAMn za}3+0QH!hNQ@C3seZv}uO!!}1jBvhP zkSRxDQ`sZ(#t+NFi_dWF%?(T(SC!F^)NBF=Ebc$x3|tcV<-Dz#R=T%i!m{qNmOzK?@gro6Ot7kfm@8KT8rw@4bLi z8&JvfO4+_I3E8sQ&~e!ar1*bkvNB{kmk@v?)%H~kmto|$)+Zj~dM3O_ z#H2Q!20J+3WU+`98NWbS@zf3&%eSf#r8CA<#0=-qBq?^4Cb;zzi+z?GU?_B{}RRCo#LMTsHTzut01#1x4dz-7IZ_G>|h%GS?i1EEdy(6 zksP@<0jn)Ex1fGsZnM+bk`j9RBEnhCLx)4R7xY`ajHvuJCJe)cs)nVVK% z4Ygw_fpp)p8vYpOLw3C~kwl^D@Y(d>;XGlnqX?Xrsw$64? zt3pjkWm8v)?F;L~nIm{Yt0B}N zZ(BwnJuUW=<*PzFCC7K+!&w69qui)nwPBKK(CYf;^xZqFFN8Y6x>+#2+l@nJstUV>h%`Dr#xD-{g zJZXom8wG>u(2dDq#|RqQ&L(iqK){kP740!H%Z@g1Ca~ok5(vIaPIC@kAtjg)Nh%9p z6^jcK0l3)*D!I6IXbnYJ_mXqeMZin$K9@lH)l@MP##rS9~dGtXM0(1$=d^`f^=}Q;SRhbUfoftG=ew!s>h zEf(xKkHBC%Fn3R84L$yJq zu7OGUw+pI`B6TfH%D>%EZ4#;LU{d~VZ-eRrSz9|y2LC&tx=?_(cfw@we>GGW$@Dca z8T{{pYFwtTg~{N5H&hcceH~27{~c{mB?4zhJ4^=uJD_@ofbZyp$>9HLs4kZ2YhW_? z-v!k(W%^o}4E}dRH7V2A!KD1(*#^}m0%vDCOp5v_cEJ((cP$*{so`Ye!+dj&C=6+A7b|kj$V0Cskj}O9wHTQiJbyBk z1*xhC_=C%eo|tmcdU%;Xf2~@VViU6Zd;;lS!TJJMLj?dm(i@r&{+^3w$QyED6$&Id zUzy34?K6mH56dNmk(Fw6Gzhc(e8N@FQj07qtg3pE9ITKPhDIZ)?4(?CT-X^;5Pnc} z{oRH(?1?L>kl3*7ohq#n6O-=jWKu{oXc%IY8Ne4&mx5Ox5dYu>1R$x6YbNvL&dI;F z+nx`tSZT6Eg&8rl@dK=Gc-*q3egFND*$}Dz)cFL?83;NfvurHOH^ixX6M^{hIh>~T z^>#egM!+JAb2zJvUEjU25j%LvWzW@%UH`He9=t&9Le!S=xz?LKvPAZvYxss$1mLHk ze5C;KP?e(?&r_}w%3kj;w z208|V2B4a5W2FEuUPvIL-DfKPH} z&@#}qW=$JE!|@Pq(=RnP@BIhf9oWIsFExgQj~bRRd;-Xx5L$q+ekGf}j)cV=ZG@T? zaX~oInC@0Ka}68me&*p2nJHMT#GM9l;?V2v3e`{$|UEi&_a(8=G6d z(-3mJ2531=iO;tZn2a^|{-aVN4lCxXAd{Vz1Ljk=h<3}IH*$6DUH6HwVX*l5heW`% zz8**+NZ4Jqbnk5?VV!}27i7DaFU0N&O9q+WQHzv!_CqFHeIPyy%Wdoo?oZ$X;KiIY z!NfFtuN#`WveMSEkGcG@DWTGb1q)9i^+o2p)Y9!T=MP*RfyQ_qD^qbS38^dZ?1z_H z2`T{wr9fL^roP?QhPPP-8y2i0a46QCQSVoj^$~$hWvAtIF>P&lgRTcYK`yn1A^xkM zMQV=}o?1y@`Kp0{3h7pWvA{O3B9NZsM!o9cGXj)ZHvLiq004Y{6$v80pFE9SRIpki zcv`bZe!Pe;a!2z3_$GwjH$sVk{tw(rA?(Wtjt{I-MmsPW5g`uxed@Db+tis0Ox$C~jD#0pmyqMH(jGFD*Djgh%M(AA$ zPhPCH!5g=f+}Q~xV)xW&o1)ZTc?k(;r8u~3g?RSFKF(N#Rs!lDakj#RuU8glQQ56?**@v# zjr&WTYdL;R7*1%lID0*TmVv0`m}))}y)auI3}#^J`D`PB^npcuS%&$671DTuK>A2p z=A+WVqUL2{R!A!lVNtns0fF?)n%S|f8-_~QjG$VyD@!0fO{$Q*P6CiDR4mP+W#-d7#7`Z^F0c4B54rcQ<}Q3D z=5_NtNAqbO`s9ac@j&M#o>1^<9;&eiR&(b+OD|L`&8K-d7!y5USdIpVga>GujyW0} zj&ZHA&>>B0d;?9gR)h%Q=+eyBHaKQlzjjX-XvN)TeM7OlAd6f{cS46`zJr^THf(Qb|J7r74l%+PvN3vuGD8mIfyT0Za@LObc+I zjrkta{4#Z5rs3K(1R&|)s5Sncf0&h`VL8+BdH@z7q>Xv^!MqfCXGPUN)@lJu+gxTmY;GNih#~su1abZ@!iTtPb|irg@VU?XyZk3Ns6Ry4(Dj5 zB~s+GX_AoyE&On2aPsf$fXuSv8Gi7;OL>!{GD7C%#>(}FT;-W%eZY}yT|)vSC-s?!CQDfGLE&|I}@tqkCKA3=X?(&A&4vZLX8kXVj zrrt1QmgSz}EB#KTF+V&)=50*4^9D#>SW6&1nc#SWi5q0cvxj8=^D8uA#BLQV={pjR zKv3$wwIsxqH~bN%`L+wGY}=Mav(15|B@e^-ai8yM@mueYhz((}=57MnGIa)`lG^TZ zhba%0;A=zphR}zbp{4ijjkERO`w4G-Ac5!4K!)XmhJ5tiZbhb2ds%_WEZZyk`Qo;) zpNF=Qc^LrS5LHnAeC)mioYjo9NFCT&usk4TOU2T_Sw|o}{o5FV1pS6tkezWB0suhL zcIdte1Gsq|Q9B*Mwyh(fA;^sY*&|=#?N_QQX(ejGO>ZEOj>l`po98*%u{*`~uuroq zmM?>C>(raBHn+F zK^xyQT&9hTL3jAE57s~M1|q=rK_CARPW{($pMJb|EaB~G*de?vf4feZf}_;%_dzN< zEkjKe4A=7kxOFd&?}h(EEWF6AZy;f`J;$Vmwb^xT7gCwM88Iv8D9?(iZnSgX=86TT4launm8wjMGOKUTu#=U*Mi`KvC1F6#k;+^-0mJmpv zT2hO$h+)w_bS8oHp@!N_&8hUccEKocrSRzo{PSGIt`D6=Xxw1-KbW8in}HZz2FmdxW_K(;kHsnmq>JsMpQ# zG-ekdw{!skNS1WhGj3qgIs>^*+b7<{?U#xk^a_jQtJs(i*BwBgZi#YZr2wT*V6CIn z@Sz%W&W|j9N%7Y%SG3HIYZpY%C?P+^eMr}8$SjMC>yQ_YC4x=xwoj4B6jsluEd%Xs zBI3WaB$~XUS#%Ls?9VI;9wQWifNLUNs+QY*7-tc#zk)#exAa#I9WcZn%Odi$!PoO0kEU<{p z$6VjA1>2c^Gl6ueHU>r=z}D;`Tij+0AtS<;|%b-{jHn~o1?wd(Ce9U!icZ06G%=1KO(oFV{DX1xXMcx-ehfph4)+r6^ z73}%&8A`}xr%%Rbrw+zPG;-J&PlfOrrW5pPAQ>^(w^g+{beQa@QnR)P!8wsQ*ejA$| zt8lPH=1eSmofDtU;ft8Lf!5z*V}4&xa8l*Sa=+O~Hcm{WH<%lKix>wvm&NK zX4zqJO>uV*2^eeQ`}42%U~+K;d$X`h40&IVWIib1#b3XU03^3mEX_A;OCBt?7$$=p zuF&Lm<%tBmzQ=@az8v_Gj31km!IbPxZ6N9>a4NcbxJFpARGxZw4}l}G<^#vLM1c2_ z4dOmPT(n;jcn6i(m|iJ6JE%L%&5*EH0E98xdp8kjhV*hppYI{zs7BC2Jc}rCY)jPj zgkw?IoGAFUn@HH-A}jhTg?a|2y6*CDP;s29$x++Yd3-2gI9R6cFr+#*5tLr3J`S11 z=wq!@pKh!aAUn93h|fOTgOyyrqEnyt4;v1w;&^?#&-UPAgq=e=bK%pQNcj30Ulgh4 z(%lW=)|-OmtK?XP?b@=Lgpy{0?Sw7OGYA!clzLGc`wz{w#Brm-?cjI^g~+-q+9Eg zIS05cdtjHKSav=aE_v{I4>I>|C3C5qgJHofM?TgbSJKGdSEx z1eU&q03`AGafoj}mH93F=j(-1JUIA4cRJl>Zr(neN z*eonp;&;AV6W;=AO9SCZP8`!U70Bid3#&dVv6Z@b4GZfpk0Z9dJ5 zDSUbgIg;tOkjR@?^VSx=!h7MBp|El7X;hgtSzaB^XAdR*7? z-B#W&9Fe!Z&g`j2A|J)^9i;YcxY{W+e_^F}m3h=dy&&AiHlOApg*>umPR)CB2z{?fAqnE9DK( z?`2fqL9Gfk;q5yW3W6P=21prnJAb|8aE4|01~rWvm@ZXjmaQ{!3s!r0u0h$llPH2+ zjlbGVhCuo-;d^{YI$9Gu=MzXDo}-71nAnb9Kp=g1u`C}<5V3VhF^&5Ye{m^+^x;*! zqm-=-($@R0>!(Cnac)J+S8r$dX(gZLv?6ZJ`v$(x(_QJR`2I?BP+%}w7Q zAR?5y$788a-`rFR)B4eIf9B>U6rVX_Oxs93!-JDD11sre)Y)!~FrIhn<|b5=asv8j zk$HU#&p1%s-_-f2P`sPeDD(G%CiV+tB0xZo%XGts1N#L*LvV0^)0S%qK$5!5q8^;s z-^7&f-b#^SJutn$i7R}ANcP;{erA8uufqbphUI%OaZ3{p4Mz$GZV@0sQ4fyX(nJOc ze_P+h`1JVW!IaFv_KU=630aj&NT?tG{nY&j!=9HJFjf=%zw3?a226P^KBwEEpCwjT@NDvrpAzi@49c zS0=w-lUZWg@D_=H!%X}jAO-R7Hmq^IKZ#3Mq)}8 zYuJM^b`5q3qpnukpzAK2sy5+s9y~xZRBvi}Xb)bKSvpL}4{nWp;HIX__Y!^(9f6}a zHT?v?kf!anHVg-EZd(0D0+95^y?&qiaOmcyJN9A%r)CFr9H#GLR3C@KH#hO!MJrXT z;c$^2xmheypLsrfL41V(Yc>kesDCoTDNA!Fx6yJhLaFU=4DVS!4b>5y*s(yds&<8~1jwGFJWdy~?l$ZB+mi z$uPKC5A>V(AX)I`X>^2HMg9)i8-rvKvP$1roIlzEzfqf8W-~1^H#eVDC5q*4RG-~P zngE90ir0xeT$aAE2z^|9kklY%*jpMP>NrN40DW26$C7=)4R1w*IKzSr-~G#U407VH zVf8ZVY}3b}m8XPkZetPJjt)dw-xk}|7vXYd{rq6dH^74CS-+QY_5(Dx4zJot%9 zL`bg8vI9?XiT@il?0reQJaZZJ(-Q#Av491sVtGVYVoyM|f1IA$ly)Y-wxwmS}) z{r4x-j#IJTaV>#!1_ouX;hAEaKBh3OOMVk}+&{kKG#xi5;#!`1ELY(xKV%rp(q$q> zYmse7%RMn^P^92Z62UO%ATJB4H(*{eA*{)vdM|egwM{PEh%+CHW8RmmCM4+!()`r?-CAOG^Y7OVP=NJ~-t{e<80pfQLA%nzR zWU*c*J^_dC?;XMVq9SgcQ6T10sO#?-0h0riT# zYcBR)M)lp)Ft=Gc8&faiD)aEfXo1I7j0Iy1<$dVQioS|o1aNz;_#aVz*p%TBc(~Ne zm6XVxO4=A(D7DClKo&JkTZ2pZmtj>rChd$ppZd^^a!3-N=B#y$4M5>o&>ZE zw68%3VSzW+eDEs@z!Huj!htZ7X>aq%8brw0g6mMr-{2N^vEoJpJ!~GkF98kB01IcE z%1sa&6v<88p+t%tW2ClcYeAquAl;UlMakou4GPl`7&(?u$4A8WbbJ@S{(1uG_5Au< z8Qe1NU_SNPMtclC{i_6|k0yCXgg`uA*Qwx;bS zNiu4%+*?pKyx`?&MQ@!S_n8B5>-}8b^oFJB3E%i@wfzB#i;6^TypZJJTW?diK+rT) zjEd!^Y#x}rm08lDY=oMI4qRy)E<1!0h5xch>S5I(9`ZkaYQRXo%B^;YMTg%;Xy>l9 zJaFxMOC%iipduBbDa!|*tI&J~fS~|Ga#i5Bm58{-m%}63W#kV3lHUYd^<215l?a?8 zo9y6)VtBfIr5;AX^xz0)0=ibo3VA5e2w8t(5J}b?u*(giOlw{kzSKe>-Mydz`=@1K zO&GAsWsdFo_k6hn$n^w{B%<wV-pfX1d&#N$LX_a*RzzfuKAcb!rhut3{`1=Tn zVk3)cwc)|*38V!nArbXqU%?g|>VSo3KYw4TuP4}TE0)&RBYn^u-^D$u4Y%L04fX54 z>Uue7f=68v3QjoZm2ZI|h!`VUD8jOR$ z{nr*@ZAnAtw%*uIc@hjJqAYOJaKz3;5DtHLGQxgkJ4FZcxT%fhdV?1MIi;M-@VJFH zvpiPp)t2FV5XVzPatKoAmZfG0)_?k{;GqYmLvL4>Up;MmQ4zdM@Wt!}Micmm}T?)KuOf>Ln0x{eoC^b~^NEf!>!WrVZip7Ths-F@XW+EoRO z=TmC230;ptbIg0EJJ+{PLV|(;Zi*{`+e$raPW-JdWb|TF`YvlJtOZ& z_N*vrpR!0uHO7ASsqcl&n@nWKIuo;$E41==a^RVNNkA-VSUdCAGtKwlK;ngC34o+k zDa)jTA_+D0s29U$Zw{%+TU^F;IIJciqz6aTv@I@U9vn@)5Vf(dL-Sj0rA^`{Kxxw6 zY-U2(Kx3#duYcSF;G}cGZrqcRV)2__lk@0s$#M_XO00j}gA6B_CvX@Z4>p;vXv4kK zEA@|i@;&*Yw!`qW{&7z}CvW>D=Jt7x~oCuL;PZri8kZlla( z2-JRYA)-{&%7JCh#^P?}B@dYzBI@SgLG|nT_thSAk(^%s9Tw=rgt;99@874GT^6;P z1(eHPR~D`*I8`-j$;pPZuV14U#Kj~r?L0L-OcK)#7f!!MEiv7~`sdX2=dLo?AyWv4 zJD1H_f)va)ZeXr_4hxx~n!Z_XK5?v9UU^G+L7w32AvBkTLMpMMnrU~Trx1!SQ`G=; zXRE8l3N7LQNb-uiL}(mA6n@jZ8LZCYRkpR&7JZd0?hz4p#JViXXSc+n^h++Ix(998 z#E|HEG(G645@x}$&=vxkD)ofQAba|}?Cg@jrUbeg85S1y`>3H|V?M<9`vf4VS-wzw zB!}QE?rT#pEXXXcM3{I`!C(120#|!*C4fC{+`wG;^9q5f^O||}VuNF_LTum)U~72J zDOdnpaYWrB#E)=Yr^|eCI^;Se9)Trk`;hx)bX9~%dn-f{<{0{iz4p5aNXxp?T8UaY z!}4Lv*PG!rr_O1_^m~paLK;VH*VOxc+fn1hht$7(P2$W@XzQ-)@u* zAL3tJD&@HyhGmp1Wk_+R{$Qu7@}o%P*+iI#@#5;;dCL>fvRlOjo%LPzkb<&?-NxD*}Tlm{=5i!4JoSpa`RB$lZ=9KL5c z9piFE1pgk}9cHd~6=OQnVMY{`*hH>8%n54u*zT}2k~|f=;2p?$u^nj7(#KqEceR0M zg;Zbd8>Vps^$pwFYEu&?8n}UFiBV^pb+yOfK*QJ3I;O;^vrAZOz(FOEzdzdW_0Wa} z}J$0Ah=7~Tg4{xkCw`qkTs*mvXw^^NfDPdCGBPOWIf zWq$KIm2X7e8EQO>K)Nk3Xr8YsX>Cy&AdsF4;=&1nF2yB`FJOQ@lL&cG2qD#maLI4# z<`=b|zN@zzWy6=utn*Juh)88-HE_z^Cz?KTb!L)TJmRqk5?a*cTU|9s|tzmkQCSI2?spntq z=+tM>&7n-{$tTG1m;~#EKE-iu&4W!SIfWbD+%9Xqk<_sxC>W-hQB`+sS)Y44` znLm3+gi#16rOx-gQ>9qsOJ(A|szQ0tRW(4bT#pNxJ@`n1p+g%EXE=LmaGqNwr_qN= z_H@BJl#UI_lN%{txQZDZ?tk*Ja?Q3p=8jO`7-2HPK)zCdjCT|2DqY4lRtk{gpIW|B zfL8A&!R&Qtd+*J`>qXuCzh&pI_h3ExFY_Dg-bZeUc7K$#yRnsWwjgzTYQU0GyLIQA@>Z94 z9SkiNc<Sskbem6xE?OPXa3s3QEG>imoS!j)YcD+OrSKkuN2K=b!a z0E4|Vyg%rj_w1ibcmNDvxVg4}g1kSphj6mg^iTxZiv0vy2D&kf)A-jZb9=?qge7GQ*RE78osiB&IIN;yO?IX zI(+Sxml-Por_5v|5SgnWkpFjl7lk#5KmQQg6KFd1sa+_Da2R#_Q(zywh18!;*qL+b zt5~Ckr85_<3;ArprDX>2%XblgWD$D#wxAX59)HY-KECEPYMP8~saV>!O|W+i!)6pr zTJ+$LSN}Z1?t&_Qe+y9uZA&y(inz^Bbi@E*|&dtRG1yNZz$y&Nsubrb;tG z?)jbtEJDtX?w#6zaDd3!)YPhl=hWSChS`(#;ySk#^9mgPxstW(j@@RHU_tK5c2XAE%fJ#K`xt?MBn5GW!e8pm?&#r-7$5iIagF{!|S}2 zb?34;>^)tZ89_|3EWm@Fce4JB(kJ`EYxBX)5&kp!BDz7PKY@x!S}3A|@`c|I!eP(b z)YI{^hlT2!M!rKfhI4v<{}`Mm>X<;7#-xD9v<2ct{n*1}^JPAL;-!rT(_5fW+RX2* z>l_cJYm2C@{TfXnGj_X9QZsXpY!Br$`F8jX#R<>`em<*x0p@sMc2?%#l53|+Kz$Ae zMr*-T)*0S0Y82v`cS8thO`&}BsRj<#gcUdYg-YF93+aCO@|1q6>RK51von@jS4r8W zV_f?}$Z)6Y__L5m!Gz^&pC4krsDT??iLY9bC}{-brnp_VM9cHD@P&nhr?a^_FNG`F zbK|2_w`71=&DS6egn~bOWfeg@g5j+}O5IUXJ?1t-utLVm0Ns4CWFt>JRE`?($O=;^ zEHV3@3LpSB_-BpV5?Hc+S`Wf`_zAbTAV=rw+YzMZ8Odc5k(HoR(LZPZstz7(A;^$g5C8 zNY=ohQ!MOvK!e6XAoQck@-CA1>nxTxjtAV>+NkgdA=UCWjpR^&;yx?{f&eMG)b`Y$ zN66?SScYBawa@EQ7rYRL9JC8eY%=;uakTrBBoBM#G)`vqxTyewVWg9A06Qi8CT2d4uzkIU@ zvP;oH69o;P%9HQa5G-yI$a*S^{lmp#sp4`)O!>cUlF@etG&5oQHE0fZMZ;#A__XqJ z-HWAh(=8WY(zt)hB0lyo5I#bBim#8IADd6xC{L=UvQR}K8AJCF2*kzQRHFZt5P@?= zb)&-|-467`2=MEfnL3*JovJ0{XxgULKz%Iu7zcyuJfJRasD4CDkTl(rixF06VPnNthBk`t;k)l$2ufp z@AN@FK8!QUMH?(q#)a+3oZiz-&3HO+Tp=!ahnlaZJr@dWma=uw&Fq96cU!UBw`R?BC}7U6Za(=kvXe<#RQ`yC z23H-0&)GV#gL7PLUs4;1{Csgk+rQUA6#YjlI!J!nKV)kK&MiXpL(~!l&%u5JqO1;@ z{P9;K9dfyI7$;8}mVTFPI`1CBfr5{XU|x(Zj8nV$dizhxxNN=A4*9k~4E)wex(B7s zD(s5KEMiq!O;joQdu#wt_k-~$Jqg!iHxQo#V+f;PGkGb{OU3EitM63V9^Z+jilKFA2nT*{*nK(Z8r|o9H$uH_er3NS zF~7YfKX=B4zBtj@Z?VPpHe8oqg50TfF~mA(#Q9#5{W+Uj^RwU0%dQ7VOWR9Zi{`II z;S72MkNatqu^*ND*-HiPPfEW}%)_ z=whWWF_}}zS1DUz@y#*WRXM*)8!pa$$IwMg=zGy6kuY3d6$05#T}a1%*KpAax1&5+JvX-%Si)1%v?%;Eu_= zSf=zjbNNwwLGNDpJqfeFH&`plT;Q+#wd)KBIel99Kg>lQ_gL}cu_5NI?4tO{t% zSiAe4Zuv6mAzV15S@$Lu5N$w9Dg+^pDH6vFbB&fFLE~rlR%pehLvk(pN5gvaS@?aS zi>3R;*kC8w^jwbiIm|ge>6})~u|te|mqtlE1CR`*kF|7;@fRM8{YqZn6TW-?jwm&8Z>c%p zz}x&+)!x14SqWOU&sG(7RH1fj@X)fI10!h#Y<-TYzFx|*R)e?a9B~f-;>A!HTtSMj zWrdoy$I7*$VZm>!mjL~B5QXwvS`7(&1)~yaM-@Dv>CHn1#n+%1Hxwu`NWx~{S@E8v zd%M;0@o_z)DvDaDDTn(sbM;4K!}Y!eOpG}+k_e)Fw&5K@2)J(q70eLubY8d0 zKyO&Bg@&qa*&?hlRE&q+KFT;4e8{2Ky^Nfu=qe#(7AX%_Ze9*IA+$Q>T)AB$19_Iw z;=pvv?bW4VgH$7+KH>uPR^9!M)qRD8nB!_8ehzs)$AcPlNux2K%u6P^fd{wzh>gtf zuOhUri>NS4!73(gidy0|H@D*iRzHuH+-7HpB_v%~ix1rZ#X@bUsQMmh7G@g$aSG0o zv-6s`EPj3wv@<7Czin8u_#G|9-1mG|t`zDwDj2};tlMKoKS%HS>*pp{>xKQ|m_U!o zr+!=X_#;+m&M?&k>6uc+D8P}Lh=JscTd5abwi6D^1kW$leL0jJp{;udwg!n%EA>MF z6y)U7uVFz#P?UsRocRj`-+AvY4BcTl!0uWK-%e2YtK&u~WK_TkcU?7fEXR}Yz5!w$ z-I=H~vR8;heQz{T6r?IA8U|L;<=Y1v81^>LUh-vpK6bze-LIbD$0;Qxlbz7<^gm=F zHE`4gHpaZ3%%DjTXBwNUK(i$33QmC^QRp6rNo#Kga^Q7S8I6y;E?=d)#U=Gq6kVL> z?tE)n>Y%YrGt)=50UOR;jL2J9G>r`|-2fz|KrvQQ7c&=oF>|B)E8t)k!5bj%wr33Pa~fF8oyUuampuh{%oKZyU@`G9lWh#+ST zU&{?LpzQH?+SG6%?QSqZFv+V6SJ~Mcx?0h)dC6kpOOo%vu(s+X^f$Vzoe{PFnOomw zHS+hwROz-9J5Oa?`~1=EHoiJ{B_zCPZ(p$rk(0gADXC(p)Gl$yQge5yx}sL#fT_|~ zF~9rni_p&!dpgJe^8$~0bx;AszP;49gM1$VrMWdQ{mdDYvLtxV7Jy@hV0 zB*t<`+>0!1qg|*I08z-sr%xnbgFM^M$kEv*w1vF)oK|8qbs-O=q~hx#o$OtUT`{yf zq^Q3Teyc5nGXdqZt6YmkrfK1X!u2n>L-%F+x4S|JpMKm`K%NDTU9{uIM!s!uO!4VR z?0LCpoq2qf$tCXl+cXAfzkc+X~)_iJ)z=xHamx#-6V(IdeEU~hu# zFFwkytd9I&Eg}NUS|ryn#ERC1{;-rDw2Sfl=gg*{_5u9a0E}*02a9Iw2IhgVn!ojo zOKFOYHmQAEbwl!$APFf|n6}XwX8)l>TtQDeRPZ?}$v%46VLxq%eaJ(36+sqn7V5zh z>!^rCekqBW3Au05#9IKl919Z;d>q+Ak9m6@8}z{Bv3-XF*%J=!6I|%QRpaDs^a0W% z-%H(pa3lW3yL6=3@FWZS?;wBly_DdbG-yFo-veCnG^~Ze0}funBek+I#T9@iFk6wn zT6VD6RZzOdV;y7_l$OPpM@We`=)xWm0|h;Z-9xYwkyrz|HIg8{F}JHQu-FCbPtnA7 z{Mvlcw-1NTut<}ze5plqJ++vsqTX7%!)h{|%FkCi{o zjw=uo;67`P_ab^~;o4O)NY8~!%aeX=%#^N-D1+^QZ@E(a5;`>KyutHPo%e23IpJn| zj+M7A^^+23hBAi}_cz;}K@h>vARz|%a-Y6&cseVt2Gl?}@F=Q^GbWM(0ZE^VWC`l1z)0;#cMz6DPRNwxQ z5OY^~p~$I#I55V7H%2Q&(T$ovSg3XsrYl6BK^)K3cFSvXRW-H+w(ITvR$UFwTkY3P z)*U<@r|U6p`XuRkh6(GWuJ37Wl!C`aj}QI!5T!KRe$d z^tX<`&M*8{)XDz619zNl;&~K2$Fq9$vjYoV7?q|?BAD}<+kZ>RwG-!RTxfGK>x=EA zG19~?8uqv;+;NI49+@#4d1q2@@r*CN>6lwHAKW=kol?e$VEp_=;10PEWOWIirYgaj z8we?B6x}ltnHixSTu?WWEdxTqu0@mLGeg~P66IZVTOLe$khHssL=a18DUwLQam?!= z;sb;T^)`;OxTK+ONZ}&xB2>Uo8CxI>y2}9}E)8{C=R|hca1OL?fWBaW|E)p(-fI{@ zh}lj<+#}}&?TM)fADB?R*9beoNio$BZ&eNE5MpI79*`Vt8Il0bbAVHD&<5X$n-zz$ z_p!6rh$4+fl%ZR9P)K6t<2dfX5Ww@XC%V^dpE?hSg(M*>+oA3!M0~%I-*ujg`fqWF zu{$@6ew!P2%S<>(VbC`}zN_GG=UQT>0#o6n<3<$5n@fUgfK}gC-1OoFd&LpDH30%U zjS1$6Ph!fUuaIE*zuU7BZpiGi$6o5*2;JmvaZH#ooRgg?xupk41An1TeER7`&aB&o zQBj#qiv#Y(L^;=hV(49yf!|Oq>`5pQ3bsDY@eso7{5e(wOmiNr`A15Fz^n)*mP7S~ zahK+r)yoFrOc*%)*O^cM5Hu_j(8WfyE0k#oyvGak^1n z&5+Po*Tb$9jO#w4_@Ua^PVMlF#;c;x*wuch*#BhMp~A5Kyoy{Bk^dY#O%GAlsFAuQ z;KG%q=`RcEM3zL9QGr|%Us^%+KMcQK`}9@N9gK`R&E8r8N8eY5>C{dK{`xKK$p7c| z?AqmcoDJIlL}q+L-CvgNSRL6UbO`5Lk|s%^2kPNO54Y%G2NSgZTK!l@lpLF*iqlQP zan-RpV;bms=ufI%a&WqZUyUxVLiFyMTx?;5mt#2g#itN?oD8CS1!pn?Mf#!77bNBq zSCcUy@S=(q0kcm5ti=8qDr#rJCKPG|FNhrRba5OBz!>)FulSCD#wD;6w^fV;WF?BB zY7jVHflFq<6uwW}3hC8QBaPz>^R4C&B#38v>Lfpwt)K(pDNaq2vshIY_wYi8`{n7H zsQ&UqI}ap(HcDVt-ixiGs;p3SUS;!@j(dSj9;IPd+|VO;H?eFcq0q@C9I|_&L2`WR z5cAHLuP<7#v&EjF;4d>o^%}13$eRj+(mIO^|CE60rP6?SlBHtmQLiG(Yp^pQuwxb? z;NdU4XIK+LqkAPjLT{@Bx1zC?w=zOX4c@870%ougo%B4b>znEpp!FmW{w=M@;>#OXzKfONt>>BBVcH|c` zY68wvm%YWnHc)}mhyE=?gWF6xs=jVejvNO_`?X$6W%p?+jdSN1oDuiBucXuHG&$h4 z^W76JB0skbJZLt}ENkEOifBNE;ryLA?dDj(cb)tVE#uyZpC!tbrK?&~J3Emo6zUq6 zlfUI~Rk1j3e$@J4eg_WkNG?0%8Ch0k-vGq{rbvQn{rK0)c$3)ZJtit8Ao&wivJfAdSL`1Q=E`x%H@ zIetPnmSY_?Jxj7hb{+xVpkWFR^!K7nG;QsC&iahunPj*%A`_;NA)KStU4O|!})KjN8pvA--F-_v=a?%DIOne?X zq3YpWDH8mz_tD8?mA>ycOR#x#_k+U_n{*yqEdK+q|JHsaBCg`-yHf?f%DS?(<~3opk0y&WJ6DD+RkP-^uUKkb zS5YhOu-ORPbWd6i1t)Dtp3=so@<~;M-j~n%1(L8#&Hm9gjf^%_utPZ);a<>l#=8^& zE?7_UPQF9R~y(E?a0o;^%rr0WFo^WDf6) zczV-_R3j1n>nL*(`2Z?LTRaRapKKah|1@;S(7_{e!f5@z0U&iGA1YQ_(^Si27^TGt zf=`Ho-#EOj+H|7!cQ$k38c(8PI-fC2j`c}=MRF5C-*<&EguU$$T`X$moIQ+N zB|!`;<^<8R&s#8?bC3@Eb5Frnif&!hw)W*paQN#!l8_09QuMe(Om~=X z?zMXU`lteGy<^b!dG}aKq7VnFO@`Qqp+sEqZ;{H`FQl=ae@= zMX8wxxaosAO(jq^mW+nTq6_VKg!giT2bE$1m4;;}_$Xh%EJWYabW!Zv2Cv}G-TX#R ziHopI+LsTZ=#EZna8v%4px*QbusZ9^*(!dDv}SH`pu+SU%JHi@#ZqIk{)m81h5m|G z%Pg+#@e5*D>v79*^cGg5S(lPbgrd%`P1AW5(b?*!Uo3S)%zNkdmMF>AvvxHqEGs;w z3@bglz_%~hnN_7>^FhDc*yi9zB)<) z7;Kigy0OSAl;*~f&`YyBN)xl|xc(P-z5&=0-Bz1W#xg;B>0=#Kx~lDnS_R;HbA3p;Ov#9;LOfqzoZPf?R+ zCO+ND!x-v3=d%}V?Pofhfg!N!Ia=9CefNZj zg}yq?Exd?MWoGNJR6C7Li+&!uz$cE$0xwoyr?i`wrtMdWV31@C$pqK1PnxT)havVB zeehjdkiVM4eH&&)Pn(hB?JYO$&B@mfv3>~9VD(zp(H`ua*yC#~^-R~0ozHu-a%qR1 z8v_Fp>AZ(R(sa2PY|KaS!D(gMFK{^*J+E|11f~!X)U06cEaxT=7x`@Q<}dVyhCebb zFx*gvQ{h2Pf`HXy*VQzPW zHzChC?SMbuQeux^JK%RYyd<-?GqmI%H;%78raF{HnlxOLy1oBQrD8-rjyc8kKz}9s zB`D}Y_C@O7Vxcv_$7#2N?8xrpJ3X*{zz!ZRDlm*z zh~_>ipm^AEKKf2+t9QrtJua-qS` zkmz*98agM4qU<;^WI)vU-r3fWo*r15s)d5r?V~$~yaKP0|4Ld^X^g}~+}Kx?NxEk{ zM-E=AzrK^aA(`HSXpFdEnFzz6g4UOr?!5Th#$UWIaPXI#zu2T80Kd?W!`^Q)psJj? z5e%A>pj1l(bpWnhkR0WpyngZfWo>go&X)USAHC#^fkHD^%?uf;7veIyP?uV$lMQgk z4$F4&2WxoXFaj`g?Y+j7wt7goC@ebKO(oA+P+k8x3XdS%5@P6D(kL=z0fDUN z^n<*eD;QfV{yb+0s*))4c{YR=GEcGhB-=WvRkoH-!H>ku^mpzHL_nhkLz9C?Q(w)l zmN`c4=`W1{CG1rBd;iEfw=p_ENj623s}tn;94^?|S>!8Otl9{u)0*Y0gOxrq2rY$) zOD`AaC@l`^E|W0YF8{tjm-3l-@Dv-f6h;Tm&&d3iRzW{f3&rC?f&zRDU##)@EQid3I}jk&qBV0|YF#TV0-82YSDR zSQ`rk)?h$Bio!Pj$N{2jgep+|%~D(ir%M*JiD7DJ6W%`5F)i*$I_yS)8hB#%O<~WM zR#btHZ8Hn*F9E&xloHs@&Y0c^?jIz{x;@^g&4Onw_ivQ zn4Qs%eM2@fAuuIs_JIw7STymUQ#u!~aXrLz4 z5i8HmHCnv3+S#)zc-MJ1HlRa}CS>Mlj|1jQ&;a`~;f%}llAt%}=83?+nFS|rWVVMV zupcW}u#2>+nC6$l;`*3}dh8Wy>$pH96>};I=@Ty8xyY1{toeq+2HBQzG$BVk7v}IY z=AIOPF3iI8cc)Y$!CaWax|E^WXu1dwR5s~&zp1bc6*4yfKvrWCz!exd3H_Y&2-1M!b2letY_NqpoV<02KK|f1} zA144jIej4XiShD^HGJdyw%P3Z2&w*C`PsRxZZBXq)w*N3xy7|=Zw?k%Sc%f7Bj08r zUeta5vFrYmRMT}O@a=jY7*DSNJb|V+Z00LNNNX1vUj@9dHs9bEpko*H_(`dTVv}TG zc!`9`Pc{i~^*M}aV{TX?`mFlm3BR*_dFf$nCz;OUTYV*o2DnWmxQSC}x@L)OBmX^v z*yv7na(WrQt~ymFuIDr%eORF=Oz2c6y;$q<-GlN+c6=@8^n6M2k8|<)yTRHQM+MM* z$D&vDQe)nwvsR&FZe_@G`M6UJJsRL2L5sUauloiDp&APu)aGdu1RIYxuTIcDo23j? z{V7HAx+>Q2C<0br&GAyUeTY1MG#~i#RQ;OGKB`O#XteVDDTyags8WIiun3v@|FSwz z!|{Il0V_KO>}o*48s0+7_We;4U}A?_VO&-lf*K?C=1&Sl;L^a%^iK`QP3FK7cJEx7 zH2z=#UL0Pb(R))-Wc{cUxrsp72ownJ%+oQTsbX}$Xy5ggzlF}i!2W<&+=WdQ4GwRb zDevS@aD4`rBcSzWOh@Cs4+5l5d8-BU9#UBnUYe3Z1!yl(G}Rm z1GGRN18?&995eTaXAWP$?_7wXzq4{gQ0*^I6&-&^d`KpM7t4KIitp zvYc9>KnDeO;k}Xtb2Hk$ObG|aG#Z@Dwk4{@ow@e01gn>LxWKp0Aso0bNGk;4YV81Y z4prRs7oLGHdpAT=?QN0d^e$=X>;thM#-o+)N6?I9wIW7ZukKN$@_6pb4^j}-C=8XE zl!g49KiNQ^{1Mril)UZggn}ziRes7(M7z8ETJfeiht3v8off&KZ42PT^{t<*1|=g8 zs*vPX+JiOY_QRLHmAl;_Ybt5F@r&r7>on!*5eC)sx*LTmJQpaba=Y2XrZ@3aYU{!;hx}Exu;#h z2!ErD@Vjg_`hir#+}0))tLHWdBf}%Z*AcQumX)S0#P(~JnFDF~RwE!_C@At)We|lW#{e&iG;8NxA0E&%1h&a#&b8r}pMq9k` z7~shI7bvYvc|hQ=$T+VFc$4j6=igxkVilsnAU;mr@6QnPiLoPcthsP5l-^tTgMsLT zB*E`=h%#Y|zlhwc?IdY6I6nU9jlZ;hK0$(=P0DjCPN*~MSOOft=Dh{^HUfn6u{FW1 z^(f->{OH0o0xHPi;>L-3vh9_A$txh8ECul1i*wt1;Ph^C)L_mzPIPZZJG>6Sa$PX( zjfzE{1Z^osURhZ$7Rg9emr3;G8Zo65q~baxG@64jNwHkTf$<5c2_C zAblJpsbsH{y7^nsTOXWAUGe&Rqfpk3w`(Jst;E~Oy5sJdJi1kOo&yR#fy4HfG`t+^Aw%U;+UA zcE1M$(40}dv5g2+Vt~P&j7*G|jIG^AIE(~kh-+$oB9eHzFdBiLe8Yp4{rQC|(%H|3 z%OFm@)z_Xb^%vZy#vdc~QD2xuJcUK+3o4HgeGMc4!x!HIQ9rWwE}UQ~y(uirpNhC} zyK@w@qM0Xd#y>*|?fge*dLy6$B!DfZM@TO(p_bJs)+|dii%6ypbXH!?{{yb*DyC|= zG&{Uy;kO+A1WaKa{3^mlbhk)!E^sV^^?Lpq%F8Fd%oO!z&;BPhG9cPiERCT`k>9W) zg;3v2Q$j@9W@?t1Ut?Izjg8oz{ehx56Y<^kNCLI3CbQNC=dbXR*k_*8zD1Z~Ye$sBAQG9UIlHx3vDnG`rBh%jdpXrUA6N>K zeG|4CQ?q5PbHp?Q)uh0F6ymwa@ZqK1H0!;5*)V~`>oM%T{Mt1?@FjToL;0;`A|+Cj zjw;PI`uwj)|7c9JlO|mdtF{1p7RyM~nz~nMrVyTmdB)L^&V0i-Y@sjqTg19^GY^H@UDu7JWLC9?Em5B$QyNy!0X(iab^l7d(Ugt+G9)&0UDt13q5^ht!5@#3 znxuBephF;=YSir7>6Dk5=B=ZH6Nas6VG3g+$A<&j4D|LigtlGnjyz!d8Aq+Q4+2ym z_vEdHrjb429(MiMvJMYi@{FCjBG(r~fzv_`bXM^cezX4_<)rJBaCB@3*jJKt#y5n< z+Yu_T5u$p&b0;5cIz^6vV+Lm@TUkQnAim8p$63?qkUQO0{@&0~`9(6skrYinQPRL- zTcAhus(9pqyD$m&IG&lI9B@Gk3ufpQic)|vps7qK!tlwP^ETcX{ar=^_6J)2cT9MK zjY1rbx*BO#)A+F|B938&r6yB!s@$*Z%X`Z-VVIc`a_RON7F$iE%KJ8Z%h0@j95 zgz+OOcYo-AtBOjmcm1G?lZLu)Jw`?2Z;V-8?1CBpcMRBbAqUiuihu{UCWLa4hHk|> zg4wh{z{OCaa5DJ&6y`wh_t}NX#c1w zBe_-^<19{0u&T`Kq)3miUYLKV)WT~G`%z+``^5#V57Y{L1=yK9pZv5MxZsB zU+EVKp^edH9bR_z?Gzl?*;6%()}%C{hh)z6Q@ryuQ9&lW4!xL&CMBcth(WA59(>guT^4Y=3PI6kZ&_6!?L??MU8%9bF^N+ zd+rG(9j*i7Bce^r*wXpPk=oBxGJ3AD=^R=}H_-Bo zrnjT?U}xd6%r#78BLpKWH<@?r*!NVY8If5vP7y?*$WvrRh}nCEqO|&JfcTXBlAWx+ zbXjD%x(vlrMHGJQFHaLV2_G*hSZm$TSxtR~(8%+GU_}-O+WiTXE;2> zx2z9Y_9N7lybO#hh@@99B5im@iyPuhI)>_0!lW<)WN*+vMJ}T}=5(A@YH$C05$DYi zb1d~YXF|CZbP*1Zz>o+6+7PVeQCCK%P`L~*K zfR+z;lfmfwlxL$%1X_VvUS>POGxFrg!4SkDr?4a?4n8bi_GdLEwlHQ2lMr6gqx(3T zbN%7wpls?)KcmVS;26SNHL$YkNVsx@EEf4aKcJU1=qnAkr}auhj+u!fyJEu*`|)#Y zb=hUgZpLtZn1$yIFEo1eUJ)!9dT9=Lwa~*Ej_wQ1S+e?Z5}T2Xo}_gCoYQjSTb%B2(JtYY%$OKM2o%1oR*iT^u66JjF}Z|Zmi z1C;Sb?r|OL)CT1iW;I&_+uK8H>#i5o6#k%pnJZ^)7xVbZjk)d%Vt$X)5G@?bIkJDu zsChtY?_J#wjmS;HQ`m>+`<;b|l<)G z@d%?}zr5Wx=BYJ>7LC41ulwpZ*x4XY^W`Y-hajZOqtm5X_Y;P9W}+oX-`Dquue(@i zS&l$qp);+~Kuv+RMUtsIw<8?FM-MA3Z-|qRk@@X|6Z10}HFSYab9ApA?I=dpbgKM^ z-}Ir~;)HmJBya)BZFw~k@0A&v12SqF)Xjk-@`hR(xoxM?diZcvB#o;xRoXgVK4E}kpi0hBXNfBmFI?1C@$ zn3RG>cW3lAeZu^bx2nCQcP#xd_sg>K!*u^8Ki2V9QeIMdF29KCbrw^UH?~f>zC-pK zuw*pW{VvL-bWMyl-Dg8r^+Scu4!5|9a)WIP%UIX^-h6hSPF9&y0XLHy0NGsZDAV5f zNB5VpSM8*w>z)M7r>cd9@$%FOur@dcuDeM40_EouAsoRJZt%( zPmbKYBI`Vvd#Rq;KFH>Ga8>L%`9p(xD5Po1W)7+729=jxy99C&}CU%IDsniIE^LqjO5Iv6p57T40fed zam}=*joC5+J!&f3F5!`v4t*3?3JG#7VMq*P#{C0qr+p%EmcuHc%ng-&C09OR_SM)S z>Y?{*nKUDIT&hrfy4b=WLtcTU#^7?K9kgh=YRuJ1WI6|vQ2k(EI0P+OZcFt^e{N$A z=b(N9Zi=9k?qUinUif}DIYssv(?q5-$xEpQMsMJS&jLKtVmVNxM!Ymnu&ub4Uv5Jn zl%9L)obZUw(UaZAOq*@t6l0Lty%b}n(4iw!dNC6@P1{;AIFEml*=gMyI9l?{2`ozS ziMy>&*lY~4z2+7Ot*fUm&3BJaE-w&;c@!%y;(c@Zp$1@V4L0ssRCA`CqV0s|~r zn(b;aMA8SAP>F3z!ev_R%V6XhoU}!T|MMd%LASiUq;7?|Ai4^leQS7#g8Fir^#rtg!1w~KRZ}E=!*FwF*jGsoa zXYY_JE5Pz(h~ zG?vWITB#WzIK`3l>;VQuc+iK&_CMHe5pw|FB;_6JpFSS)Fs7>D$SI1h3$}uDNbOOB z23kvs+_q2xGx=+LG7iTBOYK%aho`0>=CK4|+6OXw-27xc?^4B1}bf#06I^xCr2{<>)TZc;xauA1j1y55m;EjotH>YN~i zYpPyt0eWG))M|fK39PIwY2$LKA{99cdtc2EuQ{G+J_fy>r|9gLD}?Z}_&Nsjkj6-^ zY|V4eG0=xZu~VKek6}gfw&nV_?z{@z|Ig$n80=)Rk=;du*7(AhdeLileJ#!c_l;)` zQ=30hFDxI7Y6e{6{vJB;iymgw5-;AFDOE>mWsJxiaf{7%^6Tq&%u7}SzySu!*e#-egq;t4Op3;byCQfm{j;7SgOuDi8{|@} zP5CX`DcuT6sMUILJ~;|b$C(JU|01feoDLUrqMADvWKWL0iZ&&}8oV--%5%UMRBd}Y z@vEyN>Qm3q1Vgq2=ebrs+mQD#$CFpsRek}j#x?a-+dX}@UANiDzOk+;~E*z$|fqrh51*;idH;UM?W&6WoC`rNN7na z)Vj6Ia%$$+vaSUMe(C)@9L>#dUiK^Mqi%?k!+GqQTOOwnh<{ibFNYO7JeW>U07Nb) z-$hbS5;8z6@ke@T;#B~*HmMfotKwSg^y;b}BlXs!zZoYmioRR2v;3@hOsadYhKhn^ zv`&5TKbH9Y{>0Kuk%6lrCyB@KcN88u%pV}Gh1QV1+@?%u3W?ABjL&NpEg{S}S-B)tetENM=4dEEcN+}9r$%0O$BehckNEMU7n=x)^ak_WKNl`^FUX!W zF3`u^fJ4@4#qRXUzm;@MKtI1c=$EO=W|;{jol~*%SWmvd=rN|6(eXU(R0LV?WC7di zJJj9N%4F`&z<@LlB9o|!q|G&C*n$LDyzvCA|0~fZ!vw6=`RPrQMBopc*5+iPa^l^M ze_!>WZRFD>yv)WMs-e|ncXhxM^a^!xSPg}wGG?_rTMYhQ%i^w&QJdM;99Oufaxrn5 zC-AF#a#q!5y`$fF(bUF^u5UA2ZydDy)YURNzU<#eL6L1tBa4-{^H5ay2J*NKh;`~|nAEITO`B_r+ z`Qo&%DOyp!!R@Tl2-R{4Caz!fgo&gLykDMj+F~xQHlb83!m}iSioxB|2Tf~BEM@!L ze^c|U@<0D^Je{2#5Zo8DI9p;iZA10u7E=X01Cu|V3yS6;OqJz9a$(arJoz2Svjj(4 z65=+`pz=i+J0;Up9#vJQiyqQ46}s!Hw5-We537pJ)5zM*us%sd-5vu`3;n-_)YNK5 zEdK5KFuQsFjr08pKRdNnYn2gtMr`hJ#cn$YRA*oEs-sA4xGZ-s@ym9}p{)RsFNv3Q zTeYRYFn-@_=kvWzW2stleAsog_@NHxxV^)68aLb>{2P!R#~XJfLm)@3S*>n3GTnD; zJ??=lL!H?q`%q08*K3BX0uKp{HS(IzUk*$ggINR!*Ypqs_`ybB z%mg~MxemZ;bxOE`brzs?yxy|)h`i&9unppkrzaw+PC|Y z?AD!!t-62;%Vq^JkY9F&!x|$BlVpyO8p%7O zkBK#a?)(^DcdyC2@373z#-`zx5r-#&|BLr1#qR+s%+?n^NNB{yFk3gH64d}b>5k(P z!Mlv|Bpm=gGFxU=Q?i(KQzi1)%zO;N*B!dM-eB$#OaS6W-*goSCp}tlnBwP+*hdid zn@*JkIdki+>kMNU94#V;0m53T6>BI z1pUTn^E!F>c-ZxBYnH?wl+l_5R{Y2|D|ny*(yFud-xVlE%o1F=&Nd?*JW#nxC%X;< zYI?d#@Yb_RIJgt`5N&~VIX-aWnkJsd~QMQ zE7ZbeRH+e{;Q*NlhUxLX_cecoRfI+~p5?i95b8SQMwQ;|e9EDH+-#@O;K=0kZGMlVUR)dMAdn;%P7U}YSv(_q2l z*FulQ@Gyl}kVjv)=L3!N1_Ed!K2{sBg<92?H9z3+&d1!q&PddyR9N@< zu#a8Dx}r#F?@TJmPt#GyjMtfN0&|wEyf7$wBMbh@mw#-q-I&a9?C}wXr?KKaTTTx; z8I4VnElpObTN~m$wOTuZ46@Az6El((CMig6b}JPnGG}J)t=i*lW${z2$jHp?%`gX| zu+S-l`Z}%dLOlH$OHjGrj3r^|n{1dN>>j7#VP)zko#4bzEjj8sc6u zS?5&KOK=^Rq_`)?`{epmIs-+q@35v0=bMMQwHJPoxc+=tSEi2|*Ul;or6&!Aw7I0v z2{M{mas4kBxD>^8LdJ9Qg#J5%l{cJj=mRzow6u=93avd(XdTVmW)4mMmH``03YvT3 zi$%R;MMsK+eFYwnO_bdcC)6*ZhDE4Q8Nekw@@LwZbW%WVKnv- zWv}7ecp+x4a}C zmz!}W1?(k$mO2E0j2r}UNmzM=z1<0Yx>k3E=N88_tQBj3x0-?nxNH_O=_xAy%GnVj zv2C%GU0hr`a$zu}Sn~KElCCkZlBVf~8*gmewr$(i#0vM@FHaxRr3bgMC_Hz?p#@?+EH0m$(mUs&phub*^CLPzo$x+%R^78ND@yz(HlJaiq$x8Q0(PBIuq+( z3`&&d%4F3VuB8&*^O)-$Wnv?3#rl+Af<23?~1(JYTpNS~M%^}MF4q^izIu3lNNioHEzvCP- z^L}b6&O3UaID)9K`W0Je0d!G?H99%AluT1+r1612zqDEf?5bu~(zeiGW7P%LRFErd zLG8{+1vruhHKI*DCJm&mZRoFqhu1rP90ztaZVXc$Gtmxb<--`zD!IO816J#SHb)Ir zJwITHW6*0Vg4SkD%Jqo4uKKhyJw~ULBbwEssVl>~|7p!WBP}gGv9Qda)mPaVUH3v6!^j35TL&*p zjt5lW?xMO{5{m|xj=Vu$FLlGts|;%Y6E(HL`PZ6aub(8HHC`_b`-W+kb)ca~J;L^K zz>W>h7^O$zihH3R)SU-g!iDALHC>W)R#{868^!j3xUYHy;*^}!-9ActjM~Uvb&2e$ znvizbn`vQaHN{Lzb~|KzR=FOZtGcEM+ZnhVZCrp>*?k-K5?F8 zivJwm^X$ef6}YnWW=>kp%^|nW?(mE)*-XERf2(Apz4%ej1|U5?`6^GRv)`62j{`>A z&@W+d0r(z~b?5d0hOs&c6v)6)QXGsV(eE$0dQd+iK>01!8F|LoEX(GHl5c{;@S9VR zjENoBIrTD1($tn!nAOp)+VF;=OO_>8SHZ~FtRinSzATdAF!$C~PK4wLJ+NclMow+) zfJ_Q$<*si9=;ET2PAR^O*L*4eifet;la&HlIZhECQ3CK=@MSy0phhXhw>`(5tw3Q! zGhJz2frE2iYCi$lj> zU<(qG{~pytyKH_tO+~Jy^;!z^=ijS(67AHO+<*CkP_}eL4=BMzw^C~^P2$>}!X5T_ zCjch{3%x*|N6|{5ZN5j;;S@*=M~61qyk5^V4&ir~rH<;2s`7jM9gZJiZq5p&i6X-G z;K4o1twL6U+ExiJR(v9&xJ?c`UB+<t ztBze`bPcDY`IW82)(b@`w+><6NeQ4|;7!5!6JsaI69z}~|24GV)!wgMkTXWg?j`54 zJzp>wlOBtoIrA7}(<%DAnW0+K*spzr^B9p{7X=w+0f<;FcP;+r6kdUp z#_b>d5-O0`>DD)Y)vH=mn>JJ@8ApK0^}vB_TRpBDylV?X zLyaP8HC9UN^Ifb6Jy%BGi_JHKmYirj-35;i%CJMZtiqwx%#~?M3Ark=-7KQS_T^HUvtemBJ*^LN>8L+b%<*Zo7&U_Bqy4 z!y4Ax1CoBwTiMT+Yt>eS240j(%r!N3>G1{Agg_O?t?K8P-`+vwy;k5=3A04>iHJw{ zZ$=S<=5Aj3OIwG=u35~6KSd-OMMV)~Vm&9vB$+>DSuwCx{+rpOCI?-1yUgvu(tTTAHgaCB*W|~oUyPiB)L-h*sFnQ)c zP{blw$!fzMG^XW&J=$XolfJ_@Ij`fiI%a@k`{X5PQ(=3tNrU7sKI>fIIx<5Kg{>)E zx4y0*KJfwleXNfIS23fZF^yx!K{)^(sTWOR4}o#uAsAf$RQBIn27|m@LpOjkplXQ> z`V?Qdz;0H>fv&SM5}TPhxoWP6CGKMLihR}Bb1QTf%kJ~mdB?6L0<^KJ7G2MN3%!i1 zzBKwl1lvO2fa$(-<8QTQ#AYpE@Y1G7KEfJEr+b??9dqCYC-o_-Blf_H)6XBc`;W-U z5J3trdp(ihnn?;5E=s*~Ll$lBa&hK@Oy&D$`7m+JP+l|UdP7_?((d{~Y=_|Y*Z8lR zK7(uI);Cpdtz;@d2h2UXx%-q@FzWFj2uUyd_s*&;I_cH+kASF7?;=@7g9lr$PZh3X zm0{7lx{KL?U`khfzcd{m?=S2U z<7i>(6Gq3VB-#1MDoGGc>zTx6)MS@>i=)zmYBK(KNTb8)Dacp}NLETZ&$-9hPcUq* zRB433tj`L%I9FE`X70XaWPQv`+aeh4Gf1bOkXR@Xz{yzOlw+W~1b(XmslUl7c^Z^7 zt1cEDZi#lJOq#(hswMgJ*mpK&^5v5Z`!nB?B(dr<*3ow-32cmNCy7U)QHd#5zhb#8 zb#k%uYOvi!ohL6Zuoaf6Ww~5!-x9^U_PBPvgRvbh^Q+O}^EX@~F|py-HN!j8l0k$%1f`kq_H{dP)`P42@14SBq0)N-mC_OHN8c z7hOPs}|iDOxG)!0FTEr=^$bl`yvgxHit z6kg=kF8Cx5xO9=ZmE&q^m9X8%W-z5ml((lox#Y=F{olQKCCs&?NzMf;aM@+uu>uvj z@KO#&&9-MlYb+i~s5rG3i)I^r^^P|?aBzP(^k$4MUQyqWtE`c9?aqcklTAn8EXAH? zg%5-T(yDvDe(xd~5>fhq%3SG!EjZBG5@uCwmL%ZnaxC42iZy@3#aQ}uQ5#aZ8u^P? z)p)Z9G~Es!LIYL&8<&HYdjT66AyS1Xtw&6M7d19EP7peliM$$e8OCaZOfx;23XVK` z0z={hneY}=mIorokG99>FEoR7LRs^`1s*sT@k4(?(FAkhu&NNwNNC*hl2k^B`1c&+ z)>zi|J~F%&;C=Q&C}C{f9F@_5cT&niJ3>BOlAEe}72vMbZrMbiiqy!_sU79hjv{}E zi6=(;RL!sp;qvqZ#_GZ+^5fAhVBBIxBcpk*s-=WwYF{DCXzgj66Pcz@^EmELc*Al?6red z4JtWZW$FbA^LJ!M-9{C^qS;z`@dKSErh2xb5Hgw%&iQegL{CVkxM69O&*2wX<92-j zxu160VspalTg7(ynIv%|RrO;b69@8^Ql%Hxwh1cY&o9~ZwQ=t?fIL7}9~N-kM$x1CF=^E(J^kG#tRhuB^0T6?10K@{YYpF*d~ znOi&8un6%x&pjyFmkI_<>n4luH)V#;ibUyQrCQ#N7zpL7kL&qLreF4f*_%e_ZDLVk zI?i1WHq_)|suYn>cfS2Q)60hCnBdJ<8(C(w^4JlAvbUp} zH0v9dm6L3$q(Po7765(>E4w05$EI4R7aH!WaKxTnuQioRujY#zw&ym8B==gSf!Dke zfL7M0wp|Xgk$BWFB{d8KGK;(qO1|9!e5Neh>-|HCofP=miUZHZnM0R?!Fjxh?_F>w z%9Vdwu-9RLy7-6Hv4t%`_N&1bp#G}K${f!~6*_TMq$}!nE^~{uxda*ydH6meavG_D z01Zr{O1sE;uT*gLb{(0DnxN2cY2__dCCJq(RD%UNZho{4@gydm0I$3Gjh${OlT*A9c{? zxgpMf$NSCQ24p5Unw(?22L!?EA zrb~^mY|pHo+TYIt_z|NF+flYC;gzaXz8krlTAc1#-)NcFE_9n-WmIw4w9G)+UL_@? zvqR-`xKf&9X?%1pVOd@I!vZ}%g8e&kND^^~|5y90VcyY;pBThe2KBaPe|1Abv>+}m zy?uoEnZf&o3v3LNXRZJ0{K{RD$-vi?ng644Uu8j}GI_A>8G=q{hOMTf9;R*)!fAc_ z{Ma!NsZ9(ZG8H=s)F#P%qk2VMyv*WSDzQmZ@i; zz^x%>&1z=a5v4W1kqz(?_85J1mVeyRz1!Ilm6cyw{K=y;T4B4Nlz$r$%s1KnB6L>g z-2R(m1VF{_sShAS3C z9tYGmgjjQc!}^{axr+NfrWbS)BbUSUGuyhk$x`rWb3k^IAqVC@r6b9Yqn{<(1l(vT z3Pz-0sKEI1ePIgG^M1s66gb8HJ#UaugScdB`j`EyZwQfD5^<9k_xiN zBCMoDN1oWghx*$qF|+cT=FvLA&@#Oq%JPVeG$e`5=-Jh<$db#1f~T}#OQL2w>!Pnb z$_>`d4-bCe{N-!TM(J%d)wnM*t65PNqYrd^hGo+WW(UFVIVNc+4*#>`4$~`o=rg3- zijY_FZB?atWVq z2^9F=*X|19f2m@4#{)T^TOB=rV;($Sbz&ZpUCtVUb?_L|;-}WAI;4Rjsjz+8%1%da z=Z39~3V0`BY)+J9=C6Hp%Oy?9c5MgEH#{~+XRLD9r$ep0%vY9R{>lT~!&-4f>U^=X ze!AOz&;|_2G*GM>y*=?9UEn#r*1^H^KJUj7r?jfk_YFUcHf(2LO-Y&m9foTZim^xO{eivs+yTx<+&dySC}79em?fk)@HCrpug;e$ zigxIF+t){s=M>x1@H}0@pr!7c*E4dMy_#xu(%$wqoFTN$f;u=iy*gbkTZHyCfK2|yPQeGtW9#_@dFLqeJZ zkc%_r)x|k;;`V?Z^Lq}TuK}#)xvuJA!vWFEFQm+dbDvPsajFL-n(6y> zEsveISQ_oCLlz<5nrKmkqtHM%m}YG4>-0+iHM0oJsnDv*a%qf~bi4b@fhZsB-{D#d z2Mm9)9yX_A?yL{1WRF8pk{Th0IJMfI>1Z{8EdQ17z=)EIwz(PJug&R#d9Pr&aMRg+ zV;$gGQ+CqPM}<1^O{sl?#%)p$z@OS=6eWLKHjw+0pQrg@L}@Y2xN=UG6psPK6YK2> zl3|FXs%Wm`Pl#x3p|=vfk#oRFLkcg0e`y&o2y)UU zknQ^9@$N}70T%EICcK3t0>ilmb#AK1`R<=`ffqTUVrT{a0GKRIll7VQ#9ATFh|KbW zO!?@o`a0Yu;zX($!4GLI*SO zm1lEm;&rByazr5~(`#!t_7&PIV}5V`=*eEmsMc>eC%>k2Ph^9hL2P6-OrjTN01jR? z{d%I}$sKm3w|l-gb-haz-*JnTYGo;=0Xx0|-R`9ye{h#LQfZ(sj1BE!_PcmLjjRMYucq3}cTx*#{X^d+(#x0@jcGf-k7u7yd7-&Djyq?k z9f8ne27OXJeCR-znCxaV&}Gg!liu6Y1w;C!!CM*!b8Pbfh~O~#?vKeG;dEa6pI?is zbu*#J`miE*lIT}NP(ctCLFWzKiv#p2b7!DL>XLRS6$N@tsE?|z3pyp4zgzS5N;a61 zOd-Zry?^1Is&!JFjz@>cLtV=)4ITFOYUu;3U75ku{VBUQRo?Oq^-w>D{z~eJ#B;W; zpu-U{;)SZO_L*%CNEf#aM2{?iDFj6ZQN{yR%Xs}_2_^jHU2BwNyAW#8mWq~C=??QQ zS;!mcJ1oHZIV>q4f0O1HnhLH&?jS&|a65Wm&@zhQ>S%Bg#eVh;6S&wJ%ge%JWQ05t zM%t8g%rrIfkMjvj?wQ>zeKL)v(Z9@lz+ftDQLAJYgib<+;{$4lZHqQdi?U`T#)K}rvF@f5OzC;Sp@-~r3OI6n zQ@N}0A`&jkgB^H4jA>lo9M1fL)dwkjAtD8^GBL=%%UTP9{;!C z#p@r;n)5Xf?8ZQaL z2UcpvuMe<=YgyBt5|=)Wju>Q+_sv?mP~T}O9uN5bu4p588WvREcKb3$+Y@K)$ueEB z8JRNwuIf$@l-W&tLD_9ER4srtd+pgbuO=^SC%1TQR;9-WiX{IrZBNx>N>aE1{oO`N-bdq*T5Zr~ShIhdbUTb$8SaKtYIHo}_SgWC?J+ zk}c*(GdxK*jt=4PF-HN70_W+?1llJg%~tOG!&F5v-Hz5`P0HBjy`)CFI=)cfp(;?@Bj3RyN;h~TGl5+%3Cj%a02FEVuiv*N zl-nxUHeqg^T$ZW}=cZ=8%f-6IMppjk6Dl^}8yhV^b~jaj<%~Q3O{yUU;kH=pKldHK zG&bhQHRt-SBMMmlnv^~C?nv@^&;&AlXncu4n=4&MuY}rUs6PZyYR?)5SzhuiwLE0E zdkGkZxNXMp*?g$l4oU7@Hm3pBJ-LwA{W~+Iac|k}VE{1?J4e2d%FfcPc&Y0$9z)^` zFv@jD!i-l0MF!BT6+q~XH(k+Y2@m){i{yATHh6mMvUcs;>=}Cr5$UNNC-M$0LXd`( z;rM(+JMhjow#M|C@F z=uJ55ug#9sIkyNM?m|?=q)lISPC0DDV&F9gKS)UGnBS&eEK%X@tEB|LIE?89mlz=| z_ne71pO5D_nDV)3JKbx`#$j#1$@=i0ktFJcJ>F5Qn#MMBPp4BAf1L*{RX>Nrk@yNA zKsHv)xSNuN$}HXN3X7nLcxNnll($7@eyJCSgq(_{*%$w zE0R!<>YRmkM+o;L(4?iWcmM&|(dROZo4(^D*iurm?il{*sLtsA&TVsc0<5q*YI4h+ zhu;XUTl6gELXxlwwd`bep6KX7aNkQkgRY=~Q*~EjB54uj#4Y7_io1uq!;i1<-h&j_ zlV`<5gg7wpfYhgeDD+B>6fQ1w1(@-hD|ZnSFE~R6eql!N906EMfkr2KAi?YuUuCKI z1Oo0p|7kz9o)t57tI3xUo9f4n({0ZRF^SFFf444z5ItGFAa<=Vf~(aDo{N)gd~QTK z;HGlDKW#MXj@PuPBLCd`pA~a9Wi24iicbP9u?>P|RA+?yenE9)Cc!883N&F|R23x$ zOQAAa@!#u+saJk;;o=Q1&j2%mk7WK#vO~S~|9%_OvWOAZZO#?A@J-aLkY1p+`+He? zc!)QRIU%9j!%q^cuJ;5;sb;c8`9Q>LXu=d4oBE6_F)jY@993 zSZg4fAHqoRF;&-l{JjS}#Ft%90+P#3mVSFG-jA_>1gG!;M8t0|NkT^`lVN@mV93jG zKBi<=aUHJy(%+S7^=K=|f6+3kAAv9NVSx7y2W1{2#*?ZMw7%&BGdgm-hrcP91}`ZG zTyWKF1XL3%FiXY29Q_409F#GuuXIakl$fb*DNcp)c(?P2iF%$%BrNW2oc6T{@d(nI{owC!8@L6Mj4Hh5 zPMeg826!6%;!YcK{py+~XXJo!Do~l#1MQ*{QNo!lCC8A#ge6mXxz->{`^cbG8Rk0XU%T zJ;|3|`0KDc`)m$9EQ@gin1AZdHe2K5l;T6AKAd^J2P8mWGvqZocNpp(;l?gxthwB8vuAoHA{z0`%_ z_ZnlkHF#bYBP0jrjgb6e1h|`mhUr`DG`8?##@B@JF?v&iFUDYyrA%xEyFSswgji-u ztji=VcjA>FaK!CXSNf@wdp^K;x_M_tmXD+s zo9bBmcA59A;eOH#Y^jV#KOD=GEs40uT^q(fz|S&9A(1&!>Jw7neaIyg83XY1luDSM zE1DMU2;HCLAwl*HX(K59%{7!{*rVNN*aFaovade*t-n&H*04M$X~3tgAB+IatNLiU zJ+>26@KN4~`rkpVhCvlttedH(zpTr_|0w(TOj&r%Iq8GV7dc^$tNO4Mrf2{gD|WEp z>Z(MAeq-JmC0S6^DuT=zP4vRVRlw=1VaNr28BscYe!pnIN-++F$=gL9jH=q{t0iWd z2P{I(u!^g2wny(gvJJsw<^BGKSxhefBE>X#my*koA#G~y{lW-R{$`a-QsFhUDnRx5 zVorr1YkKucH8@4lQk`*SJMtWYT7`5ithc`&23hIX(~qNZI(%;6171DrOqgu>8!W2B z^}^ieX}cj49&xwsWOce*pTt(adj~poDaL+cAXY;R4`8UiFhPuQ!y1J=Jv>{zE(|as z_u+pm)%&4EuXl|0m z&fV{(mDEogHs1vX+>|xef%yt0FZlSWSr|a$*tX)w_a_j%|m8)t9&oL~sywjRyLa)oB|BmQTdo*ODLiDS;Ebf(nL$&`z zpJXBlwpRlnUE5fIjeYAU)z$olLQm#t@*NxfUO2%2el!^g?Waoe=hI@m><(aL)9~>O zS0>f|a$@Hb?V>FtqRiKW%em-=TT#wH+j?7fnbwD+#N(K9>&#&Mr%ovGWM>4rV?800 zyMix|Y4$56fB;>M;vAqbS6ckoj49IU8fg$AGN+1Alz~rnvIqV~8Y~(;X|v#>tt@v^ ztX;9;aS8?q-t$CxZt~?X;{XSSj>ZZm?q?w{E%^nutLhfa3Eg)T?Z8|scAbI^YN+FD z*1~5vl{kZl)*OfaVRHG3Nqs2S2ssar?8dewX#<*3O1}JhrZ_LP{a&SjQAY#U_C@hz z^^Xcu9A>^|#btTu7O--Rc3`@)nRf(h#*}TbjhPo1?&Fg5M9>B-_C;WAhTr>-x ziQvM((32?wzj(&Ym)V`LY=(u@x{^+36IRETgn3~nWSEyH2ds};k z)=K4!uG(YfC#Ey=bc*&W+_tOEQ`H^nx`W^+=9A~rH-UCSB8sAf`E1jB#RNDV2`9a1 zs#|BdB^y+2@t28-bV^zZXPBnBpPYgzU5i%btaivbRBt^9+ur#2_~f}Gu6(d;I{CU*h`-4sr*MnW| zIM#TgKKfFh!QsE-X1OAf60^0$_B@QgsD~GP#oWYj#5Z zqyoKH>Hqc)BW74hyU|hQJ0s&LUXKMRFPE@B&>#v~a7uNEkYknHk`mHd&2${@e}^`vTS#9o$W#GVH0vREr0I6l5{H4K{nX+=xk ze`>P!^RcSj@;qMjJy#1=RG-xFEIM6keXSgSef5JVmJ4Wi$qtUL_2G6eVwRA3X$-$h zs#{Q*QAOi$;>a&^|LQMVfC)e;=5Dzy;%}SO3b}1^YFD}=3r52KGp*7&o;VUJ*(s^L zoPS<*y0A{fGHlC)d9kzmp95aKnPFzlWM%AED}y?HX&e_P>O>CWhSS7?tQjdi9%O!X zBl!MNk(1(#c9^{W3B#Y zt%Aa}4}HbOcuBsyIG~e$3oqJi-O&U%n`rx27$nA$`imah5Vj!vjsp^wM<(EjB=|U_ z5;?<9T5s~d%`ykLZF&9$VBR;xv(Se!%`aa7@5PxKF88u%wD}q*HUO}8!+j6vd?Q!V zm&ik~g?o8s2l9G1VC#)W01&|qih8KBF6`AvmNHZLesU<&QL+;;3LkJ#IQj+60X0V* zi+rV}(|jC1cbQ49t|We#NQM;`aSae?&1ZrfHvH|W?eh!)YLVn)8*GfwoMp}oujj83 zg84F5s`hy0%E@%@i!sMeWqHfK%UhF3davUHgXa?`Q%{m`SosI0wCTrSmC>|l3Mf&{ zzRfzAn~N^%t)%_X-|+M+%=DRqRT2Ds*E46X+yLs<(aw|V=$?69BHl)4p@}AC!8s*e zCaP6hW9~VL&4aH&wU<~~39{3)_lq;IKK-o|KFPhmX&dts-dDV2%k?_cmixqY_Ex^< zOXM|mF_b7Le^)->CsuUYyKnas0ua-|%&akqwGjd>MLT$=`watlpb)YF@F*t#>dTv& z!ft8(2mk~X=STI{`^`^Kne6SyJ})7KDn#60MbSlI{d8}dNjl3DP~Ta6s3OK4QF7cn z-8%ly9D^b%B{fF56qhGL81uWtzkS54K)c_wJNlqL&D zQWqKvYlH3=VR{4!ZhltLO#A+VhxU6PUwP432Zx zua6z)GPbW+FW5#5O>HISRZF9K-CXRK-Ej`#_X# z&{kx#lffLeg!jVWv{1k7P~vr8k{bN2t+kgbUZnSnIfv(Rb=i<@NF2{I0%+fbXK(_{ z($gdQb5uV|U>lr~oyBTm11a!|IN-_81$0p!YSo1vaj9)KLpB?tW$_#dK1p`81 z(I_7KyfPU)Ji26Z(`&CEsehe~ZL{wLW)CFDe|*1kA^qQ=oLH=|Vg8G~g^#bU$m-2z zk+E&kw!L;@W=DHXlxN}3LfZre!)B3~I9D5Aq!8|rk=dPeRowYP_p)PyoQFl*vm#$m z1||ZxI~<5|m(UaUj>V@%EJRtrBMMH9uO;ez38BR211{?mF{eUe?0EOwn*8^F(H|QhKmqh7xBomh-YdCs$>Jc-Q|?V3jFsU(0cUg z)b~dYWM5Xy?S0_EgdNb)bC9!=vTW1@&Au?fiZwYcZpY%ql7!0#=Hi=mlaIz=sI?*F z_fD9EUPX0Qkx(vu9Y0qhBt4Y~%@#8CHHVP_4Am~B2oC6iLN9bU_*JDRtE_n)gHE~= zY{Cj1q7K^r{*KVXsOGH|ZAjj2@~ZS=PCqx=UGDw53KwMqRpr{NJ&9#*`EiMZo3vr1 z2=_m=UooRV-VOoNqg?@ON{4A{o`Qyve3^Z-JqaU2<%7Nx`SgB0vI>hOeuir$QJ0d( z>mlW_eO1bO^dXu}#4Nj*rO3zx_A)c|@kVF`EX2F=pG;g__-O$GIFoE#Z(0O4-nDLb zi|47ePS>z3>6%lTSqZGTz}Fr^q~um>(Brx>U(UZ)`>%om9-EneC|Ag8U}mx-1W1Y; zR;)S_WUf%UIgq=(jkkPOTr7|v+U)fTSVI6ir?MR9FFGAaCR$7laAg`nnAh7$!3OV4MShHRh z-C(&QmMs6a(Sq=OAC-b!Fev@^K{)h{<`ItFV zQQbwb#oxf78<3-o&2ne~fV3aGfy%G>?sX<0dFY|G0HVL zarCR~5P_;sko?oMqP;*^ss340iF{g)ZYBG9T^1`O<9^#;-|Hzb|JUw5tE75~-{G45 z_oIQAjO41*71x204K&}Y82RSeZZZ^)v@^dbQg_co<0lk1!FPSZZt!5qIQAUEB8?8TDW z4{hx)z7-_+_0I=CnavA*ygcFej;K=>RCi07s9K^%NtoSZSsEcb&AqbekX;VQhq%FY;)q# zyCWehJ2ZjfYj>LU(wU$oeLB&8Uxp2!X49c7d%>tUQ)`HVW?)2{K_NVM$DE!fz#U z9rk228yGej*nAgM=O>I3%9!TnioYzWM^1mZP@z*JT12kH3R1J15k4EKQ_+zAPQ42b zrGLC)m8#o2Y5%UCNyRwvbqzogBKWPJJ-}_#VDG;w>C%g>kG6#S6E-=Jf0uuLSbh!V z+K&en;J#-$unMR41{?<+zH#%C3HEVDS~@#`u3*nbc{8Rpi|hhfTVq5)r_BIo$EN~!Acu1cX;;;VI*Y7$qD_>wad?tiHtLahKmj|L zXDA2%=d=th{iQlJS$xY3l)e>`QsHC6|2TJO(lQ%zI;E`e3sqK&N$$W7<+WBBA$*%$ zk?F)ezB5ezzM;S4EkURnU+(04(B)66h!vBdkbw7N$z+hU*OVzq> ztQ>L(lssXAVHSp_(6Ma55AW&xL2m8j+Vt0uOKCy0+yeVNZI!0NhcB4X^#`QG`I5u3 z5ULA*UVgjBM+T?jHzBtu$tcC=^B3e0SRuJ=LYCCD(wHwy5g}P78IU4&;=#83k2NFq zqq~s2B{bOiH|{dWg&cHcVm*czQE-_7nj>XJE3k$z;{;@j< zc1aawi&>IX`rumP#|3Lh%wnDMA8hP#L_Ltd)BzYP?^P7qo{$yPadXc;nixmGKVoEV z67FoAgCl5cGGz%PH72EtT;pg&qgTOvZTyJJ#1%>TigF}ImccaHc?R5?_@rkwRoN8@ zyu2c!H~jbXq$B}4_+S&T63v!8f6-WP0D5EocqvbI-rhYgTPI{sgkDyK zjZL**AsjK~5Lytc`rc$pNmmP=LCZ@{SWYgJdPGt;)9i?6E~iWg;o)!6hU;^F5W1qy z`9d9awi}id`xsfvRct7gTBl}#yO+UXF3i)%ft1)cE8JScD&ek~2v^fbIV z)Va{xwMC2hFlu5@$>Mgn>oX}a?IR{_@ni0lMZRXEj(>*SY}N-&do4V*tPIj=R)9dT z6j9hC;c>MlrAzNXRTn0s2{jVuK6ky1N-o@dIkmrYU%%G?(>DF_q zhuN(`ANr2!k-6^K*S7e$nT$bW(3=!9+(^RlQh0N*|rQ&*_= z(UY*Z^kk3MdY&te3qbV)n*=nBkjNJ~%nR9a@<8v$qGL%7sSy#(Qszy`Tw?DF4$;mX z;Ctrvt>{Du)bjb+618bJjmy430c}ZdC73Ck=2wmQ0t5r&>-nB!O_P-f;liAEUZpMc zDuf7~{PDPD<|mx@EMP{*AC0R=SKo1R!UTBJinGSCbiAMe7^XSmp0mubB-g>Iii9)&JcXFU`!m) zsUzr`rxK+#FXa!-JXj*xC|ZI9fvmdyYZndvHh`{=Ms)UcWlAjtR;a5Ao(86EkZ5^q z!z$M+zpQ_hx;IJlcm1Q8*<|m>RTgY*Fb%ElfmoJNfW=|tVg|s{sUrBWG+^B5^j3zI zr9mR<=g;kT)7!hiD$SD2FhPe(A?+@q?JfiP!`i4TbLWo04Q0|ND#Pb60&YtDj>R~U&8%77RafHqzcB$~^+6RaaI5@%i-TjqwQtW-G% zQ@J)ejd!KOE%lvV+ze6tIJ3F233?piaiwGj3Ght(&b|uzc$6}xJeZ_I}t9%Fm5X=ZAu-q~(8c9#=At93?@p_chY`4$hFf`5DbE!rvm5R(pLmDz-fna>bPxVOp$ zN~a~uspMZ0y45)EVcR^~B56w+ovG1;G8e4LupuGc(`Nk1U?ejy1 zotIl(UKB6S6!I$97}PVGqr=-4)h~RmdflaH-38u69|lMtGMg42+};ws9u5 zlZ|cLwr$(m*mknX#@5ERZQI<~*%)uW_ujvmx!p6jYi`%Ab52#YOST5^DH@`R1mpNB z5XU)_GcKUTSNcoGm0n)=Z(A6Eq3t~RvtuqVI@eoM)bS)&q4db20E7PZyLR=Q!(zdE zqx?hnxEeM+Wh`%}$!&lpP;-20W4duH+-Q zzd3uYg}i)_&u#^_0#8pfL#wz};B$3H$_u=<&+pMYe#e$DX&qcQZ;*WZlY))q_{@6JO+j zg8zQ&9 zzv%GmA`bp`jT<18IF85``y%Bz@<6yS-e#PN*P5k`Tfz0QLS{<77B~)e;d@jOr{9&E z?U{9(^}v1H5SC>?eH2e~j}4VL$`lHv-{{l}`PF2*ZcXKJ|H7&veW$g7P&Ar_63O1+ z_yH*)(I}dLCGD;|DglGX%F@d;tdn%C6l%MmiK?RTI(l9{?{`p0Ub0N}|ChnJP)XnH5(8^+F?h%FQcL&J^W3Mulln<`~6 zuibT$eAi{wIR&N)WC<`(xL8T~;Zo0gwmbq`oFw?J>Mqnrb_t#T5e5>NzZY4v*X#mz zE<=}$tfGNi*Z^7tS<8=;Pi$s06f6n5K#IBOyfr^DI#Is>wat_aQzR!uQDC#|M< z>M2ew^HNuwy^LiLDa6;spuRmA2@$VZ8+(>CeOm^H5}CUDkVNB!IkwQlJJ6ggisQY$Z)Bgml~ z+f1>hOusfR@ll|9E?*`9hw<$&6^x7+KxFAOlII0;Zi@rUQJlz5k&@SZ;Z;`H7i02M zIjyYfy|hd0{(%Tr8gcp?CIH`i48@_*PJ$O6qxM)a>EUFMljo&ms44jGg72S98)L}5 z1f>c8YWaa!dB_rw;DQTG2v37hkkIL$fmP}vjA62%q4X|QXZOYUA-4-DV|W|bv`XAh z0A{8|nG3@W<(^qApS!=#!MUwWX%XGtFN$1}c`Vg8Bi2065a$$u4;& z7{t9N^$9Uogyb!P?nG2KRc95MRDlOCYhJA*h#yC&zjiOSMk9s=EwuWm^*?gA?+We| z@o)#X(&|cSvH!c^ynG|=Ae`P;ADBR7#o#<|N;VLL;MOnb22*T=D&cZ#4j6YXhS7jb ze8H`ZGk8lVsJ~ZpeZM(?@VXfj`B+L91s`t9IB)4Y8raMj_i@^`CLye<^_$d{K8Sr1 z`_#>iCtxSegA`eE6~jzdTn@*ogzX-|Cm{^4>Nic-H~Z?xA^w!xp))kqw>Kx&A5M%5 z<}NhdZhD+<8nRD8FGasf#{vw~6 zZsT8Nj(Im-k%AlZbggqkrBd$ zAZbe?O1NE-K~WV?c*)G$UZM+OCapgc!n0EbEVNZk+7_$HXrt#N>9ynBgA6xb1U!PJ z`7{Hesm(9bowr7EaD&^`*Fi+JB#Gkvhb6ID1@RmJ($)OKe@u|o9tzDb(G}Z7R&T{8 z`xN6#9Ngi%*XKnXEG|o z^h-Y;NGgINS2Pv}rR#kYlf|vwP{)$qPQiF5TlHkz+K}T!-3*~bnyxOCLn{#KB5YMY zJ!D`mLG5qM2M+H`GU6+d~jX6EuI!&TZpdvLMO_+?xJLaF6W z*BX;|QH0R)*{$xqofbKAuzfq}P%jse0qMPX;`@RUcUmFTp_}IOC{00oFW`zsY}Pqs zB~}HbKUamQ>6(=6$J2|_PtWiHZt&~-Av`H=bxTm+1*Muc83!YRPECl(T9F!EUcVj0 zt`>wKYyt)%zq;)W>rlbV6rJx=MbK8y-gsjprZfdoFT7S_s#(Fwc=7S% zcC!J_t~$tn3DM+w-S*U0IrSct#d3!JS(eE2n zc?RI&yUFI@VtC5>eR*IuBJ^iL=eWCBU7|Duu}|xFKbum$8|4}B>F@ofQ8eG)fw+}k z80E7ca7%Hy8eM0x_68MwA4L{gpYv0r&H2opDUr>FC@j$=MIQa2#sgED`5nuT8kjWD zQ1q=Y1S@^fXykyAcRP*fJ7&$Zvkci(U7&5sT>3jzef)6>@z~?A1e!_xn3IYx2 zFq-qSeT$)r?zwgof^N1bfQx|FLvDZtpAc{}BGh(>HYM=G^5(G-Ye@0LD`KzBo?BxR zY~bXjapUm(gQ1-DcY`m@^`&!07aU9b0jpI*ZjtA_bSvc0*W&5gI48pkp>h2eG=BBx zya>^?KwMoee_nL1QeC_e7j%0f zg|-G;2rlD-&cu+@1`N&cSf5_`gw}viFZ=!bE0+U8z>?C4XI}6Pa>6~6gxVPAwwsXz zIbrTm_y6s9-B5pno=DPQAkNfU@nBarG7lU_V~dY6+pdQj`2izjuYK$a`6rEyRF8S8 z+QqYe!NgUdkQ6zgVXd$V3D0Uxr`YN*i8$-w8r!jep8P#4Iu=BHE+1Y8Mdh2+zu3A_VFv4FpB}Y7kR}@7`cI96`YdE@qe;m{JSs1Rdo_JV!2Le1>N;esS zbauvOt*K6=(You79Kz(06hi2!46eZ`0~$Ha1BvCB{b~w(jfn`L2u&m@@(m-jb628= z#ARlUJ=_qCK=lR-b~ndCL@?e;SVfYknfc;eu66oZGn#Gp732z=d zlxF=`!!DgEC2dlgwgRuB#02f5D!j1#QJ5V~W~}Ve5%1_a>C60AuavI&;1Cp>VT4eu zfpB_aE1UMFhP7$1GqJy(;&|EGrxD|i+g z_k_5MoO-^;yTDVaIBOb)-P{uS(iV`rr8Y*8A5Dc1-TpCEBS*Q|;UMGSm7HSEW{nm9 z*ego6&<0_DIqYJAAeR$}JnPFMnmsJxuAI=;ih5UmC>La11lM6KLe0t5@r(Go9E`n;~7I zjpTI98YI2vS@7uZj@ou{q5mj+mLJm7)AJ+0lKKRVPn!Z3sp^DM7{VtC+J;RK7>Zo4X=A{jMda`VFZHJE6tQqw!0)l6J8JkAMp6S2FHU>)i_PLcHWA;{Jx~}stlz~C)SB+N3iexEGw3^@~Rvk2`=7YIcgCM-Y+>X z|HJ9A@yS;)pKBDxzu;-78@Z5S)aoJclE|9{I@mQwgxb9Pu?V7^n85)a2fsu>Kmc#K z+k}DnNV$k>S?cY$pGOvAQRAXl&r^(Y$|6!3y5>3(EGA*K@OaYGDu+Lnixq3*)6-CD zWGXV%@phnAw+6H$UKJ9huA#O-&4-%c0~wP%%TKJE^7ahIFwB!p62pm-{>R&e!qv*oHd$81&& z>+Z-A{{e*=OOg8Cwb`DT#X9xv1=xbuDGkV5ejCG}ziN6*A^(EiL4w;lt zF&#lC+F-97eRPiY3bcx~2MTqyLk>;lK_t?*^Y$ENUJ^j;k118Y!|4C$xZ!6j6IGoDGns%{!+>TWjyD4-N2DAV&`2#J;C zUz)klgQp|q3MtxOm{!sW7ItMvZ76gZc1BFJW8@8>(ZKn<;lPk}5b*n9S4gl=&&9P! zpZBoQ`C39Y}b5*%CQ<5Z_{I&oVn%*B}pYBZ93ypBw} z&F8^nc<7np0G`gZ2FhDE*8c`K6_CD*m@T?CKksuQzfwN8ufJz;oOcMQM(xE&_Ude9 z%aMWKuuv=oM?vatmDKL1HU?0LSDldT1H@hQiV1bOsr+cr@_ zI?nC%6~1%50uM9vG&z1v>3XMX@xH>*MGMzWJ|v?P$j5^l&=n6cE*o&Cm_(gsLe<$} zff3T}UGRO&i_sJR+5gRfSclmSD|E;(TAp+et$zvY(i~o`9(TLM0CA9{_@d%csC4=) zoX6(tLG%wLRICF&06rv z{wF91vBZ?~GhXLdX>k=56xkS(jWhL1jXppGXfBwCakxTWUW?L5qrZ&?%J4sT&cM$W z8uS4}bEDiiFVm$ zz|eKVTV!Aq;z_v{>9RXSxyIyqslh>U|Msp3NN|;di4OPRtI>JV^okHz$nNVeCO6rH zQ)ZzVN^Rv>>=hy|3vdz}9PjxWp&4XpiqBitXCe?`4NmK}-QWqI8wn3bSEY}b&I~5) z_6lt!wj!%r%$apFap_cn1!iwq2im#6Rjsv{j~Gon?!~xBrbK_=ehW(yyd<%%in-Yy*ahc{`FHN~ z*}NeMIA?-zF)~^+oACO#XiT2832|l#*t?${AWYn#3R0vg3vIgtua6P$VL*>qe*-%m zt-SJp;NS;`SBDD__&)wF%!q5FTyKSP?4N1mgaLmxDJoEm*n9E=1u0NmmH!(BH`7pl zKSv+G1{lGU!eX-n?k}nd_We-4cLoq9t!JcSXdBsubxZtxzDF9tv*h(Te9S^?wi}_z zscF5p0uV$)Zho#T!maSZla3-Bk_2m$*Wz@4NeXQ-uUjkdPQS|SK1Kk4Q2C1*gxZ!;JC*ggKUm3{PiqHC`NT~)(C;pp*Gb{lf*pbh+ z9|t4GwB1~@K{HazZh{bB$F^hzszrzSpunH&&LA~V00l>j(IA8ntqceR+N1;-EOApI zgwP!Nwu=WHorRw5A+4-*Gy>cxS{jVIn+3a@Y)jo|kFUyR)tPSdKNvWja=CK+{M3W~ za8TtATGZAhuJA8QjpV6E9{%2{2X$rz@bs7`g=vW-3L&{7#lZt=pjHGNJOgRCqswv9 zqAhCrx(b*yPg2gbi}fPOv~w%hPWu82C@JBXcoNun;SO`*VwBViK!@;q(O^zktcEAM z-ONjCP=kGY-wZrTR3rlRIS7H`I)*=ctn9Xhq0I_OFbexOdQPfUmd#Fkg7O126Yc)Z&WDlq3(OUoEc_}Ai0 zJn*ANBS$4reNlE3?WjMvP=fkuRr91SRX~3W=&gqX1;j~nuQ-e+O)H81=BPZ^u&yd`u%PZ^i_p*@Bhw^UkXNDC;q%3d?vH0PN&7*3Bj#Bz! z2i6zMh?FpD<2iR8{d&Q=#w8zx9Ll;}=!Y#{?1*gebxvd!>rA6>BFbn{BoZ#=L5+V< z9aM%9)zuyK8Fm>$Oz0a-DSKF3DGm+@qa#6C-VdP>D3PBu`npN#Il7o>I*i7Xat&Ux zD|TS(pk-0qf8e*FdVK-R5SMK$Z3sbHf0R$%eBIfaPywrau|n|n1>z9(`YNPXKZ6R~ zkwQoL*Xnc~equAz;juOM0&V;4T$({(@!Rn zwsj09l42VKKm?^@Tj-Mr<7wN3m0UB{gKo6dbmt7c^=tb?;pnXHl-pu|Y(BFr=I=*} zS3>mO4x)kt5frnXGe102C+EUG>i{_{ZK zm+Br6QwO5+xLZ^xe()w5SXYmLGqueEE6kwfEKalhfn@)^b`74x`j0&Ho&m)^*tiP( zL8!imB7kqOggp}cYq@2lRY7M?oy%KRK`r=Q>_af8n>$xr7z z`s!?n`e?k99YdfW_b}ctaQGGvqt1No-a-c4>NlY@6C7~VSo@OyracTjI3#@05^?1FDsm2 z#x;4G1D6H5HC8YP0L~)_-i_!U8dHu!Bq}V7Xx!uoNNDQ~X^>+__&%9G;|loQyQ#;m zriJ#q=foa=GbJV%NM9ARZ)59U#*XS3D*~FtnGmz*k8VAA-|;7S>ztoKiA55#pZ;8DsT@(pdaFhPC8-vYF-#uo*STQI^7op@KCNa z8Ck7&qaVTSvXBhdddq6I-I)C#iVa)A$ad`&5JHjTrQ*P6SU`#_aeB1g*nVA%&ItJ6 z-f|L(uXB<`nXE^Up843#e*Z-Ev9nG@6|~rt$i12KF-*%ws)@%Vi+(PEo(bLEGK9K0 zvwR~6fam5jJ%+KqB?mqZ03@?kbmnatQI)8X(5;cyGxo6RU*RYPijus;?vi1Q(50p4 zSvh3AWs7v+-4+OirOA;E7CWnI@bmVlT?j|&Uo*HZa~?|wf`j0m7t=8g%*DXN;89An zM#Y~uP;<+M7r7Pi0%`AR{8*$ zIy$-SPkUUI_bEVbFbmbqmkhD-_U#u4w@%5nCYo-VeuZtDaJ(3^o?qbZ)+Al6Yird8 zg8?w~N#I=2J3R$C zkAEA*ESHpyjxi914sA1MNwbZ(61411lp#k7kMLJeRA1CVvM-!UaJX%|3&L^MEZg+{u!*p#8#3v|4Suq8_4VX>?5RHAZB-TkT$-y}W(=Hh|e{n`GIN8K$<~gq#qsqR@ z{QzTQGO6u$r~oRq?af|quAL%LOOjXTX9yCwq(e)Iss-#?2M4JlHJpTS>@Fz&pC}B) z3?vL}*DB(>5!*lH&lT4-YHP~sp;<6Y8-&s9-^!OD(ihN#4716U>WdLAp;ae(1 zW_6u>ZkQee+hbyU102y-c{vRy0TQ+E$(8ZVw_7_PQU;95CijcYYklHCHEkNIlCbB6 z4Xi$GRo&4`i^t5dW&^J!zm@@#5H6rFk*K_uqL$tgtnJqN3pS$>T<9jJscB`jisSFe zqJ7Aha|?nCTgQX7?ka1VNlT~rw;^_oStCr8)n5-I4+A}^I*TD4jHD!qm0UMBITXk@ zM<2ZtXPBEur%;D@P0leLh*1sl<}sjKycXzX5+|Fgz!7GW)l#)VV>eIl{KiuzH&v!k z8#Q{JLdT_0>^%JliKHoRG%0G15adcxD_!t}n+}QmgC8P9|5*?M7~;8RCvaqzk~~>( zCkc@Z8MNArKq5JxvGT@COH~j50i77{u!rX)9?)2+nSWDG?mhm0 zM3gq6jt{4!QWy;Y4Rr6AS3lu$)V`gcg@I78yB02~K}ECRL_?iB$LRPWAne8E92%|m zds!DHk{9g*Y@pMT_l*?d;5y+B<1*6A+xd77NKo*H_=edDSY0DdP2=cKc5i= zh*WeZA{pXb*Kromp5an=#qlutv!$T61ZGPwa4rGUGyfs;_m@gdMP~QOhZo=>!(aJE z)vUT^8{}DeR)}wsjH;DrbJBO7DSH_5NUHwU#*>p{;1oW7047%((h^PM`?n7-{Kztw zM#DS8Mbw3$Gy^VCJXl=-Z|`RPFru^`1J5nuSEf8%@h)(7LZ^_xMeyzyufq|qAHf7 z9vs>)F^m^8GT9&7ACIPX?!D|KIQzuZPGu>g`U*>ylGk3N| zK1-T-iDcI-@-**}izf9ist%=^>Q0Vp>G$4sJrIv`P4@k5lyz~)x=%p>Z@7jWlFnYO ze+Y;Z+8T$7(j^xyX!*nq0?2W=l8guqEMQTW0%f6p#&CF7=NM~`W`H{AvqGxtR&}@I zz~QFOwG+oLdF6^{rdFGeiW@(aAg(8+3YtE?@U8&sY3>-*tmUusmJ#=>mwPfGZ7704 zdV`)6Ezd|Cq2K#PKQUe7ypO|JXou}A2UJ4Zl-cRkFJvn$&}lD@xEvhM1C@s33DHZa z0woPZh{nQ+kwEahqPAAYy}t$FU=E3Y-ibpzu$I@f(urP4>$I5?1zoU*o#Lp;L;;IP zFnu;{j?}~+ipiKmrAmL%;g2C!ev<<;_gSo_4PKLe1NGqDA`f0!+J^{t)XAcAVQ9}Rh(~T^4-B(5_OLMZg-E?pyZqL!_yL9SeJ1FE&ih+ ztk@svD=_=#hf0V|BdRJ&r$ZTWE2M*QTT8if}$BM3LD&X zBM7)+bN`~%rb6o0`UUnk9s)9JIjw-gq^4vNR|4bXC*f4mI_7HAPMWg?I;QoKdP z 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 K-9uwj)y-wox&&|zH@*J*^WOf?B{Vs!%8G%t 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

      VCe93Q2?c~rU8Cjp-2@2BmaYSE!7I_Z+-~@ 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 z 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 z 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 z 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�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

      (Z*nOY+ZG2GtEK9Pj_( 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

      psPp;H+#-V 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�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

      K=l9sc4{^$CIAT4we^gBeQ}_^O3#0ou;!= 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 z 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%0Dd_FP2S2>_kiGVQiX_bHB%LqW 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 z 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 z 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�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 B+S&jB literal 0 HcmV?d00001 diff --git a/examples/azure-keyvault-app/main.go b/examples/azure-keyvault-app/main.go index 35a0d12d10..d3f598897c 100644 --- a/examples/azure-keyvault-app/main.go +++ b/examples/azure-keyvault-app/main.go @@ -9,7 +9,7 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "math/big" diff --git a/examples/azure-servicebus-cosmos-worker/azure-servicebus-cosmos-worker b/examples/azure-servicebus-cosmos-worker/azure-servicebus-cosmos-worker new file mode 100755 index 0000000000000000000000000000000000000000..79988d5bdb554278943495a0604544ec96c9c1c2 GIT binary patch literal 11416407 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

      ZS&$ZSF_L&E=A`PJ6(J~IPxMeA<~ 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

      N#8JhW=H@ZrjFBv}!Ai5y`4Lew*Rl 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%0A-Q8 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 ho}N*a2O24z0aB_Y8YnrWLRq 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 *%297>b+uOxP6eD6Q(va?TGIVnrXipK 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�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

      ;&zx&U1U-xxi_jO;_ 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�U6bx%`g)b|0M30M|w(&?1gjS?~A``{O=<^yGTw_xv6j15gc= z3B-06i*hN@vhfUVN7w9PO#h6-6#Z)1PP!ZQ1VstOX6=dUFK^i^9JkHUJci22V}E|k z@YoV*2|TtWmprC#jT&A~7$o{^?-;$pK?sO=dv0P|YX3Lyi)#<>I01V38_YjXx4_|N zJv1S5)Ce?UKarTnsaW6;WbKohkqnBl6`1~Si(;O_)bJ52MT;^@!1ivrw*}Pc6YDUD z{~vSj0v}~{?foY}BwXSQN;C=_qs1DlVnESEjE0*`Fkl4Kpti*uVr?~$iH3`sIEgY2 zqiL&Et5xjLdg*Dats;umfD}+`1+@y|1+~>@8fx*5&_mwuZ|&!qnLwcRyyyRU|9&tt z^E~^q_S$Q$z4lsbuZ`l{kODamUR+Q0- zRWa4oRK>QkO|EL*nvLLO=q^5p@%&OtAuTe74A>*sYF z7`*v)lRtb#iejP&S&&~vUY{#Zp4kTGdp3k-j&2?`VSGdH(M|JvOp6ZYVXuZhJd=kd zS}=Mkb4RHCknpI1ImX`vaQuNsRn5y^q{%AoWDi~ckPX%0Zc?I8Rcvkz@omw*Rw32O z+eu8%B<#sGFwv{{0K`94$>Pn3QE4-x$t~Opsls!NU1Xy+XL}oQ!hJ|e{OOet z2vjoe;B|^m3AIf5Qn@4CUQeLS0#2xBywq2Pw{)%(0gTraGy#wfuc?T}m)eiIl0KR( zRtgZ%9_4WAQ;rARPVW?2i5SJ&#?OC8CE?Bwz(VKNFZeA>dzau@L&IXfwfY1#59pI2 z|BtjvA5cl*cG}6>9i)}x|5?M#ZkY|nPR<6(8>aQ0wgE}!Y@=hB2TyF9(VBj}*xYiD zzt)Xg4h@FGOkH#3WZYV=^R!!Qz-c7S`KB=CcNlo^j$F612d~G^0$0b{xd?H#7_MI7 zi<1jYKAQ)x|+&gA((QM%WAmyX{i)I z&iBZ2iV3}7#6zNpr+f$E{|jFBsgWTW^#>AU9l-q=;2eFFukqt!(6u8G3}~^6-Wrtx zP}4lGafl0b2D%>m5MvD<1$j=g3diT0z9oql2$G!z)&GnplS7WWcN{ERu%wOy2KNld zjllUl!IJmc*>a%{`J9iZr9^latn}ocPHjT|au#tCXOc;haa!WS9{E+}uSQEJC8y@{ zp4>nUnGP!`0|cBPfb+!2zT7#{c;2c0DqxB_wa}O6!!O) zecq#ZuvZWE?z`;S(4I96VY)W?aoBx>|1|>Bz+qZs#aiEhE#>(#Mm zbijdY+;%vDnTb@V$-J#UcLDx0yj35dGZX7(=YKn~Y_hB0P=Bh%S;xj8(DzPz8+~uy zd*B9`c`*@d>EG@V%X36@gz=BJ{m3l7@8JSVIS`N48Ts&g6>cEsDuJS@@$%UvqHk>V zR#V5G`AWE-`IM2T9zdTG7zhz;sNm<0eY#M}W|HY-n-I-@c!p0K#i~>miG9^~L0PZ| z8T*r9`5I8qys&(^OAiYFxz5D^*z)y9!PwAMhpZar5#2 zxZ7VmXjJQ31te@}tQ5Fu%=ZgDbX+B1O9__eEq)CbkBr14*Fu1+Ytp#-E0b*Ih60&uD%u8tBTqj z8XUE`K_n7N&ChHwc?AIw9lvnhxcSv)!0*GKUq5e*4kDC){As5*a1kj= zAfr;ls$pH-%?dKbc>AiWS?;%)o!_D+;> zVmb9l(`oaomt~SKyp}e9Sj)@N1F*(vCxDaAV%`@}U731sEXGte0XTL6Qj587f~4TaDHg3i9dtty3rjv(Mj7=htVT!cm0Mb?7j)<9q& zQ+NSYltC5EeWVkSfhp^u8^G#*{s4#{I;VTS3WS)+uR%WSfDk}Z0wl4O`M#|58iE!( z{uI>AmQRnuOnw_A6>ij-glnNT79c!@7*_!p^@f!<&(^O8R_SbwtG!D_-1iIVpM z?y&T2OJzQ+X1^Te!+U%>N$h|CUVFdsdk*Fz8))IR=2!D!zUij{%)tu!=VUO}|Lj_C zM0UNicB%KXbiGUcdWEjPKi`>!ql41*%%&TgN1ooaqH}h-i4wmFKez3Mjaf~+d3yk| zf2d9f?_3orfBULmhL)UIN)CiR6DQ@2=6jjOPbgW#JBHj6ue8mOTfWL67fCPWBAHkJ zt1LoDUj_DF`)12un;i|jWKn>gmP@*jLMct8Nuewaqhpub@_lwm4ckfk3-aGA%+Pn8 z<8LV08KYzxl3amX55qpp8p#hwF2G(mI9FP_(z7v`8Ih!YgV0nwmy?L$9AeTqkeJtS zf*nXaq3)8)8jj|m;>8VzOKp~15C{Ek>n3Mfi3VS(GgY2(>Wdda>M&-1v_irK^I89{?xnwPyq1PBgMEO#3QNA+L=%{ zoO+LM-hcLV(!J6jRAwG%EMKT*`YSnqk(a&xr>b|N;N8i0Swpkr`z=8$-O2YWx>+Ae zyVgHrPxV9B{mb=n*zhng4cB1J5{?WtJ(vF$lfSTGh)s*SQ)nSg}+7O|P^0Tb2uy_EU}Id;J2~I$E^C zI{iYLj1NPlgTYpw8rLj@TMQF{Kyt-fs>Cg!M`njBLpQH#t85|c5~&NB8jQPU!djYlHT*yA0+(oSA>di%43UFQg}je13e8T6O9S zWD2h!Fy0eMx&leS`6nc(9oL5}JFu#V#S#a2_YLy*(BuopnyRxwzp!cKr^zE|)*4zy z&pDp%M~GFN7PJK!t1YAE5#IEmEm>xJ*cueXdJg+@5CS;uBEU-)7Hk*CVCLy*ZDBt! zfXIbGm}i)V?168mviulw=qirRd->Hgqh#2H{ZEdM)6}}|FzNW`RtDkoPmz$s(wNud zn5o)7ENfsp02C#W=C79GhY#J=F6H!mE)c_{miOie&J)~98E>B!A_qylT)_w%d@n!y z9M#0e`?GersP-#c6WyPhc!TqPPEFdsqdsM~`R)%L7Ln6%iQ08L{;Yj}VR{s&cGcIl zf4j{c4!#`dY!J;z|LWw?v3GN;bJwuH+Za6< zcU%7Grmu>lZ}PWK^fmtWjjpx*9bXHge~`bm$=Y7T;HUJfT2CT`lwoN4UQ&jpfz`qNT=R>>DSjfbz%m>L z>1$cZ8TO}h{9${ulW%t-ZlgU3%3+ZExIyl_(;z#sP;^Zyt|{XF@o>|&;^?NPZGEB} zo3{0hzSgv@AiA!NODU*9iT}XJQbeBe;^;>zlTw+#%xqJsw|L*yh7a~-MK=w3aFk*9 zAwIIP%f&P0Z(Oy%a^0eYx13~3__3v0Al~m-BMi(CNi8)p;P-ahK6`@>&ykYOd2?Q1 z2b!RgH7aR#>}1}UPj&y)8PaIdF;0grlGHg+)^TgkcRI;|yPjq`O1yFVi*4O&i|Tf6 zDY%P`AUFj#MbwtGbH(Ef zS$u*a<{mz>5F;%uQvO=##xIFEQKmz5xJikD;i|;B;ruocA#Am=>dTE)%eO;>@8?d+ zeM1v+==ji*1KUP7Z8x^sZfvz3w&F=a^m)-A9Aq2agDH9LfzTgCp+Aa3e-w4}N9k9q z;`9}(_~-_qEsxea_M4O#OpMkBZ#!w8$p2tzTv|6yiVqBjTB?u{^5-`(GO4MJZPk!t zvf$#nfENFHgQD(((EJ5M>%3!{6rroY5g()3=#k4`jivq}C6o!CCB(P$M8((IC&vXj zP>`F2(<)VJesZ zoD%#Wj4$oi8&e{_>K3vy1ev;Oz1VNib#me5KRB;p^33LWz1TQeG?d>F0c3Z@)e)34 zr_B2u9-&M>s0+L4=kF|a%_r1fbU}m3$5885Hcx7P&PAct&Du!$2wYX!h>n*izyF3bPsf&5Bj5 zUKrqS2J7Fx+2ewRb;?zn=GWLX51}jXtH~TE;9{03Je?Oj)o#uKvVc?TulYre4hF}L zyfH%lJL`#6x~A5fVjb*eU710uWO=+QC_`*5qCyHlToAsvL92oTY_6arhEuH zKh$bo+;LKKUbow9TZe?_YQ|STqmn4=kA8+Myi=7>(BeaMfI0NFG|NpQajW- z63Dy}bfnlF{k4sitN>JXmeS8bj~FWLuNKN_PQV{@3t>zTv70rBfmhGhk(UQ zcgI2(b4cOeE_{Lt$F}ursEIsTcix=nCDBVR&&FOk;a83Mz+XDLsj=^cGOYO6w9wz( zAoMRBEC~um5(`C{k;H9Au<~fOE#`rojE&;^h5R@zF);VE#JJpi`8w;((ycTZ>s2x1 z^E~Hw6LP%k{ve-cKpZ!y?O4T@7O^!r`t4$Vdp&Rkr3Kctdeo&iW!!d6LuNi!;|@HX zzEHNZ__z@)Dz{s+MA7yd;r$w)izO2pOJL$a0!G38Btq~4@xNv3|0iR<__vJtM=QG- z^FL!<#=JN1{cnuV(mbzXx zEH>HbU}h-qAzL~91H9BBmU9&qULCp{@Yt2xO8RC?u z2?UsJ@J)*~xd>l}rCKd@^auAUq*;vSh5zhZ@LkfV7+MJ^zV6QMP`j&gpJf znDJrgd`}5Yxh>Yk`=qy6HB71LZ|xddBwwB~?ygIOIaL7?bu0 zH0y62lQwUUGhM0S?G6sIw^*PO>uNf!!c!Jq$=ZtLXz+kY&)Q1DW#v#ucvvW1sPW*7PsJ#Xo0P!OqgqpNSrPqm9))%x7g8! z>fClkzdtd+srv4fyWvQ}PpwD?5M275uTOq&(Q|)9%PRQcz1}Ds1Y;iqy`EhZS~9U% z_!(5>YHO6t(aX{OgR$HE%RgI~ni*D;e$EQI$VQ187D}p&fx_Z%ihsyt_y1XxrdnTjG81Q4B1}UqOVGcRrV9Jf zz81vLvQ^v>%z0v7r61pbV$by>Xw>jTS<|RtC|;eGHp7J~#6INOvhBLr@+&c}VO0^* zU5H~ysy7YnOdJ9Ehz2&%Iinm&recI@kBc2fB(^^*co;_jh;hGSn$*U0xD zf^KenDnmDcAPM@ZQZ_;^xecP&T(4D6jVd0;7VnbFCdY^7j9E1F5waTt5P0Ir1EOrV!6E**|8hNQCISce>e(T>{P0K zM}%0vl(XGQBJbH#(n)TL9aM@QZ9z0j)SUxAMAW5<#uGM z-RpwyL3umP=s%4|O$$~vt%TYOhK?Qn#ptEl%~vN2zPoB*&iMEW@8B@#3`C_?zAQaJ za`LPE?l2fg`R*4zLNxCj+C)F1q4oB;)4Dh4ekUrQUD}=D*VVHzkr(7Jf4wa zS*u^w6QhbJVO$t}ado`EqpFMcv+aXT8JgV18hN11oN}MP{w?WlQdLyzANBtAjC#-a{=b+|Uu8+XMVB`IQ1W>J z3R9%luKj`)L-rZT_aUiQF-Gn@y+Nt0X|~jL*+OGxn|itRHA=B zmYM9J$?QpgGBfD|i;yI}FTSXvba$Fh2iO0&Rj6s+Tx&nna)0*tY~||f7Ol;gSAs<= zYY^SiD)!9G5PVvl{ht$vZyNNk;g4W(I_)wH0*+`gJwYGh49$18C~TV7h^ndcAn6Io z23WVXWB?8bGRmv2H8IgJw!Y&dhgmwWy% z@cmL+Vu-y$t-sD5Vm6gsFIk@+V|r|ah6fav8Dp3EVFRT3IeRf<%wvp!#uBh()|ji{ z>Zw`tqv@G^`DM`Dw4&a-o1dm97t#X^Vuq7IikoiJx0)Nv3Q|vKOgn*&E`yfT74%(n z8MBxtN8Wumpig`R&@;MB0k!J$lJKDsqpO^9cCdvtI7m zuT<;-_vquF8MHsuqg&jgx80-b_2^pn=mqyEsz;Z*M@!wK^LT`Pi)Y?`I}E(L-HV9I zj&)@hxkn@QsMI~0>mD7#BaPoZywE)?P`P{_wV7#A?>EsjCa?U|Y;F|H7^eJh^8YV( z#;NbH$oc;N^&({?zU`(VC?~ARTVF7w50*g`1m-Dk@qO4EM?Eb2AO}HE5D#>bh>21i z8+(94mi~P$hkEBweE224wXk`m+Q+cPKFjT56?RRPwQ4u<9R&Gabd@_T@HW2wBiU#C z_pw#jXYffzlKp!`l2usO{Z@35JvKkdE%gmR*ZfT97pA{$=FcfAXfG0GTBL`&rv^PV zSP$~Ts8wRDP@eL_56M{SP5+fJ=;{vtqMAPHsuNf&F*K47a@Nj+imeD&bv_sP=XCz~ z#_yZ@$gxKZn*YM#Yfjv^%!zCFvzjCKMgA5*+se3o^7qGo%R1|hMi)nqB3sY0{ce#(9tN#oO5_fRS(!uo$l{lB69|E&Jk zrh&xdYInDHiHT5=cfb}A5eE|yLHvXTKAh+WJ|u=@2R=yh+9)t>&gdTC3(X}S_&F8( zz>vgnY5n}$1Xe_QTi{*CRNZLpVxxYol;4)rYZ`uPXcJZ4 z{o{-I#`y`N+!R!D*uMekllYy@9_~Un3_kB1c0LNS{&yOfYYkW^jI&=@ya#@SbqJC< z$GiiZS;VkXY>fGy+2?gw*tu%O*S7(4$6#;5=Z+&a1iZ4r8<)JrqywIW8p{Nm3FMG{ zP0j+}{)4{&P1gm85KjZWuc0;JQDhW24hnvOMMiD-)~u1(M7H4CFa@630!p z=fD!!8Bbx}fyo>Jq^?r@v>XWL?vaQoGW~x(_h*@W))WCd&r|YF`tsTNe|`u^zW=9E zjnt@-TC0BtuQ(}pvD#pUdF(x~-zS}+aIc}E0mQe5!urFvVq8F^2H}exmtyrT&eVaw zuALn4mv_Ma^z=J;gt`Pp4;gRO;oiuaJ zp-pAO8l2?VAmxByGGfUhxob!+HH-qozZl-x5h8CK|8zby{`xp@U%uh02Ewd*<&RHB z?j|VgfGhg(?HS@@zB=Gau46hY*YU@TJS9Ztt3FpU*0XZkI-VjF>!^l)P1}Y+<2>p3 zB@c!*4Aq0dl0Qd93nQ`4ldtKo7zXa8>A1o5ZGYRIRe`-!;Od?{iEr8Iu5C9zS@%~% zc`QN@Hg2_oQ+}a1@70m`+bk9D9f~a)Lt&2hq0mV&=28dZk_E#*-`5=&^EUsGrLML8 zs(vEeSu@)>^>#SHM9Cqao|<*dd8IsRgfFfi9e>W7{uC#aVwMCK8sL@MbidQ|20TSx zczyOPDW0&XEj21LSGy<&JV-`1HGTEn`p}7oMEjjMD%$(Rb3?bZi-3GQ`0sn4II8RO zpe^~o8tKBR7;mzF@Kp@A@AEB(aGx^+-sudB=mN4NO2(D&$)p^wH6I_MaiNukv5Hj& z!EeS$^aHDdkW-z&eyzx>6Rj=PPaFUZ?GImez5>(y(#ad7fYn&izpv~blGhj)T@G+! zO5-=9=b@^Y98VTLbo%}%KmBp91ZUEG;C(>6=e`Y^lLasTSk(ey?TeRWLBF$|#dNJ` z0K42KK9AS;WWk1dXED{PrB_?{1Y!1F3xa)Te{X=$vZr^6ydMtlVlh?2-uN0>Ocyzf z#J(!NlB0nx^=M!^4M&oG=-PhJ=6wK*s&m=Bq7c7Y{CVYhgBeM8vQ@!|%_}u&=xtCK zN4KAiqh+j?3^lx$zY)6e13|=sT`PHNx)yS7hNwKE>$E4RZHMY!2N1?;;Z$xCITfNr zE^!+YLJXrBix`zLpv++gf~$f;0&i98b{MK`h5a10vgIF+7)w^@(Dd zvOv9#lAyYFqKp7sk9_n;zWwDKh72QF%L!-<2GGA6G z#`WrBn#vAoI2>qt5~+CzY1?AYa=B91a8C=XM1XRW0_Xob$X*A#DuZ31sT?6qWnA)< zO-_H@`rZ0{Dw}p367A35QPI8ldv3$4@<0#obm-bicsy+0E4wE+xJ@T3x~koY=}zZ40`rl7>WYn(lyPD%cwY%cS8i zHGj|YOY)~CEq|ieUVQl@G8C1X+kvf4rGB&DyqI|G56{QckSu8Y%@`75kzeB|s}wZr z&mm&{^z)=tKx5`28YaZnHY1@O#v0_hj=BeX(01fg|rAf0uWMFLR6a zN0$}Nt<;|yhWGbdiSr;m#vgP<33L*2spi|L+A&;wS|^}q2{C#m8KGvq&;9b~+kReW zd(BJ*6o(D=d{rW}vc zkTT@WpE=%yye7zd@t(Ijo4ECf0C?$h4j2b(s=`<{h}R9``y}-d-Ve~P+cpN093rgL zo2C96NY+o2YE8Sik~+nepeMR6bZxEs7Ko9beUtRbMV8fQ;2n|Vz_pR&l=ZQS*6(UA zadrf|C^K$bl#9PvP3E0XRi;8Sw-^w-PiAUL{0a=LHkcRmDR|0JX7ft1l~|a- zj)L01U{2cpH+G5{mi7`aWivA8hj%ObOwNdZE7SZtC}W}s__l@)MOd}=>0FD_8)n$= zM=g;T%L8ZQ6I=(B$QyK|pMY+voo`E3V^o$1Wd%7&6yW57zXT@pZXW1vV9;alXp*OE z6J>2DhtzS4m@Hi2BjQ8R1m?v?mBhD)^~ zyjUh-Vz#Oi{Hr0XthPww)-*EDrQ<^bjwR<^xGv1M=uoCTTvudYi_CEO4X)7Y=vmdd za#H!qtBNOtmK=F-b+V#IXi|>8A3eV1?+x#1k2DJ)J7NM4Ym3u7+B%L70{yBmTvS79 zbyaMaDZNQU;Wu3ApeI>Db^JLo^o^&Xic~vk5!GVvGmd0_5RzDxIIt=)5pkXO$YI>Q zdF**93Fvkm5e? zIUBLkrs($*M|h9@)nBnB*?Wyh-LIX#buBm~$<%eKt^3Ea3j`h8U^XHYCM6;>Wj)G-v9=y6X7zb`fMZ6dSY&-+jS_qpdWXs#dwGl&I=` z5l$C@mCQ>V1~jb5pQa>Rd^rZbtQdP5F>PArNKHIOW!TkS_X1x+O9mqjm*kEvTOZAjy->_&!;9!(SMP@|-$V9A&cyU>+J0m- zk8?2%zl|gZpFpmF=ux5TuBSRxdlgBTH01HLqmZvhy03lt+Na^#HXhHxC_Fe!ni0v^ z_UiK0SD%RewSUq0|l(wMgu%6-zKal-je+KX;Yo!z_K{h)G@2oZ5&mQ&vRs5-&zeSn(oAp3$^yo+u z-3m3r-{W$2wT6`yF_*W`-zDb84UO2fT6Q{9TL{*zjcnK^JkW!*{HR7mpbyRpI{%;r z@iE|5pp3833B(C(-#V+7Z|XI1^|&7SYC2Xi`%I}J{U;~-_wZ)E`&Z(``yp2E-@I?m z9JYpwvKlT(H~ibufv(~F=rkYVL0J$VOT%VAJI6KN4Z!VZ zWB`5)FNyB52zf+JM1&eI~h>d{t zmRCZf!r*h~*AsaMZJmN-E!c9G zBx}KJ*8Nz;ylKKB*-r{C;WxM4O_4fq-#h+#AtjXyqT_j|>TNP_!DZ5^@(y*sc1+eS zJ9!83i-a^aoNDN}F%7zXar8ZfMcT&^YP{@k=MFtO60=m|ISt&0kVl&D94|CPcaeEh zfrv}XSXyh_bPucCKK{Koe}6k`=Ve#kFwZgzsI|osPYso{cEw#7td|c~Yd^KtdRr?x z1?U=6QK$di(WON_ZwoFpSh{y`#mW~)qx%DQX^@TYSMLW0o97>?UXHb1IE!Ta0*=w^ z2&jGkVI56s8;KY_$xB*qTrT63e{!`Kf!|_|G=;HbU7i$j!M2V(b1_}B)umsZ#jjMV zvmyT_br%DoH}+lDqvVhQ=rT`;fg$!8XQ}!skyfoYc9Xgl2(c%m`;f`S3r+beur8d^ zEq+zVOTLwjUp>-+fW+pcop6E4@7j94e(r;kE@}BRS-SQ^hhIcvlmZG_ma= znkZBg)aEIw+Xpq8A!wE?Y8?gM`i&YL-`!m?aE5g=oi8Y*wPX~1OchAd|7%Lx4FZr; zVmf=vJN*~8*b4+~Z80y(Vihra(TDpP(r-$DR@?Ac#Y}tI-^t(fdkA=XWh5~h4z8tz z(JItNr{(ERd3(FmuSnvNCVj+fYho1#_#o_)E*7C7UgY>MzQV)8O*@o^&8LIk+8MMX zYKc|6d72y8pVMV#g_cZjTv!VQNik2>Lnx2?g&wv-7+>ldMNt&#tE3Zbh+1_Qq$aLL z`4GL;mkLHxd)c-vCzHnN(Z%^TfI(Is!7v;9z7Jn=>>a`Dz-%%hvmCz=4xd)R7l6q!U1D!>wKeS?Tf7aLdnHFn(HIdH@n|a@|0~1n&nZa=C4wU|`OGcMpj{lUwFSC9~?MLsb z(_Tz~$(QcnY%_rg=Uu7}A*Hq6_9J%4VS^m8ld-mwaMA;w9c-v3e_0ZCC{NIv<@n*q{6! zH2d=hcye_EBh#}$GYKULBTOe@CfemUQF`1$msTs1XloSjGN%`4PNCDLCOt?@DTZx7 z+=zaMaOS3yHIw4&wEKQ8s^s$;Uzx@-Ep3L>!6r6rYTYrpRt(ts74KGUd;RhSeYe?M z_TwX~oqs)-#D)#69LI7L@g~?Yhh1?Zt|`gPX*IxM`DMw9q+acQdj0*~Mqu{wS7~C5 zZVqBixodcj94#iLdI)CMNH-|;Cg|uY(=AWL(1UPMeoMbdXM&_kjNDKpee7c>V3JV7F(eXay(((2rPB|UCRl5f+S|}ye)yvW0laix@ zR98xf!W1(*d6%mv@cZ~1a1K<=3uZ(f?t7}J3SX?}b;r$uKA#~uM)C5OWv}K&QmN1O zfS)Ul^l?L<1($NNThv8cNRddr{i zN7nJ=PJ_z&Y3)z&+Ye{8&w4C8r8^-{6Q%*8J$TBXQw*BU!kLHzzPf&^(*6G2@&6S; ze%$Q#*`9W3U#Y!Ftm8VMTeI6)2d*2}_TTN)0TqM%xLy56={%Ipn@c1lFy}0`Pj|O= zB76xS<`wIYyfE|N#R2nb1Vv%mKLQ(YZ8~c-k0Z%P11FB1ZjpWeYE{2l)vs3d zt81d{*~9vc8vu(iU*rb}*QwkU{0Z0T)hYp192fN@8IXwMAWc?rfEKWuNpak<#7au;gNj zcw~@9{qckP;vf89U;&bI@EP%nU5t2*U5t2*U5t2*U5t2*U5t2P7cT1qvTr}z&5ATy zD-!lMBSk?0yMw`fHZ{6H#NeroU>gXNiYPm>TC6_KqBd&`uVNoIL?TvlSB! zP(s&{g4f@@FZAD+skKUmwD*R6bCx+f0JZ$vR%E|icB#vko5?@>!{hx#m~MYJ@EuEr z>FO4)TE8zHvv?9roEI9G)^X{EK?X~-z{h$j|JgZq(!oTz-lp}}R1eetB%d?q>#yf% zicg|7qBrF8Ec;w!w`iHLJ&iKru^HJff`a6=*~oVJgT4Sw8RKgvPi0$jV->#|t({UO zN@EUBY<$c9s8#S$Yu`3b+O27D-=d+J=-*W|g*?h`O2LHj7oNuR2={~$s{_QxlBxsh z_!E{?9UzGwp3RE^bsXAXUWwDNvhz<3f7(+G0pbSyTa#cuT#>ll4z0UC$h^?ddw6^5 zdp3GMih%f^d5n5XA2;fSz!j@lUddS7q6Zn#`oYB5=TvY)#EnS>11~jTX^qf8jLmEy z#%4AUV>2yHZjI2=2Jx4yLNT{OXs(CR_} zstZirOqE>kb!@2ui8ZE}U7>!u3BS{5Cst8^vfzP!=Y+k5L6`NAin0yVlf~Li%TJ^U z5ZtjwuqK@&k`DG5({aERis|^&`*{32I2mLZ^e;D)$^u1h~4vFkn)LZTDhp)Ca%LFIcI9_69V2DxnO-XivgJ6^|sI zQHuSd@uIfS^*=&#Mh;)c3SiN)@AXo|Y~~ev#FHE5L;?ADyXIwY3xJN_J_ev5JSS5s`42_Xlgmzb%QY zX%fFPawi$$SdnkLn*KM*_w0H{z9Ytpd{gys!0>kBzttQ0x0J6)ZF^I)yS&!AOU$1k z*W=Vk;?!B9bkxnfbH1mQ?FH}sDYC1X&FoRfi}5olbY@+w;=@tG29~+WGdSOlv&8rx zyvI+Oq3N-eArWh%SLWyWT*m&Ws<=D0)pG~YB*FE_KU6vI(V!WLk!C$o3D;8dZ7MOs z8oJaPVkTVmwk|DMx$kvpNsqExTCA29{!t(utd`mYlan#PHA>P~lgSBZ7Gk$XHg0&z0$l~cy&c*jYGBnwvaoq)RrA{5-1Vilu; z)^AWnZ<4h>$g&m2e`;+ZZPS@@EbQprXW-wKRZi{NVgq)9up})Azd2eWN9qq0f_v8q zLR=Xxc}`A4MiBO!MQdly?J5M@tyKxZJL^mco>Bhwh2VKq6}hP~@7PK~B+U)VSkDtD z1ku0T>Buzbm-+?aIsZ+z5IjlPMNp;d?M4Xd(6bCX*uz{rah38r1rl)oiy8A6%?aq? z@)IOrZ@*#m$-DT~-KdWwn zm^C-E%#4*a`L|H5?_U1B=F7h!h^5`8E0g8OD|-pC&l2CH z7nHJHyU@<+;YSEK%9LNQW0=NU_}PV$5P{MYL<#wAu&J!^R=9#M_ytXn(aBjP2YbOYWb&?2ue?o6!bHV`zMtHGcgCiqX$PNRZ?IC*KY( z1a9dqewBW}LLaNRd8DWuzXp009<}Q%n-$-cGm`dE2g3C5k9Q|B5(}yGH-vCajkk3! zT(i0|9~Q$?Qz@B=Tpg_@+gzJb9lGInUiVKA5F90YSw6w zSOduQL5%{Zx!uKpbD|2Dz4&O|YdGx9!*+-3rceHWjV3!ie=-Al9Pw*}eR zd+=tTcMg4+Pw3s5eAwV^1rGRIjsemTEzIGyxmkbwT_RzV1s4vpnY=Bpc8PvS#qevF+RIGqW&UrgM0u03 zN$Ax3K24`<2Hw`@CO3eF)40W%E#%9}l20z(#M!0f0ZimQ{;pga1xxh-+XQ3Crx$P3 zJ!;T@h@96$rdiYT?Pt+{mmQ>w#RAZrSq&#kLtYyZVPnwG7Vo+K#y!2avzf1iZj1rH zPCXzHI{w1VnM;m6NqMO^g_a-=fu!Z-hP`l6w0C?v;PgL!Gq}y;r#)c}xbpzvAX!*3 zeISFRrNYyX!FquRbi-}2k$Kg70>`_N<6pv%h)dKxD}!ooPuOzprvwCXVn`4@$4x8J zg7{8WAhJbQV<5r#G_fkSU}#ZJ!~(G@mr~w8@hjPMO(!b+7Sb8_Jum-fLRJFl|;Nv8yX{ba~O$ zMN$;^;@bIe2kBxlBx_dHA$OD0>OT5Ypg;Ng)002Lzrg>)sS|GJ*>TlninZH|sJh}g z`g={ohXJb3J2XJ`(LEfhk8`MATCVd@LiGp3yFvB4ckO{PeBYmMxhzB#-TLNBS1=g6E&cgomhVqofgB_X z)qC-q(hdqZ>NqU!f}N`pH8ZLcJ(kIki0#6Hx#K%n`wwg<^icPT_>4~O zKAvv50KGj~@Ta%@A({Ph<7LF;Zfw|l8L3Hmn>V0npk=cUYTCWCcTnXCVZp1Oh%UiW zb{3I*>%WwlJ4iA)WjGQ3ss9ERZ^9jW;7srEJ-r2j=1W;TVKR{|{4rT$>t=q>rzg?Y zdciG?Q>4GvemEbI(XTiEyRMj%(*F8Gzrg4kXGZVQ*MB%~%U%)6W5bl$OomK2O0sQ(WScYgbmT4Nbq*)l zTEFP1^d3LPDUe-9-=rc2y+Wx~b(4Fboi(%JcNSk2<=E6IbwUi{iPd3+?tby#`WL;< zlsZF*OuF1AmDbI?)NOmBt{3+7*3C<@@XRAM;8%7TaKm%~CW`Wt z?X*Qt^PU(Xl5cMyD9cZYEfVQCPQ;gu5wB*?UAxL|pfV9VYW22V0P=QfN?5f#SeY*8 zG)Bs|G}J{BKWY+|<6DgLUh$Sy>i*p5S%#ll%`OcaSU{Vv-^gKmj;b<4zms{#zZ2o( zPJ8T~%>}$jg|Wl5#0Gkp(`HP*-ns{DYtn7mU~Z4`+J^5+Cf=w$)z3`oz&#c7zWB)= zfbiDu@$Hj)dP{!5J-udqp1-H}mj9${76S=K@}K1EI-E_MKj1!`4Z05JRb7OW$$v74 z!^=H&K7nGJRp>(%dQXMk5;b@>$sB|>6lsO>W*=m0>%24E+Nx(N+1;x3=iIC%Qw1}t z)~Q$TX1#Py*qePOMncTCwD+uBp_Z9^4OXuoO-`>~d0sAz?h^S_#o}|9OAmbmb`M5g1D)j-swTDM=1@6hpg}5g(p?2QmIzzCN zZHM6F;!HeNYTC!$n|UlgW~%L3ExrzKtTsOR>|EUXQvS---_q8FW7*eSkz&=IxK6vQ z4esQY+%;>x{a=RhEcnQR2X_iX@`}2E*Rd$ez3<0=b%10a2DC<80;K+K;TdRBe2Ns^ zrm}NFt-sY1&=9dgNR5j9gQOupo@j|HLW{0e85Ej`4?o7k>#Uj`8&VFb^}YQ{!day^ z-PK&c3LK^7@-0_RQ~eTdM$X*Mq{|NxyOojTiC9#)ht6Bk$hIbC2gcQm-g1zx+u!!o zdxV^9-hc6@Ei;|y7dL0mo!yeSD}KHKq4@YIQDyRLY|n2P6L~T+ZCcII!-thd%EQrv z(?5svv%wVhocOcuP)JM{Et~2{LQY!4qp2rtG?W)w^f(U^Tsl;TbLWHNNS{w4Pg~0> z$5E%&Tdl%&?(k^hTT|m+!x}F0;b_mZLpr9N4e#`-_d`|SEGur9aUwv2wY_(jG9|7| zwEysSg=acQ*c&*ws8Z}6Wxw9d_clyv*=+=D;@$h>E@*uW6HPW+)8A#^T^GLwCAFC6CQ9{1 zzO>+c?w|urst&DjQq{fo-Sx@5+2@e6Wss_{;n6!^$M#lE+>H6RQu1 zcs$zqdnuiPmIk#z0jyEqM!YQayrdRm? zBFZ+ov4qneCv{dfb)L|G#eth9>Pl^V-h8c^!Gg+pZZ5j;di!TBo%Xg+MvPd+x`VWG zVIJ_+CUo}O)Eyh=+KxlLPahINyLU2!`mbHEIz;XtcQ`fg;|7J&W3@6F4e~T z)7HG>#PFbDq1Mm%jTPkE2TO7OB-Hw@Z8?0-)4jn*=wv}1#Krf-JRH{tHBp7aJ3`kM zS)-V`wPpe%*&c!&iOcg)8Jv6i`;`F$#lD2Dl7;6c?LtQl5)mJziNin9ltdzje`&ZC zGQWHyvV0ppao+gt=6=HY4;wmrnn!Iky1UMO!UR663EZ4#uzFAXTi$n2Q)Q?Q8|As`4#Q+sH$c$<5M;cQHD22C*ZG zj@c;)O|c_a6a~k@W~ayg;a4{HoP-;DvKGZ^#1JMjTBW(s{zTlcR-eG2xgxxw#yc7x zQxMCN%$xp*P8N_t$GdeXHYW5Ns|Y(;#U$^Zu?hUoOqAjaoA zjR85lDm61%m|U192Y{-fqiHlH8sJNWFU7Hn{J|o5<0OX}XAU5ZQ81#!9OnOi@w0nX z73Y|W=s?+28Uf2jEF0!3?4LC`(TRN2=CG(H3pb9GSUa;aR=~Wks~X9uQ5dD-Srbq zrSB?!@Ij%X;77+*6CcsRaU?$@6k^@*&+nzK+V#_2wTJoX&2iOYR1+d3cFZ2gijZ22 zelO}h_{+%h54mBwx}3244bg8^B^wF5e~yFe$-HY*XwZ{>N#FkZp(r+#h1%3fTALEl za*#)u$|tE|{O;14?yKGq9hTkNKw2~V)AondVgS!_*W$}|H&*lnS|rcb$Eg+i&DzD( z1Uk5d2xfF}JMLmfB)r2DnpqV_C4@qDbK=ELN3^Bpb3Id98`<@X>E~0@`gx*OhP3-@ z%#b$ZQ4BQZFg)%YJb1c(RM*APrPj6{9fUZr`XviKXE*bVC4T#LJLAZx=eEDT!H2fv z=3RUDX(*OL1kyx{gV_4N zD|N1L*KwVL#>JOrosTNkJd|?G4MYsN=efWxcq z94`K(mRS?`q0kd5r15X(VmXxHJ`{VdV*vPa&~z?G2(!N=HAbJShUsWMC+l^vzGrMj zF+G1{#lAZH-!EDJ3_Bw|ezv&mjp%Cn`n`>+V~G)r%MYv(rG`V6yP#P5=X$4q{usr> z5Z%0avCx8~72`*|NdM! zbwBNdrObTsg-xzaHL&_wKiqS5zjNuAbPs)yl>BE>IRFxQk1OAMuP-|tvoyv> zscCdnfL0;k|1fF+aGdbGz-V{VvmHG0dTq^^z2ey zWZ0AbfJPIvO!LEk*U*Ib-~^@#E6*9Gf0hsF^T#PU+}eyahWuSG5(OXep~-=`X4>~+>#wm)fM`~D9-mvjoX{6$}pP(iq9M-9YJ2~5+a0yt1w$M=(B~?rluMTjJNJdd#QZuwRhvyy}X>3vzhygRPVo->WTsN;qV2yTAHBWipYB7%Xu z6fQ$<*VK-ZI$dw_CV%ZNS*x$)RHlEEH}>USQ){0k=w_wGJ-kwI>s?HebOCR3f4G+1 zzeR1DVu(fhHQ#JnE89B8>&GlkzDrABC1K65(}59C60@WUhd-}StFlPv^SbOhy*1O- z>S|1i8sx4LR2GRHnC|>?*Li4>^bJuKOHuij(DgF+=%=LJa$#nTq~4bsBixwHh1rqZ zx5dndVmh$^gXr4?81#v*mwe`1-{_zCTM%8NScEkyIhvB=N=-iUrZ`Iebjo+lB1SRN z+4~`)HelIWx5#znKLqyK-0b~HD3%YwcFfHT%AdSl9RtOIV?Y*vuD7quk=6fYS^ZxW zbaoRv=H6=N568eq&VP{Y8h`>oy_6^{NM z1HnH1H3qwX8M!Cmg~Jo|BTWY@Yyrl?WZ@-!NO}K72Np(WCP*7*xc^hH2tI#@&Ed-@ zPSE+6?UU(W=Ux7!9jI-{Scchzwy9Alf<-ebor1_blIGk=EkA=!yj{^N%l1{496%9z zSqBxs$M|c>O4P2rMEKKAQR1Q>U!99dkWfCsJ*%2!`xHC%O&e-Yn{aqGc`VF2>zBFc zj%0L2|NLS_kLWof2NJ)2(cXgyCzsu5KWAT0j_e0O-f;}VYGkDe%E^amG2Gl@Odt&C1_ax?hUOqbc`qeE-$^QoaV_PJT#^Hp+skKBE3ohq&_)dNelFNr$9xw`QZ|DOVhFY|o zY0qddBoyz-m4p_DKs5nK5T5_Kh4iT-&w6(%F%x;U_E9ihAIZXNjbO<6r>?O(Y&8&W z_6JBt>Y|ztpC)!R>^`xu97JP zC$b6w-+C(?ME`JPNx#{4SR<74{P(WBZ%YU6tsv8Dh`!sov`lDC4rxBuk501v`8gfH zk}SM=zHfNB+0BtT`|j#1t&B)+p9~nJkq7FS^@@2#z;+z#{rMJ=q$_4oORi*9{2YkX zl{V{(U&Cenh@f2%32E~XVQnV2OuViH3r(qa=xOg+d)kg>AMBWrW9}Ajl(K%H9v`IM zl7$Uq^+G*Pa}tkIePuo(|G2?L&^MpnU#=9P`Lhkx&(ce5d7l@_8x>MJr zvF}+wbQwHIgI`(1H4^2)trKv#Mg@t0<yD#mL8no&BDwt;R~h8FJz7);^S`;CN`9W|L_zIq3Vj?fjtow1sSCmxs(gKWK$Z8ccT_o4GmtEd-M$M| zl1z73s+{bLKSz!Kf>7GV#n&vept37}^;YK-gKe^PSAvXYLprMlntf>F*^1M5=i?;i z+Q3f0MTe!~{rq*{g&h`KBMM>fftZCqoh3$VWY__0!HR+UGwc{fwqcw`=73#Q*|R78=hgp*9X1cj?WJ;$WR+W3 z+Y5~;ZzlVLb@fA>!ujq9sgAFBag`(IsNbZJ+AhF+jHQ=~SUdNZnJOxDd2?)ua@f=$ ztPX6CF^%1~4{$X2x_2=)3vf*(d&CowsF$#`34f8;Hl*q@3WS!N zlB?ZLYrIF62axwYLf8G6_f1@W7;62PCIW|DNt_1lqG3*sBGP~g{^s`RPX2DctUHR?jYI`S8;5}+5lVc6^d*rg+KTj%VL|OvbOtnUFM6%49xMq)LCt$&29cr7G@1)?56?F2lyj#r8JWN z$c#i)7)gOY68+qDBzJdW*xYG__kQ~Q?nbg30`tD#ZRybdUm;o)sD-C1^V zAAs^dMMBkBcyLjxZ27aHmg^a~_D45n@n7)XuhubBW493`XYWYwQp&#!U90?Gh@qfD z{9|v*nGlJO16(vr|3Uv0^AeWb*Bg1g?;4SaW6STu5rCIGWk;lZRp`1!v>JMR+<)wt zxx76;^msesump5pv!5v3*Vb4<>llM+h7a?_oBO@5A%VP8zfNi42dU%j$Dc{@KTbM$ zL)G$kd!3f}eqTK1Z$*!rl&l_#1D^XEfHD`Sk@v@hV`oD%!&}3MszeEn(o#dP<(!tN z?i)_+%QxCzCXP_Jxm!z}M&(!3S~~v#W}mGR9u-G9WK$>A3^;W2ojRVpP#HCOC!K)x z;gYYxK9k~aPCEFNs^#x%j0dp8$&0(o}9RFAM$HdmA@H1BnSk4m*(fI`RlBChrQG- zL;y@oOxq_6nos9Zs;`T z8}s~-&bOq#<>kCRMVBUrZKF^Xs$K(sM?;uyqtMqV8pa+Q<>!n@a@x>ork~*4jBO7` zdns=`!7ZVdXALYJeFoNA!(ZC6lD$tjLO=?rF8hSN4wL?0<|K)$O;cgC%t5SG>z?`PdDXF8?eO1plke!KyU>Ij0E> z)Bux(<)7`c4LJNOtvWl|Z-&n7j%{|kjANTi; zx0)LJb~e1;)Yz}HVO=Cy+uybX>*FsxAw4H`9Mw217U8g%@LS0;B7tDGTlTP0vUOZc z%asrUlP~4d^kZc!4CW-TF{H*2&F-Cd(bpKlPMq&cH=pg_OUDBy^OpSq{`}xNvA>Ju z3p!=JOO<8Bz;mf1_pZ%Qp}nzEMh1#k-%2k5W@3QNX$QczK=UR-dl5{WBA*H_`+n~l6y(9V24*+FuzlC zAN(n5uEkwOoo^?ycI|M^!AiI5r> zzv;V8`+@R-IK0ozMeAAX8uE4Rp#oy3ZNq;*0}zP`X&|i2?HBmt?>_zvNDqkvsRGBk z%RuPp>%I(qHQI`KEe|A478+SpmiSQJcsnr!bUQ<|5s}8>3RqHsP|JT=>FKDIRmBX* z_HWCQA6u1KssdT|8mce(xc$N>X#Jl*`K`|Jp|d(KtWF$zC`ow1u+GOXIL>G@`C6f~ zvx_!oiA`$o6}Df)@glRYDF|?eZoP_lFN2tl!>GkCO6mw>vf>A?7rOgB#9S1_`{<=k zF$~K4mdMp;>MX}Q4orAU;Bivl2d@(SWYV7C`}?1>;G>BHO}opeDuu~}AFGKc2w4J)cwf!$V*7MHsH)gkJsXD19NkCS7qc3%6x*7@o!T{@S-)%rZ^5By>N(u;s`Qhe;#&@2}EjCOs{r5I?QgcJ?VI{+0zWL~LaGo&0C(^B^V)kTTiWS>2}mvmwf z?nKFRI@Hn{y&*r!`MyihTV#eJOV6X@g6DoD!T&8avc?+0-%6iCxH=KS)k$zi8)uP! zsZ?BkasM=gYUngXP>XxOF?_k2SaXVk+LPi_i*2@V_74&fHm-|Nw9-Tf9j}g8Vv&;` z8?Pa;O9T~ons~aVvN~Q9L6J=s{ETVF5QCIxUMVIZC$`e{2S2LguT+EN54HA#v4}8+ z;0l5r@Q2wT(-=d4zQaPBvvC$yndFd(?*&9#^bAA`M%(oQS0NT5kzC1rrfLQ_o^oD* z;}RLC0G(+Nj<;^!Esoo0NthB?!cse*;CMpg9&xN%0ghEOz_DuY0mon?gJZDb<2YHE z|B;ZIh2`U+=dM_;j^8`9iRS$fBExdCh!iZFu2Pq=A7Q#t$t=1&Udh?Jqs#x85#a2z zm%89=WyfxDb{mZgXX->aYvL1}?R(`Oai&@U&QvqNnQHF=XN)a_Gsc*q%d##Q%lpU9 z7!zjlHR!O25JD#aq`Po=UE>(>K0n7_5i%ho-6@t9GjGdf>V4>z)gmiDSs$q0Umr{` zK=$p7E|PROVo&LkiB%^eu%w3N4wy)tZc;%$g{FXCEWXFxKz)EqY7<+Im~RiFJs^VT z+oX$yl2;ljL`Cshw;4L7c!oh23wjpfT4Ax$)-P|+tr_oIvAl1^qD++x z4d}uB?(Nau)}T4y2wO1`OIUJzG%?l{DacS+6UYuUB`On_9axIQO<`&%RcDnHh0FI* zQKv%JDqC2tcQ6%9f~9K_wkgc8rQ^=;LQ;tUtp&(}xzz0_0xC|Z?~u#vmEH6k9Xca* zHLpyIW?I-Huem;dc6G;B$@GrO`FL=IlV3K$9^j!$dt?$d&n(m@?WF9#E z@?e%AUk7f?ELzT|Wfw;N5!%B<(IeDa!M8|)!(1GxDa1e6yv-sz`bL@?i}da4vS9vF zZw3PP@h6x+1gmXgl7)*xPAkAllgzs`1!wuXldsQWYIOweR!?n}C9t0u5YWT@2$NNc zL`|Q~f)iOvEPlkoKFqdLx*z++jfeTOg!?vAfdeGTdMK953O}wtO4JF78ZEy=s$c9v zpB4J~dGE0L_UdiTCgqF;bkGj6f1E85wm6+Iluo!Y@`lR)y!`0;F&lr z#+<-5Kw`tBLqJqFzY!4C`O2#SW_d4P#hkzT{0W1z#l5gjsNlQvQpie|%Ar{ zZyN$gmntm+S>*ryZa@mg`arscEBqD?b}iiR=SZ_beJkBUHkQ3_)I0m_ zAU-pun@O_Trfs&!UtOEJ3DgXI6zk1PQK6I>PJMtxs!EL8C!BhdZ{BNjc8z`AX~pyQ zIb#1fdiqxo7qxBLLYyw6TZcZT4aM8wlyrZ=maRvh@Bu=8laWqy` zthCa4DYn*Hr4*I6K`j@picl?zw%)2|I<}&=i1Iw<{r=Y8XEKRYeV+gO{`qLmoOAZs zd+oK?T6^ua)?Rzg@ytl)#}4D~1+l%6KRhEB6-y^N(KXN83pCiHUgn07usq$IK9`#U zyQx~mWzOMzcu{PhuBhEcIwrXqcDsUdfMOq25o7vRZ0WNHeV8JUduzA&sJjR zoNAxv*_L)k0@@Upaf4}Mo-O={pTnz)Cv&Z@g!lVq!OIo-AcY^ZBu*85Hc}UJTD{=Wk zZXBppio~3ARJ3X+S0e3YAG2qXj7U+7 z0XIOY{C_Irsr$4_xyj}w1vG@51n_${KpAFiU;a{w!bl(fA1^ zGAaD^3VO;TYoRig{p8SU&sgut`~(R;%r*XQszRL z)f^F4ZK6cv=JgbhR{c`-U)GD?2X%i$wCZPE1*PsI9i#XQl+V0PCB?o^$3M=ErH_*ReUM6tg!)V^Ab&RNnj?Qc3BSDLMGA))AJ|(>)u&;J@1U63#y*YU33ys; z0~HwlFVzVRZ3#>Mll^2_3MrPE)`_jE&ndyij;bDA^EJ(?t}~9$LCduZC~o}644}!q zK+}AYDN$tX=xYVFSFJ4r^5TbJR?*QK+C28u3c_b2ON!=_Ct`5=R@?LUcP>k56^cj> ze#t$1nM?l~`%XYk|J{NV^!hJK)frmTNVQAl|Kn)(`c>S|w8(=7DHP;=!@8rObyBsG zzu>b29@=S-cnkA-+c%Vy_QgntG@}*O&8VBE;os7#u~k|Q+mnwAu(KJ3W%+9;EINPl zv5RcsVV0AL)pkIqJbHI(Mq)|D7Ss10lsdIN3SfE*G@q63%-?OFZ9FZ0W~Adv+60FC z26-6H)4i#JiJ6VWtKK9S5;LnIwFEy|EV65pScAr3pFh1r0D9r*oligoQ(|y>T20qK zc$hIeOrNEAYKm&-=fPq5q_^smlVzJ1Lp^8BFPxs^J}Q2Q3e+jnQrchF0va`0Ia$1a zVH*Bp$BgL*+m$-djl8(LG$s-kU}8ZS;4uQEd+goq-p4;Gn+}H z*+kg}<$*|4UGB?IrMxA=sz!I6#!;uI_!lQxMeOKrZt|xdB&tUEcSmR6QS&rfm>D(s zrg(NSpHFML@6Ro*X>xi|`T-^(_Ec{(baiV>c^*erl3E&c5%u)$s{)*@>d}&5!vzAK z^B}4vWf_B(28QF8`k9Q9P-#ZN_K}W-cDqAc<#|)%mqj{m;r7C|83Vt20rpqvL9H{k zJ3l^~I^>}1$;8NBTR=@k93u)R2$8hl$_@eKog44xeV5-%VtezTl z)FbrdA2j>vbv!qUEDPR$(Wvp?+dFDxsibXisr37SiS!>lv@)YTT2 zc8*j;#^A#;-|qcDNFukjsR=<x|TKzZ&eGlHto2EzIp=#9er zq^>~d|NUp*rSZ{VH|r8dmRJ;IlIGY*ngca<$X9JLR$i38MvIxRQ{C~Z?wO0WTHS}{;#YO=DMoP>8(+ki-# z*u)M4#M2c_QVqOnMCi@Tejg2P?(=<=4-kH*h6Ng%g3GJ`HZHaWbv97j#Fj)=MYh1y zpuSH5nwnU~66>=8v$waA$?QU0V`4^mUgYlO5`0iq!9X%JCyUxfM8~r2bKa9YUOTs; zJRMldlNXg&j%{}sHuqu-UyTi`O-*DB*J=!9Lg5^*`$7827Yga#AjTLzX=5nBRW405mzacV?K@*Pj-|4~st5FzKX*akVFoiB|3yXFmW(vj#QRE!n;kGw9}Rn%4o} zbTIcb?2+L&_;8FzZF(g*_iC8-M`}O1bAj%Gc4K&KdtZxC*?g;YP37;)$q-NQGcUL# zU!=lTM(%VH*$f1uosZ)V3QC?O9`dJp+d)C0jQjA=Fxk<;_fbWvxM`g2xl2?Xqbd}! z%jP?3CC>Gm)DqrWkc8Ahygdl&5)m1!GYQQGlTesh>%4u!VD&>DwA!B>>uX=XR<)xI zNO?p~HD&e;{&uG7=Yb|hJ@fg+X#f{EQk%*f*x}Cnw%1!dOY@%0>=aCVjm`039yQeU zp5v~&zz8$vGUsqxNj$u8#6M2@EYnZXT*{r0K)I3puUuT-9h(X>{@rM9SOrnNp>I;& z^PD0AME*BB;G@O{Hu&yc>ow_CIs%ywh;$4?tGB+13YKyMDhA(h zM@Tm1n6b6h_}g=tXJripUwLXy1E`w<-K3oN0ZjX|T~fst{YiR;doG$@WCIg^>|C;X zuhCSf)_iL@zp=xm5!T~i_p^oJwG( zw_j2p@tbtkl%x-*!VrJsZx8Xe5sPhzzZ4dAP~=X^xaF9=dubk{<(X$ zhQEOV^~*`+0P{#~4S!2*tR4PB?XT@=34B6+Qu&{587FET^>ne~+wXe!9iMg~c-T(N zVyaHBaL!TL50cRa+)-HOSH})i+MVqcX}wR|NUfyeyI$Bfi&a#7ht^pvpti*nV7a}B zwY&Kt5P^J+-1rm2oZJ@W7Nc9(c3i_rlc&TEck2^UBgG3ZpXTp&b9iI+}PqgemN+Y&o^zn<&zu>ai#jzRD%3b5iYP)TG5S5)U zmPwz=IDc;+HEQ9!12Y2+fSuZolP+c8x@v)&|J?7s<_q%=`}2eU&^vhsHroD31_DWn zj5a+v;x`r@wzgDj|E6T@rC_BA%pbWe#FQ%h)-^sSjpm;x3X!-ZU|0JWBoo`>-SgmCV5QTac=!C zmxYdcvGx0Jx#7H*^CKOPTB%S%_@fe1g{yZVnYfmx!I6Olg0j;0eV2U%bp1xdCkzn6 z$Inoqnfj5(LU76ghXlW9E4gH=NRZ7w2MKE)^hn6TLAp*&Id5HfI&%n2x?Jx-l9O;* z_$!E$vGYTM%ir^Xtg?QK5)5O>nhL{zu(4Uui3&Bn?>qj~FtY~*-}#1IeajVC+OK-{ zZ-jN)Lb{hGBJDp`cN|uv4S%6MVX%x?zT3y5v9t|RMe~42%8sz!gvZ>V_QMpsH$zX})kW3qQ8K@D{eW1jh zKN*)dbVG1*0h0}rN2|T{q?SAl6Qm2_MCA9T#Vh4*M!Eh}>ko01`SG6dc|ikiaa3+P z)1)y|U0s=`{-fDvaD9Biv&0pMqzSi@V>G;xrptsp@VIEI-R9k(-okjKqR|S1*CuTJ zV%A0<;#MI$nxg&wW|n%9_HP@)wy8yUbOks3`!l-Ayx?Z~#Fp*j`?Xa}nRd>_@$X*P z)-v$Y3*zUIfqNQOP3$*mW39xNUE<%2K0f;L%VLPr!_y#Aiz{VYV%}AnMsCCoe2=%v)RK6(ZJiS#WMMa!; zuJf{D_$B`yNB*hpH9jkB+jF)Css9>B24E)1W!__#!x_h6w|s8}G!$w7oh>x?JucWh z(a+_l7o;DshrLx8(WmnNrD$c7fyo5x(Qp97|ELxh@evtSipK4kH+JaikLx18T~(V{ z-d+32D_!Qwe_`mRS|x&6L#%sn$?YFN&=xf-=f8C?RaHC%j$;_|g1>(j^gJfNh;z6T z4!alcT(~aOlN#LIOc?X|gZ>js2Ayv^DOIa@K+(8Gh&*NX5o`(?@Fm=6FGMQ;k_+gV zi6sDOmO~hj@Gv8Dj6c&!v!>Wo5cXPxQDDn)VHf3((5m23i~H9LMvr+&FQ~0F{Tab$ z{U*hnTg6ZL`LQuH^0&S3=0`t6c{T0AF_D*Dx>_-!Bo{%(M@rcuvYDSpC<{^{TAl)N z7xB6-#Y5fX>f(AhRS&zZgfGec8{DhH0WuaxI&6k>=7B~{cA>85C+Fau0zEXQS}>%Q zZ?obpF+&s3A>bYB3=!ksAK1 z6%$yvReq#}uUms;@-4G+{Pflt&B}loKAtQ=(6SVem^=s9yp)^2=B`_nmGfUuNo<;3 zuZ8G~ca@Y125YgkGb_;IAuFY)uE;Qa;d&<~6`71>p-jGFUAR2C{x->EUSX+CRLysF zTLdt}Zy6`-6s! zU7al^(vjp=D8n9eh3qltc}Oxh)j5dMH`o{95iWj{Q>gDSfTm+}zBPHKqp1ZJaEpF2 zQGE%gLO+(N;$a})n<}H3Vf~xZ>8*Vmmua`}6Jy_1$}rl=8Dr~$N7PZ|>QpgJb9$A4 z1-%X7>hIj_I(F_I4!sC3&|CSWhHghOb1UCq{3s(|R(R|DD2$ryzm^a>)a$~olvXQ(E)3OKQ|KdY(@WgT|lU-d?sGN+w^OKC)ID> zRzlz4mrKpLv3?^99Oz}P3PQnM)&VdS+~f-U#uu3H3oO(%m4DfF_&^S|-|k}zSHdZG zM>^BbDfhi!hrBfM`wTWqefM4Qq14gq|5z>}6w<&=vx&Q}La25BSAs!~Eai8)mm4q| zB{7a9(QVw;C$*74qR9KN*nQBVb=a&LX7=;rF|dI))E(QqOS_ALtIlE0!>M?+8%rSpv@-`9FmGYjy8`Sf}>FOwA+OQ|Uv<&7EE3q&u0`zE+EU zHty|IfP9_UFv_;=9+=&>OJschfj48)KH?+>6MrhaDzTTzpO8Fbry{A&Zen#@6q2v` zzf9lEVolt5sK!{I_a+g&_(YHl>*WOxZpcNl(G7hiOyd7x+wgE70Ho z3^Q|(f21aWKC^ZDimgr5nx8j2+F_a^D*KYO5k018JvyTjr#0!jL2o8ujJWyjJSx zN3;E)D^1aq-cg`M^|Q2Xca}M%(IT4B($)dY$RUJbYspGRlVQHH#QUw7T5R>b`zQiOmqh==KVAHV+~MATQYx&KW7a9cC{e-= z$>7c*jMr)o2LKPeAQ^R%Eo`a6D}HDC%c}T+D@GSFI@?B*xV4Zf`#EPzanX&MZH`K| z6lHe9AyG<~bN=?ppfBgt>e!Ip4El^3ZR9_f)W|#={Ca|>OrB+6@iBW9Wu7pKSO3j? z4SxP}{_{1CzQ2e5>K8m>)As^+)TxnR-4mD(aN7NYUZ< zjn@(%MOu?q`{$^(no(9+eaoCC(y#txa}ni-wSBID6(^_Rfj@2$SF9l+wW>%?s1T__ z05a=pd6OJnrk*x|TP9B?W?L2o`9&D{+lO?jJ)}vuT_0)H1vfTv@c0DJGJyaC8TtCo z!aD|}IxCvimrx2Ckb^pNR@>(;qUBHkLgQYyxrV8gId>o3Cr6Xu7OtvGZd=D;>`Hdq zs0R(aDbtT8ew6FSRADQswwSg@w~Ps)MPfH8_pnKB>|eX7ToWR}n18DM;K;8bv}XP> z=>)f9S%a5`xnQ5jyl#;~$d^}3MTlwWmiR^TR907^{Ydc*9VhU;uvpPsNgR_FUk;3) zVap+J@;gZtS3`IAeZWcPq)a1_@Aon>1j9ai4FVKT6c}#+;{L?iu|C{@{?1UhQc5QU zuNPbQ9`hZV6u?-P02v-@43{n7lXx0=DZ@(FG_(=S?4)4N=LEe_ft7`^Ry8Av%0j2n{LoAV|1fO|wfGkU?;=eBw04UmPmZ-LU^!Y-y=V1`# zTkU1R2Q{vCy;kkMgq=j>OJ&c}p%y1SIHaYMc!SQC(#Vo!hT7`6iYN)CKubA2e`!sK z1<0@^y%6kRjfx+{t4p%4QdR$axF3SL(s7DLZoUVI7$Oavx{#_Gmh;up@T<(U5DUYx zM_I%`u;os}!obHo7M}Taf1Ez%6Kx3zhSP=uog1#U<~Edp!4hlBOigAu@jXusk9;EP zaYLEb(1&ZC={IR^IfPv2?rDepSC9n7+_2-yzQI!v5~)KRh3*YVam8;b)PKKWhXLC(Yu4 z7I$FIyR?+c2I8m^YgKlBim3pFrHF zw8+1(0jCaLS?B*gu_gUE?PR3~@s&MpHh9kfs`|r6VgGgCzyBdH>c3S>oYoim-?)|j zZ^-t)qi_Ew_3yu%AXbiQ2LHHB{|kxYTy{;tuGVDO|E50uN8)7rZ=cZr+ZRzqu%Rla z|2OH8H^J)XnK|}ZyGLp3E8w$|K9#@xjd2oU&pc3^7hLdc=r!wA%AFnUy9aJvUrSHg zYM@Ir$$Z0{)48f|TyChqIsL5>A?o!v`favHX-|I*Y!BUqx}L_-u9#J%Y*(9-8Ep46E!2xoDjj2hHKLaFglh(XH^I`WlR2^EWmOm*)4;Szl5wGb5m^S%M|@G8Wmoj*b-L>C6F z$3|*IxKVIIC#aSabn&CehQ!lN-Xh=cR|xQ_49*(^VWdfJ_~HLXC<1!_SYP%+&SMKn~MIP z1iO1*HLxbpU0RnaoO9Cdd1E6>cCH+on)rLuKWbV(v)9W@$5yP0b*B$tk-1`2bbv8| z^;$?R2o{%mvQ6K>$~vSzw?8&;`t^Y*E?&RZN(qH;q56(`E!NS}v74(D!Buwe_c5b3 zKdk#ye)+qQt9Jht?tp*L^e*yyZ4|Xh>q4-yC`oJ?Fq;sGZ3s)W2qdBz&~5jbEXD zoYAF)bHOak_NI7l*dTX}cT?PS8W{3gd$9lJ*9hlu3v=R6_lU0K+$%P+5}%)iyMH%2 zSM_;qZ7tAN4r}Z3+_nzLZR^*cFbZFzepe*hyq#3}N%WJyMwj;-pLmaxEH-O>vVUYr z1xHzy#{SyHg_A7!%P|rBEsXtoI!hogSLE4b5Q2f{&n*R*aajlF(h7uOwPFY$NB*bDqEjIGXW zs}Cv1`3pzHjB;wQ_G*xmO*1)atOwv!PF|nV7R3#GEOBVcG0QBe!+lvm+VW zv=SBCm<8JQWn=clD>?LWSz``;4A}GQ51mb<;Ew(&XrYNxTdFN+saOV+*{c~A zfxI2*ZE#w~ArCHM+HYq5iw!C5s@0fn#6EVA8OoRnt0e_BiTYEK%EYFOW2pwS+*Aj6 zdp5sRNCH}$ybFJSJPk23U_ZXq&PRIOKC=F}FR8RaVl!T<`U#(38{btm?Px8hf5f*W z((KrTVBqN}PLCNf6?@e7+yUQF#t)lMg&(XtKYuxgAI>^i6r;e!e|@B0>SUYnU?%#b z_A6==-OMawc!P8RcbxLXjo7iGHc6a;sJ8GY)bG$W;rqR(JXvKw>h{Rt3y>F@VC|@q z3(2p(_ZRd%cUZ|NGt9a1`%CZmwS+u3H#9hgStC$O3hz1rINahOf52bI=aJtl{aR1^ zhS>Ksk7%x9YCBm&4K+rQkN)1P6^R2mpgX>?)!O@5*j;qAW!E+xvG@&Xz3VVjp9r~UZ z{OMWJbTa&$ivFZh9d)d|=6)Pj^{2>$Sa>2A3udP6p!0qhm>L_5r>oUIJ)JV7G&4!G zM?=`b}6aDgcXyP^-y;xgl``7wqM!f+@m#)6?4F z5VCdl>gc1Tmp+<=#};RwZ^X=eu-VPZz@by4%Ksfqj4@W5j<8cj`uP-FxJ zwNd>thz7LItjUXw^Q|qra!EX#c zu_%4F@$K{NQ9Um^2JZXqQ@u?l2ah@3AQ`Jmwi5T1+IcFta(8EZ?+*b0^x>T2@bwiM|+)zt9(Ma)E%MjF=d`2B@zW8ZKnWn6&Y`>}z*(5z>PrzkB$Vt-pzL@Jpny5E1lf>Z=qZNO&^$D|E<>mqdNw=;_bK4_@Mbt z;I16}ZUtY&<9@6oBj6>I69Ecg?}(Y{RU%+WCKQTBvraP4N@9Y~Vmx=AIn zubF*)4kq2@Z_2jzd8FebR~qwNHO#gtW@u_gm9HDp!kqVIfr!QLzbp;Uq~`MbaVnL&rsk=EAvF6YOH~S4ekcj8GI)fqHFai{ZIaAT4gCIVuI5u2e+OK;aIXD zFk+i|isL-$6@oV}kq{K`+gnZAp}EdilFT1;qJ+ZWeRT=z4oybCxivJxbTm7y{wUhU z5Y=>hj#gi}5b5JT)%>(sHjA(-CcVe%t%b*R>3!Twla3j-o&TBToXQsI+gtW+6Uo*> z{F1hcKzl7{BC!p2Fy%}H%e*120u3XG2BXY2YVe~1B|rTqDRk^|mog38GzV9`C0>_u zm1|Q^RQ>LUSu$_T+=$i~JXhu@o&6>3Qk+oGm7WH_Ye6Gug6FlFL%{U%pTZ4mREB8# z;tm53H+GxC6yyD{4j$a1|n?i->|s=*-vPz@5-1?5E8U!Igy} zbQc40R)XflUue^g12h|dLA}R^)={Z-e-k5mXCdkx9jJNSdN3yPtBDmgZ2ugK9SN-$ z_^+L(2A$QL;MGUTkfHPAIXZG8K3vSVb#!5>ezmBX0j)D?kW^<;UF!^HNHT0cBds<) zSZ!*DVSKmN8D%*y6vxpzSMkETC*Ud`5Z|sYSyPbNj-U+w#rLUgLkr0p zh@!EgX4HVN+7-NmSzeoH%<{S}oiCuQ4uszdr&Ci<^8_Ir5V}@1D@O5U<>1*AV>;WE zL5G#Gn89iar;kgliuGFF62#H|h})>v6xLu9h})Z7jTRiMb@NNKN}$adNdq)eJwRQS zW_e}V_7b2HS`LlPT)uZCKSdPHc9?F7ZqpJ&iX=OAI^5% zrtH!~#HvglZblVXwFpRA8A-+X-H4eW+bN)P--WXVz0t)F8zJe;sy|`H+v%+x+@$L#!pTB(^(-L_U1mK78H2`m^R&`|>$e&f;;+V=^K9 z{&@ZbZztcwL&1EvA$A0!Yg{{vXXVpTpAon8+3M%~Aj!vUVhvc|uLX7Rb29&5BZ+{z zV>XLh4A=34b&&G`JbsRBzPCwMa{;QVJ=ssSF&niYcQhXdrm?6>*wmBP3BG z^q?_s9uVJITMfY!OM|(4f<|pqAN*UJ8w-D@i+bACYf1_ z(QiM!vFcYBGWO(izr#J>GqYdYrx&-3p8?WSg*&;@@$BLQDb(8p@m{Aks>X2U< zqf*1Kzg?L7C~oWEY9gu?tvh>?;h)E~`W(6!KB$cm+8n&IfN*p-4|mA_^8(5cezT7-kSczY1aeyYtgJSBmaFXCKaN8GdmxPO2!1fY z^F+GnKj>eP>t3Qh&;N{Z*CKiloofOO?DMMnZ z)~|W-tNGP!zozla>DN>FwZ@*E#jjQNYYLom?a`B1KLvxPdzQ+FrD7xHJvlhBdYdj% zL>!zsjG=w&b{pDxgTtY%eGxWDkT+C_q{;HOM-%LioOa&Vu%mr@sPcOy?vr>r7&@|)`YcY9`B>F^to~JMJ5B^hH)Em zPyr{YhI01!4DB|OXO%a*92@vb4qT7(JVxUvjI?f>Pc3|8O;C5ex?&-?dM8;aek{SN zSdqs$=bdMf(&xIHM4r5zT^-zof5+mdX3@J7tGl|M00li8Bg@Y!7k~6TOQtYP*niT= zOEv*n=OhxW<&xmE9{Ex=4bvEPB2&``Wzp#RCmXTvA6=8JnC}}DCETSAX!-FYS@5@w zm>P>U$4gsh4!qK`Q60!^5)6vNbJX0x;)Pa-Awjh4Fm$!2zxLIUj*Vc?B95)9vAtCt zqpEOvB)jB*Kopu#W1?+s)qQe&Ip^2+seDH&-;V#uO@u&V9W~d!OwP9tB#Tnk*hG3e zy!kB2oa1zIUn@`B-AcCeIl?RLkJvaCJQsl)q!8s&gGe9uD( zNPjVQaBV7zG+C`|Ns`Ps)6bMTur3%f*hv!zX?bQDqc*fC^XuNB4ch-ZcU05Edo_YS z+wtMGGb20NK+9ULhP)_$m?g|{8q!c z9AbEL+VRW|=*o?cZg1s1gT~5fId1=J_KYkUhIg)NVO1Tv?6BkHG38f+{_YUl zkeTEyUh1r$*~@}U6Y|a%#vdC8nzhn`+J*PyCbAqVq@>W2n}2TB+vv}2Pxqf`=DEp)B24+hhL-g6ecv0JN zCW;DN&Z5j9p617Q^G|mqW5<=)svs0))CVJ7LIB|p)1y$qEjSW8km zmXVS645ek*a_~&7wmu#t25l6YH5al=C8{(o*k6!O;WG*tnw#lJux*A%GT9DNO)2-zrVzIJJ@~8sTm7!RCNvs1oaVF#_g!&0bx3&uczvo%D+Wvgk9>!8*P_Hh=+S0&gzfxqqAoLO}{$C z#h6naF5I`pwbYZv#pb#Hdt8KM=z}8&%QIQYA_PkX3d%T6geH~?p%-;M*y+cd9aOp8 zoM1;o6F990U*C3eUU2S@WViUr`s9H6Zy_#~Ur~zX@8`A!5My|vYR+|11NPN;g~O1_ z-(7{ayGbILLSX~H!#4(x7aaxa*-=z9t%x7Z{3)7Ns$cvmn#PM=o6Cu>spe3F>YnH0 z&wtq$q4xUO#!!1LKV7YcJ@Sb$JIfPQFLwZ_=12VanZb5ptC9IXgDpkomX&Ue!5?aE zLG%~?HwM^f=Y;BL=V)`Otjp=Ujm)BGSL>}Q zh_7<+9^b);GFp@+A{NKJVOMQ6P8NTD3YHhY^nEc{wZPms$613`nJ*3eQ&mN)ed^D$ zqAJHg{&_FofPdn*cBVObV)8 zWo5D*uPw@m2GZp?(ZHZ*i7%LpIqHAO;C;lxSN3X}1l}fP2N(rVCjwOHzS`Upa^H%R z9ru-}hpFO|@A2yxhaw*8=@lIsWADlY9S)1(31Oi)THaR{{pZ$aW?PT?){9*`k8nhr zct5wBsp5~@{}-*Z*CsJj=^JLN>STkH{W;?kqT(M{g{XL9N*_UV>58oZbK(C6n7Nw; z1cp-P*ZJZ6S~&S3`jr|yxVfcxafss}Pw9id11 z(z8O3^y6pIfmHF8pQ;dQtpe{Yjy>;MarHMOdtAL?W`M;uHD(Ue`Xd-*ekWH%0q!UW zYR6KLB0V*UvcCzwC-}2d8$O#$gP*RDv!Qp-znf`$xql_O>BT^*2+-!!ya=hnZbO2a z=Tb*f%t>PZo^oB3lLEwI*Bvt@+bneE1Hn;Uo9%=|j5_St)FqcM! zv((^g4h(mD?atCYQT2YSaDs(Btjj0$qo)o>%M9quu;9R*wa|0L3@@&vZCLT84KIW} zIeg6mH(@kvfqazGu^9>py5>^LBCLtPVJT?e)1jz9IAP?A?0Tb5!nn-mUtDb28x;~? z&U;N;9rMw31ebkC{q!73noG>ECzJTb{q%GjP zg)|o4&@A?=>H@G_qVFE&dC!X(>@BX2;Ql4(29f>7P+XdZ?dV{5*6Vxptfm;|ayIrP zhd<4f@wm!VXaW45c% z)XgM539;s|h$ZwRL|hQadFC%inL>zx?#2`j3Q3aMz>AQ zZRK6?eRI9Ir)I2Dc*T6ZQVY5=y*nM>Y5!nCoZz7i<*uK_7-5sgy|Wp-s=BZ_Apd*t zs^ktxG&v5eounCxFKwKdESvhsT&OTm4Sc7n|5reSY;~%D*bp0{GtShSHUc*}t$PAM zSn#$oQ5hsTf?sE$2?%}n{}~8WUeo;<45#j^_qO@TNm`SCvyMRi=0KpqaA{3do2$r-1lXVb7yZ0kKu# zKW8y+eWn!wmeg;?bb}QuF1#Kxrpm+GIOt5vie8*`av}zIW8iHfSf&u z#~~b_X|)CdLrXO3GYhvjKW1&+Cx?w>9{M8uk?W3Sa`SCe2rp1_GwyAhpEq$BSE_2r z_a!{ssRjEpNQ}c~WXcbxvC?h1`SqUA`Wqfs5HD91e7L*&Fw(KyIH5V(O8BhB*z90p z!$*zBcJyHl77DAz+o2gKQ}Kb#{!=Gs5K7HX&JfEhrgNgjpl)ce#g@yS#w;z~jCAa* z?-`mh^{o^}d%lQ8bWJsk!vhwu#aA)u#>jh)JP?hg@*kvx$@jZvOJ2xGh-Mu9f4I*6 z{+r=CdzB?4Fxab@C~zHZ;)jQBF<-yR~X`NZ6=j ztm^DJAViP26t!t_hvGAVKc8fb{)8PWzjz>10J~1-9EyD*@%gr-NhVzvIf+jvJr@~{ z>ob#VQ)(SgEz!oYnHnDC$M@jDlu0$C<3~|&;Mmv@;ydujeZGBsf8N*;0wtE}i!%fw z6xnWaSKJ>Q(S*V+C-@(KMsR4VaD?^|k$Hst!oRltL)%*oOOL8v7e)=WlxvJGn6en)xmX_xW(;K)xr#GwTDY6w98fY z++{O|Aio2xDraUZkL&nezvtR-|BQR72m*jjC7f)_j6CoJ)COjW;9ic?GW7u3)v=);xPCiMKX5fYrV7{pi>=7BwjljGAD;{9 zC93{$ne+tc?%FQyO+VQ3={xx6kJdKgXy+q(EYd0@d#CA7>EDRoQ~3jbh{m59TyT~;7Q3#_b#Zf{6nlZn-B0Ujej-MAjC4LN3)M-)c?e49Ifk3 z7U>2Q)svEA_D0@puIpTxuI3*2#X5%{xQ+y4f+I~vO#lx=Q_7~ zGlqwuzKZG7H^`etKHUY@?PD&W+rPT*3*El3t8d5O;FEohcO5_A^Z!}L_v+X2?bUJ4 zk+{nsxc7V@I1&iDg7gNhY)oCuCDE-3WeWxfO8&BS$?T%iX6Edc&JoQ1r_+Bf29;j_ zDOWqyqHlyOX#$p(iXl>izZDG)va82J->Kqr-{H9!w&hY0I04lnVI~@kUooP~h8TSX zcYPw@c&fcadVvB6+fvrKTNHJtT^XEoX12uCDL`PlB{ol6U-k)H!P~SZ_$h~=Wt%G% zCzn~(E=c8=;G*xogDvz8grPAWb6gt zCNEgA=rt<1ySIWe9l2f*JjAD}2xZo`htPi?@S<9(iF!G;oQN07qQ|@bZ$J>)CsG6x z+8WVsAcIq1`@-<0F9^NvZhY=z4E*?jEn8bEv`6tnT5*MYT(3}kkL__K5t|99HNh;7 zMH6uJQ%{tMIF*0@WaOlRw$}x-er&-Z*>1#!R9Ntib;AaNzLW%e_->TSq0T_&Pd-+Q zS1np6^2-*j1V;7tEx2|=Znx4$L+)QBKev87+V`!fD_OYH)RXhjQ+Ef-JbprXzhduZ zFy&%(BmbJ=w3>Ljh&a{*s2~0BcU!46=aIvoHe2{Mq5`o|=xNdtUVg}&4Q0_J9)gKQ zoZz7VNRa}t&o85!;G|c4 zkJ4kq&e#i$L(zZE|1`b9k8OoYGr)*VoBPY;zx1K%dR3-ZXOru~?QQFgrU}Zs zv0^1$OjOox^u+pHEN5=cp)LIsey1Pq+lN-DKZvUPw9Cj_Far!!9z6OB9wweH$>kB# zpZeDS%YOAMzNR@FUz3kB*V<}(UuP%LN#~tuT^i7)w5G(;&H8oCu`o;1p0;W}M;A0$ zxp8FDD&QKlzvRqk_7Kfj57CBHs~~J2V*5o=yh}~tTpv6dH$Owi>$+z$*K@%?@M1{s*5+3Y7p<=?_4+}+%p$%1H zB=~=)fGwnV!-iDkC?vRb-Ion`va`hFS%ef#xsV|n-{;@xv5|C$3ypiXyrF@XeJ{R8 zG}WfNpvVrD3lUs=&g&XcACA$sTt!5FOVtplH>h>5=QOyGYw+B2y<^+@m_n-Y5C4|G zE86TPnrxfTT{MMy;^x;u51V17y^Y7cy}fVkm-IHc{>$FNIN#pg7^gy){){u>OTSI! zKXHrcb9UQ~}f&9u%eV7%NRBQx1!I4t~ zt=w|W0VXjuO))uGk6S@Jv1#(Nil{QPK+2@u3@MX!>5r6SUi=bt^X;Zx?b}au>HqC# zYrf=Li=7`IRjYEs~j^cJq_{6Y@wy_)NF5WPzET{KkaWHW2pS)qcwTKZa?WAwXmpgHZ@T- z{Tv2MS%+imHwQP68;ZP5PQ7d&GG7fcEi|zbU%%Op)DhCZy!Z+3OlqXGqr>k`o+|Hp zqN-H2y6ms2gygztpojU)Q+m>?gsNvIuoLXZ@RET2qv|RycSbOpyk(=XqDY@_849jI zgpAP>JOBC^!iG0RD_@S>RA_G}Qq8n7i~rG1jvmYuwz>I)5^Nf!C}j&CVYlpl)vWo~ zM>_VW1u`vsrzk$BE_qTxP5XeZy5wGoshyJRor0#asJqi9 zM_lMWwc|W5X-8ncAh%ua(ywv|=E4=#BZdGYaCeJjAf7AVK_azIx2-*sp_?z?%uo)EwVR=&RS)yQ=hT0^ek3CV%4CaU6R8lj(*9P(;i z=PSWQfhhgJ+RkSutQ`2N+Ne)W9w48;+LTMs?WZ2Pn*0WkubcpBlsriRh5m==iQN6< z+$lp&kSR=9ihgUcRS?~Fu>oxShhzJjy|T;{kVYv#p>)}D#ydT>y`W#AqjL-GdA-)V zzdS>|I7AY9F3q(=1MHUcr>L@j?Ad4@=a0*{IUQ_w#Udvr_gyQZISTI- zj6Qzlz_p^7+SH^0n&3n+=`9e)(6wph&k3G^0lRvaMZrFQ%w3?QpZ&PcI$QR4fBw`A z^g+LPkdo)@?{Dx6lj8~cGd9n!BO)Eg(yHjdR0en=k9!t{xyFW}vNd#RZv@MpRl)9) zrOx*Y#Y+u;ZJjDw>`w&nVGU@y5*&ISwm)D+O#zb;VM+`1Ch=GSEh1m%a4a=D3pZtk z2NOSVLdsxDKCS{})(n0yoyTl#)*cMsyaI0>%rcNQ3t0_X#z$>!pPEoEJyg<-DdL_9 zFbfOU$!(e<8j8pzXKB=$2!<7aODRUKV1cnZ{V&=yL>bC7o^PlY#ak)(dMqm_q4vzD ztPty;@Loj??!?RzDS3Zrl#+McsgQu1;q}rfd9HiYIN$o6TqUo>BF0krvji_475KJ( zYz6KV;mL3x9Qc*13|3xKjf28NMBITPs61Wb>-p+WuI}^f5_F$E?}Wy{*&@A#EUXk{ zv5@;j)m4qY8;f0VAr9~1X46I~1g@l^{Au6|$k3mbz)d z3nH@rFkV|$AcgMNVZ=bIx6zcP1uA0wW})R;zPZqHE#F*d`4vtCeXXIBv|UQQY=`Px zj?GS*8Jh*QKV!6#q_(eQ#*`Y`DETX&ZUYa-C&#SVEPx;8Q<-k?$*hj=BKu8)j+>X; zlhxy0!(dLNsvtY}G?~)Lc_6?8_I4P`nerU#8 zP+Wj(niPAZAmNikmE*sD5vm-Il$px06K$HxvHTRtA5ow4$&fMrmv2gxxLdDt1b5w~ zSXduR_|OG>OskF2)I?<(+KH&6DMLn)bR`xM1B_wKjhuQ+a~b?LRct7PumMLMuS+J> z@w#NvI!>*UE0XTP6d%U;Z!7J+L|WVfAMK^z;<@dR2^q;P^|4dspL4u8_{HGE8|BH3 zw4>0`Ad8|f=5=;yv~p%qd32~~qf$&qkgL83 zKu}CiDhqLniCJ3d!^dGDIPZ34FV>zP`ZqO0ngY6MtLyYk#JoIu=j3pT)_0r7<#5V* zbKI(-F&})Oy3m>)W{z7sRr)IZQ#i%?*L$I z$Y?}-qV0+v~+H*_b$KOMz^`{dBlvLzvrr@esVaPymh@EW1lbUGP8o@ zN2EQ$XR^0F@(VTWWjB1eP=%8maDkCBmA~(?Vxo1ygPo3v9*<+*H;&PN31@c-ekmgj%uo#F}T zdrNP&a2KAz^tx2|S4sin5I^0*5tr04SeB^{b3k3^3pMQW-?myb47jUDj;y{x9)hIg0uj_`&}EdKpdO};@_nXhzbY9gmbe%Ai)ZM+K>gJ+5VxavJrBju=qJFnII#xhU7TqGMhyUl&v+1*2RFM#b03pL7>s`SIzKV-C5v z3+TyBG}qEE(OgUL$~Y&G5xx0`qaO$n%tkeg?-)QzO;IPNkZ6vqbps+x%mAF&H~@*f ziypymly?gFF7zG`YjFQECw~3CiQnME-}(NgPw17oZhpbB7s6ld<`*T{jmWfdwOapA z9Vi!=L5c4Gcli&lbRD2Gt^-W?is_^)R^@`%m;lSedQTU zDD`--?g_1vRl4_~>(}1dekn(OziGtv@AY2(0jps`?PVsrWIYwzxPHS~F7^p{{QSz| zDmTyGq?Rzx-q{Mw>QZNXm7*&mj;y~iQJrfcni|y-d_2aj51ricsq>kJ?0YB<+Vk+x z$x=~XBR<9-u8^*c240t%)Z)|k>5fOuf^b0VjVxEIxjbe1^Vo`Y zk@m+0fefMRV}l>LJR0sxj3jo98|6T z5eaE0C|tXcQqdHJf-C2^a1a~SWSd^t{I+H8>pF;YPvuD5i(%LHwOs9?#TJWuN|n)T zLbB>Q*E(vJ^1y4T>cSZ&IbRrs-- zGYWOVy~LNg^_8+8Q!KL^E2v$<*Y{ojItP77X0gY|7>bV=*!OESu*}Q1XdJXY-tZ@_ zq8Zz^?AV$F8PL`BIP9WKB@)X##x{QR^bn(ZHa5+%%QzW=A5|?Lfh3k|%qt%j`z_ zYVu7IH{S?acDKYHvfr<#XDmn~D0LT-U!U+EEkfla6Zue7mSV(2qvDgJmC=%`FX34k zToEJ3X>&O#u#ra;BIG7f^?1}+L9_UpbwU+qR!!ht1#?~rb;3B+Wp?dsEKgJ=tvJy% z(Ng2D;4b^fN5eGu*6CB_i_=F?X`<>>`-1rJeP0Ytw8Dd;D+j)4RkHsDNJ`QlvS8FA zH)6R+6y5O-ENT3+fgfFl>Y)6wP=Mc0c_-)`eaaSO_~jgBFiQWqG`s#kGkfRAb#JO8 z$zz{okDnox}QS^MSaYX*IFR-D0!mImiod9peQ-5O$zn=tpxl{5n8_Orqcb9=bL{V~^--T@j0 zUyEOQrziL&e>|=R>Lh2#p&WZZ@~f2~)wc0>t)ht5 z7Oa8Mq}G2?n<2$^vTF^cwytXRDmmq9p;yxyH8Rw+ib|Z4Q=_I*#ebQVRdOm&a-KXP ztK^isIkA@k|D%$_{^KRNtofg{oR7DTCdFSo%qzD9TguTBhNrgoS3z>lgxbw7r1!V; zGz|vaXx`gsS1b@*<&?@}6{eZi!Zzk&2iB^Lq>|0_RceNxDHVRi{)oh5oAn&YleAxG z3$m0bfl1Xz3KvZkK6O07QB=I%8d@;q4c}lZ-)YfuRWxy&>>HO0H&Zo~EE?EdMKNp( z@!fPIVC2daaG5=c?hn3q6JN8aQ7t4>uT^wEk$pSXb*>`VQ!$plMI`T3S$C{i|ADl} zYGbBTF*OSd4;xUS&p-dY@7Dr4CLtaNPp)Ocl!GCE6+H^p$pz(A5e;lp81)@ZIjDmx zPE@5nnF*SQ-HxuExc-uTm%%3dhW)cLE}Hqfc!@6o;O>Ad9bB8>aH#`QvC8 zy%J1|3*Pq7Zu~Y!t7v|?YiEeocqA2t!M{5ic@Sw=LVLm1t!uJNQ%^Mcu!KuAxpX0y z;O*z%u|w`3=7vM=-M;I2-tsuP2=_4}Y@W5oyHd{GEc5OdBe7Keh@aLnzQJANX+M?U zz5vuR9^F(IcGl$QEWJk%w8#kM-m*g-lz0?u)oT+?%`P_KPGZy_$QXsl3WL9?%&yro&A~x^ z$~40ci!l)i;bnfXt$Oaubu z^lSqPc{9g(iQMMqrtU$9$0J%iPeP!xW zsqX25J`gjwDg~x@Sm_M&5|>uawGV(N0&E>Q^aC z;z;`oDx9eB``<(V_KibY^<0T%%rumkLEH-XiL@)-Nick(naGY&Kdd!KH_!*kQyV1i zqx73e#fNbrFE;X0-!r8s-|QyBC*|cKk6Y-&SwmWR=zGK2GK_~G+B*G7i+7dz?HEb1 zR;sGULsOqD==_9JFY7v=Bz)4%QDZun*C;l1nMsSh*br6a#)AN`WDR37UgKd27K&_- zR-8ThVa6oyuacaj5wUr*IE^3&aJA=~Y|U*Jl>b8>RAA4 z0N~Wp;MI+Eurhz!T}co#qIX3lmsPUx-$hswmY$*zC$UF<)dv%4WbkoZGPVtgLVgVu zP9`Fi|EmC2IsnfF6ak3iK~T$J1mIr10515a0r*2M4!}kMXodf;0hr1^sFuNa_S|I~m!BB>>AHB%}9X6y>Rnm<$n2yJBN# z41O@&Ev!`nttrDoSe8gbd1@kK<;|i9JA1~x8dW3gWqK?Rs^rj8cW}t5O=?RpaG(`> zn#-Qg^pZLfv*^b2WF3SI7aKSc*_Wf0x2uN8O?T=emgP}`@S7l%;H{Bzah`rGlHIvD zyD6b`5q_^va$1w-&(l{*+=tQlP4F+a-6opchb9G07oP?33!Pyy8tuW>2?!oz47Q*R zijjC8ZQ*V&ZS-k-T9}6E60@h~#lIb#XfUlD*%v1GFbmVv;F%S<0HHYvAlAD11CGc6 z=$&%`D1~zmIm#6Jb=Yc570Co7Zzq7Sll_XD7AF2-T?SqY9Fz5n#To;ef1Z*DHxs-0F zQ8Y8zI8ynY58!bfHcD!QGY#1b`u+7ht|H}dOk~)~jtOhMaQIH4&3?nDL=<7s;N?Yd zcX%g!I7Sxz4ElL4x2A9Gw;9o`Z#1R$u5T>tFs!LeZ(lx+FT>&-jFgWNF;Go3A+9qzy$w~Lg%;^PT{f*TT5|E>^4Ll)Kx z&OOQO8Ej)!@j#wj;H1jQpiS%khN9r0=?+zEJ@$*g!xhpy{%NQWx9MR!n1-v>ZAYkMn*!qY zw6YZghuEsAfU@-5Mc2D_f=N5+k)lJ9@l9+;2xF{z%h|B}T@8W{q>tnm`o|G&a+O8P z8G1U_X4wCsdr$E}@fv-kH8EC{qeRd)p2^e7Q6MUajjRUVDDdLCA5WIWC6k)6-%2w2 z-kb4HOyCTA|D$Rq^{EDDbWP7XS5NSp`(O`OWtKOBZFDL#DoBCZvC@;bK8~87{Q1Q{ z>z$v}IX6E^8UQ?oB*t+OH59s*9{Ou1GOH<^+|6oFb6T2&&#%O z{J)kV<^iwEU?u!DVo5$RhPW46UXnqp6s7xRkB zw-|nl%C{JPi^{hc{^{7**3OBGxHwGn8KvRMwj!{ixviWx{GFZ*XKku%-(vgc6oWs` zb~9fYjP3@4((16&HM2OSQD~6Zk!a_iIfq&Po2ELB4WWTjz>3@?A9}R%lQ|Q#{8#*B zn^od>hDA*bX$5Z{)EKYHe!yUG85Vl61g*-CUinJox*EiQ9>EX; zUrAJ*JxuZtsWj}BU<%GAWE%D>#kw;(6JUQyD+sncSn@Y_NZBzMv&1(GRfKBGyMmF} zH-*ts0azXVmU_5tOpLgRv#@$Gr`hf7gL1}wn_*5qtM}>atitSQsPIv_g^SP9EcnpT z5~IXU#Dud=8F0?*%rxO9L#$BwSO0{`@Zgb}3>{*{Vk|%%i9j9}gCy#3F-W2g7lSn2 zhe6)-8us-s8Ob0mS7<7K+Bv4!Qi;n^?eRL5gj)p41YRcsr?a_1$$7%qt?G`@GP-FSo9{2*mQ4(r@AIuG2-O)pNE;6+t55`rveqFYKNLca%jT*+GuzwylWWd-^x|-V~I=x zP0J3!3``v=AKW}nh5`vNS6sng4w#`Ef};$KFwLpMo%Tnrj*VyF8yWFfjW(}#zWaL= z0qjJ(9>@Q)CCO$>h;g!YVnub&3-P~&uh1+OSi?C0`X|iwQ6SR!nW_AOC9untpE!c6 z_8rrZNq^t)?@dVFVMmA&IS(g)!>@IE-vS>^{bumQaLHP4uYpLWLFr(tYihXatUX@P=wwUfbS^?99$UU0P9Z<4s31rA18e^GMz@ct37Je zh#uM(YGk_NhBr9;sOO2Q@rQdU;lz=|f>6Ox6hI>Z1t3k)483LfaL!gemnX9-@~%&EKJX{20=CVgbt^%cilUQI8WKSM;kN$Z)j4J!J^=R9qu?pkj4XMmsF={36H8T!sj%=Lo%~m~~VB6cg&| z3xY#^%#=j5zTo@`J@cP)PHpE(MIG2UTau1ijzN_b(<%ZE!yj-6pYqLgb5*bs>80BB z6;o-8+NJ}d8yST4X)t-Xd$`_uhr!aW2p7BJkg_WdDXtn1PW?0QNC8*r%8gVKO`)^% z9xB!r)UWoA?70TczVl;{pK2^gR9$wcxEPZY_ET#P>x`~S;BxD)MRS-fXh(`5Kh+P- zfi_8{@|P#%9deKaPiun|Xt8=gi>n9Ql)zN3USAMUWro0{T_h2(t8Cgu7Wgfjc98{s zUx|k8r^ilXdWS%*gxhVL`Oeea_vU{cYRIK4#nt z*JWSq;a@CuFMhFjbl%Vnnjf~D>b`i`z1ZVdVO4MW7mM7BS@uQnNB?x8dm4WZ0^PhZ zB+%y$hCn0je-e_vK%`DxOg=2-6EB_AZ2S+i9(8^?5gvXzv8sSqJ{_Z5SX(gjy98P; z6{`zW?nx3d3-bWBFL%$XsOw>?`{AXo38@LeX z4ujlt#MT%jlr!kr@UnOsCJ--+L2Ns@F^DDIHwLlY?P3sGqxEQ~$Aaq>w+epz|Q}}MFKZm36 zS8Vh3M{pqdw9`TYRuWGVB;cwMvB?D<-)#4Oa)~VQvkL`GZ1j_^PCnoD%IBz`?cU3_ zU`R7fWKZ`+KdLOO{L@4tLZ(Qz(N5McWGCc=w{@KTys=N4^2*rm#CM&I5hg6!;| z7@nd!q+o`>B>pw%Sz2(dO?;Lg>DWwV?)aie$LsvoxkE1hbflx(8p_T;Yd~sVEFY5@ z8U7NFuhMO#{dN^{ZhhnttqUu{MrQZm&dY=>S3zy(E4A{CtyxK7)FwyS z6i`B4UG>`1^+_2WO`eWDuXx{06Df4S*yQO%=P*B}n+^jy{Bs&oI&uSlEq=nIxr>f1 zZP3Hi;D-6(lHi~Mh#zUWv%M%@_SSBEq;tyDCPj-Q^hI_~^+HwfyE;+z{DJgBW>R!- z>d)*3e?MW~9{0elPNERtZ3j!zuFO?TH0XK8B3{zheE+KjFZwS7bufRz5x}z8d&Bxl zhi!)M;=5ZkM$YhcF@CRH3jAMV{02Q5j^E0)a$dKB3Wx&5;fHiK9HCkp&!_(nb>{*f zWp(ubAOwRFcR`|2M1w{RR%`H@fM~)+HyAKbs!`N8RzLs6kSgNAy7c0$p@Kt+X*!;t7EmAOGO=8B-viyl*tf}~VZ~GN6+}UptE3IpF-Vn%X zZZQ9{1dtS#EyfW`ZO<2Q#Hn8oIATcu9FF+mmhK$!uO~7b(URtf6~o05wvkr*>{cK9 zk@OUt#QaS2!-;K&bBhWSCwo1{*dcxpYz2IJBinb+52i_KqNod#d6p(ev(;o?!7cw| z_rdMcuv4PY@$$ zg6^*ZoEun;wldLsgAMUv1}Ti`X0I2W}`x`7|s;66?CZ#KH<;O`&I5TnyF z>J2)xPm_iElrH|B`FWPwS{FE)lKIumHF;jGU7Z`~-F{sruIi#f^itQh0Xtn=>!~xK zz^HuB=-Pdfy~1A(gXM}~$&clC?7kI<0Kt)0LU!x-_)?pg!fJGY;aJy++TJ-7dx2+$Vd>Am57XAH^`E3LzQOOLf%tXi6~Eee6Wd} zc8OJlz+(HvWUfz&swuhz4h|=4$S%cKsP!ZP!uB^}K$4di`6UCKjxq7LjK|AL^gB81 zoIm;762;&A9p#y}tSCmx*q8+e`4Ylaf;F%IzUGkoDf^}z^y!W;rRj>xMtF0wYDNpZ zGbnH6ka|K1tQ_o!2A(x8&ob+Jhwka7IB?m(Iv7~+eNFHk*}IJILG3$d1^cPhA4umf z`ek1~!N$u&(?F|BfPVIS4ru)}U}S)W@o7$*OW_f8Kld2u*6@vK`~}Q;u5;8Ulu}3O zrKO^B^)L8i_N_(Sw`^>8EKelZHVOae63xaKIMeJ?kzqusQ3mG7W_dW*N(R~ozk?QR z)ma|z1^;UVZrvtPJ|jshxZ?kQp|)257XDUB+fdtDA>5ZN&&_+7Ux*jq%JBFT8VxGl zMK+3ue0wG5ulODKsSB?2si66}=&weI-*K$p=ZgwsLFe~9`}wK$ zSA9tR(pI4+@wIXub7ZkjSvwZn_bODS*3xp35$pJXnnYX%n9hkD7Y>X*86yykL_1P> zw8~fG@&#*cI%lN5)JV{mXrm5rhQcT0&HX_!IN%2qUkprX+>cyhxR3sqroF%uyDm@( zwV+SH+LJ5=w;!Zh?1o_BokAJF=~n%wk*Dg0rxB{ch_8+opA%=ooz!2j`P$nc<3woxa(0 zs8mf3`O2wc+NHC<;iowp{V8?aV8QEHi0w-QhwKjm{kSIFO5l zhPwS%^(U+PMfc)wA5J~3QnuvH6S(vFi^2LpbDYS4oHelA!l(t>`)WHyuztdm%+{uqSsKIXZ zv0qQgYpRwYSz{FOJ#2}h2YHd%iMD<*I6uQ-2A^az?bENAEn@;A(WuFk%i4NF9GIa> zW0MS4%lO4spugPyru3JK_e)Q0O(>@J)JNRZw)v$+!dEhOqQ@Mn28drjLClw?)VQRML=L$QrVTa+h(K#m{b4#y^`8+`h?YJM}jqTlyp zy`?V^05cL+r`cJMY%rW2v31zTF(v6xHrjv%fqLD5y3KNZnBD zGn$-E0^kS*awLER0P|nrKX$eAiqZ<9J5i?;Ptim1-|V%|mzmNZarVq^cgFi?^jKP2 z#b@ULWVBx=S+x22g|jjmg3@elR%iS1@Ouw_uu!cp)a5{Ugx* zVSxHQ58giUpYKj#<>`+~mI`A%VKkkE`ct4kefbk=8^f}Z8Q^RN$i{pV4Y%A}j0Ahp z#&>hr$wxcxL83VtCH9Fq-44OXM1M!EyPt$?^i5>ro?36m*H}yI4F{8f#a;AH{*D8P zEj__t##keICr_MY)yMOlllAA2(Bw-I1)d`NomnemOTb@1i^O`;_ZlPnL#6d<1j7Y* z)tRcIGZ?fcbaOa$Qvt8yD^mkF$rH@9K-sZn&iHLX#9Csu>k~WmC$Q!ducOJ(OSz4} zf7iBld0v<@p|f6##I}cj!FPVt5}EdpiwIBVkEp_?NrI;j>zF_+%i-ND%Mo>=LLx$k z0dj9?v3`TT5`89%eqZD~0cCzMn=ZUA*Kb5aJ)cBvU?giTZScQi{|akva<6#)&;IU? zi)bufz0O_vfT>SC^!IwoS!#Y2%UNoE70X#VOM4St*czTyrEmNR&m!Z(pxF^E#L}f& z`^UyyU>!oZn`e5n7n#zJQ5-${?3wCFO9Am9RT`sTOS=*qOxwm^_=wfrDo?xblewZI zosVq8slw|z?}4+VFQE!Sx@A?ue{xvU7XwSd92x)VD{P1)qAOlk5*xERB=Kgk8mgw= z)hn?Y>mGDsPLHL5`fuc?vMo3HLWT(U%D>%Mp_Xm1D5s5TQ&IY}8@)DKNymPUZ48Qu zg6b#OuUt4I*slzE%hcqnk^rL!kHZW=GfWv^?Eeig6fpzL!YIss_9b^$rJx8HIB34> z(xCaDZBg@uFQP;s7a2d2$G7tM&Hq#>o)EY>&11h=MEfR)v;p-d-L!j|$!M3d6=)cTygP=M314M2eir1ZBAH;I=aw`ZShVDw4u<^tW|f?mx} z`DeH+H=sUmuY8>)Y|mG1v`g&7AftVy&>t<4bBqFIcmr7rup-OeoR=Mm z^VCHFBCkZdVgCK;&Clo+I?V~1=J1c2K14&YrV_L80E0hz!j7nXiRRX^=ocORAROOD zzJpA2vTVJfhqx($g)Ad*-elSIHv?Jb^z-+u+{(`D1EPP_C%yX`55<=M5r8q3Q~7dp;@s@Aszv4NRjv(EsjtC{OEuJ?jrg zsp4+*ha;`2rG}e~{xI)Sg!CQz{%`0H4*4t{1pF9EdeR@NZ|oI*bR^j>jLXs3axJCa z-*4D`TdQhFU^4vE$jbNnkse_b)^q4vQ@J*JOii+xdj!`u{gDYU`VII4sTf-X-8G-Z zAE*l&N9rtsfC*e2g*}G-<$Cxtb&4KgWNtH^i97z5K*Q%=77f3(S9coTd0($+I71b8 zL&J-$sin47XK47#i=p9~LH`>xbjpCy(DVVDc&#R8((+95qq!HDXYTcah~>R$sv8k= z==TovTeR8HZ`A{iel`r~r!iO%cQ^V~8U0Z59HFNoS(f^;^ujvso2=jpyx^e>y7I0w@b=eJ(mlQ_S>pa*e&cT+D0S`*(;JN((m%C`|Q z)AlRCK3@5Hw7e!c1^KeE=`EpfiN>GI|LG>Y;;e5&?*|~lH&M*>Ce=uEGc3AaI5k7x zq->niKh028ki8QYjTCra`I=)YJwnlPX%OmmN-S? zV)qSoJ?y=6m#?l%Z<)h_!Ezlx9qo2SPJBTm{*2s_u`#oQ)>fGD5TAGAnHJvECMH*S zPtlkia!2>4fyFS28l4nBv$!@sU&SKvn=9C<{r>x=-56nPbKvZ!kzeH1pRuiwa!xsV z*cW1DhD3G*#*=IfdG5up0-4GDueK|Mi1<;5r7%U8vH1fgSaR76&P2UtopdfKA)uKD0eDi&RY10B z_eop;xaoExUGic1I(m_Qu?ZT<)@@^okvrY=mrz^1Xh+v>Gw33Uu#b?jZ4a5qg`Aqi zNcHU8Sxi|T2_u{AbA@3B3%d~D5C%KG(+4s{!!>euZo5OQOrjM*z4iA4Wx~3PRB>?HEzXu?-Dmw>41?xYJ7yaX7-@%^UWzn(L zWo|^RcT{gWOfzM!2Z8a4f|0}^c7eGAWasQeroVo!y1EzR`X6_LeE6UAgB=HQA%%Wc zEedm-&A6ndESPKU-P|V3GdD`NFhIY}l4dZwJ*EXI52|fTP!ON&{j4{o1VEml7ueKMTU}wzH~JC{0}@8#-z{!1I+hC zaer1azv0A*NCfYI&)=~EEh^AUx76WO)u^>nc-s{0!H^9kKvYki$EeQ&0m(=j0{O3z zjIfdTFDY&>nO%b3%%NYgTDi3)JcJu^LXjTW?6)SL%)a@yCIJjsM@5})e3%No)9V+Krbp^5Oy@OPEHvXcts1;w|iouj+|0iWl6(%n_bK~f&<8FBA>n{ z4KG5D(8zFZOB%Ru>L=PopjRB9fvh&ZmZOB;Xy9QTXl7}<>z@D-C3>d7YvYPYNulS# zjDXL@cB;Ylnb>qhau6mmw&Rh@-}A47^Oj4dczuu3Ste&Mma%jz!wSSusMHSvfd2#i zrQGll0gM8HA=!vEM+gXepU!uf*H7~rvszitVY)nTu`_iF2H~V#Z@{)Xr2Xkt;2S~5 zFKJO>ea6N-x;@>8T5@-c(ft)siOTf;Z=^Df znvfV5PAz4O+$Esbhtwp##3GcdqgvKe5|#^>$^6D!(GNGTLNY;zhfOd9=yBl)>bz@1 zY|PjHA;KR(l`&LNqgFcp7Wf;=`7bT&dQuaAr#8O6dIi<;CXi=l0(lYmyf)02+58D# zTcU6L313^TZ{;?#F%O^A+*i&Hl2t69tKloILK{x6--(HMd* zHKrEOS>1|h_rA}B0EJ67=&FYAw~G78S#c%`#n^__H#ReSpsyzulPDB^{rZ@L>txjS zc-Cs35J?h|F$kA9mut#h$jdd-=#xc@=c*YP3qQA7GL2xcKyVs?@j%$?0~7&6n??`` zdmoH(I$a%*gk&GWcK$y(-xZ9-jjh{a1#xVojM%MCB zZDcF%H#sqFj{c@_AA`OHg z5?9G+f1lb)LWoK6Hzo~#$6aPS_duF|GkWx-@rA zRCUa1JB-|CY%^H^a&Fk)z>1EnJD?+^ zy^g%zlRT%74tgV2rYZfZb$ULBzmxedufdTS-|Q`#FP_i~ zhSeZ6QtsK#IDBv@{`<}rL0KT6*$pvf@BJA&;32giyZ-JYcfZ~E$1x54@z+I?BqU}< z9L4`P>dTEK`cp=bG;UnZa#fXxY4_H3pu`U>(YgW%2o8fIDh^rim6m>FU^keqOEg}B zbf2I1YbtP2EnFe13-71g}n+|A`s=H>&w#C1qO-vk$ps2q+ot z_Irh&q44fD?;0l8}LHBBOx-NIX9?4?2zRyz4O$JKB3 z>({A1vzi52rRhlEdtY{?F7!(^sMJhm!EqRSmhWZl0_3lxpT|Ge5Q@eUKBTY><{szl(8J&?-LXF`TP3_#f-677Op@$00Xz^RGKy5SbgXE<<` z+fnfjCcVg+5#NAOr*hc07ZWB!-17O7sLCNh!7}ulyLpZS#dPfr-j4=Yl*}-3Z^Lu9 zK0?c6{jidjcY@lTp>7YXY-Gf(g2-n?-GZ2iR{%E5Fc)@hTMKy}mLGqmw;*M-eY+E|2FRoZK8unm(Qi( zYrHex*R?MCA$s7yHOPMdUjbxS1dur8w;GY8pL(1B?BGWxs1O`pPyEl}vqhk&2xPpe?`4ss9`H>BIs|{tgCbCD%%>li zb`E0}@Y@@3gY8XS#K!GIhl!td&X<@fLtgS1BUid3S8(WBd+$4gVkjK3;juCJ0UOr40yC}tjX^*7raqG{b2heI0!|r`ZyU4=( z>;uTWzQ^ZcNcq?dEk4YKwmroE4sXX#&%v7)yCC4G&vu0&$6t@5$oq4kLB>=q!P+$0 zVyo=jx7xl!nRej5W|gT4xXQ{YVB%bdcazd_*U@RB7#r zZ;fyFJ~U3YrHEB1eg2NFml+STTN2Eb`4x*;>BvM{crstK#A}$|#y#xpXj@Zu;bh^N zTUjFrqB~a`pB6O$U}OxO*sL38ppDkZTSRk+1t6Hh5 zv|}}r!I2R_Nxsd3c^ox!7R<}{bqnV4=>_w&Hv_YC;R?4}x=Ka0G>~2`S9WIL_w&Ir zOP%wU<7TxgB<5Pzt`)fHi+;2(EjBLp0RbJw}9i&7?n@Sb3L(N*9 zgZmZ!366aJpD9B^i*QC4%^>mZS;2|-tp{o-<4dc8b2@vD3=#sK_$;rIg;!stdguvC zPfWl=Y|Lg)W&<>$4D(cV9^n1yT0!ZanXiehm^qr1S|MIn>^*wSTV2aqw*F%e@4Szc zi47+RG)->|#DrB6JaF8!(v$VAK@14hQGdmLJ7gz*@(FVUHIWeoD$Klq$XfC(yRRCR zL#KDV)go;p$)FhFU1~9TumApD>p?AZOr~g{4qId3De-$Pv(GzR z&}cIM_t%sYgmRL#k^WhA&Ysvu9${q7jwkYF;Em{W* z>+yTkemfKkD0R;k9ym&|*YeSPEO)gDsCMhzuiKRnkutZbSWPZeIV7ltx#yKPd#IS0 z!jcNFMfcNHi{u6<`MJzS2L`d}^8PNQ=}CzJldyPji?|MBHVxw-*SNDLPi`7whcG9M zYua1KFQ;)nXSL4fysIN^O#>(unNU3*cSY=mx;$MAq?aVp+1PSJV;-%v+|bPav}s6W z-VI^7F>cdTHlT8is1gsKw@6I9nE=L_+%s7_8MPMq(>o^6ITXe`P?E+W`uPR z9?%#ZQ6F7FJxV#C&NMUx*g+Bm|FVS6KU6f||M8B`D(3myGk1Ni`SfinmC7 zY(=oLys;wac=K}W_;;829pC=8Iwrcq^&m63*r7IYi2(SK0ifHr#aEpy&Oxz>^ZGDutHxE?K}~MZgcDqCu6YN(aonnTW(jLk8RmAZObx&~69aE^G4Pgi(%`^< zO(Yx3M3%3qkrp>mkQhrag^-A%f;rZ_VsM_t<$Kq3A+loI`*BKcW9q8~g4#i!nn!U> zYsoRP!H#TM{s@DDKa3Yju|Iep4WUSykgjMjfjHctgxrNN$_(SXr;lKzYg zDyiS$R#LM4#OJOSpnrirNdu5KByagC zY6qo5?*dcPu?5{V=ltIVn)Ay`n5Wp8T)myZFCXIG~K? zg^=6hJb0KFIpolTY;r8-x5%-?o?}P0PcF{rPLAQp?$WNw%8{v*?Y7X`#it&6bl@~ zXPD>D(YEitg$Et`5b#;D;-^$HwyjU7^-KB&^{j0qU4wpC=3jibvNTCw5HoMG&+)P} z7f#`g7yTIX2TtU6nX*Tv#Si=Nw?p#0D?^;SWn(ic)z9EG5PWzl^Dj&Y$fSTv6rRfu z;(ImFu3w`rhot;CFR%Uh9N@wO@+`f-GtSzl<r*vs}>juQ3c(y=h^(Yq?*pc8Gci`+7ETd%nLTignuu|*gKS$HAt~8OnHCp?BbAk z=f5|9O*SBs75=LZ@3pP6Ohi9SlMbz7N77C3rW6|K z>~Ochg@on1B4N-a~y{+cP`CiCz7k+xauy#2l^CC@!}A;gLC zqd+kJ=P@*=ODj-HZyK+N;yorLr~InA*8hvV==68?PM9lzwW+;0ej|c(eV0 z>jzZFo-Hx@OsLop?MSOBuVc(wRwiO5hYdb8IO4YOXA0Z@aFY}>ji@*2N*u}9R7Jd4$)(Ldfcy$Dg1^W`qDZRBb)Z@r5wLHuZucp5u zci39I$>V>vy674e^X@uSu}eY!uKpUo{z>1Z{yr)-AiMqwzrKojXHh>GYt8dx>$FL! zes1inKB>1zL0S|4UG4DKm8q{`n$N7f{#l@i+hLDSp7vgL=;E!KGpW{MgC z82&aT{%q}URvEKEcrQkT9c&S)NB`;!HOi0g-@kn&JY`0j zd4E{|v=TE9+b8i&`iw2x$_Mk?a)Yvx8pne|dmEJIiYt!Fme+n^Y?=6j$d=HZpIS5P zxna$#eaTeRfpZU=R}q;ut*&Y4jCsxdjvd*wZ%cFkFE$mmj{}Fr+yK|Lou#08KPk4{8RSC z{CJ=$CyBZUl&JSVf8YFd8S`Vu3xN`K=l7iw~juA zlzpX5Lap#(`*6h9{%<+&;j#sQA;asi(XQAjS;f5jbIPO(r;TD7P_Z}ibe}nM{14N+ zTNHE5i~jwse`0CP*cYLr6oh~+TZAEg3&g4gD|`#?Qe$8F&mZQwb_3(sg%syS2{ov4 zCLkOCqTfJYf@nxTwY`tTk8`+3bdzPm`~%Dpv&bFBh+a4LA+AlcO=$dumf#Mc>gc6D)CwQY_#f(hgT6Q^?r9gp8Gl z@saSlb;HVYh%Py7!gE?aY2RDEr-X$$_tiH3r!vd`&$Xa3Y1bxCf2bz5?c&gFa|K)M z^Gl=G2~u^T@yoZ_ss#C{ORym!-iO%_daMWBtt@V6Fef^TY?j4sM-yAnszI501Dj@+ zYZ!AW7ng=FMN8SJGp2;^@6qu&on~MLSRKP*B&{2z-I)7gHnBNlXDT)$qKiospj2+> z`R@k)+Qivxwuhy@E3?aCiR;2Ci;6entk8N|OEZ>|K@t-!6emQb<;LbbrS0G5m4@Hw z!qINX+_oCU=i2@~;L%{1+7KHvZ6k}5uEw$Ks@@EoLl!})L)9+DsOuF9)(6IqL5Bqk z+&P+-45;3P!tJTXn)cL_^3Fo(}_|o`}Y@3Y>2KrRaE{hI{jd^*404VT& zLt!gNv7!(omo7Bs=6_5ikSynPB}`I(L^bCtUyGIo=PUmpCPY%^zw#(5<#0=(Zz!+p z%%@k5Rhqvjes)!C%vaPQ_5+@s9r2p1TOtNI%Mm|40%LR|T`B>=YvO;e9scLY%0IKh z%{`t2o~#d*uSQF1l1(gfT}@hWN7J<;sJ?R%IEg=(TB~}A=<(syuZ(2^L%PX~ss#ji zneS9Afc1nJ2`^Q>gB%GxrE&mYCYKME8p@?sqHOr`Ls>a}`9X6S_ag*5F|VczA?3n# z#ZjMrl3ocK8J zr0LEC_Po{(X4&cz$x3335}2h(U`B+SJ@bBx54K&Mg2o`C%bYLXzB`UeGpQssiusr; z6SIG1+FF(UIQ?Dzg=SiC{)OKHpRWSsA(Pw{Iokv>ax%;lHiz5;o3KQ<*rpCX*WZg- z5fX{$Gf6UC|F^2DN*~EX*8-I#h;2KzMa9^rn_j{9+JxPrDRW3WKXbQ%D$9#4`ee%` z0VOG~f{~;jx0LL`FLU5RcR;80c}ZF3x_Xnm-eRA`pz2dgyyA~F$VrKdSwJo+tup)7 z#^_ruziJX^xOw2d4CNZdnJD{pVPc46#mo*8p@F$0T zpETkwEv+~3L8Mx;=)RYAyQ<`W<@%Mjh8jL3a~*C@7?@nn8T{sgk|s2UTDo z!WMyr>%<0A-RNz8Me9>X^ej!dDvi%x$$vUtR9kPb`a3l82khkx_9@+bLB@ zMK1 zYjz4Oa5Sjc4z9`l?{kK!!wq;FhLC4tlj2}kjeRu_YpT(RuU8@fNmwk zf7=}Yy~ao#psQQNB98T(i%fG))IoaM2hyUM@2-gLPQFwE4p~RU6R=5E0H~%R9AaWc zT*J3IjipMA%b)X0Pv~x*`t#k!FwtY$Ws_3!xnQ?BZ>vG^z&3rv{?c;6Di<`MZz|=0 zbO*p5rVRR_mFkYX@uPM?UTSN=6j?~r`c%(zhoUGOY=4TH;R-C3vt$W775Zc?Sw^S& zXA6u2w&=1er3aaY>{ke41l|7Mg1gM?OTf&7Td3_WAcbGncn7W&q<%qWjXG?3`rGOQ z{%`>$ElW6^6fh38DE62>Wq_$F0uUykOG6(Jclgspuxcc3bYP9D8P&D*GBT&~%>uOcME#9qpa;dasXbHgD!IyYE39X4pYRKX3HAT0b`{XQHDGf&f*nd!3)1PaT}h zdEQ>G0&XGnKfjIwizm9&6M3dIGkIs!8VWGuv6a)Vct%w$L)`y&-$`bd2nRU;EJCYi+t? zWS1)s7>H>G5ZeSvsX@&R#^um#f*bqiKHxh|_mNsij*sX#^v#%$q#wn)`rI<0>2lCn zo_F(wd{pIOz21yLH@?;I^VsLQ6Y2o1Vbsj+gmNPp)@f4$Uv}~nXTfum&p|@;m{soV zPjO2($Kg~XrdUaQuO2_?L{01C9Zh#Jxgc{p(hO3a_;c1&RVyjw23s3kjZj_To%n>H z47GhuW9{k6#tA2Q3s;E~2CdHJgsdqrrNA3P5-^(rxon^XfFOfp{;N?xP~N-!!=3QK z1DydM+;*S#RvA7JU&9A~J2&8i{*8_g)V!e0@WH@>p7`L)t9syrizfHT2g&>;XIYR? zpTE--P;7C%-#v-G(2zW#O=3!)$>6t^FqW$ZFLAWwl^<}FsIi5OfUNw@X9hI>!QWiF z5BtCyt!cQyZ`f?xv|u#md85%OXmOs?%$(n42Kf=hG2Dw-YcNmp+wL%!S#_wJR?7G? zCqp$_Hj%(kswgEN#_toWYh z68+Hul;$ceQV**fAa0_Z%BwLWxjuO>81;LN|Jxwo_cH%?hyQ-DepBCI;QbQ+y$zk; zf+K(@qtJ-0eScfg?fxckgIY8{+Z)&nIlmFxwnwOS2H*MCH`F?U^-d->L8?t+IiIp& zx9w?N23&G3@+@Z1v~}Eqv(+Il^%R*j zfa~D5H)x>Sq1>Xurn$-YhMh1g+Z(2~y|>nDR~C%eAK~xNQer0h_b>(L$+-sbgKhvBp)j$RICiOS{`+bVO(K5a&vp<;euH-?QvA( zzu15yaicK4%rM_wznf$7a(DV&8e`_;!Hl`hfX%|6cN`t<5@myW*VC|?t0Z3vC)$Uj zl-FcDS@cDFcH*)6$kOFCx~(?4rKX>H-}^!@s3Tn46eZrOSX`KcYd?N{LdBX;>-qM! zi?fEHTn@#h{*@Lz@R4^E(_-fc_xA2BXuD#AHPNf&bI5{crySrt_|h)nnR8TcP=#Ti zFsEex8y`$y*1AMPp{F+TWX|`C@@kSp){6#tVnc53_3%5LCVDWJw`I-cmxz4#ZvQD> zI-8#DsR`)UzvE}n{LMQwf6$K2@4K_+8`b<5(#?;gdEyIR&T9YQ9ok>3cf? zKdkoGJsE(%!BhKlXumzPd-W1ukaU)T7FSA`^IaeA%KU2f3tu#2iK)t*uM?INyE(+-{mhd0mJ@uxmJ?z~X3*LY{?4nk*KmaW3Y>%&~|zjOZS2?u|JZzGo>F?r&j#=$*uXYKO*(|Yu;>41hA3QsEI zufUj|KFRdRk#KfQN76Fn5$1}$_eS_*HW~?g#i@OJ8hvm+;USpVAAdySZ%{ikg+H@T zntv|s{(f1U?+PuHREmu`dl_rEyg%&{o8HWE($z_cDqUTtUDa45zQD;;IdGJy>b~YX5yF&f6o^UdZu^rOMf83NU=V^CD&47BFi5)mywZ35h*gwCg!yZ-U`&q z&JpB4`MHL{hIN5-Ja67u8%E^$mbA(jTg^dsbz0xKKF6OFBI&?u(Gh_o=^c%`3Q_Sm z@h{${Gh`Sx_m)L!R&}x|stsBE2>!+Bj{}$}()kFr&iT^>WXrHEKgRF29jAZR{Bs2E zU$!HGkL$sD;pv)MQCLZHo}eE<_7WE za}j%wXWK}MZsmO)+-qFS8v;@z@qR=UpI=(QybX`?9vJk8t_h)Yx-O|roNzcXrA*qn zrNw!3Pr}TV9QN1)L!5O&3R;7Fbakvce;hlQJ7!pJP{Qe@7M6~9TladqtMf=1$23Es zQysVZB_14-XUBZy*`uJq*^`3MOHO5gD)3%C+^1LSs_snU=(B*HeEKvxsRx-brO>}@ ziwo>CIC-Bo)*p$IGQPB&m)arCMaN9Kla5t5E=P8_t;g2!p(joc6TIIsfw@Rlr}f?% z{|YuuK5o~SZ98Xw=>?v4J5&coK09?_Z=yS&Rj)dFaA_LorG5%4bI5uvuv46@T< zOd_StXGv$}A~Zrv#E>iJhZJ%KOy^V&PGHXtW4(M%OB_}>WP`WLZe8;|@5vK~oGMgD zwK&WU>q|o-;SYc6ZF!SWKBk(Sy_KgrTeIv1km8l$CtwaL>rG;F=`^_OoIpVQu zi51H&Lm14XUoj>3yZXprh>@4Ovfeu-(#v}4iM9(=2Q;v7Iqz@LVLJ#s^ZvG{M)xK@ zMw_i*eRKQ`i!xnoVKv?@A>u7_Hg}d$OY%V!+b5E&4(?~uvXMOTd#5;Rl}D1Zj9L|< z7Q7HGtx}tPT8N}E{tUGZpzr6Zi!qr^sgO^-9s?+poDv&z$P=R75E;mbrf4D=y4y{|HjJgO~FNh>qxNQ0K<3>TDccZ37k1*N^gj^VV)s^@B!Hzd_ zMkluL3Wo=h>@X+E%)fP^Pg_VKpkW(uS6A-zmyOZmV`G;7#7A`_Z<;H-U*mqU@W?s3 z#l4w_$2qT;X;)zh&P{I7v+p?^=`ASPff-ZLp4F@0Fcp4a_N2le@-ecbyFZNgargfA z9^X6pth<5yF~Ve0Eo@FD^N0Nmnr=hHVN$taQx)#?HBD1}ENl{QAX~K}6uq>aCAK4a zq~5_zTJ@QHWlq0zOA1e1CYN%jm%NrL$Z-!(Y4uX zfP+7tfu9LYznIycoF@rEaL&jz-GX!WSIoe7-aB3X38__w1ZtIX63(HTH~&-_a7_~{ zQ)tfl`-g$AeetwB?+Y(7(qw+WrL>+LcIm6&M8e$L_s77Q@nd?c4))!X`CNXH7s=+?oqNRm)&$;q6o39}1=C7?*^*Rxz~X2j7xy@k5Sl{;x9SOsXI z`zkQsabx4)cvfp9wJG=0QplLL6gkAmf)#M^Lk_VU1@ z8hEeHE8wstb7zgW&tk#kgJU@!f26$O*UL2*upQjPV%OeoW0R>sum^s+n>9u|ZO{2n z78~}bkGf&j`GQOAmtN*iFGg0y&sWg=@iu}Bd0E)P1MfSleEmJtx)-mAe}0UiaGVcQ zjd~Pw(jyGPl}vJoq{YNiLxIlAd(4`Z{d zTH*;7>fQk74Lrb!ZU$;Y&WslRDexu@6=C?6`VR0i!`%GRaXNo~Rk-!p#9Ty3sdN2m zc@7S*;u*a6+18Eh?2^?5-VNV&92Rjbkt|wpqG&P=0wX$7ta$x(k5{P#1Xj&jod>xZ-M%P$&D!=tms(&|rq$b%GEl z%`3^l62276nZR(Ev}y_^6uqYDRPaZ5U`LeuQN5vziug}NuZ3*VX(tH%{``8)vSGLBBVLW18lw7AW2;NN5mtkA&f|dLTpdvrfT z8D9-$-rsboqA}L{If!!j`8b0g->OruYK_2C?~E?){DQ87f__ zS%e<9IXXzQ%Zjjk#w_hdvM5Pb74cb>0H%3Gs?re~H9g~}R8Ew6NZKslLJK`8S*dnE zUgIk)U6d}%bmU;6t$JtqVT5I>4EqQS>(*OX zLk{BnMO^s1?r@*Cpa+VBw?NB*tJlX{^f!LQRu=?>xFTr2bG4c<6|}q3@`bE)(R!?*(qGez)pO&IRA~ z*`A;y#cWsv;vny~a`8Oz8o}Wkc%n)d4;i~e;(fgDJ}Q^@!9jJHgTz`+u+J{=jtuHw z3&zLt|9a6J0R$bH2RQ9U>yn)cm4<_}k|HJo)2_e)LHdK-Mu8<7%@>7OK*S0X7CUDK`_WUKRGfYGpy* z90u_v?hqKq;%bxPbTEN|p=&IRZc~iZ?O0-nZ%DcvNH4vXJlR{^AFQIjm6ur zWivSc;deAVgT1U1ZKA;Y#TPX`R*9@&4X5=c^MAWxg6KYD5tg`FD{?Gx-n=2%6Djp% zj~h{&KS6%ak|6Z`;0JscANqGXf6dyhkRYbeXzvJ`cJs&Tm-_P$xt#xn*T&{~{jYTT zFZa6aVU^gWcpvUdrI)gqpYJ==f9Ho>#q!)0LH+T+N!Nd(r}|mvqvUKhK-~E#&KnfV z7*NHnt5|8yBZ0$!+Qe5lx_^mSb!v$`CM`B^2<=6TW*sE0MJ6?>a)Sbok&Y%JcMQa1 z{g{4*i{0F>UE;l}rMVz4da3v8f43Rpm66;yp3TnGpYMt%J37!pTZWB zW~LmB1yLxKJhACri4?H%|3h7z+1R%D_r=Ji_U=|3kksdmKoQoibpJ@SW#{N>T z^{!EE&jcqR2yU2B9XNcx^d%fzGD@}K=i~OpLcblD(+*yzQZq*I~MO2n*W$)0-ynj4I2T= ze{d@CeLwg9Wy(dF;U-vY9ylz>(Q*GAkc|xEy>dRi_f3f~!r-L>z*-OwLIR@8f-Pq+P2& z1&qGO_`C@-8Mf)C=!(myV!KAj6QhWSG*7vK6#?zjm= z3?!8edLf?+I8LaKJ4zqX(}dFL-pGM8?kkOsgQ#{^Wt8O2Cd2Xy7xkZ5uth%=f7Wy$ z)S$J+J{34DKXRk&L#adLc~9P90WS!tthix*-B7MSIHufX+SmN92AH;cXFST`sKQ9H z)oOVQ`6=0>m>F0j)cPISTA?i+t}zIlHr;H|BsPLU0(ObLb6XU6OBqD4%6V&F_$(`b zMQr=P&|PgR8Qb2!Y1q7qao1dPMX2rTG^3NFmtPucoyYf7o7#P0^Xx%)b0atE44@N*6^hzb4csrMsnh;MFcfIQ6cpMANU^i@h$s zg@rmCc_!2CM@_-ZSw3OMan`BA9tJ8IzR+G{RW^H)bI>k6Vr zwx^QzG}A`7X()v*y85!Fi!QsA_$G=q4H((sGOAn_dHS5|uRlgG125TVpJu$5)8M7n z-004+3~+FC7=QO|I*En<WRiyid~jN?DD>1)W8Ksml!Ww)wb4Pr3k6KJJ!X2fpG_fg9y_x9e{F!{ zU@gZ+;EI7Y(g5b(6{{Dkm#ZP>f;v`3(kZNQF(M>w@nV0SDG<(GfL{5?H zBhOp%ydpdOgXtHaF3fQKf!=)b4oK4^lBa}lob~B za}hECLk@jz)wsDYMH8L~_;2x{W9=3zmpD)-q_*%v*TgH;M+@HxpDjN#-f!R9#G|DT z^Sh>NwQ98RHNKTJ=Q?_|g&(!?KU=az=U?=D1oI1cCr_MuCPes*^!+2Xm9K=7r-L&E zr9aHun#7QgYq`%&Jug%(xzHz~T93tsHL;kzYI4kf-R%1e8UN-F(60i*1CrIL+%S8v zKvH+1r=q22q_hhX0EPnOnr6D$*JJ$hY-LByr?0hx{gI#4UwXU|qD+zN zVeco_iF;z(H3e{>UAXl$^?M~mLVGD-LWfC?GD!N_=Kj83py?Zyr*%;3NDBIDn&}7o z`}zU$YHWd5lh0ag76a8^ME%a!a+SKQUp>?xkW+v9zg>TAzwG{p{@eBAIrTT^?;ifZ zeuBz1wji*&7h`nqkNvP6{J9N5yPA42Yw&!v@n7xZuY~$22}Bi`Y709TcS0eQNP9F$ zTMTqt-|rT7c^qHwL&W}=pWZ8aqll>vUMaKs9Kifvj{nAYI(9Av5N$vA6d-K|i1mM+ z-@ofNah@sB(}95pWD_BQm?HJo!bD62h^*`)6Qx7rCS>Zc_34Nn5s8h?<8Fg^-`JQV z1dO&H;|jdd*1z4K9O1qdhYI&s^2M9ek8QWk`!=AXvo@Y|SaIxHK4a=x%NiOS$M8@Qv|CSgrMlBCnj_n5RyppTGyy8GnUtFQ$ye2-m>2G09`iwo6I1sos`t~#@Kv z@`sH+X)MmLO?dy4*V|>6c38cE*}wK8_G8h*=%2L_PH511lG=S-e1x_tU%)rkYK{6Q z-|DHg_db3aUGIS5R81D{fv2Z)1Ygeei&lx#A{5Qra0cQMU!wQlC04ZSaY49BDHPV2 zi*P1PvvCgy^|-$+NaNVy_vj3MQCGl8V2WxYnXkJW=ciX|02WrDJxXjPV({~?iBAre z+>W@A$_bSB7TDFfeo=DPhDV~Hqp7=_>}7fn&r()TyfTTxbq(6|g4U_`_Jr1h{;SH+ zidGk(HJN`ub-Y6lO=HxK|AWy0nV;UHrnLJ4;3_cm%s_|C3hy_E7>0iKBOjT+@r%L^ z+V*j;>PrrpW!@vM=#v!9L8f+JZGCjZ6zfZBd3TJaQEOjz;NOOTf8o|N|N3m3wg7%! z>Z2X|{8a$#vngzd8BB~D8*^(rxaa(qi41Y$`1gyh=xG$qL3slxADq_{|B7q{p{Ha>V4E4+zDLur8S^S;9@kX;$;v&VdxxId zE4Frz_62)&jj zNA_X%k*R=&+;R65@qKEUe%JFGohVRUO>^Wi?K%z7_}d#w>zR|&N$wI%d08xP^1a!Y z&4^@Y`=b4f?JMkEzfLwb*+*hncgVtp3%1xTiVU;Z+kd@#&ojwm3?g7`pV*jhCjE8j z^a9SWYaPUPF0a$sT8D^xV13;FFCf~@`cvk^=ZKO}=#|zW)@oVh5@%PW^IJSlYn|(| zrm&6g5Wha$>Q*LD1JEO_3$&%1c9S zFTw|yd1gniPOajr#vj|h4^fx7ww>?u4l_;drB`1TYI~3$)E^j~8Le>El-Tw`p|%*0 zMKUlZ;wOjoxeA-dAf9>)-jXSVbhXeCOj|^UV$zM1Y71Luf%h^l6Z10z zA&|Rf0G-(^zB}O`*?gBu=U*`T?n*!3-kR3Ww|)i%d(zK$ReyP={*wQs{+vwx#+}ta zGIxG(rCLXn>A`|!hJSaphg=R{R0}yQm@|H+E|zi=t>;m9BJm5}@_ks_-L_!sw*O@O zu{8dc?4*8Z{v(jg9|LQibSj7z2_^yJP}816(HMQP||=!jBu$ z7k(6SMB1C)LjP9O$^LU?R-4~w4ny(Z@->^g{7@+IXfa7-&nstZ22;V^$p2dneij1( z=5y1ZKh5E$lXot|a_|dIcijKE_C=j`TK%{AYkH=B-OlQF+kfjun3z2F8vjsL+RgrZ zSNy$sUYfq^Klu;fUzDle{-4yJo~d8=pVS|ksUQAN>Tec*xm9}o-*-QL7@2iQv(v5g z-W>8*`Ssg-QGW;iG5&V_*X^W!X#UE~{Hk*CK?)7pAA#!paZGw9Jaewt+nfBT7zwq! zr^Bu4UAUFvpzFQ8ZgLY!TE)#0wQhZ=uGbf|c~cc|@u>r|Ocb{gN_Tv#B(=`gNDuT5 z5Bbu%ML+e=hsVx1IUi}2>0iq~dQ&HFU56%BQ1MuZngVX)c0g+TJ-+@9mvBc7Xf+M1bK8YTytAVvXW3oBSp^#PH?@0&GA)fA5cK@x64P3ayaBD{)G=&N=z5 zzUlqhHt4N+w8AXpu-OYSb#@f?UtJm|bI*L(X~mm-YNy2!h8fmjOea5u&PQY460S@7i` z>gmV+2BJ}A$z7Ipj|>m0#LTSHw3jISc&dy6mAdR>1=_8TBmW$;G5EaILZjAI%nkbr zI2jwJmCjTsRHVQg4vh9Y?Y6?93*%FH&Aa$l zus_@2=JYn0FE^CvPsXXsjL_DYqt-2eqMG`y9jkp$7CjylCkLJ%^C9>y63TT@3~6Mi z!q@oUV`FM=5t{b{oN|D)$>+VIOKb&*x~l461W<<$r^YdIY!e=OdU6{+Zd(O(9+&in0y8d*ka8YhA z@9CN(HUuNbnE;JB%Z?4vKKXS%@HN`hUO5Y_;qM@S?96K^;#$(|6p$&A-fMpWgRkc7 zDl$KIyFM?vKE1xStD%2)e>FW*zwSS&KQvQ6yp#H&`9H|ezsli&J4y&9GG_qCHNSV$ z#Jt+dl`=1A(T5+(NS$lz>-0ZL4C?{GL*>Lizc5mQao9ROaD?{D^C}k+_*6OURvt7R zK;+Ck6-Zx*yXbDkqU#W|E!)GcxQey;&p*Z_M*xs}RB<7XUgnXnCq=kSI5p0ZQTPwd zzcT|rfEhoT<QJi$`I^4Ea9@og)4%#tO@r{T&MLi>^<;)&Sq-jj{JAB&wtto8nhr^ zipH@29sw+`J?@$h)73F_r6d*rfE`BiVKl9G{vyMW-M;l8A4dG#FzL&O?OYbTTlw&2 z2EP?<{X0|q0jy|g97VG)Fvl8i;9x^hsMSJx5R>JIVB+6z(4s+|n+v=Vc&W@HH3tM; z$b6IM36*g&0Z*LwIfEk$Gs-fz1RW(T8dX70;WXZOm$mzc{PaTAomst@YcYs9JDYAW z383W1bo#(aA6TaA|SJA`^8L5eBcFQqHl)3t~=AG57KZpjk`Ss&=C4H zxxjni8Hs;%SY4Fl?Om#0I$EB%yBNhl9j3z~r54^!7oCd(GG*Dv&!x0= zrR#X6loQ0vPlxvikB{SV4G_&!PhR6ZOGP?Dy`oOFP&I9!M$K}+)2Ew{XY&H`&DMFh zy3xd_V;RoeI>&frrU3tqddU@EcAP-ARjG8^3-M>iuvTw=l^NQjQ`*hgdbmLC;}0WH zHrN9w0Oh!}aU8Gvaox)h-_d?!`KfP(uEt$r>ecwZ9+?i#0cNFMheyqL4 zA~OB?vH8!togdxw_q9LGo?nZ4QGcY*U&dP&0lc@jYCW82`(AX0BObMV%QaUb2w%8U z*4FWA_F3P4+f)5mcKttp$Lb%e`nOyCe%bYN^@jmD@NfRp?#I6?`^lol%=)LM{_XWI zQ@`#%sXsJRKm4E6-+WCP{`K$v2kQB$quiIJup&9;>U6UA;wzWthXEixc zwKfIvru(N`KmWk=_uDA{1?uBnYlDj{em$P%l7%^|890#-z(_^ zj=~d8ooew}=D(5@)8PzvAcdt#F$(egFl9gjrcLi>?=btrIV-Qj1Y`Wc9qfUU!;ZUZ z8dvU&?8-e+WAfqR05<`klP^o3Zx|{_2|qf_Bxupxf4cl-$)b(dYHKBb9HIg8^~J{KD4%DSrRfRK27y0@!vAa~1U!_4i#OPq~Gdw|lF9 zjoNHxZFSEgjMAezRnp)P>CyE4*>AfQkBTZn6IFf~I7RSZ&FKMYSxlt$Yq7H*G_W~0 zK6Fic+0l*zy#vg5xu(cj3m z-bsz_ZG$$kyMZ&AAE8nt;p`jUP=IxcB%sXXCKZQnIin5A>Hd50Yrbynv31SH0k%pT zX?U*V0L?WC5_8~~#5bxt!=Dh|WT((UlKPrNBZFTj_fs-|KMkq6NtBZUR=GZOo2Ib( zuHyCgzb63wBr5erPVe}oFodo4HaQdmamzKDRM;%VHkB`^MqMWdl?uH1=1t1k}H zf+F$a>t{tq5csqv^66{ZF-KN@c3NaOhm;2Ho9Y9r(EEs>_uBYc!VSG&{50*)DpZfo zpVgNxviw<$-(koCLWIzUH1WOraSwZU^QT=SEb!iY)A4M9_>+Bd7C(0XYWbys%du#` z{4|S}fPb?uc0{L%OBLK2NpSdlGnx6;rtXEA6-v2GXid6&_q*m_>>=NUdG~HI<{f3s zt4_qcL4dR4-||S(8COhyr@TWi#EAr498vgf2Yu%?;coO9x#S_Je#PTrRZ?UMFnHMj zG+ut9M7pKmuWnQ>4z_3__ebg(^sX>H^ci!_EkMo zM)M#0jvI;%ACMNRO{E_4Mn2(YK%HA2Gy`tBQZs;!fux>hz(b`il-CV41>QV!g1IMI z^S}zmi$k~lNG!6mx$uH)LgcT=g2tZ?KU|WY4xe9_W@-tGWgM%|#ywqyl>Q|874g%< zj9WVz;_a>?74BN^&?_7tEwC3sEo`5?%7T7bTEr+iPzja67Tm) zBsr0jDqDpEZg|;n(?qv)@{^cNd*?N^05WFhuh*%yuPJ92*3Ci=bNU5O70 z8>8+Ywp3;hagDOr#$m}nUjVz+d(ZyZv0GV&-S)9guxq&E3c`P?(}-K(?MuVK3*Urg z@7M7j{pWIlXUQQPq1@#poL?=8FqhmjOrXET1*BF4PTCMwSCE=ZD_$M`Y41$_I5Fz; z$Lp$rR84K*q~_rTWCI*-=s#jYa8LAtvrSr1+~b*amPVd=43-` z%>DwN`?Qf`aIs(LoikljU*5ldb`o^E| z?6mcGc3?e5`^9wtt7xAJpSDqYX;`?G@ zo!xgFdLRgW^_wQy+b?skX7+Yy-=dyY^=7Y0(Wg)uDUJN-9IhTv3QbFKuzFAWMaosA zPSg;5HYE?$luXx<@HYO+Rabtl(mksym)*y}?!Hot7N{%lSZSxOZ2N`-lZmJFQ#yp` zwLZ3ky0U(T<^ZI~QdioYzVgb4YP)BB<@%k;XygCXN1A`h{Ad7!FQxm@KaAGQ-lJaq zI;CYY{p3n%hpp6)Y!+Kg8d_j#HA;#17ITsFC;BVo6?o;Z3QA42@1-sHS^D!8tSA3d z{rT~SVCDtHYNJ1o(fyh?2AZOn$?4Jub>q)}OP7A(Zie*t z%SD=iIX7o9=X3)wSC@Wo@ea&+{3T+}o^=RkJg}XdY=}S+2>3y5-FWEpm;WItfRI8nPMxO6r zlfsUDTUWGyZL+ElNA-Lc$!ClOGq!e!B{g*Kr=~ObwmJ}mE!;DqJ9UmeH2?4XRR+V7 z8X%dN=+{?}l}~iwn4NkbgGuxOF7vZ67)4PqqO#6=Gv7I1`msBnuM->YxP}WouA_%? zq~oZI#Q1wEqhxt!5js-27s1bDzbD1_mZDS}AIO&H`aY=&4Y6|N>`9Rk>}sBki~u(r z0?{sV8@tG7+5PORfcS$WE8pseKBx6_=uCh57;FyP!pz6YP->X*nweqVwfb{4e;i{Q z)kVN!k+MWYE%Sb|A)5(A4meJ4HEf$70b8U$jX#6@d$a|ny)|d5841hS%CPOu)_6;^ zp3xhux5n46vR;(C7w$mFSM;Jgn-=Ck*g4O|=LYAKg86YF>PUgFe^q{|plPzf70efS zP$sbT;0XPD^z}AlEJnBt4+w2&T2+3jxQR1yQ%d+&(nPoxS2|UmS+=w3(ZLdHC=0i&eC0_L3CZ} z1fc`fbsd1LW(612uUr*bUn9hZFP>|0s0{$AdY7>Yx=; zwNH;?r+Vs=(z7SDz8k%QR{Jzvs`Xe%!2}Gc12hKh`MCG{krt=EZJ5;YrtYWf$3tz8 zU?b6h)rafU_0!qkeFlIA`u``PJNr|gi)NYhuCGbRqWLpvr#9K|DIr7jJS*An*-6Q& zO|{7%*;OqQLg8}G%rFo`t4QEsCTC_(tsPACyjpeDXDU>L=6#7o&TBTtHN62EDFrF**Cddl=rAM_B+Ek^Hf`E@Hr88t5f}dh|0QRknFl7R+W4Bz(|lGrp)}x?Xla^RqNT7*SZqB=%qgxO zWX#zlR+@z%c&(=L!&~?YdoXUZgHFzM|KdB-32@xiFCO%M87QYCE+CdorK zNu1#=;LL!AzKn)&0yQAqcE4}x3}%T z*p?*oKfLV>1Y>a1>Kz6F`#Ze^_FWG*BWpLQ8(3URnsNzPw`5J&qUZj&QV*eur#aGF zh_BYWM}O|rpE!Slm+h;(8}+P-KVaizc*U6VdU2g&%In2;SxiY8$CN4)Hm1D3n3-AA zwXOzb@6JyFgqx5<^M&EsWa(32{2f8&@nUxvH*{~L;91F27EMl`vYq^A=NP&#l<#2kyF{VeS9H@b zrFECfT|@jUffdqUM?asfId#)HrPPxOO6A#nR;7OYNuXB+3aIoeofmW_xKjtD^{aNM zBL{`4J|fpaysJ$f1i21EemrWc9pqxNI+oC6^;zOtpCxR5AbS2#AexX}NEBz+)hJ{A zlB^Eg#2dISHs;JPL(S-oqGX4a#*lBHaz~O+u2tmQtXcD{E*?(iFXxF=PBU6*1@?Ym zHxm0DKo%PT%doY_OtSXC$xKZX1BvR5Swqq)-J=W&xKnc1NlO#FPFl_?mSnFQ zH(`&5q4^?%JPfUGq&#D4Q8 z7o-U`0}JiH^`6B6E8GY4pAa?qUgq-UHD+-JS?e(mG_) zLTiD)wAy|VX%XyS4QG=jc9MbAD41*t(KK{Ctv_kW@wJ;Yf4FWW<;~YQlw|%bJV^_U zhc$(+(u-?}I;^^xfq#4py=_{8-saTbO2Ao4e+$6;WVv`U zDR-g2@$Yf0V7}r+YayQ+pWt3JKGEjp z#q3iuobGKU6W6P+F*&!bFIuZ^HbMl}%U^5diS@`4`TevkxRfr~F2)?IZlx3zx26o$ zz$g(cS?{H+XS5dL2QbSiWMGyPNzc|hh=L-Nq&T@9M20pMoe$Te3SjO3+y1M$uH*er zmHwmG+S;vvR|vU7`fdyQ+1cgj#mS`noEqtW5T8wo%J&>y97#w`n6)yw~&LUz^Z0TzL zd>)#XJQnFIySPKe$u47$E6|*#g&yIkgYH>E9>&?kh}`ky*Dvphl^hRqR`zLkeuK8^ zIV@}@g|csj)(%U?b0V=oSy2<)G>3RXH!wx5@OM~SH6Pz&QS_d&s^NrRRB!P&t;Mof z5Noll73O2D2dib3B^d8j$Am**av4ci0R<)PuN0JOe2adInk@a6cS^r?8+Eo-jpJLP zgEFJkszcC+=R_NA2r|u<6wz0raLR?>KWRWfkZ6^GQsNgmYU?MiK;s44+By81m!Z@m*WcYTWjPm?8t88&)JpogFgIF+U-7$jb`dTzje#l2;d1j%2HfG9Km1n*L(-H zq9le2bU6_pY{7vP7!On*+_3%#qXn(zK@Gx$KDEybc*#ka1=K_!jtZFw{FyG~2h~E` z!HOQ^h->KU@HeGsYelyUU6~C3`yWufL==(XuR&5Q3{!Qx2@hy@R=;cm6C4_gB zsU$(7RRF~IVjOe?J=SQmFhtI{=>Z53;eaJ%1&k#x1UgutFIKWDoQyck#Y;5aF1yll zAcF)0x)Qx}W1;tdFj%zEa%mj>#9y)piA)_A*vrLVna?G#%(Bh|M$I2Boa(0;FqD=y zpWL@LyAt1-jV|HH&*sH*Bn-D^e=VNpXb}c{{NeJ`m=7(Uk<-j9A>u|9@#vMhd8Px=l&34*5ZW2g^QE*{EK6N zbo@!ozGu*4JW4kOWq-U=P2gCdqLT#wHj*Kb)?yceaRbMD_)pmk zl8fsTe=s+3k-bK4ZM&NK)d7EpIpwb%8YKZ|rR+!~(|*Zj`GjwzYxpgogAv(9PVlR~MlEnJ-%1sT{looXdi82> zkM5jA!-3&^6(e-W1toNNA(u<4fvI7eJM;}W;ZPt_tw0R6#o_fmaAP3`fo3Xex~l~> zs$Aibp7ujZKnyEIK#3sv94)(H+~x>Vz3;o1mOQKXRA|J=A_};&`-=t+OCGiA5)YN* z#|S>H1yqgj55A%QtNue!S!vM87@!MJ3FXRh#kNg=5^KPp?c@xC_;dUMv4$+SANZlVDfhLR=g8YLS;%h4rMu~9EbBW;VDE&)AEh%9pX3kB0Yak z&#;4X_hA?N?%iJ2-5E{9nL3}ymA_|6C)dzD;&s}^ZYO`PqCDuOot^Eq#$J0SKGDf} zJnp1WU#jDK1EY2h7ft0ntg30Y%Mk(zsi35|e__EZcBH82$o7!e6A0T|>YmlLC?fE)fhR2#GNc5qQLE*;?_Gw-nu@lLoterk|e zf{pH1^TYURiTWP#DY+XqA!Sy553NLwnzyRW(q@;l{;$z5G>8 zThqFNhohkc+bEVk$Y2VpCB--c_{5RJS3N*08L@l ze42o5Ypvfl%IzKj4BEu7<_GXK;oGT-uh_O8AVMm7UIgRnxO9YZm4D&kjxq0)HkcP2 zO#WS?_;*E2zd0%htC9m&s1I{pO?@^Gf62EQ@>eM&ksHWCR6V|vU4Ua+ zsbgU4Ib=ENDuAw`bSQjD+ebU9mqfAc1Xd}{)KL6>_VlF}wMHBx7@<_OjXfFUkqf@{ zH^oqBPmu^d;uae2L$-#?&Y;gH)o_9H?m~c`_*fP^L}JOLP|;s#uY~D_kp%xo2)w}^ zf*Fouy7c6hm&RO~&-!BkK@bE>CfS`T*3@BooR5J2uf z9B!$JzJ2*+`#lu8o^wC&qU(dFO69}3k{OE*_DH1TV%kBp5w_zuw2XT9V z+KSb~{-^uC3Hoq(TYy_&D)<3Rrli4Q&NKx3$9f^~7g+EkGb&GGWN(YnTWlc>mZN-W z77m6*N|X&cx>axP%Ev&Eoh_Un2i^;E3K`6!f3QG}{4t6oss9YCe&)IKouX|>G9TXe zHS0hQBlF<8Xa#?ZR90Dt{G&XJ)CNzVZg-#^jDd%@2n3qK$aRyKqmhkG%_47Ze99YIFYj5R!J zOghEXd02iNkUh`fS>Z+|qH(j0R-?*1HL)j=Rq^m4UAGRF!TDyWq)QA?8-C<8BTG@o z3E%DLrojKBD18Asj!VNaR!k;R4*;>J?(QSPE2QvW`DqL~;=kfvCzjjZzt_jAKi&NJ zga2B5C$-GM{v-SQ_Rn`H>u-NghWk@|6=u^qo9p*F=xX0e|At2U7aSZEA=+~-{?riu zLzn*7kugsVq(|*4;s1W#uBq+6t?Q?N&QVPaWfRD6oml@B-?DxO{t%+0#;uLN=6me! zw|hQDEBwV*VLltJpk4gM+V2^Ue9*5V`gsT2uX{hP3+AQK3fgUdaFl*g(QXD_k!lhp zIQZMikxJrhYMXkN{ITgqwshH>aDw zyVLGQ9I0e{U24%ki=y?1OiLK*_aG)+3fK&5+TO2+Fu#~Lz9GUY3&JY-_Bdf>HrOr5 zOcZ%o+L8LFTJ_8Rm3W3O;G}5m;p(ypzmj<1F6Kilz|R&VL8q>`mTQ#Of;`J|EKN9^7`XNZ-;7>n}+{J0kQTEj3AahAiS%C97Z?SpNtiR13 zVln-&6@PK15B}QDkJ{otS_<&~k?4Er-QIKN2p#(?&^Y-_}o^?PJL1h<(?BBoUC9zHe^$orRg0k}4a&G5`Oe zjYb`hIs{*b)>nXb|94tn9ly10;APi3O^vYDVlmXA^;J%6WuiLSA^he7^poOuT00U`7@`WPa!zz!yEMF2n3x!nsb;kx0G|=0E4DcQ}t-maMRttm!ZI zCFVQCI)CuL_DUDu=bwP2Ono5OUdQI%)ON?hKTb51hfhSPF=yD&M1GgpeANEnSf9K2tzA^$ z8`8%7D)U=#3MSc|Vm!cn--^qWeelrQ1Y|hvFUo9C0QuDR1S{>w&bN{N%OF7eFs;!( z7@PvS?bMBC-T2IH>=0EK#0=)YDgAnp3qY6dTMTQ4jS65c-^|6cGPpC6ou3#v6P*9V&o zq%Ho2^VRJ0KVj?SKzk8qD#OlM*wV~;>=nK_4>d`ML8LB*AFe2aU6H!wcAh4i_@BTx zR(cWm2r2*%{{%~6GLqa)K1K&$i7XGbE~J1oEJ-6v)Ot03W+s1X4eD=T=sjzkY$axg zRtz2fO*`^$lm#DTJ2Tz^J^;xidl+A^d|sKJ2%PyKVn~%FZWk``Z;Ut@SXkdwB*Nsx zVjJ}BdX89pWq|?v+3IhmZwC8k%GsG~;p7CDjRjPZ_s|gQ*H*c0*Jt3P0@LUZL;?|c z7&2$~<5?h7<%2!XuHW63l;1+0l| zq2SXDoMi+Z0JeRj-xd}Q$WejsS6T7F;dSl09%Y!T@%Qv8QT?(29njE$&4Vy@kgjn= zpXg}pcdS>e^Iur^?EIV7y)_!wy$G};+XP4Bwk(XsH?MY##zY=GwNC=}&layy0`|)s z0L*s)Ff9rI#y?uLN8_iwuPuGQex6 z$3VDqtAz}+VcJQt(8~z|&O!1@{$+Du+hDAo^FvMY#fQT6m zAf`EhxYPl}hCvQQykH|@)0C4UqVbdj5IVOF!kax~c-U**6Av4$d*b0j2M9?v9?Xjs z2<>6Pp9n%g{5A<#@Hs#zb$~F{0m2glV_3NNc^eB)U3pS0eBRT61^8$w9vJ`8Ebf;C zI6mqTLxpMG6BRF8_e4dG1CEw$7E74tC^*_f#SKn4lLX__P=* z?)is}ibp4(6czvO;Xs7~;Y;zdBw(Sl1B4U@2p@D;*dZ3qbb!z)iiKf3=8*f zvaztjeNrscb^#Vz$%j|P50ij~KqeNWeym75ja|}b9?SXb6n@% zDBzrYoqOaB6qa=^=BH*qPHwy8v-TYDjE}JP53YrQNDOT&K9U^**dMYJ0Mkw4#owfw zO*#A-8l1P)IyQ&)%YpB}RRU|27l*iI(Zp1vhtx4Ha1g|fE6d!jw)SD0752ufb3kzx zP797SNzwD)S^$F{wv@m^F3tiybn$}mx{9AD;*>4##^c1H?x`S?59b72V4ea0kQ`Ud zGs;u!R^_Z30KgqCA(%_??Pd74jFl|QgllOo z+#`$NtSL-qKD1z0cm9qA*suksD^lUYXM;TKcAuBK0NS6%#C7;IfnGYC3%`-0!$t$~ zqFQws`;i729;+glMhe_UVfuv7$Vyje%T0$(AeJ)(evLfLx9j_ z?of|)h1#=6lIHgq7c6=$b+j?{wbV!h@6&mo9(hR^0ePB@`LNH_Gx$2T`R)U7d5zd@ z%@GTT4n#nOC%3gjgqsjE5niG~e9HPpS(vBkX&d@**HNIUx3>BUyyBLpQatAlxpMvu z^&C{wH>o8Xhus=48nwf?(}f?xI}^;PQPy^qy@AYDmZY~<5$C4n6Mkiz3qqbx-FDtw1qN0Y#U|RzmkBm8^)n8w->ZVSqeKn zr$!;IKU`MvNMjo(McUSuDe}D&Z7pNb)c7t6ZLHyYqpb#v1ovNXLarXH$kR41NYRbG z=A#2pbqukCPyJe)$C>hH)Bya!zOG-ihnUNQ+gu*Zik+OCJn z(swZZeo}i}pMcOUD4l>%K1@U?;3rP!wvE$U#^{KD-aM)`Qggm0QsEH2fc>X`Dju(F ztD|^5{9o2}kpr&-(W*HoH6E#~@_Qil@t$oU74+^nQtxUDseG7-)RS=O<)hKJ8%DN9 z=$p+^F8z2_YizQSj$-pBsmO`VR|?T$W~X>;vdZs)&Eg(yU^DgGV6(I>Z1Q2-*ldSC zKPw=A4jj=Mookw${JE~WHAdM`M=?55>T+VV0G3i{(5n*&#w%<@dnm zU*Wn+z-Gp`!Dd!l*yO{uvDprPPQHx%S&`Qoo#rtoe>SgdjZrq#QHJE+(U5N^zJ>ysM9y6pB)E=*<@?nZQnC=Nq&hP}M zV=eNcCwRu38c+Vg1r^*vy&eVJ#t}(g+F+}zpNvFj2MlkG;Z#TK;KN)(_XN)_B=Ovh5?qIIs&MgPHMjHSv@sr(A2w4kPn728}u z!3gvxzK+K_8zR;#<*%jEBb5L@vjMOaT}I2xx=y0yWnEW>HB7o5oR@CAspp^2R@EU% zAt1q*$$Dty3x$TSG2QrzN3P`0%UX)#wB{iOup$HJgRMhJIa4h-0Q~nwOAD5Rv#}g3 zDOj^48{u&{AxD%Q91QlfT4w~yirF7x#2p-+&M-M-KT_u-VN-TK{w>1Z?p}+yOs+>M zkm^dT8E24A?%sdoe<<7szb(2Z@ixfQx(ApK!D7N1$fMfE zD^uni+nSYBh$t%Kgz*}-{Xwr+!{5A=%1>08R~+&r;&tqrW}qfAh{YTosd5JlR>YuS zsde4nSl!eQn~!!B(8=jeK!Z~S=h zK^Nx3wwHHpt%!qpVBQTEv}WG3K94eQ{?a(+#js%ukl?n&wU-mI74iF@@oVSO4#7uB z=5LNefLPz#AAheEG3-9KS;=1(WY{CziMg7{G6;qu#(@^CK}2W~IAJO`*HoeldT>yk zIpR~C)w98uT~KIjDKrigB4H^aMJ?vSkeM1p$}w1Dip&Nfye00Ks8S6j`R=&=h4D7e zxQAs(!G-)HpJ{6s!TOApreNFVB5bR*nU#C*OPTVLr#maE!-!L8>~b3oJR$Bj8LG@s z5_*Z?!e&+K4)%DJG1W*YgyRJZu)p;a^54@U@{FyK$I0e}?535EVz)URCD2l_H4x!& zP^AS=doUz@0MCBt4xUm3)^|rbk2Us#zsDlj`C?3382m35Hkh9Ltz{lhuou>Em9Q_p z2m8_$!C6~V#~4LhQzI|)KArdJkuBH{UX)!Z=U4PW18AoQ{uujVvMR!1pf(cB#mkV} zz|Tu5FTcd4$ao9Kdgrm(LgR~uPh9z*L+S$sXc?xL4OYuzgR?$QEi{TgPmR37dlWAE zJUvp2j&>v5uyqcL`~Zmsb`9GD^U|BfPHbql+buHo5`VCsUE&T-#HR-vB3Rm#T>uOq zjR>u0@4~*p{!KlQdWBJRAT_d^_vyS(kGwD@l$r!OHANmWH)4dCPx0~>ULND+L0l*w z*73(3yxhXeT3%N3vJw|Jm||a{(FmGH$&JaO5?wXkwx?)efCwJBgA?-Hp~=W@(x9zm zMlf;&lrzPWMQe((MVg83(kA@IXok-so0`87_~ zoHC8A;Tu3ByqpCbN_-C_x8y40YY3!0z-3E#EDG7*c!KH135*XhM!sF$Vw0`8;Zx$* zmETl0R>+1aT`>$u)kLy2DY7+@Y)v2=rS0f5j)ngXbE0vSLuFTyu_H<_bMg{k&5a9G zk~ap9g=R8%VrQJ%x~Q{ltfYxK!!&+EVP>cL3eSkNXM1OWnIk{baCFhKzpn>!RsLk; z7OFZ9=?i|+s@|d)hK1}2yex zSz+9v8<~u#*HWZK>9v&F#!}>FTWo6?Q06@OZ!ajLCA$<7K@`ELW%~UKAU-pG#E!{p z8Z9e7ii+qv7CJ>VB$gKxnaY7&T!de&;UAmpEhbwo23yV$zIC;1a|h4y`UXZjxpJ*kK8DcHm-On7EuL&J`+TN&l3hlfZVr@U*3wRM;6`ra zrM@fMctzip)Wi;EtV4eMeP#2(S6G?cin+|!&A>b}CN!vPq&x0Xc^BB7j7>m{|nC|@TW#_0WDn$Zz7RF2^U%~}tyPt4A2tY^d`Slpg=4@QrV=D;y zEc3zX?eYz(xAK6?1`+V~!iZA4IbWz-1tVdWdzOjz+1X*IS#S%Q9s~w&I570kXi)^*<&rwY6 zYzXW5ua@OwXdsuTp~MvZbNe9Q-20S&ZeKd@;h!UGSOd+@YHLn}Gud?Ea#Ge#yt%fD#R$PaP@=zG}!)f0D-SyBeq5{srzdSF&l5bA_or49_Ccu@DeHre!^?XiQ zr`G&nDY$*X&&~yZQFaMV|8Bk7udsN!l|km3b0P57oE^u~jsJ?W^eLrImgWMSOC@ci z1tGHaD~7`^9|0w1n<0Br;UmQMWE@-X-!4r|vKjo%b1Vkm1^e(vG5)q26dt#0Yrl1{ z`$?AkA_eRve>Nx&md80fw~ja5b(!OhC3RVWQD48uuJ@W4oLZM*_WBJwKhR@LNgr>_ zs>AZO2pQmWS7lboPx1dC+5uQHz;aMoxQh>x zT%BO=e2N`?7JB8qw(%&G-@5cUP*~4kqrTpD`zikOgBRv6NcDFeAL?7TJtaLd76nrL znSl|AKkB`r0w<|tB-wAfMt+F5ss1zY);}mvk=oVYKTwh0-Jh|d0t*-v?4qjaHYU^q zq}pQa7PmE75@X=c^X$PX$|yB-xYx1AdJeZ1njcTGn4dcUFh@w;%!)qjZ1p~ z$oQOWjn85otMy=Mx;y9vb&4~QW~8vR7dXFfHlsw+IXrPdLuhc#v0h2f;5=;PKTP|X zzgJS>Gg!MOnLo})f~UZ?Vr%oGtRH9E5Vf8ELq>9&JJ%G10^fKGz6^auc?lXySq?P= za}ZIGV@}5t3Xm-JImi617<`zA1fqKEb)v`L(bOl&e6s0XORgzBzV=Edt|GVFD2e;4 z_J{loJ-1-U(*xz@Nm}(gY&B3mH_4xl$e6iAP34GQ{>d;4c|qV7e=6>D#PrO?a#{qN zu1&@ck9P+?AXqw-Si#f=JH|W6kYq(?Le;gCl z+|Hz;APLUR-C{K?4KNo#e&dq8C_`d-k^kUcbNaZqTg<7rs7Xf=CwsD!IAI<;5l0vM zhoaA~Y|$OJ$C3P3wab4#h)~X4V~CsBJsKF_Yd+Hdkad1d)gi6=V$y@+Kwv^pNo5oE zg6k{Z0hYFh$XLt0Rd061z|kNTJ?Q=T-nq|tL6&2oibz}%LX|>+T#AD z(}wL5|1V}Ej#DqfjKDZeE&j7`r*qxhSr2(rB3-}>^}0H^MAwbo;hWiz_BR-a=IQ#- z&-G;7$+phjk%g5_o$y(3N^a!F(EKk@e?jGm2K;sed0v^~3sV`O#{`-eGmAj09mdzt84 zvNaASeXbk1v`VSX;`?ue*0GnDS8<_8%OW3=o9Y1P0AVK95E=7=|P3Ngkb^Oro8q4uyexlNsxPe)wyp`<#`M5D zCyZwEG1OMI#s6cDjNAQ1ADeF)5&ky#`pO)(X1;YRGm-XSjWf)@h|vttFiLH$!(^_8F#z??<`>`FF=;%lJ)yjJMn#d59D zUzbeu(}=8azZq=X0-2}COejf1N#O*Y46}eF1<7w%Faeq&M67Kn`TL!PNv3xId5~*V zV|->{)Rz5Jo->#szJ};9%N2CjH<}Mi`GMG6 zi?Xxuz=sn&iMC<|rBUPAUb^s-f=i7qA-?0Bb3ub1|Sw=Rp4ZxJ-cQM`SMc5POgr$rCKjbp;pY;>?~Ap5WXZPjFF=C;#0A zm(!q?%eg3rr|@`f6GQ{zm%r#dR^rzVoyu;p1SpkDu>j04J;#__ zplzI*?VDpvPT2%RV}uFTP%93JKvI7nlSC|o@PBju62OH@eo~6Wd53(1RD(txrj#kQ zl$QuMl9myNsFOG;Zgvz1Y2n|2ErZDbOW@)a+|EkF(ec=+DqL;!*f9$1+Fp*BR)RHUFY!%sgzaDb1zrOGzXf_}bjrCHyl2`Kwt;uHI5edm`!(dW`H1*T#BcOwK_!sQ*+P$G{G3%d*yN zM6CJfSO-qS&zx)qBYw-Sve#!J{e>0BQ^Ltf3ws00pfKv6@Iec8wn!FQ!J-V$d!QHT z=5^{tI&jwm4yQ?VxXH@j>VFF>Z@XkV><@qiT}(ge`i!zQj=pQ0^o4zu^nGG4aWSeD zeK*6K6Ql3hX^OsShZ5*Zb9qMzd^QMtFx7?igEVQXfC&tQ}0TzMDQC}R3 zqXRl1{(Ezv?2iBf_-%&xIPJ9$|0@1YM#O~G|6;nSxng6`kFpMtdkT`Ysz>nD1IOE7 z2+zy?r@C6|ctXpuL$2E9%PBQI$p-?TXHkxoB2%PqG0s`?4BhL_Kd7y|2a9SEhMTfb z2`m8HTE-=*)!{vlqk}sN($AC^{d&#njS(V40z%A-c_?oW@UGO^xsjgcIoBwGHy2n( zfef6g73x_XA>Mb`BR$%OU~vYI->9xc`uj(!*ilsj0GJ}Ef+aARTR$m~jOWhv zK6xsqA}luNK)wxe2j^zhc&b0vs-DK@p5Rgpl3+at$uiDY1)TFBt@SMP4mg!OoNu5$ zgwm2yT;$?rpNs*zGoa~YfGTrx!4V8Mh~0A+f#V6xmV$}NKtZ%>;9HOMwGfns(p z&w>@z;mMSrJl|qz0WV%&N+PoW%z|WBlKItLYLJyvh<;}P=pIsLKlY<=%{2%@@#rpN zsdrAHaaD?I$Jh)`kNBG@e?wORVKZJM!iEBS>8_wZ%Y1x>$P?^N2Mf zF|u-9##MOn^DI|r3Vhrp2+Dt5TXin#gWi*l{ZCR|=EUIagE*q@ZOA{==P}MjUHA+K zzye1TjT;X(3IX8%I`k3aOO#K)@^~+;dOJY0o&9q}e_D!Ib1RI6y87COqy!Y8&0H3m z`DmP{;D)RZ*UMin`CyxZeIfr%ZDlo|QJb-udt0;3-1j`Hn7c2Fg!<*|p}{b2{J+|I z!2M8sONj$+`M=`^oKn+)G_kZOt;BpB1H*iTm-}%+d?Ih};4Q~OCgf%oB|Ly%LM_V2 zA%L!0S|5~SbJt~Rc7s=xg)uqF;ucdm3uCSU6H-M4cY15W>zdlJJSi!xie)g`mxVo5T>~V8^v};28jg3 zBHdQRxL&v4vV%Y@Rd|7U3M#^!iG!b!E@c+<74Ei^BJvuqK>z%`OMwu+4fe2FF|WWP z11preHXE~-wdVb!EG>YQXM}s>Bh_c;RrP-)Sjg%>rbrlxtaS|Lzk&Zz3kM1k0FOj= zSn1(h`CY_Bcc8lt@-(k<{>OU$0d4h%!h1OM!9d}myY->3xr|2FvHg1OJDqs4ru&Rq zJ-H6Lr&i4~labUP7(L{>0a(FUe04X+;>GMP=ue$0=*=<@z#-%^pkc!57D^lQH9Ras z_9~$Tprn+P*QuTU0o zVxGrvJuz#6Y|r;5jIcM}fpNw%ppI^KjTWJPbO>WXSU26w9cdvv{76*gQuzHv48PtE z;gKr<5~4&-(D)`~`tmK5$&jJiA1pf9sO0-V)+A%38ZkstBMTr34U#&yMypo&uoWGC zrRXrOj&wjFxIsw=pc!fK&>~Cmkk*AGMf`$RN$HOPr)gHt%QT zT40-3M$q$pEK+o*p+b?OMD){WDbrgVCB?&++N7w6lETUM(R)RoTVnJnsLX?*VzGsP zuO8TvW8PUp9LmCc24vEBtnAL(MHJCD-qhZ=_Oh<+7kBr3rS^k zs)&Mi%QLd#L?lb-;yuTTsQ+$GCzxAw<5hAGI12-g5*gg#<98f-weO^WB>3F?i_8pA z3n+}etyaUI?f}Ss*hP`eIfB&e<8n}cvv_gvM20vqI1v~WM4**)^N{Qxz+HH9TaMxDraWzA)l9lbVYOU(QIdh}l)(xs{hR3lkw^2Yr)qaM1 zlDi}_0%FUBHq4iAW&_sohLl`UC#UMIX4TIr%7UX{%>`hx3^WG&)o4+DzzOKvwcFV@ z@#C64_-oJ|4>d&ewZsi86M~CtBG~lW32{x-sIGaDJEZe#wVTF)O~?e^iNPMAJ5o^= z<_%M7C|u@8r^~7 zfihx4+ATID#28VP$F~UZa~pd+Ll3%*cl4nRdhNTI6q_(9?s0`?^@H}6_7_x#G@fpw z#T;D+yFThGP*U4Udk8SNCVOa`3?(9>oQ5T29(ZaJ&sE27;mRrL;4C0cDQPg-lyaVh zsb12C(%^I5-;}{;aT*OiGBK#ait$IY1^OQa&k@A#;Y&o^W+C`1%WWJmSE4=Pm?=hH_G?}%8H)dog z{&@05;SYLE%GVIPkj))Ki?)L8_kA4hjsGo~TNoma`xi4g3F z<}WguJjQDtBkVE$>EZ;eUb3H%jI%k6@6D!kp@dj_qO+0^#ayY5)^2(p6xLSV2Zd^4 zuVh{(qJR{lOGXHZ+WM+K}FPyUNq)dy)()sk$S)jI{j*!5cV z?Su#V@v1!#!w6T*PKMxoi~cjL&X|Z`ZFVu*QHu&k!ihgDhjhtLCi`GB0Xu_%TFjH5 zS-eQwh(_oIp!)h6DZ&nM=#k!mQOmY)$Y5{I)V+=7trMc+4-$KCWB5YA={Ei>Nkj;N zm-PdAPY_rrd^Lm*_9m@r8=e5m7$fJgMy)EyBEV~geDa(Ep0nbQq!HWDaOY<_itRNQ z?ohL$6FRQ)N82>9yT@TMH`+%52qchJKs^N*IL#fjphmzH5nD?TfmDEGu13yjVoBh!Cea$y(_xs}fW_KI&nk%-f>pRZr4uXYuZXL zTSp!2iJo7lt>&IEm$B0|wBBVLcMWZj0gncd@L-QUjMPDqvhFbN_!8{`e3KQRA_ek{ ztQxvew5lpR#*R;nj~)cvhd?~*Fj{<5KpX_eXPLbKqo7uda221Z_0!C4YHY+;9XrdG zpF9)&Tsn#$;TIa=1-7PJOk83CIuYr_z5w}iSrr5>zvH>X zH+w`9L$WhQwH{A7)N`fOZ8Fp~9R39H6j+LlhZBQ?YR76D&Q<$Q3M;=(@uy)jkH9PN zb#HhDxWmy0?9T)d1{PM1Nbz^VYsMp?*vFAyQ^e<>HfS)|Lt@UXCVQ?Gw35zjmRKW@ zmLE{T6cx*=y9zKjO0qK9J5s2^^DFT?>Hr>F1@m+bx`eRca{yr{e|J5wI2S9jPqCaE zYkXQ5cqJLn)3AF64+<+=I%`$0tGizQ8PLRacm54tKNjLp7PM7m*xatv^Is(a3rmym z1?qGKma@)uQs>u&f!C6?(<{*`U!&@PRQNTj#>plv5h4UT)%@Vky6{%9``?>g0$9N<1%hpmkw2!M99R9^^gOtvw^1D#i z0jfRO0%1#M2s%FKf?hyXDjy#lgsd$eYPZ*#uXiWxJqf!XVg+ZMlbP6~aIwf^#}kp* zozN{yg%9Hh))rU(QEl~V)a=QBNn5>$H$zR`IOZPu>G;r~Fr={(#ocLrgIGNR;>P3> zM6pQX0G=vIymBKzfqevyhN7qA?e;O3z) z7A?)4Q=Az{d&4rcCoqd0&W=BH< zlzM+R)C2p0&Y>78hS)f$RWm@7X^aAYL-kleO$?^iQeaFW^KtMeX!y@90BNsA2p^R% zB_8YvMK#r?q#&vTqwaf}1WyAT5r~Ufd!YxuWj>B1P@-ilfb9i3WDzv|hcK&hYS{wt zP{w0yi=5^T{Sv`-3L`r7Xuk6p`ypaHa5=cO)2Y;0y*Z3NP7Iz`TUa#~-P^4NYVkm% zFC@SLZNrG7yq1MM{F*DcG*{2B$X%9(nI-ajTs+2$k=s4_FKYoq>KOEnpl6{~VPMpu z|3M#o!#OFj_Y;F7YawOdF|(x`aGOnl8n9O0(aHd~9IOnxqqDB@kj$48jq~1_Xbh^2 zjCLDWWa-ADELga(65NS|g;5IxdByH&v;qhz5|rbD6R+FYj_o^I=nuH3fwOdcF!dch zIOsET@7eqs`l!@0T?`1gJZ(*sBlpqXa1pWGDBmKnUs}uWVRAU_KL?f0Dj#xpX7nRf zwhAVe!mPlk`lo;jt?E(;Lw9gemK(MfjGuwS%H8?33$s%wWA^hiQp)Ha)I`k)G@={2(^(aSX$D#AUlG{F4!&a)H?N=2Kj5>!< zsy)97akd__lQyEF{f*{O_?=+Pr8%5T-KrFfBl{b%TET!7);{LYv$W6};7$unA?z}G zWV&sC^eig{r~?4%cNjfCeG(n1@%4?4oOy8HSR+S=aF_`^4a^o$0*w?SrrcC+}oBNiXHbCVWA?!4d=UnI-@J8+63` z8F3CtWpg~2CH#zXGrGhl8wW-`_yosIukk_mi;d<+U^<>DtIo2&c9(EC5W-bce>ZFi7&) zK^>O(z`JlUkL-h%vu~s!9_PVrH=lWm!;-7Bpckvog6Eo=g*0rsAPvkSTx9>i2>!Z+ zmtnZHW^CwZgAp62#0#3f^tjNJ^CH>L>_1%Chx|>NLK6T@ zCxf0kXpY@HLegWx@oaev$T|@+WhWvJ7IFde|n@>V%?i)x~Y+wRuU*-IH=m}Dn zUXkErgvi!wtN+A$j6#I(VSL~)NB<9FOnsgJrg-{{OX7GsQYJ@GqSHt>EZ$G?L!@wF zq8t$xQ-^O?j+f+*;yIcQ)8I7pe#f6Ijt18v&eqIS4XF@Yo1@wLiTD@eIAH#2ppS!n z55@zcPC{u*rLDc@?U5+1g^P4FQ(`wW1z|4zx&9G>#?oM7Fm{LH1F&Bx?JCq_?w`*p5cOuo z2ROLB=0$S`#=ChHE)L#a0~d>V|7lLnR-1Z$6yt0qpWUI^*=v+@>|lQ>NEYzj3R{LTd8XLzYDrzqgBKq7;9EJ7En#OFci95@4Qk>Yq>W&5CVD@#h*OUGwI6LerDoMse;HM(S_% z{4bU*hm9$9cwwM%`SLX6g+rPJqY(q$yz5jBaRmahF~R>uB|^Zo5D6iZ>(1BnmOqA& zDq^VFe6JJs!dfZ}a+U*e4Es3mQFb>2HiR6r@B(&OMF1G1bLbP4g=Tq_6TWSy*voX_ z3CAVEE{&-I>9+yt5kbjqf>`Os>4>&D9hHjwGiTzp=uMaL|7LJIB~`dTHxOI} z4kR&TjTe%gsA_?aUl6su@myd7oVNpmj&lE`7XqhT%B}%wLsj!qOP-74@LPD93;PATEBLw49 ztNtr+*k*T5Ug?9V6!6c|Rwt>RT&`7J2Po&%;OR`Qst@kvef2GPkNzR_L9PGMzuE$< zO4oxoNGoma9k>IlO@xIN^J8J<@iE%!KcYLhEA;&o*U`QKQS}J*<9+pY_$GWVVBd_~ zxk+Z1dJ>7K3A}iMR6llrickPyL>6v96$rG}xH*io05^jPlFXN0`))PdgBk$RWUY#( z8qELrah=bN>te0?IXqHhV$OH0egpx8B{a#*{*E;q$8u9)CC01JTT=TY$o{1Za7G1& zc9QwQ0|;Zl5UIou>WanTi_t1oCB%bcpZSA$&RC7WsEP+Duwe98!QJ*^j3G>Fd{-c8 zl!yCc#4GjwUV3bIn=k#*X$)0TiL{}JP?WQV50i3D<9c-snj{m-QV-i`;Bt*+(crH| z^v5nL;D!EJY@->A*~W(k&0{wx8|e{t$MVNg4z}MS4pXotqwPs4+@72Y&dr!J7F%wj z45)baB~%Qaod#oGQ>m{Tu3oL0^NB08r~nLDxQS?m@IhYpKb;5Majcz+ku3#vi@Z`X7%j_ouypDNjw}Zled%a3PY& z&HV*&^KGa{|6#je3No6F*UW9Z30^!*0?T==Vc}W?e59B+d^ff!q0OK8XUbGuW9b4t zlvw?Boy=dDQSvz{LGrMRz41Ik6+{k$;-a z#GAPz-<&PgvPne3V`Upvi|i4rhX(b>*=Gp5f=09-DPS0Jt-uKPMT3@pp|CX877qzvW_#22KfV$Ba17<3LoQim}sCnNOmVk6^!t<7&}@_V!hw#N|Prw?t4&F}Emto)j~ z0)|7W%`+ctw|EBe>ogvKX{_x{uHQ$uH_^<49kp0&kT=%H=`Zj10O5{~?R@<WF|zuKuFEHA85xe)f1Y$^ zylvG|6aTZ-uNZyEbD8FkJ3Hw^6*V*5q5VfkvHrH`1F59qm#z63x#pH>l@%#of7i;2 zP9u?Tg}GG_u-9o>H#{C$pxw3|PoQL|RRkxq8gjZ-4YIKGp#GBaEEGdzCd0i}H3$6g zER+hA;syg^boVot;kW7Dj8rOE{j8O3VIf@RUjI>-$uUfL!eYCLew#Yr9!L;2%@Q3b#JRcrcYme`R6E`YODou-;{%bE+RAlMQ1sAb*gEz_ zHN_M?`JlEjuW%D+f#C98ks*lYG2Sdh!~*lWSky$IW0FR)gFfY0HhIav4)Vb=Py zskFjCSx@WPxq<_%e+(9>2{c~1d_){Mq*d=C3NWa0iGOZ)S}Q{mZqOme z_UJpdaG(wQD*S8w;rG`sF95xEOmJCuELt@|KUQ`s)s#DRPRR&B0fTT?L zhw}bc_V@388ha<-cairCwCZgD%laPjE&4sPeRI**3Jc+9S^RYL=u&jm?h$&k^c+gu zv&r@hj~{aEO%#a?Zlj9GVt&jrejrb_93zZEuxg`U*%XWaK@en5E(*vO_OfM;VQrnD z7_qrB0oVwHESMJlJYqHuLIdAPB`uZIIl6_5aNT7&JzNSB-35Dlxwl zUkx6>U7@n#l$OAi8pEoMogV+NNA$aM<3{uY>!OMsBoGl(Deb_F7)8u)q?N?6yyLMr z#OV145dgK}B6t9k0w=_ouoe3i;j*0A@=gnn#KidIGLaH1aN=6utD$A}ftIdi+e6D< z2(%0+dp@xJzQBnAWg8&49tQu)5Dzmr)%-Kut>&Y+)U=*FKF1yaRtv;%4-qF1v>!eM zW6MeAcbPRHYBMcaCXk9YEA;7+UVhN3u7^IZI47O`YM zoWT=v0{Pvv+iD}dAjW%E9#8Z48@5Z$-&HUVeFe!F-h)f!aYP`S{I!k3lJu!;!lMm* z^dv5Xw*Zj?T6LHs5%nYD<0-xfl=Joh-Ug@S1aUr2K@R0-VSa}H6m8>_lsWm{6s_t; z6xg1Ws*1CIZPoQsFQU`2qR7F@A}!WN|DO!N-ds(;!l%6%8A4ql4gSfwfE4T%+g6=a3VYt~)WC-!D|%|wm^ z-&*yP=yBzUPX24HZa*rr$cq*WatSuJ7335K^VM+`2wi_s$*<sBYlpWnOmh zvK5!@Nu48y^*}BB8WISy^tA=ZiMSvqIP#`IOSk3k>!C%-I!?go9-MkpYM`mxlD(0a zO@m)o;o=Yx=IhN)=@1@k`>_@Oj*sy#`awmE$r>=LK&3{;1}KZ#+AD>3e04`FFI%Bi z7s;<#b&YCFBkEPS**DlYhGUyBzSI1jjT6`(-lKpa`PF?<-Z+8fQ=N&y-KDUyQ9fCY zK-r;VjoQM%PT1BP)BM_4WWhK!svgq+gRl32mUvN^cXYuSfl>c9gugHW)R|^;U(!dy zb)YiVnUSu@(aEh*4APK%22f6$&8hILP$r^h)0M$ll9%NwYx5mG6;konIvSg$6!e=a zpnWaDvM@tdq@zkS7n+QEN>P3v)5f#>Z>4-+0fh2#oqQ6- zZ=<6Rl0F1|F;B&qG<);X6BosH=5?}*0rOG#E}PjBq^G^Uq&jNJPoNRHoB0sp*4V>b za|XVKaYJ%}a?p__Y1vTnL+l$8t48}qn)+miC>;1$*q9ph+M|MD@N$q?4$T9arq(sW zBal%!qS8NK+c+VGff0d<;w0ad+dK8-ULpX6XoWGE@;Af;BfnZrWS)*8h>9v?{@C1` zC`Iff!^Q0Ub?}85Q}DU~@%w+q@)SS!n!RvmEk3YJv=x$yr)`B~a*0w%=;DN?w%Q$4 zNYIb@kTq9=TT7vs{CgFl=&9t_pH_Wa- z&^Sz6yAbc8fM``Is6^>F+Dgu<%znz@vjdI4_VvY`R^5{&dq!VxVuXY$8EEurRXJ>^u}rI?IJD|7*Q(!S zDZ)oTw^~h`4-Qr1pROoQWr4;De^;>2p71Lu6!O*wn!1*q9`fE7Xi8g{7V`cv(mUjR z!TPZ)lJ+b#nHH?hF`gg*cbijCA7lNlv_3r(pJIHU>}xqNh6fX^tpfmD=xxQ{!rCLL zg`w08%Tj{zPo~D{?t&ZVJ^2H{G}_HUe5RV!RxOu%06L&-p+G;N>^HHhHqrU5YTDE_ zdh4vzX6i9d+T&)xHHxW!$nv3ni!YTG4uWXPky{RMg+~4G_tej~+ww{luVM$TgMVb- z{Q0zEL^E4`_(a_LY4a>q`>Cq-haPZ@N?9gM4`4K6`r}e1($k!93Kvhfk1qBFgoo~p z1Ht?kh82ZX4)?y2^uJK#lEn59^`x1MuXX4a>GrEY<5J()4$_^p>W>PsM9QxHAT{~( z71-30k+dunPQp`y2j#C4JwnykpB=$)1uWSyIyf;7Vs8;O9Nr;EL}ao%SvL6xnmR4* zNA(_AlQwk1Bo6%^*WqP5V%3>nX4q1K!yl4LRwtMr%@JQX6%$#ugm)l_!I~?S{P-V0 z8k--)FobRN#19)DQaNIlzq@&hggz(}q(UF-pGkd8#33h92o8K`^H9rQZ611KhN7}% zs?$tWYDV9evmni3|>DzyqvbT$ml8!|+w~yFfvKUSKnd zd_~-sNF_A;lWr;ahH?>8?N6)}S~UV?^$f((VM3Ph z%voH~;s`-@q}+Uw@*2G<(F5CIxB5J0w_<|HVi&`tqu^nFw7DXNB(X}F17%Y~JDB2X zA~(E0I@=^F7>a*5L0I^cu9wp~Pm2)Z$AP%+l_O^QJ6BdDU+O#6fj%rr3t@8!Y%5Vn zETw-=c?h1iY^16d+Dt1^8+(Bi_^s`9p;S!IU%**7PO}4W##S6s`zOR!I*4LFRE{ih zmNPrQNn7~?nG28TDxWWyjY zSF5e$deU&7&GlXX92IcTPYzwJIDatV5A_?qFUt7^it`sOi*kNBIRBSj73U*EjVK*a zX2Ve+FWl*Zx2IO*EO15wVnandqkugu`xb0E%J74&_GsL^g%BwJ3I?jRXGW0U4o#GN z#7L}Zcc3XAdh?S6850|AiicirM@Los(HOBn1O%ey~uyJ1f-I6a)J3Cd_A$~(gGd1yG#vEOn!nfy=Up^us%yFmz~k^TTBir zG3TOYSUlT%y$e$z1_dVmlcSw^o$|Pqr@)-{@i!5G>4C6BN8zyH9L|id-ml`TU$=>{ z;-mGzm-*8Q9+q&hf_=tua6R8Co}6TU1Q$xQ+i9=zQNEOW$}ZQhmJhet<&YH6Nc$@u zVJy9^b1dOVASe&*=WvFod}}o}<`u3y+)@+isUw6S1hb2I3w{&31;DNkY>w3J%L{&*tC`_B@~Ma;*xk;kKGptoM&Es6}WF?4($b9bX(Be|eEx^f|#b{>bio>waJK%4?1A+_qclmy*2eJQAmQd3HI~JJc zJThsp=gO<&VcxR}m3{fVf;mgUJT?Y%ZsZSyd8(wi0_#~YN7f(|n`FfDF)#9NOSq4d z>M=R4#@_*(^ns5cx-Ek-gfT_9XzfZ`AXNe^zF$SUVLO4s5JNsk1MxlsKUnGRKpZE73PCrjN_q1KC|;;xB#{JAHXYM*v+G1NuCBb>Z=Nx*6y?`*39mMxTpi+Ujq{6orV{K*?e4k zj?lbX4*8+3=((_1hIxM2DJO`(aC19?IZi)fJ_Boh2Y)EOFl+H8=J)1K+Rb;Oe~jex z&z-X(&;2v&^rqn84~jV8(=1%@)Xsz(q{)Lt0DU1BbGC%mMY%dsKf2{vV>;f}dUQ_f(dr zUhlsGB@eS?FzprmiIryIbbpTiY~g|h*Z< z#D8#)^#Q{xij{U41iNr{3=Y0nfqIi4GH9L@6r$zf)j8_b0=!}`P#XHR>6Su5t~>`~ zRS<)XHrXR5ZIqy*+R=iJbJ#}DSQ`a+^}KqeS#6*+J~hn^QI;rhv|(#(x2TT}(&iXL z@BhR;(qkWiKfr@tG&Mzi^-$bb&@U=t-+5!-Ii_aw!28ZY6|RFNw6%QQ9kb6kp>WXL?7E)ndG}nbmcrQwl1^>88zZ3NIgW(J|=&ykKikUFdPp1N~v!U!lm0*tSJMa zJ1d>q66=9lEEfC151G%&!=(pgaePXz&@Qq*8oj_h;{n*=Z1zjG%fgF}D>I$Xihj&OnIFG}L{{Luu z6Zj~r>;FH2i39~FNYEgtQKLqyHYm0kAvJ*jGcbX$6jMP<)h|u0wGomKB|vaOWE@AM zr50P;($=lD3;k9Rm$qRk1hB|r6|`2|pXq4Dr7WW6|Nh+jJd;V-^!NM!c#-Fs=XvgO z?z!ild+s^so@*sk>lpOJJia*B{n+(z__J0xu7`uEP96@%l@x&;&#RQJ-WV{Swnb%r z%r3v4{#!}~21Fdx!VI!je2I9~r$)H!w0}lk?THQy&lIeM&W$IMMULecnxz#0dSHtu zLn9>8iYw@nyY}=`I5n7Gh#lHYIjE`ls=5=|+lVBYLO`b06`A`4MyY0}2T>Qe`c*1y zR`4Jz*_bwIv%KaRj$2{J?S`N~{DHQ4a6m;CUZ)&^w`k9N)V1B5lBkY+%Y?#SImo=P z@ass4u4XOH{<4)yMhj}xmQoBw`~@pz4M%$2g8d0^Xbrm>=a1%>wa#|R#82MXDHA_S zaHo`TIHJ_Z#0RpKU%kC(+x)^bq1VFN9YSXldO!{`=@gC+lkQA>@&wlmbxCn*H3P+a z>#&7C^Ry3_kL|Js`%`;Anw%r3=sam3{#zp%(3qk{kZjR=!`O4|4*5f@#4fq5b0tQV zvV%uA;~x@2Gr))fNuUAo-PrS-_`5~rO55;a<~J1ymAaxlsl zyBvIz0brP<)*tTq#;tgA8zJKm@quso9v{UNE#L9{f$uZ)&H^sK73XTB-ewr;aG<>} zDsrn1Ez$~U#`yT){yM6GV;<4R{g6K9Tz3o(pWGnoWgH`jgroNtH1UPCV7}wyFiV2) zxZ7@SSZ2cqkFS>q??S=c!aQgs7z>Bkg_yLKSu>=CsSd|%k>Ti!eAYZiiy}ONiM}UQ zIW1pRJ?T+|O~jN+Wi=F2r_=(BX_e7>OW9D~cUy=zM|>IRX9rkQBf zKL)U}rkgUaWPkk~{MO7pKTMWsb))tE(z?sARfnU`6My3!3Fpiz=V?~aj|u!xOCM8216r!eAnv$F|liI^zb3ApJ z98X)6F`cWQo!tsmqnTdEg&ARFa?`L2>c*nDyOML!S0_g^PYzWa8|+A_QP8cBN4!Fw z1uyXDp@Dt=+spVJ{Wy6HW%Q6^sDRcw-HSh?na)mebtkJyOtwgr(HC%F0WA&ASCF6V zAq?HVp#RANR!sq7G1ZAJEK0Q8cfDIZOV`-A56!^8aDHNW>R&OuH&*ke*}W`*ogi)O zhZElftCVBHlt^s7EIZPeKhs{H~^IL4J&O^HVl1ulQ&Uts|K~q~Ia3l{ft6%vCpu6j5 z)=%ZKQplA2)g`RvPCoG?py32BoFSMo@y!eoFoRv!eV!B#HRk{%k42)$(Sm+;4|%_R z!yjoBHsUvDmdAW7QV-N$htSkwu8ML#q0#WYc|u^&Z0bH=Mtt})3| zT8KLGWZBUP+y%~ey}CMu3kH6^|8YJh@9I*w9xVPJ=)`}iV5p3<)zs`MP5MHSwjQC# zKHq{-=&~B$M}n(3ca=g%jgAdo+!_vSufKM5Y|3KasQA^H<$<>sJX;pnzF=c{;FWp4 z5z*m`%LC8P&*JFv#URig53zg2ce?I8R4{ZU1>7+3f=u02585qin%R!vDh0 zMkX>d8jo|fYmSJl4PLn>@>yBqM9;pzutVP$l#yZHNq|!Omr`))$ZL|yYyVotlPzQZ zNkCip*K(3OE&9yUUzC|#=O+g{vr-k5#Tzooe7>j8-x~PLfBQlTQUOpwP$_|ut}>=b zqR%i|3!T<~ibcCpSCRU^v^7~m!h+~}e4kwFz*Z;wkogOo%7gRE1YcMlXsdf7F;mmB zL4fMcR^5zMm-b92?Ec5$J7EcRrsLiFZRr2oF769eGAz82362u0hHPtPcP&y09r+_) zdGuMQLem#KF5irFkW{53lfBgRd{(#^g`Z?gQdF~+me=hj_EpniD`=H3BELl$J z2>O7vV=}ueJ}Fb20MyPOS6^L$-eGhs_g2RL=K8OXijVDp2i)o_4{TiU4u zFO)|&JNL>iPFKwkFoy%q26cMphpq;ET~+s3kQ<{z3GdU!oR6 zwoJXq!()B^$1mbOsfYMS8S-$gp9!RZNd@ymVztKc-ty@4j+)+@{8cb^c^=i|C-HgH zVGp`^R_@ahL**L;)g1*)Z$c@B4v42?Mv)( znMoQ$Fx}(4w)N1R($&6Z@&Ah>;a_`8@a|lF42YMcf5%TjVH!$6wTtpAdX&SJhL&;C zd));cgvSE^f%g{-7U$?svkqzriATl9WhQ@N`X+hYsCdCeE<_K-u+Qz-?160P%bDg?=OSMT<8w2U513wWO&(hoA8ufdekPFlX+d_>`7X#Od1U}{ zeyS50g%p-+}!;rpt0&9?|7NF5Q`u^Zw?8FoFK?fI)*d-5qo{TvtBM@u7o)fe-4x zEsvM@@ZN~6?)e%Y*ArBBb9rF>{9eZQHF+^7tH+0P5ZnSIpMG3VxaQ%#^%$G}FQnU# z>oJJ**&K|Ae1U=f``XxD*G4-&z{=^otBa${>s;8f5X3zqxYb#65Mb_$H2A2Z9%O$| z|8;G91>RU=JJo$qk0KM``3TTE^a6l}(t_{~iQXU74~XTqM{{>X8+SnHzIM8*-3LJ5 z5(LgP0W(#Xi58-+kXZVWuC~kkll0|x{jz}GXx7+ zW0^?iIv0$5vqKB)om$@%N<_+E`0=M5EI^SK;MBbkP3!MZUhgeruZ((2#)~hp>saGl z86R-QIjJRMzFo&|o#w7%*=WT&cFkL&27Y_nkIjnalsXo&5&7Jkb)os?RQm1RB>xIF`1GBBMPSxY#y0Yt89c$kEB4b|v_3Pqu#>JLkt@f5d+`ArkrSG7{%!!?*?+dZ7qt&=v(o>G`ndd|&V&G!rd$!zv%HSz0N;&^A5MK;ht?bP@l6WOR(sZUFQmlfCD zC=*u8zQkZJWUiRgmo}>rbWgF@J$38op5?l1V%$3GbXmm({i3c${&aFSxFnaDnW8q^ zKP{d8ljCg>aP3#pe4fpy@^R8(WdAX>;xpNGz1X0dsb0fLa%+OfNyY??-^+M20MCmZ z8`xAkh$ zr%2~QWZ3!(V~zjo3%t_!VsPt!*d~97g1R)!IZ>td<6?UXY~?stuXlTke$PovN%dIQ z0rok@_Y+2g%1m*j@jY}cwDWx~F0H(=&aM3@<6HKfW!As!BNenqOu{#G@K>R6)=Mp6@u&;1n5BWs-zM8sMhI(G-_$)1>iIgl@#;}~Xh z036N>4c-NbH3#53+cG8{=jw|wgb6dNB_pT zk}_;7kK1S0%B1sKx8urB;q`vI{u%U!?Yqju^xYMc)OUToj!L}1KsViY^~(o!U*bvg z(WLFwTt?Ov zoQJVRxW>m@hC733j0QXKX+u;3*ZEE0dedDN*G00^fNKVawF8=Lc4%m@RB3=!GDwco z2zl(a6qX-#N61ufgiJ-c`>3)jmOnIzoSM!0@1=v${11IyxK><@DJY)RYXN?T@l%$M z>7U^|@*Qf5XMHr^y!xqLEw!&+wXbf|t3|xB{XdLRXnCqyp5w$;2~y8^-kNxd1zuN{ z-sMT>PwqyiWLa#lK`9oy7{0|;tRTBq{kJX_i@JW!Qd%W*y&-TygDA*bs>1(wN z@<0EDL6UBZNCu+cB649wDm~$V+*IvK1wmEvR)Q5J-SAP4A*i4VCWFZcfz9xqO@X%; zROy+lHQZ(0AnUl7ZPsdi(m*r!=7I*@p-mOZKK<=^fRF-olnZFP3uybH0M+<+2D!lI zP>kLA*Z1CB3HJoeR1E-YGV`48J-fi>=^0>)xVymq?4K6cLVW_*Qgd%EDApZdRV2VZ zfh!T=@?Cr_)d?eDwao>#tqZUo?q?|#wQa!)O({an+&64(?J`UQsL2SRyS!%?&>eav z>+a61UyQ3zE%ps zFGHYy`CSX@VwFz@lMzstdCxAWOZ80F<=ov?-ut@E`mjDxXPdb*bLbAJDiWM7BK)^< zHt`5K^Jzfi+se75puwcHclQ2&mSa=a@Y>cfAYkfPQc&%t)P2YX($cr|s>)w>_q zmR0iICG8)-Z@~*HE8xvA_vV5s-9?|=0k4gPGuvA^0%Fnc$SFum`6A~BAg%O?#vYwOKdXCh?x28dDR-BQU>W;e#5L9&z&ZV@2Y=ahDdW!aO?h7`&FB@U7u*~E_3G$EZxD3iX4K6 zdO2=zbHR9L|Mqp^XeEW)zpLJ}{kzx{0&g^Tc%|+lKkoD|Hp{ef{!Ale?6D=}yW&*{_duN#nM>8ED%B__QW{6#SZIHVd+d(p z;_6UpE>`A*P8;Olg=|OmAIU*_>k6!`i52=9&uX4y=GzNOnOqC6Cf$*d>yOu&QV)&b zbosv*up<8lQ&|2t#+WaR<);gFLEavA4b67L@<EblV8j*R6E#z*03 zSni<~aelawEDfGFczDjHh28L+_^n0rDfI@;>%In>SIzLyOz+Vp*aGOu6b*a&fqg!I zJR7s1N>qne#1I>A=I`Xz)|m>2UCT*r?X_nmjy0IRZj3OUODZcL&D|zho%kjkS{j8~ zJfgOB;;V|d9yB7PInXq)b#^cv%?^bI*^H=Ff+cDM$rtLt^)0trT$?ZHxJHw5UxCf% z4TeLKvxRS(@kclswwH|VO4DmyT;pGX8L2z6AGF9`UTcv3jS`SO<(r2>w#&mi*mkg6 zP>boxgY8Zk{KIImL3B8FtQJK^MsKUlPbA>Kk&>PQNNj`ixqu)QK?Y=b(}u+``wJ1$ zD|0I1gD(xoW+0^Rn9cn3v^hIcn9if?6}H?C{9WvAvC{f1phx~6)MC+`XCQKuyW>3+ zU2CLwa@=o5bteOXagYJVk?XE;KYaf4@Q(9G3C}dkatY)cbNqm~$3G88oz=!+o0@e69m;8&#Ccy(k#aB z>WC$*Yy(@`jAX{I@_SS%)Qg&=IT5FWs|8%bPht`y5nDO`0Lfg$s zDCLmYOc%k!<~;J0xPnRK=z_<4rRrotcUk6P+Lw6T<wzbR;}j8aGCN0U*k6d2}Mdnppr@OxiDp`q5N z?NR7y8pX}u1;01Vv-mCSj^7s%PDJa{mA$X9F2Z2P>Z_KZwkK`VX-TEKQWw=doZtNI|B6)M2BP* zHrJ6S%c$`@I2x)~2WZiu*N^RM55ly!eth}c2F)!+pn2h>BceHd{n*YCw1-0WA>@D1_s}RmG<`q%)f9biT>V86 zp2n)5E(p2^4|YTNnKZ!JJjWtii4KWuo9oEP{xx&S(S^a+zH(Ulb}-R&<0Kw^e|oJ! z^Mez+7UfEKNR->0 zM@IQqjIYAc===MZ9ErYXwH<`@H2QA7#vuNJ^Fe&!_^u|k;s@0P&!m>v@J5g)5)4F>sKcRuq*MU+iDhi{Cid^!4A`1B}F{e%kbL=A5tTfJRO* zP@rG7oX!kvRJ{CPk^H~L6)E_!Li4#WNzpu#2zT`*t)aLA&;+SP^yYq z_?mvTQk1{BiC@Nb1%Dn>_o5qkL!niaKe?*bb^rS+RaR4Bwf6#ZJswW7D^}tMIRgl0 zIA4mr*b&*yE+bxIRRt|UqLvIHA~B|mmWNfYv0}6=HB|&r)RA}`w}H;H@Djq1FOtC^ z4W1l-%P)8XWc_M~#mE1rX@92w)@QV^Q7W(>s_2){)A;w}U<2w7 zF8>nK?D`3&oO%Kqq&L^DuUPYY1{Veo;2;=ipI4}k$`8i+u-|bo`}i+;tVw=^?O2W;;aA7=G^33r{R#s` z@()fHrCRt7Ff82iJJ!kDCh~%6N;`&~6w-w6;I(e&x$vyZbvIJ(=EaTqhNXkRjY) zit|VzXo4Nnas^~a_9RSHD6rcfUqNHX$NH=$+B8TXjY5K>0j>TitopS*Cq(@fv2RqP zrI;~3I$iaD)70O8d`x@ycQ`j15ZIDGGJAZqfLFKxQxyHcW`zoNP0DKomXa)0Z{&v{ zKlIP?Pfs6tH9|CSf`rtz;Rfv)Fb*Y!@;NFE2ihB-N_zFVd#{Jvi1Ox;ml$ zkho#XJK6vEtRBTX>jp;OkGuu#cfBZLM@o z%lNu@dcnw>C|x@X&%2oGyHL?TRD>huz#!+ z?(8#ijEy^Ana`0}(uZUDEzL7`VznvE0p4HU5z~hLoA&qfFPhFAO0$C*b*FQy%)rAp zp7rEaLD?UM0nECL9;sX|dit4`75nsz>B?`esw@H0s`QC3R0Tb^C?rv7Lx6 zP^C7YiHc=sz{ON=L`)u!hUXN9Eg*9}K*CKQA76JuCm_(D2TNG6Jo}OGz;OrRf^a7+ zOTW||mWNh+aaiEToNKTz6Jbi*pL(Y{lm*FxUW9Ev&Ijh>S!<>P$Y=w|VLBvR@X#Td zK;d?X^*uObhkOEUHSO;|=QJ~z(0IyT2)|>-bAyTE1Gy*p)f7BP1s?vyV5)Vz2EA*u zp*R&OLB)`KlS;zBJ${Sm7p_??;@D!!_u;>44=Z$bYRe!GE6oRwJeQb+t>WK{?lTnR zo^2R_VZ>BPJnQjk;NsE`br!KLH&Sxkd1`zS4JdTwheyr&LDP~)`thv!%D8Zdf{=Is zS#DA8&tdOhzas9lv`?UhOU^9CHmTu~Gm8)XYRuPC{o;}{t5UzX!Smib6`X}jlZeH3(u6^W}|T_-r6N6I#}xdC^tJ? z6n0T8e%*3CXPyVAwRV=Ok9jB=RW6bFO!1mm+#z{n52EX9@#n?pB2&Yi~I1v#_u=izhjwdH)jJN z>Iry6KTHW%Oa8;ta*GFZ{4F}7&;{9!DuMjNa|AMa>gMGz$&2|8+3y$ z+5)P8eu@gPLA)zs(_h>tFWzrakik0$4^S?pBlF$i&2FT1u%&HrQu4PyO-p^Ez(;x=oPoSp^x^*U^?7!Sur}i?k^a zc(z{-JW~xknW-L>JX4AE6^?F@o3dp$7Ms?(&ERULWXcYJraS62<`9}HDex8*m_>nN z8f_%e%ob_Oe+njLVW-3bTqi3n<#BRZVi)0!Wt>%8eX+g5Q^UDZ4 z68K-~`gaThKMIqihMMq0?tlVjeiv5dDGG)9oGgTEOPj!D!%yxXg6;gO<&PE!^ zG>QumsHUWWmr8fjFBmOjeooeVHGfdy)!e?{*6bd6Jffg`%`=Zw^KFkDw&tG)QZ-w> zfkl|mv^V{1eKDpaI@vn8?Cl0N;`^1m1P5e^9a)~ZQx_n8O z2XFUKXvf#%(5QhV@(!oqHdJTS7D$S&iIfaGRm=eFR#rPjzZNU#4^dZ>J|kHjjI0#< zm%P8e$^7CWQqs%hK`GrTcINDV*v;0YNBv7)NP2M*{X_qCit14MCZ3%Qsq}i(KgQkD zHKh=}VyurnP>KAYQ&}Tx^E`dtV|REw1cq z=gn;O-|}fLBTIt;UkjvnKD>}N;czPN*D|P-PCy_1a;fnZEi zVem#ul9KuPc{<-PNAnXqXJ@^Vh-Zj7SE99iVL|qsdBJEyAtGNq>%tTy&cy}}qk6N= zEu_gsk&>GSxlJ9P@7#%@CN-Chh7xwO<|t%8D706FO31g}g1~}m<2-1-s*v^Xi?d!c zp^)<7EB|2xI0;?e;9}=bJw4B*RfI*$q;ZCRtm+Q`)Z1Ok6gLMMMmLY{E^##i(KF9T zKj+3Ly$_XB!m!mct zq1CL(ivaMjKE_U9+qbs1Z*00WOYr-fr3MSe`m+=Z`~R?QTs)Ur#ca8G@>bY5*^7rN_|0BI9fx$xUnIHgn%%9B;RJE4u@mM`t+WuMo1VvJNr|MoOL0*<0#C18PDxT|Q9A#yWi0s%Hif&cTQL)^dirBR|*@%Nva(pT@iQ3WT9u-|J@~yzy zGb;Lzia^5O@;geXh;cUR^}pjX+#%an$HjdP+igB$|J+r( z*=m_DaUd%rV@zy{;~N!yL2YO$$(A$J(7%S_LwEaEe5E{o6%MwfKASZF#ZI`~|Hx+}qr73@hN1oa{#%|-p?Ml;MprSnSan9C!hn{6;VAk8 ze9lv-KJ6K3d)DRM5&g=EowWTCR+le==JHMihoZ!)#jP@{bxAscr-9&c2Ek*Zx&D#s z%Kg5K3DIl)2EnX>&$JztxXWiutDs0`8cyu$qyQA&l0qOMl)Uv}PPOPBG)K3*6&TuEzQe=6>57MzF zviv4kdtGFCDr9-8FJpW(d@8KLHpq~tMV;s`F{vl#4|DdyQto47VTXjXbIJpo{Vl}h z;Ly_zM0n#6UdUOePGY6nYzOOl1J_)p&Do_)dZ4H{M5KE&R?YTgOi~0<3P<;QDA~CI zDmowEyspFb-rPyxy@@lVFV+(F6`S z&okRO5&ox@)NE1;t{OQ6>njCp^a0OfcL^SE60k$tK7>?me2_ekXjQo-?rzgik zNMdf~Owg55M#E_N?##u2j7L(3zq#G5yizv0>Iw0JV-E?+c}E4sLJY5NncM{B#SupNA*S7_!h)3TxI#U8Rz zU;lh{Bnhw8*&@+@WZ$v==1*v%UuOz0u#I8j&$7$Ha!;23LM>79j#ZLn3)^Omz5daPR;4BR3GV4gZ&OP3*SG5GWHS zQ3U)g+fBzzmXUXLYofRLek96Dyk&MTu>O`TP^;Wnh~_iU70}{p-3#@`-(tSSM&=uV z7KGI1v=Y?2c3Q=vH|9^R2&|ny5h()JJ1z&YD&!Auor!$aRyz!dq9=9&oiKmBaZET8 zIA*k_^s6SY_%?bz95~azXgH9%*4HByk;pYII%1Od_b@JwIN}U_B{m#2UE)EK2oD2r zgDK3Me?0C!`N7Cd*%|(yn&4{aha@3#vI4lx_*_rUwM3m0{W;V4;Y`(KqAp=w#^^GF z3-Ze_{r-wBL%6_7o-8q*T(i&YZ}iL43eDU5?b{08Ize7JJxMM8aNwsr?BQ}q`5qAg zwK2;u=VG&+!E*xZl=E496&mw@q91<$X)9Cv)2>e+V*I=7Q{*L=y}1&ze?_Y#ize*E z%`c1iTtQz-Jq>wzj&I?PjQCYgx(>Q|wS(ee;WV`lux0OA?W;Y}^q=-e_E9)0;|fw^ z!c90yR@m40Sz*WfmVc|1HDEidbM}?JG$z9t_kuL{YnpqeW+99QBU@9X5*-I?f7D%d z%x>WPv%Y42VxFsZj=xv)6GnI~11DD#1)aYvr!Fc{^-uZ~jGGh`I+;SX7@MKR7))3$Fo+vf0^2MFVv|^>F~x4z zJR$@-Ti%l!185X_uGM;NhH>1gMX$+FN0_kq?m>Vs_rVkSwUlN34@)eM(-?^`j{ZeoJ29o?Z~Nb7wFZ_YIUfl6k5arKbN* z<7KIn1;!ZOX3aXlUYSu#z!TYBNLp%7pf>J6RUO;B^-Y`q_5%h$9bS;R#TJT~E+mPC z&j>|s%E_qhC0CeGw1r*+bC`2$vlq2B`i8W%u8F+<*`757M_bf3FDvr;fn?7iZEKY2hh&0(?OD^K z)*sn_Y;CVa8yfX3^7^NH)?|}@gVOJH)7M_(p5>ft4xt`c--nZm&HVmx?>W89aZSl% zBKyASU$Q!Wub$Y!YP8xAM!`%ti**QK*hY6oSJUSVL^+17Cj=HX zz!hw@oQhF*QW?9I|E#wvv!eGqTK?B0%S2`~v`|W`gz@9L8UPf9Q=BcFqzpNd8uv4I zTRPTHwXq_8eF597iT{;6o1M|#fhS>LSjJ}&XG3(ODM!3T{t`?Znm)Y9QlZGaeBzJH zg~^1Y|3U7)zF=J0p1=8Odz)iD-b2hRYqCe`l57``ns^MxW4?lrT&HRq%L0`(by?~# zJiIIy5T?cQY2|d<0Kv8(iR31miHwQASfLz(4Nxw+&ad9#p~jV4ObhD`?WkPB`iI z&b|h9hETeEwhNlBRN+E@XsBI+ar;7~qB@hkQ>YhZzyU2R;I1+a`4N%=!<10OA||8u zxC$U_<#i|uIn&o65ScBra0rUk2PLqbMO+=8*{`WEzR~ByaeP-e7{|GgbsCtQLQW{z zLxR@@lFMzjQ6HK?3)9^TsY-b@n80Vkg@YRDT&Uq$@eoS}M6zWs?gvt^-K5kx%t z^S7*H{-}sugDm*4K&^;uKo8u=NhUr;v4dMMf4g(zwM@~3DN2Q z-e;m(RK(6CcI^2DWlf*<^56OZxG@TA9)12r=kiz)`)*FfqIdnxFVJd~))%{2tvxSn zO@qh}A+vCvWpqZZ0x1-@IlHlU^R~qOJg`2Fe9FSQg71_D5c52AyG4Z9>QNCJnZuUc z3V(P@IPhMbuX$Ut5_fN;K!-^?%&PjtAF!AcqMEm9wA-e;6y>78L!pLB8&$g~Gg@r$ zCiW}B^Dvvtw){z|zn@sT%CF!&oQeR(kb8N-9u(r5j4Z4;cVET1pTZbId*Ohu`9iDq zT~=}W>Tu=@p^m?!pD1ING#Ffz$1j**ISzwwJ?tu_erULp;C1`i9S%$!%X!%ys>1+Z z7X7To`C65oTADPcbM#DQzSFRb={BG^_WpGnG?60xi!7yVx1jdr+-f;A-is;6Q zXu^?z-~sXl+ha%DOs;LRd5_gZ%U{PYtq}dv-%|yJLo??`E?5N-6plI#a4uPTz4bYYy zjRfX26uI4LL;wms6d_WpVL@8C>fkkR9C{o+2n%}VQ=w%LGtuUKcKv8E&JPg;Si zv!msk_jyF*4cdglm#1j5+fcPDh0IYy-c3wKFmTSrBI^`zvFk%Uoyg^obC_0koW+8I zM=QHxr{V^o1}T1!2~6n%^8dzpa9ax$7IlfS9_Lsf(E6?3DJj zJC%9Px?Y&eM+@3aw^{u|vd_p^_-&u-f22kKDHJRXMOpNjaNsq6%OvyMe?%bEqQ-18f#iw-9x%qsr2z=^~ye9?+ zn3A_h$OQUcXw{p(NXaRmsJl+V>32Z3)9+SM#Kr0p122qK8OE+JKQEhm#)xR2^R&~C zkhlJp9~l;T-00}=UxZCKk_qE;X&4!s@^*FzmB<~6W1H+FBg(?HLbuk0=RYsn4+f*dpEo#^NIOlG z1M7l|TwBlp6MGIiyWePfL?5BRb8Jg7e9QPac!7ueY!AEbOWe)ZP^`zu*z~uvoiJVu zZ0DPjUS#+=9Gu+FCX?xG7fE8^cA|EbOUyo7fL8X89p-M4n8*dpRE_!6Xc{n+{Vhh; z?Sw!49Fo=-t3*~G7rw-ADXwXMR{cPt!PgyYDoHFg?~biMKCu?mD}w!^pP4?mzF>yr zr?c_@`&fi9AQT&>omA&65+$JKo6C$%0NwtHw`mKfhBvgbP^>*M91GTj%=~5v0FONNJTyh;;)y2o z^U-X1uz`5tcnY-i-Teko#ryNizVFO!HhfIp^|-%)JFQJpB<%GHE!FzCy17@Rq|g+B zecaFZaE6)uh)8Ttz|wXGBV#+y}r!(SwkojV4M;4)%Vrg6oTrzQb7&Ni||@wEWy`2)hgA zr;P&VJccQ#`qSBFI%({~baHt=c;E@Vclzp*txHcXYTtnt9`@++K9@8m2|r|t$CJhI zNTUQdJko5J)4UwC{PjEO924f4Cq(8OhMC$HS8TV%!QX?4ja>o~TmASiX|}5$$3Lw& zqxKBBr?G|azP;*BJTG#byKgZ>7nETYBu&M&t1zRr_8e~~NTlTZCb4|kikxe`)TKox zxsv7U7yBPfGOQGpd5o`Nsf2m@j4N7bLMg;2SG11jP?X=imjEZ zLu&TyOU(~E?EEkjF6qt>%TyB#S1h1Y9p$QXSR%^rtZAimVHgEoH;L>TRs>}ndRQOr zHt)Smgzw^6>q}*p(IA_9XW?#T@vQUIsQ*!;;(f0gPg7m(|Ez(SpDX@qwEu!lOqI!i zQD)bcY(kNz*pG3e2u8kbhaI^laR5l-y>2n{ZiH#${gvI_sd|Ed#ng0b;I z=N-%_h!u95-e_3$hfEojxM-c~>Shs+Ba7K>H?owZ z^!&&|Q1a9{p^U^5JyX1+JH?l_szi%$_z1s+Y)Zg2djCgi9Uf-=9lvRu*~t@(a*#mZ z|4oS#(wCNz%Kj%Z*8-09z^p-GYRDQz|@i!(q=iWqC!gAVqR2l+3t=GT5a{OtEYD z`))S=OK_+o6YpI?|!6Lp&S8`@`>RT7ZqI%7AHm6@sm&vDFH+Wh*t47kiWog_Mc}aEbRp%rxo)DXIdfo&e&q4Xp%qy{< zZT^-I_)!+ftUV#IonOW!Wd}bbf0#4P*76X(rX6R){Ick_)==h-ir!nj}Fb~6&0-#Dz@&uuMB=BmLLf+w73g%trZlThebg_B% zptaCz4O*=lk5`T1z>GrwofVWX1$G zDq}g)QD@qJ@O~J^7u{SD-BQ6uYd4Sc>wm&y+(myYtN!~HTISM&j1?8j)%5!d3 zI8IMTFr=+Knv{Ynl^?|u8n#sxfmQQPAX3O?BbfwVtA9ITrt8>p!5QL^s9TK}h4^+j zYBs*Ot|g)}XTYnLi`vK-*u#RcCzp~@dJI z2`o!uUK}#0oc-H_z9dRf3KgX($t2TkAsSQ>#!lF6KJ*#y1WThD*A31G`KsQ{p~*t9 zRC|ap8iFS+5mrfh70uV3Y$frhrjGMPXAwozdY3GEn(M(o4~QV zK7=>1iz?QT=h_d^XSF=YXU+u;$9;btAMdjct3_{4yX#qZHis^+%Py0<&!Ew<@^v_y zuhNEvmKrkPI?hRXeKsctc0aUl&4hR^N9XlMW z^FH>7rkxA8)tn26oO$ST0nxF4tRwY=Qr42hfMRD?)Ew8>XD^#&%A)PscN(A7^}NC8 z)>f4})|NZ6EOsO3-L2z*z~WHs#+=xx%xwSn~R& zk9*c#Sca$1p4Hj4X9<-QY7Qw42jjUb%;BoJ&o^D_tFv=es}4uiV9M7qB58*N9v@v* zu5&(iyUkg&heI4EOy!Wb+jM!LUb7SPpYs!bIrr#tmoB$+G4w@Kc3nicKuSO=>n1Sg0`OTL?%x+E1UF0)+aY@9ZlR zaEnjQF)1h*M>)>r9wg9yPV)A2P{Q&13mPOn0f)ck*VxD1DNe(FX1V`)8-jXWdBGTX zwiPNFE;uOkvxfN~z90>$H%lmg;7Bg|uaqTcvXKqf$S@@c|dUI*BAp%*<%lQGYqccf8<4gAA z4wHFG!Dyx2Wgcu1dUo7rm7wR{?z73n^FE%{`pnS!)!+&B7HYeSz?w#@9}5T2-1*~Q zX1#7j4lT|kG~X_}l)2xGco9#5OdS@a3DwkEt9cRIe>5(k}=Scu?WOWc@MDmL1B+IFd zn>#X-c1;AeMaCLM?6hJ#S8D<_bVPK@U-pfTPXEg%!3f>jLqh0E-fMDGkA*r??mQKN z*Jod8kB=jWg=fGt2tUHZ?> zzg>!e*q7wQqz-%_gZ?|L z{-eCl)qmI8{;T}r{kKTa6}iy;|JHwv-TUt|gk(%cbQW5dE9lH{Oi|pj*%S3pmbK38NZa^-YHf25zuZtW#wVuOEB7WlBS7t5M~N*$kG zkZI{7@Up+<)t;)!I}Xm45sa*1{8<5IOzhf+e4)TgvnR7iVf=w_(Kf(JKX7h8aFct+ z;d_oehZ}i@5^ROh+NJv_dZ`&=on0h_iG~<%I|4^zMv#=H4K61K0Df@#7aUw-;3_!U zxYUdyv-VpI>+L??64jmfz2C*}YyQYXrmyZdyc|Zjq%81HgWt0aey_>2{bLM*^=?wJ zC2#D7B7cJnpElV?$EGi3e7rOJo3J*^-^?C1r%;V+@O_Y6EC&0T+H2y0xVYc@eqvl z=-8qTH`x*6Sr~M>c$jQ_R5q<3m+8K6twamSFP`+?xsOAGPm`ADO4>5p;jSj_{~?eb za8mXeU_Bt&AAUVj-3nd)sLOA4c}SOEa+!(!QorxfT zjU&rVRu(F8{FEN8p2f5J35+Zdh|P_ceY7SIZ~J`i`NnR>4~ne8xNzS;QwoHKDJIGJ zp5Imz9<_`LYdno)6;>3CU4&MPTvG^P*^#`EaA`vj_%7ytV-7#qv&gS}{o;~yW08Ip zamaLGD1H+$FkbM-pQnOw9BGyBUm0bCwAJVE!vtxo&(kjq5!M<+_5go3sqC9n>`g4c z?59!woFdW=;a;QcH*(3TQT7|rnIiiJ*83x;7?y>?U_bu+$7qEdDfz=oG}hl-CMgnx zf)CqF4ZCFqiCOVaMiC$Eb>UC#c5BoE1>xUK%iSbU!oE8-zvIG)RW67a9_w@jvl z(5hX>phl#zD}1z`C@Em>V%jOJ&sNh7)@Ktk$YOmqNx^zqq&-vR6NHhVC$T9fvH;ue zZ?U^H6heufg1>Wd|Ay zhS#3VwG>Zq)`3x6d_SyXHRk>-iw%ihl^wf!9kz+@p%+aXo!Vc(3`zNRedZvOxI1u}P!u<{d*dL$G)r{9xqd(@f`8k7wao63{-|uVC@_bg(&4$U!ei+YsJKLH$|Bxp* zG}M)AkaD%s6modEtfO`E9M$abiOj!oGtWw8Mwbk)vY+8y0GKL4m1{K3FVr$)v1tQd z@orm`RPUF$_lM1${Z8D)n$=cLw6pBU)sG0$0UFjd&|Wcr4Mt5+lgtOU<6YREKPjzY zYL;rU*(%er;ZDt7h|Z=x+soqRN2%;?Rz+HMn-~U@K}t&%BM?Nv4W@~ed{UFD%-tr{ zbG7@v#@v_K;~iOF?*gg%Cq4IYA2L!$3?96!9pkZZH zxXF3_M6by%%pRZ|F#gbBP3KlkEv}}D^sE_O(|m@WDRh_noUKaup6A~4&D~qaKWdJR z5mxQAVO6!Q0(ChF^-m04l>}q;ut?@uenXz+GJEW<_m@TAXG@E}r6)|27p?W&1^KdH9mtal+&nWR5rVv(vd}fQL-x)qJ=2O^Ij-c2IKiEVFq>^;^ltR;QuFM5q*+ zk@G==)B*uUBe(kR8YDIFQ~$gcv8Q&ozeU4GZ`72sm~VN)1jN^k!jQnASg$Xcst47obo_JeZU{2weuUaIFQMdFfQf&o`Myw$FPN z{aY}wX?9g-_swUv@J%BMK->7(ls3Wvlyh_!3sdH20(rk8=878R)I3x;r{V|j=jWuC z{|&0$Q*)fH*kO!g{>bd)kDP0+vG$#5+?}bqOw=W;%NQ<}H6mY`%>&Y+z2C*L#^sWd zU$$80cs7jBWsVP<)(7!_k$1yzqf(V#^iv2d7=z{Yi82LkYWiBwy4+ZJQ}&)!KAdpm z*9pge#odXeLQF9Gg=_6kmUM(8--te@C3W<*_lo zRx_C{q}mB_A39gxDl+<+Q2Bbf?3d_f8P?2}zS?17&5}AUg0y!lZCO*XukK-aFr(}} zUWw{{jJ7wsZi$q-Jl!t)$o!V%iH7-@)5H7F_n2OPsvg9{!I&x3CGzE=+55AVRrVGAeLj~s2lSD@0d9gW)j(DUuJzp zN-X*gq{*39u2{sWcfF7}G|OKaDQVp%V(ANE^(u6luN1NL53MgRE(Gk1#7#{86xOS* zFPRhH<;n7oCN}WjY8aL$df5l+_*kMBC%aL{G}SRIQgXhj14GF4UWKfHk-rB~5mAm) z6$NQoHLT!Z=?|qOf*xXDKMF(Y$jmRIN_sIik9k{EHM*R+JY6|4;plm;BBbC_yLubNg5=ToqaKi}~>3 zFYJdZ=hvG)Q!#Z@lx+sf6Bsg#)_Grk=14CyViQ?zd;=y|D@o?F9#+xf5AQW%=yT!$ zkc+0a859db_X3&jT2}#ge3|q-FoCl1}$$n6bZhbQ@p!yz)PRj{K=`#i4 zt^yZktpS?&0ZN0#`hnFvSQ;rAq-yGV=}mRAuhZ9*%Wo6-8^t@RiWIBZzbMVjD#eVu*LarZI@F1$CQ$zQkcBH_PO+goSiG=0`ItB>>8qi@(!qU)lw zYP`0|ix;P@o(dWl`78?qPrT$yl_5B!Z?C+>dMUofmd0Jd=#8jh+6g6}Gy zJd3}dT>LNm|9N!!acLD*fk;;Wij1FEy1236Wao0T8NyQwDExe$e+3_CUt-wd$G(QS z=GQhmzuxE#@`dkcCSl+;NPgO%<&RYINi$5l-kZsFK+nerjT!fCbYA>BY$o3K2WOV1 zTrn@(K_G_JKZN8Jh#^vP&od%Iw$URcQbO`1IUD}+adDYu@)5X>Fg31j z)$i!z%eX~KIyR{myb2x{Q9J!iMQ&)sTMeDZ=Fpe5+7~hgt2t9C`r)0B8&EcQ>ywYc z&jWfFFPShNcga|v7Z6G~Xo8j~MmdM}RM-k6a zBQ4MAX&PZduDPBadMzp4GTlzsGBrkG;lteZPidCx4zDN<#^vKVz_gU(kQ8NsxcJl~ zsWNUEjPoP8u$$r;2qbvaD9JSaGf@)np6Q<-3V5GWuhku@o_N;XA6sl+acpM;How!^ zfDw96c|q06xG|HYSR9Xxc`<0uv=~InZc2j~zIDw;_05?c#91E1IPy5oR)H%>Z3}tl zPNjm?sEZ7&MqMPel=fJNq#0Px$W$5~L+@xx(lI=Aub~cvSbRJKZS$rHxcp#j=sNX% z5ia}&ws_VIx5d@H)v|-=t0)+qlfxfg{10pp^gjy5=43lhPDwG4?de|ENWxv9d0EunXYF=(GM#87(y zk57pfh<|Ug;O6@SeR6y@OK^R}BO4fTc<1~$m0pkfhq&H=Us={{*0Y+LFL`{q;U&oC3Sk^#T6Na8gAwDk z?hIsHT09xP=X}TPpYXU{;zeYlG=ZhtPm90nn513&G23wvOy4<|N#=&f2bmWti(tKb z5?ZsxCw_uwL_NM)u6{}9%iIspiGOp^A__09wM8rfA(GOW_&4vWn5P%tFOf@KQodt!clXQ^s`kP5mUdSj%6``9B6?K&?YwQWEw# znVON$UIKk?-Ju{sUsu`Y89Av4`N;V(5#5|0auN1nKnC%?oz5@aj4(J3wqnBwgAq{C z`x|cyo`Dkm?S1_pg<7P$qeq06DIQryM=`^wi5u8_e91n5iC2 zfhZg~tH0un=>|r7H?mAUTKas1@?83aHQray#IrEn(E7x4{2bEZ)XEDCq4*fEP%Y|n zecfTKB$Mt~c^s`vl@TsW7&+lEXefw8RUKQO$kAt}!Wo9`aRhtq)SQg6C)79-h?Kb3 z48U_9%E@qEKY14tNQN`$&#%%l{C%=c|8Qi6^UTYbH7pTOLk{$FiQ7!|e@^0j5Rqye zKWzKfP=VV%16hMgs4?r8xzE1AhP1l5f~Wz0P|rqgBD-D|iudUs+`3-^h*99c?qOz^ z@^`aQ0G1|C(Kuj&%gP2YcFJw-DM*YzIYnt6Z7irMTX_a`k43r>vZqV^4Q5*$gzH=#H}J24~CGno0}@TS?lo)T{%NUL%Ab*}vlphn~eWY!kO?Mj|M zeI|8bhS-<70Ft~jRkQtJi2l$^JCne`cdiRxp7ydZWP{oBh~1N98w%7iE$HkW_@c{< z(=hPb#pxJGuIN^=`)JB9cgxSWikhu+E|50=T!PhZkx!N)OrO3LVUi6pb0JzH#Incy zmcN)v^J(-+9N3yhbViPHuI^I5IzBIX*Fiv-`WK|yN5oMz56?F`tb>5|&|#s*3e$Xs zbLS(H;(1We4Wl^0RWGnzj#*3_!%qdoQ-kNeSlZOlG;1Klmx~bPJo)e&9aNqhU7yVQ zt4a-CLnx$O`B;W}x6_4Q3~|IajX90Yae3j=>u3V!(xqPZJ7=Q3fC z<0UcO2qZ&B|LP>8zVd8~Zil}=^`Idnpy(td9-K83y5Q95-vzMbtu6?ki+&0_;Tt!j zJNZ;OD^EHE`TS}~7xH<$v&mh4nf6a|%csR^|JFIf!sZB-oY1)&A)|`u_R!uJLy%GU z^sS+|k68S3;fu4;vW$eC5>k1m^XPRr720WN14h(?s42G#IF_0sK%)BnE!t1z!hq;I z85*ig(a>3!N zdbIN^iTKr}zq>yi?Ylb%AGVOA<%i7;XZ4zU7svap$jy#!kGw`G!At(}=Se&dzo;$g zD>Fl2?TByfZEre|Kk%ip(|4BleztV+@Dq_zn4b0>-}slqR(~-4R0>ViB4jk}gtU=4 zc{ZJa1z1MoQZct0LwIhQ@F5fB;O4ft) zDl9amN>V6jio3z@R9)Z#oVej22<`Yyq>o=SQiY}=ZInOg#9bYpkmc7g)KXynj`Yne zWnO+tOCK}B87kn9u##qH?E`_J^&fPmt3+bG+e(Mx#Z|*xPCWs$uUR6-8e(PYV?jv&hjQe;o*<=p0m8web(J|$2N>$2bvE$ zwF^^7>(rs=AEr|!|92mBY0svA$D00)jmT~)&d{-`BVZU~QD2)a&QClk9Gzge$Ux^A z%sEC|GcDWQ=}fYl_$}!sgL&sT_5&n;ovK0lr)5_Ew64F)WEZ}pm8In1-Q0;EMaUL* zT?Pptu{s>PBA;+W41(*hG~QgSFFFDsLS}8cK}}=b*4WFJ6H-XX*brQ+FV_)HE#Dx~ z=-A+UMg_i6RDUTat>)vOiQDaP-t&})8{mCqfi<=L0$b$nx7^fDnaMoE1JEJ}uq)Se zer}z8l_~kd6Vgg9Q_1f7!IZy+uW9Ai5w<+N^a-8iY42x4^4QK7t+R)i3KmlYe(yyi zqPh3btbE+wi;VrBogFPR`N+$>sPBKvI?9Sh;Xr{C23z@jtR`hY`F3An$5R<~8iKWG zPvIFQjEIVTIuCtSar{@y8*Yn9@w71+hhkqx9=vE|th|TM9LX#pu|zsNlPbo6d=lo-e_7UY*~6RP!6PeHHEJBouXXI02UU#_!f1OC0x$d_+mP2wnc0dUJ}g zyix`IPx%ALKXRR~XXZNJMVU5u>QX+&!h!`Cxln*03CSE<70)FmgoR@{DcESSJ*4RW z8~BL&pFv(NT9i z^Y8_KoRl$So8qFCYroxM$`pOJ=^oGW^Y#BD?OoubEUy3mBqS0ral_S!paG*2uZe;t zKs3RCySUM))KWnkZny|1PV{86 zz846;B}ADI*enx%%zfc17#RcRRm(>NihWap*29;IF`6Au&syh5ji~L%slxtsqS%HM zwbpf73Au^i^0s5QYy6t?S;q6~OS}HO zC%vvGq^O7BMA!G{t=IKiKR|j|`Pu(lzdvgH4m$Vy58)YKwcnRN(^bE(!xr;Z`u%De zp?*K{)34U=SE)7`rRaBODwTBV^k*2yrn7&_&Dd4x$EI8snV43H!OPdwH%*LqVjAJk zzRPgysfbI()_!5)E=}c=NLF)s$rXil1WWp69y$u&!pjV2_-1Y-D^k*0Gm4MmJxH4C z&NUyM&g*fJ?-o{s&mzL)cbSncEew>r;aix=3m)W_hbK0%75vh|%OZ1fas^F}G15t+ z4&K3E&Ew%P0_Ee;0PA%X6MrumUHIcpu!&MCTyx(7yvJB8uiq@DTH+Sx$-`DK} zUznmEH>Du{GIp!NIpL~wSnllwcI(*mm-Lw!fwIMRL+lBfie|j|yLMW-S7pxbP$ogV ztPsxFH(aG<7oPr>5}n&Fv2s+kID>(K`lrXfnJMP?mT%#e+=#sgR#$A|mO;i%j&3;r z5%z_o6o`yqe%R{FAEQn@U(t;?-x8Pt;SrmRY7re=#r86*j&kmNNCKv3ZLrfMb5J@_ zQdd`;S17qkH^sUMm7Zzp!2TK>2zx-0KHAjc1}v#KZ@3-)li87C@2=F|6fueKq5o{B z8;^e&`Wa8zN28xB`SeKoxqzn-Q+M>!m)Bj=&u475=|DfKnvH`iAdXs*5nJqUOVbv6 z=6}Jr@D;u&M>v6Q*an#4JkgPE9^XM9Kd{Hr%~Iiug~l}cE$GqB1*coOnU%dQYrKY+CJaVg>NOgB~s;)%U~YGdSgu`c+#8o4cG=@Rpg@}dLg{gKiS9%ugmvvW2r zz3(@$=ruT&u|RVcH@6+^xPm(#aJBAWUZ95~fY2h9fT(I6B8B(viX!;AB zw3y}`%Y1g^e4GwsmM`PmN!Ms*lmNk`xP|%H8Z7mL`FQvrj^N89wm9cwHR`~ZXK6m( z;*GaIZ}G-k?;rdx<82u{%ChBw!=3fT$!yshYo9QBOgE2$DYbWVJN-7be98FIX(C=v zxAW)sd3u!brCo1b_VOdV=-kVH{Z)G}|K`{9GOh?6dig;fdc8d9FZA*y|NKh5+^B+0 zFVEDS*UP6GkA=>&?|;>!Us38B3&WKEOlP_4vI{%)b2oC=rtNnAeK@Xme7W4U@wZ+_ zGynb_+fK*%H$K>m*m#DyBvy*!!dZ(Y@0IMGi_^oDQH5BUM-hlII0_e{Z8LW^$6d43 z+s=8|fSt3I3|DdriLt-v$3P{0lw>LCsU(d=`Vr{b`Hzyl#x7bTYtYL^eAM{oFi_vZ zw+voK+}%EEChpIK3GQdK9D;k95WeaA9iMHMJxeWpzrXb#{^$gviMtEOXvR<9vq+oz zkFSQbpP0g3q2*~TMV*k=^ULvb+^Y2BEskQpLRH}$tEL{KBvtK&uPiluz=WWIt%oZf zIKcnUog0U`JYC#mk|uCvG^cD;lx(QEka*Z>__vg_&Uy)D5X%iTD4V=Jd$rrNx?p~B zCabC1Ft8FOPepu*u(7zk#)N?S%-Q{9X8JVfdu44P)UrH)#WuXY=s(yvIMd!4AqHjv z@i?F@Cl*kvM#4FqLM3M^IZeq>67*BL9Y|sgWNz0c*+0AN-wO5bMD_0=*t2n^>A&AO z7h92hAx$hnHtx4N{-{5>e_!2d`*)%9)%y39$CCy{D+ZbWr~X}q?}KwDge2_?RQf-_xYu~#ikXN&Vwcge*yk8i&NWJ|R1#EjDM=FLqc=H{GsJtF z1$yjhydIr_`l^qTEG0daq>*U+GpfF7S+}UHwS3^bL1N)wrk~F#(fD+Jr{vd4enCR{ z59?m>@tp4|xmU>|B@0M+f0yp-l*~|a8%Z;0hx{-HtJ^RvpgeZ^9lyH`G%;E0Ia&dh z$xniaIoD@x=U# zDo8GtkC5>Vn?9~_W9-B;)&h+?nn z3^+PfKD@~2_M44sM9;-}4UNlY4z8A$lHhIc2 z;ZK>g*$XcuBlxWlZ2JT6jq?BoQfCQC1$*Ty!h@fw2={+L(Bp?xvX32SC41}6tcdh~ zM)uk5gjXs!5GZH~M9WQJ`->Yl8vlma?KIrERAr4NX%^->vkHwUY+)E^WDqNM?&zn< z??~36Hem-)K88ebtQGEd1OqV)gRaU2KHtIxbTA+qX?zCvVYiBr2`(AoNJkK zL7!xtw@rD@H6_KNaNazSG=KBu20aZ^ayV<5YHwRlfXb4Cbpt6Q(tjCG!{9Z1z@QKt zN>6OPo$`B74>i@?Nr6WK{Fem4g)05(L=FS2Al)fQ`%y$)k)Sl=^Wf|U@sl8bzfRB; zZNF|M{2zO-Q>SExlG~JgOUaES%ny@we~pqWl?0VsO44k*s$>6XzW4g)hunA7KmEWG zm`e9B<+c1|`bNZ8HwB|=d1IOs`ts9^ornR#l zlIQpako{xKq0aY}G%JZHS*T<_Npm~=&<}fReEv30yG7*l&MynKWz5Np=`>k-7H{u) z;2x6dCt`_CU^MlAz>uTXJ|0lP2R-Jn%Uq6XZ;M;B#%EE!c;C?NHj>JGHB}pfwOWnC81z4kwk-v8nO=qUHGa zk=P@zu3I@iJUBEy91MNVaa5lEM<-G)!9T7oSkh8A*aA2{k`*E(LrDC4T*Rz(mDMn$}7#t&}p^X6k4Y)m8EyZx%XWYgVSV&CQyzIR6Rm2-iTA|+>$xTIkS zMDxFU{>pox%%D5;dV_>CqanwIxQw=^fS({oX>)i*pvAeUGCDXX&~iA9@a&T-qv_{g z9zE-N0%Dy8HZpzpUQa<@`*?Dm@7@b|B6-5f6}D(|41qWh66DLSBZ_N*w1Xs|GOBGEZ-Yurn@i2r#W6CI2Bz{( zQq=D%&A!Mn23y*d6<$>tc5DInl2MbRBM}e(SUHrOfDd0*?XgCcYY*g*JDU#XFbvJ! z9(^WoYO=p<5{R{Sw5V z+4pG2p#5@9-F0F|n&+cgOZ`X`T=rGu|J)yNykT<13?OsZ7#wPB)d`4)*T|Okx?wM@QgQc%R(;_h2L| zpOB!$AI+{TYBhJUp5EQAKJMMn)?m1QexRgfP7h{w%?N!0se55y%V1!$f9=dD0QB2P zlE<(0zc>!kv_tn}BYaL%XaplBYkX*YHK+?1Z1rX!LzIDN6>BtBbYf)2AGAMypI5c{ zTMx-LXk;VA_`P(Hv)}Ze9wCfCrPD-w^;&66Pv{0AV%6aiJmsQho%?)q9Ely_vLccX z+suDP>=Pjfaf+gg{=@wBu=$8AfiEqa7(;UgiarLz8_q*cddBD%X8$BEuiZ)X`Q^hw zQGn!21RtlV_m`5p{IB17D?#7!V=e2KpzsAsvr^On^w?X5dL7|AVf?4bse*LUA6So?J=6(9lo!{pOx@-<4XR1zdfrjG>tlD}+( z3r&(NtG2|m5|bJ87mnU@cd7a_y=l{oUr4X6zgIu=pMZTc{sOq(eVQ3x+qooH*hxY( z{w?2dX_F->LO{P-43O<^p@cFa*qw39{nYu+lke&Hj64z8aNl!y>&q*s`05<=*zk8GmiU~Z z9zgLQcS1_iPtCvX{_7jOK|KFsO$VO-dbzLhA%1H5)Y{draDG_NQREI7G%bhc+5*JG zNo8Ywdf0oX-#o0=!|8b5@NnefX63A5Fy|deZEe zvi8TLdG+EB73{8;m{t8nYw+(!%3(DlfaSs{9uZn$yU(0EsF+UWv2q%)M)*w19{oo;7ogFzud%Xo)Vc9O3{())ZBx=XVdb#hp7(ove`}V=#*SS znIi;+lAzFjP3^Ss;7SHj3nFLXF)pp(KWT<}Qjc`JwfyzpG|#2sdUb?lt?vHZXvPf} z_DNZGDtVmfdUR4y&zO8mNYe95OIc31K&E|t7i7sPgqMe<|8Tbd3fkh3$)-g-GatcS z-5Mgc250}h=+mOvDJ!KtLB;6uHPGX?NWntRYvmoihW@5_GSK` zX8ezFahKs=Wh)E zIz?1E+&c1Ui(AR~oLV+`T?=5B=Q@j@c(2XGP3_FWJ~2Biyp?!71f<$d!4bdyUO@Ps zfBz=`DQqU+FN0Rfi~LXV`^K&H_d*r!&xD&D`R8xi=KJAMe1QE;Ek}P({nQ%Cd42bu zee8(J^behsTvKRgYG_YtmsJ~J#NT#W|HG;6{LRSRj3coPNhiy>;>&86nwxw}dXd%T ze*{c{wK)X2~UxO_j7 z-$0ILk#=}nMR>=nr}I0i?>A6#1ym=J31E}s)G&%u7?Z2yR|82Sz76VLBvm7I&C8LvJ~4c;j4 zbGeXVpn$j4!@Yzi#$d_&^M+v1Ex8l}Uu3`;x)@_hdyeoPv$r|%g_v9?1+mfkIMLMP z5!9|GHoBhJ6-V+y%m4mD!`(43N##z*+wJatMm}NvaaF_UVYR2dDhz30OsiPzt@Nx+ zXyi`wS-gx!uX&0_M@Rm6U>`R2591@}_)4$kX8a?`VYMDRUd_$EgiGQni-nTCvyYAa z77Z-AG5DuZJNeO_LLTQ=L?`Sdgh2JI+=fF_YK{|p4Tpx+zDuS!)BauvOj@cF$R1=> z>Av?h9>UTu{FIsHD1k2m1^bNH8VIjLO|3;{VZ)(@S()W8tC5mvS!8g;QY-%7HQI<^ z#9<1M*0X^u5URz2)_yDinX{zXEF_|;LLV6s8Z_#B%ga2gMGLg_ASzeu}TL zjz`?x=xe-?h{S)&WP4tkOOAIyF>SBUoL*xl6V*g?Pldbw+{zlE3 zJ=iVW8~p^4lu)4@<6ELN^b3U~I4}9mb3+BfUq*kM8J$sArD@%j3s+q)Aufku1I_tG zorTT=e-|IpF=^p%u!H)hdu3T@7kL2-pP!Zl18%7LZPFytH+hMQa%G=Oqb z4S&BLW%1|1et`#jvpC(Pas&J~bn$3|$MY{Yj~D2Y^!N;$`^@Crp+k9duQL<~fBp7v z`(i`mM9*zOv%BSz>&0l#R3rXyDSeZeVq7fwqvKP}^kHyD#c!6Gir47kRh*zzXToSi zj}z3%itqkDL>3*=pPjGH)9>$K{kcGN-Y}=o4EU#89)5Yn0*XCe-nR|^tHtAHSs?L__Dp6 zaw8ATxoBMUjssK6Lv3kw$8!6bZc}Gxi4?@#wgNbh4(83w_NXKFI?r@E=p$UchaROo zc8*8n8*e$1P_DeO1ECy40nQm8bRd*Ni#rnenf;GODD#Rt5=!<@JtF56Y0g4UpF0Rl zjX9${wE8s{KW!PaKY;h7#s4bq)2J9_<-X@zE28(LpjR%Re=sEzz7^8u`(X6;tYArO zW&y_}!*k87aScJ2{^47+!~E!fk^)$AdLSG(_6%PHq7x4JQ4ZK$q`{%P{n7M(f#~Ez zX0f65%j7|paa~C6PK?XQ2ZnitL5zpdtIl>YYT$S7x;Y80F8?~_+GMm^{0t!NOquHV6X!R5R6UGC-|O8E;RWrjhfTjsAw z$tOC%p%g^0Svl~C-sQbo%cIzHQd8m?FKM#3Q+`cmW%%RRKafzx=h8fCNO_~2Uio@*CmIRexo1ZQLb|r8BOyg{jz&oDkLcKm-}$lEi5;N2{R|f>^qV&v3D#*{ zfb}WdGiiQa+1L@R&wNJ%>(WkOZGOlFi}(_wFz-4el@uyDQ^{#chLYg_q|~gDyIL?P z=2oHeb+dQETbBw-1P7c;%&Gx`AWv-5r(IZwZT!`GL|MB8{M!I`9Wno7?N5>_C5LN} zYq9zLtO>-ab=`3D`w=&0CfktNda~DFu$h&|yt@$$i_lfhV&~wq`3;bi+10zBRmGG) z;(yfhb-7o0Z}2U%d#1DwnS{~KpSnSZt+p^+wfM?aO|)r}yz&=~0Yr@g)h~Zm!6ns= z1T!gSw9dp;rDkTs#lvd*8uyoR+EKIJtbgKjwE%s=Kx9wcWG3ADsMe7jM8Agfihyxx zFK^|;{CHxS%Jsg{jH+4=s00r-FPJvo!e^I=PmDZA7w>Up_&@?c*SCsYA+xg$e~sNG zcLP~Q8JU~lZFE=u@#CVmwcT z7S)1I`vA3k4@S=-Y?~GqlNfZ`(zcwZmEqNaf(>#qz~F#g1N9V{8fKlWzR(iQT&U6(^HzOr7W#>Pqdw``44|OV0Lq~g z%T*MaEU^*6qdfe&(7neLV*S!&!KlI(oJy?D)D^Lx!g0z&S_C}@1(eVK+^#?JL93bH z*v+({2U=F>Di|HyFBr|g2xpvGrJkl#Tcj+$w%g6dFFgr`-qIopwYpTf%_s+o19kZe zf(0z;kw;8I_EP;$-5LykK=?DK!VqtJ^F^)*1_OyX5*}gJLt~1|!v{hi^=#G>bXu@v z{k)sXmpc-{ma`Ok?69BRb%V!V5ltT}3l_F()G}Dk##X$T!%eAqdzd#V_>en;qD% zA$71=82PI|fRihiTby`3swSB|*tW!}tJ8Bod2LliZrUqiK2`qIL&3<9DJ-ahkpb74 zb=7{aZ_VcJ&FY`n`|`w5CmqiwMAJ$6{rst4FrT&ek+_H>poLp)2p=eTT3&1KBT<-g zuzqjvBmBh7IppfC4Qfd0R-IQ%@BE5MMBQte5}j%6%!Yw*T*iW)C{u7QuEkqi@j}JmBtJ6FhNPjZUOGx5nsSVm=6wpG?9{0s*nQS}rd1 zxrzS*m$bMSfbp>vi-Y->ssjwX_~TNrI^fjb)8GxSTDF-C29%&Lw1fN+!viTHjg{iw zfOY1xREm$4Rp!NZqgydBH`QqYpA1e%Pz)J#g5qbt1BwYx+Jal_9HafwP)jb^VAaY2q>%adA zQ~&5MufNyP>c7&~j}ZDdmS@;DQ8=yhEw~6evGdzrRzj$5iKUyy;s;$5i=PkU$CbBy zAYS>&xYRhOE1{-KpIf3m(8I<>=dwsesQxQ=KjY41j8jyDnS44lPWm&uYjOYt-_(GZxy)ERy=(ViVw$B_IjNZud>@U7W6AXm;KzMUL z>$87qeYVRCFlin`EgcqVYbQk0VL1we5n5?iYRvu^J38?i1Iv$oXa}_>ea&b;0y0z{vz91AMM~@(gHYF$!E4J9y{mohIW33U z?w&oz<3-Y3Oea3+M)7C&{Le|aatD*fA{u6oLx+A1PdevCcD<3snJJ6Jivb zEr~RRsc;XzBJ2+b=*sZ!*e(Bt%oTstx8N0_3`5SMCv_u1DQi$5yf0X=%HQ(E#et#w z@S`~%PXjw6KSd_32vnhovZ5Ke@mDne+!ySOY;w>PJMfpguIiG%^ze7dU*2A?(QE_w`@`46Uw&Nc zE|jlT)J(N89X~gR2n>I zF?hyYWX2cj%;fR&vJGjYGki6EF8>AN=ioER83N?Z{>jey8okwC4kA=mw^H>7b{!ctM@8@7^ z-5-;&)h&-r@YZB*V|eTn#)+XcG~D!Sqq%fqAzrgQ%65Lh5OKbzrQh{E*HWIk+SB=uQmCP`qW%pH2Yc1+ zjQW2@u>9FQqyFDu-)xQgU(?TwsDDlTb!1ytW82HlKN5Bq_QZmP+2H21W2ETuHHk72 zEv26g>R8U*{2q&5H?619*6M^t&wpDs2j9I~OU-XHTH8~RV%z4gmeyAE&r@k`edR5? zdsp<@!V4*GdzlWi@6~k*SnmxHJAuXI?S{1D_j+#h0I%o19qib1t}b_PdFP&!!-cbK zO=tOT@plcgN=Te99y0ybjl`LCvX$?=^(}KE_IkSp_rmTlKpPwVDY4&EVY3JDJ^ej^ zU%0GGfXliDxc3nNZ@IlAz?nw{c=Aad0rr43C{KcTW5|#ABzKbVf!Jbg3o0ZaoO7m< z)07M)LI0@RflB(2SUsC0!+Ph2laDm?o%s_CeQ&P7(09{R_=GX^eftsEM*l^Wu$~d( ztR-pgR-tV69XZGB5R>Ufp)3VlVQgj0=#x!B?3M3fc6qP!ExC_Az}TOu81TgR$NW$` zU1vMhWK=hiQnE8VP zuj?|S*Sx}Yc9B1N9g*SUb8`V$a|vK{0swR-Gb;fuW|J)tV5L@&%)^~`Ja|< zDc!h08UL|sUEi5PwWdtFS+nlghT^jo8~W?1^c6?Plx(V-hw>;ZhsA#(-n(rp zUggu2*l$VXYvXt2$VkqFF5-o;G7AA zJXliq;j1(X7Kr@Ld*8z6`K3H*ygkR)^f*6JBpCfD{I#ym_^*;-VjAc69V(pZBQ2TT zOWUMl+6E{6cNvWdDzqt6e)JB8&Y^@+b*(=-IE{ur6_Med*CT)RTd$$c;nR<3U$NVO zNcKsleWfRx_HEEsO}a^KPv{p6{IZOD@ZVCSV_3%dnjUjop%$Ew0RHS6P;ltX+MYBp z&CCz$>TXc`3gu#xs@5H=#&NLWm8tPM)3RW}8a!%Jg9YnoMEoAFw{|_@HNvZ zY)WCGDOcyIt4b&865g;3^^DsT>lsd16cN8-YHIu7rnM`D%Uj0a?Qxj(%g?<7(Sna;xfWy&p(g}UhgHt8KhhmxJ(0L;E*Gu{p zK7eL78HUxI+Eq6MloSgky+KLcKX@b$v%_^z@~ZeRkNAjz)wNgN{%uE$*LM3_>>FsX zk96#GpSb)H=gEQWLg>Z+*Fvi{U>^RDKbm!sMa4X#7>~$F!qmG8fpd~a-?jbiIV*)k z#?$uYjE3UE8lu=0ZC}a$iqN6{bI#z~qS`_JSDA0a>8Gr|2RFKz$J+0CKd-kNC6+Jn zqcxk3Ja%aP2e*NEm%rr63RfmuW3gZ_Xh`Q{(>pAYX$d>;EsMn_b`AbA06hsPIVl{#trWR2vQ`)1rSTS6L6X znyZ@`^^Gj1`(!b7KV0&t$zWHo*s6|W&m23pwsH6zc!TdhYwQ&`HrmBgpYLCiqWIQo zjo!2DUQ7uxQ&DTPDGcXE93%tL^dA0b*%w%0o&Pho;`U{--&j@u#dy}5XaiqKVA*M| zZW~w-8Q6JlO2w%GsERzzSNK8XixCElqZhEMqDR{>V~ZvJE*3LETftWIu_)Pm3r92h z)lkkd!2;^Zx3Wt5LMMtzN6)@5BcM2!b551TbR5(4i{ru{m51Jfi+p~O7-QRMwb=w3 z%?#{+J%uTv?jgk!ofItjJLU#jSi$UjiR!2h6nw^h$Wx4=$*8rS&0ne}habytFjs7u zAHnE<{{U^9^h=@G&4DpcIb5}tnjp27uIlp!^V<6Qj|68hOO#Vv(h< zH1S{J{9BEu7puRl6F?3K0~eum&e{oYjy(hAR)*h@H8(ou_&~u%W5?}XZUzGDkEyPA zuiYx5nF6EOfuN#-w`hKTIFRs*SV zuQesMSIqp&vw}QE?O?M*^6a;J;44EQ0hgqZPd7yk7S!)qM}IOD=2}_RlJ*Fr zE_r){AfcTZWdc09Z(VAU;-rDES9-!Qa)6fA%OOM;>ymvR^Z^KrN`I?ULUL_RP| z7Ez69ahh&KC;d^fe3npTe^wbyAA=K=RY?f~_4-nCMHMTOS#}@YHTCDojkY-g?cL{* zO#8^UXlz$xk5fcNZ=}l!%vIbI^QxU%PVlJ3?td)Z)n+&)@@oEAf|i^m^gF<4 z&aT|Q0(7O!CYn}hO1?z0k*T^Qwo)m!x%Wfkd;7mwifmTWs^l#ttCg%EK_0wp37eLp zLq5EYGuuC@KXS!lqSuIR3{MJ4@%IgC-qF^Fa%w2n{JiWyH#4i9Zms-r3^>^8nK-<$fIJ`wi2sCkJ#FX{aG?Xk1@+^(PaK6~~|(yZDMU6p_z zMvAllr=4J*8jDk-+y3m@S>BhN*O6#-U%s5m{NMT8nK8*~)Htk$^U=9ZsXd>iD_Gk$ z>qMWUsH1E}WnLX!U$ zE}q!q3%)Y-(JtgS{}IBPT`$jm=Lm8$>t#b<%pYA!ZprlZjn4Fil{dx2UzpFKyS|jV zY~#sTZj6ZWLA1H$AHB=x?`&hb!2=TMr+of$sn^`?4UIQ@^ie+lfTk{A<5fJd_-X}T zS>THkcczxN#4^i6yL{s~i=-ShmUFy9dFTUQb1-`9QhbTEXzLFmv$9Cc-QdAOX_aBu z;Pn!Dgy0r3F~3}*QkjS0{t+?gGW2VYsQ;9a@mK+>m0b_Y4bLp2q6?|W#XdOyoDzHd zmlB2jDPW&Yt_ZIHJSS_M@A>8BVKpEVK-~ra^e%wj?Nf(qt41=!0(P|e{t`em?km8_ zE>jQA+wOr9j(1@cVB|DF3Ow?;aET5+2PEJM3a*Jg+G0NyEdgBk(A1VsvMPMfukIc+ z@HwOkCt`t^E9x91q@Ez84*D_>*MtGF=3$G*{|Uq{NfxDPp7X}KBPf=+E-&_-&eW>) zg&W^1j)dy2FC=D5oHXJ%Gt`?x1@ixLb9G}=@%}0E+xpKXCM9;mmGPX|m{(@{UfP}J zdtik>$}?OX{o%cshPB;wgR^3d?7!x?ho6gfVY{p$9(0!g6EZFT3hZx5VNlP`mpQzw zobpnA=Bzu{KY{mo)a6_BtZKAB>Nq07a{#okv5!xt@TKIz8Bj3zT5053qc5fK~asTKKy06;~M??^nS2M`#Drk`M>`-9GI6Qi*+ z;xsRec7BDKMr!J6qG+U6>eP&`DUL`*CYDPQ=?B_Y#NJ>{6%7BYvf$mzqGS437Hkrh zJT1mI)sxe_#h!#Bq!kuaY&VQKm1FE`3fsLMNm@6GyaWxwW31S#u~h9*f4TaV_8J&y z^tkY0iTE!4C*=E&O(D0^1#ifrgEuD+rgDA*_}BQYfXK!O(f-PU6_-cH^fNtx{pjGV zQR?qb__te+-f4vO-SGqL3NG@E(@TdQXh**34zCB$gPQ(zCV!;ojDHVd0lAObUJHc(9Xk)k87y&pi^TH86c+r18^#3m zhPU}>I=QmIQT(IIp)0P4rVo?*`GuVcPhv)NYL26}4l}aO8a#a*&m;6(GiyubBo! zX`!~f+RS~vYv26TcWuj5zi-|Ozwf1e7jt*}+GgL^iQaY2+S>G~&39FkwXF73Ury^j zU(S&K`uif-p0jQCX#Lu6f32H!w#wr`NK!J^o=U-MKlSAd_+nh&6yG`cy6eZk&5yM+ zd%koF;KZ|DnyO2NxgauJ>|ebKT^@c52f|yN#%Izmt9SqH;x|3Z=l)UvJ)yefaV%qj1F~jj{7@< zg*cl{?~_Lzg-4h>r$nwIuE2`rJg;Lewo6jz!_1EkJXw<(<3+PtOiO=#xKvj$h-cgf z4Z6DXns}}B1KVbDIy%u2;{|qFd#ORw8nCZTccrXei(?4#M5urqrK|4xh^xEKz z-u>mM*uSC-0DKGYC#5MlzIz3bIcbYH7Eb*WJKA1U4(DHEKWy`TeGMb9rMBmt8NRPC zkDmv%W>3Au49k|f-u%j##IN`u?gm_Mo`14|4_fOO?l~Dj2BF2UhkxcI)%KdH;B7Q1 zNA{GfB>FOBHO%vnbz1XLk>yUBA|24iPJw+c-5j?o30aVgUUs4zr}z6`jd?odX1_v* zk*&h=I>*f{Ihy^(^3PX5kUPGM?XV>LO&{NL#adq@8NA2@oMKPYWN<+8PQ{21+cdEw zvl=SlnN@PuRv2seMY74>#J-JXIehBWezvX697AiRJUnfCjOa_u3YBYi@P2=XkMlVn z-NAD0^Aib7OsAzDLX; zw*4=|VBGdI?kjK`gs(LKTQi5GhIbItO{cG68s+e~#v93;kRLHr`x>hxGd`E2efb#; z7dOn(GSz3-7v;sRzNU|9rY!3iMZ9yKQwgA`u#fwkm^r;)6emx6QYBA`rF=# zFBa*P3E72qMuQU#H}a3DtGL-&ah^mm!XWvcJI`97Y%iU|YqUpGGz)A{^M|YX#m@a+ zevlYmMXwFk%e>OIEi8Xr3)XmQZ6Vo>T3zH|)>fGbU&;P>a z;yKyMeLr1}X1i#){0h!s4{%KeckzPxtE7TZ9`p}AUo{Hw3tIlwo9E~o;%6%7Y0YG< z&Etq>Wu_tey*xLwlb;r5}N$eBufdL`KhpS7RSe^WI zUYAc5btUoQ*tza80%^wRM^VlP*laa_Z0E`>D>gu%=ZI=@JIPwk@h=}S8ai=`*k|1^ ziD2}x{7gE=?w?FWGB@L7{>Rfr(=6Q^bTy};KWKu~_#+BtWCh!1HZ#O=wT}l%w)>)T z;_@sQ>}<$4`-kvPzWeTDDx?3G8ZUxgb(HJ3U*bGwCa_H9hl?)-`&eX*%cNJIEuZ%D zeRXYbL-}U^ylbPW%`%U$zbxYGituCk+FUOe%RT1zPG{vZrW)dBFRwXQ(yncW*931h zWhfBJWwT_Ea$lgviB9l;g;V>fbmZl5AmLX)hod%t>hH> zrj4~diC59D;wtdy&(-FS9@_Cy^48o-5eUv2#umwjng8@KCxgV}R0E$F7A)B1k5=T* zaV`+!q%-WMR=WT%+Nk)3u^3oXkQZMgLy4WE+kN+131NCJ>k98QZcYyy#A)0*xfYW< zCvuhnVC6b9E0-i)LIm+Z@$>+F}u$n~N3VQ_6*M!{%N= zM;C3kv3J~)yGQyx=B@@!ac=p=4zpdL9^NfLD_HwQhkW*~&vt^b(XBE1!O1@%=Sc>W zU=M7f^Its{T>8dQ59e>OZctltz(b-f+}xR`q)QTcU|SFR~SV zvD0S&eP&07N7J!C!rctBaaNjL0kECewyxrGdlRjlU*{*SAM|-WM)`TCXg+L-UF=V7 z73pEyz=4P32NzV5yV)O|(H6&r$;i@e?=a8KVf8bn5P{^}+JCVYv#TkdD|jU>f6uqz zI6f2?EH-v_TM^SH44&;Nt%;+^-(v$dEHgb{%rbKo5f;yNM*L!1+c@9X+ingbBLU#n19AeYI3UP5mSW{rie262EL<(LYaU`#}#IbSrPcG{}%hZW*{G^ zyn1c>?tSiuZFVA~bp-!;a0PQLM-+I)amv7xst|1oUl3ZfjX*scZL><=n|G~m!4Qgr zfo5?GBr%}hLuZuBG66Bo*u>+*AR8zBEJ+8zWJ;0RV^X=Drc@D8IW!;F0s-b{Am|0u z85CEvk?NxXA@h&WmDW$}7?q95^bc~ZJTcHRc*nY%Cj@g%XXep*D4IQCqc6o6{7n0u z6Ti(_9z+A=^v8^6G=Ax$lz5&hHqW+w#Iv4ymPL*ksW~YxvOg7cQ4#!EoZ~(p|l_zhg%Hw(+h!e(L<<-3>Ja#yr>~-n*eb?N>FI>3$A_{CUN1 zo0P`Rx}0&n-gD)%`GuYj;3na{@xEN+*-G&GRFpVi>L-}0 z<+R+l4RG9E1dNNj1B2ky2YWO(&pFBW{KVA%0?EWwT&;KKRP@^D!jLW)WLRWn0Kws6 zq)@%y$>$qc%=I(k^E+A!BOF@(_aj)p870n!R&+1xl&n(HLW2EFx6kR;jN5i0!AX7g z2&o`e*;x#*<2M}waOLAdiJ#N#x|pHnR{-d&hS3S?<2>j&T0Czx67xal#Nn0@t0i$5 zn&#uJ>P)}j_m`~pE%=!_oMQ7l-{wDjG|n=5;@6!d=VpaFTwRvQjzf6!fc1ODo0H>9 ziAHCeKL{E%yTN=c75oH_^MX{wg3`uD%WfSWVis^ zOiGxL2QBvbI!^P(Zbyh!XBH;m&M53GXFX~5E*xz|7W-W%b&KSy#XPg}Rg#Hhj~R21 z?r zsS{}mCq*?KqLe^n1_v&u`sZh+_$gt&-(JJhLEBqpas}65$T;D((=-;{HMIML)6Ow)jT98*J~lmg`+3v_iRR^{wC%fGZ>A?A+ex z-@iH7E60Dz^vpo7J+w?mNc;D%N?G1xpl{*%LOVao&_fjfYAzqa+Ju{@E^f!o8*4k@ z#x0@2{b)EJ<=Gb9mG~&nY3}e*9v{J9sSD)Q0mO_#q0lXg?l#Ygc~$MlZlV2o!2{jR85bhT}2N}k$ey>{m+%$FA@5qrB94Ev{yTtf)#K*^!G2=FKs#@ z({#fA<=`B@YLb*n-?$dHSNQZv71PTW`6&1Ci+Fg58+x^!1k+p+LK|LlmC+$Bijy|0K&T$yu4q+(?*Va98(3n0v5NosCuWrcEr$`k|e&ld;G^Un`3 z^iuNTEO?NeNM*4;CsFxGyB?A9HooA1O`$@6OVMU_? z;hhv%G|tzDLUU&1a5J4bH)lqk?(%e3s5|qvOn1!6IWwwsSEajZ-9c>(%XMvdE8Uwf z>DC{`X^+QL#&qeb_F z;qHfbj05CH3|gJKOPFN5+7R}IYd!-leW;X{aHCpjiS9^fiS9^pR97F>N=tM{LQ8a~ zmUPh%TQ8>{&ciXI(~NAU6X(|79WgDN#d@r@D+`F7pBF$4W`2$+IB!Z08XeYg@MrD} zf7aE$%S*iD&Og68vuy`}*mq^TD>mP8XTH;Qb(xk$oIU&GC?QWV%yXQ_Fxzm{9P-|v zljU&l&v8u=&J(|N;WzSMY%=udEe5){3jVr0SGM2)fQ*Nyp=9NJTp3f~@6PC}CB=M= zLgSmd`+j`;_x4nJkYB?8J93oJTYc`Jqx#&Tj=DpAbVoHc71^5JtH3kt-K$i~Cr?nz z?>p3D@jC(81lZRR8eN63J;;HGkr~;f*~#6O@#QSznNcE!zDjoJ>1vyuKkVP z>FPpX(`x$*_pvfK+116qra$S45pocz3W*@i3_O_-pR|8+^EM*V`x@^zA4$H6jLnl| zPqyp1nK0ZbHd$(BS@9<_w#>Y?@-3mC%WA(t=x0BnpZ(6;SD5(F{IDfe*^)}eSK+=D zxfa3m@=4C)Hq$9?rU}#BOqWkn5b3eiR9x+>yl-3AL8PDfO)~v{75h@%%y!(`@c0~I z7OBd0@snFSfnRxGDzBENRiTr+dU)*x$@og~M^1E#fCy$usAAhTaA>i_&4gU1Z+8G6 ze7pm|w{{>{+y6}1vYrp!V9NXEO$70KSr z#VP1e;`459O8n{jro^X}cXh@)T+Di6b;de35AyFwL8%fSRjx?(V_cjqSX$a)Y;to` zV(H&ZiFfmaCBjqe5r{=P3i$GWYOun6e=ub_VgAPwLKMiX3`9$ukoKruW%R7kE=lOm zvm6p((d&SK*#^W}n96fh+xfsG0jJL_k{k&*eP)s5OxMd+ZYTZ>MY>Ety zu;6!ERBDG?u^e2=6b9VyT=rNpxAI4%?(f3tC-nrnAHIm)fdHN02c2&u3jRnKputN= z_>b5|%KHqx_V!bC{@(JJKCls&KjKgE!c%zcUqBESBzBm$e*1w+LsJ#`fhZP#3R3n1WSAbk6Zw5?ZZN{S_o^Ju zI`TDYtCv6Ys)|pky?xc#JSsmZr!9_#T5uCQj@5lGE<`x^xT=-Pp&Kft>uH;pPIiPc z^RYj?M6iWQUn~+~^z%oSH1OM5hb_gdiZ5eTyikv1szd`*&E~8;ej>c|9OJ4l;BU)% zLp!K040nwVc=>gsxXCA`<* z4n`KLO5`7Qj5QrkUj?IC0dw*cK`2^c7gZ94x#eIQ{#|eS?v?wFKNb5Zq)sDpO(UFL z-}T^+yrjbXkw2U#X7CL1i_x@DZy%sX==oN;@TaS)~X*O^g-$udKl{_qbh zI8sW6f1t`kr4O77F4?t;&UO-qV@7_^z+=|m&ciRs`;4cCXs-5%CVqpJ&vgFYq7{ag z4KcCLDS)cF0L}OznxU<^&~;0|cZIZ(HT{L7;m#^!`qybT8Y|RhFd*IeOcfPgVgWQ= z;ZHSPpt zm5Z>hoZ@TTz$4c`Q>P*~EjC1DJPOPSN;Qlsys)cWo|dv)-JsFH!)hZ@MhBd|(mtG| zhtu7hFTG|Tatu^segm~ou-Ja?OZIuao(t>l^HlTPjeNtarR}et${e>;rA*F z)>i5Ojx~y$Q#o`SR*oY4QESqRmdD3P4Gx0mi1G|)7{rX?{C>eUdfN<4^H4Zrh$8os zQEVVr2k&S-cNYYXO@$+e>9U!lwJpDZEn4dn&IPDH(l1QFOBe=i$wYf8Be^2cCSEyP zUxef~DS3y)rMpue@#yZwqs{-Czv~9Lb9W}PKOaH7Jh1bB zPx{v_gE3q+Oow7=j?pxLWh6Rs$k~j$l6^Jj`yE4aKD8Te!2*dGkr(t?Fw!9UfrkpSmWOImNIe7*oaf0M z95aXa%VK?i9j!MM_~%{djGs&IL(|#g?=*>Pw5`_qegE8{7;DlAGJGJfCQjO`=5M6g zH9NF^7BzRWaO{}uXpZyMiRz} z7+o^4($rIe!FDoQJ`#Q+%?(^+>ND1VV@>2igMa9L?CS+P{bqw!T65q9@d>@*o+0I0g8^_+@Z7g z)b=u6jeph2{#R{Zx1H>7+Dx~Z9`0#-7{hw;rkb1=hf#>LSIv_Re1~8De1{=EPieWh zgXfg<5jzG9&l6tgLvM{0yPT>zazVpC?{MJffdUcV|!*4FlX(F~%~121}b4K}T<8Hhh} z!@;=;{Jv;LP+HNN;&r~pu)aNbR_!VH*zdl0)^RTus7=uUGn|~1_}MR>VSin?hhHZ* z92`}9+>1l)qo4eoM_DiSvA-V7CbCpy@lt*TEvMA}4}@BI>IJ=(qggUmhTjSl9JKTD zuFCMcl?A&iQ@0V7Hh!Edn&CvsF)w_-W$p=tFB@FaaF}7$aJW~E({MPu=7WaAy=&gT zBARu2Wy#w!C#&Q9T51;t3)WW_ysb01tl_4T9Hw4@I$`-Re4fE9QK#Q^U(p zleBi09iE0}-B9Nf+*9O z`GAX#m_Lb#&G`C17j}js03xdnv+ThmPzF94Q%cEmq0fx>cdOC}2Ylec)rYTW9|G6f zIXj(UfU5QBe`?-O0ORok=Wq9Wz(`K(IOIG0GVtBz!pE#;ghEeJ=CpX~&Q;xr>P8lH z0oXJrx0ZeH;&F*a4BZEg<_&Z-ngkYj!44)IA&j}r@x-zuH;z#rsH(v-tJu^8&<4Jv z(a+)Uxh?IQezg8@&rdw-_{91{qMP)Sj~nWkj=cAunmcF?o7~Fkk@eWoVh1qt(>~wA zj|Y-HF{yJ#K=v(L{bp})ALi9*6p|AA4f7~^v3m4~m*#20$qq6BGrwW^scfHrg$EM{ z3Drd6xWP!0kV)Y$48z=7vNj=PdNSrIo{TvNF4I7z<*U;BbS-3(K`dMGgE`;sbl`_0 z=@ZzH7^`f-|iXY-|$@(nyUPW54b%nbF7}v0w8I>+^~4x`N|q z(J(Tj-N`39t44M#<#oI4c(?AG0Y(6p32swu@A7b~6%@}7yyT6(%BEJ1H3+wwkbQG&SO-W@>}|z}3|>f5^fk@T zhDvc;#M=+|r3y+sbe(Te3F{BGXZaTWRdsOUKlB}<%oJ(u)OfPby7(0#`3>_mx-iKCbuhDTvzAUUcnOcfw_8~2qeXLv0T#74N(;WMVYOH&85lJPQoW>;(8s%{RE}T7j=pp`ZH2-<;`UAN)?Lho?b0@q@zP0GP|uKM=92xgxs<-b#oNd& zW_#UA5n59{hi#ZyLvq&42~d5eR5#@YwM1}?6np zf%zVl%9(Am@A`{D+Z--<-ipL$W;grW%5sG&)+ZvRAKE-W(gg?#{h?KaDrhICPc8wy z8-Lk7dc#lI8TYBBf-jPB%wR(^Jap_1icKMf}+Qn3(#d^es4lww2CU;-0 z=BI{393PUJsao3^*>Zk&-yi97(BT-)9O-}F{6n|b-gX;ZAPr!07o?jmc;mNpfnGTe zoZ@!DTWVtR{MT(42tKV?)D54#XS(6vTyQQn-EeH88%!tk-EMO9)5YzC&yzdh*0FR# z4N^j01pBW^jqE5f$4B?G=jECcRUacAWGy)0vqsF-x1c z1g-=hcIUt#^G5spx5c#P16^bU_$~rE6LKLohv7`f%^)OC`q6E(D*fRN-h4cG95%I{ z9YHG$mDcnZXiP|)z!D~&RANH5zD&rQE94T%j7sNB8XkC&8~rt~CV%e$w6E!tEzZEe z7U%Do@i1u;;8X*_I$w07UPrHH5~|`DJ=ClHpm!jw3jW`^;t8uOdc(2UGsR7wZjgj} z>!i_8>GpmGu*)M;dKYT**;|-vQ1>Zkp~=aM9FC4Gn|CU{iK9ZLPk0~n?=AW;_MOUb zzX_|;nWQK=GO_n?OnZ&`q4k43TGF>fqM=)@ydf#6+LV;7FLIrU)N6{V=xxLh6YCpC zuqsgP;damS<5Ha8;t!W3>r@B-Z)I_1G@boAWp9Q`vrL&+%9q5`OMeZlpS=0wb+be%eM3u>YCC@r<)FvP^=SnFH(3Lhba1|kz%yOghfr1#14 z)h}#`kE%oo0WRJHACG;DDXuJs*yO{r-Zz z9S)j6UEK#+`Pw4XX3>$)AN1klElr>E_}j^h))!}s&;Wf^% zcw1XH8Jty6xzj>oG#u0ey8NuN`66t{#^E1=LaNKI?VP*N1Wg-%D+RKElbkb zQcn+2hY`KflDmRJJZm{t zEg^y#QP&)8d6fe_rEL^{9?*kJ@{BuP9DJjpxICLmmW4Tv=5im5k7TI{I|~E zF>V%Z6#tcB5s7|8@A%b>8QWRvq9~pmmOl^rioND*`m<&@q5qIK7ct;EsucpuXtVy{ z9SyoF=2X+Me8`IaO@0TwIV#HV4ESE!#ftYy_x2*+f>yGiBb!ti^`m~R(D!fp7ApJz zRaLoTsq+7p7o!#+bn+F^^i(l+f5}01p$j~=qc50m;FOC3i{UDF&F`20i>I{aNGth% zO(GOuDkowQ4OpkWu=%(4%*yC(`EWGO-yTUZ&77~1>RWIsx8^(;S(ieu6J2IKnah0N zUuB|M?{fZx3f}B>*7iRHiRrAM-T7KVy>>QhPqb^fBmxq^oA${kYf%dbFm5|K(p$Qd z=@9OD>qWmq&gbGbAyBY~RuJjPwR8rC?zt?QCGsLdsKyda5dL|G?w zGrYuSE2CF3yMG!e*yPR7l{%MJVO4{OGlBh^t_V+AdmvuQ_}cxB;4A$=7Zfx}%e69U zbWS;HO}VD)XLeeG+-Hky)`bCiZl`jck(9gchuyY7+hzobSquil#!%vqRxuO}mtrVt z3;mHpu}f}r7nR9BW^(uSnelViL-5BsB{P)VrsP{nZX|(!PS*W3B<_&S_l9i4EEK(` zzWjt=K??^D9@n_N<}W(dw}(`!p^Mm_gIPu_0sU4XzZB3vb~ZOori$!gisanjjdO>p z08R~%0f!X3C~0=hF2Tng+SEXF#CiT`9hTA0YKLK9xm4QJp(xGJ?{BX?US>QVC3LFc zZLz1AJ?!$>T5fKW<6-;S*s1tIJGEK4)D%K|tL|r=sviOOWlF}AG+VRA!*{y+^_b4j z=wLh052K$y)wLhwN^O|KI7*RQCfa=Pdm_Iu0pxmSlFPjE;;(z(`xgEU<&IlMeL~#x zJXs@t^z#TDv6m#S5ciaNRM^@WzLyGDrS+s(}K&%q_$CV^m4k z6lqX?S52URXr50ScboAT1n^qr)sveFo9m_#mja+AC1Q?r%V9xnRY&WT@cSd3y z3WWQ4R(Pp}>8#M}^)m0ciV1|YTvM2*6-N3P`T1+|>*#-;XJ=SEF`vV+>_m}@9@p@* zdNhoyoj&L{C0Q>9Yc`nDid#r9e>_^#$-YIOu|%}G zS|7ZWbxwElhM6#=Pz^@zf0HT_6UOyCb0>^>?k(}ZeG8`SX@avb`>mInRLnWxvbb(pH&J{IvxNh3z2@=yDGeuk^%xW)ip@B8K{~9wp z3^14b1$m%gxgeM4?yAHDv7EpaX+c?Jw>YiHt}?ax+dGk(jjne`YzgZ@dd18Dnneos zSpQ4I|Nn>*5C`Hs|Nae^g)89yCo?haep3)+f563fUg7l861$XQxSIaecVV#tc#Dwyzxh)E^eMV zijGA|zOkmr;uG5+do6>l2h@;Ct?t4T+Lhw}TxD?cFD|BzSM2XsbrBD}3KYBbjG-Q5 zKe>IjEGJWIl-^!*Y-|uOxUH$Z=}S5T9A=NP6_l#Nu6z7in`1H;w`REud;FP-P*DAv zCtp&T>@4fwFs<9bCH6*pzyFR~e{#QXvH7+tAA_o!emC-+I)6&%&fi~+ek$#f&K>{V zGGgzs%|6+V{U2mszebtqmvI)t@wz1Sy(rk=L47}KW(SL4MtJLMWV6nYO)z|wB^j)p*)Q2rmZ_9J{JzKj zj&KqG71jKOf^6T#IV+kKp?C>~n_B!%?pex9#Y!mH%MZ=LE_3w!!--U7W^SDtZ3a=q zutS2SU>{8|!Z#-9z0WW4UVPnSb>@KlQS)a_)5P^H)QAMH^!e3o#`_e*dRr|4!7VW)-Mi3y}d2@vhxQ|L8#L-#J|d z`bq5u`n<&KC z&r(Kg^LvW^Q&zmWHj^mtvBCdoYYT6x2)8(C+a#%XrgG=E_lgRPc3}u!8vW^8=mZEHJCGMyj&oZ}dh$H50AY3Apf}->-LN@K-;-5{8WgKE2*~h65J0E6MeP zm6OlyTCNmQG~I1PXsuZa9pl*yicXVwT-CUSy;Iiz+3(!0yv8fe^=HCA&f+P-cRo1H zMHO4uBp)mTVfGV0YBBSzSy;)9PVYy5$3=tj)r@5&JfG}ROY1A&!dQFz88f(MIErW^ z`Gmf#3CjQFkL*u5TbKnw#&vT*fJg1)>FR!FpUObjvD4(+D!v`ku?}u?xRZvE(Rh#g zS^U4`&DqmbC3;>ffLo~@Iow|W0eGkI`G>A>^`&PFHu}=789KcVhab-Gcp+I|>be>( zI~6=>Xgd!rG8m$6=bdl|8WDa@ysZP7d<=f9hb>8A?lW)<> zWOB!~tEf_t*n-3E9w7PKr@qhpOgJn~r`s}j2ty<5BEw)^cV@$28D210hF5mnLN9ObXe`_=u1cR;#~S(%nz_V zlq8CrWjvx|?{eqrAIVHaft%qx)22oh&lr^5_c+UaiiF}AS8gY7)Sz)<7nEdb)hZo z*IL`!7F)j-#VScV0XL;<&Y$GCvDvMKq$KhL>$W)cFm{eOS|-}j#v%$>RS+_OCA zInQ~{vo;yOik^S=kt_--#0=vu4T6oS^d;+pj4XPcm+0DV@QmGNUD1spMB5QRo5@7G z{5%IJY4^X7Az*u@KwFd=A*Lz5i0L3j7{<&!?!}l{<-D<&CkBuL3g4Qq6_41Jd~wS~ ziXcP2U&6SCl-!Hy6IKX6;#;#mwVB%WyhKO(w9DBTSboKz7agn@4XNd{nB9$w6Lf?5 z$noC3p;4LT!V3&Vki_!XP3L{M zrk7WRH)M%hUSTb(3V(Tx^_N##K5y&mC_ISlAOHwPRUhho09j&9jU-MlccxU`kr9hW zj~Ph-n@vjcx%;ZBjt!DI7xR4@=^GPA-SUhWjc&K+4#q8eUwjpzwswT_~Q(U``~&|0e-F@uee&cXNSVq9f<@hQNb=d!2%e0pt_0+G0_p^k_+MkS?s>(9ZX&%oq z8}+X{Son<*!uZiy8_EE$a+7;lK)PaBEtGR@JbQfQ=R1HweJwrIqW z@X)(-=Ki4k$o2by^3QE2cJMte1K+IurQcfSw;;2(fZl8%Vl1NND?+my4H&kon8Y)! ziG9@$7JDK)HbrpHjr3d<%Y6g8Wl=&B+`N0x;Lr~j0WZsu2!p)d`;mij<*%|~TxK&S zKvx3efjrB=_`LQR7(=boRAqqo(F+d7MpXhB2UNvi+{cG;t4r0K5UfS8MKBH%tJ5tH zZ+p$YFa|%a+Xud>UuKvb2j5?0;5%CQGY&z*T8FvfapZKQSqD8GbUAb1q;&~`1^PAL zVmCs(&C(6A_&VRNI@0qEaJI7r)aSgkUN$7X>w$r`do^WXBxFs&XTS81Zrqt_2R4s8 zMg}nkT;qL~pXHDTrcuV7+R8AiHplXDigPQ0b@G&hM8?L!Uqqb!c&Prj%x)wz6BTSW zMqfrf?|W(W4C1}g zC79csSv#oI-U*FJ^k}bFy7LN}k>S4m(Fp97n%f`k$${Gm-P4Hy`wh!(hl;j-qQ;3i zcV+t`)wJezzb4-V$@Y)bdODnrn}64IxhAkly7GtEBpu#YQ{^Xdj1M!LB=|<( zCTX&@GfFl|f~z8|Xq9PJ7U?Rpq-twBFiUDnrK~8!--Z9wvIvR>i6UJUvQBbU9@si5 z2*~G8KTNu&A5W31mvX_?VLttcCc~Bbj`o7@{yl!L=C?2pos);>_{nphVdd} zJ|oM`jSf1Y(FO8Dl5vJ=kF&xL)^MNAz2pc|*dnwo_)A>R-;d=s;>)4f;8zecMn=y0AJ~m@addLIpieBM^*39da`% z>VG(KP}6GdV4O@{OmhXrQBmwQv{>XUwwQ6>Hg9kHX!jrym!h=L&gYP-mv-wXw<8EMZR zD*Khdi2vRjq1v}Gt>Z=wH>3(a5~Z(vc{ye>U=>UKj*m!kJhlQ=O0ev&Wa#660t%7s zk)fxnO3oiceu6LleON}ZM2yCl?=x0)RdFCSR)2sR-|R2j>G!-EyZv|rmstGuSm}om z{EK2ecgITi#B$#W0>j73-*mIo)t?`eU$&ej{Dz6HbXul3xne?$4cLiEdB}}NXz=PD;C_?erOhA|Dq`+*C4paP9j9A^o`e^homCc77mDL}=!4nzdNsGY9ew)|Dk;0-&{rovVtZNV_5HXN)X)UqC4otE{665|7*rN5g2C0? zN7(9X*Kpj-kfIW_iMC#$=x2oL>lk<}d2KF<^`dxmH@zI$@s`j(*7KuS?z_?CHBIOC z`&dqbe~p#DKkY~c89mBI__0RlX@u`;gqw#aqXgea_>6V4(?5{^>zlnq}N){`iLbSs^NYt@iWnIJD*&qb##i?NExlXKD5sU3qca^4 z>UlJc03ecxyFOMx-&Tcc`&s|Kul}*W_UHm}=@Y7(h#P)G>K}|PL(u;ta*o4I{o~qk zkDA2=p+Pj>tp{7<`t7S2xuSPu1*ycw_$K@s0Hlll!*Z-ddIo z=YFC3p8?f3Z%1aWGv7WV{=t;5GvfcOX_FZ5r`;p1-T(3NibtxB;_KFuClX)tpDhEQ zagQXPF=Q#-GK}=|VT3rzyy}A`v{UlQX^#oHN30|YRQTna0{suqXuziZN5kBl@7iFKOCGzlveGB0U zvk%lQzB~EJ)$A|6{I3Fz%n{!j<{0|R`Q}91e#|~F(07jt)yt30Icux>djX-+ zq!uWe^23}_uq3VSEnq-c$dB^AlfO!ri>Of24Tv9)%<2TbXTAn0|EAAEwdZLMarTdB zWt43V(Y75wh*Z;WMI(}pA-TR}gH9sQ&}VX7t`jXOq6Vigzl{M3;^nG0{m^Hj*>CGK z+FUf+s=cIG2gd((>=!ikWy6zQ4+<1)$7s}@-eWOp$9KW2Gd=Q0jTou}fUzPAG`kWv zp|}(*qFAcW?r%Lc1C(guVaEw9i4v2>IDxH1LWsz+a}z19n(X`@D_`YKD{RV~DT#!T zIjOk$<4n13c(M(_8O*$;y1OL&LSz1z0-+{28)&lA@xzAlzhuCHx2WdRkG7ZX#dG+GO56 zdppCHoqF@HMB`4NSL7#o73)O&|UA(MRgoWZr*wuth%I!@lKPUu?}* zOJ)|Wy+7)L{Vd#TF_nJlr9k+4@SJ%9Qha%fNP@O%6*UDb2K*$#MU4d$uEkG0ob339 z>Ic5l&k83xo5$4nV*TvvzV{9|DB+I3k>m6%_8ds^206 z;zPd&v4WO}eoXA|(~jPC1SjpcBL1qMyvgXBbz2%6(mLL9+7>0V=}n~~VtPI*=8wPe zsTQQkeoFo~$I1VW1~+~A-!`i>$cOfnA3yoIk|K&on5Fp1;?rF0;{AuEh5nxzr)V-T zWhFHLuM)&pxd;@x*m4nA=wi!7V4;gG7lDN?wp;`jy4Z3Nj92*IiIPu@9~qASogY+T z83t5?%P^oCT!sPF;4%!T2A5$#HMk4|<5kT>s8*dD1>C=l3dY7p$-%9du6mp9r2pi# za8o6yw%8gZGU@I8V|eRmCT_5I>VejUugrk**GvXS+!Tn}_NPE_5=$I}s;=a>LS8EZ zv&2UgcCB*}nvq|XS^4MuaMO4DQ#RKILs-K5#1$fyo5wg9_IP4f@GIx7yV|qa>ae z`K0h7E|O9S{wlRozmwB3aKC0F;@1YEBJ%V>yPMbcC&;7Yd%O>}BJ=bItNvU6nBW1{ zkDx#9HIPVQv`^=1VYDZKNiK}`BrwT^(Vhe*xiH$3z$BNZVp1ic^e)(PK6L#rRe1~P zKu&dp4oFGbV;+(=r>FP{|(rC}Wgb&94{=9K28I4~sxpvS`H<$pK{B>i!r%=Nn zhK|M00lzN8|B9GPbZY?r|3!#yA%fU(A%?^am0Z2|AAqWY+6MWgsjg}V^|kg&wQw8g z1Z4EIspoQ0i0-GhI5DxCs-OT*7_Z=?P~8R}3)O9DJS5EYZC0ATpDx1GV$uHU4H|I#V;%=|e-9WPwCLmyp}Oac zc_hdKR!;VJbhQ32p}JpiI}_g#^dmxIsP107s}A#5!~Vcs0$;16wYv|RN<@^3v2X*? zgZ9E0j=J+3LrAuE(B3gKcK7NPs*~|HUq@XPsym;rjXly&Z@MW|cZz#DWm>4Nl&{)= zsFWx`gkwrHxcUD}ACi4sgd^3CL`cd+cpR2>lf?}^HB+lY)g}I* z2@5+93fAylo3w_PRukiTG1i;$#iBgu%3oF~2Ei6_1yv2>%{wN0Ph6}(f~qHXW{pa? zql6Mzj4TY7elBZGyj_&2Ng;_Ae{z=i^2K|Z^38At3>b#&?w-(jucs0+gQzrcVWFjA z&l8^$&zM-GvEU42W1$sfF-?RhcVMyM(AoGO^eyl|rMq>TtRbnDITeLbc~1W> z6M_1)g7eF^&}>I~?oiE>@fV4fE^_?ra^lQHlWp4aM%D4!Co8aWHdXI-@0=Snzox3T z=2bC!Wrd(@zK)+*qvOXdDAt$cQJ=jv)CE%V9)AK_wX7mv#!y5_+na-yya8AHO*IQ)-T%$=WjG?h1h7=oGnz!B?)Em1} zZ zvzfjDZbcG}*aFcHqaWKs^}n$q0r?5ne-^5HP`4l}4dCxsXv@Jo?8J*|c_st+dZDCaMN&Qoi&e-p3w zs>bJMr7S#G8oe#jlf>M*A+hdu7!Yy%x%Ps5h*~_9{I+nui?^Gy5ousw@e=^>T~# za--|z81x79?@KmWavxJY)*Yc|tq}0f(_+oUcnnS0Tq21gI*QWkXq--pV~I<)??gcs zy4wgx?cUt!ZDWb(_HD|oz5@Ckj>za|B}0i|Z5>OtDJK`x0CEFN=5Uh;mF2@kVyOoVeWN3gW*;x2EsF|fe zm>#Yj^yDi(QNkuhsRJ&s{8iq ze50yU=ApfSN@KRtcKgVU2u2eOREe$0Fe?-T7^y2JvpY=i67IP{R#NdcE}^kDszTKN zMOO-bXO^~-*chB1$7-?c805E~NMj-{te>$6=Zx$3E%H{dcMnSrY#*+jT2h=djcJ|U zM6m79%t5@P`K@gte!z+RKuQAVGAbA2!@Z4Nv@66n3jc`as@%ak-^N0^j98O%`oFa^y zsfO)|86HYrm>2;_E(HI0mql@TahOO6_E*C^5Q?u>X0qO?SAe@^`Z!S^$LXUdAK<^f z9>xb){nK5x2p(JyR-f};fYsi}fj&Z~F4!lOzsXmQ_HnnjI$xo+9p=bYOc+ zG+oS*W>i@;*U!I}yV7TKv|hybIkGMR|5+$g#d`bJCv;^VPos&EMUm&gRsGe(dcKKC&*W%gER0{p zxQ2-F@AjnpgX-@gY6ZVz(AP_%anDrdD*_IG;?5!PzwMz=PN}R00ou4s6%bl z6uXE@b;Nz#uC6cVEFIdr>5PWdz1)jD7w{gj`gg1D7#v^chanyB!jP&j>d2-0bmZe5 zbmYNyn!=zDY^+2(_;-8KXK4J5#zSbCEBb9sn9;w;ju&$VaONErjW?R+^HppH&M)EV z0Y{Ew+h6xLa&0@60sn#UH8i^ioN$fer>;9lUpT5s;%n{ecKz+LpGsPM6YiTg1y>uYaNXX`n7)1Ki{|{xKasK;fW#KW-Bf zK?Fu>$+L|+#it$;fd+9Pb+~W>hTp`W`BDSG3{Rm1M))CTB!Z|E|ApJ>-_%F!u}iUV z-54!hk#SoJG8DxZ8Hep9C#S7RMh2tOHawQiiiN;jnVX0dcDINLswCq|Xy!PBLAT<# zLctXDSz)K>0W)ZE#cpyWvOP#Y(lVhcGzoF$dIK&Piz_`9yikS z_3UuFyUkhuv)P8ZpL0nW3#sUX#E*Cln5V-J%Kv|tE4Z7B@`vbgR{TMX8i^T8TnN%{ z!XKOc;vK@7_!BmLhEtMgfn8+1h?*UFKo|G+!tuKu14+-ldHhdYqV3rnzwaJl$4EaK zuR{Sa4TD-&J!y9$rvK4?KiZ}btJ?hG@k`e28>07YHaE9f zx$HN-?Vntk1-k4riqvMTzs!N_4}78HZL(KD8=+tF)MM4>)dzi@KFil@zrFpq&U*U^ zm+YWuE*h^vyo2j&$JYDW-};K1*P{-|t@ZWxZS=L|YxPwQVf*dtVAt0n`|swzv(=r?lF4MUtqmH8{`Wl6p&1 zDBKUtT%xZ*s8f|ox^nlZ+<)s~GfG3)QAH3b#&&YT?LIl#8jWuX$jR@&0Xca#rzJT# zev!yYX99V!zn+QWDjiMqAfp-?s*<6S8Tzs*5?_*GO^_T!34aQGc@xQAR`}C*XW9tg z(}m;RVQvD9p%b}^d#OW!x|BCH8kcx(poQeVl4y>9X@J!%*7}W>ubn^(8!%7g^b-v1 z3(d;gO@u`7nHGe^L`l8i1v|z_9N=9yENfhfl4=dO)-nUk3@c4GZA1two~2v*t8uh5 zEy9MyB7~~8Yx?UP8R%pv`8xNbvgO8!K{skwBLZVMoPpL3h%6g=DD)CE<4du=#F9M@ zbxsTqKCfPPi6yQ-v@9Cm?8PI#6T{~!TxNxN*360FdV41nOY}HYuUy6}lKC!cbEqqR z<)Lz77)pCHeE)?4I_$UU`!5t*9fh&Pm4_ColFmUTLk}%dEpGq)8{aIBYVrz(mY#t} zuRWIn=;uf6Z8i%n;;BCOXN~P5Y3?3WMFB(AV6_gbB)$a7924dv7ft5HsFtIGm-knv zj&kJ!%_4k|?2uhe2X;;ij+0t2Z+TSg(3*JoyH@UZO*4v7jI?(+dqzlXN@K)&HbXw0Wy_K-6YeO^JsgXF# zpc&pz!n8cMyj(U@p-?Wj5gwNV zr*u8D7aDz%t_So^~yVo^~C9Un*)kqj73> zfRg1^W8#}@R~2J(S#`BLvtJ%bURjb${+Kr=46;_!O_r<4_jYYXc<_`j8VH(htzCBF z?oEB@R{ZnEw(-sJ&tvheQKyjR{Dyy;ozKhdaQ=FHGux-9{4UML1M`deto8BeI6e}& zWvKoj7zz;xNp5O1a_FP_e{A#q-~IvpFQNaLCe&~1XRmPLbXS@)V$*ubH=9EB4{N7H zb;vf~HP`~bNiFo>+hl=#f+*8?W-J|ga8s|))A!kQ%f7g+`BgQJ4JR)~{7yQarSvoH z?14Of=6v0NG$VvDL+mY<^>jG~3=!h2hLhjMn|Nh-hvn-DlV&M*wfEkLrl#6$W}r7( zr;N$Yhe7mOG9;QU(B3QrNR1UONuC4sB9`9Sv?WvY8lL#)=b6XZJqO;Hi?A3=JSZfN zCa#BBD1G;WWS{P_fo=uoNJ1yu;k^vl0=SS%T0_*IV@TpNMWvvBPecEz zNy+W3rW(6rK{$^m-o1m>s&AVvV-e-h{(&ADnhb+AIk1Q(RKHep5r{y<9|ZAsui=3& z|B#r(Njr|t0b8g(5O`Sp#0kdNq@^7eGEveFxE^F3l~Vixa%g$5Qxp8zNk1}?6BVba zbkzk(V$cNk)P1AL>p+nYLNnV^MIhh8a})XaHb$nxF{oW`xb{T_*sc8neq@mZD)D!{ zOTUwrn;=tmcqgbaPBQt)+q#sZ#m0#4 z6(7~2Jr{?;G0adAsUSP~MO35Y#uiQPNVj`H{O`vgNRA{%_{4vCXAY+1j3t`stKikM zgeaYDx||SYWVR3m6eBxrmjxHN#2_{G(V2&f%DiTzFRN zoWwURS?j-KB*wpKjD(v=Q`!e329!U3D*$EI92x&`CL!I@^N;z1!kK5i_|aD57XJBX zR2B`Z(Ay1XjeF)ee}~uAAKCJk6wJhe{|>4VA{Jm=qKio1W}^V~L>zyTZ33-)MYByA}isb5!hef%?DrE!I0 zk1kew?4PYPd4!r=vhCk&vQH!S03Sx3>LSouoCa;R_+o3k9|GgAJB9{Xu;(G0Q2x;k z(@U_4=+oWo*UA5k{W_Kk_(N~e{P2z0q!fXAB>@Hj*})NAB07$hZj8nM8Y_J(7JoIe zV@qUl6P|!L&75*3%&G}lt#`4wC&lPRg#eM%nS;f|5cXoX_9W~*V0gYq%>n4mbHXqr z+H)=G$z!E!qKQWh^ieqpf82PsF9hKT86}KK?rzripEo+XZZk#3x%e_-RrqIyZ=Ff) zGnNRa*)GVn02#8}ecE-}{iyc2)23Sx~i^&-PUth9@uSCjJMN-Sis~{Nz&y z!>){!g22S%mJ4d$ov(HVBKQZL+Wr~E@##hr-mkwW7DA$9#s}J+!h+XEL|hzR>6+D1 zqdyDJ$m*TMEbPU`5IGsYsi7oapIy<0L#P~VUNPEzpDm69P-wS4EgZ8%t3Fea<|jIG z&*vv(F6{V;nKKwcz)YBY!8nS=oLp!r(4V9^iqXFQWG>IYp8h2E?dE)d&6lyKt?N%l z+x~y5>SzDI)$RXWzK;InXKe2xea3LOhN^_Ojw|q0C~7>sw}@4`p`3)Wz0D!Ag55Zl*zPB_k&xk5|7LNlz44iJ9&0d_tqKu;I{M!zI@HLh}%{$#kDn+OX^j+=i|&D z`I?ETOSxKCu1@8Csd9cSWxxoZaD|hE_97g>gzF@LMP|5_qg>WW_2=ynhW-{Kx}b9i z8?Y5T@;BlTOt(^YnlT9JOovRZ*4Vg6JdkA zvjMM>i_SL)UD~?|eA4mFmfGO#@q-js8TyE!SAWOXz~=88S=rV54eI@YtM`XojOn@7 z{l1Qin7aBh;GS88va6mr#u^Tne;%4ypjq*St-khYrDf0LthWR5+3a*D8~S%AXs7`e zH^Xv~4>qzIfMI;U8{S&jS=1Dh4n@gQ#m6mG1&lxSUv`^d&H>oJ2L65LCIjJEF8jm3 zI#;CLF2cWytsR8<{rU1W+Y~|#4+gEOVa7?f?JkJke{lohKaI;GZYl54Q2xn&3R) zGa3Kr&xish!#nO&n%-Z~=)3+_h0BL<$Zob#??U{4Q-!+ z>&d|pHe+{KzZ;iROsLvE(?^e7(w!guCG_;#nq6m9BiBy5sK7^tezZ9B^onq@O?%|k zjd#@S>QfD^s9DXMksXV2ilMDKtYqDSf17xbvo3^D4d z31JD;*g-17i9c@TNjUWTSHcG;w&^RkF^22fLEg5FdE)VUOX5(wq|En_@$Tv7AL>%? z`5t8sK3&*aeE8VuMR+7VLl#teu5QSZ_m(fNZtHS5muCD%BK51QiqZ#-PVS)5)}?U9 zMyzJ{8P%7Eojw5OuZ}ioh4l)+CY}~1eiu<|CmdrIMkwoc1xKLxT2ST`%<-HVBaGbA zp+`0qrxbJ_xnk<4c6B=qKB&_8n!AXtKhmJUydKUuf20))Dg}FuR|rir>OKl0aE=DZE3W@L`Oa z74=QrikopJE^NLma%U*tI3CXf;t?p?9Olmf7-p`adneI7P)ZLf%vVMFEYb2vVu5fV zn(TNq5>QWH%U4V|Q)?!y1N~@;BgfIc1dz#7Po*-0kGJU^?Iv&Ro|Shx@mcf+QYRwbEkjX0G2iAt!~hVGw2QepnqoLRi{V#gWlihh5ZVQnlpBrI_~%O&NZ)%eQA$QxV=-q%(#oW_4R8o z!(U&c?f8_z|N1XNbsOoq1_t<_@?GoPVkk=kF2I7RuQGM z$Ke8T5fgJ9E-aIW6z4-zl=}=EV3DDEDOK7WA*FlWTea1}r_xw6)EAAnns!`=`?m;S<9IG0e z`zr+^x@D&O3tE}@M>X9eHB3W!8t^Cn{8s?lXItFBs1}=gVLL+8jQ}onqfND8sNcnX zr`^nTy$cF``l(*Aq64{=n2p}4!dAR=-TW`-5arK5i(+m`jZOGdriqS;7F=Lb@8{g) z`#OW5VCZS0T^#kt%fgCVZNYU$O}a^#BC!|JtX|b!?A#rJMYnw|RY-F@D61~RKBcUx zxMp|1@u8aCgrIiMzoa##?;DD8r8D2%-4u*3Z*c^>nQz{;-vB9VmyEsYMQ&pM^aF61 zZv>}aPP>uXoq1Ec%{a@VQ5V!qZ$lL71vIOjagqGBMnQ1%#DBd$;lvCUs{|20SuU3K0)Uww%O#AZO^cD}IV1UK z6(jl4Tdj}8Or_F;&>Q<1#93uQH0qbyf9*lo{Lz1`rJknhp#Lri_SfxyANBwBH(T$& znNNM4{$JZS=zqt5zyDLJpd@+go+Gq_)cPpSUInmi>(h~^ca8)mpoqAVeoQgmksJ1z zUz=C&WgXrejwDXaxk&Puyj(76BEq+V5Epe{tsQ*Ol7%8j@>G)tzdRucIGAVH-02@nBpDZ8=@%wC4lpTx8O6@Th;z1wSBsWH^0iE8lDbT7Ec( zp|cQwyug<Y z^=raBfqhkMk5ukE?fRSr3ke4U#-@Dw6-E*6p>Y3Qsc6XW=+P;KYKRAe$j?~fJZ zxNklMa`dIxz9c*LC4eC@j&FZJB8P6n6PNTY^KR}bnFD80*My3fS#h2g;#gNP{dh2? zymrtz_ST`p6CL|1Hu0(U9x2`kjNGQLdn4MnH~agHT{&!Qp?l5-J_J2gqY6Ah6**Q# zm*I(M-y+qqy;yC#I)?TwQYF~Gw-tC9aoDadV01M8Xh{u^Wj7c}UX>d#zqg)oZjN`t zdYQ@HZHO3&M@EOgw+^S#u0+(iXnF0R#QhrW<%%{^;n%!eH8IO_%RpdJ>CLf@;QwzX zgGW*+rxb7PTxT+%d8`XWAQ#yTZ2=`sED%-$AU8&Ua|Icl3^m=kSN&R7NkF_QMu$v$(y;vpRgz_(d1apUr$){k!aGt$M0Z$6A*bU0g5c#Xn ztgpJLA%_kll70GO?Xp~HE^|=no~LT^`9WA)`4&K)#-$7#1j-d(bCP19PPR=l`$Qai zk=6R_Yl62umKPzbQiqIbndNq0v*i{^UVe~mj6mf%TVV%WS&pO!%PXiOVt zVKDgxD=#!l)}2xEV>T@d)!m2{ZGgkFu!a*&hSnp89s5v3 z>y(j2OnvP1PrR|Cp(`G<_nHwU#{-fw)>{y1@L^HqkmWM!#bWmECOtQ|)5 zaprN{iN@cF5qFz#+mW8H$#N|BACUEiMg-%_Of(TIUpB3`w(H~BlZ&f7$Di=MUDca> z7F4b0vwhWSS2$U6xO%T;7sDoK)*E@2p{MI{Fh#M_trsNuR{Fsh&PTnf{Zr8yA)ShX zdDFh|xWO!lXC#4!_`;uZ_k!fWULl>IVq^xN+1SbM92qTdns8P?zHP$yr1`-YUjWFr ztZ_^cdLdV9KmrWSw%GCtrYeY??`VpHFpG1I7wILAaH{l%cf09;Etf?&#R$$2C_gczT(upH9|Mw6F=aZebOW95Gf&Ah*W z;&SeuS;sd`-yBU}vg_fBaUM=i+KbTw;glCO;@aRxlZx*RKsh+{lSSIU^LfXlN!ww> zhsKwBw-5Gpx&gG@xJ9kiK~d>B*0F#CX+98V0j8m1{S~S&Vz&z@hxBu@JXkIN$oLyE zQbJn7k9C+GM2JBgj39SUH2(KYeBO^NB41ZOJ}XolRk~E7k-=aNO}%lht1B+mc==G9a7?n%?ppP2cs3Yub?IYd7uY zTCEnx;xENY-*lE6nIQbpp6^6+cgK=9SPW;V!e9OM_r7J5#2Ny?nW+z;R0=^%eH{PZ zzG^Mj5=U`Jx+qt1{Kew;k^&v@s*`?u$!H0=AA*?wesl39>Pm8G3CGS?jj~`cXv=gP z1{~Dyb^nAl#abv7gjpl=s8M9Gfh*5#xhcH6(9~LEx#70~>x$w55gxBa6+?Wsxi=D1 zj2jW6++f5J|3|F!wP^BII9@-D^;@DBwkUGn0yN@#2}ub{`oXmB%I4lzAoxVclo9~m z6Mbu6^;WR!<-!;o9xeYnN1S|(-_D(`TfBYAQMn4?SpN~2=FjkH!OZ3@WM=2TG94TcqTOq{|Y8ynUz6Qf7>NR#5$8&r5w& zsZ#1gC)j0(Sc7g|xg3y-(3xc`bE8;z9#^tDDOZEcbM7k7tO1kyhF4{>zdx zUu1i<$t>pDp@^h{p*o2wd^&z|K*u*f1s#ts%^c9P>GnKp!rva+6UBU+CYmElEHT5# zDb}wjsod5n_FFuc%r?{+=@FBsPFMY<)SrE{cE#QhKi6O-gH8B8|F^$6=W+m(eAdf9 zTnseUyQ&}3F;8zXMfNte2tiY0O%mgdUeVG|!pRGoVx?XrIhox)NE!>1K-8ThAyC~O zv%thTks$cGcg_&erTcuo;Ok?1jSaz6SpSEKJ)7p{Gi=k`!bLocO$ZZUE0KLtE6|SK zEjLX^?c zyFNbB#|L~M4!2D|EiftHJ?&HsoXqNCNfU?O6))_oRTtvYl@z+yNa|rP+B+{H0Rk*oi-rs&_ZXur} za0|KpAv{REZ+`lwHEC-cBDYiH2pCu=`}PIm^ux$;Mkx0+6&_`{DST~($1xw6!bAQY zk2~eY2(0W)Nj~Evfh=Hh#cPTXnVRBoMRPd|6?G@Ri2g)o>~{KzhwT+dGBq#85Bjfa zZMrq;!~Iucx&6ogv1F(53FmcnQ81(}f`8GLz4FKKMtWZ3@L~tujFCBVB z)2IlBjlLml?K`>T!HOkEa$J3{@mOS+2iXB7?_fKiu-4Qr+Q=D8G+00X8=1w>@%QP< z8Gpa|-y+FNN(f@Jdg2s{UU>>Cg*{i{{ZB?rC)ur}!ITujD6N&h==BLFi-wPM3p{JE z{eC+{@$<38GcU=swUflVSH+Ui66CmPIpM2;pw{)4@%;Q0lg0iQ7b~anNc9;EXhd@0 z(Xr&6NU5*K1RCqs_$T;e=nRbwhl?wYywpUC*??4Ek;0mC1pZwz2jf4E7Yf8V^}ZOY zYiIWSmmsb16-}4XgXYrJOP-MW75l|Kf7WbLcK=gqJyIvLbxxX8CtUT-X%P7x;R{zK z=es13&Sa?36HeTsuIzynulY^3UCjjgp>fwxuU7MNuD;ZdRXE>%!JRlCXAzhN735mO z)k*&vy$d>ttZ6gh9TgA}PysPNi@2sv;qWdA$ILg7IYi>*!CEPArfAO(WASCN(oaE3 zIoBXR!I_XT$IACiI}SuDAwR^INLBf4SM?5`1yyefetbiIVnvZIpJ>99mzfGN;G=PW zk-teU$<3BTN?(h`x5h}n+U_lg8wAx+%0S&Kqi=~GBYN59LmoD6by_I0+PeNj zLZJ(%ljXHMxhTWUD>- z`D!ka9lqS-BaFgY$~}JfE2{sNRqtN<+RYTF=BhqKI4C~du?tTF?$`n1GA>+5}v}C5wvUKj|Qt z=832Ll0hE#j3Xuv1AT~HH5`f?hT^s$)#*Xw&L#q5^PgdrcDHjhrNZZv1RyQY^r$o3 zX@#(VE6-c!kM0+LG>^wEr^l$XxYOq!qw_Z|aMQ1n!uQAZMtY{S7o><;YQ!=m~IvZ4pPc^m8*XVb8aPY6)ZFqH#!pg9)b;4&u_#;0*U$hG-6+22y9`>fzrE44qaBiN!uZqoe68l$7Jcw?&l zZjddRx8+ge`toPO_0`@B*QX;z{@1ZpsV0W+*JjOQTmXfyE+4?4=HLt>vF-9_@c=FJaMrj&S;{APFq~f0J}(%n|he zUnZR~{%Fek2bg*6Gag~d1(V&%RrakDFEOy!euP|@&Bok!zhALg#%f{TV*&nDhX1fU`HlCr(meT> zWLd8m^(`|mxzbVWr)0|Qju=;?_VH0pDf`dwZy zx75!fk1uw&AMwL1#!>UG@t(YEqfvZ&lO3Z{Z-6}RkoR1PY8C-iOD@`p>Qutk$AqpV zBA9{}0^`EE2lP7;E;g$7IUuC{MRxCQ*AKbwP?K69p%bk><@bMOd{@(2?XA{{e?WDBbyEyKkTV`DggwFy2amsIdW4)T~iei)Tig?RN>Kh zSy3eI)q{U9{*x6JPHX&8{)sNhIUK-v*R0wM1x*fbO8p70F?a~`?VTSy0Y0bl?3vD* zoMg9)uL$L&9-cmcnW^jKAetsM0{J{>H`}jGaB5gHOW-X2rZ1E@o4-j^7V0d5G^HY6 zqhGF3kzO6i_sGbz-<@#lEmb#6u9C6ed1J7Fz2J;u!d?_9#YJ5QBWONvybwQ069VBM_g!Hx1i{gXAw}WxyxAw?3txYN5G8R% zF$8ZqH@v~M8=D&HaGv>4bBxYzQ856TTrZ0y;XiI-=H9YO5)3hK#*VlMx(?ajS z{+h8qJK^?Qs;;@N>PF&4whuph<8{S1j30mNcz&^0sGoAudR`Scr!L{x&-oQio`;x! z@q~Wj0v@!-LfH6=FXX!>e)}Lzj8qe@nzXBcj_9LhU_VZ%XSCvl;z>7FjlJ=f;&6Om zSsJ$SbmHlAc3%4r+lE59ejGkdY|*WNhPG_8 z*7;}WzcvFT@p*iQ-=YIG^g)m)2k$uDRTWNhwbt02A3OLzj`c=t#1oib?C8b<@3GGu#*D_69VCRB27(qJ&7j_H9sw+F zGjfktLasQ02wz1+Ip*EHRynkD7*z41B8#|wMIj9Agu&(_sn;s(IAh@y72-1>0lV%8 zBOd*wSP=#NwOFsVB+)nut15_4d1O=Hv@2S=0uL`K7OBUaH^T#f4f#Gcz&|hio8OW>rd-wHWdB#-LU`7H2|t!}lKxE{eZqCl#lcB9?=-RP$)oPQ75=(*$pG3) z=Jj&-&dk2o$=&?Rz zZ@?&~NGyEb)vCn}sD2U4>nB%TNCby-R|8lGxA$q6rlx0#1bJf-5R}|gBteOIFcXn< zor8!Z^(P`~ymv)V=Z6ifhWn=k)ZPe$_Y3nX2>8s@#Qh?un;)69`#8e~R8W?&{i8kO$I&#IdbZt<1P26yN_gL`DS2G=u zP8pk1eMdO)!$rDPyYlSM!=XQu@n}7&UfUCvyp!62%j#u|r2EB(DtyG+a8HCb+7FU> zEAJhGkjDGrJat;MKP%5;I2>1=$MvH{kP4%TYsY$xM3}O8`q#0CDmf`p11}yMPE48X zWZ;Cw`GQbwavj8rz)S?tY;9X?LJoMP9u* zA_VwhJ4R|vYe?eY_kIR`Md29>=JPWL{(Sn0q9>2@y>`%{HU?3XdHnX;*f2y*^izMt z6G7v&JExHBm<8N79)|nKf|Lwx@rR^1T|c$ilZ&WL#Qx;1Laxm4NCrp;8_s*Y*KE+z7&&6LYz1db4y!d+ zwxV{>A?dOMygg`Els9%+#Q>GXVRG{5OyQBWgEm4YbBHaJ2v>TqqzhMC#mg#2>Kg2| zufFW#WhyV24mbYU6!PbQ1wOQ-*yNT9hEx4Dn@Ynkg$J$=+&~S{9{o>#uvzXX8y%(V*l05_0_) zukQE1`Tld&*`1wtiMQ@@__+E-kO7tj2Tpd^#>*Nqn-Od1#1H*lm}A?}R3|jCupMN~ zFu9u7pPd=76tvAMwfC&fElSz`?RMxi$@DHa&xBxon07Lt0IvUEviJM_AFcE11_1>@ z(>AUaT%+F?jqv4Smmy*tPV_(|d@`}naFr(gM>SPM%U4!+iYDDzrm>6m*HG<`^njw{ zV#$tcLiG=->iVW>-D8Q)nHaCJ`Zq##eJIJJ#txbL4b>zz?VO!+@10orYoYpFR}}ei z`^>}XeJC5l`|i)Qp}!i*N8bsON7^}W#Dr`t%rsP3Eg&&E<=mU6dAGqZrVVu|)K;>^!(;=5{koNMFgXmSj0 zwr_`Ky=z6T|7@q9-#S|UN~m^)l?~qS_?cDkdu|GTZ--`zy^>><>caUjhR$op8xhQM zVm;r9mA)Or5=IVsuXvr*JsWM)($q@`i+#ZKH=&+nB9#G%Cd_v6CAwqXClbw3R&u{| z)L(;1B+(fI8uEu8WM?Apcey$Y0nOB{s=U^+SKFu81=8bn(nmXewBf_}yFGvB*B5-i z%G^22^vh$fL%)2?Z7KkL=8-M>aoV|HQhdP_*guEidfitznl(=A7H%t$Te-&#sfC$X zNx_=RzDoYN)hX{z24`)N&G^U`0WB<|1+}P&lSpE|U7h2mgjxh2LN&MDd*Dd~F04zT zMIgE$X(bXJdy}crn?eDb?)HQr3G$cY|9H>OH7zo=K_1hwaB%IeJMYYsDrAtbdR%%_ zM+b1yvMmN+MoV#3C?E{h(Fysn-vPGm8t!T}Os2BF)fYvRBMt(Sl&NBo?0Dnb?KA-$ zyStv1aQctjN&tM+8d22xS1e3d^9sidUe;#7^nR(cpt00Dz524C-og9SdkXd1{BC-n zMcrl~{7TEty1L6!@4yZT0Fy4oeKS|_b=OZgXDB@7_0|M-G}{9VT~jCf!YM)hL&4AM zO=P0(x2*sCInjff8c(4TH)TUL14F@|DT5K$K{>%J#*DyaQOj3jWR)9Ex6*4aIDOOcgd0{n(F0T!2A_7JI z%kEUxceg*Sre%MBs!)$A4RNy@*xis7shlvrXGBOu!unROI25B;m}TT&GeOBm?*nX# z#Is`Q&~G-K;YvVIDu8-gy~_I<&Uu50J&qP}`gB#@O1(c*z0qd%B9K+fe!XVr zmi1E`a{5TqVsb?=2Mi^ZNQL(h4g{IwVrw%j(m8;&P3hFC=KOy685WcNjt=*1O+p&B zSp~dAl3X4(C93^k3%O5|5^g%M00`A{@3ZzddCa5Dn$*EEEhfh?Sy6~Nz%sjX`A$;X zH+Z9n1t&w8{rtK4A9HYe{znRAkS7vCCGykB1<_D6Pg7#d23iY8R7+=Bo)q z&4I;se8sdcvxR^gdCEn{s=ia?TlBH}_p|o@aFltVEbH>+h%$}bq*!}IPSScOluDa# zA|Yi3d3hG~5quXnz+7VjV%%x`GLAauS8^h$ZmU&MDc%2NMc$>G)C#|23gB`vO2!L{ z8fh)efLBeLNT8M?iDmz;E+dePR!hf(D}M(B`(gkxBd*N(bO!ZAD_2}h9x zDT&L#M%JK()_MqXOYF<~wbkuONT=LjIgRZiiJ|LuM&fNG3rD`;U5_Hw$)EV*U8au< z^%3QR(8`hW?bA+@yL@L%=`GsRpg(+izB$nMJ-6;-MSI%b*oBX1a?nFOXl%=u2EK%9 zkA(o(n+9KAC;n4s?on&1BUdl=7VW&phuc5(YrQ_!@X_G*gXUDpJA6^=6bSrCjXE&@ zW9y&wh&Et21Yp&~Q22YRhYqck~u*Aj(#dzoYlQ@^2%v-g)LC5gdpzB(?SY9UC0~CQBlpf1AggiVt&qn^W9d zbOq`4>1uCu+QpoAzzXuym9Lbm#@!{0vfk3lzzle`aZ8F9cimK}q1SjF?s4m3vRRg) za6>=fznX9jYGqZ*j-kftBM#*7WSfJ$&%hl2Y+2_XfsrGXe~vD2>ZdEfXSJ~*J1r#* z>uVMKt&sgbpMe}w>=G(NZ^duA7EGQ>T_Q`R%biWaax{dN&v`02CURl={A5S9ca)*( z)`3J>Whxr(EQkaVmJ}(;>l5ADR6FPwQLWJSLAx&ev}0k1lzES%4zdMyjuu#1G=Vpq z;}jKrTf-lRLTp9jM4!-CK_n6^#8Mcn72(oder_y`TwsbWf}A+Dy|j$mz2T3Em4=^1 z_n-HTZ&ff|z7*=oh7C=GqT?(wHZ0vu0F$6;Nx}eWI9k4Z+R>53DHOS*ces2*E!K{4ltFf@k0#{3?A65AD;~Z@HiBTw1?D)x zFqt=HWJM11g!i~NE=dPBRi77ht;OINhw8Td%)9;icNPI%C~!%O;sSXYh+&u7kPOW#LA&y%w^(=DPJ+xj1k2PZhA42 zF#cTeJt_i@`pzkENGBwOrw+I-1;LNhgk){)z2BmZNo%tXih!=_T7(R%Y*ia}nm{Do zZ3{Wif|o=fIRMa)Nc4F-%A^qDEHv{WhNkl?`&pc?+Dj_56^+Iet4K*zO7|$*iCi*A z$9irdV9Du`@~^6YEeD>lrt@T{NqOCW2DlbgpVeYU{r)>yPP3T}X46F5RF%4vo@D{s zyOHp5-t~Mq`mbM?>El8^TBW}(WbY52-47AAkiD1eqZxN3)$vbSk3RogjJCWCHa1k3 z04iERWky>QWrB9o%IY4XU*W`APQC%(9-6scC7Jfdb0f*hz2=A_D@+v}mYBM9=deW8 z(rs4q=en&WaUWkS$6|bYxO9DZ@m^ebU~OKFBs-RY)xWqD(U9%`3xBY|xLbMwmsqF|sgRzHa;gQ$3|QipIHl=A zcBH{nBV6?G z5jXg`Zty>Lga3&eJSgb!Zv$QT@sB-dXbE%3x)uIo9raKId(h5&8ON7u8H3a=>3!9U zZmru_#p5NHbhv_vE(_|H9^au5c3;7qhQ!(Y^3MPq%6B9fQ*G8E4TW zdm0;a*J?C$D<4Kfcf(mswW&0}R|QQv?AzeO8Un?EnpbcG`24ZL zEI|O?tJ*{fQh<>^hoFd0mmG=1STD>*I5QIZUofw)2SE4`7Qy6C2nP(0b`-7RFIo%p$6+qc3?5vG~djWJdT)y2|O=!i2CN6ACTc;y}ITO}CpfB>22 z{hG+x<|Lj@sG#%FX6A$GiN$w%YdvNqz9UM!FIS4V-0VZlW^$m+Rny@*sW&5k%}L`)mEzucKmvzd{<*z)z6m+g;t!BELdug z$YTZft9u|mZi>KCjK@ZXxk*OIow|%5eB+uLkJOOU_H>6mr!ix`xP_yEJu%n|{}-aa z^`6$pllpjq4=B;8w-_b5hfUYpIC4Kr%8h@1>)4vQ*4B!{&l5BF2{Do34ft6pia^Ll zEQF;WZN33~4k~E_F#7+t{n!uvzvNilS=j*oL?Pq?C4C@$$L$D6A7qYnr9b4EBlHqa zN|ys+*$HhyKWgaUlNDJq$<%!m<$eB8Sb07_eXP7x2zjC*WT^@XA=5P*PI~bV_cr;& zjQRo;%oHjXPF>%ukdUrKNOyL+m??z7&qst`jx?%wfsEB2+x!VRGtXJ>2>a5U1grbi z>Py5*XuslQmENxo{=(m{-e4Fl8HrUlv0u&j0sb{!_tThP<0N|C1Sj#*Wgy9H>06U| zh1_7fx^VzV@)Y;8_NrfH?NvW!uX>1SPF>4Z-=SGQU`l)%&X$3GUijHNpr8G-04jK19KbW1G5g~`96X_F z=-L5AwZ)GV96A^~Ku5>q>~4Zp@v(kAy;`H zyuwqYPMH=DU(21m^d0(FRdw6IDOIBePOCb1&d`#x!%04@)%ZrEKciT`&291)(+ejC zHl}#~XmI(`2HSYuuvRUn5g?LjcELV(%9?kLrt`gRzkwxtns2Gc(p;|X|EK$~EfVhZ z2CJ*EdiJ-Zh4)#@MF!9>Ud{|ycPP%mKj2fmdugBrE;s&U-#N{`W9>(p^B=U|-X{rg z8kT8-WqRnOvwiok-o4&vT9%{a7Y2MC&5ZRDThhEo(4ReK{ND`U8t=;Vz~Pq?xCQv7 z@r+E%{{cp*?!N_VYOaLFBV*=Jv}O{<%CBH2rov*9e zlty!rd9GOYBYUSzLPqwJOJLOWaJ%=)N)^6DM}Fk#h|Qr2Jmm{E>V@T!^q7tM07>LJ z8UA!P?GtJOY-=szc>FMbg9KR?6sqURqc)#(jt{#h+G97(`CUoIIF9|gGfrM{Xoi-{ z=rhc~Qb^Vuj7})~q&X=xgQQt;r52>IDFfHwn?aS@3e)+M*G(@boJJvvMnZ`;aA{Zd z0iOj`Z}Zu{YLjFLCxlB;L9Gv$T5yqY&-K#lb%td_Hqou!Hb<$h;-HL}`B@aK`A#L z1_nKpe&ZB-LnmcRKBHGDJ3uFoGVgG8!L{x%io?4qWvo*jn=(?UHro5-mu`Xbo{I1? zXBQP=I3qQj(Jl3pwm#GL-GSZPH2g&?(ZN-~^{%ZtQbU0m2cddg6khyp8}G3}uAScC zUjGLN0@KCdSLONG!TyFMrt~$S9^NRwO9!;S`y8P8^EVEAIV6IT*Spzs(&0cFPN>z> zjfWR`mHukfYwXhom1H;bk6^h09Pw~T`*ummXuX7jtgfVnb^<}Hra>);xD1YO^Tw~I zqGY#(+^ndB)hVY8>fqZYC1X{`!Qt9Di+BZ8u=v=A*c@SOS^MHxZ#)nDhA19R^lw^k zoz)5-Z9f6aI1oDZUqsTfuWBNjzV?00ffcF{@CvC-2UvV8Liwj}pomkETuC5lgX4^k z=0WmYK92|aCh*O-D>@9W^z1u1bvmDH!mL{84a$W5L)Z$K2*UW1a9fN-1Py8J8}3Ju zqO7%J(r@@kYqVpB1}WMQ&OB4b=o=3;uIiay`hG~i6~dpIU86#ERlHrZi{v1Z31dT- zcig%1zaxnx_H>`!5B|tv`UJHhzaaH<**Svfy&Ieq-2a2&L^bZ(RFk_Cubn(K$hEaIXz5` z&W1UUFM?c+uH0NZ)OLnPRrTE-oErbvfh7z;SU?W`9(&qC`7hvcT$7^(}ev zUKxfa$6>$I2yyVKmbN8CC&PXRv66EmVip(9MHF|Z+NCcB`t+1IWb{sl?ai7eTldZm zJbZA2KOFUASH2EiZa``Kxs{=rZ`yrxLy=9h+ER2a0bIZ5`M<;dZ`G*hmHJ(}f)G~` zY^HW>l-?@Za|L=sQwojbv4${O#V9U^Z`pW^A>=|`t?E!$xEZOvozMVNHG&+yLzDS- z^#g@q9#&+(T_6!jqk8Li{GF(e7Uw#&=+D*AVmwD`hZcCPAAv)!*p#_ge!58x8YTv! z-v!|XF#u5hd`rroSc0@17TA4Jp!+%I2SanblW!A&L2YEsEB*8%WxnpGzxU)qU-vTs znsktjG^pOUn$kKVeF?@Sr;G|O{(Boj7#$K$j#^zi=n_>Es_UkS1XPn%e=_g)-yh1w zVZOKaba`~S0a)dNlL`inq+VA&JY~jEIT*U z`E;)1K-A8YgstO>^{rSLF6vj)(ZK#u;%u=!jVP%hjFiHKA8( zDIes*Q3yP`tVuu^e%sQ3v+B4~=6r$W=B{ul^XSL&!YF9wpXk0oB@z-r|12&Hx5%qxPBVGEqDxf*;mMtT&kjd1R6cM8NR!8^t8z73NeS#|Vs8`Y-n zWLXQ68fY+&+4DQ_V1Hgu)EBZ%)k*#M|B&}4;8j)E|91ie!Vqpy0#QVQMuj?o8YN;h zVZ0X-i9(f%w$uU9Iz&hi%V6*(kZZV_Dy_8Aiq%?MtwT#G&IGOEjN*XO%HVY3MT#PAh1Q{%4B{RtmAD+(rJ=@gMRLWe{(|i>&qT-ozQM8 z9uRwp7aj71-xDFX{`r(6sC9yv2$YVXHt=NMF-wK6u~W6cs*sXORoJ)MAuMFSRKn_J zZG77M^G|jmtm)zm!f;yx^9f5#!~504dnBwg9uElX<0toqu)^O;SU>myLQ5y0O;V}N z@Vk;#FerR-3RcTf$V&1hvx>5|*CpVu>0lPlHONqloJ%+QPh>Fe@lL)eEqpRmD-S=7 zYB7ki`lafI;CrO-Sq^^TMOX*v$WB{UUtO)|!CyvVUlV&J+}O;KKwpoKkIEp?3&cfv zAyT-e@^FIo$v!#U;PW{lG%ltrXAA3=ddC?fg;!+G%a6pa$SjNfm`QWmU`?7#w(0mM zvp$0dMkF?pkG+&Tt?7Y(V>9fqYO}>Z{u}L&XVjc&#+{Vw z%~-|Eg%>VJy-Q_>puRm{9t|%kk|BkqCYl1%i6M%A23`N8izq~tC)Dr^5aw1cp31v$s zZtVjHe)_S}ynFM+x98vZ*FEO9_Luwc=PHsBy21l>G$UHH=}=#G`&l*5-b?pOeq+nz z0zK*v_kc<3%hcfb`l2*1`>;SY_YS#<2HqCnx36D5tsIf*MV^FmqS_-a`uyq_qA6P^IG&J9SFzrYYk6y+z_CLXP@g)|W#Q9c- z8iaXJLsa$NYWnT!q<(uK5}3idV4H|s>~k%5Ni=Cvf-v!Hw)aRyc1P&pZaQ9xnN$<# zx&BAZGs?_hS7u~f&2i%VCE7IWigxaQDnwe$YCg(tw2HgMtoYA-Z{EmmIYWFUJHs#l6a++#OLg{K1cXZIY z+5@OntU#6rt%~iD$8T+7KSsudiUw6-(8hlN#)GmPT9S3dK51Hl2+NwOgVyj$p_Le8 zR-T_fP3!YN(U$wF3ryNF_(lv$<`>%RosWLM9P>v5G27Zz_$u_;-G8rTMMg0uh95#}7d){FB%kv* z;mb}Q+3AHCQk7w^SFF|7-3iDi-L@@EAyeF>?&x# z7qp*UCHhjD>?+aM6?uf%#&7-V?mED|IIXFlC=(Ok!lS8VLi~V81OxA>@%(-|GSnYK zs;8Gq%(i-ZsZ4&VJobljq;9FUHa4jwU&lB#-lLxzh|4ULBv+ z7((w*5~cMr6sWXb4h1s>6rh#HUJeG*G8;(3-R_ucFg60>85Mg*UA&Ymvh`fb{9`EU zKnu%Yq_7##v_)v5uiVM1z_Uj*m2x!VLJ6{58=4q*# z+jUppE#q5h`~dpyZScQQ88s`?cY7SiVohf&D>7c5@j+Gyz>5rQJ5uTh#$+V@jcC!| z`$;mMuWrq>JT>{*c9)(R&p5MOeTf^`)95z`TW5~ql~!H&44Mt#S5T zHBSf!Cv|pz*cW$*nZ~o2sKlK}OuTuI6^l2oHz7y7nI^Wyb6b=eLk0l~cB~lgicGQA zkfY5YT|miapd`#(xiBAp5X3^0<^J!&g#^CufD6YTg%QOQ1rMRciePRN)&5BH9NGy% zB>ALxNkDbGo5~G=ZRNJ%uo0pb*Vpxgu2&##&KGymxW9acie=I>B1q zNj$8!u^QLw817n(L&(=Jt;o$Fyx!ctYCFbQ;|v)Gma5rrc%5CFLp+MFS6k7GZI#FS z;J~2SehtP}#O9TZMyWapLROs#LROtFPAlNdJh6f1pdJ72cmJ~~ z*5Rie_7Y+&eGZ&~ea*CqYWSPC< zFXxF##Z&l8Zf}#rj?^MUDv!B8oa8aT=x03U7TzRzj4H(bHbUa%1o$UNQs; z-1)COiuug9?@2O|{5Vy2lOJVTYb`&Dw~L_$LQZ>npvjMBm1D_Gq(_<6LOSx}^prYM z_*=B7wwHR<EFZ%QvBD`DEn}+ zO{&>Qq1u#-Jc?~&?R<$`AAv=|>T#!%J@tZ(uNT{LPUnR}*4;MKHw~x;4I}BMCMw$9 zEk?_-lxe6$BpWE~hV1@O~#-#kYm&h;< z`Us$=kX)(nlJmcb3@3~4H8NV{Pf6t9A+%WYgLU}4-+oaH@ zhc!PectZRL!Rv@+aLU7UIfx78_tWn_y7c0*_xy9@{O`g)IV2$9n62+dbKu|c&pT0m zeEuo=wIvJgrO9;?j!m%l%S^`=54=y`<7cGnRKI;n<7cIp#nwe)I|KPI68$P86o1;3 zXM}s{qHDA_ZFX7Vx~sbkUES18`Ekx#cqnxv6P&I-KQ(>?C%8UrJdaM_y{V^+pedz= zO~ge*V7#uZFknFeXLN&|zV#`I_ zBheklgcjHGoYdbz-4;|XVFI!TeedH})oFNX>`mbzjig8*Lo^X^H-8&*8Z>{KnR$l1 zW#s30$>BtWSw{es$ly<+MQge-YNj=WYVHIIS<;tsFO6Z-wL7}I-IwH7b7w8K6yJw< zM$svFi4EGvM$=G!tMN*xSxumLJ@gF>s5Bv5|L$VB)?Q;vMlHr8oVFO7PZP@I(V}%fUSPa}_USh<6_ZpbyY-`M$o!Jj*Xr z*s#;+r(oKnp#$oe%1N2u4N*c&vH@i*BwTj^EXeG~+9zf)6eh%bW60dviKq$tOQNyP zWiFmd0v}Pkvy7L;d+%?f41=1{!2jZCo7UjQTPS|DQAcpRwQG{6qVI}7`m>bO^*~YAwKC+ z*3$m3rwu3r{L1k)evMBY>$nG9w`bybB11C6fMR@7&v*23-iaynF(%9CV}iYFp%0bs zeNW#~=tD1?2B?tl!0uefh(3P8f}i*KjmQTd>#|Lk_qptiq(FYJ->kio6PiB#qFoU| z@h`VK;h+!f(H9Oh2S~YEt~+P@gt@0h25&DVvMBMyB8}e3W%2y%NaKGxOo$(Gep$TJ zam+8%n4pis4?HupSX?qRU=+EdJDJcf;IUJ{#Zq zNW3@kMNV%ni=T9y&U>bkY49g(0dCGnTgz+j7{9p5S}5L| z;uPAGvdUG~bOS6|)_W8va&lM*;0dCLI{evo9f_cm@qlcZa&=bIleRgSM!saldN)xV zu@hoD!c-O3CX4|@a_Ldk^C7xilUf}&W;>Y(+|R(A=$@q3Wwz||Yj4rWyK&~;(P2G& zC`CjS{VjL&cN11bpZ+!oEa+o9ch2_-Eu3i<##Rc0a04&hqr#y0BP=ZqA-Apd&_$AU zv+eHma9cOB=ViXvy{|`V{YcgOE+n>AfJEm{>Fu)UvU=iw2TQEWoTCE0xJs=-f>~|% z6-F+S62&>3&?zz2=3}$#x|M1(>>@}Y=(&~ZdHp3WNdsgMxqaUlRj5ICpWVL=U3=jhGcQMTtwR*U+4)=(@X>#1wl!f( zSdm`3FkQgJ4?rD#8*I3x-Lmwzwc6lgLvn_#ikN6={tYH*ROOk3U#7+Tm4aUe5cGBs zD_5Z{8h?8vng64>aP#9lxSFGzu;_*!OJq2W7lR-$qqWXrvDdpomrHcHP?vMLpubMx zwl{N;1tgK|8TRTf-z!$2(jh*2yHn~04PpoPD;>!k{F2>+=(R^yW z6Zc}~3+>Epeo?G$NMcktx~=-0$0fNz2hc*W{-R%!H%-zvP9(nIMvQrbxe+rXkM$Hh zb*}!K+KeCGdgQOHvY{M3&#w=<1i!ZS@_!8^VE5Vix%6M8@a4H3BZG->gX!ZHwK)Bg zzzfG#$0Trz z$uD1B3$1<5Wp9YgJMz-KBCV#s2eXVSTj%I!T#I~TEQg6;m4JtGGz{dL$v-3LEwagl8Bq^yxRiL7703&n_?tH$Q4Ca>4!}n zRa%`il9aEEDa)crQ@SbpwTub-@M0sEAt*` zIkqf*1TkLF^8sP^HXe4uHNh+))Fj4+J7fR%C<2h(MvSdXzOe|W93nz zPPTNs@c49!WDa?W7n(+=omObG3viKBS6pN8IHiWL*#u$Kj zd3k<*hqA)Wq3e_f>bRmTekltPCtYD?s!b$Aowz#E_%4Qvx&29T^$= z4|b-xr~rF50zCF_<1U+Jz>jB~`#om>P+PpwU$g5Yo^h(Z^A`mDvc19j23Z(3{FhBP zyH$WZFvTA51y8si$WQ%CbvQ?za%D>#&AK z6}Vv)jnqz(x<9D?9gtGksy)i0mjrK>B;!k7)%Rf5wnQEAzhlNcO?ka=-P5JKkN zjc@oNWFBDc*AL>OGqu;X#F7cge&KEWaT2`y&i7lGh$UgL`cF*am--J2*XJsrXip1H z0}(YY>`6FZAj#xt)=SEQa5~4xGVH^ZT#{P>{gmWL##ww)sr>Zqriqy(@|8D1nSR&j|nfpKeEjfS zKE})WS@78OY_s2SrW^736gK)9^g=%EF39YQm*6A0`l`l1gc*g(tW7q?ckm|F}TunHNKhI4GeVj3hSF~i_ zN3>+=gRUjHty(gb%4L7pP}#@Y;(dIL!z!Da`j2dB$-gfo1W(&m{5>UY-*#FtK&{aH zN=qusX+-7tmIl0*I6PXkbvw{={-)r+2)64~jHy?ihw^u6o|@Z4{o!7n|*@MFO+3Y4e=N>lZ3TO-@>ylrfm zp3&rWoagoje8sTxKG)@AUAF1+zAjt2H2Cp}wRObjA5+ENW=m;npbb7KRUE{W0tRsn zd@vA2Z(wD$Z16vjeL9xK&(81E0&OJrO5}^T1?{+a@2v@}%jKO+Bj0&So8m~9@b$b- zP)di=!7rnubYwA6fe98L4|q=V^JSq(?5oJ&XDPpQ@S93;-S2@_Q#yw3V5QYpo&AOY zXy4MpO*0QyImK{k{D-vNoLIr}g7^Eei}!{j#XjugixGV!O4nS44WS z)*BDnBr8@^qt;l5Y2))EckY41nPm5+f`?Sg?Jl@*Y(R0PtZ-~6akr%0x=|4x_zb#O zS>Zpf47XIsrhE&gyQMU?$;*}OBNbN`wrWab4?H#}&f5_Gdt(N3A9^#~W-1y~ci52E zS(kJ!aGGoPH%@c#2k?-iGWJe7@(v-ouu5g(2_hj`EV4Gc6WIUoQ2TmSFjd+7Jv5k` zT)fn^ggmz(MJ`@~Men(622uEqF1E>AOjC2G>327u?L(4S5tNyFck^FSptnUOgGtVU z8-h;6t{V8kXd)QLo|1<}b|m_E#^~7Ami1k6lC99!XgL?X;S*YRm_?aPFip^smpQzo zc}-btZCR{|b?(eiJj#1<+Kb>$hvJD;#$hdAyb&RKO-Xc1`lxyvzNP6e$OCNju=lHa zXnA~YXCkp?&fOnYdwyQtn7Z?OTl|{b8q|3LVThy6%#G>Et8jr2Nbhc!i&P^@qUqs%fd$kZw%f5&cNklp!la zY~85Xdd1vjsF-ZM1NrBx&6}E8n2Bdy^UWBT%u}Lzgmxt;9ZY1U9o`#3imC0ScwH&} z7Nj`2Z3@nJ`RSF6#VTDYboq%c)3|VYLnJ=p%P>a>6+SWVgtEft=4~UqSEoZq4ck$< zmAWJGPA6d>4$9v8bzAr}KIqPll>@kTuH4Vm3`ZS~T+wfuHZeZ^hGYjt-Ly+lyOmXC zsKrJAukm{QV6S*W(?zhWhi{gjWh}z}?IuMQ0{V)6 zOADWxd6YAXYfh#Qzr=%zIeB7l7eD^1L*&{KOv@Wmr{&3IgV!-Fv+%m!TTv-ArcBGe zf0xb93g4^#h90yG4p9iGmigJAnpx=G85#VHTJ4Vaj0}7RTRtJCXPhcJgmjtjsg2+{ z%*&h?0{`g8_|hU%wdzP`Gqpm67QQ^AuPP+RCX1_07HNf=pf6@2*Smm=(|@OET{oWb z&OSCv&)do@UHA2-y&@i)ALkGWSXF(?Ox?7;{dwBv=TX7@Ed72cwriWG9en-jcb%*o zFJ`j7W>_#;dwow&>hRkp`QRjeXJqQ=^Pg-W^y>&mi+=xhIrPVQH#ukgqAbn(B@v$# zHzS^N;YA=JmQ&2zXwd?tYOrLdDA|l;vQ;^jY_KIeD_NMHz0zc=8+uu)eJ#~-$y9pw z4o#*y!j<*)&sAklOVt~|^z7RI6)PeRy25Rz2)eD7^zE%d8}#hGnoKovtfhL+QazGP zrDyNnWU8WzEY(U&byG5xp1oKy)%9J9RpWBr29aiaOb8;)j#wcRTF%B19Z7>DM^3N% zPo)jxtT1d51yBF!RGr`HN>hBCNNi@d9Uc?Q_!HlPA|E(4DDq!_u_Eh|MLv0-iu_`W z+6qAz%qN>SxZM)ZODXaFphU*U&92N9$uc|KqcU$xmU)cIe3bxH7GSp(lzmgmyfG-# zi?|ZcO_sQdWYMD2k|la~Q)0B;5})T&(C)^vpxs~m+1lNZEb+;ERbunzpxwVwi9_2h zF`821<;fC%=Sn;|S>jwP@lRG_KQK9oY&L#366k5ymKUUy`paag6I`h+{j-u}(V{bx zaCYX|i?v%~;;xpKj}1zsf4;ik+J0OT(u=Lkj>$3~B%@c*Zke~FlsU6Bz~&!ZiPt1c zoNYaR|E2(&6)N#<)@^oe_xDpu9GEQeOjqKNWQj*vi9bq~c&JMJS-T~6PbqOivcwEm z;t!K0UP7{HQI?gc{`tor{r(x=ZmEy(IiRC2#|JIH_ddgAX0p@+t<=B0Wi2nQ&$y0k zUeiU%mY2mw1|xDNpQ1&JEh)-fPWKzcfjB?crDml60DCFi;FF(;Rh?%E#X}Dwq4)h{ zs*$%E+v~yGXi-rzm7cw$lc{Q5s?V*gzR6U2_PQohJ>^nuwp1VgQ>{>qdiLI)Zmj^W zuD`V!pRrWWS}J_QbMy>-J(Ns$6|u5_|Ie20wq$8~_I{pB75$T?T4t%{B~$6yyF8id z?=ICs-cr?J+`#T2J;icL8imOb%IfTMIVbSOJDtpBv5xNa%Zz+pk@KGomh&xcNdz!FlCFs&8sC-{m}eGg{?4n^!>6-{m{d<(pvn1|{>2 zRlXBj15P9k*6sR< zt%9)bZzlRU9X(!f>M3K=y!{T4$e^I?s2N;1SwX@hHuZvEDA(XmbTS*E%42Vo4rY&b z(QMvg8k41n$a08)2gp?1L1jIUilee9A*YGS%P%+QU7N^`QVXhx@Q%e^5#Dni<+WF6 zD?q%8#EunpgkuGFSn}pK)nHNlQP)F#AG3PmB!PRcAFXc4Is`J?>6^EcjWyypmPWqgPJRnD{qwHDzy!Krpxxp&aopHQB?N;2Q^js?ZD zveSE!mpE&&j1PY&3j5{_9|0NjuA^z&Sw-P+LU29*HyWfF7xEUVmZwP>Ej`e7BkDbf|E*OeSZr6&2aBQuA zH2lUZrGLr(70*OHI*+=7vsUR^BPs51VUT2mLdsm>jH_R@Yk*51!!;WCr5lb zQ*=z1kzG{gqQ#^%7m~7i%N2Q$7irb}m(@Nqi^Ftte)xNl9wET&oK2KYHAiKy;@L~@cP&PnSZe8ynbtsJjEogdnLwqTD&j@CEk!jBj;}OW2yQ!FQT%5{>StHz zc#$mn>6@3!b;!`mi2|uE#q!&#R>|lad;xQZV2Y^V2=!4bhVKl;g`;@+E{sDXywGdCGe;P&j`C%qQ>`bDEYiGFA^HPELTMP~gr!RR@%W9^BkzW=3g!SJZV*nbU!Ei$!^S4IH~=_%J#G&*92* zWSOBy4c*dB;~6{lAxQGG_3tqrYVrk%pq;HG!@NnS@)}G|_Wc^j>-fu8)80eBwhr|> z-K-~e4wnvH?Wc?sK~<@R;^Q0&J-DUo45HEJTusG^?q2qlO3EVdh9u3Do4&rzD?kC1 z@kQ_xp1Ii8ke{v`2~Yg#JR(TqRZ`nsNU1Ll^X`tb#ED)Kz|dGF?r=+{cYv5^xG)lw zL}iJt@_q|rTkTUE`uUT-%c~ncsqLYpV&~>t`90YQ+<=T^hQDZ}+taQ*RWDt((=y=; z&1(nLCa4$FSm~JqlAZ_r2^CJm=R`}YykHYm= zWpb2S6#=`i%1v~g*{`&o5HlxjFRkwqq4Q6k`5HH`s5I6k@tim2JjfUp7tfkR^jhzW zseyjohUk&6=8SHi;+qaKVt4v?5vcX`Z>ZNCcWUyN({3?exT?%?)_6#)f!B=P6CA_k zyv5j4r7@0VU+1l>bgY&h${BU6Sgma;keLIE9bJvno^qyxsrahZl+z$iq5=c#J_;ad z-eFt?2E65L2n(ab#p>m7xPGPBa%2@3+J4=;TbC$?GO3D5QcZOd^HY& zCynSkn)9m{tgR*wkEe@8t;s73jc$bDB>Hd}4Y|Xk65agY@N{g1CDF|TWTx#Cs(pf? z0;k$)oGM+MN`}Qy&E32gdr;?D3{dXHbt`;#&vlqbF@Je4MI0xYs-*W>QnoDW4l~)u zm`M+@k9fh+J>e&ZIR5m|3^6WoIi?bqi-Qd|h_Ea#9S=#f_AMLlW=boqADbC@fFJ&h z+&Jqfc`6FF8kTHb*fuZ!m2WV>6;n4mM!)2n$bh*<1<4Az-MglfV_BQ|2+JzB=(9k2 zGW_YX*+s$mZ{l3bSbldaNxlsi_=> zVgV>+hg)I|;+SjL)Ecp=(4ucNbok)%&oEZ?Bn#jF;B#oD^RXl(B?sX8-BG`EIT^j< zXfI4jgrjYjwiU%aaPaJ+h3J~K|Kyv9s=@A>@9VRw_~I?)h&eXa)@b1+v~r1cYp}nT zRkIpxe`$f~&&%!c!8&d*QXPgo%Er4*J~voH#W+?CQaU_RCXV(+*dcc#!ZI*yjw%nQ zf8y*~U)GA{7VOlGGq$5e7rt1IT%P6VW6D_)N{8*WDVGU1?7A;Yx%1kd#TIm?E z@~N&h+g?j)jdzrmWeYQ2uTg&~pq~0mh!%e;rr^Kx#q-|X0BzUs+BQVj+{!)ZH}#i% z)pyfh)?JJA9hr)L*tNT+oECJ~f|X z+NSYG3;gB;Jw<#tt^YPZCBWk8@>3>6GK&UPnWga&x!~7k(r#t(PG6SQXEKFuIeF$f zZcRmHvCPDi*te#T-=@;86PZfy{=sghQg_Jsktes$zH$D^AJlaDu3-Soe*QgwZp~FU z3=#_-;*GrKJ@dccIO@G-cLqpXhrY(5)VdOX4Oo7wyPLoNMUVJ(z@FGfVEyg$FHXk7 z_l@`<(l+#s^L?;8**R(b|8py`#J||Nxf!OgAM^Hc6_U2rg=(e5h>zMqpFZ-*?A>*! zh(i+}1RTbGb7AVU*W)rhN*rXYbiyqylOcQ)l}J{j>Vox`7a`iN28dg+Xo3GvX=Oa; zVO~=&<04rn9uV=Y%G2nSzLTLOd%Qr8nLIYM%(&jtlTs1Y#9>@**B5VZ!B3ttG8tqX zbh+7|raY(mvnE}k`qx%nD&U8N3&&^A8!K$#ES53-%MwuWtao2G)gx^Of~GGy9nKDh z`{Ef9Fm`~RUe+0=0=t9YI@@Vmd-g7N!*b_4d+t%?@_PU8o7J9VKq9zmsV z&VP*#i2jF07OoG~o&htiE=;RD5NYX`{#Sn4JE@+-*wb}PJ1!QZ;5)V2YZut1N}^K85zk})=|fobM* zsm|NwTXZjL$;EYZ^G^^88iX-~x|b^%?NWSLwp?lrMISO%$c_J(D+jblcTZQ7qLp;F zHj&K|x1Dd(#s6U%p@_diV`Vx%P%LJ9pG+z?9NnpB_{#u{bEIOb4RH zbIyWuloh^IHM>l@q0WEQc~?5nG2VZEDctRRSXXn-vAOpr{ac8YU)wf}|^> zTT|!$`LvPvTXrkjWVeFN+`RMt6VRHSh9h3Jwv=)FlZnAN76u`wQn3mQ5Z=cp_`_Q0 z%2u_xsy44_SgJ!r>*3A*lk@XEC*PmcDJkEp?=_rVlbobm12cW$X3mkAVke%SQirA` zL(+88(nEgYI4$-Ldj!~_;Y>Qbsh-a!@X6cl3nU{I&ae$~Fy-FK8}H9qs*@dgI+&D> zANL}IXSb+O={k*R0BaaP3z4S|GoWJao+g#@*g39n6;NXCi~2maA3SKmvFdBfoE~+?V2d zAP?kBm}kd2_vn^T%l-1d91>cj{Z~4PJXG@=n#wQEd^W=#I)fS?uD?3dX`N}v(WSLd zU3re0!Va@I%AwbHz+24^6bni5ziqYC`uaPkG3f*>JaqYG8ONSvj^gyvraTG|qg(CW z`miB{!KVfO$3KU`w4gI*%8gQJPsFdf`E^Uu@{Mg&b`snn;rJPddmOxWIq+lnNDo~z zRlnkAe1jE%QYWW#kTcav0akDhG0{tQreYum77=@&0x9_LB8d zdW)l3k#VdMmx|y8Y437rC$&whgLqGvhJVJQ=H>_Xr9COmhUfgPXPURB?_0M2*1<y2&XsqEP{=2$L_RWn6B>FHTUGDw$Ie)J*zVW1P$x`TXi?n zZ#?7K&#W!S{S`0t0Bk%=%5W`V7v6;W^E+fl3SX%_5@)&evf6j5-q!qHt&-3~@KsQO zec?G0jrF?eVg!cq^`knt^?{}-JbHbAwIM}fns#g|D{8t49^HoT1drPPHjE-13#vw| zF*#$wwqm;1ndUL714WG;*C*g6+q2u3hB0NVGZf8+Kb5jmAwtNy1v@-O?A4k0UpFAJIUSxo1>F$y!(%_^#e+=5Y2nalj>DR(>F5pm{<&vPaqHt##Au|Xm%$!O z;~9q!Ovl&D84xs6s6;(W-;;f1x*pc)A)c{_LiD)WzSa19`J7^`txWgnJ?33OrB2w4r;CS&* zRXGftE>gGv@ShubfFJs+E*seBRwnF$kODP-;uBOnyR^QXX>oEzL&V}xxbM$a6>xH) zjxEf``#3nZ@VSo|6j!FxY7G4epjIOGq?6k@Y9Mt{7 zL|Kr(7V}HEvFYS+`p5k25Fy~=NNOOKV(W0GOYV^dE-)JFvwn_DM6O>pN01iZ)OcO-niR zm8YwQ=u)f;D{~oNKZz9J*WlGX@dk%qHT{}?4c>+KvYfwCju$3>lRB==0Q!#I0UPgG zVaN^XmSp3`0N}b?a2sq@LvrYa<2BZ5`DgS481=odU~4-aZIJyGxu7P0GcOSg2p)Z7YsoqzJ3$n}4iyS{(gW7fKKyA^e?TR}&=xlt?peMR(i0InRdYju(j zzWez4FWT9gMH$zlUg;Wjr-Bv{ZMCIa(ZRs9q>!*qcxBUd^jMKE9DHh+qe#Q`L&Ne& zAi`1X?9Q3dqQ@T;>$yE#e?Vt%14}fv+CC*Saf1p~IkIE5oR6Aw;x6Z-+R>-1?_B!< z00njTDn*Tza_&oJ(KTpZME{E@_<>7g9=HY2f)*rTgnfNlF^oAWQ9Y!CY1CR_jXwE1~rU3BEmRq9B#*!1$Yv$iAS z>{B4u5rSL)?X5G}!}aN2X!WL)zRFmBHdu`Jf8&QmX3JTYA45oGQziTG=!v>1ZMSag`I^9)#!n!rN-WM=!6l`!Zur(jPCoNuBk1 zs8+@nH$OA{2#JfE4|H9Wo(XsA17p?6WCSvb$9X{T>PhzOr z-&~2Apx_nWJvf9?Ax`WEdex{`2k8|y^@6|fH1y@_ot#2`F2bRA@ZTJ+jBi5JtZ-0^ z%~?wfZkw~*Pv)$PnX_n6HAz@a|2#2(T|==?86z;|)x4BK>nE1t_ClbR3X$dP{P1pE zjOxr`-3KyknG79n&=02k!bizRVxP}ziIXN}sdzc{d;NO71s}C7MY4VbV*L@T9hnOt z@AVz8H`iwxDAKC=57&M(tFnQ< zxbo34bnK^<7wX}AkGY4lB#ACpGT%R5D7@32WpLu*KL4YedRLgp9geTCOw8v)t@Wc? zCMEHgrVFsv3MbW;+2>;|edg0>boF%av^shM^n?Qx%54Hg_9@OoWZazohCa(Ufeca` zqF3N9BJk4s1BhLzVW_#gcdoQMgT=>?bYPmg^(OjK7U(6wY8ti z{Wj$C+WPdG%HcXQ@j&ED~MZvywS3Z1kSA^iR4P?CSkDXP3U zoEI>;ntRx|@FMRudb+JLPVjs2512uhRmKID4qcsC;{C*B`)rG4D^s?mWNT<)d)}S- zsT{9qzujxEir(|*55x8 z=&}m9zS+vy;4_9bcL^u9sl;E7U9iTfxl3%=gjN=e?~9sS{P~l4k7k^A*C>mZSb`nSPbmhI-}k^!Ax!<73^D`bmYO4yVW_#}xkyqxZtwnv7Qe_ZV}1 zXwdC-zk90=aI)%D2^cLSR;^7DRK?ZuoEPT%2c|M`6IpE~L;}m8rby~4y7>1}C%=wE z{`2M6&FTwy*LJ(R2vL$>??H$&`Sm(JBH??|?0L^5ABxX5X zS*7uD&5B7iKGq4Dbn9KPCHP~n3H6gQGriA_mu}Rr4FCD@v9mKVF4a&OfXI_I&W|7< zXc@A8q83_e4L|Kb2j~DjLtHsoS}ysR*a#1J)Wm&%w{YGqH>AKm>F>* zQbe}YQE+G*1nh^Sgm!~=m?C9#hq5~5yj z)sG-gwCEjqt&;{>y$s^eo-GT21ot*wziR@-G%EE4!X$}+_;ms)`joMr3g7ThZD3kE zUE>1;h9xonxU?RD^hcT6j9c{skrpDOUl3hiM`rU!#Da>{_YNlWC(55y^uJLUEWfj}iJ>^VLNi$KaBBs$Ku;7X=yR*Wa5 zO*oJzDSgVy^S*%LC^u=%J7toxvd%og7p7Gn?w19*D{?JPRFE%_R}P;FpXvH1%B zGTZl{FW{RIm|V5rYW~wH^l{X8q7R!4)$48PD`$>;^mdH}9LIb% zD{vBr*drRh)$eUQTJa6sWMbPBwF7!iHu8UVIMz9+FDF^wT~}Fs=bz9{eWwQXS^Nvv z`~*{#J)V~7T~1xHO9>7pYquvH=e5{m{!2jfTDnfSYsWogVmDB<+pj%Q*^U?nK{5Y?dwM&5;$BQ%1sQ1qdvQ#Wb7_`+afbU?zADds z{OLBIbo~CGWBvI`59?3%|NYjd8KfHt3q~{hc}tE|*YQpUX#X|)`ROwg@XBFdNy?)$ zD{^hl1eWN(1GrzBZ#7-pr5(!YZMCu_g@7JVqc$qAT)>Q?;8o=b#B9DoxZWaw2~t6` zmaq)xM@x(d$eIKh%3|l`LSlK4^B|FPX)K(}(raF6Z0aD9_7I1Ut)B$|4sifRSV7xm zD9yZ8XaPWlUGzy<@IWZ|otjl7agzTPN`Lo=R+Mfj4P8oY<4Y1C+pm2HCjyZMK?PIn zY#=P=`CA6WxxMLYus`g7Lbk)ajc7edViRK@mV63G&)YA+&^=X-m@0x#UuOk;=tg~t z=iJRKwF~l&U+&YC9f{$14I&EYt5A1NKD*PiN$vhxI`A$vM;AyQ#q*+l#yU4(k5+x?10z zjW!scn+jXT=R=pd?{!dPuqEN%xqgj|-<#d|{ER(I;5AzG!Ee++3;}^C-4bEQhUy@% zt2NPm_D8Dl zFfKJHru2n;MMtVmH#=n!5&jPyh||;hzYstp`4Aig&FCe?W>q z>=Te;zR%Y4f=@HM1tYPmKE-o7d?Wsl+OtRmcP~qh#Jm9OZX_}sPxf9otW{_1W+Y|? zRjL1OzQSr-@}G8UJ2|MW6w8dyG$nu7<7w#V=ucCqGWhmwG656|wIU{a8Cl8|NX<>N zlIxLy+!oxO|GIoFO|^<{n=0vEov4ClYY@N~%3t7^gHl zt9{N=4>YqAY~^zA)W_Y3P-fr!(KcJ7jh@biSaU`06oNSd@s9>nXbTM#nHRc6QxZEp zv?&2~FJM)@e;QEaC$kLD!wU>hS>GLag$5qZ+dkUCM6qCL)4{w^hXgZ zi!*(=CW0^qNdS-AYvo2rR57j88;&r9*j(>@+ei^mhk7Kp=~Gju0UO`vrT_^r!G z!EZlhiRY}C(6;f7H|+tx?;iB6_#O97fZtUWR>jb9ZL9d9s@NTVub~PX_TLr1gEPM~ zei04={s#RTtAU6E`W=)V;P)e6Q`ilDeab3-I|aWFU2ctE@`JXG|M4&OfZy7IyTNY@ zadi$9k}X>UL{D&a4LZGTUH|_19uU1Bb^SMpcJkRnom*l1?l#n%qTkQQitpR!8Z-pk z==TA(AMEL4+m%1(Vv)4(b{Ee$A_s+S><{%$>U^df%LfJmp?CNBE_pQ{g0E@Guh-dE zrmTSdzIsK_wKLs3e8ghI9q0cn0cFHrG5eQFlZYn?QK+g&9O7*qpoTl9tev6$XNy3i zB$3#ZYyru%C5I_rHMa09;tiAY!u7HHR9Xx7TfBe2p9Jz_FG>ILoN<@>)S1+G zVdj%=1ly7yoirYZRuY0SaGMHydww+~+R-zKaX~^&$ZxP(6=X=AlT)-=m)A+am*iJ` zoA~QbzQa<);87<8%@{Y+n$hv>cA62t!EZ+3)!8Bm&-N8vr^%>c6%vDkgiI*CY}Kum zBy4lIWeg-?;lN446!2ZeV3DJn=eU$H_2VWtzvSIES}(Mfj=e*YqQIR=hO(u-mnWp#JC&*r-aeV{H4kl0gtX9U zyKh!Zfzw%L#W$Py%Ar36$J|m?CXX<+fhw?>Wys}ek<$+_`8z@5TAYq34e?% z!D{#m$7itG6aA)dXwhsiq2A96$BUwQy<{I~&i^8`vSW06I&dnkIN_47>@R*)g*#n$ z_KzR0SE1SrEwO|i?VdQ4=T23b;m~8<6Z_-eNa$<~&gXScWbw0es8*{)_k@yltLjRs{zjiXc6Yf{eveS?N$r-O zRn_g&PpLuai{^dw==Q0;n1fgQ9RLuWqC2HHlT3EkW{aBUK#-dFAeYCZxp>9Y7{KHHRbxdlGYNW-P+XrbGdqUs`{DAF+Q_~Huc;rO znaK1O=8AY4Q<1=exM4V$hW|1%kSf0902)P1uuWL;oaYxPVuEQCd5F2paq=s>2;XN8acY%YPXodW=H;@TPpCF~OdJX$my{0I18dDJ9*@-^h7q+Cs3p01|&I~YaoXRpi32T$}bc=fwLBs4+{`^w~IZ88Q^_7F|kRsanf zgw=@wFyfY*VrnSEen%72?A}M2<0sVD*Ms!uTm+qX>l8Jbo7_sLVsZ)W~$1V z9ME65W6+m9f8-Mr^tYy~(ci|?-K${%{r&mKR`fTVfE1%0TlYXvbW|KUYH!sI~T@LdaTLLGWG<5bA4>Jy3>Sa8j%;+DWgXPz59oY zRAbhNU#Uj=!R3Y^|5c}|AxIjKE)J~iQE!IcaZRB-g}5;;bwDR zDu%u>$jxUnplI{@G#$U=v)TT0@0!poNvp7)~z3VJa{HDt*dbM=9GcC7X`)wo1x%r{r z7p?lSw2ipt`cDC#{QfHsN53i#UDHcqOnlC2op#gsL1!F#vysw6*S~0kFX@1Z2Tifx zF)R+o$EBAJCPEe)<>F^?ye0Dw=km^kh1vcK*d}gTrHUrD3D1=;+4+tB_; zusR}Vf3aCcHyZ(78XxbpHXJYBp>qv5^vAn4U>3?XH5?m9M5&xw^_gw32y27IS()C! z*+P~vW1_-N$qdKXN)a2EEq5IwHmaMhp#^RUnOgYLES4Xos2}%I1ed?iUEef>WBd-? zwjp$*WTSF8FNe9|VHUdU4Za~_-u7nllQ)s^$lIiXb=$vN;hkLw?TQK7zrBjFjySg>ui1X@fa8|=O~f3w}$*}z@?bUW?1rs{qi_@2 zJu0Wb^{m%RPaq7B?;r%UPJ*w=uYi0ckT%GxN+ID6SdAJp$oo^i6qCTAXo*Xw+QV|G z+MtCDE26OA@#D+Vs!m{aU=2TuPl&R?bTXyZBt5+)quzUG5X$sUq-K z%}<@oIBK@|8QyTeuE`p()Un*4SZ3RXRoCcn95h2L(1kmmg&#lF?zo>0fdwtQOZ?BJ z5L6;BJa)>FAfXRoQ=X*;2Bf7zwVEniMPh&V2~PWkOY7$sgN=Iz5&TL!=pG8G`DYLitN)uB zy=Vi+xc&IhEgsV7-be2bvoGKSH1YvA%?P?w~LZJw7R)%iR2IyK=NQ zzlYeh*sh!bugwp3oi6a_-5$}S2`Kz6 z3gQ`CHW3m8NQ5FaN2rk-wuXq;>6aaR`X##80T7!4-&&6apG_=0p6y6dZr&u3Tvm>rK z7OuiH$(C!>sXQ^Wj3Ez>Ng^gupsI$ct#FYBRY_8ZGDl6`FAvmEb{|!aOB}f3yRjm+ z9%dmsf1Ha=Um z`nLXRbz3T*Xstcy^mbbN;RkzYt@q-dzP1qdoqLyT!QLf1Yfs4nQuSUb zciVTji@cw5MsUz*)Zj+KvixeEy~AgSgquUPLzNN^B*Df4Gu)`;NQM>CV5f@^a>0Ax z5<*6=N&rH@0`+=GlD{Q>h?=$d5`7~(T6>QZUEI2|X7z;x>NeR!{Y{x#j< z*QV%8m{nI3>lMDm_EI(y6L*YJF-HwjwNf=IB%vGEREH_tT@ZZ>x#01&+93tx#P=|Y zCS$9Hj=16*i%&#Tqt>z@GYO3V7EprdH&n9{;W2TnsgF0nn?Nyz`P#7=TSbM}P z|0GjpX z0N_0^M^HnCH@5?I)<}ce2?{!#TE+-y#I{|$CYPexm*@6GdhLn6{uu--%h4rUm+oAc zLzmoM0>|qAVFmkPhF!m@S$g6Qu{)%|x@qsiT51Gln&LVa89(yX4Fr;@_Uvy+k2peUHV|f zo>I3^PJBxpV}T-!VWK$axm6Mrow~EVv1Ka4_{MluN{|ZIt*g!dg zAY_UynkWeqBO7a z3gYt|r}#Y2G{Y^m15_bjUnOd%H~Z@isirww*0bGXw!+=wGT=^t_+X1FksXggm@PRE zV#Hy<7QD@_E`u=31}qh@{yltK`-VN=KrX&Lm5IgK_iknrj&I+~6`e9$YJ|#eVo{(m!y+S}BM|m76r>O-KN7iz#nHiA9F+hQ8I@?4RGUN&Gah z71cP+7FaSVNh(gO!yL}N8-vTi-ly53vlgpIw$dhzc9yfSpeM7oeCxBa_~9Gv_Fv?T zc2&sWEHXov#mY)iVea0Xr~lbfu5$?RM`wfR4}R7AN_H{&3*jf~xw21FPxgvA`p|-S zK5zS0;UbItuCk*irs*)5#Bf{x-#=8l3B_KzYUr9jFtqs9WoA|~b^S3|@`9{Pezl(~ zGwihLYE2`nHArFIQ-ztnD#a{z6&@A0x$ zrOug_7E~CxK32UU&FWCUMu=}J8qKC> zxn9$T<$6KLY2b90#s0VbQE;wsaGGVYRoz$?_cM6kGBLegY#y*>T&(6NVTLkdd35S& zGHs)D1tCYW=I~bV4X-tGL4J}pYM+*koFSq`?B{PrjG>)^K7ln?W$?I8C0i0h3JGsd zN$4#))bX_CN>+<=aE-r%*OWgOm#H#WO>D5fc;7HPDfFm4n#NVQOnz#L_mi{TAgSiT>DQGe&TQrx z>zvqX@_-cgu)BIgCVxy>OLL6LYTN_S>dg-NS4Hv*TY1!x6E4Dzc1f4YbUD8#fYBmqDjyazs0&3>^h zO;P~aVgq+r5Ut`A0s6ro+M?x5m8$a@x_OsU7HDzjGk}(}z(q&G)P@O^J{$0jh(vrf z%>2m6$Ui^w?M2$&orJu890K5o%(8fo+|v4evM-&6uN zpY=+CPQyegP27D$O}o!(CZ8lnj|Z8KU183Fb9}rv(3+_O+s|P;)kHsnN0I^@GSvxM zhvfXv>E*j3^O8?@gG}{%5|N+(0z}?=XIn(}REZ9e`INIOBIn84l^i7&Z0ysP$L42o z7@Mop2s-UsQoSRu^22H9$2+=KzRNYMaue5XmEfa1TdPn(|E>=$x=5&xP0qx8O!(-^ z!Hfv3r~9h^t9Q=B*@$m$>?CHU%oCb+eSxACXWM?8<7}F!w3^$R3wsyg$cW|ihW*WQ zdZTVh%c)4i^Tq&9zzP_!YSqCht+F<~@AOM+*+y&Gt7;hmjMGaC*MzQ7@3NRLxDl)> z_mR0^f2;*Zglf)3%+$M(%H-V+Ou(n|&PHtX@eXadLHOtN)~EQUCCStE|1|3@4WU^C zl-eUVIHKu8qF#6(F+98`F3B?uK1)#cO`mK?`rUmsKJaiT8IF@di{D<(S-#&}p!)=_ zd-vap{QSy%-}P;nWSwFO6k&^VCfO6RXYo^RwbQ+4UsF5qn~`{2tVuj9@wi-Ee{#}a zVtP}@f16zF{0o{vrpdk0ZMiDd%D0+WkhSe9u~jxMn3su<(z^cf_%R>i z{U^CsN9xroUSThiN&#-OTl5c;?_PEIgwR^48%=A_$O8Y_QB2T2{$O1uh$$ujrB#IM zZ*-_z%PuMqz$rnrhSv_GG(y|$gi}VFaz>w!4_STICw(=3iaxa)0*vaP?e(ChnvIHi zFv)+_q~oSItl}`en*QX7>~xEgJE`Rau=_>@{yj$(n_o+pKWI%09^m${xw3E|j22yT zo_HP;w(J{N%%)41DtFE`{O;`C{gKeYSKONHTi{$HXD0Yat~S%zM!Kwlt^o(>2Gczq z{Q}6@T^~R${u4lt`%Y`K4vPKwB7;U@kVS7d2;Vy-G~74l_wkI_ui6({1DsP z`1Ox{fGNSSssUP@7-U7-`HJ3fK(@DdGx><0;(IgA1liigh+)(1tY^;(vPyl{l~TMp z$5}U4G&dj*wSisn5`i79pf&8n0<1q*62QK*$Y7s&a}xG^gS|wsH;7hJfghGQJOJLt zuQ!L_SAri;(Y=Phi-SMYhdeYLyW5$bIkn zslqnJ1jH>*j!Mz^m`v|4i5Ak3^A;2VCy?Lg7)UJZxZZ}+0^J~oTIR7fC^f;M1)ZnE zOz=Vsye@m+6|ntrg$CYv&bu&L^yQD*p@AVdvOB!a$n=H*nox)%Te~O(K1Tuqm_ew( z*I762YXC3N4H|fb4hLXFLnaA3vnGi_JO2<^2L-TB|6|fal>N`c4BS`Z*8S0k`0KJcxE(XN?Jq|91`!<#H!K3Oq6%C&0$p~ZXOzJNBJh_ub-B` zr}g%%Rdjh8OJz2daTrYU*F*Z?&q?wAU)^GJ%`1(gnZSzK|DD*)-rHlZ-eb%aCXHcM#;c#JpuNMY@<8j%1pC3URU-C+-sG0SL+JgX4O)FL(m5cnt z2v=@>g6t2FD^%Obl%|{&sYMw6D`h_r;ZQ)+TUHd7HO(`@(A)4#F!U}v#)xIC`Aoo> zCP_%q(CdAUKlFU3&2qOF7>G{x3Oz^O<&d{?o7^Qf#;jxwJzNdHyTiyarG`JB?bqP@ z=9Z^=X1?~mBgyi%dsQ9rHFZgCmOp(ahePbnVCY`&ILn|FZ7VOZ%3*~;^E5RMO7Tgp z0sswRwb8x>)2241i;FXDG88%o`_J=&u~_;0pz?iO<%i$Xw(?a|d>0a*y)=b4ss)b!4+uh&nf?OnZ{crph24<}L{Amx zl9$76_KnZDrMUW={bpswXFR4Kp+$Eo0nLUIuJ{iwDP2N~4%e%A(E$zFZjal{^w7#V z9ndI8c5Hkvv+@1xlE%%sT|epidP&zEB@1>`U3SszQ0?c6kwry}gtVrSln`3Er+n~N zvX-1WF;aCx^_)&4tA>(!5SUFP{^yyDYT|z)u7vZvSGP(5?T!*N^h&9T;k>4Is0;mn z!H$WQKfW|nJBLTgs0h_w;eZ%~izMazO6B;aT%RoE%fnqM4Nbo$^`4=miqpr899C64 zZNZ#Q#~kB;q>m}QD5daYl7-idcZHjLUqtzS38C88aO6@c1)LA}jGVe??txa)r)RW) z>9NA&8hgh*eq+BNarK;z$A+$dlH_{>@6f7Is%hvkRVP)?>3l5nBX#w+x)xboXqDkS z#!s@clH2{tuBEbIesrK88>;QcOBHx5ze5I1=R*1~RNH|E^*Kdbd-k(B4o+!LZnBDR z=KEC~rYgRLHmX%3^^d=(^1P~(RQL1?s*a;EmsK65#!v)Z@Zk4b5O?q90C5%Dvy4g_ znjS%6Oyd6x9#qgV$AoIf@teZV3e^_#O9kdwffreUD3}CALH?SOEOVV1D4@KHNgrBy ztjYI`pVLFvGbg3-YgFj^mnfrE!x%B+J8_wq!DUKkF6VU#GlIelp$J2Wh_`v1)HaCi z14AN>?+gof{UqG=^+?wpWnCM~x;|6Zb$waae}o?#_2bG5CR}#ORi%YntA+?zR_bW| z!;@NCfB&YS^~Ie70!(Xq1hvy;pLEfs7mz(vTdr3W;b{1(lp-!m7V%!#@2Pnt{y)(m zhSdK<+m(PvRh{hw5(!AW!x9Vvb-<`WS%Ly4Vq}6r@4!TYPz_6KP{d#rLP#JiYG4w~ zbQqmlthCyS6)ml{YD+N!)&!7MWl<4GD~Q`2V=XR)080M%{m!|wWI@|Le;$~-o#orl zcfPX?8FIyylZnt3gyup)s9^#Tf+s=h=OS2E|DKK2mw(kDeae|*>u)N%Z2_qwDBa6f zC`2jKGg64M9FK+bCqJk2{{e~rKTslpZ5|CIG%$eRQEC)4$zf<_HYy1X$>Edhe+c`j zu~Gc(EqVWbQ-r^J|6x<&rAH(D{RjQl^)$b;rp=ly#E@wK)X1H`8WDO0-~T_5rPVFI zaoQ~M@5+irNwdoYWu^TWM}d7o80?;lGz0pFVZLYP?IkRso0O0YqNTb<8F8TwQ7P`e zTd=}fBOrt7@JEr8ahtNOp@c)Ki-ptzx-7wgUq!Nu`4`Ix8<0Fj8{JYJVc0bk_ zVmBagMQD^aQ^9`-`B=`~z~D{XQ$Umkp2&}s^;x}L*7(u7tkX#R|A8Si@X9N%%({^n zx(L~{S!J0Oi#p8~eGJ?4iv-^ZQ81ce7=Lm|!PtPqT_U|s@r44(lODPr>!(Ki`U4C* z)|XyK7Y;#L^s_O%knYWnXNf^Bih{qwF!~s$bskEVXX&T#wCl-E>37<_PTkG)nJA!k z9La`W7X5=mBpdcQVxEH5^TfnAt*7KHrPzM;^DVa-Q~uR7h@4WDXZVwlDG|v3IE9mx~ zY+^JS!$BCI@E780A~%+3a%=22u~oRo_dbT|xw0(d<0IH10sRE8oQv&8zk>O=k!zIu zc^8_oaH`;DH(+zPn>M?>r`z4z&Fy>J!@hb3`5Mfb!(o}%mSyLU{W zdy?DRm|!eB7s(i@cX1+%$?#A-%Uc1LD(Baf{nPxR=p zQq~m;EX6iDdb7Jl zil{&$6wyu>!ADgD{aRD$QS#%zm6ip$xs>Udo1j6q41p3KKcy&9$RNZj6hH|&BG*=%U%6)BNBJ>eTNi6ci|vUHoQ@zO?A?4W#Fr&0{XG37af(ch$hUF2Ypspbfy-lX z`ekGT6%rxz4XRr?gl`51*0^o%%7RR}m$yjZw4AyPz86){Q|!AH%tD1^Ue zD-w~|C_Xi_h}L@Of%RAXwAuhzr(bHr{vq%4}0z~QKi#4up)C{8G>5l(Sq!epy#QP-lOqm{3cIeEG8+`VM+}gEt!9c zk@bDm6VnF0ItZC%9;)bfJx*04-9T6Dbs_GH^}D}+3zL_F8Ohmy@}#ESc-CBEjSU{H(BZ z%GoNbPzv=;s07nRs#z1VAqRn!gk9GHYUEI2mc2WUVc`GHClvJ+f>^?86kLvnpfCYCZWwto_Q- z&>g*CEC!9@??z+!HG)R=PK5>x045k)7vl?+>tzywS(l8R+64TtGawX&|m4i;m4 zpi;8QSJcfBIjNaPBkjdP_RVI^%BR;3&$+eO$MrrZKEWm*y*)E`GNfVF_^Q<(qU}&8 zd`k5EWZyNB_ijLMzdw3SUjOZCeo+5+N$i5W{vSYL=8a`93}Oy<5$h-46~kuz@l#kc zbxM5~8_)iP_w6Nzn}{AX9Yt^`tB@OlAU`K2=T+6u%TYyP?+{hgZLJjb-fR@*(?#V) zic+P3Y4Z~?acka4Rg@~{0+xeH3;#yst+5X9uNj07u-Gefu@f53(MXYjtq(6e^J44b z7W$)fDx&0!>jO;KVzoYCD;zv+f-}%Wvt4%KisK&#@n-;k2J`1~gf}qf0Wu*s1@=uL zZ#;qIk1(5pa}4}XWAQNw4ZD5X<%M^7F9$=7` z%Pev}4B!KYA^3o`ip$l0185TF!pJ7E!&!EvC*a1?9=ofW<9$Eg9be}OOc8zHWbEBJ z5_~}4TjsOvZ5V}&mzQOPGaho+of?^g7RAjLB`V|SA+?fg500{Kkb|3~JiJC_i zsm`5s@ZPJ?{q3HV%Y@%!p$!CiF$Y4>5+MXY4Le|Kk&pK zz*?a^->!ya{P6g!+961FaP*K5S>Tqutheu-fC2|NbG&b$z;8>-LbNa#^L-<)|3`Vg zck}umbvM1?@!gGmYfk*bUH9!sH>eZu?)!#2{xw;Lgw*_uEyKTMdf(AtL(e?lJEMm* zp+4!g>nl=xTCo^hFYC()NN;ym{k`YsWqo!pKe|;5pPa>4>lY{ zxtMq}kc)NG!Jph}Pud_Ze5(8hISl=DaccDud3fv9Nx1%P0e;*yamAOGyx+SR#!I>S zn89tQ#F6hvc8^N-^}y0sZt2)+vRjyJzDgF?|D@bZRi9%#QYVNoyj8^23`C7eixz7gu;uDA7bs&?vaPkjrfX2{@tvmMV7_Xy z)*@Bws+x@J+sD*u=ZQhJ;06SdTTeEDrOm}pPL0^i7VwMD!}t&2SG&y*Y72V8iS4`S zu8gj%rK18G42UaDQtE-#JXN(h#^ZIPGq;y^l>0|&8`?wG$>{+?FQe);Pz1S+s?Puv z-VIj%y-{iJ*aWRoy;N+1k%|9UU&o^jac160Yu!-Tt3b+~o7k$WMw_-r8f||{(y`dK zJ&w;v#wLkv`$}BlsO)|Qj*3(6m#0o|DXxLAgm7$w=#4nSTqvAvcfbdfk z!ibTy@Bg~SZr_!cw`2>gBD!MA|56V`YZWrLL`(UXR|;y&>lA8CNz~Tx>Q8y&t60=t z<1!gMYr^c7@zkVdQ=`SR*I(Pw5OwA?t2%Ae$SkOy~^1`eYvOFOs94!6M(CNnS;eSQNhYMM9u`PDN zAkLQmWaM0gWx9`qqjI6UrsDn=-=)@$2@Gw=hG`Y<&Gm5|XH{b-t0pu4%O#)SIx^_F zeH-FWjMxR1GKp&QVK~tZqd#NX{)z8SwEjaEutn!5D62_p!E&`jwl6Obj2nK(7Waum zdA_&UW--87^ZHGbA6qrJCKuk1`$U6TcdECi|31&meKZ*30txN%0u{_<#-DPZIMC1@ zd01~gLe}v{B|H0s5Bmcnx#9JqI=AusUYLEOax6Y7yW>OW(S70zSOudJCr3aYHepeS z+qaLezck~wM%ADPeZtXGU6eYf|oT38d6bDv?mk9}K$$9cr;*@A#*Gxrcc*dN^mwz?(Z zE6jL4`*N$8)Oa2t7FS*1ujvx&nb>c8N0dFp}y{5IIvs&KmXx zdfXtq07P%0BY{96P%{KOV*%ny4naM82dn&%HhvqkSnnE)@ z2#gHn0cG_h^hc9bda3TlyC9b$5U2<;O-dF~lG_E>eyYl@M1c zG_$@mmi|o=YTA)VnP&el%>G|uqi!g=yRH$#HpiH}*d0hfHP}c(iGuZ}5Rg8O@jMiT z0pj>Q7z|&b!WFkd4cX%=c!y~AfXFv z7~EYSHaDsOOXJ+i{**vY_Q8U|ur)94QyMn2|0!hd6gDUO+$a%t3!W!Dm(3o-gX_At zOpIXNzR$fr?!?b9%?PE#t@rmSf7cTiq}_$HW=9OvN;EO=M@P;b0DzVprP8 z-(Z{hy!br8mcB1_=BL8byd-xYavT^{D)B=t{kHrdZ^h5X6VkmvHr-& zAl3;7y2r6)@x+5L=*h!V)@=#5lY*`=D73fC;GXI-$B@d6ejz-deGeeU+q5xx69PL%E30Ak!LrW-IstlLZoge+fJk4tJXYHELkD z>b<5k_fNjKB-%gO&|bCdDsRd(loR&9W?y-I9EUEso>i|Liy&8n%Dxjh>|cGEVAok= z$6Um&mREnuk3NmX?uUE^cH8lp*zI95EXuq%3Og1N@xMk)ZjN7<82swn#o)IDC57>O z=!!P*v#MUT#}60b&N}{!HrfaHe^0jFB7`FG<9Wq8cI=`>&F6+(GL(iGObp}~~6^T*K7_So5NE{y5a zG?y8V!@q0AkwO3B0R0m8c*;0CYG{z)oj%XEJ$Z`7k03bJP-2 zaR#iNPqYrMqG0RuM>l|B8V7)gmSM;~)wc^aB%v=K2XD~l$=Wt=ycxd__U2)d_!AiR zB<@d?QF0l6v*xF9WFEutpfTbS2&;snBcAx3p7=eWd&8d*ZO2%McMIlNEBQi6*z9Z~ zr=Dg%d>8`50S0UI8%NdnIBHT$ra;?0Hm5j28>TSbE~zzQSet&+IvqkCqlHMtPkTcg zY#wq!q3k9AMv_@*QBBjAkj5v-h9}Lz#rLV!Qs29=?KB%@C*U=fuLKH=>yMuitlU>R zMqF}t)&XOw_?}P}S7d%})_ca%2az6w5$^s6%>M7e8P+2eW?zIxDNuoH+G%mXqluDA zCYyl?@#HAPW`D^I;mq!)?bw_;Px|Vdf8pu7vsn@95um!*@|$cEu_5Uib7ECC<|)Fup!qV$5Lbc!X4T1g z{V)zUcKM2XXG4w5dNGv68LH&=CH>>$$r?&6GY-|D}?ddzLEB$YE||5efUe*o}@Z7|V{m(Iw= zoCVBet^IM|US*eI7s!*>V}2FZ0++!r5U)?|Qbr37_7+%6086l8FtW_N{nV{xmmtgM z$if_$*xy=?=MwV@ z%LV0evuG9zA4ZA=LEt#q8+_UTpnE|XNXO>LlB&H4K(Mv9^)W`>#12X+YCA(2611NC zi~0iL;fP-#agl3uoOLr6IFpI!hLUFI@8AG<5{X=nv2p2$xX8#1Gk&i(yF>qcOeDYz zV;#wY8k-G0tu8VKq~7U+E=<`p9|VHH=7X&?lRg|~=_>{qO$WED;dBtxlWFZ+ih**Z zK+?%hZ}xA~Q3>YHJ20^>)%xpSIEhB@TQDjWaDSBn*^*J7!q(e8X-zP``^(n(E6oY? zyVu$ETk-!)g#SgPE2y$oh2byeMtv?+ ztxX{DvTGqwiN};cVO<9W>ao3AplmHsGKC_!{F^fMmrE#9m^ZDCts-~w8+tMRCqq5z zt(Gc8H*gdK*Z@INQkBtCstPGpF7UrXi51dPtj4k)l57mNXQ%%+1?5LcmW*ImkAVqI z{MjH|!rB;yQvS*XkDf)qf}ss|q@smsmlu?;d9!reok<#k6%pHBO1~8b-YP{gq!vPB zOGUE6jZI!v-Mqfc2qJI=3|6<^*$zB`&4%vq4RkC+n?+?Dkq-2W8NpS!-1v*L;1bG@ zc04pXN)zE=$sE86HwG|;%L_{3%7pe?)81dE?S&L3k8*HxsnYfw$^{aSk zzn=Lyq}u;*&>cqDUG>GhWDG+I|3Y6tHAyiS5dr}*ut`}4om3akla;vrkQifs@;2PS zBc&p+WEEcc+w`miPX8Qs5Mef|G;-s_mbIc1Z4ON^>F8#3LWT(=@GlJYd zd8v5&D6?4P1JhJRwmGnjp*98$`tIj`8C?+q=sbku4E1RI*LCiKDIq&BJ~bG^yy9wT z( z@a9{`7AsXmda7b=KdK^R6!!g{KenZX=U#4WVfl|XTY1#hraDj7uKS#D)w{=I;1T<% z;J0JxC-_Y+eILJ_O6!rL#Erp7PybyQZFFN`65eE9U+z^>+6|+O*taIoXXK&l<8HwH zxg71;k>lOr^aO52ktY}B8M)}Yyyfw23q1kNv)*~3r58ytb1J>*@$<9k&4IH_fl&Ix z>GoQGV5hiV5E2bd+L%@WIb~y0EmuSat)HSa@c66#bnxKcVegKw<9Enik=D5mUqk00F!yr*?t1Lc5lH^JSAHAF==k=e!%y&&tIPcSH7=(et;gpe`BBj6g(RWt=VVB z$17BPygoAdp-}{;Qf-e1d+ZP+s%9Ke>YRAy*bWCt82xkcdm!chORvZA4SUNHF$&Xg z4t_A2ZV!Yrnq<$ZkX`q5G4zO{i|1H*l@ImvXoeT$s_Fq}|1}IoYUd{~QgDx0H=M)* zZ}y`u#1-ct;# z6H?9#D9^*Gk9q#d*g7`(mv4J8ZF-{yu|lrwL;I5-z!#ZGQE#mtM)%7_|I6d?CztVy zzt22e>|&z;y5V~O#QiSI8{Dnr?)bfO141c+8@UnYJl`0QZfYN@Qx9N=)0F;h&BB&e zdA^Idcs{YTQGvVG7Ds75gymCW;Z z0?m@h$sm$YV#H1%EW8TO>`kDg9UGJ76Ppv5*^m$6`>=gNmD0PLii8eSiTcX&bzKLL zp|!e>uw2x|?+ig7!{M7>f-sC;4mX-c*2SmPBux7dGrMCmUAoa#SVRU zIXHU+{sTH3Tm)n&>!@ z5ZADK`aSugt2>Y%kEj?1V> zq^kwcbjY^Lb)&?AakQl~?8bPvqG6_ojd)`qWf>|F>B36Uk7pO))KSQIn?Yl7;~{$aSP-Mw8fVb0^f4a1n*4allBTMF%__HO9PvpP+%gV8(erFmVE*;FU(STJaP^cgHP?1M5P z&3i>?-*%e)aYz+=Ddwx>E&eVv`<`J-lTUWg=Fru1A?#R&9SN5!tCRIbS#kr`JgG;v z-)MgaTRqqyqiIC{8ttiFZHuCGHc;~4ed!gQu^FG|+pgHdqiWHf%19m@ob&pTZ>u#L z%0PxX!J*Lvgn!wbejhcbU(cT8iqLQHYH5q3=_h>^|5y+a9-is4r2mYN4y>6F~@}94&h_ zk>O=pdY3iRca}ypGRDk`THFx%`8QWY5S36l2voj?% zmKLiDUOCG;W|D>tv5^q0brj}>?V z3D~?GV`!4AZthruS;$&o?xjg(i_e7g^ynbgj^-YZo2{Z-NMMzi)2=W@m8~uTMdPHh zE?1jzqlf~Q4@3%CR6MrYwKvhoL1V>Yn1FQ?D7#ob+rTm-pA`jG=%cl`-T2kqpBS4# zRE0pSB_r>dRx;P9+Ku97EV)0SXd2sZql%Hviu=#G+o<|0ApxX9HLQ$8kIECkJWjmE z8ots#p*yj-Crn6yE(FynBIJ8qlMg$OqA;6$SCMQaA1L%{5}6km_E0Xo)~jz;Xi`w@ z>V#w}xqH2na2HLx+vDq=N*gY8XwLaSV&CVI<3b!^0LnN}nJu8ZrfinV?8yQZ-odMi z`;&m_F5I0J)4Ted4bw1&vIWO3y!EH1VuR zVOF@aXxc0w(|*?UyYDy)IzRaXd*hX9nUDhvO^r&I{!dOtd)2?pb? zpHa0b8gUA1C*qnMs_q3`As!S?>KnxcyKZ7P0fn3F_)9qiW}_pRp?%%_YG;%Qxjc~r zZvA#bYlz{10?}qd$oLidb>wQ7aw%iMnN@mWwvpKHpNKhMcYA_2U zE;JUwdfERJ9aJao!}3U6l8FmeIL3vZx!`|BC!OfLb<=-}&aAR9I``amN6B}fvlw12 z7&E1`ld!BR56>|uY4&XH*(yG=RVy{=Z0y0QZ)8t_3;4AEkMWsSV&l`Hq-5HH@4)9d zzykUMnOVjI`%y9OW*C+FZkAES^`WgHxI48~1jDA{YzS&=F@Gcw>^J_uW7rH4Ky13u z%yKjnzt^}3|>XfYbwdPu&Ga>&!Md!BJ~Jm1s{62AkhO1tR!Mc~@KMpZ3d$M7nmU&k?U*9w0BiMiOG4gBVg`%m$k zeVZ+hNq60Gd+FIRYq-$#E=o=}?wCCTJhe?Iwh71te`RVux3_V7 zPfa%h*m_hnjK(n-RNrYhcfxQUOo^t1-4G}Pis>Y_+;T<<2CTz-k?*_)*q7Z1?3=gA z@Li-)r}M*lwWpv%4`M;#6VN`7;*R7_)}XBR!c3g8o6!uuOIm@C4jK!EXApaQwV z?Bo5|Kmry{pR|7Y8^w8k`~H5KYUt?CwMHXw&y@C0@ej7t^pDDS`+sVp5;?o5k|F@- z)_Z!o@t~Zh4B%N5cFZ$Pe-1h$KdnIu97Ir%z%A%8`%?e}#d&QjHF~%`u^aIY2wck~ zN2EZ`kyufORgMT#+NT0w?GH)~Ek%M>^3fSn8}^fsC>*=!E>}n6uq#w4^uOu>HMub}@hzA5y4SJoH{250xPC#X9Bt@QwIW431f z56Xzp#-b7%8wkVXf-g5~es7t-#ia^X0RXz`f zp6#WGJ2HW6=@@Jfsry)ZIU@0<`**`^XIL$OxD*cxOOY`w>cq}ja_C71bxrjyBJkM# zpN)z|IIJK7*TK1%-J?5afniyM=R6Srs}CO!yxl0zy+cwc5I$M zj`=TYHNR2$RkYs~lwO?nyoO^#y+}(J%V#*q?QD9|F%I*YUNJ~Sx9k1kpzCr|(Uq1a zs+Y#qpI1AZH(`-}`IrJA1l--JFawY=X@3MiXmZ!EB4+JH=X?QX?uOrht*S||;r$++ zb0>ur0+bFI!=3Ys06mbgcHIyWj7aC4Nht#=t8MRNwKJx3zIx^VqL!_MB#PlIwT*RH z8{=&*Q5!L_J)(_3np_$&3|#v7dO)XIFlymeXkptbXg3=Yzp28Sk zU1%g`CzyLrqMbSEoZpK8u0es}sI>i}0WnZpxhm6~q$WU1B_jffYli0FNKtFfXp&5) z0iUl}dtqf=Bc44wF)XRMzhyLAS|Vga0N+DLm^G?^N70YM=sFhgaZ@g|l}63!?Z#V zIYs#B60Mk=Y7L*lNv<~QVvQEPwoD+8HWv*AvsBiXX4~`MQNFSCHUtga{jv6SkDgTO z>5FwnwPp4KL>_*TfJMEHgR$aNEj`Tf9*f7)(;5^k%ML5Aj_x9hSv${;ZzP94M>Oy( zrY$BA6=T|TAnKeepfoRDr&PL`X*2)koIkU)Xyz=a(9pI6P~Zm4yYuDg6wnzP5zh{E zhYsz>)Zvj(rz>KWs0et)C=p*oE0I3B3o_^+69S314-q9AFe+Awl8{f$Em%gPE z4Qm%sqFikAamUoNYtT=*P^7tg6!s0m8gxOl8-xImH0IW*^pQ8e##)Y{cbuXEEpc{Y4aGc0&M6HxJgYQyGY?KuK zf9NPn_21;6qy6AJcwqN8GJha1%V7jKbuiq06xoaPAKjEoK&M(MWv9`a$~Hr)?nq=X zM)bHo1@_uM7@{{kr!CQ&Hly^866b7+9t3grj2Uz9D1{)Frk>MwV>`;Rfq?`?pGCh@ zs!RCb4dRG7o3HX6%?O&@IqYEkH|#z@B*3ffDBX6!!Upq&L5kf4E`=Q#8fkJR3)roS zuni`zU=(p{&Tean%wLFb*5)*eW!-1vGz?*Z7{Wm!9=0n2`O|hn*kI?dd7|FLihu71GFY#2 zC17~|bc2J&QC`?N?DnfQ7yV7v+l(I(@46XWE!1*MJG-yW`0Wm!9A+ybqMW;If3C|w z+5h9(2y^TzA_r4NLyW*uLRUI@s>@B4B+2c#Qn*1DggVogH!%Ku4CEp^m42Mvi$kE< z22>BJ+%rIlP)Zb(5fO@p&h|gTq66?ml%gz#_4$JeS;`jc`hFs$`zn~~a{{MRX;&<3 z*Zhtck1YZPF#i@dBhkwL$$L$fA3reHLodhl@<5+|d}YL02U1Wg1}N04oqYA0dUc+9 z^%7tGS-m=anPgmzSJMA`Ouhb4y$&#CwR*Kzy;{guWq4&}_)(8KecHhmwH@pm8`ZK; zvCBc^{OKBSgy&E1QT+?-|M+)`H&=}C6qEQl!fVM4;)}M2n`F0dXwT+`kOJB$ z41P;wD!P-{iA0E8Ks61>PuEoUuCt8^;!Bym6SyQ^Z%o1AKwX0>sut6w)0X^n7PNG z2D7@N)Qy0MO~EUxN430vLcKTn{yLR(xq3B>uQJrD1?p8lyu$qJUh3s^^)i|1 zlGLm5>eZ=#;nlypNCnrbSD*0JQT6I__3CZD+Rax@J3ao~Gzau;aWW@jw!?hO!DUuh zMLmHrI3aFF$uP73UaZ7oH;kt}oZ?=rV*|aD;ME7R7q7%hD-Ok3z49P3FipM#p~Qb; zrsm}j2qbGS5vu%%)fOm7o>Z^K@YQJb>OuADD!#fxy;`JRrQwy>pI++qboDx!DU;Nz z@#@v7&++Qt4u!vZ^$A}cRj)2ruioaX-Rf1UdR2#4nBT76C8&3QWU@8t)fX2F3cup3 zN7SqL)T;;hYAIe}dIcsuSdSK=b`UiwbkE^ttCg@a2%(39Lc{}GU1`MmftH%Qa4Xb9 zCZXEre^jQe5=~J%tkKMD=QI0LzmgAn3pRXULQbo4bITLVg4yjmXuV$ov!nGJD?qF- z^2w>nvg-nq_aZa_z%H?N9 zW0Q$3K@@kEbt*DP#o9eX^O3V-02d>@T#H0ZF~xA zIUZB&Xy4KQ47^5K@G#Y^Lx%T@H3{wtdkgGamDmcZn_GGPz;^ znX7>0l1_x;O@}p6s#DX9nLXc8)(@>=Iar%2U|~QE$&w}6xmYVDKw*D5Ydv;?v;NAT z7x1GsGVu;uBd45crjfDhKxBULoqFzfJ_WXjI$dZ|Hvm8;fpDmOtY3B#Yu{l6g{sDo zi4(aj;U)+g%->~N_B~23Z&^CtzJLbfW%Tq~fiDAVQCv+s z%042njb=@S{$pj#Mv&!-=V}ygt-b(MqcOt+DF520pnTwQsn|peoQR12StEMC+q4x> z1HvNKt*YOcR?IFZUgk%?EWiV%VZs1uTZ`G3Sqe?#!Q<$8vC8czg2WOc1QJ|k-H`;S zF(RW=<1qmav#MFNKS3xZ{s(}kN1JOnt^j@zD@O?&lh#WJld9cjRGco4t~ zNaKSNKirf%`L+gervHM1%w}gN20;{V-PTi4u$trrz5=Pg!XkEDRRDqm4>f9*56HM! z0D-zbMEwX8HP!jBdFbP5&j>w0NhGRXk@h=0R;#zLFI@ln;45Sj#7VN*PMQCvLc0<@ zuqLe$7d3!^s#ASblWd4hvN>Ur%>msUC7@-OIrwpuxOj&jM@c^K@Z%`qp89hN(8nI- zO^%b{BFppXhfUSX)1D^GsKyD(AW;_nFL3Y&rFL16Zeq`Tc(?=t<&bIr69m>e>^{K) zS)CccqB4{^9HpXU$2`_cd2q~Q<&+1a6_1b@zTn7h%tCzQaB-`PI9X(S-g4lBe3{?`pRtj(EZ9TAnCQZGT#Y*anTCc>VN@}{a=_@Z# zOHm^ek}lC()XvBxeaZ{G-*I)tW!|i=pqb~%y*Q#(5;wT zOE9G`!s*1z_1cNV+kYT^rMm|bw2iv6qWjXw;3CdhyXPljOQr_2VjFcZ`th_1A=qhz z%A6>|I(Lx5EmMeenC_EGq0696VvfLk=>J+ZC8F*qHdfhd9lMWNbvoqBkU9_YWHgnj z0cYE)J6ZmXD*xCARjw46*DCe#l^$p`10bMc*hsMceoD~&6rTGt_~YVFK7R`NQ_LSY zSe0oRWGHx_DOUi(D*&nhAnbOt$0;&`_jEV&`5jtP%x9P%C)$?LhJ%$1!Ik!_%Nz&q zSos{R2y+xu7U!fB4^v7<%Y>`34(EyMQfj1ya$E(c10^};qX1*G3_i$8 zeaw`w^a&QZ_TZ=Z>LSYU~m*f#$*p4!Q*~T=7V5OqNWPT9~U-tpKg2}J;M2`U? zCuu;xRHh9ip1974+b}^Z8ovp5eP^V9Go^d;_5DMR%w0IYb0ZWFOT$(ElxI;^ zcz>7YKZ9=ze!3`dtPik|Uva1dz-AFE0#2Ct4zP4?2W9@`FU^&C?Wc4ayAvT>msu$G zckFGwTt=}~AFw2V6T|sUX>);Svs4_V%}J`w-I2Pv-X(t~6I&$F| zbD!mTqrwq7o`Giumonw53_gVT3dj-#yo91D0$xJV6ag=xXwJb8njGHY2Tcy|@Pj6Y zcLgky2s0G4O4qSQuGkw1ups4?NXRSwyae2x`;M3gpZG^eN;PTPi~bJ= zHQ)F*&qY+3DzUuo75&U6iO+w;GxgGi;z3u@OC_=D9R$1dOm3Vt?uF)h+4~dfr9|^t zA(q~qTS9G&w5_uAH>K(^u768jh70;mSa|lq$Lz~>3|jSb*z-FV=c5*q9wtCQ4;6j1 zO@@j;oZfSe^XxIO)k;AA44Sl7WF=>0ldAJ)J*bS%-` zf0xI1P;X%D>09rK$BZf)h)PvCAY@WP%A(m%X{4ayDnNRblaIEb3N@;s+=j%wKyF$* zO~)RlMRi0ZFYCa)cjN^MoARWH zZXfHP+CCrS*Kf$&ngQ0s*Ra#4VQ7Xf7s{|cRPWm|q?X&*mcr3T`{ee16JI)(=nEW> zre&|dArG(5b9)=(jb%^cl}(~Ne?e+q*2+~VuB6jR&Rj{vjml*tgN?R|KN!oV zBd-~lj3#b{Vj={Q#uts||KQltXw1QnqlA`Y4x8YTa^96=W9qpBF+USKSKD69?4uCw zeQ7+xSJ6QRcy>@F2nlD3)P2yw6G(Uq0Y--zc&r@6@n&E6A!T?f8M;!E!Jtuwz;II- zj!pFVK9G1GEBF~siVhbEWSN$d%QTcf=ArztEE^Dj4bQ&ImAJBN(Pb`v9PC zyB1yM;>W?RMVGnwajo*B(kTXMl*r{~)kmJ}(G0%6<6G(Zs-}Ue>?o&zx z`vyi6DN&-XSa*kWA3Nj)dcQTs*S!~%8pB?TL!d|+szG_^$0^kua-1X(@&!_EWtq33 zOeCy7f}S%9WWiW1c=u6wGSH4Sim+uL#(cezUv)nQcs6gKsWb$P2sz;b@L8!OnqK`Z zRsi2K^fN1BdgYU10*8Jd)aB&sXI0*6RgQ19M&&sj?~q2QEDj8iHoMHhJGQ4~PTr;S zE*(Al3=CZ#Y9w5%P_KK*=4zp*-aNRemU2NNh4s&qb;JmmfQ3XkfW(AV^7<#_=lQRb zrk=2!tx0F&p221wKaROB-r>hFH=lR-am+2`9ex~hi+P71$6R`}bFiFLZRQMet6+c% z!fvToLD(VnFFOUQt=1P;5lX$7HDQDb+ZK_G;5wuSX5V%M%8UJj(6%I5^L`@X zM=o6S_y7-#J*uOB=*ik@c>lz@q2;30fTcoUX;HWJK7|n;m3-bPC|HlB5f%j57;M8H z#|*onyD7S^!12Uy<(%=Ubd;1GK?Fpo5S~MR-m+`rtRYU-vZ`-m5RU%MVHzM{(8*eR z7sH|LiGk_ER7JZebTRjEh{RWbrLMD>-l$v&b@%u^hZ2(SfE0Y!d+yL>B9YkLf3@kOvtzeUBml!X3d^2qn+U zi@y&R7+wwt;r90;$6o;1-2O!fN1_)a^tph-yi%xn6VO_rhSw0syp=X;$5(mAE8E@P zI@qX#v?Z`1ft1UC0NZiN!=H&$AdCtmjuRV#?PWA$EP!LRyGRKMA%IVUNazZ+4pt)l z*S!Z)X~zb+8ZetS$r?9P`!I3y{#$+3-?Y?El7<4StL*$(Tgwvrud}TjJMu>G(BxI5o}5+!(ir>FW02 z3D)u&2^w%-qzrBNj*xJ8??jjn8?!{Gff`8~H-@iN0`Hcj=n%H`q^w*BLskMV#m3h8 zB=F7G@VN+Ifw3;Xq~cUOrrrAQOEOPvi;Js>o9C%G)vojg%(721{|2Dq;EalWFst^@ z!~TxBTpS!E8DLMjtyFdr{$2sT#FchJ|7MlkjiHvfa7&># zaivBOP`Xl#<&)VRgB6(raB>5raUXV>?0}si=JcZvFl1kd`|Tit9bY26A`R5~Ea$QuV z_Flh(+pAbfYQVAO{NtPP{9SBXOHAFGnCA%#QXbhxSo6wryfQkGD z(i_!yg^b`n@RoKSFk%cR6B}W$F(PB$nDZ?PS3ZQn{-L$u3Md?)tkI;ZHJ9mU@^A-cSSiJ&B|Xu<=Sg-*ULhe6C)4`Uu-ihSdb#DUO$<}~dr zd!H{F&GnH%A(huIgT&284c0?(&}zVH;(_d-tbu5NR)_`Z6C$DUt^lzbZYLME3)$AH z6oEt!{2LA=5n`ezrXN0ZF{v|Hk0t4%xmO)F;)s+kWubJ|qSyaPeBef`@nc4P> z_6P%s7iL2%r)#Zb5w=$TvI)z(Fq?W<_=J$zyR=qf{>q3oN-tH;l!Mnq>E*xPg(F6-g%3nGWg-pP_B_^KdX4o8zFxEyD>Fw)(9N$Mp+^8MgWz zgYM=3Q*`h5G->h`tjq*x(7of>Di~ZRx#<`v@_$L5Dz#HGK!;0x(n+ze%noZ(KZS*e z66jei*dp+NE8<5@T*jv55BRXW&|{Kht+;G-*VgbEY-YT#Z8m4TA#BcSuh^`DgBW^5 zCW^8Yf&kAsrhh>aw|d94fsJX6@)ga3kOQ-~NNaF=BX*-5thvpSY;HgMt>SjX1~1uR z+u(7}C|;|4DfJto_M&aSU-4Qr5$xEm>$T~(htHrNL!P87L!IO`(|s4O;Ru9zZASAt zU6VRrkc;N^^oDo!{!wL5li!j8Y+#NEzlCKWUA2^RhzZFxTLfUAuvp1>;Bl;xr#9NS z5hpiKjZ@+v+bQdF5#%K;KAUEW(>O#t=!VmFVAACDv};FKerQy2BMD4^L`%J+bXHEq z)t4g5)YLG8W0_syfM4vCQ_+nTGRrRpObw$gQ-oF3r)SOSdf8ow)QN-ewCr)H%~gq$ zrv6NtLFS6UfUwNrW`VPXeR*l82wrWR5$DX*twKeS zS^VoMD*bewzFMab@`_anLt&I|)ndweUuAQG^CJ^Ze++v z3+05}g@U(YMb#A8>=qVnjfSB>uCNunLR6V$2T8#g+FtYT3Y#*l$BMXm^!UK(PGBHF!GWlp^8$O8`SxE(@W2)Ab z?)yovUTQ|wr1mS5qSeuRI?;H@hwcO%?gXRCgS#b}w@;gUhmMa{t%r|-H5EHbjq8kc z*R(@}e6`D1v8^F-2;;M&3fDlW@7IhO*H+JqJ(zPH0 z?LRg@;he6jdS-x{F{8ac3F{w>2Y!xH`9a!_{yRB`8neUHtV^>m=4-05a2^NeTa{kO zJ}E1r4WSNm56w=P#(Ak6n8&>|DOwe*&hBQ?;vyx_hDCF;QB0M@h43=;2^S*+qaw+n z`n^>BH6Yg6RUh*ww~9P(`NoAJR2Jg?0x7QHrtT9M>mikPrA}MJG^CSGTMby4mS9-7 ztF(9Pv}#-kri^I=i4P5jp3KyGLNIN;?|h=Uo*dm|>--B(C_Pd6QpTc;u+C549jhnR z0+TIEI17%?fOVx@5d!2Ddct(j`4p~c2Cdf+1+=QGNJ&tT!%<-hHn#<0-xj?l^s7AW zLPnK=^~6yR!DcC_MWdZ0U*UvHb%?8o)+P@47LB$`Q-xLAjrQ?>H>b+$bv9Lg^&3SM zl`qBmCaTfC@y%GO93a-Zp^$c#&w$pFD}su=f+|d>$A8Bd+8SmG%(2!G{^6o63jb3s z!Cz9LM3=(oTH1G;&-`ZF!!%$d{&9?bKVEBNwdL0_ygq(q6tBzQh{Y;ZAdB$Y$!EZj zE?0!Ac?DKX2VP@y_DFmfRwdD>ng@KBWZr>oYK*G8a9>fLFx|Ei2TMjIwENPpv?Jt(k;{Wlnf1Gw5w4;&ku5)pkw#10w~ zR&-;acSj0&YyODs@7R8cEk-CPXCokr3$Y23c5^#O&|Fun37bStrZ&1nP9zN>WZFPt zLIUJul$Lyc({h6ItG-mCA2~l^@87hLi2gnHm=Y9~Ib}opC_x#wD^^fAR$;?U@qdBO z0HQ{&kEhl03PE8yihnM!s+U=VYgN!1mSLrB8IYz;%V6D6C)mz9;Sy{cr2<$5$P%rB z6w=Zv$k!FRDp&1~)zlx#HBor1lnuB-7(&qrd zj5ZG%Y)h^%54_Sm;A+#S6N0M3^-O`jg?*S(E0mai+$EHdR3N!a;nwgGEZzvscYd?& zLjurhX&?4)wC%&{Un;az-jt_MP8h9%9kFPo3S?3CfzN;;U9PYXywX143j5$g=wM0a z+|rVnWz(qDv+gXL1OxD<7yuqZ4+D^dBX4VF-!rpx;TCKBQRSUe z)?Zn(vLt26N+&BC7*&-lPv}s3eQ3T)o`ktZ>uvnaEJx{p(2vv?Y@IiOck-3E< zj55M9xn*mtOcn@C5t%I1^%uz%`0xsuWID)X8ATN6ZYT9%K*U7`Ds-8{mf43RtKn>_ zexmA&+P%aGsZ?i}WAKH{%f^8MtNly67o1y-jx6HQJ0Ys=jjA_52~l#BU;&PpE>ZbL zA^VaqUBV(s0~X~A3W?{jON7B9;X1$BD&F^>A2o6QO;rExc#TcVEsrQ#s*EW+qWeVU zuf@_bU4T*!G7-t(GXThxtDas5S~4AI`Fp_^1Am9X=-xXc@j}Z;e7C706RH|%JSP1R|gyap2epTRC( ztBJ;PY)|mBhUW6O=_Q+H!4-;TDqqSCC?hO?xm#jsW(h12njI6OV19yJA5V)DI547! zXM}Gs9@T27E-1re7-F*HH%8T+pEAC^R!y^qcpan2f-6UK4XWFPuB6iM#|}z=@(B_~ zk}{SC#6uUN9LDWJJ#Zt!$0-OcXny)-p?ShF7iw89(+fy*PEP1V>KO_-xj{r zpSIS%%v)#EGWX|-mMU+`;q#(&xp9-CWv#|6N#KfvJso@o45@N`T+bTEv`IWe{>DJ3 zFv7(sJ$Gczz$1o*zBhe4U<8p3LZj4WtPyZ7*rMduER|m z)pP$>41YF@&#l#K?ja?@(^hzEZFx5wpL>d|m6WKOQx0^ffJ@yDhK8SRvvz6!TdCi! z4_m-U{g_24G*E#uoVSZkdv2uuCt1IwMEy+JR;WS+^bm|_%Z4g@8+ujFDu~sG8gfIA z9NFYj{!6p)wI!fpk*`(<$tWQIY`<_y!kO|F;4=010+(9V+~jL;9c_c#I)5YdP15u| zB0xunfj)dEmcNn`05j$P3h=Ebo0_brFv2VTkBs!j5?f426C89GT%nfoX~Vx(&sV_Y zBu(tF?Xl7#@QZv%3c&9G9lsa+Y(3i`_!Ag!Zmv+@TRxH~NKo&L7V#(28PY4;_;UvauA_;C`2Uq-*(z6QHBzW6N8y@*yb!FjGbVt`<0Ss0$Ww zJD%-mndv*>hK&T2MJye8758-P3%33MbE7j}cJq?VnRm{bUDl6oYRMgC7l1L9;=AN{ zx5wvVAd`Mf=mnIc9s4w6>1q3m zwZmppx&q}{<5b!Lowl55khX%?Kw{6eX!Eb2rs;a^Hox%$)#eWk5752&yl$t0)?>?6 zL!~mNy#1G`Mt|JK*hb$JpdwCZz6PK`t_Xw+AP9ux+S-^+v=FxuI$o=0I07qW*wFfk zjL;^(uvY|F#^>ZMc-k0cFKll_@m=#f?BnZE94)oB)9b-OqrNYiDWdO8s28Vj!#-G3 zOw8rE89!&!NR0K{4ovh|KU_xveyv)W5k`v0e6WWCj`K@6)~^!+pH%QUBHuw~heKYC zxBqb{+>rP~16pV67kbmVBO>uF=PFE$nycW6I0LXE6k~{Gf#6{`kZP`ilyCI{9zX&{ zP^SVi%mpN5!UC86hVsNjL_Am;KV}e(#92~5k~;7bM@l7mPu+k2Ic8u^d_!lBAE&?9 z#M6x43x~3?+VjTbxDAQmJQh`*eh)iKRn;zD740G0^&mAVN4loD&rY|hMBd? zSo)#}?I9lFg~I#qH?zJnmOg5~#Mth;;RyVf9HuSp4B#9Urv_lqP0yJzFwq^0BAd|T z4jm*)SzqC>+3-8cPl#P-uzMm4##nDhxJ>&(Pcbpb8k8%}3lZ{SU5Y$o#*kbQZRUGu z^B#m0+O#58=JR4gaz1iNp-fD(aDZ13Sqg0tEIJ}zF<>E8!%^om9Nyo+h^X;fRjqAA z{&Ki^$HDik?d;xCt!#+Om-4}{qio2zHLxM*JiUPOfkI^NO)V=#L$w{(){KS7Mr1Bc zw0@!C(NK#(16N6mPJ=0gqkehch|w>}0R3Wuh<*uuL82hDVN^s&rS>f(3wZdl50W6V z7tIrn>>kh{Y?mtSyf#n2vf4fUeiP2`t;O-gPzlM6nj|%BlB!vm(h%dHWOGo_sEt`1 z+8qWR)+)gEGRs!%No1HWbAIQ>39N*Y#J(6(hmCLMWIHyvIDLSocBm9`>;{{|xKT zgyy!NX0u;U=oDwTa#z@Y_^tQ=F{v#SWEt#_gY%y-RYFg! zezprIAli#Kv7`b8voWFQU=O#lR0Qa@!&|`WPqoUPGR{d-OhmiHkP783FY8drC3*c1 zVbZ_el`yX_dJd0EH-9Yl&oRV)cR2+6y&wCtS$p~OI(~xIC0I)ln)a^VAD|GSJ~clv zgnIP;0I8^=+CIe#u}VCOTZk)9g-KB7QE$agFaxafjTT2ybFOGrEyA zW}H8;O{jR;2RX|r3NV2D7l9f z#nlcQ+;gb8f?fBFtzcceO2JgVl({G)tYEMGnF{9N<`n9bW}BnC5CI^o5dpwF!%M+4 zz(BG z{oURFb&qd)T7F(&09I-|CkF)PRGhAuo0KC&YM4PFDKH-7FXoKua*xmQ_&%^o9--Ew z&}dNj*|rS$R!m?dw;z>w{Hg-C?{E%xZ>4>)^%@1s{?o3?x><3JXyPq zr3}jsIUd>sAYebdr>B;6;s%-MpWz43IGcq6kr$X0&;17v8{R5By1l2J_g_-EudE;D zdX)9?p!EsjHP+Z%jsFWBuR8Ih%+e%Ty;hIC^#x}v!=LeY^aQ$m{vK9&f>;rZqLA=l zqad8fiXE8XtnL;XXpBG-8?Ebj&cIYG>}u#hoX~&F%lgE4U|KuaYMT|95M~I}|KKtb zIElhUuBRhJ9v=jI*#3IJv*e%eVO4|8WJO911x|@U;@!~S(4#2D9T<;;@ZO#41Y!&t zMi2|IpiC5ms1+c`IS5^w`VFa73(=(iv*Db7V12_Y_xgL4UaI^lV^CJukUaFq?=mDoG;4ct0^aekX+$rf(|Yc)X&U2pYWx2e zKC;j7G;RdJBw)&ujL{see@bxMd{E)WFSIodUIU54OMu&D%pXAXAMb2ibNkygkmwUc zk6#R5Wt*D>jh4!q@~=5jXw^LTU1)8#R%hw;DUadC`UQV}#-HWq7QNZP_o7gCH- z*5>;rv#mFAn(@#$?-}Wgneo^`)K|yW{SOzQLxzze_(MweupQT*LZjmlj>WuT+%)Y) ze{faH@=+xFVzo{9gIm{B)&YfJN11cc_LK}@f&IY^9PD=pa}Y{;2zeo^2V>Y{?aBlK zTk!)YhHFo-qQrr@)Tvh2UPQ`Xj>3t|sg(cv8dCPisE#w<8=wfBelT>9Jr8tI9$L$7U13D_|aw}$M$ywHaa3!p_@Rq zFxcT61^*F%tKpZ8K7^5+jzq!ZbR=BaXQ73}k+E6(jR&7Z7L;!+`web*1S9sOS=ae| z`g3z<hXr+6xuE+Ewu!v%U09OOE$9O5 z1nju39F37w4(Vd$r~`SBu|3vCZ6beWQyPFQ+7he{l2$3tx5?dqj|WFAxP4!vXD%>x z5F6j%!T~C#?<=fEvz`p-21nOu*92dj=wc2EO$@cB>j((+w-a;dY zj>ZW`pWbhI8}Fa*QVF@3khVMPU%9HIy73d*&rNu5R>Qt? z7Z+B<%<$Hj+)DX5VD)X{9&$xk8i)oqetUBo$r+nSq9_%*85@^D6nN_PyTf9{z1d$sixhh=0ZX4ZIYQ!1y!fl2d0u zTH}EdyioI-U@nsu&ouoAdvL39sKer(jXW~G?qANC$Fu+R=S@qtzI^A+J?gf0nR$G0 z!`qk6+{c&kU)F8vGIJka%~X%1%os9 zvx0^p#!FWkFD>qQ=DTy~EEGtWv2GuB=u4n(0IgC-lIg$3fp!iHwjeqA6r@x-Kv=y2 zis7(TM1HL0-|S~N4E+^3j}srTC*u63zl&P181ylHQ+r^sXwK6Zo0jusJNK}Dm?6tc z)hXKvJ;3)2j_Kv{u6Pc(Z4(21cdm%qM=F&#p)EC%9M(2S-o~Bu@VT z75NfhV}d~9kJZzwc!HScryOo-_){z8&j`z=e~bg?4ghabCV)kyfnk#&k>myFz)mYz za`$P3%Vf~FtOFvL9f63iH02( zVH6~9+izJR_IXU2f&K+Hmy&%o3Gg<+ABXcTE($0ihK;#^*d`)NuWTVW&d)iS&5kcIUoKTTF*e@ zcoRp-d$%}I()B>8VGGOP`pY=rrs5k;+fFU{tXymo<};y0xMXT=JZ{RJW&jQEf4oZ` zn{sBP@772njN-xrJRB2{6Mz0EHPM6hp=;^B28%f{9v^32@G&$VuM+3PrucyeDKNPW z?ZZbZ#d3-61IDv1_`WQv81U!x??4~43GC#y87amTVyvxZV}Zlk5kp zBN!0cq7`1~f4-(aGLA~Je6BMT9W3S*{{oxoHXO9s)#57o$4BI6Oi~aCyj%^uyxI4y zq99>$^Uo@XXYu6}rEcc7C4A%`Ou<(kYI>gmd01ip{3__8l9eskJ-6YvT0Sqf%#)2sDoh^TTV>o|)8~Kf8s{yNqA(N_Wy8T!x&)qw5 zj4f;nRPQDz!$fSC`!eyWz<(<~`P(MOcQKNM99Gv~VCf_x{6nmyJI^#-GpnqVu*JJ2 zQ(1D8mK+7)lxcdj)~JO|BnH2->G(?Dv#e$*8|Ot*wlwWE0^kyCQ3IgT3E)|)Z9MP0s%=;q%eBZ8>o=ASLziB| zP|hf25cFmDf_9fWNO80MSK87-Hhcwad@}(qbXFSMG3mT1!W%G+hk4T|I6z=7<{tckW{6UMGSBp6)FM0c_vlta{V&kWtTygw2P8E zpOj%#ZlXod-r@#<;dy*vfyD$p-(dXMs(*~k5wc)zwi{*Xa=i=l5kD!tiG*>rglD3^7)!z{dwvA^l*-lv z;EcvRh~oiY9*-Wr6opN1no%D1ZvehFW5=c4`EDY?z5-zm+hvwMDR`&k1;e^Sjt6tN zvjMhSdPvw|lQfENBRYN`zNJX2(ouHd*6QJBX!X6dMOM}(~G5naZ!vIX;I5ANB0kb+68jay>KuPRD$eUlgmU6DR+$Ce1*p6uoJsNF1_?X zbRU>RhmgbLj~E2n_bKOomvV;6ae8}1BV+G8f$3>$RO34wLztqZOFr8}YC=z?F@&D7 zjig_MxfSvSTjt_QjaA_g9Vh^F5Squ+D)13*%~il!sVbyhscNB8RUIPIsts|bYGch4 z@}c!v45}mygIR}Jf+RwuX{osdbvY=o9T6StwcIm^u0a0HYzwyK{tg(S{WWqcjwEJM zjFG#XQHlzAZ^tqKqV>Qr=H`1gxklCdh|i&0A4EwU92e^Z@hj(pm?)7&JSe4Ko5rjh zuU^F~y1=wwvW^#5?)1SDNF7p(gov*JKylT%X~U_WLbGVw^5{9SG8&a2%C^jrRLZu1 zpi09E+p;Y!%BTPY)<7x4sC-!TT(M8tmI?Sm>1Q%hO;Dm0uqLI5W=}KyeFky=Ie+qC zxnyU^W!Mn8D3P!Ryn$la!qS50GfX-hV=-N|G++jY6fX|4ZV20AmKZ7w2WQp=!}jZu+OQ20gn4plWROJ++lJmS zZ0oQcyEbenu{9#BFqBEcXWJwx(dV!svm627Vv=Z){%Zncd&Y>Z$dijImBt<@qE)os zyc@RSzb;(bReN}e@Jh+nf|x=h+_0_D_};KaU-yGGvIZrxQAKgQbz}+oF zEC@ZL1{imCko;Y&UpjT4ja{O6I1s7uRXC`XvQCt$`_neNGkC#L~O5+;k zuN;&VMrBtiw?z>S>wrp7wOJrmB(N@;`>l$PA2+JF9fH;M7JAi2IZAaU!TMniqi$A-3wDN!C(mDdx zL>i%R4QlYAh=hgUt`XL0BA$CEJp6l&N?E#yeTP@!BmacT%n*27-dVq`{uc9d&|@>I z9s%O?pU|MAWnq!FaIHd4tGwwOST%lu%9k^ws}czP7p1X5tJE`(nsr@3GNqnwI3|ZN zTEs>qka*`q*wgLkzWpc_`;%aY>U08zQdQ!|Rbj}iJPj-wBpBm=4HBTH?Mw{I(TJC_ zDgW^XY|5;hFl@@tawG}p&m?qG3YmrDzxT@vofZyCHJ|+n+gWab0MUBoj8#)ytO0AA zXbUi>NtcQ#FG+k*xpj$6TSIp-u8&-*29-GUL%#H$iN9}9Gu?_Z7k~Kn8`NM_ZX{D8 zwHTFZ)EbTFa)l4RMM?0>fG*CuM>3Z=Ne@BV-_wM@MfzG_bR_6TKg9fdC;i3LqKt%Nm!T;jm^Nv-0ltxpSUnSa|v7n8%$1e zu}!y%_L%-+SYR~~-{Tj{eguG4ESwitdIdN6NU|1uL-Eqt0C%eJL6a90w2+=%9Og5< z>nm`HD;>+cjv1JrB)M&DB@ko!v27&0PN9zPmLhNVI}b8YgVySnLhI9>Y_6_U5xn_@ z9C7n61Pj~H_C-l_Y!o!0Rw~a;?Z+1clYxcVtZEHlB8)|N8Ojv|N^qLZ7^ksraoTJ( z-Ny=kqZ*o8eun_p$Q7*`GIM96S=M=-#g!D>!y;)zSR~oW`a+xKW%lqKu^3m$r45U* z=?lw)$C0$M-dS4kSLZ z2J=~9X_#Fk)3@7t@lr@iAo=0fVH-(wg*Zt#3*BEi%o_f!l&5GzH$c^E6S$M^?JCaN zt|hH3y-JjL1oYvY048wz;1O>W@p1bWB)PZc6yYnvcH5Ry8j{`q@r8(goG(E;d@bZx zjz?qpnr&1S`9uCw+Vn65Xju&?ttFUuhWHm|TeSavG}|t@BQ#?vv`(64(|*^2W{~ei z(67+BtRGy7)^`+!`5o4xlZtUiSvZndEY!O&J+8DR8gELP>~xn%Pk*_zAw8?vNP+&f z%mR!ngfBJ(&86pfqXNSGo|I6fMkpbrM<{X2Gc71#&Am7t+kZFb3_&XrGTI!oK~yda z!~o~733O#SBu|pyF)ANE1LzrL7)Rxa}A2J=?le9*ZpG{ zOQSMP6UQNtbWfAfQu@v?E7DDd7tOp<2VST0LE1JvIQhT^ju~KHBMjN2K{_B;j|;{y_grjW<&U#E3;_5ny{hr#ze&gpS&&(2xYJDbK2} zdq~|t;+93gA4Q2Mz+EclAauD^_B4(TKpv)Y_pg;o1?jLG(}Yc%{uKnrqU)~}mTB#a z{-AiNc^m!^zR}Q0{7b{v8ua}B*dJoxPiP(fzpnm1@DGlKKYRBGF*JMR5|Qf)!AkYS ztP!_G;mo6p1Icm8=ukh^?R$jx;D0PS@gDRy_iQo$@-N!xJfjcI{wYRCbpP~da=3r0 zOcG{83)l5VG%$!kJhNe{(b7;2QzfH})-M;khVh@i%4v`W7cHCA8{Iqo)mOB=r8B77>SLsLiuPfO`YioZ^*O4; zLrz#(k^&o^37{0Kd6r3@J_D*LQpp45l08T+!v@Pm@y6QuGHpX`**NK#QsLz0 zh~!tgu6n3!-tqx~bzlgafaTgl8V`RJ<_*cQ$avdkcP1(?Hv{_Bc2);(T9R zW^`tBWJYvQ948>MhzpAXf}^PD+_qhC8QGNlp666mFCip4^Zk9^e_lQxa{Jy}Rk!NY zIj5dFb?TIeS&>{66*yf(4(zu;&F#PaERh2WZyc6&u(2cv#H1SPEZSm)pT=4(kTVWx z+;91}OVk!7#EcLFWjE494PWbV-W!f>Ja<1~{ZbMpG4gIy-Ms*jr}WArr0ztZd|~WXxwwO`dxBfX7j7f}eyRAsgoR=>8!1;c zP7^dwu-{H2Xto-5X7KaIBCWne5=5kq4QjIks>c%e863;awK0_0$P|=mTv_HgxM_{+ zgKeDt&$dMOqE_;|Ix5 z!sG7Kv4JW!%q~DfepE@&-^ulJnF4)M;3!w9z#UxMwBtvW$e>mbU_gPNeSB0d*n zgD*2G#a#AN?+^=0iAt4my8;z9#Nx{C)5kaLu>y;b&=s27z0w`-INB3(cdtMQ*cl^; zeiq{u9rg>5gRTVOVP`)9LcGmLK^VN`HN=gtWwtLZ1r-RV_%hz?cDvj(6&@l!T`kTP zLMuRbrZOZv-4nX9JI){(*S*{m*n@+aSIoRP&1H>0!hqgdtg(KcjW!vw1g}7QFRJwy zubZn4LKjuqZ+Ft`7ZWp_!LgOj@Yp;dtLQg-&*`L^MhbV!jrPmXw84z5a}BXQd&(86 zMIkTb*P)`G5VnxOV9G5VL*UJ=tX-ifhl|uANFC-drO-nb`$m>@=0j?uOLcaK?QSvq zN=XUL)LFKhNKJxOFnql;N80HLIVD>D_C1WqEHjybPu*q;S3mF@QC$m zlq;5+IpZ7$^NOjIQkTKbvQ-a>Ji#kqTNzu4pRldmA|LGO!s({aiyXh@t2o$rGZIxW z5ydxf9*D&n2&TY5xfCy;-h25Fa8#T~Fm!F?mJjhaa^S7~OIvHa)LgQq2BkrPVTHyG zv=Z1fcQ8p>g{SV&g&B-d?Ege=I=O>V)aAFRphD zk71C#9Bca0574q1x<5!WYF!7(6-JO(l)<4XN64p`obs9{_t@E~-w$Fww2I}>JVHfN z!DncFxm?xkh}?7`_Xug0v-hz57;WG&oO{Py0rypMDV{EuVbyZc;Qq5G1>Acx?`pEccpTvhF{Jc(%dw|Nsjpg{QLc~AD3$*f z4H(*g3(DJgd(giEq^kpoj3ZqIOvny8tCiE1%pWD{1nntU!Zy2XVbrj%Z&2|UBtGSz zSpw2JS!s}V3jMOK$bq>bw}wXoL0cFVVuzmNvWf%8;`q`zeq(6_9?AHi{Uvdee_bVK zFyr7|gDC(?8sscmJFkqT7l?Ou!wG!q#G(lHagF07;!2jDSi_*-V0D4wP0qy#qCb~5GF*- z1a?Pt@j;%>h69n*>1jmZq9|)YGgVGZ$74%Yx%oGbNME9#Sao@tE1ZsRBp0lST6|nM{7K@l7MJVIM zG1;j+>>-i@u0K$lEfnFf3sr)^MMyxXKSn;b0gR7&BMX}thJLo4w{Ypcflo2mVSP1| zMG7y0(@IE;D*Hp&oq=!88{qZ9A=A_Bi>g@}D8PQ;eIXE>Dv$NMsgQ;397lXXnjJ^^ zR$WEe1v8-+B;A%tGH#eOs5r)-WhkEMN|=srh-gQZ{X2L&(K%@hj_+*vE!)93nU~d% zgn!?y$+b;d36R=;y0@*`-V9G6t+Z85c(nC;074GU;q=vaSZUa+eaQY`Q#*{Wpr1GI z*!I{RQ`^EVSN`V<(2r@pp9z5})F8D8aQcZ47i0Z%^e#BDyiyI}q!SCW#GoLUGxS&H zw6}c!E&x&ob+GROJ`!RGVKj;Em8S_sy~SR=nZt96>rfr(1<78Ft3Bt$X3f>!&h_hb zKZMhl-mOeM%O#&ERN9Q|C!};&@g=8-nP;+Gns=~0)Sa94!71G^q81=u+s16|6B-z$&>a13vY`7P;5@f$gL+Avu%+W~Ye3 z6R_SM)ip^!NX8WXu=?F&^n*&2q#tIgG;#fqlpskzT!K^(*$XLZDn-IjYM(1bDE)9u zcF_;rC56@Syw(p%sfbY>b~lwEP_6aDh3aF*p;fy^kX7snkXUjl@PSBZvkHv_-#qfq z@2DSuYBMQ_IGQOoP=3H&kPXE)c$vbL=GePVhIiKfcIs`T_ZrRA)!1n_7CX)_!tk9k z9V~r*04i*k_66a=|F!Bw#p;_c#-88thlv8pTv%6ux@H^g=Q4=7a3aPCNQAC})$on< zW<2+~IyWU7-YLz?@ToGq^T>+jv>etU|EfVOB%J%$R~P6Y-LFmLZjUKUQih#3xpz=l z1zR&cj{og?n5?@bpSRp=5iEmtxRU(DDPp+zyqSaLXexO78{vJAWS1rVTqohpKI1A?O4EZV>9)u)nuj~<(A>?0|;sAuBS z&+)g*vm5`NYX!BkqRmSmQZ7)Nzy+nr3j^ej>#_i=Uz!+HQb~1Pf{wSe}1VF#PP{F>SL<) z_V$Y?#c(G43G*vYbh-vZ0adW8%I&|L4F|(%)}k^9!FdQGK}SQ1`#Hn_0ZInCtDLM~ zLGBvKA)~}zE$AKKU|{`7Z?*3R-^IeIOjadKCAY#)&asQmyWM-^ zd0yXGO;2A@OVzdS7zkYwC!E4!mG*DGOC?A1uL-t$)1|)%@Mq}N9GjKx6gF+4dBamb zk=O}@^`&t7!GO{$lp=O1WMpoBnf-oo;*-TIPZoMSBbVkiw0}*dqI$D+t?=aAZE1yQ z=ak(VN%NOkMhVn^8evWUoB2x;K6#)6It8@`Ol)cX(s#!(`eCEcNtlbwnqlvJD^))v zB}mc_e?cmPPgIH|{jfxeXl?#dEh(&qaaunleMISp=_*0sJCSPuq12D*`i_JgoTfe& z2Og*CQD1-utO*);$ozb2&t&jn1-7BZR2ZE8v^Zt4T`%vW#0~{#-Fdic+G@bcG~3&c zR8Ad6m-EGuWisNiM=`Mpr$6&OvZV7(>G85`Ov%#Hw8?&X-9Dfz8NYvWoDVNZEk))D zN?~ZLI&3;|gjM>ymsR?_o8lD=LYN40kiqn;g=w2T9^a>=L!BaxlJr{JDpz4$l!|w~f(0IwVD|jje+I8St~y{uy4ZQR^uP4U!abH6gnz zzAn54{Qz@!h8sIp8LMeI?p@r%!yyC4^vyFn*UipIvjP{TacNW_F%idwE2hq3n?b95|!4?ZeQ!IjrPayX%Qy10@-|CKkAz5>T9e3?PN&QQO>Wh z0*6q3#8saMB7fnkugKt)W5{wmm$d;k4WNUi3AKhoPw?GX8X7V!Qh)SXoF(QPh#Ji9 zSU8+}{<6zEv0+(1!zB`Z3}4fU21ufzLl7f0lpQ-;h}ZEPPg>NUNOQZS8Gf$SAjkAX zVpri~nZC=N&+|J&hg9C+D(dd*gZgLGN;!X0<*dUcIvVAugu~DERV(_K)VE6NuuA=V zrp{vO;7jgcRDw#Scbh*x&F(rPsS8Tkt972hD>Wls!NaBg5Bh9zy^^T#QAS-f|k#zB4T(e|+1x>N4J0u*btm-jX z&y#x0lw@+M9;AtQF>1hB{s=AukmHlPm3IFXQbk<_*tRNhk0~0K>g?&|M37B%F4z=1 zEpEn8-0BH+b_cg5m*#3(1N`Mibldz13~P({IeFes@Hf-D4}Y_~?{fUWug=~#k;+_JfC(>J-+92(>4{|ZAc_CN_;9XNeG>m&(}*tK&EtJ63E0r?LBs;H^}*r~y^l8* zHewzB$#-B43%<*ZxWNsy0mCxx<#a*qL0~6|eke-sGT4*m>t-g&o=`Ve$mIaS4XHH~ zb|Z;x_id!6XBi+r=Ob8O=lpstd#q9JLAfo3dq_LZK{ttBqDdcPNEJ2IDx_j+=^L!p z1$WWe88bGt-&wTFYM3Z|vqU-+^Zg8^Yx0l{CuzN6EyA{B6rilcGT>mM{P1U8(_Vy{ zO0$2npQ8>ZfGBIxA^AK#e>gHZPhX>>Qkm2EP;a$b=L~o3MgDbwE5b{}84TuV72nqW z-R02t;p{($OVFk2C0jxr%)zR{&Q}RuyGJFUPGSNFui^B;Zy~^Oe>OX;9OX=a*1?Nm zIKgUB;z-L5Q%uOPtp%_hY$(Z4`Ld&LW}!%jnwADCIN&LlBsGmq$QwXCQJSAQ}z#avjV$WMa>6{kCxua1 ziVeOlJGJ!`3XThiuDTf^Mr9*6JKI&%=*5}65-Ufo1Wbr4!=h>c7d|ZX=yL(w#-`#RjstK8${cK9SklNN3T;cv)P7 z-(WSIDGi2QpW0APrgsK#Xk$-4M)&N(GjzNT+8aD*yDnqjXMH7ouimq3_aYs?GtwTU z5^U88Y`#E({k(?L^L~nmaVCsA3pagVxUhNOcbaVa{;jiB-|Hyu?_8D?E-rX=>wW)R zvdX8Fio6BrACzA!ZFXDZ!1i8{$Qt(**!sfDX(}5BQ<+u=rkhXPucvBeq)g#5!+`dM z$zOy9yWMwnoao$j$;I5X4E(44`>PrpL26c6Uf~$z#2Do39K$XV{kVBG9{cczRD<(I z*vEz^alU=qC+{}dmHcxZ{&4<071y?GIR`c?76R9EQ5A|KhwPVZPd*oG)&|ohUzPo) z35rN?o&Qs4JZ&ll%SS*11LjgeT$X@1#BU1_YY9$^xI=>jrvi)pBP}gYuo&v^3H-}i zI0i|$8aEOME(gFc&!DpN__QDen$>jT5?n#7Kk;vt!oRqpD6D6`uO}-A9L5qlu!IoOCIhe% zs4}GMCh2bVWg=ZH-;;)OoQb;-%yTCMe!361Ysp|k)&%IvKNfTWUN&ns09H-!I_`Jr zcFa5Uzw~roTFoeD@UZ`1l%1yDzF~A!rb}Y(FQy7qohO&#`EnUnhl}0eZj5U}Smfks z;fI}J*t?+V#^C>ati*PkpXUyzFGG{{V)3m63Rs&bw8IpRmVL|s%U2IT5(%tqfBsuj zsKQH#-)g$A4Rh&|jctn9Us{?#Df#lF23o#g@q;4)Py&2!Cqo#nfO|~V`REiMHblW? zv^v8B7X`){q&186mkg>oa9tO-obC3wzwLv9lq4E0QMUu+Faw^$FRP0?xSQ>xo&hCC zV)~vsNfi6R>J7&Rp({TAP6*Z6cDAde@7Z4fYpxV#E29O?*0_KHSO6g)~Rrt=%2d7fX_EUE8!dN{NXqs*=pzq z2uLMJH2pzZb-p`1p@}|J3+N%>@*f0_UWH%I@YP41h)EnSX%`!~cuM}T6eNA!R;*va zdOS=O>?E$r2bl;RIxhL?BweWlV7Ly4HUdNj-fC5kw0ZP$R?=(Fp5oyIp z(b)yKnmDzUYeoLU9kJ?*;+eI66xXP|=|~fkwZ6T0D8UTk!>Ti|W9G>mn%Q~8Xv^g) z>*V$spT!4H-4FcO`4~c+p-W*_NPl~f8*RuK7rGStPovk$i=-k5FLluzKlgmvthlk&{J08Dfn{^itoh)62KWXd6Mh`TCUM0?xwz>LmVF!)Cf?_XsQDcp9 zbMJu%;tJdu=iK5&sday2!yfNX>Gyp(-VJab*p))Gq!!zs#$e|MGHID0_G@^pjZs2e z*q0dzw-AHvfUYvw4wQ?T^vGI+o=II&m@FKj;&v)S`{QL0{A-3;XqcuPO%Q=N26EmZnAs54<(2A^e3?GF>Fh{GzWot znzosoi783EQ2SZ}4O5UOxE)hr7s7E~9J;=JhO6jJ@7bR4rR^}k+vod$`iM{oYUI3A zLB-&9yWxYKUj1RsY$0g8pHZ5iWUuC!syhP0n zrhEyuxro7Ei?~(K6+%Qz=ma5!|khMF?)N2Q$c>UdYg^9A+sEV_#XVJ5*AMa7H2^qY5#yRlg#l9QklWxr~Nwc4ikhp*rPy@0r+N_?yO9Ju8J2Z`oO>sSs ze&fG>p1@Y`c&EQMBh7n03dQ(vOsUV!L#fxdRq9zlL$VA=NYr6wU;J&4Sz)LsR>TKZ z;7wHCX}wq!J015OeJ41re-uHo{Y~jukiV`d)?MTa_c+X(+>WfObuUs^+aDgFAEF)- z;|t&Ji?unsy3)R8capo!*vg2r2@ZSy=NBV4VgtZ?HUsk?Z(nD)tILTgGp4W3HPQ2( z?KqQdk7y3_PDDU3drqzCk>n*q%vM9Q9cu31?G}uz=MIE4NynKOoPRxctVU%A2dc>< z&aj6FWjlu`!vPd&3H%FmDYx8-0FHOx*tW2I!UK1Kg;0azO@`o-YlKC~2S-CK9|Z(S zCG-w0_3!ORWI2e?1jdJh9cJd@Z+l-CXJ}Mxh_(;ov2Qf`X;dr^FI7K{iuJ_rbadx+ zqhgu(d4dlUvQesIF8X#ylZIpkSf4cHcx0#{M--uqXh+fHC@PGTV^D$|R|e0+0xTG9 z&a`7mVt*_y|0y(xb_e?!t&q4T;k!-1FaNjk9riJ_fbVF+B3lv@S2V+SQ!n^o`0nXS zaN(a}WsmE01OWe0`0f#6E*{l&e0=wLht~1k2*Gy`P}wE$-M~1$I}cv~w*cP_=C>5S zgP(9L52#~!3cPFBpy1tbfp=m~-U|w0bs|HnZ|Fane{Z)I9>E(z>N>f~%9zA%Ajq?? z_+1LTyXAZh@3_%~VCH`r-u>yLR0P6vW2}Z}P+JY}`t*y#JJdhAOWw2$XE=UNZC;+> zyN^(LMH%3`1h~sXVfG)y;}R&1@&n&1>#hPkZV{j1e40Jpp{{UQ6Sip1EI2N#+Oe;B zqYSEgwY{LK*W}U?sycF7GE0Vv|D-ZJaoh~ABxi^aQHk^FUg@r6aq}N8e+r4)7dDK?WcRv~uJpRn`9B&$}gl(T_t_U6X6y0;(EJR7FtrVG^k7l&e71 zIXG)M8B{G$psE&{%^tcFpz3V?IURo@&8E6kD|v(!I#TV+tJ)kSJ`hBu#)qx{|Klge ze}$j!`+@lBv%Ab_O?^O}Dj0+?%lYH+(;Gf8(CkJ3%lK&)OU-Yq)D--bIrCHip-u`v z72{`y?*!}FqSz3Et4u4f1r4?SRumh6+s?j@09imfO1dcjs>+x|^#9Jsp%6oFlFbeolYR##g&U z@YGIV>bZlw{}1hFG}$;XfN|$1C!y4GvK@4}d_=E3W74+~_cXQvOfAJvF+JjO9eyjP zOSQtOjc_%kE`M!hrtf4isQ>-;J8qwL)9p8TJw<2bV?s!~^9|mgBpc8s{~YY;=`BM9 z+eh=73XktZ7(AI(@JnIsm;XqSj<2ZBMC~0n&FQ>6odx#&X7)E*>~9~4{p}s{AAWWA z;zSwP-%4PgYy+Q7Iy}B5`&$&+lL(8e$*iba#U2vJW$yzSD_pjXHoiD6<03vu={nGe zzmC``DG=@bztb9|w;w6XCha}Lt%Y>?fGcJP-=)*)M^1uEh>Ztzwe2Tafp_^z&&ChV zpXRh~Ukg{4)MYLXfyN29QW4cjrN^8n-iQL9Ly#Fe8WCDtEUFAWwcLDkr&77 zK*Z;0UYtO!@!ORpu@<<~cM^8g`g#iQa22$c{J_@4iea{!b8sR)JZ!F9w7i9kRI8n1 z_Wij@QYrZO7s#$Uf`JE=^{<%lIsnPeD z{WzRzU$&ze(TH1tIR2v^$Y@>|KWoe9QyVU%yn-WU{W>iijH_UbfKC_z#g)TsurslT zlgqNNI5{bQ3SxC2eito)XBf=-K5c8OSP`rzbXS;l&g;ai>T#@YVrZPh5v{@aKrf0P zS(7b&k6)9NdH_4?wV7~wtedLG*Eo-u^=L%(VgSylhm7AiWTDCa77NJsm;Cc7{{nnh1%D|<9p8ZMJR6~VU_X^ATZgRcnRiSZM`&aS=w zBbmP?JM#=LFb*9ZvlJ{+IkV@Zl(;j`s`Kd3kq})MSw5`}|J{ML*20JJgPqFLja{~OU zz5*_9<`_-=U|&nXZuE*LRDuu9&LI*QsjT0dym0VDd>|aamuml3m?6akj)m;3As8r# z;g+IsVzd>wmMmVW^a;qh9QW+s$L0Eh2y&8TyvO{c>Tpt5@s-t0wzrq%xMb}K`RcId z#B7LPy2g-D*II|=JEaY8aA)n-0 z1wF!l{ak@9@TL?C`N$T^TgLJxv|ip>_`bbhpMp>PN@C|$Xe1|I@b;>%6ntned+GSI zFYgF7`ReCv(S|MZjrkXXYi+Tgz9xx&G6gezOJY_UGwpY|hB3!#3F*Q5A&|pa@reUO z*I2EenSqJJuClgu>bZ}%sZ;;b(h`rFU)_y5q|C2CpB(?k{TS^45bkJ}uglk^mLo%S zSQk7v(U}B~fu#TW;&^<(lN|9W)PCqoY8kFOQ7mXbq5d2s_u7dJ&ntAg za$M=Agn?pm9_5R^keCC(AcS*7iUxSwDy-19) zp#d}}^k0L&Io84_d1E{q;BY=V;nn1V4;jL>s87NM5h^|*Dxj?sF530{8%xF?w(6>v zRH2TVD^VaEnw%Bru?)C&zj(uKH+i|b?kXzuj*0bye!-heY?zWaH{4d`#TyQCvodDs z*_n2(UU>-yxu+0;8Y)YDgkw<}h!wGGdxG`3HSI>upb!sjB#sq3=Q0Ad(77!J&?DxHEpy;N-(SXCmyz?9VX_ zx2qX0?LXYp+b#M~783gp_o{(~=WuTy!pFRzdfq<_z79yvo64uv%(1P`GlEQ9OsmugQ<1zid^!GG^x@GO;KL{1NC(9u>Nj7MK# zJM3peWgt1-zS!D<|^9hP%STYY8 zU+KpO^Y`MR8q`8TjvXA;$hP!VR=E+;s|-P*w(cIy%@K-!zHkdf1in=dk=5lrPf}4`(^<(#$O!sF9i<)GgI5G%c3lyLn6P@C`@N8x1Pp50a|E z@svI&SJVLkO$Tk1rt}|s{ zG}Fe;!hMc!coGe8c5WSV(=-5HPow-Raf{`dU%-i#Ip;H`vZ0(x!Fo<&&n`zss<@G4 z4m7F&S8*>tum&GZtLa6ypngN3y77g3#ux634v{2kJ|p@SKGVH@Cz^zuPscDDJ`R_@ zv6^1e`op?bluN0ArUzpHPBKj}~!VGeg?Z$G2A(%P9_Bd5~ z1=0O*q&&aHiX|GR8WhWnlTFk9b=2i88#GyyNJNQI?oz$n%{<@<&S7Ll8 zR;3yFP%Cn%eKtNr>e#s9K|t}UE5ft(LT+dtrsr45zc?3&n^G>8Ef5F}mX2|N?<7rd zO(_<_x&GbL2i94sO7Nebrs5k-iB~50wSD4a_&)T0cWeX6tj3XcMBDXP|Bt2H-M6rA zPN&Sd{fwNb#ZwmI}xlZ`B01PL4` zUwbrmJ}7}}DGBy3u4K0;k1QREPI0^5+J{ys@qZzIIVwgz5%DMA zVEiS^fNT-GA{kX5w5(o^M>{GJ){O{>pQ4(OPqF{(J-KvrRXygNiUU3W_#Rb5?w@eM z_wBy#v;Hmj3g#)U;BJJzBPEl2lB0m0Kg==ZGmSJOVLw#7B(cNb)2^nt&cFd{VFrUBvF3f1TpLu_W;_?dF)Rn4hgJH* zM%WKWgEv?;DF~Ee0nvYJ*$`HQ-2M6y;XZE!&W|jd0H|E5_k0Jt61-JZzU0KdGcwmRMkiMW`f$WJx$O2oehDY>+!{z}kI&qmWGGc1Ijscz^pHlOmGi6fESLu6G z^G1EIqznPN^u1yl1h3&eYR-HJO@sX^;9NfQuLZi$Zng+F2j`_}Bg&9uc<7#U^Ojpbj21-86z?5pF4zo;BGhTWtAMR*7+NQ|Ir6g)9Tg;ia( z4Tbvq$PuMKv|ZtiKH9FJ=Sp!)$}QKzv~c$rn5bP`m=33Jn^FR%&poq0=MQ)uX~X4X z+pmwYKs2{n-}A*Wwg|C5V2N8T;chxPVSk_s2I(@Wp8?h#a)nO9RqPOQpRhxarhBHOb9xv0CDlJ~OX0Qake zRbZOd@7W%{Z`AjyoplKT~kZ{A6KG3*vxv~A`fj{t}G3W?E$2a(Ty>0Z?YMR)a(8Ui(w*Z~blgb_lU za;$~-;SQ!8y+7?xhVLXd_BpRM79CH~$@#uQ%+@kur{Hg<@09p!nswxLcUg9yFpkgew8EddI2u8$`-el!CJE}c9!rr9>VPN8WM3) zKePHaUOLT4cZd4N5NYsLxSBCFKI5AVRQXvx-Sx6QmrL;%av8QC7kkF#9H&y5fck57 zq!m7Z?*x{r)}@Vvv@IfKlwTm4U%tR zvWNLio9tKN3IEk;`-*RfHnR_e$~9*DbIVE~;847Ku7TQ9@qVeA){pA}bN$$ax!x04 zhfpwLu0Knc(=VxlUq#%O z=DkeSRlB8Qlhq;ZmcEs4>8_%U^M>00avj@OcK3T)>8Q90wPRW}wJ6tgKrV}n3k?_# z4@CsOLyNcDMg87OQf9fGB_vf=7r7L7RdK4aaIp(6(@6C`+F4;jD}#Qfxnv+bgD6o- za+-kd3FRKbXz$^YCF)R>J-_8V5?*!~e<;G>B~+_P?>LJgj-j{wH79 zCRhPq0ERDt{cqj+B>UfKQvPHqU+Soq-IRUt5!x630s+Cy@&cOS#%5xYi~&O$^^$I+ zZk%Z>&>+6wtdaITmnh}8MY1NWe;aX6s~Xh16 z#+{%Pd4GPEhge<<6F_*KfmSoE{Kx;sac28FQ0Sk^?vA&p6!d~r7)A(*?( zFX5ju{;A*}s6(?#fGLnPUmd^4)g2bYVV%f=X1$HLCs%PU0kvQ1--o>&kIGPosmqsK z(g>$tyksmAZwIEe*G;9`Y|v9J;r4r1Ag^JZrfv57XR+q8XXy?5&DU^)^osQ~>ClI2 z?sAN@*pDV>zF%iH9le4yGYo)6%7^`jv%NT`Nzu-3=%&b~y2_Yr%~T!{`V|>fI1o^4 zb{_wbjI&9`*(Bp^l5ut=$s}VA$W*S$W^1ysm}D}R;lA+O=&Pczk}3v`peq)0v|O<^ zd5II)kU?WNF?RIODpyjPvSB)HrV_gguK}88+~Kb!+d*acNR+-1q?%zyYw_e)x+PklJmnmzMjQ#P`d3T`t9M zsGxsabkIMl7kl$08DzX?HwP%2Wg^Toxu*i{`lP^-KgW0_QWGSq$WSN}Nw@@j8xba7x(7;$1^WGDDM?+ra zUrl@+cnEm_ez)`y@Viwm#oOdEY`a_(F1K%|u|~JWP*Ty$P^WoIVlwDc3m!KGj^|M= zYP}>(QhhaKGo|v(=%iJjVKcX8vr16Wtbk}XGpbT)B4y4t^ApWx6AYVSMI7e2aWJ)> z#Dc=v*Z)M!e76ebi+LT%*nK^D&dI@ zG~$O7TkJnPt0YZTNCtEkAioj@y3@YvZxlf1;`OpNzQuhr*Wdq`9Sx_MgG;!j$bOg!9x;Ig|lEW;oog)a!y;Dx?Z1b-%oNA;shZsgO+xMk?k@ znuPKd{Mm?ZQu-IW4jxns81VYTgf;6QZ;A44#Kr#lC;(NG@~uNzRK7?_&6|!}CI6yv z_p$F$EAoI2|7G?!P^H2P#1p>cbABKCw`M3G!3%_LCHM(15d4J~2vrW-F}`QNq=BVKf5mcG718(7?@(X#pW=HZbvRxf_v^8ei3`L>uZ|$yAe~O} znK{kaSZjg3RK60GZ%SOO)>{6KglXZE?{%&D5KB;cq-(dwU;L~ClYgsW0PL*9WD!<5 zoW5o;(fA&_Cur3{jq#07bnzCrMF5ttmxq1scgwEvRWI=$!3Z zK_e=(C};~0L_x#$vHCQnpG_}Ps~WCoO+Sa+N0hU_89z zEX3hQUvFg1s132d3ceZ&NMkXnjNC^vjI(KDJiZCe0=(|uAU$|ZUV+BKQ#jt*iJ+7) z`R1TF=;I+!$JEQ!jQSu)=~Uaw$GvF2ly) zf)xlXI>p7|P1y$C=<~6ZM#6?u-)*`$ zIHec@RoTuR+)K5g=9*fBq52ykgT!OPc%TKl#T`tsL}X81%l4O~!(b zedqTdrT`Mf`1E~gt4J1w^(pX32EL^55B(b&7+!&ox8SkiJ$u0+ekVSM%<&<9n2~EZ zaZk;N4Q-ysG}1mnOwbyEYo8&L_fh$}2bIZiW0b7&6n$a&mxC0Z&{_HJ;6c}#e|5Y# zcx7>hzxe#FqIXupzx3kJm7pai{uA$iR~-^H5jGs`Z@eEb;R*>}&T)on9ned`&@mF_ z4z4Nu*51Fz7Rs^pII`CbXRAo8pR|!r{A(TT4GM{?=@qtx36;MTesCgd1Zahn00F|9 zT!lN-o(oD2KGRZhs)dMnp{k~;_&tXQ0mORRI@x31t359$+_4cP46!T0RHmdL~q z>*P{+YHt|IQbgoKT-p_UF`6zt=sPkIJ7~XLHDp2REpoq7bcQhx*&lz6zD;(DRMcdv22;rhLtD>E#;?_kr+#k=2LP__@7Kb^P0=-uhC7-Wmf9nch--Q+s|rSOI<(9 z!Me?pAr|~|G?PYaxQceOzgZ$SYv%^km4w1su?Qm7(r)Ogu4A`nE5O_IUc; z6z#DHVcO}3VFWC`jyiBWw8w-2ZLgO;EI#@vF+`fJmx_Gs`QVr})420Ce$YR?<`nIl zo(IPRR0+qcBa$~xr^Eg!d-XLigZS6w;mouGd@=TVa&DF1TKFf>H16N7PcA}1h*txo ziPE%L6Nk+~r=etoK?qLCAJnuJ_M6d&k6%0`13l&IM04FB`bXe`UL$>{{z~s3z@czK zARTu;3Z{V=1vCFL$=@@PKTqYyS0sPm)cpQ+1!&2%+IO3xr5Hx!e0v;5q1TV^hV!1@ z0$f0*2H0`RRSi%SbIL(H+%ar`2gy!Iw;$Ie?{#WrvtXQuEM~#jmghI){Jbaf_sZ|t zC3Gj0Aq2q%C7d!6JB;+PP zBw0M-dE)%+k-P-Ib_cN!ZihYKeROR7I<_<6(SEgB0bY9@L}bKHrFFl6LwkSvH3h$P2mb{v{NaG{A|HEpCw+z*padUmfLHs&AAKkL zo8Vtp0PPP1%^=@#zjlLP=-&RJtjB2g_O0qB?%v+##UJF}KGh0T;mZ*!Fw!#N)y}T6 zd#1k!1+YZ<7xEZ-uqYN5q__R^%F?{I2slMjvY^v=D03F4R&OMwa^QA6$+eXRyh3WO z-*lBKEB|c)0ZHpCeecBjO0Nf5uKpYr1Bru~85(IRu5hO;)wWTNKydYh&oGs}Fkfg6 z!cnqWWI^-PzHScnw#v_jsq#z~^(iW87RaF>&@^uhhqHJ|_BH?0b_vutC8n6dMzsY{ z`R$71zQjKn+`Mw8UZOwmihJHFR%BxGh%7@gC21@>MIHN6SZTj<&{erG9dqZ85dY-O zbbCR)DmhnaL}muDEvGvNCcpsAvR}x2#U71QfzG?i91Ajqvlsf=6dm?E`1VG*N^JEd zO7x%+6T25(f&DeN(XDf4XU-w_dn``wZS2n1*k0 z(nCj1rh_+OlQc^_qg z#uzNKaE}DPdpmk5j0kbOG<+dSc>AuMO?JqSkFBP>U?zsQCPC1XcGvkB*L3R%s?+~WBOPFQaIBUlX+Q&%Epa=&@ zaWWn#qt{T8?QvvZj{}4tAQxeu8rHPoM}`qyM@hrc#8ge>0gUu{9O;+J@0+pNO~C?~ zhd@3IlWrWC?rPfLs&At6!F+_JjnX3};VHHpclNiJK{L`x><%paVawOY8Ps}eC5@uV zM7(drmE)JxR+s@VSzAiRMtP~0+}L<(0GbC@@rw8Rab>H-TC2nf2N|l?vbQl;RrH_- zB3f)(Yg(#WDH~c5%wqyJe`mNt1+D`y(C1+_<^GqI`xkt{cuq;&KaBSKjG8JH5w{LE zp1^m+H>x-s(j6+k{4c~e!^&}i0mmKOYJapH1Oda=vLVbwT{wXb1kx|$do~9LKQ?V4 z_dsu`bPyMIKBJd2n|4XV`7#gV29OK>Vc4_o|31TqKK$7ALINM1<~xVaV*~Lw(>E~w zR-vTR8033C!g9bl?0Y(gy&Rh=&S9AQF}(3zC&9k+)YkvD*7z!ügztiz6aqg?~ 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%0DIt1XtP{i6HZHEjtG)%(LA07_zilnCPW+0}SR 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
      -Jl;mE81H3PvOtn)jo|D>_H`U(FTss9BD^-qMR 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 z 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

      5GiY-;_M;jhNLXOj6fWwnh6V?PRQ8Q6``qi2a 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

      RmE+9(Zt5pwYi$G94ee9*7P3gW4WcXnN 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 s)e`+l}D&6Dspzst#@ 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 z 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 z


      +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 z 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
    1. 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

      ?I|h~NV=j}{ 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 z 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
    2. FM~() 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

      4p? z&aQyAwWt0k&ve_H=`E0l`p_9_iPzNA!n>_WL(3h4@ac$2TKnf;w|dbuS%y5Ov^naV zf_fm>?EZykF@h~7;--A7xrnb@NCx|jRA#X0^-}IxQcOFNpHL7WlhnGnQE}Q!e58HU zvPRFlr+^Ed$9p$#5KX+@$3UxBO5oUdp)OADZ2iE4h$rb$Z`<74lPwDHr?2Xe(F+L1 z$cmlar1Y*E3g|RzmxcGmM|t!|$$~bBG$CBd5>-PcRA;M-!#RH`eVNX61&4aE5y{MQ znRSmxp;8{!NA9?fZqF&287eCHNYjQ=NNZ#LlWDpyvDGE^$>u*2Gu7Z$X!wp3?vnus zd~7J*uT=l%jMVg7EYnXCqa;&QP#uKq zV+JqeGa~tHt~9ah=oK96X;U3!Aj$>d6J{FB0!|F<(rx^ zPR8tIf5X#21$3wjQ)%!D%inLq-U}v-RnbvdY$zeBSRt=eM`@!RdxIF|)N z39*;_a$ze@n`Pjimv=#PY50C-ggSAIezUYcseAUn1k@_9jIbE)V7G-zJLa#XQu5Xl z-E)V+&-&0P$1x&+bDfmx=yq{bCCz2~g$9iKH4$`u?FIO9E4Av>EV;w!CXoSjuEm}y zp7Yu{?YM#ZgG?)xYF-jSxa?`GreWTX58l)~)*&aYny#~o#jl_abH{z>BLEn%>qD`= zgzjW*O=C61qcn76V9<~S!Wv@wgJD(;GQ4?Ma>&>7=D z%$Zl`N{H+DZVY9t$j3?L-k&JslRft4A3ac?j;4Za;Kj=%j^5cW6IR^RhV)S8O!E#k z84rS4VA-?uV^8q0u{?*WCpgDQo}=RoSH&caINgX@9fv zxWh=kY*?BR_kt*-bxxIbAwrj@NR*GAG}0&kUWX_EOu#MPGq0}fv=ibIdEcr2dAmYz zLLYDGF}zd#Fp^O4Vg}SrA;J125g>0HXgZ6S-CS(8BV5~UNKTN8Q={)(!uu) z@Hj(LaJ_%p=YC)jdkrS&xe42SrbXX(UN=GDVGK%50?NwFaX*pKIL8<$ydOVzF+3|B z*5o(z@#eCYy-WmR1Jp+ylu-uvs|QTIBQ}(+mCu6yebw?dZkZpTU7Ahr`8c|M6kdu_ zzqo)`EZxaayf3pj{9**#j@qWM()VoDjoDP#u* zRHi`EgujUM0bo2os~`uHN38?O5gU}M!prH8t5|3UB}cy1)S^Aiy3jcRQWAO_N<3Z7fR{VU?l>VHCCS05diC6$fbqYQ%lI;{8xl>eAl>UC)%{L72dQn6*p1i zeecf%9MS)r%6Si*>0Hx#JA2ud2al;b2gu5Gyf^1DBpx}x!X%Q3Sl3Zm!iz?i@Dgx} zZKP!2=tYP#r3{u}lDv@_+J}U&nD|}&mC@(vex?iU*rQG(l6*C)=St9ZqBPXK{oncY z3b36kj%ba+Wa%cUcQdEe$tPpX{9i{_wIljZT?U zZ!Rn*pOWi82{P~IAs92i!Ym&u1V!5;Oz~ex2+-hGR+y?)t8j-GiD(I9RWSzT#;gRC{Xp8rUO(@8`oT*C+zCUW3Y(~z<)NSP3qT)ushh8S+?9bV})WQvdf z?;#z$4R%?mwp##~=%B^-&dZZvt$}_7AHrY1+0vEvJ#7!AWa`S`+|YdgM)cbWFwCMs z>T0srMD=1Knm3;1y(4AUjHZ4aD^PBZAL^%9=+5Ql+7fCiwXV*xN%72~IkfZfZyDmm zYdsrGSh1``W>HP`?ymVc6{|t2PO`UGARptToLqd&u-N?lPzC=(YbzE4(r;-QTbEK}+La84S=nz0 zQ)yehTA(M&5)}Y{q?yHyqO7j0GQT-}9fW*I6tZq@WYD|j3XLLeN!I1!_JBqix)!|- zH829raA$br=}zms^*y8}PH@!r;^}@*gnCeJ_h@q)diE()47h|fL)NVkFuVO39LU=U zcXVio@Iw*I$WR0yF5q%zvr!qY0(&pqXnD9v5hO7pjQomz-5!;WkC(jcI<&#LV6Cwt zUI<;ga*c~CQAYUqHD5nA(+cLL^S;TaeW5V(%wuXdHPKY0wly8u1+vAiT33^W9Liy= zuLVG-Ue%1Lzp*aG=XRBij=>nI6yd0EP0wSZ`YK7`R9XP{-&A9Ol*vf2pg%>6=yEsiWep*zl)9SmaIlu210)-hI3jTYEq4%f-?7zhOBxUmJD3p0FyN(Fjjz4p@w5^lht)w-#rtMH3lLirM8uZpq z<3{GZWsW)hsg3o-36^1N)#_HW#MOHzwKoT3+EyBu zJGSL|qGEIbpeTkv6YEd-L}|FtCs!>?g$@;#8Y}*RJZ#vlhZVvAuQ~ei8w~SB>%DY= zr(Qj-XS9F90TE;T6PhKE4IP}2BROFV7ByZi&N%sdtJUWUp9v%lxS*GqiD#c4Pbjk0 zu(dd%cp!H24Hz^*eg8GQ>x{&5$tg`1{Sr?zknAqx&0{nCW~b@qJ$)A$D0^d_Fausm zoVWw8tu$mDeY3<{)dE+euee3+y>EioPSd8EB;jJGfzIz>2+PlqR~<>Xgbkl_6Z>lAy6vN3(#J24E!7t+VY0kKNi5|wSDYf_5fp7rUb{k}Vy1;b z#iw=Fw)kUJzVlikwpuF$m8MV@?__OA?^zSyYQO}lqCh(`nM6a-JW1c6cdSpj|AK&E z-OTNX1gl}TX@EZrX=K3{Yu+5^rDvQ0~p=5YRQ05sU@ z_aLBTPSUWh+deJEDuStJ9ERh+`+FouT_Qpiq(ypL)39E&60YPb|A@n`h{(Y4a?;yM zp|gT6HLGD)XmxW4MF#v9KwNtWXG(LlW`m72fq`?wM`-<#GNi=v(npyGP{p;Z{wO>D zd{5f|<84v53&qRWY#*h5moXRRh>SMBvow!H7V%-o$ZDU<3yHU>*uQOEZ#icTCk!d1 zbC|f}Tw0OWKg0IOz7q@*A{r19UU^|C%RzmkCZg8Gu`U>-ZcVWM>?feg+`CQ0R}`U9 zfEABARP3(}e90iuzj$gt47x!Sy$3Jgbdt0Mu_1J$eB6}l;lC@}6E<|jM5(ATd;sc;xFfyHz5>y}*c$RZ(~he%r?O4;#u@+GMaOauS*x1TIB1!{Yv5Mo4R zXjfC`_}XZbMlI|#QQTzFDZd!15ZbuNun>`uX^0h1vA)wHX3yR(`MZ*zTnUf}Z&ZDP zpyxML8CAGer-!g%LEO105O$Wqtb2y7*ySf$qBY4n`8?|s!SmVO9shD%evPlMc2u@k zMpN>Ps)B>`XYNw>;9D2{`ZnT~zF%qg-H3W%lcS^X-wxPtme##m3ai?re^zxKJ2Aqb`D6%qVPJp08I->l(mz?=+E5EqLX zKUU>;AutlLA?s0ZYy}R&gm9x$DO?hziv+U|-kG}bm2*T$%oOtLFjpzKH3`Ay_JDu< zJ&xy145y`fSxjb(?{LbSwwr;TF~b0S3w1=xGh5jp;QFPRz&zP_%uq#V@CIEs4@NyEtAvudoz9RgtHfv7`2C4G@3MZ- ziNs&-(RBP%xbMRm;#onq1aqjz-VQe~uU5O4>=bR$YhNHAkIGiRUL^6bd_of)(1vhS z%R9(soKzVk=wn~Mz4n&*{Fshyu*W>f`H;zc49P)OWmaA6efTtnL8r;5%Jm;vCFte? zZk82iP=Kr;YHJv+dvEM6MA8{}3{#4UIniT_MCQfAs<^(e9u*-NFU|49_9wS{IVbi!^TWeDA|p(I&WKhl9atW@;D#! z<5E`BuTZxjM*i_F_dRX`6KOp!ZMq-)*BJbv?~F7uat^kpl|u5{n;tp||BkEo?a{8X(*C}D#LX@oS$4ahNb3|mE<&83*9HrA z6hAWpk6~Cr+xLp7@j5j>jO0juBXWx%!7~h43ti304fLs(J*o}#2Zs~6Yt+W4 zSctxQdEEg{)cf5v%d3I{Z4WYbSLk<)`~K016(^CdEW@8Yu`xiS^qR$60vPC8^fNI* zU<{FLoa5LPdoNW*Y68CRv4#HHlBr(gq-h;y zL^Wupy%D2;BWV79?eIGZICOSnxRImp-)~#Nm5wi+GFRJf_HO~nlLS2Uw+fNE3o$R6 z^iM_3l1Rli#$$eWqd_rE@UGxMJfGWVsrq2O6y3?IV8b(F*1=)85Zzf0{KV3FbpMZs zY*ucf5r{t-nNSGbZ-M3-@n@WrVI{yyyq4`GuI)jmFS@Tem8^ug?0?|hy3sV(T;ZgB zpSO8&2+#Nh<%~Fhk1xZPUtU6q7dIP+Flq1E8R|`6=M}*l2k&_~pX4DP$tNx<)OL`r1r}f*=h=)FtBQ$H;}(`7C|?>KTr8Rm;9-u|dA5aBh+=S0{LlDw+cQ zuMCGowge{5S?0#FT)iZ_A`<7*LX-@AwurSuXq4y>2gI70o279CQ+B%hLZ@GGBsi9} zc7-0K!-&O#ME^c~6u#{TAp&2yQ>>6buc}>*CAh!v=sODUzfmebt$i_^rh21~VCDgu zpG54@%XGW|^?skoj~XLiAANJS7<`#hA!~HV=#(bDP zQ;b4u92h{Yz7lEso`2C_SY*WNTlWlcY3UH6a>-}-`U(5Y?I#%9Myvb8+5_#bJ+@Sf z=YHt6WNBz(2L2?+RlyC#&^H10hJDSQEULOhvl9I;(K*EO7#z^i&3e}$)I~|1IAA*xV@%)OP!|JshZ^&N zMd5Cj91C@h{a`pI_0{1x>gpEmkW~%R;m>dcrcj%;yywhtR8$RWcH}iP1HL}-nrW*_ z{0^Om_xZp$8;0qHrxW77d+;JnfwP!(kT4$@=$G9e`({(!6jP7)4Ig#}k`ER>D!PmO zp!;R;1M-S}h<+(~IX7g`js*Pt8I`STDL?Mndvz}64}kcz>iSN706QX#EHY4tf_)k} zOy2~kc3A)$P#RI;_Vs9Bnzpng8P`?%B|L^bO20I&3v}t^=Z*95_wyjlG)YDwld!qX zI6nK{b-zewm*C{It>J6S4lHAuQ{rnw;kY1eRr z(8tGkF5$JSt^cRfo))<9gLw*oE4+NLdKnjRdppwt$}UysR}gySFwwQ5Bdu66Pe;uh z*>~e_zZjDL90)(^kGx15ZrtXZ1TWGa2hQuzTy%UJYryNMDrz6T`St7>l>>!?FvmDT z{xzj9QT4S^Q-WgO9EtqF#Z5{g1@f;5`xe8rkGhp?vv@Ajn#m@OUe4rMmN&?nU$9 zpi1CPzoTy<@_c64%;C#c_iQ3_ebyhMk&qUyBo#KYL3<@&r^h59Go1NGx(DW8hw|{j z=1lywiM^neT0cfP5?AE{lga4|FYyFLDnGbl;JGi!_3skVAGCeTO(KTNJZLqcv>pWN znB%e?lpvn3#nJrCJg>Ytv5ujukXPwBdm$|DE159?9|$Oo5JJ1p1N`u%E#D|#f^P!F zw5rmPha~^RQL$5WIDMUHs0Q&OL)z3H)q0@;%`Chr6au${##Hz%rEf(%<{98dUpgjX~}!{JcqSV`Zav{VN&1v+bXx?Hsnit0#w2-%lDeVG@Gb zNl1_jSShiI(y+2mm2CQs^G9~Te~Usiz9#X3$#pvP1KtGPgG0HECEklms??BqIMfgP znc>v`dpp)SV%$+(825*aKKbg0Ok@VCAqw^!ej`IVI%%z+=CGp=Mf_+1*;*shL z)(I$oXUfd<1mXR7O7Vks6N=V?#=2DUyP=`88{c47RnY4AY&ovxXU(NkVztkAYcR5e zJKQCw+yxyV12RQvi_KYSXS;ckPt0_NAGsb}z!k7Zk3rYHJ%(HEdhNevR=w*;aC=EF z=L^w>H%I&@->Y)dVvPJ?`|K2h$FHEwo0#x3$B1tB3##!gWA>0N+|L7dew+S%2aox@ ze|WdJs^JZO*m)g=H$zrBqg0uHX?*(3;wP1~h2-Fiw+y^W^wk(cN#Kt8-02Z2e7PI; zjDLru2ns*&f~Jauq0ETH^!=2)-0@)JiVzq_{zYWZzoUN|(ktE0a7!3cjMwFR@K`0g zxWN`>rM!9iFEaRypVz^oaF`m~8*(`=_Dn_V*_2%AZQMt?$&`wlKHQV{;>`BTFfbDR zR)w&$l^Y5=pAc=5lD%#R(ZoErc|PnKb-;|1l*?TOfagg24{RN|XbR>3vZWnJ%nV$F zx}AumG0|*@n)Lx;Hlj%awi6$+s%l97c)r29Lwo$guecho=Bb&!9`h_?0waAdbvb2? zZKP46lm1a=C%qly(G&3k(JnR7aSL1WH`QD?QgkIfQp8QN)m-44#>%;(YqFRDnQ8*= zuHYGVXmG}6Qd2nb(kOD~0Y)>lBOshl(RFg;%m2H}S`6*3xC0=gxCmy$63Yj$>CSBh zhqKpgOzfm!vuovk$}SE2D@xK+t@P$Fu)!U)K3K|H;2k_LYG?T&{?s?Ra4zk?5;-`Q z9pi;k*#Zzl*_@i_6bl*;Qtm{m1 zVl#?eBl8h|?XodY&3`?FdzkqgP#ETK3_gMi_*XHIaSwJcyK^4!Ha3`i018rpYJPCZ z(y`rmje;h`mn&+OUFYGvNBlMrC0SIBps)Zfgz(ehM_Xchia6p3BN4UK%SsUdi@W#& zQL60Nkosw-LCZ@*DQf)hUMQD*VKQ82JqecD6;(@R53;%=m7oYeiC?bFmTU?LjB22Y zSCd(+dI>(?f!U|Pr`=ty3=u)7KW=ngERBe8&uAlO4_=9|Qzqh2T6-A3`-+8+8C62S z<&0{!gAydLhlY4Wb(a3_jUpb?!Jx?V>CkGC0~w79k5Vy1lswyfcfW}0O!*ksqlDG7 zqj(edjQTeD54`bUyU_*w^y*#yf?eDm=k048rJk`#PDzwv8X0zaR*{*OP(h@9UlchQhs^hjT5`zjs+UT$xB+||3fle zHJpuH&h&jS|Afg^kd@%J%fI{ZtW0r<-dBZxY-npZLgB|CNgRm+Ppf3 z;#M+w7^gE9cW?=DU@CetR+pp*pJ$e|)$wpn*sLPr7I%dSIued6%A*!~VxPtax#puh zP?zJUg_0|*P#Ow_owO)r(Xsq8kBdscp%b#19}b2k`>}ErT7E1dHEs>C)i<}&S<*B` zeoQZjaNlx*ZC&yEIflo44+bCUO=Se0qkr=Zy;Xg)^@@|I&9*O5JkgUk6DRC2So*5& z18;LGhXpQ`Tm6!r)p4HGr&w1Bm$a4?*eLH6uw`3v*=Ui!cyb#r#pf9Ih~87owvW04 zhA75~FIxLw>T!Hs!w!l3LbL}|%XD#2qZsL>erKeX{vS2bucn^oB6-4tVa+iBZzBr^ z50O>^0zm$Ee(Xtr+>D|_JF6)w5n$8o0syoY#X;MzhAdpa6aYA_h>nL+)kDdWEJIH3 z5+=U;mj7*}3Dsfd7RO>JU_J&D zL#a7>JS%}ALLxkc7YQukMlhEK8g-QNtdmSBcDJwU`;jo)kZz!2>v5;%ex^p4rLhHH zRdrFPO4VO8()!Xu2T04r?;QTvXLR4YV72QS4Q1KV{8&z<_pSZ;R z`1%6@xFQ`wC2TK8^2WNB6k;s2nIjWq^r4&-l1&%_OOtE@_9t6|_KC?P@U5N^uIaYJ z*3r~;sX!JAO&olty(dN8{;6i;xIt8CS0u7Fblo(PV7oC~0-09g z4*roD4m(nbAHglkuOHjNRb-MM&@Z=fU+Gg|f6Gf^e(MElo`9gHorFtbrBK6=ieWdM zeA6DeM5$g_xUr+`rN_yUL81D>2S+#9;4Wa{@_`o~nd_KW-mDZ)xxHNmT%{s-PzG z*i(4cAt(Im-_C2sngz&JUXXJE-oljth*ztcl>cA3E*E6r^}?spT%x1uEJ+U9M=ptP zY_Nblrp#GYgvR4=eEW)50UctptWk3CYIX=VdUg%@Cqo!=BGksPqrxsk;6ds+{~mze zi$WZeZPCnxzuhU#IErB~PLc6emK=touDkHj$54u60S}XW3tMV2Q2}$L-zjRF>#^%8 z>2pzM;7`nnC7SkBLT)vlQ1GX5F3q$0Z8Q-dvLu6X!s4xc=zq5bkH)w9m(JI=Is z!b4?YoV+@(cjx8hrlp^B;L!k87%}b1Hv2A5v%gxT6LIQ znAm(Ll6{0unE8z&ca^Ll(h@=+>L5#N@#@g+es(WFf&-chmKo4ivQX&pB{3Ru1+sG57n+rPjNK8RR+yG(i6zg z1~u=|?GWoMNtue+Ynb6%$ln5u-A!UrS!$PoZd6_*NsznDbn#m5fLaa*&pt_?O`Z>E z)CTs{{~yt;O8tLC(;;8ozDoZVFZj`ic4%>~3_Hl=hdw=aQ)tmUnr|oDQ?^Z(St;I^I7DG5M29J4mLXG>LAJ%qN{;A( z82&&0Au{mN$>acQvfINT9sdLj8tZ=>4`cbvzx0*9Id6wz@xt|D{(|ParG!*(7KLxJrDAN)9@wO-HiT;(k(QK$#{N`5L+YwKVSFV zJ0sn~2n%2vzRk>VJF-Hvb*{sp39M;`9T47zssFrx&HaOMihUIi5pY9}P829M2~^n| zt~LNPc^h$;jMqjl{tJ6slHia)nh)8y0zQ>aR@(HZ!NLI?UfA#x4=j7R9{@gLf6VZ& z_6(DjVq>RPQ2qQL01hnEA~I#hJ^@uuF{n5Czh3O9T{>nwRK8UT-6;ib>0>GXTi9wp ztKVUjf`G9;|KUu8N_fpvkAR%Twy>$~-TMOI(HIU?#7>nqT0k4>G1v^6aft?WPOD`J z^KF87Gzua@(fC@&c%>9VQCb2h;r1vUOB|u-Y(GG1k)lak$nA*_;LVs^g2!o)qZUsP( z+};$D`#DFlG=aqgYW0-JaRkv;j425l^Z9(7t4u3Z`}ro$dJuWUs6{o1>Zblx`q95cr1ie^cMTyas=xqba>!uZt^e79BLYW3j0pY7{KF1o4X@jEthbAid z-(8mep*H-Ny}B8CE#u2T_r{#HBrINmVNHKTNjLa&z!hGu^e@1DnrE)?-j9_zft=zlpXYm0IRB zO}(6h^Cx-gB1E1ODv&lS%oC$9^YoHE)A?i&yKDW{ke3&)kb;~*GK#l*i}Q^3m4frv zaZ7$Ww&YZ{Hx0H6Oz39GQk!p6CeE`;BKe48-luLgsWP5d{^!T5TbQ8{yv0eWNSB5l z%>E|aBTiFu$ir{Yoy3NjrQs*vpLOVOQ^064gu({D4ZkRBC!LSl`8(^Ajz0aL#6mDU z5bi1AceC73M>fi=Fpr1gOyD65-u(T0FICtuGjdiKDq86*wKR(m_lXj#V}1P+jKwQahmK+D)VQWR@R@)n=;UA6{gmrL2EIpF({g6IGn^ZVEsp7 zM3}~rmdll}#4HqKt+)df{UzOthf`jf?xSIA+(sM`+OG*UWP6SgUJ%Q24Wy_ilY$8)*0fVY)y6R=2 zWdp0i5eg<8?Nro>#g&w<$c`lt7UF=$te&nii)>F?i}751MyCKo=LQ-;j`V0DJF5zg z=mmf7pEnMO=+pU54xJf5>`w)$6cXEW-U_?ft}kKmG6yJ4nlbx%r$fJPDaCk+bWy4> z7A0X#H^SzgcWV(N^R3CPn1LAEl_s9=!_Cti1Qw`MjAPmT)Wk4A)V`j!&sK}| zNq(9m*QA)eWCyAH`rQ9}wGQ}vfKy#SOVS!PTtX+&L7~?~!GzCcc5QP4Z2m8|=SVgmA)`*qN?j|@}cu3Q48tYIN zh7~ZSX^kZ9c>2&Ix9*1wXtFroocC1wJZ%)l6W_UjqiF^zpjlVH&z;fc5EhI_sd9Rq zm*F~!SssWkfBjiI&xk9BLmx3+o+gr0YeU;b%8_$2At&*>^dEdyHh$@BC#lfDZp=3t zj7NK4^-0A>%F}^19F{Js1h{lpv$k7g;1sgFcCi|faMed5A^(&uH8ag6>31Pjd#+?e zoA(6{qa8e3dwVj*AoR~bzEuxX)d~O^*?#iXni9WnzX4$Q2F^G1|5y+)W=y})_^r8S zKR}P5ucE=D15vtmV@KJlrEw>^yeVXiF_4xO-H~9xgWO0k_@LCN43_NLYH# ziQNt(T7B9%Bn4adEn(-cvV{|Dk=YGa;&JxSqL?h~ylxzcFp4H@qG;+Si|1d!C(m|l zqRMsuqE}C46~Gi8;&cpp1C<<%n;gDTe4I=+%$AV;W_kQPg7os=o9w9{-6_9|GXkUYS@1)Mn^|l$urM^_xGTV#QB31ymO6$0} zsuW1iObm!FapLX*{P4^-^FQ4RATqRplJ`ps$>Sgz;#BLGr^<-ezaBWcuYq4!h+}Y0 zl_dx|0-8^W*L88FH@bU6yMO*SvqUh4iWpj1AM0tLKQ%4c?CpIP4?kp`A-of zT>%yA(gHjrDiH$xUGd)y?y*$0_fV#&Iegy_Vs3%RthXSqmtzZ1L>Tkot5@WR5{pfq zcdJp~W>FsaLs1Sl+u$WKrNo%IO1Y0o?~1;|qmIZC&n+NhyrT>UNu_;<+j;-sgcgwP z@qh4a;Oo~pB=|Rs^HC%xPAECf$x0O2{vC8!^AE0QuML#A=r6B%G{nJo(0TfE_-6~q zD>5S7@}|^A0)%IHOLsLvlwx+2fHuk~$NgOlhsATn=GFDSJDqIa}igDzN% zmZkA!1oH09AQpUGhZ{G>N*cfdE27zoO%hRN*l3@jXn-(JvRZ7Pkm9c<4@>x4^3_G# z3gU}Junad}gqIc&H+9S#1nq1jJ?;X|aisD6m;7&%5hZD_!xa$Z@wpK?H)Ehp{5(|^ z2(b%Tmf>hkRlVxQ8g_6{^MbW2c-w?*@cxH@Mv0CSY@)Mmw^#545LS2avX=4i*rU6D z+BX!LB^8cVP6lV8u9H8Rbd8z=m65XxU&1YNnaNcDU~e`T&h0eKl{l32w2`CV@GPw7 zf77~IQF3^8)1YMX%u}j(nliw#IE-RLsIyHoU@JQCbCFNUM{g2ZVG)tZSxU3>3#AHi zgvI1b9BjuB9N<~bbSFh8zfqZLtgQXeyH4aycgaBA@$bgT5@8)nJS(MJ;RfwXfAqHI z3cpf&sT)_`Q(NYkc^+UpB|ccTuYcdbe)|J==P!;xOPX)u?>Z;q+>jTHP!fUmc-RgzpqV5qk}0KF@V2>T|myHK0U*AJa)k^&r2VVonM zow+W5U+cbplE}|z(pPYHEhHz(4n19eIr6@P%PFxv#;0a0i}nTc&xv%JLSWj{&F;)? z7X}5IFWdPlt#xBP{XHd8kP}lM@5Qn_M@c<>RBM81ay|W$$47JSn=o3x6cF?0!ieuE zD~fJfKb~S_MWDien@rx2V6NF}EJ4{%c&4>ESlSatnPF??LXaam zk*Rgnv*W<&n3}_&yZ3({SUxu1sr-|uK*3>X!aT_UUDsv$EErw7B-c${bA>7%QGX!J z(^%QOAMmUECzljU0h27~C}pRRv}>o(2NWWMy{}>C%9m*`NZ%}+q+!=3 z$u}KUzi4xtXo+ET$^1lJDYT`wB;EN&c5+Yfc1hZ?@2tC*CQ{<`UEcFd=R_UOs8(hH zdcm#ID)W6p=@-kLQVwc$mi3PTqtP_P-#z)M%?|C+ z=5|R5LK)JDx&(K=V1z~<6Yhi_kH|-fPT68Xhy7AI8xtcln zNU@Z@`_64`h6M0Y@P*LK4I|S$@aCwhmDfR61|E2Nw~WAuJmO;(zSnM38K0Z@X=H z58n}ctC|Z78*2Ua|Bs}z zfQssQ`#2~H3rH;~4GT+mEZyCm(k0SJBi-F0B_Q414bmY}(j7l)0TGaTFaP%(Jx37s z-aB{ZnVDz4-_O&CLj3)^rSg@2G<;qN$z}&1>#tl`boTz-8>HthB-i~{{UJV}nKUMf zPImbrU4-$R{k}IL_h&R2H7pdJpIQ5SKOrKLiT}8G6CzEP^zOgKB&%e>xQB|6@tkcI z@O$P>>um98Kq68(vn?M#S5Q?VrqJ8bCQMm_7ad+$SU^^jdVGOz61(#uOPvS5msok| zH1V#NcuIxi^XH2QP-CfPK~_Vmuuu+B;hm}J2BdSS@KbiUiDc)c?d5N>pjJ>(gJ$(q z88Adg$e6w38IT7h{l86!oZ)`igL}7jW8YiPBjbm5N{BzPE$}PLgS*`s97Nzv4S?{c zLda$Lf_w2uPsLV+{wsA8*9Kib@01SyajE=%Ni)As32~q3NI$*99=l3GQto!@UkS{} znRcb}$0`l9U93x)=)xGYFgzu8{g5GxNWZa<-R%K03_8*SU2PoiQC;NTZU{#Ht3v6< z$yHnaT5H>gQgv>Tk)kkot|62@Z1CL%{g}jfTy0WZDaIE6G6yq$kJh>y?M~KIfd!bV z_wnxnLzmmr_;bgVCLZ3r<%q78MZ0Kfq50J$bP9S-sweogAASn*-=$?;sL`QGBWJ-! z^N8o;p{LqS`xGUxkDT@i=-1!9_7Erc47mpsobF%$)Xm;-ea*D^;)w78IXI+oe;27W z%+i{inas*iM}ZKAVpqJqz%8%t|6gzjjHjqH38wYpaay*&anR4 zDa-3|Ekye%3_C4dw{W^eP?#}ln3RSfVr%uBW8eQEaDG^21a~;}4rU?UPRM;7UL!x4tx+1`4#fNc zX73`uSHFhm@|KrU*GG$X6hshDlGqtIf^!WS=^V_Lle^(=7oACp==zi=iSL;+9U?SO z(v3tA!0CL(~FW<*)70j(T_JWCLEOsuQb8<7fY^cxLs27BF2q^#2 zGgx$sxi@-c@ROZBeOrV-luhf>I00iaRXKwZM6MjZV1u!>#STOkI+gH+Pn28iAdy6e zeHIAQqyow65*25zQaH~?O4IZZWBElM7Ra2eFy0Z7BP--&j9Qe!j{$@U8a#*4VKZK$ zl#S<%UN|us+Jx@hX>*0e#zK2Tq|u}g7X)ae3kCce`kDOH3pLfxmJn_Wv>4v z#YD7Mfp63ZB4q%EH@>?+@jU3ww0BXc)JwZC3ym=#NH!+=2E%_!18@U2VG%E05;A)( z_x89X-yng-o!4acnmT>8f_Wyp$hFOCz$UfWHwYVD;qbSweB%3vJ^1l)QeL|1*{xjj zjw2V&^>M5;uzM za?LBV{fNRm&cchx{OA+uUz}(&?V#Adf9(N&TATUgi}jP0)llS*SAU&kv-SCL)S-F- z`{tL&gK@W7gbP#dr>bXn-Qhh%@nT*>UBZN}p9KHTW!wVZy|3tpZ%cGl2jwdTAn+JM zzKkY&Bcp6%wEGl!lONI>?diY6)O&}!azdBBch|tOpD*HS#QO&2Op^xQ@N}<6>Vbsf z0BCJ*^?HEfYPX^VybpS;RTc=uBHA&({CD850|zC=dtKY&rhNM?h@v=&C0zHxWC{G! zpR(1%0mpW&u@Q{#V}x1s08U_SK^+yY-p|_teNs$hK$!?eH?!Ocw{@$;zyid7rqzFj z%HR3|TeklER&ILX0%LRo(iO|k_8%)-?+6g=J{kh8&)$n!aUaMWyVx{$VNp<;>rhGl z>%v|AaN!5${C}`qtaeG%wKRqlUKI1fz*fA;dRqN_STo;x3%#WT0=m}fQ16V~@aJrF ztknfc6PtbKFp;7G^WK?RbN;2F1AwT%V{46J`9|kXt z)iJzijy>GGKMZePAlVEP;55f+u_N`$0z=|Pi)?D~f)2&h17zDgx-BS=Z@k8L{ZDK2e?Z7Q9#%Q$LF0@X{Q@PdfdGmBlG-1f8x zf~-T$q}0$>NP|Ng$TV?1*x}zejxyp1end9~kv#pp7xSZr6Uae9ByA`66#g-YVZI0d zC^2%$RA$bMB~=~3UxmMC7!Y931-*6SZ-PJc73d1*ewGa7j|Tpv0?*IIARB@2B;SxQ zCNA9cm|~9n(mE;hg0IG4$(0Z=;?;nsKuU9!+p4}O8*2EUVI!#us}W`jwQtI0j~D=+ z7tGRLWg6L>@;f!^w;492k!XGC%6JTcd}`C7^9b@L&&Zq_x~OgP0u}j;AI! z#+Ya)7hPlxNPhb`2+3xeg-VcWzFK=C9v{0M8AN2vLWPckqs~ya`ZU)v;%KGx2ac)g zeBv~rF3J9-l%YWAR`t}oC=OdJNB{>&W0nIuofhOFsS)yWeQpVdgx=iNSbx!nhz&=* zIaR{=h;FH;K*4Xh?sjS^^^^$R3bJ=`3YplD)~iY^c+Qw3?>n5va{_F4x$uXwuR2V$ zb|^TK{>{eT{~=}-FN0Xu(q{AYl*K3Q8Nv`eXWS>Hp<;G$pBm7EatewO3&QtZY?`TiiWi7&w};{Uc17`cXu|Y# z3Q_MEPlk7aJ$SGf&iMzE%eZ5=P9g}Qvx*TqAhzUBBLD{@uZVvi>ga)A!8H=z#}AZ)4&2P z&Pq(|7*V@hNyh&$!=h#M*PZ6V!&8AvpHc?(t#FQqL%o7qp^}&H(kLG<&=-%S5;X&) z#(*0l0nzBkZ?#l-lJ+V~^|s-xSBQRUiBN@X9pJtUGHRx*i1C5?;X}eSA!&D*+W3Ji z**((aW^LuF2aSyx=<7$huk%U!USgcQVhyxnS2ajVmPz~cat+2aa}XP0g_(!kZ*?*_ zT&%KRQN?~is6Mj9%f9!JoL$Ar?-{b|!7h|i+Bl`dWj83ID=^c!5R!kSLi)RK`f$=n zUPJexX3qIagmdfyS2_s)Y0r~UiQb2_cO`0jDjLD@B>^cdgK{R0fpH(2&n6B)1$$Re zMaHoxBl_-F#(-s-yCh2HT{oSdj^9JV^xIfL#t_F=brI=Z<;y%zMeh$6r6YL#Qp1@cERaPIujT&+=i?Q1}4n@rzDHI)`8A9veb-*L)Hz^kAXO->Aj%@esMp^z>6fz1_*OKxb(WkihOJ`4g^yj(zjcA3wyr-tT zE!ydXdjHP#W&?c)z7Y6B0tGElCc!F|Ij|rC1N)>(moGzQxsq zt#kEXM+l@vwc!JfAS?RYx%8fFNx@@JBegMa#KY=V=5Ibd@t?V3$K)h$CU($uq?3~) z&WeUVTS&{nO0sZ&Nywh&AWbJT1heAbNbXSoGmSTI!sXL+9uDrE0geo)3taGgZ2-~$ zll;ibxsjz!$s%z~@E+DNzRKW46z)*n;zf9Q$~*#LdFxKDp~+!V{O45ynpPkujZEnM zEyz?Ug@W8;^OaF4!8fgjK|+7J^Rrm-RsM~dogKQqk(b2M5)-SAoVW5bbkQV)H`P8uUaUA zYp}RycHz8{R0hLO>CEN|5VASa#nY)o(&~nL{1`!M!3WSdjZ1f12ji9`@Edp4NEzYn zI9MuhU&Glj*tE2>ygh}w(EIwRyY>O*+>zSa>3-KZ9o(%o`q>VRG~e%q9|Vuq=mGc? z|8Vm9UPtNuFzC!zg~_ff-$>TjMR7yV zqZGzmBz=Cv7*b1|xhtH0(;!l%Xq1!a4$bbbgiYekiZIo_nf3?^WDof$7TF_Q|L$YQ z$E-bwNw#VQ-J7PP)*iQoCLQc*GH9!Ez~9MhB#ofD=F|4eZtk|FVQYNe@UAx!;(;&* zk|_1Gci*yJsec7yz_R5tQJUO*Jy8=X`0{6+^{BpxY?xwHdAN#)J2TWHYSJAfDpqC@gnx&tTuT@o{(wq$cO1&mQb9{!Hc7 zH^waJa5%LeLO`NO&l#Ns{((#Lb#epzC)a5WHc*J|+5_79W5_|#LPDg_r;F9 z81o+W@3Nf&0+T*A;_^4kkVy`6jsLDf%G^PTTPPTOE}^~5v!%?2n=7lOD7B#q50w#9 z@v6T^G5%W|CdO23RNc#9>TEFJSe_)x`A44e@XkO}puA`j8M23{d3Jy(Wd$-aCo$QxSLTa}vSX*mJVZAh`ci z9L`aWF{H*ARx?bCv)Tq2Pnk-Vq6PzvZ|NfszDF3hMJz`mF}v_>5qx~Cp)%`HY~RbC zxZQbX*v&Q@kNSfd&O{>jcFHbm#-{lN_~xPhhs0o%?`@TCRB=aW2p^9tK>J!4`m^!h z&Nsgn&w@8!%<4p$SRQWMcZ@lt)8*90Tj?5ff0VLhvbH>u|F`J6Kjg!u))_C`9q-ir zCHnbOV#vJ|v&yP?)eeDHLUro*PkcuaX3hq#WVH)vfcD==(MhJWSKqH{uhJ|?fS2y< zXh`1x5Mq^^0iku!ycr1T#8IH-t8o+pg~Em3jbuk5+8)uPz0sq5(e4)<;>Cl@xBeMq zQ;|Le&LplU$+t*3t?sJwy{y930ap7TWclP!6h}$-YVWQWHkB7r!rh7oGRA_aot^zaj%+&zkBW!|NDk-OAG zJ6cZ!wOoj-_wvFSMHsD_KCFv@FF^YJo$Iv-BjPbG)G7?IN?l2GQtRyypheoyHtjrU zBmZdAzvN(T6xc_=LHTVIVl@H&eo|w%KaB}y$xxgD@HS-}Y00h!N#27-3Ls|MWL=0J zUGP($)z43s>lj1XT`5lU7UIBEF1|AAvhbWD=_$>gXDolnm5BgIrA%ukVE#rQXqs*p z-oDJ^2G?+}*MpKb#8a6h#|NOd7jZi>Ql9_G==q7bs9a|&vQc3_Oc)I0C(CJOs1$wA zlL~Efbul}Hr%v2z;TFbQ8+OLPuht4G?ysLwcd|$85R+dycOHA{+H!F!*>G{b^v1za zBo8){=y(LH%VR-nW&BeWIelQ48ER>S3OtkJ^w_=U;bE68)Yj$Ual zr$~KUou$sVo@A0qiIH#E$&;gxZXz-~Slh;g%P?Z^BcSRP{;J59q@ZRnYeixWbIoNj z_~lMweJg}*bnv}l;d^EYIqg!(2;BB_Jl(B@CwB)la>EMG6>(3bBwoB?%CQO-X2QySsC28eN!A%0058C}45+WfUpR?p%M^_6M(QL=6>gje^?9`FMVZ zT%60dox8M6D^u2z-b83k+_asr7XNR3xTU41d|vXgkE=gR-IHTPIBBdauNYVd8q4lI z(KkOO$L0M_C1(Jm?>Z1pOj8Du~B)L>l)qL;A%9fgcAmApw%_@l6}`(WsAm1R5+ zQzXwMnuQH-jUiJH0sawJnvZtHS1d-A;tpK*F-J42gO(Id7at zg@*8d2in#8i|WH?Wk_j0HDf(KL(yif?tlmDyf{hl7T(*%VD!eR3ZNu$b;S3kM-!}8 z6p#i;y#IDeDyK_x@mAc&8e-Z7A+~wqNHSTK36LHK8CZG;dR@DS58tC$b?k*a-C$2t zkAo5+`$nUtsKdT=fo)8IUTl$iH0EGk4%G{<=z8 zD5Fl6=SAG*?px+M8=w9}#xbwVg4Ug0j=ftD>96wx;(YU7jwjQPQ;$e>?e#JKvb&aW zy629gr@6o_5!tQ#N#QL5^3E~V>pc(BDxJ8znTxr{$e*L$0Olrt+b>8hX80woLDH6I zGWeo$0gm>0oTP-?@_L24bV9M;h3_nt`uZ9Ud#pmO({QF_^8^#y?RFU%Vw@VxshL@Y z-A?2QzS?QvdeEIT1lYf<3?JM@`aYoBY0#4X%2%dtO`fe&(pyxQ8Ep(9M@s6{rT8)6 zU6OPaDd;)9(Yh&ZnNTDwXKXm{ z@Yei&;G-AoMhKkW+WYbItB$3@e)v9ekT8iBz!X{K&ta8&?oM#3lJP85_nSZ6!(R82 z^P4B7-%20SndvAVKPB+`wWqU&Ts&UWepLc>j}4)jq!eqQ5^LZSYhV>~rITwAot;DZ zx{Neg0{Ti0=6aT!wM*fe52AfUlrtBk_{c9z@v)v31)!8NrlqdTHP2Rc20hxq#)Ma4MIKMq%ZQhDmIccjtnr(e3R--6)Ig!hK}?!1)#7 z#xnwN(C{PRCe@AEjl_=vTLY+Z>42p{4$r7hoyyEbVWwx?VJ z#J%BTgJk?q-rt1dgf~yJ1Z7P`yfg_P`ZnUd9_)P*5bRy4gP3)e{^px?FGZ-{QBW2( zV{hFf6Hh3;*N>hig<4(<=dk_d;^jG|6i*|ERn7gGOVmXauF{+*<}V{#F=og7Ez`#wv)`J?Y#&@5M)Cp}vJ5I9`PA zc;V;^S2H*mGhql;SAQxS;3<3(M@&@bpjP`yen9MJ5(57YP)Xnq=t0P2rJ5ErgS~V)Q?U2l$0YresLFq^vxRzPbPbVJx46grRa07tL|6CG;_E=t<2`{1;|KP&h`Wog?WLN-4V-u0 znF~IA`BXYX6$nP!ldF3nyw;ZnbnmgdlZaSLXHrP|F>!<|Ury_~vom4Wf5IhwmAHrZ zvF31I7z|v0i*vng&+MI~X~JigE4H-|WHeo^G4d@za;b`$&YIk=>0k~86nbtMzgQB& zxXXXR{sLCxCjUf*l^+mq6ibpMp%4?oA=rzL@X&yY74eAv&6n@u0$!~7c_AvLFIo&G znoFjqQXH>dKSK$v+g&-|)MB9!?JT*Nv=XR>%lWRyBiw;YZnC=g|f%3@K*sDWo z6yDn!VOnxiKZ%C#6ePUZ2dzo0m)N4e2`%N;>Uoz)vgg^VEb&x`RmsIQ76hsqjRl+$ z4-ZGF|9u}Y4oHGqJ10x{b2Fu|CNKAZ4LYmqO5pf7(7WYv_f0lPT`l#4c%|AXcd18JItYW048^(EF=|A4N|X`1ID;9?`}5n`w{j zi)Q&&UHqQg%cm;yYV-h~){gU!S7jJ(%Kd9MfQ*qVD_K7v=+|ySOAYjFa`@wLJVucn zUBFh^cN(t`j;c)X;9$#6pCbuUBg6=0KLacpe@Xo2>j`!MQ^hKOxJd}i zMr6Wdl9KR(@XTRFf7k*MZhzJWpzpk*=QMJ{ z(9A3fy)+7Xm4uUQg|c_WF&S#f)M+v4vT7vOB-E+()CepZtInJC{$I+?pH~MbebV>H zEnr-{KSd4G>?o?|%888fvffMiA52^OZSXBHh>H`G#o0eym&JMP)ArXX0f${Z2bZXJ ziu}bp6NayTRSu%FUhVAg+g;&+J89FRs1cTnxQ4n5`bSDfu^D-0FSmV$wM*39k$T-C zf3LZblP~t|M~<$!0Yj$M+o+!kgNjp_k7Gi^=HjCvva|JQgoW7*YJM=G6Kkf!AXH{X z_?be&j*Rj*#x-4)MFxAkiLCaas?lVv4O!p^hcdQTt!03XXvho6JvcSHVa@kj&{m-r z5>beU?7eqn1Vf66h|vP{V6}8y&jZ%RU>st3PV@>(2gl zy#*n_nC^Wq$I*MjCit57>JM;avyyb=>z!eenr_0)*Jo>$v`a((g(AHhCU$8PWZ@HJ zp^~)wT8<+kxif>pi&58`7B#uYeFu5KoDCc>`K(E5AfP*D>Be8(){fF<`+O zs7mJN6p~tBjGzx#{$~Egb@MN?$|6Y|U)sJUWH;0TWL2LK#U#vwR%#0911ctBeuVho zV?F&4zKFQd8_tTtnu$mD=@Iz%--rt8;qaT*e5}=VRTAAQV4Oa*2bf6KhFO=Rfuv=tA$6e;cVov**YPwo z5P%=dP4Y7+%t&v75Tb#oc8D_Tq}W;QCle0Pp|91-xO$EsL#HzOqA${tlVQK~EM7{EOi%02v>L!&L${61zE!ul{ZF*KgAv z)Pa6$`6sb3vS^erWO9ZxbMygx>?J7B&IoyoKv>nl$42;DXe?#rK;dZ8i~3JmDQ@!< z%`*kL7L7*u{Ud;@t4VD~^(quYH>Q7jAC?-8A{|6%%*f5k+1VI@P-VrJ|1meJ7~x5C zB6%Ft4AA3&74;{4@VBb>X@O}tJ70!YIhkIc4I$a2uO)_k0>~;+CVNw0j7KSU6&C1f zt_gQ&L%E)EtFVfc2EsEwAq`M617D+jaqlr}KrnQ{sfWA=)-4O>ZZy$mw)$G&ux2U}}tG^W(<&!&7EU6~N2&v}FGu^4e~Xa}E<9jPCsT zOATN)hd-LVI!-Nlp&(@~PtGMahxCT+l?6>FXP@=c0A8EiO$G|&-|Ey8JeP|DY2mIM}E$5jR%V7LSuG6H2(Ldlt&&#qn zT>fVn2pDHg#-v%NFa4yZ^uc-2yQZsO$oVlTWYI`%qsrp23Bq3HDK#lFLb3LTpV#9S zCrIsZK+VDO2`31k9o@!Qvm|W-pMsX>x?QD!V&^u?*JKNDn*wQ&YL!4T-Q)9~_MpI1 zB{RPf_IOrGgh~dLQ0!p>Ti{)bBv*ftX+I#{S_b3TZ7$b5MSt>77&!+mK2eGtEjRj# z4Y4*TJ2RgrY%hGjeQ9F8^+wQiE?&*gT&?rNiUGB+5&aFeS2{#rQ)rj>8&*}1fc?OD zjQZB}MqAsXf?TTw_QpI%eM;}2hmfnMP1ue+$Yk z^kQ#KZ+uPHC3x(?*#CB)C9p8kc=E_Y253$dvw)UsRhpGo@q)~IqEBQ8r(bFiuX*Zw<=-A3|lTpA9Cbj(PvPfr>X`1X*I>xjcv{SlVLq1}XN@RPNV<>8nNuMij;?EiOD_mmgIWhL3Dw1|ov5_Y(3wuV&=6lySNOZz7>B{CrXDkOdjW@*t)Bil|%&4jbvyp8>lYm80>Xo01^KO z?)eCnINiHkU15x6@jO5)Zt5(8DZ?nocv3N-?d=lv0z`7|U6=$;+6F?dJOK#}gT2}O zT^)TU0Ge$8kbCmCLPgE9T2%Blp-FNI#e|`qrm^|`f2EO0Z$uO~)um~e#ER^9tohxA z6-^8-wFpCnJ9`Vys*8}CWgzo~Js($YGvh`TKqpGnX-cxp=N_1l+&S&WN} zsI~!qzu-V!67KB(9*d9yKH#dF4x(M;R@DZ_DWqZRW+6Bd2sZ+A>tSt7Z~GffLLe-} zdoBl9BJt4mvL2(}y#hcw{lm=Pu!v;SsFC&m*;X&N%a|2Q~Ul4e-(Z8yhgpWmFym<5Zfdj zN{Fu~_30{N*eV`UAzj?fF9*+5Q{XYwxUk8;ufZ7x3IW`@V35SeLgB@WIn*HR*g}?5 zU=Cm3osk56X%FiC?-h_uKrEjHR>OX}V)Slh68FTask96lU;euu<*HSA&A_p@tDqSI z{z%MVc|!9GNP0rQ+s7+$;vB&M=h-Cu05ymb>IA-!19WK;EvZPg&q$htxv*{}S90@K zYZ`#fJb1))!yYyx|0+Y+D0C}!=e{v5$4${dj;#}X@j4veg)BWr$MkmRmcB{_@MotY z4TxZilw6mYE_El7BVufMko~#W!HJ2KgU`taVPg^uT?Bjq212#26dUcrKrjHOuG+a< z?kDfuz0|?(6{k89^RdSp2+{&#J+DzHc7%D{V;n^E`x6-@A^7#hD0XGj z0l7u%7WTSN-IpC;7&_b4-}r>)Z%`u@I#G@Bab04+T2cW1BN5iT6u-c>D=f}N1+JU- zYYa2(r$(w>1g>S~Ecmg8=d<7~N?(N1pvGTYiQyy}6ca~hTicLU})<^4~gEH~$WvVR4{$GiXWB7%D>V5~{LXZ_FeIkI9tDj&bs$!!==PH9suzx4>78Pt z{cgG!9Dg}fDq)Y}$hBL?*tatzvzM?J9VQqD@$`k*jT(!=n6EvDFqr+{Y^jvpF}mBZ zp&W@NJ_oFEq4$r$!VmiEwP6to_uk;Cr&qtAXBF3gAYD;6 zr+vX&_yZkQ%wVA>9VInf!~$g%BO?(DjBQ5svWj{iaiOP#9~2r#nfutm;090X2a>1)1Z=Hw1SJxqhojxS<6H6Cw$47d zDq8{+9!DHO*q8f0uP9IU>3f`~MoTjeqeGG3ig&YXbK#?ev#s2P7No?!t~FL$4NMS0 zKheSWuco$t*C+Hd>eYR!n(=X~jgr}5y>T76RlrumgQpnLLs47|HBmAR}J88 zV^CPcS`rY$3#)w)aPa#5{?(Er@IZDhTUdTg=Xrt$vD`@e44S6!ARpB=;OT0(-$9MQ zU+QX0Y-S}V+*p!X^a~iyTA`S_{RbOUO-MJADr|_n9~4Y@3Ch`8$#u%X-80U=m&2Z> z8@AO{MhIAT4`>ef4(R27XFUigS`C7)aep}N2^b&OraI*2s@uwyi)m+z9EILZRk;_P zC?PD4T2EA0RBVnfIRi87W;^QJMg3Rf^qQuUPLF`Z-r*A{3`&UZ;|f#``3&&rNAwsm zG;iL8b-g(RtovAo3T)z1p@+IUeX7mcC&SSOe1Y`ZBJsQ%|AEnWLz&3=fxb-w{7|J0 z?jqp-_H9nbEUAJV2fTQ+|&4wq?c(=VKy6 zL%O`OgqORXy!#h(y>qU%c|x>oV_CVqJ-l_pVQ>SWb_O2yJW}KXwW4Oha^^$<1I`_{YR>!dl)G@L?CdL!hsf$-?|Je4PpQ^9&GIxg=JmV3fM5%%({~H z;fY%T8kA_nW0Y!HE)tpIM>dILQ{YE>R75k)7uBNTQKQAL`_o`PAk!SYzRs&a)VBv+ zL424Cw1IDT>qK*b1MLtA^)>YaSkVNgNv);_T&2PdRtS6?Pn{^)+i8?zo6Al9AVv#3 z^AYnBBK-*i8K=--VZ>&m_PBsXNqWH92RJe^0O9|x+sLJ!AEQ3WwIu(xX-R$x{WH`I znaPc#Nb%>ovDj^=>X2x6uH{o*kZN;W!Zx~NHx#!)yqgJNDXt)nXP>6jlOZTGM2$x$ z%X`U?PAMJBDmwMhYyN!QD>npC69k*$dKm{W>vsvt_8pK-r}>4cTGo3pLH5L;Vb zYxAcksPlkC)3$BF7gV2~!_lW4z3!x|VD9k}>7xB-iopgJIG{xgqMaP0sf;f?W^ z;Rl<&m<}nXi1fqMw%%B+G2s{)wN30VlrYU!O?H72>|DQW-LqL0O2 zw}QhSE{EQIHy===cBmlysm9{d{G(Dqs-)tH}uewl*OO8PSjh)wdDJAnH{Q zFKA)dWH9Q-tGZUaD4(FdTAhXL`6;`iO0(yMPB}Fy<$H_-;MPdiE!<@5%ol0|#Fivw2G@NC%SA*u z@L5Kl8~>!kubQtR-gBz5Lv9GZ^h*ATmAVJqk2i92g6r}V39|1xm>j$Jm8oj4Z%JWHrXVUR3?{y?sJ@9?WRT1^DhNbilaxjF7Iks4_0@*H%Qp0vuqf#O1mKgiZnf<|Kc9a7;8m{GLJ1z>@Hdxu1g6^*CIPO@JJ zPb5ZJzF-7hi8FkS6gucJk|S&hG%2qFCG%iS{HOw5@nCVV*elVkh>oC#aLL_7WX5hhUwCCw(7-hEUwxI5;4@9unaP9w>5M_l>u>Z6lGR=d9aEeN7T7lc6 z#STD>PG);6O7KdnbV86*Sy0~(5B7&-`L0526#m$>Im`Q=~>X? zi@OMCw@&V1eS7Ju$%*k`!z~z@l7Rj|Lgu}v?dz5_R)LmyVP&V#0&SA`%Mg4_A!Vn# z*ZDBAJ%!$?0}~DA4I2dwj&&`<)IyiAc%A#L9@(!9_WL2rD1T1mh zRHSuJofo}cD5SMw6p)T&LFb`29#+<%J50-`xTb$ZTdU%q4!lNNpYmC>j4ZO-b|RO&Y%aHdWTTJh(kn>iSo> zXu#`*DTzw3^ZMZT`?s#tVt|a?2(7FYy|+WzW&|=vV|vxDC_WsE)bNQm|3F&&2VAi~ zAoiX7wICk<7D!mH16?#UIUezj#Z?pLCBkh-9hif15qX1XJ<1o>@eJ*WTgrAiObd}R z$nH`(ateFj+D{&b0r$L;8L@JS=F~y2UbiV|eW1*?xfIitNxtWevL@KDO9F}w^+^XQ ztOLre(MT1d>OpZIq& zXq7gK+D#aq>Y7csG9Zh z?peN5{UW$V5^vcq{Lw{wq^jT};p0iuM}&|4Ps{u&Gc|;h_-@dRW-F-HsW&}#vPK)n zZ%sDf?~XhG1XEjF>NLX>Ta#=pCN_>=d>Wx@#HavXl}xM@frI?*&JX&A?Ksn)LM4B; zn4wtSvdcTMO?_Y#iGGG76BDQOcq1iT-KxxHSTPZcB zBGnKeB~1`pRDS)gq|}UhV9WDASzl!G8zYQw>PCioqj}NxU6Gr%V9_F%zr>_dQ(3Zh zr+M$So!eUPTTCyU()kJ%9e+vEOoJLhB&7tb&0!7}m1@b0(fL4ey$$E^=!<5E#2mwS*Gv~n`tH8At6)O zRvrW=?cK7jHya{udK9-_vTHosM8wffxdbtWJ=X$-fMEtHycT$j&6OjQ5AOJ!jM{d3 z*hYN+v!(A=;`tYJWFDnU^1%Uc%U+oy7t!CIN zBgB6O&2FbI9-!z|jN_o?>fDg>+9*Z@-{TphV>uXAm-|xjn_no7a?k~OSvP~=kw1WO zxNOIDsz$S@k}*K%G-_q%N-9w2blPtcZsm2!F`(n+o5KK1iz5VnOlURBC3&-3f;!4G zc7-7F5UtN|RL#TPpC?0D)lF7x`pd2^{gdIxION!PABH{^EiVv*;;uG}ukWtaj9^sn z|8BS{l&{?Iai-R5BiPzSF$N9z`lmLGf{}DsFjm5*=YQ_bLQ74L)=2*1$3%oZ27Uu7 zZwV!Os?7nl%95hVrUe*r`>rKAfTdy75E?xH@r0LO-}o^^*Y;|s^>Mt9f7!z~Xfp~A zi3;WbfU8DM?vW@PP{@Bv{2DBNr85{Ee+q2RrxHo{sQPFt~$$fkt)+e?VK8NG;+|5FLk>(@KflW=`WKV;=%ZMm#gxtAF55bU_ zNu;Zg@EJ?aqV8G_8&1UKO~ZcfB$IFl{kD)5Ua)$>fH5urr13$mERghZ>-EZ0cSj58 z*t^^p;_TPL;S7|CR8mfppL#W7WWQzx@v!D za}hhUuX6Bmfrq-xX%2Do!d%(GD2!cbiSvRUK!vbDt3d(0)OFxrFLU|91TdFREQ_0T zQ8UDdV*9yw*XznGG9wMd=e>Z!|E!3c>`-lYof_X3#@yIZA}qg@ZJbRy&wjBD@3deo z`~A$NFedj^eg7|6gQO=1x|KIn7+lAUbiuKzo_P`d3*e7r)Jc)`Fvouv=5M7=x|B5R zI@rGZ=~Rc_NRZuQVEC3E(X{3++oSR28oFBHKM~(Hv}#x~d7+w;Ut+(jDZg zLj6=$!71;q6{bozJs3vM6)*2}`_2`UjFC2MCHyR$&VGwK4LL~z<*002oY0DF#@kBD zA2^KV*%0h(2a(lQhyf6UlV5izFaFYcgolcVOD;C3S$0K!2HzXSr|3A>A!Qqf1+oo# z(>WU_G4-fEk}n-q5zBfK>uq)io3m-jFB}~*009&2`lpmHVfjPcz!&|xM(A3xVGkpl zC!MLAQJxoM>1*xJ+UpwIUDCif$}DWgLFd!+t5AccV{B*#EwBfx(vM%u7B*|Y<)-5{ zhP_I%D($~>Q%Ux!uxf3tm|hsaI}s3(x=K~g>cu|1?n8BKwE2Fo18&I-C}o`vtCOk@KcW{IbLRY*E8kB5YW>8~L-w?IwEQEfhq zUY{|5Q1w-?KGh`T@hJl@9Y)-&ENvQDA?L7gmVh69lR0!u4Fb%PB}{dJUKRx;-{f^0716 zrvT=K6f0lh-0khUi7l0aWAn3-dXOhFy=p6@1Ug|pu~wp@_9>?qx!WR z!Shp(r$;aL0Z!S^pwC6Z#lS6EXm)e+ki3i9J`Y&T=}M`0N5JP8!uy}TJ$mVN9tX^R zMcoqcRogrWZWm6)1$okF{KtM*TB3?CZU4%0J`{N0BDQ*=x^7!|_n%>Uub9qNR%z!wDflS&>h#hUWk*+OxM-Fe=pbZmeTn2)Q z&1^>?<5Q*{v@_YFxixkh*yVf&v>Lf;soY#m*J#?P60GM&dK^te8?u?1_tvz_$$ z5Au0RS!eu<&jN0e+#h$<4eMl)A5OO0cO9r(%@X5q9B|g8orb7#Ec~Lwn6~=~HJ;v&IQG$0D5e?T1u?`VWf207J*t9FLdj z=Xem{TbR(Eq)`qs_X!T?2~&hUzhx&YFsDgG|4F+-{MYHgr;J+ovma&G=ki#fr$%mS zW?A1HIT>~5Yyz1ZD7NaN9W=k1=G1d$h6zeZ`({derP>82!6p4J__=a>JB*=yTBB|T zJh7vshU~lBDTcc_Uc8N}H{=DgumZa3dTq|;HmNuhP->GBsHc)Y`t7ugoxDCu4kfLZRIqiHmkiU>v-k`mG&>lnk6jENMxi?+8U*y-cimEc z+nol!(b?ZyJ2N`f=C=&j0w4|cgAKkB2Q<>E?={!fBxUO+YQIx$Y9sc)%UIPSNA4*+LBo{;sx?tUJf{ z{VRLCt+YxavGzj&LfQnBdbr`C65-^|ZFwMw=k4FG67g4*@}AfolbxgqWI&2wSCE3B zR$t<|JhH(q*sb%iTx72Xut5WBeyeM=cj`ja&^}lH*>*fS6~J$E>F%ga*b92I!_f@HBGr_iP^-UC^U8hTdy!um^l( zKBTXLmj-D?gwrW;H8H2!WHwz0k28ZZvsS-;P=BodPlL2G{8BZCddT1aQoJwp;2lpD zi_kKhq=9=;+{c{mqgoxrTDLQ!Tqq2?sdhu%?timmyWSzwSN$i8EFqW z;_`Bhgty8nUzDyr{8DwT_U5nnt`}nvN*0~{4|KBkXFMwEkWU&rSEDnXJ6uKEThplI zb=8S#wRtcnH4AagMBe>vgr2Gji3Y=QAjHv9WEQK7)*k zf^q2hsO>5xLLRAUNMjjd2AP-#occvC6g6!hJp=%CT=fSTGg?-K2rosyE`J&@y9B(N zrBNw;yLT88?g}BCFA7syOLKD^>K;owCijyW~ z_{SpoXEaOf`#--ZDAOD1VlGWby|fY-mdP#Y?wiz@^$2UASeMJX9s)yHtv_KMH|Za{WVq} zW(WJ78LOXBhAf}<0l!@tBLw(8J95sgsFu~DfAEx0r`ER7^p*atTPuqwI4qa`!&H0$ zBvUK|jx4n2-&ek5z&CZwan%tSD73!ihTnV?YLw9o!A+fAw8|F+2PPfOgdb_T^iu+* z23I8Zvq?j$8T#M!UsnIyb+I|864A7#_RmG{pG8zFg&yo2BxNUy zVo^AfR;2t_5$nf+4l+vN_nU^*VnmAfi<&ZSDP*U6y?Slj#f2+I_?^DXVPU*oo3AsHPA*|Q$&M>l0M+MKIFDp z7?UpLZ^Nqr``0Dp|3-eE?75l(^SCmE624Luq-v7;hxnqT4@$RC#i8XM3%Mx-5D<7c zi^KY6_|2%3Fln(-SGzaTsF~_XDX24B_|A7RMJ`?xqeCfwJBw?9o@>O!RBd|09F#fN z;A-ijlpFc90$3}q7tiq`s@GG%Mh@B5k%>%a^tZF9k=e6nMYD7$w)Evyi%<)Gn-Hv9 zVDd+r)z}!2lz@`{h-km4*i7Mv79ebeMb-=*7lVowMZ0A!MwJI9D|WZm`>)wNtRArM zjh0ov5LaN~J*9g4U?9?a-zeTr1wcyaf*fju0y1=>jK8f*^II1LT@C0@&wbBa5F!Au z&)Hh*pI_PmA8{uxgbOTd+C#XF0F{$d`b+fSMsJvdFplWw7XEDc^Ov;yh40>E1M>Cb zqR`H~h!9sJ`yc8I-N8iGt9reC^IJCerMR{3V70oS6b2klxwZ5hScH^458VFN@b zb#UW1o}cmw`@C&~3cHuL(@Po$LVzDcX4eK%)BoAwaY5JPwZ{)#Bjt+d&tCi02d4%m zR{)gmki4qcFd!EpkQ}pkdFKe>UYqm%Z>0Fb%*oSbFW!CMfB61**t_djr!P~IX0xmK zRpi{(KeV~U3A@o_UD(l@&__TC*V*c~_NnAt*xDQprncfZVSPTvgGC?`C$_q3w;1cp6aDrKeu}3!e&ILV=lvGZlALUpF~3^PCm&>bBp=<%?J0>)@r```v^NUuJ@B;&)lF?qr07BL$kC+ zKJUF61?uy*&WrXsXe|{Z{sD%shT%S9zR(9^UpmIJ&Qx_qZrJ7D!i03L3a4SBBY+Y< z=(A49?oW7GpxNOay#p(7AWVGtE@|-moYnE|S482KbaR?nbQ1$U?+Th#0_KhrruVvl zGKZ^Xsdl3^v^$)m-Kg})?20z&HCbnKpE?KDA%?_nn$v>5te>wkngxU=z>^ijmpE@aie~f`iCY0Ws&05^uQN19aTx403 z+rB3`b(GA{MC*@=4$*|)fEVq|@FWUICk!J{N5-t5KIqzP&1J$(4Qk?P2TA`%1~`;G=xhQ>Pg5boj_B`9SI5 ztNs)aZcjVMvB0sIUtsf9>P2h{5cSMe2u!v3eb@s;KQvZ6BOOde5~*<4*yK*=({Ki^ z*E-0-Fq=C}jof<6`q7_U8D2Gv;Z$Qb#{~QZjqgzQL5I5d%Oss;xrRRLNK>brkJ8PS zZ~izigJb-UsCS93V#J`B!G!9QfcQ*hA_YZ1X4^{C#^=w4P5sh8sKYxKDVcp zN{2L@G=h$+U%zL5ze(2L{`irHW0K?1%lCIc*DtHvcxW&-_;6s@y9D`CW z|FrFS{YlGl=&w{$d{ljRSUCO6h01m5uXRk^le*xB7S{&>Po#xl6`wSrTu`C)@9v;i z4LY1u z=4MTtXL3dzenp=k&rgt8MeH@wkDurlT%Gk6}hgm2!uF4sD_S zHJpO&eIFtIRT*ZSr1|7hDCfiNLE+-%$2AUlcyrIX(-2xWY$^TMu57FuHZL`0t~qheMN4fBO+8cFuMiC{c)F_e=`Zzp{>ZJ*o$3aj#4Yye(w@bxX(?m@ zh4}kfP4D*DhlbO`w9}UwFyCtiYqQckRClv^8^_&|Up!$iHF>+|8@87ot3mL0{a-mo$}k%`5;s__+0Xw8DNeb{K8juei* zH4w4#R%v!Han1Ka58e8gUN6Z3!{w`M~2+-Y>wnovhgd*U8Orw4G2KZ5ggXX(%pC&)B~gHsDbns zQk<2*u>!;v1?=b%0k{U_dUFs(cMMey{rUvSE+YN+>|WU!Lw8H>bCBBjACLjD@QbIu}=c@p2RS1Fl8IC9`f zV}Q+bc;7omviFqEJhd@oHHZ6uyqeydl)R23vKHdxZYd+foJ0=>VO6L`>ill=2Qh`h z8*{Y1_XT)4%UxTx-`&pr?*BOu{lrSlFmL{b(Dsq4u%1)&qnK}<40z8wG5GNf@T?vc zMgsH$%-vg{A!&byK=Edq1}8~4JHiv9Izmds=k-m>!T3kg2Wn`|%2f?Mhqon>pnfbr zVeaG5=eOaJ5gUtJ1abO`Wxakah&!p!a$sNHEq{d&oMeD6A`S{zlQ9 zYfFWafxERxV%6Dw5Y_sHshcNrvHpvy_hzpp{{$S@8izrnYw*<$uU?^#VprO%0}0hR zZ{4>O7z=QxO`ZEY9*_!MY^rk2DGEl=cv|QM>vu$jf@+9xUX$iK99w&>+8JEI_VQGL zmh|gQ3lelLWf1iqduf#L(dCxyvy0~lQYJd@epggm8eN`vARc#D?J>s-FHY6N>a5}g z5=xfs!Ly==7A-D=QDZm~xzV-oAmU1O@;QdN_NS<~LtsrQseu?Pf}Zo>$KS@rAhzb1 zox5a&ewnAD^Hg}qqM!=D55Ddq!rffz#KS_*NP3EmB>9F>BE*IrA9|}(hUSJMFi3E& zy8t#uNa3x22y~_t<%gIkWw^!KG(9{_oEulyQU9IlEb>xi%}R&ZQ#ZGw{mT zj<#)O5+Eq#ySQ>A*;Q$xMQ_1Q0SBnsH$6Y*N><8}&YbRSyFnpO#Xr+Vkc|hB7i+~t zyGh&niDnUXdL^TCp!wj!1+}eG09k=a5&ts@FW*e%?CdI&`L)^H~*`K;%YaLkYXuJ z0hPuF?on5O1b_3!KPcsH;Uq1$$~Hhh^RDR+l*5X0*(&{o$3!Ns?tBxFK9S$w`6h8& z)o5YN&|$G^q?HO*Fu!R2V6s)%850-+F@I*JqdqD38QnD`qZhaw7BHal9Dw=6ha6Kh zUYNgs9PY3a(kjYjB>tQd=FWH2f)|6XWblErqB=@oJiaF?g*QF-);*gj468Lg%0B9b zx0I9=t~JWrL>jR%g<0rC7VBEK#i_O%>qOdI=fxe)(Gm*!6%#=$bi>Db8f+s2LgH-I z{6ND5!G;-%%v_IK<3PtDGzikTr<`B2w8wdZ^&}&?BPHm1TQ6re69O_@ZVeO4as8X| z9(Ao`F2OwIzg3dW$6>>-{eo*=|MHohOu@qRUYNGelSHut_<~oDK~W6X_}QHt zE}gx2tsf-U^O2qqPEoEbsS}8`J0%AAoilt!5n=TJLNZaJeb{SBwI}2N-hYwk&2r25 zRW;GASw0Q;Ga&+|?~_2!L5>@L74XUD-F4Go8h~-z6(^g}^9~YuhC*Dzb6D+6Uu=3(w~6UOAM-gt6^9 zW&8@a`Y*0lJkam5ol6=%w*U?l8SvcZ45Qx<_*44jowId51uF2g^d~Tie0XRSck@E! zNJR+PTy)&UGxRoIZxI_kVRya?@~Z@Hvxw=R$ey3LwGv2rLmm^wH{4qjwK36um2o^v zhIeDR9%$^e96c=aKfDn*Y{KFu&N8E9IJ^(N7;&;v_A;**&aNuoT=-?P&1K3uR@Xq=$HjTcZ8`mz3Mx&!PdCGigshKx1% zgqWBH^=44Xy5^-{eShMh4i9CC@pXRyS}Dk$@ffqOgJe5`?QVS_v??Lf66c8y_e{dj zKU_Y4knNv@S#$(vyC;>0vY;?Oxe!s}JFUdbJ|v6^dA-7YQlXD99nT==5`O=MJ}SRj zq~@^t(KMuGmmKRC+t(hmBI@JgX$u#*9G0VdutBWWIO#$7TZZJ%dvbqPqWM2JuQzTO z;BI=5GEp8Qt<$>MU~+T&YDQL0FJ*RJ+54Pes+0IV^{ghV7H(bk19YHmiR7ce)^320k&nSF>6pvN~!+yw#xE5sxI1Lk4DnY8k2AMr@SP>pK9Vr^!1V)=vU^B&m*4YxEyrUeG&`U5{ zIl*LWb=Lu&dkIjU!7%wef~`g@7?2yGOf_P2fMiJjM}9NMci6D^WBm9A+9!wFb5_QF zb2{@{2WmOZk|TFm(C$pw&;&mZfITn_!{}Brqy-DQK^)ycfkj{YXxXJp8M`yV_b9Mx zOf@Adic2c!!pA$)*TCH)D4YvZ{Wu3gdZLgYn$ho01_-fs2_Jq8g%qrGeN#dI44(Ps zoZa_i(0eJshY_Iu%ON=jW@|tEg-gtd^uW)(RmE}do*hnS_zwlR2moT2z@xN-secA1 zo;XXDBD6Y|TSS)-*5t0Rt*rY0hg<{5kDV2H{FIY^d?J)&{iEv+%h;EzfwVy_(rSx0 zQ{zS{mH{0s=)!-`Y?eJ>i2;7_AM%bkx|5=&A`1C1cmQ=_gb5$J5k897OF zse+q7RDSYHKDLcPwv7`p?WHKueNHFdPw@H0-M&R6k)KrTlW!_xEWxuvZ$m=5-fZ4^ zG2{7g+yQQNwU*W&<|}5771u85WX=Kv!JUHf3EGi~F`mgm0N zDvNwhEX)HzsFm-Z{J2=ZwIRWFO zHplhFA%m;!bv$Ri1C4l;QUd0hF_LfF*|_q888HN$He3KU{0Q{KkPB55fftxp>m4Aa zG;vLpBM1iwNh39lXw%2TV0xeT-qU2ODxX?whmz@&yCNWJz}}u$3siQAPv>X`GVi(4 zjQ{6DOaNQ<<3i1JAj=@wS(yYZjc4vECKVjyAu&kz4ez<&5q`p`Wq0&ME z43$;Lw_SI#83E|F=in-J%u8qO40bK=6*9z#?f}H89%dQ*a`N})x9n`-z24;gv4|Ve z>f6639z)jO3tv%l;_AtN22JnXcvr(jZuKO5=*uwm7|qlDH3M%yk=B+S@E-RS)gm-c zvhV|7Jg8EioxES_K^)qa3lOWLFE+7HFVjq(N(5_u;poWevvKo#%eb)48FRiNK-A^* zi|0uHby(#;TgsO&^WsP|;9cm3ieDHjf*V^KXpa$NoEiSOYI3~wW?}_wlLz8RWLo$=V|4iQBKX&FigIep#)YHFQKagsh zS~tz9W?4K6Go`gS+%(M@1vfS21Ut$;d!AmsGo401^ITq}b7f9EGjCp-P%xM5Zh8F^ zO1shfgjua#JUCV5d#=vs_E8^mFhLy?`iZXJ*aw$m)V^ z>UopK@*zD|y43CF+gvF!@7Gkj)1A00`pxDN2t{y#ljhl$uDM4 zp!=mXeHWlVBkd>9$d(kCu`+;o^A_nl+47=#VcOlaL2EZFNXPi{0v}q@Ptk1p^xG>; zW*vl#HKxiqC=ub)Xoi>V7cR{!oz-|_sY(6mU7F^!fwd+qUw?EURy`AdUsD#NI&DAx z<-Dhyt8iR-cB0ATMs%Q)UPmw8$SpVqI%uxTZlo*f8jue8JQH`5@cuaoIr!#j(T`fp z=p(RE-UI|zZ(nBGriOYrK_kd2H+4?2Mm0eL`syr22(f_oS!ys3YO=rkTB> zyGCzOXyH6LVniWfl}Z1VVH&abbi4ktt^DBRHTK;JQW2={O-#<^%!Wkr!9P97#_}Q# z%6O8xxM?UtN>w9GxN*NU36NB__t!;|ZE+{y*xr1|cA2v|39!~=#KVck>-@=>4s1NB z(upF$dKU;K81qg)g^dXod=!Eh@gf4-C>g?-h#_bOil|gQ2sQpt5rugk4Lc?zz_G&C zhzB=fMqXclO{`%E$tTp2S=^bMbYmegu=nsX%oip|U8Hn&#hv2r;E|<`Iia!vavaI^ zz0F%OpC6H#b@h?s68cgoiR)}&g6?2X+gJKl5^&;hjq*+&0ZXlx^pA{go_*p!v*y=8 z203I>pPqRy+NIdr_N8R0yqQBiqEq|3}-z5EVHF0>}p|2k< zUN-bn!9pK{8KJ8@ z8+p(RYr_Hm|7%0Nc*w2x>_h^xANI{f?DKnw2e`pZY4Z)kX6m-0|rxP&&40W41_o*Za5$Gno$|1I}tT_ZP&CKgcjWJ4wrjq&O7~z@C&VZ_xfornf>$PVsdKLCSpl z8`6wq#HbFSZ<^ZDIu$}Jc={{09duupE~7T44e^HJx$~?9hbEy!2UfM1Y=eF(&2Zm` zpmY#@AisT~DxH{l{lgg((_z`;hxm<*nR~)%1a)8fX}Ie5{lA9a-P$$0D&JWbJ)o4IKi?2budWnML4@`+WQ#?s+~X`&_^c#_9T4VznYTRiW4xa+{$YxtbS z4L4$^$=EXd$;ouIU-?Piyacfk>~!_(HplWg<+4QRi3=m?YacwOnO(@ofpW<7_!f0N}gdCC^hiWLaNUNkYsG{ipnLcx1o<75Y&uY)!P1c ztxe_i{X<4~zYMxYlL>IvlHo4KL@bXNrdIFbCv z(Ju9OA4Kx_p!jW7$;Vj}4(n6+XKeSq6LgePluo0zT&=VEGaV9?yFI6McJphF^p;s) z;HFH^Nj7H48lUJJO%rY{VNx>K{NBaodANqss(d-&t+gU(p406v=xz>A)ahpTlPMOe>^c$)^z16;-aNZr;}m`qUZ{GFe}?e8$EEm^^NT`!`N~GDIk)+?sQLC( z>2%FWO@Q!o8sjo28hdkMV^_rT~^*BG}>Zh z)*om}joW3(tRGx*uN&r?nFs-hGj@TfI<@PO5uQYy_+2!YqOT6{-Z8WeTs+U#0N4Y* z%79QW`HrJ-z1_!?I0mf#u86^S#CjIM6x5!mPa0^7o$E_`?)FHjTN5njG*GiPvN)$KZF;P?lQ6rB| zIWi6=0y2G9Qf&4x;{M)D|1D|~25}8o?XLpg*y$=~_>0V>PR*X`S9$BBmw!Vxh1u;#=1ZACgWIk+t|oM5YBk~rctX3v+IgLIg}jdJ z`Tlov{io%%zt2$Y#07wlv4FBio8hky%V~{1~VB}o19k#+JKg&VW;pV{fy6pnEse~B4fMT&#Bz4>&op))*|;rpOGD(JI9!Xqs&K!->ve$GkyPP7uui6*VIN$Ctkl%wHf;+vBGcL ztu5;Ko4%DnZ^Ps33ES>PAMk>0^hV*l;`V+}SU)>!b6{74H#lt{8QY#bB_^Mxu}MU8 z%o$Gk&leaRH6i$GulPZ&x)l~3>0&BMpU^C#i=P$$Tm*pQ^H}^MgPM4d#A*&K|hE0QR&y9icDdH)d~(Z=YmP&&%8)Ir=gjuw0kXv`G7V`@o`mD!NX0t`F z`uOv*J=EQ7P0GV{APRAj=mVSH&FK_-E zofU)d%+wrso?MHo+iG^7Wnwsq0O^H1zrE#ln(|0Gk1HmqCRSENkYT=o#n!CZ=Oy9H zQ1Orx=q7mFre5(Vc!t)EiE&>T7dstE7p;x3hhk~+(4py>q8xUKl+GLFywXbOOqP{> zL>Q6rr8lUFNhh8KbBX|@vuux+(ev+vk7p{-ts$!x0o*Iizs_%~J&bjIsH4c9BC6BG z)b;ljA$@!6GlhFqm#ZL!>E|Zlk0-Bt5ZX38(MTw5c(@N}fS~Ikb-SWY^Pjs2)GP_q ztXoSGw+};!G|`M?f}uTK@aQ!HQM9w+XOHl7P}YMe&BKO1T(c@*mf`*HERVHGKt_g1 zp~n&{|0#zuae>T*^eDC!D-}R+6 zNQSi`bqEfQSZ)$v#t-^{qaK$jC>I*&i+y|QILGie_^p$xJKZ_GQEdb~I%4trC0U08 z{fovRyl>fD;ukQ~pp7?r1$5@;X4=5?qu{;u<2A(T>Qxt4{-LZ^+})3-;f9lYGC5jE znP<70{Q9nW`udUOWao_Gv|00+3~tsPMb&*DLIBAmIZH=hWSUMiv02ip5Es=T02zMw z-$BeTF2%Oe=5Jr`e;R8ESBeQ=B1A0P(1H|lvPdubiNUW25Au)K#q1D%LlYm6j#J#< z3}zHuXPC9_E0!i*k_{5MEwk}6@JD-5D&Sd(B^m`(n+xCSchefaay3auy-&L&H(0y0 zIG_T|kG{)T;N2S>(5--B<*oiBr{mI+tmQE^nd?}cU8+9AuV{3rk#+DQLQzL}jF6Mc zUMa`I8ZT>+vMBdv+k%)A7_hTDoh;|O3XPa)O=?fm)8LfVT(!NQ)R8lq)M!kx+Ansp zgg~0OpCv~sw?a=fi21DImgyv|U;IX^#R{y`nFi3jduJm8=_J)O1`Mu_!H`Mv4hW1B z$Pn;CtQD(euigO{6@S#_y~+^q*rL_eZL-s?DOH!W;_b#Kjque_FMijQ3`PrqgW56q zC zR$%)|vc!GzT+yLcLCR6cqL|w@bhS z1}T24|4ssTdYf27mU?7X9QHUA8ufDh()QU3A!16F`d+D}>S4_-@bQu$stzdj^gw(x zx9s-4!+kyiJZYbP465lCx8N^TNnC>(c!m`c*&0Dj0E)USyJIXg`%_9wn4xOZ-_`7Q zQ93Dk#>@GrQEO06_}x$DIolL7M@Fax0(7@|4jG+~t;B+@f>-R?&#oQuz#bBSK|u^7g!(+r&~!C3E7+ME%!J9uVThsD>ZkhirPnvdn1^ z-T8;{pTa6foYcK1NC;QLRg&nJ?=RXAN?jaq4thPody=b`hTcZmt)4p)U|n;8bO|<* zw#KoGzpO{6x6gMpi69ANOFKlzdqfa}vM-N1l|fNVi=(A{LIV}JAQVx~^tA=(gwWWI zpK^?RdW_00yLptIU{?J6Q00mEHLr9#PhV7i((*ZY(uU=Saq4_1p+oqGuppGD`Y*#1xQsGsP9UWPqzi;HKIQSK{JKgCDn0rX&gnRh%#P=T2BJrYx8t^Q<0vrg7cd24xg5FdM&y5NIg-1 z(fclI{EGOTAVpB8Ep@_F0ZUOe%_84NrUW;~xZ-LWQF@`c6>*2S{A!^1CruAh>(Fr4 z+Yrjq@7?Oo3tGp!fF~edWg3^*GeR@vx4Zds$WBX_bYL~d5SioySsnFX9;>lN=Z@7g zz>EVS2&3}=tzehiD07Y#U{VL|8~E60+UCAA8l&30kt-) z&Empj0evo}JEmz?5Yn^%Bd)t%H8Z#b=FWd~&l^y^V{HT=vI@OuyN@`@@QLpRj`z-; zw*wGdK1J^ziQ4C@fw9(+E^wzxRtkLXFKeHz9WZ`C5>H*wX^a}D_-25a$K+}!HXjD` zvkr7U2tnU4C5iHZQ>~fOSNb0K-5$W&V4H5yQ&Z3iosq(t09Fz?3R45Ba}l6+n&|EY zio)iuzBc z<4YpTs6k|lRMVz~#M=JG*Mgb5e1+9cS;4&)QZGTr*$xm|b=x40_2o2y=Ai?sV{WE2 z0i$IY^WV%Put8XOGWCs^S7sCS4?7E)n}Yk^162fg#y(?l#g`)Z3d@yqGD&UR+G;Cx zq?O^yC^&+pmufSl_YlD3c8foJgc=DlfqF)1bjkin&^a%|L)i7ams#tn4r(-uDo+-8 zImLouBT9dVVCTP?V(*@4;0{<99cS<4?*+%g7I*R6p#uS5XAu`}4B$ z&xE*em|H7$oGI=}`)50{kbAoO^g=)U97uptmlUMkg(eBh5Sih$=WD(3ETp|#A_Kr8 zz$?X~mkEEbHpf%$migLcGD=dqXXC_d1upG?WC8E$=wD+Gob^~I82!?Lp)+t_$ym!5 z%4%*+lUY8LXX^g4z;>rX`2L{3Li`P58m5)ogW~wrH!Y_HktJTiw5ngrvR%4HZ;EuW z=X+kX^o7$2gIj{DulcafbAvnXXW zH1&3pC0K8Ih6rYjdbdNf@=<^FeCM8G&XD-84@0w5B^av6Rt63Uc(ILfK(Q#p(>{;m z{u#2*fpl$QW7ThmiO;zc!w9g}eH@B)M}D0SkLqTQtHS$rLu3s@WFLe?mI;+Kcr~u% z8hj-U{!04zEB%8lGP-zlYgceb4bq?L#GmSezm)IPlZMdx5l`uKCsA?cFQdQjpl_Jh zdf!q-X7moCqEb#&hHze^8$o|k`1E;-X>#)9bMlT}j6VK)`Q(0f`TzPUS{V(=$@-$x z(@vnDT^?&9+IwR7DRT2ZJ(tO2Kz=@WxNtj*%q7(+zxmyo*$;=F@A@##5?EVhI_WD< z@_Pw<5ShS}7O{tZIa*qGi<`SJG131L$;=VPT$va>P!re?&J`Eb0VOlhs)q*0iwQ?e zkI#~bYLHq(Jr^2ngJjjX$iLSI^vZ^p+m>CHObl2<1A!Q{C%1b)-nAKc&%e?KuRJ4Z zdY5-xpbyp4%bpfZE$lok&qgW2;j!~39pxiPZ7<^%yL}n-rM}n|Ao}S zx){Zw2hSfd8>TFz40Aq-hacX^)j~<;dnMkp2>EUgG@gz{G1M3E zY-|+c7YMJx?lPGfh~ndR@}8jg^af7Nr|UonrK>p^hJEw~vsfp7OZHiF>Z?F6ZiofT zu3~$q28t538{b5VjgYSwtwMOxNefw^y&v{9o2JiiI#f1$02FJ4ENyedkLXhX6;t&r4{QH;jf zWkoCG1@yyWP*dQ0Hfxlx)H4w3LcP1yAQ`C=jVWz~B=D0^+dfa|4&{-pgwS$RahCk| z=PkXDuTyHJLI_%Xr|?5mhyR)VkEnvN2jaYKnj_)=v0co@gX@;Lqw#oZgu=a)Av+r7 zEwS_ht$MAgckeOJfjXb)Y@F{E!VhSu$RUhm$$MA|<@yra9Sd-5rkeon1?$VZe=1@e zl5+o~RXaRVOLAE9%it|rG&p<{-F}WlMY#&hoiO_R;42X{QPD}SUX#;qAZ2gi_*2_r zicuPz`MdN`q^;e?w(-|VMqnn{o*Crhjqe^kkX@LfgZqC79iDaIEYW*g=*KRM}O68A5OwcjEh2z-8oZGgzErFG|vV zRAxr6;qCB|v05i@%MEGYkn#Ug%u)d-A?}acfoRX~z~lq*HcqD_lF?a9&tL)0m{Hu{ zMaS=x2TNZ_NgN(1^ScL%t2`1X$EbjuPS%vPtv6djt$S_XhO(6q-=4)PWBFDtc|%$V z;~a3U{^&5WZJ85}Rjyiqm*0)Yxp{X{9~IDF?3aWW6hqDJ%`$!I#XoCH>8)=g9NM9I z3f%dA*^m@lv(^ryh>rMt@;n{mFpg-JekZ96g;Zi4x!sLvr-PSnQi9e(@Hi=xLR<|{e++?n5hvX#{CvdkfK&_WXCKLAoy8h;``kZ!uGJ)SOo zkz6M;)In(FIzi;!&CB3)A!{k|t3^1jSoXu+W7f)|M_h{^0OzH)0!k>KIE&P_k^ad~ zgTq57!jR=caD4s|kI?z1CK{fK`7#bZq#6&esC(`g&r$c^A0O#gP9`$eVr_922Qs?C z(_zLw#nO?QkO@zIz>g!bb(ul^!<|2CwuLT@etRq*7By?&jdmnhCnylm zuT=i_FCr`*w`hBc(k}j~o1M|MAws{qtXHnrB^uqFksbo9K;)5(T0s%N%qDw>HOj~9 z!`Z~oz;u?aw7iO=jvo~IE}^;cjfkd`$}_>}u#@qz-R%)disPAde^sn#z&;BKKk}XN&AcSlQRjkE_(DoGv$; znx(OA1x=D;zD&7OTukiu%ah&fzhs)S-8VX+R9lxwq}AJ#QVIAt)M&ta*uiruX1Hyk z=Nc<=D#qXP<>l9{Yf8gs$;3TL?s6ny17CjpC?#3=Iyl!@(4aTQ*T`&eqcRBp5jI70 z@-9C!voKo3l7Lf+K(>t#USc7^Q-2O^UE0ey-T!h*a+jlNLrr-m8Qei`O*?bxS1O0` z<3F)8|BTh+?|;e`_Oonsi3=i-R?jiKga@))!w)HA@B>YHXAcj`WDY zbxg}u$o}at9qH{#$2@&?O?7b$*jAnlE(dFM;Xx^;?z2NyhTab*3b6vURl%gyPM6%J>f&61gM*eg|-hmMwAHy|{E|L!E4zG-i6E8Tti3X>X?)NAW^7F8kL z@L7D!m49dxp`yE&N}!iTHWR!E<{y($$DOhF%gZlgr0-9yhProINj`P8p|E|M`+VD- z2kg!z=x%!2maPLa!8V%0ylBF*peFhz=i8DBn0^5agLrUj&*vE!tN zk4v#N9_CIp5Ek+;J^C->yZj>?yGrvD?qVnkYXN~7cE{SjgZXc07VX34dgEdCztpHh z^FhZSh#+QUmpvs+7w#a`w*y*L8B)4>#yIv6jhnj#AdLg(8wtCEzaJ{C)VK3Pvi}+1 zk@>d2ox|-zzkv|rgds#xzwJAF8@`mNhE_M&Yl$0FHFuYb^oilcS`S;tWCoV_AQlBL zZ^WQ>i=E)F1~T#$Vls^rH+gZBcyWTc1%u1@NRNx`@iRnn4j?_@w<-q(^!+J~$2%M8|A;)KPv1w1UGEfCm)y z;bJ+5`bXCT>Q952hRb|L2F2qEAtH1614}&AKjF@Spj3jz;SWc3=ScS#Wc{(+taL*M ziNP`zJ?@f!rPY|cq=!Pkn;?2(Y9{{vCOvfsWTxU|9LsNmE{)}rHL&y*@4lQ=>B^rf z!q(sZ{nm5tY0>Iy#7Y-!*A5$Fi0loJr;dAxlZrP!*f`nBsN$1)ny|Wt_)vMK4jO*2 zuhTj5J!dzWG~D>`8_1x?CmK-bB!l_@>qB^nCrhFy))u`BA|qJ51M^*A2Tv8~A9TlJ z?s$=fuy&e%>sjr&?$r)rJ+ zjOM?Bz$-ljhxJ)z#cy7Ix2G>-tk0`FvjFi{s=E>;1Fr0z@XT^a%>dXpfE|~^b{{|1 z!c({hBnUzoJs1q8q;mjA9Em5Nkus7UQ}zdN;c9#GMK8(}+n(=&JPER5!e`wPUW0~H z#iR^;`mYPi%I6;*I_bFf68F*Nm_Dyuz55BO$kp)M=y0b2AN(J=L4-OG>yh*oQG1o0 zlK+MUJ0)iUB|CMWzp(0g8NG1`WyD*oIjur#0e3dU+1t@pGm+3kL=9f;^j$hV;9pkC zg$1-<=xvxy&(HhRKV1Cu#xV@lDChz%pY0QX6JW=~P^J^0_+{>Tv`4STiQ7@yp+Opu z3pK4YBdiB7I85(2h5ly%Dav92!hH$wO;5V5WP7eHRtAC6UecuwE=yvb)sVnCEy6Ul z3`Yn0&Y`fI6>r3A@GFayX%2(K&T}aD4IEkiJAyFe??Z4@mtu4vXjrpRC8c~ff^cLi zlbbmx1hfarU{ZaVPwGwH`(MqOH=-A=8s!)5o*hlJB|gcwdU+Hb{gCuA{Y&aRF;C9^pa~uLRKM=F;6K(AstxN}nPkMb)P_;=t7*5r=08)Z? zE?lmrJ^{yA&k2^VVV-}VpyVG$oPl{at->BJ9xi|KivpiD2X9pGWk~JYEx>P<_Jfy8 zRWGur%hxBMF!##U{-a1+HC;nV{eSTko3WLmhzX6tGP^j1V`v6r+*QoTYB=KVf?uM_ ztp=G#CSNMs0@r(y>P_ z`iwkOD11WCKn2Ku!3i~cw;)oLVGvnN4d}^h+Z$5w@wOcJr61vAN=%LFdbb>yDoTg? z=bc2`nM825k{{%A~8!wb_piy#c*oUu@24K9^b3H!(D(uv(#+z&JBu%tf4#Ep9|o^{ ztX@mN1I%{1>dc?eo~FF!fM_mlo*@aJFf(bqDL7bab}WcU{Fm^J?*3*0B$ivgQC)tvVpQ?ZK4IHtTc<$wW1aYryegfQwUoA}qpJ>x>gl2?jesH{B`Mt<5Tqi@JV1j{)5?*<4w-jPxHuPIT=<|FqTbg{O6{jcL(H_&9$ z<5NVNGi#S!-aD*SZ`LlGym$ZQ`n>B}pzbw5zMzy>Ve?-DQ5UNQ9_PKgTZ{{a_T%Y@ zgo>cpAhnH+P*4(Bn07wB{P)pU#5=>{FVV8k!rs1(g*Rk&y|So0{{*P(v;ha#2bIO> z$9H!$@g|hlI*UJ#|Fvc@Bp{ab(fw^OukaAV`x8oZ`gho#w*U2NQR%k@QI_@Uoe3Z{ zJEMIQepCvSQ#wJDI_XFExb!{Nn7L1Qnc?X(7`lM z>qM{5pb&y#{KFS$H1qXA-zPLjKh|?|8vpnQLj;ebW3mE@8onx(T%fNK=i%a4|4Jhq z0zy~+;YPhoCLCfJ3l$8tU&j>$G=>p*7;{z9yA+9j^3@^t$G%jV!m4z4ZnybpbA;V1KU_6n?D zuMw>WkQsH)i^dA^x5V10g7w5`;>Fs(uIDqq(nc{}UhiV+%E`mUVpGE)e~LCfqW}l? zi_v^-yO9rsSD+gcd=--|grleW&H9vgK~oLDCK|uZYO%2yBim6TXZ$h0j(zP(Ir-8R z{@;WFipz9qs(B9&0(xiEmFHPg9H?f3>dDju5DwC^E{nC}R_H(L*9vDlVET_cLUiqWuW3tv5s5TiY}Ch(U@qQdT2YlzZ1&* z3Z4Hf8b|1P`)z|u6xo*yb|voFQ#)2r6mY_fwRPkvrhl*bADMR(KTRZjtcnj%ZwR9I z%1lfKIJU6pxrzSaH^9@9=XfmeEuQ*M72qj z%gdkLe2MP7V*(d*kcU2qCfQ+U`#YlttO5Mq@JZx2^xid0sYn?-o|BJ6LJ*#p)O*o% z93Jn^utcf2nnYgQ55WN*_D``lQYY<^>v^9rwj(EzE79BhzM+2rO>`ttCX$2B)|CQ( zuom2F#EKVF&stkUHf0H;{kXo`0I%DH20@iu;$uoLZW5ZAiR&RM(wOv}M>KB@)wjT8JH|^qdMN5PUqXL zw~4DgesQwlu1ziNW0)AlH*Aig%&y=bQqzIs^6zN*!Pn~z?AHkb5^`TE@tA^U6fLVl zI8pXiJ*@@c+-hyhzxKK)+(XXBD#+(PqwZB?X1Ivi0P}xtY4CfrVpd|?!Mr*RamSP5 zwC#AJyLsDJdKcruoWbkMc77AhhH@}71%JR1TVHNu+b4dQc9TozL|z!Meh-*uIrb4X zk=aPJ3vJ_nuxw@<%z*&kSLyDDlq|OGpu@u3Ul@6K40;vlRqI*rFLs{_*B8ezz8|$x zf33>-6)SvrO7#@wr(UtWc2na37o-2`yqWTnP{N&?dp+!E>FxP3-;EvrBj3}|i(d;L zS4WL5z0lVJl)g(<;-k^l5{i!HwQF>JWk-KO>p~j-<5aKKm?fR0_Eklk3F3>HM+;1bZ&FT`W1V4 zrW%;Y&i>q z?Qh_J9eWmmAGA;%alZDdZD(X**aHsT1;uOh4uasKsR_lGMn4zd(GC1$`a1Zc0o6-; z{m15QX4^j%t(?BV!hToj`o$?v+Cm7xxGASlsAM>P?hZ3~y_<3xuF9>rp9U|COXweYj0M zt)dD`;h*IGZtA}*b?I4Ru8dTsJ3`*PM&dVov#|Yw(R3t%8yhI1!S$D4d z;wE&n@t_xW7Y09ZOvdd4^D}liK4&9Iy6UrC>YS{kg(eY?q{^OZzI{rRl^9EG{e&Of z@sTJoVuR~uSnLVU1w`)nrP0DFxiU$g?~Lb<@lO|C?ADCk-|Qdu!)gIp$BLq|+R{JR zqwnZjD{bks+l#$gg4D}F5)^uWIhFL!rE;$Y0`4(UZqk&pMV2z85>iILU`<1vKHH)t z)rY$y8Zqsk694mhIC$X@&!`Iw{L9z0FXQR2*h#pOGodDg{abYPEV&V%RZFc&=-4O( zR3Vm=w-JezlAZ&jQi0|Y{`Ftid*Mj&FFp&VXC%Y+0o*JdXEys=KW16fv{6{qZ-rt3 zHVbY45E1}hYSiYUzb2@lQz#Z++Ir&y#1NVC9aF>oj{mxm*Tc1JZA2 zMGCL#uj|A5cGEL__1df&TQe+?#QTb~(2xk83Sw=h`lzgrY1_+*KZ92i#f;y46TV{$ zG+^`IH$av>r3weHN;_`ml5t9gLK+rTiunqy3~WMWB4<3?I1>8A&|;Gpi+=H(IqaVT zwD#lkFxJ{T_&eT|%`A;MoTv5~wwLjDB%>I%2-~=%9X!A{e4Fm`nPR^<9fCTCExZ6C zpDT-o^pm_S2O=}+WYyF+v{0y;?fu!qH_KM%g(BR?c}?kF^1X{Fzkjs+dY`);va!>j z)oY7bm`6$Ti#_Cl5=nHd#(6W(w{N)wo3F|7`>~PG1O=}%Uvy8oj`qd)P3!VzMw+p~ zMMd82wynlyq2e5jPJQp2=HyNJH7ZI&>uPMU%J?RXgQi~;=MsH+DyWtDG&xK%J;!Vm zmG^|3!CoZY(=tL(5UUZJY@1=j{HJ(K>+pn}g2Dj=^Y1~_WF+rY6V!&!{*)PR-H^|R zb@@Qu2ck*pd+PWs7t~;N6HMLUZEKs4e$lZv1eH>43^XsguMQ)U$u zU;c=Tr<2pjfQU2%eeucnyFcFEJN%fK5eBjdFFH850r_Pg`KkR$KGJ-?ot_A_&J2@X}T`mPC0ff`SA_v`5dm2`=40)M~01P3iI7A6{hiAM~j^^ zRZqzJgdzIeJ+A$*G|}&9Gg1wB0&gS$%i=hR^@sid`jyDx>Z<1w>FHCKIgryFa5qxm zpBjWO@40c`)7hxj&KI`mPNgHV`WhBzU|_uo030qaXRQGl63^f=^43N@OdI=TGvkS1%Jn4&%&~BQ$_2Vi!1?#VaiTFn!-K4X zx(2RDV8-rn1FHO>^`5oVgiO!d8GlYQR;xVHi6ALz5||bVj*|<&Ng?2!RHYdwt<+6X z9jk%S_w^hcz%Ep2`r)%ZzrFs_D^#za%c&JNO08I1Y89`Y(Tx_y>}$rz;mz=%2(G8< z=-M%sW`NB|B1(Xsluq*yY^g}Y$(NOGntuN7hJ@1tJpL0|GAHwDTIAdo!a4cbIqnlt zigE)T#CpTcF0A?C(~G1lx)rP4KhtP!CWQwhER{KiC)qt_*fbhYC`%-OWQ+6P;;pds1Ko~7T1Ptve?dtr%=ap#xy|qw=uzT{(;$MXI>t9f6RX$8b z!di5pWtQ^~Q=1o?kuY+h*)&ZJtyImL%G|)~A`Qf3sp`!&{+kA9LrX;mtOb^g+cwmL zQD4-%x=Yx$C*80=Sf2fHj%>$03^Du@{?qX zZca;MFFs&n&UtzJA@LvrFUlrg_?TV9w63Y6fk#(MUymME`xAh;q7LEke79a88>yS! zWj&hG;=$sSE`9a5z~ttGm9&?%h7K>ygEMh?NuG+Xo`z5Y?qVB>K1F#+CA@^CTw1F* zFhf+1U}uXSab-0sAUwBp*$ouCH=@%x8y7c{VIE?pQ#vY__cE~Kl)Ztt`PJpOdD^n} zpTS&#P2Z!BCxJ-L@xu`LjG>NqQJTrhj>z6AjiS1$qKvwq+GNYi<1~|H6^7|=OUeU% zq{d-y%NZ(5OE%2+HB_P3J&W>v$1ZWeUDnx4EcCSGRuGjluoH_VXvKHCT&SxV^m3oV zJF%ddSqI@{CoNVV{`!77*=vbpqPr*|&x6zd0O-q;f1KI#zP@%THqD3_Xkw0XH9rS6Oncg(Fe+MhG9qx~q^A=s3CthutxW01J(3Mj`tS=)l_*iRDD-j87Ae-e7x`Gyjp(`$9+$povq>N z7!q_>tLyMS%KH$>E;c!JF?gNQ%d139K}JK6mMl=}>q$`7TvEx(nmcb6eh^QmH8Tr( z2d032Z;9RLX35Yt;QG;F?`vm$-t>@|Dd$FzQgltQ^<|uv_bHXRFFG6Lfennfsuz#%p2|HX>W`8W%7&o*5I%}puRqD3iD4p;FGY~^ z$zLxkr*R9d3R0{7LHb{mr?f#ko@m0B3RXM>dEfWX)o6OJZXaCIwxf%M6`Beo0bP&? zBwm5VEh2Y%0RkjvEDQUn2a044a)}z#OhUNR@Y-N^TgbK5)FM9WB@KU2S%lOqbHtRD z@7KxxG=t0W^{{axc$9Z_5SmH6uu>>%YTu!sEw2uAA0nS6?i0&k$E#xk$3BA3p#aqj z>CRcH@vfSoTf+zCGh-KF3{$Tf&ub9dMm0PNTg~}xFAK}*`b!&zq`ZQ-^+2&PG7GYm zV!&~M%(p|{&$z>R6}{eA>P(da)qpQN zX)F1LERQ;{m?_JBp{c=e)a{Fg`ShP7tbN*&u_{Dz-j1OWAUVNX#(Y}yKwF2-+1CG% zn6vemKe6GPNiPQ#Uu()t`$XsXCO@Q)*+k9pLu>i$GOT(s89YRl@nlQ@k;hR#H(Ied zkAa6(hs2hYUJUQOqaTdRyJ(KY>lm{*eCK%CFghVphpvDabW2x}`|MNIqXAX}5b~r#HxAds z?h%}BLWrc~1QGbBZLaR<$uH5W?J`q8Qi=XK)4%{3W8K5jw?jO*v3YAKptv*t6S3AH zsNZJrZ=*x7&WgJz17N7CPn!<5JG*K}E-Xow{rL5#{14yw#z6b#;?@-E7-X{FCNud1bYuD&xTW!3GE~Bc_eI{>FFi%z zlI%)F(b}2ax9*8kgd|yk&w9^xMM*UulSb2J0yn(3e8P0i3f0Q?zqmSlKP`?cAiRC& z(0LkPTmk~yeO4tGXaO#9b$S*Z#|v8yXlMK?xwWuKcny7pQ(qU-Cor1zMxf5BEWz2# zE9q63X0|-7j(?l=x453`D<~>XL|$c1i4LE_;V3Rys1={RqrL-deM0+Qhvmnd%Jy60 z(JX#}Iwpu^G&s^AyFCE@s#42E0D>KqBd3hY-zRhF4okIx~raKnYr5I z&Cs86O#itka)Rmw#q%T|+PrNROWB21w8zGW_Yg9ag@>tm+dz|G9}^BPBcd%`&-Uyf z73lu_PYv-xtxYQ#M8Qm~1y2rF>W}s_=JIHmEH@9dl<{Z{wmxIXq8I{DILh&$!lMSq zE?|bZ7=&#U>xv8OYoF?wbeVjK#u968PH8``Xb^EV-M=!o?N}Osry!rXYk=2%CPNrY z9$3s`V+k7LZcEE{W~O6W3OB6#=SOgbCIBB5Q|UBIRFyZWji;Tnt>6WG5U+HIG>O|A zBYi3!B*hK0=X_b8L*YXm_&pWkWd|1QF}BEB0gK zuHqTl(k0IK1_|M;9u?oE7dWIgTrTOkw-y>Wc!#~t>4v{Yc@kg|x*B^pkEL_W#fVfP zkb_&lw4uY7sBv0GM2+Jz-(QH0u3ZEa0Ur9GRDU1pP0Tx3fCG3TcXMRikVJ19;c=^L zUPxjK$(?%PeR%l@2lE0=r0>hDTCeW3y0~47o-BDp9Ld7>1(pQij`A8^VSYU z8xz|8ni0nPP#^ePk&*85uKHarom?9DSlUjra^#uy+`Y)XE;3AQmsd5?)mKv^ zIj+vrFw#}!ZT6&oJn)j%jZvOs5t3_kc2{XvUErl{0uNZ>*6n2ihq{I(02w8V5$k}GJ=76h{9wjvwWy0dJ; z04b-YgX>Xx)!BdS4=$Ef*t9r=*xqCQ3iKhjf3!kvsbG9$?OK`hVMz3 z^wH`v8Arhvi=UKgZ8hFAM+(|m`*}qqeCFsMx=+^xbtoP%vUM!ZDB83@Y*3BN&S#YR zm^5mwBTe{JYlo`tDL&g?NhmzFtN@}UInXO4MZ!#X# zcoMir3#(ttTGY=)+!uZ=f`ZJt~VFW|J#>h3Nls0LGOc{Yic=Ljw zPKXs$U4>TmJ*BQsE&DgxhpekCP9+;_-^?HCjrC_kj73ENT3s|G{ zlkZBDWeE|}D}qE`WA<&A?pQh#TKGoiRzF7*oa4_8+Tc8WY1}&fG3h(jxFS8s?z~bK`ocJl4Xb1?@y_ z;{WN|nG_6?KxTOwbOE!cTbywr3pUUKY_u4=-hLs{y9GL!UKo zEYA6~-q96}v`yNQh_zLIKfY*a7=D)C-i}o&X0$gNrvXOD8cffJ@M_Z^!=&m>Jpe8N zagRG*UbbyTQVFO?@@3CW^YM@!gIHvq-rF!n8rk1!>D+vY%-cqQ8&nVIy{>DiNNq?? z8hJ=(PZSsaP+h#p2*J+hOxeC3C*O1F!d(-qz)35f>XNQeB4t? z0i<#okW4^k=Inmo&Vp&0lM0ndeM~A&pwuLGk4cbkjw#ma$?!}`mGB7r`FEhlrj*1% z+Cw%rTOjMg!{e&wv|4lfdXShV%8z^zO8nNKXyKEL&dYNkg z)4~>5oxd}!dME!c++ePbuX~sFVJe)};0fV={5k+cxZ7kRZ=Ty-P*brvfJ797Ur(i<4b&VCmu2pkavM;n!lyFft^3pL)T_LW{b#-cm$3?)u z3VTzqibx|tM6>4gW>k3RW6Ek!ad;5O=-8kB-rcU^g2*{W$6*g46S22FpW zAfuN}511LjCMbtjl%D_RZC(O%9V%=onLzO05y*p6luF;q5;*g-m@-NhuhtbDkI{$( zuvEY+GkFr&kG*rW{hSQ^Ku%uPt|UR1ivcp}+WK0W2E)fEqc{gqhX?)2jJW3;qC3E5 zK@n{dM1i;~O1*>~D9>6!qGb?Kp%g$F7}aCe+@6!*tpHbsvtFl8o80G&P9?f}vn?3q zPDVb+O{$U09S&R7<#&u>i{x!o7|zNT%Nzpr(IQfK6+amz$QE30G3ED~(Wl;6Egit~ z3EKJ|8wd{z2zIUwKU&BBzIc%9pj7`E9(nO#Wo=;Ylsw0j7hUsjd!Z>ef4FZaxX4@k zh_?%H;mw&{v6r5in(E{Tc_-ti>s#s;%f{HI?dNl+xvg4GmYy$lGSwm0)BsO+&En|f z>`k6j)8V{kmM#FBINGx9U*VDux>Tkoj1^i9pW#}1VJLeHE2un|bhtM!Pi)#|IkL2> zQSpOEs`}uwQU%Say0nZmv)g3W7bD3Wj5*>34PDgb={s-81lC{o)*o5WPn5Ctcc!lB z8>*FNg4|{l3+!5d8WXWDDq8o^diUBcjFxSYDkDakY=wdvj{n%N)MTw#>2SuI{_Z%p zalo-OoM~7wA_2;0%Qsgy66S#$>~3YVblhElu#G*D?UMUnT-MmmPcp;%#7hm#XDvj- z_H30EETWYFp!acz=bDZ>b%m^6BT3Ap$7)qEax%MhXtCk(jU`Y+hRLjIRHaYNIagjz zBT(y-x3BQ)hSJ_Lt060k{I&!SWzk%Xw8^X`&uCu3pz8>*UA|MD-K|e~zrF%1Bo2>$ zohWTiiVllgruV=~BiVyG&VJmb{gW99hCfmyDW>14mB`a>;VZHhFjuXA<@|;|%`tvWAQMCY)HF+to zk%2m0+jBY(VLhW()|x_zeTMu z+IdN4?ia6?GWtn}_63m$e>}t0r1Y#>xKEl|Sz9Rf0{OXQVQwuc+$Q__uLd z2+Jzpy~5NUFndZjC-t4$bBQKt{3=rUc{YOyF3CGH6YUwNR;RAXV?N*JaM|`tN#~@d zke@;+Jy}!6&hmJ57?oyb3K{9vxl6P*L-%CY@?m|+^;(s6uz=eK-1|_Hn*IG677Fap znX@7pjb0gc^8+hfye(gTnw70Dy!1A-pVOs4B<`U45ODDSE)a#$7R>DWf#MK1Kv`FE zb<2}O^A2DybK);}d;VobZKezeY00_8I8NJ8%~mJVTnlEA1f?g=3p+m704uBVk}fqo zu5{DH4MVwsm+`uG$=TaHu2`R!bmk)~pr9VQi6zdo9P$?^;7oDxiHYtX9T}Go&{IM? zb`r>N&1iG)AMfe=z!o>Bx_1_y^FD3#uvUc6g8;F^`FarZac^z1;0LD$}(3UYwQslin zzUS6TZj=nQ8mZut2S@47H>?C)LFwPq_?&N(FBHGuIyW71@zSn(1o~hKb{rJ|pvzil49(b- zXeW;C*G?VMjp2pjnq7W42{rU=?eC91jD09LYBAVFHZ1gcvr95<{8Bq`Jj(O-4l?u6 zyi@Tt>Yj9mk1g%kmmnuklT&h8uR*{ILlCPj@kp^uH5_BM0Z=s}qPBAM0BbDj+v(_5 zi(X+I-_Xkg9i;ZAyVb9Pyyr9i|9LHawOb;{o_(Wt8o6@(FXH8vXap51}37=YzU z!FrzU8)oqh*#wMHyy}XFNX>X^G9^XT`vURYb9;<^=UaVVs?Xf9X>Q?sGxe8 zm@f|_5U28d_(Ms;pZI)=XUo^uQf%j+C{&9Fmy_-6(pscsTc>4>fpSQ!b$Dy-u^r;- z<KkO$kCd)8lwULu(B-D$%-mtvVzuqXwuF#{h4C9!5qS8u61Zmcf51mKw<;qlAqBw zQ%=koJ9CjTtHo$!^SNaCqlWb9&nG#D0Y09>9%RJyNWWSlF9^2O(e6^|eLp{c??{nU z3A6Uj$#nIQZLcQ$v{FXv=AqY5njrKMnp#! zkSOHK7~{*h-kGxbD{}DZOw57uwp^Vb@nxuNL+Y+cHczYp^AoCBvOG-%Esyx+QIFMh zv}=$|wM|HXe}bkSlt;}Ti}22Wz4N7!`mcAf#Skb=Rv1<9n~C0%Ii30Y4c*nmQmy%B zTLSN2XHC8^V3h~Hl4>ZXK{4H@_VGuWQ(FQgh>95qp_7HOcw;emFq%mYBxqh?;{|os zaqtyWY+RM3ZZ5^(NOrQyjj33|h-J>`OtR1RY=ycPKge8@e1?+fK`MS&Xz;C2nku#J zV{erd$&F5A3~F2Uk39nT%-zM;IXNyR8Ma~}-g+Vu(ck9EGVI)nLOGeytKEswhSGL2 zmoqKu?02Hi1N#Yv_`VLyrnz}r_a6xY-S91_TgYtFr0a#$9;R_ zeveOv?KdxE-jmrgl04~`vQ%{GKK`MRtAm{O*AaNDf{)jCJix`1tc15}fq+ zhE^+Rh_L)&w?nHP-NeEL`Wagij5MXaGx%^6RoGIdlGn&reh%YEfaE8nlr;wX=Fr_g zaxnASWs!5=wc~(H4 z`*$Yp&;-{ARfli?@#kd6CcKLR0p2sw=G=V~@I>qb{+{t(Eo0;ABcJzX=rl zT!p!Vfq3)zob2Jj!Ep9ru3`Fg9q=AB+Yo*JnWlQW@OFn z?0Bq_XFh;4^$ETtFjU|au_vC?^x&EWg4i4U6#kbR{O!9=-pgEl_1=x47bf5KvR_gE zqY2e5Bjslwe=T0RYBE=ZTGa8bB=rw306(^SQl0QC`xN8!`sR~O3JVsoNMcGEhjv{J zm5TdW3+8zcntPdAv5x;SIbJzdTJ2c=-l3FXMR{TS?D@9v)gHPNi*>XXYXh?;hM=eI zPEB53<*(%wc{X*CpFa$78lLKiUYzxMi-n!&&#~c5AtQ~tjh)H z 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à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%0A4^XwJX_OEZ!Swlu}8oZ;vh(q-nX1OZU@ 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

      LbO;pkTO{4N8Zeqh#HAZ)pAZ1srGvr#Uv*8Yv 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

      S^ser!Ci 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

      Z%vk^7Wm6*r_OZeJZR5_~ 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%0A)>aAyqL}K{cWOEq`ZB`Z6f44pX zTV~Q*h|I`{(r6R&01X`??L-#p2CS7|5X3WvX+F%|gI$am3r|A?VM-=$=g#SC)hs4&A6Qpe+Yu4fmdV^pYQ){!HB zsah4yTjwPznl*9yzN1(@#p@xr&CG7B%-G~vatjtzzPAoV-Z&aIlRCT7?yP`Ar89do zFY``12aP*@Qf5m`wBdWtjM9XP`s;iB8nMjg+W3CLns#fwFF7688i*C5zBo$%i)Ai8 zKt#q+7s3S7d&KLJoviRs>A~RL&{G)089eGTl+FaOJ%J862<^U2H2uyhI/v6ej5 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%0Ab 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

      tF`hGZ~1eO#$To6>zY%U)%(3MR!Z%BlF! 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

      EPZA<_bgn7`H0Q|>5kX&ncd#7}9 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 z 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%0DGc6zflKwldP2JO@rq?ie%97UWFlV<2VVTh8{`4 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

      _5(Vx6L1o3nhxg%O#2n{CJEh9=bc@si$v> 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

      dWEAb?X{1j6dTW=BPOUe3wGP@{oPXzl0dw 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

      XBQ#wQ+( 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 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -104,7 +106,7 @@ func (h *Handler) handleGetBucketStatistics(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -208,7 +210,7 @@ func (h *Handler) handleSearchResources(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/macie2/handler_buckets_test.go b/services/macie2/handler_buckets_test.go index 3e7b8f0e3a..7b43425e5a 100644 --- a/services/macie2/handler_buckets_test.go +++ b/services/macie2/handler_buckets_test.go @@ -1,7 +1,7 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -30,7 +31,7 @@ func TestBucketsAndBatchCustomDataIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) buckets, _ := resp["buckets"].([]any) assert.Empty(t, buckets) }, @@ -44,7 +45,7 @@ func TestBucketsAndBatchCustomDataIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) count, _ := resp["bucketCount"].(float64) assert.InDelta(t, 0, count, 0.0001) }, @@ -62,7 +63,7 @@ func TestBucketsAndBatchCustomDataIdentifiers(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cdiID := createResp["customDataIdentifierId"] // BatchGetCustomDataIdentifiers @@ -72,7 +73,7 @@ func TestBucketsAndBatchCustomDataIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp, jsonx.V1())) items, _ := batchResp["customDataIdentifiers"].([]any) assert.Len(t, items, 1) }, @@ -88,7 +89,7 @@ func TestBucketsAndBatchCustomDataIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, _ := resp["matchingResources"].([]any) assert.Empty(t, results) }, @@ -156,7 +157,7 @@ func describeBuckets(t *testing.T, h *macie2.Handler, criteria map[string]any) [ require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) buckets, ok := resp["buckets"].([]any) if !ok { @@ -173,7 +174,7 @@ func getBucketStatistics(t *testing.T, h *macie2.Handler) map[string]any { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/macie2/handler_classification_jobs.go b/services/macie2/handler_classification_jobs.go index d270b5d1b2..b7b6284620 100644 --- a/services/macie2/handler_classification_jobs.go +++ b/services/macie2/handler_classification_jobs.go @@ -1,13 +1,14 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" "slices" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseJobPath(method string, parts []string) (string, string) { @@ -148,7 +149,7 @@ func (h *Handler) handleCreateClassificationJob(body []byte) (any, int, error) { InitialRun bool `json:"initialRun"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -211,7 +212,7 @@ func (h *Handler) handleListClassificationJobs(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -241,7 +242,7 @@ func (h *Handler) handleUpdateClassificationJob(jobID string, body []byte) (int, JobStatus string `json:"jobStatus"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -278,7 +279,7 @@ func (h *Handler) handlePutClassificationExportConfiguration(body []byte) (int, Configuration *ClassificationExportConfig `json:"configuration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -321,7 +322,7 @@ func (h *Handler) handleUpdateClassificationScope(scopeID string, body []byte) ( S3 *ClassificationScopeS3Update `json:"s3"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_classification_jobs_test.go b/services/macie2/handler_classification_jobs_test.go index dc01b1354f..f381f910f4 100644 --- a/services/macie2/handler_classification_jobs_test.go +++ b/services/macie2/handler_classification_jobs_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -26,7 +27,7 @@ func TestUpdateClassificationScope_ExcludedBucketsSurviveIndependentAdds(t *test require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) scopes, _ := listResp["classificationScopes"].([]any) require.Len(t, scopes, 1) scope0, _ := scopes[0].(map[string]any) @@ -59,7 +60,7 @@ func TestUpdateClassificationScope_ExcludedBucketsSurviveIndependentAdds(t *test require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) s3, ok := got["s3"].(map[string]any) require.True(t, ok, "got %#v", got) excludes, ok := s3["excludes"].(map[string]any) @@ -79,7 +80,7 @@ func TestUpdateClassificationScope_ExcludedBucketsSurviveIndependentAdds(t *test require.Equal(t, http.StatusOK, rec.Code) rec = doRequest(t, h, http.MethodGet, "/classification-scopes/"+scopeID, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) s3, ok = got["s3"].(map[string]any) require.True(t, ok) excludes, ok = s3["excludes"].(map[string]any) @@ -111,7 +112,7 @@ func TestClassificationJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp["jobId"] assert.NotEmpty(t, jobID) assert.Equal(t, "RUNNING", createResp["jobStatus"]) @@ -123,7 +124,7 @@ func TestClassificationJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, jobID, descResp["jobId"]) assert.Equal(t, "ONE_TIME", descResp["jobType"]) assert.Equal(t, "test-job", descResp["name"]) @@ -135,7 +136,7 @@ func TestClassificationJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["items"].([]any) require.Len(t, items, 1) item0 := items[0].(map[string]any) @@ -155,7 +156,7 @@ func TestClassificationJobs(t *testing.T) { // Verify update rec = doRequest(t, h, http.MethodGet, "/jobs/"+jobID, nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "CANCELLED", updated["jobStatus"]) }, }, @@ -184,11 +185,11 @@ func TestClassificationJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/jobs/"+resp["jobId"], nil) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "IDLE", desc["jobStatus"]) }, }, @@ -219,7 +220,7 @@ func TestClassificationConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) cfg, _ := getResp["configuration"].(map[string]any) assert.Nil(t, cfg["s3Destination"]) @@ -238,7 +239,7 @@ func TestClassificationConfig(t *testing.T) { // Verify rec = doRequest(t, h, http.MethodGet, "/classification-export-configuration", nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) updCfg, _ := updated["configuration"].(map[string]any) s3Dest, _ := updCfg["s3Destination"].(map[string]any) assert.Equal(t, "my-export-bucket", s3Dest["bucketName"]) @@ -254,7 +255,7 @@ func TestClassificationConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) scopes, _ := listResp["classificationScopes"].([]any) require.Len(t, scopes, 1) @@ -267,7 +268,7 @@ func TestClassificationConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var scopeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &scopeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &scopeResp, jsonx.V1())) assert.Equal(t, scopeID, scopeResp["id"]) // UpdateClassificationScope @@ -321,7 +322,7 @@ func createTestJob(t *testing.T, h *macie2.Handler, name, jobType string) (strin require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["jobId"], resp["jobArn"] } @@ -351,7 +352,7 @@ func TestListClassificationJobsFilterAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -374,7 +375,7 @@ func TestListClassificationJobsFilterAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["items"].([]any) require.True(t, ok) @@ -393,7 +394,7 @@ func TestListClassificationJobsFilterAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -406,7 +407,7 @@ func TestListClassificationJobsFilterAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) items2, ok := resp2["items"].([]any) require.True(t, ok) require.Len(t, items2, 1) @@ -431,7 +432,7 @@ func TestClassificationJobUserPausedDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var paused map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &paused)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &paused, jsonx.V1())) details, ok := paused["userPausedDetails"].(map[string]any) require.True(t, ok, "userPausedDetails must be present while USER_PAUSED") assert.NotEmpty(t, details["jobPausedAt"]) @@ -444,7 +445,7 @@ func TestClassificationJobUserPausedDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resumed map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resumed)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resumed, jsonx.V1())) assert.Nil(t, resumed["userPausedDetails"], "userPausedDetails must clear once no longer USER_PAUSED") } @@ -544,7 +545,7 @@ func TestClassificationJobTagging(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "test", tags["env"]) @@ -567,13 +568,13 @@ func TestClassificationJobCreateFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var al map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &al)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &al, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/custom-data-identifiers", map[string]any{"name": "cdi", "regex": `.+`}) require.Equal(t, http.StatusOK, rec.Code) var cdi map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cdi)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cdi, jsonx.V1())) rec = doRequest(t, h, http.MethodPost, "/jobs", map[string]any{ "name": "full-field-job", @@ -589,13 +590,13 @@ func TestClassificationJobCreateFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/jobs/"+created["jobId"], nil) require.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) allowListIDs, ok := desc["allowListIds"].([]any) require.True(t, ok) diff --git a/services/macie2/handler_custom_data_identifiers.go b/services/macie2/handler_custom_data_identifiers.go index 24ded90b5b..bf1e9fee8a 100644 --- a/services/macie2/handler_custom_data_identifiers.go +++ b/services/macie2/handler_custom_data_identifiers.go @@ -1,11 +1,12 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseCustomDataIDPath(method string, parts []string) (string, string) { @@ -98,7 +99,7 @@ func (h *Handler) handleCreateCustomDataID(body []byte) (any, int, error) { SeverityLevels []SeverityLevel `json:"severityLevels"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -152,7 +153,7 @@ func (h *Handler) handleListCustomDataIDs(body []byte) (any, int, error) { MaxResults *int32 `json:"maxResults"` NextToken string `json:"nextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) limit := 0 if req.MaxResults != nil { @@ -181,7 +182,7 @@ func (h *Handler) handleTestCustomDataID(body []byte) (any, int, error) { Keywords []string `json:"keywords"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -214,7 +215,7 @@ func (h *Handler) handleBatchGetCustomDataIdentifiers(body []byte) (any, int, er IDs []string `json:"ids"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -250,7 +251,7 @@ func (h *Handler) handleListManagedDataIdentifiers(body []byte) (any, int, error } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/macie2/handler_custom_data_identifiers_test.go b/services/macie2/handler_custom_data_identifiers_test.go index fa424d00ab..467ab93b49 100644 --- a/services/macie2/handler_custom_data_identifiers_test.go +++ b/services/macie2/handler_custom_data_identifiers_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -35,7 +36,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]string - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["customDataIdentifierId"]) }, }, @@ -50,7 +51,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { "keywords": []string{"phone", "tel"}, }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["customDataIdentifierId"] }, @@ -59,7 +60,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "phone-detector", resp["name"]) assert.Equal(t, "detects phone numbers", resp["description"]) assert.NotEmpty(t, resp["arn"]) @@ -78,7 +79,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.InDelta(t, float64(2), resp["matchCount"], 0.001) }, }, @@ -91,7 +92,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp, "items") }, }, @@ -104,7 +105,7 @@ func TestMacie2_CustomDataIdentifiers(t *testing.T) { "regex": `.+`, }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["customDataIdentifierId"] }, @@ -208,7 +209,7 @@ func TestMacie2_CustomDataIdentifierWireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["customDataIdentifierId"] doRequest(t, h, http.MethodDelete, "/custom-data-identifiers/"+id, nil) @@ -267,14 +268,14 @@ func TestCustomDataIdentifierDeletedField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["customDataIdentifierId"] rec2 := doRequest(t, h, http.MethodGet, "/custom-data-identifiers/"+id, nil) require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) deleted, hasDeleted := resp["deleted"] require.True(t, hasDeleted, "GetCustomDataIdentifier must include a 'deleted' field") assert.Equal(t, false, deleted) @@ -286,7 +287,7 @@ func TestCustomDataIdentifierDeletedField(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code, "Get on a soft-deleted identifier must not 404") var afterDelete map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &afterDelete)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &afterDelete, jsonx.V1())) assert.Equal(t, true, afterDelete["deleted"]) // BatchGetCustomDataIdentifiers must also return the soft-deleted @@ -297,7 +298,7 @@ func TestCustomDataIdentifierDeletedField(t *testing.T) { require.Equal(t, http.StatusOK, batchRec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp, jsonx.V1())) items, ok := batchResp["customDataIdentifiers"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -328,13 +329,13 @@ func TestCustomDataIdentifierSeverityLevels(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec2 := doRequest(t, h, http.MethodGet, "/custom-data-identifiers/"+created["customDataIdentifierId"], nil) require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) levels, ok := resp["severityLevels"].([]any) require.True(t, ok) require.Len(t, levels, 2) @@ -355,7 +356,7 @@ func TestListCustomDataIDsEmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) v, ok := resp["items"] require.True(t, ok, "response must contain items key") diff --git a/services/macie2/handler_enablement.go b/services/macie2/handler_enablement.go index f5900897e5..3930578674 100644 --- a/services/macie2/handler_enablement.go +++ b/services/macie2/handler_enablement.go @@ -1,12 +1,13 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "time" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseMaciePath(method string, parts []string) (string, string) { @@ -78,7 +79,7 @@ func (h *Handler) handleEnableMacie(body []byte) (int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } @@ -117,7 +118,7 @@ func (h *Handler) handleUpdateMacieSession(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/macie2/handler_enablement_test.go b/services/macie2/handler_enablement_test.go index 0832390b60..6d791bed22 100644 --- a/services/macie2/handler_enablement_test.go +++ b/services/macie2/handler_enablement_test.go @@ -1,7 +1,7 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -54,7 +55,7 @@ func TestMacie2_Session(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ONE_HOUR", resp["findingPublishingFrequency"]) assert.Equal(t, "ENABLED", resp["status"]) assert.NotEmpty(t, resp["serviceRole"]) @@ -132,7 +133,7 @@ func TestDisableMacie_DeletesResources(t *testing.T) { require.Equal(t, http.StatusOK, jobRec.Code) var jobResp map[string]string - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jobResp, jsonx.V1())) jobID := jobResp["jobId"] require.NotEmpty(t, jobID) @@ -143,7 +144,7 @@ func TestDisableMacie_DeletesResources(t *testing.T) { require.Equal(t, http.StatusOK, cdiRec.Code) var cdiResp map[string]string - require.NoError(t, json.Unmarshal(cdiRec.Body.Bytes(), &cdiResp)) + require.NoError(t, json.Unmarshal(cdiRec.Body.Bytes(), &cdiResp, jsonx.V1())) cdiID := cdiResp["customDataIdentifierId"] require.NotEmpty(t, cdiID) @@ -154,7 +155,7 @@ func TestDisableMacie_DeletesResources(t *testing.T) { require.Equal(t, http.StatusOK, allowListRec.Code) var allowListResp map[string]string - require.NoError(t, json.Unmarshal(allowListRec.Body.Bytes(), &allowListResp)) + require.NoError(t, json.Unmarshal(allowListRec.Body.Bytes(), &allowListResp, jsonx.V1())) allowListID := allowListResp["id"] require.NotEmpty(t, allowListID) @@ -297,7 +298,7 @@ func TestSessionTimestampsPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range []string{"createdAt", "updatedAt"} { raw, ok := resp[field] @@ -320,7 +321,7 @@ func TestSessionUpdatedAtAdvances(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var before map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &before, jsonx.V1())) createdAt := before["createdAt"].(string) time.Sleep(1001 * time.Millisecond) @@ -332,7 +333,7 @@ func TestSessionUpdatedAtAdvances(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var after map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &after, jsonx.V1())) assert.Equal(t, createdAt, after["createdAt"].(string), "createdAt must not change after update") assert.NotEqual(t, after["createdAt"], after["updatedAt"], diff --git a/services/macie2/handler_findings.go b/services/macie2/handler_findings.go index b63eec3a12..071159e651 100644 --- a/services/macie2/handler_findings.go +++ b/services/macie2/handler_findings.go @@ -1,11 +1,12 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseFindingsPath(method string, parts []string) (string, string) { @@ -83,7 +84,7 @@ func (h *Handler) handleGetFindings(body []byte) (any, int, error) { FindingIDs []string `json:"findingIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -111,7 +112,7 @@ func (h *Handler) handleListFindings(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } @@ -147,7 +148,7 @@ func (h *Handler) handleCreateSampleFindings(body []byte) (int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } @@ -167,7 +168,7 @@ func (h *Handler) handleGetFindingStatistics(body []byte) (any, int, error) { Size int `json:"size"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -223,7 +224,7 @@ func (h *Handler) handleGetFindingsPublicationConfiguration() (any, int, error) func (h *Handler) handlePutFindingsPublicationConfiguration(body []byte) (int, error) { var cfg FindingsPublicationConfig - if err := json.Unmarshal(body, &cfg); err != nil { + if err := json.Unmarshal(body, &cfg, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_findings_filters.go b/services/macie2/handler_findings_filters.go index a0ba4f4d7e..86d043084e 100644 --- a/services/macie2/handler_findings_filters.go +++ b/services/macie2/handler_findings_filters.go @@ -1,7 +1,7 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +9,7 @@ import ( "strconv" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseFindingsFilterPath(method string, parts []string) (string, string) { @@ -80,7 +81,7 @@ func (h *Handler) handleCreateFindingsFilter(body []byte) (any, int, error) { Name string `json:"name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -138,7 +139,7 @@ func (h *Handler) handleUpdateFindingsFilter(id string, body []byte) (any, int, Name string `json:"name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_findings_filters_test.go b/services/macie2/handler_findings_filters_test.go index 1288d9a670..a002eeed77 100644 --- a/services/macie2/handler_findings_filters_test.go +++ b/services/macie2/handler_findings_filters_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -36,7 +37,7 @@ func TestMacie2_FindingsFilters(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]string - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["arn"]) assert.NotEmpty(t, resp["id"]) assert.Contains(t, resp["arn"], "findings-filter") @@ -53,7 +54,7 @@ func TestMacie2_FindingsFilters(t *testing.T) { "position": int32(3), }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"] }, @@ -62,7 +63,7 @@ func TestMacie2_FindingsFilters(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "test-filter", resp["name"]) assert.Equal(t, "NOOP", resp["action"]) assert.Equal(t, "test desc", resp["description"]) @@ -77,7 +78,7 @@ func TestMacie2_FindingsFilters(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp, "findingsFilterListItems") }, }, @@ -90,7 +91,7 @@ func TestMacie2_FindingsFilters(t *testing.T) { "action": "ARCHIVE", }) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"] }, @@ -130,7 +131,7 @@ func TestListFindingsFiltersEmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) v, ok := resp["findingsFilterListItems"] require.True(t, ok, "response must contain findingsFilterListItems key") diff --git a/services/macie2/handler_findings_test.go b/services/macie2/handler_findings_test.go index 46c17c0313..190d9ea785 100644 --- a/services/macie2/handler_findings_test.go +++ b/services/macie2/handler_findings_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -46,7 +47,7 @@ func TestMacie2_Findings(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp, "findingIds") ids, ok := resp["findingIds"].([]any) @@ -68,7 +69,7 @@ func TestMacie2_Findings(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp, "findings") }, }, @@ -86,7 +87,7 @@ func TestMacie2_Findings(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp, "countsByGroup") }, }, @@ -107,7 +108,7 @@ func TestMacie2_Findings(t *testing.T) { if tt.name == "GetFindings returns findings array" { listRec := doRequest(t, h, http.MethodPost, "/findings", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ids := listResp["findingIds"].([]any) body = map[string]any{"findingIds": ids} } @@ -131,7 +132,7 @@ func TestListFindingsEmptyNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) v, ok := resp["findingIds"] require.True(t, ok, "response must contain findingIds key") @@ -151,7 +152,7 @@ func TestGetFindingsEmptyInputNotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) v, ok := resp["findings"] require.True(t, ok, "response must contain findings key") @@ -175,7 +176,7 @@ func TestCreateSampleFindingsFieldShape(t *testing.T) { listRec := doRequest(t, h, http.MethodPost, "/findings", map[string]any{}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ids, ok := listResp["findingIds"].([]any) require.True(t, ok) require.Len(t, ids, 2) @@ -184,7 +185,7 @@ func TestCreateSampleFindingsFieldShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) findings, ok := getResp["findings"].([]any) require.True(t, ok) require.Len(t, findings, 2) @@ -266,7 +267,7 @@ func TestFindingsPublicationConfig(t *testing.T) { // Verify rec = doRequest(t, h, http.MethodGet, "/findings-publication-configuration", nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) _, hasTopClassification := updated["publishClassificationFindings"] _, hasTopPolicy := updated["publishPolicyFindings"] diff --git a/services/macie2/handler_members.go b/services/macie2/handler_members.go index ab1c595ddf..626d071fee 100644 --- a/services/macie2/handler_members.go +++ b/services/macie2/handler_members.go @@ -1,7 +1,7 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -9,6 +9,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseMembersPath(method string, parts []string) (string, string) { @@ -156,7 +157,7 @@ func (h *Handler) handleCreateMember(body []byte) (int, error) { Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -249,7 +250,7 @@ func (h *Handler) handleUpdateMemberSession(accountID string, body []byte) (int, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } @@ -272,7 +273,7 @@ func (h *Handler) handleCreateInvitations(body []byte) (any, int, error) { DisableEmailNotification bool `json:"disableEmailNotification"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -291,7 +292,7 @@ func (h *Handler) handleAcceptInvitation(body []byte) (int, error) { MasterAccount string `json:"masterAccount"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -312,7 +313,7 @@ func (h *Handler) handleDeclineInvitations(body []byte) (any, int, error) { AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } @@ -329,7 +330,7 @@ func (h *Handler) handleDeleteInvitations(body []byte) (any, int, error) { AccountIDs []string `json:"accountIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_members_test.go b/services/macie2/handler_members_test.go index f2593080e0..6331f64e13 100644 --- a/services/macie2/handler_members_test.go +++ b/services/macie2/handler_members_test.go @@ -1,7 +1,7 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -38,7 +39,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getMem map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getMem)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getMem, jsonx.V1())) assert.Equal(t, "111111111111", getMem["accountId"]) assert.Equal(t, "member@example.com", getMem["email"]) assert.Equal(t, "Created", getMem["relationshipStatus"]) @@ -52,7 +53,7 @@ func TestMembers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) members, _ := listResp["members"].([]any) assert.Len(t, members, 1) @@ -63,7 +64,7 @@ func TestMembers(t *testing.T) { // List after delete rec = doRequest(t, h, http.MethodGet, "/members", nil) var afterList map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterList)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterList, jsonx.V1())) membersAfter, _ := afterList["members"].([]any) assert.Empty(t, membersAfter) }, @@ -87,7 +88,7 @@ func TestMembers(t *testing.T) { // Verify status changed rec = doRequest(t, h, http.MethodGet, "/members/222222222222", nil) var mem map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mem)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mem, jsonx.V1())) assert.Equal(t, "Removed", mem["relationshipStatus"]) }, }, @@ -111,7 +112,7 @@ func TestMembers(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/members/333333333333", nil) var mem map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mem)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mem, jsonx.V1())) assert.Equal(t, "PAUSED", mem["relationshipStatus"]) }, }, @@ -175,7 +176,7 @@ func TestListMembersOnlyAssociatedAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members, ok := resp["members"].([]any) require.True(t, ok) require.Len(t, members, 1) @@ -192,7 +193,7 @@ func TestListMembersOnlyAssociatedAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members, ok := resp["members"].([]any) require.True(t, ok) assert.Len(t, members, 2) @@ -205,7 +206,7 @@ func TestListMembersOnlyAssociatedAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members, ok := resp["members"].([]any) require.True(t, ok) require.Len(t, members, 1) @@ -221,7 +222,7 @@ func TestListMembersOnlyAssociatedAndPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) members2, ok := resp2["members"].([]any) require.True(t, ok) require.Len(t, members2, 1) @@ -255,7 +256,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var countResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &countResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &countResp, jsonx.V1())) count, _ := countResp["invitationsCount"].(float64) assert.InDelta(t, 2, count, 0.0001) @@ -264,7 +265,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) invitations, _ := listResp["invitations"].([]any) assert.Len(t, invitations, 2) }, @@ -285,7 +286,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var adminResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &adminResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &adminResp, jsonx.V1())) admin, _ := adminResp["administrator"].(map[string]any) assert.Equal(t, "123456789012", admin["accountId"]) }, @@ -306,7 +307,7 @@ func TestInvitations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var declineResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &declineResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &declineResp, jsonx.V1())) assert.Empty(t, declineResp["unprocessedAccounts"]) // DeleteInvitations diff --git a/services/macie2/handler_organization.go b/services/macie2/handler_organization.go index 51a40772aa..3feec867ea 100644 --- a/services/macie2/handler_organization.go +++ b/services/macie2/handler_organization.go @@ -1,11 +1,12 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseAdminPath(method string, parts []string) (string, string) { @@ -70,7 +71,7 @@ func (h *Handler) handleEnableOrganizationAdminAccount(body []byte) (int, error) AdminAccountID string `json:"adminAccountId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } @@ -116,7 +117,7 @@ func (h *Handler) handleUpdateOrganizationConfiguration(body []byte) (int, error AutoEnable bool `json:"autoEnable"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_organization_test.go b/services/macie2/handler_organization_test.go index 8db0e3f2c1..096cf8f486 100644 --- a/services/macie2/handler_organization_test.go +++ b/services/macie2/handler_organization_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -34,7 +35,7 @@ func TestOrgAdmin(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) accounts, _ := listResp["adminAccounts"].([]any) assert.Len(t, accounts, 1) @@ -45,7 +46,7 @@ func TestOrgAdmin(t *testing.T) { // Verify removed rec = doRequest(t, h, http.MethodGet, "/admin", nil) var afterList map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterList)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &afterList, jsonx.V1())) accountsAfter, _ := afterList["adminAccounts"].([]any) assert.Empty(t, accountsAfter) }, @@ -60,7 +61,7 @@ func TestOrgAdmin(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) autoEnable, _ := descResp["autoEnable"].(bool) assert.False(t, autoEnable) @@ -73,7 +74,7 @@ func TestOrgAdmin(t *testing.T) { // Verify change rec = doRequest(t, h, http.MethodGet, "/admin/configuration", nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.True(t, updated["autoEnable"].(bool)) }, }, @@ -100,7 +101,7 @@ func TestDescribeOrganizationConfigurationWireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "autoEnable") assert.Contains(t, resp, "maxAccountLimitReached") diff --git a/services/macie2/handler_resource_profiles.go b/services/macie2/handler_resource_profiles.go index c82c4a95ce..95eca6269a 100644 --- a/services/macie2/handler_resource_profiles.go +++ b/services/macie2/handler_resource_profiles.go @@ -1,8 +1,10 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseResourceProfilesPath(method string, parts []string) (string, string) { @@ -81,7 +83,7 @@ func (h *Handler) handleUpdateResourceProfile(resourceARN string, body []byte) ( } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } @@ -117,7 +119,7 @@ func (h *Handler) handleUpdateResourceProfileDetections(resourceARN string, body } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } } diff --git a/services/macie2/handler_resource_profiles_test.go b/services/macie2/handler_resource_profiles_test.go index 34f1e182df..fd66781717 100644 --- a/services/macie2/handler_resource_profiles_test.go +++ b/services/macie2/handler_resource_profiles_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -30,7 +31,7 @@ func TestResourceProfiles(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var profile map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &profile, jsonx.V1())) assert.Equal(t, arn, profile["resourceArn"]) // UpdateResourceProfile @@ -42,7 +43,7 @@ func TestResourceProfiles(t *testing.T) { // Verify rec = doRequest(t, h, http.MethodGet, "/resource-profiles?resourceArn="+arn, nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.EqualValues(t, 75, updated["sensitivityScore"]) assert.True(t, updated["sensitivityScoreOverridden"].(bool)) }, @@ -59,7 +60,7 @@ func TestResourceProfiles(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var artResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &artResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &artResp, jsonx.V1())) artifacts, _ := artResp["artifacts"].([]any) assert.Empty(t, artifacts) @@ -68,7 +69,7 @@ func TestResourceProfiles(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var detResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detResp, jsonx.V1())) detections, _ := detResp["detections"].([]any) assert.Empty(t, detections) diff --git a/services/macie2/handler_reveal_configuration.go b/services/macie2/handler_reveal_configuration.go index f10c21e53c..fc379b834c 100644 --- a/services/macie2/handler_reveal_configuration.go +++ b/services/macie2/handler_reveal_configuration.go @@ -1,12 +1,13 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseRevealCfgPath(method string, _ []string) (string, string) { @@ -57,7 +58,7 @@ func (h *Handler) handleUpdateRevealConfiguration(body []byte) (any, int, error) } `json:"retrievalConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_reveal_configuration_test.go b/services/macie2/handler_reveal_configuration_test.go index d10f2a64c5..65052be1b4 100644 --- a/services/macie2/handler_reveal_configuration_test.go +++ b/services/macie2/handler_reveal_configuration_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -28,7 +29,7 @@ func TestRevealConfiguration(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) cfg, _ := getResp["configuration"].(map[string]any) assert.Equal(t, "DISABLED", cfg["status"]) @@ -44,7 +45,7 @@ func TestRevealConfiguration(t *testing.T) { // Verify rec = doRequest(t, h, http.MethodGet, "/reveal-configuration", nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) updCfg, _ := updated["configuration"].(map[string]any) assert.Equal(t, "ENABLED", updCfg["status"]) assert.Equal(t, "arn:aws:kms:us-east-1:000000000000:key/reveal-key", updCfg["kmsKeyId"]) @@ -93,7 +94,7 @@ func TestSensitiveDataOccurrences(t *testing.T) { // Get finding IDs rec := doRequest(t, h, http.MethodPost, "/findings", nil) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) findingIDs, _ := listResp["findingIds"].([]any) require.NotEmpty(t, findingIDs) findingID, _ := findingIDs[0].(string) @@ -107,7 +108,7 @@ func TestSensitiveDataOccurrences(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var avail map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &avail)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &avail, jsonx.V1())) assert.Equal(t, "AVAILABLE", avail["code"]) }, }, diff --git a/services/macie2/handler_sensitivity_inspection.go b/services/macie2/handler_sensitivity_inspection.go index 644fc6353d..0c5eb245ce 100644 --- a/services/macie2/handler_sensitivity_inspection.go +++ b/services/macie2/handler_sensitivity_inspection.go @@ -1,12 +1,13 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseTemplatesPath(method string, parts []string) (string, string) { @@ -85,7 +86,7 @@ func (h *Handler) handleUpdateSensitivityInspectionTemplate(templateID string, b Name string `json:"name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_sensitivity_inspection_test.go b/services/macie2/handler_sensitivity_inspection_test.go index 26dd8177f3..daf66f8d48 100644 --- a/services/macie2/handler_sensitivity_inspection_test.go +++ b/services/macie2/handler_sensitivity_inspection_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -25,7 +26,7 @@ func TestUpdateSensitivityInspectionTemplate_FieldsSurviveIndependentUpdates(t * require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) templates, _ := listResp["sensitivityInspectionTemplates"].([]any) require.Len(t, templates, 1) tmpl0, _ := templates[0].(map[string]any) @@ -53,7 +54,7 @@ func TestUpdateSensitivityInspectionTemplate_FieldsSurviveIndependentUpdates(t * require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "original description", updated["description"], "description must survive an Update that never mentioned it") @@ -84,7 +85,7 @@ func TestSensitivityInspectionTemplates(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) templates, _ := listResp["sensitivityInspectionTemplates"].([]any) require.Len(t, templates, 1) @@ -97,7 +98,7 @@ func TestSensitivityInspectionTemplates(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, templateID, getResp["sensitivityInspectionTemplateId"]) // UpdateSensitivityInspectionTemplate @@ -118,7 +119,7 @@ func TestSensitivityInspectionTemplates(t *testing.T) { // Verify update rec = doRequest(t, h, http.MethodGet, "/templates/sensitivity-inspections/"+templateID, nil) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "Updated description", updated["description"]) }, }, diff --git a/services/macie2/handler_tags.go b/services/macie2/handler_tags.go index 7c3525992d..0fd9fcf6be 100644 --- a/services/macie2/handler_tags.go +++ b/services/macie2/handler_tags.go @@ -1,10 +1,12 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseTagPath(method string, parts []string) (string, string) { @@ -63,7 +65,7 @@ func (h *Handler) handleTagResource(resourceARN string, body []byte) (int, error Tags map[string]string `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return http.StatusBadRequest, ErrValidation } diff --git a/services/macie2/handler_tags_test.go b/services/macie2/handler_tags_test.go index b5140e1dea..2fe0598b6a 100644 --- a/services/macie2/handler_tags_test.go +++ b/services/macie2/handler_tags_test.go @@ -1,7 +1,7 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -48,7 +49,7 @@ func TestMacie2_Tags(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -169,7 +170,7 @@ func TestMacie2_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["customDataIdentifierId"] doRequest(t, h, http.MethodDelete, "/custom-data-identifiers/"+id, nil) @@ -220,14 +221,14 @@ func TestCreationTagsVisibleViaTagAPI(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) arn := created["arn"] rec2 := doRequest(t, h, http.MethodGet, "/tags/"+arn, nil) require.Equal(t, http.StatusOK, rec2.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp, jsonx.V1())) tags, ok := tagResp["tags"].(map[string]any) require.True(t, ok, "tags must be an object") @@ -248,7 +249,7 @@ func TestUntagResourceRemovesSpecificKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) arn := created["arn"] doRequest(t, h, http.MethodPost, "/tags/"+arn, @@ -260,7 +261,7 @@ func TestUntagResourceRemovesSpecificKey(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp, jsonx.V1())) tags, ok := tagResp["tags"].(map[string]any) require.True(t, ok) @@ -285,7 +286,7 @@ func TestTagResourceMergesWithCreationTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) arn := created["arn"] doRequest(t, h, http.MethodPost, "/tags/"+arn, @@ -295,7 +296,7 @@ func TestTagResourceMergesWithCreationTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagResp, jsonx.V1())) tags, ok := tagResp["tags"].(map[string]any) require.True(t, ok) diff --git a/services/macie2/handler_test.go b/services/macie2/handler_test.go index 8544fd75fb..98338c2256 100644 --- a/services/macie2/handler_test.go +++ b/services/macie2/handler_test.go @@ -2,7 +2,7 @@ package macie2_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *macie2.Handler, method, path string, body any) * if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/macie2/handler_usage.go b/services/macie2/handler_usage.go index 0ef8e37fa4..26e4807e1d 100644 --- a/services/macie2/handler_usage.go +++ b/services/macie2/handler_usage.go @@ -1,8 +1,10 @@ package macie2 import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseUsagePath(method string, parts []string) (string, string) { @@ -46,7 +48,7 @@ func (h *Handler) handleGetUsageStatistics(body []byte) (any, int, error) { } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, http.StatusBadRequest, ErrValidation } } diff --git a/services/macie2/handler_usage_test.go b/services/macie2/handler_usage_test.go index 6a1bc63c44..f7dad328f7 100644 --- a/services/macie2/handler_usage_test.go +++ b/services/macie2/handler_usage_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -29,7 +30,7 @@ func TestUsageAndManagedIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, _ := resp["records"].([]any) assert.Empty(t, records) }, @@ -43,7 +44,7 @@ func TestUsageAndManagedIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) totals, _ := resp["usageTotals"].([]any) assert.NotEmpty(t, totals) }, @@ -57,7 +58,7 @@ func TestUsageAndManagedIdentifiers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["items"].([]any) assert.NotEmpty(t, items) diff --git a/services/macie2/list_filter_params_test.go b/services/macie2/list_filter_params_test.go index 4c35ab824e..8ccdd887b2 100644 --- a/services/macie2/list_filter_params_test.go +++ b/services/macie2/list_filter_params_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -31,7 +32,7 @@ func TestBuckets_DescribeBuckets_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Buckets []map[string]any `json:"buckets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.Buckets, 1, "maxResults=1 must limit the page to 1 item") require.NotEmpty(t, page1.NextToken, "a partial page must return a nextToken") @@ -44,7 +45,7 @@ func TestBuckets_DescribeBuckets_MaxResultsHonoured(t *testing.T) { NextToken string `json:"nextToken"` Buckets []map[string]any `json:"buckets"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Buckets, 2, "second page must return the remainder") } @@ -72,7 +73,7 @@ func TestBuckets_DescribeBuckets_SortCriteriaHonoured(t *testing.T) { var resp struct { Buckets []map[string]any `json:"buckets"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Buckets, 3) assert.Equal(t, "bbb-bucket", resp.Buckets[0]["bucketName"]) @@ -106,7 +107,7 @@ func TestGetFindingStatistics_FindingCriteriaHonoured(t *testing.T) { var stats struct { CountsByGroup []map[string]any `json:"countsByGroup"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &stats)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &stats, jsonx.V1())) require.Len(t, stats.CountsByGroup, 1, "FindingCriteria must exclude TypeB's group") assert.Equal(t, "Policy:IAMUser/TypeA", stats.CountsByGroup[0]["groupKey"]) } @@ -142,7 +143,7 @@ func TestFindingsFilter_ArchiveActionHonoured(t *testing.T) { var listResp struct { FindingIDs []string `json:"findingIds"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.FindingIDs, 2) rec4 := doRequest(t, h, http.MethodPost, "/findings/describe", map[string]any{ @@ -153,7 +154,7 @@ func TestFindingsFilter_ArchiveActionHonoured(t *testing.T) { var describeResp struct { Findings []map[string]any `json:"findings"` } - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &describeResp, jsonx.V1())) require.Len(t, describeResp.Findings, 2) for _, f := range describeResp.Findings { @@ -189,7 +190,7 @@ func TestListFindings_SortCriteriaHonoured(t *testing.T) { var listResp struct { FindingIDs []string `json:"findingIds"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.FindingIDs, 2) rec3 := doRequest(t, h, http.MethodPost, "/findings/describe", map[string]any{ @@ -200,7 +201,7 @@ func TestListFindings_SortCriteriaHonoured(t *testing.T) { var describeResp struct { Findings []macie2.Finding `json:"findings"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &describeResp, jsonx.V1())) byID := make(map[string]string, len(describeResp.Findings)) for _, f := range describeResp.Findings { @@ -236,7 +237,7 @@ func TestListClassificationJobs_SortCriteriaHonoured(t *testing.T) { var resp struct { Items []map[string]any `json:"items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Items, 2) assert.Equal(t, "zzz-job", resp.Items[0]["name"]) diff --git a/services/macie2/multi_region_test.go b/services/macie2/multi_region_test.go index b307d1465d..b37c623342 100644 --- a/services/macie2/multi_region_test.go +++ b/services/macie2/multi_region_test.go @@ -2,7 +2,8 @@ package macie2_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -180,8 +182,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/macie2/pagination_tie_test.go b/services/macie2/pagination_tie_test.go index 11063a361a..58ec372854 100644 --- a/services/macie2/pagination_tie_test.go +++ b/services/macie2/pagination_tie_test.go @@ -1,7 +1,7 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -54,7 +55,7 @@ func TestDescribeBuckets_TiedObjectCount_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) buckets, _ := resp["buckets"].([]any) for _, item := range buckets { @@ -105,7 +106,7 @@ func TestListClassificationJobs_TiedName_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) created[resp["jobId"]] = true } @@ -120,7 +121,7 @@ func TestListClassificationJobs_TiedName_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["items"].([]any) for _, item := range items { @@ -168,7 +169,7 @@ func TestListCustomDataIdentifiers_TiedName_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) created[resp["customDataIdentifierId"]] = true } @@ -180,7 +181,7 @@ func TestListCustomDataIdentifiers_TiedName_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["items"].([]any) for _, item := range items { @@ -228,7 +229,7 @@ func TestListAllowLists_TiedName_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) created[resp["id"]] = true } @@ -240,7 +241,7 @@ func TestListAllowLists_TiedName_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["allowLists"].([]any) for _, item := range items { @@ -286,7 +287,7 @@ func TestListFindingsFilters_TiedPosition_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) created[resp["id"]] = true } @@ -298,7 +299,7 @@ func TestListFindingsFilters_TiedPosition_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["findingsFilterListItems"].([]any) for _, item := range items { @@ -348,7 +349,7 @@ func TestListFindings_TiedType_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, truthRec.Code) var truthResp map[string]any - require.NoError(t, json.Unmarshal(truthRec.Body.Bytes(), &truthResp)) + require.NoError(t, json.Unmarshal(truthRec.Body.Bytes(), &truthResp, jsonx.V1())) truthIDs, _ := truthResp["findingIds"].([]any) require.Len(t, truthIDs, dupCount) @@ -369,7 +370,7 @@ func TestListFindings_TiedType_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) ids, _ := resp["findingIds"].([]any) for _, id := range ids { diff --git a/services/macie2/persistence.go b/services/macie2/persistence.go index b3b7a57e14..75bb9ea699 100644 --- a/services/macie2/persistence.go +++ b/services/macie2/persistence.go @@ -2,7 +2,7 @@ package macie2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -52,7 +52,7 @@ const macie2SnapshotVersion = 3 // ClassExportConfig, FindingsPubConfig, and RevealConfig are single pointers, // not collections, and are persisted directly alongside the tables. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Session *Session `json:"session,omitempty"` Tags map[string]map[string]string `json:"tags"` Administrator *AdministratorAccount `json:"administrator,omitempty"` diff --git a/services/macie2/tag_leak_test.go b/services/macie2/tag_leak_test.go index a7214cfe9c..02bc109c6f 100644 --- a/services/macie2/tag_leak_test.go +++ b/services/macie2/tag_leak_test.go @@ -1,13 +1,14 @@ package macie2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/macie2" ) @@ -31,7 +32,7 @@ func TestMacie2_Delete_ClearsTags(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) arnStr, id := created["arn"], created["id"] require.NotEmpty(t, arnStr) @@ -45,7 +46,7 @@ func TestMacie2_Delete_ClearsTags(t *testing.T) { }) require.Equal(t, http.StatusOK, otherRec.Code) var otherCreated map[string]string - require.NoError(t, json.Unmarshal(otherRec.Body.Bytes(), &otherCreated)) + require.NoError(t, json.Unmarshal(otherRec.Body.Bytes(), &otherCreated, jsonx.V1())) otherArn := otherCreated["arn"] otherRec = doRequest( t, h, http.MethodPost, "/tags/"+otherArn, map[string]any{"tags": map[string]string{"k": "v"}}, @@ -61,7 +62,7 @@ func TestMacie2_Delete_ClearsTags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/tags/"+otherArn, nil) require.Equal(t, http.StatusOK, rec.Code) var otherTags map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &otherTags)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &otherTags, jsonx.V1())) assert.NotEmpty(t, otherTags["tags"]) }) @@ -76,7 +77,7 @@ func TestMacie2_Delete_ClearsTags(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var created map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) arnStr, id := created["arn"], created["id"] require.NotEmpty(t, arnStr) @@ -96,6 +97,6 @@ func assertMacie2SnapshotTagsCleared(t *testing.T, h *macie2.Handler, arnStr str var probe struct { Tags map[string]map[string]string `json:"tags"` } - require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &probe)) + require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &probe, jsonx.V1())) assert.NotContains(t, probe.Tags, arnStr) } diff --git a/services/managedblockchain/accessors_test.go b/services/managedblockchain/accessors_test.go index aa0245f9c8..a3e131bf45 100644 --- a/services/managedblockchain/accessors_test.go +++ b/services/managedblockchain/accessors_test.go @@ -2,7 +2,8 @@ package managedblockchain_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -70,7 +72,7 @@ func TestHandler_CreateAccessor(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) } }) @@ -111,7 +113,7 @@ func TestHandler_GetAccessor(t *testing.T) { var out struct { AccessorID string `json:"AccessorId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &out, jsonx.V1())) id := tt.accessorID if id == "" { @@ -123,7 +125,7 @@ func TestHandler_GetAccessor(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Accessor") } }) @@ -155,7 +157,7 @@ func TestHandler_DeleteAccessor(t *testing.T) { var out struct { AccessorID string `json:"AccessorId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &out, jsonx.V1())) rec := doRequest(t, h, http.MethodDelete, "/accessors/"+out.AccessorID, nil) assert.Equal(t, tt.wantStatus, rec.Code) @@ -171,7 +173,7 @@ func TestHandler_DeleteAccessor(t *testing.T) { Status string `json:"Status"` } `json:"Accessor"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, "PENDING_DELETION", getOut.Accessor.Status) }) } @@ -208,7 +210,7 @@ func TestHandler_ListAccessors(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accessors, ok := resp["Accessors"].([]any) require.True(t, ok) @@ -246,7 +248,7 @@ func TestHandler_AccessorRoundTrip(t *testing.T) { BillingToken string `json:"BillingToken"` NetworkType string `json:"NetworkType"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut.AccessorID) assert.NotEmpty(t, createOut.BillingToken) assert.Equal(t, "ETHEREUM_MAINNET", createOut.NetworkType) @@ -258,7 +260,7 @@ func TestHandler_AccessorRoundTrip(t *testing.T) { var getOut struct { Accessor map[string]any `json:"Accessor"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, "AVAILABLE", getOut.Accessor["Status"]) // List. @@ -268,7 +270,7 @@ func TestHandler_AccessorRoundTrip(t *testing.T) { var listOut struct { Accessors []map[string]any `json:"Accessors"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listOut, jsonx.V1())) assert.Len(t, listOut.Accessors, 1) // Delete. @@ -284,7 +286,7 @@ func TestHandler_AccessorRoundTrip(t *testing.T) { var listOut2 struct { Accessors []map[string]any `json:"Accessors"` } - require.NoError(t, json.NewDecoder(listRec2.Body).Decode(&listOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec2.Body), &listOut2, jsonx.V1())) require.Len(t, listOut2.Accessors, 1) assert.Equal(t, "PENDING_DELETION", listOut2.Accessors[0]["Status"]) }) @@ -359,7 +361,7 @@ func TestHandler_ListAccessorsFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) accessors := resp["Accessors"].([]any) assert.Len(t, accessors, tt.wantCount) @@ -474,7 +476,7 @@ func TestHandler_AccessorLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) accessorID, _ := createResp["AccessorId"].(string) require.NotEmpty(t, accessorID) @@ -485,7 +487,7 @@ func TestHandler_AccessorLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) accessor := getResp["Accessor"].(map[string]any) assert.Equal(t, accessorID, accessor["Id"]) @@ -496,7 +498,7 @@ func TestHandler_AccessorLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) accessors := listResp["Accessors"].([]any) assert.Len(t, accessors, 1) @@ -511,7 +513,7 @@ func TestHandler_AccessorLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec5.Code) var getResp5 map[string]any - require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &getResp5)) + require.NoError(t, json.Unmarshal(rec5.Body.Bytes(), &getResp5, jsonx.V1())) accessor5 := getResp5["Accessor"].(map[string]any) assert.Equal(t, "PENDING_DELETION", accessor5["Status"]) }) diff --git a/services/managedblockchain/framework_attributes_test.go b/services/managedblockchain/framework_attributes_test.go index 8b0f9edb1f..d4bac9d0a1 100644 --- a/services/managedblockchain/framework_attributes_test.go +++ b/services/managedblockchain/framework_attributes_test.go @@ -1,12 +1,14 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_CreateNetwork_FrameworkConfiguration verifies CreateNetwork's @@ -73,7 +75,7 @@ func TestHandler_CreateNetwork_FrameworkConfiguration(t *testing.T) { var createResp struct { NetworkID string `json:"NetworkId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/networks/"+createResp.NetworkID, nil) require.Equal(t, http.StatusOK, rec.Code) @@ -89,7 +91,7 @@ func TestHandler_CreateNetwork_FrameworkConfiguration(t *testing.T) { VpcEndpointServiceName string `json:"VpcEndpointServiceName"` } `json:"Network"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotEmpty(t, getResp.Network.VpcEndpointServiceName, "VpcEndpointServiceName must be populated regardless of FrameworkConfiguration") @@ -294,7 +296,7 @@ func TestHandler_CreateMember_FrameworkAttributesRoundTrip(t *testing.T) { var createResp struct { MemberID string `json:"MemberId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/networks/"+networkID+"/members/"+createResp.MemberID, nil) require.Equal(t, http.StatusOK, rec.Code) @@ -310,7 +312,7 @@ func TestHandler_CreateMember_FrameworkAttributesRoundTrip(t *testing.T) { } `json:"FrameworkAttributes"` } `json:"Member"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "admin", getResp.Member.FrameworkAttributes.Fabric.AdminUsername) assert.NotEmpty(t, getResp.Member.FrameworkAttributes.Fabric.CaEndpoint) @@ -364,7 +366,7 @@ func TestHandler_CreateNode_FrameworkAttributesRoundTrip(t *testing.T) { var createResp struct { NodeID string `json:"NodeId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/networks/"+networkID+"/nodes/"+createResp.NodeID+"?memberId="+memberID, nil) @@ -382,7 +384,7 @@ func TestHandler_CreateNode_FrameworkAttributesRoundTrip(t *testing.T) { } `json:"FrameworkAttributes"` } `json:"Node"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.wantStateDB, getResp.Node.StateDB) assert.Equal(t, "AWS Owned KMS Key", getResp.Node.KmsKeyArn, diff --git a/services/managedblockchain/handler_accessors.go b/services/managedblockchain/handler_accessors.go index 20dba28190..e3ca32fbcf 100644 --- a/services/managedblockchain/handler_accessors.go +++ b/services/managedblockchain/handler_accessors.go @@ -1,16 +1,18 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateAccessor(c *echo.Context, body []byte) error { var req createAccessorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } diff --git a/services/managedblockchain/handler_members.go b/services/managedblockchain/handler_members.go index 24ca90d926..680e8ae539 100644 --- a/services/managedblockchain/handler_members.go +++ b/services/managedblockchain/handler_members.go @@ -1,10 +1,12 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateMember(c *echo.Context, networkID string, body []byte) error { @@ -14,7 +16,7 @@ func (h *Handler) handleCreateMember(c *echo.Context, networkID string, body []b var req createMemberRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } @@ -124,7 +126,7 @@ func (h *Handler) handleUpdateMember(c *echo.Context, resource string, body []by var req updateMemberRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } diff --git a/services/managedblockchain/handler_networks.go b/services/managedblockchain/handler_networks.go index 1416e6b303..31856782ea 100644 --- a/services/managedblockchain/handler_networks.go +++ b/services/managedblockchain/handler_networks.go @@ -1,16 +1,18 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateNetwork(c *echo.Context, body []byte) error { var req createNetworkRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } diff --git a/services/managedblockchain/handler_nodes.go b/services/managedblockchain/handler_nodes.go index 4e049d2c03..4fd90fdb96 100644 --- a/services/managedblockchain/handler_nodes.go +++ b/services/managedblockchain/handler_nodes.go @@ -1,10 +1,12 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateNode handles POST /networks/{networkId}/nodes. Unlike member @@ -17,7 +19,7 @@ func (h *Handler) handleCreateNode(c *echo.Context, networkID string, body []byt } var req createNodeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } @@ -141,7 +143,7 @@ func (h *Handler) handleUpdateNode(c *echo.Context, resource string, body []byte var req updateNodeRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } } diff --git a/services/managedblockchain/handler_proposals.go b/services/managedblockchain/handler_proposals.go index 356250c66f..10c846f519 100644 --- a/services/managedblockchain/handler_proposals.go +++ b/services/managedblockchain/handler_proposals.go @@ -1,10 +1,12 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateProposal(c *echo.Context, networkID string, body []byte) error { @@ -14,7 +16,7 @@ func (h *Handler) handleCreateProposal(c *echo.Context, networkID string, body [ var req createProposalRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } @@ -128,7 +130,7 @@ func (h *Handler) handleVoteOnProposal(c *echo.Context, resource string, body [] var req voteOnProposalRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } diff --git a/services/managedblockchain/handler_sdk_route_table_test.go b/services/managedblockchain/handler_sdk_route_table_test.go index 3898d2a8e3..b4b62e31b7 100644 --- a/services/managedblockchain/handler_sdk_route_table_test.go +++ b/services/managedblockchain/handler_sdk_route_table_test.go @@ -1,7 +1,7 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -116,7 +117,7 @@ func TestExtractOperation_SDKRouteTable(t *testing.T) { var resp struct { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEqual(t, "resource not found", resp.Message, "method=%s path=%s op=%s: dispatched to the unmatched-route default", tc.method, tc.path, tc.op) }) diff --git a/services/managedblockchain/handler_tags.go b/services/managedblockchain/handler_tags.go index 4175bd5551..a8b283de87 100644 --- a/services/managedblockchain/handler_tags.go +++ b/services/managedblockchain/handler_tags.go @@ -1,11 +1,13 @@ package managedblockchain import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTagsForResource(c *echo.Context, resourceARN string) error { @@ -30,7 +32,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string, body [] var req tagResourceRequest - if parseErr := json.Unmarshal(body, &req); parseErr != nil { + if parseErr := json.Unmarshal(body, &req, jsonx.V1()); parseErr != nil { return writeError(c, http.StatusBadRequest, "InvalidRequestException", "invalid request body") } diff --git a/services/managedblockchain/handler_test.go b/services/managedblockchain/handler_test.go index 0afbe440a6..3598b04f8a 100644 --- a/services/managedblockchain/handler_test.go +++ b/services/managedblockchain/handler_test.go @@ -1,7 +1,7 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_HandlerMetadata(t *testing.T) { @@ -341,7 +343,7 @@ func TestHandler_ErrorResponseHasCodeField(t *testing.T) { assert.Equal(t, tt.wantHTTP, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantCode, resp["Code"], "error response must include Code field; body: %s", rec.Body.String()) assert.NotEmpty(t, resp["message"], @@ -388,7 +390,7 @@ func TestHandler_ErrorResponseMessageNotEmpty(t *testing.T) { assert.NotEqual(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["message"], "error response must include non-empty message") assert.NotEmpty(t, resp["Code"], "error response must include non-empty Code") }) diff --git a/services/managedblockchain/input_validation_test.go b/services/managedblockchain/input_validation_test.go index 7be832329f..77ebc98b15 100644 --- a/services/managedblockchain/input_validation_test.go +++ b/services/managedblockchain/input_validation_test.go @@ -1,13 +1,15 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func networkBody(mutate func(body, member, fabric map[string]any)) map[string]any { @@ -108,7 +110,7 @@ func TestCreateNetwork_InputValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["Code"]) assert.NotContains(t, resp["message"], "InvalidRequestException") }) @@ -122,7 +124,7 @@ func TestCreateNetwork_RealisticIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Regexp(t, `^n-[A-Z2-7]{26}$`, resp["NetworkId"]) assert.Regexp(t, `^m-[A-Z2-7]{26}$`, resp["MemberId"]) } @@ -134,7 +136,7 @@ func TestErrorMessages_NoCodePrefix(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["Code"]) assert.NotContains(t, resp["message"], "ResourceNotFoundException") } diff --git a/services/managedblockchain/invitations_test.go b/services/managedblockchain/invitations_test.go index 8e4c01d8a7..0bf1d22962 100644 --- a/services/managedblockchain/invitations_test.go +++ b/services/managedblockchain/invitations_test.go @@ -1,13 +1,15 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -42,7 +44,7 @@ func TestHandler_ListInvitations(t *testing.T) { var resp struct { Invitations []map[string]any `json:"Invitations"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Len(t, resp.Invitations, tt.wantLen) }) } @@ -119,7 +121,7 @@ func TestHandler_InvitationNetworkSummary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) invitations := resp["Invitations"].([]any) require.Len(t, invitations, 1) @@ -153,7 +155,7 @@ func TestHandler_InvitationLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) invitations := listResp["Invitations"].([]any) assert.Len(t, invitations, 1) @@ -199,7 +201,7 @@ func TestHandler_InvitationOmitsTopLevelNetworkFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) invitations := resp["Invitations"].([]any) require.Len(t, invitations, 1) diff --git a/services/managedblockchain/members_test.go b/services/managedblockchain/members_test.go index ef58dec0ac..53be6e30b3 100644 --- a/services/managedblockchain/members_test.go +++ b/services/managedblockchain/members_test.go @@ -1,7 +1,7 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -128,7 +129,7 @@ func TestHandler_MemberLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createNetResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createNetResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createNetResp, jsonx.V1())) networkID := createNetResp["NetworkId"].(string) // Create member @@ -142,7 +143,7 @@ func TestHandler_MemberLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createMemResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createMemResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createMemResp, jsonx.V1())) memberID := createMemResp["MemberId"].(string) assert.NotEmpty(t, memberID) @@ -155,7 +156,7 @@ func TestHandler_MemberLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) members, ok := listResp["Members"].([]any) require.True(t, ok) assert.Len(t, members, 2) @@ -430,7 +431,7 @@ func TestHandler_ListMembersFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members := resp["Members"].([]any) assert.Len(t, members, tt.wantCount) @@ -523,7 +524,7 @@ func TestHandler_MemberSummaryIsOwned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) members := resp["Members"].([]any) require.Len(t, members, 1) @@ -552,7 +553,7 @@ func TestHandler_MemberObjectIsOwned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) member := resp["Member"].(map[string]any) isOwned, ok := member["IsOwned"] @@ -610,7 +611,7 @@ func TestHandler_UpdateMemberLogPublishingConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) member := getResp["Member"].(map[string]any) logConfig, ok := member["LogPublishingConfiguration"] @@ -708,7 +709,7 @@ func TestHandler_CreateMemberWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) memberID, _ := resp["MemberId"].(string) require.NotEmpty(t, memberID) @@ -718,7 +719,7 @@ func TestHandler_CreateMemberWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var memResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1())) member := memResp["Member"].(map[string]any) tags := member["Tags"].(map[string]any) diff --git a/services/managedblockchain/multi_region_test.go b/services/managedblockchain/multi_region_test.go index d530c57313..5824f23b7e 100644 --- a/services/managedblockchain/multi_region_test.go +++ b/services/managedblockchain/multi_region_test.go @@ -2,7 +2,8 @@ package managedblockchain_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -198,8 +200,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/managedblockchain/networks_test.go b/services/managedblockchain/networks_test.go index 851fb6bbf6..3265ceec9d 100644 --- a/services/managedblockchain/networks_test.go +++ b/services/managedblockchain/networks_test.go @@ -2,7 +2,7 @@ package managedblockchain_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -275,7 +276,7 @@ func TestHandler_CreateNetwork(t *testing.T) { if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) } }) @@ -316,7 +317,7 @@ func TestHandler_GetNetwork(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) networkID := createResp["NetworkId"].(string) id := tt.networkID @@ -329,7 +330,7 @@ func TestHandler_GetNetwork(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Network") } }) @@ -376,7 +377,7 @@ func TestHandler_ListNetworks(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) networks, ok := resp["Networks"].([]any) require.True(t, ok) @@ -466,7 +467,7 @@ func TestHandler_VotingPolicyStoredAndReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) networkID := createResp["NetworkId"].(string) @@ -474,7 +475,7 @@ func TestHandler_VotingPolicyStoredAndReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) network := getResp["Network"].(map[string]any) @@ -549,7 +550,7 @@ func TestHandler_ListNetworksFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) networks := resp["Networks"].([]any) assert.Len(t, networks, tt.wantCount) @@ -674,7 +675,7 @@ func TestHandler_CreateNetworkWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) networkID, _ := resp["NetworkId"].(string) require.NotEmpty(t, networkID) @@ -684,7 +685,7 @@ func TestHandler_CreateNetworkWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &netResp, jsonx.V1())) network := netResp["Network"].(map[string]any) tags := network["Tags"].(map[string]any) @@ -713,7 +714,7 @@ func TestHandler_CreateNetworkFoundingMemberTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) networkID, _ := resp["NetworkId"].(string) memberID, _ := resp["MemberId"].(string) @@ -724,7 +725,7 @@ func TestHandler_CreateNetworkFoundingMemberTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var memResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &memResp, jsonx.V1())) member := memResp["Member"].(map[string]any) tags := member["Tags"].(map[string]any) diff --git a/services/managedblockchain/nodes_test.go b/services/managedblockchain/nodes_test.go index d6eccfe9a5..bb9b415d2d 100644 --- a/services/managedblockchain/nodes_test.go +++ b/services/managedblockchain/nodes_test.go @@ -1,7 +1,8 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -39,7 +41,7 @@ func TestHandler_NodeLifecycle_RealWireShape(t *testing.T) { var createOut struct { NodeID string `json:"NodeId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) require.NotEmpty(t, createOut.NodeID) nodePath := "/networks/" + netID + "/nodes/" + createOut.NodeID + "?memberId=" + memID @@ -163,7 +165,7 @@ func TestHandler_GetNode(t *testing.T) { var createOut struct { NodeID string `json:"NodeId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) getPath := fmt.Sprintf("%s/%s?memberId=%s", nodesPath, createOut.NodeID, memID) rec := doRequest(t, h, http.MethodGet, getPath, nil) @@ -210,7 +212,7 @@ func TestHandler_ListNodes(t *testing.T) { var out struct { Nodes []map[string]any `json:"Nodes"` } - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &out, jsonx.V1())) assert.Len(t, out.Nodes, tt.wantLen) }) } @@ -244,7 +246,7 @@ func TestHandler_DeleteNode(t *testing.T) { var createOut struct { NodeID string `json:"NodeId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) delPath := fmt.Sprintf("%s/%s?memberId=%s", nodesPath, createOut.NodeID, memID) rec := doRequest(t, h, http.MethodDelete, delPath, nil) @@ -377,7 +379,7 @@ func TestHandler_ListNodesFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nodes := resp["Nodes"].([]any) assert.Len(t, nodes, tt.wantCount) @@ -477,7 +479,7 @@ func TestHandler_NodeSummaryAvailabilityZone(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp, jsonx.V1())) nodes := listResp["Nodes"].([]any) require.Len(t, nodes, 1) @@ -550,7 +552,7 @@ func TestHandler_UpdateNodeLogPublishingConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) nodeResp := getResp["Node"].(map[string]any) logConfig, ok := nodeResp["LogPublishingConfiguration"] @@ -598,7 +600,7 @@ func TestHandler_CreateNodeWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nodeID, _ := resp["NodeId"].(string) require.NotEmpty(t, nodeID) @@ -609,7 +611,7 @@ func TestHandler_CreateNodeWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var nodeResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &nodeResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &nodeResp, jsonx.V1())) node := nodeResp["Node"].(map[string]any) tags := node["Tags"].(map[string]any) @@ -674,7 +676,7 @@ func TestHandler_NodeLifecycleBasicViaHTTP(t *testing.T) { } var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) nodeID, _ := createResp["NodeId"].(string) require.NotEmpty(t, nodeID) @@ -685,7 +687,7 @@ func TestHandler_NodeLifecycleBasicViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) node := getResp["Node"].(map[string]any) assert.Equal(t, nodeID, node["Id"]) @@ -697,7 +699,7 @@ func TestHandler_NodeLifecycleBasicViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) nodes := listResp["Nodes"].([]any) assert.Len(t, nodes, 1) diff --git a/services/managedblockchain/pagination_test.go b/services/managedblockchain/pagination_test.go index 011d631e39..7a3a13e8f9 100644 --- a/services/managedblockchain/pagination_test.go +++ b/services/managedblockchain/pagination_test.go @@ -1,13 +1,15 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListNetworks_Pagination verifies ListNetworks honors @@ -33,7 +35,7 @@ func TestHandler_ListNetworks_Pagination(t *testing.T) { rec := doRequestWithQuery(t, h, "/networks", map[string]string{"maxResults": "2"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Networks, 2) require.NotEmpty(t, page1.NextToken, "a 5-item list capped at maxResults=2 must return a NextToken") @@ -41,7 +43,7 @@ func TestHandler_ListNetworks_Pagination(t *testing.T) { rec = doRequestWithQuery(t, h, "/networks", map[string]string{"maxResults": "2", "nextToken": page1.NextToken}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Networks, 2) require.NotEmpty(t, page2.NextToken) @@ -49,7 +51,7 @@ func TestHandler_ListNetworks_Pagination(t *testing.T) { rec = doRequestWithQuery(t, h, "/networks", map[string]string{"maxResults": "2", "nextToken": page2.NextToken}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page3)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page3, jsonx.V1())) assert.Len(t, page3.Networks, 1) assert.Empty(t, page3.NextToken, "the final page must omit NextToken") @@ -69,7 +71,7 @@ func TestHandler_ListNetworks_Pagination(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/networks", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &unpaged)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &unpaged, jsonx.V1())) assert.Len(t, unpaged.Networks, 5) assert.Empty(t, unpaged.NextToken) } @@ -109,7 +111,7 @@ func TestHandler_ListMembers_Pagination(t *testing.T) { rec := doRequestWithQuery(t, h, "/networks/"+networkID+"/members", map[string]string{"maxResults": "3"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Members, 3) require.NotEmpty(t, page1.NextToken) @@ -121,7 +123,7 @@ func TestHandler_ListMembers_Pagination(t *testing.T) { rec = doRequestWithQuery(t, h, "/networks/"+networkID+"/members", map[string]string{"maxResults": "3", "nextToken": page1.NextToken}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Members, 1) assert.Empty(t, page2.NextToken) } diff --git a/services/managedblockchain/persistence.go b/services/managedblockchain/persistence.go index 68fc780427..d41dd9dc04 100644 --- a/services/managedblockchain/persistence.go +++ b/services/managedblockchain/persistence.go @@ -2,7 +2,7 @@ package managedblockchain import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -63,8 +63,8 @@ func buildProposalVoteDTORegistry() (*store.Registry, *store.Table[proposalVoteD // is a derived reverse-lookup cache rebuilt from the tables above by // rebuildARNIndexLocked on Restore, exactly as it was before this refactor. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -141,7 +141,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreTablesLocked rebuilds every store.Table on b from tables' per-table // JSON, factored out of Restore to keep Restore's own cognitive complexity // low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreTablesLocked(tables map[string]jsontext.Value) error { if err := b.registry.RestoreAll(tables); err != nil { return fmt.Errorf("managedblockchain: restore tables: %w", err) } diff --git a/services/managedblockchain/persistence_test.go b/services/managedblockchain/persistence_test.go index c693ad79dd..aee491df59 100644 --- a/services/managedblockchain/persistence_test.go +++ b/services/managedblockchain/persistence_test.go @@ -1,12 +1,13 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -366,11 +367,11 @@ func TestManagedBlockchain_PersistenceVersionMismatch(t *testing.T) { require.NotNil(t, snap) var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) tt.mutate(t, raw) - mutated, err := json.Marshal(raw) + mutated, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) // Seed b2 with unrelated pre-existing state so a discarded diff --git a/services/managedblockchain/proposals_test.go b/services/managedblockchain/proposals_test.go index 4d666de547..12be123952 100644 --- a/services/managedblockchain/proposals_test.go +++ b/services/managedblockchain/proposals_test.go @@ -2,7 +2,8 @@ package managedblockchain_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -75,7 +77,7 @@ func TestHandler_CreateProposal(t *testing.T) { if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) } }) @@ -104,7 +106,7 @@ func TestCreateProposal_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) proposalID, _ := resp["ProposalId"].(string) require.NotEmpty(t, proposalID) @@ -112,7 +114,7 @@ func TestCreateProposal_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) proposal := getResp["Proposal"].(map[string]any) proposalArn, _ := proposal["Arn"].(string) require.NotEmpty(t, proposalArn) @@ -158,7 +160,7 @@ func TestHandler_GetProposal(t *testing.T) { var createOut struct { ProposalID string `json:"ProposalId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) pid := tt.proposalID if pid == "" { @@ -170,7 +172,7 @@ func TestHandler_GetProposal(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Proposal") } }) @@ -210,7 +212,7 @@ func TestHandler_ListProposals(t *testing.T) { var resp struct { Proposals []map[string]any `json:"Proposals"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Len(t, resp.Proposals, tt.wantLen) }) } @@ -243,7 +245,7 @@ func TestHandler_ListProposalVotes(t *testing.T) { var createOut struct { ProposalID string `json:"ProposalId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) path := fmt.Sprintf("/networks/%s/proposals/%s/votes", netID, createOut.ProposalID) rec := doRequest(t, h, http.MethodGet, path, nil) @@ -252,7 +254,7 @@ func TestHandler_ListProposalVotes(t *testing.T) { var resp struct { ProposalVotes []map[string]any `json:"ProposalVotes"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Len(t, resp.ProposalVotes, tt.wantLen) }) } @@ -314,7 +316,7 @@ func TestHandler_ProposalRoundTrip(t *testing.T) { var createOut struct { ProposalID string `json:"ProposalId"` } - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut.ProposalID) // Get. @@ -325,7 +327,7 @@ func TestHandler_ProposalRoundTrip(t *testing.T) { var getOut struct { Proposal map[string]any `json:"Proposal"` } - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &getOut, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", getOut.Proposal["Status"]) // List votes. @@ -336,7 +338,7 @@ func TestHandler_ProposalRoundTrip(t *testing.T) { var votesOut struct { ProposalVotes []map[string]any `json:"ProposalVotes"` } - require.NoError(t, json.NewDecoder(votesRec.Body).Decode(&votesOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(votesRec.Body), &votesOut, jsonx.V1())) assert.Empty(t, votesOut.ProposalVotes) }) } @@ -442,7 +444,7 @@ func TestHandler_ProposalActionsStoredAndReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) proposalID := createResp["ProposalId"].(string) @@ -450,7 +452,7 @@ func TestHandler_ProposalActionsStoredAndReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) proposal := getResp["Proposal"].(map[string]any) @@ -498,7 +500,7 @@ func TestHandler_ProposalSummaryOmitsNetworkID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) proposals := resp["Proposals"].([]any) require.Len(t, proposals, 1) @@ -535,7 +537,7 @@ func TestHandler_ListProposalsStatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) proposals, _ := listResp["Proposals"].([]any) assert.Len(t, proposals, 2, @@ -548,7 +550,7 @@ func TestHandler_ListProposalsStatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, listApprovedRec.Code) var listApprovedResp map[string]any - require.NoError(t, json.Unmarshal(listApprovedRec.Body.Bytes(), &listApprovedResp)) + require.NoError(t, json.Unmarshal(listApprovedRec.Body.Bytes(), &listApprovedResp, jsonx.V1())) approvedProposals, _ := listApprovedResp["Proposals"].([]any) assert.Empty(t, approvedProposals, @@ -579,7 +581,7 @@ func TestHandler_ListProposalsNoStatusFilterReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) ownerID := netResp["MemberId"].(string) @@ -590,7 +592,7 @@ func TestHandler_ListProposalsNoStatusFilterReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, propRec1.Code) var prop1 map[string]any - require.NoError(t, json.Unmarshal(propRec1.Body.Bytes(), &prop1)) + require.NoError(t, json.Unmarshal(propRec1.Body.Bytes(), &prop1, jsonx.V1())) propID1 := prop1["ProposalId"].(string) @@ -609,7 +611,7 @@ func TestHandler_ListProposalsNoStatusFilterReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) proposals, _ := listResp["Proposals"].([]any) assert.Len(t, proposals, 2, "listing without status filter must return all proposals") @@ -629,7 +631,7 @@ func TestHandler_ListProposalsNoStatusFilterReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, listApprovedRec.Code) var listApprovedResp map[string]any - require.NoError(t, json.Unmarshal(listApprovedRec.Body.Bytes(), &listApprovedResp)) + require.NoError(t, json.Unmarshal(listApprovedRec.Body.Bytes(), &listApprovedResp, jsonx.V1())) approvedProposals, _ := listApprovedResp["Proposals"].([]any) assert.Len(t, approvedProposals, 1, "filtering by APPROVED must return only approved proposals") @@ -671,7 +673,7 @@ func TestHandler_ProposalExpirationDateViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) proposalID, _ := createResp["ProposalId"].(string) require.NotEmpty(t, proposalID) @@ -680,7 +682,7 @@ func TestHandler_ProposalExpirationDateViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) proposal := getResp["Proposal"].(map[string]any) assert.NotEmpty(t, proposal["ExpirationDate"]) @@ -706,7 +708,7 @@ func TestHandler_ProposalLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) proposalID, _ := createResp["ProposalId"].(string) require.NotEmpty(t, proposalID) @@ -716,7 +718,7 @@ func TestHandler_ProposalLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) proposal := getResp["Proposal"].(map[string]any) assert.Equal(t, proposalID, proposal["ProposalId"]) @@ -728,7 +730,7 @@ func TestHandler_ProposalLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) proposals := listResp["Proposals"].([]any) assert.Len(t, proposals, 1) @@ -737,7 +739,7 @@ func TestHandler_ProposalLifecycleViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var votesResp map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &votesResp)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &votesResp, jsonx.V1())) votes := votesResp["ProposalVotes"].([]any) assert.Empty(t, votes) } diff --git a/services/managedblockchain/proposals_voting_test.go b/services/managedblockchain/proposals_voting_test.go index 4688be42ee..2f5dc2999d 100644 --- a/services/managedblockchain/proposals_voting_test.go +++ b/services/managedblockchain/proposals_voting_test.go @@ -1,7 +1,7 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -175,7 +176,7 @@ func TestHandler_ProposalOutstandingVoteCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["Proposal"].(map[string]any) outstanding := int(p["OutstandingVoteCount"].(float64)) @@ -257,7 +258,7 @@ func TestHandler_ProposalStatusTransitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createNetResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createNetResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createNetResp, jsonx.V1())) networkID := createNetResp["NetworkId"].(string) firstMemberID := createNetResp["MemberId"].(string) @@ -275,7 +276,7 @@ func TestHandler_ProposalStatusTransitions(t *testing.T) { require.Equal(t, http.StatusOK, memRec.Code) var createMemResp map[string]any - require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &createMemResp)) + require.NoError(t, json.Unmarshal(memRec.Body.Bytes(), &createMemResp, jsonx.V1())) extraMemberIDs = append(extraMemberIDs, createMemResp["MemberId"].(string)) } @@ -288,7 +289,7 @@ func TestHandler_ProposalStatusTransitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createPropResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createPropResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createPropResp, jsonx.V1())) proposalID := createPropResp["ProposalId"].(string) @@ -313,7 +314,7 @@ func TestHandler_ProposalStatusTransitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["Proposal"].(map[string]any) assert.Equal(t, tt.wantStatus, p["Status"]) @@ -353,7 +354,7 @@ func TestHandler_VoteOnProposalAlreadyCompleted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &netResp, jsonx.V1())) networkID := netResp["NetworkId"].(string) memberID := netResp["MemberId"].(string) @@ -365,7 +366,7 @@ func TestHandler_VoteOnProposalAlreadyCompleted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &propResp, jsonx.V1())) proposalID := propResp["ProposalId"].(string) votePath := fmt.Sprintf("/networks/%s/proposals/%s/votes", networkID, proposalID) @@ -382,7 +383,7 @@ func TestHandler_VoteOnProposalAlreadyCompleted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["Proposal"].(map[string]any) assert.Equal(t, "APPROVED", p["Status"]) @@ -415,7 +416,7 @@ func TestHandler_VoteThresholdFloatPrecision(t *testing.T) { require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) ownerMemberID := netResp["MemberId"].(string) @@ -450,7 +451,7 @@ func TestHandler_VoteThresholdFloatPrecision(t *testing.T) { require.Equal(t, http.StatusOK, propRec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp, jsonx.V1())) propID := propResp["ProposalId"].(string) votePath := fmt.Sprintf("/networks/%s/proposals/%s/votes", netID, propID) @@ -465,7 +466,7 @@ func TestHandler_VoteThresholdFloatPrecision(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["Proposal"].(map[string]any) assert.Equal(t, "APPROVED", p["Status"], @@ -497,7 +498,7 @@ func TestHandler_ApprovedProposalExecutesInvitationActions(t *testing.T) { require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) ownerMemberID := netResp["MemberId"].(string) @@ -507,7 +508,7 @@ func TestHandler_ApprovedProposalExecutesInvitationActions(t *testing.T) { require.Equal(t, http.StatusOK, listBefore.Code) var listBeforeResp map[string]any - require.NoError(t, json.Unmarshal(listBefore.Body.Bytes(), &listBeforeResp)) + require.NoError(t, json.Unmarshal(listBefore.Body.Bytes(), &listBeforeResp, jsonx.V1())) assert.Empty(t, listBeforeResp["Invitations"], "no invitations should exist before proposal approval") @@ -525,7 +526,7 @@ func TestHandler_ApprovedProposalExecutesInvitationActions(t *testing.T) { require.Equal(t, http.StatusOK, propRec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp, jsonx.V1())) propID := propResp["ProposalId"].(string) @@ -540,7 +541,7 @@ func TestHandler_ApprovedProposalExecutesInvitationActions(t *testing.T) { require.Equal(t, http.StatusOK, listAfter.Code) var listAfterResp map[string]any - require.NoError(t, json.Unmarshal(listAfter.Body.Bytes(), &listAfterResp)) + require.NoError(t, json.Unmarshal(listAfter.Body.Bytes(), &listAfterResp, jsonx.V1())) invitations, _ := listAfterResp["Invitations"].([]any) assert.Len(t, invitations, 1, @@ -573,7 +574,7 @@ func TestHandler_RejectionThresholdImpossibleApproval(t *testing.T) { require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) m0ID := netResp["MemberId"].(string) @@ -594,7 +595,7 @@ func TestHandler_RejectionThresholdImpossibleApproval(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r, jsonx.V1())) return r["MemberId"].(string) } @@ -610,7 +611,7 @@ func TestHandler_RejectionThresholdImpossibleApproval(t *testing.T) { require.Equal(t, http.StatusOK, propRec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp, jsonx.V1())) propID := propResp["ProposalId"].(string) votePath := fmt.Sprintf("/networks/%s/proposals/%s/votes", netID, propID) @@ -631,7 +632,7 @@ func TestHandler_RejectionThresholdImpossibleApproval(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["Proposal"].(map[string]any) assert.Equal(t, "REJECTED", p["Status"], @@ -662,7 +663,7 @@ func TestHandler_ProposalExpiresAfterExpirationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) p, ok := resp["Proposal"].(map[string]any) require.True(t, ok) assert.Equal(t, "EXPIRED", p["Status"]) @@ -677,7 +678,7 @@ func TestHandler_ProposalExpiresAfterExpirationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) proposals, ok := resp["Proposals"].([]any) require.True(t, ok) require.Len(t, proposals, 1) @@ -741,7 +742,7 @@ func TestHandler_ApprovedRemovalProposalCascadeDeletesEmptyNetwork(t *testing.T) require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) ownerMemberID := netResp["MemberId"].(string) @@ -759,7 +760,7 @@ func TestHandler_ApprovedRemovalProposalCascadeDeletesEmptyNetwork(t *testing.T) require.Equal(t, http.StatusOK, propRec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp, jsonx.V1())) propID := propResp["ProposalId"].(string) @@ -802,7 +803,7 @@ func TestHandler_ApprovedProposalActionFailedWhenTargetMemberAlreadyGone(t *test require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) netID := netResp["NetworkId"].(string) ownerID := netResp["MemberId"].(string) @@ -823,7 +824,7 @@ func TestHandler_ApprovedProposalActionFailedWhenTargetMemberAlreadyGone(t *test require.Equal(t, http.StatusOK, propRec.Code) var propResp map[string]any - require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp)) + require.NoError(t, json.Unmarshal(propRec.Body.Bytes(), &propResp, jsonx.V1())) propID := propResp["ProposalId"].(string) @@ -842,7 +843,7 @@ func TestHandler_ApprovedProposalActionFailedWhenTargetMemberAlreadyGone(t *test require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) proposal, ok := getResp["Proposal"].(map[string]any) require.True(t, ok) diff --git a/services/managedblockchain/store_test.go b/services/managedblockchain/store_test.go index df45f9acfb..b08fc0cfa5 100644 --- a/services/managedblockchain/store_test.go +++ b/services/managedblockchain/store_test.go @@ -2,7 +2,8 @@ package managedblockchain_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -61,7 +63,7 @@ func doRequest(t *testing.T, h *managedblockchain.Handler, method, path string, if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -133,7 +135,7 @@ func doRoutedRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -206,7 +208,7 @@ func createTestNetwork(t *testing.T, h *managedblockchain.Handler) (string, stri NetworkID string `json:"NetworkId"` MemberID string `json:"MemberId"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) return out.NetworkID, out.MemberID } diff --git a/services/managedblockchain/tags_test.go b/services/managedblockchain/tags_test.go index 088bc4d2f7..858a99ffaa 100644 --- a/services/managedblockchain/tags_test.go +++ b/services/managedblockchain/tags_test.go @@ -1,7 +1,7 @@ package managedblockchain_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/managedblockchain" ) @@ -138,7 +139,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) // Get the network to find its ARN networkID := createResp["NetworkId"].(string) @@ -146,7 +147,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &netResp, jsonx.V1())) network := netResp["Network"].(map[string]any) arn := network["Arn"].(string) assert.NotEmpty(t, arn) @@ -161,7 +162,7 @@ func TestHandler_TagOperations(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) @@ -233,7 +234,7 @@ func TestHandler_UntagResourceQuery(t *testing.T) { require.Equal(t, http.StatusOK, netRec.Code) var netResp map[string]any - require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp)) + require.NoError(t, json.Unmarshal(netRec.Body.Bytes(), &netResp, jsonx.V1())) network := netResp["Network"].(map[string]any) arn := network["Arn"].(string) @@ -298,7 +299,7 @@ func TestHandler_TagNodeViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].(map[string]any) assert.Equal(t, "gold", tags["tier"]) diff --git a/services/marketplaceentitlementservice/cbor.go b/services/marketplaceentitlementservice/cbor.go index 84aff4ef14..651350c58a 100644 --- a/services/marketplaceentitlementservice/cbor.go +++ b/services/marketplaceentitlementservice/cbor.go @@ -3,12 +3,15 @@ package marketplaceentitlementservice import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "strconv" "strings" "github.com/aws/smithy-go/encoding/cbor" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // The pinned SDK speaks Smithy RPCv2 CBOR (POST /service/AWSMPEntitlementService/operation/); @@ -33,7 +36,7 @@ func cborToJSONBytes(body []byte) ([]byte, error) { return nil, fail(ErrInvalidParameter, "expected a CBOR map") } - return json.Marshal(cborToAny(m)) + return json.Marshal(cborToAny(m), jsonx.V1()) } func cborToAny(v cbor.Value) any { @@ -55,13 +58,13 @@ func cborToAny(v cbor.Value) any { case cbor.String: return string(t) case cbor.Uint: - return json.Number(strconv.FormatUint(uint64(t), 10)) + return jsonx.Number(strconv.FormatUint(uint64(t), 10)) case cbor.NegInt: if uint64(t) > math.MaxInt64 { return float64(-1) - float64(t) } - return json.Number(strconv.FormatInt(-1-int64(t), 10)) //nolint:gosec // bounded by the MaxInt64 check above + return jsonx.Number(strconv.FormatInt(-1-int64(t), 10)) //nolint:gosec // bounded by the MaxInt64 check above case cbor.Float64: return float64(t) case cbor.Float32: @@ -78,11 +81,10 @@ func cborToAny(v cbor.Value) any { } func jsonToCBORBytes(body []byte) ([]byte, error) { - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fail(ErrInternalServiceError, "encode response: %v", err) } @@ -109,14 +111,14 @@ func anyToCBOR(v any, key string) cbor.Value { return cbor.String(t) case bool: return cbor.Bool(t) - case json.Number: + case jsonx.Number: return numberToCBOR(t, cborTimeKeys[key]) default: return &cbor.Nil{} } } -func numberToCBOR(n json.Number, timestamp bool) cbor.Value { +func numberToCBOR(n jsonx.Number, timestamp bool) cbor.Value { if !timestamp && !strings.ContainsAny(string(n), ".eE") { if i, err := n.Int64(); err == nil { if i >= 0 { diff --git a/services/marketplaceentitlementservice/handler.go b/services/marketplaceentitlementservice/handler.go index 82f1326fdc..85dca8cac0 100644 --- a/services/marketplaceentitlementservice/handler.go +++ b/services/marketplaceentitlementservice/handler.go @@ -1,7 +1,7 @@ package marketplaceentitlementservice import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -46,7 +47,7 @@ func decode(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return fail(ErrInvalidParameter, "malformed request body: %v", err) } @@ -148,7 +149,7 @@ func (h *Handler) Handler() echo.HandlerFunc { } func (h *Handler) writeCBOR(c *echo.Context, out any) error { - raw, err := json.Marshal(out) + raw, err := json.Marshal(out, jsonx.V1()) if err == nil { var enc []byte diff --git a/services/marketplaceentitlementservice/persistence.go b/services/marketplaceentitlementservice/persistence.go index e008500154..c664f97fce 100644 --- a/services/marketplaceentitlementservice/persistence.go +++ b/services/marketplaceentitlementservice/persistence.go @@ -2,7 +2,7 @@ package marketplaceentitlementservice import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/marketplacemetering/customers.go b/services/marketplacemetering/customers.go index 77cd241b3d..24318f4f85 100644 --- a/services/marketplacemetering/customers.go +++ b/services/marketplacemetering/customers.go @@ -5,11 +5,12 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ent "github.com/blackbirdworks/gopherstack/services/marketplaceentitlementservice" ) @@ -236,7 +237,7 @@ func (b *InMemoryBackend) IssueRegistrationToken(productCode, accountID string) issued := b.now().Unix() b.mu.RUnlock() - raw, _ := json.Marshal(tokenClaims{P: productCode, A: accountID, I: issued}) + raw, _ := json.Marshal(tokenClaims{P: productCode, A: accountID, I: issued}, jsonx.V1()) payload := base64.RawURLEncoding.EncodeToString(raw) return payload + "." + mac(payload), nil @@ -257,7 +258,8 @@ func (b *InMemoryBackend) ResolveCustomer(token string) (*ResolvedCustomer, erro var claims tokenClaims - if err != nil || json.Unmarshal(raw, &claims) != nil || !validProductCode(claims.P) || !validAccountID(claims.A) { + if err != nil || json.Unmarshal(raw, &claims, jsonx.V1()) != nil || !validProductCode(claims.P) || + !validAccountID(claims.A) { return nil, fail(ErrInvalidToken, "the registration token is not valid") } diff --git a/services/marketplacemetering/customers_test.go b/services/marketplacemetering/customers_test.go index b250d0d20a..e898132092 100644 --- a/services/marketplacemetering/customers_test.go +++ b/services/marketplacemetering/customers_test.go @@ -2,7 +2,7 @@ package marketplacemetering_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" mm "github.com/blackbirdworks/gopherstack/services/marketplacemetering" ) @@ -87,7 +88,7 @@ func TestRegisterUsage(t *testing.T) { require.NoError(t, decErr) var claims map[string]any - require.NoError(t, json.Unmarshal(raw, &claims)) + require.NoError(t, json.Unmarshal(raw, &claims, jsonx.V1())) assert.Equal(t, tt.product, claims["productCode"]) assert.Equal(t, "n-1", claims["nonce"]) assert.Equal(t, testAccount, claims["customerAWSAccountId"]) diff --git a/services/marketplacemetering/handler.go b/services/marketplacemetering/handler.go index f9d559dc86..cc2733c612 100644 --- a/services/marketplacemetering/handler.go +++ b/services/marketplacemetering/handler.go @@ -2,7 +2,7 @@ package marketplacemetering import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -82,7 +83,7 @@ func decode(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return fail(ErrValidation, "malformed request body: %v", err) } diff --git a/services/marketplacemetering/persistence.go b/services/marketplacemetering/persistence.go index 61161f167f..39f22270ce 100644 --- a/services/marketplacemetering/persistence.go +++ b/services/marketplacemetering/persistence.go @@ -2,7 +2,7 @@ package marketplacemetering import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/marketplacemetering/register.go b/services/marketplacemetering/register.go index 3db3223d05..42c26faef7 100644 --- a/services/marketplacemetering/register.go +++ b/services/marketplacemetering/register.go @@ -3,11 +3,12 @@ package marketplacemetering import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strconv" "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // RegisterUsageInput is the RegisterUsage request. @@ -67,11 +68,11 @@ func signRegistration(p *Product, in *RegisterUsageInput, account string, issued enc := base64.RawURLEncoding header, _ := json.Marshal(map[string]string{ "alg": "HS256", "typ": "JWT", "kid": "v" + strconv.Itoa(int(p.PublicKeyVersion)), - }) + }, jsonx.V1()) claims, _ := json.Marshal(map[string]any{ "productCode": in.ProductCode, "nonce": in.Nonce, "customerAWSAccountId": account, "publicKeyVersion": p.PublicKeyVersion, "iat": issued, - }) + }, jsonx.V1()) signing := enc.EncodeToString(header) + "." + enc.EncodeToString(claims) return signing + "." + enc.EncodeToString([]byte(mac(signing))) diff --git a/services/mediaconvert/endpoints_test.go b/services/mediaconvert/endpoints_test.go index 49036e6033..897666ac8c 100644 --- a/services/mediaconvert/endpoints_test.go +++ b/services/mediaconvert/endpoints_test.go @@ -2,7 +2,8 @@ package mediaconvert_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -41,7 +43,7 @@ func TestDescribeEndpoints_POST(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) endpoints, ok := out["endpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 1) @@ -73,7 +75,7 @@ func TestDescribeEndpoints_WithModeAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) endpoints, ok := out["endpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 1) @@ -93,7 +95,7 @@ func TestDescribeEndpoints_MaxResultsCaps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) endpoints, ok := out["endpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 1) diff --git a/services/mediaconvert/handler_certificates.go b/services/mediaconvert/handler_certificates.go index c1fda617d2..e9318f7c55 100644 --- a/services/mediaconvert/handler_certificates.go +++ b/services/mediaconvert/handler_certificates.go @@ -1,11 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseCertificateRoute(method, suffix string) mcRoute { @@ -34,7 +36,7 @@ type associateCertificateInput struct { func (h *Handler) handleAssociateCertificate(c *echo.Context, body []byte) error { var in associateCertificateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_endpoints.go b/services/mediaconvert/handler_endpoints.go index e8f314d7ab..905460443f 100644 --- a/services/mediaconvert/handler_endpoints.go +++ b/services/mediaconvert/handler_endpoints.go @@ -1,10 +1,12 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Endpoints handler --- @@ -27,7 +29,7 @@ type endpointEntry struct { func (h *Handler) handleDescribeEndpoints(c *echo.Context, body []byte) error { var in describeEndpointsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } } diff --git a/services/mediaconvert/handler_job_templates.go b/services/mediaconvert/handler_job_templates.go index faac04a49d..08ee60a3d7 100644 --- a/services/mediaconvert/handler_job_templates.go +++ b/services/mediaconvert/handler_job_templates.go @@ -1,12 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -60,7 +61,7 @@ type jobTemplatesListOutput struct { func (h *Handler) handleCreateJobTemplate(c *echo.Context, body []byte) error { var in createJobTemplateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -138,7 +139,7 @@ type updateJobTemplateInput struct { func (h *Handler) handleUpdateJobTemplate(c *echo.Context, name string, body []byte) error { var in updateJobTemplateInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_jobs.go b/services/mediaconvert/handler_jobs.go index 0efa62f2be..985fb45d2c 100644 --- a/services/mediaconvert/handler_jobs.go +++ b/services/mediaconvert/handler_jobs.go @@ -1,12 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -67,7 +68,7 @@ type jobsListOutput struct { func (h *Handler) handleCreateJob(c *echo.Context, body []byte) error { var in createJobInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -113,7 +114,7 @@ type updateJobInput struct { func (h *Handler) handleUpdateJob(c *echo.Context, id string, body []byte) error { var in updateJobInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_jobs_query.go b/services/mediaconvert/handler_jobs_query.go index a7b2c2e80c..73d4386dc7 100644 --- a/services/mediaconvert/handler_jobs_query.go +++ b/services/mediaconvert/handler_jobs_query.go @@ -1,11 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parseJobsQueriesRoute(method, suffix string) mcRoute { @@ -61,7 +63,7 @@ type startJobsQueryOutput struct { func (h *Handler) handleStartJobsQuery(c *echo.Context, body []byte) error { var in startJobsQueryInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_policy.go b/services/mediaconvert/handler_policy.go index 584cb4ff63..9c2c02817b 100644 --- a/services/mediaconvert/handler_policy.go +++ b/services/mediaconvert/handler_policy.go @@ -1,10 +1,12 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func parsePolicyRoute(method string) mcRoute { @@ -55,7 +57,7 @@ type policyInputEntry struct { func (h *Handler) handlePutPolicy(c *echo.Context, body []byte) error { var in putPolicyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_presets.go b/services/mediaconvert/handler_presets.go index 46f3cb2068..2ca68a8446 100644 --- a/services/mediaconvert/handler_presets.go +++ b/services/mediaconvert/handler_presets.go @@ -1,12 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -55,7 +56,7 @@ type presetsListOutput struct { func (h *Handler) handleCreatePreset(c *echo.Context, body []byte) error { var in createPresetInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -120,7 +121,7 @@ type updatePresetInput struct { func (h *Handler) handleUpdatePreset(c *echo.Context, name string, body []byte) error { var in updatePresetInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_probe.go b/services/mediaconvert/handler_probe.go index 2bd1ec93d9..f904e47523 100644 --- a/services/mediaconvert/handler_probe.go +++ b/services/mediaconvert/handler_probe.go @@ -1,10 +1,12 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Probe handler --- @@ -19,7 +21,7 @@ type probeOutput struct { func (h *Handler) handleProbe(c *echo.Context, body []byte) error { var in probeInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_queues.go b/services/mediaconvert/handler_queues.go index f8e0e4b64d..8864d2e773 100644 --- a/services/mediaconvert/handler_queues.go +++ b/services/mediaconvert/handler_queues.go @@ -1,12 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -62,7 +63,7 @@ type queuesListOutput struct { func (h *Handler) handleCreateQueue(c *echo.Context, body []byte) error { var in createQueueInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -124,7 +125,7 @@ type updateQueueInput struct { func (h *Handler) handleUpdateQueue(c *echo.Context, name string, body []byte) error { var in updateQueueInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_resource_shares.go b/services/mediaconvert/handler_resource_shares.go index 5e2092ddb9..89df8d11f2 100644 --- a/services/mediaconvert/handler_resource_shares.go +++ b/services/mediaconvert/handler_resource_shares.go @@ -1,10 +1,12 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- Resource share handlers --- @@ -16,7 +18,7 @@ type createResourceShareInput struct { func (h *Handler) handleCreateResourceShare(c *echo.Context, body []byte) error { var in createResourceShareInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_tags.go b/services/mediaconvert/handler_tags.go index 5740771c51..d97f9b1cd4 100644 --- a/services/mediaconvert/handler_tags.go +++ b/services/mediaconvert/handler_tags.go @@ -1,11 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseTagRoute maps tag-path requests to operations. Per the real @@ -70,7 +72,7 @@ func (h *Handler) handleListTagsForResource(c *echo.Context, resourceARN string) func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { var in tagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -85,7 +87,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { func (h *Handler) handleUntagResource(c *echo.Context, resourceARN string, body []byte) error { var in untagResourceInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mediaconvert/handler_test.go b/services/mediaconvert/handler_test.go index 3feef9e596..c3272fad80 100644 --- a/services/mediaconvert/handler_test.go +++ b/services/mediaconvert/handler_test.go @@ -2,7 +2,8 @@ package mediaconvert_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -30,7 +32,7 @@ func doRequest(t *testing.T, h *mediaconvert.Handler, method, path string, body var reqBody *bytes.Reader if body != nil { - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(bodyBytes) } else { @@ -71,7 +73,7 @@ func parseJSONResponse(t *testing.T, h *mediaconvert.Handler, method, path strin var resp map[string]any if rec.Body.Len() > 0 { - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) } return resp, rec.Code @@ -357,7 +359,7 @@ func TestErrValidationMappedTo400(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) job := resp["job"].(map[string]any) id := job["id"].(string) @@ -406,7 +408,7 @@ func TestListHandlers_ReturnEmptySlices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) list, ok := resp[tt.key] require.True(t, ok, "key %q missing from response", tt.key) diff --git a/services/mediaconvert/janitor_test.go b/services/mediaconvert/janitor_test.go index 93240829e3..9b5b88f3ed 100644 --- a/services/mediaconvert/janitor_test.go +++ b/services/mediaconvert/janitor_test.go @@ -1,7 +1,8 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -404,7 +406,7 @@ func TestFullJobLifecycle_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) jobID := jobData["id"].(string) assert.Equal(t, "SUBMITTED", jobData["status"]) @@ -418,7 +420,7 @@ func TestFullJobLifecycle_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out2 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out2, jsonx.V1())) j2 := out2["job"].(map[string]any) assert.Equal(t, "COMPLETE", j2["status"]) timing := j2["timing"].(map[string]any) diff --git a/services/mediaconvert/job_templates_test.go b/services/mediaconvert/job_templates_test.go index f22ef32d39..a7a6e3da5f 100644 --- a/services/mediaconvert/job_templates_test.go +++ b/services/mediaconvert/job_templates_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -27,7 +29,7 @@ func TestMediaConvert_JobTemplate_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) jtData, ok := createResp["jobTemplate"].(map[string]any) require.True(t, ok) assert.Equal(t, templateName, jtData["name"]) @@ -53,7 +55,7 @@ func TestMediaConvert_JobTemplate_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) updatedJT, ok := updateResp["jobTemplate"].(map[string]any) require.True(t, ok) assert.Equal(t, "updated description", updatedJT["description"]) @@ -118,7 +120,7 @@ func TestCreateJobTemplate_WithTags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) jt := resp["jobTemplate"].(map[string]any) tags := jt["tags"].(map[string]any) assert.Equal(t, "12345", tags["cost-center"]) @@ -165,7 +167,7 @@ func TestCreateJobTemplate_AccelerationHopDestinationsStatusUpdateInterval(t *te require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) jt := resp["jobTemplate"].(map[string]any) accel := jt["accelerationSettings"].(map[string]any) @@ -238,7 +240,7 @@ func TestUpdateJobTemplate_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) jt := resp["jobTemplate"].(map[string]any) accel := jt["accelerationSettings"].(map[string]any) diff --git a/services/mediaconvert/jobs_test.go b/services/mediaconvert/jobs_test.go index 7543ff2220..cc5a04bbf4 100644 --- a/services/mediaconvert/jobs_test.go +++ b/services/mediaconvert/jobs_test.go @@ -1,7 +1,8 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -23,7 +25,7 @@ func createTestJob(t *testing.T, h *mediaconvert.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) job, ok := resp["job"].(map[string]any) require.True(t, ok) id, _ := job["id"].(string) @@ -68,7 +70,7 @@ func TestMediaConvert_Job_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) jobData, ok := createResp["job"].(map[string]any) require.True(t, ok) assert.Equal(t, role, jobData["role"]) @@ -130,7 +132,7 @@ func TestCreateJob_WithTags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) j := resp["job"].(map[string]any) tags := j["tags"].(map[string]any) assert.Equal(t, "nightly", tags["run"]) @@ -279,7 +281,7 @@ func TestListJobs_OmitsTotalCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotContains(t, out, "totalCount") assert.Len(t, out["jobs"], 2) } @@ -336,7 +338,7 @@ func TestCreateJob_TimingViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) job := out["job"].(map[string]any) timing := job["timing"].(map[string]any) assert.Greater(t, timing["submitTime"], float64(0)) @@ -463,7 +465,7 @@ func TestUpdateJob_ViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData, ok := out["job"].(map[string]any) require.True(t, ok) assert.InDelta(t, float64(5), jobData["priority"], 0) @@ -511,7 +513,7 @@ func TestCreateJob_HopDestinationsViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) hops, ok := jobData["hopDestinations"].([]any) require.True(t, ok) @@ -588,7 +590,7 @@ func TestCreateJob_StatusUpdateIntervalViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) assert.Equal(t, "SECONDS_20", jobData["statusUpdateInterval"]) assert.Equal(t, "ENABLED", jobData["simulateReservedQueue"]) @@ -608,7 +610,7 @@ func TestCreateJob_AccelerationViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) assert.Equal(t, "PREFERRED", jobData["accelerationStatus"]) as := jobData["accelerationSettings"].(map[string]any) @@ -688,7 +690,7 @@ func TestCreateJob_MessagesFieldViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) _, hasMessages := jobData["messages"] assert.True(t, hasMessages, "messages field should be present") @@ -786,14 +788,14 @@ func TestCreateJob_ClientRequestTokenDedupViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec1.Code) var out1 map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&out1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &out1, jsonx.V1())) id1 := out1["job"].(map[string]any)["id"].(string) rec2 := doRequest(t, h, http.MethodPost, "/2017-08-29/jobs", body) require.Equal(t, http.StatusCreated, rec2.Code) var out2 map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &out2, jsonx.V1())) id2 := out2["job"].(map[string]any)["id"].(string) assert.Equal(t, id1, id2, "duplicate token should return same job ID") @@ -872,7 +874,7 @@ func TestCreateJob_JobEngineVersionViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) assert.Equal(t, "2017-08-29", jobData["jobEngineVersionUsed"]) assert.Equal(t, "2017-08-29", jobData["jobEngineVersionRequested"]) @@ -956,7 +958,7 @@ func TestCreateJob_PriorityViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobData := out["job"].(map[string]any) assert.InDelta(t, float64(15), jobData["priority"], 0) } @@ -1188,7 +1190,7 @@ func TestListJobs_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobs, ok := out["jobs"].([]any) require.True(t, ok) diff --git a/services/mediaconvert/multi_region_test.go b/services/mediaconvert/multi_region_test.go index e1921199bc..7a174f4823 100644 --- a/services/mediaconvert/multi_region_test.go +++ b/services/mediaconvert/multi_region_test.go @@ -2,7 +2,8 @@ package mediaconvert_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -172,8 +174,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/mediaconvert/persistence.go b/services/mediaconvert/persistence.go index abce59e334..3eb22ed0ba 100644 --- a/services/mediaconvert/persistence.go +++ b/services/mediaconvert/persistence.go @@ -2,10 +2,12 @@ package mediaconvert import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -75,7 +77,7 @@ func newDirtyDTORegistry() (*store.Registry, *store.Table[counterSnapshot], *sto // absent: it was never persisted pre-Phase-3.3 either (see the old Restore, // which always reset it to empty). type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` Certificates map[string]struct{} `json:"certificates"` Policy *Policy `json:"policy,omitempty"` @@ -142,7 +144,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "mediaconvert: failed to marshal snapshot", "error", err) @@ -222,7 +224,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreDirtyTablesLocked restores the "dirty" tables (queueCounters, // tokenIndex) from tables via the ephemeral DTO registry, converting each DTO // back to its live type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, cDTOs, tDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/mediaconvert/policy_test.go b/services/mediaconvert/policy_test.go index 27698a9271..ac0cbebac8 100644 --- a/services/mediaconvert/policy_test.go +++ b/services/mediaconvert/policy_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -86,7 +88,7 @@ func TestMediaConvert_Policy_DeleteAfterGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) policy, ok := out["policy"].(map[string]any) require.True(t, ok) assert.Equal(t, "ALLOWED", policy["httpInputs"]) @@ -114,7 +116,7 @@ func TestPutPolicy_Success(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) pol, ok := out["policy"].(map[string]any) require.True(t, ok) assert.Equal(t, "ALLOWED", pol["httpInputs"]) @@ -142,7 +144,7 @@ func TestGetPolicy_AfterPut(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) pol := out["policy"].(map[string]any) assert.Equal(t, "DISABLED", pol["s3Inputs"]) } diff --git a/services/mediaconvert/presets_test.go b/services/mediaconvert/presets_test.go index 5547f44942..f4a083ea63 100644 --- a/services/mediaconvert/presets_test.go +++ b/services/mediaconvert/presets_test.go @@ -1,7 +1,8 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -28,7 +30,7 @@ func TestMediaConvert_Preset_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) pData, ok := createResp["preset"].(map[string]any) require.True(t, ok) assert.Equal(t, presetName, pData["name"]) @@ -135,7 +137,7 @@ func TestCreatePreset_WithTags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) p := resp["preset"].(map[string]any) tags := p["tags"].(map[string]any) assert.Equal(t, "alpha", tags["project"]) @@ -216,7 +218,7 @@ func TestUpdatePreset_Success(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) preset, ok := out["preset"].(map[string]any) require.True(t, ok) assert.Equal(t, "updated desc", preset["description"]) diff --git a/services/mediaconvert/queues_test.go b/services/mediaconvert/queues_test.go index d6d4b13685..c1093cd51b 100644 --- a/services/mediaconvert/queues_test.go +++ b/services/mediaconvert/queues_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -59,7 +61,7 @@ func TestMediaConvert_Queue_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) queueData, ok := createResp["queue"].(map[string]any) require.True(t, ok) assert.Equal(t, queueName, queueData["name"]) @@ -86,7 +88,7 @@ func TestMediaConvert_Queue_FullLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) updatedQueue, ok := updateResp["queue"].(map[string]any) require.True(t, ok) assert.Equal(t, "PAUSED", updatedQueue["status"]) @@ -140,7 +142,7 @@ func TestMediaConvert_ListQueues_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queues, ok := out["queues"].([]any) require.True(t, ok) require.Len(t, queues, 1) @@ -191,7 +193,7 @@ func TestMediaConvert_UpdateQueue_ConcurrentJobsAndReservationPlanSettings(t *te require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queueData := out["queue"].(map[string]any) assert.InDelta(t, float64(7), queueData["concurrentJobs"], 0) @@ -248,7 +250,7 @@ func TestMediaConvert_CreateQueue_MaximumConcurrentFeeds(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) createQueue, ok := createResp["queue"].(map[string]any) require.True(t, ok) tt.check(t, createQueue) @@ -258,7 +260,7 @@ func TestMediaConvert_CreateQueue_MaximumConcurrentFeeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) getQueue, ok := getResp["queue"].(map[string]any) require.True(t, ok) tt.check(t, getQueue) @@ -284,7 +286,7 @@ func TestMediaConvert_UpdateQueue_MaximumConcurrentFeeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queueData, ok := out["queue"].(map[string]any) require.True(t, ok) assert.InDelta(t, float64(9), queueData["maximumConcurrentFeeds"], 0) @@ -319,7 +321,7 @@ func TestCreateQueue_WithTags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) queue := resp["queue"].(map[string]any) tags := queue["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) @@ -459,7 +461,7 @@ func TestListQueues_JobCountsViaHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queues, ok := out["queues"].([]any) require.True(t, ok) require.Len(t, queues, 2) @@ -505,7 +507,7 @@ func TestCreateQueue_ReservationPlanViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queueData := out["queue"].(map[string]any) rp, ok := queueData["reservationPlan"].(map[string]any) require.True(t, ok, "reservationPlan should be in response") @@ -525,7 +527,7 @@ func TestQueue_NoLegacyReservationPlanNameField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queueData := out["queue"].(map[string]any) _, hasOldField := queueData["reservationPlanName"] assert.False(t, hasOldField, "legacy reservationPlanName field should not be present") @@ -555,7 +557,7 @@ func TestCreateQueue_ConcurrentJobsViaHTTP(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) queueData := out["queue"].(map[string]any) assert.InDelta(t, float64(4), queueData["concurrentJobs"], 0) } @@ -576,7 +578,7 @@ func TestCreateQueue_ConcurrentJobsZeroDistinctFromUnset(t *testing.T) { require.Equal(t, http.StatusCreated, unset.Code) var unsetOut map[string]any - require.NoError(t, json.NewDecoder(unset.Body).Decode(&unsetOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(unset.Body), &unsetOut, jsonx.V1())) unsetQueue := unsetOut["queue"].(map[string]any) _, hasField := unsetQueue["concurrentJobs"] assert.False(t, hasField, "concurrentJobs must be omitted entirely when the client never sent it") @@ -588,7 +590,7 @@ func TestCreateQueue_ConcurrentJobsZeroDistinctFromUnset(t *testing.T) { require.Equal(t, http.StatusCreated, explicitZero.Code) var zeroOut map[string]any - require.NoError(t, json.NewDecoder(explicitZero.Body).Decode(&zeroOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(explicitZero.Body), &zeroOut, jsonx.V1())) zeroQueue := zeroOut["queue"].(map[string]any) zeroVal, hasZeroField := zeroQueue["concurrentJobs"] require.True(t, hasZeroField, "an explicit concurrentJobs:0 must round-trip as a present field, not be dropped") diff --git a/services/mediaconvert/resource_shares.go b/services/mediaconvert/resource_shares.go index 35bd9a957b..cbc130061f 100644 --- a/services/mediaconvert/resource_shares.go +++ b/services/mediaconvert/resource_shares.go @@ -1,11 +1,13 @@ package mediaconvert import ( - "encoding/json" + "encoding/json/v2" "fmt" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // CreateResourceShare records a resource-share request for the given job ID. @@ -38,7 +40,7 @@ func (b *InMemoryBackend) CreateResourceShare(jobID, supportCaseID string) (stri details, err := json.Marshal(struct { ShareToken string `json:"shareToken"` SharedAt float64 `json:"sharedAt"` - }{ShareToken: token, SharedAt: epochSeconds(time.Now())}) + }{ShareToken: token, SharedAt: epochSeconds(time.Now())}, jsonx.V1()) if err != nil { return "", fmt.Errorf("encode share details: %w", err) } diff --git a/services/mediaconvert/resource_shares_test.go b/services/mediaconvert/resource_shares_test.go index 6a1b0c0750..18e4350b5b 100644 --- a/services/mediaconvert/resource_shares_test.go +++ b/services/mediaconvert/resource_shares_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -20,7 +22,7 @@ func TestMediaConvert_CreateResourceShare_TableTests(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) job, _ := resp["job"].(map[string]any) id, _ := job["id"].(string) @@ -121,7 +123,7 @@ func TestCreateResourceShare_SetsShareStatus(t *testing.T) { ShareToken string `json:"shareToken"` SharedAt float64 `json:"sharedAt"` } - require.NoError(t, json.Unmarshal([]byte(*got.LastShareDetails), &details)) + require.NoError(t, json.Unmarshal([]byte(*got.LastShareDetails), &details, jsonx.V1())) assert.NotEmpty(t, details.ShareToken) assert.Greater(t, details.SharedAt, float64(0)) } diff --git a/services/mediaconvert/search_test.go b/services/mediaconvert/search_test.go index 6c831c3520..cafbc5a779 100644 --- a/services/mediaconvert/search_test.go +++ b/services/mediaconvert/search_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -74,7 +76,7 @@ func TestSearchJobs_QueueFilter(t *testing.T) { require.Equal(t, http.StatusCreated, recQ.Code) var qResp map[string]any - require.NoError(t, json.Unmarshal(recQ.Body.Bytes(), &qResp)) + require.NoError(t, json.Unmarshal(recQ.Body.Bytes(), &qResp, jsonx.V1())) qMap, _ := qResp["queue"].(map[string]any) qARN, _ := qMap["arn"].(string) @@ -239,7 +241,7 @@ func TestSearchJobs_FilterByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) jobs, _ := out["jobs"].([]any) assert.Len(t, jobs, tt.wantCount) }) diff --git a/services/mediaconvert/tags_test.go b/services/mediaconvert/tags_test.go index 6178a0f26f..34af452930 100644 --- a/services/mediaconvert/tags_test.go +++ b/services/mediaconvert/tags_test.go @@ -1,13 +1,15 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediaconvert" ) @@ -40,7 +42,7 @@ func TestMediaConvert_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsOut map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&tagsOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &tagsOut, jsonx.V1())) resourceTags, _ := tagsOut["resourceTags"].(map[string]any) tags, _ := resourceTags["tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) @@ -55,7 +57,7 @@ func TestMediaConvert_Tags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/2017-08-29/tags/"+arn, nil) require.Equal(t, http.StatusOK, rec.Code) tagsOut = map[string]any{} - require.NoError(t, json.NewDecoder(rec.Body).Decode(&tagsOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &tagsOut, jsonx.V1())) resourceTags, _ = tagsOut["resourceTags"].(map[string]any) assert.Empty(t, resourceTags["tags"]) } diff --git a/services/mediaconvert/versions_test.go b/services/mediaconvert/versions_test.go index d20677857e..8100cc54db 100644 --- a/services/mediaconvert/versions_test.go +++ b/services/mediaconvert/versions_test.go @@ -1,12 +1,14 @@ package mediaconvert_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListVersions_ReturnsVersions(t *testing.T) { @@ -39,7 +41,7 @@ func TestListVersions_ContainsKnownVersion(t *testing.T) { } `json:"versions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Versions) found := false diff --git a/services/medialive/handler.go b/services/medialive/handler.go index fa8998ce13..2b518528f0 100644 --- a/services/medialive/handler.go +++ b/services/medialive/handler.go @@ -1,7 +1,8 @@ package medialive import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -448,7 +450,7 @@ func (h *Handler) handleREST(c *echo.Context) error { var body map[string]any if c.Request().ContentLength != 0 { - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && err.Error() != "EOF" { c.Response().Header().Set(amznErrorTypeHeader, "BadRequestException") diff --git a/services/medialive/handler_batch_test.go b/services/medialive/handler_batch_test.go index c269fda308..0ba2abc079 100644 --- a/services/medialive/handler_batch_test.go +++ b/services/medialive/handler_batch_test.go @@ -1,12 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestBatch_StartStopDelete(t *testing.T) { @@ -80,7 +82,7 @@ func TestBatch_StartStopKnownChannels(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) successful := startResp["successful"].([]any) assert.Len(t, successful, 1) assert.Equal(t, chID, successful[0].(map[string]any)["id"]) @@ -97,7 +99,7 @@ func TestBatch_StartStopKnownChannels(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp, jsonx.V1())) delSuccessful := delResp["successful"].([]any) assert.Len(t, delSuccessful, 1) } @@ -111,7 +113,7 @@ func TestBatch_StartNotFound(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failed := resp["failed"].([]any) assert.Len(t, failed, 1) } @@ -127,7 +129,7 @@ func TestBatch_DeleteInputSecurityGroups(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/prod/inputSecurityGroups", map[string]any{}) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) groupID := created["securityGroup"].(map[string]any)["id"].(string) rec = doRequest(t, h, http.MethodPost, "/prod/batch/delete", map[string]any{ @@ -135,7 +137,7 @@ func TestBatch_DeleteInputSecurityGroups(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) successful := resp["successful"].([]any) require.Len(t, successful, 1) assert.Equal(t, groupID, successful[0].(map[string]any)["id"]) diff --git a/services/medialive/handler_channels_test.go b/services/medialive/handler_channels_test.go index 596fb2283f..78776c2d5d 100644 --- a/services/medialive/handler_channels_test.go +++ b/services/medialive/handler_channels_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -36,7 +37,7 @@ func TestChannel_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) ch := resp["channel"].(map[string]any) assert.Contains(t, ch["arn"], "arn:aws:medialive:us-east-1:000000000000:channel:") assert.Equal(t, "CREATING", ch["state"]) @@ -76,7 +77,7 @@ func TestChannel_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/channels/"+channelID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-channel", descResp["name"]) assert.Equal(t, "IDLE", descResp["state"]) @@ -86,7 +87,7 @@ func TestChannel_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) ch := updateResp["channel"].(map[string]any) assert.Equal(t, "updated-channel", ch["name"]) @@ -94,7 +95,7 @@ func TestChannel_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/channels", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["channels"], 1) // Delete @@ -117,7 +118,7 @@ func TestChannel_StartStop(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/prod/channels/"+channelID+"/start", nil) assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.Equal(t, "STARTING", startResp["state"]) // Start again returns conflict @@ -128,7 +129,7 @@ func TestChannel_StartStop(t *testing.T) { rec = doRequest(t, h, http.MethodPost, "/prod/channels/"+channelID+"/stop", nil) assert.Equal(t, http.StatusOK, rec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Equal(t, "STOPPING", stopResp["state"]) } @@ -144,19 +145,19 @@ func TestChannel_PipelinesRunningCount(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/channels/"+channelID, nil) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.InDelta(t, 0, descResp["pipelinesRunningCount"], 0, "IDLE channel reports 0 running pipelines") rec = doRequest(t, h, http.MethodPost, "/prod/channels/"+channelID+"/start", nil) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.InDelta(t, 0, startResp["pipelinesRunningCount"], 0, "STARTING channel reports 0 running pipelines") // The backend advances internal state to RUNNING immediately (see // StartChannel's doc comment), so an immediate Describe should already // report the class's full pipeline count. rec = doRequest(t, h, http.MethodGet, "/prod/channels/"+channelID, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "RUNNING", descResp["state"]) assert.InDelta(t, 2, descResp["pipelinesRunningCount"], 0, "RUNNING STANDARD channel reports 2 running pipelines") } @@ -227,7 +228,7 @@ func TestListChannels_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["channels"]) } diff --git a/services/medialive/handler_cloudwatch_alarm_templates_test.go b/services/medialive/handler_cloudwatch_alarm_templates_test.go index 49aafbc968..bbbc5fed2a 100644 --- a/services/medialive/handler_cloudwatch_alarm_templates_test.go +++ b/services/medialive/handler_cloudwatch_alarm_templates_test.go @@ -1,12 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCWAlarmTemplateGroup_CRUD(t *testing.T) { @@ -25,7 +27,7 @@ func TestCWAlarmTemplateGroup_CRUD(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["id"]) assert.Equal(t, "test-cw-group", resp["name"]) assert.NotEmpty(t, resp["createdAt"]) @@ -73,7 +75,7 @@ func TestCWAlarmTemplateGroup_GetUpdateListDelete(t *testing.T) { ) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) // Get @@ -92,14 +94,14 @@ func TestCWAlarmTemplateGroup_GetUpdateListDelete(t *testing.T) { ) require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "cw-group-updated", updated["name"]) // List rec = doRequest(t, h, http.MethodGet, "/prod/cloudwatch-alarm-template-groups", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["cloudWatchAlarmTemplateGroups"].([]any) assert.Len(t, items, 1) @@ -169,7 +171,7 @@ func TestCWAlarmTemplate_CRUD(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["id"]) assert.Equal(t, "InputLossSeconds", resp["metricName"]) assert.NotEmpty(t, resp["createdAt"]) @@ -202,7 +204,7 @@ func TestCWAlarmTemplate_GetUpdateListDelete(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) // Get by ID @@ -219,14 +221,14 @@ func TestCWAlarmTemplate_GetUpdateListDelete(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "ActiveAlerts", updated["metricName"]) // List rec = doRequest(t, h, http.MethodGet, "/prod/cloudwatch-alarm-templates", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["cloudWatchAlarmTemplates"].([]any) assert.Len(t, items, 1) diff --git a/services/medialive/handler_cluster_test.go b/services/medialive/handler_cluster_test.go index 04cb47a09b..8d903a2d84 100644 --- a/services/medialive/handler_cluster_test.go +++ b/services/medialive/handler_cluster_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -23,7 +24,7 @@ func createTestCluster(t *testing.T, h *medialive.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -48,7 +49,7 @@ func TestCluster_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:medialive:us-east-1:000000000000:cluster:") assert.Equal(t, "ACTIVE", resp["state"]) assert.NotEmpty(t, resp["id"]) @@ -91,7 +92,7 @@ func TestCluster_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/clusters/"+clusterID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, clusterID, descResp["id"]) assert.Equal(t, "ACTIVE", descResp["state"]) @@ -101,14 +102,14 @@ func TestCluster_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated-cluster", updateResp["name"]) // List rec = doRequest(t, h, http.MethodGet, "/prod/clusters", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) clusters := listResp["clusters"].([]any) assert.Len(t, clusters, 1) @@ -116,7 +117,7 @@ func TestCluster_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodDelete, "/prod/clusters/"+clusterID, nil) assert.Equal(t, http.StatusOK, rec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp, jsonx.V1())) assert.Equal(t, "DELETED", delResp["state"]) assert.Equal(t, 0, medialive.ClusterCount(h.Backend.(*medialive.InMemoryBackend))) @@ -158,7 +159,7 @@ func TestClusterAlerts_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) alerts := resp["alerts"].([]any) assert.Empty(t, alerts) } @@ -179,7 +180,7 @@ func TestNodeRegistrationScript(t *testing.T) { assert.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) script, ok := resp["nodeRegistrationScript"].(string) assert.True(t, ok) assert.NotEmpty(t, script) @@ -198,7 +199,7 @@ func TestNode_CRUD(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) nodeID := createResp["id"].(string) assert.NotEmpty(t, nodeID) assert.Equal(t, "ACTIVE", createResp["state"]) @@ -215,7 +216,7 @@ func TestNode_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/clusters/"+clusterID+"/nodes/"+nodeID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, nodeID, descResp["id"]) // Update node @@ -231,7 +232,7 @@ func TestNode_CRUD(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated-node", updateResp["name"]) assert.Equal(t, "BACKUP", updateResp["role"]) @@ -247,14 +248,14 @@ func TestNode_CRUD(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var stateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stateResp, jsonx.V1())) assert.Equal(t, "DRAINING", stateResp["state"]) // List nodes rec = doRequest(t, h, http.MethodGet, "/prod/clusters/"+clusterID+"/nodes", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) nodes := listResp["nodes"].([]any) assert.Len(t, nodes, 1) @@ -356,7 +357,7 @@ func TestListClusterAlerts(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) alerts := resp["alerts"].([]any) if tt.wantEmpty { diff --git a/services/medialive/handler_error_type_test.go b/services/medialive/handler_error_type_test.go index df89404e59..9c742f9a75 100644 --- a/services/medialive/handler_error_type_test.go +++ b/services/medialive/handler_error_type_test.go @@ -2,7 +2,7 @@ package medialive_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/medialive" @@ -90,7 +91,7 @@ func TestDescribeChannel_UnknownChannelRawEnvelope(t *testing.T) { require.NoError(t, err) var envelope map[string]any - require.NoError(t, json.Unmarshal(raw, &envelope)) + require.NoError(t, json.Unmarshal(raw, &envelope, jsonx.V1())) _, hasMessage := envelope["Message"] assert.True(t, hasMessage, "raw body must carry a Message key restjson.GetErrorInfo reads: %s", raw) diff --git a/services/medialive/handler_event_bridge_rule_templates_test.go b/services/medialive/handler_event_bridge_rule_templates_test.go index aa74931c2d..49bc5375cd 100644 --- a/services/medialive/handler_event_bridge_rule_templates_test.go +++ b/services/medialive/handler_event_bridge_rule_templates_test.go @@ -1,12 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEBRuleTemplateGroup_CRUD(t *testing.T) { @@ -24,7 +26,7 @@ func TestEBRuleTemplateGroup_CRUD(t *testing.T) { ) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) assert.NotEmpty(t, id) assert.NotEmpty(t, created["createdAt"]) @@ -50,7 +52,7 @@ func TestEBRuleTemplateGroup_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/eventbridge-rule-template-groups", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["eventBridgeRuleTemplateGroups"].([]any), 1) // Delete @@ -135,7 +137,7 @@ func TestEBRuleTemplate_CRUD(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) assert.NotEmpty(t, created["createdAt"]) assert.NotEmpty(t, created["modifiedAt"]) @@ -152,14 +154,14 @@ func TestEBRuleTemplate_CRUD(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, "MEDIALIVE_MULTIPLEX_ALERT", updated["eventType"]) // List rec = doRequest(t, h, http.MethodGet, "/prod/eventbridge-rule-templates", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["eventBridgeRuleTemplates"].([]any), 1) // Delete diff --git a/services/medialive/handler_input_security_groups_test.go b/services/medialive/handler_input_security_groups_test.go index 9a6dd7e99a..86b3619913 100644 --- a/services/medialive/handler_input_security_groups_test.go +++ b/services/medialive/handler_input_security_groups_test.go @@ -1,13 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -26,7 +27,7 @@ func TestInputSecurityGroup_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) sg := createResp["securityGroup"].(map[string]any) groupID := sg["id"].(string) @@ -53,7 +54,7 @@ func TestInputSecurityGroup_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) updatedSG := updateResp["securityGroup"].(map[string]any) updatedRules := updatedSG["whitelistRules"].([]any) assert.Len(t, updatedRules, 2) @@ -62,7 +63,7 @@ func TestInputSecurityGroup_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/inputSecurityGroups", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["inputSecurityGroups"], 1) // Delete: real AWS's DeleteInputSecurityGroup marks the group DELETED @@ -77,7 +78,7 @@ func TestInputSecurityGroup_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/inputSecurityGroups/"+groupID, nil) assert.Equal(t, http.StatusOK, rec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "DELETED", describeResp["state"]) } @@ -89,6 +90,6 @@ func TestListInputSecurityGroups_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["inputSecurityGroups"]) } diff --git a/services/medialive/handler_inputdevice_test.go b/services/medialive/handler_inputdevice_test.go index 87305f1f3d..d83214b698 100644 --- a/services/medialive/handler_inputdevice_test.go +++ b/services/medialive/handler_inputdevice_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -100,7 +101,7 @@ func TestHandlerListInputDevices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) devices := resp["inputDevices"].([]any) assert.Len(t, devices, tt.wantCount) }) @@ -146,7 +147,7 @@ func TestHandlerDescribeInputDevice(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["name"]) } }) @@ -192,7 +193,7 @@ func TestHandlerUpdateInputDevice(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["name"]) } }) @@ -337,7 +338,7 @@ func TestHandlerTransferInputDevice_WireCasing(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) transfers := resp["inputDeviceTransfers"].([]any) require.Len(t, transfers, 1) @@ -432,7 +433,7 @@ func TestHandlerListInputDeviceTransfers(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) transfers := resp["inputDeviceTransfers"].([]any) assert.Len(t, transfers, tt.wantCount) } @@ -494,7 +495,7 @@ func TestStartInputDeviceMaintenanceWindow(t *testing.T) { // keys and would pass this test even with the phantom field // still present. var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "maintenanceWindowActive") } }) diff --git a/services/medialive/handler_inputs_test.go b/services/medialive/handler_inputs_test.go index 2efbe79479..d5c9e81d95 100644 --- a/services/medialive/handler_inputs_test.go +++ b/services/medialive/handler_inputs_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -26,7 +27,7 @@ func TestInput_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/inputs/"+inputID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-input", descResp["name"]) assert.Equal(t, "DETACHED", descResp["state"]) assert.Contains(t, descResp["arn"], "arn:aws:medialive:us-east-1:000000000000:input:") @@ -37,7 +38,7 @@ func TestInput_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) inp := updateResp["input"].(map[string]any) assert.Equal(t, "updated-input", inp["name"]) @@ -45,7 +46,7 @@ func TestInput_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/inputs", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["inputs"], 1) // Delete: real terraform-provider-aws's waitInputDeleted polls @@ -60,7 +61,7 @@ func TestInput_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/inputs/"+inputID, nil) assert.Equal(t, http.StatusOK, rec.Code) var deletedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deletedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deletedResp, jsonx.V1())) assert.Equal(t, "DELETED", deletedResp["state"]) } @@ -196,7 +197,7 @@ func TestListInputs_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["inputs"]) } diff --git a/services/medialive/handler_multiplex_test.go b/services/medialive/handler_multiplex_test.go index 926b0b73c3..2a45767c82 100644 --- a/services/medialive/handler_multiplex_test.go +++ b/services/medialive/handler_multiplex_test.go @@ -1,13 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -25,7 +26,7 @@ func createTestMultiplex(t *testing.T, h *medialive.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["multiplex"].(map[string]any) return m["id"].(string) @@ -55,7 +56,7 @@ func TestMultiplex_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) m := resp["multiplex"].(map[string]any) assert.Contains(t, m["arn"], "arn:aws:medialive:us-east-1:000000000000:multiplex:") assert.Equal(t, "CREATING", m["state"]) @@ -100,7 +101,7 @@ func TestMultiplex_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/multiplexes/"+multiplexID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-multiplex", descResp["name"]) assert.Equal(t, "IDLE", descResp["state"]) @@ -114,7 +115,7 @@ func TestMultiplex_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) m := updateResp["multiplex"].(map[string]any) assert.Equal(t, "updated-multiplex", m["name"]) settings := m["multiplexSettings"].(map[string]any) @@ -124,7 +125,7 @@ func TestMultiplex_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["multiplexes"], 1) // Delete: real AWS's DeleteMultiplex marks the multiplex DELETED rather @@ -139,7 +140,7 @@ func TestMultiplex_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes/"+multiplexID, nil) assert.Equal(t, http.StatusOK, rec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "DELETED", describeResp["state"]) } @@ -153,7 +154,7 @@ func TestMultiplex_StartStop(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/prod/multiplexes/"+multiplexID+"/start", nil) assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.Equal(t, "STARTING", startResp["state"]) // Start again returns conflict @@ -164,7 +165,7 @@ func TestMultiplex_StartStop(t *testing.T) { rec = doRequest(t, h, http.MethodPost, "/prod/multiplexes/"+multiplexID+"/stop", nil) assert.Equal(t, http.StatusOK, rec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Equal(t, "STOPPING", stopResp["state"]) // Stop again returns conflict @@ -239,7 +240,7 @@ func TestMultiplex_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["multiplexes"]) } @@ -270,7 +271,7 @@ func TestMultiplexProgram_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) prog := createResp["multiplexProgram"].(map[string]any) assert.Equal(t, "prog-1", prog["programName"]) settings := prog["multiplexProgramSettings"].(map[string]any) @@ -290,7 +291,7 @@ func TestMultiplexProgram_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes/"+multiplexID+"/programs/prog-1", nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "prog-1", descResp["programName"]) // Update @@ -312,7 +313,7 @@ func TestMultiplexProgram_CRUD(t *testing.T) { ) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) updatedProg := updateResp["multiplexProgram"].(map[string]any) updatedSettings := updatedProg["multiplexProgramSettings"].(map[string]any) assert.Equal(t, 2, int(updatedSettings["programNumber"].(float64))) @@ -322,7 +323,7 @@ func TestMultiplexProgram_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes/"+multiplexID+"/programs", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["multiplexPrograms"], 1) // Delete @@ -431,7 +432,7 @@ func TestMultiplexProgram_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["multiplexPrograms"]) } @@ -450,14 +451,14 @@ func TestMultiplexAlerts(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) mux := created["multiplex"].(map[string]any) muxID := mux["id"].(string) rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes/"+muxID+"/alerts", nil) require.Equal(t, http.StatusOK, rec.Code) var alertsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alertsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &alertsResp, jsonx.V1())) assert.NotNil(t, alertsResp["alerts"]) rec = doRequest(t, h, http.MethodGet, "/prod/multiplexes/missing/alerts", nil) diff --git a/services/medialive/handler_reservations_test.go b/services/medialive/handler_reservations_test.go index 0ec5f47197..549547d2d9 100644 --- a/services/medialive/handler_reservations_test.go +++ b/services/medialive/handler_reservations_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -27,7 +28,7 @@ func TestOfferings_ListDescribe(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) offerings := resp["offerings"].([]any) assert.GreaterOrEqual(t, len(offerings), 3) }, @@ -54,7 +55,7 @@ func TestOfferings_Describe(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/prod/offerings/87654321", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "87654321", resp["offeringId"]) assert.NotEmpty(t, resp["region"]) _, hasName := resp["name"] @@ -77,7 +78,7 @@ func TestReservations_PurchaseListDescribeDeleteUpdate(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var purchaseResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &purchaseResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &purchaseResp, jsonx.V1())) resv := purchaseResp["reservation"].(map[string]any) reservationID := resv["reservationId"].(string) assert.NotEmpty(t, reservationID) @@ -92,7 +93,7 @@ func TestReservations_PurchaseListDescribeDeleteUpdate(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/reservations", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["reservations"].([]any), 1) // Update name @@ -101,7 +102,7 @@ func TestReservations_PurchaseListDescribeDeleteUpdate(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var updatedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updatedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updatedResp, jsonx.V1())) updatedResv := updatedResp["reservation"].(map[string]any) assert.Equal(t, "renamed-reservation", updatedResv["name"]) diff --git a/services/medialive/handler_schedules_test.go b/services/medialive/handler_schedules_test.go index 72f8eacbdd..f28c7e7b4f 100644 --- a/services/medialive/handler_schedules_test.go +++ b/services/medialive/handler_schedules_test.go @@ -1,12 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSchedule_DescribeDelete(t *testing.T) { @@ -53,7 +55,7 @@ func TestBatchUpdateSchedule(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) creates := resp["creates"].(map[string]any)["scheduleActions"].([]any) assert.Len(t, creates, 1) diff --git a/services/medialive/handler_signal_maps_test.go b/services/medialive/handler_signal_maps_test.go index 27833083de..2427d5c7c9 100644 --- a/services/medialive/handler_signal_maps_test.go +++ b/services/medialive/handler_signal_maps_test.go @@ -1,12 +1,14 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSignalMap_CRUD(t *testing.T) { @@ -23,7 +25,7 @@ func TestSignalMap_CRUD(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["id"]) assert.Equal(t, "CREATE_COMPLETE", resp["status"]) monitorDeployment, _ := resp["monitorDeployment"].(map[string]any) @@ -60,7 +62,7 @@ func TestSignalMap_GetListDelete(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) // Get by ID @@ -75,7 +77,7 @@ func TestSignalMap_GetListDelete(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/signal-maps", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["signalMaps"].([]any) assert.Len(t, items, 1) @@ -89,7 +91,7 @@ func TestSignalMap_GetListDelete(t *testing.T) { rec = doRequest(t, h, http.MethodPost, "/prod/signal-maps/"+id+"/monitor-deployment", nil) require.Equal(t, http.StatusAccepted, rec.Code) var deployResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deployResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deployResp, jsonx.V1())) deployMonitorDeployment, _ := deployResp["monitorDeployment"].(map[string]any) assert.Equal(t, "DEPLOYMENT_COMPLETE", deployMonitorDeployment["status"]) @@ -127,7 +129,7 @@ func TestListSignalMaps_OmitsGetOnlyFields(t *testing.T) { var out struct { SignalMaps []map[string]any `json:"signalMaps"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.SignalMaps, 1) item := out.SignalMaps[0] diff --git a/services/medialive/handler_tags_test.go b/services/medialive/handler_tags_test.go index f2a1e040e5..0697aa7e49 100644 --- a/services/medialive/handler_tags_test.go +++ b/services/medialive/handler_tags_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags(t *testing.T) { @@ -20,7 +22,7 @@ func TestTags(t *testing.T) { // Get ARN rec := doRequest(t, h, http.MethodGet, "/prod/channels/"+channelID, nil) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) resourceARN := descResp["arn"].(string) // CreateTags @@ -33,7 +35,7 @@ func TestTags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/tags/"+resourceARN, nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -48,7 +50,7 @@ func TestTags(t *testing.T) { // Verify tag removed rec = doRequest(t, h, http.MethodGet, "/prod/tags/"+resourceARN, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags = listResp["tags"].(map[string]any) assert.NotContains(t, tags, "env") assert.Equal(t, "platform", tags["team"]) @@ -74,14 +76,14 @@ func TestTags_StaySyncedWithResource(t *testing.T) { }) require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) ch := created["channel"].(map[string]any) channelARN := ch["arn"].(string) rec = doRequest(t, h, http.MethodGet, "/prod/tags/"+channelARN, nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["tags"].(map[string]any) assert.Equal(t, "video-team", tags["owner"]) @@ -96,7 +98,7 @@ func TestTags_StaySyncedWithResource(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/prod/channels/"+channelID, nil) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) descTags := descResp["tags"].(map[string]any) assert.Equal(t, "video-team", descTags["owner"]) assert.Equal(t, "1234", descTags["cost-center"]) diff --git a/services/medialive/handler_test.go b/services/medialive/handler_test.go index 6dae23bd1c..fd04dd3ad4 100644 --- a/services/medialive/handler_test.go +++ b/services/medialive/handler_test.go @@ -2,7 +2,7 @@ package medialive_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -39,7 +40,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -64,7 +65,7 @@ func decodeBody(t *testing.T, body []byte) map[string]any { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) return resp } @@ -79,7 +80,7 @@ func createTestChannel(t *testing.T, h *medialive.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ch := resp["channel"].(map[string]any) return ch["id"].(string) @@ -95,7 +96,7 @@ func createTestInput(t *testing.T, h *medialive.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) inp := resp["input"].(map[string]any) return inp["id"].(string) diff --git a/services/medialive/list_summary_shapes_test.go b/services/medialive/list_summary_shapes_test.go index 409a4d6912..b6a6abfe17 100644 --- a/services/medialive/list_summary_shapes_test.go +++ b/services/medialive/list_summary_shapes_test.go @@ -1,7 +1,7 @@ package medialive_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/medialive/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListChannels_SummaryTagsRoundTrip proves ChannelSummary.Tags (over-wide @@ -57,7 +59,7 @@ func TestListNetworks_RawBodyOmitsTags(t *testing.T) { var listResp struct { Networks []map[string]any `json:"networks"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Networks, 1) assert.NotContains(t, listResp.Networks[0], "tags", "Network has no tags field on any CRUD/List shape") assert.Equal(t, "net-leak", listResp.Networks[0]["name"]) diff --git a/services/medialive/multi_region_test.go b/services/medialive/multi_region_test.go index c41173597f..e3f57b54ac 100644 --- a/services/medialive/multi_region_test.go +++ b/services/medialive/multi_region_test.go @@ -2,7 +2,8 @@ package medialive_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/medialive" ) @@ -174,8 +176,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/medialive/persistence.go b/services/medialive/persistence.go index 49edf6e6ce..ab5164d596 100644 --- a/services/medialive/persistence.go +++ b/services/medialive/persistence.go @@ -2,7 +2,7 @@ package medialive import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -44,7 +44,7 @@ const medialiveSnapshotVersion = 1 // intentionally absent: it is an ephemeral reverse index rebuilt from // InputDevices on Restore, and was never part of the persisted shape. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` ScheduleActions map[string][]*storedScheduleAction `json:"scheduleActions"` AccountKmsKeyID string `json:"accountKmsKeyId"` diff --git a/services/medialive/whitebox_test.go b/services/medialive/whitebox_test.go index a74c3d1d1d..3ef48fae64 100644 --- a/services/medialive/whitebox_test.go +++ b/services/medialive/whitebox_test.go @@ -2,7 +2,7 @@ package medialive import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func tagStoreCount(b *InMemoryBackend) int { @@ -27,7 +29,7 @@ func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body any) if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -50,7 +52,7 @@ func decodeWhiteboxBody(t *testing.T, body []byte) map[string]any { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) return resp } diff --git a/services/mediapackage/handler.go b/services/mediapackage/handler.go index 7f01e80a2b..05603e71a2 100644 --- a/services/mediapackage/handler.go +++ b/services/mediapackage/handler.go @@ -1,7 +1,8 @@ package mediapackage import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strconv" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -163,7 +165,12 @@ func (h *Handler) handleREST(c *echo.Context) error { var body map[string]any if c.Request().ContentLength != 0 { - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && err.Error() != "EOF" { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &body, + jsonx.V1(), + ); err != nil && + err.Error() != "EOF" { return c.JSON(http.StatusBadRequest, map[string]any{ keyMessage: "invalid JSON body", keyType: "UnprocessableEntityException", diff --git a/services/mediapackage/handler_channels_test.go b/services/mediapackage/handler_channels_test.go index c9382bb512..9eefe29458 100644 --- a/services/mediapackage/handler_channels_test.go +++ b/services/mediapackage/handler_channels_test.go @@ -1,7 +1,7 @@ package mediapackage_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediapackage" ) @@ -29,7 +30,7 @@ func TestChannel_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:mediapackage:us-east-1:000000000000:channels/my-channel") assert.Equal(t, "my-channel", resp["id"]) assert.Equal(t, "live stream", resp["description"]) @@ -76,7 +77,7 @@ func TestChannel_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/channels/"+channelID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, channelID, descResp["id"]) // Update @@ -85,14 +86,14 @@ func TestChannel_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated description", updateResp["description"]) // List rec = doRequest(t, h, http.MethodGet, "/channels", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["channels"], 1) // Delete @@ -150,7 +151,7 @@ func TestChannel_RotateCredentials(t *testing.T) { // Get original credentials rec := doRequest(t, h, http.MethodGet, "/channels/"+channelID, nil) var before map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before, jsonx.V1())) hls := before["hlsIngest"].(map[string]any) eps := hls["ingestEndpoints"].([]any) originalPassword := eps[0].(map[string]any)["password"].(string) @@ -160,7 +161,7 @@ func TestChannel_RotateCredentials(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var after map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after, jsonx.V1())) hls = after["hlsIngest"].(map[string]any) eps = hls["ingestEndpoints"].([]any) newPassword := eps[0].(map[string]any)["password"].(string) @@ -181,7 +182,7 @@ func TestChannel_ConfigureLogs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, channelID, resp["id"]) } @@ -193,7 +194,7 @@ func TestChannel_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["channels"]) } @@ -281,7 +282,7 @@ func TestHandler_RotateChannelCredentials_RealPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, channelID, resp["id"]) // The old (fictional) path must no longer be recognized as this operation. @@ -309,7 +310,7 @@ func TestHandler_ConfigureLogs_ReflectsInDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) egress, ok := resp["egressAccessLogs"].(map[string]any) require.True(t, ok, "egressAccessLogs should be present after ConfigureLogs") @@ -333,7 +334,7 @@ func TestHandler_Channel_CreatedAtPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["createdAt"]) } @@ -354,7 +355,7 @@ func TestRotateIngestEndpointCredentials(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["id"]) hls := resp["hlsIngest"].(map[string]any) @@ -401,7 +402,7 @@ func TestRotateIngestEndpointCredentials(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var chResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &chResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &chResp, jsonx.V1())) hls := chResp["hlsIngest"].(map[string]any) eps := hls["ingestEndpoints"].([]any) require.NotEmpty(t, eps) diff --git a/services/mediapackage/handler_harvest_jobs_test.go b/services/mediapackage/handler_harvest_jobs_test.go index 4e4900543b..b0bd02c259 100644 --- a/services/mediapackage/handler_harvest_jobs_test.go +++ b/services/mediapackage/handler_harvest_jobs_test.go @@ -1,7 +1,7 @@ package mediapackage_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediapackage" ) @@ -22,7 +23,7 @@ func createTestOriginEndpointForHarvest(t *testing.T, h *mediapackage.Handler, c require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -61,7 +62,7 @@ func TestHarvestJob_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "job-1", resp["id"]) assert.Equal(t, "IN_PROGRESS", resp["status"]) assert.NotEmpty(t, resp["arn"]) @@ -175,7 +176,7 @@ func TestHarvestJob_Describe(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "job-desc", resp["id"]) assert.Equal(t, "IN_PROGRESS", resp["status"]) assert.NotEmpty(t, resp["arn"]) @@ -238,7 +239,7 @@ func TestHarvestJob_List(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) jobs := resp["harvestJobs"].([]any) assert.Len(t, jobs, 4) }, @@ -251,7 +252,7 @@ func TestHarvestJob_List(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) jobs := resp["harvestJobs"].([]any) assert.Len(t, jobs, 3) for _, j := range jobs { @@ -269,7 +270,7 @@ func TestHarvestJob_List(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) jobs := resp["harvestJobs"].([]any) assert.Len(t, jobs, 4) for _, j := range jobs { @@ -360,7 +361,7 @@ func TestHarvestJob_CycleCreateDescribeList(t *testing.T) { assert.Equal(t, 1, mediapackage.HarvestJobCount(backend)) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, "cycle-job", created["id"]) assert.Contains(t, created["arn"].(string), "harvest_jobs/cycle-job") @@ -369,7 +370,7 @@ func TestHarvestJob_CycleCreateDescribeList(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &described, jsonx.V1())) assert.Equal(t, "cycle-job", described["id"]) assert.Equal(t, created["arn"], described["arn"]) assert.Equal(t, "2024-06-01T00:00:00Z", described["startTime"]) @@ -380,7 +381,7 @@ func TestHarvestJob_CycleCreateDescribeList(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var listed map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listed, jsonx.V1())) jobs := listed["harvestJobs"].([]any) assert.Len(t, jobs, 1) @@ -418,7 +419,7 @@ func TestHarvestJob_Create_NeverClaimsSuccessBeforeWorkHappens(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", resp["status"]) } diff --git a/services/mediapackage/handler_origin_endpoints_test.go b/services/mediapackage/handler_origin_endpoints_test.go index 685fe24af6..1226f7d125 100644 --- a/services/mediapackage/handler_origin_endpoints_test.go +++ b/services/mediapackage/handler_origin_endpoints_test.go @@ -1,13 +1,14 @@ package mediapackage_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediapackage" ) @@ -34,7 +35,7 @@ func TestOriginEndpoint_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:mediapackage:us-east-1:000000000000:origin_endpoints/ep1") assert.Equal(t, "ep1", resp["id"]) assert.Equal(t, "ch1", resp["channelId"]) @@ -89,7 +90,7 @@ func TestOriginEndpoint_CRUD(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/origin_endpoints/"+epID, nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, epID, descResp["id"]) assert.Equal(t, channelID, descResp["channelId"]) @@ -100,7 +101,7 @@ func TestOriginEndpoint_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated endpoint", updateResp["description"]) assert.Equal(t, "DENY", updateResp["origination"]) @@ -108,7 +109,7 @@ func TestOriginEndpoint_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/origin_endpoints", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["originEndpoints"], 1) // Delete @@ -158,7 +159,7 @@ func TestOriginEndpoint_DefaultOrigination(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ALLOW", resp["origination"]) assert.Equal(t, "index", resp["manifestName"]) } @@ -171,7 +172,7 @@ func TestOriginEndpoint_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["originEndpoints"]) } @@ -251,7 +252,7 @@ func TestHandler_OriginEndpoint_CreatedAtPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["createdAt"]) } @@ -277,7 +278,7 @@ func TestHandler_OriginEndpoint_PackagingConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) require.Contains(t, created, "authorization") require.Contains(t, created, "hlsPackage") assert.NotContains(t, created, "dashPackage", "unset packaging blocks should be omitted, not null-filled") @@ -286,7 +287,7 @@ func TestHandler_OriginEndpoint_PackagingConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described, jsonx.V1())) auth, ok := described["authorization"].(map[string]any) require.True(t, ok) assert.Equal(t, "arn:aws:iam::000000000000:role/r", auth["secretsRoleArn"]) @@ -300,7 +301,7 @@ func TestHandler_OriginEndpoint_PackagingConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) endpoints, ok := listResp["originEndpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 1) @@ -364,7 +365,7 @@ func TestHandler_OriginEndpoint_MssPackage_FullDepthRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described, jsonx.V1())) mss, ok := described["mssPackage"].(map[string]any) require.True(t, ok) diff --git a/services/mediapackage/handler_tags_test.go b/services/mediapackage/handler_tags_test.go index 3d521666eb..257e33df1a 100644 --- a/services/mediapackage/handler_tags_test.go +++ b/services/mediapackage/handler_tags_test.go @@ -1,7 +1,7 @@ package mediapackage_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags(t *testing.T) { @@ -20,7 +22,7 @@ func TestTags(t *testing.T) { // Get ARN rec := doRequest(t, h, http.MethodGet, "/channels/"+channelID, nil) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) resourceARN := descResp["arn"].(string) // TagResource @@ -33,7 +35,7 @@ func TestTags(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/tags/"+resourceARN, nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -48,7 +50,7 @@ func TestTags(t *testing.T) { // Verify tag removed rec = doRequest(t, h, http.MethodGet, "/tags/"+resourceARN, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags = listResp["tags"].(map[string]any) assert.NotContains(t, tags, "env") assert.Equal(t, "platform", tags["team"]) diff --git a/services/mediapackage/handler_test.go b/services/mediapackage/handler_test.go index b8ac228e93..b61970078c 100644 --- a/services/mediapackage/handler_test.go +++ b/services/mediapackage/handler_test.go @@ -2,7 +2,7 @@ package mediapackage_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediapackage" ) @@ -30,7 +31,7 @@ func doRequest(t *testing.T, h *mediapackage.Handler, method, path string, body if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -62,7 +63,7 @@ func doRequestJSON(t *testing.T, h *mediapackage.Handler, method, path string, b } var out map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) return rec.Code, out } @@ -77,7 +78,7 @@ func createTestChannel(t *testing.T, h *mediapackage.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } @@ -92,7 +93,7 @@ func createTestOriginEndpoint(t *testing.T, h *mediapackage.Handler, channelID s require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["id"].(string) } diff --git a/services/mediapackage/multi_region_test.go b/services/mediapackage/multi_region_test.go index 4b9ac9eef4..bd66b6e01c 100644 --- a/services/mediapackage/multi_region_test.go +++ b/services/mediapackage/multi_region_test.go @@ -2,7 +2,8 @@ package mediapackage_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/mediapackage" ) @@ -172,8 +174,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/mediapackage/persistence.go b/services/mediapackage/persistence.go index 5dc4b45d58..b2f98b2943 100644 --- a/services/mediapackage/persistence.go +++ b/services/mediapackage/persistence.go @@ -2,7 +2,7 @@ package mediapackage import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -31,7 +31,7 @@ const mediapackageSnapshotVersion = 1 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountId"` Region string `json:"region"` diff --git a/services/mediastore/containers.go b/services/mediastore/containers.go index 706c0ed7f2..00c5f2cca0 100644 --- a/services/mediastore/containers.go +++ b/services/mediastore/containers.go @@ -2,7 +2,7 @@ package mediastore import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "regexp" @@ -10,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -199,7 +200,7 @@ func (b *InMemoryBackend) ListContainers( // PutContainerPolicy stores a container access policy. func (b *InMemoryBackend) PutContainerPolicy(ctx context.Context, name, policy string) error { - if !json.Valid([]byte(policy)) { + if !jsontext.Value([]byte(policy)).IsValid(jsonx.V1()) { return ErrInvalidPolicy } diff --git a/services/mediastore/handler.go b/services/mediastore/handler.go index 41ae9a09d2..f62dd59c65 100644 --- a/services/mediastore/handler.go +++ b/services/mediastore/handler.go @@ -2,7 +2,7 @@ package mediastore import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "sort" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -131,7 +132,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -221,7 +222,7 @@ func (h *Handler) dispatch(c *echo.Context, op string, body []byte) error { func (h *Handler) handleCreateContainer(c *echo.Context, body []byte) error { var req createContainerRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -244,7 +245,7 @@ func (h *Handler) handleCreateContainer(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteContainer(c *echo.Context, body []byte) error { var req deleteContainerRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -262,7 +263,7 @@ func (h *Handler) handleDeleteContainer(c *echo.Context, body []byte) error { func (h *Handler) handleDescribeContainer(c *echo.Context, body []byte) error { var req describeContainerRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -283,7 +284,7 @@ func (h *Handler) handleDescribeContainer(c *echo.Context, body []byte) error { func (h *Handler) handleListContainers(c *echo.Context, body []byte) error { var req listContainersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -309,7 +310,7 @@ func (h *Handler) handleListContainers(c *echo.Context, body []byte) error { func (h *Handler) handlePutContainerPolicy(c *echo.Context, body []byte) error { var req putContainerPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -327,7 +328,7 @@ func (h *Handler) handlePutContainerPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleGetContainerPolicy(c *echo.Context, body []byte) error { var req getContainerPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -346,7 +347,7 @@ func (h *Handler) handleGetContainerPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteContainerPolicy(c *echo.Context, body []byte) error { var req deleteContainerPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -364,7 +365,7 @@ func (h *Handler) handleDeleteContainerPolicy(c *echo.Context, body []byte) erro func (h *Handler) handlePutCorsPolicy(c *echo.Context, body []byte) error { var req putCorsPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -382,7 +383,7 @@ func (h *Handler) handlePutCorsPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleGetCorsPolicy(c *echo.Context, body []byte) error { var req getCorsPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -401,7 +402,7 @@ func (h *Handler) handleGetCorsPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteCorsPolicy(c *echo.Context, body []byte) error { var req deleteCorsPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -419,7 +420,7 @@ func (h *Handler) handleDeleteCorsPolicy(c *echo.Context, body []byte) error { func (h *Handler) handlePutLifecyclePolicy(c *echo.Context, body []byte) error { var req putLifecyclePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -437,7 +438,7 @@ func (h *Handler) handlePutLifecyclePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleGetLifecyclePolicy(c *echo.Context, body []byte) error { var req getLifecyclePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -456,7 +457,7 @@ func (h *Handler) handleGetLifecyclePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteLifecyclePolicy(c *echo.Context, body []byte) error { var req deleteLifecyclePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -474,7 +475,7 @@ func (h *Handler) handleDeleteLifecyclePolicy(c *echo.Context, body []byte) erro func (h *Handler) handlePutMetricPolicy(c *echo.Context, body []byte) error { var req putMetricPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -492,7 +493,7 @@ func (h *Handler) handlePutMetricPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleGetMetricPolicy(c *echo.Context, body []byte) error { var req getMetricPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -511,7 +512,7 @@ func (h *Handler) handleGetMetricPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDeleteMetricPolicy(c *echo.Context, body []byte) error { var req deleteMetricPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -529,7 +530,7 @@ func (h *Handler) handleDeleteMetricPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleStartAccessLogging(c *echo.Context, body []byte) error { var req startAccessLoggingRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -547,7 +548,7 @@ func (h *Handler) handleStartAccessLogging(c *echo.Context, body []byte) error { func (h *Handler) handleStopAccessLogging(c *echo.Context, body []byte) error { var req stopAccessLoggingRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -565,7 +566,7 @@ func (h *Handler) handleStopAccessLogging(c *echo.Context, body []byte) error { func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -585,7 +586,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -603,7 +604,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { func (h *Handler) handleListTagsForResource(c *echo.Context, body []byte) error { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/mediastore/handler_tags_test.go b/services/mediastore/handler_tags_test.go index 37ccfff6dc..bafde795f1 100644 --- a/services/mediastore/handler_tags_test.go +++ b/services/mediastore/handler_tags_test.go @@ -1,12 +1,14 @@ package mediastore_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Tags(t *testing.T) { @@ -48,7 +50,7 @@ func TestHandler_Tags(t *testing.T) { require.Equal(t, http.StatusOK, setupRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(setupRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(setupRec.Body.Bytes(), &createResp, jsonx.V1())) containerMap, _ := createResp["Container"].(map[string]any) containerARN, _ := containerMap["ARN"].(string) diff --git a/services/mediastore/handler_test.go b/services/mediastore/handler_test.go index 753201ff9f..1addee30a1 100644 --- a/services/mediastore/handler_test.go +++ b/services/mediastore/handler_test.go @@ -2,7 +2,7 @@ package mediastore_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediastore" ) @@ -32,7 +33,7 @@ func doRequest(t *testing.T, h *mediastore.Handler, op string, body any) *httpte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -65,7 +66,7 @@ func unmarshalBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -235,7 +236,7 @@ func TestHandler_ExtractResource(t *testing.T) { h := newTestHandler(t) e := echo.New() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) diff --git a/services/mediastore/lifecycle_policy.go b/services/mediastore/lifecycle_policy.go index 1070178e24..63ae3f799b 100644 --- a/services/mediastore/lifecycle_policy.go +++ b/services/mediastore/lifecycle_policy.go @@ -2,13 +2,15 @@ package mediastore import ( "context" - "encoding/json" + "encoding/json/jsontext" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutLifecyclePolicy stores a lifecycle policy for a container. func (b *InMemoryBackend) PutLifecyclePolicy(ctx context.Context, name, policy string) error { - if !json.Valid([]byte(policy)) { + if !jsontext.Value([]byte(policy)).IsValid(jsonx.V1()) { return ErrInvalidPolicy } diff --git a/services/mediastoredata/handler_test.go b/services/mediastoredata/handler_test.go index 2d984b9470..83d28ff3d6 100644 --- a/services/mediastoredata/handler_test.go +++ b/services/mediastoredata/handler_test.go @@ -6,7 +6,7 @@ import ( "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediastoredata" ) @@ -196,7 +197,7 @@ func TestMediaStoreData_PutObject(t *testing.T) { if tt.wantETag { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ETag"]) assert.NotEmpty(t, resp["StorageClass"]) } @@ -354,7 +355,7 @@ func TestMediaStoreData_ListItems(t *testing.T) { } `json:"Items"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Items, len(tt.wantNames)) for i, item := range resp.Items { @@ -468,7 +469,7 @@ func TestMediaStoreData_Lifecycle(t *testing.T) { } `json:"Items"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Items, 1) assert.Equal(t, tt.wantFolder, listResp.Items[0].Name) assert.Equal(t, "FOLDER", listResp.Items[0].Type) @@ -496,7 +497,7 @@ func TestMediaStoreData_PutObject_SHA256InResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, wantSHA, resp["ContentSHA256"]) assert.NotEmpty(t, rec.Header().Get("ETag")) } @@ -559,7 +560,7 @@ func TestMediaStoreData_PathValidation(t *testing.T) { // AWS-wide/gopherstack-wide convention for parameter // validation failures (see errors.go). var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -605,7 +606,7 @@ func TestMediaStoreData_StorageClassValidation(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -645,7 +646,7 @@ func TestMediaStoreData_UploadAvailabilityValidation(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -692,7 +693,7 @@ func TestMediaStoreData_ObjectSizeLimit(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -819,7 +820,7 @@ func TestMediaStoreData_RangeRequests(t *testing.T) { // only matches this exact string, not a fabricated // "InvalidRangeException". var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "RequestedRangeNotSatisfiableException", resp["__type"]) assert.NotEmpty(t, rec.Header().Get("Content-Range")) } @@ -848,7 +849,7 @@ func TestMediaStoreData_ListItems_Pagination(t *testing.T) { } `json:"Items"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) assert.Len(t, page1.Items, 2) require.NotNil(t, page1.NextToken) @@ -863,7 +864,7 @@ func TestMediaStoreData_ListItems_Pagination(t *testing.T) { } `json:"Items"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.Items, 2) // Names must not overlap pages. @@ -932,7 +933,7 @@ func TestMediaStoreData_ContentSHA256Verification(t *testing.T) { // payload hash that doesn't match the actual body), not a fabricated // mediastoredata-specific "InvalidContentSHA256Exception". var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "XAmzContentSHA256Mismatch", resp["__type"]) }) diff --git a/services/mediatailor/handler.go b/services/mediatailor/handler.go index 192492dfcb..194f4fb4f5 100644 --- a/services/mediatailor/handler.go +++ b/services/mediatailor/handler.go @@ -1,7 +1,8 @@ package mediatailor import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -277,7 +279,12 @@ func (h *Handler) handleREST(c *echo.Context) error { var body map[string]any if c.Request().ContentLength != 0 { - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && err.Error() != "EOF" { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &body, + jsonx.V1(), + ); err != nil && + err.Error() != "EOF" { c.Response().Header().Set(amznErrorTypeHeader, "BadRequestException") return c.JSON(http.StatusBadRequest, map[string]any{keyMessage: "invalid JSON body"}) diff --git a/services/mediatailor/handler_alerts_test.go b/services/mediatailor/handler_alerts_test.go index 8f1255ce3d..ce9dbc8dce 100644 --- a/services/mediatailor/handler_alerts_test.go +++ b/services/mediatailor/handler_alerts_test.go @@ -1,12 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListAlerts(t *testing.T) { @@ -37,7 +39,7 @@ func TestListAlerts(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if !tt.wantItems { assert.Equal(t, "BadRequestException", rec.Header().Get("X-Amzn-Errortype")) diff --git a/services/mediatailor/handler_channel_policy_test.go b/services/mediatailor/handler_channel_policy_test.go index 7e75eba6fc..649146ba0c 100644 --- a/services/mediatailor/handler_channel_policy_test.go +++ b/services/mediatailor/handler_channel_policy_test.go @@ -1,13 +1,15 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestChannelPolicy_FullCycle's subtests share one Handler and depend on @@ -43,7 +45,7 @@ func TestChannelPolicy_FullCycle(t *testing.T) { //nolint:tparallel // subtests t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["Policy"], "2012-10-17") }, }, diff --git a/services/mediatailor/handler_channels_test.go b/services/mediatailor/handler_channels_test.go index b456ef12ec..691529e14e 100644 --- a/services/mediatailor/handler_channels_test.go +++ b/services/mediatailor/handler_channels_test.go @@ -1,13 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -35,7 +36,7 @@ func TestChannel_CreateAndDescribe(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "my-channel", resp["ChannelName"]) assert.Contains(t, resp["Arn"], "arn:aws:mediatailor:us-east-1:000000000000:channel/my-channel") assert.Equal(t, "STOPPED", resp["ChannelState"]) @@ -80,7 +81,7 @@ func TestChannel_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/channel/test-channel", nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-channel", descResp["ChannelName"]) assert.Equal(t, "STOPPED", descResp["ChannelState"]) @@ -92,14 +93,14 @@ func TestChannel_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Len(t, updateResp["Outputs"], 1) // List rec = doRequest(t, h, http.MethodGet, "/channels", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Items"], 1) // Delete @@ -126,7 +127,7 @@ func TestChannel_StartStop(t *testing.T) { // Verify running rec = doRequest(t, h, http.MethodGet, "/channel/ch1", nil) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "RUNNING", descResp["ChannelState"]) // Start again is idempotent @@ -139,7 +140,7 @@ func TestChannel_StartStop(t *testing.T) { // Verify stopped rec = doRequest(t, h, http.MethodGet, "/channel/ch1", nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "STOPPED", descResp["ChannelState"]) // Stop again is idempotent @@ -201,7 +202,7 @@ func TestChannel_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Items"]) } @@ -227,7 +228,7 @@ func TestListChannels_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } @@ -252,7 +253,7 @@ func TestChannelOutput_WithHLS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) outputs, _ := resp["Outputs"].([]any) require.Len(t, outputs, 1) out, _ := outputs[0].(map[string]any) @@ -308,7 +309,7 @@ func TestCreateChannel_ReturnsTier(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BASIC", resp["Tier"], "Tier must default to BASIC") } @@ -362,7 +363,7 @@ func TestCreateChannel_FillerSlate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) fs, ok := resp["FillerSlate"].(map[string]any) require.True(t, ok, "FillerSlate must be present in response") @@ -387,7 +388,7 @@ func TestCreateChannel_TagsSurviveDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) createdTags, _ := created["tags"].(map[string]any) assert.Equal(t, "prod", createdTags["env"], "tags must be present in the create response") @@ -395,7 +396,7 @@ func TestCreateChannel_TagsSurviveDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described, jsonx.V1())) describedTags, _ := described["tags"].(map[string]any) assert.Equal(t, "prod", describedTags["env"], "tags set at creation must survive to DescribeChannel") } @@ -417,7 +418,7 @@ func TestChannel_AudiencesAndTimeShift(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) audiences, _ := resp["Audiences"].([]any) assert.ElementsMatch(t, []any{"aud1", "aud2"}, audiences) ts, ok := resp["TimeShiftConfiguration"].(map[string]any) @@ -430,7 +431,7 @@ func TestChannel_AudiencesAndTimeShift(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) updateResp := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) audiences, _ = updateResp["Audiences"].([]any) assert.ElementsMatch(t, []any{"aud3"}, audiences) assert.Nil(t, updateResp["TimeShiftConfiguration"], "UpdateChannel omitting TimeShiftConfiguration must clear it") @@ -466,7 +467,7 @@ func TestCreateChannel_Tier(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantTier, resp["Tier"]) } }) diff --git a/services/mediatailor/handler_functions_test.go b/services/mediatailor/handler_functions_test.go index ce1ab0b21c..b025edbb52 100644 --- a/services/mediatailor/handler_functions_test.go +++ b/services/mediatailor/handler_functions_test.go @@ -1,13 +1,15 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestFunction_CRUD's subtests share one Handler and depend on running in @@ -39,7 +41,7 @@ func TestFunction_CRUD(t *testing.T) { //nolint:tparallel // subtests are order- t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "fn1", resp["FunctionId"]) assert.Equal(t, "CUSTOM_OUTPUT", resp["FunctionType"]) assert.Contains(t, resp["Arn"], ":mediatailor:") @@ -55,7 +57,7 @@ func TestFunction_CRUD(t *testing.T) { //nolint:tparallel // subtests are order- t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "fn1", resp["FunctionId"]) assert.Equal(t, "my function", resp["Description"]) }, @@ -69,7 +71,7 @@ func TestFunction_CRUD(t *testing.T) { //nolint:tparallel // subtests are order- t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1) }, @@ -161,7 +163,7 @@ func TestListFunctions_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } diff --git a/services/mediatailor/handler_live_sources_test.go b/services/mediatailor/handler_live_sources_test.go index b3a6897e9f..d067ff9d53 100644 --- a/services/mediatailor/handler_live_sources_test.go +++ b/services/mediatailor/handler_live_sources_test.go @@ -1,7 +1,7 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -40,7 +41,7 @@ func TestLiveSource_Create(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ls1", resp["LiveSourceName"]) assert.Equal(t, "sl1", resp["SourceLocationName"]) assert.Contains(t, resp["Arn"], ":mediatailor:") @@ -105,7 +106,7 @@ func TestLiveSource_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ls1", resp["LiveSourceName"]) // update @@ -117,7 +118,7 @@ func TestLiveSource_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) cfgs, _ := updated["HttpPackageConfigurations"].([]any) require.Len(t, cfgs, 1) cfg0, _ := cfgs[0].(map[string]any) @@ -128,7 +129,7 @@ func TestLiveSource_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["Items"].([]any) assert.Len(t, items, 1) @@ -202,7 +203,7 @@ func TestListLiveSources_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } diff --git a/services/mediatailor/handler_logs_test.go b/services/mediatailor/handler_logs_test.go index f479e61136..ca94cd4063 100644 --- a/services/mediatailor/handler_logs_test.go +++ b/services/mediatailor/handler_logs_test.go @@ -1,13 +1,15 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestConfigureLogsForChannel(t *testing.T) { @@ -30,7 +32,7 @@ func TestConfigureLogsForChannel(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ch1", resp["ChannelName"]) logTypes, _ := resp["LogTypes"].([]any) assert.Len(t, logTypes, 1) @@ -83,7 +85,7 @@ func TestConfigureLogsForPlaybackConfiguration(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "pc1", resp["PlaybackConfigurationName"]) assert.InDelta(t, float64(60), resp["PercentEnabled"], 0.0001) }, @@ -196,7 +198,7 @@ func TestConfigureLogsForChannel_PersistsToDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) logCfg, ok := resp["LogConfiguration"].(map[string]any) require.True(t, ok, "DescribeChannel must include LogConfiguration") @@ -225,7 +227,7 @@ func TestConfigureLogsForPlaybackConfiguration_PersistsToGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) logCfg, ok := resp["LogConfiguration"].(map[string]any) require.True(t, ok, "GetPlaybackConfiguration must include LogConfiguration") @@ -328,7 +330,7 @@ func TestConfigureLogsForPlaybackConfiguration_SurvivesRePut(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) logCfg, ok := resp["LogConfiguration"].(map[string]any) require.True(t, ok) diff --git a/services/mediatailor/handler_playback_configurations_test.go b/services/mediatailor/handler_playback_configurations_test.go index 816ce67550..c909bf0406 100644 --- a/services/mediatailor/handler_playback_configurations_test.go +++ b/services/mediatailor/handler_playback_configurations_test.go @@ -1,13 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -32,7 +33,7 @@ func TestPlaybackConfiguration_PutAndGet(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "my-config", resp["Name"]) assert.Contains( t, @@ -83,7 +84,7 @@ func TestPlaybackConfiguration_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/playbackConfiguration/test-config", nil) assert.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "test-config", getResp["Name"]) assert.Equal(t, "https://ads.example.com", getResp["AdDecisionServerUrl"]) @@ -91,7 +92,7 @@ func TestPlaybackConfiguration_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/playbackConfigurations", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Items"], 1) // Delete @@ -124,7 +125,7 @@ func TestPlaybackConfiguration_PutIdempotent(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/playbackConfiguration/cfg1", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "https://new-ads.example.com", resp["AdDecisionServerUrl"]) } @@ -165,7 +166,7 @@ func TestPlaybackConfiguration_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Items"]) } @@ -187,7 +188,7 @@ func TestListPlaybackConfigurations_WithNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 3) } @@ -280,7 +281,7 @@ func TestPutPlaybackConfiguration_TagsReplacedOnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["tags"].(map[string]any) assert.Contains(t, tags, "new", "new tag must be present after update") @@ -301,7 +302,7 @@ func TestPutPlaybackConfiguration_HlsConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hlsCfg, ok := resp["HlsConfiguration"].(map[string]any) require.True(t, ok, "HlsConfiguration must be present in response") @@ -366,14 +367,14 @@ func TestPutPlaybackConfiguration_ExtraConfigRoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assertPlaybackConfigExtras(t, putResp) rec = doRequest(t, h, http.MethodGet, "/playbackConfiguration/cfg1", nil) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assertPlaybackConfigExtras(t, getResp) } @@ -447,7 +448,7 @@ func TestPutPlaybackConfiguration_AdsPersonalization(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) tt.check(t, putResp) name, _ := tt.body["Name"].(string) @@ -455,7 +456,7 @@ func TestPutPlaybackConfiguration_AdsPersonalization(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) tt.check(t, getResp) }) } @@ -476,13 +477,13 @@ func TestPutPlaybackConfiguration_DualStackFieldsAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) rec = doRequest(t, h, http.MethodGet, "/playbackConfiguration/cfg-dualstack", nil) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) for _, resp := range []map[string]any{putResp, getResp} { _, ok := resp["DualStackPlaybackEndpointPrefix"] diff --git a/services/mediatailor/handler_prefetch_schedules_test.go b/services/mediatailor/handler_prefetch_schedules_test.go index 45cb29f107..c15ecf4792 100644 --- a/services/mediatailor/handler_prefetch_schedules_test.go +++ b/services/mediatailor/handler_prefetch_schedules_test.go @@ -1,13 +1,15 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPrefetchSchedule_CRUD(t *testing.T) { @@ -28,7 +30,7 @@ func TestPrefetchSchedule_CRUD(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "sched1", resp["Name"]) assert.Equal(t, "pc1", resp["PlaybackConfigurationName"]) assert.Contains(t, resp["Arn"], ":mediatailor:") @@ -58,7 +60,7 @@ func TestPrefetchSchedule_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "sched1", resp["Name"]) // list @@ -66,7 +68,7 @@ func TestPrefetchSchedule_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["Items"].([]any) assert.Len(t, items, 1) @@ -136,7 +138,7 @@ func TestListPrefetchSchedules_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } @@ -167,7 +169,7 @@ func TestListPrefetchSchedules_PostWithBodyPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1, "body MaxResults must limit the page size") assert.NotEmpty(t, resp["NextToken"], "a NextToken must be returned when more pages remain") @@ -204,7 +206,7 @@ func TestCreatePrefetchSchedule_RetrievalAndConsumption(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) retrieval, ok := resp["Retrieval"].(map[string]any) require.True(t, ok, "Retrieval must be present in response") @@ -246,7 +248,7 @@ func TestListPrefetchSchedules_FiltersByScheduleTypeAndStreamID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2, "ScheduleType=SINGLE must exclude the RECURRING schedule") @@ -255,7 +257,7 @@ func TestListPrefetchSchedules_FiltersByScheduleTypeAndStreamID(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ = resp["Items"].([]any) assert.Len(t, items, 2, "StreamId=stream-1 must match single-a and recurring-a only") } @@ -278,7 +280,7 @@ func TestPrefetchSchedule_TagsAndScheduleTypeRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "RECURRING", resp["ScheduleType"]) assert.Equal(t, "stream-9", resp["StreamId"]) tags, _ := resp["tags"].(map[string]any) diff --git a/services/mediatailor/handler_programs_test.go b/services/mediatailor/handler_programs_test.go index 013bac219c..c200aa7f66 100644 --- a/services/mediatailor/handler_programs_test.go +++ b/services/mediatailor/handler_programs_test.go @@ -1,12 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestProgram_CRUD(t *testing.T) { @@ -24,7 +26,7 @@ func TestProgram_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, "prog1", created["ProgramName"]) assert.Equal(t, "ch1", created["ChannelName"]) assert.Contains(t, created["Arn"], ":mediatailor:") @@ -34,7 +36,7 @@ func TestProgram_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var described map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &described, jsonx.V1())) assert.Equal(t, "prog1", described["ProgramName"]) assert.Equal(t, "sl1", described["SourceLocationName"]) @@ -49,7 +51,7 @@ func TestProgram_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var schedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp, jsonx.V1())) items, _ := schedResp["Items"].([]any) assert.Len(t, items, 1) item0, _ := items[0].(map[string]any) @@ -151,7 +153,7 @@ func TestHandleGetChannelSchedule_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var schedResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schedResp, jsonx.V1())) items, _ := schedResp["Items"].([]any) require.Len(t, items, 1) } diff --git a/services/mediatailor/handler_source_locations_test.go b/services/mediatailor/handler_source_locations_test.go index 1d2a862431..4783fbb050 100644 --- a/services/mediatailor/handler_source_locations_test.go +++ b/services/mediatailor/handler_source_locations_test.go @@ -1,13 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -32,7 +33,7 @@ func TestSourceLocation_CreateAndDescribe(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "my-location", resp["SourceLocationName"]) assert.Contains(t, resp["Arn"], "arn:aws:mediatailor:us-east-1:000000000000:sourceLocation/my-location") httpCfg, _ := resp["HttpConfiguration"].(map[string]any) @@ -76,7 +77,7 @@ func TestSourceLocation_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/sourceLocation/test-sl", nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "test-sl", descResp["SourceLocationName"]) // Update @@ -85,7 +86,7 @@ func TestSourceLocation_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) httpCfg, _ := updateResp["HttpConfiguration"].(map[string]any) assert.Equal(t, "https://updated.example.com", httpCfg["BaseUrl"]) @@ -93,7 +94,7 @@ func TestSourceLocation_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/sourceLocations", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Items"], 1) // Delete @@ -152,7 +153,7 @@ func TestSourceLocation_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Items"]) } @@ -172,7 +173,7 @@ func TestListSourceLocations_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } @@ -267,7 +268,7 @@ func TestCreateSourceLocation_TagsSurviveDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["tags"].(map[string]any) assert.Equal(t, "video", tags["team"], "tags set at creation must survive to DescribeSourceLocation") } @@ -285,7 +286,7 @@ func TestSourceLocation_Timestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) require.NotNil(t, created["CreationTime"], "CreationTime must be populated") require.NotNil(t, created["LastModifiedTime"], "LastModifiedTime must be populated") @@ -295,7 +296,7 @@ func TestSourceLocation_Timestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updated map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updated, jsonx.V1())) assert.Equal(t, created["CreationTime"], updated["CreationTime"], "CreationTime must not change on update") require.NotNil(t, updated["LastModifiedTime"]) } diff --git a/services/mediatailor/handler_tags_test.go b/services/mediatailor/handler_tags_test.go index 2817fabed1..2892d5c111 100644 --- a/services/mediatailor/handler_tags_test.go +++ b/services/mediatailor/handler_tags_test.go @@ -1,7 +1,7 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTags_FullCycle(t *testing.T) { @@ -25,7 +27,7 @@ func TestTags_FullCycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) resourceARN, _ := putResp["PlaybackConfigurationArn"].(string) // TagResource @@ -38,7 +40,7 @@ func TestTags_FullCycle(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/tags/"+resourceARN, nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "media", tags["team"]) @@ -53,7 +55,7 @@ func TestTags_FullCycle(t *testing.T) { // Verify tag removed rec = doRequest(t, h, http.MethodGet, "/tags/"+resourceARN, nil) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ = listResp["tags"].(map[string]any) assert.NotContains(t, tags, "env") assert.Equal(t, "media", tags["team"]) @@ -94,7 +96,7 @@ func TestTagResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ = resp["PlaybackConfigurationArn"].(string) } else { arn = "arn:aws:mediatailor:us-east-1:000000000000:playbackConfiguration/nonexistent" @@ -132,7 +134,7 @@ func TestListTagsForResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ = resp["PlaybackConfigurationArn"].(string) } else { arn = "arn:aws:mediatailor:us-east-1:000000000000:playbackConfiguration/nonexistent" @@ -170,7 +172,7 @@ func TestUntagResource(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ = resp["PlaybackConfigurationArn"].(string) // Actually tag it first diff --git a/services/mediatailor/handler_test.go b/services/mediatailor/handler_test.go index 010eb8ad3d..df6f724bc5 100644 --- a/services/mediatailor/handler_test.go +++ b/services/mediatailor/handler_test.go @@ -2,7 +2,7 @@ package mediatailor_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -32,7 +33,7 @@ func doRequest(t *testing.T, h *mediatailor.Handler, method, path string, body a if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -528,7 +529,7 @@ func TestHandler_TagsWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // A PascalCase "Tags" key must NOT be how tags are surfaced. _, wrongKeyPresent := resp["Tags"] @@ -550,7 +551,7 @@ func TestHandler_TagsWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok, "response must carry tags under lowercase 'tags' key") @@ -568,7 +569,7 @@ func TestHandler_TagsWireKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["tags"].(map[string]any) require.True(t, ok, "response must carry tags under lowercase 'tags' key") @@ -591,7 +592,7 @@ func TestHandler_ChannelTimestamps_EpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) creationTime, ok := resp["CreationTime"].(float64) require.True(t, ok, "CreationTime must decode as a JSON number, got %T", resp["CreationTime"]) @@ -625,7 +626,7 @@ func TestHandler_PaginationQueryParamCasing(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1, "lowercase maxResults query param must limit the page size") assert.NotEmpty(t, resp["NextToken"], "a NextToken must be returned when more pages remain") @@ -643,7 +644,7 @@ func TestHandler_PaginationQueryParamCasing(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1, "PascalCase MaxResults query param must limit the page size") assert.NotEmpty(t, resp["NextToken"], "a NextToken must be returned when more pages remain") @@ -661,7 +662,7 @@ func TestHandler_PaginationQueryParamCasing(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1, "ListFunctions must actually paginate, not return every function") assert.NotEmpty(t, resp["NextToken"], "a NextToken must be returned when more pages remain") @@ -695,7 +696,7 @@ func TestHandler_PaginationQueryParamCasing(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 1, "GetChannelSchedule must actually paginate, not return every program") assert.NotEmpty(t, resp["NextToken"], "a NextToken must be returned when more pages remain") diff --git a/services/mediatailor/handler_vod_sources_test.go b/services/mediatailor/handler_vod_sources_test.go index 6b99e2ab46..fa2488bf60 100644 --- a/services/mediatailor/handler_vod_sources_test.go +++ b/services/mediatailor/handler_vod_sources_test.go @@ -1,13 +1,14 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -37,7 +38,7 @@ func TestVodSource_CreateAndDescribe(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "my-vod", resp["VodSourceName"]) assert.Equal(t, "sl1", resp["SourceLocationName"]) assert.Contains( @@ -87,7 +88,7 @@ func TestVodSource_CRUD(t *testing.T) { rec = doRequest(t, h, http.MethodGet, "/sourceLocation/sl1/vodSource/vod1", nil) assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "vod1", descResp["VodSourceName"]) // Update @@ -99,14 +100,14 @@ func TestVodSource_CRUD(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Len(t, updateResp["HttpPackageConfigurations"], 2) // List rec = doRequest(t, h, http.MethodGet, "/sourceLocation/sl1/vodSources", nil) assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Items"], 1) // Delete @@ -154,7 +155,7 @@ func TestVodSource_ListEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Items"]) } @@ -177,7 +178,7 @@ func TestListVodSources_WithItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Items"].([]any) assert.Len(t, items, 2) } @@ -238,7 +239,7 @@ func TestCreateVodSource_TagsSurviveDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["tags"].(map[string]any) assert.Equal(t, "video", tags["team"], "tags set at creation must survive to DescribeVodSource") } @@ -260,7 +261,7 @@ func TestVodSource_Timestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) require.NotNil(t, created["CreationTime"]) require.NotNil(t, created["LastModifiedTime"]) } diff --git a/services/mediatailor/multi_region_test.go b/services/mediatailor/multi_region_test.go index 48215c9fd1..b5a6bab9d8 100644 --- a/services/mediatailor/multi_region_test.go +++ b/services/mediatailor/multi_region_test.go @@ -2,7 +2,8 @@ package mediatailor_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -180,8 +182,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/mediatailor/persistence.go b/services/mediatailor/persistence.go index 2e5840fc82..e0771067ec 100644 --- a/services/mediatailor/persistence.go +++ b/services/mediatailor/persistence.go @@ -2,7 +2,7 @@ package mediatailor import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -32,7 +32,7 @@ const mediatailorSnapshotVersion = 1 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/mediatailor/wire_field_fixes_test.go b/services/mediatailor/wire_field_fixes_test.go index 733124b622..ffc4bba2d2 100644 --- a/services/mediatailor/wire_field_fixes_test.go +++ b/services/mediatailor/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package mediatailor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mediatailor" ) @@ -153,7 +154,7 @@ func TestGetPrefetchSchedule_NoCreationTimeOnWire(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains( t, resp, "CreationTime", "GetPrefetchScheduleOutput has no CreationTime member on the real API; emitting one is a fabricated field", @@ -224,7 +225,7 @@ func TestCreateChannel_NoLogConfigurationOnWire(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotContains( t, createResp, "LogConfiguration", "CreateChannelOutput has no LogConfiguration member on the real API", @@ -236,7 +237,7 @@ func TestCreateChannel_NoLogConfigurationOnWire(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code, updateRec.Body.String()) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotContains( t, updateResp, "LogConfiguration", "UpdateChannelOutput has no LogConfiguration member on the real API", @@ -246,7 +247,7 @@ func TestCreateChannel_NoLogConfigurationOnWire(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code, describeRec.Body.String()) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Contains( t, describeResp, "LogConfiguration", "DescribeChannelOutput.LogConfiguration IS required on the real API and must stay present", diff --git a/services/memorydb/acls_test.go b/services/memorydb/acls_test.go index ec99afe7ea..cfdcef82a3 100644 --- a/services/memorydb/acls_test.go +++ b/services/memorydb/acls_test.go @@ -2,13 +2,14 @@ package memorydb_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -119,7 +120,7 @@ func TestUpdateACLSliceNoAlias(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) acls := resp["ACLs"].([]any) acl := acls[0].(map[string]any) users := acl["UserNames"].([]any) diff --git a/services/memorydb/dataplane_test.go b/services/memorydb/dataplane_test.go index 18144e2916..e5087b49dd 100644 --- a/services/memorydb/dataplane_test.go +++ b/services/memorydb/dataplane_test.go @@ -3,7 +3,7 @@ package memorydb_test import ( "bufio" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net" "strconv" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -114,7 +115,7 @@ func describeClusterObj(t *testing.T, h *memorydb.Handler, name string) map[stri var resp struct { Clusters []map[string]any `json:"Clusters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Clusters, 1) return resp.Clusters[0] diff --git a/services/memorydb/errcode_test.go b/services/memorydb/errcode_test.go index 4306b8c722..ff94b90ac2 100644 --- a/services/memorydb/errcode_test.go +++ b/services/memorydb/errcode_test.go @@ -1,12 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // -- Error __type wire-shape regression tests ------------------------------- @@ -22,7 +24,7 @@ func responseType(t *testing.T, body []byte) string { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) typ, _ := resp["__type"].(string) @@ -105,7 +107,7 @@ func TestDeleteUser_CascadesFromACL(t *testing.T) { UserNames []string `json:"UserNames"` } `json:"ACLs"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ACLs, 1) assert.NotContains(t, resp.ACLs[0].UserNames, "in-use-user") } diff --git a/services/memorydb/events.go b/services/memorydb/events.go index f533898f7c..ae5c0faaf0 100644 --- a/services/memorydb/events.go +++ b/services/memorydb/events.go @@ -2,10 +2,11 @@ package memorydb import ( "context" - "encoding/json" "fmt" "sort" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AddEvent appends an event to the backend event log (used internally for seeding). @@ -75,7 +76,7 @@ func (b *InMemoryBackend) DescribeEvents(ctx context.Context, req *describeEvent // field. Real aws-sdk-go-v2 clients serialize these TStamp shapes as a JSON // number of epoch seconds (awsjson1.1), so n arrives as json.Number, not an // RFC3339 string. Returns nil, nil when n is the empty (unset) value. -func parseEpochRequestTime(n json.Number) (*time.Time, error) { +func parseEpochRequestTime(n jsonx.Number) (*time.Time, error) { if n == "" { return nil, nil //nolint:nilnil // absent filter is a valid, distinct state from "parse failed" } diff --git a/services/memorydb/events_test.go b/services/memorydb/events_test.go index e11be642f3..89dbec1982 100644 --- a/services/memorydb/events_test.go +++ b/services/memorydb/events_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -83,7 +84,7 @@ func TestDescribeEvents_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Events []map[string]any `json:"Events"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first, jsonx.V1())) require.Len(t, first.Events, 1, "first page must truncate to MaxResults") require.NotEmpty(t, first.NextToken, "NextToken must be set when more events remain") @@ -94,7 +95,7 @@ func TestDescribeEvents_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Events []map[string]any `json:"Events"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &second)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &second, jsonx.V1())) require.Len(t, second.Events, 1, "second page must return the next event") assert.NotEqual(t, first.Events[0]["Message"], second.Events[0]["Message"], "no event must repeat across pages") } diff --git a/services/memorydb/handler.go b/services/memorydb/handler.go index c4e703f486..5802b14970 100644 --- a/services/memorydb/handler.go +++ b/services/memorydb/handler.go @@ -2,7 +2,7 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -150,7 +151,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } diff --git a/services/memorydb/handler_acls.go b/services/memorydb/handler_acls.go index 1e76accc6c..1093fb6b9f 100644 --- a/services/memorydb/handler_acls.go +++ b/services/memorydb/handler_acls.go @@ -2,16 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateACL(ctx context.Context, c *echo.Context, body []byte) error { var req createACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -34,7 +36,7 @@ func (h *Handler) handleCreateACL(ctx context.Context, c *echo.Context, body []b func (h *Handler) handleDescribeACLs(ctx context.Context, c *echo.Context, body []byte) error { var req describeACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -61,7 +63,7 @@ func (h *Handler) handleDescribeACLs(ctx context.Context, c *echo.Context, body func (h *Handler) handleDeleteACL(ctx context.Context, c *echo.Context, body []byte) error { var req deleteACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -80,7 +82,7 @@ func (h *Handler) handleDeleteACL(ctx context.Context, c *echo.Context, body []b func (h *Handler) handleUpdateACL(ctx context.Context, c *echo.Context, body []byte) error { var req updateACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_acls_test.go b/services/memorydb/handler_acls_test.go index fe9ff8d87b..9de290f055 100644 --- a/services/memorydb/handler_acls_test.go +++ b/services/memorydb/handler_acls_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -105,7 +106,7 @@ func TestHandler_ACL_Tags(t *testing.T) { // Get ACL ARN var aclResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp, jsonx.V1())) aclMap := aclResp["ACL"].(map[string]any) aclARN := aclMap["ARN"].(string) @@ -290,7 +291,7 @@ func TestHandler_Pagination_NextToken(t *testing.T) { rec1 := doRequest(t, h, "DescribeACLs", map[string]any{"MaxResults": 2}) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) acls1, _ := resp1["ACLs"].([]any) assert.Len(t, acls1, 2) nextToken, _ := resp1["NextToken"].(string) @@ -303,7 +304,7 @@ func TestHandler_Pagination_NextToken(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) acls2, _ := resp2["ACLs"].([]any) assert.NotEmpty(t, acls2) diff --git a/services/memorydb/handler_clusters.go b/services/memorydb/handler_clusters.go index 102346888b..7aba7437d3 100644 --- a/services/memorydb/handler_clusters.go +++ b/services/memorydb/handler_clusters.go @@ -2,7 +2,7 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "time" @@ -10,12 +10,13 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateCluster(ctx context.Context, c *echo.Context, body []byte) error { var req createClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -42,7 +43,7 @@ func (h *Handler) handleCreateCluster(ctx context.Context, c *echo.Context, body func (h *Handler) handleDescribeClusters(ctx context.Context, c *echo.Context, body []byte) error { var req describeClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -71,7 +72,7 @@ func (h *Handler) handleDescribeClusters(ctx context.Context, c *echo.Context, b func (h *Handler) handleDeleteCluster(ctx context.Context, c *echo.Context, body []byte) error { var req deleteClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -100,7 +101,7 @@ func (h *Handler) handleDeleteCluster(ctx context.Context, c *echo.Context, body func (h *Handler) handleUpdateCluster(ctx context.Context, c *echo.Context, body []byte) error { var req updateClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -121,7 +122,7 @@ func (h *Handler) handleUpdateCluster(ctx context.Context, c *echo.Context, body func (h *Handler) handleBatchUpdateCluster(ctx context.Context, c *echo.Context, body []byte) error { var req batchUpdateClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -165,7 +166,7 @@ func (h *Handler) handleBatchUpdateCluster(ctx context.Context, c *echo.Context, func (h *Handler) handleFailoverShard(ctx context.Context, c *echo.Context, body []byte) error { var req failoverShardRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -184,7 +185,7 @@ func (h *Handler) handleFailoverShard(ctx context.Context, c *echo.Context, body func (h *Handler) handleListAllowedNodeTypeUpdates(ctx context.Context, c *echo.Context, body []byte) error { var req listAllowedNodeTypeUpdatesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_clusters_lifecycle_test.go b/services/memorydb/handler_clusters_lifecycle_test.go index cb96d1b0d9..a87af2b427 100644 --- a/services/memorydb/handler_clusters_lifecycle_test.go +++ b/services/memorydb/handler_clusters_lifecycle_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -46,7 +47,7 @@ func TestHandler_DescribeClusters_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) assert.Len(t, clusters, tt.wantCount) @@ -88,7 +89,7 @@ func TestHandler_DescribeClusters_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1, jsonx.V1())) // NextToken may be empty or non-empty depending on implementation nextToken, _ := resp1["NextToken"].(string) @@ -98,7 +99,7 @@ func TestHandler_DescribeClusters_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) clusters := resp2["Clusters"].([]any) // At minimum should return a valid response @@ -137,7 +138,7 @@ func TestHandler_DescribeClusters_ShowShards(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) require.Len(t, clusters, 1) @@ -574,7 +575,7 @@ func TestHandler_BatchUpdateCluster_Mixed(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) processed := resp["ProcessedClusters"].([]any) unprocessed := resp["UnprocessedClusters"].([]any) @@ -681,7 +682,7 @@ func TestHandler_Engine_Valkey(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl := resp["Cluster"].(map[string]any) assert.Equal(t, tt.wantEngine, cl["Engine"]) assert.Equal(t, tt.wantVersion, cl["EngineVersion"]) @@ -880,7 +881,7 @@ func TestHandler_UpdateCluster_AutoMinorVersionUpgradeNotSettable(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl := resp["Cluster"].(map[string]any) assert.Equal(t, true, cl["AutoMinorVersionUpgrade"], "no real client can change this via UpdateCluster") } @@ -1076,7 +1077,7 @@ func TestHandler_CreateCluster_RestoreFromSnapshot(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl := resp["Cluster"].(map[string]any) assert.Equal(t, tt.wantEngineVersion, cl["EngineVersion"]) assert.Equal(t, "restored-cluster", cl["Name"]) @@ -1215,7 +1216,7 @@ func TestHandler_BatchUpdateCluster_MissingNames(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) processed := resp["ProcessedClusters"].([]any) unprocessed := resp["UnprocessedClusters"].([]any) assert.Len(t, processed, tt.wantProcessed) diff --git a/services/memorydb/handler_clusters_test.go b/services/memorydb/handler_clusters_test.go index de76d5addd..f716d12c63 100644 --- a/services/memorydb/handler_clusters_test.go +++ b/services/memorydb/handler_clusters_test.go @@ -2,7 +2,7 @@ package memorydb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -58,7 +59,7 @@ func TestHandler_CreateCluster(t *testing.T) { if tt.name == "missing target header" { e := echo.New() - bodyBytes, _ := json.Marshal(tt.body) + bodyBytes, _ := json.Marshal(tt.body, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) rec := httptest.NewRecorder() c := e.NewContext(req, rec) @@ -74,7 +75,7 @@ func TestHandler_CreateCluster(t *testing.T) { if tt.wantCluster { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusterVal, ok := resp["Cluster"] require.True(t, ok, "response should contain Cluster field") @@ -137,7 +138,7 @@ func TestHandler_DescribeClusters(t *testing.T) { if tt.wantCount > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters, ok := resp["Clusters"].([]any) require.True(t, ok) assert.Len(t, clusters, tt.wantCount) @@ -207,7 +208,7 @@ func TestHandler_ClusterResponse_ParameterGroupStatus(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) clusters, _ := resp["Clusters"].([]any) require.Len(t, clusters, 1) cl, _ := clusters[0].(map[string]any) @@ -228,7 +229,7 @@ func TestHandler_ClusterResponse_MultiRegionClusterName(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cl, _ := createResp["Cluster"].(map[string]any) // Field must be present (empty string is fine for a cluster not in multi-region). @@ -250,7 +251,7 @@ func TestHandler_ClusterParameterGroupStatus_InSync(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp, jsonx.V1())) cl, _ := resp["Cluster"].(map[string]any) assert.Equal(t, "in-sync", cl["ParameterGroupStatus"], "default ParameterGroupStatus must be in-sync") @@ -343,7 +344,7 @@ func TestHandler_BatchUpdateCluster(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) processed := resp["ProcessedClusters"].([]any) assert.Len(t, processed, tt.wantProcessed) @@ -403,7 +404,7 @@ func TestHandler_UpdateCluster(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cluster := resp["Cluster"].(map[string]any) assert.Equal(t, "updated", cluster["Description"]) } @@ -562,7 +563,7 @@ func TestHandler_SnsTopicStatusStoredOnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) cluster, _ := updateResp["Cluster"].(map[string]any) gotStatus, _ := cluster["SnsTopicStatus"].(string) @@ -733,7 +734,7 @@ func TestHandler_DeleteCluster_WithSnapshot_EmitsEvent(t *testing.T) { require.Equal(t, http.StatusOK, evRec.Code) var evResp map[string]any - require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &evResp)) + require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &evResp, jsonx.V1())) events, _ := evResp["Events"].([]any) // At least create + delete events. assert.GreaterOrEqual(t, len(events), 2, "expected create and delete events") @@ -789,7 +790,7 @@ func TestHandler_BatchUpdateCluster_Extended(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) processed, _ := resp["ProcessedClusters"].([]any) unprocessed, _ := resp["UnprocessedClusters"].([]any) assert.Len(t, processed, tt.wantProcessed) @@ -873,7 +874,7 @@ func TestHandler_EnginePatchVersion_AllFamilies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl, _ := resp["Cluster"].(map[string]any) assert.Equal(t, tt.wantPatchVersion, cl["EnginePatchVersion"], diff --git a/services/memorydb/handler_engine_versions.go b/services/memorydb/handler_engine_versions.go index 911a9182e0..d82b2f2cb5 100644 --- a/services/memorydb/handler_engine_versions.go +++ b/services/memorydb/handler_engine_versions.go @@ -2,16 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeEngineVersions(ctx context.Context, c *echo.Context, body []byte) error { var req describeEngineVersionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_engine_versions_test.go b/services/memorydb/handler_engine_versions_test.go index ad7258ac70..7a93978f6b 100644 --- a/services/memorydb/handler_engine_versions_test.go +++ b/services/memorydb/handler_engine_versions_test.go @@ -1,12 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DescribeEngineVersions(t *testing.T) { @@ -51,7 +53,7 @@ func TestHandler_DescribeEngineVersions(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions := resp["EngineVersions"].([]any) assert.GreaterOrEqual(t, len(versions), tt.wantMinCount) }) @@ -86,7 +88,7 @@ func TestHandler_DescribeEngineVersions_Filtering(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, _ := resp["EngineVersions"].([]any) assert.GreaterOrEqual(t, len(versions), tt.wantMinCount) @@ -148,7 +150,7 @@ func TestHandler_DescribeEngineVersions_Filtered(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions := resp["EngineVersions"].([]any) assert.GreaterOrEqual(t, len(versions), tt.wantMin) @@ -194,7 +196,7 @@ func TestHandler_DescribeEngineVersions_IncludesValkey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions := resp["EngineVersions"].([]any) assert.GreaterOrEqual(t, len(versions), tt.wantMinCount) @@ -225,7 +227,7 @@ func TestHandler_DescribeEngineVersions_EachHasEngine(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, v := range resp["EngineVersions"].([]any) { ev := v.(map[string]any) diff --git a/services/memorydb/handler_events.go b/services/memorydb/handler_events.go index b10d74a016..5fd0b4822f 100644 --- a/services/memorydb/handler_events.go +++ b/services/memorydb/handler_events.go @@ -2,12 +2,13 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -20,7 +21,7 @@ const defaultDescribeEventsLimit = 100 func (h *Handler) handleDescribeEvents(ctx context.Context, c *echo.Context, body []byte) error { var req describeEventsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_events_test.go b/services/memorydb/handler_events_test.go index c1a8093bb0..aee2c59225 100644 --- a/services/memorydb/handler_events_test.go +++ b/services/memorydb/handler_events_test.go @@ -2,7 +2,7 @@ package memorydb_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -98,7 +99,7 @@ func TestWireEpoch_DescribeEvents_DateIsNumber(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, _ := resp["Events"].([]any) require.NotEmpty(t, events, "expected at least one event for the created cluster") @@ -130,7 +131,7 @@ func TestWireEpoch_DescribeEvents_StartTimeAcceptsEpochNumber(t *testing.T) { "DescribeEvents must accept an epoch-seconds StartTime the way a real SDK client sends it") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, _ := resp["Events"].([]any) assert.NotEmpty(t, events, "StartTime=0 (epoch start) should not filter out the cluster-creation event") @@ -143,7 +144,7 @@ func TestWireEpoch_DescribeEvents_StartTimeAcceptsEpochNumber(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) resp = nil - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, _ = resp["Events"].([]any) assert.Empty(t, events, "a future StartTime should filter out all past events") } @@ -183,7 +184,7 @@ func TestHandler_DescribeEvents(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events := resp["Events"].([]any) assert.Len(t, events, tt.wantCount) }) @@ -242,7 +243,7 @@ func TestHandler_Events_Generated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, _ := resp["Events"].([]any) assert.NotEmpty(t, events, "expected events for %s", tt.wantSrcName) }) @@ -308,7 +309,7 @@ func TestHandler_Events_SourceTypeFiltering(t *testing.T) { require.Equal(t, http.StatusOK, evRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &resp, jsonx.V1())) events, _ := resp["Events"].([]any) assert.GreaterOrEqual(t, len(events), tt.wantEventCount) }) @@ -435,7 +436,7 @@ func TestHandler_Events_AutoPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events := resp["Events"].([]any) require.NotEmpty(t, events, "expected at least one event for source %q type %q", tt.wantSrc, tt.wantType) @@ -501,7 +502,7 @@ func TestHandler_DescribeEvents_Duration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events := resp["Events"].([]any) assert.GreaterOrEqual(t, len(events), tt.wantMinCount) }) diff --git a/services/memorydb/handler_multi_region_cluster_membership_test.go b/services/memorydb/handler_multi_region_cluster_membership_test.go index 46e7c2d026..b8e561cc01 100644 --- a/services/memorydb/handler_multi_region_cluster_membership_test.go +++ b/services/memorydb/handler_multi_region_cluster_membership_test.go @@ -1,12 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_MultiRegionCluster_TLSEnabled verifies TLSEnabled defaults to @@ -60,7 +62,7 @@ func TestHandler_MultiRegionCluster_TLSEnabled(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mrc, _ := resp["MultiRegionCluster"].(map[string]any) require.NotNil(t, mrc) assert.Equal(t, tt.wantTLS, mrc["TLSEnabled"]) @@ -86,7 +88,7 @@ func TestHandler_DescribeMultiRegionClusters_ShowClusterDetails(t *testing.T) { require.Equal(t, http.StatusOK, createMRC.Code) var mrcResp map[string]any - require.NoError(t, json.Unmarshal(createMRC.Body.Bytes(), &mrcResp)) + require.NoError(t, json.Unmarshal(createMRC.Body.Bytes(), &mrcResp, jsonx.V1())) mrc, _ := mrcResp["MultiRegionCluster"].(map[string]any) mrcName, _ := mrc["MultiRegionClusterName"].(string) require.NotEmpty(t, mrcName) @@ -108,7 +110,7 @@ func TestHandler_DescribeMultiRegionClusters_ShowClusterDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mrcs, _ := resp["MultiRegionClusters"].([]any) require.Len(t, mrcs, 1) got, _ := mrcs[0].(map[string]any) @@ -125,7 +127,7 @@ func TestHandler_DescribeMultiRegionClusters_ShowClusterDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mrcs, _ := resp["MultiRegionClusters"].([]any) require.Len(t, mrcs, 1) got, _ := mrcs[0].(map[string]any) @@ -160,7 +162,7 @@ func TestHandler_CreateCluster_MultiRegionClusterName_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["__type"], "MultiRegionClusterNotFoundFault") } @@ -180,7 +182,7 @@ func TestHandler_CreateCluster_MultiRegionClusterName_Linked(t *testing.T) { require.Equal(t, http.StatusOK, createMRC.Code) var mrcResp map[string]any - require.NoError(t, json.Unmarshal(createMRC.Body.Bytes(), &mrcResp)) + require.NoError(t, json.Unmarshal(createMRC.Body.Bytes(), &mrcResp, jsonx.V1())) mrc, _ := mrcResp["MultiRegionCluster"].(map[string]any) mrcName, _ := mrc["MultiRegionClusterName"].(string) require.NotEmpty(t, mrcName) @@ -194,7 +196,7 @@ func TestHandler_CreateCluster_MultiRegionClusterName_Linked(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl, _ := resp["Cluster"].(map[string]any) assert.Equal(t, mrcName, cl["MultiRegionClusterName"]) } diff --git a/services/memorydb/handler_multi_region_clusters.go b/services/memorydb/handler_multi_region_clusters.go index 0f26dea002..bd796ec767 100644 --- a/services/memorydb/handler_multi_region_clusters.go +++ b/services/memorydb/handler_multi_region_clusters.go @@ -2,17 +2,19 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateMultiRegionCluster(ctx context.Context, c *echo.Context, body []byte) error { var req createMultiRegionClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -42,7 +44,7 @@ func (h *Handler) handleCreateMultiRegionCluster(ctx context.Context, c *echo.Co func (h *Handler) handleDeleteMultiRegionCluster(ctx context.Context, c *echo.Context, body []byte) error { var req deleteMultiRegionClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -71,7 +73,7 @@ func (h *Handler) handleDeleteMultiRegionCluster(ctx context.Context, c *echo.Co func (h *Handler) handleDescribeMultiRegionClusters(ctx context.Context, c *echo.Context, body []byte) error { var req describeMultiRegionClustersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -108,7 +110,7 @@ func (h *Handler) handleDescribeMultiRegionClusters(ctx context.Context, c *echo func (h *Handler) handleDescribeMultiRegionParameterGroups(ctx context.Context, c *echo.Context, body []byte) error { var req describeMultiRegionParameterGroupsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -143,7 +145,7 @@ func (h *Handler) handleDescribeMultiRegionParameterGroups(ctx context.Context, func (h *Handler) handleListAllowedMultiRegionClusterUpdates(ctx context.Context, c *echo.Context, body []byte) error { var req listAllowedMultiRegionClusterUpdatesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -170,7 +172,7 @@ func (h *Handler) handleListAllowedMultiRegionClusterUpdates(ctx context.Context func (h *Handler) handleUpdateMultiRegionCluster(ctx context.Context, c *echo.Context, body []byte) error { var req updateMultiRegionClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -196,7 +198,7 @@ func (h *Handler) handleUpdateMultiRegionCluster(ctx context.Context, c *echo.Co func (h *Handler) handleDescribeMultiRegionParameters(ctx context.Context, c *echo.Context, body []byte) error { var req describeMultiRegionParametersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_multi_region_clusters_test.go b/services/memorydb/handler_multi_region_clusters_test.go index b12e81e4c7..03736590fd 100644 --- a/services/memorydb/handler_multi_region_clusters_test.go +++ b/services/memorydb/handler_multi_region_clusters_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -59,7 +60,7 @@ func TestHandler_DescribeMultiRegionParameters_WithGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["MultiRegionParameters"]) } @@ -75,7 +76,7 @@ func TestHandler_ListAllowedMultiRegionClusterUpdates_OK(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var mrcOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mrcOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mrcOut, jsonx.V1())) mrc := mrcOut["MultiRegionCluster"].(map[string]any) mrcName := mrc["MultiRegionClusterName"].(string) @@ -126,7 +127,7 @@ func TestHandler_UpdateMultiRegionCluster_OK(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var mrcOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mrcOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mrcOut, jsonx.V1())) mrc := mrcOut["MultiRegionCluster"].(map[string]any) mrcName := mrc["MultiRegionClusterName"].(string) @@ -137,7 +138,7 @@ func TestHandler_UpdateMultiRegionCluster_OK(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) updated := out["MultiRegionCluster"].(map[string]any) assert.Equal(t, "updated description", updated["Description"]) } @@ -224,7 +225,7 @@ func TestHandler_CreateMultiRegionCluster(t *testing.T) { if tt.wantMRC { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) mrc, ok := resp["MultiRegionCluster"] require.True(t, ok) mrcMap := mrc.(map[string]any) @@ -272,7 +273,7 @@ func TestHandler_DeleteMultiRegionCluster(t *testing.T) { var createResp map[string]any createRec := doRequest(t, h, "DescribeMultiRegionClusters", map[string]any{}) - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusters := createResp["MultiRegionClusters"].([]any) require.Len(t, clusters, 1) clusterName := clusters[0].(map[string]any)["MultiRegionClusterName"].(string) @@ -342,7 +343,7 @@ func TestHandler_DescribeMultiRegionClusters(t *testing.T) { if tt.wantCount > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["MultiRegionClusters"].([]any) assert.Len(t, clusters, tt.wantCount) } @@ -382,7 +383,7 @@ func TestHandler_DescribeMultiRegionParameterGroups(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["MultiRegionParameterGroups"].([]any) assert.Len(t, groups, tt.wantCount) } @@ -414,7 +415,7 @@ func TestHandler_MultiRegionParameterGroups_DefaultSeeded(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, _ := resp["MultiRegionParameterGroups"].([]any) assert.NotEmpty(t, groups, "multi-region parameter group %q should be seeded", tt.pgName) }) @@ -430,7 +431,7 @@ func TestHandler_MultiRegionParameterGroups_DefaultCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, _ := resp["MultiRegionParameterGroups"].([]any) assert.GreaterOrEqual(t, len(groups), 4, "at least 4 default multi-region parameter groups expected") } @@ -457,7 +458,7 @@ func TestHandler_MultiRegionParameters_DefaultNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) params, _ := resp["MultiRegionParameters"].([]any) assert.NotEmpty(t, params, "multi-region parameters should be non-empty for %q", tt.pgName) }) @@ -481,7 +482,7 @@ func TestHandler_MultiRegionParameters_HaveSourceField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) params, _ := resp["MultiRegionParameters"].([]any) require.NotEmpty(t, params) @@ -593,7 +594,7 @@ func TestHandler_DescribeMultiRegionParameterGroups_FilteredAndNotFound(t *testi if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["MultiRegionParameterGroups"].([]any) assert.Len(t, groups, tt.wantCount) } diff --git a/services/memorydb/handler_parameter_groups.go b/services/memorydb/handler_parameter_groups.go index 00c088e52f..868477dad3 100644 --- a/services/memorydb/handler_parameter_groups.go +++ b/services/memorydb/handler_parameter_groups.go @@ -2,17 +2,19 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateParameterGroup(ctx context.Context, c *echo.Context, body []byte) error { var req createParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -35,7 +37,7 @@ func (h *Handler) handleCreateParameterGroup(ctx context.Context, c *echo.Contex func (h *Handler) handleDescribeParameterGroups(ctx context.Context, c *echo.Context, body []byte) error { var req describeParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -63,7 +65,7 @@ func (h *Handler) handleDescribeParameterGroups(ctx context.Context, c *echo.Con func (h *Handler) handleDeleteParameterGroup(ctx context.Context, c *echo.Context, body []byte) error { var req deleteParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -82,7 +84,7 @@ func (h *Handler) handleDeleteParameterGroup(ctx context.Context, c *echo.Contex func (h *Handler) handleUpdateParameterGroup(ctx context.Context, c *echo.Context, body []byte) error { var req updateParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -103,7 +105,7 @@ func (h *Handler) handleUpdateParameterGroup(ctx context.Context, c *echo.Contex func (h *Handler) handleDescribeParameters(ctx context.Context, c *echo.Context, body []byte) error { var req describeParametersRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -135,7 +137,7 @@ func (h *Handler) handleDescribeParameters(ctx context.Context, c *echo.Context, func (h *Handler) handleResetParameterGroup(ctx context.Context, c *echo.Context, body []byte) error { var req resetParameterGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_parameter_groups_test.go b/services/memorydb/handler_parameter_groups_test.go index a661f38af9..a07cc72396 100644 --- a/services/memorydb/handler_parameter_groups_test.go +++ b/services/memorydb/handler_parameter_groups_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -67,7 +68,7 @@ func TestHandler_DescribeParameters_OK(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["Parameters"]) } @@ -595,7 +596,7 @@ func TestHandler_Pagination_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) pgs, _ := resp["ParameterGroups"].([]any) assert.LessOrEqual(t, len(pgs), tt.maxResults) if tt.maxResults >= 5 { @@ -866,7 +867,7 @@ func TestDescribeParameters_Pagination(t *testing.T) { var allParams struct { Parameters []map[string]any `json:"Parameters"` } - require.NoError(t, json.Unmarshal(all.Body.Bytes(), &allParams)) + require.NoError(t, json.Unmarshal(all.Body.Bytes(), &allParams, jsonx.V1())) require.NotEmpty(t, allParams.Parameters) pageSize := len(allParams.Parameters) - 1 @@ -882,7 +883,7 @@ func TestDescribeParameters_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Parameters []map[string]any `json:"Parameters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &first, jsonx.V1())) require.Len(t, first.Parameters, pageSize, "first page must truncate to MaxResults") require.NotEmpty(t, first.NextToken, "NextToken must be set when more parameters remain") @@ -897,7 +898,7 @@ func TestDescribeParameters_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Parameters []map[string]any `json:"Parameters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &second)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &second, jsonx.V1())) require.Len(t, second.Parameters, len(allParams.Parameters)-pageSize, "second page must return the remainder") assert.NotEqual( t, first.Parameters[0]["Name"], second.Parameters[0]["Name"], "no parameter must repeat across pages", diff --git a/services/memorydb/handler_reserved_nodes.go b/services/memorydb/handler_reserved_nodes.go index 0e3e84006e..0c224a4fd0 100644 --- a/services/memorydb/handler_reserved_nodes.go +++ b/services/memorydb/handler_reserved_nodes.go @@ -2,16 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeReservedNodes(ctx context.Context, c *echo.Context, body []byte) error { var req describeReservedNodesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -33,7 +35,7 @@ func (h *Handler) handleDescribeReservedNodes(ctx context.Context, c *echo.Conte func (h *Handler) handleDescribeReservedNodesOfferings(ctx context.Context, c *echo.Context, body []byte) error { var req describeReservedNodesOfferingsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -59,7 +61,7 @@ func (h *Handler) handleDescribeReservedNodesOfferings(ctx context.Context, c *e func (h *Handler) handlePurchaseReservedNodesOffering(ctx context.Context, c *echo.Context, body []byte) error { var req purchaseReservedNodesOfferingRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_reserved_nodes_test.go b/services/memorydb/handler_reserved_nodes_test.go index 13bd235941..faafa8aca4 100644 --- a/services/memorydb/handler_reserved_nodes_test.go +++ b/services/memorydb/handler_reserved_nodes_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -45,7 +46,7 @@ func TestHandler_DescribeReservedNodes(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nodes := resp["ReservedNodes"].([]any) assert.Len(t, nodes, tt.wantCount) @@ -93,7 +94,7 @@ func TestHandler_DescribeReservedNodesOfferings(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) offerings := resp["ReservedNodesOfferings"].([]any) assert.GreaterOrEqual(t, len(offerings), tt.wantMin) @@ -150,7 +151,7 @@ func TestHandler_PurchaseReservedNodesOffering(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rn, ok := resp["ReservedNode"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, rn["NodeType"]) @@ -179,7 +180,7 @@ func TestHandler_PurchaseReservedNodesOffering_ThenDescribe(t *testing.T) { require.Equal(t, http.StatusOK, recDescribe.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &resp, jsonx.V1())) nodes := resp["ReservedNodes"].([]any) assert.Len(t, nodes, 1) @@ -196,7 +197,7 @@ func TestWireEpoch_ReservedNode_StartTimeIsNumber(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rn, _ := resp["ReservedNode"].(map[string]any) require.NotNil(t, rn) @@ -238,7 +239,7 @@ func TestHandler_ReservedNodes_PurchaseAndDescribe(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rn, _ := resp["ReservedNode"].(map[string]any) assert.NotNil(t, rn) assert.NotEmpty(t, rn["ReservationId"]) @@ -257,7 +258,7 @@ func TestHandler_ReservedNodesOfferings_Seeded(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) offerings, _ := resp["ReservedNodesOfferings"].([]any) assert.GreaterOrEqual(t, len(offerings), 3, "at least 3 reserved node offerings should be seeded") } @@ -281,7 +282,7 @@ func TestHandler_ReservedNodes_DescribeAfterPurchase(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) nodes, _ := resp["ReservedNodes"].([]any) assert.Len(t, nodes, 1) @@ -345,7 +346,7 @@ func TestHandler_ReservedNodes_WithPurchase(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nodes := resp["ReservedNodes"].([]any) assert.Len(t, nodes, tt.wantCount) @@ -384,7 +385,7 @@ func TestHandler_ReservedNodesOfferings_Filtered(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) offerings := resp["ReservedNodesOfferings"].([]any) assert.Len(t, offerings, tt.wantCount) @@ -441,7 +442,7 @@ func TestHandler_DescribeReservedNodesOfferings_DurationFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) offerings := resp["ReservedNodesOfferings"].([]any) assert.GreaterOrEqual(t, len(offerings), tt.wantMinCount) diff --git a/services/memorydb/handler_service_updates.go b/services/memorydb/handler_service_updates.go index 5daadc40fb..b758a93d36 100644 --- a/services/memorydb/handler_service_updates.go +++ b/services/memorydb/handler_service_updates.go @@ -2,17 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeServiceUpdates(ctx context.Context, c *echo.Context, body []byte) error { var req describeServiceUpdatesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } updates, err := h.Backend.DescribeServiceUpdates(ctx, &req) diff --git a/services/memorydb/handler_service_updates_test.go b/services/memorydb/handler_service_updates_test.go index 4131cfcbfe..ae16d54868 100644 --- a/services/memorydb/handler_service_updates_test.go +++ b/services/memorydb/handler_service_updates_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -34,7 +35,7 @@ func TestWireEpoch_DescribeServiceUpdates_DatesAreNumbers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates, _ := resp["ServiceUpdates"].([]any) require.NotEmpty(t, updates) @@ -62,7 +63,7 @@ func TestHandler_DescribeServiceUpdates_Basic(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["ServiceUpdates"]) } @@ -125,7 +126,7 @@ func TestHandler_DescribeServiceUpdates_Filtering(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates, _ := resp["ServiceUpdates"].([]any) assert.GreaterOrEqual(t, len(updates), tt.wantMinCount) assert.LessOrEqual(t, len(updates), tt.wantMaxCount) @@ -172,7 +173,7 @@ func TestHandler_DescribeServiceUpdates_Filtered(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates := resp["ServiceUpdates"].([]any) assert.Len(t, updates, tt.wantCount) @@ -227,7 +228,7 @@ func TestHandler_DescribeServiceUpdates_SeededFixtures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates := resp["ServiceUpdates"].([]any) assert.GreaterOrEqual(t, len(updates), tt.wantMinCount) }) @@ -244,7 +245,7 @@ func TestHandler_DescribeServiceUpdates_FieldsPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates := resp["ServiceUpdates"].([]any) require.NotEmpty(t, updates) @@ -316,7 +317,7 @@ func TestHandler_DescribeServiceUpdates_ClusterNamesFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates := resp["ServiceUpdates"].([]any) require.Len(t, updates, tt.wantCount) @@ -352,7 +353,7 @@ func TestHandler_BatchUpdateCluster_ThenDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) updates := resp["ServiceUpdates"].([]any) require.Len(t, updates, 1) assert.Equal(t, "complete", updates[0].(map[string]any)["Status"]) diff --git a/services/memorydb/handler_shards_test.go b/services/memorydb/handler_shards_test.go index 91f44d8580..e6d1f3b424 100644 --- a/services/memorydb/handler_shards_test.go +++ b/services/memorydb/handler_shards_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -69,7 +70,7 @@ func TestHandler_ListAllowedNodeTypeUpdates_OK(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out["ScaleUpNodeTypes"]) assert.NotNil(t, out["ScaleDownNodeTypes"]) } @@ -114,7 +115,7 @@ func TestHandler_FailoverShard_EmitsEvent_ViaMinimalBody(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "failover: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl, _ := resp["Cluster"].(map[string]any) assert.Equal(t, "failover-cluster", cl["Name"]) @@ -124,7 +125,7 @@ func TestHandler_FailoverShard_EmitsEvent_ViaMinimalBody(t *testing.T) { }) require.Equal(t, http.StatusOK, evRec.Code) var evResp map[string]any - require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &evResp)) + require.NoError(t, json.Unmarshal(evRec.Body.Bytes(), &evResp, jsonx.V1())) events, _ := evResp["Events"].([]any) assert.GreaterOrEqual(t, len(events), 2, "create + failover events expected") } @@ -277,7 +278,7 @@ func TestHandler_UpdateCluster_ShardConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl := resp["Cluster"].(map[string]any) assert.InDelta(t, tt.wantShards, cl["NumberOfShards"], 0) assert.InDelta(t, tt.wantReplicas, firstShardReplicaCount(t, cl), 0) @@ -335,7 +336,7 @@ func TestHandler_DescribeClusters_ShowShardDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) require.Len(t, clusters, 1) cl := clusters[0].(map[string]any) @@ -398,7 +399,7 @@ func TestHandler_ShardNodes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) clusters := resp["Clusters"].([]any) cl := clusters[0].(map[string]any) @@ -489,7 +490,7 @@ func TestHandler_FailoverShard(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Cluster"]) } }) @@ -520,7 +521,7 @@ func TestHandler_FailoverShard_EmitsEvent(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) events := resp["Events"].([]any) found := false @@ -584,7 +585,7 @@ func TestHandler_ListAllowedNodeTypeUpdates(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["ScaleUpNodeTypes"]) assert.NotNil(t, resp["ScaleDownNodeTypes"]) } diff --git a/services/memorydb/handler_snapshots.go b/services/memorydb/handler_snapshots.go index 577ddc606c..08df00abf6 100644 --- a/services/memorydb/handler_snapshots.go +++ b/services/memorydb/handler_snapshots.go @@ -2,16 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var req createSnapshotRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -38,7 +40,7 @@ func (h *Handler) handleCreateSnapshot(ctx context.Context, c *echo.Context, bod func (h *Handler) handleCopySnapshot(ctx context.Context, c *echo.Context, body []byte) error { var req copySnapshotRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -70,7 +72,7 @@ func (h *Handler) handleCopySnapshot(ctx context.Context, c *echo.Context, body func (h *Handler) handleDeleteSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var req deleteSnapshotRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -89,7 +91,7 @@ func (h *Handler) handleDeleteSnapshot(ctx context.Context, c *echo.Context, bod func (h *Handler) handleDescribeSnapshots(ctx context.Context, c *echo.Context, body []byte) error { var req describeSnapshotRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -124,7 +126,7 @@ func (h *Handler) handleDescribeSnapshots(ctx context.Context, c *echo.Context, func (h *Handler) handleExportSnapshot(ctx context.Context, c *echo.Context, body []byte) error { var req exportSnapshotRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_snapshots_test.go b/services/memorydb/handler_snapshots_test.go index 4e4b8b8273..d0a7f1a662 100644 --- a/services/memorydb/handler_snapshots_test.go +++ b/services/memorydb/handler_snapshots_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "sync" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -41,7 +42,7 @@ func TestWireShape_Snapshot_NoTopLevelCreationTime_HasDataTiering(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snap, _ := resp["Snapshot"].(map[string]any) require.NotNil(t, snap) @@ -146,7 +147,7 @@ func TestHandler_ExportSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "export snapshot: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snap, _ := resp["Snapshot"].(map[string]any) assert.Equal(t, "export-snap", snap["Name"], "Snapshot.Name must match") assert.NotEmpty(t, snap["ARN"], "Snapshot.ARN must be present") @@ -236,7 +237,7 @@ func TestHandler_CreateSnapshot(t *testing.T) { if tt.wantSnapshot { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snap, ok := resp["Snapshot"] require.True(t, ok) snapMap := snap.(map[string]any) @@ -309,7 +310,7 @@ func TestHandler_CopySnapshot(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snap := resp["Snapshot"].(map[string]any) assert.Equal(t, tt.wantName, snap["Name"]) } @@ -523,7 +524,7 @@ func TestHandler_Snapshot_FilterBySource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps, _ := resp["Snapshots"].([]any) assert.GreaterOrEqual(t, len(snaps), tt.wantMinResults, "filter=%q: expected >= %d snapshots", tt.filterSource, tt.wantMinResults) @@ -627,7 +628,7 @@ func TestHandler_DescribeSnapshots_Filtered(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snapshots := resp["Snapshots"].([]any) assert.Len(t, snapshots, tt.wantCount) @@ -711,7 +712,7 @@ func TestHandler_AutomatedSnapshot_OnCreate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) if tt.wantAutoSnap { @@ -785,7 +786,7 @@ func TestHandler_DescribeSnapshots_SourceFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) assert.GreaterOrEqual(t, len(snaps), tt.wantMinCount) @@ -999,7 +1000,7 @@ func TestHandler_DescribeSnapshots_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) assert.Len(t, snaps, 2) assert.NotEmpty(t, resp["NextToken"]) diff --git a/services/memorydb/handler_subnet_groups.go b/services/memorydb/handler_subnet_groups.go index 424fc4e25a..e19cc1f89e 100644 --- a/services/memorydb/handler_subnet_groups.go +++ b/services/memorydb/handler_subnet_groups.go @@ -2,19 +2,20 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateSubnetGroup(ctx context.Context, c *echo.Context, body []byte) error { var req createSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -37,7 +38,7 @@ func (h *Handler) handleCreateSubnetGroup(ctx context.Context, c *echo.Context, func (h *Handler) handleDescribeSubnetGroups(ctx context.Context, c *echo.Context, body []byte) error { var req describeSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -60,7 +61,7 @@ func (h *Handler) handleDescribeSubnetGroups(ctx context.Context, c *echo.Contex func (h *Handler) handleDeleteSubnetGroup(ctx context.Context, c *echo.Context, body []byte) error { var req deleteSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -79,7 +80,7 @@ func (h *Handler) handleDeleteSubnetGroup(ctx context.Context, c *echo.Context, func (h *Handler) handleUpdateSubnetGroup(ctx context.Context, c *echo.Context, body []byte) error { var req updateSubnetGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_subnet_groups_test.go b/services/memorydb/handler_subnet_groups_test.go index e61d074d47..490e3ccc97 100644 --- a/services/memorydb/handler_subnet_groups_test.go +++ b/services/memorydb/handler_subnet_groups_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -283,7 +284,7 @@ func TestHandler_SubnetGroup_SupportedNetworkTypesAndAvailabilityZone(t *testing require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sg, _ := resp["SubnetGroup"].(map[string]any) require.NotNil(t, sg) diff --git a/services/memorydb/handler_tags.go b/services/memorydb/handler_tags.go index fe75c677d4..70160154c8 100644 --- a/services/memorydb/handler_tags.go +++ b/services/memorydb/handler_tags.go @@ -2,16 +2,18 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTags(ctx context.Context, c *echo.Context, body []byte) error { var req listTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -30,7 +32,7 @@ func (h *Handler) handleListTags(ctx context.Context, c *echo.Context, body []by func (h *Handler) handleTagResource(ctx context.Context, c *echo.Context, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -60,7 +62,7 @@ func (h *Handler) handleTagResource(ctx context.Context, c *echo.Context, body [ func (h *Handler) handleUntagResource(ctx context.Context, c *echo.Context, body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_tags_test.go b/services/memorydb/handler_tags_test.go index 9c185347d6..018ded1354 100644 --- a/services/memorydb/handler_tags_test.go +++ b/services/memorydb/handler_tags_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -42,7 +43,7 @@ func TestHandler_Tags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) clusterMap := createResp["Cluster"].(map[string]any) clusterARN := clusterMap["ARN"].(string) @@ -52,7 +53,7 @@ func TestHandler_Tags(t *testing.T) { if tt.wantStatus == http.StatusOK { var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) tagList := tagsResp["TagList"].([]any) require.NotEmpty(t, tagList) } @@ -470,7 +471,7 @@ func TestHandler_CreateCluster_TagsStored(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tagList, _ := listResp["TagList"].([]any) require.Len(t, tagList, 2) @@ -504,7 +505,7 @@ func TestHandler_Tags_AllResources(t *testing.T) { "Tags": []map[string]any{{"Key": "Env", "Value": "prod"}}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["SubnetGroup"].(map[string]any)["ARN"].(string) }, @@ -523,7 +524,7 @@ func TestHandler_Tags_AllResources(t *testing.T) { "Tags": []map[string]any{{"Key": "Env", "Value": "prod"}}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["User"].(map[string]any)["ARN"].(string) }, @@ -538,7 +539,7 @@ func TestHandler_Tags_AllResources(t *testing.T) { "Tags": []map[string]any{{"Key": "Env", "Value": "prod"}}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ParameterGroup"].(map[string]any)["ARN"].(string) }, @@ -559,7 +560,7 @@ func TestHandler_Tags_AllResources(t *testing.T) { "Tags": []map[string]any{{"Key": "Env", "Value": "prod"}}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Snapshot"].(map[string]any)["ARN"].(string) }, @@ -578,7 +579,7 @@ func TestHandler_Tags_AllResources(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagList := resp["TagList"].([]any) assert.NotEmpty(t, tagList) @@ -664,7 +665,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "create: %s", rec.Body) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) resourceARN := tt.getARN(createResp) require.NotEmpty(t, resourceARN) @@ -683,7 +684,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagList, _ := listResp["TagList"].([]any) assert.Len(t, tagList, 2) @@ -697,7 +698,7 @@ func TestHandler_TagOperations(t *testing.T) { // Verify only 1 tag remains. listRec2 := doRequest(t, h, "ListTags", map[string]any{"ResourceArn": resourceARN}) require.Equal(t, http.StatusOK, listRec2.Code) - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp, jsonx.V1())) tagList2, _ := listResp["TagList"].([]any) assert.Len(t, tagList2, 1) }) @@ -794,7 +795,7 @@ func TestHandler_TagResource_Limit(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clusterMap := createResp["Cluster"].(map[string]any) arn := clusterMap["ARN"].(string) @@ -890,7 +891,7 @@ func TestHandler_Tags_Extended(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagList := resp["TagList"].([]any) tags := make(map[string]string) for _, t := range tagList { @@ -931,7 +932,7 @@ func TestHandler_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tagList := resp["TagList"].([]any) assert.Len(t, tagList, 1) tag := tagList[0].(map[string]any) diff --git a/services/memorydb/handler_test.go b/services/memorydb/handler_test.go index 6d99adc725..d367ccffd6 100644 --- a/services/memorydb/handler_test.go +++ b/services/memorydb/handler_test.go @@ -2,7 +2,7 @@ package memorydb_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -23,7 +24,7 @@ func doCreateCluster(t *testing.T, h *memorydb.Handler, body map[string]any) (ma t.Helper() rec := doRequest(t, h, "CreateCluster", body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp, rec.Code } @@ -37,7 +38,7 @@ func doDescribeUsers(t *testing.T, h *memorydb.Handler, userName string) []any { rec := doRequest(t, h, "DescribeUsers", body) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) users, _ := resp["Users"].([]any) return users @@ -52,7 +53,7 @@ func doDescribeACLs(t *testing.T, h *memorydb.Handler, aclName string) []any { rec := doRequest(t, h, "DescribeACLs", body) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) acls, _ := resp["ACLs"].([]any) return acls @@ -67,7 +68,7 @@ func doDescribeSnapshots(t *testing.T, h *memorydb.Handler, snapshotName string) rec := doRequest(t, h, "DescribeSnapshots", body) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps, _ := resp["Snapshots"].([]any) return snaps @@ -82,7 +83,7 @@ func doDescribeParameterGroups(t *testing.T, h *memorydb.Handler, pgName string) rec := doRequest(t, h, "DescribeParameterGroups", body) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pgs, _ := resp["ParameterGroups"].([]any) return pgs @@ -93,7 +94,7 @@ func doDescribeParameters(t *testing.T, h *memorydb.Handler, pgName string) []an rec := doRequest(t, h, "DescribeParameters", map[string]any{"ParameterGroupName": pgName}) require.Equal(t, http.StatusOK, rec.Code, "DescribeParameters failed: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) params, _ := resp["Parameters"].([]any) return params @@ -130,7 +131,7 @@ func doRequest(t *testing.T, h *memorydb.Handler, op string, body any) *httptest if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -238,7 +239,7 @@ func TestHandler_Infrastructure(t *testing.T) { // callers use this instead and assert on the result back in the main // goroutine. func doRequestAsync(h *memorydb.Handler, op string, body any) (*httptest.ResponseRecorder, error) { - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) if err != nil { return nil, err } @@ -280,7 +281,7 @@ func collectSnapshotARNs(t *testing.T, h *memorydb.Handler) []string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps, _ := resp["Snapshots"].([]any) @@ -383,7 +384,7 @@ func TestExtractResourceSnapshotName(t *testing.T) { func doRequestNoTarget(t *testing.T, h *memorydb.Handler, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -409,7 +410,7 @@ func doRequestWithServiceHeader( //nolint:unused // existing issue. ) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -554,7 +555,7 @@ func TestHandler_ExtractResource(t *testing.T) { t.Parallel() h := newTestHandler(t) - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -741,7 +742,7 @@ func createCluster(t *testing.T, h *memorydb.Handler, body map[string]any) map[s require.Equal(t, http.StatusOK, rec.Code, "create cluster failed: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -818,7 +819,7 @@ func TestPaginationAcrossResourceTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Find the list field. var items []any diff --git a/services/memorydb/handler_users.go b/services/memorydb/handler_users.go index 3217145680..d469649a1d 100644 --- a/services/memorydb/handler_users.go +++ b/services/memorydb/handler_users.go @@ -2,18 +2,20 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/v2" "math" "net/http" "slices" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateUser(ctx context.Context, c *echo.Context, body []byte) error { var req createUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -36,7 +38,7 @@ func (h *Handler) handleCreateUser(ctx context.Context, c *echo.Context, body [] func (h *Handler) handleDescribeUsers(ctx context.Context, c *echo.Context, body []byte) error { var req describeUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -92,7 +94,7 @@ func filterUsersByName(users []*User, filters []userFilterReq) []*User { func (h *Handler) handleDeleteUser(ctx context.Context, c *echo.Context, body []byte) error { var req deleteUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -111,7 +113,7 @@ func (h *Handler) handleDeleteUser(ctx context.Context, c *echo.Context, body [] func (h *Handler) handleUpdateUser(ctx context.Context, c *echo.Context, body []byte) error { var req updateUserRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/memorydb/handler_users_test.go b/services/memorydb/handler_users_test.go index 7448593fe0..91b3d0c270 100644 --- a/services/memorydb/handler_users_test.go +++ b/services/memorydb/handler_users_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -42,7 +43,7 @@ func TestWireAuthType_DefaultUserIsNoPassword(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) user, _ := resp["User"].(map[string]any) auth, _ := user["Authentication"].(map[string]any) @@ -86,7 +87,7 @@ func TestWireAuthType_UpdateUserValidatesType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) user, _ := resp["User"].(map[string]any) auth, _ := user["Authentication"].(map[string]any) assert.Equal(t, "no-password", auth["Type"]) @@ -172,7 +173,7 @@ func TestHandler_UserResponse_NoEngineField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) u, _ := resp["User"].(map[string]any) _, hasEngine := u["Engine"] assert.False(t, hasEngine, "Engine must not appear in the User response (not part of the real SDK type)") @@ -192,7 +193,7 @@ func TestHandler_UserResponse_ACLNames_CreateReturnsEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) u, _ := resp["User"].(map[string]any) aclNames, hasField := u["ACLNames"] diff --git a/services/memorydb/lifecycle_test.go b/services/memorydb/lifecycle_test.go index 5cd2491ff2..161e50989a 100644 --- a/services/memorydb/lifecycle_test.go +++ b/services/memorydb/lifecycle_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -29,7 +30,7 @@ func TestCluster_LifecycleDelay_Default(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cl, _ := resp["Cluster"].(map[string]any) assert.Equal(t, "available", cl["Status"]) } @@ -63,7 +64,7 @@ func TestCluster_LifecycleDelay_CreatingThenAvailable(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, "body: %s", createRec.Body) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cl, _ := createResp["Cluster"].(map[string]any) assert.Equal(t, "creating", cl["Status"], "CreateCluster response must show creating while pending") @@ -72,7 +73,7 @@ func TestCluster_LifecycleDelay_CreatingThenAvailable(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) clusters, _ := descResp["Clusters"].([]any) require.Len(t, clusters, 1) got, _ := clusters[0].(map[string]any) @@ -85,7 +86,7 @@ func TestCluster_LifecycleDelay_CreatingThenAvailable(t *testing.T) { require.Equal(t, http.StatusOK, afterRec.Code) var afterResp map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterResp)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterResp, jsonx.V1())) afterClusters, _ := afterResp["Clusters"].([]any) require.Len(t, afterClusters, 1) afterGot, _ := afterClusters[0].(map[string]any) @@ -123,7 +124,7 @@ func TestCluster_LifecycleDelay_UpdateAndUnrelatedOpsObserveOverlay(t *testing.T require.Equal(t, http.StatusOK, updateRec.Code, "body: %s", updateRec.Body) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) cl, _ := updateResp["Cluster"].(map[string]any) assert.Equal(t, "creating", cl["Status"], "UpdateCluster response must still observe the pending status") assert.Equal(t, "updated while creating", cl["Description"]) diff --git a/services/memorydb/models_events.go b/services/memorydb/models_events.go index c6a1a00d64..4c73580c72 100644 --- a/services/memorydb/models_events.go +++ b/services/memorydb/models_events.go @@ -1,8 +1,9 @@ package memorydb import ( - "encoding/json" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Event represents a MemoryDB event. @@ -19,13 +20,13 @@ type Event struct { // requires a quoted RFC3339 string -- decoding a real client's request would // fail with a SerializationException. See parseEpochRequestTime (backend.go). type describeEventsRequest struct { - MaxResults *int32 `json:"MaxResults,omitempty"` - Duration *int32 `json:"Duration,omitempty"` - StartTime json.Number `json:"StartTime,omitempty"` - EndTime json.Number `json:"EndTime,omitempty"` - SourceName string `json:"SourceName,omitempty"` - SourceType string `json:"SourceType,omitempty"` - NextToken string `json:"NextToken,omitempty"` + MaxResults *int32 `json:"MaxResults,omitempty"` + Duration *int32 `json:"Duration,omitempty"` + StartTime jsonx.Number `json:"StartTime,omitempty"` + EndTime jsonx.Number `json:"EndTime,omitempty"` + SourceName string `json:"SourceName,omitempty"` + SourceType string `json:"SourceType,omitempty"` + NextToken string `json:"NextToken,omitempty"` } // eventObject.Date is epoch seconds (float64), matching the real diff --git a/services/memorydb/parameter_groups_test.go b/services/memorydb/parameter_groups_test.go index de0b417a5f..37a4b30e06 100644 --- a/services/memorydb/parameter_groups_test.go +++ b/services/memorydb/parameter_groups_test.go @@ -2,13 +2,14 @@ package memorydb_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -118,7 +119,7 @@ func TestDescribeParameters_Sorted(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) params, _ := out["Parameters"].([]any) for i := 1; i < len(params); i++ { diff --git a/services/memorydb/persistence.go b/services/memorydb/persistence.go index 3820a8d821..2f70cfe712 100644 --- a/services/memorydb/persistence.go +++ b/services/memorydb/persistence.go @@ -2,8 +2,10 @@ package memorydb import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -32,7 +34,7 @@ const memorydbSnapshotVersion = 1 // [store.Table.Snapshot] slice. type backendSnapshot struct { ParameterGroups map[string][]*ParameterGroup `json:"parameterGroups"` - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Clusters map[string][]*Cluster `json:"clusters"` ACLs map[string][]*ACL `json:"acls"` SubnetGroups map[string][]*SubnetGroup `json:"subnetGroups"` @@ -89,7 +91,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { DefaultRegion: b.defaultRegion, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "memorydb: failed to marshal snapshot", "error", err) diff --git a/services/memorydb/persistence_test.go b/services/memorydb/persistence_test.go index 22f8e93a07..99d3ce0a01 100644 --- a/services/memorydb/persistence_test.go +++ b/services/memorydb/persistence_test.go @@ -1,13 +1,14 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -259,10 +260,10 @@ func TestInMemoryBackend_Restore_IncompatibleVersion(t *testing.T) { // current memorydbSnapshotVersion constant. var raw map[string]any - require.NoError(t, json.Unmarshal(original.Snapshot(ctx), &raw)) + require.NoError(t, json.Unmarshal(original.Snapshot(ctx), &raw, jsonx.V1())) raw["version"] = -1 - badSnap, err := json.Marshal(raw) + badSnap, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) fresh := memorydb.NewInMemoryBackend("123456789012", "us-east-1") diff --git a/services/memorydb/shard_detail_test.go b/services/memorydb/shard_detail_test.go index ef4d7fe011..18dcee75b9 100644 --- a/services/memorydb/shard_detail_test.go +++ b/services/memorydb/shard_detail_test.go @@ -1,7 +1,7 @@ package memorydb_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -16,7 +17,7 @@ func decodeBody(t *testing.T, body []byte) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out } diff --git a/services/memorydb/snapshots_test.go b/services/memorydb/snapshots_test.go index fadb512861..aa93a4e590 100644 --- a/services/memorydb/snapshots_test.go +++ b/services/memorydb/snapshots_test.go @@ -2,13 +2,14 @@ package memorydb_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -56,7 +57,7 @@ func TestDescribeSnapshots(t *testing.T) { if tt.wantCount > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) assert.Len(t, snaps, tt.wantCount) } @@ -99,7 +100,7 @@ func TestDescribeSnapshotNoTopLevelCreationTimeField(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) snaps := resp["Snapshots"].([]any) require.Len(t, snaps, 1) diff --git a/services/memorydb/tags_test.go b/services/memorydb/tags_test.go index 334cd811da..068783db24 100644 --- a/services/memorydb/tags_test.go +++ b/services/memorydb/tags_test.go @@ -2,13 +2,14 @@ package memorydb_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/memorydb" ) @@ -108,7 +109,7 @@ func TestTagResourceReturnsTagList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagList, ok := resp["TagList"].([]any) require.True(t, ok) @@ -138,7 +139,7 @@ func TestUntagResourceReturnsTagList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagList := resp["TagList"].([]any) assert.Len(t, tagList, 1) diff --git a/services/mgn/handler.go b/services/mgn/handler.go index 65fd2ddf8d..a653293bd2 100644 --- a/services/mgn/handler.go +++ b/services/mgn/handler.go @@ -2,7 +2,7 @@ package mgn import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -239,7 +240,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { addErrorFields(body, apiErr) } - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) @@ -385,14 +386,14 @@ func decodeJSONBody(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validationError("malformed request body: " + err.Error()) } var pg struct { NextToken string `json:"nextToken"` } - if json.Unmarshal(body, &pg) == nil && page.ValidateToken(pg.NextToken) != nil { + if json.Unmarshal(body, &pg, jsonx.V1()) == nil && page.ValidateToken(pg.NextToken) != nil { return validationError("Invalid nextToken") } @@ -402,7 +403,7 @@ func decodeJSONBody(body []byte, v any) error { // marshalResponse marshals v, wrapping any error as an internal failure // (marshaling our own well-typed wire structs should never fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, internalServerError("mgn: marshal response: " + err.Error()) } diff --git a/services/mgn/multi_region_test.go b/services/mgn/multi_region_test.go index 467dace111..bb52c77f2f 100644 --- a/services/mgn/multi_region_test.go +++ b/services/mgn/multi_region_test.go @@ -2,7 +2,8 @@ package mgn_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/mgn" ) @@ -183,8 +185,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/mgn/persistence.go b/services/mgn/persistence.go index 1df02b9f57..c3115392e1 100644 --- a/services/mgn/persistence.go +++ b/services/mgn/persistence.go @@ -2,7 +2,7 @@ package mgn import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -19,11 +19,11 @@ const mgnSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the MGN backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` - ServiceInitialized bool `json:"serviceInitialized"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` + ServiceInitialized bool `json:"serviceInitialized"` } // Snapshot serialises the backend state to JSON. diff --git a/services/mgn/s3import_launch.go b/services/mgn/s3import_launch.go index f731522c9c..e081a81957 100644 --- a/services/mgn/s3import_launch.go +++ b/services/mgn/s3import_launch.go @@ -2,13 +2,16 @@ package mgn import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -388,10 +391,9 @@ func parseActionParameters(raw string) (map[string]string, error) { ExternalParameters map[string]string `json:"externalParameters"` } - dec := json.NewDecoder(bytes.NewReader([]byte(raw))) - dec.DisallowUnknownFields() + dec := jsontext.NewDecoder(bytes.NewReader([]byte(raw))) - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), json.RejectUnknownMembers(true)); err != nil { return nil, fmt.Errorf("%w: %w", errImportBadParameters, err) } diff --git a/services/mgn/wire_field_fixes_test.go b/services/mgn/wire_field_fixes_test.go index 924cf8026c..29405e5ab1 100644 --- a/services/mgn/wire_field_fixes_test.go +++ b/services/mgn/wire_field_fixes_test.go @@ -2,7 +2,8 @@ package mgn_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/mgn" @@ -37,7 +39,7 @@ func newRawServer(t *testing.T, h *mgn.Handler) string { func rawPost(t *testing.T, url string, body map[string]any) map[string]any { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, url, bytes.NewReader(raw)) @@ -50,7 +52,7 @@ func rawPost(t *testing.T, url string, body map[string]any) map[string]any { t.Cleanup(func() { _ = resp.Body.Close() }) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) require.Equal(t, http.StatusOK, resp.StatusCode, "response: %v", out) return out diff --git a/services/mq/broker_pagination_test.go b/services/mq/broker_pagination_test.go index 99fd89e905..8af5a254dc 100644 --- a/services/mq/broker_pagination_test.go +++ b/services/mq/broker_pagination_test.go @@ -4,7 +4,8 @@ package mq_test // continuation across pages, maxResults limits, and default listing. import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mq" ) @@ -54,11 +56,11 @@ func TestListBrokers_PaginationOpaqueToken(t *testing.T) { rec := doRequest(t, h, http.MethodGet, path, nil) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var brokers []any - require.NoError(t, json.Unmarshal(out["brokerSummaries"], &brokers)) + require.NoError(t, json.Unmarshal(out["brokerSummaries"], &brokers, jsonx.V1())) assert.Len(t, brokers, tt.wantCount) rawToken, hasToken := out["nextToken"] @@ -66,7 +68,7 @@ func TestListBrokers_PaginationOpaqueToken(t *testing.T) { require.True(t, hasToken, "nextToken must be present when more pages exist") var tok string - require.NoError(t, json.Unmarshal(rawToken, &tok)) + require.NoError(t, json.Unmarshal(rawToken, &tok, jsonx.V1())) assert.NotEmpty(t, tok) // Token must be opaque base64 integer, not a broker name. @@ -74,7 +76,7 @@ func TestListBrokers_PaginationOpaqueToken(t *testing.T) { assert.Equal(t, tt.wantCount, offset, "token encodes offset = items returned so far") } else if hasToken { var tok string - require.NoError(t, json.Unmarshal(rawToken, &tok)) + require.NoError(t, json.Unmarshal(rawToken, &tok, jsonx.V1())) assert.Empty(t, tok, "nextToken must be empty string when no more pages") } }) @@ -92,27 +94,27 @@ func TestListBrokers_PaginationContinuation(t *testing.T) { rec1 := doRequest(t, h, http.MethodGet, "/v1/brokers?maxResults=2", nil) require.Equal(t, http.StatusOK, rec1.Code) - var page1 map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + var page1 map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) var tok string - require.NoError(t, json.Unmarshal(page1["nextToken"], &tok)) + require.NoError(t, json.Unmarshal(page1["nextToken"], &tok, jsonx.V1())) require.NotEmpty(t, tok) rec2 := doRequest(t, h, http.MethodGet, "/v1/brokers?maxResults=2&nextToken="+tok, nil) require.Equal(t, http.StatusOK, rec2.Code) - var page2 map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + var page2 map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) var brokers2 []any - require.NoError(t, json.Unmarshal(page2["brokerSummaries"], &brokers2)) + require.NoError(t, json.Unmarshal(page2["brokerSummaries"], &brokers2, jsonx.V1())) assert.Len(t, brokers2, 1, "page 2 should contain the remaining broker") // No further pages. if rawTok2, ok := page2["nextToken"]; ok { var tok2 string - require.NoError(t, json.Unmarshal(rawTok2, &tok2)) + require.NoError(t, json.Unmarshal(rawTok2, &tok2, jsonx.V1())) assert.Empty(t, tok2, "no nextToken on final page") } } diff --git a/services/mq/configurations_test.go b/services/mq/configurations_test.go index fe6441e74c..88d2eff153 100644 --- a/services/mq/configurations_test.go +++ b/services/mq/configurations_test.go @@ -2,7 +2,8 @@ package mq_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mq" ) @@ -79,7 +81,7 @@ func TestUpdateConfiguration(t *testing.T) { updateBody, err := json.Marshal(map[string]any{ "description": "updated description", "data": "...", - }) + }, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -331,11 +333,11 @@ func TestListConfigurations_PaginationOpaqueToken(t *testing.T) { rec := doRequest(t, h, http.MethodGet, path, nil) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var cfgs []any - require.NoError(t, json.Unmarshal(out["configurations"], &cfgs)) + require.NoError(t, json.Unmarshal(out["configurations"], &cfgs, jsonx.V1())) assert.Len(t, cfgs, tt.wantCount) rawToken, hasToken := out["nextToken"] @@ -343,13 +345,13 @@ func TestListConfigurations_PaginationOpaqueToken(t *testing.T) { require.True(t, hasToken) var tok string - require.NoError(t, json.Unmarshal(rawToken, &tok)) + require.NoError(t, json.Unmarshal(rawToken, &tok, jsonx.V1())) offset := decodeOpaqueToken(t, tok) assert.Equal(t, tt.wantCount, offset) } else if hasToken { var tok string - require.NoError(t, json.Unmarshal(rawToken, &tok)) + require.NoError(t, json.Unmarshal(rawToken, &tok, jsonx.V1())) assert.Empty(t, tok) } }) diff --git a/services/mq/handler_brokers.go b/services/mq/handler_brokers.go index 22394e9104..83f38e9eaf 100644 --- a/services/mq/handler_brokers.go +++ b/services/mq/handler_brokers.go @@ -1,7 +1,7 @@ package mq import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "sort" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -39,7 +40,7 @@ type createBrokerInput struct { func (h *Handler) handleCreateBroker(c *echo.Context, body []byte) error { var in createBrokerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -233,7 +234,7 @@ type updateBrokerResponse struct { func (h *Handler) handleUpdateBroker(c *echo.Context, brokerID string, body []byte) error { var in updateBrokerInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -550,7 +551,7 @@ type promoteInput struct { func (h *Handler) handlePromote(c *echo.Context, brokerID string, body []byte) error { var in promoteInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mq/handler_configurations.go b/services/mq/handler_configurations.go index 32a8c2702e..4c082a8c13 100644 --- a/services/mq/handler_configurations.go +++ b/services/mq/handler_configurations.go @@ -1,7 +1,7 @@ package mq import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -25,7 +26,7 @@ type createConfigurationInput struct { func (h *Handler) handleCreateConfiguration(c *echo.Context, body []byte) error { var in createConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body"), @@ -122,7 +123,7 @@ type updateConfigurationInput struct { func (h *Handler) handleUpdateConfiguration(c *echo.Context, configID string, body []byte) error { var in updateConfigurationInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON( http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body"), diff --git a/services/mq/handler_tags.go b/services/mq/handler_tags.go index e2fd087cce..f9a87f9b49 100644 --- a/services/mq/handler_tags.go +++ b/services/mq/handler_tags.go @@ -1,10 +1,12 @@ package mq import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTags(c *echo.Context, resourceARN string) error { @@ -22,7 +24,7 @@ type createTagsInput struct { func (h *Handler) handleCreateTags(c *echo.Context, resourceARN string, body []byte) error { var in createTagsInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mq/handler_test.go b/services/mq/handler_test.go index 8d5443f2eb..b84bfcb03a 100644 --- a/services/mq/handler_test.go +++ b/services/mq/handler_test.go @@ -3,7 +3,7 @@ package mq_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mq" ) @@ -47,7 +48,7 @@ func doRequest(t *testing.T, h *mq.Handler, method, path string, body any) *http var reqBody *bytes.Reader if body != nil { - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(bodyBytes) } else { @@ -92,7 +93,7 @@ func parseResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/mq/handler_users.go b/services/mq/handler_users.go index 4802132281..fbe69684dc 100644 --- a/services/mq/handler_users.go +++ b/services/mq/handler_users.go @@ -1,13 +1,14 @@ package mq import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -27,7 +28,7 @@ type createUserBody struct { func (h *Handler) handleCreateUser(c *echo.Context, brokerID, username string, body []byte) error { var in createUserBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } @@ -83,7 +84,7 @@ type updateUserBody struct { func (h *Handler) handleUpdateUser(c *echo.Context, brokerID, username string, body []byte) error { var in updateUserBody - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return c.JSON(http.StatusBadRequest, errorResponse("BadRequestException", "invalid request body")) } diff --git a/services/mq/models.go b/services/mq/models.go index a3e02c9d10..eeab71ccef 100644 --- a/services/mq/models.go +++ b/services/mq/models.go @@ -1,8 +1,10 @@ package mq import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -245,7 +247,7 @@ func (l LdapServerMetadata) MarshalJSON() ([]byte, error) { a := alias(l) a.ServiceAccountPassword = "" - b, err := json.Marshal(a) + b, err := json.Marshal(a, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal ldap server metadata: %w", err) } diff --git a/services/mq/multi_region_test.go b/services/mq/multi_region_test.go index 296bdd746d..65b4fca182 100644 --- a/services/mq/multi_region_test.go +++ b/services/mq/multi_region_test.go @@ -1,7 +1,8 @@ package mq_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mq" ) @@ -38,7 +40,7 @@ func regionCall(t *testing.T, h *mq.Handler, region, method, path, body string) out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out @@ -129,9 +131,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/mq/persistence.go b/services/mq/persistence.go index 0adc89f782..1d07f21127 100644 --- a/services/mq/persistence.go +++ b/services/mq/persistence.go @@ -2,9 +2,11 @@ package mq import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -29,7 +31,7 @@ const mqSnapshotVersion = 1 // store.Table-backed, see store_setup.go) but was persisted before this // refactor and remains so. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -56,7 +58,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "mq: failed to marshal snapshot", "error", err) diff --git a/services/mq/user_summary_wire_test.go b/services/mq/user_summary_wire_test.go index 8bdc3389ce..5243f9e988 100644 --- a/services/mq/user_summary_wire_test.go +++ b/services/mq/user_summary_wire_test.go @@ -1,13 +1,14 @@ package mq_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mq" ) @@ -40,7 +41,7 @@ func TestUserSummary_NoFabricatedConsoleAccess(t *testing.T) { "ListUsers' UserSummary items must not carry a fabricated consoleAccess key") broker := describeTestBroker(t, h, brokerID) - usersRaw, err := json.Marshal(broker["users"]) + usersRaw, err := json.Marshal(broker["users"], jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(usersRaw), "consoleAccess", "DescribeBrokerOutput.Users (UserSummary) must not carry a fabricated consoleAccess key") diff --git a/services/mwaa/airflow_access.go b/services/mwaa/airflow_access.go index b1466338f0..4a49869c44 100644 --- a/services/mwaa/airflow_access.go +++ b/services/mwaa/airflow_access.go @@ -5,7 +5,7 @@ import ( "context" "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -13,6 +13,8 @@ import ( "strings" "time" "unicode" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -71,7 +73,7 @@ func (e *airflowEngine) doWith( } if out != nil && len(res.body) > 0 { - _ = json.Unmarshal(res.body, out) + _ = json.Unmarshal(res.body, out, jsonx.V1()) } return res.status, res.body, nil @@ -127,7 +129,7 @@ func (e *airflowEngine) newToken(key, envName, kind string) string { _, _ = rand.Read(sig) enc := base64.RawURLEncoding - payload, _ := json.Marshal(map[string]any{"env": envName, "type": kind, "exp": exp.Unix()}) + payload, _ := json.Marshal(map[string]any{"env": envName, "type": kind, "exp": exp.Unix()}, jsonx.V1()) tok := enc.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`)) + "." + enc.EncodeToString(payload) + "." + enc.EncodeToString(sig) @@ -276,7 +278,7 @@ func (e *airflowEngine) proxyRest( if req.Body != nil { var err error - if body, err = json.Marshal(req.Body); err != nil { + if body, err = json.Marshal(req.Body, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: Body is not JSON: %w", ErrInvalidParameter, err) } } @@ -297,7 +299,7 @@ func (e *airflowEngine) proxyRest( doc := any(map[string]any{}) if len(raw) > 0 { - if jerr := json.Unmarshal(raw, &doc); jerr != nil { + if jerr := json.Unmarshal(raw, &doc, jsonx.V1()); jerr != nil { doc = string(raw) } } diff --git a/services/mwaa/airflow_auth.go b/services/mwaa/airflow_auth.go index 72457c870b..5e68c3fd42 100644 --- a/services/mwaa/airflow_auth.go +++ b/services/mwaa/airflow_auth.go @@ -4,13 +4,15 @@ import ( "context" "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" "net/url" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -115,7 +117,7 @@ func (e *airflowEngine) loginV3(ctx context.Context, t airflowTarget) ([]*http.C } func (e *airflowEngine) v3Token(ctx context.Context, t airflowTarget) (string, error) { - body, _ := json.Marshal(map[string]string{"username": airflowAdminUser, "password": t.pass}) + body, _ := json.Marshal(map[string]string{"username": airflowAdminUser, "password": t.pass}, jsonx.V1()) res, err := e.request(ctx, http.MethodPost, t.base+"/auth/token", body, http.Header{ headerContentType: {"application/json"}, @@ -128,7 +130,8 @@ func (e *airflowEngine) v3Token(ctx context.Context, t airflowTarget) (string, e Token string `json:"access_token"` } - if res.status >= http.StatusMultipleChoices || json.Unmarshal(res.body, &out) != nil || out.Token == "" { + if res.status >= http.StatusMultipleChoices || json.Unmarshal(res.body, &out, jsonx.V1()) != nil || + out.Token == "" { return "", fmt.Errorf("%w: status %d", errAirflowLogin, res.status) } diff --git a/services/mwaa/airflow_auth_test.go b/services/mwaa/airflow_auth_test.go index 5507348082..1b8700dc6d 100644 --- a/services/mwaa/airflow_auth_test.go +++ b/services/mwaa/airflow_auth_test.go @@ -1,7 +1,7 @@ package mwaa_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "os" "path/filepath" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const startupBody = "export MY_VAR=from-startup\necho hello-startup\n" @@ -196,7 +197,7 @@ func TestAirflowAuth_SSOLoginAndRest(t *testing.T) { desc, err := rig.b.GetEnvironment(t.Context(), "auth") require.NoError(t, err) - raw, _ := json.Marshal(desc) + raw, _ := json.Marshal(desc, jsonx.V1()) assert.NotContains(t, string(raw), pass) rec := doMWAARequest(t, rig.h, http.MethodPost, "/webtoken/auth", nil) @@ -204,7 +205,7 @@ func TestAirflowAuth_SSOLoginAndRest(t *testing.T) { var tok map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok, jsonx.V1())) sso := rawRequest(t, rig.h, http.MethodGet, "/aws_mwaa/aws-console-sso?login=true&token="+tok["WebToken"], "", nil) require.Equal(t, http.StatusFound, sso.Code) @@ -235,7 +236,7 @@ func TestAirflowAuth_BrowserTarget(t *testing.T) { var tok map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok, jsonx.V1())) env, err := rig.b.GetEnvironment(t.Context(), "host") require.NoError(t, err) diff --git a/services/mwaa/airflow_engine_test.go b/services/mwaa/airflow_engine_test.go index 4be1b516ed..2571834f15 100644 --- a/services/mwaa/airflow_engine_test.go +++ b/services/mwaa/airflow_engine_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "maps" "net/http" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -414,7 +415,7 @@ func TestAirflowEngine_CLIAndTokens(t *testing.T) { var tok map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok, jsonx.V1())) assert.NotEmpty(t, tok["CliToken"]) tests := []struct { @@ -442,7 +443,7 @@ func TestAirflowEngine_CLIAndTokens(t *testing.T) { var resp map[string]string - require.NoError(t, json.Unmarshal(out.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(out.Body.Bytes(), &resp, jsonx.V1())) stdout, err := base64.StdEncoding.DecodeString(resp["stdout"]) require.NoError(t, err) stderr, err := base64.StdEncoding.DecodeString(resp["stderr"]) @@ -466,7 +467,7 @@ func TestAirflowEngine_WebLoginAndRest(t *testing.T) { var tok map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tok, jsonx.V1())) env, err := rig.b.GetEnvironment(t.Context(), "web") require.NoError(t, err) diff --git a/services/mwaa/airflow_sync.go b/services/mwaa/airflow_sync.go index a763753543..6828e1f177 100644 --- a/services/mwaa/airflow_sync.go +++ b/services/mwaa/airflow_sync.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -18,6 +18,7 @@ import ( awss3 "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" s3backend "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -200,7 +201,7 @@ func (e *airflowEngine) stageStatic(ctx context.Context, dir string, in airflowL _ = os.Chmod(filepath.Join(dir, "state"), airflowDirMode) - passwords, _ := json.Marshal(map[string]string{airflowAdminUser: in.adminPass}) + passwords, _ := json.Marshal(map[string]string{airflowAdminUser: in.adminPass}, jsonx.V1()) for name, data := range map[string][]byte{ "requirements.txt": reqs, diff --git a/services/mwaa/environments_validation_test.go b/services/mwaa/environments_validation_test.go index 31af2efa1c..e12fdde6ba 100644 --- a/services/mwaa/environments_validation_test.go +++ b/services/mwaa/environments_validation_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -441,7 +442,7 @@ func TestWorkerReplacementStrategy_AbsentFromCreate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "an unknown/invented field on Create must not fail validation") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasField := resp["WorkerReplacementStrategy"] assert.False(t, hasField, "CreateEnvironment response must never echo WorkerReplacementStrategy") } diff --git a/services/mwaa/export_test.go b/services/mwaa/export_test.go index b4ab003473..551925057d 100644 --- a/services/mwaa/export_test.go +++ b/services/mwaa/export_test.go @@ -1,9 +1,11 @@ package mwaa import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // EnvironmentCount returns the total number of environments in the backend across @@ -68,7 +70,7 @@ func NewInvokeRequest(method, path string) *invokeRestAPIRequest { func ResponseJSON(t *testing.T, r *InvokeRestAPIResponse) string { t.Helper() - raw, err := json.Marshal(r.RestAPIResponse) + raw, err := json.Marshal(r.RestAPIResponse, jsonx.V1()) if err != nil { t.Fatal(err) } diff --git a/services/mwaa/handler.go b/services/mwaa/handler.go index 76d590e740..1cf8259daa 100644 --- a/services/mwaa/handler.go +++ b/services/mwaa/handler.go @@ -2,7 +2,7 @@ package mwaa import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -328,7 +329,7 @@ func decodeJSONBody(c *echo.Context, target any) bool { return false } - if jsonErr := json.Unmarshal(body, target); jsonErr != nil { + if jsonErr := json.Unmarshal(body, target, jsonx.V1()); jsonErr != nil { _ = writeErrorResponse(c, http.StatusBadRequest, "ValidationException", "invalid request body") return false diff --git a/services/mwaa/handler_cli_token_test.go b/services/mwaa/handler_cli_token_test.go index 6812d4491f..0cf2aef90f 100644 --- a/services/mwaa/handler_cli_token_test.go +++ b/services/mwaa/handler_cli_token_test.go @@ -1,13 +1,16 @@ package mwaa_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateCliToken_HTTP_NonAvailable_Returns404(t *testing.T) { @@ -58,7 +61,7 @@ func TestHandler_CliToken_HappyPath(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["CliToken"]) } @@ -95,7 +98,7 @@ func TestHandler_CreateCliToken(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["CliToken"]) } }) @@ -118,7 +121,7 @@ func TestCliToken_HTTP_ResponseStructure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["CliToken"]) assert.NotEmpty(t, resp["WebServerHostname"]) @@ -156,7 +159,7 @@ func TestHTTP_TokensIncludeWebServerHostname(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantKey]) assert.NotEmpty(t, resp["WebServerHostname"]) assert.Contains(t, resp["WebServerHostname"], "amazonaws.com") diff --git a/services/mwaa/handler_environments_test.go b/services/mwaa/handler_environments_test.go index 9ffc310db6..c6a79201a3 100644 --- a/services/mwaa/handler_environments_test.go +++ b/services/mwaa/handler_environments_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -71,7 +72,7 @@ func TestHandler_CreateEnvironment(t *testing.T) { if tt.wantArn { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) } }) @@ -122,7 +123,7 @@ func TestHandler_GetEnvironment(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Environment"]) } }) @@ -168,7 +169,7 @@ func TestHandler_ListEnvironments(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) envs, ok := resp["Environments"].([]any) require.True(t, ok) @@ -317,7 +318,7 @@ func TestGetEnvironment_DerivedFields(t *testing.T) { Environment mwaa.Environment `json:"Environment"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) env := resp.Environment assert.Equal(t, int32(2), env.Schedulers) @@ -393,7 +394,7 @@ func TestListEnvironments_Pagination(t *testing.T) { Environments []string `json:"Environments"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantNames, resp.Environments) assert.Equal(t, tt.wantNext, resp.NextToken) }) @@ -481,7 +482,7 @@ func TestListEnvironments_HTTP_NoMaxResults_UsesDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["Environments"] assert.True(t, ok, "response must have Environments key") } @@ -510,7 +511,7 @@ func TestListEnvironments_HTTP_NextToken_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) envs1 := resp1["Environments"].([]any) assert.Len(t, envs1, 3) @@ -525,7 +526,7 @@ func TestListEnvironments_HTTP_NextToken_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) envs2 := resp2["Environments"].([]any) assert.Len(t, envs2, 2, "second page should have the remaining 2 environments") @@ -555,7 +556,7 @@ func TestHTTP_GetEnvironment_DefaultsPresent(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) env := resp["Environment"].(map[string]any) assert.InEpsilon(t, float64(10), env["MaxWorkers"], 0.001, "default MaxWorkers=10 should be visible via HTTP") @@ -1014,7 +1015,7 @@ func TestLifecycle_HTTP_CreateResponseDoesNotExposeStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) assert.Nil(t, resp["Status"], "create response must not expose Status") } @@ -1040,7 +1041,7 @@ func TestLifecycle_HTTP_GetEnvShowsCreatingThenAvailable(t *testing.T) { Status string `json:"Status"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(get1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(get1.Body.Bytes(), &resp1, jsonx.V1())) assert.Equal(t, "CREATING", resp1.Environment.Status) // Second GET: AVAILABLE @@ -1052,7 +1053,7 @@ func TestLifecycle_HTTP_GetEnvShowsCreatingThenAvailable(t *testing.T) { Status string `json:"Status"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(get2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(get2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, "AVAILABLE", resp2.Environment.Status) } @@ -1210,7 +1211,7 @@ func TestHTTP_FullCRUDLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] assert.NotEmpty(t, envARN) @@ -1224,7 +1225,7 @@ func TestHTTP_FullCRUDLifecycle(t *testing.T) { EnvironmentClass string `json:"EnvironmentClass"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(get1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(get1.Body.Bytes(), &resp1, jsonx.V1())) assert.Equal(t, "CREATING", resp1.Environment.Status) assert.Equal(t, "2.9.2", resp1.Environment.AirflowVersion) assert.Equal(t, "mw1.medium", resp1.Environment.EnvironmentClass) @@ -1237,7 +1238,7 @@ func TestHTTP_FullCRUDLifecycle(t *testing.T) { Status string `json:"Status"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(get2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(get2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, "AVAILABLE", resp2.Environment.Status) // Update. @@ -1255,7 +1256,7 @@ func TestHTTP_FullCRUDLifecycle(t *testing.T) { EnvironmentClass string `json:"EnvironmentClass"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(get3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(get3.Body.Bytes(), &resp3, jsonx.V1())) assert.Equal(t, "UPDATING", resp3.Environment.Status) assert.Equal(t, "mw1.large", resp3.Environment.EnvironmentClass) @@ -1304,7 +1305,7 @@ func TestHTTP_LoggingConfig_AllModules(t *testing.T) { LoggingConfiguration *mwaa.LoggingConfiguration `json:"LoggingConfiguration"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.Environment.LoggingConfiguration) require.NotNil(t, resp.Environment.LoggingConfiguration.DagProcessingLogs) assert.Equal(t, "INFO", resp.Environment.LoggingConfiguration.DagProcessingLogs.LogLevel) @@ -1345,7 +1346,7 @@ func TestHTTP_LoggingConfig_CloudWatchLogGroupArn_NotEchoedFromRequest(t *testin LoggingConfiguration *mwaa.LoggingConfiguration `json:"LoggingConfiguration"` } `json:"Environment"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) require.NotNil(t, resp.Environment.LoggingConfiguration) require.NotNil(t, resp.Environment.LoggingConfiguration.DagProcessingLogs) assert.Equal(t, "INFO", resp.Environment.LoggingConfiguration.DagProcessingLogs.LogLevel) diff --git a/services/mwaa/handler_metrics.go b/services/mwaa/handler_metrics.go index cac93f0911..a369a1ce3e 100644 --- a/services/mwaa/handler_metrics.go +++ b/services/mwaa/handler_metrics.go @@ -1,7 +1,7 @@ package mwaa import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handlePublishMetrics(c *echo.Context, name string) error { @@ -19,7 +20,7 @@ func (h *Handler) handlePublishMetrics(c *echo.Context, name string) error { var req publishMetricsRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/mwaa/handler_metrics_test.go b/services/mwaa/handler_metrics_test.go index 8bada07a86..e1abccd3e0 100644 --- a/services/mwaa/handler_metrics_test.go +++ b/services/mwaa/handler_metrics_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PublishMetrics(t *testing.T) { @@ -120,7 +122,7 @@ func TestHandler_PublishMetrics_NotFound_ErrorType(t *testing.T) { Message string `json:"message"` Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body.Type) } diff --git a/services/mwaa/handler_rest_api.go b/services/mwaa/handler_rest_api.go index 8b0f149334..063e810c8d 100644 --- a/services/mwaa/handler_rest_api.go +++ b/services/mwaa/handler_rest_api.go @@ -1,7 +1,7 @@ package mwaa import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleInvokeRestAPI(c *echo.Context, name string) error { @@ -19,7 +20,7 @@ func (h *Handler) handleInvokeRestAPI(c *echo.Context, name string) error { var req invokeRestAPIRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/mwaa/handler_rest_api_test.go b/services/mwaa/handler_rest_api_test.go index d52b7aed8d..6eb983ff8c 100644 --- a/services/mwaa/handler_rest_api_test.go +++ b/services/mwaa/handler_rest_api_test.go @@ -1,7 +1,7 @@ package mwaa_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_InvokeRestApi(t *testing.T) { @@ -126,7 +128,7 @@ func TestHandler_InvokeRestApi(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InDelta(t, float64(200), resp["RestApiStatusCode"], 0) } }) diff --git a/services/mwaa/handler_tags.go b/services/mwaa/handler_tags.go index 55208bd07f..b1c1d54d95 100644 --- a/services/mwaa/handler_tags.go +++ b/services/mwaa/handler_tags.go @@ -1,7 +1,7 @@ package mwaa import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTagsForResource(c *echo.Context, resourceARN string) error { @@ -42,7 +43,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string) error { Tags map[string]string `json:"Tags"` } - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/mwaa/handler_tags_test.go b/services/mwaa/handler_tags_test.go index 6eae6720be..79c03fbeae 100644 --- a/services/mwaa/handler_tags_test.go +++ b/services/mwaa/handler_tags_test.go @@ -1,13 +1,15 @@ package mwaa_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagsFlow(t *testing.T) { @@ -39,7 +41,7 @@ func TestHandler_TagsFlow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] require.NotEmpty(t, envARN) @@ -54,7 +56,7 @@ func TestHandler_TagsFlow(t *testing.T) { assert.Equal(t, http.StatusOK, listTagRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listTagRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listTagRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags, ok := tagsResp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "test", tags["env"]) @@ -104,7 +106,7 @@ func TestHandler_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] require.NotEmpty(t, envARN) @@ -129,7 +131,7 @@ func TestHandler_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].(map[string]any) assert.Len(t, tags, tt.wantTagsLen) }) @@ -158,14 +160,14 @@ func TestListTagsForResource_HTTP_EmptyTagsShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] rec := doMWAARequest(t, h, http.MethodGet, "/tags/"+envARN, nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["Tags"] assert.True(t, ok, "response must have Tags key even when empty") } @@ -187,7 +189,7 @@ func TestTagLimit_HTTP_TagResource_Exceeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] // Build 51 tags. @@ -257,7 +259,7 @@ func TestTags_HTTP_CreateWithTagsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) envARN := createResp["Arn"] // ListTagsForResource returns the creation tags. @@ -267,7 +269,7 @@ func TestTags_HTTP_CreateWithTagsRoundTrip(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagsResp, jsonx.V1())) assert.Equal(t, "airflow", tagsResp.Tags["service"]) assert.Equal(t, "production", tagsResp.Tags["tier"]) } diff --git a/services/mwaa/handler_test.go b/services/mwaa/handler_test.go index 931a1a0360..daf2fbff23 100644 --- a/services/mwaa/handler_test.go +++ b/services/mwaa/handler_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -37,7 +38,7 @@ func doMWAARequest(t *testing.T, h *mwaa.Handler, method, path string, body any) if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/mwaa/handler_web_login_token_test.go b/services/mwaa/handler_web_login_token_test.go index df79cda172..48a6370ea6 100644 --- a/services/mwaa/handler_web_login_token_test.go +++ b/services/mwaa/handler_web_login_token_test.go @@ -1,13 +1,16 @@ package mwaa_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateWebLoginToken_HTTP_NonAvailable_Returns404(t *testing.T) { @@ -57,7 +60,7 @@ func TestHandler_WebToken_HappyPath(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WebToken"]) } @@ -94,7 +97,7 @@ func TestHandler_CreateWebLoginToken(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WebToken"]) } }) @@ -117,7 +120,7 @@ func TestWebLoginToken_HTTP_ResponseStructure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WebToken"]) assert.NotEmpty(t, resp["WebServerHostname"]) diff --git a/services/mwaa/persistence.go b/services/mwaa/persistence.go index 87e7877f6f..0487a5eaae 100644 --- a/services/mwaa/persistence.go +++ b/services/mwaa/persistence.go @@ -2,7 +2,7 @@ package mwaa import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -73,7 +73,7 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Metrics map[string]map[string][]MetricDatum `json:"metrics"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -173,7 +173,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds the environments store.Table from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, envDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/mwaa/tags_test.go b/services/mwaa/tags_test.go index 6a92630053..880fd4b324 100644 --- a/services/mwaa/tags_test.go +++ b/services/mwaa/tags_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -333,7 +334,7 @@ func TestBackend_ARNIndex(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) envARN = resp["Arn"] } diff --git a/services/mwaa/web_login_identity_test.go b/services/mwaa/web_login_identity_test.go index bf89dc60dd..447ef94342 100644 --- a/services/mwaa/web_login_identity_test.go +++ b/services/mwaa/web_login_identity_test.go @@ -2,7 +2,7 @@ package mwaa_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/mwaa" ) @@ -52,7 +53,7 @@ func TestCreateWebLoginTokenIamIdentity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.want, out["IamIdentity"]) }) } diff --git a/services/neptune/engine_probe.go b/services/neptune/engine_probe.go index ebc2449e50..bf006a76d8 100644 --- a/services/neptune/engine_probe.go +++ b/services/neptune/engine_probe.go @@ -7,7 +7,7 @@ import ( "crypto/sha1" //nolint:gosec // RFC 6455 mandates SHA-1 for the handshake accept key "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -17,6 +17,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -98,7 +100,7 @@ func ProbeGremlin(ctx context.Context, addr string) error { } var resp gremlinResponse - if err = json.Unmarshal(reply, &resp); err != nil { + if err = json.Unmarshal(reply, &resp, jsonx.V1()); err != nil { return fmt.Errorf("decode gremlin response: %w", err) } @@ -114,7 +116,7 @@ func gremlinPayload() ([]byte, error) { RequestID: uuid.NewString(), Op: "eval", Args: map[string]any{"gremlin": gremlinProbeQ, "language": "gremlin-groovy"}, - }) + }, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode gremlin request: %w", err) } diff --git a/services/neptune/gremlin/frame.go b/services/neptune/gremlin/frame.go index 5f789a44e5..4ede1d092a 100644 --- a/services/neptune/gremlin/frame.go +++ b/services/neptune/gremlin/frame.go @@ -2,11 +2,14 @@ package gremlin import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "github.com/google/uuid" "github.com/gorilla/websocket" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const uuidBytes = 16 @@ -79,7 +82,8 @@ func recoverFrame(messageType int, data []byte) FrameRequest { RequestID string `json:"requestId"` } - if json.NewDecoder(bytes.NewReader(body)).Decode(&raw) == nil && raw.RequestID != "" { + if json.UnmarshalDecode(jsontext.NewDecoder(bytes.NewReader(body)), &raw, jsonx.V1()) == nil && + raw.RequestID != "" { req.ID = raw.RequestID } diff --git a/services/neptune/gremlin/graphson.go b/services/neptune/gremlin/graphson.go index f859ea5711..a2a981569c 100644 --- a/services/neptune/gremlin/graphson.go +++ b/services/neptune/gremlin/graphson.go @@ -2,9 +2,12 @@ package gremlin import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "math" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -190,10 +193,9 @@ func (w graphsonWriter) emptyMap() any { func marshalNoEscape(v any) ([]byte, error) { var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(false) + enc := jsontext.NewEncoder(&buf, jsonx.V1(), jsontext.EscapeForHTML(false)) - if err := enc.Encode(v); err != nil { + if err := json.MarshalEncode(enc, v); err != nil { return nil, err //nolint:wrapcheck // plain encode error } @@ -203,7 +205,7 @@ func marshalNoEscape(v any) ([]byte, error) { // decodeGraphSON turns a decoded JSON request value (numbers as json.Number) into engine values. func decodeGraphSON(v any) (any, error) { switch t := v.(type) { - case json.Number: + case jsonx.Number: return numberFromJSON(t), nil case []any: return decodeGraphSONList(t) @@ -219,7 +221,7 @@ func decodeGraphSON(v any) (any, error) { return v, nil } -func numberFromJSON(n json.Number) any { +func numberFromJSON(n jsonx.Number) any { if i, err := n.Int64(); err == nil { return i } @@ -295,7 +297,7 @@ func decodeTyped(typ string, val any) (any, error) { func decodeNumber(val any) (any, error) { switch t := val.(type) { - case json.Number: + case jsonx.Number: return numberFromJSON(t), nil case string: f, err := strconv.ParseFloat(t, 64) diff --git a/services/neptune/gremlin/server.go b/services/neptune/gremlin/server.go index fe995d2fd9..c872ef47a8 100644 --- a/services/neptune/gremlin/server.go +++ b/services/neptune/gremlin/server.go @@ -3,7 +3,8 @@ package gremlin import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/websocket" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" ) @@ -151,10 +153,9 @@ func parseJSONRequest(body []byte, c codec) (*message, error) { Processor string `json:"processor"` } - dec := json.NewDecoder(bytes.NewReader(body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(body)) - if err := dec.Decode(&raw); err != nil { + if err := json.UnmarshalDecode(dec, &raw, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, invalidArg("Malformed message: %v", err) } @@ -422,7 +423,7 @@ func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) { func toJSONNumber(v any) any { if f, ok := v.(float64); ok { - return json.Number(formatFloat(f)) + return jsonx.Number(formatFloat(f)) } return v @@ -437,7 +438,12 @@ func readHTTPRequest(w http.ResponseWriter, r *http.Request) (*httpRequest, erro var req httpRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil && !errors.Is(err, io.EOF) { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(r.Body), + &req, + jsonx.V1(), + ); err != nil && + !errors.Is(err, io.EOF) { return nil, invalidArg("Malformed request body: %v", err) } @@ -459,5 +465,8 @@ func writeHTTPError(w http.ResponseWriter, e *Error, id string) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(map[string]string{jsonReqID: id, jsonCode: e.Code, "detailedMessage": e.Detail}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]string{jsonReqID: id, jsonCode: e.Code, "detailedMessage": e.Detail}, + ) } diff --git a/services/neptune/gremlin/server_test.go b/services/neptune/gremlin/server_test.go index 70ac09fe0c..c7b5f289bf 100644 --- a/services/neptune/gremlin/server_test.go +++ b/services/neptune/gremlin/server_test.go @@ -2,7 +2,8 @@ package gremlin_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/neptune/gremlin" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" @@ -55,7 +57,7 @@ type wsResponse struct { Code int `json:"code"` } `json:"status"` Result struct { - Data json.RawMessage `json:"data"` + Data jsontext.Value `json:"data"` } `json:"result"` } @@ -75,7 +77,7 @@ func call(t *testing.T, c *websocket.Conn, mt int, payload []byte) []wsResponse require.NoError(t, err) var r wsResponse - require.NoError(t, json.Unmarshal(data, &r), string(data)) + require.NoError(t, json.Unmarshal(data, &r, jsonx.V1()), string(data)) out = append(out, r) @@ -89,7 +91,7 @@ const evalFrame = `{"requestId":"11111111-1111-1111-1111-111111111111","op":"eva `"args":{"gremlin":%q,"language":"gremlin-groovy","aliases":{"g":"g"}%s}}` func evalBody(script, extra string) string { - b, _ := json.Marshal(script) + b, _ := json.Marshal(script, jsonx.V1()) return strings.Replace(strings.Replace(evalFrame, "%q", string(b), 1), "%s", extra, 1) } diff --git a/services/neptune/gremlin_ws_proxy_test.go b/services/neptune/gremlin_ws_proxy_test.go index 7e43c9c833..0916fad851 100644 --- a/services/neptune/gremlin_ws_proxy_test.go +++ b/services/neptune/gremlin_ws_proxy_test.go @@ -5,7 +5,7 @@ import ( "crypto/sha256" "encoding/binary" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "net" "net/http" @@ -22,6 +22,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -136,7 +137,7 @@ func wsFreePort(t *testing.T) int { func wsEval(script string) []byte { b, _ := json.Marshal(map[string]any{ "requestId": wsTestReqID, "op": "eval", "processor": "", "args": map[string]any{"gremlin": script}, - }) + }, jsonx.V1()) return b } @@ -290,7 +291,7 @@ func TestGremlinProxyFrameAuthorization(t *testing.T) { return } - require.NoError(t, json.Unmarshal(raw, &out), string(raw)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1()), string(raw)) assert.InDelta(t, tt.wantCode, out.Status.Code, 0) assert.Contains(t, out.Status.Message, tt.wantMsg) diff --git a/services/neptune/handler_test.go b/services/neptune/handler_test.go index 6ca880a42b..b8aa07df99 100644 --- a/services/neptune/handler_test.go +++ b/services/neptune/handler_test.go @@ -1,7 +1,7 @@ package neptune_test import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "io" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/neptune" ) @@ -552,7 +553,7 @@ func TestPersistenceRoundTrip(t *testing.T) { // Verify it's valid JSON var raw map[string]any - require.NoError(t, json.Unmarshal(data, &raw)) + require.NoError(t, json.Unmarshal(data, &raw, jsonx.V1())) restored := neptune.NewInMemoryBackend("000000000000", "us-east-1") require.NoError(t, restored.Restore(t.Context(), data)) diff --git a/services/neptune/iam_auth.go b/services/neptune/iam_auth.go index 519d2bddfa..bb562a9181 100644 --- a/services/neptune/iam_auth.go +++ b/services/neptune/iam_auth.go @@ -4,7 +4,7 @@ import ( "bytes" "cmp" "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/bolt" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" "github.com/blackbirdworks/gopherstack/services/neptune/gremlin" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" @@ -289,7 +290,7 @@ func (ca clusterAuth) authenticateBolt(auth map[string]any, now time.Time) (*iam } var tok map[string]string - if err := json.Unmarshal([]byte(raw), &tok); err != nil { + if err := json.Unmarshal([]byte(raw), &tok, jsonx.V1()); err != nil { return nil, errIAMBadBoltToken } @@ -435,7 +436,7 @@ func authorizeProxied(w http.ResponseWriter, r *http.Request) bool { Gremlin string `json:"gremlin"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) script = cmp.Or(req.Gremlin, script) } diff --git a/services/neptune/iam_dataplane_test.go b/services/neptune/iam_dataplane_test.go index 76c2aee13b..ab8212a7c9 100644 --- a/services/neptune/iam_dataplane_test.go +++ b/services/neptune/iam_dataplane_test.go @@ -3,7 +3,7 @@ package neptune_test import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "io" "net" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/bolt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/iam" "github.com/blackbirdworks/gopherstack/services/neptune" @@ -233,7 +234,7 @@ func dpGremlinWS(t *testing.T, c neptune.DBCluster, accessKey, script string) (m frame, err := json.Marshal(map[string]any{ "requestId": "7f1a8f4c-0b0e-4a8a-9d3a-1c2d3e4f5a6b", "op": "eval", "processor": "", "args": map[string]any{"gremlin": script}, - }) + }, jsonx.V1()) require.NoError(t, err) require.NoError(t, conn.WriteMessage(websocket.TextMessage, frame)) @@ -241,7 +242,7 @@ func dpGremlinWS(t *testing.T, c neptune.DBCluster, accessKey, script string) (m require.NoError(t, err) var out map[string]any - require.NoError(t, json.Unmarshal(raw, &out)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1())) return out, nil } @@ -294,7 +295,7 @@ func dpBoltToken(t *testing.T, c neptune.DBCluster, accessKey, secret, service s raw, err := json.Marshal(map[string]string{ "Authorization": req.Header.Get("Authorization"), "HttpMethod": http.MethodGet, "X-Amz-Date": req.Header.Get("X-Amz-Date"), "Host": req.Host, - }) + }, jsonx.V1()) require.NoError(t, err) return string(raw) diff --git a/services/neptune/opencypher/graph_test.go b/services/neptune/opencypher/graph_test.go index 758876f8ba..594970b179 100644 --- a/services/neptune/opencypher/graph_test.go +++ b/services/neptune/opencypher/graph_test.go @@ -1,12 +1,13 @@ package opencypher_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" ) @@ -22,7 +23,7 @@ func run(t *testing.T, g *opencypher.Graph, q string, params map[string]any) (st return "", err } - b, err := json.Marshal(res) + b, err := json.Marshal(res, jsonx.V1()) require.NoError(t, err) return string(b), nil @@ -149,7 +150,7 @@ func TestNodeAndRelationshipShapes(t *testing.T) { var rows []map[string]map[string]any - require.NoError(t, json.Unmarshal([]byte(got), &rows)) + require.NoError(t, json.Unmarshal([]byte(got), &rows, jsonx.V1())) require.Len(t, rows, 1) a, r := rows[0]["a"], rows[0]["r"] diff --git a/services/neptune/opencypher/persist.go b/services/neptune/opencypher/persist.go index c9ddacf56a..fc0fea1a5e 100644 --- a/services/neptune/opencypher/persist.go +++ b/services/neptune/opencypher/persist.go @@ -3,11 +3,14 @@ package opencypher import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "sort" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -63,7 +66,7 @@ func (g *Graph) Export(ctx context.Context) ([]byte, error) { }) } - b, err := json.Marshal(d) + b, err := json.Marshal(d, jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode graph: %w", err) } @@ -105,10 +108,9 @@ func (g *Graph) Import(ctx context.Context, data []byte) error { } func decodeUseNumber(data []byte, v any) error { - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(data)) - return dec.Decode(v) + return json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()) } func encodeProps(p map[string]any) map[string]any { @@ -149,7 +151,7 @@ func decodeProps(p map[string]any) map[string]any { func decodeValue(v any) any { switch t := v.(type) { - case json.Number: + case jsonx.Number: if i, err := t.Int64(); err == nil { return i } diff --git a/services/neptune/opencypher/value.go b/services/neptune/opencypher/value.go index 39e5ddc023..b5f1a3a1b3 100644 --- a/services/neptune/opencypher/value.go +++ b/services/neptune/opencypher/value.go @@ -3,12 +3,15 @@ package opencypher import ( "bytes" "cmp" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Result is the table produced by RETURN; a query with no RETURN has no columns. @@ -36,8 +39,8 @@ func (r *Result) MarshalJSON() ([]byte, error) { buf.WriteByte(',') } - k, _ := json.Marshal(col) - v, err := json.Marshal(jsonValue(row[j])) + k, _ := json.Marshal(col, jsonx.V1()) + v, err := json.Marshal(jsonValue(row[j]), jsonx.V1()) if err != nil { return nil, fmt.Errorf("encode %s: %w", col, err) } @@ -112,11 +115,10 @@ func ParseParameters(raw string) (map[string]any, error) { return map[string]any{}, nil } - dec := json.NewDecoder(strings.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(strings.NewReader(raw)) var m map[string]any - if err := dec.Decode(&m); err != nil { + if err := json.UnmarshalDecode(dec, &m, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, &Error{Code: CodeInvalidParameter, Detail: "parameters must be a JSON object: " + err.Error()} } @@ -129,7 +131,7 @@ func ParseParameters(raw string) (map[string]any, error) { func normalize(v any) any { switch t := v.(type) { - case json.Number: + case jsonx.Number: if i, err := t.Int64(); err == nil { return i } diff --git a/services/neptune/opencypher_front.go b/services/neptune/opencypher_front.go index 1a864f5095..ce60f4072f 100644 --- a/services/neptune/opencypher_front.go +++ b/services/neptune/opencypher_front.go @@ -2,7 +2,8 @@ package neptune import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -20,6 +21,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/bolt" "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sgfilter" "github.com/blackbirdworks/gopherstack/services/neptune/gremlin" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" @@ -169,7 +171,7 @@ type cypherCall struct { func writeCypherJSON(w http.ResponseWriter, status int, body any) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") w.WriteHeader(status) - _ = json.NewEncoder(w).Encode(body) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), body) } func writeCypherError(w http.ResponseWriter, status int, code, detail string) { @@ -207,7 +209,7 @@ var errMethodNotAllowed = errors.New("method not allowed") func readCypherJSON(body io.Reader) (cypherCall, error) { var req cypherRequest - if err := json.NewDecoder(body).Decode(&req); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(body), &req, jsonx.V1()); err != nil { return cypherCall{}, fmt.Errorf("decode request: %w", err) } @@ -225,7 +227,7 @@ func readCypherJSON(body io.Reader) (cypherCall, error) { case string: call.params = p default: - raw, _ := json.Marshal(p) + raw, _ := json.Marshal(p, jsonx.V1()) call.params = string(raw) } @@ -291,7 +293,7 @@ func (f *cypherFront) runQuery(ctx context.Context, w http.ResponseWriter, query return } - writeCypherJSON(w, http.StatusOK, map[string]json.RawMessage{"results": rowsOrEmpty(rows)}) + writeCypherJSON(w, http.StatusOK, map[string]jsontext.Value{"results": rowsOrEmpty(rows)}) } func (f *cypherFront) serveExplain(ctx context.Context, w http.ResponseWriter, call cypherCall, params map[string]any) { @@ -318,9 +320,9 @@ func (f *cypherFront) serveExplain(ctx context.Context, w http.ResponseWriter, c _, _ = io.WriteString(w, plan) } -func rowsOrEmpty(rows []byte) json.RawMessage { +func rowsOrEmpty(rows []byte) jsontext.Value { if len(rows) == 0 { - return json.RawMessage("[]") + return jsontext.Value("[]") } return rows diff --git a/services/neptune/opencypher_front_test.go b/services/neptune/opencypher_front_test.go index 2574392dcc..3792a13275 100644 --- a/services/neptune/opencypher_front_test.go +++ b/services/neptune/opencypher_front_test.go @@ -2,7 +2,7 @@ package neptune_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/neptune" ) @@ -72,7 +73,7 @@ func cypherDo(t *testing.T, method, target, contentType, body string) (int, map[ require.NoError(t, err) var out map[string]any - require.NoError(t, json.Unmarshal(raw, &out), string(raw)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1()), string(raw)) return resp.StatusCode, out } diff --git a/services/neptune/opencypher_queries_internal_test.go b/services/neptune/opencypher_queries_internal_test.go index b9bc663d6b..1e3d6f9cd4 100644 --- a/services/neptune/opencypher_queries_internal_test.go +++ b/services/neptune/opencypher_queries_internal_test.go @@ -2,7 +2,7 @@ package neptune import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/neptune/opencypher" ) @@ -22,7 +23,7 @@ func statusDo(t *testing.T, f *cypherFront, method, target string) (int, map[str f.serveQueryStatus(rec, req) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return rec.Code, out } diff --git a/services/neptune/persistence.go b/services/neptune/persistence.go index 7b5c12c5c4..fc4c2f4a2f 100644 --- a/services/neptune/persistence.go +++ b/services/neptune/persistence.go @@ -2,7 +2,7 @@ package neptune import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -54,14 +54,14 @@ func regionalDTOKeyFn[V any](d *regionalDTO[V]) string { return regionKey(d.Regi // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ClusterRoles map[string]map[string][]string `json:"clusterRoles"` Tags map[string]map[string][]Tag `json:"tags"` ParameterOverrides map[string]map[string]ParameterValue `json:"parameterOverrides"` ClusterParameterOverrides map[string]map[string]ParameterValue `json:"clusterParameterOverrides"` PendingMaintenanceActions map[string]map[string]PendingMaintenanceAction `json:"pendingMaintenanceActions"` EventsLog map[string][]Event `json:"eventsLog"` - OpenCypherGraphs map[string]json.RawMessage `json:"openCypherGraphs,omitempty"` + OpenCypherGraphs map[string]jsontext.Value `json:"openCypherGraphs,omitempty"` AccountID string `json:"accountID"` Region string `json:"region"` Version int `json:"version"` @@ -289,7 +289,7 @@ func unwrapRegionalDTOs[V any](dtos *store.Table[regionalDTO[V]], setRegion func // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, clusterDTOs, instanceDTOs, subnetGroupDTOs, clusterParameterGroupDTOs, clusterSnapshotDTOs, parameterGroupDTOs, clusterEndpointDTOs, eventSubscriptionDTOs, globalClusterDTOs := buildPersistenceDTORegistry() @@ -342,12 +342,12 @@ func (b *InMemoryBackend) graphLocked(key string) *opencypher.Graph { return g } -func (b *InMemoryBackend) exportGraphsLocked(ctx context.Context) map[string]json.RawMessage { +func (b *InMemoryBackend) exportGraphsLocked(ctx context.Context) map[string]jsontext.Value { if len(b.graphs) == 0 { return nil } - out := make(map[string]json.RawMessage, len(b.graphs)) + out := make(map[string]jsontext.Value, len(b.graphs)) for key, g := range b.graphs { raw, err := g.Export(ctx) @@ -363,7 +363,7 @@ func (b *InMemoryBackend) exportGraphsLocked(ctx context.Context) map[string]jso return out } -func (b *InMemoryBackend) importGraphsLocked(ctx context.Context, dumps map[string]json.RawMessage) { +func (b *InMemoryBackend) importGraphsLocked(ctx context.Context, dumps map[string]jsontext.Value) { b.graphs = make(map[string]*opencypher.Graph, len(dumps)) for key, raw := range dumps { diff --git a/services/networkfirewall/handler.go b/services/networkfirewall/handler.go index 721cad7a10..418abf4e0d 100644 --- a/services/networkfirewall/handler.go +++ b/services/networkfirewall/handler.go @@ -2,8 +2,7 @@ package networkfirewall import ( "context" - "encoding/json" - "errors" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -12,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -85,7 +85,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if json.Unmarshal(body, &data) != nil { + if json.Unmarshal(body, &data, jsonx.V1()) != nil { return "" } @@ -127,12 +127,12 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - _, isSyntax := errors.AsType[*json.SyntaxError](err) - _, isType := errors.AsType[*json.UnmarshalTypeError](err) + isSyntax := jsonx.IsSyntaxError(err) + isType := jsonx.IsTypeError(err) if isSyntax || isType { err = invalid("The request body is not valid: %v", err) diff --git a/services/networkfirewall/ordering_test.go b/services/networkfirewall/ordering_test.go index eaeab0fdc3..90dfa2acd7 100644 --- a/services/networkfirewall/ordering_test.go +++ b/services/networkfirewall/ordering_test.go @@ -1,7 +1,8 @@ package networkfirewall_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "testing" @@ -10,23 +11,25 @@ import ( "github.com/aws/aws-sdk-go-v2/service/networkfirewall/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // retime rewrites timeField on every record that has idField, giving the i-th id (sorted) times[i]. func retime(t *testing.T, snap []byte, timeField string, times []string) []byte { t.Helper() - var root map[string]json.RawMessage + var root map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &root)) + require.NoError(t, json.Unmarshal(snap, &root, jsonx.V1())) - var tables map[string]json.RawMessage + var tables map[string]jsontext.Value - require.NoError(t, json.Unmarshal(root["tables"], &tables)) + require.NoError(t, json.Unmarshal(root["tables"], &tables, jsonx.V1())) for name, raw := range tables { var rows []map[string]any - if json.Unmarshal(raw, &rows) != nil { + if json.Unmarshal(raw, &rows, jsonx.V1()) != nil { continue } @@ -50,18 +53,18 @@ func retime(t *testing.T, snap []byte, timeField string, times []string) []byte } } - b, err := json.Marshal(rows) + b, err := json.Marshal(rows, jsonx.V1()) require.NoError(t, err) tables[name] = b } - tb, err := json.Marshal(tables) + tb, err := json.Marshal(tables, jsonx.V1()) require.NoError(t, err) root["tables"] = tb - out, err := json.Marshal(root) + out, err := json.Marshal(root, jsonx.V1()) require.NoError(t, err) return out diff --git a/services/networkfirewall/persistence.go b/services/networkfirewall/persistence.go index 727b6973df..2cf39f7ea0 100644 --- a/services/networkfirewall/persistence.go +++ b/services/networkfirewall/persistence.go @@ -2,7 +2,7 @@ package networkfirewall import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -13,8 +13,8 @@ const networkFirewallSnapshotVersion = 1 // backendSnapshot is the on-disk shape: one JSON array per registered table. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes backend state to JSON. diff --git a/services/networkfirewall/resource_policy.go b/services/networkfirewall/resource_policy.go index 73ae4c26a5..551b14ec16 100644 --- a/services/networkfirewall/resource_policy.go +++ b/services/networkfirewall/resource_policy.go @@ -2,7 +2,11 @@ package networkfirewall import ( "context" - "encoding/json" + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutResourcePolicyInput is the PutResourcePolicy request. @@ -29,10 +33,10 @@ type DeleteResourcePolicyInput = DescribeResourcePolicyInput func validatePolicyDocument(doc string) error { var parsed struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if err := json.Unmarshal([]byte(doc), &parsed); err != nil || len(parsed.Statement) == 0 { + if err := json.Unmarshal([]byte(doc), &parsed, jsonx.V1()); err != nil || len(parsed.Statement) == 0 { return invalidResourcePolicy("The policy must be a JSON document with a Statement") } diff --git a/services/networkmanager/corenetworkpolicydiff.go b/services/networkmanager/corenetworkpolicydiff.go index e2ddc6a36f..65e364880b 100644 --- a/services/networkmanager/corenetworkpolicydiff.go +++ b/services/networkmanager/corenetworkpolicydiff.go @@ -1,8 +1,11 @@ package networkmanager import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "reflect" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // This file implements the real ADD/MODIFY/REMOVE structural diff @@ -28,17 +31,17 @@ import ( type namedSection struct { key string - raw json.RawMessage + raw jsontext.Value } // policyDocSections is the subset of the real Cloud WAN policy-document // schema's top-level keys this diff engine reads. type policyDocSections struct { - CoreNetworkConfiguration json.RawMessage `json:"core-network-configuration"` - Segments []json.RawMessage `json:"segments"` - NetworkFunctionGroups []json.RawMessage `json:"network-function-groups"` - SegmentActions []json.RawMessage `json:"segment-actions"` - AttachmentPolicies []json.RawMessage `json:"attachment-policies"` + CoreNetworkConfiguration jsontext.Value `json:"core-network-configuration"` + Segments []jsontext.Value `json:"segments"` + NetworkFunctionGroups []jsontext.Value `json:"network-function-groups"` + SegmentActions []jsontext.Value `json:"segment-actions"` + AttachmentPolicies []jsontext.Value `json:"attachment-policies"` } func parsePolicyDocSections(doc string) policyDocSections { @@ -51,22 +54,22 @@ func parsePolicyDocSections(doc string) policyDocSections { // CreateCoreNetwork) -- an error here means an empty/absent document, // which decodes to the zero value, itself a valid "nothing to diff" // input to diffNamedSections. - _ = json.Unmarshal([]byte(doc), &s) + _ = json.Unmarshal([]byte(doc), &s, jsonx.V1()) return s } -func namedByKey(items []json.RawMessage, keyField string) map[string]namedSection { +func namedByKey(items []jsontext.Value, keyField string) map[string]namedSection { out := make(map[string]namedSection, len(items)) for _, item := range items { - var fields map[string]json.RawMessage - if err := json.Unmarshal(item, &fields); err != nil { + var fields map[string]jsontext.Value + if err := json.Unmarshal(item, &fields, jsonx.V1()); err != nil { continue } var key string - if err := json.Unmarshal(fields[keyField], &key); err != nil { + if err := json.Unmarshal(fields[keyField], &key, jsonx.V1()); err != nil { continue } @@ -82,7 +85,7 @@ func namedByKey(items []json.RawMessage, keyField string) map[string]namedSectio // key present in either oldItems or newItems, keyed by keyField (e.g. // "name", "rule-number"). func diffSectionEntries( - oldItems, newItems []json.RawMessage, + oldItems, newItems []jsontext.Value, keyField, changeType, pathPrefix string, values func(key string) *CoreNetworkChangeValues, ) []CoreNetworkChange { @@ -139,9 +142,9 @@ func withRawJSON(v *CoreNetworkChangeValues, raw string) *CoreNetworkChangeValue return v } -func jsonEqual(a, b json.RawMessage) bool { +func jsonEqual(a, b jsontext.Value) bool { var av, bv any - if json.Unmarshal(a, &av) != nil || json.Unmarshal(b, &bv) != nil { + if json.Unmarshal(a, &av, jsonx.V1()) != nil || json.Unmarshal(b, &bv, jsonx.V1()) != nil { return string(a) == string(b) } @@ -159,7 +162,7 @@ const ( // diffCoreNetworkConfiguration compares the single "core-network-configuration" // object, which has no natural key -- a single MODIFY/ADD/REMOVE covers it. -func diffCoreNetworkConfiguration(oldRaw, newRaw json.RawMessage) []CoreNetworkChange { +func diffCoreNetworkConfiguration(oldRaw, newRaw jsontext.Value) []CoreNetworkChange { base := CoreNetworkChange{ Identifier: coreNetworkConfigurationIdentifier, IdentifierPath: coreNetworkConfigurationChangeType, Type: coreNetworkConfigurationChangeType, diff --git a/services/networkmanager/corenetworks.go b/services/networkmanager/corenetworks.go index f9355f8fda..3bd265fad4 100644 --- a/services/networkmanager/corenetworks.go +++ b/services/networkmanager/corenetworks.go @@ -1,10 +1,11 @@ package networkmanager import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -42,7 +43,7 @@ func (b *InMemoryBackend) CreateCoreNetwork( return nil, validationError(fmt.Sprintf("%s %s not found", resourceGlobalNetwork, globalNetworkID)) } - if policyDocument != "" && !json.Valid([]byte(policyDocument)) { + if policyDocument != "" && !jsontext.Value([]byte(policyDocument)).IsValid(jsonx.V1()) { return nil, coreNetworkPolicyError("PolicyDocument is not valid JSON", []CoreNetworkPolicyError{ {ErrorCode: "InvalidPolicyDocument", Message: "PolicyDocument must be valid JSON", Path: "/"}, }) @@ -170,7 +171,7 @@ func (b *InMemoryBackend) PutCoreNetworkPolicy( return nil, nil, notFoundError(resourceCoreNetwork, coreNetworkID) } - if !json.Valid([]byte(policyDocument)) { + if !jsontext.Value([]byte(policyDocument)).IsValid(jsonx.V1()) { return nil, nil, coreNetworkPolicyError("PolicyDocument is not valid JSON", []CoreNetworkPolicyError{ {ErrorCode: "InvalidPolicyDocument", Message: "PolicyDocument must be valid JSON", Path: "/"}, }) diff --git a/services/networkmanager/handler.go b/services/networkmanager/handler.go index 40d7a603c5..6ab7053341 100644 --- a/services/networkmanager/handler.go +++ b/services/networkmanager/handler.go @@ -2,7 +2,7 @@ package networkmanager import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -245,7 +246,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { addErrorFields(body, apiErr) } - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) @@ -378,7 +379,7 @@ func decodeJSONBody(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validationError("malformed request body: " + err.Error()) } @@ -388,7 +389,7 @@ func decodeJSONBody(body []byte, v any) error { // marshalResponse marshals v, wrapping any error as an internal failure // (marshaling our own well-typed wire structs should never fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, internalServerError("networkmanager: marshal response: " + err.Error()) } diff --git a/services/networkmanager/introspection.go b/services/networkmanager/introspection.go index ffceea9890..f0d2c763c7 100644 --- a/services/networkmanager/introspection.go +++ b/services/networkmanager/introspection.go @@ -1,9 +1,10 @@ package networkmanager import ( - "encoding/json" + "encoding/json/v2" "sort" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -201,7 +202,7 @@ func (b *InMemoryBackend) coreNetworkScopedResourceItems( } func mustJSON(v any) string { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return "{}" } diff --git a/services/networkmanager/persistence.go b/services/networkmanager/persistence.go index cdb47f4c19..a996c5daa4 100644 --- a/services/networkmanager/persistence.go +++ b/services/networkmanager/persistence.go @@ -2,7 +2,7 @@ package networkmanager import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -20,11 +20,11 @@ const networkManagerSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Network Manager // backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - OrgStatus *organizationStatus `json:"orgStatus"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + OrgStatus *organizationStatus `json:"orgStatus"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/networkmanager/resourcepolicy.go b/services/networkmanager/resourcepolicy.go index b784652e07..d97230c78e 100644 --- a/services/networkmanager/resourcepolicy.go +++ b/services/networkmanager/resourcepolicy.go @@ -1,6 +1,10 @@ package networkmanager -import "encoding/json" +import ( + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" +) // This file implements PARITY.md family W: a resource-based IAM-style JSON // policy document attached to a NetworkManager resource ARN (used for @@ -16,7 +20,7 @@ func (b *InMemoryBackend) PutResourcePolicy(resourceArn, policyDocument string) b.mu.Lock("PutResourcePolicy") defer b.mu.Unlock() - if !json.Valid([]byte(policyDocument)) { + if !jsontext.Value([]byte(policyDocument)).IsValid(jsonx.V1()) { return validationError("PolicyDocument is not valid JSON") } diff --git a/services/networkmanager/validate.go b/services/networkmanager/validate.go index 0f640f3cb0..d52a4ebd95 100644 --- a/services/networkmanager/validate.go +++ b/services/networkmanager/validate.go @@ -1,13 +1,14 @@ package networkmanager import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" "strconv" "unicode/utf8" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -93,7 +94,7 @@ func decodeObject(body []byte) (map[string]any, bool) { } var m map[string]any - if err := json.Unmarshal(body, &m); err != nil { + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { return nil, false } diff --git a/services/networkmonitor/handler.go b/services/networkmonitor/handler.go index b1fa05d524..5d9b874387 100644 --- a/services/networkmonitor/handler.go +++ b/services/networkmonitor/handler.go @@ -2,7 +2,7 @@ package networkmonitor import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -293,9 +294,6 @@ func (h *Handler) dispatch( } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - var code string var status int @@ -313,8 +311,8 @@ func (h *Handler) handleError(c *echo.Context, err error) error { status = http.StatusBadRequest code = "ValidationException" case errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): status = http.StatusBadRequest code = "ValidationException" default: @@ -402,7 +400,7 @@ func extractTagResourceARN(path string) string { func (h *Handler) handleCreateMonitor(ctx context.Context, body []byte) ([]byte, error) { var req createMonitorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -430,7 +428,7 @@ func (h *Handler) handleCreateMonitor(ctx context.Context, body []byte) ([]byte, Tags: m.Tags, } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleDeleteMonitor(ctx context.Context, path string) ([]byte, error) { @@ -473,7 +471,7 @@ func (h *Handler) handleGetMonitor(ctx context.Context, path string) ([]byte, er ModifiedAt: epochSeconds(m.ModifiedAt), } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleUpdateMonitor( @@ -487,7 +485,7 @@ func (h *Handler) handleUpdateMonitor( } var req updateMonitorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -505,7 +503,7 @@ func (h *Handler) handleUpdateMonitor( Tags: m.Tags, } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleListMonitors(ctx context.Context, query url.Values) ([]byte, error) { @@ -529,7 +527,7 @@ func (h *Handler) handleListMonitors(ctx context.Context, query url.Values) ([]b NextToken: outToken, } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleCreateProbe(ctx context.Context, path string, body []byte) ([]byte, error) { @@ -539,7 +537,7 @@ func (h *Handler) handleCreateProbe(ctx context.Context, path string, body []byt } var req createProbeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -552,7 +550,7 @@ func (h *Handler) handleCreateProbe(ctx context.Context, path string, body []byt return nil, err } - return json.Marshal(toProbeWire(probe)) + return json.Marshal(toProbeWire(probe), jsonx.V1()) } func (h *Handler) handleDeleteProbe(ctx context.Context, path string) ([]byte, error) { @@ -591,7 +589,7 @@ func (h *Handler) handleGetProbe(ctx context.Context, path string) ([]byte, erro return nil, err } - return json.Marshal(toProbeWire(probe)) + return json.Marshal(toProbeWire(probe), jsonx.V1()) } func (h *Handler) handleUpdateProbe(ctx context.Context, path string, body []byte) ([]byte, error) { @@ -607,7 +605,7 @@ func (h *Handler) handleUpdateProbe(ctx context.Context, path string, body []byt } var req updateProbeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -616,7 +614,7 @@ func (h *Handler) handleUpdateProbe(ctx context.Context, path string, body []byt return nil, err } - return json.Marshal(toProbeWire(probe)) + return json.Marshal(toProbeWire(probe), jsonx.V1()) } func (h *Handler) handleListTagsForResource(ctx context.Context, path string) ([]byte, error) { @@ -634,7 +632,7 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, path string) ([ tags = map[string]string{} } - return json.Marshal(listTagsForResourceResponse{Tags: tags}) + return json.Marshal(listTagsForResourceResponse{Tags: tags}, jsonx.V1()) } func (h *Handler) handleTagResource(ctx context.Context, path string, body []byte) ([]byte, error) { @@ -644,7 +642,7 @@ func (h *Handler) handleTagResource(ctx context.Context, path string, body []byt } var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/networkmonitor/handler_monitors_test.go b/services/networkmonitor/handler_monitors_test.go index 1414a279a4..61ba10624f 100644 --- a/services/networkmonitor/handler_monitors_test.go +++ b/services/networkmonitor/handler_monitors_test.go @@ -1,13 +1,16 @@ package networkmonitor_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerCreateMonitor(t *testing.T) { @@ -185,7 +188,7 @@ func TestHandlerListMonitors(t *testing.T) { } var resp map[string]any - if err := json.Unmarshal(rr.Body.Bytes(), &resp); err != nil { + if err := json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -271,9 +274,9 @@ func TestHandlerGetMonitorProbeTimestampsEpochFloat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out struct { - Probes []map[string]json.RawMessage `json:"probes"` + Probes []map[string]jsontext.Value `json:"probes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Probes, 1, "expected one probe in GetMonitor response") createdAtRaw, hasCreatedAt := out.Probes[0]["createdAt"] @@ -281,7 +284,7 @@ func TestHandlerGetMonitorProbeTimestampsEpochFloat(t *testing.T) { if hasCreatedAt { var asFloat float64 - require.NoError(t, json.Unmarshal(createdAtRaw, &asFloat), + require.NoError(t, json.Unmarshal(createdAtRaw, &asFloat, jsonx.V1()), "probe createdAt in GetMonitor must be JSON number, got: %s", string(createdAtRaw)) assert.Greater(t, asFloat, float64(0)) } @@ -310,15 +313,15 @@ func TestHandlerGetMonitorTimestampsEpochFloat(t *testing.T) { rec := doNMRequest(t, h, http.MethodGet, "/monitors/epoch-mon", nil) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) fieldRaw, ok := raw[tt.field] assert.True(t, ok, "%s must be present", tt.field) if ok { var asFloat float64 - require.NoError(t, json.Unmarshal(fieldRaw, &asFloat), + require.NoError(t, json.Unmarshal(fieldRaw, &asFloat, jsonx.V1()), "%s must be JSON number, got: %s", tt.field, string(fieldRaw)) assert.Greater(t, asFloat, float64(0)) } @@ -382,7 +385,7 @@ func TestHandlerListMonitorsPagination(t *testing.T) { NextToken string `json:"nextToken"` Monitors []any `json:"monitors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) pageCounts = append(pageCounts, len(out.Monitors)) token = out.NextToken @@ -412,7 +415,7 @@ func TestHandlerListMonitorsTokenPastEnd(t *testing.T) { NextToken string `json:"nextToken"` Monitors []any `json:"monitors"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.Monitors, "token past last item must return empty list, not first page") assert.Empty(t, out.NextToken) diff --git a/services/networkmonitor/handler_probes_test.go b/services/networkmonitor/handler_probes_test.go index 31d3610f5b..5d857395b4 100644 --- a/services/networkmonitor/handler_probes_test.go +++ b/services/networkmonitor/handler_probes_test.go @@ -1,12 +1,15 @@ package networkmonitor_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerProbeLifecycle(t *testing.T) { @@ -38,7 +41,7 @@ func TestHandlerProbeLifecycle(t *testing.T) { } var probeResp map[string]any - if err := json.Unmarshal(rr.Body.Bytes(), &probeResp); err != nil { + if err := json.Unmarshal(rr.Body.Bytes(), &probeResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal probe: %v", err) } @@ -96,15 +99,15 @@ func TestHandlerProbeTimestampsEpochFloat(t *testing.T) { rec := doNMRequest(t, h, http.MethodGet, "/monitors/ts-mon/probes/"+probeID, nil) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) createdAtRaw, hasCreatedAt := raw["createdAt"] assert.True(t, hasCreatedAt, "createdAt must be present in GetProbe response") if hasCreatedAt { var asFloat float64 - require.NoError(t, json.Unmarshal(createdAtRaw, &asFloat), + require.NoError(t, json.Unmarshal(createdAtRaw, &asFloat, jsonx.V1()), "createdAt must be a JSON number (epoch seconds), got: %s", string(createdAtRaw)) assert.Greater(t, asFloat, float64(0), "createdAt epoch value must be positive") } @@ -145,7 +148,7 @@ func TestHandlerProbeAddressFamilyAutoDetect(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantFamily, out["addressFamily"], "addressFamily for %s", tt.destination) }) } @@ -169,6 +172,6 @@ func TestHandlerUpdateProbeStatePending(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "PENDING", out["state"], "probe state after UpdateProbe with state=PENDING") } diff --git a/services/networkmonitor/handler_tags_test.go b/services/networkmonitor/handler_tags_test.go index b5a07e40e9..3d37da5bc6 100644 --- a/services/networkmonitor/handler_tags_test.go +++ b/services/networkmonitor/handler_tags_test.go @@ -1,9 +1,11 @@ package networkmonitor_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerTags(t *testing.T) { @@ -21,7 +23,7 @@ func TestHandlerTags(t *testing.T) { } var mon map[string]any - if err := json.Unmarshal(rr.Body.Bytes(), &mon); err != nil { + if err := json.Unmarshal(rr.Body.Bytes(), &mon, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } @@ -36,7 +38,7 @@ func TestHandlerTags(t *testing.T) { } var tagResp map[string]any - if err := json.Unmarshal(rr.Body.Bytes(), &tagResp); err != nil { + if err := json.Unmarshal(rr.Body.Bytes(), &tagResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal tags: %v", err) } @@ -58,7 +60,7 @@ func TestHandlerTags(t *testing.T) { } rr = doNMRequest(t, h, http.MethodGet, "/tags/"+monARN, nil) - if err := json.Unmarshal(rr.Body.Bytes(), &tagResp); err != nil { + if err := json.Unmarshal(rr.Body.Bytes(), &tagResp, jsonx.V1()); err != nil { t.Fatalf("unmarshal: %v", err) } diff --git a/services/networkmonitor/handler_test.go b/services/networkmonitor/handler_test.go index d0771c314c..671ad94a6a 100644 --- a/services/networkmonitor/handler_test.go +++ b/services/networkmonitor/handler_test.go @@ -2,7 +2,7 @@ package networkmonitor_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/networkmonitor" ) @@ -36,7 +37,7 @@ func doNMRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) if err != nil { t.Fatalf("marshal body: %v", err) } @@ -69,7 +70,7 @@ func createMonitorP(t *testing.T, h *networkmonitor.Handler, name string) string require.Equal(t, http.StatusOK, rec.Code, "create monitor: %s", rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arn, _ := out["monitorArn"].(string) require.NotEmpty(t, arn) @@ -90,7 +91,7 @@ func createProbeP(t *testing.T, h *networkmonitor.Handler, monitorName, destinat require.Equal(t, http.StatusOK, rec.Code, "create probe: %s", rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) id, _ := out["probeId"].(string) require.NotEmpty(t, id) diff --git a/services/networkmonitor/persistence.go b/services/networkmonitor/persistence.go index 4128694355..cdef74dee7 100644 --- a/services/networkmonitor/persistence.go +++ b/services/networkmonitor/persistence.go @@ -2,7 +2,7 @@ package networkmonitor import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -25,9 +25,9 @@ const networkmonitorSnapshotVersion = 1 // backend. Tables holds one JSON-encoded array per registered store.Table // (just "monitors"), produced by [store.Registry.SnapshotAll]. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - NextProbeSeq int64 `json:"next_probe_seq"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + NextProbeSeq int64 `json:"next_probe_seq"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/oam/persistence.go b/services/oam/persistence.go index ee310d30a2..e7b2cbe8e1 100644 --- a/services/oam/persistence.go +++ b/services/oam/persistence.go @@ -2,7 +2,7 @@ package oam import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,11 +12,11 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Seq int64 `json:"seq"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Seq int64 `json:"seq"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/oam/policy.go b/services/oam/policy.go index c38d3f1445..27c497cfac 100644 --- a/services/oam/policy.go +++ b/services/oam/policy.go @@ -1,11 +1,13 @@ package oam import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -15,24 +17,24 @@ const ( ) type rawPolicy struct { - Version string `json:"Version,omitempty"` - Statement json.RawMessage `json:"Statement"` + Version string `json:"Version,omitempty"` + Statement jsontext.Value `json:"Statement"` } -func decodeStatements(raw json.RawMessage) ([]map[string]any, bool) { +func decodeStatements(raw jsontext.Value) ([]map[string]any, bool) { trimmed := strings.TrimSpace(string(raw)) switch { case strings.HasPrefix(trimmed, "{"): var one map[string]any - if json.Unmarshal(raw, &one) != nil { + if json.Unmarshal(raw, &one, jsonx.V1()) != nil { return nil, false } return []map[string]any{one}, true case strings.HasPrefix(trimmed, "["): var many []map[string]any - if json.Unmarshal(raw, &many) != nil { + if json.Unmarshal(raw, &many, jsonx.V1()) != nil { return nil, false } @@ -63,7 +65,7 @@ func stringList(v any) []string { func validateSinkPolicy(policy string) error { var p rawPolicy - if err := json.Unmarshal([]byte(policy), &p); err != nil { + if err := json.Unmarshal([]byte(policy), &p, jsonx.V1()); err != nil { return fail(ErrInvalidParameter, "Policy is not valid JSON") } @@ -120,7 +122,7 @@ func (b *InMemoryBackend) sinkPolicyAllowsLocked( } var p rawPolicy - if json.Unmarshal([]byte(sink.Policy), &p) != nil { + if json.Unmarshal([]byte(sink.Policy), &p, jsonx.V1()) != nil { return false } @@ -141,7 +143,7 @@ func (b *InMemoryBackend) sinkPolicyAllowsLocked( return false } - doc, err := json.Marshal(map[string]any{"Version": p.Version, "Statement": applicable}) + doc, err := json.Marshal(map[string]any{"Version": p.Version, "Statement": applicable}, jsonx.V1()) if err != nil { return false } diff --git a/services/oam/realclient_links_test.go b/services/oam/realclient_links_test.go index 96f2ef845c..b6b01c7600 100644 --- a/services/oam/realclient_links_test.go +++ b/services/oam/realclient_links_test.go @@ -1,7 +1,7 @@ package oam_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/oam" ) @@ -23,11 +24,11 @@ func allowPolicy(account, condition string) string { if condition != "" { var c any - _ = json.Unmarshal([]byte(condition), &c) + _ = json.Unmarshal([]byte(condition), &c, jsonx.V1()) stmt["Condition"] = c } - b, _ := json.Marshal(map[string]any{"Version": "2012-10-17", "Statement": []any{stmt}}) + b, _ := json.Marshal(map[string]any{"Version": "2012-10-17", "Statement": []any{stmt}}, jsonx.V1()) return string(b) } diff --git a/services/ociapigateway/auth.go b/services/ociapigateway/auth.go index 7228d56e18..41f9a74700 100644 --- a/services/ociapigateway/auth.go +++ b/services/ociapigateway/auth.go @@ -7,7 +7,8 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "errors" "fmt" @@ -20,6 +21,7 @@ import ( "github.com/golang-jwt/jwt/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -170,7 +172,11 @@ func (b *InMemoryBackend) remoteKeys(ctx context.Context, uri string, hours *int } `json:"keys"` } - if err = json.NewDecoder(io.LimitReader(resp.Body, jwksMaxBytes)).Decode(&doc); err != nil { + if err = json.UnmarshalDecode( + jsontext.NewDecoder(io.LimitReader(resp.Body, jwksMaxBytes)), + &doc, + jsonx.V1(), + ); err != nil { return nil, err } @@ -460,7 +466,7 @@ func (b *InMemoryBackend) customAuth(ctx context.Context, a *authDoc, token stri payload = map[string]any{"type": "USER_DEFINED", "data": data} } - body, _ := json.Marshal(payload) //nolint:errchkjson // static shape + body, _ := json.Marshal(payload, jsonx.V1()) //nolint:errchkjson // static shape out, err := inv.InvokeFunction(ctx, a.FunctionID, FunctionRequest{ Method: http.MethodPost, Header: http.Header{"Content-Type": {"application/json"}}, Body: body, @@ -475,7 +481,7 @@ func (b *InMemoryBackend) customAuth(ctx context.Context, a *authDoc, token stri Active bool `json:"active"` } - if json.Unmarshal(out.Body, &verdict) != nil || !verdict.Active { + if json.Unmarshal(out.Body, &verdict, jsonx.V1()) != nil || !verdict.Active { return authResult{wwwAuth: verdict.WWWAuth} } diff --git a/services/ociapigateway/auth_test.go b/services/ociapigateway/auth_test.go index 390b485b5f..866d961d0a 100644 --- a/services/ociapigateway/auth_test.go +++ b/services/ociapigateway/auth_test.go @@ -5,7 +5,8 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "math/big" "net/http" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ociapigateway "github.com/blackbirdworks/gopherstack/services/ociapigateway" ) @@ -51,7 +53,7 @@ func pemOf(t *testing.T, k *rsa.PrivateKey, kid string) string { b, err := json.Marshal(map[string]string{ "format": "PEM", "kid": kid, "key": string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: der})), - }) + }, jsonx.V1()) require.NoError(t, err) return string(b) @@ -262,9 +264,9 @@ func TestJWTRemoteJWKS(t *testing.T) { fetches.Add(1) var key map[string]any - _ = json.Unmarshal([]byte(jwkOf(k, "r1")), &key) + _ = json.Unmarshal([]byte(jwkOf(k, "r1")), &key, jsonx.V1()) - _ = json.NewEncoder(w).Encode(map[string]any{"keys": []any{key}}) + _ = json.MarshalEncode(jsontext.NewEncoder(w, jsonx.V1()), map[string]any{"keys": []any{key}}) })) t.Cleanup(jwks.Close) @@ -356,7 +358,7 @@ func TestCustomAuthenticator(t *testing.T) { Token string `json:"token"` } - _ = json.Unmarshal(in.Body, &p) + _ = json.Unmarshal(in.Body, &p, jsonx.V1()) verdict := map[string]any{"active": false, "wwwAuthenticate": `Bearer realm="orders"`} @@ -367,7 +369,7 @@ func TestCustomAuthenticator(t *testing.T) { verdict = map[string]any{"active": true, "scope": []string{"orders.write"}} } - out, _ := json.Marshal(verdict) + out, _ := json.Marshal(verdict, jsonx.V1()) return ociapigateway.FunctionResponse{Status: 200, Body: out}, nil }} diff --git a/services/ociapigateway/certificates.go b/services/ociapigateway/certificates.go index 4e776742ba..e15a4e1795 100644 --- a/services/ociapigateway/certificates.go +++ b/services/ociapigateway/certificates.go @@ -3,7 +3,7 @@ package ociapigateway import ( "crypto/tls" "crypto/x509" - "encoding/json" + "encoding/json/jsontext" "encoding/pem" "time" @@ -13,12 +13,12 @@ import ( type createCertificateIn struct { Tags - CompartmentID string `json:"compartmentId"` - DisplayName string `json:"displayName"` - PrivateKey string `json:"privateKey"` - Certificate string `json:"certificate"` - Intermediate string `json:"intermediateCertificates"` - Locks json.RawMessage `json:"locks"` + CompartmentID string `json:"compartmentId"` + DisplayName string `json:"displayName"` + PrivateKey string `json:"privateKey"` + Certificate string `json:"certificate"` + Intermediate string `json:"intermediateCertificates"` + Locks jsontext.Value `json:"locks"` } type updateCertificateIn struct { @@ -33,7 +33,7 @@ type CertificateWire struct { TimeNotValidAfter time.Time `json:"timeNotValidAfter"` DefinedTags map[string]map[string]any `json:"definedTags,omitempty"` FreeformTags map[string]string `json:"freeformTags,omitempty"` - Locks json.RawMessage `json:"locks,omitempty"` + Locks jsontext.Value `json:"locks,omitempty"` ID string `json:"id"` CompartmentID string `json:"compartmentId"` DisplayName string `json:"displayName"` diff --git a/services/ociapigateway/dataplane.go b/services/ociapigateway/dataplane.go index 24794a4f73..77916d1246 100644 --- a/services/ociapigateway/dataplane.go +++ b/services/ociapigateway/dataplane.go @@ -1,7 +1,7 @@ package ociapigateway import ( - "encoding/json" + "encoding/json/v2" "io" "maps" "net/http" @@ -9,6 +9,7 @@ import ( "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -26,7 +27,10 @@ func writeGWError(w http.ResponseWriter, status int, msg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) - out, _ := json.Marshal(map[string]any{"code": status, "message": msg}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + map[string]any{"code": status, "message": msg}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = w.Write(out) } diff --git a/services/ociapigateway/dataplane_test.go b/services/ociapigateway/dataplane_test.go index fef97d428b..b22b60c78f 100644 --- a/services/ociapigateway/dataplane_test.go +++ b/services/ociapigateway/dataplane_test.go @@ -2,7 +2,7 @@ package ociapigateway_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ociapigateway "github.com/blackbirdworks/gopherstack/services/ociapigateway" ) @@ -452,7 +453,7 @@ func TestSpecRoundTrip(t *testing.T) { } `json:"specification"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, "STOCK_RESPONSE_BACKEND", out.Specification.Routes[0].Backend.Type) assert.NotContains(t, body, "StubResponse") } diff --git a/services/ociapigateway/deployments.go b/services/ociapigateway/deployments.go index e0b3aa781f..f67d68bd15 100644 --- a/services/ociapigateway/deployments.go +++ b/services/ociapigateway/deployments.go @@ -1,7 +1,7 @@ package ociapigateway import ( - "encoding/json" + "encoding/json/jsontext" "time" "github.com/blackbirdworks/gopherstack/pkgs/page" @@ -10,18 +10,18 @@ import ( type createDeploymentIn struct { Tags - GatewayID string `json:"gatewayId"` - CompartmentID string `json:"compartmentId"` - PathPrefix string `json:"pathPrefix"` - DisplayName string `json:"displayName"` - Locks json.RawMessage `json:"locks"` - Specification json.RawMessage `json:"specification"` + GatewayID string `json:"gatewayId"` + CompartmentID string `json:"compartmentId"` + PathPrefix string `json:"pathPrefix"` + DisplayName string `json:"displayName"` + Locks jsontext.Value `json:"locks"` + Specification jsontext.Value `json:"specification"` } type updateDeploymentIn struct { Tags - DisplayName *string `json:"displayName"` - Specification json.RawMessage `json:"specification"` + DisplayName *string `json:"displayName"` + Specification jsontext.Value `json:"specification"` } // DeploymentWire is the wire form of a deployment. @@ -37,8 +37,8 @@ type DeploymentWire struct { Endpoint string `json:"endpoint"` DisplayName string `json:"displayName"` LifecycleState string `json:"lifecycleState"` - Locks json.RawMessage `json:"locks,omitempty"` - Specification json.RawMessage `json:"specification,omitempty"` + Locks jsontext.Value `json:"locks,omitempty"` + Specification jsontext.Value `json:"specification,omitempty"` } func (b *InMemoryBackend) deploymentView(d *Deployment, full bool) DeploymentWire { diff --git a/services/ociapigateway/gateways.go b/services/ociapigateway/gateways.go index 91ae8de001..7ce31e0923 100644 --- a/services/ociapigateway/gateways.go +++ b/services/ociapigateway/gateways.go @@ -1,36 +1,38 @@ package ociapigateway import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "slices" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) type createGatewayIn struct { Tags - Locks json.RawMessage `json:"locks"` - CaBundles json.RawMessage `json:"caBundles"` - ResponseCache json.RawMessage `json:"responseCacheDetails"` - DisplayName string `json:"displayName"` - CompartmentID string `json:"compartmentId"` - EndpointType string `json:"endpointType"` - SubnetID string `json:"subnetId"` - CertificateID string `json:"certificateId"` - IPMode string `json:"ipMode"` - NSGs []string `json:"networkSecurityGroupIds"` + Locks jsontext.Value `json:"locks"` + CaBundles jsontext.Value `json:"caBundles"` + ResponseCache jsontext.Value `json:"responseCacheDetails"` + DisplayName string `json:"displayName"` + CompartmentID string `json:"compartmentId"` + EndpointType string `json:"endpointType"` + SubnetID string `json:"subnetId"` + CertificateID string `json:"certificateId"` + IPMode string `json:"ipMode"` + NSGs []string `json:"networkSecurityGroupIds"` } type updateGatewayIn struct { Tags - CaBundles json.RawMessage `json:"caBundles"` - ResponseCache json.RawMessage `json:"responseCacheDetails"` - DisplayName *string `json:"displayName"` - CertificateID *string `json:"certificateId"` - NSGs []string `json:"networkSecurityGroupIds"` + CaBundles jsontext.Value `json:"caBundles"` + ResponseCache jsontext.Value `json:"responseCacheDetails"` + DisplayName *string `json:"displayName"` + CertificateID *string `json:"certificateId"` + NSGs []string `json:"networkSecurityGroupIds"` } type changeCompartmentIn struct { @@ -43,9 +45,9 @@ type GatewayWire struct { TimeUpdated time.Time `json:"timeUpdated"` DefinedTags map[string]map[string]any `json:"definedTags,omitempty"` FreeformTags map[string]string `json:"freeformTags,omitempty"` - Locks json.RawMessage `json:"locks,omitempty"` - CaBundles json.RawMessage `json:"caBundles,omitempty"` - ResponseCache json.RawMessage `json:"responseCacheDetails,omitempty"` + Locks jsontext.Value `json:"locks,omitempty"` + CaBundles jsontext.Value `json:"caBundles,omitempty"` + ResponseCache jsontext.Value `json:"responseCacheDetails,omitempty"` ID string `json:"id"` CompartmentID string `json:"compartmentId"` EndpointType string `json:"endpointType"` @@ -117,12 +119,12 @@ func (b *InMemoryBackend) validateGateway(in *createGatewayIn) *APIError { return b.checkCertificateRef(in.CertificateID) } -func jsonIsNoCache(raw json.RawMessage) bool { +func jsonIsNoCache(raw jsontext.Value) bool { var d struct { Type string `json:"type"` } - return json.Unmarshal(raw, &d) == nil && d.Type == "NONE" + return json.Unmarshal(raw, &d, jsonx.V1()) == nil && d.Type == "NONE" } func (b *InMemoryBackend) gatewayNameTaken(compartment, name, except string) bool { @@ -169,7 +171,7 @@ func (b *InMemoryBackend) CreateGateway(in createGatewayIn) (GatewayWire, string return gatewayView(g), wr, g.Etag, nil } -func nullRaw(r json.RawMessage) json.RawMessage { +func nullRaw(r jsontext.Value) jsontext.Value { if string(r) == jsonNull { return nil } diff --git a/services/ociapigateway/handler.go b/services/ociapigateway/handler.go index 714b9cd74f..69cec4f7f0 100644 --- a/services/ociapigateway/handler.go +++ b/services/ociapigateway/handler.go @@ -3,7 +3,8 @@ package ociapigateway import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +118,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociapigateway: encode response: %w", err) } @@ -162,10 +164,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -187,7 +188,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -262,7 +266,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociapigateway/helpers_test.go b/services/ociapigateway/helpers_test.go index e791ca8a95..810f0ec7f2 100644 --- a/services/ociapigateway/helpers_test.go +++ b/services/ociapigateway/helpers_test.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "crypto/rsa" "crypto/x509" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "io" @@ -19,6 +19,7 @@ import ( "github.com/oracle/oci-go-sdk/v65/common" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ociapigateway "github.com/blackbirdworks/gopherstack/services/ociapigateway" @@ -190,7 +191,7 @@ func specFromJSON(t *testing.T, s string) *apigateway.ApiSpecification { t.Helper() var spec apigateway.ApiSpecification - require.NoError(t, json.Unmarshal([]byte(s), &spec)) + require.NoError(t, json.Unmarshal([]byte(s), &spec, jsonx.V1())) return &spec } diff --git a/services/ociapigateway/models.go b/services/ociapigateway/models.go index 6158ff5b8a..d03c5e2ef9 100644 --- a/services/ociapigateway/models.go +++ b/services/ociapigateway/models.go @@ -1,7 +1,7 @@ package ociapigateway import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -38,59 +38,59 @@ func (t *Tags) merge(in Tags) { // Gateway is an API gateway. type Gateway struct { - TimeCreated time.Time `json:"timeCreated"` - TimeUpdated time.Time `json:"timeUpdated"` - Tags Tags `json:"tags"` - TransitionAt *time.Time `json:"transitionAt,omitempty"` - Locks json.RawMessage `json:"locks,omitempty"` - CaBundles json.RawMessage `json:"caBundles,omitempty"` - ResponseCache json.RawMessage `json:"responseCache,omitempty"` - ID string `json:"id"` - CompartmentID string `json:"compartmentId"` - EndpointType string `json:"endpointType"` - DisplayName string `json:"displayName"` - SubnetID string `json:"subnetId"` - Hostname string `json:"hostname"` - CertificateID string `json:"certificateId,omitempty"` - IPMode string `json:"ipMode,omitempty"` - State string `json:"state"` - Etag string `json:"etag"` - NSGs []string `json:"networkSecurityGroupIds,omitempty"` + TimeCreated time.Time `json:"timeCreated"` + TimeUpdated time.Time `json:"timeUpdated"` + Tags Tags `json:"tags"` + TransitionAt *time.Time `json:"transitionAt,omitempty"` + Locks jsontext.Value `json:"locks,omitempty"` + CaBundles jsontext.Value `json:"caBundles,omitempty"` + ResponseCache jsontext.Value `json:"responseCache,omitempty"` + ID string `json:"id"` + CompartmentID string `json:"compartmentId"` + EndpointType string `json:"endpointType"` + DisplayName string `json:"displayName"` + SubnetID string `json:"subnetId"` + Hostname string `json:"hostname"` + CertificateID string `json:"certificateId,omitempty"` + IPMode string `json:"ipMode,omitempty"` + State string `json:"state"` + Etag string `json:"etag"` + NSGs []string `json:"networkSecurityGroupIds,omitempty"` } // Deployment is an API deployment on a gateway. type Deployment struct { - TimeCreated time.Time `json:"timeCreated"` - TimeUpdated time.Time `json:"timeUpdated"` - Tags Tags `json:"tags"` - TransitionAt *time.Time `json:"transitionAt,omitempty"` - ID string `json:"id"` - GatewayID string `json:"gatewayId"` - CompartmentID string `json:"compartmentId"` - PathPrefix string `json:"pathPrefix"` - DisplayName string `json:"displayName"` - State string `json:"state"` - Etag string `json:"etag"` - Locks json.RawMessage `json:"locks,omitempty"` - Spec json.RawMessage `json:"specification"` + TimeCreated time.Time `json:"timeCreated"` + TimeUpdated time.Time `json:"timeUpdated"` + Tags Tags `json:"tags"` + TransitionAt *time.Time `json:"transitionAt,omitempty"` + ID string `json:"id"` + GatewayID string `json:"gatewayId"` + CompartmentID string `json:"compartmentId"` + PathPrefix string `json:"pathPrefix"` + DisplayName string `json:"displayName"` + State string `json:"state"` + Etag string `json:"etag"` + Locks jsontext.Value `json:"locks,omitempty"` + Spec jsontext.Value `json:"specification"` } // Certificate is a TLS certificate usable by a gateway. type Certificate struct { - TimeCreated time.Time `json:"timeCreated"` - TimeUpdated time.Time `json:"timeUpdated"` - TimeNotValidAfter time.Time `json:"timeNotValidAfter"` - Tags Tags `json:"tags"` - TransitionAt *time.Time `json:"transitionAt,omitempty"` - Locks json.RawMessage `json:"locks,omitempty"` - ID string `json:"id"` - CompartmentID string `json:"compartmentId"` - DisplayName string `json:"displayName"` - CertPEM string `json:"certificate"` - Intermediate string `json:"intermediateCertificates,omitempty"` - State string `json:"state"` - Etag string `json:"etag"` - SubjectNames []string `json:"subjectNames"` + TimeCreated time.Time `json:"timeCreated"` + TimeUpdated time.Time `json:"timeUpdated"` + TimeNotValidAfter time.Time `json:"timeNotValidAfter"` + Tags Tags `json:"tags"` + TransitionAt *time.Time `json:"transitionAt,omitempty"` + Locks jsontext.Value `json:"locks,omitempty"` + ID string `json:"id"` + CompartmentID string `json:"compartmentId"` + DisplayName string `json:"displayName"` + CertPEM string `json:"certificate"` + Intermediate string `json:"intermediateCertificates,omitempty"` + State string `json:"state"` + Etag string `json:"etag"` + SubjectNames []string `json:"subjectNames"` } // WorkRequest records an asynchronous operation. diff --git a/services/ociapigateway/spec.go b/services/ociapigateway/spec.go index 331f768915..63fdb134e0 100644 --- a/services/ociapigateway/spec.go +++ b/services/ociapigateway/spec.go @@ -2,12 +2,15 @@ package ociapigateway import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/url" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Backend, authentication and policy discriminators. @@ -144,12 +147,12 @@ type authDoc struct { } type requestPolicies struct { - Authentication *authDoc `json:"authentication"` - RateLimiting *rateDoc `json:"rateLimiting"` - Cors *corsDoc `json:"cors"` - MutualTLS json.RawMessage `json:"mutualTls"` - UsagePlans json.RawMessage `json:"usagePlans"` - DynamicAuthentication json.RawMessage `json:"dynamicAuthentication"` + Authentication *authDoc `json:"authentication"` + RateLimiting *rateDoc `json:"rateLimiting"` + Cors *corsDoc `json:"cors"` + MutualTLS jsontext.Value `json:"mutualTls"` + UsagePlans jsontext.Value `json:"usagePlans"` + DynamicAuthentication jsontext.Value `json:"dynamicAuthentication"` } type setItem struct { @@ -196,19 +199,19 @@ type authzDoc struct { } type routeRequestPolicies struct { - Authorization *authzDoc `json:"authorization"` - Cors *corsDoc `json:"cors"` - HeaderTransform *transformDoc `json:"headerTransformations"` - QueryTransform *transformDoc `json:"queryParameterTransformations"` - QueryValidations json.RawMessage `json:"queryParameterValidations"` - HeaderValidations json.RawMessage `json:"headerValidations"` - BodyValidation json.RawMessage `json:"bodyValidation"` - ResponseCacheLookup json.RawMessage `json:"responseCacheLookup"` + Authorization *authzDoc `json:"authorization"` + Cors *corsDoc `json:"cors"` + HeaderTransform *transformDoc `json:"headerTransformations"` + QueryTransform *transformDoc `json:"queryParameterTransformations"` + QueryValidations jsontext.Value `json:"queryParameterValidations"` + HeaderValidations jsontext.Value `json:"headerValidations"` + BodyValidation jsontext.Value `json:"bodyValidation"` + ResponseCacheLookup jsontext.Value `json:"responseCacheLookup"` } type routeResponsePolicies struct { - HeaderTransform *transformDoc `json:"headerTransformations"` - ResponseCacheStore json.RawMessage `json:"responseCacheStore"` + HeaderTransform *transformDoc `json:"headerTransformations"` + ResponseCacheStore jsontext.Value `json:"responseCacheStore"` } type routeDoc struct { @@ -221,7 +224,7 @@ type routeDoc struct { type specDoc struct { RequestPolicies *requestPolicies `json:"requestPolicies"` - LoggingPolicies json.RawMessage `json:"loggingPolicies"` + LoggingPolicies jsontext.Value `json:"loggingPolicies"` Routes []routeDoc `json:"routes"` } @@ -231,7 +234,7 @@ var ( prefixCharRe = regexp.MustCompile(`^[A-Za-z0-9$\-_.+!*'(),%;:@&=]+$`) ) -func isPresent(raw json.RawMessage) bool { +func isPresent(raw jsontext.Value) bool { return len(raw) > 0 && !bytes.Equal(raw, []byte(jsonNull)) } @@ -265,13 +268,13 @@ func validatePathPrefix(p string) *APIError { } // compileSpec decodes and validates a deployment specification. -func compileSpec(raw json.RawMessage) (*compiledSpec, *APIError) { +func compileSpec(raw jsontext.Value) (*compiledSpec, *APIError) { if !isPresent(raw) { return nil, errMissing("specification is required") } var doc specDoc - if err := json.Unmarshal(raw, &doc); err != nil { + if err := json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return nil, errParam("specification is not valid: " + err.Error()) } @@ -312,7 +315,7 @@ func validateRequestPolicies(p *requestPolicies) *APIError { return nil } - for name, raw := range map[string]json.RawMessage{ + for name, raw := range map[string]jsontext.Value{ "mutualTls": p.MutualTLS, "usagePlans": p.UsagePlans, "dynamicAuthentication": p.DynamicAuthentication, } { if isPresent(raw) { @@ -525,7 +528,7 @@ func validateRouteRequestPolicies(p *routeRequestPolicies) *APIError { return nil } - for name, raw := range map[string]json.RawMessage{ + for name, raw := range map[string]jsontext.Value{ "queryParameterValidations": p.QueryValidations, "headerValidations": p.HeaderValidations, "bodyValidation": p.BodyValidation, "responseCacheLookup": p.ResponseCacheLookup, } { diff --git a/services/ociartifacts/dataplane.go b/services/ociartifacts/dataplane.go index 3772030349..042339cd55 100644 --- a/services/ociartifacts/dataplane.go +++ b/services/ociartifacts/dataplane.go @@ -4,12 +4,13 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry" ) @@ -111,7 +112,7 @@ func (b *InMemoryBackend) IssueToken(user string, anon bool, scopes []Scope) (st b.mu.RUnlock() body, _ := json.Marshal( - tokenClaims{Sub: user, Anon: anon, Scopes: raw, Exp: exp}, + tokenClaims{Sub: user, Anon: anon, Scopes: raw, Exp: exp}, jsonx.V1(), ) //nolint:errchkjson // static shape payload := base64.RawURLEncoding.EncodeToString(body) @@ -131,7 +132,7 @@ func (b *InMemoryBackend) ParseToken(token string) (tokenClaims, bool) { } var c tokenClaims - if json.Unmarshal(raw, &c) != nil { + if json.Unmarshal(raw, &c, jsonx.V1()) != nil { return tokenClaims{}, false } @@ -274,7 +275,7 @@ func (b *InMemoryBackend) RecordPush(display, ref, digest, user string, body []b var doc manifestDoc - _ = json.Unmarshal(body, &doc) + _ = json.Unmarshal(body, &doc, jsonx.V1()) b.mu.Lock("RecordPush") defer b.mu.Unlock() diff --git a/services/ociartifacts/handler.go b/services/ociartifacts/handler.go index 69e6ba2dd5..2520893c7a 100644 --- a/services/ociartifacts/handler.go +++ b/services/ociartifacts/handler.go @@ -7,7 +7,8 @@ package ociartifacts import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -20,6 +21,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -118,7 +120,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociartifacts: encode response: %w", err) } @@ -172,10 +174,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr(http.StatusBadRequest, "CannotParseRequest", "The request body is not valid JSON for this operation") } @@ -194,7 +195,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -266,7 +270,7 @@ func (h *Handler) admin(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociartifacts/helpers_test.go b/services/ociartifacts/helpers_test.go index 21b98b682d..40bee2da4e 100644 --- a/services/ociartifacts/helpers_test.go +++ b/services/ociartifacts/helpers_test.go @@ -7,7 +7,7 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "io" @@ -22,6 +22,7 @@ import ( "github.com/oracle/oci-go-sdk/v65/genericartifactscontent" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -254,7 +255,7 @@ func (e *env) upload( func jsonBody(t *testing.T, v any) string { t.Helper() - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(out) diff --git a/services/ociartifacts/registry.go b/services/ociartifacts/registry.go index 4dc292baf2..9140ad9173 100644 --- a/services/ociartifacts/registry.go +++ b/services/ociartifacts/registry.go @@ -5,11 +5,12 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry" ) @@ -28,7 +29,7 @@ type regErrorEntry struct { } func writeJSON(w http.ResponseWriter, status int, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { status, raw = http.StatusInternalServerError, []byte(`{"errors":[{"code":"UNKNOWN","message":"encode"}]}`) } diff --git a/services/ociartifacts/registry_test.go b/services/ociartifacts/registry_test.go index 5dbbf1fb00..28c43b61ee 100644 --- a/services/ociartifacts/registry_test.go +++ b/services/ociartifacts/registry_test.go @@ -1,7 +1,7 @@ package ociartifacts_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociregistry/ocitest" "github.com/blackbirdworks/gopherstack/services/ociartifacts" ) @@ -36,7 +37,7 @@ func (e *env) token(t *testing.T, authz, scope string) (int, tokenReply) { var out tokenReply if resp.Status == http.StatusOK { - require.NoError(t, json.Unmarshal(resp.Body, &out)) + require.NoError(t, json.Unmarshal(resp.Body, &out, jsonx.V1())) } return resp.Status, out @@ -845,7 +846,7 @@ func manifestFor(t *testing.T, cfgDigest, layerDigest string, layerSize, cfgSize "layers": []any{map[string]any{ "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", "size": layerSize, "digest": layerDigest, }}, - }) + }, jsonx.V1()) require.NoError(t, err) return body diff --git a/services/ocicontainerengine/handler.go b/services/ocicontainerengine/handler.go index 82ccbad374..dfa6cc9b02 100644 --- a/services/ocicontainerengine/handler.go +++ b/services/ocicontainerengine/handler.go @@ -2,7 +2,7 @@ package ocicontainerengine import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +116,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocicontainerengine: encode response: %w", err) } @@ -163,7 +164,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -185,7 +186,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -254,7 +258,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocicontainerengine/helpers_test.go b/services/ocicontainerengine/helpers_test.go index 5d56c80776..b242888e8a 100644 --- a/services/ocicontainerengine/helpers_test.go +++ b/services/ocicontainerengine/helpers_test.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "crypto/rsa" "crypto/x509" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "io" @@ -19,6 +19,7 @@ import ( ke "github.com/oracle/oci-go-sdk/v65/containerengine" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -345,7 +346,7 @@ func (e *env) mkPool( } func quote(s string) string { - b, _ := json.Marshal(s) + b, _ := json.Marshal(s, jsonx.V1()) return string(b) } diff --git a/services/ocicontainerengine/models.go b/services/ocicontainerengine/models.go index 2790480923..65e599f08e 100644 --- a/services/ocicontainerengine/models.go +++ b/services/ocicontainerengine/models.go @@ -1,7 +1,7 @@ package ocicontainerengine import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -80,15 +80,15 @@ type TagCfg struct { // ClusterOptions is the cluster create and update options block. type ClusterOptions struct { - K8sNetwork *NetworkConfig `json:"kubernetesNetworkConfig,omitempty"` - AddOns *AddOns `json:"addOns,omitempty"` - Admission *Admission `json:"admissionControllerOptions,omitempty"` - PersistentVolume *TagCfg `json:"persistentVolumeConfig,omitempty"` - ServiceLb *TagCfg `json:"serviceLbConfig,omitempty"` - OIDCAuth json.RawMessage `json:"openIdConnectTokenAuthenticationConfig,omitempty"` - OIDCDiscovery json.RawMessage `json:"openIdConnectDiscovery,omitempty"` - ServiceLbSubnetID []string `json:"serviceLbSubnetIds,omitempty"` - IPFamilies []string `json:"ipFamilies,omitempty"` + K8sNetwork *NetworkConfig `json:"kubernetesNetworkConfig,omitempty"` + AddOns *AddOns `json:"addOns,omitempty"` + Admission *Admission `json:"admissionControllerOptions,omitempty"` + PersistentVolume *TagCfg `json:"persistentVolumeConfig,omitempty"` + ServiceLb *TagCfg `json:"serviceLbConfig,omitempty"` + OIDCAuth jsontext.Value `json:"openIdConnectTokenAuthenticationConfig,omitempty"` + OIDCDiscovery jsontext.Value `json:"openIdConnectDiscovery,omitempty"` + ServiceLbSubnetID []string `json:"serviceLbSubnetIds,omitempty"` + IPFamilies []string `json:"ipFamilies,omitempty"` } // KeyDetail references an image signing key. @@ -144,11 +144,11 @@ type Cluster struct { // Placement is one nodeConfigDetails placement configuration. type Placement struct { - PreemptibleConfig json.RawMessage `json:"preemptibleNodeConfig,omitempty"` - AvailabilityDom string `json:"availabilityDomain"` - SubnetID string `json:"subnetId"` - CapacityReserveID string `json:"capacityReservationId,omitempty"` - FaultDomains []string `json:"faultDomains,omitempty"` + PreemptibleConfig jsontext.Value `json:"preemptibleNodeConfig,omitempty"` + AvailabilityDom string `json:"availabilityDomain"` + SubnetID string `json:"subnetId"` + CapacityReserveID string `json:"capacityReservationId,omitempty"` + FaultDomains []string `json:"faultDomains,omitempty"` } // NodeConfig is nodeConfigDetails. @@ -205,8 +205,8 @@ type NodePool struct { QuantityPerSub *int `json:"quantityPerSubnet,omitempty"` Tags Tags `json:"tags"` NodeMetadata map[string]string `json:"nodeMetadata,omitempty"` - Eviction json.RawMessage `json:"eviction,omitempty"` - Cycling json.RawMessage `json:"cycling,omitempty"` + Eviction jsontext.Value `json:"eviction,omitempty"` + Cycling jsontext.Value `json:"cycling,omitempty"` ID string `json:"id"` ClusterID string `json:"clusterId"` CompartmentID string `json:"compartmentId"` diff --git a/services/ocicontainerengine/nodepools.go b/services/ocicontainerengine/nodepools.go index 6915f697c7..7a95f7dd1a 100644 --- a/services/ocicontainerengine/nodepools.go +++ b/services/ocicontainerengine/nodepools.go @@ -2,7 +2,7 @@ package ocicontainerengine import ( "encoding/binary" - "encoding/json" + "encoding/json/jsontext" "math" "net/netip" "regexp" @@ -46,10 +46,10 @@ type CreateNodePoolIn struct { Quantity *int `json:"quantityPerSubnet"` NodeConfig *NodeConfigIn `json:"nodeConfigDetails"` NodeMetadata map[string]string `json:"nodeMetadata"` - Eviction json.RawMessage `json:"nodeEvictionNodePoolSettings"` - Cycling json.RawMessage `json:"nodePoolCyclingDetails"` - SecondaryVnics json.RawMessage `json:"secondaryVnics"` - PrimaryVnic json.RawMessage `json:"primaryVnic"` + Eviction jsontext.Value `json:"nodeEvictionNodePoolSettings"` + Cycling jsontext.Value `json:"nodePoolCyclingDetails"` + SecondaryVnics jsontext.Value `json:"secondaryVnics"` + PrimaryVnic jsontext.Value `json:"primaryVnic"` Compartment string `json:"compartmentId"` ClusterID string `json:"clusterId"` Name string `json:"name"` @@ -71,10 +71,10 @@ type UpdateNodePoolIn struct { SSHKey *string `json:"sshPublicKey"` Shape *string `json:"nodeShape"` NodeMetadata map[string]string `json:"nodeMetadata"` - Eviction json.RawMessage `json:"nodeEvictionNodePoolSettings"` - Cycling json.RawMessage `json:"nodePoolCyclingDetails"` - SecondaryVnics json.RawMessage `json:"secondaryVnics"` - PrimaryVnic json.RawMessage `json:"primaryVnic"` + Eviction jsontext.Value `json:"nodeEvictionNodePoolSettings"` + Cycling jsontext.Value `json:"nodePoolCyclingDetails"` + SecondaryVnics jsontext.Value `json:"secondaryVnics"` + PrimaryVnic jsontext.Value `json:"primaryVnic"` LaunchType string `json:"networkLaunchType"` Labels []KeyValue `json:"initialNodeLabels"` SubnetIDs []string `json:"subnetIds"` @@ -105,8 +105,8 @@ type NodePoolWire struct { NodeSourceDetails *NodeSource `json:"nodeSourceDetails,omitempty"` QuantityPerSubnet *int `json:"quantityPerSubnet,omitempty"` NodeConfigDetails *NodeConfig `json:"nodeConfigDetails,omitempty"` - Eviction json.RawMessage `json:"nodeEvictionNodePoolSettings,omitempty"` - Cycling json.RawMessage `json:"nodePoolCyclingDetails,omitempty"` + Eviction jsontext.Value `json:"nodeEvictionNodePoolSettings,omitempty"` + Cycling jsontext.Value `json:"nodePoolCyclingDetails,omitempty"` Nodes []NodeWire `json:"nodes,omitempty"` ID string `json:"id"` ClusterID string `json:"clusterId"` @@ -171,7 +171,7 @@ func nodePoolView(np *NodePool, summary bool) NodePoolWire { return w } -func rejectUnsupported(secondary, primary json.RawMessage, launch string) *APIError { +func rejectUnsupported(secondary, primary jsontext.Value, launch string) *APIError { if len(secondary) > 0 && string(secondary) != "null" && string(secondary) != "[]" { return errParam("secondaryVnics are not supported by this emulator") } diff --git a/services/ocicontainerinstances/handler.go b/services/ocicontainerinstances/handler.go index e20e9b677a..b7d3610826 100644 --- a/services/ocicontainerinstances/handler.go +++ b/services/ocicontainerinstances/handler.go @@ -3,7 +3,8 @@ package ocicontainerinstances import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +118,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocicontainerinstances: encode response: %w", err) } @@ -168,10 +170,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -193,7 +194,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -262,7 +266,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocicontainerinstances/instances.go b/services/ocicontainerinstances/instances.go index 00f1c5a148..46210b2fb8 100644 --- a/services/ocicontainerinstances/instances.go +++ b/services/ocicontainerinstances/instances.go @@ -1,11 +1,12 @@ package ocicontainerinstances import ( - "encoding/json" + "encoding/json/v2" "slices" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -23,13 +24,13 @@ const ( ) func (in *Instance) clone() *Instance { - raw, err := json.Marshal(in) + raw, err := json.Marshal(in, jsonx.V1()) if err != nil { return in } out := &Instance{} - if json.Unmarshal(raw, out) != nil { + if json.Unmarshal(raw, out, jsonx.V1()) != nil { return in } @@ -172,7 +173,7 @@ func (b *InMemoryBackend) resolveCreds(secrets []PullSecret) ([]Credential, erro Password string `json:"password"` } - if json.Unmarshal([]byte(raw), &auth) != nil || auth.Username == "" || auth.Password == "" { + if json.Unmarshal([]byte(raw), &auth, jsonx.V1()) != nil || auth.Username == "" || auth.Password == "" { return nil, errVaultSecretShape } diff --git a/services/ocicontainerinstances/models.go b/services/ocicontainerinstances/models.go index 979f7b29e4..927876d227 100644 --- a/services/ocicontainerinstances/models.go +++ b/services/ocicontainerinstances/models.go @@ -1,7 +1,7 @@ package ocicontainerinstances import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -110,7 +110,7 @@ type Container struct { State string `json:"lifecycleState"` Details string `json:"lifecycleDetails,omitempty"` WorkingDir string `json:"workingDirectory,omitempty"` - Security json.RawMessage `json:"securityContext,omitempty"` + Security jsontext.Value `json:"securityContext,omitempty"` Command []string `json:"command,omitempty"` Args []string `json:"arguments,omitempty"` Mounts []VolumeMount `json:"volumeMounts,omitempty"` @@ -170,7 +170,7 @@ type Instance struct { Restart string `json:"containerRestartPolicy"` Etag string `json:"etag"` Target string `json:"target,omitempty"` - Security json.RawMessage `json:"securityContext,omitempty"` + Security jsontext.Value `json:"securityContext,omitempty"` Containers []*Container `json:"containers"` Volumes []Volume `json:"volumes,omitempty"` Vnics []Vnic `json:"vnics"` diff --git a/services/ocicontainerinstances/validate.go b/services/ocicontainerinstances/validate.go index 4189af447c..cd086133d0 100644 --- a/services/ocicontainerinstances/validate.go +++ b/services/ocicontainerinstances/validate.go @@ -3,13 +3,15 @@ package ocicontainerinstances import ( "cmp" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/netip" "path" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -152,7 +154,7 @@ func (b *InMemoryBackend) buildVnics(inst *Instance, vnics []createVnicIn) *APIE return nil } -func checkSecurity(raw json.RawMessage) *APIError { +func checkSecurity(raw jsontext.Value) *APIError { if len(raw) == 0 || string(raw) == "null" { return nil } @@ -161,7 +163,7 @@ func checkSecurity(raw json.RawMessage) *APIError { Type string `json:"securityContextType"` } - if err := json.Unmarshal(raw, &sc); err != nil || sc.Type != "LINUX" { + if err := json.Unmarshal(raw, &sc, jsonx.V1()); err != nil || sc.Type != "LINUX" { return errParam("securityContext.securityContextType must be LINUX") } diff --git a/services/ocicontainerinstances/volumes.go b/services/ocicontainerinstances/volumes.go index cd44c26fc7..de23dfb81f 100644 --- a/services/ocicontainerinstances/volumes.go +++ b/services/ocicontainerinstances/volumes.go @@ -2,13 +2,16 @@ package ocicontainerinstances import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "os" "path" "path/filepath" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -166,13 +169,13 @@ func (s *scratch) binds(mounts []VolumeMount) []string { } // securityUser maps a LINUX security context to docker's uid[:gid] user and the fsGroup supplementary group. -func securityUser(raw json.RawMessage) string { +func securityUser(raw jsontext.Value) string { var sc struct { User *int `json:"runAsUser"` Group *int `json:"runAsGroup"` } - if len(raw) == 0 || json.Unmarshal(raw, &sc) != nil || sc.User == nil { + if len(raw) == 0 || json.Unmarshal(raw, &sc, jsonx.V1()) != nil || sc.User == nil { return "" } diff --git a/services/ocicontainerinstances/wire.go b/services/ocicontainerinstances/wire.go index ef59865aee..2a3ba70a9c 100644 --- a/services/ocicontainerinstances/wire.go +++ b/services/ocicontainerinstances/wire.go @@ -1,7 +1,7 @@ package ocicontainerinstances import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -49,7 +49,7 @@ type ( ImageURL string `json:"imageUrl"` DisplayName string `json:"displayName"` WorkingDir string `json:"workingDirectory"` - SecurityCtx json.RawMessage `json:"securityContext"` + SecurityCtx jsontext.Value `json:"securityContext"` Command []string `json:"command"` Arguments []string `json:"arguments"` VolumeMounts []VolumeMount `json:"volumeMounts"` @@ -61,7 +61,7 @@ type ( Graceful *int64 `json:"gracefulShutdownTimeoutInSeconds"` Freeform map[string]string `json:"freeformTags"` Defined map[string]any `json:"definedTags"` - SecurityCtx json.RawMessage `json:"securityContext"` + SecurityCtx jsontext.Value `json:"securityContext"` Compartment string `json:"compartmentId"` AD string `json:"availabilityDomain"` Shape string `json:"shape"` @@ -114,7 +114,7 @@ type instanceSummaryWire struct { Details string `json:"lifecycleDetails,omitempty"` Shape string `json:"shape"` Restart string `json:"containerRestartPolicy"` - Security json.RawMessage `json:"securityContext,omitempty"` + Security jsontext.Value `json:"securityContext,omitempty"` ShapeConfig shapeConfigWire `json:"shapeConfig"` Count int `json:"containerCount"` VolumeCount int `json:"volumeCount"` @@ -218,7 +218,7 @@ type containerSummaryWire struct { Details string `json:"lifecycleDetails,omitempty"` InstanceID string `json:"containerInstanceId"` ImageURL string `json:"imageUrl"` - Security json.RawMessage `json:"securityContext,omitempty"` + Security jsontext.Value `json:"securityContext,omitempty"` NoResource bool `json:"isResourcePrincipalDisabled"` } diff --git a/services/ocicore/handler.go b/services/ocicore/handler.go index 8810659825..86bde9aa17 100644 --- a/services/ocicore/handler.go +++ b/services/ocicore/handler.go @@ -2,7 +2,7 @@ package ocicore import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -114,7 +115,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocicore: encode response: %w", err) } @@ -157,7 +158,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -179,7 +180,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -248,7 +252,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocicore/instance.go b/services/ocicore/instance.go index ca5e1d1c4d..e0bbb8e2b3 100644 --- a/services/ocicore/instance.go +++ b/services/ocicore/instance.go @@ -2,10 +2,13 @@ package ocicore import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -39,7 +42,7 @@ type LaunchInstanceIn struct { ImageID string `json:"imageId"` Shape string `json:"shape"` SubnetID string `json:"subnetId"` - LaunchVolumeAttachments []json.RawMessage `json:"launchVolumeAttachments"` + LaunchVolumeAttachments []jsontext.Value `json:"launchVolumeAttachments"` } func checkMetadata(md map[string]string, ext map[string]any) *APIError { @@ -50,7 +53,7 @@ func checkMetadata(md map[string]string, ext map[string]any) *APIError { } for k, v := range ext { - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) size += len(k) + len(raw) } diff --git a/services/ocievents/condition.go b/services/ocievents/condition.go index 3082564441..f0dec8bc81 100644 --- a/services/ocievents/condition.go +++ b/services/ocievents/condition.go @@ -2,11 +2,14 @@ package ocievents import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseCondition decodes a rule condition: a JSON object whose leaves are strings, numbers, booleans or @@ -16,15 +19,15 @@ func parseCondition(s string) (map[string]any, *APIError) { return nil, errMissing("condition is required") } - dec := json.NewDecoder(bytes.NewReader([]byte(s))) - dec.UseNumber() + data := []byte(s) + dec := jsontext.NewDecoder(bytes.NewReader(data)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, errParam("condition is not valid JSON: " + err.Error()) } - if dec.More() { + if rest := bytes.TrimLeft(data[dec.InputOffset():], " \t\r\n"); len(rest) > 0 && rest[0] != ']' && rest[0] != '}' { return nil, errParam("condition must be a single JSON object") } @@ -64,7 +67,7 @@ func validateNode(path string, v any) *APIError { return errParam(path + ": array elements must be strings, numbers or booleans") } } - case string, json.Number, bool: + case string, jsonx.Number, bool: default: return errParam(path + ": null is not a valid filter value") } @@ -74,7 +77,7 @@ func validateNode(path string, v any) *APIError { func isScalar(v any) bool { switch v.(type) { - case string, json.Number, float64, bool: + case string, jsonx.Number, float64, bool: return true default: return false @@ -85,7 +88,7 @@ func scalarString(v any) string { switch t := v.(type) { case string: return t - case json.Number: + case jsonx.Number: return t.String() case float64: return strconv.FormatFloat(t, 'f', -1, 64) diff --git a/services/ocievents/delivery_test.go b/services/ocievents/delivery_test.go index e6c6617746..0078c7be85 100644 --- a/services/ocievents/delivery_test.go +++ b/services/ocievents/delivery_test.go @@ -1,7 +1,7 @@ package ocievents_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ocievents "github.com/blackbirdworks/gopherstack/services/ocievents" ocinotifications "github.com/blackbirdworks/gopherstack/services/ocinotifications" ociobjectstorage "github.com/blackbirdworks/gopherstack/services/ociobjectstorage" @@ -167,7 +168,7 @@ func TestFilterMatching(t *testing.T) { require.Len(t, got, 1) var env map[string]any - require.NoError(t, json.Unmarshal([]byte(got[0]), &env)) + require.NoError(t, json.Unmarshal([]byte(got[0]), &env, jsonx.V1())) assert.Equal(t, tt.event.EventType, env["eventType"]) assert.Equal(t, "0.1", env["cloudEventsVersion"]) assert.Equal(t, "2.0", env["eventTypeVersion"]) @@ -379,7 +380,7 @@ func (p *pipeline) streamed(t *testing.T) []map[string]any { for _, m := range msgs { var env map[string]any - require.NoError(t, json.Unmarshal(m.Value, &env)) + require.NoError(t, json.Unmarshal(m.Value, &env, jsonx.V1())) out = append(out, env) } @@ -438,7 +439,7 @@ func TestObjectEventsDelivered(t *testing.T) { assert.Equal(t, ociobjectstorage.DefaultNamespace, details["namespace"]) var fromFn map[string]any - require.NoError(t, json.Unmarshal([]byte(invoked[i]), &fromFn)) + require.NoError(t, json.Unmarshal([]byte(invoked[i]), &fromFn, jsonx.V1())) assert.Equal(t, streamed[i]["eventID"], fromFn["eventID"]) } diff --git a/services/ocievents/emit.go b/services/ocievents/emit.go index b126f77024..7f9d10526e 100644 --- a/services/ocievents/emit.go +++ b/services/ocievents/emit.go @@ -2,11 +2,13 @@ package ocievents import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Delivery statuses. @@ -96,13 +98,13 @@ func buildEnvelope(ev Event, id string) ([]byte, map[string]any, error) { CompartmentID: ev.CompartmentID, ResourceName: ev.ResourceName, ResourceID: ev.ResourceID, AvailabilityDomain: ad, AdditionalDetails: details, }, - }) + }, jsonx.V1()) if err != nil { return nil, nil, err //nolint:wrapcheck // plain marshal failure } var generic map[string]any - if err = json.Unmarshal(raw, &generic); err != nil { + if err = json.Unmarshal(raw, &generic, jsonx.V1()); err != nil { return nil, nil, err //nolint:wrapcheck // plain unmarshal failure } diff --git a/services/ocievents/handler.go b/services/ocievents/handler.go index 80c8e93608..1dc775fb16 100644 --- a/services/ocievents/handler.go +++ b/services/ocievents/handler.go @@ -3,7 +3,8 @@ package ocievents import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +117,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocievents: encode response: %w", err) } @@ -154,10 +156,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -179,7 +180,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -257,7 +261,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocievents/rules_test.go b/services/ocievents/rules_test.go index d9e05e0808..77911aed05 100644 --- a/services/ocievents/rules_test.go +++ b/services/ocievents/rules_test.go @@ -1,7 +1,7 @@ package ocievents_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,8 @@ import ( "github.com/oracle/oci-go-sdk/v65/events" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRuleLifecycle(t *testing.T) { @@ -247,7 +249,7 @@ func TestCreateRuleValidation(t *testing.T) { m := validRuleBody() tt.mutate(m) - raw, err := json.Marshal(m) + raw, err := json.Marshal(m, jsonx.V1()) require.NoError(t, err) status, body := rawDo(t, http.MethodPost, e.base+"/20181201/rules", string(raw)) diff --git a/services/ocifunctions/docker_test.go b/services/ocifunctions/docker_test.go index 28f4b9b572..1bcbdcde93 100644 --- a/services/ocifunctions/docker_test.go +++ b/services/ocifunctions/docker_test.go @@ -1,7 +1,7 @@ package ocifunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "os" "os/exec" @@ -16,6 +16,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsid" "github.com/blackbirdworks/gopherstack/pkgs/gcpserve" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" oci "github.com/blackbirdworks/gopherstack/services/ocifunctions" ) @@ -148,7 +149,7 @@ func TestDocker_FDKImage(t *testing.T) { got := map[string]string{} if ierr == nil && out != "" && resp.RawResponse.StatusCode == http.StatusOK { - require.NoError(t, json.Unmarshal([]byte(out), &got), out) + require.NoError(t, json.Unmarshal([]byte(out), &got, jsonx.V1()), out) } return resp.RawResponse, got, ierr diff --git a/services/ocifunctions/fake_runtime_test.go b/services/ocifunctions/fake_runtime_test.go index d6259d71e2..8a7630c45d 100644 --- a/services/ocifunctions/fake_runtime_test.go +++ b/services/ocifunctions/fake_runtime_test.go @@ -2,7 +2,8 @@ package ocifunctions_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,7 @@ import ( "sync/atomic" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errNoSocketDir = errors.New("no socket directory mounted at /tmp/iofs") @@ -99,8 +101,10 @@ func (f *fakeRuntime) handler(id string, spec container.Spec) http.Handler { w.Header().Set("Content-Type", "application/json") w.Header().Set("Fn-Http-Status", "200") w.Header().Set("Fn-Http-H-X-Echo", "1") - _ = json.NewEncoder(w). - Encode(map[string]any{"body": string(body), "env": specEnv(spec), "path": r.URL.Path}) + _ = json.MarshalEncode( + jsontext.NewEncoder(w, jsonx.V1()), + map[string]any{"body": string(body), "env": specEnv(spec), "path": r.URL.Path}, + ) } }) } diff --git a/services/ocifunctions/funcs.go b/services/ocifunctions/funcs.go index ba0f50f5c0..f48ea409f0 100644 --- a/services/ocifunctions/funcs.go +++ b/services/ocifunctions/funcs.go @@ -1,7 +1,7 @@ package ocifunctions import ( - "encoding/json" + "encoding/json/jsontext" "maps" "strings" "time" @@ -39,8 +39,8 @@ type fnIn struct { Source *sourceIn `json:"sourceDetails"` Name string `json:"displayName"` AppID string `json:"applicationId"` - Failure json.RawMessage `json:"failureDestination"` - Success json.RawMessage `json:"successDestination"` + Failure jsontext.Value `json:"failureDestination"` + Success jsontext.Value `json:"successDestination"` } type fnWire struct { @@ -60,8 +60,8 @@ type fnWire struct { LifecycleState string `json:"lifecycleState"` Shape string `json:"shape,omitempty"` InvokeEndpoint string `json:"invokeEndpoint"` - Success json.RawMessage `json:"successDestination,omitempty"` - Failure json.RawMessage `json:"failureDestination,omitempty"` + Success jsontext.Value `json:"successDestination,omitempty"` + Failure jsontext.Value `json:"failureDestination,omitempty"` Memory int64 `json:"memoryInMBs"` Timeout int `json:"timeoutInSeconds"` } diff --git a/services/ocifunctions/handler.go b/services/ocifunctions/handler.go index dad9738a7d..ec40a337c5 100644 --- a/services/ocifunctions/handler.go +++ b/services/ocifunctions/handler.go @@ -2,7 +2,7 @@ package ocifunctions import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +117,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocifunctions: encode response: %w", err) } @@ -174,7 +175,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -196,7 +197,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -258,7 +262,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocifunctions/invoke_test.go b/services/ocifunctions/invoke_test.go index 18435e46e8..ff2803a089 100644 --- a/services/ocifunctions/invoke_test.go +++ b/services/ocifunctions/invoke_test.go @@ -2,7 +2,7 @@ package ocifunctions_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" oci "github.com/blackbirdworks/gopherstack/services/ocifunctions" ) @@ -116,7 +117,7 @@ func TestInvoke_FDKContract(t *testing.T) { require.NoError(t, err) var got echo - require.NoError(t, json.Unmarshal([]byte(out), &got)) + require.NoError(t, json.Unmarshal([]byte(out), &got, jsonx.V1())) assert.Equal(t, "hello", got.Body) assert.Equal(t, "/call", got.Path) assert.Equal(t, "1", resp.RawResponse.Header.Get("Fn-Http-H-X-Echo")) diff --git a/services/ocifunctions/models.go b/services/ocifunctions/models.go index 0babf8141f..25495d094f 100644 --- a/services/ocifunctions/models.go +++ b/services/ocifunctions/models.go @@ -1,7 +1,7 @@ package ocifunctions import ( - "encoding/json" + "encoding/json/jsontext" "maps" "time" ) @@ -104,8 +104,8 @@ type Function struct { Image string `json:"image"` ImageDigest string `json:"imageDigest,omitempty"` Etag string `json:"etag"` - Success json.RawMessage `json:"successDestination,omitempty"` - Failure json.RawMessage `json:"failureDestination,omitempty"` + Success jsontext.Value `json:"successDestination,omitempty"` + Failure jsontext.Value `json:"failureDestination,omitempty"` Memory int64 `json:"memoryInMBs"` Seq int64 `json:"seq"` Timeout int `json:"timeoutInSeconds"` diff --git a/services/ocifunctions/persistence_test.go b/services/ocifunctions/persistence_test.go index 01acc87b0c..69682631da 100644 --- a/services/ocifunctions/persistence_test.go +++ b/services/ocifunctions/persistence_test.go @@ -1,7 +1,7 @@ package ocifunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" oci "github.com/blackbirdworks/gopherstack/services/ocifunctions" ) @@ -84,10 +85,10 @@ func TestRestoreRejects(t *testing.T) { app := src.mkApp(t, "app", nil) body := map[string]any{} - require.NoError(t, json.Unmarshal(src.handler.Snapshot(t.Context()), &body)) + require.NoError(t, json.Unmarshal(src.handler.Snapshot(t.Context()), &body, jsonx.V1())) tt.mutate(body) - out, err := json.Marshal(body) + out, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) dst := newEnv(t, envOpts{}) diff --git a/services/ociidentity/handler.go b/services/ociidentity/handler.go index fd731fe458..1d6274e9aa 100644 --- a/services/ociidentity/handler.go +++ b/services/ociidentity/handler.go @@ -2,7 +2,7 @@ package ociidentity import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -113,7 +114,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociidentity: encode response: %w", err) } @@ -156,7 +157,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -178,7 +179,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -240,7 +244,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociidentity/handler_test.go b/services/ociidentity/handler_test.go index 154320a3f2..c4f01984e1 100644 --- a/services/ociidentity/handler_test.go +++ b/services/ociidentity/handler_test.go @@ -3,7 +3,7 @@ package ociidentity_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" oci "github.com/blackbirdworks/gopherstack/services/ociidentity" ) @@ -71,7 +72,7 @@ func TestRawErrorEnvelopes(t *testing.T) { Code string `json:"code"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &eb)) + require.NoError(t, json.Unmarshal(body, &eb, jsonx.V1())) assert.Equal(t, tt.wantCode, eb.Code) assert.NotEmpty(t, eb.Message) }) @@ -87,7 +88,12 @@ func TestEnforcedAuthAndAdminEndpoint(t *testing.T) { assert.Equal(t, http.StatusUnauthorized, svcErr(t, err).GetHTTPStatusCode()) body, err := json.Marshal( - map[string]string{"tenancy": testTenancy, "user": "ocid1.user.oc1..bootstrap", "publicKey": e.kp.pubPEM}, + map[string]string{ + "tenancy": testTenancy, + "user": "ocid1.user.oc1..bootstrap", + "publicKey": e.kp.pubPEM, + }, + jsonx.V1(), ) require.NoError(t, err) diff --git a/services/ociloadbalancer/handler.go b/services/ociloadbalancer/handler.go index 92581c3156..d6efc9b90b 100644 --- a/services/ociloadbalancer/handler.go +++ b/services/ociloadbalancer/handler.go @@ -3,7 +3,8 @@ package ociloadbalancer import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +118,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociloadbalancer: encode response: %w", err) } @@ -162,10 +164,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -187,7 +188,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -262,7 +266,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociloadbalancer/store.go b/services/ociloadbalancer/store.go index baa3fdb44d..9a8889bf26 100644 --- a/services/ociloadbalancer/store.go +++ b/services/ociloadbalancer/store.go @@ -4,7 +4,7 @@ import ( "cmp" "crypto/tls" "encoding/binary" - "encoding/json" + "encoding/json/v2" "net/netip" "slices" "strings" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" "github.com/blackbirdworks/gopherstack/pkgs/page" @@ -164,13 +165,13 @@ func (b *InMemoryBackend) transitionAt() *time.Time { // clone deep-copies a load balancer; stored load balancers are immutable once published. func (lb *LoadBalancer) clone() *LoadBalancer { - raw, err := json.Marshal(lb) + raw, err := json.Marshal(lb, jsonx.V1()) if err != nil { return lb } out := &LoadBalancer{} - if json.Unmarshal(raw, out) != nil { + if json.Unmarshal(raw, out, jsonx.V1()) != nil { return lb } diff --git a/services/ocilogging/agents.go b/services/ocilogging/agents.go index 20744d8a4e..4d44664b5a 100644 --- a/services/ocilogging/agents.go +++ b/services/ocilogging/agents.go @@ -2,10 +2,12 @@ package ocilogging import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -28,7 +30,7 @@ type CreateAgentConfigIn struct { GroupAssoc *groupAssociationWire `json:"groupAssociation"` Name string `json:"displayName"` Compartment string `json:"compartmentId"` - ServiceConfig json.RawMessage `json:"serviceConfiguration"` + ServiceConfig jsontext.Value `json:"serviceConfiguration"` } // UpdateAgentConfigIn is the UpdateUnifiedAgentConfiguration request body. @@ -38,7 +40,7 @@ type UpdateAgentConfigIn struct { Description *string `json:"description"` Name *string `json:"displayName"` GroupAssoc *groupAssociationWire `json:"groupAssociation"` - ServiceConfig json.RawMessage `json:"serviceConfiguration"` + ServiceConfig jsontext.Value `json:"serviceConfiguration"` } // AgentConfigWire is the GetUnifiedAgentConfiguration response. @@ -54,7 +56,7 @@ type AgentConfigWire struct { LifecycleState string `json:"lifecycleState"` ConfigurationState string `json:"configurationState"` GroupAssociation groupAssociationWire `json:"groupAssociation"` - ServiceConfig json.RawMessage `json:"serviceConfiguration"` + ServiceConfig jsontext.Value `json:"serviceConfiguration"` Enabled bool `json:"isEnabled"` } @@ -88,7 +90,7 @@ func agentView(a *AgentConfig) AgentConfigWire { } // validateServiceConfig checks the polymorphic serviceConfiguration and returns its configurationType. -func (b *InMemoryBackend) validateServiceConfig(raw json.RawMessage) (string, *APIError) { +func (b *InMemoryBackend) validateServiceConfig(raw jsontext.Value) (string, *APIError) { if len(raw) == 0 || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) { return "", errMissing("serviceConfiguration is required") } @@ -104,7 +106,7 @@ func (b *InMemoryBackend) validateServiceConfig(raw json.RawMessage) (string, *A } `json:"sources"` } - if err := json.Unmarshal(raw, &c); err != nil { + if err := json.Unmarshal(raw, &c, jsonx.V1()); err != nil { return "", errParam("serviceConfiguration is not a valid configuration object") } diff --git a/services/ocilogging/handler.go b/services/ocilogging/handler.go index 897686c2de..9564c52e0d 100644 --- a/services/ocilogging/handler.go +++ b/services/ocilogging/handler.go @@ -2,7 +2,7 @@ package ocilogging import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +116,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocilogging: encode response: %w", err) } @@ -161,7 +162,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -183,7 +184,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -252,7 +256,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocilogging/ingest.go b/services/ocilogging/ingest.go index d7a9b7b04a..9a0012d10b 100644 --- a/services/ocilogging/ingest.go +++ b/services/ocilogging/ingest.go @@ -1,12 +1,14 @@ package ocilogging import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "unicode/utf8" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -140,7 +142,7 @@ type ServiceEvent struct { // EmitServiceLog stores the event in every ACTIVE SERVICE log whose source matches; it returns how many logs took it. func (b *InMemoryBackend) EmitServiceLog(service, resource, category string, ev ServiceEvent) int { - data, err := json.Marshal(ev.Data) + data, err := json.Marshal(ev.Data, jsonx.V1()) if err != nil { return 0 } diff --git a/services/ocilogging/models.go b/services/ocilogging/models.go index 4021b7813e..c30863401c 100644 --- a/services/ocilogging/models.go +++ b/services/ocilogging/models.go @@ -1,7 +1,7 @@ package ocilogging import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -87,21 +87,21 @@ type Log struct { // AgentConfig is a stored unified agent configuration. type AgentConfig struct { - TimeCreated time.Time `json:"timeCreated"` - TimeModified time.Time `json:"timeModified"` - TransitionAt *time.Time `json:"transitionAt,omitempty"` - ServiceConfig json.RawMessage `json:"serviceConfiguration"` - Tags Tags `json:"tags"` - ID string `json:"id"` - CompartmentID string `json:"compartmentId"` - Name string `json:"displayName"` - Description string `json:"description,omitempty"` - State string `json:"state"` - ConfigType string `json:"configurationType"` - Etag string `json:"etag"` - Groups []string `json:"groupList,omitempty"` - Seq int64 `json:"seq"` - Enabled bool `json:"isEnabled"` + TimeCreated time.Time `json:"timeCreated"` + TimeModified time.Time `json:"timeModified"` + TransitionAt *time.Time `json:"transitionAt,omitempty"` + ServiceConfig jsontext.Value `json:"serviceConfiguration"` + Tags Tags `json:"tags"` + ID string `json:"id"` + CompartmentID string `json:"compartmentId"` + Name string `json:"displayName"` + Description string `json:"description,omitempty"` + State string `json:"state"` + ConfigType string `json:"configurationType"` + Etag string `json:"etag"` + Groups []string `json:"groupList,omitempty"` + Seq int64 `json:"seq"` + Enabled bool `json:"isEnabled"` } // Entry is one ingested log record. diff --git a/services/ocilogging/persistence_test.go b/services/ocilogging/persistence_test.go index 7162513235..00de9b90b7 100644 --- a/services/ocilogging/persistence_test.go +++ b/services/ocilogging/persistence_test.go @@ -1,7 +1,7 @@ package ocilogging_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" oci "github.com/blackbirdworks/gopherstack/services/ocilogging" ) @@ -220,7 +221,7 @@ func TestAdminKeyEndpoint(t *testing.T) { t.Parallel() e := newEnv(t, envOpts{}) - pub, err := json.Marshal(e.kp.pubPEM) + pub, err := json.Marshal(e.kp.pubPEM, jsonx.V1()) require.NoError(t, err) status, _ := rawDo(t, http.MethodPost, e.base+"/_gopherstack/oci/keys", diff --git a/services/ocilogging/query.go b/services/ocilogging/query.go index 2f086be207..c46621e28e 100644 --- a/services/ocilogging/query.go +++ b/services/ocilogging/query.go @@ -2,7 +2,7 @@ package ocilogging import ( "cmp" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" @@ -10,6 +10,7 @@ import ( "strings" "unicode" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -624,7 +625,7 @@ func scalarString(v any) string { return "" } - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return string(b) } diff --git a/services/ocilogging/search.go b/services/ocilogging/search.go index 3c5c8e6b6a..9c8c500d3d 100644 --- a/services/ocilogging/search.go +++ b/services/ocilogging/search.go @@ -1,13 +1,14 @@ package ocilogging import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -106,7 +107,7 @@ func (b *InMemoryBackend) buildRow(l *Log, e *Entry) *row { var data any = e.Data var parsed any - if json.Unmarshal([]byte(e.Data), &parsed) == nil { + if json.Unmarshal([]byte(e.Data), &parsed, jsonx.V1()) == nil { if _, isMap := parsed.(map[string]any); isMap { data = parsed } diff --git a/services/ocimonitoring/alarms.go b/services/ocimonitoring/alarms.go index b3ba39da3a..bb4105bf01 100644 --- a/services/ocimonitoring/alarms.go +++ b/services/ocimonitoring/alarms.go @@ -1,7 +1,7 @@ package ocimonitoring import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "regexp" "slices" @@ -63,57 +63,57 @@ type SuppressionWire struct { // CreateAlarmIn is the CreateAlarm request body. type CreateAlarmIn struct { Tags - InSubtree *bool `json:"metricCompartmentIdInSubtree"` - PerDimension *bool `json:"isNotificationsPerMetricDimensionEnabled"` - Enabled *bool `json:"isEnabled"` - Suppression *SuppressionWire `json:"suppression"` - ResourceGroup *string `json:"resourceGroup"` - Resolution *string `json:"resolution"` - Pending *string `json:"pendingDuration"` - Body *string `json:"body"` - MessageFormat *string `json:"messageFormat"` - Repeat *string `json:"repeatNotificationDuration"` - RuleName *string `json:"ruleName"` - NotifVersion *string `json:"notificationVersion"` - NotifTitle *string `json:"notificationTitle"` - EvalSlack *string `json:"evaluationSlackDuration"` - AlarmSummary *string `json:"alarmSummary"` - Name string `json:"displayName"` - Compartment string `json:"compartmentId"` - MetricComp string `json:"metricCompartmentId"` - Namespace string `json:"namespace"` - Query string `json:"query"` - Severity string `json:"severity"` - Destinations []string `json:"destinations"` - Overrides []json.RawMessage `json:"overrides"` + InSubtree *bool `json:"metricCompartmentIdInSubtree"` + PerDimension *bool `json:"isNotificationsPerMetricDimensionEnabled"` + Enabled *bool `json:"isEnabled"` + Suppression *SuppressionWire `json:"suppression"` + ResourceGroup *string `json:"resourceGroup"` + Resolution *string `json:"resolution"` + Pending *string `json:"pendingDuration"` + Body *string `json:"body"` + MessageFormat *string `json:"messageFormat"` + Repeat *string `json:"repeatNotificationDuration"` + RuleName *string `json:"ruleName"` + NotifVersion *string `json:"notificationVersion"` + NotifTitle *string `json:"notificationTitle"` + EvalSlack *string `json:"evaluationSlackDuration"` + AlarmSummary *string `json:"alarmSummary"` + Name string `json:"displayName"` + Compartment string `json:"compartmentId"` + MetricComp string `json:"metricCompartmentId"` + Namespace string `json:"namespace"` + Query string `json:"query"` + Severity string `json:"severity"` + Destinations []string `json:"destinations"` + Overrides []jsontext.Value `json:"overrides"` } // UpdateAlarmIn is the UpdateAlarm request body. type UpdateAlarmIn struct { Tags - Name *string `json:"displayName"` - Compartment *string `json:"compartmentId"` - MetricComp *string `json:"metricCompartmentId"` - InSubtree *bool `json:"metricCompartmentIdInSubtree"` - Namespace *string `json:"namespace"` - ResourceGroup *string `json:"resourceGroup"` - Query *string `json:"query"` - Resolution *string `json:"resolution"` - Pending *string `json:"pendingDuration"` - Severity *string `json:"severity"` - Body *string `json:"body"` - PerDimension *bool `json:"isNotificationsPerMetricDimensionEnabled"` - MessageFormat *string `json:"messageFormat"` - Destinations []string `json:"destinations"` - Repeat *string `json:"repeatNotificationDuration"` - Suppression *SuppressionWire `json:"suppression"` - Enabled *bool `json:"isEnabled"` - RuleName *string `json:"ruleName"` - NotifVersion *string `json:"notificationVersion"` - NotifTitle *string `json:"notificationTitle"` - EvalSlack *string `json:"evaluationSlackDuration"` - AlarmSummary *string `json:"alarmSummary"` - Overrides []json.RawMessage `json:"overrides"` + Name *string `json:"displayName"` + Compartment *string `json:"compartmentId"` + MetricComp *string `json:"metricCompartmentId"` + InSubtree *bool `json:"metricCompartmentIdInSubtree"` + Namespace *string `json:"namespace"` + ResourceGroup *string `json:"resourceGroup"` + Query *string `json:"query"` + Resolution *string `json:"resolution"` + Pending *string `json:"pendingDuration"` + Severity *string `json:"severity"` + Body *string `json:"body"` + PerDimension *bool `json:"isNotificationsPerMetricDimensionEnabled"` + MessageFormat *string `json:"messageFormat"` + Destinations []string `json:"destinations"` + Repeat *string `json:"repeatNotificationDuration"` + Suppression *SuppressionWire `json:"suppression"` + Enabled *bool `json:"isEnabled"` + RuleName *string `json:"ruleName"` + NotifVersion *string `json:"notificationVersion"` + NotifTitle *string `json:"notificationTitle"` + EvalSlack *string `json:"evaluationSlackDuration"` + AlarmSummary *string `json:"alarmSummary"` + Overrides []jsontext.Value `json:"overrides"` } // AlarmWire is the Alarm response shape. @@ -145,7 +145,7 @@ type AlarmWire struct { Repeat string `json:"repeatNotificationDuration,omitempty"` LifecycleState string `json:"lifecycleState"` Destinations []string `json:"destinations"` - Overrides []json.RawMessage `json:"overrides,omitempty"` + Overrides []jsontext.Value `json:"overrides,omitempty"` Enabled bool `json:"isEnabled"` } diff --git a/services/ocimonitoring/alarms_test.go b/services/ocimonitoring/alarms_test.go index 0d7d64e76c..6525e9b923 100644 --- a/services/ocimonitoring/alarms_test.go +++ b/services/ocimonitoring/alarms_test.go @@ -1,7 +1,7 @@ package ocimonitoring_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,8 @@ import ( "github.com/oracle/oci-go-sdk/v65/monitoring" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (e *env) alarmDetails(topic string, mod func(*monitoring.CreateAlarmDetails)) monitoring.CreateAlarmDetails { @@ -305,7 +307,7 @@ func TestAlarmFiringDeliversToNotifications(t *testing.T) { } `json:"alarmMetaData"` } - require.NoError(t, json.Unmarshal([]byte(msg.body), &n)) + require.NoError(t, json.Unmarshal([]byte(msg.body), &n, jsonx.V1())) assert.Equal(t, "OK_TO_FIRING", n.Type) assert.Equal(t, "CRITICAL", n.Severity) assert.Equal(t, "cpu-high", n.Title) @@ -327,7 +329,7 @@ func TestAlarmFiringDeliversToNotifications(t *testing.T) { Type string `json:"type"` } - require.NoError(t, json.Unmarshal([]byte(o.sink.next(t).body), &ok)) + require.NoError(t, json.Unmarshal([]byte(o.sink.next(t).body), &ok, jsonx.V1())) assert.Equal(t, "FIRING_TO_OK", ok.Type) hist, err := e.mon.GetAlarmHistory(t.Context(), monitoring.GetAlarmHistoryRequest{AlarmId: a.Id}) @@ -509,7 +511,7 @@ func TestAlarmGroupedThreshold(t *testing.T) { } `json:"alarmMetaData"` } - require.NoError(t, json.Unmarshal([]byte(o.sink.next(t).body), &n)) + require.NoError(t, json.Unmarshal([]byte(o.sink.next(t).body), &n, jsonx.V1())) assert.Equal(t, 1, n.AlarmMetaData[0].TotalMetricsFiring, "only web2 breaches; db1 is filtered out") assert.Equal(t, []map[string]string{{"host": "web2"}}, n.AlarmMetaData[0].Dimensions) } diff --git a/services/ocimonitoring/eval.go b/services/ocimonitoring/eval.go index dc2b5915c1..19b8134724 100644 --- a/services/ocimonitoring/eval.go +++ b/services/ocimonitoring/eval.go @@ -2,12 +2,14 @@ package ocimonitoring import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -231,9 +233,9 @@ func renderNotice(a *Alarm, kind string, now time.Time, hits []firing) (string, ) if a.MessageFormat == formatPretty { - out, err = json.MarshalIndent(w, "", " ") + out, err = json.Marshal(w, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) } else { - out, err = json.Marshal(w) + out, err = json.Marshal(w, jsonx.V1()) } if err != nil { diff --git a/services/ocimonitoring/handler.go b/services/ocimonitoring/handler.go index 0ee1af6e2f..6e2a129c60 100644 --- a/services/ocimonitoring/handler.go +++ b/services/ocimonitoring/handler.go @@ -2,7 +2,7 @@ package ocimonitoring import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +116,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocimonitoring: encode response: %w", err) } @@ -154,7 +155,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -176,7 +177,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -245,7 +249,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocimonitoring/models.go b/services/ocimonitoring/models.go index fed338bd5f..f3b51796e0 100644 --- a/services/ocimonitoring/models.go +++ b/services/ocimonitoring/models.go @@ -1,7 +1,7 @@ package ocimonitoring import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -75,7 +75,7 @@ type Alarm struct { PerDimension *bool `json:"isNotificationsPerMetricDimensionEnabled,omitempty"` Tags Tags `json:"tags"` Extra map[string]string `json:"extra,omitempty"` - Overrides []json.RawMessage `json:"overrides,omitempty"` + Overrides []jsontext.Value `json:"overrides,omitempty"` ID string `json:"id"` Name string `json:"displayName"` CompartmentID string `json:"compartmentId"` diff --git a/services/ocimonitoring/persistence_test.go b/services/ocimonitoring/persistence_test.go index 264b0d9624..1f2ec0b94c 100644 --- a/services/ocimonitoring/persistence_test.go +++ b/services/ocimonitoring/persistence_test.go @@ -1,7 +1,7 @@ package ocimonitoring_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" oci "github.com/blackbirdworks/gopherstack/services/ocimonitoring" ) @@ -150,7 +151,7 @@ func TestAdminKeyEndpoint(t *testing.T) { t.Parallel() e := newEnv(t, envOpts{}) - pub, err := json.Marshal(e.kp.pubPEM) + pub, err := json.Marshal(e.kp.pubPEM, jsonx.V1()) require.NoError(t, err) status, _ := rawDo(t, http.MethodPost, e.base+"/_gopherstack/oci/keys", diff --git a/services/ocimysql/channels.go b/services/ocimysql/channels.go index 5652f02f85..2f79c13220 100644 --- a/services/ocimysql/channels.go +++ b/services/ocimysql/channels.go @@ -1,7 +1,7 @@ package ocimysql import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "strings" @@ -28,13 +28,13 @@ type ChannelSourceIn struct { // ChannelTargetIn is the channel target details. type ChannelTargetIn struct { - DelayInSeconds *int `json:"delayInSeconds"` - TargetType string `json:"targetType"` - DBSystemID string `json:"dbSystemId"` - ChannelName string `json:"channelName"` - ApplierUsername string `json:"applierUsername"` - TablesWithoutPrimaryKeyHandling string `json:"tablesWithoutPrimaryKeyHandling"` - Filters json.RawMessage `json:"filters"` + DelayInSeconds *int `json:"delayInSeconds"` + TargetType string `json:"targetType"` + DBSystemID string `json:"dbSystemId"` + ChannelName string `json:"channelName"` + ApplierUsername string `json:"applierUsername"` + TablesWithoutPrimaryKeyHandling string `json:"tablesWithoutPrimaryKeyHandling"` + Filters jsontext.Value `json:"filters"` } // CreateChannelIn is the CreateChannel body. diff --git a/services/ocimysql/dbsystems.go b/services/ocimysql/dbsystems.go index 2ff6784d18..8afb68f2a3 100644 --- a/services/ocimysql/dbsystems.go +++ b/services/ocimysql/dbsystems.go @@ -1,7 +1,8 @@ package ocimysql import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "regexp" @@ -9,6 +10,7 @@ import ( "time" "unicode" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -64,7 +66,7 @@ type BackupPolicyIn struct { WindowStartTime *string `json:"windowStartTime"` RetentionInDays *int `json:"retentionInDays"` SoftDelete string `json:"softDelete"` - CopyPolicies json.RawMessage `json:"copyPolicies"` + CopyPolicies jsontext.Value `json:"copyPolicies"` } // DeletionPolicyIn is the create/update deletion policy. @@ -89,33 +91,33 @@ type SourceIn struct { // CreateDBSystemIn is the CreateDBSystem body. type CreateDBSystemIn struct { Tags - Extra map[string]json.RawMessage `json:"-"` - IsHighlyAvailable *bool `json:"isHighlyAvailable"` - DataStorageGBs *int `json:"dataStorageSizeInGBs"` - Port *int `json:"port"` - PortX *int `json:"portX"` - DataStorage *DataStorageIn `json:"dataStorage"` - BackupPolicy *BackupPolicyIn `json:"backupPolicy"` - Source *SourceIn `json:"source"` - DeletionPolicy *DeletionPolicyIn `json:"deletionPolicy"` - Maintenance map[string]any `json:"maintenance"` - Description string `json:"description"` - AdminPassword string `json:"adminPassword"` - DisplayName string `json:"displayName"` - ShapeName string `json:"shapeName"` - AvailabilityDom string `json:"availabilityDomain"` - FaultDomain string `json:"faultDomain"` - ConfigurationID string `json:"configurationId"` - MysqlVersion string `json:"mysqlVersion"` - AdminUsername string `json:"adminUsername"` - SubnetID string `json:"subnetId"` - HostnameLabel string `json:"hostnameLabel"` - IPAddress string `json:"ipAddress"` - CrashRecovery string `json:"crashRecovery"` - DBManagement string `json:"databaseManagement"` - DatabaseMode string `json:"databaseMode"` - AccessMode string `json:"accessMode"` - CompartmentID string `json:"compartmentId"` + Extra map[string]jsontext.Value `json:"-"` + IsHighlyAvailable *bool `json:"isHighlyAvailable"` + DataStorageGBs *int `json:"dataStorageSizeInGBs"` + Port *int `json:"port"` + PortX *int `json:"portX"` + DataStorage *DataStorageIn `json:"dataStorage"` + BackupPolicy *BackupPolicyIn `json:"backupPolicy"` + Source *SourceIn `json:"source"` + DeletionPolicy *DeletionPolicyIn `json:"deletionPolicy"` + Maintenance map[string]any `json:"maintenance"` + Description string `json:"description"` + AdminPassword string `json:"adminPassword"` + DisplayName string `json:"displayName"` + ShapeName string `json:"shapeName"` + AvailabilityDom string `json:"availabilityDomain"` + FaultDomain string `json:"faultDomain"` + ConfigurationID string `json:"configurationId"` + MysqlVersion string `json:"mysqlVersion"` + AdminUsername string `json:"adminUsername"` + SubnetID string `json:"subnetId"` + HostnameLabel string `json:"hostnameLabel"` + IPAddress string `json:"ipAddress"` + CrashRecovery string `json:"crashRecovery"` + DBManagement string `json:"databaseManagement"` + DatabaseMode string `json:"databaseMode"` + AccessMode string `json:"accessMode"` + CompartmentID string `json:"compartmentId"` } func validPassword(p string) bool { @@ -906,13 +908,13 @@ func (h *Handler) createDBSystem(q *req) error { return q.json(http.StatusOK, d, etag) } -func extras(body []byte) map[string]json.RawMessage { - var all map[string]json.RawMessage - if json.Unmarshal(body, &all) != nil { +func extras(body []byte) map[string]jsontext.Value { + var all map[string]jsontext.Value + if json.Unmarshal(body, &all, jsonx.V1()) != nil { return nil } - out := map[string]json.RawMessage{} + out := map[string]jsontext.Value{} for _, k := range extraKeys { if v, ok := all[k]; ok && string(v) != "null" { diff --git a/services/ocimysql/handler.go b/services/ocimysql/handler.go index f81ca587b9..75346061cc 100644 --- a/services/ocimysql/handler.go +++ b/services/ocimysql/handler.go @@ -2,7 +2,7 @@ package ocimysql import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +116,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocimysql: encode response: %w", err) } @@ -163,7 +164,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -185,7 +186,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -254,7 +258,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocimysql/lifecycle.go b/services/ocimysql/lifecycle.go index b851c375d2..c5db7d2af0 100644 --- a/services/ocimysql/lifecycle.go +++ b/services/ocimysql/lifecycle.go @@ -2,7 +2,7 @@ package ocimysql import ( "context" - "encoding/json" + "encoding/json/jsontext" "net/http" "net/netip" "slices" @@ -159,29 +159,29 @@ func (b *InMemoryBackend) mutable(id, ifMatch string, states ...string) (*DBSyst // UpdateDBSystemIn is the UpdateDBSystem body. type UpdateDBSystemIn struct { Tags - DataStorageGBs *int `json:"dataStorageSizeInGBs"` - HostnameLabel *string `json:"hostnameLabel"` - SubnetID *string `json:"subnetId"` - ShapeName *string `json:"shapeName"` - MysqlVersion *string `json:"mysqlVersion"` - ConfigID *string `json:"configurationId"` - AdminUsername *string `json:"adminUsername"` - Port *int `json:"port"` - Extra map[string]json.RawMessage `json:"-"` - IPAddress *string `json:"ipAddress"` - Description *string `json:"description"` - HA *bool `json:"isHighlyAvailable"` - AdminPassword *string `json:"adminPassword"` - PortX *int `json:"portX"` - DataStorage *DataStorageIn `json:"dataStorage"` - BackupPolicy *BackupPolicyIn `json:"backupPolicy"` - Deletion *DeletionPolicyIn `json:"deletionPolicy"` - Maintenance map[string]any `json:"maintenance"` - DisplayName *string `json:"displayName"` - DBManagement string `json:"databaseManagement"` - DatabaseMode string `json:"databaseMode"` - AccessMode string `json:"accessMode"` - CrashRecovery string `json:"crashRecovery"` + DataStorageGBs *int `json:"dataStorageSizeInGBs"` + HostnameLabel *string `json:"hostnameLabel"` + SubnetID *string `json:"subnetId"` + ShapeName *string `json:"shapeName"` + MysqlVersion *string `json:"mysqlVersion"` + ConfigID *string `json:"configurationId"` + AdminUsername *string `json:"adminUsername"` + Port *int `json:"port"` + Extra map[string]jsontext.Value `json:"-"` + IPAddress *string `json:"ipAddress"` + Description *string `json:"description"` + HA *bool `json:"isHighlyAvailable"` + AdminPassword *string `json:"adminPassword"` + PortX *int `json:"portX"` + DataStorage *DataStorageIn `json:"dataStorage"` + BackupPolicy *BackupPolicyIn `json:"backupPolicy"` + Deletion *DeletionPolicyIn `json:"deletionPolicy"` + Maintenance map[string]any `json:"maintenance"` + DisplayName *string `json:"displayName"` + DBManagement string `json:"databaseManagement"` + DatabaseMode string `json:"databaseMode"` + AccessMode string `json:"accessMode"` + CrashRecovery string `json:"crashRecovery"` } type updateEffect struct { @@ -228,7 +228,7 @@ func (b *InMemoryBackend) applyUpdate(n *DBSystem, in UpdateDBSystemIn) (updateE for k, v := range in.Extra { if n.Extra == nil { - n.Extra = map[string]json.RawMessage{} + n.Extra = map[string]jsontext.Value{} } n.Extra[k] = v diff --git a/services/ocimysql/models.go b/services/ocimysql/models.go index 10049fd971..400ad67502 100644 --- a/services/ocimysql/models.go +++ b/services/ocimysql/models.go @@ -1,7 +1,7 @@ package ocimysql import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -40,13 +40,13 @@ func (t *Tags) merge(in Tags) { // BackupPolicy is the automatic backup policy of a DB system. type BackupPolicy struct { - Tags Tags `json:"tags"` - WindowStartTime string `json:"windowStartTime"` - SoftDelete string `json:"softDelete"` - CopyPolicies json.RawMessage `json:"copyPolicies,omitempty"` - RetentionInDays int `json:"retentionInDays"` - IsEnabled bool `json:"isEnabled"` - PitrEnabled bool `json:"pitrEnabled"` + Tags Tags `json:"tags"` + WindowStartTime string `json:"windowStartTime"` + SoftDelete string `json:"softDelete"` + CopyPolicies jsontext.Value `json:"copyPolicies,omitempty"` + RetentionInDays int `json:"retentionInDays"` + IsEnabled bool `json:"isEnabled"` + PitrEnabled bool `json:"pitrEnabled"` } // DeletionPolicy controls what DeleteDBSystem does. @@ -64,48 +64,48 @@ type Source struct { // DBSystem is a MySQL DB system. AdminPassword and RootSecret are never returned by the API. type DBSystem struct { - TimeCreated time.Time `json:"timeCreated"` - TimeUpdated time.Time `json:"timeUpdated"` - LastAutoBackup time.Time `json:"lastAutoBackup"` - Tags Tags `json:"tags"` - TransitionAt *time.Time `json:"transitionAt,omitempty"` - Source *Source `json:"source,omitempty"` - Extra map[string]json.RawMessage `json:"extra,omitempty"` - Maintenance map[string]any `json:"maintenance,omitempty"` - FD string `json:"faultDomain"` - AdminUser string `json:"adminUsername"` - ID string `json:"id"` - CompartmentID string `json:"compartmentId"` - Name string `json:"displayName"` - Description string `json:"description,omitempty"` - SubnetID string `json:"subnetId"` - Shape string `json:"shapeName"` - Version string `json:"mysqlVersion"` - ConfigID string `json:"configurationId"` - Hostname string `json:"hostnameLabel,omitempty"` - AD string `json:"availabilityDomain"` - EngineHost string `json:"engineHost,omitempty"` - State string `json:"state"` - After string `json:"after,omitempty"` - Details string `json:"details,omitempty"` - Etag string `json:"etag"` - IP string `json:"ipAddress"` - AdminPass string `json:"adminPassword,omitempty"` - RootSecret string `json:"rootSecret,omitempty"` - DatabaseMode string `json:"databaseMode"` - AccessMode string `json:"accessMode"` - CrashRecovery string `json:"crashRecovery"` - DBManagement string `json:"databaseManagement"` - Deletion DeletionPolicy `json:"deletionPolicy"` - BackupPolicy BackupPolicy `json:"backupPolicy"` - DataGB int `json:"dataStorageSizeInGBs"` - MaxGB int `json:"maxStorageSizeInGBs,omitempty"` - Port int `json:"port"` - PortX int `json:"portX"` - EnginePort int `json:"enginePort,omitempty"` - Seq int64 `json:"seq"` - AutoExpand bool `json:"isAutoExpandStorageEnabled"` - HA bool `json:"isHighlyAvailable"` + TimeCreated time.Time `json:"timeCreated"` + TimeUpdated time.Time `json:"timeUpdated"` + LastAutoBackup time.Time `json:"lastAutoBackup"` + Tags Tags `json:"tags"` + TransitionAt *time.Time `json:"transitionAt,omitempty"` + Source *Source `json:"source,omitempty"` + Extra map[string]jsontext.Value `json:"extra,omitempty"` + Maintenance map[string]any `json:"maintenance,omitempty"` + FD string `json:"faultDomain"` + AdminUser string `json:"adminUsername"` + ID string `json:"id"` + CompartmentID string `json:"compartmentId"` + Name string `json:"displayName"` + Description string `json:"description,omitempty"` + SubnetID string `json:"subnetId"` + Shape string `json:"shapeName"` + Version string `json:"mysqlVersion"` + ConfigID string `json:"configurationId"` + Hostname string `json:"hostnameLabel,omitempty"` + AD string `json:"availabilityDomain"` + EngineHost string `json:"engineHost,omitempty"` + State string `json:"state"` + After string `json:"after,omitempty"` + Details string `json:"details,omitempty"` + Etag string `json:"etag"` + IP string `json:"ipAddress"` + AdminPass string `json:"adminPassword,omitempty"` + RootSecret string `json:"rootSecret,omitempty"` + DatabaseMode string `json:"databaseMode"` + AccessMode string `json:"accessMode"` + CrashRecovery string `json:"crashRecovery"` + DBManagement string `json:"databaseManagement"` + Deletion DeletionPolicy `json:"deletionPolicy"` + BackupPolicy BackupPolicy `json:"backupPolicy"` + DataGB int `json:"dataStorageSizeInGBs"` + MaxGB int `json:"maxStorageSizeInGBs,omitempty"` + Port int `json:"port"` + PortX int `json:"portX"` + EnginePort int `json:"enginePort,omitempty"` + Seq int64 `json:"seq"` + AutoExpand bool `json:"isAutoExpandStorageEnabled"` + HA bool `json:"isHighlyAvailable"` } // Backup is a DB system backup. Dump holds the logical dump when the docker engine took it. @@ -134,24 +134,24 @@ type Backup struct { // ChannelSource is the replication source of a channel; the password is never stored. type ChannelSource struct { - Extra map[string]json.RawMessage `json:"extra,omitempty"` - SourceType string `json:"sourceType"` - Hostname string `json:"hostname"` - Username string `json:"username"` - SslMode string `json:"sslMode"` - Port int `json:"port"` - HasPassword bool `json:"hasPassword"` + Extra map[string]jsontext.Value `json:"extra,omitempty"` + SourceType string `json:"sourceType"` + Hostname string `json:"hostname"` + Username string `json:"username"` + SslMode string `json:"sslMode"` + Port int `json:"port"` + HasPassword bool `json:"hasPassword"` } // ChannelTarget is the DB system a channel replicates into. type ChannelTarget struct { - TargetType string `json:"targetType"` - DBSystemID string `json:"dbSystemId"` - ChannelName string `json:"channelName"` - ApplierUsername string `json:"applierUsername"` - TablesWithoutPrimaryKeyHandling string `json:"tablesWithoutPrimaryKeyHandling"` - Filters json.RawMessage `json:"filters,omitempty"` - DelayInSeconds int `json:"delayInSeconds"` + TargetType string `json:"targetType"` + DBSystemID string `json:"dbSystemId"` + ChannelName string `json:"channelName"` + ApplierUsername string `json:"applierUsername"` + TablesWithoutPrimaryKeyHandling string `json:"tablesWithoutPrimaryKeyHandling"` + Filters jsontext.Value `json:"filters,omitempty"` + DelayInSeconds int `json:"delayInSeconds"` } // Channel is a replication channel. It records configuration and lifecycle only; no data is replicated. diff --git a/services/ocinosql/alter.go b/services/ocinosql/alter.go index f1be37a408..2fc0c31509 100644 --- a/services/ocinosql/alter.go +++ b/services/ocinosql/alter.go @@ -1,10 +1,12 @@ package ocinosql import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -121,7 +123,7 @@ func checkAddColumn(cols []Column, c Column) *APIError { return nil } -func coerceDefault(ty *dtype, raw json.RawMessage) (any, string) { +func coerceDefault(ty *dtype, raw jsontext.Value) (any, string) { v, err := decodeJSON(raw) if err != nil { return nil, "is not a valid literal" @@ -154,7 +156,7 @@ func reshapeRows(t *Table, removed []string, added []Column) { } } - r.Value, _ = json.Marshal(m) + r.Value, _ = json.Marshal(m, jsonx.V1()) } } @@ -216,9 +218,9 @@ func renderIdentity(id *Identity) string { return " GENERATED BY DEFAULT AS IDENTITY" } -func renderDefault(raw json.RawMessage) string { +func renderDefault(raw jsontext.Value) string { var s string - if json.Unmarshal(raw, &s) == nil { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil { return "'" + strings.ReplaceAll(s, "'", "''") + "'" } diff --git a/services/ocinosql/ddl.go b/services/ocinosql/ddl.go index b48777d1f8..c8efdde147 100644 --- a/services/ocinosql/ddl.go +++ b/services/ocinosql/ddl.go @@ -1,11 +1,13 @@ package ocinosql import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "strconv" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -20,12 +22,12 @@ var identRe = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9_]*$`) // Column is one table column. type Column struct { - Name string `json:"name"` - Type string `json:"type"` - Default json.RawMessage `json:"default,omitempty"` - NotNull bool `json:"notNull,omitempty"` - AsUUID bool `json:"asUuid,omitempty"` - Gen bool `json:"generated,omitempty"` + Name string `json:"name"` + Type string `json:"type"` + Default jsontext.Value `json:"default,omitempty"` + NotNull bool `json:"notNull,omitempty"` + AsUUID bool `json:"asUuid,omitempty"` + Gen bool `json:"generated,omitempty"` } // Identity is the table's identity column spec and its counter. @@ -318,21 +320,21 @@ func (p *parser) parseColumnOption(col *Column, t *dtype, id *Identity) (bool, * return true, id, nil } -func (p *parser) defaultLiteral() (json.RawMessage, *APIError) { +func (p *parser) defaultLiteral() (jsontext.Value, *APIError) { t := p.next() switch { case t.kind == tkNumber: - return json.RawMessage(t.text), nil + return jsontext.Value(t.text), nil case t.kind == tkString: - b, _ := json.Marshal(t.text) + b, _ := json.Marshal(t.text, jsonx.V1()) return b, nil case t.up == kwTrue || t.up == kwFalse: - return json.RawMessage(strings.ToLower(t.text)), nil + return jsontext.Value(strings.ToLower(t.text)), nil case t.up == kwNull: - return json.RawMessage("null"), nil + return jsontext.Value("null"), nil case t.text == "-" && p.peek().kind == tkNumber: - return json.RawMessage("-" + p.next().text), nil + return jsontext.Value("-" + p.next().text), nil } return nil, errParam("syntax error: DEFAULT must be a number, string, boolean or NULL literal") diff --git a/services/ocinosql/handler.go b/services/ocinosql/handler.go index 4f9a1016e1..dfb281ccec 100644 --- a/services/ocinosql/handler.go +++ b/services/ocinosql/handler.go @@ -3,7 +3,8 @@ package ocinosql import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +118,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocinosql: encode response: %w", err) } @@ -164,10 +166,9 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - dec := json.NewDecoder(bytes.NewReader(q.body)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(q.body)) - if err := dec.Decode(v); err != nil { + if err := json.UnmarshalDecode(dec, v, jsonx.V1(), jsonx.UseNumber()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -189,7 +190,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -258,7 +262,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocinosql/limits.go b/services/ocinosql/limits.go index 5ba7ab51f7..8869fe6d6c 100644 --- a/services/ocinosql/limits.go +++ b/services/ocinosql/limits.go @@ -1,8 +1,9 @@ package ocinosql import ( - "encoding/json" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Service limits from Oracle's "Oracle NoSQL Database Cloud Service Limits" @@ -18,7 +19,7 @@ func valueBytes(v any) int { switch x := v.(type) { case string: return len(x) - case json.Number: + case jsonx.Number: return len(x.String()) case map[string]any: n := 0 diff --git a/services/ocinosql/models.go b/services/ocinosql/models.go index 0c45a77e8d..7fb5196c81 100644 --- a/services/ocinosql/models.go +++ b/services/ocinosql/models.go @@ -1,7 +1,7 @@ package ocinosql import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -46,9 +46,9 @@ type Limits struct { // Row is one stored table row. type Row struct { - Expire *time.Time `json:"expire,omitempty"` - Version string `json:"version"` - Value json.RawMessage `json:"value"` + Expire *time.Time `json:"expire,omitempty"` + Version string `json:"version"` + Value jsontext.Value `json:"value"` } // IndexKey is one key of a secondary index. diff --git a/services/ocinosql/rows.go b/services/ocinosql/rows.go index ef5c06e37f..6be2183f69 100644 --- a/services/ocinosql/rows.go +++ b/services/ocinosql/rows.go @@ -3,11 +3,13 @@ package ocinosql import ( "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -35,26 +37,26 @@ type usageWire struct { // UpdateRowResult is the UpdateRow response body. type UpdateRowResult struct { - Version *string `json:"version"` - ExistingVersion *string `json:"existingVersion,omitempty"` - GeneratedValue *string `json:"generatedValue,omitempty"` - ExistingValue json.RawMessage `json:"existingValue,omitempty"` - Usage usageWire `json:"usage"` + Version *string `json:"version"` + ExistingVersion *string `json:"existingVersion,omitempty"` + GeneratedValue *string `json:"generatedValue,omitempty"` + ExistingValue jsontext.Value `json:"existingValue,omitempty"` + Usage usageWire `json:"usage"` } // RowResult is the GetRow response body. type RowResult struct { - TimeOfExpiration *time.Time `json:"timeOfExpiration,omitempty"` - Value json.RawMessage `json:"value"` - Usage usageWire `json:"usage"` + TimeOfExpiration *time.Time `json:"timeOfExpiration,omitempty"` + Value jsontext.Value `json:"value"` + Usage usageWire `json:"usage"` } // DeleteRowResult is the DeleteRow response body. type DeleteRowResult struct { - ExistingVersion *string `json:"existingVersion,omitempty"` - ExistingValue json.RawMessage `json:"existingValue,omitempty"` - IsSuccess bool `json:"isSuccess"` - Usage usageWire `json:"usage"` + ExistingVersion *string `json:"existingVersion,omitempty"` + ExistingValue jsontext.Value `json:"existingValue,omitempty"` + IsSuccess bool `json:"isSuccess"` + Usage usageWire `json:"usage"` } func unitsFor(size int) int { return max(1, (size+bytesPerUnit-1)/bytesPerUnit) } @@ -189,7 +191,7 @@ func (t *Table) generateIdentity(col string, out map[string]any, given map[strin v := strconv.FormatInt(id.Next, 10) id.Next += id.Increment - out[col], given[col] = json.Number(v), true + out[col], given[col] = jsonx.Number(v), true return &v, nil } @@ -293,7 +295,7 @@ func (b *InMemoryBackend) UpdateRow(ref, ifMatch string, in updateRowIn) (Update return b.refusedPut(t, existing, in, now), nil } - raw, _ := json.Marshal(row) + raw, _ := json.Marshal(row, jsonx.V1()) t.Rows[key] = &Row{Value: raw, Version: t.nextVersion(), Expire: expire} w := unitsFor(len(raw)) t.record(now, 0, w) @@ -346,7 +348,7 @@ func parseKey(t *Table, parts []string) (map[string]any, *APIError) { var raw any = val if sv.types[i].isNumeric() { - raw = json.Number(val) + raw = jsonx.Number(val) } n, msg := coerce(sv.types[i], raw) diff --git a/services/ocinosql/sqlexec.go b/services/ocinosql/sqlexec.go index a2479f3f5f..849b559911 100644 --- a/services/ocinosql/sqlexec.go +++ b/services/ocinosql/sqlexec.go @@ -1,12 +1,12 @@ package ocinosql import ( - "encoding/json" "slices" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -373,7 +373,7 @@ func (pl *plan) sortEntries(es []entry) { func (pl *plan) project(es []entry) []map[string]any { st := pl.stmt if st.count { - return []map[string]any{{"Column_1": json.Number(strconv.Itoa(len(es)))}} + return []map[string]any{{"Column_1": jsonx.Number(strconv.Itoa(len(es)))}} } out := make([]map[string]any, 0, len(es)) diff --git a/services/ocinosql/sqlparse.go b/services/ocinosql/sqlparse.go index 0ce8cc9d24..bff8b6e844 100644 --- a/services/ocinosql/sqlparse.go +++ b/services/ocinosql/sqlparse.go @@ -1,9 +1,10 @@ package ocinosql import ( - "encoding/json" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type step struct { @@ -493,7 +494,7 @@ func (p *parser) parseOperand() (expr, *APIError) { return nil, p.fail("a number") } - return &litExpr{v: json.Number("-" + n.text)}, nil + return &litExpr{v: jsonx.Number("-" + n.text)}, nil case t.kind == tkIdent && !isLiteralKw(t.up): steps, err := p.parsePath() if err != nil { @@ -518,7 +519,7 @@ func isLiteralKw(up string) bool { return up == kwTrue || up == kwFalse || up == func literalOf(t tok) (expr, bool) { switch { case t.kind == tkNumber: - return &litExpr{v: json.Number(t.text)}, true + return &litExpr{v: jsonx.Number(t.text)}, true case t.kind == tkString: return &litExpr{v: t.text}, true case t.kind == tkVar: diff --git a/services/ocinosql/tables.go b/services/ocinosql/tables.go index 35b6d094a0..83c4d024c3 100644 --- a/services/ocinosql/tables.go +++ b/services/ocinosql/tables.go @@ -1,13 +1,14 @@ package ocinosql import ( - "encoding/json" + "encoding/json/v2" "net/http" "slices" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -369,7 +370,7 @@ func schemaView2(t *Table) *schemaWire { if len(c.Default) > 0 { var s string - if json.Unmarshal(c.Default, &s) != nil { + if json.Unmarshal(c.Default, &s, jsonx.V1()) != nil { s = string(c.Default) } diff --git a/services/ocinosql/values.go b/services/ocinosql/values.go index 646010f0f0..4d780f2aa5 100644 --- a/services/ocinosql/values.go +++ b/services/ocinosql/values.go @@ -3,7 +3,8 @@ package ocinosql import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "math" "math/big" @@ -13,6 +14,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/strs" ) @@ -46,18 +48,17 @@ const ( ) func decodeJSON(raw []byte) (any, error) { - dec := json.NewDecoder(bytes.NewReader(raw)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(raw)) var v any - if err := dec.Decode(&v); err != nil { + if err := json.UnmarshalDecode(dec, &v, jsonx.V1(), jsonx.UseNumber()); err != nil { return nil, fmt.Errorf("decode json: %w", err) } return v, nil } -func decodeRow(raw json.RawMessage) map[string]any { +func decodeRow(raw jsontext.Value) map[string]any { v, err := decodeJSON(raw) if err != nil { return map[string]any{} @@ -69,7 +70,7 @@ func decodeRow(raw json.RawMessage) map[string]any { } func coerceInt(v any, lo, hi int64, kind string) (any, string) { - n, ok := v.(json.Number) + n, ok := v.(jsonx.Number) if !ok { return nil, "is not a valid " + kind } @@ -93,7 +94,7 @@ func coerceInt(v any, lo, hi int64, kind string) (any, string) { return nil, "is out of range for " + kind } - return json.Number(strconv.FormatInt(i, 10)), "" + return jsonx.Number(strconv.FormatInt(i, 10)), "" } func parseTimestamp(v any) (time.Time, bool) { @@ -106,7 +107,7 @@ func parseTimestamp(v any) (time.Time, bool) { return t.UTC(), true } } - case json.Number: + case jsonx.Number: if ms, err := strconv.ParseInt(x.String(), 10, 64); err == nil { return time.UnixMilli(ms).UTC(), true } @@ -149,7 +150,7 @@ func coerce(t *dtype, v any) (any, string) { func coerceScalar(t *dtype, v any) (any, string) { switch t.kind { case kNumber: - n, ok := v.(json.Number) + n, ok := v.(jsonx.Number) if _, rok := new(big.Rat).SetString(n.String()); !ok || !rok { return nil, "is not a valid NUMBER" } @@ -263,7 +264,7 @@ func coerceRecord(t *dtype, v any) (any, string) { return out, "" } -func cmpNum(a, b json.Number) (int, bool) { +func cmpNum(a, b jsonx.Number) (int, bool) { ra, ok1 := new(big.Rat).SetString(a.String()) rb, ok2 := new(big.Rat).SetString(b.String()) @@ -277,8 +278,8 @@ func cmpNum(a, b json.Number) (int, bool) { // compareVals orders two scalar values of the same family; ok is false when they are not comparable. func compareVals(a, b any) (int, bool) { switch x := a.(type) { - case json.Number: - if y, ok := b.(json.Number); ok { + case jsonx.Number: + if y, ok := b.(jsonx.Number); ok { return cmpNum(x, y) } case string: @@ -302,7 +303,7 @@ func compareVals(a, b any) (int, bool) { } func keyPart(v any) string { - if n, ok := v.(json.Number); ok { + if n, ok := v.(jsonx.Number); ok { if r, rok := new(big.Rat).SetString(n.String()); rok { return r.RatString() } @@ -326,7 +327,7 @@ func rowKey(pk []string, row map[string]any) (string, *APIError) { parts[i] = keyPart(v) } - b, _ := json.Marshal(parts) //nolint:errchkjson // []string cannot fail + b, _ := json.Marshal(parts, jsonx.V1()) //nolint:errchkjson // []string cannot fail return string(b), nil } @@ -340,7 +341,7 @@ func validUUID(s string) bool { } func coerceFloat(kind string, v any) (any, string) { - n, ok := v.(json.Number) + n, ok := v.(jsonx.Number) if !ok { return nil, "is not a valid " + kind } @@ -350,5 +351,5 @@ func coerceFloat(kind string, v any) (any, string) { return nil, "is not a valid " + kind } - return json.Number(strconv.FormatFloat(f, 'g', -1, 64)), "" + return jsonx.Number(strconv.FormatFloat(f, 'g', -1, 64)), "" } diff --git a/services/ocinotifications/handler.go b/services/ocinotifications/handler.go index 9e9d2dc97c..0250d6844e 100644 --- a/services/ocinotifications/handler.go +++ b/services/ocinotifications/handler.go @@ -2,7 +2,7 @@ package ocinotifications import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -117,7 +118,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocinotifications: encode response: %w", err) } @@ -168,7 +169,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -190,7 +191,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -278,7 +282,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocinotifications/publish.go b/services/ocinotifications/publish.go index 9418c1535e..87b4cec7ef 100644 --- a/services/ocinotifications/publish.go +++ b/services/ocinotifications/publish.go @@ -3,7 +3,8 @@ package ocinotifications import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -116,7 +119,7 @@ func (b *InMemoryBackend) queueConfirmation(s *Subscription, t *Topic) { "SubscriptionId": s.ID, "ConfirmationURL": d.ConfirmationURL, "Message": "You have chosen to subscribe to the topic " + t.Name + ". To confirm the subscription, visit the ConfirmationURL included in this message.", - }) + }, jsonx.V1()) d.Body = string(body) d.Title = "Confirm your subscription to " + t.Name b.route(d) @@ -154,7 +157,7 @@ func (b *InMemoryBackend) PublishMessage(topicID, messageType string, in Publish return PublishWire{}, errParam("a message is limited to 64 KB") } - if messageType == msgJSON && !json.Valid([]byte(*in.Body)) { + if messageType == msgJSON && !jsontext.Value([]byte(*in.Body)).IsValid(jsonx.V1()) { return PublishWire{}, errParam("body must be valid JSON when messageType is JSON") } diff --git a/services/ocinotifications/subs.go b/services/ocinotifications/subs.go index de6576d716..e12d9fbf5d 100644 --- a/services/ocinotifications/subs.go +++ b/services/ocinotifications/subs.go @@ -1,7 +1,7 @@ package ocinotifications import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/mail" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -104,7 +105,7 @@ func policyOf(s *Subscription) deliveryPolicyWire { } func subView(s *Subscription) SubWire { - pol, _ := json.Marshal(policyOf(s)) //nolint:errchkjson // static shape + pol, _ := json.Marshal(policyOf(s), jsonx.V1()) //nolint:errchkjson // static shape return SubWire{ ID: s.ID, diff --git a/services/ociobjectstorage/auth_test.go b/services/ociobjectstorage/auth_test.go index 94450b9ab6..94c243c587 100644 --- a/services/ociobjectstorage/auth_test.go +++ b/services/ociobjectstorage/auth_test.go @@ -1,7 +1,7 @@ package ociobjectstorage_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -114,14 +115,17 @@ func TestAdminKeyRegistration(t *testing.T) { _, err := e.client.GetNamespace(t.Context(), objectstorage.GetNamespaceRequest{}) assert.Equal(t, 401, svcErr(t, err).GetHTTPStatusCode()) - payload, _ := json.Marshal(map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.keys.pubPEM}) + payload, _ := json.Marshal( + map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.keys.pubPEM}, + jsonx.V1(), + ) code, body := rawDo(t, http.MethodPost, e.baseURL+"/_gopherstack/oci/keys", string(payload)) require.Equal(t, http.StatusCreated, code, body) var out struct { KeyID string `json:"keyId"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, testTenancy+"/"+testUser+"/"+e.keys.fprint, out.KeyID) resp, err := e.client.GetNamespace(t.Context(), objectstorage.GetNamespaceRequest{}) diff --git a/services/ociobjectstorage/handler.go b/services/ociobjectstorage/handler.go index a7a60b6e8f..b20647f401 100644 --- a/services/ociobjectstorage/handler.go +++ b/services/ociobjectstorage/handler.go @@ -2,7 +2,7 @@ package ociobjectstorage import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -112,7 +113,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociobjectstorage: encode response: %w", err) } @@ -151,7 +152,10 @@ func (h *Handler) fail(q *req, err error) { q.w.WriteHeader(ae.Status) if q.r.Method != http.MethodHead { - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } } @@ -268,7 +272,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociobjectstorage/ops.go b/services/ociobjectstorage/ops.go index 7243b1315d..7659a5f2b6 100644 --- a/services/ociobjectstorage/ops.go +++ b/services/ociobjectstorage/ops.go @@ -1,11 +1,13 @@ package ociobjectstorage import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func buildOps() map[string]opFunc { @@ -54,7 +56,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", diff --git a/services/ociqueue/handler.go b/services/ociqueue/handler.go index 62a3e9dcfc..74493562ac 100644 --- a/services/ociqueue/handler.go +++ b/services/ociqueue/handler.go @@ -2,7 +2,7 @@ package ociqueue import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +117,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ociqueue: encode response: %w", err) } @@ -174,7 +175,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -196,7 +197,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -265,7 +269,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ociqueue/helpers_test.go b/services/ociqueue/helpers_test.go index bde7f5c137..60b9f673b3 100644 --- a/services/ociqueue/helpers_test.go +++ b/services/ociqueue/helpers_test.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "crypto/rsa" "crypto/x509" - "encoding/json" + "encoding/json/v2" "encoding/pem" "fmt" "io" @@ -19,6 +19,7 @@ import ( "github.com/oracle/oci-go-sdk/v65/queue" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -223,7 +224,7 @@ func get(t *testing.T, c queue.QueueClient, q queue.Queue, mod func(*queue.GetMe } func quote(s string) string { - b, _ := json.Marshal(s) + b, _ := json.Marshal(s, jsonx.V1()) return string(b) } diff --git a/services/ociqueue/queues.go b/services/ociqueue/queues.go index 99019f4c11..95b81da2e2 100644 --- a/services/ociqueue/queues.go +++ b/services/ociqueue/queues.go @@ -1,7 +1,7 @@ package ociqueue import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "slices" "strconv" @@ -27,27 +27,27 @@ const ( // CreateQueueIn is the CreateQueue request body. type CreateQueueIn struct { Tags - Retention *int `json:"retentionInSeconds"` - Visibility *int `json:"visibilityInSeconds"` - Timeout *int `json:"timeoutInSeconds"` - ChannelLimit *int `json:"channelConsumptionLimit"` - DLQCount *int `json:"deadLetterQueueDeliveryCount"` - KMSKeyID *string `json:"customEncryptionKeyId"` - Name string `json:"displayName"` - Compartment string `json:"compartmentId"` - Capabilities []json.RawMessage `json:"capabilities"` + Retention *int `json:"retentionInSeconds"` + Visibility *int `json:"visibilityInSeconds"` + Timeout *int `json:"timeoutInSeconds"` + ChannelLimit *int `json:"channelConsumptionLimit"` + DLQCount *int `json:"deadLetterQueueDeliveryCount"` + KMSKeyID *string `json:"customEncryptionKeyId"` + Name string `json:"displayName"` + Compartment string `json:"compartmentId"` + Capabilities []jsontext.Value `json:"capabilities"` } // UpdateQueueIn is the UpdateQueue request body. type UpdateQueueIn struct { Tags - Name *string `json:"displayName"` - Visibility *int `json:"visibilityInSeconds"` - Timeout *int `json:"timeoutInSeconds"` - ChannelLimit *int `json:"channelConsumptionLimit"` - DLQCount *int `json:"deadLetterQueueDeliveryCount"` - KMSKeyID *string `json:"customEncryptionKeyId"` - Capabilities []json.RawMessage `json:"capabilities"` + Name *string `json:"displayName"` + Visibility *int `json:"visibilityInSeconds"` + Timeout *int `json:"timeoutInSeconds"` + ChannelLimit *int `json:"channelConsumptionLimit"` + DLQCount *int `json:"deadLetterQueueDeliveryCount"` + KMSKeyID *string `json:"customEncryptionKeyId"` + Capabilities []jsontext.Value `json:"capabilities"` } // PurgeIn is the PurgeQueue request body. @@ -131,7 +131,7 @@ func firstErr(errs ...*APIError) *APIError { return nil } -func checkCapabilities(c []json.RawMessage) *APIError { +func checkCapabilities(c []jsontext.Value) *APIError { if len(c) > 0 { return errParam("capabilities are not supported by this emulator") } diff --git a/services/ocistreaming/cursors.go b/services/ocistreaming/cursors.go index 8398e57860..4e39d60a55 100644 --- a/services/ocistreaming/cursors.go +++ b/services/ocistreaming/cursors.go @@ -2,7 +2,7 @@ package ocistreaming import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strconv" @@ -10,6 +10,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -39,7 +41,7 @@ type cursorTok struct { } func (c cursorTok) encode() string { - raw, _ := json.Marshal(c) //nolint:errchkjson // static shape + raw, _ := json.Marshal(c, jsonx.V1()) //nolint:errchkjson // static shape return base64.RawURLEncoding.EncodeToString(raw) } @@ -48,7 +50,7 @@ func decodeCursor(streamID, v string) (cursorTok, error) { var c cursorTok raw, err := base64.RawURLEncoding.DecodeString(v) - if err != nil || json.Unmarshal(raw, &c) != nil || c.Stream != streamID { + if err != nil || json.Unmarshal(raw, &c, jsonx.V1()) != nil || c.Stream != streamID { return c, errParam("The cursor is invalid or does not belong to this stream") } diff --git a/services/ocistreaming/handler.go b/services/ocistreaming/handler.go index ad3f717cba..4220d6d96f 100644 --- a/services/ocistreaming/handler.go +++ b/services/ocistreaming/handler.go @@ -2,7 +2,7 @@ package ocistreaming import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -116,7 +117,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocistreaming: encode response: %w", err) } @@ -174,7 +175,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -196,7 +197,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -258,7 +262,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocistreaming/service_test.go b/services/ocistreaming/service_test.go index 935e5ecdef..052cc03a6d 100644 --- a/services/ocistreaming/service_test.go +++ b/services/ocistreaming/service_test.go @@ -2,7 +2,7 @@ package ocistreaming_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -95,7 +96,10 @@ func TestAdminKeyRegistration(t *testing.T) { _, err := e.admin.ListStreamPools(t.Context(), req) assert.Equal(t, http.StatusUnauthorized, svcErr(t, err).GetHTTPStatusCode()) - payload, _ := json.Marshal(map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.kp.pubPEM}) + payload, _ := json.Marshal( + map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.kp.pubPEM}, + jsonx.V1(), + ) code, body := rawDo(t, http.MethodPost, e.base+"/_gopherstack/oci/keys", string(payload)) require.Equal(t, http.StatusCreated, code, body) diff --git a/services/ocivault/handler.go b/services/ocivault/handler.go index 8523e4ebdd..0ec2c2d340 100644 --- a/services/ocivault/handler.go +++ b/services/ocivault/handler.go @@ -2,7 +2,7 @@ package ocivault import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/ociauth" @@ -115,7 +116,7 @@ type errorBody struct { func (q *req) header(k, v string) { q.w.Header().Set(k, v) } func (q *req) json(status int, v any, etag string) error { - out, err := json.Marshal(v) + out, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("ocivault: encode response: %w", err) } @@ -173,7 +174,7 @@ func (q *req) decode(v any) error { return errMissing("A request body is required") } - if err := json.Unmarshal(q.body, v); err != nil { + if err := json.Unmarshal(q.body, v, jsonx.V1()); err != nil { return newErr( http.StatusBadRequest, "CannotParseRequest", @@ -195,7 +196,10 @@ func (h *Handler) fail(q *req, err error) { q.header("Content-Type", "application/json") q.w.WriteHeader(ae.Status) - out, _ := json.Marshal(errorBody{Code: ae.Code, Message: ae.Message}) //nolint:errchkjson // static shape + out, _ := json.Marshal( + errorBody{Code: ae.Code, Message: ae.Message}, + jsonx.V1(), + ) //nolint:errchkjson // static shape _, _ = q.w.Write(out) } @@ -257,7 +261,7 @@ func (h *Handler) adminKeys(q *req) { var in adminKeyReq body, _ := io.ReadAll(io.LimitReader(q.r.Body, adminBodyLimit)) - if err := json.Unmarshal(body, &in); err != nil || in.Tenancy == "" || in.User == "" { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil || in.Tenancy == "" || in.User == "" { h.fail(q, errParam("tenancy, user and publicKey are required")) return diff --git a/services/ocivault/handler_test.go b/services/ocivault/handler_test.go index 4e5db40ae3..ad23de5ad4 100644 --- a/services/ocivault/handler_test.go +++ b/services/ocivault/handler_test.go @@ -2,7 +2,7 @@ package ocivault_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -112,7 +113,7 @@ func TestPathVaultRouting(t *testing.T) { VaultID string `json:"vaultId"` } - require.NoError(t, json.Unmarshal([]byte(out), &k)) + require.NoError(t, json.Unmarshal([]byte(out), &k, jsonx.V1())) assert.Equal(t, *v.Id, k.VaultID) code, out = rawDo(t, http.MethodGet, e.base+"/_vault/"+*v.Id+"/20180608/keys?compartmentId="+testCompartment, "") @@ -161,7 +162,7 @@ func TestErrorBodyShapeAndUnknownRoutes(t *testing.T) { Message string `json:"message"` } - require.NoError(t, json.Unmarshal([]byte(out), &eb)) + require.NoError(t, json.Unmarshal([]byte(out), &eb, jsonx.V1())) assert.Equal(t, tt.wantCode, eb.Code) assert.NotEmpty(t, eb.Message) assert.NotEqual(t, eb.Code, eb.Message) @@ -234,7 +235,10 @@ func TestAdminKeyRegistration(t *testing.T) { _, err := e.vaults.ListVaults(t.Context(), listReq) assert.Equal(t, http.StatusUnauthorized, svcErr(t, err).GetHTTPStatusCode()) - payload, _ := json.Marshal(map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.kp.pubPEM}) + payload, _ := json.Marshal( + map[string]string{"tenancy": testTenancy, "user": testUser, "publicKey": e.kp.pubPEM}, + jsonx.V1(), + ) code, body := rawDo(t, http.MethodPost, e.base+"/_gopherstack/oci/keys", string(payload)) require.Equal(t, http.StatusCreated, code, body) diff --git a/services/ocivault/models.go b/services/ocivault/models.go index 6fcbc68a31..60af20ab9d 100644 --- a/services/ocivault/models.go +++ b/services/ocivault/models.go @@ -1,7 +1,7 @@ package ocivault import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -106,7 +106,7 @@ type Secret struct { Description string `json:"description,omitempty"` State string `json:"state"` Etag string `json:"etag"` - Rules []json.RawMessage `json:"rules,omitempty"` + Rules []jsontext.Value `json:"rules,omitempty"` Versions []*SecretVersion `json:"versions"` Seq int64 `json:"seq"` Current int64 `json:"current"` diff --git a/services/ocivault/seal.go b/services/ocivault/seal.go index c8851b7ec5..fb6cf32bee 100644 --- a/services/ocivault/seal.go +++ b/services/ocivault/seal.go @@ -12,8 +12,10 @@ import ( _ "crypto/sha512" // registers SHA-384/512 for crypto.Hash.New "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "hash" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -51,7 +53,7 @@ func aadBytes(aad map[string]string) []byte { return nil } - b, _ := json.Marshal(aad) //nolint:errchkjson // map[string]string always marshals; keys are sorted + b, _ := json.Marshal(aad, jsonx.V1()) //nolint:errchkjson // map[string]string always marshals; keys are sorted return b } diff --git a/services/ocivault/secrets.go b/services/ocivault/secrets.go index fce0df635b..3c55f64207 100644 --- a/services/ocivault/secrets.go +++ b/services/ocivault/secrets.go @@ -3,13 +3,15 @@ package ocivault import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "slices" "strconv" "time" "github.com/blackbirdworks/gopherstack/pkgs/iso8601" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -37,16 +39,16 @@ type CreateSecretIn struct { DefinedTags map[string]map[string]any `json:"definedTags"` Metadata map[string]any `json:"metadata"` SecretContent *SecretContent `json:"secretContent"` - ReplicationConfig json.RawMessage `json:"replicationConfig"` - RotationConfig json.RawMessage `json:"rotationConfig"` - SecretGenerationContext json.RawMessage `json:"secretGenerationContext"` + ReplicationConfig jsontext.Value `json:"replicationConfig"` + RotationConfig jsontext.Value `json:"rotationConfig"` + SecretGenerationContext jsontext.Value `json:"secretGenerationContext"` EnableAutoGeneration *bool `json:"enableAutoGeneration"` CompartmentID string `json:"compartmentId"` KeyID string `json:"keyId"` SecretName string `json:"secretName"` VaultID string `json:"vaultId"` Description string `json:"description"` - SecretRules []json.RawMessage `json:"secretRules"` + SecretRules []jsontext.Value `json:"secretRules"` } // UpdateSecretIn is the UpdateSecret request body. @@ -57,11 +59,11 @@ type UpdateSecretIn struct { DefinedTags map[string]map[string]any `json:"definedTags"` Metadata map[string]any `json:"metadata"` SecretContent *SecretContent `json:"secretContent"` - ReplicationConfig json.RawMessage `json:"replicationConfig"` - RotationConfig json.RawMessage `json:"rotationConfig"` - SecretGenerationContext json.RawMessage `json:"secretGenerationContext"` + ReplicationConfig jsontext.Value `json:"replicationConfig"` + RotationConfig jsontext.Value `json:"rotationConfig"` + SecretGenerationContext jsontext.Value `json:"secretGenerationContext"` EnableAutoGeneration *bool `json:"enableAutoGeneration"` - SecretRules []json.RawMessage `json:"secretRules"` + SecretRules []jsontext.Value `json:"secretRules"` } type expiryRule struct { @@ -70,7 +72,7 @@ type expiryRule struct { Interval string `json:"secretVersionExpiryInterval"` } -func unsupported(raw json.RawMessage, auto *bool, what string) *APIError { +func unsupported(raw jsontext.Value, auto *bool, what string) *APIError { if len(bytes.TrimSpace(raw)) > 0 && string(bytes.TrimSpace(raw)) != "null" || auto != nil && *auto { return errParam(what + " is not supported by this emulator") } @@ -78,10 +80,10 @@ func unsupported(raw json.RawMessage, auto *bool, what string) *APIError { return nil } -func rejectUnsupported(repl, rot, gen json.RawMessage, auto *bool) *APIError { +func rejectUnsupported(repl, rot, gen jsontext.Value, auto *bool) *APIError { for _, c := range []struct { what string - raw json.RawMessage + raw jsontext.Value }{ {what: "replicationConfig", raw: repl}, {what: "rotationConfig", raw: rot}, @@ -95,13 +97,18 @@ func rejectUnsupported(repl, rot, gen json.RawMessage, auto *bool) *APIError { return unsupported(nil, auto, "enableAutoGeneration") } -func validateRules(rules []json.RawMessage) *APIError { +func validateRules(rules []jsontext.Value) *APIError { for _, r := range rules { var head struct { RuleType string `json:"ruleType"` } - if err := json.Unmarshal(r, &head); err != nil || (head.RuleType != ruleExpiry && head.RuleType != ruleReuse) { + if err := json.Unmarshal( + r, + &head, + jsonx.V1(), + ); err != nil || + (head.RuleType != ruleExpiry && head.RuleType != ruleReuse) { return errParam("secretRules[].ruleType must be SECRET_EXPIRY_RULE or SECRET_REUSE_RULE") } @@ -115,9 +122,9 @@ func validateRules(rules []json.RawMessage) *APIError { return nil } -func parseExpiry(raw json.RawMessage) (expiryRule, *APIError) { +func parseExpiry(raw jsontext.Value) (expiryRule, *APIError) { var e expiryRule - if err := json.Unmarshal(raw, &e); err != nil { + if err := json.Unmarshal(raw, &e, jsonx.V1()); err != nil { return e, errParam("invalid SECRET_EXPIRY_RULE") } @@ -130,13 +137,13 @@ func parseExpiry(raw json.RawMessage) (expiryRule, *APIError) { return e, nil } -func ruleOfType(rules []json.RawMessage, t string) json.RawMessage { +func ruleOfType(rules []jsontext.Value, t string) jsontext.Value { for _, r := range rules { var head struct { RuleType string `json:"ruleType"` } - if json.Unmarshal(r, &head) == nil && head.RuleType == t { + if json.Unmarshal(r, &head, jsonx.V1()) == nil && head.RuleType == t { return r } } @@ -144,7 +151,7 @@ func ruleOfType(rules []json.RawMessage, t string) json.RawMessage { return nil } -func (b *InMemoryBackend) versionExpiry(rules []json.RawMessage) *time.Time { +func (b *InMemoryBackend) versionExpiry(rules []jsontext.Value) *time.Time { raw := ruleOfType(rules, ruleExpiry) if raw == nil { return nil diff --git a/services/ocivault/secrets_test.go b/services/ocivault/secrets_test.go index 4246998146..379b082494 100644 --- a/services/ocivault/secrets_test.go +++ b/services/ocivault/secrets_test.go @@ -1,7 +1,7 @@ package ocivault_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" oci "github.com/blackbirdworks/gopherstack/services/ocivault" ) @@ -644,7 +645,7 @@ func TestSecretIfMatchAndCompartmentMove(t *testing.T) { require.NoError(t, err) assert.Equal(t, "ocid1.compartment.oc1..moved", *moved.CompartmentId) - raw, err := json.Marshal(moved.Secret) + raw, err := json.Marshal(moved.Secret, jsonx.V1()) require.NoError(t, err) assert.Contains(t, string(raw), "currentVersionNumber") } diff --git a/services/ocivault/secretwire.go b/services/ocivault/secretwire.go index 61f6c10afa..3d0e484fd4 100644 --- a/services/ocivault/secretwire.go +++ b/services/ocivault/secretwire.go @@ -1,7 +1,7 @@ package ocivault import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -20,7 +20,7 @@ type secretWire struct { VaultID string `json:"vaultId"` KeyID string `json:"keyId"` Description string `json:"description,omitempty"` - SecretRules []json.RawMessage `json:"secretRules,omitempty"` + SecretRules []jsontext.Value `json:"secretRules,omitempty"` } type secretSummaryWire struct { diff --git a/services/omics/delete_precondition_test.go b/services/omics/delete_precondition_test.go index d913d06d06..ae40065d2c 100644 --- a/services/omics/delete_precondition_test.go +++ b/services/omics/delete_precondition_test.go @@ -1,12 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDeleteRun_RequiresTerminalState verifies real AWS DeleteRun semantics @@ -26,7 +28,7 @@ func TestDeleteRun_RequiresTerminalState(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) runID := startResp["id"].(string) delRec := doRequest(t, h, http.MethodDelete, "/run/"+runID, nil) @@ -55,7 +57,7 @@ func TestDeleteReferenceStore_RequiresEmpty(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+storeID+"/importjob", map[string]any{ @@ -68,7 +70,7 @@ func TestDeleteReferenceStore_RequiresEmpty(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) refs, ok := listResp["references"].([]any) require.True(t, ok) require.Len(t, refs, 1) @@ -100,7 +102,7 @@ func TestDeleteSequenceStore_RequiresEmpty(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/importjob", map[string]any{ @@ -113,7 +115,7 @@ func TestDeleteSequenceStore_RequiresEmpty(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) readSets, ok := listResp["readSets"].([]any) require.True(t, ok) require.Len(t, readSets, 1) @@ -147,7 +149,7 @@ func TestDeleteReference_RequiresNoAssociatedReadSet(t *testing.T) { require.Equal(t, http.StatusCreated, refStoreRec.Code) var refStore map[string]any - require.NoError(t, json.Unmarshal(refStoreRec.Body.Bytes(), &refStore)) + require.NoError(t, json.Unmarshal(refStoreRec.Body.Bytes(), &refStore, jsonx.V1())) refStoreID := refStore["id"].(string) refJobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+refStoreID+"/importjob", map[string]any{ @@ -160,7 +162,7 @@ func TestDeleteReference_RequiresNoAssociatedReadSet(t *testing.T) { require.Equal(t, http.StatusOK, refListRec.Code) var refListResp map[string]any - require.NoError(t, json.Unmarshal(refListRec.Body.Bytes(), &refListResp)) + require.NoError(t, json.Unmarshal(refListRec.Body.Bytes(), &refListResp, jsonx.V1())) refs, ok := refListResp["references"].([]any) require.True(t, ok) require.Len(t, refs, 1) @@ -173,7 +175,7 @@ func TestDeleteReference_RequiresNoAssociatedReadSet(t *testing.T) { require.Equal(t, http.StatusCreated, seqStoreRec.Code) var seqStore map[string]any - require.NoError(t, json.Unmarshal(seqStoreRec.Body.Bytes(), &seqStore)) + require.NoError(t, json.Unmarshal(seqStoreRec.Body.Bytes(), &seqStore, jsonx.V1())) seqStoreID := seqStore["id"].(string) readSetJobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+seqStoreID+"/importjob", map[string]any{ @@ -190,7 +192,7 @@ func TestDeleteReference_RequiresNoAssociatedReadSet(t *testing.T) { require.Equal(t, http.StatusOK, readSetListRec.Code) var readSetListResp map[string]any - require.NoError(t, json.Unmarshal(readSetListRec.Body.Bytes(), &readSetListResp)) + require.NoError(t, json.Unmarshal(readSetListRec.Body.Bytes(), &readSetListResp, jsonx.V1())) readSets, ok := readSetListResp["readSets"].([]any) require.True(t, ok) require.Len(t, readSets, 1) diff --git a/services/omics/handler.go b/services/omics/handler.go index cb633586ce..0cdc04ccf8 100644 --- a/services/omics/handler.go +++ b/services/omics/handler.go @@ -1,7 +1,7 @@ package omics import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -782,7 +783,7 @@ func readJSON(c *echo.Context, v any) error { return nil } - if jsonErr := json.Unmarshal(body, v); jsonErr != nil { + if jsonErr := json.Unmarshal(body, v, jsonx.V1()); jsonErr != nil { if writeErr := c.JSON(http.StatusBadRequest, errResp(errValidation, "invalid JSON")); writeErr != nil { return writeErr } diff --git a/services/omics/handler_annotation_stores_test.go b/services/omics/handler_annotation_stores_test.go index eece97ac5b..8128a5d787 100644 --- a/services/omics/handler_annotation_stores_test.go +++ b/services/omics/handler_annotation_stores_test.go @@ -1,13 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -31,7 +32,7 @@ func TestOmics_AnnotationStore(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) // Real CreateAnnotationStoreOutput is narrower than // GetAnnotationStoreOutput -- no storeArn/reference member // (api_op_CreateAnnotationStore.go:68-95); storeArn is @@ -98,14 +99,14 @@ func TestCreateAnnotationStoreStoresReference(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Equal(t, "CREATING", createResp["status"]) getRec := doRequest(t, h, http.MethodGet, "/annotationStore/ann-store-ref", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotNil(t, getResp["reference"]) // GetAnnotationStore advances CREATING->ACTIVE on its first poll (the // waiter-hang fix -- see PARITY.md), so the immediate Get after Create @@ -130,7 +131,7 @@ func TestCreateAnnotationStore_ResponseShape(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "v1", resp["versionName"]) assert.NotContains(t, resp, "storeArn") assert.NotContains(t, resp, "reference") @@ -157,7 +158,7 @@ func TestListAnnotationImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusCreated, jobRec.Code) var job map[string]any - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &job, jsonx.V1())) jobID := job["jobId"].(string) // storeName filter: no job targets "other-store". @@ -166,7 +167,7 @@ func TestListAnnotationImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs, ok := resp["annotationImportJobs"].([]any) require.True(t, ok) assert.Empty(t, jobs) @@ -177,7 +178,7 @@ func TestListAnnotationImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) jobs2, ok := resp2["annotationImportJobs"].([]any) require.True(t, ok) require.Len(t, jobs2, 1) @@ -188,7 +189,7 @@ func TestListAnnotationImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) jobs3, ok := resp3["annotationImportJobs"].([]any) require.True(t, ok) assert.Empty(t, jobs3) @@ -197,7 +198,7 @@ func TestListAnnotationImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var resp4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4, jsonx.V1())) jobs4, ok := resp4["annotationImportJobs"].([]any) require.True(t, ok) require.Len(t, jobs4, 1) @@ -218,7 +219,7 @@ func createAnnotationStorePair(t *testing.T, h *omics.Handler) map[string]string require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids[name], _ = resp["id"].(string) } @@ -307,7 +308,7 @@ func TestListAnnotationStores_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.ElementsMatch(t, tc.wantNames, annotationStoreNames(t, resp["annotationStores"])) }) } @@ -348,7 +349,7 @@ func TestListAnnotationStoreVersions_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["annotationStoreVersions"].([]any) require.True(t, ok) assert.Len(t, versions, tc.wantCount) diff --git a/services/omics/handler_configurations_test.go b/services/omics/handler_configurations_test.go index 25cca88b2e..31b52066cb 100644 --- a/services/omics/handler_configurations_test.go +++ b/services/omics/handler_configurations_test.go @@ -1,12 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestOmics_Configuration exercises the Configuration CRUD family. @@ -39,7 +41,7 @@ func TestOmics_Configuration(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "cfg1", resp["name"]) assert.Equal(t, "ACTIVE", resp["status"]) assert.NotEmpty(t, resp["arn"]) @@ -101,14 +103,14 @@ func TestS3AccessPolicy_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) assert.Equal(t, apArn, putResp["s3AccessPointArn"]) getRec := doRequest(t, h, http.MethodGet, "/s3accesspolicy/"+apArn, nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) policy, _ := getResp["s3AccessPolicy"].(string) assert.JSONEq(t, `{"Version":"2012-10-17"}`, policy, "real wire key is s3AccessPolicy") assert.Nil(t, getResp["policy"], "policy is not a real wire key") diff --git a/services/omics/handler_read_sets_test.go b/services/omics/handler_read_sets_test.go index 7f3934320d..a5a80de901 100644 --- a/services/omics/handler_read_sets_test.go +++ b/services/omics/handler_read_sets_test.go @@ -3,7 +3,7 @@ package omics_test import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -31,7 +32,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/sequencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequestRaw(t, h, http.MethodPut, @@ -49,7 +50,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/sequencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequestRaw(t, h, http.MethodPut, @@ -67,7 +68,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/sequencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequest(t, h, http.MethodPost, @@ -76,7 +77,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { ) require.Equal(t, http.StatusCreated, rec2.Code) var uploadResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &uploadResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &uploadResp, jsonx.V1())) uploadID := uploadResp["uploadId"].(string) payload := []byte("ACGT sequence data") @@ -90,7 +91,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { ) require.Equal(t, http.StatusOK, rec3.Code) var partResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &partResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &partResp, jsonx.V1())) assert.Equal(t, expectedChecksum, partResp["checksum"]) assert.Equal(t, "SHA256", partResp["checksumAlgorithm"]) }, @@ -102,7 +103,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/sequencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequest(t, h, http.MethodPost, @@ -111,7 +112,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { ) require.Equal(t, http.StatusCreated, rec2.Code) var uploadResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &uploadResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &uploadResp, jsonx.V1())) uploadID := uploadResp["uploadId"].(string) payload := []byte("hello omics") @@ -128,7 +129,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { ) require.Equal(t, http.StatusOK, rec4.Code) var rsResp map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &rsResp)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &rsResp, jsonx.V1())) rsID := rsResp["readSetId"].(string) rec5 := doRequestRaw(t, h, http.MethodGet, @@ -146,7 +147,7 @@ func TestOmics_UploadReadSetPart_And_GetReadSet(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/sequencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequestRaw(t, h, http.MethodGet, @@ -179,7 +180,7 @@ func TestCreateMultipartReadSetUpload_WireShape(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) rec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/upload", map[string]any{ @@ -191,7 +192,7 @@ func TestCreateMultipartReadSetUpload_WireShape(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "FASTQ", resp["sourceFileType"]) assert.Equal(t, "sample-1", resp["sampleId"]) assert.Equal(t, "subject-1", resp["subjectId"]) @@ -211,7 +212,7 @@ func TestReadSetMetadata_FileTypeField(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/importjob", map[string]any{ @@ -224,7 +225,7 @@ func TestReadSetMetadata_FileTypeField(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) readSets, ok := listResp["readSets"].([]any) require.True(t, ok) require.Len(t, readSets, 1) @@ -280,7 +281,7 @@ func TestReadSetMetadata_FilesField_ImportJob(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/importjob", map[string]any{ @@ -293,7 +294,7 @@ func TestReadSetMetadata_FilesField_ImportJob(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) readSets, ok := listResp["readSets"].([]any) require.True(t, ok) require.Len(t, readSets, 1) @@ -309,7 +310,7 @@ func TestReadSetMetadata_FilesField_ImportJob(t *testing.T) { require.Equal(t, http.StatusOK, metaRec.Code) var meta map[string]any - require.NoError(t, json.Unmarshal(metaRec.Body.Bytes(), &meta)) + require.NoError(t, json.Unmarshal(metaRec.Body.Bytes(), &meta, jsonx.V1())) files, ok := meta["files"].(map[string]any) require.True(t, ok, "files sub-object must be present") assert.Contains(t, files, "source1") @@ -357,7 +358,7 @@ func TestReadSetMetadata_FilesField_MultipartUpload(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) uploadRec := doRequest(t, h, http.MethodPost, @@ -367,7 +368,7 @@ func TestReadSetMetadata_FilesField_MultipartUpload(t *testing.T) { require.Equal(t, http.StatusCreated, uploadRec.Code) var uploadResp map[string]any - require.NoError(t, json.Unmarshal(uploadRec.Body.Bytes(), &uploadResp)) + require.NoError(t, json.Unmarshal(uploadRec.Body.Bytes(), &uploadResp, jsonx.V1())) uploadID := uploadResp["uploadId"].(string) part1Rec := doRequestRaw(t, h, http.MethodPut, @@ -396,7 +397,7 @@ func TestReadSetMetadata_FilesField_MultipartUpload(t *testing.T) { // "readSetId" -- the files sub-object only ever appears on // GetReadSetMetadata, so fetch it there. var completeResp map[string]any - require.NoError(t, json.Unmarshal(completeRec.Body.Bytes(), &completeResp)) + require.NoError(t, json.Unmarshal(completeRec.Body.Bytes(), &completeResp, jsonx.V1())) readSetID, ok := completeResp["readSetId"].(string) require.True(t, ok, "readSetId must be present") require.NotEmpty(t, readSetID) @@ -408,7 +409,7 @@ func TestReadSetMetadata_FilesField_MultipartUpload(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var rs map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &rs)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &rs, jsonx.V1())) files, ok := rs["files"].(map[string]any) require.True(t, ok, "files sub-object must be present") @@ -476,7 +477,7 @@ func TestUploadReadSetPart_BodyReadError_InternalServerException(t *testing.T) { require.Equal(t, http.StatusInternalServerError, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InternalServerException", resp["__type"]) }) } diff --git a/services/omics/handler_readjson_test.go b/services/omics/handler_readjson_test.go index 138e1727d2..d13e3fad6c 100644 --- a/services/omics/handler_readjson_test.go +++ b/services/omics/handler_readjson_test.go @@ -2,7 +2,8 @@ package omics_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +12,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestReadJSONMalformedWritesExactlyOneDocument guards against the same @@ -32,14 +35,14 @@ func TestReadJSONMalformedWritesExactlyOneDocument(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) - dec := json.NewDecoder(rec.Body) + dec := jsontext.NewDecoder(rec.Body) var first map[string]any - require.NoError(t, dec.Decode(&first)) + require.NoError(t, json.UnmarshalDecode(dec, &first, jsonx.V1())) require.Contains(t, first, "message") var second map[string]any - err := dec.Decode(&second) + err := json.UnmarshalDecode(dec, &second, jsonx.V1()) require.ErrorIs( t, err, diff --git a/services/omics/handler_reference_stores_test.go b/services/omics/handler_reference_stores_test.go index 1f94d9367e..30de0ab053 100644 --- a/services/omics/handler_reference_stores_test.go +++ b/services/omics/handler_reference_stores_test.go @@ -1,7 +1,7 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -32,7 +33,7 @@ func TestOmics_ReferenceStore(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:omics:") assert.Equal(t, "test-store", resp["name"]) }, @@ -66,7 +67,7 @@ func TestOmics_ReferenceStore(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rec2 := doRequest(t, h, http.MethodGet, "/referencestore/"+resp["id"].(string), nil) assert.Equal(t, http.StatusOK, rec2.Code) @@ -80,7 +81,7 @@ func TestOmics_ReferenceStore(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rec2 := doRequest(t, h, http.MethodDelete, "/referencestore/"+resp["id"].(string), nil) assert.Equal(t, http.StatusOK, rec2.Code) @@ -98,7 +99,7 @@ func TestOmics_ReferenceStore(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores := resp["referenceStores"].([]any) assert.Len(t, stores, 2) }) @@ -144,7 +145,7 @@ func TestOmics_GetReference_Binary(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return fmt.Sprintf("/referencestore/%s/reference/doesnotexist", resp["id"]) }, @@ -157,7 +158,7 @@ func TestOmics_GetReference_Binary(t *testing.T) { rec := doRequest(t, h, http.MethodPost, "/referencestore", map[string]any{"name": "s"}) require.Equal(t, http.StatusCreated, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["id"].(string) rec2 := doRequest(t, h, http.MethodPost, @@ -176,7 +177,7 @@ func TestOmics_GetReference_Binary(t *testing.T) { ) require.Equal(t, http.StatusOK, rec3.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &listResp, jsonx.V1())) refs := listResp["references"].([]any) require.Len(t, refs, 1) refID := refs[0].(map[string]any)["id"].(string) @@ -210,14 +211,14 @@ func TestDeleteReferenceStoreReturnsID(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) storeID := createResp["id"].(string) delRec := doRequest(t, h, http.MethodDelete, "/referencestore/"+storeID, nil) require.Equal(t, http.StatusOK, delRec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp, jsonx.V1())) assert.Equal(t, storeID, delResp["id"]) } @@ -233,7 +234,7 @@ func TestListReferenceImportJobs_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+storeID+"/importjob", map[string]any{ @@ -247,7 +248,7 @@ func TestListReferenceImportJobs_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs, ok := resp["importJobs"].([]any) require.True(t, ok) assert.Empty(t, jobs, "no import job has failed") @@ -257,7 +258,7 @@ func TestListReferenceImportJobs_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) jobs2, ok := resp2["importJobs"].([]any) require.True(t, ok) assert.Len(t, jobs2, 1) @@ -274,7 +275,7 @@ func TestGetReferenceMetadata_FilesField(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+storeID+"/importjob", map[string]any{ @@ -287,7 +288,7 @@ func TestGetReferenceMetadata_FilesField(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) refs, ok := listResp["references"].([]any) require.True(t, ok) require.Len(t, refs, 1) @@ -300,7 +301,7 @@ func TestGetReferenceMetadata_FilesField(t *testing.T) { require.Equal(t, http.StatusOK, metaRec.Code) var meta map[string]any - require.NoError(t, json.Unmarshal(metaRec.Body.Bytes(), &meta)) + require.NoError(t, json.Unmarshal(metaRec.Body.Bytes(), &meta, jsonx.V1())) files, ok := meta["files"].(map[string]any) require.True(t, ok, "files sub-object must be present") source, ok := files["source"].(map[string]any) diff --git a/services/omics/handler_runs_test.go b/services/omics/handler_runs_test.go index 733fcd424f..074f90c72b 100644 --- a/services/omics/handler_runs_test.go +++ b/services/omics/handler_runs_test.go @@ -1,13 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -31,7 +32,7 @@ func TestOmics_RunGroup(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:omics:") }, }, @@ -43,7 +44,7 @@ func TestOmics_RunGroup(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["items"]) }, }, @@ -100,7 +101,7 @@ func TestOmics_Run(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:omics:") }, }, @@ -153,7 +154,7 @@ func TestRunStartsAsPending(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PENDING", resp["status"]) } @@ -171,7 +172,7 @@ func TestStartRunReturnsPartialResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["arn"]) assert.NotEmpty(t, resp["id"]) assert.Equal(t, "PENDING", resp["status"]) @@ -192,7 +193,7 @@ func TestUpdateRunCachePersistsDescription(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cacheID := createResp["id"].(string) updateRec := doRequest(t, h, http.MethodPost, "/runCache/"+cacheID, map[string]any{ @@ -204,7 +205,7 @@ func TestUpdateRunCachePersistsDescription(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "updated description", getResp["description"]) } @@ -222,7 +223,7 @@ func TestListRunsInBatchReturnsAssociatedRuns(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp, jsonx.V1())) batchID := batchResp["id"].(string) // Start a second run explicitly associated with this batch via the @@ -242,7 +243,7 @@ func TestListRunsInBatchReturnsAssociatedRuns(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) runs, ok := listResp["runs"].([]any) require.True(t, ok) assert.Len(t, runs, 2) @@ -265,11 +266,11 @@ func TestListRunsInBatchEmptyForOtherBatch(t *testing.T) { require.Equal(t, http.StatusCreated, batch2Rec.Code) var b1 map[string]any - require.NoError(t, json.Unmarshal(batch1Rec.Body.Bytes(), &b1)) + require.NoError(t, json.Unmarshal(batch1Rec.Body.Bytes(), &b1, jsonx.V1())) batchID1 := b1["id"].(string) var b2 map[string]any - require.NoError(t, json.Unmarshal(batch2Rec.Body.Bytes(), &b2)) + require.NoError(t, json.Unmarshal(batch2Rec.Body.Bytes(), &b2, jsonx.V1())) batchID2 := b2["id"].(string) // Associate a run with batch 1. @@ -286,7 +287,7 @@ func TestListRunsInBatchEmptyForOtherBatch(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) runs, ok := listResp["runs"].([]any) require.True(t, ok) assert.Len(t, runs, 1) @@ -317,7 +318,7 @@ func TestCancelRunGuardsTerminalState(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) runID := startResp["id"].(string) // Cancel once. @@ -349,7 +350,7 @@ func TestStartRun_ResponseIncludesOptionalFields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["uuid"], "StartRunOutput.uuid must be populated") assert.Equal(t, "VPC", resp["networkingMode"]) assert.Equal(t, "s3://bucket/output", resp["runOutputUri"]) @@ -367,7 +368,7 @@ func TestRun_BatchIDSerializedAsBatchIdKey(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) runRec := doRequest(t, h, http.MethodPost, "/run", map[string]any{ @@ -379,14 +380,14 @@ func TestRun_BatchIDSerializedAsBatchIdKey(t *testing.T) { require.Equal(t, http.StatusCreated, runRec.Code) var run map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run, jsonx.V1())) runID := run["id"].(string) getRec := doRequest(t, h, http.MethodGet, "/run/"+runID, nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, batchID, getResp["batchId"], "real wire key is batchId") assert.Nil(t, getResp["runBatchId"], "runBatchId is not a real wire key") } @@ -412,7 +413,7 @@ func TestListRuns_FiltersByNameRunGroupBatchStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) runs, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, runs, 1) @@ -422,7 +423,7 @@ func TestListRuns_FiltersByNameRunGroupBatchStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) runs2, ok := resp2["items"].([]any) require.True(t, ok) require.Len(t, runs2, 1) @@ -432,7 +433,7 @@ func TestListRuns_FiltersByNameRunGroupBatchStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) runs3, ok := resp3["items"].([]any) require.True(t, ok) assert.Empty(t, runs3, "no run has been cancelled yet") @@ -450,7 +451,7 @@ func TestListRunTasks_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusCreated, runRec.Code) var run map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run, jsonx.V1())) runID := run["id"].(string) // The auto-created task starts PENDING; filtering for RUNNING must exclude it. @@ -458,7 +459,7 @@ func TestListRunTasks_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tasks, ok := resp["items"].([]any) require.True(t, ok) assert.Empty(t, tasks) @@ -467,7 +468,7 @@ func TestListRunTasks_FiltersByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) tasks2, ok := resp2["items"].([]any) require.True(t, ok) assert.Len(t, tasks2, 1) @@ -486,7 +487,7 @@ func TestListRunGroups_FiltersByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, groups, 1) @@ -508,7 +509,7 @@ func TestListRunBatches_FiltersByNameAndStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) batches, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, batches, 1) @@ -520,7 +521,7 @@ func TestListRunBatches_FiltersByNameAndStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) batches2, ok := resp2["items"].([]any) require.True(t, ok) assert.Len(t, batches2, 2) @@ -537,7 +538,7 @@ func TestListRunsInBatch_FiltersByRunID(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) runRec := doRequest(t, h, http.MethodPost, "/run", map[string]any{ @@ -547,14 +548,14 @@ func TestListRunsInBatch_FiltersByRunID(t *testing.T) { require.Equal(t, http.StatusCreated, runRec.Code) var run map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run, jsonx.V1())) runID := run["id"].(string) rec := doRequest(t, h, http.MethodGet, "/runBatch/"+batchID+"/run?runId=does-not-exist", nil) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) runs, ok := resp["runs"].([]any) require.True(t, ok) assert.Empty(t, runs, "runId filter must exclude non-matching runs") @@ -563,7 +564,7 @@ func TestListRunsInBatch_FiltersByRunID(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) runs2, ok := resp2["runs"].([]any) require.True(t, ok) require.Len(t, runs2, 1) @@ -587,7 +588,7 @@ func TestDeleteBatch_RequiresTerminalState(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) omics.SetRunBatchStatusForTest(backend, batchID, "SUBMITTING") diff --git a/services/omics/handler_sequence_stores_test.go b/services/omics/handler_sequence_stores_test.go index ba22dcc24c..cd1fcceee6 100644 --- a/services/omics/handler_sequence_stores_test.go +++ b/services/omics/handler_sequence_stores_test.go @@ -1,12 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOmics_SequenceStore(t *testing.T) { @@ -29,7 +31,7 @@ func TestOmics_SequenceStore(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:omics:") assert.Equal(t, "seq-store", resp["name"]) }, @@ -55,7 +57,7 @@ func TestOmics_SequenceStore(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) stores := resp["sequenceStores"].([]any) assert.Empty(t, stores) }, @@ -89,7 +91,7 @@ func TestSequenceStoreHasStatusAndUpdateTime(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, "ACTIVE", created["status"]) id, ok := created["id"].(string) @@ -99,7 +101,7 @@ func TestSequenceStoreHasStatusAndUpdateTime(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACTIVE", resp["status"]) assert.NotEmpty(t, resp["updateTime"]) } @@ -122,7 +124,7 @@ func TestCreateSequenceStoreETagAlgorithmAndS3AccessConfig(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SHA256up", resp["eTagAlgorithmFamily"]) assert.NotContains(t, resp, "eTagAlgorithm") @@ -143,13 +145,13 @@ func TestDeleteSequenceStoreReturnsID(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) storeID := createResp["id"].(string) delRec := doRequest(t, h, http.MethodDelete, "/sequencestore/"+storeID, nil) require.Equal(t, http.StatusOK, delRec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp, jsonx.V1())) assert.Equal(t, storeID, delResp["id"]) } diff --git a/services/omics/handler_shares_test.go b/services/omics/handler_shares_test.go index 4c8b50ba37..3d03699125 100644 --- a/services/omics/handler_shares_test.go +++ b/services/omics/handler_shares_test.go @@ -1,7 +1,7 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -78,7 +79,7 @@ func createShare(t *testing.T, h *omics.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, _ := resp["shareId"].(string) @@ -158,7 +159,7 @@ func TestOmics_Share_ResponseShape(t *testing.T) { require.Less(t, rec.Code, http.StatusBadRequest) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) keys := make([]string, 0, len(resp)) for k := range resp { @@ -183,7 +184,7 @@ func TestOmics_GetShare_FullObjectFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) share, ok := resp["share"].(map[string]any) require.True(t, ok) @@ -265,7 +266,7 @@ func createSharePair(t *testing.T, h *omics.Handler) map[string]string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids[key], _ = resp["shareId"].(string) } @@ -355,7 +356,7 @@ func TestListShares_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) var want []string if tc.wantKey != "" { diff --git a/services/omics/handler_tags_test.go b/services/omics/handler_tags_test.go index a17493f3ba..45bb68244f 100644 --- a/services/omics/handler_tags_test.go +++ b/services/omics/handler_tags_test.go @@ -1,7 +1,7 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOmics_Tags(t *testing.T) { @@ -21,7 +23,7 @@ func TestOmics_Tags(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var wfResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &wfResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &wfResp, jsonx.V1())) wfARN := wfResp["arn"].(string) // TagResource @@ -33,7 +35,7 @@ func TestOmics_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["tags"].(map[string]any) assert.Equal(t, "test", tags["env"]) } diff --git a/services/omics/handler_test.go b/services/omics/handler_test.go index f63508583f..dda411a38d 100644 --- a/services/omics/handler_test.go +++ b/services/omics/handler_test.go @@ -2,13 +2,14 @@ package omics_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http/httptest" "testing" "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -48,7 +49,7 @@ func doRequest(t *testing.T, h *omics.Handler, method, path string, body any) *h if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/omics/handler_variant_stores_test.go b/services/omics/handler_variant_stores_test.go index 9bfee1679d..27b8409fe9 100644 --- a/services/omics/handler_variant_stores_test.go +++ b/services/omics/handler_variant_stores_test.go @@ -1,13 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -31,7 +32,7 @@ func TestOmics_VariantStore(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "var-store", resp["name"]) assert.NotEmpty(t, resp["id"]) assert.NotContains(t, resp, "storeArn") @@ -82,7 +83,7 @@ func TestCreateVariantStoreStoresReference(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["reference"]) assert.Equal(t, "CREATING", resp["status"]) } @@ -106,7 +107,7 @@ func TestListVariantImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusCreated, jobRec.Code) var job map[string]any - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &job)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &job, jsonx.V1())) jobID := job["jobId"].(string) rec := doRequest(t, h, http.MethodPost, "/import/variants", @@ -114,7 +115,7 @@ func TestListVariantImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs, ok := resp["variantImportJobs"].([]any) require.True(t, ok) assert.Empty(t, jobs) @@ -123,7 +124,7 @@ func TestListVariantImportJobs_FiltersByStatusStoreNameAndIds(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) jobs2, ok := resp2["variantImportJobs"].([]any) require.True(t, ok) require.Len(t, jobs2, 1) @@ -142,7 +143,7 @@ func createVariantStorePair(t *testing.T, h *omics.Handler) map[string]string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids[name], _ = resp["id"].(string) } @@ -231,7 +232,7 @@ func TestListVariantStores_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.ElementsMatch(t, tc.wantNames, variantStoreNames(t, resp["variantStores"])) }) } diff --git a/services/omics/handler_workflows_test.go b/services/omics/handler_workflows_test.go index 315ed6ac10..838abd5f4b 100644 --- a/services/omics/handler_workflows_test.go +++ b/services/omics/handler_workflows_test.go @@ -1,12 +1,14 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOmics_Workflow(t *testing.T) { @@ -29,7 +31,7 @@ func TestOmics_Workflow(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["arn"], "arn:aws:omics:") assert.NotEmpty(t, resp["id"]) assert.Equal(t, "CREATING", resp["status"]) @@ -50,7 +52,7 @@ func TestOmics_Workflow(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["items"]) }, }, @@ -90,7 +92,7 @@ func TestWorkflowStartsAsCreating(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CREATING", resp["status"]) } @@ -107,7 +109,7 @@ func TestCreateWorkflowReturnsPartialResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["arn"]) assert.NotEmpty(t, resp["id"]) assert.Nil(t, resp["name"], "full workflow object must not be returned") @@ -127,14 +129,14 @@ func TestWorkflowHasTypeField(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) wfID := createResp["id"].(string) getRec := doRequest(t, h, http.MethodGet, "/workflow/"+wfID, nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "PRIVATE", getResp["type"]) } @@ -151,7 +153,7 @@ func TestUpdateWorkflowReturnsWorkflow(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) wfID := createResp["id"].(string) updateRec := doRequest(t, h, http.MethodPost, "/workflow/"+wfID, map[string]any{ @@ -161,7 +163,7 @@ func TestUpdateWorkflowReturnsWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated-name", updateResp["name"]) assert.Equal(t, "new description", updateResp["description"]) } @@ -191,7 +193,7 @@ func TestCreateWorkflow_ResponseIncludesUUID(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["uuid"], "CreateWorkflowOutput.uuid must be populated") } @@ -208,7 +210,7 @@ func TestListWorkflows_FiltersByNameAndType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) workflows, ok := resp["items"].([]any) require.True(t, ok) require.Len(t, workflows, 1) @@ -220,7 +222,7 @@ func TestListWorkflows_FiltersByNameAndType(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) workflows2, ok := resp2["items"].([]any) require.True(t, ok) assert.Empty(t, workflows2) @@ -237,7 +239,7 @@ func TestListWorkflowVersions_FiltersByType(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) wfID := wf["id"].(string) verRec := doRequest(t, h, http.MethodPost, "/workflow/"+wfID+"/version", map[string]any{"versionName": "v1"}) @@ -249,7 +251,7 @@ func TestListWorkflowVersions_FiltersByType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["items"].([]any) require.True(t, ok) assert.Empty(t, versions) @@ -258,7 +260,7 @@ func TestListWorkflowVersions_FiltersByType(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) versions2, ok := resp2["items"].([]any) require.True(t, ok) assert.Len(t, versions2, 1) diff --git a/services/omics/lifecycle_poll_test.go b/services/omics/lifecycle_poll_test.go index d8bf3b0b1f..3d38213b66 100644 --- a/services/omics/lifecycle_poll_test.go +++ b/services/omics/lifecycle_poll_test.go @@ -11,12 +11,14 @@ package omics_test // way real AWS eventually does. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func Test_GetWorkflow_AdvancesCreatingToActiveOnPoll(t *testing.T) { @@ -30,7 +32,7 @@ func Test_GetWorkflow_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) id := created["id"].(string) require.Equal(t, "CREATING", created["status"]) @@ -38,7 +40,7 @@ func Test_GetWorkflow_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "ACTIVE", got["status"], "waiter clients poll GetWorkflow until Status==ACTIVE") } @@ -53,14 +55,14 @@ func Test_GetAnnotationStore_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) require.Equal(t, "CREATING", created["status"]) getRec := doRequest(t, h, http.MethodGet, "/annotationStore/my-store", nil) require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "ACTIVE", got["status"]) } @@ -74,14 +76,14 @@ func Test_GetVariantStore_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) require.Equal(t, "CREATING", created["status"]) getRec := doRequest(t, h, http.MethodGet, "/variantStore/my-vstore", nil) require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "ACTIVE", got["status"]) } @@ -96,7 +98,7 @@ func Test_GetWorkflowVersion_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) workflowID := wf["id"].(string) verRec := doRequest(t, h, http.MethodPost, "/workflow/"+workflowID+"/version", map[string]any{ @@ -105,14 +107,14 @@ func Test_GetWorkflowVersion_AdvancesCreatingToActiveOnPoll(t *testing.T) { require.Equal(t, http.StatusCreated, verRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &created, jsonx.V1())) require.Equal(t, "CREATING", created["status"]) getRec := doRequest(t, h, http.MethodGet, "/workflow/"+workflowID+"/version/v1", nil) require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "ACTIVE", got["status"]) } @@ -131,7 +133,7 @@ func Test_GetRun_AdvancesPendingToRunningToCompletedAcrossPolls(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var started map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started, jsonx.V1())) id := started["id"].(string) require.Equal(t, "PENDING", started["status"]) @@ -139,7 +141,7 @@ func Test_GetRun_AdvancesPendingToRunningToCompletedAcrossPolls(t *testing.T) { require.Equal(t, http.StatusOK, poll1.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(poll1.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(poll1.Body.Bytes(), &p1, jsonx.V1())) assert.Equal(t, "RUNNING", p1["status"], "RunRunningWaiter polls until Status==RUNNING") assert.NotEmpty(t, p1["startTime"]) @@ -147,7 +149,7 @@ func Test_GetRun_AdvancesPendingToRunningToCompletedAcrossPolls(t *testing.T) { require.Equal(t, http.StatusOK, poll2.Code) var p2 map[string]any - require.NoError(t, json.Unmarshal(poll2.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(poll2.Body.Bytes(), &p2, jsonx.V1())) assert.Equal(t, "COMPLETED", p2["status"], "RunCompletedWaiter polls until Status==COMPLETED") assert.NotEmpty(t, p2["stopTime"]) } @@ -167,14 +169,14 @@ func Test_GetRunTask_AdvancesPendingToRunningToCompletedAcrossPolls(t *testing.T require.Equal(t, http.StatusCreated, startRec.Code) var started map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started, jsonx.V1())) runID := started["id"].(string) tasksRec := doRequest(t, h, http.MethodGet, "/run/"+runID+"/task", nil) require.Equal(t, http.StatusOK, tasksRec.Code) var tasksResp map[string]any - require.NoError(t, json.Unmarshal(tasksRec.Body.Bytes(), &tasksResp)) + require.NoError(t, json.Unmarshal(tasksRec.Body.Bytes(), &tasksResp, jsonx.V1())) tasks := tasksResp["items"].([]any) require.Len(t, tasks, 1) taskID := tasks[0].(map[string]any)["taskId"].(string) @@ -183,14 +185,14 @@ func Test_GetRunTask_AdvancesPendingToRunningToCompletedAcrossPolls(t *testing.T require.Equal(t, http.StatusOK, poll1.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(poll1.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(poll1.Body.Bytes(), &p1, jsonx.V1())) assert.Equal(t, "RUNNING", p1["status"]) poll2 := doRequest(t, h, http.MethodGet, "/run/"+runID+"/task/"+taskID, nil) require.Equal(t, http.StatusOK, poll2.Code) var p2 map[string]any - require.NoError(t, json.Unmarshal(poll2.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(poll2.Body.Bytes(), &p2, jsonx.V1())) assert.Equal(t, "COMPLETED", p2["status"]) } @@ -209,7 +211,7 @@ func Test_CancelRun_TerminalStateIsNotAdvancedByFurtherPolls(t *testing.T) { require.Equal(t, http.StatusCreated, startRec.Code) var started map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &started, jsonx.V1())) id := started["id"].(string) cancelRec := doRequest(t, h, http.MethodPost, "/run/"+id+"/cancel", nil) @@ -220,7 +222,7 @@ func Test_CancelRun_TerminalStateIsNotAdvancedByFurtherPolls(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "CANCELLED", got["status"]) } } diff --git a/services/omics/list_summary_shapes_test.go b/services/omics/list_summary_shapes_test.go index 2bc2f2afeb..42f90e7ed8 100644 --- a/services/omics/list_summary_shapes_test.go +++ b/services/omics/list_summary_shapes_test.go @@ -2,7 +2,8 @@ package omics_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +13,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListSummaries_MemberRoundTrips drives each op's Create/Start then List @@ -166,7 +169,7 @@ func TestListReadSetUploadParts_RawBodyUsesPartSourceKey(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) uploadRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/upload", map[string]any{ @@ -178,7 +181,7 @@ func TestListReadSetUploadParts_RawBodyUsesPartSourceKey(t *testing.T) { require.Equal(t, http.StatusCreated, uploadRec.Code) var upload map[string]any - require.NoError(t, json.Unmarshal(uploadRec.Body.Bytes(), &upload)) + require.NoError(t, json.Unmarshal(uploadRec.Body.Bytes(), &upload, jsonx.V1())) uploadID := upload["uploadId"].(string) partRec := doRequest( @@ -198,7 +201,7 @@ func TestListReadSetUploadParts_RawBodyUsesPartSourceKey(t *testing.T) { var listResp struct { Parts []map[string]any `json:"parts"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Parts, 1) assert.Equal(t, "SOURCE1", listResp.Parts[0]["partSource"]) @@ -244,7 +247,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/activationjob", map[string]any{ @@ -269,7 +272,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/importjob", map[string]any{ @@ -295,7 +298,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/sequencestore/"+storeID+"/importjob", map[string]any{ @@ -321,7 +324,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+storeID+"/importjob", map[string]any{ @@ -347,7 +350,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, storeRec.Code) var store map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &store, jsonx.V1())) storeID := store["id"].(string) jobRec := doRequest(t, h, http.MethodPost, "/referencestore/"+storeID+"/importjob", map[string]any{ @@ -413,7 +416,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) wfID := wf["id"].(string) runRec := doRequest(t, h, http.MethodPost, "/run", map[string]any{ @@ -425,7 +428,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, runRec.Code) var run map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run, jsonx.V1())) runID := run["id"].(string) listRec := doRequest(t, h, http.MethodGet, "/run/"+runID+"/task", nil) @@ -445,7 +448,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) wfID := wf["id"].(string) runRec := doRequest(t, h, http.MethodPost, "/run", map[string]any{ @@ -478,7 +481,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) wfID := wf["id"].(string) batchRec := doRequest(t, h, http.MethodPost, "/runBatch", map[string]any{ @@ -495,7 +498,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) listRec := doRequest(t, h, http.MethodGet, "/runBatch/"+batchID+"/run", nil) @@ -543,7 +546,7 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { require.Equal(t, http.StatusCreated, wfRec.Code) var wf map[string]any - require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf)) + require.NoError(t, json.Unmarshal(wfRec.Body.Bytes(), &wf, jsonx.V1())) wfID := wf["id"].(string) verRec := doRequest(t, h, http.MethodPost, "/workflow/"+wfID+"/version", map[string]any{ @@ -566,14 +569,14 @@ func TestListSummaries_OmitDescribeOnlyFields(t *testing.T) { func listItems(t *testing.T, body []byte, key string) []map[string]any { t.Helper() - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(body, &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) raw, ok := resp[key] require.True(t, ok, "response missing key %q", key) var items []map[string]any - require.NoError(t, json.Unmarshal(raw, &items)) + require.NoError(t, json.Unmarshal(raw, &items, jsonx.V1())) return items } diff --git a/services/omics/multi_region_test.go b/services/omics/multi_region_test.go index 160187145f..dad3847770 100644 --- a/services/omics/multi_region_test.go +++ b/services/omics/multi_region_test.go @@ -2,7 +2,8 @@ package omics_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -172,8 +174,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/omics/pagination_query_params_test.go b/services/omics/pagination_query_params_test.go index 3e37de9490..c36d89d4ac 100644 --- a/services/omics/pagination_query_params_test.go +++ b/services/omics/pagination_query_params_test.go @@ -18,12 +18,14 @@ package omics_test // "maxResults" as the query key; that is covered separately below. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func Test_ListReferenceStores_PaginatesViaQueryString(t *testing.T) { @@ -46,7 +48,7 @@ func Test_ListReferenceStores_PaginatesViaQueryString(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores := resp["referenceStores"].([]any) assert.Len(t, stores, 2, "maxResults=2 from the query string must be honored") require.NotEmpty(t, resp["nextToken"], "a nextToken must be returned when more pages remain") @@ -59,7 +61,7 @@ func Test_ListReferenceStores_PaginatesViaQueryString(t *testing.T) { require.Equal(t, http.StatusOK, nextRec.Code) var nextResp map[string]any - require.NoError(t, json.Unmarshal(nextRec.Body.Bytes(), &nextResp)) + require.NoError(t, json.Unmarshal(nextRec.Body.Bytes(), &nextResp, jsonx.V1())) remaining := nextResp["referenceStores"].([]any) assert.Len(t, remaining, 1, "nextToken from the query string must resume from page two") } @@ -81,7 +83,7 @@ func Test_ListAnnotationStores_PaginatesViaQueryString(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores := resp["annotationStores"].([]any) assert.Len(t, stores, 2) require.NotEmpty(t, resp["nextToken"]) @@ -104,13 +106,13 @@ func Test_ListRunBatches_UsesMaxItemsNotMaxResultsQueryParam(t *testing.T) { require.Equal(t, http.StatusOK, ignoredRec.Code) var ignoredResp map[string]any - require.NoError(t, json.Unmarshal(ignoredRec.Body.Bytes(), &ignoredResp)) + require.NoError(t, json.Unmarshal(ignoredRec.Body.Bytes(), &ignoredResp, jsonx.V1())) assert.Len(t, ignoredResp["items"].([]any), 3, "maxResults must not cap ListBatch") limitedRec := doRequest(t, h, http.MethodGet, "/runBatch?maxItems=1", nil) require.Equal(t, http.StatusOK, limitedRec.Code) var limitedResp map[string]any - require.NoError(t, json.Unmarshal(limitedRec.Body.Bytes(), &limitedResp)) + require.NoError(t, json.Unmarshal(limitedRec.Body.Bytes(), &limitedResp, jsonx.V1())) assert.Len(t, limitedResp["items"].([]any), 1, "maxItems must cap ListBatch") } diff --git a/services/omics/persistence.go b/services/omics/persistence.go index 4ea867662e..3ce9b72b5e 100644 --- a/services/omics/persistence.go +++ b/services/omics/persistence.go @@ -2,7 +2,7 @@ package omics import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -40,7 +40,7 @@ const omicsSnapshotVersion = 2 // restored directly. The five left-raw maps (see the InMemoryBackend doc // comment in store.go) are persisted as plain fields alongside Tables. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` UploadParts map[string]map[string][]*ReadSetUploadPart `json:"uploadParts"` UploadPartData map[string]map[string]map[string]map[int][]byte `json:"uploadPartData"` ReadSetBytes map[string]map[string][]byte `json:"readSetBytes"` diff --git a/services/omics/run_options_test.go b/services/omics/run_options_test.go index 3d4181be6f..8b49ec326d 100644 --- a/services/omics/run_options_test.go +++ b/services/omics/run_options_test.go @@ -1,20 +1,22 @@ package omics_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func decodeBody(t *testing.T, body []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1())) return m } diff --git a/services/omics/runbatch_route_test.go b/services/omics/runbatch_route_test.go index 53c9700d6c..8bcd8f6683 100644 --- a/services/omics/runbatch_route_test.go +++ b/services/omics/runbatch_route_test.go @@ -15,7 +15,7 @@ package omics_test // batch *records* — the reverse of what those two real operations do. import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -23,6 +23,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Test_ListRunsInBatch_ReachableOnlyViaGET proves the real AWS wire shape @@ -37,14 +39,14 @@ func Test_ListRunsInBatch_ReachableOnlyViaGET(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) getRec := doRequest(t, h, http.MethodGet, "/runBatch/"+batchID+"/run", nil) assert.Equal(t, http.StatusOK, getRec.Code, "real ListRunsInBatch is GET") var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotNil(t, getResp["runs"], "GET must be classified as ListRunsInBatch") e := echo.New() @@ -68,7 +70,7 @@ func Test_DeleteBatch_DeletesBatchResourceViaURIID(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) delRec := doRequest(t, h, http.MethodDelete, "/runBatch/"+batchID, nil) @@ -92,7 +94,7 @@ func Test_DeleteRunBatch_DeletesOnlyRunsLeavesBatchIntact(t *testing.T) { require.Equal(t, http.StatusCreated, batchRec.Code) var batch map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batch, jsonx.V1())) batchID := batch["id"].(string) runRec := doRequest(t, h, http.MethodPost, "/run", map[string]any{ @@ -104,7 +106,7 @@ func Test_DeleteRunBatch_DeletesOnlyRunsLeavesBatchIntact(t *testing.T) { require.Equal(t, http.StatusCreated, runRec.Code) var run map[string]any - require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run)) + require.NoError(t, json.Unmarshal(runRec.Body.Bytes(), &run, jsonx.V1())) runID := run["id"].(string) delRec := doRequest(t, h, http.MethodPost, "/runBatch/delete", map[string]any{ @@ -113,7 +115,7 @@ func Test_DeleteRunBatch_DeletesOnlyRunsLeavesBatchIntact(t *testing.T) { require.Equal(t, http.StatusOK, delRec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp, jsonx.V1())) assert.Empty(t, delResp, "real DeleteRunBatchOutput is empty — no errors array") getBatchRec := doRequest(t, h, http.MethodGet, "/runBatch/"+batchID, nil) diff --git a/services/omics/s3_source.go b/services/omics/s3_source.go index c6f4fdc5fe..3b5a3139a0 100644 --- a/services/omics/s3_source.go +++ b/services/omics/s3_source.go @@ -2,10 +2,12 @@ package omics import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -78,7 +80,7 @@ func (h *Handler) registryMapFromURI(ctx context.Context, m map[string]any, uri } var out map[string]any - if err = json.Unmarshal(data, &out); err != nil || out == nil { + if err = json.Unmarshal(data, &out, jsonx.V1()); err != nil || out == nil { return nil, fmt.Errorf("%w: containerRegistryMapUri must contain a JSON object", ErrValidation) } @@ -92,7 +94,7 @@ func (h *Handler) inlineSettingsFromURI(ctx context.Context, uri string) ([]inli } var out []inlineRunSettingWire - if err = json.Unmarshal(data, &out); err != nil { + if err = json.Unmarshal(data, &out, jsonx.V1()); err != nil { return nil, fmt.Errorf( "%w: batchRunSettings.s3UriSettings must contain a JSON array of run settings", ErrValidation, diff --git a/services/omics/wire_field_additions_test.go b/services/omics/wire_field_additions_test.go index e541cb2311..9799aa07fd 100644 --- a/services/omics/wire_field_additions_test.go +++ b/services/omics/wire_field_additions_test.go @@ -2,7 +2,7 @@ package omics_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/omics" ) @@ -578,7 +579,7 @@ func TestListAnnotationImportJobs_OmitsGetOnlyFields(t *testing.T) { var resp struct { ImportJobs []map[string]any `json:"annotationImportJobs"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ImportJobs, 1) job := resp.ImportJobs[0] @@ -626,7 +627,7 @@ func TestListVariantImportJobs_OmitsGetOnlyFields(t *testing.T) { var resp struct { ImportJobs []map[string]any `json:"variantImportJobs"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ImportJobs, 1) job := resp.ImportJobs[0] @@ -682,7 +683,7 @@ func TestOmicsStoreLists_OmitGetOnlyFields(t *testing.T) { var resp struct { Stores []map[string]any `json:"annotationStores"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Stores, 1) return resp.Stores[0] @@ -708,7 +709,7 @@ func TestOmicsStoreLists_OmitGetOnlyFields(t *testing.T) { var resp struct { Stores []map[string]any `json:"variantStores"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Stores, 1) return resp.Stores[0] @@ -737,7 +738,7 @@ func TestOmicsStoreLists_OmitGetOnlyFields(t *testing.T) { var resp struct { Versions []map[string]any `json:"annotationStoreVersions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Versions, 1) return resp.Versions[0] diff --git a/services/opensearch/access_policy.go b/services/opensearch/access_policy.go index f714881411..da063e14eb 100644 --- a/services/opensearch/access_policy.go +++ b/services/opensearch/access_policy.go @@ -1,9 +1,10 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" ) @@ -28,7 +29,7 @@ func accessPolicyDenies(accessPolicies, action, resourceARN string) bool { } var pd iam.PolicyDocument - if err := json.Unmarshal([]byte(accessPolicies), &pd); err != nil { + if err := json.Unmarshal([]byte(accessPolicies), &pd, jsonx.V1()); err != nil { return false } diff --git a/services/opensearch/bulk_test.go b/services/opensearch/bulk_test.go index 4ec6401b32..99503156e5 100644 --- a/services/opensearch/bulk_test.go +++ b/services/opensearch/bulk_test.go @@ -2,7 +2,7 @@ package opensearch_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -33,7 +34,7 @@ func doBulkRequest(t *testing.T, h *opensearch.Handler, path, contentType, ndjso var out map[string]any if len(raw) > 0 { - require.NoError(t, json.Unmarshal(raw, &out)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1())) } return resp.StatusCode, out diff --git a/services/opensearch/data_sources.go b/services/opensearch/data_sources.go index 18ea2c9aee..8b0db4d17d 100644 --- a/services/opensearch/data_sources.go +++ b/services/opensearch/data_sources.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/arn" @@ -14,7 +14,7 @@ const dataSourceStatusActive = "ACTIVE" // AddDataSource adds a data source to a domain. func (b *InMemoryBackend) AddDataSource( domainName, name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, ) (string, error) { if domainName == "" { return "", fmt.Errorf("%w: DomainName is required", ErrInvalidParameter) @@ -54,7 +54,7 @@ func (b *InMemoryBackend) AddDataSource( // AddDirectQueryDataSource adds a direct-query data source. func (b *InMemoryBackend) AddDirectQueryDataSource( name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, openSearchArns []string, dataSourceAccessPolicy ...string, ) (string, error) { @@ -132,7 +132,7 @@ func (b *InMemoryBackend) ListDataSources(domainName string) ([]*DataSource, err // Status are optional and left unchanged when omitted. func (b *InMemoryBackend) UpdateDataSource( domainName, name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, status string, ) error { b.mu.Lock("UpdateDataSource") @@ -209,7 +209,7 @@ func (b *InMemoryBackend) GetDirectQueryDataSource(name string) (*DirectQueryDat // and OpenSearchArns on every update call. func (b *InMemoryBackend) UpdateDirectQueryDataSource( name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, openSearchArns []string, dataSourceAccessPolicy string, ) (*DirectQueryDataSource, error) { diff --git a/services/opensearch/documents_handler_test.go b/services/opensearch/documents_handler_test.go index c490890057..699f1579d2 100644 --- a/services/opensearch/documents_handler_test.go +++ b/services/opensearch/documents_handler_test.go @@ -1,7 +1,7 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -23,7 +24,7 @@ func decodeBody(t *testing.T, resp *http.Response) map[string]any { var out map[string]any if len(raw) > 0 { - require.NoError(t, json.Unmarshal(raw, &out)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1())) } return out diff --git a/services/opensearch/domains_test.go b/services/opensearch/domains_test.go index eb6762cecf..bf56474b0e 100644 --- a/services/opensearch/domains_test.go +++ b/services/opensearch/domains_test.go @@ -1,7 +1,7 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -40,7 +40,7 @@ func TestDeleteDomain_Cascade(t *testing.T) { b := opensearch.NewInMemoryBackend(testAccountID, testRegion) b.AddDomainInternal("my-domain", "") - _, err := b.AddDataSource("my-domain", "ds1", "desc", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err := b.AddDataSource("my-domain", "ds1", "desc", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.NoError(t, err) b.AddPackageInternal("pkg-001", "test-pkg", "TXT-DICTIONARY") diff --git a/services/opensearch/handler.go b/services/opensearch/handler.go index ee1c6898f3..1bcaa4922e 100644 --- a/services/opensearch/handler.go +++ b/services/opensearch/handler.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/endpointstrategy" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -504,7 +505,7 @@ func (h *Handler) handleConfigPostRoute(w http.ResponseWriter, r *http.Request, body, _ := httputils.ReadBody(r) var req domainJSON if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if vErr := validateDomainOptions(&req); vErr != nil { @@ -833,7 +834,7 @@ func (h *Handler) dispatchDomainPostRoutesExtended( NodeID string `json:"NodeId"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } m, err := h.Backend.StartDomainMaintenance(domainName, req.Action, req.NodeID) if err != nil { @@ -850,7 +851,7 @@ func (h *Handler) dispatchDomainPostRoutesExtended( Account string `json:"Account"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } _ = h.Backend.RevokeVpcEndpointAccess(domainName, req.Account) w.WriteHeader(http.StatusOK) diff --git a/services/opensearch/handler_advanced.go b/services/opensearch/handler_advanced.go index 104b974477..efccba51a7 100644 --- a/services/opensearch/handler_advanced.go +++ b/services/opensearch/handler_advanced.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +9,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -159,7 +160,7 @@ func (h *Handler) handleUpgradeDomainRoutes(w http.ResponseWriter, r *http.Reque PerformCheckOnly bool `json:"PerformCheckOnly"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } upgradeErr := h.Backend.CheckUpgradeDomain(req.DomainName, req.TargetVersion) diff --git a/services/opensearch/handler_advanced_test.go b/services/opensearch/handler_advanced_test.go index 0546e25ee3..380979aec5 100644 --- a/services/opensearch/handler_advanced_test.go +++ b/services/opensearch/handler_advanced_test.go @@ -1,13 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -75,7 +77,7 @@ func TestOpenSearchHandler_GetCompatibleVersions(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) versions, ok := out["CompatibleVersions"].([]any) require.True(t, ok) @@ -102,7 +104,7 @@ func TestOpenSearchHandler_ListInstanceTypeDetails(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) details, ok := out["InstanceTypeDetails"].([]any) require.True(t, ok) @@ -168,7 +170,7 @@ func TestGetCompatibleVersions(t *testing.T) { } var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) versions, ok := out["CompatibleVersions"].([]any) require.True(t, ok) @@ -198,7 +200,7 @@ func TestListInstanceTypeDetails_InstanceRoleAndSecurity(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) details, ok := out["InstanceTypeDetails"].([]any) require.True(t, ok) @@ -268,7 +270,7 @@ func TestListVersions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) versions, ok := out["Versions"].([]any) require.True(t, ok) @@ -303,7 +305,7 @@ func TestListVersions_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, resp1.StatusCode) var page1 map[string]any - require.NoError(t, json.NewDecoder(resp1.Body).Decode(&page1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp1.Body), &page1, jsonx.V1())) versions1 := page1["Versions"].([]any) assert.Len(t, versions1, 3) @@ -316,7 +318,7 @@ func TestListVersions_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, resp2.StatusCode) var page2 map[string]any - require.NoError(t, json.NewDecoder(resp2.Body).Decode(&page2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp2.Body), &page2, jsonx.V1())) versions2 := page2["Versions"].([]any) assert.NotEmpty(t, versions2) @@ -447,7 +449,7 @@ func TestDescribeInstanceTypeLimits_ResponseFormat(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) limitsByRole, ok := out["LimitsByRole"].(map[string]any) require.True(t, ok, "LimitsByRole must be an object") @@ -517,7 +519,7 @@ func TestUpgradeDomain_HTTPHandler(t *testing.T) { if len(tt.wantFields) > 0 { var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, out, field) } @@ -590,7 +592,7 @@ func TestListInstanceTypeDetails_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) details, ok := out["InstanceTypeDetails"].([]any) require.True(t, ok) diff --git a/services/opensearch/handler_applications.go b/services/opensearch/handler_applications.go index 9ea4e60b5f..f37f08500b 100644 --- a/services/opensearch/handler_applications.go +++ b/services/opensearch/handler_applications.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -9,6 +9,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -150,7 +151,7 @@ func (h *Handler) handleDefaultApplicationSettingRoutes(w http.ResponseWriter, r } if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -215,7 +216,7 @@ func (h *Handler) handleApplicationIDRoutes(w http.ResponseWriter, r *http.Reque DataSources []appDSJSON `json:"DataSources"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } appConfigs := make([]AppConfig, len(req.AppConfigs)) for i, ac := range req.AppConfigs { @@ -289,7 +290,7 @@ func (h *Handler) handleCreateApplication(w http.ResponseWriter, r *http.Request } var req createApplicationRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_applications_test.go b/services/opensearch/handler_applications_test.go index 2d1484def3..7f023ebe13 100644 --- a/services/opensearch/handler_applications_test.go +++ b/services/opensearch/handler_applications_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -133,7 +135,7 @@ func TestApplications_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &out, jsonx.V1())) apps, ok := out["ApplicationSummaries"].([]any) require.True(t, ok) @@ -156,7 +158,7 @@ func TestApplications_GetAndUpdateWireShape(t *testing.T) { cr := doRequest(t, h, http.MethodPost, "/2021-01-01/opensearch/application", map[string]any{"Name": "wire-app"}) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) cr.Body.Close() require.Equal(t, http.StatusOK, cr.StatusCode) @@ -172,7 +174,7 @@ func TestApplications_GetAndUpdateWireShape(t *testing.T) { require.Equal(t, http.StatusOK, gr.StatusCode) var gOut map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&gOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &gOut, jsonx.V1())) assert.Equal(t, "ACTIVE", gOut["status"]) assert.NotEmpty(t, gOut["endpoint"]) assert.NotEmpty(t, gOut["createdAt"]) @@ -185,7 +187,7 @@ func TestApplications_GetAndUpdateWireShape(t *testing.T) { require.Equal(t, http.StatusOK, ur.StatusCode) var uOut map[string]any - require.NoError(t, json.NewDecoder(ur.Body).Decode(&uOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ur.Body), &uOut, jsonx.V1())) assert.NotContains(t, uOut, "status") assert.NotEmpty(t, uOut["createdAt"]) assert.NotEmpty(t, uOut["lastUpdatedAt"]) @@ -281,7 +283,7 @@ func createTestApplication(t *testing.T, h *opensearch.Handler, name string) str require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) id, ok := out["id"].(string) require.True(t, ok) @@ -301,7 +303,7 @@ func domainARN(t *testing.T, h *opensearch.Handler, domainName string) string { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) @@ -340,7 +342,7 @@ func TestDataSourceAttachments_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, ar.StatusCode) var attOut map[string]any - require.NoError(t, json.NewDecoder(ar.Body).Decode(&attOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ar.Body), &attOut, jsonx.V1())) assert.Equal(t, appID, attOut["id"]) assert.Equal(t, arn, attOut["dataSourceArn"]) assert.Equal(t, arn, attOut["arn"]) @@ -356,7 +358,7 @@ func TestDataSourceAttachments_HTTPHandler(t *testing.T) { map[string]any{"dataSourceArn": arn}) defer ar2.Body.Close() var attOut2 map[string]any - require.NoError(t, json.NewDecoder(ar2.Body).Decode(&attOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ar2.Body), &attOut2, jsonx.V1())) assert.Equal(t, attOut["attachmentId"], attOut2["attachmentId"]) lr := doRequest(t, h, http.MethodPost, @@ -365,7 +367,7 @@ func TestDataSourceAttachments_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var listOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &listOut, jsonx.V1())) attachments, ok := listOut["attachments"].([]any) require.True(t, ok) require.Len(t, attachments, 1) @@ -384,7 +386,7 @@ func TestDataSourceAttachments_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var descOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&descOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &descOut, jsonx.V1())) assert.Equal(t, "ATTACHED", descOut["status"]) detR := doRequest(t, h, http.MethodPost, @@ -619,7 +621,7 @@ func TestCapabilities_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, rr.StatusCode) var regOut map[string]any - require.NoError(t, json.NewDecoder(rr.Body).Decode(®Out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rr.Body), ®Out, jsonx.V1())) assert.Equal(t, appID, regOut["applicationId"]) assert.Equal(t, "ai-capability", regOut["capabilityName"]) assert.Equal(t, "active", regOut["status"]) @@ -633,7 +635,7 @@ func TestCapabilities_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, gr.StatusCode) var getOut map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &getOut, jsonx.V1())) assert.Equal(t, "active", getOut["status"]) assert.Equal(t, []any{}, getOut["failures"]) @@ -643,7 +645,7 @@ func TestCapabilities_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var deregOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&deregOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &deregOut, jsonx.V1())) // DeregisterCapabilityOutput always reports "deleting" per its doc, // regardless of this emulator's actual (synchronous) removal. assert.Equal(t, "deleting", deregOut["status"]) @@ -744,7 +746,7 @@ func TestMigrations_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, sr.StatusCode) var startOut map[string]any - require.NoError(t, json.NewDecoder(sr.Body).Decode(&startOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(sr.Body), &startOut, jsonx.V1())) migrationID, ok := startOut["migrationId"].(string) require.True(t, ok) require.NotEmpty(t, migrationID) @@ -757,7 +759,7 @@ func TestMigrations_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, gr.StatusCode) var getOut map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&getOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &getOut, jsonx.V1())) assert.Equal(t, appID, getOut["applicationId"]) assert.Equal(t, "SUCCEEDED", getOut["status"]) // No saved-object store exists to migrate real objects, so counts @@ -774,7 +776,7 @@ func TestMigrations_HTTPHandler(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var listOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &listOut, jsonx.V1())) migrations, ok := listOut["migrations"].([]any) require.True(t, ok) require.Len(t, migrations, 1) @@ -783,7 +785,7 @@ func TestMigrations_HTTPHandler(t *testing.T) { "/2021-01-01/opensearch/app-migrations?applicationId="+appID+"&status=PENDING", nil) defer filteredR.Body.Close() var filteredOut map[string]any - require.NoError(t, json.NewDecoder(filteredR.Body).Decode(&filteredOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(filteredR.Body), &filteredOut, jsonx.V1())) assert.Empty(t, filteredOut["migrations"]) }, }, diff --git a/services/opensearch/handler_bulk.go b/services/opensearch/handler_bulk.go index 7c508df9a4..b3be4e2030 100644 --- a/services/opensearch/handler_bulk.go +++ b/services/opensearch/handler_bulk.go @@ -2,13 +2,15 @@ package opensearch import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // bulkActionMeta is the per-action metadata object documented for every @@ -38,9 +40,9 @@ type bulkActionEnvelope struct { // scripting engine, so a non-empty Script is rejected (see // handleBulkUpdate). type bulkUpdateBody struct { - Doc map[string]any `json:"doc,omitempty"` - Script json.RawMessage `json:"script,omitempty"` - DocAsUpsert bool `json:"doc_as_upsert,omitempty"` + Doc map[string]any `json:"doc,omitempty"` + Script jsontext.Value `json:"script,omitempty"` + DocAsUpsert bool `json:"doc_as_upsert,omitempty"` } // bulkAction is one parsed action line plus its source (nil for "delete"). @@ -48,7 +50,7 @@ type bulkAction struct { Op string Index string ID string - Source json.RawMessage + Source jsontext.Value } const ( @@ -186,7 +188,7 @@ func parseBulkActions(body []byte) ([]bulkAction, error) { for i := 0; i < len(lines); i++ { var env bulkActionEnvelope - if err := json.Unmarshal(lines[i], &env); err != nil { + if err := json.Unmarshal(lines[i], &env, jsonx.V1()); err != nil { return nil, fmt.Errorf("malformed action line %d: %w", i+1, err) } @@ -238,7 +240,7 @@ func (h *Handler) processBulkAction(domainName, defaultIndex string, act bulkAct } } -func (h *Handler) processBulkIndex(domainName, index, id string, source json.RawMessage) (map[string]any, bool) { +func (h *Handler) processBulkIndex(domainName, index, id string, source jsontext.Value) (map[string]any, bool) { doc, err := unmarshalBulkSource(source) if err != nil { return bulkErrorItem(bulkOpIndex, index, id, http.StatusBadRequest, @@ -258,7 +260,7 @@ func (h *Handler) processBulkIndex(domainName, index, id string, source json.Raw return bulkSuccessItem(bulkOpIndex, index, newID, result, meta), false } -func (h *Handler) processBulkCreate(domainName, index, id string, source json.RawMessage) (map[string]any, bool) { +func (h *Handler) processBulkCreate(domainName, index, id string, source jsontext.Value) (map[string]any, bool) { doc, err := unmarshalBulkSource(source) if err != nil { return bulkErrorItem(bulkOpCreate, index, id, http.StatusBadRequest, @@ -273,7 +275,7 @@ func (h *Handler) processBulkCreate(domainName, index, id string, source json.Ra return bulkSuccessItem(bulkOpCreate, index, newID, docResultCreated, meta), false } -func (h *Handler) processBulkUpdate(domainName, index, id string, source json.RawMessage) (map[string]any, bool) { +func (h *Handler) processBulkUpdate(domainName, index, id string, source jsontext.Value) (map[string]any, bool) { if id == "" { return bulkErrorItem(bulkOpUpdate, index, id, http.StatusBadRequest, "illegal_argument_exception", "_id is required for the update action"), true @@ -281,7 +283,7 @@ func (h *Handler) processBulkUpdate(domainName, index, id string, source json.Ra var body bulkUpdateBody if len(source) > 0 { - if err := json.Unmarshal(source, &body); err != nil { + if err := json.Unmarshal(source, &body, jsonx.V1()); err != nil { return bulkErrorItem(bulkOpUpdate, index, id, http.StatusBadRequest, "illegal_argument_exception", "invalid update body"), true } @@ -339,13 +341,13 @@ func (h *Handler) processBulkDelete(domainName, index, id string) (map[string]an // unmarshalBulkSource decodes a bulk action's source line, tolerating an // absent one (an empty document, matching IndexDocument's own handling of a // missing body). -func unmarshalBulkSource(source json.RawMessage) (map[string]any, error) { +func unmarshalBulkSource(source jsontext.Value) (map[string]any, error) { if len(source) == 0 { return map[string]any{}, nil } doc := map[string]any{} - if err := json.Unmarshal(source, &doc); err != nil { + if err := json.Unmarshal(source, &doc, jsonx.V1()); err != nil { return nil, err } diff --git a/services/opensearch/handler_capabilities.go b/services/opensearch/handler_capabilities.go index 5189667b78..5b6d601d7c 100644 --- a/services/opensearch/handler_capabilities.go +++ b/services/opensearch/handler_capabilities.go @@ -1,12 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // capabilityConfigJSON is the wire shape of CapabilityBaseRequestConfig / @@ -71,7 +72,7 @@ func (h *Handler) handleRegisterCapability(w http.ResponseWriter, r *http.Reques var req registerCapabilityRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_data_source_attachments.go b/services/opensearch/handler_data_source_attachments.go index ba671b72fd..6e4b1f1461 100644 --- a/services/opensearch/handler_data_source_attachments.go +++ b/services/opensearch/handler_data_source_attachments.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Sub-path segments for the four data source attachment routes under @@ -104,7 +105,7 @@ func (h *Handler) readDataSourceAttachmentRequest( var req dataSourceAttachmentRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return dataSourceAttachmentRequest{}, false @@ -191,7 +192,7 @@ func (h *Handler) handleListDataSourceAttachments(w http.ResponseWriter, r *http var req listDataSourceAttachmentsRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_data_sources.go b/services/opensearch/handler_data_sources.go index ae193a16fb..32e97115b8 100644 --- a/services/opensearch/handler_data_sources.go +++ b/services/opensearch/handler_data_sources.go @@ -1,12 +1,14 @@ package opensearch import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // directQueryDataSourceJSON renders a DirectQueryDataSource as the wire-shape @@ -15,11 +17,11 @@ import ( // "DataSourceName" -- they are genuinely different field names on the real // API, not a typo. type directQueryDataSourceJSON struct { - DataSourceArn string `json:"DataSourceArn"` - DataSourceName string `json:"DataSourceName"` - DataSourceType json.RawMessage `json:"DataSourceType,omitempty"` - Description string `json:"Description,omitempty"` - OpenSearchArns []string `json:"OpenSearchArns"` + DataSourceArn string `json:"DataSourceArn"` + DataSourceName string `json:"DataSourceName"` + DataSourceType jsontext.Value `json:"DataSourceType,omitempty"` + Description string `json:"Description,omitempty"` + OpenSearchArns []string `json:"OpenSearchArns"` } func toDirectQueryDataSourceJSON(ds *DirectQueryDataSource) directQueryDataSourceJSON { @@ -44,10 +46,10 @@ type getDirectQueryDataSourceOutputJSON struct { // dataSourceJSON renders a DataSource as the wire-shape types.DataSourceDetails // / GetDataSourceOutput object (top-level fields, no envelope). type dataSourceJSON struct { - Description string `json:"Description,omitempty"` - Name string `json:"Name"` - Status string `json:"Status,omitempty"` - DataSourceType json.RawMessage `json:"DataSourceType,omitempty"` + Description string `json:"Description,omitempty"` + Name string `json:"Name"` + Status string `json:"Status,omitempty"` + DataSourceType jsontext.Value `json:"DataSourceType,omitempty"` } func toDataSourceJSON(ds *DataSource) dataSourceJSON { @@ -129,13 +131,13 @@ func (h *Handler) handleUpdateDirectQueryDataSource( return } var req struct { - DataSourceType json.RawMessage `json:"DataSourceType"` - Description string `json:"Description"` - DataSourceAccessPolicy string `json:"DataSourceAccessPolicy"` - OpenSearchArns []string `json:"OpenSearchArns"` + DataSourceType jsontext.Value `json:"DataSourceType"` + Description string `json:"Description"` + DataSourceAccessPolicy string `json:"DataSourceAccessPolicy"` + OpenSearchArns []string `json:"OpenSearchArns"` } if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -160,9 +162,9 @@ func (h *Handler) handleUpdateDirectQueryDataSource( // (types.UpdateDataSourceInput -- DomainName and Name come from the URL // path, not the body). type updateDataSourceRequest struct { - Description string `json:"Description"` - Status string `json:"Status"` - DataSourceType json.RawMessage `json:"DataSourceType"` + Description string `json:"Description"` + Status string `json:"Status"` + DataSourceType jsontext.Value `json:"DataSourceType"` } // handleUpdateDataSource handles PUT /2021-01-01/opensearch/domain/{DomainName}/dataSource/{Name}. @@ -176,7 +178,7 @@ func (h *Handler) handleUpdateDataSource(w http.ResponseWriter, r *http.Request, var req updateDataSourceRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -195,9 +197,9 @@ func (h *Handler) handleUpdateDataSource(w http.ResponseWriter, r *http.Request, // addDataSourceRequest is the JSON request body for AddDataSource. type addDataSourceRequest struct { - Name string `json:"Name"` - Description string `json:"Description"` - DataSourceType json.RawMessage `json:"DataSourceType"` + Name string `json:"Name"` + Description string `json:"Description"` + DataSourceType jsontext.Value `json:"DataSourceType"` } // addDataSourceOutput is the JSON response for AddDataSource. @@ -214,7 +216,7 @@ func (h *Handler) handleAddDataSource(w http.ResponseWriter, r *http.Request, do } var req addDataSourceRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -246,11 +248,11 @@ func (h *Handler) handleAddDataSource(w http.ResponseWriter, r *http.Request, do // addDirectQueryDataSourceRequest is the JSON request body for AddDirectQueryDataSource. type addDirectQueryDataSourceRequest struct { - DataSourceName string `json:"DataSourceName"` - Description string `json:"Description"` - DataSourceType json.RawMessage `json:"DataSourceType"` - DataSourceAccessPolicy string `json:"DataSourceAccessPolicy"` - OpenSearchArns []string `json:"OpenSearchArns"` + DataSourceName string `json:"DataSourceName"` + Description string `json:"Description"` + DataSourceType jsontext.Value `json:"DataSourceType"` + DataSourceAccessPolicy string `json:"DataSourceAccessPolicy"` + OpenSearchArns []string `json:"OpenSearchArns"` } // addDirectQueryDataSourceOutput is the JSON response for AddDirectQueryDataSource. @@ -267,7 +269,7 @@ func (h *Handler) handleAddDirectQueryDataSource(w http.ResponseWriter, r *http. } var req addDirectQueryDataSourceRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_data_sources_test.go b/services/opensearch/handler_data_sources_test.go index 0647e8e372..efa4f7f28b 100644 --- a/services/opensearch/handler_data_sources_test.go +++ b/services/opensearch/handler_data_sources_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -47,7 +49,7 @@ func TestAddDataSource_DataSourceTypeJSON(t *testing.T) { require.Equal(t, http.StatusOK, getResp.StatusCode) var ds map[string]any - require.NoError(t, json.NewDecoder(getResp.Body).Decode(&ds)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getResp.Body), &ds, jsonx.V1())) // No "DataSource" envelope: fields are top-level. assert.Equal(t, "my-ds", ds["Name"]) @@ -85,7 +87,7 @@ func TestAddDirectQueryDataSource_DataSourceTypeJSON(t *testing.T) { require.Equal(t, http.StatusOK, getResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(getResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getResp.Body), &out, jsonx.V1())) assert.Equal(t, "dq-ds", out["DataSourceName"]) dsType, ok := out["DataSourceType"].(map[string]any) @@ -97,7 +99,7 @@ func TestAddDataSource_DomainNotFound(t *testing.T) { t.Parallel() b := opensearch.NewInMemoryBackend(testAccountID, testRegion) - _, err := b.AddDataSource("nonexistent", "ds1", "desc", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err := b.AddDataSource("nonexistent", "ds1", "desc", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.Error(t, err) assert.ErrorIs(t, err, opensearch.ErrDomainNotFound) } @@ -106,10 +108,10 @@ func TestAddDirectQueryDataSource_Duplicate(t *testing.T) { t.Parallel() b := opensearch.NewInMemoryBackend(testAccountID, testRegion) - _, err := b.AddDirectQueryDataSource("ds-1", "desc", json.RawMessage(`{"CloudWatchLog":{}}`), nil) + _, err := b.AddDirectQueryDataSource("ds-1", "desc", jsontext.Value(`{"CloudWatchLog":{}}`), nil) require.NoError(t, err) - _, err = b.AddDirectQueryDataSource("ds-1", "desc2", json.RawMessage(`{"SecurityLake":{}}`), nil) + _, err = b.AddDirectQueryDataSource("ds-1", "desc2", jsontext.Value(`{"SecurityLake":{}}`), nil) require.Error(t, err) assert.ErrorIs(t, err, opensearch.ErrDataSourceAlreadyExists) } @@ -118,7 +120,7 @@ func TestDirectQueryDataSource_ARN(t *testing.T) { t.Parallel() b := opensearch.NewInMemoryBackend(testAccountID, testRegion) - dsARN, err := b.AddDirectQueryDataSource("my-dq", "desc", json.RawMessage(`{"CloudWatchLog":{}}`), nil) + dsARN, err := b.AddDirectQueryDataSource("my-dq", "desc", jsontext.Value(`{"CloudWatchLog":{}}`), nil) require.NoError(t, err) assert.Contains(t, dsARN, "directQueryDataSource/my-dq") assert.Contains(t, dsARN, testAccountID) @@ -185,7 +187,7 @@ func TestDataSources_Lifecycle(t *testing.T) { b.AddDomainInternal("ds-domain", "") for _, name := range tt.addSources { - _, err := b.AddDataSource("ds-domain", name, "", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err := b.AddDataSource("ds-domain", name, "", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.NoError(t, err) } @@ -234,7 +236,7 @@ func TestDirectQuery_DeleteAndList(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) sources, ok := lOut["DirectQueryDataSources"].([]any) require.True(t, ok) require.Len(t, sources, 1) @@ -250,7 +252,7 @@ func TestDirectQuery_DeleteAndList(t *testing.T) { lr2 := doRequest(t, h, http.MethodGet, "/2021-01-01/opensearch/directQueryDataSource", nil) defer lr2.Body.Close() var lOut2 map[string]any - require.NoError(t, json.NewDecoder(lr2.Body).Decode(&lOut2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr2.Body), &lOut2, jsonx.V1())) sources2 := lOut2["DirectQueryDataSources"].([]any) assert.Empty(t, sources2) } @@ -281,7 +283,7 @@ func TestDirectQuery_UpdateReturnsARN(t *testing.T) { require.Equal(t, http.StatusOK, ur.StatusCode) var uOut map[string]any - require.NoError(t, json.NewDecoder(ur.Body).Decode(&uOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ur.Body), &uOut, jsonx.V1())) assert.Contains(t, uOut, "DataSourceArn") } @@ -310,7 +312,7 @@ func TestDataSources_ListAndGet(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) sources, ok := lOut["DataSources"].([]any) require.True(t, ok) assert.Len(t, sources, 2) @@ -322,7 +324,7 @@ func TestDataSources_ListAndGet(t *testing.T) { require.Equal(t, http.StatusOK, gr.StatusCode) var ds map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&ds)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &ds, jsonx.V1())) assert.Equal(t, "ds-alpha", ds["Name"]) assert.Equal(t, "ACTIVE", ds["Status"]) } @@ -355,7 +357,7 @@ func TestDataSources_UpdateAndDelete(t *testing.T) { require.Equal(t, http.StatusOK, ur.StatusCode) var uOut map[string]any - require.NoError(t, json.NewDecoder(ur.Body).Decode(&uOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ur.Body), &uOut, jsonx.V1())) assert.Contains(t, uOut["Message"], "updated") // Get reflects the updated description. @@ -363,7 +365,7 @@ func TestDataSources_UpdateAndDelete(t *testing.T) { "/2021-01-01/opensearch/domain/ds-ud-domain/dataSource/ds-target", nil) defer gr.Body.Close() var gOut map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&gOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &gOut, jsonx.V1())) assert.Equal(t, "after", gOut["Description"]) // Delete. @@ -373,7 +375,7 @@ func TestDataSources_UpdateAndDelete(t *testing.T) { require.Equal(t, http.StatusOK, del.StatusCode) var delOut map[string]any - require.NoError(t, json.NewDecoder(del.Body).Decode(&delOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(del.Body), &delOut, jsonx.V1())) assert.Equal(t, "DataSource deleted", delOut["Message"]) // List should be empty after delete. @@ -381,7 +383,7 @@ func TestDataSources_UpdateAndDelete(t *testing.T) { "/2021-01-01/opensearch/domain/ds-ud-domain/dataSource", nil) defer lr.Body.Close() var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) remaining := lOut["DataSources"].([]any) assert.Empty(t, remaining) } @@ -584,6 +586,6 @@ func TestOpenSearchBackend_AddDataSource_MissingName(t *testing.T) { _, err := b.CreateDomain(opensearch.CreateDomainInput{Name: "my-domain"}) require.NoError(t, err) - _, err = b.AddDataSource("my-domain", "", "desc", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err = b.AddDataSource("my-domain", "", "desc", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.Error(t, err) } diff --git a/services/opensearch/handler_domain_config.go b/services/opensearch/handler_domain_config.go index 8d914a6b3f..91cc9a7530 100644 --- a/services/opensearch/handler_domain_config.go +++ b/services/opensearch/handler_domain_config.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // dryRunResultsJSON mirrors aws-sdk-go-v2 types.DryRunResults. @@ -209,7 +210,7 @@ func (h *Handler) handleCancelDomainConfigChange( var req cancelDomainConfigChangeRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_domain_config_test.go b/services/opensearch/handler_domain_config_test.go index d2961b37ab..a86c778701 100644 --- a/services/opensearch/handler_domain_config_test.go +++ b/services/opensearch/handler_domain_config_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -31,7 +33,7 @@ func TestOpenSearchHandler_UpdateDomainConfig(t *testing.T) { assert.Equal(t, http.StatusOK, upResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(upResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(upResp.Body), &out, jsonx.V1())) domainConfig, ok := out["DomainConfig"].(map[string]any) require.True(t, ok) @@ -58,7 +60,7 @@ func Test_UpdateDomainConfig_DryRun(t *testing.T) { assert.Equal(t, http.StatusOK, dryResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(dryResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dryResp.Body), &out, jsonx.V1())) domainConfig, ok := out["DomainConfig"].(map[string]any) require.True(t, ok) @@ -75,7 +77,7 @@ func Test_UpdateDomainConfig_DryRun(t *testing.T) { defer descResp.Body.Close() var descOut map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&descOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &descOut, jsonx.V1())) status, ok := descOut["DomainStatus"].(map[string]any) require.True(t, ok) assert.Equal(t, "OpenSearch_2.7", status["EngineVersion"], "dry run must not persist the change") @@ -101,7 +103,7 @@ func TestOpenSearchHandler_DefaultApplicationSetting(t *testing.T) { // GET before any setting → empty ARN. resp := doRequest(t, h, http.MethodGet, "/2021-01-01/opensearch/defaultApplicationSetting", nil) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Empty(t, out["applicationArn"]) @@ -115,7 +117,7 @@ func TestOpenSearchHandler_DefaultApplicationSetting(t *testing.T) { assert.Equal(t, http.StatusOK, putResp.StatusCode) var putOut map[string]any - require.NoError(t, json.NewDecoder(putResp.Body).Decode(&putOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(putResp.Body), &putOut, jsonx.V1())) assert.Equal(t, appArn, putOut["applicationArn"]) // GET after PUT → should return the stored ARN. @@ -125,7 +127,7 @@ func TestOpenSearchHandler_DefaultApplicationSetting(t *testing.T) { assert.Equal(t, http.StatusOK, getResp.StatusCode) var out2 map[string]any - require.NoError(t, json.NewDecoder(getResp.Body).Decode(&out2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getResp.Body), &out2, jsonx.V1())) assert.Equal(t, appArn, out2["applicationArn"]) // PUT with SetAsDefault=false clears the default. @@ -135,7 +137,7 @@ func TestOpenSearchHandler_DefaultApplicationSetting(t *testing.T) { assert.Equal(t, http.StatusOK, clearResp.StatusCode) var clearOut map[string]any - require.NoError(t, json.NewDecoder(clearResp.Body).Decode(&clearOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(clearResp.Body), &clearOut, jsonx.V1())) assert.Empty(t, clearOut["applicationArn"]) } @@ -167,7 +169,7 @@ func TestDescribeDomainConfig_RealData(t *testing.T) { require.Equal(t, http.StatusOK, cfgResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(cfgResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cfgResp.Body), &out, jsonx.V1())) domainConfig, ok := out["DomainConfig"].(map[string]any) require.True(t, ok) @@ -447,7 +449,7 @@ func TestUpdateDomainConfig_AllOptions(t *testing.T) { require.Equal(t, http.StatusOK, upResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(upResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(upResp.Body), &out, jsonx.V1())) tt.verify(t, out) }) } @@ -515,7 +517,7 @@ func TestDescribeDomainConfig_FullConfig(t *testing.T) { require.Equal(t, http.StatusOK, cfgResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(cfgResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cfgResp.Body), &out, jsonx.V1())) dc, ok := out["DomainConfig"].(map[string]any) require.True(t, ok) @@ -602,7 +604,7 @@ func TestUpdateDomainConfig_MutatesState(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) tt.verifyFn(t, out) }) } @@ -670,7 +672,7 @@ func TestCancelDomainConfigChange_ReturnsLastChangeID(t *testing.T) { var got struct { CancelledChangeIDs []string `json:"CancelledChangeIds"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &got, jsonx.V1())) if tt.wantEmptyIDs { assert.Empty(t, got.CancelledChangeIDs) diff --git a/services/opensearch/handler_domain_maintenance_test.go b/services/opensearch/handler_domain_maintenance_test.go index 610ce9c36d..e24576ca11 100644 --- a/services/opensearch/handler_domain_maintenance_test.go +++ b/services/opensearch/handler_domain_maintenance_test.go @@ -1,12 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDomainMaintenance_StartListGet(t *testing.T) { @@ -23,7 +26,7 @@ func TestDomainMaintenance_StartListGet(t *testing.T) { require.Equal(t, http.StatusOK, sr.StatusCode) var sOut map[string]any - require.NoError(t, json.NewDecoder(sr.Body).Decode(&sOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(sr.Body), &sOut, jsonx.V1())) maintID := sOut["MaintenanceId"].(string) assert.NotEmpty(t, maintID) @@ -34,7 +37,7 @@ func TestDomainMaintenance_StartListGet(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) maintenances, ok := lOut["DomainMaintenances"].([]any) require.True(t, ok) assert.Len(t, maintenances, 1) @@ -46,7 +49,7 @@ func TestDomainMaintenance_StartListGet(t *testing.T) { require.Equal(t, http.StatusOK, gr.StatusCode) var gOut map[string]any - require.NoError(t, json.NewDecoder(gr.Body).Decode(&gOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(gr.Body), &gOut, jsonx.V1())) assert.Equal(t, maintID, gOut["MaintenanceId"]) } @@ -111,7 +114,7 @@ func TestDeleteDomain_CleansUpMaintenances(t *testing.T) { var got struct { DomainMaintenances []any `json:"DomainMaintenances"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &got, jsonx.V1())) assert.Empty(t, got.DomainMaintenances, "expected no orphaned maintenances after delete+recreate") }) } diff --git a/services/opensearch/handler_domain_options.go b/services/opensearch/handler_domain_options.go index e51573f026..ea0db43575 100644 --- a/services/opensearch/handler_domain_options.go +++ b/services/opensearch/handler_domain_options.go @@ -1,11 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // domainClusterConfig holds the cluster configuration request parameters for a domain. @@ -31,12 +33,12 @@ type domainClusterConfigAlias domainClusterConfig // UnmarshalJSON records which members the request set, so UpdateDomainConfig can // leave omitted ones unchanged. func (cc *domainClusterConfig) UnmarshalJSON(data []byte) error { - if err := json.Unmarshal(data, (*domainClusterConfigAlias)(cc)); err != nil { + if err := json.Unmarshal(data, (*domainClusterConfigAlias)(cc), jsonx.V1()); err != nil { return err } - var raw map[string]json.RawMessage - if err := json.Unmarshal(data, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return err } diff --git a/services/opensearch/handler_domain_options_test.go b/services/opensearch/handler_domain_options_test.go index 6b0a397227..642f70b1af 100644 --- a/services/opensearch/handler_domain_options_test.go +++ b/services/opensearch/handler_domain_options_test.go @@ -1,13 +1,16 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAudit1_CreateDomain_FullClusterConfig verifies all ClusterConfig fields round-trip through @@ -101,7 +104,7 @@ func TestCreateDomain_FullClusterConfig(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) cc, ok := status["ClusterConfig"].(map[string]any) @@ -130,7 +133,7 @@ func TestCreateDomain_SoftwareUpdateOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) swu, ok := status["SoftwareUpdateOptions"].(map[string]any) @@ -203,7 +206,7 @@ func TestCreateDomain_EBSOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) ebs, ok := status["EBSOptions"].(map[string]any) @@ -274,7 +277,7 @@ func TestCreateDomain_EncryptionOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) @@ -344,7 +347,7 @@ func TestCreateDomain_DomainEndpointOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) deo, ok := status["DomainEndpointOptions"].(map[string]any) @@ -426,7 +429,7 @@ func TestCreateDomain_AdvancedSecurityOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) aso, ok := status["AdvancedSecurityOptions"].(map[string]any) @@ -485,7 +488,7 @@ func TestCreateDomain_VPCOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) vpc, ok := status["VPCOptions"].(map[string]any) @@ -546,7 +549,7 @@ func TestCreateDomain_CognitoOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) cognito, ok := status["CognitoOptions"].(map[string]any) @@ -624,7 +627,7 @@ func TestCreateDomain_LogPublishingOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) logs, ok := status["LogPublishingOptions"].(map[string]any) @@ -665,7 +668,7 @@ func TestCreateDomain_SnapshotOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) snapOpts, ok := status["SnapshotOptions"].(map[string]any) @@ -722,7 +725,7 @@ func TestCreateDomain_AccessPolicies(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DomainStatus"].(map[string]any) require.True(t, ok) gotPolicies, _ := status["AccessPolicies"].(string) diff --git a/services/opensearch/handler_domain_status_test.go b/services/opensearch/handler_domain_status_test.go index e6c75d119e..da99345c86 100644 --- a/services/opensearch/handler_domain_status_test.go +++ b/services/opensearch/handler_domain_status_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "strconv" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -33,7 +35,7 @@ func TestOpenSearchHandler_DescribeDomainHealth(t *testing.T) { assert.Equal(t, http.StatusOK, healthResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(healthResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(healthResp.Body), &out, jsonx.V1())) assert.Equal(t, "Active", out["DomainState"]) // 3 instances * 5 shards = 15. TotalShards is NumberOfShards, a string @@ -61,7 +63,7 @@ func TestOpenSearchHandler_DescribeDomainNodes(t *testing.T) { assert.Equal(t, http.StatusOK, nodesResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(nodesResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(nodesResp.Body), &out, jsonx.V1())) nodes, ok := out["DomainNodesStatusList"].([]any) require.True(t, ok) @@ -125,7 +127,7 @@ func TestOpenSearchHandler_DescribeDomainChangeProgress(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["ChangeProgressStatus"].(map[string]any) require.True(t, ok) @@ -151,7 +153,7 @@ func TestOpenSearchHandler_DescribeDryRunProgress(t *testing.T) { require.NoError(t, err) var out map[string]any - require.NoError(t, json.Unmarshal(bodyBytes, &out)) + require.NoError(t, json.Unmarshal(bodyBytes, &out, jsonx.V1())) status, ok := out["DryRunProgressStatus"].(map[string]any) require.True(t, ok) @@ -204,7 +206,7 @@ func TestDescribeDomainHealth_AdditionalFields(t *testing.T) { require.Equal(t, http.StatusOK, hResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(hResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(hResp.Body), &out, jsonx.V1())) // Existing fields. assert.Equal(t, "Active", out["DomainState"]) @@ -247,7 +249,7 @@ func TestDescribeDomainNodes_StorageAndAZ(t *testing.T) { require.Equal(t, http.StatusOK, nResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(nResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(nResp.Body), &out, jsonx.V1())) nodes, ok := out["DomainNodesStatusList"].([]any) require.True(t, ok) @@ -279,7 +281,7 @@ func TestDescribeDomainChangeProgress_Timestamps(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["ChangeProgressStatus"].(map[string]any) require.True(t, ok) @@ -301,7 +303,7 @@ func TestDescribeDryRunProgress_ValidationFailures(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) status, ok := out["DryRunProgressStatus"].(map[string]any) require.True(t, ok) @@ -339,7 +341,7 @@ func TestGetDomainHealth_WarmNodeCount(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) warmCount, ok := out["WarmNodeCount"].(string) require.True(t, ok, "WarmNodeCount must be present") diff --git a/services/opensearch/handler_domains.go b/services/opensearch/handler_domains.go index 6fbb7a7278..7469368f48 100644 --- a/services/opensearch/handler_domains.go +++ b/services/opensearch/handler_domains.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -124,7 +125,7 @@ func (h *Handler) handleCreateDomain(w http.ResponseWriter, r *http.Request) { } var req domainJSON - if err = json.Unmarshal(body, &req); err != nil { + if err = json.Unmarshal(body, &req, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -249,7 +250,7 @@ func (h *Handler) handleDescribeDomains(w http.ResponseWriter, r *http.Request) } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } domains, err := h.Backend.DescribeDomains(req.DomainNames) @@ -430,7 +431,7 @@ func (h *Handler) handleStartServiceSoftwareUpdate(w http.ResponseWriter, r *htt } var req startServiceSoftwareUpdateRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -482,7 +483,7 @@ func (h *Handler) handleRollbackServiceSoftwareUpdate(w http.ResponseWriter, r * } var req rollbackServiceSoftwareUpdateRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -552,7 +553,7 @@ func (h *Handler) handleCancelServiceSoftwareUpdate(w http.ResponseWriter, r *ht } var req cancelServiceSoftwareUpdateRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_domains_test.go b/services/opensearch/handler_domains_test.go index 81974116e0..98dc682469 100644 --- a/services/opensearch/handler_domains_test.go +++ b/services/opensearch/handler_domains_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -62,7 +64,7 @@ func TestStartServiceSoftwareUpdate_ScheduleAt(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) swo, ok := out["ServiceSoftwareOptions"].(map[string]any) require.True(t, ok, "expected ServiceSoftwareOptions in response") @@ -109,7 +111,7 @@ func TestOpenSearchHandler_DescribeDomains(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainStatusList"].([]any) require.True(t, ok) @@ -141,7 +143,7 @@ func TestOpenSearchHandler_DescribeDomains_All(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainStatusList"].([]any) require.True(t, ok) @@ -184,7 +186,7 @@ func TestDescribeDomains_FullStatusShape(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainStatusList"].([]any) require.True(t, ok) @@ -424,7 +426,7 @@ func TestListDomainNames_EngineTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) domainNames, ok := out["DomainNames"].([]any) require.True(t, ok) @@ -516,7 +518,7 @@ func TestDescribeDomains_FullDomainStatus(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainStatusList"].([]any) require.True(t, ok) @@ -582,7 +584,7 @@ func TestListDomainNames_ReturnsBothDomains(t *testing.T) { EngineType string `json:"EngineType"` } `json:"DomainNames"` } - require.NoError(t, json.NewDecoder(resp.Body).Decode(&got)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &got, jsonx.V1())) assert.Len(t, got.DomainNames, tt.wantCount) returnedNames := make(map[string]bool, len(got.DomainNames)) @@ -682,7 +684,7 @@ func Test_DomainStatus_DomainID(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createStatus, ok := createOut["DomainStatus"].(map[string]any) require.True(t, ok, "DomainStatus missing") assert.Equal(t, "123456789012/domainid-test", createStatus["DomainId"]) @@ -693,7 +695,7 @@ func Test_DomainStatus_DomainID(t *testing.T) { require.Equal(t, http.StatusOK, describeResp.StatusCode) var describeOut map[string]any - require.NoError(t, json.NewDecoder(describeResp.Body).Decode(&describeOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(describeResp.Body), &describeOut, jsonx.V1())) describeStatus, ok := describeOut["DomainStatus"].(map[string]any) require.True(t, ok, "DomainStatus missing") assert.Equal(t, "123456789012/domainid-test", describeStatus["DomainId"]) @@ -771,7 +773,7 @@ func TestOpenSearchHandler_ListDomainNames(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) names, ok := out["DomainNames"].([]any) require.True(t, ok) @@ -1122,7 +1124,7 @@ func TestInsights_HTTPHandler(t *testing.T) { if tt.wantCode == http.StatusOK && tt.path == "/2021-01-01/opensearch/insights" { var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) insights, ok := out["Insights"].([]any) require.True(t, ok) assert.Empty(t, insights) diff --git a/services/opensearch/handler_inbound_connections.go b/services/opensearch/handler_inbound_connections.go index 9907b5a2fa..1e76155517 100644 --- a/services/opensearch/handler_inbound_connections.go +++ b/services/opensearch/handler_inbound_connections.go @@ -1,12 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // describeConnectionsRequest is the shared request body shape for @@ -154,7 +155,7 @@ func (h *Handler) readDescribeConnectionsRequest( var req describeConnectionsRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "failed to parse body") return describeConnectionsRequest{}, false diff --git a/services/opensearch/handler_inbound_connections_test.go b/services/opensearch/handler_inbound_connections_test.go index 53e5708eb5..687732156d 100644 --- a/services/opensearch/handler_inbound_connections_test.go +++ b/services/opensearch/handler_inbound_connections_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -41,7 +43,7 @@ func TestInboundConnections_DescribeRejectDelete(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) conns, ok := dOut["Connections"].([]any) require.True(t, ok) require.NotEmpty(t, conns) @@ -57,7 +59,7 @@ func TestInboundConnections_DescribeRejectDelete(t *testing.T) { require.Equal(t, http.StatusOK, rr.StatusCode) var rOut map[string]any - require.NoError(t, json.NewDecoder(rr.Body).Decode(&rOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rr.Body), &rOut, jsonx.V1())) rConn := rOut["Connection"].(map[string]any) assert.Equal(t, "REJECTED", rConn["ConnectionStatus"].(map[string]any)["StatusCode"]) @@ -68,7 +70,7 @@ func TestInboundConnections_DescribeRejectDelete(t *testing.T) { require.Equal(t, http.StatusOK, del.StatusCode) var delOut map[string]any - require.NoError(t, json.NewDecoder(del.Body).Decode(&delOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(del.Body), &delOut, jsonx.V1())) delConn := delOut["Connection"].(map[string]any) assert.Equal(t, "conn-inb-1", delConn["ConnectionId"]) } @@ -164,7 +166,7 @@ func TestOutboundConnection_CreateThenAcceptMirrorsBothSides(t *testing.T) { require.Equal(t, http.StatusOK, cr.StatusCode) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) connID := cOut["ConnectionId"].(string) // Accepting the mirrored inbound connection also activates the outbound side. @@ -174,7 +176,7 @@ func TestOutboundConnection_CreateThenAcceptMirrorsBothSides(t *testing.T) { require.Equal(t, http.StatusOK, ar.StatusCode) var aOut map[string]any - require.NoError(t, json.NewDecoder(ar.Body).Decode(&aOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ar.Body), &aOut, jsonx.V1())) aConn := aOut["Connection"].(map[string]any) assert.Equal(t, "ACTIVE", aConn["ConnectionStatus"].(map[string]any)["StatusCode"]) @@ -182,7 +184,7 @@ func TestOutboundConnection_CreateThenAcceptMirrorsBothSides(t *testing.T) { defer dr.Body.Close() var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) conns := dOut["Connections"].([]any) require.Len(t, conns, 1) outConn := conns[0].(map[string]any) diff --git a/services/opensearch/handler_indices.go b/services/opensearch/handler_indices.go index 01e5a43931..9d3488486b 100644 --- a/services/opensearch/handler_indices.go +++ b/services/opensearch/handler_indices.go @@ -1,12 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createIndexRealRequest and updateIndexRealRequest mirror @@ -46,7 +47,7 @@ func (h *Handler) handleCreateIndexRealRoute(w http.ResponseWriter, r *http.Requ var req createIndexRealRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if req.IndexName == "" { @@ -79,7 +80,7 @@ func (h *Handler) handleUpdateIndexRoute(w http.ResponseWriter, r *http.Request, body, _ := httputils.ReadBody(r) var req updateIndexRealRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } _, err := h.Backend.UpdateIndex(parts[0], parts[1], nil, nil, req.IndexSchema) @@ -301,7 +302,7 @@ func (h *Handler) handleCreateIndex(w http.ResponseWriter, r *http.Request, sp i } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if _, err := h.Backend.CreateIndex(sp.domain, sp.index, req.Mappings, req.Settings, req.Aliases, nil); err != nil { @@ -322,7 +323,7 @@ func (h *Handler) handleIndexDocument(w http.ResponseWriter, r *http.Request, sp body, _ := httputils.ReadBody(r) var doc map[string]any if len(body) > 0 { - if err := json.Unmarshal(body, &doc); err != nil { + if err := json.Unmarshal(body, &doc, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid document body") return @@ -360,7 +361,7 @@ func (h *Handler) handleSearchIndex(w http.ResponseWriter, r *http.Request, sp i Size *int `json:"size"` } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid search body") return diff --git a/services/opensearch/handler_insights.go b/services/opensearch/handler_insights.go index 6a81df76c5..2b76de02de 100644 --- a/services/opensearch/handler_insights.go +++ b/services/opensearch/handler_insights.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // insightEntityJSON matches types.InsightEntity (used by ListInsights and @@ -52,7 +53,7 @@ func (h *Handler) handleListInsights(w http.ResponseWriter, r *http.Request) { var req listInsightsRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -81,7 +82,7 @@ func (h *Handler) handleDescribeInsightDetails(w http.ResponseWriter, r *http.Re var req describeInsightDetailsRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -111,7 +112,7 @@ func (h *Handler) handleInsightFeedback(w http.ResponseWriter, r *http.Request) var req insightFeedbackRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_migrations.go b/services/opensearch/handler_migrations.go index e19243b5f4..b77be92966 100644 --- a/services/opensearch/handler_migrations.go +++ b/services/opensearch/handler_migrations.go @@ -1,13 +1,14 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strconv" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // migrationSourceJSON matches types.MigrationSource. @@ -108,7 +109,7 @@ func (h *Handler) handleStartMigration(w http.ResponseWriter, r *http.Request) { var req startMigrationRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_outbound_connections.go b/services/opensearch/handler_outbound_connections.go index 2f1e13f5e4..0452b9f938 100644 --- a/services/opensearch/handler_outbound_connections.go +++ b/services/opensearch/handler_outbound_connections.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCCOutboundRoutes handles outbound cross-cluster connection sub-routes. @@ -129,7 +130,7 @@ func (h *Handler) handleCreateOutboundConnection(w http.ResponseWriter, r *http. var req createOutboundConnectionRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "failed to parse body") return diff --git a/services/opensearch/handler_outbound_connections_test.go b/services/opensearch/handler_outbound_connections_test.go index 297c7cf987..cdd352887e 100644 --- a/services/opensearch/handler_outbound_connections_test.go +++ b/services/opensearch/handler_outbound_connections_test.go @@ -1,12 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOutboundConnections_CreateDescribeDelete(t *testing.T) { @@ -29,7 +32,7 @@ func TestOutboundConnections_CreateDescribeDelete(t *testing.T) { require.Equal(t, http.StatusOK, cr.StatusCode) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) connID := cOut["ConnectionId"].(string) assert.NotEmpty(t, connID) assert.Equal(t, "my-alias", cOut["ConnectionAlias"]) @@ -44,7 +47,7 @@ func TestOutboundConnections_CreateDescribeDelete(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) conns, ok := dOut["Connections"].([]any) require.True(t, ok) assert.Len(t, conns, 1) @@ -55,7 +58,7 @@ func TestOutboundConnections_CreateDescribeDelete(t *testing.T) { require.Equal(t, http.StatusOK, ir.StatusCode) var iOut map[string]any - require.NoError(t, json.NewDecoder(ir.Body).Decode(&iOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ir.Body), &iOut, jsonx.V1())) inConns, ok := iOut["Connections"].([]any) require.True(t, ok) require.Len(t, inConns, 1) @@ -71,7 +74,7 @@ func TestOutboundConnections_CreateDescribeDelete(t *testing.T) { require.Equal(t, http.StatusOK, del.StatusCode) var delOut map[string]any - require.NoError(t, json.NewDecoder(del.Body).Decode(&delOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(del.Body), &delOut, jsonx.V1())) conn := delOut["Connection"].(map[string]any) assert.Equal(t, connID, conn["ConnectionId"]) } diff --git a/services/opensearch/handler_packages.go b/services/opensearch/handler_packages.go index 79d0e1a3ef..29bf1e6d99 100644 --- a/services/opensearch/handler_packages.go +++ b/services/opensearch/handler_packages.go @@ -1,12 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDissociatePackage( @@ -42,7 +43,7 @@ func (h *Handler) handleDissociatePackages(w http.ResponseWriter, r *http.Reques } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } packageIDs := make([]string, 0, len(req.PackageList)) @@ -143,7 +144,7 @@ func (h *Handler) handleDescribePackages(w http.ResponseWriter, r *http.Request) MaxResults int32 `json:"MaxResults"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } filters := make(map[string][]string, len(req.Filters)) @@ -185,7 +186,7 @@ func (h *Handler) handleUpdatePackageRoute(w http.ResponseWriter, r *http.Reques PackageDescription string `json:"PackageDescription"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } pkg, updateErr := h.Backend.UpdatePackage(req.PackageID, req.PackageDescription) @@ -212,7 +213,7 @@ func (h *Handler) handleUpdatePackageScopeRoute(w http.ResponseWriter, r *http.R PackageUserList []string `json:"PackageUserList"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } pkg, err := h.Backend.UpdatePackageScope(req.PackageID, req.Operation, req.PackageUserList) @@ -363,7 +364,7 @@ func (h *Handler) handlePackageRootRoutes(w http.ResponseWriter, r *http.Request PackageDescription string `json:"PackageDescription"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } var pkgSource *PackageSource if req.PackageSource != nil { @@ -501,7 +502,7 @@ func (h *Handler) handleAssociatePackages(w http.ResponseWriter, r *http.Request } var req associatePackagesRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_packages_test.go b/services/opensearch/handler_packages_test.go index fe64f5fea3..80d437409d 100644 --- a/services/opensearch/handler_packages_test.go +++ b/services/opensearch/handler_packages_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -98,7 +100,7 @@ func TestOpenSearchHandler_DeletePackage_RejectedWhileAssociated(t *testing.T) { map[string]any{"PackageName": "delpkg-pkg", "PackageType": "TXT-DICTIONARY"}) var pkgOut map[string]any - require.NoError(t, json.NewDecoder(pkgResp.Body).Decode(&pkgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pkgResp.Body), &pkgOut, jsonx.V1())) pkgResp.Body.Close() pkgDetails, ok := pkgOut["PackageDetails"].(map[string]any) @@ -138,7 +140,7 @@ func TestOpenSearchHandler_DissociatePackage(t *testing.T) { map[string]any{"PackageName": "my-pkg", "PackageType": "TXT-DICTIONARY"}) var pkgOut map[string]any - require.NoError(t, json.NewDecoder(pkgResp.Body).Decode(&pkgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pkgResp.Body), &pkgOut, jsonx.V1())) pkgResp.Body.Close() pkgDetails, ok := pkgOut["PackageDetails"].(map[string]any) @@ -160,7 +162,7 @@ func TestOpenSearchHandler_DissociatePackage(t *testing.T) { assert.Equal(t, http.StatusOK, dissocResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(dissocResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dissocResp.Body), &out, jsonx.V1())) details2, ok := out["DomainPackageDetails"].(map[string]any) require.True(t, ok) @@ -184,7 +186,7 @@ func TestOpenSearchHandler_DissociatePackages(t *testing.T) { pkgResp := doRequest(t, h, http.MethodPost, "/2021-01-01/packages", map[string]any{"PackageName": name, "PackageType": "TXT-DICTIONARY"}) var pkgOut map[string]any - require.NoError(t, json.NewDecoder(pkgResp.Body).Decode(&pkgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pkgResp.Body), &pkgOut, jsonx.V1())) pkgResp.Body.Close() id := pkgOut["PackageDetails"].(map[string]any)["PackageID"].(string) @@ -211,7 +213,7 @@ func TestOpenSearchHandler_DissociatePackages(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) list, ok := out["DomainPackageDetailsList"].([]any) require.True(t, ok) @@ -233,7 +235,7 @@ func TestListPackagesForDomain_ReturnsDomainPackageDetailsShape(t *testing.T) { pkgResp := doRequest(t, h, http.MethodPost, "/2021-01-01/packages", map[string]any{"PackageName": "list-pkg", "PackageType": "TXT-DICTIONARY"}) var pkgOut map[string]any - require.NoError(t, json.NewDecoder(pkgResp.Body).Decode(&pkgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pkgResp.Body), &pkgOut, jsonx.V1())) pkgResp.Body.Close() pkgID := pkgOut["PackageDetails"].(map[string]any)["PackageID"].(string) @@ -250,7 +252,7 @@ func TestListPackagesForDomain_ReturnsDomainPackageDetailsShape(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) list, ok := lOut["DomainPackageDetailsList"].([]any) require.True(t, ok) require.Len(t, list, 1) @@ -272,7 +274,7 @@ func TestListDomainsForPackage_ReturnsDomainPackageDetailsShape(t *testing.T) { pkgResp := doRequest(t, h, http.MethodPost, "/2021-01-01/packages", map[string]any{"PackageName": "shared-pkg", "PackageType": "TXT-DICTIONARY"}) var pkgOut map[string]any - require.NoError(t, json.NewDecoder(pkgResp.Body).Decode(&pkgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pkgResp.Body), &pkgOut, jsonx.V1())) pkgResp.Body.Close() pkgID := pkgOut["PackageDetails"].(map[string]any)["PackageID"].(string) @@ -287,7 +289,7 @@ func TestListDomainsForPackage_ReturnsDomainPackageDetailsShape(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) list, ok := lOut["DomainPackageDetailsList"].([]any) require.True(t, ok) require.Len(t, list, 1) diff --git a/services/opensearch/handler_reserved_instances.go b/services/opensearch/handler_reserved_instances.go index 29c5550712..45276a1a41 100644 --- a/services/opensearch/handler_reserved_instances.go +++ b/services/opensearch/handler_reserved_instances.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleReservedInstancesRoutes handles GET /reservedInstances → DescribeReservedInstances. @@ -68,7 +69,7 @@ func (h *Handler) handlePurchaseReservedInstanceOffering(w http.ResponseWriter, InstanceCount int `json:"InstanceCount"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if req.InstanceCount == 0 { diff --git a/services/opensearch/handler_reserved_instances_test.go b/services/opensearch/handler_reserved_instances_test.go index 7d1b67ab08..2aed7d8114 100644 --- a/services/opensearch/handler_reserved_instances_test.go +++ b/services/opensearch/handler_reserved_instances_test.go @@ -1,12 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { @@ -21,7 +24,7 @@ func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { require.Equal(t, http.StatusOK, lor.StatusCode) var loOut map[string]any - require.NoError(t, json.NewDecoder(lor.Body).Decode(&loOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lor.Body), &loOut, jsonx.V1())) offerings, ok := loOut["ReservedInstanceOfferings"].([]any) require.True(t, ok) require.NotEmpty(t, offerings, "must have at least one offering") @@ -40,7 +43,7 @@ func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { require.Equal(t, http.StatusOK, pr.StatusCode) var pOut map[string]any - require.NoError(t, json.NewDecoder(pr.Body).Decode(&pOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(pr.Body), &pOut, jsonx.V1())) assert.NotEmpty(t, pOut["ReservedInstanceId"]) assert.Equal(t, "my-reservation", pOut["ReservationName"]) @@ -51,7 +54,7 @@ func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) instances, ok := dOut["ReservedInstances"].([]any) require.True(t, ok) require.Len(t, instances, 1) @@ -67,7 +70,7 @@ func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { require.Equal(t, http.StatusOK, fr.StatusCode) var fOut map[string]any - require.NoError(t, json.NewDecoder(fr.Body).Decode(&fOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(fr.Body), &fOut, jsonx.V1())) filtered := fOut["ReservedInstances"].([]any) require.Len(t, filtered, 1) assert.Equal(t, reservationID, filtered[0].(map[string]any)["ReservedInstanceId"]) @@ -79,7 +82,7 @@ func TestReservedInstances_ListOfferingsAndPurchase(t *testing.T) { require.Equal(t, http.StatusOK, ofr.StatusCode) var ofOut map[string]any - require.NoError(t, json.NewDecoder(ofr.Body).Decode(&ofOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ofr.Body), &ofOut, jsonx.V1())) filteredOfferings := ofOut["ReservedInstanceOfferings"].([]any) require.Len(t, filteredOfferings, 1) assert.Equal(t, offeringID, filteredOfferings[0].(map[string]any)["ReservedInstanceOfferingId"]) diff --git a/services/opensearch/handler_scheduled_actions.go b/services/opensearch/handler_scheduled_actions.go index a8aad1267c..39c36a60bc 100644 --- a/services/opensearch/handler_scheduled_actions.go +++ b/services/opensearch/handler_scheduled_actions.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // updateScheduledActionRequest is the JSON request body for @@ -30,7 +31,7 @@ func (h *Handler) handleUpdateScheduledAction(w http.ResponseWriter, r *http.Req var req updateScheduledActionRequest if len(body) > 0 { - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_scheduled_actions_test.go b/services/opensearch/handler_scheduled_actions_test.go index b72706b05b..e01eceb547 100644 --- a/services/opensearch/handler_scheduled_actions_test.go +++ b/services/opensearch/handler_scheduled_actions_test.go @@ -1,13 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -32,7 +34,7 @@ func TestScheduledActions_ListForDomain(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) actions, ok := out["ScheduledActions"].([]any) require.True(t, ok) require.Len(t, actions, 1) @@ -45,7 +47,7 @@ func TestScheduledActions_ListForDomain(t *testing.T) { require.Equal(t, http.StatusOK, otherResp.StatusCode) var otherOut map[string]any - require.NoError(t, json.NewDecoder(otherResp.Body).Decode(&otherOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(otherResp.Body), &otherOut, jsonx.V1())) assert.Empty(t, otherOut["ScheduledActions"]) } @@ -75,7 +77,7 @@ func TestScheduledActions_UpdateReschedulesExistingAction(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) action, ok := out["ScheduledAction"].(map[string]any) require.True(t, ok) assert.Equal(t, "action-upd", action["Id"]) diff --git a/services/opensearch/handler_serverless.go b/services/opensearch/handler_serverless.go index 3bed19a7c2..951544f995 100644 --- a/services/opensearch/handler_serverless.go +++ b/services/opensearch/handler_serverless.go @@ -1,11 +1,12 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -101,7 +102,7 @@ func (h *Handler) handleServerlessCollectionCreate(w http.ResponseWriter, r *htt KmsKeyArn string `json:"kmsKeyArn"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } coll, err := h.Backend.CreateServerlessCollection( @@ -166,7 +167,7 @@ func (h *Handler) handleServerlessCollectionBatchRoutes(w http.ResponseWriter, r Names []string `json:"names"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } colls := h.Backend.BatchGetServerlessCollections(req.IDs, req.Names) if colls == nil { @@ -217,7 +218,7 @@ func (h *Handler) handleServerlessPolicyCRUDRoot( Description string `json:"description"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } result, err := ops.create(req.Type, req.Name, req.Description, req.Policy) if err != nil { @@ -265,7 +266,7 @@ func (h *Handler) handleServerlessPolicyCRUDByName( PolicyVersion string `json:"policyVersion"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } result, err := ops.update(policyType, name, req.Description, req.Policy, req.PolicyVersion) if err != nil { @@ -379,7 +380,7 @@ func (h *Handler) handleServerlessSecurityConfigCollection(w http.ResponseWriter Description string `json:"description"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } sc, err := h.Backend.CreateServerlessSecurityConfig( req.Type, @@ -428,7 +429,7 @@ func (h *Handler) handleServerlessSecurityConfigItem(w http.ResponseWriter, r *h ConfigVersion string `json:"configVersion"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } sc, err := h.Backend.UpdateServerlessSecurityConfig( id, @@ -512,7 +513,7 @@ func (h *Handler) handleServerlessNetworkPolicyRoutes( Description string `json:"description"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } np, err := h.Backend.CreateServerlessNetworkPolicy( req.Type, diff --git a/services/opensearch/handler_serverless_jsonrpc.go b/services/opensearch/handler_serverless_jsonrpc.go index e9c47a43e2..58fd5ea3d3 100644 --- a/services/opensearch/handler_serverless_jsonrpc.go +++ b/services/opensearch/handler_serverless_jsonrpc.go @@ -1,7 +1,8 @@ package opensearch import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "sort" @@ -10,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // openSearchServerlessTargetPrefix is the real opensearchserverless@v1.34.4 @@ -72,7 +74,7 @@ func (h *Handler) handleServerlessJSONRPC(c *echo.Context, op string) error { var input map[string]any if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &input); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &input, jsonx.V1()); jsonErr != nil { return awserr.Write(c, awserr.ProtocolJSON10, awserr.APIError{ Code: errValidation, Message: "invalid JSON", @@ -100,7 +102,7 @@ func (h *Handler) handleServerlessJSONRPC(c *echo.Context, op string) error { return awserr.Write(c, awserr.ProtocolJSON10, apiErr) } - payload, marshalErr := json.Marshal(out) + payload, marshalErr := json.Marshal(out, jsonx.V1()) if marshalErr != nil { return awserr.Write(c, awserr.ProtocolJSON10, serverlessInternalError()) } @@ -697,7 +699,7 @@ func policyDetailJR(v any) map[string]any { m["description"] = pl.Description } if pl.Policy != "" { - m["policy"] = json.RawMessage(pl.Policy) + m["policy"] = jsontext.Value(pl.Policy) } return m @@ -732,13 +734,13 @@ func decodeSAMLOptionsJR(raw any) *ServerlessSAMLOptions { return nil } - b, err := json.Marshal(m) + b, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil } var opts ServerlessSAMLOptions - if unmarshalErr := json.Unmarshal(b, &opts); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(b, &opts, jsonx.V1()); unmarshalErr != nil { return nil } diff --git a/services/opensearch/handler_serverless_real_client_test.go b/services/opensearch/handler_serverless_real_client_test.go index 17f0134206..968fa95f0c 100644 --- a/services/opensearch/handler_serverless_real_client_test.go +++ b/services/opensearch/handler_serverless_real_client_test.go @@ -1,7 +1,7 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -70,7 +71,7 @@ func decodeDocument(t *testing.T, doc interface{ UnmarshalSmithyDocument(v any) var v any require.NoError(t, doc.UnmarshalSmithyDocument(&v)) - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return string(b) diff --git a/services/opensearch/handler_serverless_test.go b/services/opensearch/handler_serverless_test.go index cb6d55947a..9614485870 100644 --- a/services/opensearch/handler_serverless_test.go +++ b/services/opensearch/handler_serverless_test.go @@ -1,13 +1,15 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -43,7 +45,7 @@ func TestServerless_CreateCollection(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail, ok := out["createCollectionDetail"].(map[string]any) require.True(t, ok, "createCollectionDetail missing") @@ -67,7 +69,7 @@ func TestServerless_CreateCollection_DefaultType(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["createCollectionDetail"].(map[string]any) assert.Equal(t, "SEARCH", detail["type"]) } @@ -92,7 +94,7 @@ func TestServerless_BatchGetCollections(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) details, ok := out["collectionDetails"].([]any) require.True(t, ok) @@ -116,7 +118,7 @@ func TestServerless_ListCollections(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) summaries, ok := out["collectionSummaries"].([]any) require.True(t, ok) @@ -132,7 +134,7 @@ func TestServerless_DeleteCollection(t *testing.T) { createResp := doRequest(t, h, http.MethodPost, "/2021-11-01/opensearch/serverless/collection", map[string]any{"name": "to-delete"}) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() id := createOut["createCollectionDetail"].(map[string]any)["id"].(string) @@ -144,7 +146,7 @@ func TestServerless_DeleteCollection(t *testing.T) { assert.Equal(t, http.StatusOK, delResp.StatusCode) var delOut map[string]any - require.NoError(t, json.NewDecoder(delResp.Body).Decode(&delOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(delResp.Body), &delOut, jsonx.V1())) detail := delOut["deleteCollectionDetail"].(map[string]any) assert.Equal(t, "DELETED", detail["status"]) @@ -152,7 +154,7 @@ func TestServerless_DeleteCollection(t *testing.T) { listResp := doRequest(t, h, http.MethodGet, "/2021-11-01/opensearch/serverless/collections", nil) defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) summaries := listOut["collectionSummaries"].([]any) assert.Empty(t, summaries) } @@ -190,7 +192,7 @@ func TestServerless_CreateAccessPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail, ok := out["accessPolicyDetail"].(map[string]any) require.True(t, ok) @@ -221,7 +223,7 @@ func TestServerless_GetAccessPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["accessPolicyDetail"].(map[string]any) assert.Equal(t, "get-test", detail["name"]) } @@ -244,7 +246,7 @@ func TestServerless_ListAccessPolicies(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) summaries := out["accessPolicySummaries"].([]any) assert.Len(t, summaries, 2) } @@ -259,7 +261,7 @@ func TestServerless_UpdateAccessPolicy(t *testing.T) { map[string]any{"name": "update-ap", "type": "data", "policy": `[{"old":true}]`}) var createOut map[string]any - require.NoError(t, json.NewDecoder(r.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &createOut, jsonx.V1())) r.Body.Close() version := createOut["accessPolicyDetail"].(map[string]any)["policyVersion"].(string) @@ -276,7 +278,7 @@ func TestServerless_UpdateAccessPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["accessPolicyDetail"].(map[string]any) assert.Equal(t, "updated", detail["description"]) } @@ -300,7 +302,7 @@ func TestServerless_DeleteAccessPolicy(t *testing.T) { "/2021-11-01/opensearch/serverless/accesspolicies?type=data", nil) defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) assert.Empty(t, listOut["accessPolicySummaries"].([]any)) } @@ -339,7 +341,7 @@ func TestServerless_CreateSecurityConfig(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail, ok := out["securityConfigDetail"].(map[string]any) require.True(t, ok) @@ -357,7 +359,7 @@ func TestServerless_GetSecurityConfig(t *testing.T) { map[string]any{"type": "saml"}) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() id := createOut["securityConfigDetail"].(map[string]any)["id"].(string) @@ -368,7 +370,7 @@ func TestServerless_GetSecurityConfig(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, id, out["securityConfigDetail"].(map[string]any)["id"]) } @@ -390,7 +392,7 @@ func TestServerless_ListSecurityConfigs(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) summaries := out["securityConfigSummaries"].([]any) assert.Len(t, summaries, 3) } @@ -404,7 +406,7 @@ func TestServerless_UpdateSecurityConfig(t *testing.T) { map[string]any{"type": "saml", "description": "old"}) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() id := createOut["securityConfigDetail"].(map[string]any)["id"].(string) @@ -421,7 +423,7 @@ func TestServerless_UpdateSecurityConfig(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["securityConfigDetail"].(map[string]any) assert.Equal(t, "updated desc", detail["description"]) } @@ -435,7 +437,7 @@ func TestServerless_DeleteSecurityConfig(t *testing.T) { map[string]any{"type": "saml"}) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() id := createOut["securityConfigDetail"].(map[string]any)["id"].(string) @@ -472,7 +474,7 @@ func TestServerless_CreateEncryptionPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["encryptionPolicyDetail"].(map[string]any) assert.Equal(t, "enc-policy", detail["name"]) assert.NotEmpty(t, detail["policyVersion"]) @@ -495,7 +497,7 @@ func TestServerless_ListEncryptionPolicies(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) summaries := out["encryptionPolicySummaries"].([]any) assert.Len(t, summaries, 2) } @@ -515,7 +517,7 @@ func TestServerless_GetEncryptionPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, "get-ep", out["encryptionPolicyDetail"].(map[string]any)["name"]) } @@ -528,7 +530,7 @@ func TestServerless_UpdateEncryptionPolicy(t *testing.T) { map[string]any{"name": "upd-ep", "type": "encryption", "policy": `{"old":true}`}) var createOut map[string]any - require.NoError(t, json.NewDecoder(r.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(r.Body), &createOut, jsonx.V1())) r.Body.Close() version := createOut["encryptionPolicyDetail"].(map[string]any)["policyVersion"].(string) @@ -543,7 +545,7 @@ func TestServerless_UpdateEncryptionPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, "updated", out["encryptionPolicyDetail"].(map[string]any)["description"]) } @@ -587,7 +589,7 @@ func TestServerless_CreateNetworkPolicy(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) detail := out["networkPolicyDetail"].(map[string]any) assert.Equal(t, "net-policy", detail["name"]) } @@ -609,7 +611,7 @@ func TestServerless_ListNetworkPolicies(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) summaries := out["networkPolicySummaries"].([]any) assert.Len(t, summaries, 3) } @@ -655,7 +657,7 @@ func TestDomain_OffPeakWindowOptions_Create(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) st := out["DomainStatus"].(map[string]any) opw, ok := st["OffPeakWindowOptions"].(map[string]any) @@ -691,7 +693,7 @@ func TestDomain_OffPeakWindowOptions_UpdateConfig(t *testing.T) { assert.Equal(t, http.StatusOK, upResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(upResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(upResp.Body), &out, jsonx.V1())) cfg := out["DomainConfig"].(map[string]any) opwCfg := cfg["OffPeakWindowOptions"].(map[string]any) opwOpts := opwCfg["Options"].(map[string]any) @@ -721,7 +723,7 @@ func TestDomain_IdentityCenterOptions_Create(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) st := out["DomainStatus"].(map[string]any) idcOpts, ok := st["IdentityCenterOptions"].(map[string]any) @@ -752,7 +754,7 @@ func TestDomain_IdentityCenterOptions_UpdateConfig(t *testing.T) { assert.Equal(t, http.StatusOK, upResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(upResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(upResp.Body), &out, jsonx.V1())) cfg := out["DomainConfig"].(map[string]any) idcCfg := cfg["IdentityCenterOptions"].(map[string]any) idcOpts := idcCfg["Options"].(map[string]any) @@ -779,7 +781,7 @@ func TestDomain_EnableSoftwareUpdateOptions_Create(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) st := out["DomainStatus"].(map[string]any) swOpts, ok := st["SoftwareUpdateOptions"].(map[string]any) @@ -809,7 +811,7 @@ func TestDomain_ClusterConfigOmitsBlueGreenDeploymentOptions(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) cc := out["DomainStatus"].(map[string]any)["ClusterConfig"].(map[string]any) assert.NotContains(t, cc, "BlueGreenDeploymentOptions") assert.NotContains(t, cc, "ColdStorageEnabled") @@ -838,7 +840,7 @@ func TestPackage_CreateWithSource(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) pkg := out["PackageDetails"].(map[string]any) assert.Equal(t, "my-dictionary", pkg["PackageName"]) @@ -869,7 +871,7 @@ func TestPackage_CreateWithEncryptionOptions(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) pkg := out["PackageDetails"].(map[string]any) encOpts, ok := pkg["PackageEncryptionOptions"].(map[string]any) @@ -889,7 +891,7 @@ func TestPackage_AvailablePackageVersion(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) pkg := out["PackageDetails"].(map[string]any) assert.Equal(t, "1", pkg["AvailablePackageVersion"]) } @@ -908,7 +910,7 @@ func TestServerless_Persistence_CollectionsRoundTrip(t *testing.T) { map[string]any{"name": "persist-coll", "type": "TIMESERIES"}) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() origID := createOut["createCollectionDetail"].(map[string]any)["id"].(string) @@ -924,7 +926,7 @@ func TestServerless_Persistence_CollectionsRoundTrip(t *testing.T) { defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) summaries := listOut["collectionSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, origID, summaries[0].(map[string]any)["id"]) @@ -947,7 +949,7 @@ func TestServerless_Persistence_AccessPoliciesRoundTrip(t *testing.T) { defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) summaries := listOut["accessPolicySummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "persist-ap", summaries[0].(map[string]any)["name"]) diff --git a/services/opensearch/handler_tags.go b/services/opensearch/handler_tags.go index 8d35500958..5b495f50ef 100644 --- a/services/opensearch/handler_tags.go +++ b/services/opensearch/handler_tags.go @@ -1,10 +1,11 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -67,7 +68,7 @@ func (h *Handler) handleAddTags(w http.ResponseWriter, r *http.Request) { } var req addTagsInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -104,7 +105,7 @@ func (h *Handler) handleRemoveTags(w http.ResponseWriter, r *http.Request) { } var req removeTagsInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return diff --git a/services/opensearch/handler_tags_test.go b/services/opensearch/handler_tags_test.go index 84d393efe8..a75a99ccff 100644 --- a/services/opensearch/handler_tags_test.go +++ b/services/opensearch/handler_tags_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -21,7 +23,7 @@ func createDomainAndGetARN(t *testing.T, h *opensearch.Handler, domainName strin }) var createOut map[string]any - require.NoError(t, json.NewDecoder(createResp.Body).Decode(&createOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createResp.Body), &createOut, jsonx.V1())) createResp.Body.Close() status := createOut["DomainStatus"].(map[string]any) @@ -50,7 +52,7 @@ func TestOpenSearchHandler_AddTags(t *testing.T) { defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) tagList, ok := listOut["TagList"].([]any) require.True(t, ok) @@ -84,7 +86,7 @@ func TestOpenSearchHandler_RemoveTags(t *testing.T) { defer listResp.Body.Close() var listOut map[string]any - require.NoError(t, json.NewDecoder(listResp.Body).Decode(&listOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listResp.Body), &listOut, jsonx.V1())) tagList, ok := listOut["TagList"].([]any) require.True(t, ok) @@ -105,7 +107,7 @@ func TestOpenSearchHandler_ListTags_EmptyDomain(t *testing.T) { defer resp.Body.Close() var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) tagList, ok := out["TagList"].([]any) require.True(t, ok) diff --git a/services/opensearch/handler_test.go b/services/opensearch/handler_test.go index 117add802e..4658bc2a09 100644 --- a/services/opensearch/handler_test.go +++ b/services/opensearch/handler_test.go @@ -2,7 +2,7 @@ package opensearch_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -46,7 +47,7 @@ func doRequest(t *testing.T, h *opensearch.Handler, method, path string, body an var reqBody io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) diff --git a/services/opensearch/handler_vpc_endpoints.go b/services/opensearch/handler_vpc_endpoints.go index 1fb854c1bc..340232b15a 100644 --- a/services/opensearch/handler_vpc_endpoints.go +++ b/services/opensearch/handler_vpc_endpoints.go @@ -1,12 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // vpcEndpointSummaryJSON mirrors types.VpcEndpointSummary: DomainArn, Status, @@ -58,7 +59,7 @@ func (h *Handler) handleAuthorizeVpcEndpointAccess( } var req authorizeVpcEndpointAccessRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { h.writeError(r, w, http.StatusBadRequest, "ValidationException", "invalid JSON body") return @@ -95,7 +96,7 @@ func (h *Handler) handleVpcEndpointsRoutes(w http.ResponseWriter, r *http.Reques VpcEndpointIDs []string `json:"VpcEndpointIds"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } endpoints, errs := h.Backend.DescribeVpcEndpoints(req.VpcEndpointIDs) h.writeJSON(r, w, map[string]any{"VpcEndpoints": endpoints, "VpcEndpointErrors": errs}) @@ -130,7 +131,7 @@ func (h *Handler) handleUpdateVpcEndpoint(w http.ResponseWriter, r *http.Request VpcEndpointID string `json:"VpcEndpointId"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } ep, updateErr := h.Backend.UpdateVpcEndpoint(req.VpcEndpointID, req.VpcOptions) @@ -158,7 +159,7 @@ func (h *Handler) handleVpcEndpointRootRoutes(w http.ResponseWriter, r *http.Req DomainArn string `json:"DomainArn"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } ep, createErr := h.Backend.CreateVpcEndpoint(req.DomainArn, req.VpcOptions) if createErr != nil { diff --git a/services/opensearch/handler_vpc_endpoints_test.go b/services/opensearch/handler_vpc_endpoints_test.go index 3ff1e04797..b22b99ab4d 100644 --- a/services/opensearch/handler_vpc_endpoints_test.go +++ b/services/opensearch/handler_vpc_endpoints_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -102,7 +104,7 @@ func TestVpcEndpoints_CreateAndList(t *testing.T) { require.Equal(t, http.StatusOK, cr.StatusCode) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) ep := cOut["VpcEndpoint"].(map[string]any) assert.NotEmpty(t, ep["VpcEndpointId"]) assert.Equal(t, "ACTIVE", ep["Status"]) @@ -120,7 +122,7 @@ func TestVpcEndpoints_CreateAndList(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) eps, ok := lOut["VpcEndpointSummaryList"].([]any) require.True(t, ok) assert.Len(t, eps, 1) @@ -175,7 +177,7 @@ func TestVpcEndpoints_ListOmitsGetOnlyFields(t *testing.T) { require.Equal(t, http.StatusOK, lr.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &out, jsonx.V1())) items, ok := out[tt.key].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -205,7 +207,7 @@ func TestVpcEndpoints_DescribeByIDs(t *testing.T) { cr := doRequest(t, h, http.MethodPost, "/2021-01-01/opensearch/vpcEndpoints", map[string]any{"DomainArn": domARN, "VpcOptions": map[string]any{}}) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) cr.Body.Close() epID := cOut["VpcEndpoint"].(map[string]any)["VpcEndpointId"].(string) @@ -216,7 +218,7 @@ func TestVpcEndpoints_DescribeByIDs(t *testing.T) { require.Equal(t, http.StatusOK, dr.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) described, ok := dOut["VpcEndpoints"].([]any) require.True(t, ok) assert.Len(t, described, 1) @@ -232,7 +234,7 @@ func TestVpcEndpoints_UpdateAndDelete(t *testing.T) { cr := doRequest(t, h, http.MethodPost, "/2021-01-01/opensearch/vpcEndpoints", map[string]any{"DomainArn": domARN, "VpcOptions": map[string]any{}}) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) cr.Body.Close() epID := cOut["VpcEndpoint"].(map[string]any)["VpcEndpointId"].(string) @@ -248,7 +250,7 @@ func TestVpcEndpoints_UpdateAndDelete(t *testing.T) { require.Equal(t, http.StatusOK, del.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(del.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(del.Body), &dOut, jsonx.V1())) summary := dOut["VpcEndpointSummary"].(map[string]any) assert.Equal(t, epID, summary["VpcEndpointId"]) assert.Equal(t, domARN, summary["DomainArn"]) @@ -258,7 +260,7 @@ func TestVpcEndpoints_UpdateAndDelete(t *testing.T) { lr := doRequest(t, h, http.MethodGet, "/2021-01-01/opensearch/vpcEndpoints", nil) defer lr.Body.Close() var lOut map[string]any - require.NoError(t, json.NewDecoder(lr.Body).Decode(&lOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(lr.Body), &lOut, jsonx.V1())) eps := lOut["VpcEndpointSummaryList"].([]any) assert.Empty(t, eps) } @@ -304,7 +306,7 @@ func TestVpcEndpoints_DescribeUnknownIDReturnsEndpointNotFoundError(t *testing.T require.Equal(t, http.StatusOK, dr.StatusCode) var dOut map[string]any - require.NoError(t, json.NewDecoder(dr.Body).Decode(&dOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(dr.Body), &dOut, jsonx.V1())) errs, ok := dOut["VpcEndpointErrors"].([]any) require.True(t, ok) require.Len(t, errs, 1) diff --git a/services/opensearch/interfaces.go b/services/opensearch/interfaces.go index 34262241f8..1f74cdc80e 100644 --- a/services/opensearch/interfaces.go +++ b/services/opensearch/interfaces.go @@ -2,7 +2,7 @@ package opensearch import ( "context" - "encoding/json" + "encoding/json/jsontext" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -48,16 +48,16 @@ type StorageBackend interface { DeleteOutboundConnection(connectionID string) (*OutboundConnection, error) // Data source operations - AddDataSource(domainName, name, description string, dataSourceType json.RawMessage) (string, error) + AddDataSource(domainName, name, description string, dataSourceType jsontext.Value) (string, error) GetDataSource(domainName, name string) (*DataSource, error) ListDataSources(domainName string) ([]*DataSource, error) - UpdateDataSource(domainName, name, description string, dataSourceType json.RawMessage, status string) error + UpdateDataSource(domainName, name, description string, dataSourceType jsontext.Value, status string) error DeleteDataSource(domainName, name string) error // Direct-query data source operations AddDirectQueryDataSource( name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, openSearchArns []string, dataSourceAccessPolicy ...string, ) (string, error) @@ -65,7 +65,7 @@ type StorageBackend interface { GetDirectQueryDataSource(name string) (*DirectQueryDataSource, error) UpdateDirectQueryDataSource( name, description string, - dataSourceType json.RawMessage, + dataSourceType jsontext.Value, openSearchArns []string, dataSourceAccessPolicy string, ) (*DirectQueryDataSource, error) diff --git a/services/opensearch/lifecycle_policies.go b/services/opensearch/lifecycle_policies.go index 7c685a0e92..85760fa302 100644 --- a/services/opensearch/lifecycle_policies.go +++ b/services/opensearch/lifecycle_policies.go @@ -1,11 +1,13 @@ package opensearch import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // slLifecyclePolicyResourceTypeIndex is the only real ResourceType value @@ -53,7 +55,7 @@ type lifecyclePolicyDocument struct { // (matching every other serverless policy family in this package). func parseLifecycleRules(policy string) []lifecycleRule { var doc lifecyclePolicyDocument - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return nil } diff --git a/services/opensearch/models.go b/services/opensearch/models.go index afd93ec76f..6f002682be 100644 --- a/services/opensearch/models.go +++ b/services/opensearch/models.go @@ -1,7 +1,7 @@ package opensearch import ( - "encoding/json" + "encoding/json/jsontext" "regexp" "time" @@ -196,11 +196,11 @@ type InboundConnection struct { // DataSource represents a data source attached to an OpenSearch domain. type DataSource struct { - Name string `json:"name"` - Description string `json:"description"` - Status string `json:"status,omitempty"` - DomainName string `json:"-"` - DataSourceType json.RawMessage `json:"dataSourceType,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + Status string `json:"status,omitempty"` + DomainName string `json:"-"` + DataSourceType jsontext.Value `json:"dataSourceType,omitempty"` } // DirectQueryDataSource represents a direct-query data source. @@ -208,12 +208,12 @@ type DirectQueryDataSource struct { // DataSourceType is stored as raw JSON for the same reason as // DataSource.DataSourceType above -- types.DirectQueryDataSourceType is // also a tagged union (CloudWatchLog / SecurityLake members). - DataSourceType json.RawMessage `json:"dataSourceType,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - DataSourceArn string `json:"dataSourceArn"` - DataSourceAccessPolicy string `json:"dataSourceAccessPolicy,omitempty"` - OpenSearchArns []string `json:"openSearchArns"` + DataSourceType jsontext.Value `json:"dataSourceType,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + DataSourceArn string `json:"dataSourceArn"` + DataSourceAccessPolicy string `json:"dataSourceAccessPolicy,omitempty"` + OpenSearchArns []string `json:"openSearchArns"` } // DomainPackageDetails holds details about a package associated with a domain. diff --git a/services/opensearch/multi_region_test.go b/services/opensearch/multi_region_test.go index f64f2ac3e4..a3e70f5598 100644 --- a/services/opensearch/multi_region_test.go +++ b/services/opensearch/multi_region_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opensearch" ) @@ -38,7 +40,7 @@ func regionDo(t *testing.T, h *opensearch.Handler, region, method, path, body st out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out @@ -127,9 +129,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/opensearch/persistence.go b/services/opensearch/persistence.go index 1120d80970..06ff58d6d4 100644 --- a/services/opensearch/persistence.go +++ b/services/opensearch/persistence.go @@ -2,7 +2,7 @@ package opensearch import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -118,11 +118,11 @@ func fromDryRunSnapshot(v *dryRunSnapshot) *DryRunStatus { } type dataSourceSnapshot struct { - Name string `json:"name"` - Description string `json:"description"` - Status string `json:"status,omitempty"` - DomainName string `json:"domainName"` - DataSourceType json.RawMessage `json:"dataSourceType,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + Status string `json:"status,omitempty"` + DomainName string `json:"domainName"` + DataSourceType jsontext.Value `json:"dataSourceType,omitempty"` } func dataSourceSnapshotKey(v *dataSourceSnapshot) string { return dataSourceKey(v.DomainName, v.Name) } @@ -381,7 +381,7 @@ var dirtyTableNames = struct { // conversion notes. type backendSnapshot struct { AccountCapacityLimits ServerlessCapacityLimits `json:"accountCapacityLimits"` - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` VpcAuthorizations map[string][]AuthorizedPrincipal `json:"vpcAuthorizations"` ScheduledActions map[string][]*ScheduledAction `json:"scheduledActions"` PackageAssociations map[string]map[string]bool `json:"packageAssociations"` diff --git a/services/opensearch/persistence_test.go b/services/opensearch/persistence_test.go index ab2a20ce0a..52b7dad38c 100644 --- a/services/opensearch/persistence_test.go +++ b/services/opensearch/persistence_test.go @@ -1,7 +1,7 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" "net/http" "net/http/httptest" "testing" @@ -633,10 +633,10 @@ func TestOpenSearchHandler_Persistence_AdditionalResources(t *testing.T) { opensearch.SeedInboundConnection(b, "conn-abc") - _, err = b.AddDataSource("snap-domain", "my-ds", "desc", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err = b.AddDataSource("snap-domain", "my-ds", "desc", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.NoError(t, err) - _, err = b.AddDirectQueryDataSource("my-dq", "desc", json.RawMessage(`{"CloudWatchLog":{}}`), []string{}) + _, err = b.AddDirectQueryDataSource("my-dq", "desc", jsontext.Value(`{"CloudWatchLog":{}}`), []string{}) require.NoError(t, err) b.AddPackageInternal("pkg-001", "test-pkg", "TXT-DICTIONARY") @@ -786,7 +786,7 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { require.NoError(t, err) // "Dirty" DTO tables: domainDataSources, domainIndexes, dryRuns. - _, err = original.AddDataSource(domain.Name, "ds-1", "a data source", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err = original.AddDataSource(domain.Name, "ds-1", "a data source", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.NoError(t, err) _, err = original.CreateIndex(domain.Name, "idx-1", nil, nil, nil, nil) @@ -806,7 +806,7 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { _, err = original.AddDirectQueryDataSource( "dq-1", "a direct query source", - json.RawMessage(`{"CloudWatchLog":{}}`), + jsontext.Value(`{"CloudWatchLog":{}}`), nil, ) require.NoError(t, err) diff --git a/services/opensearch/store_test.go b/services/opensearch/store_test.go index 8035a6941c..ed03f21384 100644 --- a/services/opensearch/store_test.go +++ b/services/opensearch/store_test.go @@ -1,7 +1,7 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" "testing" "github.com/stretchr/testify/assert" @@ -67,10 +67,10 @@ func TestExportCounts(t *testing.T) { opensearch.SeedInboundConnection(b, "conn-1") - _, err := b.AddDataSource("d1", "ds-1", "desc", json.RawMessage(`{"S3GlueDataCatalog":{}}`)) + _, err := b.AddDataSource("d1", "ds-1", "desc", jsontext.Value(`{"S3GlueDataCatalog":{}}`)) require.NoError(t, err) - _, err = b.AddDirectQueryDataSource("dq-1", "desc", json.RawMessage(`{"CloudWatchLog":{}}`), nil) + _, err = b.AddDirectQueryDataSource("dq-1", "desc", jsontext.Value(`{"CloudWatchLog":{}}`), nil) require.NoError(t, err) _, err = b.CreateApplication("app-1", nil, nil, nil) diff --git a/services/opensearch/wire_field_fixes_test.go b/services/opensearch/wire_field_fixes_test.go index 9623549ddf..2ace603785 100644 --- a/services/opensearch/wire_field_fixes_test.go +++ b/services/opensearch/wire_field_fixes_test.go @@ -1,7 +1,8 @@ package opensearch_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +12,8 @@ import ( opensearchsdktypes "github.com/aws/aws-sdk-go-v2/service/opensearch/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestUpgradeDomain_RealSDKClient proves UpgradeDomainOutput @@ -64,7 +67,7 @@ func TestUpgradeDomain_RawBody_NoInventedStepStatus(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) _, hasStepStatus := out["StepStatus"] assert.False(t, hasStepStatus, "UpgradeDomainOutput has no StepStatus member") @@ -87,7 +90,7 @@ func TestVpcEndpoint_RawBody_NoLeakedStatusUntil(t *testing.T) { cr := doRequest(t, h, http.MethodPost, "/2021-01-01/opensearch/vpcEndpoints", map[string]any{"DomainArn": domARN, "VpcOptions": map[string]any{"SubnetIds": []string{"subnet-1"}}}) var cOut map[string]any - require.NoError(t, json.NewDecoder(cr.Body).Decode(&cOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(cr.Body), &cOut, jsonx.V1())) cr.Body.Close() epID := cOut["VpcEndpoint"].(map[string]any)["VpcEndpointId"].(string) @@ -100,7 +103,7 @@ func TestVpcEndpoint_RawBody_NoLeakedStatusUntil(t *testing.T) { require.Equal(t, http.StatusOK, descResp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(descResp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(descResp.Body), &out, jsonx.V1())) endpoints, ok := out["VpcEndpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 1, "endpoint must still be present during its DELETING window") diff --git a/services/opsworks/handler.go b/services/opsworks/handler.go index 29b3c85410..41204d20b2 100644 --- a/services/opsworks/handler.go +++ b/services/opsworks/handler.go @@ -2,7 +2,7 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -270,13 +271,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrNotFound): return writeError(c, http.StatusBadRequest, errResp("ResourceNotFoundException", err.Error())) @@ -287,8 +285,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err // ValidationException, not 501. return writeError(c, http.StatusBadRequest, errResp("ValidationException", err.Error())) case errors.Is(err, errInvalidRequest), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): return writeError(c, http.StatusBadRequest, errResp("ValidationException", err.Error())) default: logger.Load(c.Request().Context()).ErrorContext(c.Request().Context(), "opsworks error", "error", err) diff --git a/services/opsworks/handler_agent_versions.go b/services/opsworks/handler_agent_versions.go index aa310db815..c42b2b202b 100644 --- a/services/opsworks/handler_agent_versions.go +++ b/services/opsworks/handler_agent_versions.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDescribeAgentVersions handles DescribeAgentVersions requests. @@ -17,7 +19,7 @@ func (h *Handler) handleDescribeAgentVersions(_ context.Context, body []byte) (a } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_apps.go b/services/opsworks/handler_apps.go index 067c5359f6..5a5184dd70 100644 --- a/services/opsworks/handler_apps.go +++ b/services/opsworks/handler_apps.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateApp handles CreateApp requests. @@ -15,7 +17,7 @@ func (h *Handler) handleCreateApp(_ context.Context, body []byte) (any, error) { AppOptions } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -35,7 +37,7 @@ func (h *Handler) handleDescribeApps(_ context.Context, body []byte) (any, error } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -57,7 +59,7 @@ func (h *Handler) handleUpdateApp(_ context.Context, body []byte) (any, error) { AppOptions } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -74,7 +76,7 @@ func (h *Handler) handleDeleteApp(_ context.Context, body []byte) (any, error) { AppID string `json:"AppId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_commands.go b/services/opsworks/handler_commands.go index 404792631b..b26858f30e 100644 --- a/services/opsworks/handler_commands.go +++ b/services/opsworks/handler_commands.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDescribeCommands handles DescribeCommands requests. @@ -16,7 +18,7 @@ func (h *Handler) handleDescribeCommands(_ context.Context, body []byte) (any, e } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_deployments.go b/services/opsworks/handler_deployments.go index e1322b004c..64c329ac6a 100644 --- a/services/opsworks/handler_deployments.go +++ b/services/opsworks/handler_deployments.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateDeployment handles CreateDeployment requests. @@ -20,7 +22,7 @@ func (h *Handler) handleCreateDeployment(_ context.Context, body []byte) (any, e LayerIDs []string `json:"LayerIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -44,7 +46,7 @@ func (h *Handler) handleDescribeDeployments(_ context.Context, body []byte) (any } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_ecs_clusters.go b/services/opsworks/handler_ecs_clusters.go index 12fdb7634f..69f6c65340 100644 --- a/services/opsworks/handler_ecs_clusters.go +++ b/services/opsworks/handler_ecs_clusters.go @@ -2,9 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -21,7 +22,7 @@ func (h *Handler) handleRegisterEcsCluster(_ context.Context, body []byte) (any, StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -39,7 +40,7 @@ func (h *Handler) handleDeregisterEcsCluster(_ context.Context, body []byte) (an EcsClusterArn string `json:"EcsClusterArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -60,7 +61,7 @@ func (h *Handler) handleDescribeEcsClusters(_ context.Context, body []byte) (any } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_elastic_ips.go b/services/opsworks/handler_elastic_ips.go index 0862569cda..b5640218d2 100644 --- a/services/opsworks/handler_elastic_ips.go +++ b/services/opsworks/handler_elastic_ips.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleRegisterElasticIP handles RegisterElasticIp requests. The real @@ -16,7 +18,7 @@ func (h *Handler) handleRegisterElasticIP(_ context.Context, body []byte) (any, StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -34,7 +36,7 @@ func (h *Handler) handleDeregisterElasticIP(_ context.Context, body []byte) (any ElasticIP string `json:"ElasticIp"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -52,7 +54,7 @@ func (h *Handler) handleAssociateElasticIP(_ context.Context, body []byte) (any, InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -69,7 +71,7 @@ func (h *Handler) handleDisassociateElasticIP(_ context.Context, body []byte) (a ElasticIP string `json:"ElasticIp"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -89,7 +91,7 @@ func (h *Handler) handleDescribeElasticIps(_ context.Context, body []byte) (any, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -109,7 +111,7 @@ func (h *Handler) handleUpdateElasticIP(_ context.Context, body []byte) (any, er Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_elastic_load_balancers.go b/services/opsworks/handler_elastic_load_balancers.go index 8601ec67bb..d90a8c361b 100644 --- a/services/opsworks/handler_elastic_load_balancers.go +++ b/services/opsworks/handler_elastic_load_balancers.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleAttachElasticLoadBalancer handles AttachElasticLoadBalancer requests. @@ -13,7 +15,7 @@ func (h *Handler) handleAttachElasticLoadBalancer(_ context.Context, body []byte LayerID string `json:"LayerId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +33,7 @@ func (h *Handler) handleDetachElasticLoadBalancer(_ context.Context, body []byte LayerID string `json:"LayerId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -50,7 +52,7 @@ func (h *Handler) handleDescribeElasticLoadBalancers(_ context.Context, body []b } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_instances.go b/services/opsworks/handler_instances.go index 598ef5ceba..1d775260c4 100644 --- a/services/opsworks/handler_instances.go +++ b/services/opsworks/handler_instances.go @@ -2,10 +2,11 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" ) @@ -25,7 +26,7 @@ func (h *Handler) handleCreateInstance(_ context.Context, body []byte) (any, err LayerIDs []string `json:"LayerIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -56,7 +57,7 @@ func (h *Handler) handleRegisterInstance(_ context.Context, body []byte) (any, e InstanceExtras } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -74,7 +75,7 @@ func (h *Handler) handleDeregisterInstance(_ context.Context, body []byte) (any, InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -92,7 +93,7 @@ func (h *Handler) handleAssignInstance(_ context.Context, body []byte) (any, err LayerIDs []string `json:"LayerIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -109,7 +110,7 @@ func (h *Handler) handleUnassignInstance(_ context.Context, body []byte) (any, e InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -129,7 +130,7 @@ func (h *Handler) handleDescribeInstances(_ context.Context, body []byte) (any, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -156,7 +157,7 @@ func (h *Handler) handleUpdateInstance(_ context.Context, body []byte) (any, err LayerIDs []string `json:"LayerIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -185,7 +186,7 @@ func (h *Handler) handleDeleteInstance(_ context.Context, body []byte) (any, err InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -204,7 +205,7 @@ func (h *Handler) handleStartInstance(_ context.Context, body []byte) (any, erro InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -221,7 +222,7 @@ func (h *Handler) handleStopInstance(_ context.Context, body []byte) (any, error InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -238,7 +239,7 @@ func (h *Handler) handleRebootInstance(_ context.Context, body []byte) (any, err InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -276,9 +277,9 @@ func instancesToJSON(instances []*Instance) []map[string]any { "ReportedOs": map[string]any{}, } - if raw, err := json.Marshal(i.Extras); err == nil { + if raw, err := json.Marshal(i.Extras, jsonx.V1()); err == nil { var extra map[string]any - if json.Unmarshal(raw, &extra) == nil { + if json.Unmarshal(raw, &extra, jsonx.V1()) == nil { maps.Copy(m, extra) } } diff --git a/services/opsworks/handler_layers.go b/services/opsworks/handler_layers.go index b776cfd869..0ffb64302d 100644 --- a/services/opsworks/handler_layers.go +++ b/services/opsworks/handler_layers.go @@ -2,9 +2,11 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateLayer handles CreateLayer requests. @@ -17,7 +19,7 @@ func (h *Handler) handleCreateLayer(_ context.Context, body []byte) (any, error) LayerSettings } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -37,7 +39,7 @@ func (h *Handler) handleDescribeLayers(_ context.Context, body []byte) (any, err } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -59,7 +61,7 @@ func (h *Handler) handleUpdateLayer(_ context.Context, body []byte) (any, error) LayerSettings } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -76,7 +78,7 @@ func (h *Handler) handleDeleteLayer(_ context.Context, body []byte) (any, error) LayerID string `json:"LayerId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -121,9 +123,9 @@ func layersToJSON(layers []*Layer) []map[string]any { "Attributes": attrs, } - if raw, err := json.Marshal(l.Settings); err == nil { + if raw, err := json.Marshal(l.Settings, jsonx.V1()); err == nil { var extra map[string]any - if json.Unmarshal(raw, &extra) == nil { + if json.Unmarshal(raw, &extra, jsonx.V1()) == nil { maps.Copy(m, extra) } } diff --git a/services/opsworks/handler_load_based_scaling.go b/services/opsworks/handler_load_based_scaling.go index 057ad6731e..942075ac0c 100644 --- a/services/opsworks/handler_load_based_scaling.go +++ b/services/opsworks/handler_load_based_scaling.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleSetLoadBasedAutoScaling handles SetLoadBasedAutoScaling requests. @@ -15,7 +17,7 @@ func (h *Handler) handleSetLoadBasedAutoScaling(_ context.Context, body []byte) Enable bool `json:"Enable"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -33,7 +35,7 @@ func (h *Handler) handleDescribeLoadBasedAutoScaling(_ context.Context, body []b } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_rds_db_instances.go b/services/opsworks/handler_rds_db_instances.go index c8dfdaf3a6..fc783768ff 100644 --- a/services/opsworks/handler_rds_db_instances.go +++ b/services/opsworks/handler_rds_db_instances.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleRegisterRdsDBInstance handles RegisterRdsDbInstance requests. @@ -15,7 +17,7 @@ func (h *Handler) handleRegisterRdsDBInstance(_ context.Context, body []byte) (a DBPassword string `json:"DbPassword"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -34,7 +36,7 @@ func (h *Handler) handleDeregisterRdsDBInstance(_ context.Context, body []byte) RdsDBInstanceArn string `json:"RdsDbInstanceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -53,7 +55,7 @@ func (h *Handler) handleDescribeRdsDBInstances(_ context.Context, body []byte) ( } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -74,7 +76,7 @@ func (h *Handler) handleUpdateRdsDBInstance(_ context.Context, body []byte) (any DBPassword string `json:"DbPassword"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_service_errors.go b/services/opsworks/handler_service_errors.go index e6c43b18ef..cfcbe37102 100644 --- a/services/opsworks/handler_service_errors.go +++ b/services/opsworks/handler_service_errors.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleDescribeServiceErrors handles DescribeServiceErrors requests. @@ -15,7 +17,7 @@ func (h *Handler) handleDescribeServiceErrors(_ context.Context, body []byte) (a } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -37,7 +39,7 @@ func (h *Handler) handleDescribeRaidArrays(_ context.Context, body []byte) (any, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_stacks.go b/services/opsworks/handler_stacks.go index 6c4f58813f..800c37c4ce 100644 --- a/services/opsworks/handler_stacks.go +++ b/services/opsworks/handler_stacks.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateStack handles CreateStack requests. @@ -36,7 +38,7 @@ func (h *Handler) handleCreateStack(_ context.Context, body []byte) (any, error) Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -114,7 +116,7 @@ func (h *Handler) handleCloneStack(_ context.Context, body []byte) (any, error) CloneAppIDs []string `json:"CloneAppIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -164,7 +166,7 @@ func (h *Handler) handleDescribeStacks(_ context.Context, body []byte) (any, err } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -206,7 +208,7 @@ func (h *Handler) handleUpdateStack(_ context.Context, body []byte) (any, error) StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -252,7 +254,7 @@ func (h *Handler) handleDeleteStack(_ context.Context, body []byte) (any, error) StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -269,7 +271,7 @@ func (h *Handler) handleStartStack(_ context.Context, body []byte) (any, error) StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -286,7 +288,7 @@ func (h *Handler) handleStopStack(_ context.Context, body []byte) (any, error) { StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -303,7 +305,7 @@ func (h *Handler) handleGetHostnameSuggestion(_ context.Context, body []byte) (a LayerID string `json:"LayerId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -321,7 +323,7 @@ func (h *Handler) handleDescribeStackSummary(_ context.Context, body []byte) (an StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -339,7 +341,7 @@ func (h *Handler) handleDescribeStackProvisioningParameters(_ context.Context, b StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_tags.go b/services/opsworks/handler_tags.go index 3c10d43636..f8225e36e4 100644 --- a/services/opsworks/handler_tags.go +++ b/services/opsworks/handler_tags.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleTagResource handles TagResource requests. @@ -13,7 +15,7 @@ func (h *Handler) handleTagResource(_ context.Context, body []byte) (any, error) ResourceArn string `json:"ResourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +33,7 @@ func (h *Handler) handleUntagResource(_ context.Context, body []byte) (any, erro TagKeys []string `json:"TagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -50,7 +52,7 @@ func (h *Handler) handleListTags(_ context.Context, body []byte) (any, error) { MaxResults int32 `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_test.go b/services/opsworks/handler_test.go index 1964c9ab5a..836123741e 100644 --- a/services/opsworks/handler_test.go +++ b/services/opsworks/handler_test.go @@ -2,7 +2,7 @@ package opsworks_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/opsworks" ) @@ -29,7 +30,7 @@ func doTarget(t *testing.T, h *opsworks.Handler, operation string, body any) *ht if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -50,7 +51,7 @@ func parseJSON(t *testing.T, body []byte) map[string]any { t.Helper() var result map[string]any - require.NoError(t, json.Unmarshal(body, &result)) + require.NoError(t, json.Unmarshal(body, &result, jsonx.V1())) return result } diff --git a/services/opsworks/handler_time_based_scaling.go b/services/opsworks/handler_time_based_scaling.go index 0fe13b6653..9e7499d081 100644 --- a/services/opsworks/handler_time_based_scaling.go +++ b/services/opsworks/handler_time_based_scaling.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleSetTimeBasedAutoScaling handles SetTimeBasedAutoScaling requests. @@ -13,7 +15,7 @@ func (h *Handler) handleSetTimeBasedAutoScaling(_ context.Context, body []byte) InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +33,7 @@ func (h *Handler) handleDescribeTimeBasedAutoScaling(_ context.Context, body []b } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } diff --git a/services/opsworks/handler_users_permissions.go b/services/opsworks/handler_users_permissions.go index ee29435fb3..c562c40da9 100644 --- a/services/opsworks/handler_users_permissions.go +++ b/services/opsworks/handler_users_permissions.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleCreateUserProfile handles CreateUserProfile requests. @@ -15,7 +17,7 @@ func (h *Handler) handleCreateUserProfile(_ context.Context, body []byte) (any, AllowSelfManagement bool `json:"AllowSelfManagement"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -38,7 +40,7 @@ func (h *Handler) handleDeleteUserProfile(_ context.Context, body []byte) (any, IamUserArn string `json:"IamUserArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -56,7 +58,7 @@ func (h *Handler) handleDescribeUserProfiles(_ context.Context, body []byte) (an } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -77,7 +79,7 @@ func (h *Handler) handleUpdateUserProfile(_ context.Context, body []byte) (any, SSHPublicKey string `json:"SshPublicKey"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -112,7 +114,7 @@ func (h *Handler) handleUpdateMyUserProfile(_ context.Context, body []byte) (any SSHPublicKey string `json:"SshPublicKey"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -152,7 +154,7 @@ func (h *Handler) handleSetPermission(_ context.Context, body []byte) (any, erro AllowSudo bool `json:"AllowSudo"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -171,7 +173,7 @@ func (h *Handler) handleDescribePermissions(_ context.Context, body []byte) (any } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -206,7 +208,7 @@ func (h *Handler) handleGrantAccess(_ context.Context, body []byte) (any, error) ValidForInMinutes int32 `json:"ValidForInMinutes"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/handler_volumes.go b/services/opsworks/handler_volumes.go index 63c5c36b0d..7f1b471055 100644 --- a/services/opsworks/handler_volumes.go +++ b/services/opsworks/handler_volumes.go @@ -2,8 +2,10 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleRegisterVolume handles RegisterVolume requests. @@ -13,7 +15,7 @@ func (h *Handler) handleRegisterVolume(_ context.Context, body []byte) (any, err StackID string `json:"StackId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +33,7 @@ func (h *Handler) handleDeregisterVolume(_ context.Context, body []byte) (any, e VolumeID string `json:"VolumeId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -49,7 +51,7 @@ func (h *Handler) handleAssignVolume(_ context.Context, body []byte) (any, error InstanceID string `json:"InstanceId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -66,7 +68,7 @@ func (h *Handler) handleUnassignVolume(_ context.Context, body []byte) (any, err VolumeID string `json:"VolumeId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -87,7 +89,7 @@ func (h *Handler) handleDescribeVolumes(_ context.Context, body []byte) (any, er } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -108,7 +110,7 @@ func (h *Handler) handleUpdateVolume(_ context.Context, body []byte) (any, error MountPoint string `json:"MountPoint"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/opsworks/interfaces.go b/services/opsworks/interfaces.go index 2108c0e51f..d38a371d84 100644 --- a/services/opsworks/interfaces.go +++ b/services/opsworks/interfaces.go @@ -2,7 +2,7 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -314,10 +314,10 @@ type LayerSettings struct { Attributes map[string]string `json:"Attributes,omitempty"` CustomInstanceProfileArn string `json:"CustomInstanceProfileArn,omitempty"` CustomJSON string `json:"CustomJson,omitempty"` - CustomRecipes json.RawMessage `json:"CustomRecipes,omitempty"` - CloudWatchLogsConfiguration json.RawMessage `json:"CloudWatchLogsConfiguration,omitempty"` - LifecycleEventConfiguration json.RawMessage `json:"LifecycleEventConfiguration,omitempty"` - VolumeConfigurations json.RawMessage `json:"VolumeConfigurations,omitempty"` + CustomRecipes jsontext.Value `json:"CustomRecipes,omitempty"` + CloudWatchLogsConfiguration jsontext.Value `json:"CloudWatchLogsConfiguration,omitempty"` + LifecycleEventConfiguration jsontext.Value `json:"LifecycleEventConfiguration,omitempty"` + VolumeConfigurations jsontext.Value `json:"VolumeConfigurations,omitempty"` Packages []string `json:"Packages,omitempty"` CustomSecurityGroupIDs []string `json:"CustomSecurityGroupIds,omitempty"` } diff --git a/services/opsworks/layers.go b/services/opsworks/layers.go index 8b86af2e27..029a81572d 100644 --- a/services/opsworks/layers.go +++ b/services/opsworks/layers.go @@ -1,7 +1,7 @@ package opsworks import ( - "encoding/json" + "encoding/json/jsontext" "maps" "reflect" "slices" @@ -185,7 +185,7 @@ func overlayBool(dst **bool, src *bool) { } } -func overlayRaw(cur, in json.RawMessage) json.RawMessage { +func overlayRaw(cur, in jsontext.Value) jsontext.Value { if len(in) > 0 { return in } diff --git a/services/opsworks/models.go b/services/opsworks/models.go index d26fe01151..757f8e54c1 100644 --- a/services/opsworks/models.go +++ b/services/opsworks/models.go @@ -1,10 +1,12 @@ package opsworks import ( - "encoding/json" + "encoding/json/v2" "maps" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -176,7 +178,7 @@ func (i *storedInstance) UnmarshalJSON(data []byte) error { alias } - if err := json.Unmarshal(data, &v); err != nil { + if err := json.Unmarshal(data, &v, jsonx.V1()); err != nil { return err } diff --git a/services/opsworks/multi_region_test.go b/services/opsworks/multi_region_test.go index 4ff7f930b9..449c1d35dd 100644 --- a/services/opsworks/multi_region_test.go +++ b/services/opsworks/multi_region_test.go @@ -2,7 +2,8 @@ package opsworks_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/opsworks" ) @@ -176,8 +178,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/opsworks/persistence.go b/services/opsworks/persistence.go index 033bba6ecf..94df4a6de0 100644 --- a/services/opsworks/persistence.go +++ b/services/opsworks/persistence.go @@ -2,7 +2,7 @@ package opsworks import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -30,7 +30,7 @@ const opsworksSnapshotVersion = 1 // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` diff --git a/services/opsworks/whitebox_test.go b/services/opsworks/whitebox_test.go index be4e71e088..7a7a15be66 100644 --- a/services/opsworks/whitebox_test.go +++ b/services/opsworks/whitebox_test.go @@ -1,11 +1,13 @@ package opsworks import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestFormatOpsWorksTimeNonUTCZone builds every timestamp input in a non-UTC @@ -81,10 +83,10 @@ func TestStoredInstanceUnmarshalJSON_LegacyLayerID(t *testing.T) { t.Parallel() var legacy storedInstance - require.NoError(t, json.Unmarshal([]byte(`{"instanceId":"i-1","layerId":"l-1"}`), &legacy)) + require.NoError(t, json.Unmarshal([]byte(`{"instanceId":"i-1","layerId":"l-1"}`), &legacy, jsonx.V1())) require.Equal(t, []string{"l-1"}, legacy.LayerIDs) var current storedInstance - require.NoError(t, json.Unmarshal([]byte(`{"instanceId":"i-2","layerIds":["l-2","l-3"]}`), ¤t)) + require.NoError(t, json.Unmarshal([]byte(`{"instanceId":"i-2","layerIds":["l-2","l-3"]}`), ¤t, jsonx.V1())) require.Equal(t, []string{"l-2", "l-3"}, current.LayerIDs) } diff --git a/services/organizations/account_provisioning.go b/services/organizations/account_provisioning.go index 56a3b02127..58f43014ec 100644 --- a/services/organizations/account_provisioning.go +++ b/services/organizations/account_provisioning.go @@ -1,8 +1,10 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const defaultAccessRoleName = "OrganizationAccountAccessRole" @@ -28,7 +30,7 @@ func accessRoleTrustPolicy(managementAccountID string) string { "Principal": map[string]string{"AWS": fmt.Sprintf("arn:aws:iam::%s:root", managementAccountID)}, "Action": "sts:AssumeRole", }}, - }) + }, jsonx.V1()) return string(doc) } diff --git a/services/organizations/default_policy_test.go b/services/organizations/default_policy_test.go index 3c710b366a..3d5ead4f98 100644 --- a/services/organizations/default_policy_test.go +++ b/services/organizations/default_policy_test.go @@ -1,12 +1,15 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDefaultFullAWSAccessPolicy_ViaHandler verifies that every organization @@ -21,7 +24,7 @@ func TestDefaultFullAWSAccessPolicy_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp describePolicyResp - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "p-FullAWSAccess", resp.Policy.PolicySummary.ID) assert.Equal(t, "FullAWSAccess", resp.Policy.PolicySummary.Name) @@ -44,7 +47,7 @@ func TestDefaultFullAWSAccessPolicy_ARN_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp describePolicyResp - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "arn:aws:organizations::aws:policy/SERVICE_CONTROL_POLICY/p-FullAWSAccess", @@ -65,7 +68,7 @@ func TestDefaultFullAWSAccessPolicy_AttachedToRoot_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp listPoliciesForTargetResp - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) found := false @@ -90,7 +93,7 @@ func TestDeleteFullAWSAccessPolicy_Rejected_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "AccessDeniedException", errResp["__type"]) // The survivor check: DescribePolicy must still find it afterward. @@ -115,14 +118,14 @@ func TestUpdateFullAWSAccessPolicy_Rejected_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "AccessDeniedException", errResp["__type"]) describeRec := doRequest(t, h, "DescribePolicy", map[string]any{"PolicyId": "p-FullAWSAccess"}) require.Equal(t, http.StatusOK, describeRec.Code) var resp describePolicyResp - require.NoError(t, json.NewDecoder(describeRec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(describeRec.Body), &resp, jsonx.V1())) assert.Equal(t, "FullAWSAccess", resp.Policy.PolicySummary.Name, "name must not be hijacked") assert.JSONEq(t, `{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]}`, @@ -149,7 +152,7 @@ func TestUserPolicy_AwsManagedFalse_StillDeletable_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp createPolicyResp - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) assert.False(t, createResp.Policy.PolicySummary.AwsManaged, "user-created policy must not be AwsManaged") policyID := createResp.Policy.PolicySummary.ID diff --git a/services/organizations/delegated_administrators_test.go b/services/organizations/delegated_administrators_test.go index 0e508fe649..bebfba20c0 100644 --- a/services/organizations/delegated_administrators_test.go +++ b/services/organizations/delegated_administrators_test.go @@ -1,7 +1,8 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -90,7 +92,7 @@ func TestDelegatedServices(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &createResp, jsonx.V1())) accountID := createResp["CreateAccountStatus"].(map[string]any)["AccountId"].(string) rec := doRequest(t, h, "EnableAWSServiceAccess", map[string]any{ @@ -111,7 +113,7 @@ func TestDelegatedServices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) services, ok := resp["DelegatedServices"].([]any) require.True(t, ok) require.Len(t, services, 1) @@ -407,7 +409,7 @@ func TestRegisterDelegatedAdmin_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) statusObj := createResp["CreateAccountStatus"].(map[string]any) accountID := statusObj["AccountId"].(string) diff --git a/services/organizations/effective_policy.go b/services/organizations/effective_policy.go index 1ae31675ec..92c937c0c8 100644 --- a/services/organizations/effective_policy.go +++ b/services/organizations/effective_policy.go @@ -1,9 +1,11 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validEffectivePolicyTypes is the EffectivePolicyType enum (aws-sdk-go-v2 organizations v1.53.5 enums.go). @@ -130,12 +132,12 @@ func (b *InMemoryBackend) mergeTagStyleChain(chain []effectivePolicyEntry) (stri for _, entry := range slices.Backward(chain) { var obj map[string]any - if err := json.Unmarshal([]byte(entry.content), &obj); err == nil { + if err := json.Unmarshal([]byte(entry.content), &obj, jsonx.V1()); err == nil { mergeJSONObjects(merged, obj) } } - if data, err := json.Marshal(merged); err == nil { + if data, err := json.Marshal(merged, jsonx.V1()); err == nil { return string(data), chain[0].id } diff --git a/services/organizations/effective_policy_test.go b/services/organizations/effective_policy_test.go index 229f10a176..0b63e2c2fa 100644 --- a/services/organizations/effective_policy_test.go +++ b/services/organizations/effective_policy_test.go @@ -1,13 +1,15 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -137,7 +139,7 @@ func TestDescribeEffectivePolicy_MergeTagPolicy(t *testing.T) { // Merged content should have both "env" (from child) and "owner" (from parent). var merged map[string]any - require.NoError(t, json.Unmarshal([]byte(ep.PolicyContent), &merged)) + require.NoError(t, json.Unmarshal([]byte(ep.PolicyContent), &merged, jsonx.V1())) tags, hasTags := merged["tags"].(map[string]any) require.True(t, hasTags, "merged policy should have 'tags' object") @@ -234,7 +236,7 @@ func TestHandler_DescribeEffectivePolicy(t *testing.T) { require.Equal(t, http.StatusOK, acctRec.Code) var acctResp map[string]any - require.NoError(t, json.NewDecoder(acctRec.Body).Decode(&acctResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(acctRec.Body), &acctResp, jsonx.V1())) status := acctResp["CreateAccountStatus"].(map[string]any) targetID = status["AccountId"].(string) @@ -247,7 +249,7 @@ func TestHandler_DescribeEffectivePolicy(t *testing.T) { require.Equal(t, http.StatusOK, policyRec.Code) var policyResp map[string]any - require.NoError(t, json.NewDecoder(policyRec.Body).Decode(&policyResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(policyRec.Body), &policyResp, jsonx.V1())) policyObj := policyResp["Policy"].(map[string]any) summary := policyObj["PolicySummary"].(map[string]any) policyID := summary["Id"].(string) @@ -274,7 +276,7 @@ func TestHandler_DescribeEffectivePolicy(t *testing.T) { if tt.wantContent { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ep, ok := resp["EffectivePolicy"].(map[string]any) require.True(t, ok, "response must have EffectivePolicy") assert.NotEmpty(t, ep["PolicyContent"]) diff --git a/services/organizations/handler.go b/services/organizations/handler.go index b765d40a32..fac4ae4a82 100644 --- a/services/organizations/handler.go +++ b/services/organizations/handler.go @@ -1,7 +1,7 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -139,7 +140,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } diff --git a/services/organizations/handler_accounts.go b/services/organizations/handler_accounts.go index 73e71913c1..f69d557859 100644 --- a/services/organizations/handler_accounts.go +++ b/services/organizations/handler_accounts.go @@ -1,12 +1,13 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -165,7 +166,7 @@ func (h *Handler) dispatchAccount(c *echo.Context, op string, body []byte) (bool func (h *Handler) handleListAccounts(c *echo.Context, body []byte) error { var req listAccountsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } @@ -237,7 +238,7 @@ func (h *Handler) validateCreateAccountInput( func (h *Handler) handleCreateAccount(c *echo.Context, body []byte) error { var req createAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -258,7 +259,7 @@ func (h *Handler) handleCreateAccount(c *echo.Context, body []byte) error { func (h *Handler) handleDescribeCreateAccountStatus(c *echo.Context, body []byte) error { var req describeCreateAccountStatusRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -272,7 +273,7 @@ func (h *Handler) handleDescribeCreateAccountStatus(c *echo.Context, body []byte func (h *Handler) handleDescribeAccount(c *echo.Context, body []byte) error { var req describeAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -286,7 +287,7 @@ func (h *Handler) handleDescribeAccount(c *echo.Context, body []byte) error { func (h *Handler) handleRemoveAccountFromOrganization(c *echo.Context, body []byte) error { var req removeAccountFromOrganizationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -299,7 +300,7 @@ func (h *Handler) handleRemoveAccountFromOrganization(c *echo.Context, body []by func (h *Handler) handleMoveAccount(c *echo.Context, body []byte) error { var req moveAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -312,7 +313,7 @@ func (h *Handler) handleMoveAccount(c *echo.Context, body []byte) error { func (h *Handler) handleCloseAccount(c *echo.Context, body []byte) error { var req closeAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -329,7 +330,7 @@ func (h *Handler) handleCloseAccount(c *echo.Context, body []byte) error { func (h *Handler) handleCreateGovCloudAccount(c *echo.Context, body []byte) error { var req createGovCloudAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -350,7 +351,7 @@ func (h *Handler) handleCreateGovCloudAccount(c *echo.Context, body []byte) erro func (h *Handler) handleListCreateAccountStatus(c *echo.Context, body []byte) error { var req listCreateAccountStatusRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -375,7 +376,7 @@ func (h *Handler) handleListCreateAccountStatus(c *echo.Context, body []byte) er func (h *Handler) handleListAccountsWithInvalidEffectivePolicy(c *echo.Context, body []byte) error { var req listAccountsWithInvalidEffectivePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_accounts_test.go b/services/organizations/handler_accounts_test.go index d4a078af30..a660e0b34c 100644 --- a/services/organizations/handler_accounts_test.go +++ b/services/organizations/handler_accounts_test.go @@ -1,7 +1,8 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -96,7 +98,7 @@ func TestCreateAccountStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) status := createResp["CreateAccountStatus"].(map[string]any) requestID, ok := status["Id"].(string) require.True(t, ok, "CreateAccountStatus.Id must be present") @@ -106,7 +108,7 @@ func TestCreateAccountStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) statuses, ok := listResp["CreateAccountStatuses"].([]any) require.True(t, ok) @@ -208,7 +210,7 @@ func TestCreateAccount_RoleName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) // Describe account. status := resp["CreateAccountStatus"].(map[string]any) @@ -218,7 +220,7 @@ func TestCreateAccount_RoleName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&descResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &descResp, jsonx.V1())) acct := descResp["Account"].(map[string]any) assert.NotContains(t, acct, "RoleName") @@ -283,7 +285,7 @@ func TestCreateAccount_IamUserAccessToBilling(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantIamAccess != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) status := resp["CreateAccountStatus"].(map[string]any) accountID := status["AccountId"].(string) @@ -292,7 +294,7 @@ func TestCreateAccount_IamUserAccessToBilling(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&descResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &descResp, jsonx.V1())) acct := descResp["Account"].(map[string]any) assert.NotContains(t, acct, "IamUserAccessToBilling") @@ -325,7 +327,7 @@ func TestCloseAccount_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) statusObj := createResp["CreateAccountStatus"].(map[string]any) accountID := statusObj["AccountId"].(string) @@ -371,7 +373,7 @@ func TestEmailUniqueness_ViaHandler(t *testing.T) { AccountID string `json:"AccountId"` } `json:"CreateAccountStatus"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "FAILED", resp.CreateAccountStatus.State) assert.Equal(t, "EMAIL_ALREADY_EXISTS", resp.CreateAccountStatus.FailureReason) assert.Empty(t, resp.CreateAccountStatus.AccountID) @@ -392,7 +394,7 @@ func TestCreateAccount_NoGovCloudID_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) statusObj, ok := resp["CreateAccountStatus"].(map[string]any) require.True(t, ok, "response must have CreateAccountStatus") @@ -417,7 +419,7 @@ func TestGovCloudAccount_HasGovCloudID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) statusObj, ok := resp["CreateAccountStatus"].(map[string]any) require.True(t, ok, "response must have CreateAccountStatus") @@ -458,7 +460,7 @@ func TestHandler_ListAccounts(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) accounts, ok := resp["Accounts"].([]any) require.True(t, ok) assert.NotEmpty(t, accounts) @@ -531,7 +533,7 @@ func TestHandler_DescribeCreateAccountStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) status := createResp["CreateAccountStatus"].(map[string]any) statusID := status["Id"].(string) @@ -599,7 +601,7 @@ func TestHandler_MoveAccount(t *testing.T) { require.Equal(t, http.StatusOK, ouRec.Code) var ouResp map[string]any - require.NoError(t, json.NewDecoder(ouRec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ouRec.Body), &ouResp, jsonx.V1())) ou := ouResp["OrganizationalUnit"].(map[string]any) ouID := ou["Id"].(string) @@ -658,7 +660,7 @@ func TestHandler_CloseAccount(t *testing.T) { require.Equal(t, http.StatusOK, acctRec.Code) var acctResp map[string]any - require.NoError(t, json.NewDecoder(acctRec.Body).Decode(&acctResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(acctRec.Body), &acctResp, jsonx.V1())) status := acctResp["CreateAccountStatus"].(map[string]any) body = map[string]any{"AccountId": status["AccountId"]} @@ -736,7 +738,7 @@ func TestHandler_CreateGovCloudAccount(t *testing.T) { if tt.wantGovID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) status, ok := resp["CreateAccountStatus"].(map[string]any) require.True(t, ok, "response must have CreateAccountStatus") diff --git a/services/organizations/handler_delegated_administrators.go b/services/organizations/handler_delegated_administrators.go index 78559fc5bf..d44847e721 100644 --- a/services/organizations/handler_delegated_administrators.go +++ b/services/organizations/handler_delegated_administrators.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -81,7 +82,7 @@ func (h *Handler) dispatchDelegatedAdmin(c *echo.Context, op string, body []byte func (h *Handler) handleRegisterDelegatedAdministrator(c *echo.Context, body []byte) error { var req registerDelegatedAdministratorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -94,7 +95,7 @@ func (h *Handler) handleRegisterDelegatedAdministrator(c *echo.Context, body []b func (h *Handler) handleDeregisterDelegatedAdministrator(c *echo.Context, body []byte) error { var req deregisterDelegatedAdministratorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -107,7 +108,7 @@ func (h *Handler) handleDeregisterDelegatedAdministrator(c *echo.Context, body [ func (h *Handler) handleListDelegatedAdministrators(c *echo.Context, body []byte) error { var req listDelegatedAdministratorsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -144,7 +145,7 @@ func (h *Handler) handleListDelegatedAdministrators(c *echo.Context, body []byte func (h *Handler) handleListDelegatedServicesForAccount(c *echo.Context, body []byte) error { var req listDelegatedServicesForAccountRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_effective_policy.go b/services/organizations/handler_effective_policy.go index a70841fb8e..235a5db36d 100644 --- a/services/organizations/handler_effective_policy.go +++ b/services/organizations/handler_effective_policy.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -62,7 +63,7 @@ func (h *Handler) dispatchEffectivePolicy(c *echo.Context, op string, body []byt func (h *Handler) handleDescribeEffectivePolicy(c *echo.Context, body []byte) error { var req describeEffectivePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -87,7 +88,7 @@ func (h *Handler) handleDescribeEffectivePolicy(c *echo.Context, body []byte) er func (h *Handler) handleListEffectivePolicyValidationErrors(c *echo.Context, body []byte) error { var req listEffectivePolicyValidationErrorsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_handshakes.go b/services/organizations/handler_handshakes.go index 16e5f71102..459feee8d7 100644 --- a/services/organizations/handler_handshakes.go +++ b/services/organizations/handler_handshakes.go @@ -1,13 +1,14 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -274,7 +275,7 @@ func (h *Handler) dispatchTransferOps(c *echo.Context, op string, body []byte) ( func (h *Handler) handleAcceptHandshake(c *echo.Context, body []byte) error { var req acceptHandshakeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -292,7 +293,7 @@ func (h *Handler) handleAcceptHandshake(c *echo.Context, body []byte) error { func (h *Handler) handleCancelHandshake(c *echo.Context, body []byte) error { var req cancelHandshakeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -310,7 +311,7 @@ func (h *Handler) handleCancelHandshake(c *echo.Context, body []byte) error { func (h *Handler) handleDeclineHandshake(c *echo.Context, body []byte) error { var req declineHandshakeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -328,7 +329,7 @@ func (h *Handler) handleDeclineHandshake(c *echo.Context, body []byte) error { func (h *Handler) handleDescribeHandshake(c *echo.Context, body []byte) error { var req describeHandshakeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -346,7 +347,7 @@ func (h *Handler) handleDescribeHandshake(c *echo.Context, body []byte) error { func (h *Handler) handleDescribeResponsibilityTransfer(c *echo.Context, body []byte) error { var req describeResponsibilityTransferRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -376,7 +377,7 @@ func (h *Handler) handleEnableAllFeatures(c *echo.Context, _ []byte) error { func (h *Handler) handleInviteAccountToOrganization(c *echo.Context, body []byte) error { var req inviteAccountToOrganizationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -398,7 +399,7 @@ func (h *Handler) handleInviteAccountToOrganization(c *echo.Context, body []byte func (h *Handler) handleInviteOrganizationToTransferResponsibility(c *echo.Context, body []byte) error { var req inviteOrganizationToTransferResponsibilityRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -449,7 +450,7 @@ func (h *Handler) handleLeaveOrganization(c *echo.Context, _ []byte) error { func (h *Handler) handleListHandshakesForAccount(c *echo.Context, body []byte) error { var req listHandshakesFilterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } @@ -486,7 +487,7 @@ func (h *Handler) handleListHandshakesForAccount(c *echo.Context, body []byte) e func (h *Handler) handleListHandshakesForOrganization(c *echo.Context, body []byte) error { var req listHandshakesFilterRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } @@ -522,7 +523,7 @@ func (h *Handler) handleListHandshakesForOrganization(c *echo.Context, body []by func (h *Handler) handleListInboundResponsibilityTransfers(c *echo.Context, body []byte) error { var req listInboundResponsibilityTransfersRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } @@ -556,7 +557,7 @@ func (h *Handler) handleListInboundResponsibilityTransfers(c *echo.Context, body func (h *Handler) handleListOutboundResponsibilityTransfers(c *echo.Context, body []byte) error { var req listOutboundResponsibilityTransfersRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } @@ -589,7 +590,7 @@ func (h *Handler) handleListOutboundResponsibilityTransfers(c *echo.Context, bod func (h *Handler) handleTerminateResponsibilityTransfer(c *echo.Context, body []byte) error { var req terminateResponsibilityTransferRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -616,7 +617,7 @@ func (h *Handler) handleTerminateResponsibilityTransfer(c *echo.Context, body [] func (h *Handler) handleUpdateResponsibilityTransfer(c *echo.Context, body []byte) error { var req updateResponsibilityTransferRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_handshakes_test.go b/services/organizations/handler_handshakes_test.go index 40c7e46a7c..41ddf05b15 100644 --- a/services/organizations/handler_handshakes_test.go +++ b/services/organizations/handler_handshakes_test.go @@ -2,7 +2,8 @@ package organizations_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -33,7 +35,7 @@ func TestHandshakeOps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var inviteResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&inviteResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &inviteResp, jsonx.V1())) invited := inviteResp["Handshake"].(map[string]any) handshakeID, ok := invited["Id"].(string) require.True(t, ok, "InviteAccountToOrganization must return a Handshake.Id") @@ -55,7 +57,7 @@ func handshakeListContains(t *testing.T, rec *httptest.ResponseRecorder, handsha t.Helper() var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) handshakes, ok := resp["Handshakes"].([]any) require.True(t, ok) @@ -110,7 +112,7 @@ func TestEnableAllFeatures(t *testing.T) { if tt.wantAction != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) hs, ok := resp["Handshake"].(map[string]any) require.True(t, ok, "response must contain Handshake") assert.Equal(t, tt.wantAction, hs["Action"]) @@ -193,7 +195,7 @@ func TestHandshakeFilter_Handler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) handshakes := resp["Handshakes"].([]any) assert.Len(t, handshakes, tt.wantCount) @@ -333,7 +335,7 @@ func TestHandshakeExpiration_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) handshake := resp["Handshake"].(map[string]any) assert.Equal(t, "EXPIRED", handshake["State"].(string)) } @@ -355,7 +357,7 @@ func TestInviteAccount_DuplicateOpen_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, r2.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(r2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "DuplicateHandshakeException", errResp["__type"]) } @@ -513,7 +515,7 @@ func TestHandler_HandshakeLifecycle(t *testing.T) { if tt.wantState != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) hs, ok := resp["Handshake"].(map[string]any) require.True(t, ok, "response must have Handshake field") @@ -582,7 +584,7 @@ func TestHandler_DescribeResponsibilityTransfer(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) details, ok := resp["ResponsibilityTransfer"].(map[string]any) require.True(t, ok, "response must have ResponsibilityTransfer") assert.Equal(t, tt.transferID, details["Id"]) diff --git a/services/organizations/handler_organization.go b/services/organizations/handler_organization.go index e9a0b9d037..4df466400a 100644 --- a/services/organizations/handler_organization.go +++ b/services/organizations/handler_organization.go @@ -1,10 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createOrganizationRequest struct { @@ -49,7 +51,7 @@ func (h *Handler) dispatchOrg(c *echo.Context, op string, body []byte) (bool, er func (h *Handler) handleCreateOrganization(c *echo.Context, body []byte) error { var req createOrganizationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_organizational_units.go b/services/organizations/handler_organizational_units.go index 8782b8aeb2..d2f071e1eb 100644 --- a/services/organizations/handler_organizational_units.go +++ b/services/organizations/handler_organizational_units.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -122,7 +123,7 @@ func (h *Handler) dispatchOU(c *echo.Context, op string, body []byte) (bool, err func (h *Handler) handleCreateOrganizationalUnit(c *echo.Context, body []byte) error { var req createOrganizationalUnitRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -140,7 +141,7 @@ func (h *Handler) handleCreateOrganizationalUnit(c *echo.Context, body []byte) e func (h *Handler) handleDescribeOrganizationalUnit(c *echo.Context, body []byte) error { var req describeOrganizationalUnitRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -154,7 +155,7 @@ func (h *Handler) handleDescribeOrganizationalUnit(c *echo.Context, body []byte) func (h *Handler) handleDeleteOrganizationalUnit(c *echo.Context, body []byte) error { var req deleteOrganizationalUnitRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -167,7 +168,7 @@ func (h *Handler) handleDeleteOrganizationalUnit(c *echo.Context, body []byte) e func (h *Handler) handleUpdateOrganizationalUnit(c *echo.Context, body []byte) error { var req updateOrganizationalUnitRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -181,7 +182,7 @@ func (h *Handler) handleUpdateOrganizationalUnit(c *echo.Context, body []byte) e func (h *Handler) handleListOrganizationalUnitsForParent(c *echo.Context, body []byte) error { var req listOrganizationalUnitsForParentRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -202,7 +203,7 @@ func (h *Handler) handleListOrganizationalUnitsForParent(c *echo.Context, body [ func (h *Handler) handleListAccountsForParent(c *echo.Context, body []byte) error { var req listAccountsForParentRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -223,7 +224,7 @@ func (h *Handler) handleListAccountsForParent(c *echo.Context, body []byte) erro func (h *Handler) handleListParents(c *echo.Context, body []byte) error { var req listParentsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -243,7 +244,7 @@ func (h *Handler) handleListParents(c *echo.Context, body []byte) error { func (h *Handler) handleListChildren(c *echo.Context, body []byte) error { var req listChildrenRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_organizational_units_test.go b/services/organizations/handler_organizational_units_test.go index f83119a1d4..1e36a88037 100644 --- a/services/organizations/handler_organizational_units_test.go +++ b/services/organizations/handler_organizational_units_test.go @@ -1,13 +1,16 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_CreateOrganizationalUnit tests the HTTP handler for CreateOrganizationalUnit. @@ -38,7 +41,7 @@ func TestHandler_CreateOrganizationalUnit(t *testing.T) { require.Equal(t, http.StatusOK, rootsRec.Code) var rootsResp map[string]any - require.NoError(t, json.NewDecoder(rootsRec.Body).Decode(&rootsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rootsRec.Body), &rootsResp, jsonx.V1())) roots := rootsResp["Roots"].([]any) rootID := roots[0].(map[string]any)["Id"].(string) @@ -50,7 +53,7 @@ func TestHandler_CreateOrganizationalUnit(t *testing.T) { if tt.wantOU { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ou, ok := resp["OrganizationalUnit"].(map[string]any) require.True(t, ok, "response should contain OrganizationalUnit") assert.NotEmpty(t, ou["Id"]) @@ -90,7 +93,7 @@ func TestHandler_ListParents(t *testing.T) { require.Equal(t, http.StatusOK, acctRec.Code) var acctResp map[string]any - require.NoError(t, json.NewDecoder(acctRec.Body).Decode(&acctResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(acctRec.Body), &acctResp, jsonx.V1())) status := acctResp["CreateAccountStatus"].(map[string]any) accountID := status["AccountId"].(string) @@ -99,7 +102,7 @@ func TestHandler_ListParents(t *testing.T) { if tt.wantParents { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) parents, ok := resp["Parents"].([]any) require.True(t, ok, "response should contain Parents") assert.NotEmpty(t, parents) @@ -164,7 +167,7 @@ func TestOUDepth_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var rootsResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&rootsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &rootsResp, jsonx.V1())) roots := rootsResp["Roots"].([]any) rootID := roots[0].(map[string]any)["Id"].(string) @@ -179,7 +182,7 @@ func TestOUDepth_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "depth %d should succeed", d) var ouResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ouResp, jsonx.V1())) parentID = ouResp["OrganizationalUnit"].(map[string]any)["Id"].(string) } @@ -205,7 +208,7 @@ func TestOUNameUniqueness_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var rootsResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&rootsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &rootsResp, jsonx.V1())) roots := rootsResp["Roots"].([]any) rootID := roots[0].(map[string]any)["Id"].(string) @@ -258,7 +261,7 @@ func TestHandler_DescribeOrganizationalUnit(t *testing.T) { require.Equal(t, http.StatusOK, ouRec.Code) var ouResp map[string]any - require.NoError(t, json.NewDecoder(ouRec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ouRec.Body), &ouResp, jsonx.V1())) ou := ouResp["OrganizationalUnit"].(map[string]any) ouID := ou["Id"].(string) @@ -295,7 +298,7 @@ func TestHandler_DeleteOrganizationalUnit(t *testing.T) { require.Equal(t, http.StatusOK, ouRec.Code) var ouResp map[string]any - require.NoError(t, json.NewDecoder(ouRec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ouRec.Body), &ouResp, jsonx.V1())) ou := ouResp["OrganizationalUnit"].(map[string]any) ouID := ou["Id"].(string) @@ -332,7 +335,7 @@ func TestHandler_UpdateOrganizationalUnit(t *testing.T) { require.Equal(t, http.StatusOK, ouRec.Code) var ouResp map[string]any - require.NoError(t, json.NewDecoder(ouRec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(ouRec.Body), &ouResp, jsonx.V1())) ou := ouResp["OrganizationalUnit"].(map[string]any) ouID := ou["Id"].(string) diff --git a/services/organizations/handler_pagination_test.go b/services/organizations/handler_pagination_test.go index b6d51956ae..8a29247858 100644 --- a/services/organizations/handler_pagination_test.go +++ b/services/organizations/handler_pagination_test.go @@ -2,7 +2,8 @@ package organizations_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -73,7 +75,7 @@ func TestHandler_Pagination(t *testing.T) { if tt.nextToken != "" { reqBody["NextToken"] = tt.nextToken } - bodyBytes, _ := json.Marshal(reqBody) + bodyBytes, _ := json.Marshal(reqBody, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) req.Header.Set("X-Amz-Target", "AWSOrganizationsV20161128.ListAccounts") @@ -94,7 +96,7 @@ func TestHandler_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var res map[string]any - err = json.Unmarshal(rec.Body.Bytes(), &res) + err = json.Unmarshal(rec.Body.Bytes(), &res, jsonx.V1()) require.NoError(t, err) accounts, ok := res["Accounts"].([]any) @@ -139,7 +141,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` Accounts []map[string]any `json:"Accounts"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.Accounts, 2, "MaxResults=2 must truncate to 2 items") require.NotEmpty(t, resp.NextToken, "truncated page must carry a NextToken") @@ -155,7 +157,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` Accounts []map[string]any `json:"Accounts"` } - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp2, jsonx.V1())) require.Len(t, resp2.Accounts, 2, "second page must continue from the token") }) @@ -180,7 +182,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { } `json:"PolicySummary"` } `json:"Policy"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&pResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &pResp, jsonx.V1())) rec = doRequest(t, h, "AttachPolicy", map[string]any{ "PolicyId": pResp.Policy.PolicySummary.ID, @@ -200,7 +202,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` Policies []map[string]any `json:"Policies"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.Policies, 1) require.NotEmpty(t, resp.NextToken) }) @@ -221,7 +223,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { ID string `json:"Id"` } `json:"OrganizationalUnit"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ouResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ouResp, jsonx.V1())) rec = doRequest(t, h, "CreatePolicy", map[string]any{ "Name": "p", @@ -238,7 +240,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { } `json:"PolicySummary"` } `json:"Policy"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&pResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &pResp, jsonx.V1())) policyID := pResp.Policy.PolicySummary.ID for _, targetID := range []string{rootID, ouResp.OrganizationalUnit.ID} { @@ -259,7 +261,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` Targets []map[string]any `json:"Targets"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.Targets, 1) require.NotEmpty(t, resp.NextToken) }) @@ -284,7 +286,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { AccountID string `json:"AccountId"` } `json:"CreateAccountStatus"` } - require.NoError(t, json.NewDecoder(caRec.Body).Decode(&caResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(caRec.Body), &caResp, jsonx.V1())) rec = doRequest(t, h, "RegisterDelegatedAdministrator", map[string]any{ "AccountId": caResp.CreateAccountStatus.AccountID, @@ -302,7 +304,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` DelegatedAdministrators []map[string]any `json:"DelegatedAdministrators"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.DelegatedAdministrators, 1) require.NotEmpty(t, resp.NextToken) }) @@ -329,7 +331,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` CreateAccountStatuses []map[string]any `json:"CreateAccountStatuses"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.CreateAccountStatuses, 2) require.NotEmpty(t, resp.NextToken) }) @@ -359,7 +361,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` Tags []map[string]any `json:"Tags"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.Tags, 3, "all 3 tags fit under the default page size") require.Empty(t, resp.NextToken) }) @@ -383,7 +385,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` EnabledServicePrincipals []map[string]any `json:"EnabledServicePrincipals"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.EnabledServicePrincipals, 1) require.NotEmpty(t, resp.NextToken) @@ -409,7 +411,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { AccountID string `json:"AccountId"` } `json:"CreateAccountStatus"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&caResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &caResp, jsonx.V1())) accountID := caResp.CreateAccountStatus.AccountID for _, sp := range []string{"config.amazonaws.com", "cloudtrail.amazonaws.com"} { @@ -433,7 +435,7 @@ func TestListOps_HonorMaxResultsAndNextToken(t *testing.T) { NextToken string `json:"NextToken"` DelegatedServices []map[string]any `json:"DelegatedServices"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) require.Len(t, resp.DelegatedServices, 1) require.NotEmpty(t, resp.NextToken) }) diff --git a/services/organizations/handler_policies.go b/services/organizations/handler_policies.go index dd472d9a15..1ed3c8670d 100644 --- a/services/organizations/handler_policies.go +++ b/services/organizations/handler_policies.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -115,7 +116,7 @@ func (h *Handler) dispatchPolicy(c *echo.Context, op string, body []byte) (bool, func (h *Handler) handleCreatePolicy(c *echo.Context, body []byte) error { var req createPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -133,7 +134,7 @@ func (h *Handler) handleCreatePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDescribePolicy(c *echo.Context, body []byte) error { var req describePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -147,7 +148,7 @@ func (h *Handler) handleDescribePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleUpdatePolicy(c *echo.Context, body []byte) error { var req updatePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -161,7 +162,7 @@ func (h *Handler) handleUpdatePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDeletePolicy(c *echo.Context, body []byte) error { var req deletePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -174,7 +175,7 @@ func (h *Handler) handleDeletePolicy(c *echo.Context, body []byte) error { func (h *Handler) handleListPolicies(c *echo.Context, body []byte) error { var req listPoliciesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -195,7 +196,7 @@ func (h *Handler) handleListPolicies(c *echo.Context, body []byte) error { func (h *Handler) handleEnablePolicyType(c *echo.Context, body []byte) error { var req enablePolicyTypeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -209,7 +210,7 @@ func (h *Handler) handleEnablePolicyType(c *echo.Context, body []byte) error { func (h *Handler) handleDisablePolicyType(c *echo.Context, body []byte) error { var req disablePolicyTypeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_policy_attachments.go b/services/organizations/handler_policy_attachments.go index 53cab343c2..5801f0be49 100644 --- a/services/organizations/handler_policy_attachments.go +++ b/services/organizations/handler_policy_attachments.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -67,7 +68,7 @@ func (h *Handler) dispatchPolicyAttachments(c *echo.Context, op string, body []b func (h *Handler) handleAttachPolicy(c *echo.Context, body []byte) error { var req attachPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -80,7 +81,7 @@ func (h *Handler) handleAttachPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleDetachPolicy(c *echo.Context, body []byte) error { var req detachPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -93,7 +94,7 @@ func (h *Handler) handleDetachPolicy(c *echo.Context, body []byte) error { func (h *Handler) handleListPoliciesForTarget(c *echo.Context, body []byte) error { var req listPoliciesForTargetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -114,7 +115,7 @@ func (h *Handler) handleListPoliciesForTarget(c *echo.Context, body []byte) erro func (h *Handler) handleListTargetsForPolicy(c *echo.Context, body []byte) error { var req listTargetsForPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_resource_policy.go b/services/organizations/handler_resource_policy.go index 964e5a3ba3..8b213511b8 100644 --- a/services/organizations/handler_resource_policy.go +++ b/services/organizations/handler_resource_policy.go @@ -1,10 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type resourcePolicySummaryObject struct { @@ -70,7 +72,7 @@ func (h *Handler) handlePutResourcePolicy(c *echo.Context, body []byte) error { Tags []Tag `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_roots.go b/services/organizations/handler_roots.go index 2d42c4f4ff..abf114b21a 100644 --- a/services/organizations/handler_roots.go +++ b/services/organizations/handler_roots.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -43,7 +44,7 @@ type listRootsRequest struct { func (h *Handler) handleListRoots(c *echo.Context, body []byte) error { var req listRootsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } diff --git a/services/organizations/handler_service_access.go b/services/organizations/handler_service_access.go index 7f090ac437..f755a41ac2 100644 --- a/services/organizations/handler_service_access.go +++ b/services/organizations/handler_service_access.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -52,7 +53,7 @@ func (h *Handler) dispatchServiceAccess(c *echo.Context, op string, body []byte) func (h *Handler) handleEnableAWSServiceAccess(c *echo.Context, body []byte) error { var req enableAWSServiceAccessRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -65,7 +66,7 @@ func (h *Handler) handleEnableAWSServiceAccess(c *echo.Context, body []byte) err func (h *Handler) handleDisableAWSServiceAccess(c *echo.Context, body []byte) error { var req disableAWSServiceAccessRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -79,7 +80,7 @@ func (h *Handler) handleDisableAWSServiceAccess(c *echo.Context, body []byte) er func (h *Handler) handleListAWSServiceAccessForOrganization(c *echo.Context, body []byte) error { var req listAWSServiceAccessRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } } diff --git a/services/organizations/handler_tags.go b/services/organizations/handler_tags.go index b417eec0ed..c6776b0736 100644 --- a/services/organizations/handler_tags.go +++ b/services/organizations/handler_tags.go @@ -1,11 +1,12 @@ package organizations import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -49,7 +50,7 @@ func (h *Handler) dispatchTags(c *echo.Context, op string, body []byte) (bool, e func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -62,7 +63,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } @@ -75,7 +76,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { func (h *Handler) handleListTagsForResource(c *echo.Context, body []byte) error { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return h.writeError(c, http.StatusBadRequest, "SerializationException", "invalid request body") } diff --git a/services/organizations/handler_test.go b/services/organizations/handler_test.go index 3b3559145b..ba36cb0908 100644 --- a/services/organizations/handler_test.go +++ b/services/organizations/handler_test.go @@ -2,7 +2,8 @@ package organizations_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -38,7 +40,7 @@ func doRequest(t *testing.T, h *organizations.Handler, op string, body any) *htt if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -81,7 +83,7 @@ func newHandlerWithOrg(t *testing.T) (*organizations.Handler, string) { require.Equal(t, http.StatusOK, rec.Code) var rootsResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&rootsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &rootsResp, jsonx.V1())) roots := rootsResp["Roots"].([]any) rootID := roots[0].(map[string]any)["Id"].(string) @@ -99,7 +101,7 @@ func createAccountViaHandler(t *testing.T, h *organizations.Handler, name, email require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) status := resp["CreateAccountStatus"].(map[string]any) return status["AccountId"].(string) @@ -118,7 +120,7 @@ func createPolicyViaHandler(t *testing.T, h *organizations.Handler, name string) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) policy := resp["Policy"].(map[string]any) summary := policy["PolicySummary"].(map[string]any) diff --git a/services/organizations/organization_test.go b/services/organizations/organization_test.go index e87134f1ae..eeddca40df 100644 --- a/services/organizations/organization_test.go +++ b/services/organizations/organization_test.go @@ -1,13 +1,15 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -122,7 +124,7 @@ func TestHandler_CreateOrganization(t *testing.T) { if tt.wantOrgID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) org, ok := resp["Organization"].(map[string]any) require.True(t, ok, "response should contain Organization") assert.NotEmpty(t, org["Id"]) @@ -326,7 +328,7 @@ func TestAvailablePolicyTypes_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) org := resp["Organization"].(map[string]any) pts, ok := org["AvailablePolicyTypes"].([]any) @@ -549,7 +551,7 @@ func TestDeleteOrganization_WithMembers_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "OrganizationNotEmptyException", errResp["__type"]) } diff --git a/services/organizations/pagination_sort_totality_test.go b/services/organizations/pagination_sort_totality_test.go index 3156b5640a..2aa46eb3ac 100644 --- a/services/organizations/pagination_sort_totality_test.go +++ b/services/organizations/pagination_sort_totality_test.go @@ -1,12 +1,13 @@ package organizations_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -94,7 +95,7 @@ func TestListPoliciesSortIsTotal(t *testing.T) { ID string `json:"Id"` } `json:"Policies"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ids := make([]string, len(resp.Policies)) for i, p := range resp.Policies { diff --git a/services/organizations/paths_test.go b/services/organizations/paths_test.go index c1054c9425..a4f0a7191c 100644 --- a/services/organizations/paths_test.go +++ b/services/organizations/paths_test.go @@ -1,7 +1,7 @@ package organizations_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -189,10 +190,10 @@ func TestPathsDetachedOrCyclic(t *testing.T) { require.NotNil(t, data) snap := organizations.NewBackendSnapshot() - require.NoError(t, json.Unmarshal(data, snap)) + require.NoError(t, json.Unmarshal(data, snap, jsonx.V1())) snap.AccountParent[acctID] = "ou-doesnotexist-00000000" - corrupted, err := json.Marshal(snap) + corrupted, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) fresh := organizations.NewInMemoryBackend("000000000000", "us-east-1") @@ -219,10 +220,10 @@ func TestPathsDetachedOrCyclic(t *testing.T) { require.NotNil(t, data) snap := organizations.NewBackendSnapshot() - require.NoError(t, json.Unmarshal(data, snap)) + require.NoError(t, json.Unmarshal(data, snap, jsonx.V1())) var ous []organizations.OrganizationalUnit - require.NoError(t, json.Unmarshal(snap.Tables["ous"], &ous)) + require.NoError(t, json.Unmarshal(snap.Tables["ous"], &ous, jsonx.V1())) for i := range ous { switch ous[i].ID { @@ -233,14 +234,14 @@ func TestPathsDetachedOrCyclic(t *testing.T) { } } - rawOUs, err := json.Marshal(ous) + rawOUs, err := json.Marshal(ous, jsonx.V1()) require.NoError(t, err) snap.Tables["ous"] = rawOUs snap.OUParent[ouA.ID] = ouB.ID snap.OUParent[ouB.ID] = ouA.ID - corrupted, err := json.Marshal(snap) + corrupted, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) fresh := organizations.NewInMemoryBackend("000000000000", "us-east-1") diff --git a/services/organizations/persistence.go b/services/organizations/persistence.go index f55a4e9068..bed68e487c 100644 --- a/services/organizations/persistence.go +++ b/services/organizations/persistence.go @@ -2,11 +2,13 @@ package organizations import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -67,7 +69,7 @@ func newDirtyDTORegistry() (*store.Registry, *store.Table[delegatedAdminSnapshot // preserves that existing gap rather than fixing it as a side effect of the // datalayer swap. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Org *Organization `json:"org"` Root *Root `json:"root"` ResourcePolicy *ResourcePolicy `json:"resourcePolicy,omitempty"` @@ -159,7 +161,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { StatusCounter: b.statusCounter, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "organizations: failed to marshal snapshot", "error", err) @@ -229,7 +231,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreDelegatedAdminsLocked restores the "dirty" delegatedAdmins table // from tables via the ephemeral DTO registry, converting each DTO back to // its live *DelegatedAdmin. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDelegatedAdminsLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDelegatedAdminsLocked(tables map[string]jsontext.Value) error { dtoReg, daDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/organizations/persistence_test.go b/services/organizations/persistence_test.go index d167e9c099..7db4d5f1b3 100644 --- a/services/organizations/persistence_test.go +++ b/services/organizations/persistence_test.go @@ -1,12 +1,13 @@ package organizations_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -245,7 +246,7 @@ func TestPersistence_EnsureNonNilMaps(t *testing.T) { // After EnsureNonNilMaps all maps in the snapshot should be non-nil. // We can verify via round-trip: marshal+unmarshal should not panic. - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) assert.NotNil(t, data, tt.name) }) diff --git a/services/organizations/policies.go b/services/organizations/policies.go index eb307ce6f2..6fa76f43f7 100644 --- a/services/organizations/policies.go +++ b/services/organizations/policies.go @@ -2,8 +2,10 @@ package organizations import ( "cmp" - "encoding/json" + "encoding/json/jsontext" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const policyStatusEnabled = "ENABLED" @@ -103,7 +105,7 @@ func policyContentMaxSize(policyType string) (int, bool) { // MalformedPolicyDocumentException and documents exceeding the per-type size // quota with ConstraintViolationException(POLICY_CONTENT_LIMIT_EXCEEDED). func validatePolicyContent(content, policyType string) error { - if !json.Valid([]byte(content)) { + if !jsontext.Value([]byte(content)).IsValid(jsonx.V1()) { return ErrMalformedPolicyDocument } diff --git a/services/organizations/policies_test.go b/services/organizations/policies_test.go index 4d6b301258..73b0136636 100644 --- a/services/organizations/policies_test.go +++ b/services/organizations/policies_test.go @@ -1,7 +1,8 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "regexp" "strings" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -91,7 +93,7 @@ func TestHandler_EnablePolicyType(t *testing.T) { rootsRec := doRequest(t, h, "ListRoots", map[string]any{}) var rootsResp map[string]any - require.NoError(t, json.NewDecoder(rootsRec.Body).Decode(&rootsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rootsRec.Body), &rootsResp, jsonx.V1())) roots := rootsResp["Roots"].([]any) rootID := roots[0].(map[string]any)["Id"].(string) @@ -545,7 +547,7 @@ func TestDeletePolicy_Attached_ViaHandler(t *testing.T) { roots := doRequest(t, h, "ListRoots", nil) var rootsResp map[string]any - require.NoError(t, json.Unmarshal(roots.Body.Bytes(), &rootsResp)) + require.NoError(t, json.Unmarshal(roots.Body.Bytes(), &rootsResp, jsonx.V1())) rootID := rootsResp["Roots"].([]any)[0].(map[string]any)["Id"].(string) doRequest(t, h, "EnablePolicyType", map[string]any{"RootId": rootID, "PolicyType": "SERVICE_CONTROL_POLICY"}) @@ -559,7 +561,7 @@ func TestDeletePolicy_Attached_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, cp.Code) var cpResp map[string]any - require.NoError(t, json.Unmarshal(cp.Body.Bytes(), &cpResp)) + require.NoError(t, json.Unmarshal(cp.Body.Bytes(), &cpResp, jsonx.V1())) policyID := cpResp["Policy"].(map[string]any)["PolicySummary"].(map[string]any)["Id"].(string) doRequest(t, h, "AttachPolicy", map[string]any{"PolicyId": policyID, "TargetId": rootID}) @@ -568,7 +570,7 @@ func TestDeletePolicy_Attached_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "PolicyInUseException", errResp["__type"]) } @@ -689,7 +691,7 @@ func TestDisablePolicyType_WithAttached_ViaHandler(t *testing.T) { roots := doRequest(t, h, "ListRoots", nil) var rootsResp map[string]any - require.NoError(t, json.Unmarshal(roots.Body.Bytes(), &rootsResp)) + require.NoError(t, json.Unmarshal(roots.Body.Bytes(), &rootsResp, jsonx.V1())) rootID := rootsResp["Roots"].([]any)[0].(map[string]any)["Id"].(string) doRequest(t, h, "EnablePolicyType", map[string]any{"RootId": rootID, "PolicyType": "TAG_POLICY"}) @@ -703,7 +705,7 @@ func TestDisablePolicyType_WithAttached_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, cp.Code) var cpResp map[string]any - require.NoError(t, json.Unmarshal(cp.Body.Bytes(), &cpResp)) + require.NoError(t, json.Unmarshal(cp.Body.Bytes(), &cpResp, jsonx.V1())) policyID := cpResp["Policy"].(map[string]any)["PolicySummary"].(map[string]any)["Id"].(string) doRequest(t, h, "AttachPolicy", map[string]any{"PolicyId": policyID, "TargetId": rootID}) @@ -712,7 +714,7 @@ func TestDisablePolicyType_WithAttached_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConstraintViolationException", errResp["__type"]) } @@ -989,7 +991,7 @@ func TestCreatePolicy_MalformedContent_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "MalformedPolicyDocumentException", errResp["__type"]) } diff --git a/services/organizations/policy_attachments_test.go b/services/organizations/policy_attachments_test.go index 1136def74e..c1390403a0 100644 --- a/services/organizations/policy_attachments_test.go +++ b/services/organizations/policy_attachments_test.go @@ -1,7 +1,8 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -418,7 +420,7 @@ func TestAttachPolicy_UnknownTarget_ViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var polResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&polResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &polResp, jsonx.V1())) policyID := polResp["Policy"].(map[string]any)["PolicySummary"].(map[string]any)["Id"].(string) // Attempt to attach to a non-existent target. diff --git a/services/organizations/resource_policy_test.go b/services/organizations/resource_policy_test.go index 34c9e64670..d6ee82f30b 100644 --- a/services/organizations/resource_policy_test.go +++ b/services/organizations/resource_policy_test.go @@ -2,7 +2,8 @@ package organizations_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -254,7 +256,7 @@ func TestHandler_ResourcePolicy(t *testing.T) { if tt.op == "DescribeResourcePolicy" && tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) rp, ok := resp["ResourcePolicy"].(map[string]any) require.True(t, ok, "response must have ResourcePolicy") assert.NotEmpty(t, rp["Content"]) @@ -374,7 +376,7 @@ func TestPutResourcePolicy_Happy(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotNil(t, resp["ResourcePolicy"]) }) } diff --git a/services/organizations/roots_test.go b/services/organizations/roots_test.go index b8b9e9c91c..f955d95239 100644 --- a/services/organizations/roots_test.go +++ b/services/organizations/roots_test.go @@ -1,12 +1,15 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListRoots tests the HTTP handler for ListRoots. @@ -38,7 +41,7 @@ func TestHandler_ListRoots(t *testing.T) { if tt.wantRoots { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) roots, ok := resp["Roots"].([]any) require.True(t, ok, "response should contain Roots") assert.NotEmpty(t, roots) diff --git a/services/organizations/scp_test.go b/services/organizations/scp_test.go index 21c0fc92c8..89a3264ab6 100644 --- a/services/organizations/scp_test.go +++ b/services/organizations/scp_test.go @@ -2,12 +2,14 @@ package organizations_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/iam" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -124,11 +126,11 @@ func TestRestoreMigratesMissingDefaultSCPs(t *testing.T) { o := newSCPOrg(t) - var snap map[string]json.RawMessage - require.NoError(t, json.Unmarshal(o.b.Snapshot(context.Background()), &snap)) + var snap map[string]jsontext.Value + require.NoError(t, json.Unmarshal(o.b.Snapshot(context.Background()), &snap, jsonx.V1())) oldShape := func(key string, v any) { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) snap[key] = raw @@ -137,7 +139,7 @@ func TestRestoreMigratesMissingDefaultSCPs(t *testing.T) { oldShape("targetPolicies", map[string][]string{o.rootID: {"p-FullAWSAccess"}}) oldShape("policyTargets", map[string][]string{"p-FullAWSAccess": {o.rootID}}) - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) require.NoError(t, err) restored := organizations.NewInMemoryBackend("000000000000", "us-east-1") diff --git a/services/organizations/service_access_test.go b/services/organizations/service_access_test.go index 3e108f3e42..79bc281f8b 100644 --- a/services/organizations/service_access_test.go +++ b/services/organizations/service_access_test.go @@ -1,12 +1,15 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestBackend_ServiceAccess tests enabling/disabling AWS service access. @@ -181,7 +184,7 @@ func TestServiceAccess_Handler(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &resp, jsonx.V1())) principals := resp["EnabledServicePrincipals"].([]any) assert.Empty(t, principals, "disabled service should not appear") diff --git a/services/organizations/tags_test.go b/services/organizations/tags_test.go index 5842a509c8..0a0bd20058 100644 --- a/services/organizations/tags_test.go +++ b/services/organizations/tags_test.go @@ -1,7 +1,8 @@ package organizations_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/organizations" ) @@ -325,7 +327,7 @@ func TestTagOps_NonExistentResource_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "TargetNotFoundException", errResp["__type"], "%s on unknown resource must return TargetNotFoundException", tt.name) }) @@ -357,7 +359,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&descResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &descResp, jsonx.V1())) org := descResp["Organization"].(map[string]any) orgID := org["Id"].(string) @@ -373,7 +375,7 @@ func TestHandler_TagOperations(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var tagsResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&tagsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &tagsResp, jsonx.V1())) tags, ok := tagsResp["Tags"].([]any) require.True(t, ok) assert.NotEmpty(t, tags) @@ -635,7 +637,7 @@ func TestTagResource_ReservedPrefix_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "InvalidInputException", errResp["__type"]) } diff --git a/services/outposts/capacity_ledger_delete_cleanup_test.go b/services/outposts/capacity_ledger_delete_cleanup_test.go index bcc2ac96a4..00e689b6c5 100644 --- a/services/outposts/capacity_ledger_delete_cleanup_test.go +++ b/services/outposts/capacity_ledger_delete_cleanup_test.go @@ -1,17 +1,20 @@ package outposts_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" outpostssdk "github.com/aws/aws-sdk-go-v2/service/outposts" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // snapshotTables is a local decode of backendSnapshot's exported shape, // just enough to inspect one table's raw contents in a black-box test. type snapshotTables struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` } // TestDeleteOutpost_CleansRunningInstanceLedger guards against a ghost-row @@ -52,7 +55,7 @@ func TestDeleteOutpost_CleansRunningInstanceLedger(t *testing.T) { require.NoError(t, err) var snap snapshotTables - require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &snap)) + require.NoError(t, json.Unmarshal(h.Snapshot(t.Context()), &snap, jsonx.V1())) require.NotContains(t, string(snap.Tables["runningInstances"]), leakedInstanceID, "DeleteOutpost must clean up runningInstances rows for its own Asset(s), not leak them") diff --git a/services/outposts/handler.go b/services/outposts/handler.go index fdb1152d8b..907b3ea887 100644 --- a/services/outposts/handler.go +++ b/services/outposts/handler.go @@ -2,7 +2,7 @@ package outposts import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -576,7 +577,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { status, errType = http.StatusNotFound, "NotFoundException" } - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) @@ -662,7 +663,7 @@ func decodeJSONBody(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validationError("malformed request body: " + err.Error()) } @@ -672,7 +673,7 @@ func decodeJSONBody(body []byte, v any) error { // marshalResponse marshals v, wrapping any error as an internal failure // (marshaling our own well-typed wire structs should never fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, fmt.Errorf("outposts: marshal response: %w", err) } diff --git a/services/outposts/multi_region_test.go b/services/outposts/multi_region_test.go index 9e8d9f5237..c3d699d069 100644 --- a/services/outposts/multi_region_test.go +++ b/services/outposts/multi_region_test.go @@ -2,7 +2,8 @@ package outposts_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/outposts" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/outposts/persistence.go b/services/outposts/persistence.go index d3b130eb5c..c0b8856888 100644 --- a/services/outposts/persistence.go +++ b/services/outposts/persistence.go @@ -2,7 +2,7 @@ package outposts import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -19,10 +19,10 @@ const outpostsSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Outposts backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/personalize/handler.go b/services/personalize/handler.go index 11ec7f9348..b00620272a 100644 --- a/services/personalize/handler.go +++ b/services/personalize/handler.go @@ -2,7 +2,7 @@ package personalize import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -230,7 +231,7 @@ func writeRuntimeRESTError(c *echo.Context, status int, errType, message string) c.Response().Header().Set("Content-Type", personalizeRuntimeContentType) c.Response().Header().Set("X-Amzn-Errortype", errType) - payload, err := json.Marshal(map[string]string{"message": message}) + payload, err := json.Marshal(map[string]string{"message": message}, jsonx.V1()) if err != nil { return err } @@ -263,7 +264,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt var input map[string]any if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON", ErrValidation) } } @@ -280,7 +281,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt return nil, err } - return json.Marshal(output) + return json.Marshal(output, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { @@ -302,7 +303,10 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err c.Response().Header().Set("Content-Type", personalizeContentType) - payload, marshalErr := json.Marshal(map[string]string{"__type": errType, "message": errorMessage(errType, err)}) + payload, marshalErr := json.Marshal( + map[string]string{"__type": errType, "message": errorMessage(errType, err)}, + jsonx.V1(), + ) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } @@ -497,13 +501,13 @@ func decodeConfig[T any](raw map[string]any) *T { return nil } - b, marshalErr := json.Marshal(raw) + b, marshalErr := json.Marshal(raw, jsonx.V1()) if marshalErr != nil { return nil } var cfg T - if err := json.Unmarshal(b, &cfg); err != nil { + if err := json.Unmarshal(b, &cfg, jsonx.V1()); err != nil { return nil } diff --git a/services/personalize/handler_test.go b/services/personalize/handler_test.go index b4a6c14d4f..b2bba336c2 100644 --- a/services/personalize/handler_test.go +++ b/services/personalize/handler_test.go @@ -1,7 +1,7 @@ package personalize_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/personalize" ) @@ -52,7 +53,7 @@ func personalizeDoWithPrefix( ) *httptest.ResponseRecorder { t.Helper() - payload, err := json.Marshal(body) + payload, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -70,7 +71,7 @@ func personalizeUnmarshal(t *testing.T, rec *httptest.ResponseRecorder) map[stri t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/personalize/multi_region_test.go b/services/personalize/multi_region_test.go index f7b552ec40..95a0f1ecab 100644 --- a/services/personalize/multi_region_test.go +++ b/services/personalize/multi_region_test.go @@ -2,7 +2,8 @@ package personalize_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/personalize" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/personalize/persistence.go b/services/personalize/persistence.go index 367e62bee6..752b95427c 100644 --- a/services/personalize/persistence.go +++ b/services/personalize/persistence.go @@ -2,7 +2,7 @@ package personalize import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -38,7 +38,7 @@ const personalizeSnapshotVersion = 1 // *T, so it does not fit store.Table's keyed-by-identity-value shape) and is // persisted here directly instead. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountId"` Region string `json:"region"` diff --git a/services/personalize/validate.go b/services/personalize/validate.go index 7b4f839711..e630bc2022 100644 --- a/services/personalize/validate.go +++ b/services/personalize/validate.go @@ -2,11 +2,13 @@ package personalize import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -44,7 +46,7 @@ func validateSchemaDocument(schema string) error { } var doc map[string]any - if err := json.Unmarshal([]byte(schema), &doc); err != nil { + if err := json.Unmarshal([]byte(schema), &doc, jsonx.V1()); err != nil { return fmt.Errorf("%w: schema is not valid JSON", ErrValidation) } diff --git a/services/pinpoint/applications_settings_test.go b/services/pinpoint/applications_settings_test.go index 855e991429..c529116937 100644 --- a/services/pinpoint/applications_settings_test.go +++ b/services/pinpoint/applications_settings_test.go @@ -1,12 +1,15 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestApplicationSettings_BodyPersistence(t *testing.T) { @@ -82,7 +85,7 @@ func TestApplicationSettings_BodyPersistence(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) // Update settings. @@ -90,14 +93,14 @@ func TestApplicationSettings_BodyPersistence(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) // GET settings back. getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/settings", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) if tc.wantCampaignHook { hook, ok := getResp["CampaignHook"].(map[string]any) @@ -169,7 +172,7 @@ func TestApplicationSettings_CloudWatchMetrics(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "CloudWatchMetricsEnabled") }) } @@ -229,14 +232,14 @@ func TestApplicationSettings_EventTaggingCases(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) assert.NotContains(t, putResp, "EventTaggingEnabled") getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/settings", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, getResp, "EventTaggingEnabled") }) } @@ -307,7 +310,7 @@ func TestApplicationSettings_LimitsCases(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) limits, ok := resp["Limits"].(map[string]any) require.True(t, ok, "Limits must be an object") assert.InDelta(t, tc.checkVal, limits[tc.checkKey], 0.001) @@ -345,7 +348,7 @@ func TestApplicationDateRangeKpi(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, tc.kpiName, resp["KpiName"]) assert.NotNil(t, resp["KpiResult"]) @@ -464,7 +467,7 @@ func TestApplicationSettings_FullRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) assert.NotContains(t, putResp, "CloudWatchMetricsEnabled") assert.NotContains(t, putResp, "EventTaggingEnabled") assert.NotNil(t, putResp["CampaignHook"]) @@ -476,7 +479,7 @@ func TestApplicationSettings_FullRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, getResp, "CloudWatchMetricsEnabled") assert.NotContains(t, getResp, "EventTaggingEnabled") }) @@ -505,7 +508,7 @@ func TestApplicationSettings_CampaignHook(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var settings map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings, jsonx.V1())) gotHook := settings["CampaignHook"].(map[string]any) assert.Equal(t, "arn:aws:lambda:us-east-1:123456789012:function:SegmentHook", gotHook["LambdaFunctionName"]) @@ -547,7 +550,7 @@ func TestApplicationSettings_QuietTime(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var settings map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings, jsonx.V1())) qt := settings["QuietTime"].(map[string]any) assert.Equal(t, tc.wantStart, qt["Start"]) @@ -577,7 +580,7 @@ func TestApplicationSettings_Limits(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var settings map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings, jsonx.V1())) got := settings["Limits"].(map[string]any) assert.EqualValues(t, 500, got["Daily"]) @@ -620,7 +623,7 @@ func TestApplicationSettings_MultipleUpdates(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var settings map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings, jsonx.V1())) assert.NotContains(t, settings, "CloudWatchMetricsEnabled") @@ -648,7 +651,7 @@ func TestApplicationSettings_EventTagging(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var settings map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &settings, jsonx.V1())) assert.NotContains(t, settings, "EventTaggingEnabled") assert.NotContains(t, settings, "CloudWatchMetricsEnabled") @@ -690,7 +693,7 @@ func TestHandler_ApplicationSettings(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var appResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&appResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &appResp, jsonx.V1())) appID, _ := appResp["Id"].(string) require.NotEmpty(t, appID) @@ -706,7 +709,7 @@ func TestHandler_ApplicationSettings(t *testing.T) { assert.Equal(t, tt.wantStatus, rec2.Code) var settingsResp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&settingsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &settingsResp, jsonx.V1())) assert.Equal(t, appID, settingsResp["ApplicationId"]) // CampaignHook, Limits, and QuietTime must be non-nil empty objects so // the Terraform provider flatten helpers don't panic on nil dereferences. @@ -753,19 +756,19 @@ func TestAppSettings_LastModifiedDate_ConsistentAfterUpdate(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) putDate, _ := putResp["LastModifiedDate"].(string) require.NotEmpty(t, putDate, "PUT must return non-empty LastModifiedDate") getRec1 := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/settings", nil) require.Equal(t, http.StatusOK, getRec1.Code) var getResp1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1, jsonx.V1())) getRec2 := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/settings", nil) require.Equal(t, http.StatusOK, getRec2.Code) var getResp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2, jsonx.V1())) date1, _ := getResp1["LastModifiedDate"].(string) date2, _ := getResp2["LastModifiedDate"].(string) @@ -786,7 +789,7 @@ func TestAppSettings_LastModifiedDate_UpdatesOnSecondPut(t *testing.T) { map[string]any{"CloudWatchMetricsEnabled": true}) require.Equal(t, http.StatusOK, put1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(put1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(put1.Body.Bytes(), &r1, jsonx.V1())) date1, _ := r1["LastModifiedDate"].(string) require.NotEmpty(t, date1) @@ -795,7 +798,7 @@ func TestAppSettings_LastModifiedDate_UpdatesOnSecondPut(t *testing.T) { map[string]any{"EventTaggingEnabled": true}) require.Equal(t, http.StatusOK, put2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(put2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(put2.Body.Bytes(), &r2, jsonx.V1())) date2, _ := r2["LastModifiedDate"].(string) require.NotEmpty(t, date2) @@ -803,7 +806,7 @@ func TestAppSettings_LastModifiedDate_UpdatesOnSecondPut(t *testing.T) { getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/settings", nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) getDate, _ := getResp["LastModifiedDate"].(string) assert.Equal(t, date2, getDate, "GET must return the most recent PUT's LastModifiedDate") diff --git a/services/pinpoint/apps_test.go b/services/pinpoint/apps_test.go index de86fe4eee..b2ef7bbd34 100644 --- a/services/pinpoint/apps_test.go +++ b/services/pinpoint/apps_test.go @@ -1,13 +1,16 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestBackend_CreateApp(t *testing.T) { @@ -284,7 +287,7 @@ func TestAppNotFound_Returns404(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "NotFoundException", resp["__type"]) }) } @@ -301,7 +304,7 @@ func TestCreateApp_ResponseShape(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"], "Id must be present") assert.NotEmpty(t, resp["Arn"], "Arn must be present") @@ -325,7 +328,7 @@ func TestGetApps_ReflectsCreatedApps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) item := resp["Item"].([]any) assert.Len(t, item, len(names)) @@ -344,7 +347,7 @@ func TestDeleteApp_RemovesFromList(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) appID := created["Id"].(string) doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "also-here"}) @@ -358,7 +361,7 @@ func TestDeleteApp_RemovesFromList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) item := listResp["Item"].([]any) assert.Len(t, item, 1) } @@ -377,7 +380,7 @@ func TestHandlerReset(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Empty(t, items) } @@ -439,7 +442,7 @@ func TestHandler_CreateApp(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.NotEmpty(t, resp["Arn"]) } @@ -480,7 +483,7 @@ func TestHandler_GetApp(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) appID, _ = resp["Id"].(string) } else { @@ -527,7 +530,7 @@ func TestHandler_DeleteApp(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) appID, _ = resp["Id"].(string) } else { @@ -580,7 +583,7 @@ func TestHandler_GetApps(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tt.wantCount) @@ -649,7 +652,7 @@ func TestHandler_GetAppsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, ok := resp["Item"].([]any) if tt.wantCount > 0 { @@ -679,7 +682,7 @@ func TestHandler_GetAppsContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.NewDecoder(rec1.Body).Decode(&resp1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec1.Body), &resp1, jsonx.V1())) page1, ok := resp1["Item"].([]any) require.True(t, ok, "expected Item array in first-page response") @@ -695,7 +698,7 @@ func TestHandler_GetAppsContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&resp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &resp2, jsonx.V1())) page2, ok := resp2["Item"].([]any) require.True(t, ok, "expected Item array in second-page response") @@ -740,7 +743,7 @@ func TestHandler_GetApps_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) created[resp["Id"].(string)] = true } @@ -752,7 +755,7 @@ func TestHandler_GetApps_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) for _, item := range items { diff --git a/services/pinpoint/attributes_test.go b/services/pinpoint/attributes_test.go index 365ed0a2d4..e87d0aadce 100644 --- a/services/pinpoint/attributes_test.go +++ b/services/pinpoint/attributes_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestAudit6_RemoveAttributes_RemovesBlacklistedNamesOnly verifies @@ -36,14 +38,14 @@ func TestRemoveAttributes_RemovesBlacklistedNamesOnly(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "endpoint-custom-attributes", resp["AttributeType"]) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/endpoints/ep-1", nil) require.Equal(t, http.StatusOK, getRec.Code) var ep map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep, jsonx.V1())) attrs, _ := ep["Attributes"].(map[string]any) _, hasInterests := attrs["Interests"] diff --git a/services/pinpoint/campaigns_fields_test.go b/services/pinpoint/campaigns_fields_test.go index 6ce470a3c4..85119a1c42 100644 --- a/services/pinpoint/campaigns_fields_test.go +++ b/services/pinpoint/campaigns_fields_test.go @@ -2,7 +2,7 @@ package pinpoint_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCampaign_AdditionalTreatments(t *testing.T) { @@ -108,7 +110,7 @@ func TestCampaign_AdditionalTreatments(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantHasTreatment { treatments, _ := resp["AdditionalTreatments"].([]any) @@ -203,7 +205,7 @@ func TestCampaign_StateMachine(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) campaignID := createResp["Id"].(string) if tc.updateBody == nil { @@ -219,7 +221,7 @@ func TestCampaign_StateMachine(t *testing.T) { assert.Equal(t, tc.wantStatus, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) state, _ := updateResp["State"].(map[string]any) require.NotNil(t, state) @@ -258,7 +260,7 @@ func TestCampaign_DateRangeKpi(t *testing.T) { map[string]any{"Name": "kpi-camp", "SegmentId": "seg-1"}) require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campaignID := cr["Id"].(string) kpiRec := doPinpointRequest(t, h, http.MethodGet, @@ -266,7 +268,7 @@ func TestCampaign_DateRangeKpi(t *testing.T) { require.Equal(t, http.StatusOK, kpiRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(kpiRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(kpiRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, campaignID, resp["CampaignId"]) assert.Equal(t, tc.kpiName, resp["KpiName"]) @@ -314,7 +316,7 @@ func TestCampaign_GetActivities(t *testing.T) { "/v1/apps/"+appID+"/campaigns", tc.campaignBody) require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campaignID := cr["Id"].(string) actRec := doPinpointRequest(t, h, http.MethodGet, @@ -322,7 +324,7 @@ func TestCampaign_GetActivities(t *testing.T) { require.Equal(t, http.StatusOK, actRec.Code) var actResp map[string]any - require.NoError(t, json.Unmarshal(actRec.Body.Bytes(), &actResp)) + require.NoError(t, json.Unmarshal(actRec.Body.Bytes(), &actResp, jsonx.V1())) assert.Contains(t, actResp, "Item") }) } @@ -380,7 +382,7 @@ func TestCampaign_SegmentVersion(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantSegVersion != 0 { assert.InDelta(t, tc.wantSegVersion, resp["SegmentVersion"], 0.001) } else { @@ -457,14 +459,14 @@ func TestCampaign_TemplateConfiguration_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campID, nil) require.Equal(t, http.StatusOK, getRec.Code) var c map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c, jsonx.V1())) tmplCfg, ok := c["TemplateConfiguration"].(map[string]any) assert.True(t, ok, "TemplateConfiguration must be present") @@ -502,14 +504,14 @@ func TestCampaign_Limits_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campID, nil) require.Equal(t, http.StatusOK, getRec.Code) var c map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c, jsonx.V1())) got := c["Limits"].(map[string]any) assert.EqualValues(t, 200, got["Daily"]) @@ -540,14 +542,14 @@ func TestCampaign_Hook_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campID, nil) require.Equal(t, http.StatusOK, getRec.Code) var c map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c, jsonx.V1())) got := c["Hook"].(map[string]any) assert.Equal(t, "arn:aws:lambda:us-east-1:123456789012:function:SegmentFilter", got["LambdaFunctionName"]) @@ -566,7 +568,7 @@ func TestCampaign_TemplateConfiguration_OnUpdate(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campID := cr["Id"].(string) // Update to set template configuration @@ -584,7 +586,7 @@ func TestCampaign_TemplateConfiguration_OnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var c map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c, jsonx.V1())) tmpl := c["TemplateConfiguration"].(map[string]any) email := tmpl["EmailTemplate"].(map[string]any) @@ -617,14 +619,14 @@ func TestCampaign_CustomDeliveryConfiguration(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) campID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campID, nil) require.Equal(t, http.StatusOK, getRec.Code) var c map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &c, jsonx.V1())) got := c["CustomDeliveryConfiguration"].(map[string]any) assert.Equal(t, "arn:aws:lambda:us-east-1:123456789012:function:CustomDelivery", got["DeliveryUri"]) @@ -655,7 +657,7 @@ func TestPagination_Campaigns_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, p1Rec.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1, jsonx.V1())) items1, _ := p1["Item"].([]any) assert.Len(t, items1, 2, "page 1 should contain 2 items") @@ -669,7 +671,7 @@ func TestPagination_Campaigns_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, p2Rec.Code) var p2 map[string]any - require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2, jsonx.V1())) items2, _ := p2["Item"].([]any) assert.Len(t, items2, 2, "page 2 should contain 2 items") @@ -682,7 +684,7 @@ func TestPagination_Campaigns_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, p3Rec.Code) var p3 map[string]any - require.NoError(t, json.Unmarshal(p3Rec.Body.Bytes(), &p3)) + require.NoError(t, json.Unmarshal(p3Rec.Body.Bytes(), &p3, jsonx.V1())) items3, _ := p3["Item"].([]any) assert.Len(t, items3, 1, "page 3 should contain the remaining 1 item") @@ -707,7 +709,7 @@ func TestPagination_Campaigns_NoToken_ReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, 3) @@ -732,7 +734,7 @@ func TestPagination_TokenEncoding(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tok, _ := resp["NextToken"].(string) require.NotEmpty(t, tok) @@ -756,7 +758,7 @@ func TestPagination_EmptyList_NoToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Empty(t, items) @@ -778,7 +780,7 @@ func TestGetCampaignVersions_CrossAppIsolation(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) campaignID, _ := createResp["Id"].(string) require.NotEmpty(t, campaignID) diff --git a/services/pinpoint/campaigns_test.go b/services/pinpoint/campaigns_test.go index fa1bc26fe3..9ad07e45cb 100644 --- a/services/pinpoint/campaigns_test.go +++ b/services/pinpoint/campaigns_test.go @@ -1,13 +1,16 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCampaignFullDTO_Create(t *testing.T) { @@ -169,7 +172,7 @@ func TestCampaignFullDTO_Create(t *testing.T) { require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", tc.body) @@ -180,7 +183,7 @@ func TestCampaignFullDTO_Create(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, appID, resp["ApplicationId"]) @@ -299,13 +302,13 @@ func TestCampaignStateMachine_Update(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", tc.createBody) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) campaignID := created["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPut, "/v1/apps/"+appID+"/campaigns/"+campaignID, tc.updateBody) @@ -316,7 +319,7 @@ func TestCampaignStateMachine_Update(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantState != "" { state, _ := resp["State"].(map[string]any) @@ -342,14 +345,14 @@ func TestCampaignVersioning(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", map[string]any{"Name": "versioned", "SegmentId": "seg-1"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) campaignID := created["Id"].(string) // Do 3 updates. @@ -363,7 +366,7 @@ func TestCampaignVersioning(t *testing.T) { verRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campaignID+"/versions", nil) require.Equal(t, http.StatusOK, verRec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp, jsonx.V1())) items, _ := verResp["Item"].([]any) assert.Len(t, items, 4, "should have 4 versions") @@ -371,7 +374,7 @@ func TestCampaignVersioning(t *testing.T) { v1Rec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/campaigns/"+campaignID+"/versions/1", nil) require.Equal(t, http.StatusOK, v1Rec.Code) var v1Resp map[string]any - require.NoError(t, json.Unmarshal(v1Rec.Body.Bytes(), &v1Resp)) + require.NoError(t, json.Unmarshal(v1Rec.Body.Bytes(), &v1Resp, jsonx.V1())) assert.InDelta(t, float64(1), v1Resp["Version"], 0.001) } @@ -387,14 +390,14 @@ func TestCampaignPauseUnpauseCycle(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", map[string]any{"Name": "cycle", "SegmentId": "seg-1"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) campaignID := created["Id"].(string) // Check initial state. @@ -406,7 +409,7 @@ func TestCampaignPauseUnpauseCycle(t *testing.T) { map[string]any{"IsPaused": true}) require.Equal(t, http.StatusOK, pauseRec.Code) var paused map[string]any - require.NoError(t, json.Unmarshal(pauseRec.Body.Bytes(), &paused)) + require.NoError(t, json.Unmarshal(pauseRec.Body.Bytes(), &paused, jsonx.V1())) pausedState, _ := paused["State"].(map[string]any) assert.Equal(t, "PAUSED", pausedState["CampaignStatus"]) @@ -415,7 +418,7 @@ func TestCampaignPauseUnpauseCycle(t *testing.T) { map[string]any{"IsPaused": false}) require.Equal(t, http.StatusOK, unpauseRec.Code) var unpaused map[string]any - require.NoError(t, json.Unmarshal(unpauseRec.Body.Bytes(), &unpaused)) + require.NoError(t, json.Unmarshal(unpauseRec.Body.Bytes(), &unpaused, jsonx.V1())) unpausedState, _ := unpaused["State"].(map[string]any) assert.Equal(t, "SCHEDULED", unpausedState["CampaignStatus"]) } @@ -440,7 +443,7 @@ func TestCampaign_ScheduleFrequencyRoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", @@ -455,7 +458,7 @@ func TestCampaign_ScheduleFrequencyRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedule, _ := resp["Schedule"].(map[string]any) assert.Equal(t, freq, schedule["Frequency"]) @@ -471,7 +474,7 @@ func TestCampaign_AdditionalTreatments_RoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/campaigns", @@ -495,7 +498,7 @@ func TestCampaign_AdditionalTreatments_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) treatments, _ := resp["AdditionalTreatments"].([]any) assert.Len(t, treatments, 2) @@ -516,7 +519,7 @@ func TestCampaignCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) campaignID, _ := createResp["Id"].(string) require.NotEmpty(t, campaignID) @@ -626,7 +629,7 @@ func TestHandler_CreateCampaign(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, appID, resp["ApplicationId"]) @@ -652,7 +655,7 @@ func TestGetCampaignVersion_UnknownVersionNotFound(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.NewDecoder(createRec.Body).Decode(&created)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(createRec.Body), &created, jsonx.V1())) campaignID, _ := created["Id"].(string) require.NotEmpty(t, campaignID) @@ -668,7 +671,7 @@ func TestGetCampaignVersion_UnknownVersionNotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, missingRec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(missingRec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(missingRec.Body), &errResp, jsonx.V1())) assert.Equal(t, "NotFoundException", errResp["__type"]) } @@ -696,7 +699,7 @@ func TestHandler_GetCampaigns_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) created[resp["Id"].(string)] = true } @@ -708,7 +711,7 @@ func TestHandler_GetCampaigns_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) for _, item := range items { diff --git a/services/pinpoint/channel_credential_echo_test.go b/services/pinpoint/channel_credential_echo_test.go index ee1740ef02..33a4e5039c 100644 --- a/services/pinpoint/channel_credential_echo_test.go +++ b/services/pinpoint/channel_credential_echo_test.go @@ -1,7 +1,7 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -207,7 +208,7 @@ func TestGetAdmChannel_NoRawSecretInBody(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &body, jsonx.V1())) assert.NotContains(t, body, "ClientId") assert.NotContains(t, body, "ClientSecret") @@ -231,7 +232,7 @@ func TestGetApnsChannel_NoRawSecretInBody(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &body, jsonx.V1())) for _, k := range []string{"BundleId", "Certificate", "TeamId", "TokenKey", "TokenKeyId"} { assert.NotContains(t, body, k) diff --git a/services/pinpoint/channels_test.go b/services/pinpoint/channels_test.go index 7048dfa951..c8d40ab382 100644 --- a/services/pinpoint/channels_test.go +++ b/services/pinpoint/channels_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestChannel_PerTypeFields(t *testing.T) { @@ -129,7 +131,7 @@ func TestChannel_PerTypeFields(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPut, @@ -141,7 +143,7 @@ func TestChannel_PerTypeFields(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantEnabled, resp["Enabled"]) assert.NotEmpty(t, resp["CreationDate"]) @@ -160,7 +162,7 @@ func TestChannel_PerTypeFields(t *testing.T) { "/v1/apps/"+appID+"/channels/"+tc.channelType, nil) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, resp["Enabled"], getResp["Enabled"]) assert.Equal(t, resp["HasCredential"], getResp["HasCredential"]) }) @@ -175,7 +177,7 @@ func TestChannel_VersionIncrements(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) for i := 1; i <= 3; i++ { @@ -184,7 +186,7 @@ func TestChannel_VersionIncrements(t *testing.T) { map[string]any{"ApiKey": "key", "Enabled": true}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InDelta(t, float64(i), resp["Version"], 0.001, "version should increment on each put") } } @@ -197,7 +199,7 @@ func TestChannel_CreationDatePreserved(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec1 := doPinpointRequest(t, h, http.MethodPut, @@ -205,7 +207,7 @@ func TestChannel_CreationDatePreserved(t *testing.T) { map[string]any{"ApiKey": "key", "Enabled": true}) require.Equal(t, http.StatusOK, rec1.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) creationDate1 := r1["CreationDate"].(string) rec2 := doPinpointRequest(t, h, http.MethodPut, @@ -213,7 +215,7 @@ func TestChannel_CreationDatePreserved(t *testing.T) { map[string]any{"ApiKey": "key-updated", "Enabled": true}) require.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) creationDate2 := r2["CreationDate"].(string) assert.Equal(t, creationDate1, creationDate2, "CreationDate should be preserved on update") @@ -231,7 +233,7 @@ func TestChannel_AllChannelsListed(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) channelTypes := []string{"gcm", "email", "sms"} @@ -250,7 +252,7 @@ func TestChannel_AllChannelsListed(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) channels, _ := listResp["Channels"].(map[string]any) assert.Len(t, channels, 3) @@ -324,7 +326,7 @@ func TestSMSChannel_Attributes(t *testing.T) { "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantEnabled, resp["Enabled"]) getRec := doPinpointRequest(t, h, http.MethodGet, @@ -332,7 +334,7 @@ func TestSMSChannel_Attributes(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr, jsonx.V1())) chType, _ := gr["ChannelType"].(string) assert.True(t, chType == "SMS" || chType == "sms", "expected SMS channel type, got %q", chType) }) @@ -412,7 +414,7 @@ func TestEmailChannel_Identity(t *testing.T) { "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantEnabled, resp["Enabled"]) chType, _ := resp["ChannelType"].(string) assert.True(t, chType == "EMAIL" || chType == "email", "expected EMAIL channel type, got %q", chType) @@ -468,7 +470,7 @@ func TestChannel_Delete_ReturnsChannel(t *testing.T) { require.Equal(t, http.StatusOK, delRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, tc.channelType, ch["ChannelType"]) }) } @@ -495,7 +497,7 @@ func TestGetChannels_IncludesExtraFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) channels, ok := resp["Channels"].(map[string]any) require.True(t, ok, "Channels must be a map") diff --git a/services/pinpoint/channels_types_test.go b/services/pinpoint/channels_types_test.go index d827e89af7..f54fedf3d5 100644 --- a/services/pinpoint/channels_types_test.go +++ b/services/pinpoint/channels_types_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestChannel_APNS_CertificateAuth(t *testing.T) { @@ -28,7 +30,7 @@ func TestChannel_APNS_CertificateAuth(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, true, ch["Enabled"]) assert.Equal(t, true, ch["HasCredential"], "certificate auth sets HasCredential") @@ -56,7 +58,7 @@ func TestChannel_APNS_TokenAuth(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, true, ch["Enabled"]) // BundleId sets HasCredential; TokenKey sets HasTokenKey @@ -83,7 +85,7 @@ func TestChannel_APNS_Sandbox(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "apns_sandbox", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -108,7 +110,7 @@ func TestChannel_ADM_HasCredential(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "adm", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -133,7 +135,7 @@ func TestChannel_Baidu_HasCredential(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "baidu", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -158,7 +160,7 @@ func TestChannel_GCM_ServiceJSON(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "gcm", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -180,7 +182,7 @@ func TestChannel_Voice_EnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "voice", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -196,7 +198,7 @@ func TestChannel_Voice_EnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var ch2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &ch2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &ch2, jsonx.V1())) assert.Equal(t, false, ch2["Enabled"]) assert.EqualValues(t, 2, ch2["Version"]) @@ -216,7 +218,7 @@ func TestChannel_InApp_EnableDisable(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, true, ch["Enabled"]) } @@ -239,7 +241,7 @@ func TestChannel_SMS_ShortCode(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ch map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ch, jsonx.V1())) assert.Equal(t, "sms", ch["ChannelType"]) assert.Equal(t, true, ch["Enabled"]) @@ -304,7 +306,7 @@ func TestSMSChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) assert.Equal(t, tc.wantEnabled, putResp["Enabled"]) assert.NotContains(t, putResp, "PromotionalMessagesPerSecond") @@ -324,7 +326,7 @@ func TestSMSChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tc.wantEnabled, getResp["Enabled"]) @@ -385,7 +387,7 @@ func TestGCMChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantAuthMethod != "" { assert.Equal(t, tc.wantAuthMethod, resp["DefaultAuthenticationMethod"]) @@ -427,7 +429,7 @@ func TestAPNSChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) // APNSChannelResponse has no BundleId/Certificate/TeamId members -- only // HasCredential/HasTokenKey booleans -- so raw request secrets must never @@ -460,7 +462,7 @@ func TestEmailChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "noreply@example.com", resp["FromAddress"]) assert.Equal(t, "arn:aws:ses:us-east-1:123456789012:identity/example.com", resp["Identity"]) @@ -475,7 +477,7 @@ func TestEmailChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "noreply@example.com", getResp["FromAddress"]) assert.Equal(t, "my-config-set", getResp["ConfigurationSet"]) @@ -499,7 +501,7 @@ func TestBaiduChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) // BaiduChannelResponse's credential member is "Credential" (the API key, // required), not "ApiKey"; SecretKey has no response member at all. @@ -525,7 +527,7 @@ func TestADMChannel_PerTypeFields(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) // ADMChannelResponse has no ClientId/ClientSecret members -- only // HasCredential -- so neither must be echoed back on the wire. @@ -546,7 +548,7 @@ func TestVoiceChannel_BasicResponse(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["Enabled"]) assert.NotEmpty(t, resp["ChannelType"]) @@ -573,6 +575,6 @@ func TestApnsChannel_DefaultAuthenticationMethod(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TOKEN", resp["DefaultAuthenticationMethod"]) } diff --git a/services/pinpoint/endpoints_test.go b/services/pinpoint/endpoints_test.go index dab1f1ed60..db218f6848 100644 --- a/services/pinpoint/endpoints_test.go +++ b/services/pinpoint/endpoints_test.go @@ -1,13 +1,15 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEndpoint_FullShape(t *testing.T) { @@ -119,7 +121,7 @@ func TestEndpoint_FullShape(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) endpointID := "ep-" + tc.name @@ -137,7 +139,7 @@ func TestEndpoint_FullShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantChannelType != "" { assert.Equal(t, tc.wantChannelType, resp["ChannelType"]) @@ -174,7 +176,7 @@ func TestEndpoint_UserAttributes(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPut, "/v1/apps/"+appID+"/endpoints/ep-1", @@ -196,7 +198,7 @@ func TestEndpoint_UserAttributes(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) user, ok := resp["User"].(map[string]any) require.True(t, ok, "User field must be present") @@ -217,7 +219,7 @@ func TestEndpointBatch_FullShape(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) // Real EndpointBatchRequest.Item is a JSON array of EndpointBatchItem, @@ -258,7 +260,7 @@ func TestEndpointBatch_FullShape(t *testing.T) { getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/endpoints/ep-batch-1", nil) require.Equal(t, http.StatusOK, getRec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r1, jsonx.V1())) assert.NotNil(t, r1["Attributes"]) assert.NotNil(t, r1["Metrics"]) assert.NotNil(t, r1["Demographic"]) @@ -267,7 +269,7 @@ func TestEndpointBatch_FullShape(t *testing.T) { getRec2 := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/endpoints/ep-batch-2", nil) require.Equal(t, http.StatusOK, getRec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &r2, jsonx.V1())) assert.Equal(t, "INACTIVE", r2["EndpointStatus"]) assert.Equal(t, "ALL", r2["OptOut"]) } @@ -284,7 +286,7 @@ func TestEndpoint_EffectiveDate_RoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) effectiveDate := "2026-01-15T10:30:00Z" @@ -299,7 +301,7 @@ func TestEndpoint_EffectiveDate_RoundTrip(t *testing.T) { getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/endpoints/ep-eff", nil) require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, effectiveDate, resp["EffectiveDate"]) } @@ -330,7 +332,7 @@ func TestEndpoint_UserAttributes_MultiValue(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ep map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep, jsonx.V1())) user := ep["User"].(map[string]any) assert.Equal(t, "user-001", user["UserId"]) @@ -390,7 +392,7 @@ func TestEndpoint_UserAttributes_UpdateMerge(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ep map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep, jsonx.V1())) ua := ep["User"].(map[string]any)["UserAttributes"].(map[string]any) assert.Equal(t, []any{"gold"}, ua["tier"]) @@ -435,7 +437,7 @@ func TestGetUserEndpoints_ByUserID(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Item"].([]any) assert.Len(t, items, 2, "only endpoints for shared-user") @@ -489,7 +491,7 @@ func TestEndpoint_UserAttributes_BatchUpdate(t *testing.T) { require.Equal(t, http.StatusOK, getRec1.Code) var ep1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &ep1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &ep1, jsonx.V1())) ua1 := ep1["User"].(map[string]any)["UserAttributes"].(map[string]any) assert.Equal(t, []any{"beta-testers"}, ua1["segment"]) @@ -499,7 +501,7 @@ func TestEndpoint_UserAttributes_BatchUpdate(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var ep2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &ep2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &ep2, jsonx.V1())) ua2 := ep2["User"].(map[string]any)["UserAttributes"].(map[string]any) assert.Equal(t, []any{"power-users"}, ua2["segment"]) } @@ -532,7 +534,7 @@ func TestEndpoint_Metrics_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ep map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep, jsonx.V1())) metrics := ep["Metrics"].(map[string]any) assert.InDelta(t, 12.0, metrics["session_count"], 0.001) @@ -577,7 +579,7 @@ func TestEndpoint_Demographic_Location(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var ep map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &ep, jsonx.V1())) demo := ep["Demographic"].(map[string]any) assert.Equal(t, "4.2.1", demo["AppVersion"]) @@ -730,7 +732,7 @@ func TestUpdateEndpoint_ReturnsMessageBody(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) msg, _ := resp["Message"].(string) assert.Equal(t, "Accepted", msg, diff --git a/services/pinpoint/error_envelope_test.go b/services/pinpoint/error_envelope_test.go index 6d933eab06..852db40172 100644 --- a/services/pinpoint/error_envelope_test.go +++ b/services/pinpoint/error_envelope_test.go @@ -1,7 +1,7 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/pinpoint" @@ -90,7 +91,7 @@ func TestErrorEnvelope_GetAppNotFoundDecodesToTypedError(t *testing.T) { require.NoError(t, err) var envelope map[string]any - require.NoError(t, json.Unmarshal(raw, &envelope)) + require.NoError(t, json.Unmarshal(raw, &envelope, jsonx.V1())) require.Equal(t, "NotFoundException", envelope["__type"], "raw body must carry __type key restjson.GetErrorInfo's fallback reads: %s", raw) diff --git a/services/pinpoint/event_streams_test.go b/services/pinpoint/event_streams_test.go index 90f69a765a..cfb20696b1 100644 --- a/services/pinpoint/event_streams_test.go +++ b/services/pinpoint/event_streams_test.go @@ -1,13 +1,15 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestEventStream_PutAndGet_Fields(t *testing.T) { @@ -30,7 +32,7 @@ func TestEventStream_PutAndGet_Fields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var es map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &es)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &es, jsonx.V1())) assert.Equal(t, destArn, es["DestinationStreamArn"]) assert.Equal(t, roleArn, es["RoleArn"]) @@ -59,7 +61,7 @@ func TestEventStream_Replace(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var es map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &es)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &es, jsonx.V1())) assert.Equal(t, stream2, es["DestinationStreamArn"], "second PUT must replace first") } @@ -101,13 +103,13 @@ func TestEventStream_AppIsolation(t *testing.T) { getA := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appA+"/eventstream", nil) require.Equal(t, http.StatusOK, getA.Code) var esA map[string]any - require.NoError(t, json.Unmarshal(getA.Body.Bytes(), &esA)) + require.NoError(t, json.Unmarshal(getA.Body.Bytes(), &esA, jsonx.V1())) assert.Equal(t, streamA, esA["DestinationStreamArn"]) getB := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appB+"/eventstream", nil) require.Equal(t, http.StatusOK, getB.Code) var esB map[string]any - require.NoError(t, json.Unmarshal(getB.Body.Bytes(), &esB)) + require.NoError(t, json.Unmarshal(getB.Body.Bytes(), &esB, jsonx.V1())) assert.Equal(t, streamB, esB["DestinationStreamArn"]) } diff --git a/services/pinpoint/events_test.go b/services/pinpoint/events_test.go index dfabb35397..6b49df5e61 100644 --- a/services/pinpoint/events_test.go +++ b/services/pinpoint/events_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPutEvents_AppLifeCycleEvent(t *testing.T) { @@ -150,7 +152,7 @@ func TestPutEvents_ReturnsEventResults(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["Results"].(map[string]any) require.True(t, ok, "EventsResponse must have Results") @@ -199,7 +201,7 @@ func TestPutEvents_MultipleEndpoints(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["Results"].(map[string]any) @@ -226,7 +228,7 @@ func TestPutEvents_EmptyBatch(t *testing.T) { require.Equal(t, http.StatusAccepted, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["Results"].(map[string]any) assert.Empty(t, results, "empty BatchItem → empty Results") diff --git a/services/pinpoint/export_import_jobs_test.go b/services/pinpoint/export_import_jobs_test.go index 041f33b3b7..295f738c2d 100644 --- a/services/pinpoint/export_import_jobs_test.go +++ b/services/pinpoint/export_import_jobs_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/pinpoint/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestImportJob_CreatesSegment(t *testing.T) { @@ -33,7 +36,7 @@ func TestImportJob_CreatesSegment(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["Item"].([]any) require.Len(t, items, 1, "import job must materialise exactly one segment") @@ -70,7 +73,7 @@ func TestImportJob_DefaultSegmentName(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["Item"].([]any) require.Len(t, items, 1) @@ -97,7 +100,7 @@ func TestImportJob_SegmentGetByID(t *testing.T) { listRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments", nil) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["Item"].([]any) segID := items[0].(map[string]any)["Id"].(string) @@ -106,7 +109,7 @@ func TestImportJob_SegmentGetByID(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var s map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s, jsonx.V1())) assert.Equal(t, "IMPORT", s["SegmentType"]) assert.Equal(t, "direct-import", s["Name"]) } @@ -302,7 +305,7 @@ func TestHandler_CreateExportJob(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, "CREATED", resp["JobStatus"]) @@ -345,7 +348,7 @@ func TestHandler_CreateImportJob(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, "CREATED", resp["JobStatus"]) @@ -376,7 +379,7 @@ func TestGetSegmentImportJobs_FiltersBySegment(t *testing.T) { segsRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments", nil) require.Equal(t, http.StatusOK, segsRec.Code) var segsResp map[string]any - require.NoError(t, json.Unmarshal(segsRec.Body.Bytes(), &segsResp)) + require.NoError(t, json.Unmarshal(segsRec.Body.Bytes(), &segsResp, jsonx.V1())) items, _ := segsResp["Item"].([]any) require.Len(t, items, 1, "import job must materialise exactly one segment") @@ -388,7 +391,7 @@ func TestGetSegmentImportJobs_FiltersBySegment(t *testing.T) { require.Equal(t, http.StatusOK, jobsRec.Code) var jobsResp map[string]any - require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp)) + require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp, jsonx.V1())) jobs, _ := jobsResp["Item"].([]any) assert.Len(t, jobs, 1, "GetSegmentImportJobs must return the job that created the segment") @@ -415,7 +418,7 @@ func TestGetSegmentImportJobs_OtherSegmentReturnsEmpty(t *testing.T) { map[string]any{"Name": "unrelated-segment"}) require.Equal(t, http.StatusCreated, segRec.Code) var segResp map[string]any - require.NoError(t, json.Unmarshal(segRec.Body.Bytes(), &segResp)) + require.NoError(t, json.Unmarshal(segRec.Body.Bytes(), &segResp, jsonx.V1())) unrelatedSegID := segResp["Id"].(string) // GetSegmentImportJobs for the unrelated segment → must return empty list. @@ -424,7 +427,7 @@ func TestGetSegmentImportJobs_OtherSegmentReturnsEmpty(t *testing.T) { require.Equal(t, http.StatusOK, jobsRec.Code) var jobsResp map[string]any - require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp)) + require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp, jsonx.V1())) jobs, _ := jobsResp["Item"].([]any) assert.Empty(t, jobs, "GetSegmentImportJobs must return empty for segments not created by an import job") @@ -457,7 +460,7 @@ func TestGetSegmentImportJobs_MultipleJobs_IsolatedBySegment(t *testing.T) { segsRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments", nil) require.Equal(t, http.StatusOK, segsRec.Code) var segsResp map[string]any - require.NoError(t, json.Unmarshal(segsRec.Body.Bytes(), &segsResp)) + require.NoError(t, json.Unmarshal(segsRec.Body.Bytes(), &segsResp, jsonx.V1())) items, _ := segsResp["Item"].([]any) require.Len(t, items, 2) @@ -471,7 +474,7 @@ func TestGetSegmentImportJobs_MultipleJobs_IsolatedBySegment(t *testing.T) { require.Equal(t, http.StatusOK, jobsRec.Code) var jobsResp map[string]any - require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp)) + require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp, jsonx.V1())) jobs, _ := jobsResp["Item"].([]any) assert.Len(t, jobs, 1, "each segment's GetSegmentImportJobs must return only its own job, segment %s", segID) diff --git a/services/pinpoint/handler.go b/services/pinpoint/handler.go index 22c0f037e8..89d7cf7d5f 100644 --- a/services/pinpoint/handler.go +++ b/services/pinpoint/handler.go @@ -2,7 +2,7 @@ package pinpoint import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -682,7 +683,7 @@ func unmarshalBody(c *echo.Context, dst any) bool { return false } - if jsonErr := json.Unmarshal(body, dst); jsonErr != nil { + if jsonErr := json.Unmarshal(body, dst, jsonx.V1()); jsonErr != nil { _ = writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") return false diff --git a/services/pinpoint/handler_applications_settings.go b/services/pinpoint/handler_applications_settings.go index 4afb694d98..62390b7cd8 100644 --- a/services/pinpoint/handler_applications_settings.go +++ b/services/pinpoint/handler_applications_settings.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractSettingsOp returns the settings operation name. @@ -74,7 +75,7 @@ func (h *Handler) handleUpdateApplicationSettings(c *echo.Context, appID string) } if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &incoming); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &incoming, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } } diff --git a/services/pinpoint/handler_apps.go b/services/pinpoint/handler_apps.go index d77502e28b..688c57ab5c 100644 --- a/services/pinpoint/handler_apps.go +++ b/services/pinpoint/handler_apps.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractAppsCollectionOp returns the operation for the apps collection. @@ -78,7 +79,7 @@ func (h *Handler) handleCreateApp(c *echo.Context) error { var req createAppRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_attributes.go b/services/pinpoint/handler_attributes.go index 7a56616a01..4e4d789a1a 100644 --- a/services/pinpoint/handler_attributes.go +++ b/services/pinpoint/handler_attributes.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleRemoveAttributes handles PUT /v1/apps/{appId}/attributes/{attributeType}. @@ -21,7 +22,7 @@ func (h *Handler) handleRemoveAttributes(c *echo.Context, appID, attributeType s var req removeAttributesRequest if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } } diff --git a/services/pinpoint/handler_channels.go b/services/pinpoint/handler_channels.go index dc3fa55213..a7b2e4abbc 100644 --- a/services/pinpoint/handler_channels.go +++ b/services/pinpoint/handler_channels.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -9,6 +9,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) extractChannelOp(method, channelType string) string { @@ -186,7 +187,7 @@ func (h *Handler) handleGetChannels(c *echo.Context, appID string) error { func parseGCMChannelExtra(body []byte) (bool, map[string]any) { var req updateGCMChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -205,7 +206,7 @@ func parseGCMChannelExtra(body []byte) (bool, map[string]any) { func parseAPNSChannelExtra(body []byte) (bool, map[string]any) { var req updateAPNSChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -225,7 +226,7 @@ func parseAPNSChannelExtra(body []byte) (bool, map[string]any) { func parseEmailChannelExtra(body []byte) (bool, map[string]any) { var req updateEmailChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -246,7 +247,7 @@ func parseEmailChannelExtra(body []byte) (bool, map[string]any) { func parseSMSChannelExtra(body []byte) (bool, map[string]any) { var req updateSMSChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -276,7 +277,7 @@ func parseChannelExtra(channelType string, body []byte) (bool, map[string]any) { return parseSMSChannelExtra(body) case channelKeyADM: var req updateADMChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -293,7 +294,7 @@ func parseChannelExtra(channelType string, body []byte) (bool, map[string]any) { return req.Enabled, extra case channelKeyBaidu: var req updateBaiduChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } @@ -310,7 +311,7 @@ func parseChannelExtra(channelType string, body []byte) (bool, map[string]any) { return req.Enabled, extra default: var req updateChannelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return false, nil } diff --git a/services/pinpoint/handler_endpoints.go b/services/pinpoint/handler_endpoints.go index 6e779891ef..a8686301cd 100644 --- a/services/pinpoint/handler_endpoints.go +++ b/services/pinpoint/handler_endpoints.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) extractEndpointSubOp(method, rest string) string { @@ -136,7 +137,7 @@ func (h *Handler) handleUpdateEndpoint(c *echo.Context, appID, endpointID string } var req updateEndpointRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } @@ -221,7 +222,7 @@ func (h *Handler) handleUpdateEndpointsBatch(c *echo.Context, appID string) erro } var req updateEndpointsBatchRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_event_streams.go b/services/pinpoint/handler_event_streams.go index 91fe05dcb3..84416a2cba 100644 --- a/services/pinpoint/handler_event_streams.go +++ b/services/pinpoint/handler_event_streams.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractEventStreamOp returns the event stream operation name. @@ -71,7 +72,7 @@ func (h *Handler) handlePutEventStream(c *echo.Context, appID string) error { } var req putEventStreamRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_events.go b/services/pinpoint/handler_events.go index 53a9605954..3531a2359b 100644 --- a/services/pinpoint/handler_events.go +++ b/services/pinpoint/handler_events.go @@ -1,12 +1,13 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handlePutEvents handles POST /v1/apps/{appId}/events. @@ -26,7 +27,7 @@ func (h *Handler) handlePutEvents(c *echo.Context, appID string) error { } var req putEventsRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_export_import_jobs.go b/services/pinpoint/handler_export_import_jobs.go index b8f83679c1..6d7f481826 100644 --- a/services/pinpoint/handler_export_import_jobs.go +++ b/services/pinpoint/handler_export_import_jobs.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -83,7 +84,7 @@ func (h *Handler) handleCreateExportJob(c *echo.Context, appID string) error { } var req createExportJobRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } @@ -119,7 +120,7 @@ func (h *Handler) handleCreateImportJob(c *echo.Context, appID string) error { } var req createImportJobRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_journeys.go b/services/pinpoint/handler_journeys.go index 1e90b20632..575a518fc8 100644 --- a/services/pinpoint/handler_journeys.go +++ b/services/pinpoint/handler_journeys.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractJourneysOp returns the journeys collection operation name. @@ -149,7 +150,7 @@ func (h *Handler) dispatchJourneyRun(c *echo.Context, appID, journeyID, rest str func (h *Handler) handleCreateJourney(c *echo.Context, appID string) error { return h.handleCreateNamedAppResource(c, appID, func(body []byte, region, appID string) (any, error) { var req createJourneyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, errInvalidRequestBody } @@ -249,7 +250,7 @@ func (h *Handler) handleUpdateJourneyState(c *echo.Context, appID, journeyID str } var req updateJourneyStateRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_messages.go b/services/pinpoint/handler_messages.go index be302bc67d..fa32ae0806 100644 --- a/services/pinpoint/handler_messages.go +++ b/services/pinpoint/handler_messages.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" @@ -9,6 +9,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleSendMessages handles POST /v1/apps/{appId}/messages. @@ -23,7 +24,7 @@ func (h *Handler) handleSendMessages(c *echo.Context, appID string) error { } var req sendMessagesRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } @@ -54,7 +55,7 @@ func (h *Handler) handleSendUsersMessages(c *echo.Context, appID string) error { var req sendUsersMessagesRequest if len(body) > 0 { - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } } @@ -105,7 +106,7 @@ func (h *Handler) handleVerifyOTPMessage(c *echo.Context, appID string) error { var req verifyOTPMessageRequest if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } code := req.Otp @@ -136,7 +137,7 @@ func (h *Handler) handlePhoneNumberValidate(c *echo.Context) error { } var req phoneNumberValidateRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_recommender_configurations.go b/services/pinpoint/handler_recommender_configurations.go index d38b01d5d8..fbdf8b93c4 100644 --- a/services/pinpoint/handler_recommender_configurations.go +++ b/services/pinpoint/handler_recommender_configurations.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractRecommendersCollectionOp returns the operation for the recommenders collection. @@ -95,7 +96,7 @@ func (h *Handler) handleCreateRecommenderConfiguration(c *echo.Context) error { } var req createRecommenderConfigRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse( c, http.StatusBadRequest, @@ -236,7 +237,7 @@ func (h *Handler) handleUpdateRecommenderConfiguration( } var req createRecommenderConfigRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse( c, http.StatusBadRequest, diff --git a/services/pinpoint/handler_segments.go b/services/pinpoint/handler_segments.go index 240d5c5e68..fa9fec7652 100644 --- a/services/pinpoint/handler_segments.go +++ b/services/pinpoint/handler_segments.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractSegmentsOp returns the segments collection operation name. @@ -105,7 +106,7 @@ func (h *Handler) dispatchSegmentByID(c *echo.Context, appID, rest string) error func (h *Handler) handleCreateSegment(c *echo.Context, appID string) error { return h.handleCreateNamedAppResource(c, appID, func(body []byte, region, appID string) (any, error) { var req createSegmentRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, errInvalidRequestBody } diff --git a/services/pinpoint/handler_tags.go b/services/pinpoint/handler_tags.go index e9e47b700a..3d12cdc909 100644 --- a/services/pinpoint/handler_tags.go +++ b/services/pinpoint/handler_tags.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractTagOperation resolves the operation for tag-related paths. @@ -59,7 +60,7 @@ func (h *Handler) handleTagResource(c *echo.Context, resourceARN string) error { var req tagResourceRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_templates.go b/services/pinpoint/handler_templates.go index b44b480a96..1079ad76c8 100644 --- a/services/pinpoint/handler_templates.go +++ b/services/pinpoint/handler_templates.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractTemplateOperation resolves the operation name for paths under /v1/templates/. @@ -221,7 +222,7 @@ func (h *Handler) createTemplateByType(body []byte, region, templateName, templa func (h *Handler) createEmailTemplateARN(body []byte, region, templateName string) (string, error) { var req createEmailTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", errInvalidRequestBody } @@ -235,7 +236,7 @@ func (h *Handler) createEmailTemplateARN(body []byte, region, templateName strin func (h *Handler) createInAppTemplateARN(body []byte, region, templateName string) (string, error) { var req createInAppTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", errInvalidRequestBody } @@ -249,7 +250,7 @@ func (h *Handler) createInAppTemplateARN(body []byte, region, templateName strin func (h *Handler) createPushTemplateARN(body []byte, region, templateName string) (string, error) { var req createPushTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", errInvalidRequestBody } @@ -263,7 +264,7 @@ func (h *Handler) createPushTemplateARN(body []byte, region, templateName string func (h *Handler) createSMSTemplateARN(body []byte, region, templateName string) (string, error) { var req createSmsTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", errInvalidRequestBody } @@ -277,7 +278,7 @@ func (h *Handler) createSMSTemplateARN(body []byte, region, templateName string) func (h *Handler) createVoiceTemplateARN(body []byte, region, templateName string) (string, error) { var req createVoiceTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", errInvalidRequestBody } @@ -381,7 +382,7 @@ func (h *Handler) applyTemplateUpdate(body []byte, templateName, templateType, v // updateEmailTemplateFromBody parses and applies an email template update. func (h *Handler) updateEmailTemplateFromBody(body []byte, name, version string, createNew bool) error { var req createEmailTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return errInvalidRequestBody } @@ -396,7 +397,7 @@ func (h *Handler) updateEmailTemplateFromBody(body []byte, name, version string, // updateInAppTemplateFromBody parses and applies an in-app template update. func (h *Handler) updateInAppTemplateFromBody(body []byte, name, version string, createNew bool) error { var req createInAppTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return errInvalidRequestBody } @@ -411,7 +412,7 @@ func (h *Handler) updateInAppTemplateFromBody(body []byte, name, version string, // updatePushTemplateFromBody parses and applies a push template update. func (h *Handler) updatePushTemplateFromBody(body []byte, name, version string, createNew bool) error { var req createPushTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return errInvalidRequestBody } @@ -426,7 +427,7 @@ func (h *Handler) updatePushTemplateFromBody(body []byte, name, version string, // updateSMSTemplateFromBody parses and applies an SMS template update. func (h *Handler) updateSMSTemplateFromBody(body []byte, name, version string, createNew bool) error { var req createSmsTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return errInvalidRequestBody } @@ -441,7 +442,7 @@ func (h *Handler) updateSMSTemplateFromBody(body []byte, name, version string, c // updateVoiceTemplateFromBody parses and applies a voice template update. func (h *Handler) updateVoiceTemplateFromBody(body []byte, name, version string, createNew bool) error { var req createVoiceTemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return errInvalidRequestBody } @@ -555,7 +556,7 @@ func (h *Handler) handleUpdateTemplateActiveVersion(c *echo.Context, templateNam Version string `json:"Version"` } - if len(body) > 0 && json.Unmarshal(body, &req) != nil { + if len(body) > 0 && json.Unmarshal(body, &req, jsonx.V1()) != nil { return writeErrorResponse(c, http.StatusBadRequest, "BadRequestException", "invalid request body") } diff --git a/services/pinpoint/handler_templates_rejection_test.go b/services/pinpoint/handler_templates_rejection_test.go index 736a890c06..482b841c21 100644 --- a/services/pinpoint/handler_templates_rejection_test.go +++ b/services/pinpoint/handler_templates_rejection_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestUpdateTemplate_RejectedUpdate_DoesNotDoubleWrite is a regression test @@ -40,7 +42,7 @@ func TestUpdateTemplate_RejectedUpdate_DoesNotDoubleWrite(t *testing.T) { "a rejected update must not write a second (success) response onto the same body") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp), + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()), "response body must decode as exactly one JSON object -- a second "+ "write appended after the committed 404 corrupts it") assert.Equal(t, "NotFoundException", resp["__type"]) diff --git a/services/pinpoint/handler_test.go b/services/pinpoint/handler_test.go index 4332e4dcbf..df08cd14ea 100644 --- a/services/pinpoint/handler_test.go +++ b/services/pinpoint/handler_test.go @@ -2,7 +2,8 @@ package pinpoint_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -38,7 +40,7 @@ func doPinpointRequest(t *testing.T, h *pinpoint.Handler, method, path string, b if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -96,7 +98,7 @@ func createTestApp(t *testing.T, h *pinpoint.Handler, name string) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) id, _ := resp["Id"].(string) require.NotEmpty(t, id) @@ -109,7 +111,7 @@ func pinpointJSON(t *testing.T, body []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1())) return m } @@ -563,7 +565,7 @@ func TestHandler_ErrorPaths(t *testing.T) { bodyBytes = []byte(s) } else if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/pinpoint/journeys_activities_test.go b/services/pinpoint/journeys_activities_test.go index b20588ac00..35753a4636 100644 --- a/services/pinpoint/journeys_activities_test.go +++ b/services/pinpoint/journeys_activities_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestJourney_StateMachine(t *testing.T) { @@ -74,7 +76,7 @@ func TestJourney_StateMachine(t *testing.T) { map[string]any{"Name": "sm-journey"}) require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) journeyID := cr["Id"].(string) assert.Equal(t, "DRAFT", cr["State"]) @@ -100,7 +102,7 @@ func TestJourney_StateMachine(t *testing.T) { "/v1/apps/"+appID+"/journeys/"+journeyID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) assert.Equal(t, tc.wantFinal, j["State"]) } }) @@ -126,7 +128,7 @@ func TestJourney_ListByState(t *testing.T) { map[string]any{"Name": name}) require.Equal(t, http.StatusCreated, rec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &j, jsonx.V1())) journeyIDs[i] = j["Id"].(string) } @@ -147,7 +149,7 @@ func TestJourney_ListByState(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["Item"].([]any) assert.Len(t, items, 3) @@ -321,7 +323,7 @@ func TestJourney_Activities(t *testing.T) { "body: %s", createRec.Body.String()) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) journeyID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, @@ -329,7 +331,7 @@ func TestJourney_Activities(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) activities, _ := j["Activities"].(map[string]any) assert.NotNil(t, activities, "Activities must be present") @@ -369,7 +371,7 @@ func TestJourney_DateRangeKpi(t *testing.T) { map[string]any{"Name": "kpi-journey"}) require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) journeyID := cr["Id"].(string) kpiRec := doPinpointRequest(t, h, http.MethodGet, @@ -377,7 +379,7 @@ func TestJourney_DateRangeKpi(t *testing.T) { require.Equal(t, http.StatusOK, kpiRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(kpiRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(kpiRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, journeyID, resp["JourneyId"]) assert.Equal(t, tc.kpiName, resp["KpiName"]) @@ -421,7 +423,7 @@ func TestJourney_RunsAfterActivation(t *testing.T) { map[string]any{"Name": "runs-journey"}) require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) journeyID := cr["Id"].(string) if tc.activate { @@ -436,7 +438,7 @@ func TestJourney_RunsAfterActivation(t *testing.T) { require.Equal(t, http.StatusOK, runsRec.Code) var runsResp map[string]any - require.NoError(t, json.Unmarshal(runsRec.Body.Bytes(), &runsResp)) + require.NoError(t, json.Unmarshal(runsRec.Body.Bytes(), &runsResp, jsonx.V1())) items, _ := runsResp["Item"].([]any) assert.Len(t, items, tc.wantRuns) }) @@ -486,14 +488,14 @@ func TestJourney_LinkedActivityGraph(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) assert.Equal(t, "act-wait", j["StartActivity"]) @@ -541,14 +543,14 @@ func TestJourney_QuietTimeAndOpenHours(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) qt := j["QuietTime"].(map[string]any) assert.Equal(t, "21:00", qt["Start"]) @@ -585,14 +587,14 @@ func TestJourney_LimitsRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) got := j["Limits"].(map[string]any) assert.EqualValues(t, 100, got["DailyCap"]) @@ -645,14 +647,14 @@ func TestJourney_RandomSplitAndHoldout(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) acts := j["Activities"].(map[string]any) holdout := acts["act-holdout"].(map[string]any)["HOLDOUT"].(map[string]any) @@ -681,7 +683,7 @@ func TestJourney_UpdateActivities(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) // Add a second activity by updating the journey @@ -706,7 +708,7 @@ func TestJourney_UpdateActivities(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) acts := j["Activities"].(map[string]any) assert.Len(t, acts, 2) @@ -741,14 +743,14 @@ func TestJourney_RefreshOnSegmentUpdate(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) assert.Equal(t, true, j["RefreshOnSegmentUpdate"]) assert.Equal(t, "PT1H", j["RefreshFrequency"]) @@ -779,14 +781,14 @@ func TestJourney_StartCondition(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &cr, jsonx.V1())) jID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys/"+jID, nil) require.Equal(t, http.StatusOK, getRec.Code) var j map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &j, jsonx.V1())) sc := j["StartCondition"].(map[string]any) assert.Equal(t, "entry from segment", sc["Description"]) diff --git a/services/pinpoint/journeys_test.go b/services/pinpoint/journeys_test.go index b3f91dcf43..628e44e0ec 100644 --- a/services/pinpoint/journeys_test.go +++ b/services/pinpoint/journeys_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -12,6 +13,8 @@ import ( pinpointtypes "github.com/aws/aws-sdk-go-v2/service/pinpoint/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestJourneyFullDTO_Create(t *testing.T) { @@ -146,7 +149,7 @@ func TestJourneyFullDTO_Create(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/journeys", tc.body) @@ -157,7 +160,7 @@ func TestJourneyFullDTO_Create(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, appID, resp["ApplicationId"]) @@ -285,14 +288,14 @@ func TestJourneyStateValidation(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/journeys", map[string]any{"Name": "j"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) journeyID := created["Id"].(string) for _, state := range tc.setupTransitions { @@ -318,14 +321,14 @@ func TestJourneyUpdate_BlockedWhenActive(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/journeys", map[string]any{"Name": "j"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) journeyID := created["Id"].(string) // Activate the journey. @@ -346,7 +349,7 @@ func TestJourneyUpdate_BlockedWhenActive(t *testing.T) { require.Equal(t, http.StatusConflict, updateRec.Code, updateRec.Body.String()) var errResp map[string]string - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) } @@ -469,14 +472,14 @@ func TestJourneyUpdate_RoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/journeys", map[string]any{"Name": "j"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) journeyID := created["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPut, @@ -484,7 +487,7 @@ func TestJourneyUpdate_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp[tc.checkField], "%s field must be non-nil after update", tc.checkField) }) @@ -503,7 +506,7 @@ func TestJourney_MultipleActivities_RoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) activities := map[string]any{ @@ -538,7 +541,7 @@ func TestJourney_MultipleActivities_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp, jsonx.V1())) returnedActivities, _ := resp["Activities"].(map[string]any) assert.Len(t, returnedActivities, 3, "all 3 activities round-trip") @@ -565,7 +568,7 @@ func TestPagination_Journeys_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, p1Rec.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1, jsonx.V1())) items1, _ := p1["Item"].([]any) assert.Len(t, items1, 2) @@ -576,7 +579,7 @@ func TestPagination_Journeys_NextToken(t *testing.T) { p2Rec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/journeys?page-size=2&token="+tok, nil) var p2 map[string]any - require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2, jsonx.V1())) items2, _ := p2["Item"].([]any) assert.Len(t, items2, 1, "last page returns remaining journey") @@ -599,7 +602,7 @@ func TestJourneyCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) journeyID, _ := createResp["Id"].(string) require.NotEmpty(t, journeyID) @@ -695,7 +698,7 @@ func TestJourneyARNPresent(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotContains(t, resp, "Arn") } @@ -737,7 +740,7 @@ func TestHandler_CreateJourney(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, appID, resp["ApplicationId"]) assert.Equal(t, "DRAFT", resp["State"]) @@ -770,7 +773,7 @@ func TestHandler_GetJourneys_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) created[resp["Id"].(string)] = true } @@ -782,7 +785,7 @@ func TestHandler_GetJourneys_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) for _, item := range items { diff --git a/services/pinpoint/messages_test.go b/services/pinpoint/messages_test.go index cc729048d2..29062bc1cc 100644 --- a/services/pinpoint/messages_test.go +++ b/services/pinpoint/messages_test.go @@ -1,13 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -91,7 +92,7 @@ func TestOTP_SendAndVerify(t *testing.T) { "verify body: %s", verifyRec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Valid") } }) @@ -135,7 +136,7 @@ func TestOTP_SendAndVerify_CodeMatch(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp, jsonx.V1())) results, _ := sendResp["Result"].(map[string]any) assert.NotEmpty(t, results, "SendOTP should return results") @@ -146,7 +147,7 @@ func TestOTP_SendAndVerify_CodeMatch(t *testing.T) { require.Equal(t, http.StatusOK, verifyRec.Code) var verifyResp map[string]any - require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &verifyResp)) + require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &verifyResp, jsonx.V1())) assert.Equal(t, tc.wantValid, verifyResp["Valid"], "Valid field") }) } @@ -181,7 +182,7 @@ func TestOTP_CodeMatch_CorrectCode(t *testing.T) { require.Equal(t, http.StatusOK, verifyNoCode.Code) var noCodeResp map[string]any - require.NoError(t, json.Unmarshal(verifyNoCode.Body.Bytes(), &noCodeResp)) + require.NoError(t, json.Unmarshal(verifyNoCode.Body.Bytes(), &noCodeResp, jsonx.V1())) assert.True(t, noCodeResp["Valid"].(bool), "empty code falls back to has-pending-OTP check") } @@ -204,7 +205,7 @@ func TestOTP_CodeMatch_WrongCode(t *testing.T) { require.Equal(t, http.StatusOK, verifyRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp, jsonx.V1())) assert.False(t, resp["Valid"].(bool), "wrong OTP code must return Valid=false") } @@ -222,7 +223,7 @@ func TestOTP_CodeMatch_NoOTPSent(t *testing.T) { require.Equal(t, http.StatusOK, verifyRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(verifyRec.Body.Bytes(), &resp, jsonx.V1())) assert.False(t, resp["Valid"].(bool), "no OTP sent → Valid=false") } @@ -275,7 +276,7 @@ func TestSendUsersMessages_WithEndpoints(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &resp, jsonx.V1())) result, _ := resp["Result"].(map[string]any) require.NotNil(t, result) @@ -314,7 +315,7 @@ func TestSendUsersMessages_UnknownUser(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &resp, jsonx.V1())) result, _ := resp["Result"].(map[string]any) require.NotNil(t, result) @@ -335,7 +336,7 @@ func TestSendUsersMessages_EmptyBody(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) result, _ := resp["Result"].(map[string]any) assert.Empty(t, result, "no users in request → empty result") } @@ -402,7 +403,7 @@ func TestPhoneNumberValidate_E164Input(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, wrapped := resp["NumberValidateResponse"] assert.False(t, wrapped, "NumberValidateResponse must not appear as a wrapper key") @@ -438,7 +439,7 @@ func TestPhoneNumberValidate_UnknownCountry(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) inner := resp assert.Equal(t, "ZZ", inner["CountryCodeIso2"], "unknown country returns ZZ") @@ -459,7 +460,7 @@ func TestPhoneNumberValidate_NationalFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) inner := resp assert.Equal(t, "+12125551234", inner["CleansedPhoneNumberE164"], @@ -479,7 +480,7 @@ func TestPhoneNumberValidate_PhoneTypeAndCarrier(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) inner := resp assert.NotEmpty(t, inner["PhoneType"], "PhoneType must be set") @@ -514,7 +515,7 @@ func TestSendMessages_ResponseFlat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, wrapped := resp["MessageResponse"] assert.False(t, wrapped, "MessageResponse must not appear as a wrapper key") @@ -562,7 +563,7 @@ func createTestInAppCampaign( require.Equal(t, http.StatusCreated, campRec.Code, campRec.Body.String()) var camp map[string]any - require.NoError(t, json.Unmarshal(campRec.Body.Bytes(), &camp)) + require.NoError(t, json.Unmarshal(campRec.Body.Bytes(), &camp, jsonx.V1())) campaignID, _ := camp["Id"].(string) require.NotEmpty(t, campaignID) @@ -589,7 +590,7 @@ func TestGetInAppMessages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) campaigns, ok := resp["InAppMessageCampaigns"].([]any) require.True(t, ok, "InAppMessageCampaigns must be present and be an array") assert.Empty(t, campaigns) @@ -607,7 +608,7 @@ func TestGetInAppMessages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) campaigns, ok := resp["InAppMessageCampaigns"].([]any) require.True(t, ok) require.Len(t, campaigns, 1) @@ -641,7 +642,7 @@ func TestGetInAppMessages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) campaigns, ok := resp["InAppMessageCampaigns"].([]any) require.True(t, ok) assert.Empty(t, campaigns, "a paused campaign doesn't run, per real AWS's IsPaused semantics") @@ -657,7 +658,7 @@ func TestGetInAppMessages(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "NotFoundException", resp["__type"]) }) } diff --git a/services/pinpoint/multi_region_test.go b/services/pinpoint/multi_region_test.go index 9e449aa507..b413eb2aef 100644 --- a/services/pinpoint/multi_region_test.go +++ b/services/pinpoint/multi_region_test.go @@ -2,7 +2,8 @@ package pinpoint_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -184,8 +186,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/pinpoint/payload_size.go b/services/pinpoint/payload_size.go index 647c1f0c1d..b396a5dee2 100644 --- a/services/pinpoint/payload_size.go +++ b/services/pinpoint/payload_size.go @@ -1,10 +1,13 @@ package pinpoint import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Payload size ceilings sourced from @@ -54,10 +57,10 @@ func checkPayloadSize(c *echo.Context, body []byte, limit int) bool { func putEventsExceedsEventQuota(body []byte) bool { var raw struct { BatchItem map[string]struct { - Events map[string]json.RawMessage `json:"Events"` + Events map[string]jsontext.Value `json:"Events"` } `json:"BatchItem"` } - if json.Unmarshal(body, &raw) != nil { + if json.Unmarshal(body, &raw, jsonx.V1()) != nil { return false } diff --git a/services/pinpoint/payload_size_test.go b/services/pinpoint/payload_size_test.go index 4ef39a6aa7..feffeb13d8 100644 --- a/services/pinpoint/payload_size_test.go +++ b/services/pinpoint/payload_size_test.go @@ -1,12 +1,15 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Mirrors the unexported limits in payload_size.go (7 MB / 4 MB / 15 KB from @@ -28,7 +31,7 @@ func jsonBodyOfSize(t *testing.T, prefix, suffix string, targetLen int) []byte { body := prefix + strings.Repeat("a", padLen) + suffix require.Len(t, body, targetLen) - require.True(t, json.Valid([]byte(body)), "constructed body must be valid JSON") + require.True(t, jsontext.Value([]byte(body)).IsValid(jsonx.V1()), "constructed body must be valid JSON") return []byte(body) } @@ -37,7 +40,7 @@ func requirePayloadTooLarge(t *testing.T, body []byte) { t.Helper() var envelope map[string]any - require.NoError(t, json.Unmarshal(body, &envelope)) + require.NoError(t, json.Unmarshal(body, &envelope, jsonx.V1())) require.Equal(t, "PayloadTooLargeException", envelope["__type"]) } diff --git a/services/pinpoint/persistence.go b/services/pinpoint/persistence.go index fcb72e06c7..1998caeab8 100644 --- a/services/pinpoint/persistence.go +++ b/services/pinpoint/persistence.go @@ -2,7 +2,7 @@ package pinpoint import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -48,21 +48,21 @@ const pinpointSnapshotVersion = 2 // plain JSON-friendly struct with no live/non-serialisable state, so a // direct field-for-field mapping (no separate DTO type) is sufficient. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AppSettings map[string]*StoredAppSettings `json:"appSettings"` - CampaignVersions map[string][]*Campaign `json:"campaignVersions"` - SegmentVersions map[string][]*Segment `json:"segmentVersions"` - TemplateVersionHistory map[string][]templateVersionItem `json:"templateVersionHistory"` - TemplateVersionData map[string]map[string]json.RawMessage `json:"templateVersionData"` - TemplateActiveVersion map[string]string `json:"templateActiveVersion"` - CampaignActivities map[string][]campaignActivity `json:"campaignActivities"` - JourneyRuns map[string][]*journeyRun `json:"journeyRuns"` - AppEvents map[string][]storedPinpointEvent `json:"appEvents"` - SentMessages map[string]int `json:"sentMessages"` - OtpCodes map[string]string `json:"otpCodes"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AppSettings map[string]*StoredAppSettings `json:"appSettings"` + CampaignVersions map[string][]*Campaign `json:"campaignVersions"` + SegmentVersions map[string][]*Segment `json:"segmentVersions"` + TemplateVersionHistory map[string][]templateVersionItem `json:"templateVersionHistory"` + TemplateVersionData map[string]map[string]jsontext.Value `json:"templateVersionData"` + TemplateActiveVersion map[string]string `json:"templateActiveVersion"` + CampaignActivities map[string][]campaignActivity `json:"campaignActivities"` + JourneyRuns map[string][]*journeyRun `json:"journeyRuns"` + AppEvents map[string][]storedPinpointEvent `json:"appEvents"` + SentMessages map[string]int `json:"sentMessages"` + OtpCodes map[string]string `json:"otpCodes"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // persistRegistry builds an ephemeral [store.Registry] over every @@ -183,7 +183,7 @@ func (b *InMemoryBackend) resetMapStateLocked() { b.campaignVersions = make(map[string][]*Campaign) b.segmentVersions = make(map[string][]*Segment) b.templateVersionHistory = make(map[string][]templateVersionItem) - b.templateVersionData = make(map[string]map[string]json.RawMessage) + b.templateVersionData = make(map[string]map[string]jsontext.Value) b.templateActiveVersion = make(map[string]string) b.campaignActivities = make(map[string][]campaignActivity) b.journeyRuns = make(map[string][]*journeyRun) @@ -327,9 +327,9 @@ func rebuildARNIndexLocked(b *InMemoryBackend) { } } -func nonNilStringMap2(m map[string]map[string]json.RawMessage) map[string]map[string]json.RawMessage { +func nonNilStringMap2(m map[string]map[string]jsontext.Value) map[string]map[string]jsontext.Value { if m == nil { - return make(map[string]map[string]json.RawMessage) + return make(map[string]map[string]jsontext.Value) } return m diff --git a/services/pinpoint/recommender_configurations_test.go b/services/pinpoint/recommender_configurations_test.go index 84cc1fc386..2b68006141 100644 --- a/services/pinpoint/recommender_configurations_test.go +++ b/services/pinpoint/recommender_configurations_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -282,7 +284,7 @@ func TestRecommenderConfiguration_FullCRUD(t *testing.T) { "body: %s", createRec.Body.String()) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) recID := cr["Id"].(string) require.NotEmpty(t, recID) @@ -313,7 +315,7 @@ func TestRecommenderConfiguration_FullCRUD(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, recID, gr["Id"]) updateRec := doPinpointRequest(t, h, http.MethodPut, @@ -368,7 +370,7 @@ func TestRecommenderConfiguration_ListAll(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tc.wantLen) }) @@ -520,14 +522,14 @@ func TestRecommender_Attributes_RoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) recID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/recommenders/"+recID, nil) require.Equal(t, http.StatusOK, getRec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r, jsonx.V1())) assert.Equal(t, "attr-recommender", r["Name"]) assert.EqualValues(t, 5, r["RecommendationsPerMessage"]) @@ -567,14 +569,14 @@ func TestRecommender_RecommendationsPerMessage(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) recID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/recommenders/"+recID, nil) require.Equal(t, http.StatusOK, getRec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r, jsonx.V1())) assert.EqualValues(t, tc.recommendationsPerMsg, r["RecommendationsPerMessage"]) }) @@ -600,7 +602,7 @@ func TestRecommender_UpdateAttributes(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) recID := cr["Id"].(string) putRec := doPinpointRequest(t, h, http.MethodPut, "/v1/recommenders/"+recID, @@ -621,7 +623,7 @@ func TestRecommender_UpdateAttributes(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var r map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &r, jsonx.V1())) assert.EqualValues(t, 7, r["RecommendationsPerMessage"]) gotAttrs := r["Attributes"].(map[string]any) @@ -650,7 +652,7 @@ func TestRecommender_List_MultipleConfigs(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Item"].([]any) assert.Len(t, items, 3) @@ -762,7 +764,7 @@ func TestHandler_CreateRecommenderConfiguration(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.Equal(t, "my-recommender", resp["Name"]) } diff --git a/services/pinpoint/segments_test.go b/services/pinpoint/segments_test.go index 039ed7e7a0..47fdaf9107 100644 --- a/services/pinpoint/segments_test.go +++ b/services/pinpoint/segments_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -23,7 +25,7 @@ func createTestSegment(t *testing.T, h *pinpoint.Handler, appID, name string) st require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) id, _ := resp["Id"].(string) require.NotEmpty(t, id) @@ -134,7 +136,7 @@ func TestSegmentFullDTO_Create(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/segments", tc.body) @@ -145,7 +147,7 @@ func TestSegmentFullDTO_Create(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantSegmentType, resp["SegmentType"]) assert.NotEmpty(t, resp["Id"]) @@ -223,21 +225,21 @@ func TestSegmentUpdate_DimensionsRoundTrip(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/segments", map[string]any{"Name": "seg"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) segID := created["Id"].(string) rec := doPinpointRequest(t, h, http.MethodPut, "/v1/apps/"+appID+"/segments/"+segID, tc.updateBody) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantSegmentType, resp["SegmentType"]) assert.InDelta(t, tc.wantVersion, resp["Version"], 0.001) @@ -258,14 +260,14 @@ func TestSegmentVersioning(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/segments", map[string]any{"Name": "versioned-seg"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) segID := created["Id"].(string) // 2 updates. @@ -278,7 +280,7 @@ func TestSegmentVersioning(t *testing.T) { verRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments/"+segID+"/versions", nil) require.Equal(t, http.StatusOK, verRec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &verResp, jsonx.V1())) items, _ := verResp["Item"].([]any) assert.Len(t, items, 3, "3 versions: 1 create + 2 updates") } @@ -295,14 +297,14 @@ func TestSegment_VersionRetrieval(t *testing.T) { appRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps", map[string]any{"Name": "app"}) require.Equal(t, http.StatusCreated, appRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(appRec.Body.Bytes(), &appResp, jsonx.V1())) appID := appResp["Id"].(string) createRec := doPinpointRequest(t, h, http.MethodPost, "/v1/apps/"+appID+"/segments", map[string]any{"Name": "seg-v"}) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) segID := created["Id"].(string) updateRec := doPinpointRequest(t, h, http.MethodPut, "/v1/apps/"+appID+"/segments/"+segID, @@ -314,7 +316,7 @@ func TestSegment_VersionRetrieval(t *testing.T) { "/v1/apps/"+appID+"/segments/"+segID+"/versions/1", nil) require.Equal(t, http.StatusOK, v1Rec.Code) var v1 map[string]any - require.NoError(t, json.Unmarshal(v1Rec.Body.Bytes(), &v1)) + require.NoError(t, json.Unmarshal(v1Rec.Body.Bytes(), &v1, jsonx.V1())) assert.InDelta(t, float64(1), v1["Version"], 0.001) assert.Equal(t, "seg-v", v1["Name"]) } @@ -366,7 +368,7 @@ func TestSegmentVersions_Deeper(t *testing.T) { }) require.Equal(t, http.StatusCreated, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) segID := created["Id"].(string) for i := range tc.updateCount { @@ -381,7 +383,7 @@ func TestSegmentVersions_Deeper(t *testing.T) { require.Equal(t, http.StatusOK, versionsRec.Code) var versionsResp map[string]any - require.NoError(t, json.Unmarshal(versionsRec.Body.Bytes(), &versionsResp)) + require.NoError(t, json.Unmarshal(versionsRec.Body.Bytes(), &versionsResp, jsonx.V1())) items, _ := versionsResp["Item"].([]any) assert.Len(t, items, tc.wantVersions, "wrong version count") @@ -390,7 +392,7 @@ func TestSegmentVersions_Deeper(t *testing.T) { require.Equal(t, http.StatusOK, vRec.Code) var vResp map[string]any - require.NoError(t, json.Unmarshal(vRec.Body.Bytes(), &vResp)) + require.NoError(t, json.Unmarshal(vRec.Body.Bytes(), &vResp, jsonx.V1())) assert.InDelta(t, float64(tc.fetchVersion), vResp["Version"], 0.001) }) } @@ -435,7 +437,7 @@ func TestSegmentJobsDeeper(t *testing.T) { map[string]any{"Name": "seg-for-jobs"}) require.Equal(t, http.StatusCreated, segRec.Code) var segResp map[string]any - require.NoError(t, json.Unmarshal(segRec.Body.Bytes(), &segResp)) + require.NoError(t, json.Unmarshal(segRec.Body.Bytes(), &segResp, jsonx.V1())) segID := segResp["Id"].(string) if tc.jobType == "export" { @@ -462,7 +464,7 @@ func TestSegmentJobsDeeper(t *testing.T) { require.Equal(t, http.StatusOK, jobsRec.Code) var jobsResp map[string]any - require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp)) + require.NoError(t, json.Unmarshal(jobsRec.Body.Bytes(), &jobsResp, jsonx.V1())) assert.Contains(t, jobsResp, "Item") }) } @@ -522,7 +524,7 @@ func TestSegment_ImportType(t *testing.T) { require.Equal(t, http.StatusCreated, jobRec.Code) var jr map[string]any - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr, jsonx.V1())) definition := jr["Definition"].(map[string]any) segID := definition["SegmentId"].(string) require.NotEmpty(t, segID) @@ -532,7 +534,7 @@ func TestSegment_ImportType(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var s map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s, jsonx.V1())) assert.Equal(t, "IMPORT", s["SegmentType"]) @@ -577,7 +579,7 @@ func TestSegment_DynamicWithSegmentGroups(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) // No ImportDefinition → DIMENSIONAL type assert.Equal(t, "DIMENSIONAL", cr["SegmentType"]) @@ -588,7 +590,7 @@ func TestSegment_DynamicWithSegmentGroups(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var s map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s, jsonx.V1())) assert.Equal(t, "DIMENSIONAL", s["SegmentType"]) @@ -639,14 +641,14 @@ func TestSegment_DimensionsAttributes(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) segID := cr["Id"].(string) getRec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments/"+segID, nil) require.Equal(t, http.StatusOK, getRec.Code) var s map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s, jsonx.V1())) d := s["Dimensions"].(map[string]any) @@ -685,7 +687,7 @@ func TestSegment_UpdatePreservesType(t *testing.T) { require.Equal(t, http.StatusCreated, jobRec.Code) var jr map[string]any - require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr)) + require.NoError(t, json.Unmarshal(jobRec.Body.Bytes(), &jr, jsonx.V1())) segID := jr["Definition"].(map[string]any)["SegmentId"].(string) require.NotEmpty(t, segID) @@ -695,7 +697,7 @@ func TestSegment_UpdatePreservesType(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var ur map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &ur)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &ur, jsonx.V1())) assert.Equal(t, "IMPORT", ur["SegmentType"]) assert.Equal(t, "type-preserve-seg-v2", ur["Name"]) @@ -739,7 +741,7 @@ func TestSegment_SegmentGroups_UpdateReplaces(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) segID := cr["Id"].(string) v2Groups := map[string]any{ @@ -770,7 +772,7 @@ func TestSegment_SegmentGroups_UpdateReplaces(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var s map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &s, jsonx.V1())) sg := s["SegmentGroups"].(map[string]any) assert.Equal(t, "ANY", sg["Include"]) @@ -797,7 +799,7 @@ func TestPagination_Segments_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, p1Rec.Code) var p1 map[string]any - require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1)) + require.NoError(t, json.Unmarshal(p1Rec.Body.Bytes(), &p1, jsonx.V1())) items1, _ := p1["Item"].([]any) assert.Len(t, items1, 2) @@ -807,7 +809,7 @@ func TestPagination_Segments_NextToken(t *testing.T) { p2Rec := doPinpointRequest(t, h, http.MethodGet, "/v1/apps/"+appID+"/segments?page-size=2&token="+tok, nil) var p2 map[string]any - require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2)) + require.NoError(t, json.Unmarshal(p2Rec.Body.Bytes(), &p2, jsonx.V1())) items2, _ := p2["Item"].([]any) assert.Len(t, items2, 2) @@ -828,7 +830,7 @@ func TestSegmentCRUD(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) segmentID, _ := createResp["Id"].(string) require.NotEmpty(t, segmentID) @@ -910,7 +912,7 @@ func TestHandler_CreateSegment(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, appID, resp["ApplicationId"]) @@ -945,7 +947,7 @@ func TestGetSegmentVersion_UnknownVersionNotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, missingRec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(missingRec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(missingRec.Body), &errResp, jsonx.V1())) assert.Equal(t, "NotFoundException", errResp["__type"]) } @@ -973,7 +975,7 @@ func TestHandler_GetSegments_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) created[resp["Id"].(string)] = true } @@ -985,7 +987,7 @@ func TestHandler_GetSegments_DuplicateNames_NoDropOrDupAcrossPages(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) for _, item := range items { diff --git a/services/pinpoint/store.go b/services/pinpoint/store.go index e1f47359c2..46648f6e8a 100644 --- a/services/pinpoint/store.go +++ b/services/pinpoint/store.go @@ -1,7 +1,7 @@ package pinpoint import ( - "encoding/json" + "encoding/json/jsontext" "maps" "strings" "time" @@ -33,7 +33,7 @@ type InMemoryBackend struct { campaignVersions map[string][]*Campaign segmentVersions map[string][]*Segment templateVersionHistory map[string][]templateVersionItem - templateVersionData map[string]map[string]json.RawMessage + templateVersionData map[string]map[string]jsontext.Value templateActiveVersion map[string]string campaignActivities map[string][]campaignActivity journeyRuns map[string][]*journeyRun @@ -58,7 +58,7 @@ func NewInMemoryBackend(region, accountID string) *InMemoryBackend { campaignVersions: make(map[string][]*Campaign), segmentVersions: make(map[string][]*Segment), templateVersionHistory: make(map[string][]templateVersionItem), - templateVersionData: make(map[string]map[string]json.RawMessage), + templateVersionData: make(map[string]map[string]jsontext.Value), templateActiveVersion: make(map[string]string), campaignActivities: make(map[string][]campaignActivity), journeyRuns: make(map[string][]*journeyRun), @@ -84,7 +84,7 @@ func (b *InMemoryBackend) Reset() { b.campaignVersions = make(map[string][]*Campaign) b.segmentVersions = make(map[string][]*Segment) b.templateVersionHistory = make(map[string][]templateVersionItem) - b.templateVersionData = make(map[string]map[string]json.RawMessage) + b.templateVersionData = make(map[string]map[string]jsontext.Value) b.templateActiveVersion = make(map[string]string) b.campaignActivities = make(map[string][]campaignActivity) b.journeyRuns = make(map[string][]*journeyRun) diff --git a/services/pinpoint/tags_test.go b/services/pinpoint/tags_test.go index 3e38a54a26..60d3f4615d 100644 --- a/services/pinpoint/tags_test.go +++ b/services/pinpoint/tags_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "strings" @@ -9,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // pinpointEncodeARN URL-encodes an ARN for use in URL paths. @@ -66,7 +69,7 @@ func TestUntagResource_EmptyTagKeys(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &appResp, jsonx.V1())) arn, _ := appResp["Arn"].(string) require.NotEmpty(t, arn, "app ARN must be present") @@ -121,7 +124,7 @@ func TestUntagResource_RemovesSpecificTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var appResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &appResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &appResp, jsonx.V1())) arn, _ := appResp["Arn"].(string) encodedARN := pinpointEncodeARN(arn) @@ -142,7 +145,7 @@ func TestUntagResource_RemovesSpecificTags(t *testing.T) { require.Equal(t, http.StatusOK, listTagRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listTagRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listTagRec.Body.Bytes(), &tagsResp, jsonx.V1())) remaining, _ := tagsResp["tags"].(map[string]any) @@ -205,7 +208,7 @@ func TestTagCampaignViaARN(t *testing.T) { require.Equal(t, http.StatusCreated, recC.Code) var cResp map[string]any - require.NoError(t, json.NewDecoder(recC.Body).Decode(&cResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(recC.Body), &cResp, jsonx.V1())) campaignARN, _ := cResp["Arn"].(string) require.NotEmpty(t, campaignARN) @@ -219,7 +222,7 @@ func TestTagCampaignViaARN(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var tagsBody map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&tagsBody)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &tagsBody, jsonx.V1())) tagsMap, _ := tagsBody["tags"].(map[string]any) assert.Equal(t, "42", tagsMap["cost-center"]) } @@ -235,7 +238,7 @@ func TestTagJourneyViaARN(t *testing.T) { require.Equal(t, http.StatusCreated, recJ.Code) var jResp map[string]any - require.NoError(t, json.NewDecoder(recJ.Body).Decode(&jResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(recJ.Body), &jResp, jsonx.V1())) assert.NotContains(t, jResp, "Arn") journeyARN := "arn:aws:mobiletargeting:" + testRegion + ":" + testAccountID + @@ -260,7 +263,7 @@ func TestTagSegmentViaARN(t *testing.T) { require.Equal(t, http.StatusCreated, recS.Code) var sResp map[string]any - require.NoError(t, json.NewDecoder(recS.Body).Decode(&sResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(recS.Body), &sResp, jsonx.V1())) segmentARN, _ := sResp["Arn"].(string) require.NotEmpty(t, segmentARN) @@ -284,7 +287,7 @@ func TestTagEmailTemplateViaARN(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var tResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&tResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &tResp, jsonx.V1())) templateARN, _ := tResp["Arn"].(string) require.NotEmpty(t, templateARN) @@ -298,7 +301,7 @@ func TestTagEmailTemplateViaARN(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listBody map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&listBody)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &listBody, jsonx.V1())) tagsMap, _ := listBody["tags"].(map[string]any) assert.Equal(t, "email", tagsMap["type"]) @@ -334,7 +337,7 @@ func TestHandler_TagOperations(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var appResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&appResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &appResp, jsonx.V1())) appARN, _ := appResp["Arn"].(string) require.NotEmpty(t, appARN) @@ -353,7 +356,7 @@ func TestHandler_TagOperations(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.NewDecoder(listRec.Body).Decode(&tagsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(listRec.Body), &tagsResp, jsonx.V1())) tagsMap, _ := tagsResp["tags"].(map[string]any) assert.Equal(t, "integration", tagsMap["owner"]) diff --git a/services/pinpoint/template_versions.go b/services/pinpoint/template_versions.go index aca47d1d7b..a99ef33f25 100644 --- a/services/pinpoint/template_versions.go +++ b/services/pinpoint/template_versions.go @@ -1,10 +1,13 @@ package pinpoint import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const latestTemplateVersion = "latest" @@ -49,13 +52,13 @@ func (b *InMemoryBackend) nextTemplateVersionLocked( return current, nil } - raw, err := json.Marshal(live) + raw, err := json.Marshal(live, jsonx.V1()) if err != nil { return "", fmt.Errorf("snapshot template version: %w", err) } if b.templateVersionData[key] == nil { - b.templateVersionData[key] = make(map[string]json.RawMessage) + b.templateVersionData[key] = make(map[string]jsontext.Value) } b.templateVersionData[key][current] = raw @@ -137,7 +140,7 @@ func pickTemplateVersion[T any]( } var out T - if err := json.Unmarshal(raw, &out); err != nil { + if err := json.Unmarshal(raw, &out, jsonx.V1()); err != nil { return nil, false, fmt.Errorf("decode template version: %w", err) } @@ -345,7 +348,7 @@ func unlockedDelete[T any]( } // restoreLatestLocked rewinds the live template to an older snapshot, keeping its tags. -func (b *InMemoryBackend) restoreLatestLocked(name, templateType string, raw json.RawMessage) error { +func (b *InMemoryBackend) restoreLatestLocked(name, templateType string, raw jsontext.Value) error { switch strings.ToLower(templateType) { case templateTypeEmail: t, _ := b.emailTemplates.Get(name) @@ -372,9 +375,9 @@ func (b *InMemoryBackend) restoreLatestLocked(name, templateType string, raw jso return nil } -func restoreTemplate[T any](dst *T, raw json.RawMessage, tags func(*T) *map[string]string) error { +func restoreTemplate[T any](dst *T, raw jsontext.Value, tags func(*T) *map[string]string) error { var fresh T - if err := json.Unmarshal(raw, &fresh); err != nil { + if err := json.Unmarshal(raw, &fresh, jsonx.V1()); err != nil { return fmt.Errorf("restore template version: %w", err) } @@ -384,7 +387,7 @@ func restoreTemplate[T any](dst *T, raw json.RawMessage, tags func(*T) *map[stri return nil } -func (b *InMemoryBackend) liveTemplateJSONLocked(name, templateType string) (string, json.RawMessage, bool) { +func (b *InMemoryBackend) liveTemplateJSONLocked(name, templateType string) (string, jsontext.Value, bool) { var ( version string live any @@ -417,7 +420,7 @@ func (b *InMemoryBackend) liveTemplateJSONLocked(name, templateType string) (str return "", nil, false } - raw, err := json.Marshal(live) + raw, err := json.Marshal(live, jsonx.V1()) if err != nil { return "", nil, false } @@ -452,7 +455,7 @@ func (b *InMemoryBackend) ListTemplateVersions( var meta templateVersionMeta if len(raw) > 0 { - _ = json.Unmarshal(raw, &meta) + _ = json.Unmarshal(raw, &meta, jsonx.V1()) } cp.CreationDate = meta.CreationDate diff --git a/services/pinpoint/template_versions_test.go b/services/pinpoint/template_versions_test.go index b372d01730..d81de1fe50 100644 --- a/services/pinpoint/template_versions_test.go +++ b/services/pinpoint/template_versions_test.go @@ -1,19 +1,21 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func decodeBody(t *testing.T, body []byte) map[string]any { t.Helper() var got map[string]any - require.NoError(t, json.Unmarshal(body, &got)) + require.NoError(t, json.Unmarshal(body, &got, jsonx.V1())) return got } diff --git a/services/pinpoint/templates_create_new_version_test.go b/services/pinpoint/templates_create_new_version_test.go index 8a7095b0ee..b8467baf1a 100644 --- a/services/pinpoint/templates_create_new_version_test.go +++ b/services/pinpoint/templates_create_new_version_test.go @@ -1,12 +1,14 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestUpdateTemplate_CreateNewVersion(t *testing.T) { @@ -79,14 +81,14 @@ func TestUpdateTemplate_CreateNewVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var got map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, tt.wantVersion, got["Version"]) rec = doPinpointRequest(t, h, http.MethodGet, path+"/versions", nil) require.Equal(t, http.StatusOK, rec.Code) var vers map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vers)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &vers, jsonx.V1())) assert.Len(t, vers["Item"], tt.wantVersions) }) } diff --git a/services/pinpoint/templates_email_test.go b/services/pinpoint/templates_email_test.go index 932640f4dd..ded66dce11 100644 --- a/services/pinpoint/templates_email_test.go +++ b/services/pinpoint/templates_email_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -25,7 +27,7 @@ func TestListTemplates_EmailListed(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) require.NotEmpty(t, items) @@ -140,7 +142,7 @@ func TestEmailTemplate_BodyPersistence(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "get status") var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantSubject != "" { assert.Equal(t, tc.wantSubject, resp["Subject"], "Subject") @@ -219,7 +221,7 @@ func TestEmailTemplate_VersionBumpsOnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantVersion, resp["Version"], "Version after updates") }) } @@ -281,7 +283,7 @@ func TestEmailTemplate_DefaultSubstitutions(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantSubs, resp["DefaultSubstitutions"], "DefaultSubstitutions") }) @@ -377,7 +379,7 @@ func TestInAppTemplate_BodyPersistence(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "get status") var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantLayout != "" { assert.Equal(t, tc.wantLayout, resp["Layout"]) @@ -508,7 +510,7 @@ func TestInAppTemplate_ContentStructure(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "BOTTOM_BANNER", tmpl["Layout"]) assert.Equal(t, "Upgrade promo", tmpl["TemplateDescription"]) @@ -564,7 +566,7 @@ func TestInAppTemplate_MultipleContentItems(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) gotContent := tmpl["Content"].([]any) require.Len(t, gotContent, 3) @@ -609,7 +611,7 @@ func TestInAppTemplate_UpdateContent(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "TOP_BANNER", tmpl["Layout"]) content := tmpl["Content"].([]any) @@ -730,7 +732,7 @@ func TestHandler_CreateEmailTemplate(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, "Created", resp["Message"]) } @@ -765,7 +767,7 @@ func TestHandler_CreateInAppTemplate(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, "Created", resp["Message"]) } @@ -790,7 +792,7 @@ func TestEmailTemplate_TemplateType(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "EMAIL", resp["TemplateType"]) } @@ -811,7 +813,7 @@ func TestInAppTemplate_TemplateTypeAndCustomConfig(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "INAPP", resp["TemplateType"]) customConfig, _ := resp["CustomConfig"].(map[string]any) diff --git a/services/pinpoint/templates_push_test.go b/services/pinpoint/templates_push_test.go index 7fafd588dc..8ddbc7dd3e 100644 --- a/services/pinpoint/templates_push_test.go +++ b/services/pinpoint/templates_push_test.go @@ -1,7 +1,8 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pinpoint" ) @@ -25,7 +27,7 @@ func TestListTemplates_SMSListed(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) require.NotEmpty(t, items) @@ -119,7 +121,7 @@ func TestSmsTemplate_BodyPersistence(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "get status") var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantBody != "" { assert.Equal(t, tc.wantBody, resp["Body"], "Body") @@ -231,7 +233,7 @@ func TestPushTemplate_BodyPersistence(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "get status") var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantDescription != "" { assert.Equal(t, tc.wantDescription, resp["TemplateDescription"]) @@ -339,7 +341,7 @@ func TestPushTemplate_PerPlatformOverrides(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "PUSH", tmpl["TemplateType"]) assert.Equal(t, "reco-1", tmpl["RecommenderId"]) @@ -388,7 +390,7 @@ func TestPushTemplate_UpdatePerPlatform(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) def := tmpl["Default"].(map[string]any) assert.Equal(t, "v2 body", def["Body"]) @@ -431,7 +433,7 @@ func TestSMSTemplate_RecommenderID(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "Hello from {{sender}}", tmpl["Body"]) @@ -458,7 +460,7 @@ func TestSMSTemplate_UpdateRecommenderID(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "Hello v2", tmpl["Body"]) assert.Equal(t, "reco-new", tmpl["RecommenderId"]) @@ -565,7 +567,7 @@ func TestHandler_CreatePushTemplate(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, "Created", resp["Message"]) } @@ -600,7 +602,7 @@ func TestHandler_CreateSmsTemplate(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Arn"]) assert.Equal(t, "Created", resp["Message"]) } diff --git a/services/pinpoint/templates_test.go b/services/pinpoint/templates_test.go index 3c72455b17..db319eaeef 100644 --- a/services/pinpoint/templates_test.go +++ b/services/pinpoint/templates_test.go @@ -1,7 +1,7 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestVoiceTemplate_FullCRUD(t *testing.T) { @@ -62,7 +64,7 @@ func TestVoiceTemplate_FullCRUD(t *testing.T) { "body: %s", createRec.Body.String()) var cr map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &cr, jsonx.V1())) assert.NotEmpty(t, cr["Message"]) getRec := doPinpointRequest(t, h, http.MethodGet, @@ -70,7 +72,7 @@ func TestVoiceTemplate_FullCRUD(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, templateName, gr["TemplateName"]) if tc.wantBody != "SKIP" { assert.Equal(t, tc.wantBody, gr["Body"]) @@ -118,7 +120,7 @@ func TestVoiceTemplate_FullFieldSet(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var gr map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &gr, jsonx.V1())) assert.Equal(t, templateName, gr["TemplateName"]) assert.Equal(t, "VOICE", gr["TemplateType"]) @@ -139,7 +141,7 @@ func TestVoiceTemplate_FullFieldSet(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var gr2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &gr2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &gr2, jsonx.V1())) assert.Equal(t, "Matthew", gr2["VoiceId"]) assert.Equal(t, "en-GB", gr2["LanguageCode"]) @@ -190,7 +192,7 @@ func TestVoiceTemplate_VersionHistory(t *testing.T) { require.Equal(t, http.StatusOK, versionsRec.Code) var versionsResp map[string]any - require.NoError(t, json.Unmarshal(versionsRec.Body.Bytes(), &versionsResp)) + require.NoError(t, json.Unmarshal(versionsRec.Body.Bytes(), &versionsResp, jsonx.V1())) items, _ := versionsResp["Item"].([]any) assert.Len(t, items, tc.wantVersions) }) @@ -214,7 +216,7 @@ func TestListTemplates_VoiceListed(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) require.NotEmpty(t, items) @@ -243,7 +245,7 @@ func TestListTemplates_MixedTypes(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.GreaterOrEqual(t, len(items), 3) } @@ -365,7 +367,7 @@ func TestListTemplates_PrefixFilter(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tc.wantCount, "Item count with prefix=%q", tc.prefix) @@ -456,7 +458,7 @@ func TestListTemplates_TypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tc.wantCount, @@ -545,7 +547,7 @@ func TestListTemplates_PrefixAndTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tc.wantCount, @@ -622,7 +624,7 @@ func TestTemplateVersionHistory(t *testing.T) { require.Equal(t, http.StatusOK, verRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(verRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) assert.Len(t, items, tc.wantVersions, @@ -687,7 +689,7 @@ func TestTemplate_LastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, getRec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &resp1, jsonx.V1())) assert.NotEmpty(t, resp1["CreationDate"], "CreationDate should be set") assert.NotEmpty(t, resp1["LastModifiedDate"], "LastModifiedDate should be set after create") @@ -701,7 +703,7 @@ func TestTemplate_LastModifiedDate(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &resp2, jsonx.V1())) assert.NotEmpty(t, resp2["LastModifiedDate"], "LastModifiedDate should be present after update") }) @@ -750,7 +752,7 @@ func TestListTemplates_SortedOutput(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) require.Len(t, items, len(tc.creates)) @@ -821,7 +823,7 @@ func TestTemplate_ARNPresent(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["Arn"].(string) assert.NotEmpty(t, arn, "template ARN must be present in GET response") @@ -888,7 +890,7 @@ func TestTemplate_TagsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) tagsRaw, _ := resp["tags"].(map[string]any) @@ -925,7 +927,7 @@ func TestListTemplates_FieldCompleteness(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Item"].([]any) require.Len(t, items, 3) @@ -964,7 +966,7 @@ func TestVoiceTemplate_TagsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var tmpl map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &tmpl, jsonx.V1())) assert.Equal(t, "Hello {{user.FirstName}}, your appointment is tomorrow.", tmpl["Body"]) assert.NotEmpty(t, tmpl["Arn"]) @@ -988,7 +990,7 @@ func TestVoiceTemplate_TagRoundTrip(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) templateARN, _ := createResp["Arn"].(string) require.NotEmpty(t, templateARN) @@ -1003,7 +1005,7 @@ func TestVoiceTemplate_TagRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags, _ := tagsResp["tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) diff --git a/services/pinpoint/wire_field_fixes_test.go b/services/pinpoint/wire_field_fixes_test.go index e9af4f80b0..bcc23fb650 100644 --- a/services/pinpoint/wire_field_fixes_test.go +++ b/services/pinpoint/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package pinpoint_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/pinpoint/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestApplicationDateRangeKpi_RequiredTimeRange covers gopherstack-6flj: @@ -216,7 +218,7 @@ func TestCreateSegment_RawImportDefinitionFieldIgnored(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "DIMENSIONAL", out["SegmentType"], "CreateSegment must not accept ImportDefinition; the real WriteSegmentRequest has no such member") assert.Nil(t, out["ImportDefinition"]) @@ -245,7 +247,7 @@ func TestCreateJourney_RawTagsFieldIgnored(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Nil(t, out["tags"], "CreateJourney must not accept or echo tags; the real WriteJourneyRequest/JourneyResponse have no such member") diff --git a/services/pipes/enrichment_test.go b/services/pipes/enrichment_test.go index 28778976b8..fdb351ce45 100644 --- a/services/pipes/enrichment_test.go +++ b/services/pipes/enrichment_test.go @@ -6,12 +6,13 @@ package pipes_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -297,7 +298,7 @@ func TestEnrichment_LambdaInvocation(t *testing.T) { } else { // Nil response: original records payload forwarded. var event map[string]any - require.NoError(t, json.Unmarshal(targetPayloads[0], &event)) + require.NoError(t, json.Unmarshal(targetPayloads[0], &event, jsonx.V1())) _, hasRecords := event["Records"] assert.True(t, hasRecords, "original Records payload should be forwarded when enricher returns nil") } diff --git a/services/pipes/errsweep_wire_shape_test.go b/services/pipes/errsweep_wire_shape_test.go index 9617e60448..4da8d5bfd4 100644 --- a/services/pipes/errsweep_wire_shape_test.go +++ b/services/pipes/errsweep_wire_shape_test.go @@ -1,7 +1,7 @@ package pipes_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/pipes" @@ -58,7 +59,7 @@ func TestHandler_MalformedBodyCarriesTypedErrorCode(t *testing.T) { require.NoError(t, err) var decoded map[string]any - require.NoError(t, json.Unmarshal(raw, &decoded)) + require.NoError(t, json.Unmarshal(raw, &decoded, jsonx.V1())) require.Equal(t, "ValidationException", decoded["__type"], "raw response body must carry __type; got: %s", raw) require.NotEmpty(t, decoded["message"]) diff --git a/services/pipes/filter.go b/services/pipes/filter.go index b135ffe5ac..977e94f122 100644 --- a/services/pipes/filter.go +++ b/services/pipes/filter.go @@ -2,12 +2,14 @@ package pipes import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "reflect" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/eventpattern" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // matchesAnyFilter returns true if body passes at least one of the given filters. @@ -67,8 +69,8 @@ func matchesSingleFilter(body string, f Filter) bool { // and/or content-filter objects) or a nested object; a bare scalar is not a // valid EventBridge pattern value and never matches (see isJSONObject). func matchesJSONPattern(msgBody, pattern string) bool { - var patternMap map[string]json.RawMessage - if err := json.Unmarshal([]byte(pattern), &patternMap); err != nil { + var patternMap map[string]jsontext.Value + if err := json.Unmarshal([]byte(pattern), &patternMap, jsonx.V1()); err != nil { // Malformed pattern: fall back to substring. return strings.Contains(msgBody, pattern) } @@ -77,8 +79,8 @@ func matchesJSONPattern(msgBody, pattern string) bool { return true } - var msgMap map[string]json.RawMessage - if err := json.Unmarshal([]byte(msgBody), &msgMap); err != nil { + var msgMap map[string]jsontext.Value + if err := json.Unmarshal([]byte(msgBody), &msgMap, jsonx.V1()); err != nil { // Message body is not a JSON object; pattern cannot match. return false } @@ -89,7 +91,7 @@ func matchesJSONPattern(msgBody, pattern string) bool { // matchesPatternObject reports whether every field in patternMap is // satisfied by msgMap (fields at one level are ANDed). "$or" is a // combinator, not a message field, so it is dispatched separately. -func matchesPatternObject(patternMap, msgMap map[string]json.RawMessage) bool { +func matchesPatternObject(patternMap, msgMap map[string]jsontext.Value) bool { for field, ruleRaw := range patternMap { if field == "$or" { if !matchesOrCombinator(ruleRaw, msgMap) { @@ -111,9 +113,9 @@ func matchesPatternObject(patternMap, msgMap map[string]json.RawMessage) bool { // matchesOrCombinator evaluates a "$or" combinator // (eb-filtering-complex-example-or): ruleRaw must decode to an array of // pattern objects, and msgMap matches if any one of them fully matches. -func matchesOrCombinator(ruleRaw json.RawMessage, msgMap map[string]json.RawMessage) bool { - var alternatives []json.RawMessage - if err := json.Unmarshal(ruleRaw, &alternatives); err != nil { +func matchesOrCombinator(ruleRaw jsontext.Value, msgMap map[string]jsontext.Value) bool { + var alternatives []jsontext.Value + if err := json.Unmarshal(ruleRaw, &alternatives, jsonx.V1()); err != nil { return false } @@ -135,15 +137,15 @@ func matchesOrCombinator(ruleRaw json.RawMessage, msgMap map[string]json.RawMess // its first non-whitespace byte rather than by attempting to unmarshal it -- // unmarshalling JSON `null` into a map succeeds with a nil map, which would // otherwise misclassify a literal null rule element as an object. -func isJSONObject(raw json.RawMessage) bool { +func isJSONObject(raw jsontext.Value) bool { trimmed := bytes.TrimSpace(raw) return len(trimmed) > 0 && trimmed[0] == '{' } -func decodeJSONObject(raw json.RawMessage) (map[string]json.RawMessage, bool) { - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil { +func decodeJSONObject(raw jsontext.Value) (map[string]jsontext.Value, bool) { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil { return nil, false } @@ -157,13 +159,13 @@ func decodeJSONObject(raw json.RawMessage) (map[string]json.RawMessage, bool) { // needed because {"exists": false} matches precisely when the field is // absent, so evaluation cannot short-circuit on absence the way every other // operator does. -func fieldMatchesRule(msgVal json.RawMessage, exists bool, ruleRaw json.RawMessage) bool { +func fieldMatchesRule(msgVal jsontext.Value, exists bool, ruleRaw jsontext.Value) bool { if isJSONObject(ruleRaw) { return matchesNestedRule(msgVal, exists, ruleRaw) } - var rules []json.RawMessage - if err := json.Unmarshal(ruleRaw, &rules); err != nil { + var rules []jsontext.Value + if err := json.Unmarshal(ruleRaw, &rules, jsonx.V1()); err != nil { return false } @@ -179,7 +181,7 @@ func fieldMatchesRule(msgVal json.RawMessage, exists bool, ruleRaw json.RawMessa // matchesNestedRule descends one level into the event for a nested pattern // object. A nested pattern can only match a present, JSON-object-shaped // field. -func matchesNestedRule(msgVal json.RawMessage, exists bool, ruleRaw json.RawMessage) bool { +func matchesNestedRule(msgVal jsontext.Value, exists bool, ruleRaw jsontext.Value) bool { if !exists { return false } @@ -216,7 +218,7 @@ func matchesNestedRule(msgVal json.RawMessage, exists bool, ruleRaw json.RawMess // msgExists is false whenever the field was absent from the message; every // operator besides exists requires a value to compare against, so absence // fails them all except an explicit {"exists": false}. -func matchesRule(msgVal json.RawMessage, msgExists bool, rule json.RawMessage) bool { +func matchesRule(msgVal jsontext.Value, msgExists bool, rule jsontext.Value) bool { if isJSONObject(rule) { ruleObj, ok := decodeJSONObject(rule) if !ok { @@ -247,13 +249,13 @@ func matchesRule(msgVal json.RawMessage, msgExists bool, rule json.RawMessage) b // numerically-equal event number). reflect.DeepEqual (not ==) is required // because a malformed pattern or event can decode to a non-comparable type // (a JSON array or object), which would panic under ==. -func matchesExactRule(msgVal, rule json.RawMessage) bool { +func matchesExactRule(msgVal, rule jsontext.Value) bool { var ruleAny, msgAny any - if err := json.Unmarshal(rule, &ruleAny); err != nil { + if err := json.Unmarshal(rule, &ruleAny, jsonx.V1()); err != nil { return false } - if err := json.Unmarshal(msgVal, &msgAny); err != nil { + if err := json.Unmarshal(msgVal, &msgAny, jsonx.V1()); err != nil { return false } @@ -263,7 +265,7 @@ func matchesExactRule(msgVal, rule json.RawMessage) bool { // matchesRuleObject dispatches a single-key content-filter object to its // matcher. Supported: prefix, suffix, numeric, cidr, anything-but, // equals-ignore-case. -func matchesRuleObject(msgVal json.RawMessage, ruleObj map[string]json.RawMessage) bool { +func matchesRuleObject(msgVal jsontext.Value, ruleObj map[string]jsontext.Value) bool { if prefixRaw, ok := ruleObj["prefix"]; ok { return matchesPrefixRule(msgVal, prefixRaw) } @@ -291,18 +293,18 @@ func matchesRuleObject(msgVal json.RawMessage, ruleObj map[string]json.RawMessag return false } -func decodeString(raw json.RawMessage) (string, bool) { +func decodeString(raw jsontext.Value) (string, bool) { var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return "", false } return s, true } -func decodeFloat(raw json.RawMessage) (float64, bool) { +func decodeFloat(raw jsontext.Value) (float64, bool) { var f float64 - if err := json.Unmarshal(raw, &f); err != nil { + if err := json.Unmarshal(raw, &f, jsonx.V1()); err != nil { return 0, false } @@ -312,7 +314,7 @@ func decodeFloat(raw json.RawMessage) (float64, bool) { // matchesPrefixRule matches a prefix rule value against msgVal. AWS supports // both a plain string prefix and a case-insensitive nested form // (eb-filtering-prefix-matching-ignore-case): {"prefix": {"equals-ignore-case": "foo"}}. -func matchesPrefixRule(msgVal, prefixRaw json.RawMessage) bool { +func matchesPrefixRule(msgVal, prefixRaw jsontext.Value) bool { msgStr, ok := decodeString(msgVal) if !ok { return false @@ -338,7 +340,7 @@ func matchesPrefixRule(msgVal, prefixRaw json.RawMessage) bool { // matchesSuffixRule matches a suffix rule value against msgVal. AWS supports // both a plain string suffix and a case-insensitive nested form // (eb-filtering-suffix-matching-ignore-case): {"suffix": {"equals-ignore-case": "foo"}}. -func matchesSuffixRule(msgVal, suffixRaw json.RawMessage) bool { +func matchesSuffixRule(msgVal, suffixRaw jsontext.Value) bool { msgStr, ok := decodeString(msgVal) if !ok { return false @@ -363,7 +365,7 @@ func matchesSuffixRule(msgVal, suffixRaw json.RawMessage) bool { // nestedEqualsIgnoreCase extracts the string value of a nested // {"equals-ignore-case": "..."} object, as used inside prefix/suffix rules. -func nestedEqualsIgnoreCase(nested map[string]json.RawMessage) (string, bool) { +func nestedEqualsIgnoreCase(nested map[string]jsontext.Value) (string, bool) { ciRaw, ok := nested["equals-ignore-case"] if !ok { return "", false @@ -374,7 +376,7 @@ func nestedEqualsIgnoreCase(nested map[string]json.RawMessage) (string, bool) { // matchesEqualsIgnoreCaseRule matches a standalone // {"equals-ignore-case": "..."} rule (eb-filtering-equals-ignore-case-matching). -func matchesEqualsIgnoreCaseRule(msgVal, valRaw json.RawMessage) bool { +func matchesEqualsIgnoreCaseRule(msgVal, valRaw jsontext.Value) bool { msgStr, ok := decodeString(msgVal) if !ok { return false @@ -393,9 +395,9 @@ func matchesEqualsIgnoreCaseRule(msgVal, valRaw json.RawMessage) bool { // services/eventbridge/pattern.go's matchNumeric. msgVal must decode as a // JSON number; a string-encoded number (as DynamoDB Streams' "N" attribute // wrapper produces) does not match. -func matchesNumericRule(msgVal, rulesRaw json.RawMessage) bool { +func matchesNumericRule(msgVal, rulesRaw jsontext.Value) bool { var ruleList []any - if err := json.Unmarshal(rulesRaw, &ruleList); err != nil { + if err := json.Unmarshal(rulesRaw, &ruleList, jsonx.V1()); err != nil { return false } @@ -410,7 +412,7 @@ func matchesNumericRule(msgVal, rulesRaw json.RawMessage) bool { // matchesCIDRRule reports whether the string msgVal is an IP address inside // the given CIDR range (eb-filtering-ip-address), via pkgs/eventpattern, // shared with services/eventbridge/pattern.go's matchCIDR. -func matchesCIDRRule(msgVal, cidrRaw json.RawMessage) bool { +func matchesCIDRRule(msgVal, cidrRaw jsontext.Value) bool { ipStr, ok := decodeString(msgVal) if !ok { return false @@ -426,14 +428,14 @@ func matchesCIDRRule(msgVal, cidrRaw json.RawMessage) bool { // existsWant extracts {"exists": true/false}'s boolean, ok=false if the key // is absent or not a bool. -func existsWant(ruleObj map[string]json.RawMessage) (bool, bool) { +func existsWant(ruleObj map[string]jsontext.Value) (bool, bool) { existsRaw, hasKey := ruleObj["exists"] if !hasKey { return false, false } var want bool - if err := json.Unmarshal(existsRaw, &want); err != nil { + if err := json.Unmarshal(existsRaw, &want, jsonx.V1()); err != nil { return false, false } @@ -448,19 +450,19 @@ func existsWant(ruleObj map[string]json.RawMessage) (bool, bool) { // records use, where every AttributeValue is string-wrapped); a non-string // msgVal is never equal to a string exclusion value, so it always counts as // "anything but" (matchesRuleObject negates this function's result). -func matchesAnythingBut(anythingButRaw, msgVal json.RawMessage) bool { +func matchesAnythingBut(anythingButRaw, msgVal jsontext.Value) bool { msgStr, ok := decodeString(msgVal) if !ok { return false } var single string - if err := json.Unmarshal(anythingButRaw, &single); err == nil { + if err := json.Unmarshal(anythingButRaw, &single, jsonx.V1()); err == nil { return msgStr == single } var excluded []string - if err := json.Unmarshal(anythingButRaw, &excluded); err == nil { + if err := json.Unmarshal(anythingButRaw, &excluded, jsonx.V1()); err == nil { return slices.Contains(excluded, msgStr) } diff --git a/services/pipes/filter_validation.go b/services/pipes/filter_validation.go index 4135b95d6c..0e4b5c9795 100644 --- a/services/pipes/filter_validation.go +++ b/services/pipes/filter_validation.go @@ -1,9 +1,11 @@ package pipes import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // isKnownPipeMatcher reports whether key is a matcher-object key that pipes' @@ -54,7 +56,7 @@ func validateFilterPattern(pattern string) error { } var patternMap map[string]any - if err := json.Unmarshal([]byte(trimmed), &patternMap); err != nil { + if err := json.Unmarshal([]byte(trimmed), &patternMap, jsonx.V1()); err != nil { return fmt.Errorf("pattern: %w: not valid JSON: %w", ErrValidation, err) } diff --git a/services/pipes/handler.go b/services/pipes/handler.go index f351c348a9..bce6f104a0 100644 --- a/services/pipes/handler.go +++ b/services/pipes/handler.go @@ -2,7 +2,7 @@ package pipes import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -350,40 +351,37 @@ func errMessage(err error) string { } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, ErrNotFound): payload, _ := json.Marshal(map[string]string{ keyTypeField: "NotFoundException", keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusNotFound, payload) case errors.Is(err, ErrAlreadyExists), errors.Is(err, ErrConflict): payload, _ := json.Marshal(map[string]string{ keyTypeField: "ConflictException", keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusConflict, payload) case errors.Is(err, ErrQuota): payload, _ := json.Marshal(map[string]string{ keyTypeField: "ServiceQuotaExceededException", keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrValidation): payload, _ := json.Marshal(map[string]string{ keyTypeField: errCodeValidation, keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): // This branch used to omit keyTypeField entirely, so // restjson.GetErrorInfo (aws-sdk-go-v2 aws/protocol/restjson/ // decoder_util.go:15) found no code in the header (unset) or the @@ -398,7 +396,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: "InternalException", keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusInternalServerError, payload) } @@ -512,7 +510,7 @@ func (h *Handler) handleCreatePipe(ctx context.Context, path string, body []byte } var req createPipeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -535,7 +533,7 @@ func (h *Handler) handleCreatePipe(ctx context.Context, path string, body []byte return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } func (h *Handler) handleDescribePipe(ctx context.Context, path string) ([]byte, error) { @@ -549,7 +547,7 @@ func (h *Handler) handleDescribePipe(ctx context.Context, path string) ([]byte, return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } // pipeSummary matches types.Pipe (the summary shape ListPipesOutput.Pipes uses), @@ -613,7 +611,7 @@ func (h *Handler) handleListPipes(ctx context.Context, query url.Values) ([]byte }) } - return json.Marshal(listPipesResponse{Pipes: items, NextToken: res.NextToken}) + return json.Marshal(listPipesResponse{Pipes: items, NextToken: res.NextToken}, jsonx.V1()) } func (h *Handler) handleDeletePipe(ctx context.Context, path string) ([]byte, error) { @@ -627,7 +625,7 @@ func (h *Handler) handleDeletePipe(ctx context.Context, path string) ([]byte, er return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } func (h *Handler) handleUpdatePipe(ctx context.Context, path string, body []byte) ([]byte, error) { @@ -637,7 +635,7 @@ func (h *Handler) handleUpdatePipe(ctx context.Context, path string, body []byte } var req updatePipeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -657,7 +655,7 @@ func (h *Handler) handleUpdatePipe(ctx context.Context, path string, body []byte return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } func (h *Handler) handleStartPipe(ctx context.Context, path string) ([]byte, error) { @@ -671,7 +669,7 @@ func (h *Handler) handleStartPipe(ctx context.Context, path string) ([]byte, err return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } func (h *Handler) handleStopPipe(ctx context.Context, path string) ([]byte, error) { @@ -685,7 +683,7 @@ func (h *Handler) handleStopPipe(ctx context.Context, path string) ([]byte, erro return nil, err } - return json.Marshal(toPipeResponse(p)) + return json.Marshal(toPipeResponse(p), jsonx.V1()) } type tagResourceRequest struct { @@ -699,7 +697,7 @@ func (h *Handler) handleTagResource(ctx context.Context, path string, body []byt } var req tagResourceRequest - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, unmarshalErr) } @@ -750,7 +748,7 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, path string) ([ return nil, err } - return json.Marshal(listTagsResponse{Tags: tags}) + return json.Marshal(listTagsResponse{Tags: tags}, jsonx.V1()) } func extractTagsARN(path string) (string, error) { diff --git a/services/pipes/handler_test.go b/services/pipes/handler_test.go index a87aa2e720..3ca6f18f6e 100644 --- a/services/pipes/handler_test.go +++ b/services/pipes/handler_test.go @@ -3,7 +3,7 @@ package pipes_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -32,7 +33,7 @@ func doPipesRequest(t *testing.T, h *pipes.Handler, method, path string, body an if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -340,7 +341,7 @@ func createTestPipeWithARN(t *testing.T, h *pipes.Handler, pipeName string) stri require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Arn"].(string) } @@ -529,7 +530,7 @@ func TestPipes_Handler_Reset(t *testing.T) { var out struct { Pipes []any `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Pipes, tt.wantAfter) }) } @@ -634,7 +635,7 @@ func TestHandler_ListPipesFiltering(t *testing.T) { Name string `json:"Name"` } `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Pipes, 2) }) @@ -647,7 +648,7 @@ func TestHandler_ListPipesFiltering(t *testing.T) { Name string `json:"Name"` } `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Pipes, 1) assert.Equal(t, "sqs-beta", out.Pipes[0].Name) }) @@ -688,7 +689,7 @@ func TestHandler_SourceAndTargetParameters(t *testing.T) { } `json:"SqsQueueParameters"` } `json:"SourceParameters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) assert.Equal(t, 5, created.SourceParameters.SqsQueueParameters.BatchSize) assert.JSONEq(t, `{"fixed":"value"}`, created.TargetParameters.InputTemplate) } @@ -713,7 +714,7 @@ func TestHandler_ListPipesIncludesSourceTarget(t *testing.T) { var out struct { Pipes []map[string]any `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Pipes, 1) assert.Equal(t, "arn:aws:sqs:us-east-1:000000000000:my-queue", out.Pipes[0]["Source"]) assert.Equal(t, "arn:aws:lambda:us-east-1:000000000000:function:my-fn", out.Pipes[0]["Target"]) @@ -740,7 +741,7 @@ func auditDo(t *testing.T, h *pipes.Handler, method, path string, body any) *htt if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -763,7 +764,7 @@ func auditCreate(t *testing.T, h *pipes.Handler, name string, body map[string]an require.Equal(t, http.StatusOK, rec.Code, "create pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -775,7 +776,7 @@ func auditDescribe(t *testing.T, h *pipes.Handler, name string) map[string]any { require.Equal(t, http.StatusOK, rec.Code, "describe pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -839,7 +840,7 @@ func TestStartStop_ConflictException(t *testing.T) { "real AWS returns 409 ConflictException, not 400 ValidationException") var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ConflictException", resp["__type"], "error type must be ConflictException; body: %s", rec.Body.String()) }) @@ -881,7 +882,7 @@ func TestServiceQuotaExceededException(t *testing.T) { // The key assertion is the error type when it does fail. if rec.Code != http.StatusOK { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ServiceQuotaExceededException", resp["__type"], "quota exceeded must return ServiceQuotaExceededException; body: %s", rec.Body.String()) } @@ -908,7 +909,7 @@ func TestListPipes_EnrichmentInSummary(t *testing.T) { var out struct { Pipes []map[string]any `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Pipes, 1) enrichment, _ := out.Pipes[0]["Enrichment"].(string) @@ -935,7 +936,7 @@ func TestListPipes_NoEnrichmentOmitted(t *testing.T) { var out struct { Pipes []map[string]any `json:"Pipes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Pipes, 1) _, hasEnrichment := out.Pipes[0]["Enrichment"] @@ -954,7 +955,7 @@ func TestInvalidNextToken_ValidationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"], "invalid NextToken must return ValidationException; body: %s", rec.Body.String()) } @@ -1020,7 +1021,7 @@ func TestServiceQuotaErrorCode(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ServiceQuotaExceededException", resp["__type"], "1001st pipe must fail with ServiceQuotaExceededException; body: %s", rec.Body.String()) } @@ -1144,6 +1145,6 @@ func TestHandler_UpdatePipeDesiredState(t *testing.T) { var out struct { DesiredState string `json:"DesiredState"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "STOPPED", out.DesiredState) } diff --git a/services/pipes/persistence.go b/services/pipes/persistence.go index 00808669a9..e2cd4d22ef 100644 --- a/services/pipes/persistence.go +++ b/services/pipes/persistence.go @@ -2,7 +2,7 @@ package pipes import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strings" @@ -39,10 +39,10 @@ const pipesSnapshotVersion = 3 // Restore must pre-register every (resource, region) tuple found in Tables // before calling registry.RestoreAll, see preRegisterSnapshotTables below. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -82,7 +82,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { // "/" (see store_setup.go's pipesTable/ // enrichmentCountsTable); splitting on the first "/" recovers both parts // (region names never contain "/"). -func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]json.RawMessage) { +func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]jsontext.Value) { for key := range tables { name, region, found := strings.Cut(key, "/") if !found { @@ -128,7 +128,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { } if snap.Tables == nil { - snap.Tables = make(map[string]json.RawMessage) + snap.Tables = make(map[string]jsontext.Value) } b.preRegisterSnapshotTables(snap.Tables) diff --git a/services/pipes/pipe_lifecycle_test.go b/services/pipes/pipe_lifecycle_test.go index 96eba038ea..90a613a68a 100644 --- a/services/pipes/pipe_lifecycle_test.go +++ b/services/pipes/pipe_lifecycle_test.go @@ -8,7 +8,7 @@ package pipes_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -247,7 +248,7 @@ func TestLifecycle_DeleteReturnsBody(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DELETING", resp["CurrentState"]) assert.Equal(t, tt.pipeName, resp["Name"]) assert.NotEmpty(t, resp["Arn"]) diff --git a/services/pipes/pipes_test.go b/services/pipes/pipes_test.go index 9d45152f60..c26edaf1a9 100644 --- a/services/pipes/pipes_test.go +++ b/services/pipes/pipes_test.go @@ -5,13 +5,14 @@ package pipes_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -57,7 +58,7 @@ func TestPagination_Limit(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pipeList, _ := resp["Pipes"].([]any) assert.Len(t, pipeList, tt.wantCount) }) @@ -87,7 +88,7 @@ func TestPagination_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, page1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(page1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(page1.Body.Bytes(), &resp1, jsonx.V1())) list1 := resp1["Pipes"].([]any) assert.Len(t, list1, 2) assert.NotEmpty(t, resp1["NextToken"], "NextToken should be present when more pages exist") @@ -98,7 +99,7 @@ func TestPagination_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, page2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(page2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(page2.Body.Bytes(), &resp2, jsonx.V1())) list2 := resp2["Pipes"].([]any) assert.NotEmpty(t, list2) diff --git a/services/pipes/runner.go b/services/pipes/runner.go index 7288d1c616..b641961b29 100644 --- a/services/pipes/runner.go +++ b/services/pipes/runner.go @@ -2,7 +2,7 @@ package pipes import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" @@ -10,6 +10,7 @@ import ( "time" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" @@ -367,7 +368,7 @@ func (r *Runner) pollSQSPipe(ctx context.Context, p *Pipe) { return } - payload, err := json.Marshal(sqsPipeEvent{Records: buildSQSRecords(p, msgs)}) + payload, err := json.Marshal(sqsPipeEvent{Records: buildSQSRecords(p, msgs)}, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "pipes: failed to marshal SQS records", "pipe", p.Name, "error", err) diff --git a/services/pipes/runner_targets_test.go b/services/pipes/runner_targets_test.go index a2691514bc..0390007edb 100644 --- a/services/pipes/runner_targets_test.go +++ b/services/pipes/runner_targets_test.go @@ -8,7 +8,7 @@ package pipes_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "sync" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -40,7 +41,7 @@ func b3Do(t *testing.T, h *pipes.Handler, method, path string, body any) *httpte if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -63,7 +64,7 @@ func b3Create(t *testing.T, h *pipes.Handler, name string, body map[string]any) require.Equal(t, http.StatusOK, rec.Code, "create pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -75,7 +76,7 @@ func b3Describe(t *testing.T, h *pipes.Handler, name string) map[string]any { require.Equal(t, http.StatusOK, rec.Code, "describe pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -276,7 +277,7 @@ func b4Do(t *testing.T, h *pipes.Handler, method, path string, body any) *httpte var b []byte if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -297,7 +298,7 @@ func b4Create(t *testing.T, h *pipes.Handler, name string, body map[string]any) rec := b4Do(t, h, http.MethodPost, "/v1/pipes/"+name, body) require.Equal(t, http.StatusOK, rec.Code, "create pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -307,7 +308,7 @@ func b4Describe(t *testing.T, h *pipes.Handler, name string) map[string]any { rec := b4Do(t, h, http.MethodGet, "/v1/pipes/"+name, nil) require.Equal(t, http.StatusOK, rec.Code, "describe pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -925,7 +926,7 @@ func TestTarget_Firehose_InputTemplate(t *testing.T) { } else { // No template → SQS records JSON is forwarded. var event map[string]any - require.NoError(t, json.Unmarshal(records[0], &event)) + require.NoError(t, json.Unmarshal(records[0], &event, jsonx.V1())) _, hasRecords := event["Records"] assert.True(t, hasRecords, "Firehose should receive SQS records payload") } diff --git a/services/pipes/runner_test.go b/services/pipes/runner_test.go index 0f3e99d89b..5cb441616e 100644 --- a/services/pipes/runner_test.go +++ b/services/pipes/runner_test.go @@ -2,7 +2,7 @@ package pipes_test import ( "context" - "encoding/json" + "encoding/json/v2" "sync" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -138,7 +139,7 @@ func TestPipesRunner_SQSToLambda(t *testing.T) { EventSource string `json:"eventSource"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payloads[0], &event)) + require.NoError(t, json.Unmarshal(payloads[0], &event, jsonx.V1())) require.Len(t, event.Records, 2) assert.Equal(t, "msg-1", event.Records[0].MessageID) assert.Equal(t, "hello", event.Records[0].Body) @@ -313,7 +314,7 @@ func TestPipesRunner_FilterCriteria(t *testing.T) { require.Len(t, calls, 1) var event map[string]any - require.NoError(t, json.Unmarshal(payloads[0], &event)) + require.NoError(t, json.Unmarshal(payloads[0], &event, jsonx.V1())) require.Len(t, event, 1) // payload is forwarded - just check Lambda was called once diff --git a/services/pipes/runner_timestream.go b/services/pipes/runner_timestream.go index 6676d8c05f..e3d92103af 100644 --- a/services/pipes/runner_timestream.go +++ b/services/pipes/runner_timestream.go @@ -3,12 +3,14 @@ package pipes import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -88,7 +90,7 @@ func (r *Runner) invokeTimestreamTarget(ctx context.Context, p *Pipe, payload [] // or the payload itself as a single event. func splitPipeEvents(payload []byte) []any { var v any - if err := json.Unmarshal(payload, &v); err != nil { + if err := json.Unmarshal(payload, &v, jsonx.V1()); err != nil { return nil } @@ -331,11 +333,11 @@ func decodeEmbeddedJSON(v any) any { } var out any - if json.Unmarshal([]byte(s), &out) == nil { + if json.Unmarshal([]byte(s), &out, jsonx.V1()) == nil { return out } - if raw, err := base64.StdEncoding.DecodeString(s); err == nil && json.Unmarshal(raw, &out) == nil { + if raw, err := base64.StdEncoding.DecodeString(s); err == nil && json.Unmarshal(raw, &out, jsonx.V1()) == nil { return out } @@ -354,7 +356,7 @@ func pipeScalarString(v any) string { return "" } - b, _ := json.Marshal(v) + b, _ := json.Marshal(v, jsonx.V1()) return string(b) } diff --git a/services/pipes/sources_poll.go b/services/pipes/sources_poll.go index 508b443796..2ee04025e2 100644 --- a/services/pipes/sources_poll.go +++ b/services/pipes/sources_poll.go @@ -3,9 +3,10 @@ package pipes import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -148,7 +149,7 @@ func (r *Runner) pollKinesisShard(ctx context.Context, p *Pipe, shardID, startin return } - payload, err := json.Marshal(kinesisPipeEvent{Records: buildKinesisRecords(p, shardID, records)}) + payload, err := json.Marshal(kinesisPipeEvent{Records: buildKinesisRecords(p, shardID, records)}, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "pipes: failed to marshal Kinesis records", "pipe", p.Name, "error", err) @@ -218,7 +219,7 @@ func (r *Runner) pollDynamoDBShard(ctx context.Context, p *Pipe, shardID, starti return } - payload, err := json.Marshal(dynamoDBPipeEvent{Records: buildDynamoDBRecords(p, records)}) + payload, err := json.Marshal(dynamoDBPipeEvent{Records: buildDynamoDBRecords(p, records)}, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "pipes: failed to marshal DynamoDB stream records", "pipe", p.Name, "error", err) @@ -312,7 +313,7 @@ func filterDynamoDBRecords(p *Pipe, records []DynamoDBStreamRecord) []DynamoDBSt NewImage: rec.NewImage, OldImage: rec.OldImage, }, - }) + }, jsonx.V1()) if err == nil && matchesAnyFilter(string(body), filters) { out = append(out, rec) } diff --git a/services/pipes/sources_test.go b/services/pipes/sources_test.go index bd36b94b67..70b31e069d 100644 --- a/services/pipes/sources_test.go +++ b/services/pipes/sources_test.go @@ -15,13 +15,14 @@ package pipes_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -828,7 +829,7 @@ func TestPipesRunner_StreamSourcePolling(t *testing.T) { EventSource string `json:"eventSource"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payloads[0], &event)) + require.NoError(t, json.Unmarshal(payloads[0], &event, jsonx.V1())) require.Len(t, event.Records, 1) assert.Equal(t, "pk1", event.Records[0].Kinesis.PartitionKey) assert.Equal(t, "aws:kinesis", event.Records[0].EventSource) @@ -997,7 +998,7 @@ func TestPipesRunner_StreamSourcePolling(t *testing.T) { EventName string `json:"eventName"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payloads[0], &event)) + require.NoError(t, json.Unmarshal(payloads[0], &event, jsonx.V1())) require.Len(t, event.Records, 1) assert.Equal(t, "INSERT", event.Records[0].EventName) }, diff --git a/services/pipes/tags_test.go b/services/pipes/tags_test.go index c92bd68b2d..7c524cf576 100644 --- a/services/pipes/tags_test.go +++ b/services/pipes/tags_test.go @@ -1,12 +1,14 @@ package pipes_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestTags_CreateAndDescribe verifies tags are stored on create and returned on describe. @@ -96,7 +98,7 @@ func TestTags_UpdateViaTagResource(t *testing.T) { tagsRec := auditDo(t, h, http.MethodGet, "/tags/"+pipeARN, nil) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags, _ := tagsResp["tags"].(map[string]any) for k, v := range tt.wantTags { diff --git a/services/pipes/targets_test.go b/services/pipes/targets_test.go index 6ad1309a74..d0c4db5f2d 100644 --- a/services/pipes/targets_test.go +++ b/services/pipes/targets_test.go @@ -9,7 +9,7 @@ package pipes_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -38,7 +39,7 @@ func b2Do(t *testing.T, h *pipes.Handler, method, path string, body any) *httpte var b []byte if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } e := echo.New() @@ -58,7 +59,7 @@ func b2Create(t *testing.T, h *pipes.Handler, name string, body map[string]any) rec := b2Do(t, h, http.MethodPost, "/v1/pipes/"+name, body) require.Equal(t, http.StatusOK, rec.Code, "create pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -68,7 +69,7 @@ func b2Describe(t *testing.T, h *pipes.Handler, name string) map[string]any { rec := b2Do(t, h, http.MethodGet, "/v1/pipes/"+name, nil) require.Equal(t, http.StatusOK, rec.Code, "describe pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -78,7 +79,7 @@ func b2Update(t *testing.T, h *pipes.Handler, name string, body map[string]any) rec := b2Do(t, h, http.MethodPut, "/v1/pipes/"+name, body) require.Equal(t, http.StatusOK, rec.Code, "update pipe %q: %s", name, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/pipes/wire_key_case_restore_test.go b/services/pipes/wire_key_case_restore_test.go index b6f47fc77f..83969a1403 100644 --- a/services/pipes/wire_key_case_restore_test.go +++ b/services/pipes/wire_key_case_restore_test.go @@ -1,12 +1,13 @@ package pipes_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -41,7 +42,7 @@ func TestWireKeyCase_OldSnapshotKeysStillDecode(t *testing.T) { var got pipes.ECSTaskTargetParameters - require.NoError(t, json.Unmarshal([]byte(tt.raw), &got)) + require.NoError(t, json.Unmarshal([]byte(tt.raw), &got, jsonx.V1())) assert.Equal(t, []string{"s-1"}, got.NetworkConfiguration.AwsvpcConfiguration.Subnets) assert.Equal(t, "FARGATE", got.CapacityProviderStrategy[0].CapacityProvider) assert.Equal(t, 2, got.CapacityProviderStrategy[0].Weight) diff --git a/services/pipes/wire_time.go b/services/pipes/wire_time.go index 1940351891..d60d35497c 100644 --- a/services/pipes/wire_time.go +++ b/services/pipes/wire_time.go @@ -1,8 +1,10 @@ package pipes import ( - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // epochSecondsPtr converts *time.Time into the epoch-seconds-with-millisecond- @@ -44,7 +46,7 @@ func (k KinesisStreamSourceParameters) MarshalJSON() ([]byte, error) { }{ StartingPositionTimestamp: epochSecondsPtr(k.StartingPositionTimestamp), alias: alias(k), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of MarshalJSON. Without it, a real client's @@ -59,7 +61,7 @@ func (k *KinesisStreamSourceParameters) UnmarshalJSON(data []byte) error { *alias }{alias: (*alias)(k)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/pipes/wire_time_test.go b/services/pipes/wire_time_test.go index 2d7cbe608e..33d9914184 100644 --- a/services/pipes/wire_time_test.go +++ b/services/pipes/wire_time_test.go @@ -1,7 +1,7 @@ package pipes_test import ( - "encoding/json" + "encoding/json/v2" "net/http/httptest" "testing" "time" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/pipes" ) @@ -60,7 +61,7 @@ func TestKinesisStreamSourceParameters_UnmarshalJSON_TimeIsEpochSeconds(t *testi t.Parallel() var params pipes.KinesisStreamSourceParameters - err := json.Unmarshal([]byte(tt.body), ¶ms) + err := json.Unmarshal([]byte(tt.body), ¶ms, jsonx.V1()) if tt.wantErr { require.Error(t, err) diff --git a/services/polly/handler.go b/services/polly/handler.go index 89e09fc4cb..c4c7fa2672 100644 --- a/services/polly/handler.go +++ b/services/polly/handler.go @@ -2,7 +2,7 @@ package polly import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -318,7 +319,7 @@ func (h *Handler) startSpeechSynthesisStream(c *echo.Context) error { return encodeErr } - closed, err := json.Marshal(map[string]int{"RequestCharacters": result.RequestCharacters}) + closed, err := json.Marshal(map[string]int{"RequestCharacters": result.RequestCharacters}, jsonx.V1()) if err != nil { return err } @@ -383,7 +384,7 @@ func decodeStreamText(body io.Reader) (string, string, error) { } var event streamTextEvent - if jsonErr := json.Unmarshal(message.Payload, &event); jsonErr != nil { + if jsonErr := json.Unmarshal(message.Payload, &event, jsonx.V1()); jsonErr != nil { return "", "", jsonErr } texts = append(texts, event.Text) @@ -613,7 +614,7 @@ func decodeRequest(c *echo.Context, value any) error { if err != nil { return fmt.Errorf("%w: failed to read body", ErrValidation) } - if jsonErr := json.Unmarshal(body, value); jsonErr != nil { + if jsonErr := json.Unmarshal(body, value, jsonx.V1()); jsonErr != nil { return fmt.Errorf("%w: invalid JSON: %w", ErrValidation, jsonErr) } diff --git a/services/polly/handler_test.go b/services/polly/handler_test.go index ed29c5f91a..65775fb85c 100644 --- a/services/polly/handler_test.go +++ b/services/polly/handler_test.go @@ -2,7 +2,7 @@ package polly_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/polly" ) @@ -30,7 +31,7 @@ func request( var payload []byte if body != nil { var err error - payload, err = json.Marshal(body) + payload, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -47,7 +48,7 @@ func responseMap(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/polly/multi_region_test.go b/services/polly/multi_region_test.go index 9a1c0d2748..31f87290ac 100644 --- a/services/polly/multi_region_test.go +++ b/services/polly/multi_region_test.go @@ -2,7 +2,8 @@ package polly_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/polly" ) @@ -174,8 +176,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/polly/persistence.go b/services/polly/persistence.go index 4cb7d5c3da..2ebc758956 100644 --- a/services/polly/persistence.go +++ b/services/polly/persistence.go @@ -2,7 +2,7 @@ package polly import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -36,10 +36,10 @@ const pollySnapshotVersion = 2 // The built-in voice catalogue (InMemoryBackend.voices) is static read-only // data, not a mutable resource collection, and is intentionally excluded. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. It implements diff --git a/services/polly/speech_test.go b/services/polly/speech_test.go index 5e16aa19e0..28ddb2f189 100644 --- a/services/polly/speech_test.go +++ b/services/polly/speech_test.go @@ -2,7 +2,7 @@ package polly_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/polly" ) @@ -190,7 +191,7 @@ func TestStartSpeechSynthesisStreamValidationExceptionTaxonomy(t *testing.T) { // "ValidationException: EngineNotSupportedException: voice ..."), so // assert on the parsed field rather than searching the raw body. var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ValidationException", out["__type"]) }) } @@ -240,7 +241,7 @@ func TestStartSpeechSynthesisStreamRequiresGenerativeEngine(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ValidationException", out["__type"]) }) } @@ -648,7 +649,7 @@ func TestSpeechMarksVisemeVariety(t *testing.T) { } var m map[string]any - require.NoError(t, json.Unmarshal(line, &m)) + require.NoError(t, json.Unmarshal(line, &m, jsonx.V1())) if m["type"] == "viseme" { marks = append(marks, m) @@ -780,7 +781,7 @@ func TestSpeechMarkCounts(t *testing.T) { continue } var ev map[string]any - require.NoError(t, json.Unmarshal([]byte(line), &ev), "invalid JSON line: %s", line) + require.NoError(t, json.Unmarshal([]byte(line), &ev, jsonx.V1()), "invalid JSON line: %s", line) typ, _ := ev["type"].(string) counts[typ]++ } @@ -836,7 +837,7 @@ func TestSpeechMarkTimeOrder(t *testing.T) { continue } var ev map[string]any - require.NoError(t, json.Unmarshal([]byte(line), &ev)) + require.NoError(t, json.Unmarshal([]byte(line), &ev, jsonx.V1())) timeVal, _ := ev["time"].(float64) assert.GreaterOrEqual(t, timeVal, prevTime, "marks must be non-decreasing by time") prevTime = timeVal diff --git a/services/polly/throttle_test.go b/services/polly/throttle_test.go index f4566ac17d..be817c5712 100644 --- a/services/polly/throttle_test.go +++ b/services/polly/throttle_test.go @@ -2,7 +2,7 @@ package polly_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/polly" ) @@ -162,7 +163,7 @@ func TestStartSpeechSynthesisStream_ThrottlingHTTPWireShape(t *testing.T) { require.Equal(t, http.StatusBadRequest, second.Code) var out map[string]string - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ThrottlingException", out["__type"]) } @@ -189,6 +190,6 @@ func TestStartSpeechSynthesisStream_ServiceQuotaHTTPWireShape(t *testing.T) { require.Equal(t, http.StatusPaymentRequired, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ServiceQuotaExceededException", out["__type"]) } diff --git a/services/pricing/catalog.go b/services/pricing/catalog.go index f4f90a6e0e..2e6380a2f6 100644 --- a/services/pricing/catalog.go +++ b/services/pricing/catalog.go @@ -3,13 +3,15 @@ package pricing import ( "crypto/sha256" "encoding/base32" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" "sort" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -129,7 +131,7 @@ func render(s *spec) *entry { Product: productJSON{Attributes: attrs, ProductFamily: s.family, SKU: sku}, ServiceCode: s.service, Terms: terms, Version: catalogVersion, PublicationDate: publicationDate, } - raw, _ := json.Marshal(item) + raw, _ := json.Marshal(item, jsonx.V1()) return &entry{item: item, json: string(raw), region: s.region.code, service: s.service} } diff --git a/services/pricing/handler.go b/services/pricing/handler.go index 0ad13cad0a..309551dd0c 100644 --- a/services/pricing/handler.go +++ b/services/pricing/handler.go @@ -2,7 +2,7 @@ package pricing import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -33,7 +34,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrInvalidParameter, "malformed request body: %v", err) } } diff --git a/services/pricing/pricelists.go b/services/pricing/pricelists.go index f176e1e331..d1fb720ec5 100644 --- a/services/pricing/pricelists.go +++ b/services/pricing/pricelists.go @@ -1,11 +1,13 @@ package pricing import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -213,7 +215,7 @@ func RenderFile(code, ver, region, kind string) ([]byte, string, bool) { } } - raw, _ := json.Marshal(f) + raw, _ := json.Marshal(f, jsonx.V1()) return raw, "application/json", true } diff --git a/services/pricing/pricing_more_test.go b/services/pricing/pricing_more_test.go index bc174a683e..0ca7c46d52 100644 --- a/services/pricing/pricing_more_test.go +++ b/services/pricing/pricing_more_test.go @@ -1,7 +1,7 @@ package pricing_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/pricing" ) @@ -77,7 +78,7 @@ func TestReservedTermMatrix(t *testing.T) { } `json:"terms"` } - require.NoError(t, json.Unmarshal([]byte(out.PriceList[0]), &item)) + require.NoError(t, json.Unmarshal([]byte(out.PriceList[0]), &item, jsonx.V1())) require.Len(t, item.Terms.Reserved, 12) seen := map[string]bool{} @@ -168,7 +169,7 @@ func TestSavingsPlansPriceLists(t *testing.T) { } `json:"products"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &file)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &file, jsonx.V1())) require.Len(t, file.Terms.SavingsPlan, 6) assert.Len(t, file.Products, 6) require.NotEmpty(t, file.Terms.SavingsPlan[0].Rates) diff --git a/services/pricing/pricing_test.go b/services/pricing/pricing_test.go index 55e19f5b40..d3732cf002 100644 --- a/services/pricing/pricing_test.go +++ b/services/pricing/pricing_test.go @@ -1,7 +1,7 @@ package pricing_test import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/services/pricing" ) @@ -206,7 +207,7 @@ func TestProductShape(t *testing.T) { ServiceCode string `json:"serviceCode"` } - require.NoError(t, json.Unmarshal([]byte(out.PriceList[0]), &item)) + require.NoError(t, json.Unmarshal([]byte(out.PriceList[0]), &item, jsonx.V1())) assert.Equal(t, "AmazonEC2", item.ServiceCode) assert.Equal(t, "Compute Instance", item.Product.ProductFamily) assert.Equal(t, "US East (N. Virginia)", item.Product.Attributes["location"]) @@ -305,7 +306,7 @@ func TestPriceListsAndFile(t *testing.T) { OfferCode string `json:"offerCode"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &file)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &file, jsonx.V1())) assert.Equal(t, "AmazonS3", file.OfferCode) assert.NotEmpty(t, file.Products) } else { diff --git a/services/pricing/savingsplans.go b/services/pricing/savingsplans.go index 577b69e358..0db1c1188a 100644 --- a/services/pricing/savingsplans.go +++ b/services/pricing/savingsplans.go @@ -3,11 +3,13 @@ package pricing import ( "crypto/sha256" "encoding/base32" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -152,7 +154,7 @@ func renderSavingsPlans(region string) []byte { }) } - raw, _ := json.Marshal(f) + raw, _ := json.Marshal(f, jsonx.V1()) return raw } diff --git a/services/quicksight/dataset_security.go b/services/quicksight/dataset_security.go index 94b3487486..9388e95989 100644 --- a/services/quicksight/dataset_security.go +++ b/services/quicksight/dataset_security.go @@ -1,8 +1,10 @@ package quicksight import ( - "encoding/json" + "encoding/json/v2" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const dataSetUseAsRLSRules = "RLS_RULES" @@ -32,13 +34,13 @@ func validateDataSetSecurity(s DataSetSecurity, allowUseAs bool) error { } func cloneJSONValue[T any](v T) T { - raw, err := json.Marshal(v) + raw, err := json.Marshal(v, jsonx.V1()) if err != nil { return v } var out T - if json.Unmarshal(raw, &out) != nil { + if json.Unmarshal(raw, &out, jsonx.V1()) != nil { return v } diff --git a/services/quicksight/error_envelope_test.go b/services/quicksight/error_envelope_test.go index ba7d52131a..2bafd09075 100644 --- a/services/quicksight/error_envelope_test.go +++ b/services/quicksight/error_envelope_test.go @@ -1,7 +1,7 @@ package quicksight_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/quicksight" @@ -92,7 +93,7 @@ func TestErrorEnvelope_DescribeDataSetNotFoundDecodesToTypedError(t *testing.T) require.NoError(t, err) var envelope map[string]any - require.NoError(t, json.Unmarshal(raw, &envelope)) + require.NoError(t, json.Unmarshal(raw, &envelope, jsonx.V1())) require.Equal(t, "ResourceNotFoundException", envelope["Code"], "raw body must carry the Code key restjson.GetErrorInfo checks first: %s", raw) diff --git a/services/quicksight/handler_paths.go b/services/quicksight/handler_paths.go index 7b1404e484..47bcf7a7aa 100644 --- a/services/quicksight/handler_paths.go +++ b/services/quicksight/handler_paths.go @@ -1,7 +1,8 @@ package quicksight import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "io" "net/http" @@ -14,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -971,7 +973,7 @@ func classifyRestorePaths(method string, segs []string, n int) (string, string) func readBody(c *echo.Context) (map[string]any, error) { var body map[string]any - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil { return nil, err } @@ -1090,7 +1092,7 @@ func writeJSON(c *echo.Context, code int, body any) error { c.Response().Header().Set("Content-Type", "application/json") c.Response().WriteHeader(code) - return json.NewEncoder(c.Response()).Encode(body) + return json.MarshalEncode(jsontext.NewEncoder(c.Response(), jsonx.V1()), body) } func writeError(c *echo.Context, code int, errCode, msg string) error { diff --git a/services/quicksight/handler_test.go b/services/quicksight/handler_test.go index 9a643a2a90..b7a8328d6e 100644 --- a/services/quicksight/handler_test.go +++ b/services/quicksight/handler_test.go @@ -2,7 +2,7 @@ package quicksight_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/quicksight" ) @@ -187,7 +188,7 @@ func doRequest(t *testing.T, h *quicksight.Handler, method, path string, body an var bodyBytes []byte if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -209,7 +210,7 @@ func parseBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/quicksight/models.go b/services/quicksight/models.go index b76543114f..8f6e3c3b27 100644 --- a/services/quicksight/models.go +++ b/services/quicksight/models.go @@ -1,7 +1,7 @@ package quicksight import ( - "encoding/json" + "encoding/json/jsontext" "regexp" "time" ) @@ -288,7 +288,7 @@ func (a *storedAnalysis) toAnalysis() *Analysis { // field of its own (see store_setup.go's doc comment for the full list and // rationale) -- these round-trip directly, same as before conversion. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` GroupMembers map[string]bool `json:"groupMembers"` Tags map[string]map[string]string `json:"tags"` diff --git a/services/quicksight/multi_region_test.go b/services/quicksight/multi_region_test.go index a432ebd472..730bedf430 100644 --- a/services/quicksight/multi_region_test.go +++ b/services/quicksight/multi_region_test.go @@ -2,7 +2,8 @@ package quicksight_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/quicksight" ) @@ -176,8 +178,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/ram/errsweep_wire_shape_test.go b/services/ram/errsweep_wire_shape_test.go index 6a929860e5..1599357a91 100644 --- a/services/ram/errsweep_wire_shape_test.go +++ b/services/ram/errsweep_wire_shape_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/ram" @@ -61,7 +62,7 @@ func TestHandler_MalformedBodyCarriesTypedErrorCode(t *testing.T) { require.NoError(t, err) var decoded map[string]any - require.NoError(t, json.Unmarshal(raw, &decoded)) + require.NoError(t, json.Unmarshal(raw, &decoded, jsonx.V1())) require.Equal(t, "InvalidParameterException", decoded["__type"], "raw response body must carry __type; got: %s", raw) require.NotEmpty(t, decoded["message"]) diff --git a/services/ram/handler.go b/services/ram/handler.go index 59688b40cf..3e5c5eff49 100644 --- a/services/ram/handler.go +++ b/services/ram/handler.go @@ -3,7 +3,7 @@ package ram import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/collections" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -669,7 +670,7 @@ func writeInternalServerError(c *echo.Context) error { payload, err := json.Marshal(map[string]string{ keyTypeField: "ServerInternalException", keyMessageField: "internal server error", - }) + }, jsonx.V1()) if err != nil { return err } @@ -724,7 +725,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { if errors.Is(err, idempotency.ErrParamsMismatch) { payload, _ := json.Marshal(map[string]string{ keyTypeField: "IdempotentParameterMismatchException", keyMessageField: err.Error(), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) } @@ -732,19 +733,15 @@ func (h *Handler) handleError(c *echo.Context, err error) error { for _, e := range errCodeLookup { if errors.Is(err, e.err) { payload, _ := json.Marshal( - map[string]string{keyTypeField: e.code, keyMessageField: errorMessage(err, e.code)}, + map[string]string{keyTypeField: e.code, keyMessageField: errorMessage(err, e.code)}, jsonx.V1(), ) return c.JSONBlob(http.StatusBadRequest, payload) } } - - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): // These branches used to omit keyTypeField entirely, so // restjson.GetErrorInfo (aws-sdk-go-v2 aws/protocol/restjson/ // decoder_util.go:15) found no code in the header (unset) or the diff --git a/services/ram/handler_permission_versions.go b/services/ram/handler_permission_versions.go index e944138c6a..8ec3b189bb 100644 --- a/services/ram/handler_permission_versions.go +++ b/services/ram/handler_permission_versions.go @@ -2,7 +2,7 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createPermissionVersionRequest struct { @@ -29,7 +30,7 @@ type createPermissionVersionResponse struct { func (h *Handler) handleCreatePermissionVersion(_ context.Context, body []byte) ([]byte, error) { var req createPermissionVersionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -72,7 +73,7 @@ func (h *Handler) handleCreatePermissionVersion(_ context.Context, body []byte) pv := p.Versions[version] return json.Marshal( - createPermissionVersionResponse{Permission: toPermissionDetailObject(p, pv)}, + createPermissionVersionResponse{Permission: toPermissionDetailObject(p, pv)}, jsonx.V1(), ) } @@ -113,7 +114,7 @@ func (h *Handler) handleDeletePermissionVersion( } return json.Marshal( - deletePermissionVersionResponse{ReturnValue: true, PermissionStatus: "DELETING"}, + deletePermissionVersionResponse{ReturnValue: true, PermissionStatus: "DELETING"}, jsonx.V1(), ) } @@ -146,7 +147,7 @@ func toPermissionVersionSummaryObject(p *Permission, pv *PermissionVersion) perm func (h *Handler) handleListPermissionVersions(_ context.Context, body []byte) ([]byte, error) { var req listPermissionVersionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -175,7 +176,7 @@ func (h *Handler) handleListPermissionVersions(_ context.Context, body []byte) ( return nil, pErr2 } - return json.Marshal(listPermissionVersionsResponse{NextToken: nextToken, Permissions: paged}) + return json.Marshal(listPermissionVersionsResponse{NextToken: nextToken, Permissions: paged}, jsonx.V1()) } type setDefaultPermissionVersionRequest struct { @@ -192,7 +193,7 @@ func (h *Handler) handleSetDefaultPermissionVersion( body []byte, ) ([]byte, error) { var req setDefaultPermissionVersionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -208,5 +209,5 @@ func (h *Handler) handleSetDefaultPermissionVersion( return nil, err } - return json.Marshal(setDefaultPermissionVersionResponse{ReturnValue: true}) + return json.Marshal(setDefaultPermissionVersionResponse{ReturnValue: true}, jsonx.V1()) } diff --git a/services/ram/handler_permission_versions_test.go b/services/ram/handler_permission_versions_test.go index 19147a50b4..ef1213231b 100644 --- a/services/ram/handler_permission_versions_test.go +++ b/services/ram/handler_permission_versions_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -44,7 +45,7 @@ func TestListPermissionVersions_BuiltIn(t *testing.T) { Version string `json:"version"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Permissions, 1) assert.Equal(t, "1", resp.Permissions[0].Version) }) @@ -358,7 +359,7 @@ func TestListPermissionVersions_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -367,7 +368,7 @@ func TestListPermissionVersions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) totalSeen += len(resp.Permissions) nextToken = resp.NextToken diff --git a/services/ram/handler_permissions.go b/services/ram/handler_permissions.go index 6f29b8afbc..0e3f9ebd33 100644 --- a/services/ram/handler_permissions.go +++ b/services/ram/handler_permissions.go @@ -2,13 +2,14 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // permissionStatusAttachable is the steady-state PermissionStatus for every @@ -134,7 +135,7 @@ type createPermissionResponse struct { func (h *Handler) handleCreatePermission(_ context.Context, body []byte) ([]byte, error) { var req createPermissionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -169,7 +170,7 @@ func (h *Handler) handleCreatePermission(_ context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(createPermissionResponse{Permission: toPermissionSummaryObject(p)}) + return json.Marshal(createPermissionResponse{Permission: toPermissionSummaryObject(p)}, jsonx.V1()) } type deletePermissionResponse struct { @@ -187,7 +188,7 @@ func (h *Handler) handleDeletePermission(_ context.Context, c *echo.Context) ([] return nil, err } - return json.Marshal(deletePermissionResponse{ReturnValue: true, PermissionStatus: "DELETING"}) + return json.Marshal(deletePermissionResponse{ReturnValue: true, PermissionStatus: "DELETING"}, jsonx.V1()) } type getPermissionRequest struct { @@ -201,7 +202,7 @@ type getPermissionResponse struct { func (h *Handler) handleGetPermission(_ context.Context, body []byte) ([]byte, error) { var req getPermissionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -214,7 +215,7 @@ func (h *Handler) handleGetPermission(_ context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(getPermissionResponse{Permission: toPermissionDetailObject(p, pv)}) + return json.Marshal(getPermissionResponse{Permission: toPermissionDetailObject(p, pv)}, jsonx.V1()) } type listPermissionsRequest struct { @@ -231,7 +232,7 @@ type listPermissionsResponse struct { func (h *Handler) handleListPermissions(_ context.Context, body []byte) ([]byte, error) { var req listPermissionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -252,7 +253,7 @@ func (h *Handler) handleListPermissions(_ context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(listPermissionsResponse{NextToken: nextToken, Permissions: page}) + return json.Marshal(listPermissionsResponse{NextToken: nextToken, Permissions: page}, jsonx.V1()) } type promotePermissionCreatedFromPolicyRequest struct { @@ -269,7 +270,7 @@ func (h *Handler) handlePromotePermissionCreatedFromPolicy( body []byte, ) ([]byte, error) { var req promotePermissionCreatedFromPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -283,6 +284,6 @@ func (h *Handler) handlePromotePermissionCreatedFromPolicy( } return json.Marshal( - promotePermissionCreatedFromPolicyResponse{Permission: toPermissionSummaryObject(p)}, + promotePermissionCreatedFromPolicyResponse{Permission: toPermissionSummaryObject(p)}, jsonx.V1(), ) } diff --git a/services/ram/handler_permissions_test.go b/services/ram/handler_permissions_test.go index b5dee68c5d..82106b869e 100644 --- a/services/ram/handler_permissions_test.go +++ b/services/ram/handler_permissions_test.go @@ -1,7 +1,8 @@ package ram_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -45,7 +47,7 @@ func TestBuiltInPermissions_Present(t *testing.T) { PermissionType string `json:"permissionType"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.Permissions, "built-in permission for %s should exist", tt.resourceType) assert.Equal(t, tt.resourceType, resp.Permissions[0].ResourceType) assert.Equal(t, "AWS_MANAGED", resp.Permissions[0].PermissionType) @@ -61,9 +63,9 @@ func TestBuiltInPermissions_Count(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Permissions, ram.BuiltInPermissionCount) } @@ -106,9 +108,9 @@ func TestListPermissions_TypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Permissions, tt.wantCount) }) } @@ -174,9 +176,9 @@ func TestListPermissions_TypeFilter_WithCustom(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Permissions, tt.wantCount) }) } @@ -229,7 +231,7 @@ func TestBuiltInPermission_PermissionType(t *testing.T) { IsResourceTypeDefault bool `json:"isResourceTypeDefault"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantPermissionType, resp.Permission.PermissionType) assert.Equal(t, tt.wantIsDefault, resp.Permission.IsResourceTypeDefault) }) @@ -289,7 +291,7 @@ func TestDeleteCustomPermission_Allowed(t *testing.T) { Arn string `json:"arn"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) path := fmt.Sprintf("/deletepermission?permissionArn=%s", createResp.Permission.Arn) rec := doRAMRawRequest(t, h, http.MethodDelete, path, nil) @@ -338,12 +340,12 @@ func TestPermissionResponses_NoResourceRegionScopeField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Permission json.RawMessage `json:"permission"` + Permission jsontext.Value `json:"permission"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) - var permFields map[string]json.RawMessage - require.NoError(t, json.Unmarshal(resp.Permission, &permFields)) + var permFields map[string]jsontext.Value + require.NoError(t, json.Unmarshal(resp.Permission, &permFields, jsonx.V1())) assert.NotContains(t, permFields, "resourceRegionScope") }) } @@ -379,7 +381,7 @@ func TestIsResourceTypeDefault(t *testing.T) { IsResourceTypeDefault bool `json:"isResourceTypeDefault"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantDefault, resp.Permission.IsResourceTypeDefault) }) } @@ -402,7 +404,7 @@ func TestCustomerPermission_NotResourceTypeDefault(t *testing.T) { IsResourceTypeDefault bool `json:"isResourceTypeDefault"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) assert.False(t, createResp.Permission.IsResourceTypeDefault) } @@ -446,7 +448,7 @@ func TestListPermissions_ResourceTypeFilter(t *testing.T) { ResourceType string `json:"resourceType"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantMinCount == 0 { assert.Empty(t, resp.Permissions) @@ -480,7 +482,7 @@ func TestListPermissions_ResourceTypeFilter_CaseInsensitive(t *testing.T) { ResourceType string `json:"resourceType"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty( t, resp.Permissions, "resourceType filter must match case-insensitively, per the doc's own example", @@ -527,12 +529,12 @@ func TestGetPermission_BuiltIn_HasPolicy(t *testing.T) { Permission string `json:"permission"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.Permission.Permission, "built-in permission should have non-empty policy") // Policy should be valid JSON. var policy map[string]any - assert.NoError(t, json.Unmarshal([]byte(resp.Permission.Permission), &policy)) + assert.NoError(t, json.Unmarshal([]byte(resp.Permission.Permission), &policy, jsonx.V1())) }) } } @@ -558,7 +560,7 @@ func TestListPermissions_SummaryHasType(t *testing.T) { PermissionType string `json:"permissionType"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, p := range resp.Permissions { assert.NotEmpty(t, p.PermissionType, "permission %q should have PermissionType set", p.Name) @@ -669,7 +671,7 @@ func TestPermissionNotFound_UsesUnknownResourceException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "UnknownResourceException", resp["__type"]) } @@ -949,7 +951,7 @@ func TestListPermissions_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -958,7 +960,7 @@ func TestListPermissions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.Permissions) @@ -1069,7 +1071,7 @@ func TestPromotePermissionCreatedFromPolicy_Table(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) perm := resp["permission"].(map[string]any) assert.Equal(t, tc.wantType, perm["permissionType"]) assert.Equal(t, tc.wantName, perm["name"]) @@ -1087,7 +1089,7 @@ func TestListPermissions_Smoke(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) perms, ok := listResp["permissions"].([]any) require.True(t, ok) assert.NotEmpty(t, perms, "ListPermissions must return the built-in AWS-managed permissions") @@ -1099,7 +1101,7 @@ func TestListPermissions_Smoke(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var versionsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &versionsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &versionsResp, jsonx.V1())) versions, ok := versionsResp["permissions"].([]any) require.True(t, ok) require.NotEmpty(t, versions, "AWSRAMDefaultPermissionEC2Subnet must have at least one version") diff --git a/services/ram/handler_principals.go b/services/ram/handler_principals.go index e554023d3d..b4f413b08b 100644 --- a/services/ram/handler_principals.go +++ b/services/ram/handler_principals.go @@ -2,9 +2,11 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type principalObject struct { @@ -42,7 +44,7 @@ type listPrincipalsResponse struct { func (h *Handler) handleListPrincipals(_ context.Context, body []byte) ([]byte, error) { var req listPrincipalsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -81,5 +83,5 @@ func (h *Handler) handleListPrincipals(_ context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(listPrincipalsResponse{NextToken: nextToken, Principals: page}) + return json.Marshal(listPrincipalsResponse{NextToken: nextToken, Principals: page}, jsonx.V1()) } diff --git a/services/ram/handler_principals_test.go b/services/ram/handler_principals_test.go index 81a7e21b78..8678f399c5 100644 --- a/services/ram/handler_principals_test.go +++ b/services/ram/handler_principals_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -31,7 +32,7 @@ func TestListPrincipals_Pagination(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) shareARN := createResp.ResourceShare.ResourceShareArn require.NotEmpty(t, shareARN) @@ -104,7 +105,7 @@ func TestListPrincipals_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -113,7 +114,7 @@ func TestListPrincipals_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.Principals) @@ -151,7 +152,7 @@ func TestListPrincipals_ResourceShareArnsFilter(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(createA.Body.Bytes(), &respA)) + require.NoError(t, json.Unmarshal(createA.Body.Bytes(), &respA, jsonx.V1())) shareArnA := respA.ResourceShare.ResourceShareArn require.NotEmpty(t, shareArnA) @@ -174,7 +175,7 @@ func TestListPrincipals_ResourceShareArnsFilter(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"principals"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len( t, resp.Principals, 1, "resourceShareArns must scope results to the requested share, not return every share", @@ -229,7 +230,7 @@ func TestListPrincipals_ResourceOwnerFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) principals := resp["principals"].([]any) assert.Len(t, principals, tc.wantCount) }) diff --git a/services/ram/handler_resource_shares.go b/services/ram/handler_resource_shares.go index 9e53ccad40..36d64430a3 100644 --- a/services/ram/handler_resource_shares.go +++ b/services/ram/handler_resource_shares.go @@ -2,13 +2,14 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // resourceShareObject is the JSON representation of a ResourceShare. @@ -76,7 +77,7 @@ type createResourceShareResponse struct { func (h *Handler) handleCreateResourceShare(_ context.Context, body []byte) ([]byte, error) { var req createResourceShareRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -109,7 +110,7 @@ func (h *Handler) handleCreateResourceShare(_ context.Context, body []byte) ([]b return json.Marshal(createResourceShareResponse{ ResourceShare: toResourceShareObject(rs), - }) + }, jsonx.V1()) } func (h *Handler) createResourceShare(req createResourceShareRequest) (*ResourceShare, error) { @@ -173,7 +174,7 @@ type getResourceSharesResponse struct { func (h *Handler) handleGetResourceShares(_ context.Context, body []byte) ([]byte, error) { var req getResourceSharesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +202,7 @@ func (h *Handler) handleGetResourceShares(_ context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(getResourceSharesResponse{NextToken: nextToken, ResourceShares: page}) + return json.Marshal(getResourceSharesResponse{NextToken: nextToken, ResourceShares: page}, jsonx.V1()) } // getResourceSharesByARN looks up each requested ARN individually, applying @@ -322,7 +323,7 @@ type updateResourceShareResponse struct { func (h *Handler) handleUpdateResourceShare(_ context.Context, body []byte) ([]byte, error) { var req updateResourceShareRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -349,7 +350,7 @@ func (h *Handler) handleUpdateResourceShare(_ context.Context, body []byte) ([]b return json.Marshal(updateResourceShareResponse{ ResourceShare: toResourceShareObject(rs), - }) + }, jsonx.V1()) } type deleteResourceShareResponse struct { @@ -373,7 +374,7 @@ func (h *Handler) handleDeleteResourceShare(_ context.Context, c *echo.Context) return nil, err } - return json.Marshal(deleteResourceShareResponse{ReturnValue: true}) + return json.Marshal(deleteResourceShareResponse{ReturnValue: true}, jsonx.V1()) } type enableSharingWithAwsOrganizationResponse struct { @@ -385,7 +386,7 @@ func (h *Handler) handleEnableSharingWithAwsOrganization() ([]byte, error) { return nil, err } - return json.Marshal(enableSharingWithAwsOrganizationResponse{ReturnValue: true}) + return json.Marshal(enableSharingWithAwsOrganizationResponse{ReturnValue: true}, jsonx.V1()) } type promoteResourceShareCreatedFromPolicyResponse struct { @@ -415,5 +416,5 @@ func (h *Handler) handlePromoteResourceShareCreatedFromPolicy( return nil, err } - return json.Marshal(promoteResourceShareCreatedFromPolicyResponse{ReturnValue: true}) + return json.Marshal(promoteResourceShareCreatedFromPolicyResponse{ReturnValue: true}, jsonx.V1()) } diff --git a/services/ram/handler_resource_shares_test.go b/services/ram/handler_resource_shares_test.go index 04648796c5..5602dc395e 100644 --- a/services/ram/handler_resource_shares_test.go +++ b/services/ram/handler_resource_shares_test.go @@ -1,7 +1,8 @@ package ram_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -387,7 +389,7 @@ func TestCreateResourceShare_PermissionArns(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) shareARN := createResp.ResourceShare.ResourceShareArn // Verify permissions were associated. @@ -397,9 +399,9 @@ func TestCreateResourceShare_PermissionArns(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Permissions, tt.wantPermCount) }) } @@ -455,9 +457,9 @@ func TestGetResourceShares_OtherAccounts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - ResourceShares []json.RawMessage `json:"resourceShares"` + ResourceShares []jsontext.Value `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceShares, tt.wantCount) }) } @@ -499,7 +501,7 @@ func TestAllowExternalPrincipals_Default(t *testing.T) { AllowExternalPrincipals bool `json:"allowExternalPrincipals"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantExternal, resp.ResourceShare.AllowExternalPrincipals) }) } @@ -576,7 +578,7 @@ func TestCreateResourceShare_WithPrincipalsAndResources(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp, jsonx.V1())) shareARN := shareResp.ResourceShare.ResourceShareArn // Check principals. @@ -587,9 +589,9 @@ func TestCreateResourceShare_WithPrincipalsAndResources(t *testing.T) { require.Equal(t, http.StatusOK, principalRec.Code) var principalResp struct { - Principals []json.RawMessage `json:"principals"` + Principals []jsontext.Value `json:"principals"` } - require.NoError(t, json.Unmarshal(principalRec.Body.Bytes(), &principalResp)) + require.NoError(t, json.Unmarshal(principalRec.Body.Bytes(), &principalResp, jsonx.V1())) assert.Len(t, principalResp.Principals, tt.wantPrincipals) // Check resources. @@ -600,9 +602,9 @@ func TestCreateResourceShare_WithPrincipalsAndResources(t *testing.T) { require.Equal(t, http.StatusOK, resourceRec.Code) var resourceResp struct { - Resources []json.RawMessage `json:"resources"` + Resources []jsontext.Value `json:"resources"` } - require.NoError(t, json.Unmarshal(resourceRec.Body.Bytes(), &resourceResp)) + require.NoError(t, json.Unmarshal(resourceRec.Body.Bytes(), &resourceResp, jsonx.V1())) assert.Len(t, resourceResp.Resources, tt.wantResources) }) } @@ -654,7 +656,7 @@ func TestCreateResourceShare_AutoAssociatesDefaultPermission(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp, jsonx.V1())) listRec := doRAMRequest(t, h, "/listresourcesharepermissions", map[string]any{ "resourceShareArn": shareResp.ResourceShare.ResourceShareArn, @@ -666,7 +668,7 @@ func TestCreateResourceShare_AutoAssociatesDefaultPermission(t *testing.T) { Arn string `json:"arn"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Permissions, 1) assert.Equal(t, "arn:aws:ram::aws:permission/AWSRAMDefaultPermissionEC2Subnet", listResp.Permissions[0].Arn) }) @@ -689,7 +691,7 @@ func TestCreateResourceShare_NoAutoAttachWithoutResources(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &shareResp, jsonx.V1())) listRec := doRAMRequest(t, h, "/listresourcesharepermissions", map[string]any{ "resourceShareArn": shareResp.ResourceShare.ResourceShareArn, @@ -725,7 +727,7 @@ func TestGetResourceShares_PermissionArnFilter(t *testing.T) { Name string `json:"name"` } `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ResourceShares, 1) assert.Equal(t, "with-perm-share", resp.ResourceShares[0].Name) } @@ -761,7 +763,7 @@ func TestGetResourceShares_TagFilters(t *testing.T) { Name string `json:"name"` } `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ResourceShares, 1) assert.Equal(t, "tagged-share", resp.ResourceShares[0].Name) } @@ -811,9 +813,9 @@ func TestGetResourceShares_NameFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - ResourceShares []json.RawMessage `json:"resourceShares"` + ResourceShares []jsontext.Value `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceShares, tt.wantCount) }) } @@ -863,7 +865,7 @@ func TestResourceShare_TagsInResponse(t *testing.T) { } `json:"tags"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceShare.Tags, tt.wantTags) }) } @@ -883,7 +885,7 @@ func TestResourceShare_FeatureSetStandard(t *testing.T) { FeatureSet string `json:"featureSet"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "STANDARD", resp.ResourceShare.FeatureSet) } @@ -1046,7 +1048,7 @@ func TestGetResourceShares_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -1055,7 +1057,7 @@ func TestGetResourceShares_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.ResourceShares) @@ -1087,7 +1089,7 @@ func TestGetResourceShares_StatusFilter(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) delRec := doRAMRawRequest(t, h, http.MethodDelete, "/deleteresourceshare?resourceShareArn="+createResp.ResourceShare.ResourceShareArn, nil) @@ -1109,7 +1111,7 @@ func TestGetResourceShares_StatusFilter(t *testing.T) { Name string `json:"name"` } `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceShares, 1) assert.Equal(t, "live-share", resp.ResourceShares[0].Name) } @@ -1149,7 +1151,7 @@ func TestDeleteResourceShare_RemovesFromMap(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var createBody map[string]any - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createBody)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &createBody, jsonx.V1())) shareARN := createBody["resourceShare"].(map[string]any)["resourceShareArn"].(string) require.NotEmpty(t, shareARN) @@ -1168,7 +1170,7 @@ func TestDeleteResourceShare_RemovesFromMap(t *testing.T) { require.Equal(t, http.StatusOK, listResp.Code) var listBody map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listBody)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listBody, jsonx.V1())) shares := listBody["resourceShares"].([]any) for _, s := range shares { @@ -1200,14 +1202,14 @@ func TestPaginationTokenIsOpaque(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nextToken, _ := resp["nextToken"].(string) require.NotEmpty(t, nextToken, "expected a nextToken for multi-page result") // The token must not be a plain integer. var plainInt int - err := json.Unmarshal([]byte(nextToken), &plainInt) + err := json.Unmarshal([]byte(nextToken), &plainInt, jsonx.V1()) require.Error(t, err, "nextToken should not be a plain integer") // Following the token must yield the next page without overlap. @@ -1219,7 +1221,7 @@ func TestPaginationTokenIsOpaque(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) page1Shares := resp["resourceShares"].([]any) page2Shares := resp2["resourceShares"].([]any) diff --git a/services/ram/handler_resources.go b/services/ram/handler_resources.go index 60683074c9..10d493c367 100644 --- a/services/ram/handler_resources.go +++ b/services/ram/handler_resources.go @@ -2,11 +2,12 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -52,7 +53,7 @@ type listResourcesResponse struct { func (h *Handler) handleListResources(_ context.Context, body []byte) ([]byte, error) { var req listResourcesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -85,7 +86,7 @@ func (h *Handler) handleListResources(_ context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(listResourcesResponse{NextToken: nextToken, Resources: page}) + return json.Marshal(listResourcesResponse{NextToken: nextToken, Resources: page}, jsonx.V1()) } type listPendingInvitationResourcesRequest struct { @@ -104,7 +105,7 @@ func (h *Handler) handleListPendingInvitationResources( body []byte, ) ([]byte, error) { var req listPendingInvitationResourcesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -129,7 +130,7 @@ func (h *Handler) handleListPendingInvitationResources( } return json.Marshal( - listPendingInvitationResourcesResponse{NextToken: nextToken, Resources: page}, + listPendingInvitationResourcesResponse{NextToken: nextToken, Resources: page}, jsonx.V1(), ) } @@ -147,7 +148,7 @@ type getResourcePoliciesResponse struct { func (h *Handler) handleGetResourcePolicies(_ context.Context, body []byte) ([]byte, error) { var req getResourcePoliciesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -177,7 +178,7 @@ func (h *Handler) handleGetResourcePolicies(_ context.Context, body []byte) ([]b return nil, err } - return json.Marshal(getResourcePoliciesResponse{NextToken: nextToken, Policies: page}) + return json.Marshal(getResourcePoliciesResponse{NextToken: nextToken, Policies: page}, jsonx.V1()) } type resourceTypeObject struct { @@ -320,7 +321,7 @@ type listResourceTypesRequest struct { func (h *Handler) handleListResourceTypes(_ context.Context, body []byte) ([]byte, error) { var req listResourceTypesRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -350,7 +351,7 @@ func (h *Handler) handleListResourceTypes(_ context.Context, body []byte) ([]byt pg := page.New(types, req.NextToken, limit, len(awsShareableResourceTypes)) - return json.Marshal(listResourceTypesResponse{ResourceTypes: pg.Data, NextToken: pg.Next}) + return json.Marshal(listResourceTypesResponse{ResourceTypes: pg.Data, NextToken: pg.Next}, jsonx.V1()) } // associatedSourceObject is the JSON representation of an AssociatedSource (RAM's wire @@ -386,7 +387,7 @@ type listSourceAssociationsRequest struct { func (h *Handler) handleListSourceAssociations(_ context.Context, body []byte) ([]byte, error) { var req listSourceAssociationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -408,5 +409,5 @@ func (h *Handler) handleListSourceAssociations(_ context.Context, body []byte) ( return nil, err } - return json.Marshal(listSourceAssociationsResponse{NextToken: nextToken, SourceAssociations: page}) + return json.Marshal(listSourceAssociationsResponse{NextToken: nextToken, SourceAssociations: page}, jsonx.V1()) } diff --git a/services/ram/handler_resources_test.go b/services/ram/handler_resources_test.go index ebbcbd2619..69ee1aa8a5 100644 --- a/services/ram/handler_resources_test.go +++ b/services/ram/handler_resources_test.go @@ -1,7 +1,8 @@ package ram_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -28,7 +30,7 @@ func TestListSourceAssociations_WireShape(t *testing.T) { SourceID string `json:"sourceId"` } `json:"sourceAssociations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.SourceAssociations) assert.NotContains( t, rec.Body.String(), `"associations"`, @@ -106,7 +108,7 @@ func TestResourceRegionScope_InListResources(t *testing.T) { ResourceRegionScope string `json:"resourceRegionScope"` } `json:"resources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Resources, 1) assert.Equal(t, tt.resourceARN, resp.Resources[0].Arn) assert.Equal(t, tt.wantType, resp.Resources[0].Type) @@ -148,7 +150,7 @@ func TestListResources_ResourceShareArnsFilter(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len( t, resp.Resources, 1, "resourceShareArns must scope results to the requested share, not return every share", @@ -215,7 +217,7 @@ func TestResourceTypeDerivation(t *testing.T) { Type string `json:"type"` } `json:"resources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Resources, 1) assert.Equal(t, tt.wantType, resp.Resources[0].Type) }) @@ -291,9 +293,9 @@ func TestListPendingInvitationResources(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp struct { - Resources []json.RawMessage `json:"resources"` + Resources []jsontext.Value `json:"resources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Resources, tt.wantResources) }) } @@ -312,7 +314,7 @@ func TestListResourceTypes(t *testing.T) { ServiceName string `json:"serviceName"` } `json:"resourceTypes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.ResourceTypes) @@ -340,7 +342,7 @@ func TestListResourceTypes_ExpandedSet(t *testing.T) { ResourceRegionScope string `json:"resourceRegionScope"` } `json:"resourceTypes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Greater(t, len(resp.ResourceTypes), 4, "should list more than the original 4 types") @@ -490,7 +492,7 @@ func TestListResources_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -499,7 +501,7 @@ func TestListResources_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.Resources) @@ -580,7 +582,7 @@ func TestListPendingInvitationResources_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -589,7 +591,7 @@ func TestListPendingInvitationResources_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp.Resources) }) @@ -645,7 +647,7 @@ func TestGetResourcePolicies_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -667,7 +669,7 @@ func TestGetResourcePolicies_EmptyArns(t *testing.T) { var resp struct { Policies []string `json:"policies"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.Policies) } @@ -722,7 +724,7 @@ func TestListResources_ResourceOwnerFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources := resp["resources"].([]any) assert.Len(t, resources, tc.wantCount) }) @@ -788,7 +790,7 @@ func TestListResources_ResourceTypeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources := resp["resources"].([]any) assert.Len(t, resources, tc.wantCount) }) @@ -852,7 +854,7 @@ func TestGetResourcePolicies_OnlySharedResourcesGetPolicies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) var policies []any if p, ok := resp["policies"]; ok { diff --git a/services/ram/handler_share_associations.go b/services/ram/handler_share_associations.go index d4bdb79baa..c8f4df67bf 100644 --- a/services/ram/handler_share_associations.go +++ b/services/ram/handler_share_associations.go @@ -2,8 +2,10 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // associationObject is the JSON representation of a ResourceShareAssociation. @@ -46,7 +48,7 @@ type associateResourceShareResponse struct { func (h *Handler) handleAssociateResourceShare(_ context.Context, body []byte) ([]byte, error) { var req associateResourceShareRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -86,7 +88,7 @@ func (h *Handler) handleAssociateResourceShare(_ context.Context, body []byte) ( objs = append(objs, toAssociationObject(a)) } - return json.Marshal(associateResourceShareResponse{ResourceShareAssociations: objs}) + return json.Marshal(associateResourceShareResponse{ResourceShareAssociations: objs}, jsonx.V1()) } type disassociateResourceShareRequest struct { @@ -102,7 +104,7 @@ type disassociateResourceShareResponse struct { func (h *Handler) handleDisassociateResourceShare(_ context.Context, body []byte) ([]byte, error) { var req disassociateResourceShareRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -129,7 +131,7 @@ func (h *Handler) handleDisassociateResourceShare(_ context.Context, body []byte objs = append(objs, toAssociationObject(a)) } - return json.Marshal(disassociateResourceShareResponse{ResourceShareAssociations: objs}) + return json.Marshal(disassociateResourceShareResponse{ResourceShareAssociations: objs}, jsonx.V1()) } type getResourceShareAssociationsRequest struct { @@ -152,7 +154,7 @@ func (h *Handler) handleGetResourceShareAssociations( body []byte, ) ([]byte, error) { var req getResourceShareAssociationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -194,6 +196,6 @@ func (h *Handler) handleGetResourceShareAssociations( } return json.Marshal( - getResourceShareAssociationsResponse{NextToken: nextToken, ResourceShareAssociations: page}, + getResourceShareAssociationsResponse{NextToken: nextToken, ResourceShareAssociations: page}, jsonx.V1(), ) } diff --git a/services/ram/handler_share_associations_test.go b/services/ram/handler_share_associations_test.go index a5b0568d58..e078029fa5 100644 --- a/services/ram/handler_share_associations_test.go +++ b/services/ram/handler_share_associations_test.go @@ -1,13 +1,15 @@ package ram_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -271,9 +273,9 @@ func TestGetResourceShareAssociations_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - ResourceShareAssociations []json.RawMessage `json:"resourceShareAssociations"` + ResourceShareAssociations []jsontext.Value `json:"resourceShareAssociations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.ResourceShareAssociations, tt.wantCount) }) } @@ -315,15 +317,15 @@ func TestAssociationStatusMessage_InResponse(t *testing.T) { StatusMessage string `json:"statusMessage"` } `json:"resourceShareAssociations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.ResourceShareAssociations) // statusMessage is optional; verify the field exists in JSON (can be empty). // We check by re-parsing as raw map. var raw struct { - ResourceShareAssociations []map[string]json.RawMessage `json:"resourceShareAssociations"` + ResourceShareAssociations []map[string]jsontext.Value `json:"resourceShareAssociations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.NotEmpty(t, raw.ResourceShareAssociations) // statusMessage should NOT appear when empty (omitempty). _, present := raw.ResourceShareAssociations[0]["statusMessage"] @@ -358,7 +360,7 @@ func TestAssociateResourceShare_AutoAssociatesDefaultPermission(t *testing.T) { Arn string `json:"arn"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Permissions, 1) assert.Equal(t, "arn:aws:ram::aws:permission/AWSRAMDefaultPermissionEC2Subnet", listResp.Permissions[0].Arn) @@ -372,7 +374,7 @@ func TestAssociateResourceShare_AutoAssociatesDefaultPermission(t *testing.T) { listRec = doRAMRequest(t, h, "/listresourcesharepermissions", map[string]any{ "resourceShareArn": rs.ARN, }) - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.Permissions, 1, "adding a second resource of an already-covered type must not duplicate") } @@ -446,7 +448,7 @@ func TestGetResourceShareAssociations_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -455,7 +457,7 @@ func TestGetResourceShareAssociations_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) totalSeen += len(resp.ResourceShareAssociations) nextToken = resp.NextToken diff --git a/services/ram/handler_share_invitations.go b/services/ram/handler_share_invitations.go index 260c813ddd..02fc8f2f39 100644 --- a/services/ram/handler_share_invitations.go +++ b/services/ram/handler_share_invitations.go @@ -2,8 +2,10 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // invitationObject is the JSON representation of a ResourceShareInvitation. @@ -42,7 +44,7 @@ func (h *Handler) handleAcceptResourceShareInvitation( body []byte, ) ([]byte, error) { var req acceptResourceShareInvitationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -57,7 +59,7 @@ func (h *Handler) handleAcceptResourceShareInvitation( return json.Marshal(acceptResourceShareInvitationResponse{ ResourceShareInvitation: toInvitationObject(inv), - }) + }, jsonx.V1()) } type rejectResourceShareInvitationRequest struct { @@ -73,7 +75,7 @@ func (h *Handler) handleRejectResourceShareInvitation( body []byte, ) ([]byte, error) { var req rejectResourceShareInvitationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -88,7 +90,7 @@ func (h *Handler) handleRejectResourceShareInvitation( return json.Marshal(rejectResourceShareInvitationResponse{ ResourceShareInvitation: toInvitationObject(inv), - }) + }, jsonx.V1()) } type getResourceShareInvitationsRequest struct { @@ -108,7 +110,7 @@ func (h *Handler) handleGetResourceShareInvitations( body []byte, ) ([]byte, error) { var req getResourceShareInvitationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -128,6 +130,6 @@ func (h *Handler) handleGetResourceShareInvitations( } return json.Marshal( - getResourceShareInvitationsResponse{NextToken: nextToken, ResourceShareInvitations: page}, + getResourceShareInvitationsResponse{NextToken: nextToken, ResourceShareInvitations: page}, jsonx.V1(), ) } diff --git a/services/ram/handler_share_invitations_test.go b/services/ram/handler_share_invitations_test.go index 3681611d28..b7623c2207 100644 --- a/services/ram/handler_share_invitations_test.go +++ b/services/ram/handler_share_invitations_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -97,7 +98,7 @@ func TestGetResourceShareInvitations_Status(t *testing.T) { Status string `json:"status"` } `json:"resourceShareInvitations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ResourceShareInvitations, 1) assert.Equal(t, tt.wantStatus, resp.ResourceShareInvitations[0].Status) }) @@ -371,7 +372,7 @@ func TestGetResourceShareInvitations_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -380,7 +381,7 @@ func TestGetResourceShareInvitations_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.ResourceShareInvitations) @@ -417,7 +418,7 @@ func TestAcceptInvitation_HTTP(t *testing.T) { Status string `json:"status"` } `json:"resourceShareInvitation"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ACCEPTED", resp.ResourceShareInvitation.Status) // Double-accept should return AlreadyAccepted. diff --git a/services/ram/handler_share_permissions.go b/services/ram/handler_share_permissions.go index 80ddf52212..dcac65641b 100644 --- a/services/ram/handler_share_permissions.go +++ b/services/ram/handler_share_permissions.go @@ -2,9 +2,11 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listResourceSharePermissionsRequest struct { @@ -24,7 +26,7 @@ func (h *Handler) handleListResourceSharePermissions( body []byte, ) ([]byte, error) { var req listResourceSharePermissionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -45,7 +47,7 @@ func (h *Handler) handleListResourceSharePermissions( } return json.Marshal( - listResourceSharePermissionsResponse{NextToken: nextToken, Permissions: page}, + listResourceSharePermissionsResponse{NextToken: nextToken, Permissions: page}, jsonx.V1(), ) } @@ -65,7 +67,7 @@ func (h *Handler) handleAssociateResourceSharePermission( body []byte, ) ([]byte, error) { var req associateResourceSharePermissionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -83,7 +85,7 @@ func (h *Handler) handleAssociateResourceSharePermission( return nil, err } - return json.Marshal(associateResourceSharePermissionResponse{ReturnValue: true}) + return json.Marshal(associateResourceSharePermissionResponse{ReturnValue: true}, jsonx.V1()) } type disassociateResourceSharePermissionRequest struct { @@ -100,7 +102,7 @@ func (h *Handler) handleDisassociateResourceSharePermission( body []byte, ) ([]byte, error) { var req disassociateResourceSharePermissionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -116,7 +118,7 @@ func (h *Handler) handleDisassociateResourceSharePermission( return nil, err } - return json.Marshal(disassociateResourceSharePermissionResponse{ReturnValue: true}) + return json.Marshal(disassociateResourceSharePermissionResponse{ReturnValue: true}, jsonx.V1()) } type replacePermissionAssociationsRequest struct { @@ -166,7 +168,7 @@ func (h *Handler) handleReplacePermissionAssociations( body []byte, ) ([]byte, error) { var req replacePermissionAssociationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -189,7 +191,7 @@ func (h *Handler) handleReplacePermissionAssociations( return json.Marshal(replacePermissionAssociationsResponse{ ReplacePermissionAssociationsWork: toReplacePermissionAssociationsWorkObject(work), - }) + }, jsonx.V1()) } // permissionAssociationObject matches types.AssociatedPermission @@ -221,7 +223,7 @@ type listPermissionAssociationsResponse struct { func (h *Handler) handleListPermissionAssociations(_ context.Context, body []byte) ([]byte, error) { var req listPermissionAssociationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -250,7 +252,7 @@ func (h *Handler) handleListPermissionAssociations(_ context.Context, body []byt return nil, err } - return json.Marshal(listPermissionAssociationsResponse{NextToken: nextToken, Permissions: page}) + return json.Marshal(listPermissionAssociationsResponse{NextToken: nextToken, Permissions: page}, jsonx.V1()) } // shareMatchesPermissionFilter applies the featureSet and associationStatus filters. @@ -288,7 +290,7 @@ func (h *Handler) handleListReplacePermissionAssociationsWork( body []byte, ) ([]byte, error) { var req listReplacePermissionAssociationsWorkRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -307,5 +309,5 @@ func (h *Handler) handleListReplacePermissionAssociationsWork( return json.Marshal(listReplacePermissionAssociationsWorkResponse{ NextToken: nextToken, ReplacePermissionAssociationsWorks: page, - }) + }, jsonx.V1()) } diff --git a/services/ram/handler_share_permissions_test.go b/services/ram/handler_share_permissions_test.go index 2f3ef71190..91e2f03040 100644 --- a/services/ram/handler_share_permissions_test.go +++ b/services/ram/handler_share_permissions_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -75,7 +76,7 @@ func TestAssociateBuiltInPermission(t *testing.T) { PermissionType string `json:"permissionType"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Permissions, 1) assert.Equal(t, tt.permARN, resp.Permissions[0].Arn) assert.Equal(t, "AWS_MANAGED", resp.Permissions[0].PermissionType) @@ -145,7 +146,7 @@ func TestReplacePermissionAssociations(t *testing.T) { ID string `json:"id"` } `json:"replacePermissionAssociationsWork"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.ReplacePermissionAssociationsWork.ID) // This mock performs the association swap synchronously (no async worker), // so the work item is already COMPLETED by the time the call returns. @@ -181,7 +182,7 @@ func TestListReplacePermissionAssociationsWork(t *testing.T) { ID string `json:"id"` } `json:"replacePermissionAssociationsWork"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) workID := createResp.ReplacePermissionAssociationsWork.ID require.NotEmpty(t, workID) @@ -203,7 +204,7 @@ func TestListReplacePermissionAssociationsWork(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp listResp - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ReplacePermissionAssociationsWorks, 1) w := resp.ReplacePermissionAssociationsWorks[0] @@ -224,7 +225,7 @@ func TestListReplacePermissionAssociationsWork(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp listResp - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.ReplacePermissionAssociationsWorks) }) @@ -237,7 +238,7 @@ func TestListReplacePermissionAssociationsWork(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp listResp - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.ReplacePermissionAssociationsWorks) }) } @@ -415,7 +416,7 @@ func TestDisassociateResourceSharePermission_BlockedWhileResourceOfTypeAttached( assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "OperationNotPermittedException", errResp["__type"]) // The permission must still be associated -- the disassociation was refused, not @@ -516,7 +517,7 @@ func TestListResourceSharePermissions_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -525,7 +526,7 @@ func TestListResourceSharePermissions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ nextToken = resp.NextToken @@ -580,7 +581,7 @@ func TestListPermissionAssociations_PermissionVersionFilter(t *testing.T) { PermissionVersion string `json:"permissionVersion"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len( t, resp.Permissions, 1, "permissionVersion must scope results to shares pinned to that version", @@ -670,7 +671,7 @@ func TestListPermissionAssociations_Pagination(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) return @@ -679,7 +680,7 @@ func TestListPermissionAssociations_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp respBody - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pages++ totalSeen += len(resp.Permissions) @@ -712,7 +713,7 @@ func TestListResourceSharePermissions_RealData(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp, jsonx.V1())) shareARN := shareResp.ResourceShare.ResourceShareArn permRec := doRAMRequest(t, h, "/createpermission", map[string]any{ @@ -727,7 +728,7 @@ func TestListResourceSharePermissions_RealData(t *testing.T) { Arn string `json:"arn"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(permRec.Body.Bytes(), &permResp)) + require.NoError(t, json.Unmarshal(permRec.Body.Bytes(), &permResp, jsonx.V1())) permARN := permResp.Permission.Arn // Associate permission with share. @@ -748,7 +749,7 @@ func TestListResourceSharePermissions_RealData(t *testing.T) { Arn string `json:"arn"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Permissions, 1) assert.Equal(t, permARN, listResp.Permissions[0].Arn) } @@ -781,7 +782,7 @@ func TestListResourceSharePermissions_ReportsAssociatedVersion(t *testing.T) { ResourceShareArn string `json:"resourceShareArn"` } `json:"resourceShare"` } - require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp)) + require.NoError(t, json.Unmarshal(shareRec.Body.Bytes(), &shareResp, jsonx.V1())) shareARN := shareResp.ResourceShare.ResourceShareArn permRec := doRAMRequest(t, h, "/createpermission", map[string]any{ @@ -796,7 +797,7 @@ func TestListResourceSharePermissions_ReportsAssociatedVersion(t *testing.T) { Arn string `json:"arn"` } `json:"permission"` } - require.NoError(t, json.Unmarshal(permRec.Body.Bytes(), &permResp)) + require.NoError(t, json.Unmarshal(permRec.Body.Bytes(), &permResp, jsonx.V1())) permARN := permResp.Permission.Arn // Create a second version and make it the default, then pin the share to @@ -833,7 +834,7 @@ func TestListResourceSharePermissions_ReportsAssociatedVersion(t *testing.T) { DefaultVersion bool `json:"defaultVersion"` } `json:"permissions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Permissions, 1) assert.Equal( t, "1", listResp.Permissions[0].Version, diff --git a/services/ram/handler_tags.go b/services/ram/handler_tags.go index 1a696f54b5..07afce382c 100644 --- a/services/ram/handler_tags.go +++ b/services/ram/handler_tags.go @@ -2,8 +2,10 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type tagResourceRequest struct { @@ -14,7 +16,7 @@ type tagResourceRequest struct { func (h *Handler) handleTagResource(_ context.Context, body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -42,7 +44,7 @@ type untagResourceRequest struct { func (h *Handler) handleUntagResource(_ context.Context, body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -73,7 +75,7 @@ type listTagsForResourceResponse struct { func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]byte, error) { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -91,5 +93,5 @@ func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]b return nil, err } - return json.Marshal(listTagsForResourceResponse{Tags: toTagObjects(tags)}) + return json.Marshal(listTagsForResourceResponse{Tags: toTagObjects(tags)}, jsonx.V1()) } diff --git a/services/ram/handler_tags_test.go b/services/ram/handler_tags_test.go index 95ac326fd6..6c546df151 100644 --- a/services/ram/handler_tags_test.go +++ b/services/ram/handler_tags_test.go @@ -1,13 +1,14 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -221,7 +222,7 @@ func TestToTagObjectsSorted(t *testing.T) { } `json:"tags"` } `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ResourceShares, 1) tags := resp.ResourceShares[0].Tags @@ -259,7 +260,7 @@ func TestTagsRoundTrip(t *testing.T) { Value string `json:"value"` } `json:"tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Tags, 1) assert.Equal(t, "env", listResp.Tags[0].Key) assert.Equal(t, "prod", listResp.Tags[0].Value) @@ -276,6 +277,6 @@ func TestTagsRoundTrip(t *testing.T) { "resourceShareArn": rs.ARN, }) require.Equal(t, http.StatusOK, listRec2.Code) - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &listResp, jsonx.V1())) assert.Empty(t, listResp.Tags) } diff --git a/services/ram/handler_test.go b/services/ram/handler_test.go index 56b3781ab5..7efb50f55c 100644 --- a/services/ram/handler_test.go +++ b/services/ram/handler_test.go @@ -2,7 +2,8 @@ package ram_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -29,7 +31,7 @@ func doRAMRequest(t *testing.T, h *ram.Handler, path string, body any) *httptest if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -249,7 +251,7 @@ func TestHandler_Reset(t *testing.T) { ResourceShares []any `json:"resourceShares"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.ResourceShares) } @@ -286,9 +288,9 @@ func TestReset_ReSeedsBuiltIns(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var custResp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &custResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &custResp, jsonx.V1())) assert.Empty(t, custResp.Permissions, "customer permissions cleared after reset") rec2 := doRAMRequest(t, h, "/listpermissions", map[string]any{ @@ -297,9 +299,9 @@ func TestReset_ReSeedsBuiltIns(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var awsResp struct { - Permissions []json.RawMessage `json:"permissions"` + Permissions []jsontext.Value `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &awsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &awsResp, jsonx.V1())) assert.Len(t, awsResp.Permissions, ram.BuiltInPermissionCount, "built-in permissions re-seeded after reset") }) diff --git a/services/ram/idempotent_ops.go b/services/ram/idempotent_ops.go index bb26a8dab5..294dd9f4ff 100644 --- a/services/ram/idempotent_ops.go +++ b/services/ram/idempotent_ops.go @@ -2,11 +2,12 @@ package ram import ( "context" - "encoding/json" + "encoding/json/v2" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func usesClientToken(op string) bool { @@ -32,7 +33,7 @@ func (h *Handler) replayClientToken( token := query.Get("clientToken") var fields map[string]any - if len(body) > 0 && json.Unmarshal(body, &fields) == nil { + if len(body) > 0 && json.Unmarshal(body, &fields, jsonx.V1()) == nil { if t, ok := fields["clientToken"].(string); ok && token == "" { token = t } diff --git a/services/ram/multi_region_test.go b/services/ram/multi_region_test.go index a808a85ea5..c6ef35283a 100644 --- a/services/ram/multi_region_test.go +++ b/services/ram/multi_region_test.go @@ -2,7 +2,8 @@ package ram_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -178,8 +180,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/ram/permission_version_shape_test.go b/services/ram/permission_version_shape_test.go index b23b59ec55..f14b14bc28 100644 --- a/services/ram/permission_version_shape_test.go +++ b/services/ram/permission_version_shape_test.go @@ -1,7 +1,7 @@ package ram_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/ram" ) @@ -104,7 +105,7 @@ func Test_ListPermissionVersions_OmitsPolicyDocumentField(t *testing.T) { var raw struct { Permissions []map[string]any `json:"permissions"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.Permissions, 2) for _, item := range raw.Permissions { diff --git a/services/ram/persistence.go b/services/ram/persistence.go index e2796621c3..5914e499fb 100644 --- a/services/ram/persistence.go +++ b/services/ram/persistence.go @@ -2,10 +2,12 @@ package ram import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -35,7 +37,7 @@ const ramSnapshotVersion = 1 // newer) build of this backend as though it were the current shape; see // Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` SharePermissions map[string]map[string]int32 `json:"sharePermissions"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -88,7 +90,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ram: failed to snapshot backend state", "error", err) diff --git a/services/ram/policy_shares.go b/services/ram/policy_shares.go index 9edd05861c..25cfa942bb 100644 --- a/services/ram/policy_shares.go +++ b/services/ram/policy_shares.go @@ -1,7 +1,7 @@ package ram import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" @@ -9,6 +9,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // policyShareNamePrefix names every CREATED_FROM_POLICY share this backend creates via @@ -227,7 +228,7 @@ func policyTemplateFromActions(actions []string) string { "Effect": "Allow", "Action": actions, "Resource": "*", - }) + }, jsonx.V1()) if err != nil { return `{"Effect":"Allow","Action":[],"Resource":"*"}` } diff --git a/services/rds/engine_dumpstore.go b/services/rds/engine_dumpstore.go index bb85a6e748..d1e72ee5f7 100644 --- a/services/rds/engine_dumpstore.go +++ b/services/rds/engine_dumpstore.go @@ -2,12 +2,14 @@ package rds import ( "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "os" "path/filepath" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -47,7 +49,10 @@ func (s *dumpStore) save(key string, at time.Time, d engineData) error { rec := dumpRecord{At: at, Key: key, Dump: d.dump, Password: d.password, DBName: d.dbName} - raw, err := json.Marshal(rec) //nolint:gosec // the master password must come back with the restored data + raw, err := json.Marshal( + rec, + jsonx.V1(), + ) //nolint:gosec // the master password must come back with the restored data if err != nil { return fmt.Errorf("marshal dump: %w", err) } @@ -102,7 +107,7 @@ func (s *dumpStore) load() []dumpRecord { } var rec dumpRecord - if json.Unmarshal(raw, &rec) == nil && rec.Key != "" { + if json.Unmarshal(raw, &rec, jsonx.V1()) == nil && rec.Key != "" { out = append(out, rec) } } diff --git a/services/rds/engine_pgext_docker_test.go b/services/rds/engine_pgext_docker_test.go index bcba13989a..8fa2c9234a 100644 --- a/services/rds/engine_pgext_docker_test.go +++ b/services/rds/engine_pgext_docker_test.go @@ -3,7 +3,8 @@ package rds_test import ( "context" "database/sql" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/rds" "github.com/blackbirdworks/gopherstack/services/s3" @@ -71,7 +73,7 @@ func startPgExtEnv(t *testing.T) *pgExtEnv { return } - out, _ := json.Marshal(map[string]any{"fn": r.PathValue("name"), "echo": json.RawMessage(in)}) + out, _ := json.Marshal(map[string]any{"fn": r.PathValue("name"), "echo": jsontext.Value(in)}, jsonx.V1()) _, _ = w.Write(out) }) mux.Handle("/", s3e) diff --git a/services/rds/master_secret.go b/services/rds/master_secret.go index 1a5e5f6202..119680524a 100644 --- a/services/rds/master_secret.go +++ b/services/rds/master_secret.go @@ -3,13 +3,14 @@ package rds import ( "crypto/rand" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net/url" "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -86,7 +87,7 @@ func masterSecretBody(user string) (string, error) { return "", fmt.Errorf("generate master password: %w", err) } - body, err := json.Marshal(map[string]string{"username": user, "password": hex.EncodeToString(raw)}) + body, err := json.Marshal(map[string]string{"username": user, "password": hex.EncodeToString(raw)}, jsonx.V1()) if err != nil { return "", fmt.Errorf("encode master user secret: %w", err) } diff --git a/services/rds/persistence.go b/services/rds/persistence.go index 9d0e03bcc1..f24572656d 100644 --- a/services/rds/persistence.go +++ b/services/rds/persistence.go @@ -2,11 +2,13 @@ package rds import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -30,7 +32,7 @@ import ( const rdsSnapshotVersion = 3 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string][]Tag `json:"tags"` ClusterRoles map[string][]DBClusterRole `json:"clusterRoles"` InstanceRoles map[string]map[string]string `json:"instanceRoles"` @@ -86,7 +88,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { DefaultCACertificateID: b.defaultCACertificateID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "rds: failed to marshal snapshot", "error", err) @@ -235,11 +237,11 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { return h.Backend.Snapshot(ctx) } - snaps := make(map[string]json.RawMessage) + snaps := make(map[string]jsontext.Value) for region, b := range h.backends { snaps[region] = b.Snapshot(ctx) } - data, _ := json.Marshal(snaps) + data, _ := json.Marshal(snaps, jsonx.V1()) return data } @@ -253,8 +255,8 @@ func (h *Handler) Restore(ctx context.Context, data []byte) error { return h.Backend.Restore(ctx, data) } - var snaps map[string]json.RawMessage - if err := json.Unmarshal(data, &snaps); err != nil { + var snaps map[string]jsontext.Value + if err := json.Unmarshal(data, &snaps, jsonx.V1()); err != nil { // Fallback for backwards compatibility with single-region snapshots. return h.Backend.Restore(ctx, data) } diff --git a/services/rds/persistence_test.go b/services/rds/persistence_test.go index bf73b2a246..e99badbeaf 100644 --- a/services/rds/persistence_test.go +++ b/services/rds/persistence_test.go @@ -1,13 +1,15 @@ package rds_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rds" ) @@ -21,16 +23,16 @@ func TestPersistence_SnapshotJSON_ContainsExtendedKeys(t *testing.T) { snap := b.Snapshot(t.Context()) require.NotNil(t, snap) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) // As of the Phase 3.3 pkgs/store conversion, resource collections backed by // a store.Table are serialized under the nested "tables" blob (produced by // store.Registry.SnapshotAll) rather than as top-level snapshot keys. require.Contains(t, raw, "tables") - var tables map[string]json.RawMessage - require.NoError(t, json.Unmarshal(raw["tables"], &tables)) + var tables map[string]jsontext.Value + require.NoError(t, json.Unmarshal(raw["tables"], &tables, jsonx.V1())) for _, key := range []string{ "customEngineVersions", diff --git a/services/rdsdata/column_origin_realclient_test.go b/services/rdsdata/column_origin_realclient_test.go index a9a36efccb..83227f7c8f 100644 --- a/services/rdsdata/column_origin_realclient_test.go +++ b/services/rdsdata/column_origin_realclient_test.go @@ -1,7 +1,7 @@ package rdsdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rdsdata" ) @@ -93,7 +94,7 @@ func TestExecuteStatement_ColumnMetadata_TableOrigin_InsideTransaction(t *testin require.Equal(t, http.StatusOK, rec.Code) var begin map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &begin)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &begin, jsonx.V1())) txID, ok := begin["transactionId"].(string) require.True(t, ok) @@ -107,7 +108,7 @@ func TestExecuteStatement_ColumnMetadata_TableOrigin_InsideTransaction(t *testin require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cols, ok := resp["columnMetadata"].([]any) require.True(t, ok) diff --git a/services/rdsdata/errsweep_wire_shape_test.go b/services/rdsdata/errsweep_wire_shape_test.go index 892396fd70..e4a4d72ce3 100644 --- a/services/rdsdata/errsweep_wire_shape_test.go +++ b/services/rdsdata/errsweep_wire_shape_test.go @@ -1,7 +1,7 @@ package rdsdata_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/rdsdata" @@ -61,7 +62,7 @@ func TestHandler_MalformedBodyCarriesTypedErrorCode(t *testing.T) { require.NoError(t, err) var decoded map[string]any - require.NoError(t, json.Unmarshal(raw, &decoded)) + require.NoError(t, json.Unmarshal(raw, &decoded, jsonx.V1())) require.Equal(t, "BadRequestException", decoded["__type"], "raw response body must carry __type; got: %s", raw) require.NotEmpty(t, decoded["message"]) diff --git a/services/rdsdata/handler.go b/services/rdsdata/handler.go index 7b8ef820ae..fea68e1acc 100644 --- a/services/rdsdata/handler.go +++ b/services/rdsdata/handler.go @@ -3,7 +3,7 @@ package rdsdata import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -257,7 +258,7 @@ func writeInternalServerError(c *echo.Context) error { payload, err := json.Marshal(map[string]string{ keyTypeField: "InternalServerErrorException", keyMessageField: "internal server error", - }) + }, jsonx.V1()) if err != nil { return err } @@ -270,32 +271,32 @@ func stripCode(err error, code string) string { } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - var apiErr *apiError switch { case errors.As(err, &apiErr): - payload, _ := json.Marshal(map[string]string{keyTypeField: apiErr.code, keyMessageField: apiErr.msg}) + payload, _ := json.Marshal( + map[string]string{keyTypeField: apiErr.code, keyMessageField: apiErr.msg}, + jsonx.V1(), + ) return c.JSONBlob(apiErr.status, payload) case errors.Is(err, ErrTransactionNotFound): payload, _ := json.Marshal(map[string]string{ keyTypeField: "TransactionNotFoundException", keyMessageField: stripCode(err, "TransactionNotFoundException"), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusNotFound, payload) case errIsValidation(err): payload, _ := json.Marshal(map[string]string{ keyTypeField: "BadRequestException", keyMessageField: stripCode(err, "BadRequestException"), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): // These branches used to omit keyTypeField entirely, so // restjson.GetErrorInfo (aws-sdk-go-v2 aws/protocol/restjson/ // decoder_util.go:15) found no code in the header (unset) or the @@ -410,7 +411,7 @@ func validateRequiredFields(fields ...requiredField) error { func (h *Handler) handleExecuteStatement(ctx context.Context, body []byte) ([]byte, error) { var req executeStatementRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -489,7 +490,7 @@ func marshalExecuteResponse( } } - out, err := json.Marshal(resp) + out, err := json.Marshal(resp, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal response: %w", err) } @@ -532,7 +533,7 @@ func formatRecordsAsJSONString(records [][]Field, columns []ColumnMetadata) (str rows[i] = row } - out, err := json.Marshal(rows) + out, err := json.Marshal(rows, jsonx.V1()) if err != nil { return "", fmt.Errorf("marshal formatted records: %w", err) } @@ -571,7 +572,7 @@ type batchExecuteStatementResponse struct { func (h *Handler) handleBatchExecuteStatement(ctx context.Context, body []byte) ([]byte, error) { var req batchExecuteStatementRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -600,7 +601,7 @@ func (h *Handler) handleBatchExecuteStatement(ctx context.Context, body []byte) return nil, err } - return json.Marshal(batchExecuteStatementResponse{UpdateResults: results}) + return json.Marshal(batchExecuteStatementResponse{UpdateResults: results}, jsonx.V1()) } type beginTransactionRequest struct { @@ -616,7 +617,7 @@ type beginTransactionResponse struct { func (h *Handler) handleBeginTransaction(ctx context.Context, body []byte) ([]byte, error) { var req beginTransactionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -634,7 +635,7 @@ func (h *Handler) handleBeginTransaction(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(beginTransactionResponse{TransactionID: txID}) + return json.Marshal(beginTransactionResponse{TransactionID: txID}, jsonx.V1()) } type commitTransactionRequest struct { @@ -649,7 +650,7 @@ type commitTransactionResponse struct { func (h *Handler) handleCommitTransaction(ctx context.Context, body []byte) ([]byte, error) { var req commitTransactionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -666,7 +667,7 @@ func (h *Handler) handleCommitTransaction(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(commitTransactionResponse{TransactionStatus: status}) + return json.Marshal(commitTransactionResponse{TransactionStatus: status}, jsonx.V1()) } type rollbackTransactionRequest struct { @@ -681,7 +682,7 @@ type rollbackTransactionResponse struct { func (h *Handler) handleRollbackTransaction(ctx context.Context, body []byte) ([]byte, error) { var req rollbackTransactionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -698,7 +699,7 @@ func (h *Handler) handleRollbackTransaction(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(rollbackTransactionResponse{TransactionStatus: status}) + return json.Marshal(rollbackTransactionResponse{TransactionStatus: status}, jsonx.V1()) } type executeSQLRequest struct { @@ -715,7 +716,7 @@ type executeSQLResponse struct { func (h *Handler) handleExecuteSQL(ctx context.Context, body []byte) ([]byte, error) { var req executeSQLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -734,7 +735,7 @@ func (h *Handler) handleExecuteSQL(ctx context.Context, body []byte) ([]byte, er return nil, err } - return json.Marshal(executeSQLResponse{SQLStatementResults: results}) + return json.Marshal(executeSQLResponse{SQLStatementResults: results}, jsonx.V1()) } func arrayToJSONValue(a *ArrayValue) any { diff --git a/services/rdsdata/handler_test.go b/services/rdsdata/handler_test.go index f1c565618a..9d59e1c8d9 100644 --- a/services/rdsdata/handler_test.go +++ b/services/rdsdata/handler_test.go @@ -2,7 +2,7 @@ package rdsdata_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/rdsdata" ) @@ -30,7 +31,7 @@ func doRDSDataRequest(t *testing.T, h *rdsdata.Handler, path string, body any) * if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -348,7 +349,7 @@ func TestHandler_ConcurrentRequests_Race(t *testing.T) { "resourceArn": "arn:aws:rds:us-east-1:000000000000:cluster:c", "secretArn": "arn:aws:secretsmanager:us-east-1:000000000000:secret:s", "sql": "SELECT " + string(rune('0'+i%10)), - }) + }, jsonx.V1()) e := echo.New() req := httptest.NewRequest(http.MethodPost, "/Execute", bytes.NewReader(body)) diff --git a/services/rdsdata/real_docker_test.go b/services/rdsdata/real_docker_test.go index e38ce4eb3e..8579fdabc9 100644 --- a/services/rdsdata/real_docker_test.go +++ b/services/rdsdata/real_docker_test.go @@ -1,7 +1,7 @@ package rdsdata_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "os/exec" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rds" "github.com/blackbirdworks/gopherstack/services/rdsdata" "github.com/blackbirdworks/gopherstack/services/secretsmanager" @@ -95,7 +96,7 @@ func (d *dockerDataAPI) call(path string, body map[string]any) (int, map[string] out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(d.t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(d.t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return rec.Code, out diff --git a/services/rdsdata/real_engine.go b/services/rdsdata/real_engine.go index 1bb884cc44..6163d0156e 100644 --- a/services/rdsdata/real_engine.go +++ b/services/rdsdata/real_engine.go @@ -3,7 +3,7 @@ package rdsdata import ( "context" "database/sql" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/url" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" _ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -127,7 +128,7 @@ func (e *realEngine) loginFor(ctx context.Context, resourceARN string) (realLogi Password string `json:"password"` } - if json.Unmarshal([]byte(raw), &creds) != nil || creds.Username == "" || creds.Password == "" { + if json.Unmarshal([]byte(raw), &creds, jsonx.V1()) != nil || creds.Username == "" || creds.Password == "" { return realLogin{}, false, errInvalidSecret("the secret must be a JSON object with username and password") } diff --git a/services/rdsdata/real_handler_test.go b/services/rdsdata/real_handler_test.go index c4ac215514..3080618e3e 100644 --- a/services/rdsdata/real_handler_test.go +++ b/services/rdsdata/real_handler_test.go @@ -2,7 +2,7 @@ package rdsdata //nolint:testpackage // white-box tests of the unexported placeh import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandlerMapsModeledExceptions(t *testing.T) { @@ -50,7 +52,7 @@ func TestHandlerMapsModeledExceptions(t *testing.T) { body, err := json.Marshal(map[string]string{ "resourceArn": testClusterARN, "secretArn": testSecretARN, "sql": "SELECT 1", - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/Execute", bytes.NewReader(body)) @@ -63,7 +65,7 @@ func TestHandlerMapsModeledExceptions(t *testing.T) { var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["__type"]) }) } diff --git a/services/rdsdata/sql_test.go b/services/rdsdata/sql_test.go index d5af4b393f..41d1645149 100644 --- a/services/rdsdata/sql_test.go +++ b/services/rdsdata/sql_test.go @@ -2,7 +2,7 @@ package rdsdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rdsdata" ) @@ -125,7 +126,7 @@ func TestHandler_ExecuteSQL_Response(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["sqlStatementResults"] require.True(t, ok) @@ -148,6 +149,6 @@ func TestHandler_ExecuteSQL_Response_NotNull(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["sqlStatementResults"]) } diff --git a/services/rdsdata/statements_test.go b/services/rdsdata/statements_test.go index f9b662525b..9af0f197a1 100644 --- a/services/rdsdata/statements_test.go +++ b/services/rdsdata/statements_test.go @@ -2,7 +2,7 @@ package rdsdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rdsdata" ) @@ -93,7 +94,7 @@ func TestHandler_ExecuteStatement_WithTransaction(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rec := doRDSDataRequest(t, h, "/Execute", map[string]any{ @@ -150,7 +151,7 @@ func TestHandler_ExecuteStatement_Response(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasRecords := resp["records"] assert.True(t, hasRecords, "records key must be present") @@ -202,7 +203,7 @@ func TestHandler_ExecuteStatement_IncludeResultMetadata(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasCols := resp["columnMetadata"] assert.Equal(t, tt.wantColumnMetadata, hasCols, @@ -246,7 +247,7 @@ func TestHandler_ExecuteStatement_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, field := range tt.fields { _, ok := resp[field] @@ -274,7 +275,7 @@ func TestHandler_ExecuteStatement_FormatRecordsAsJSON(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasRecords := resp["records"] assert.False(t, hasRecords, "records must be omitted when formatRecordsAs=JSON") @@ -285,7 +286,7 @@ func TestHandler_ExecuteStatement_FormatRecordsAsJSON(t *testing.T) { require.True(t, ok, "formattedRecords must be a JSON string") var rows []map[string]any - require.NoError(t, json.Unmarshal([]byte(formatted), &rows)) + require.NoError(t, json.Unmarshal([]byte(formatted), &rows, jsonx.V1())) require.Len(t, rows, 1) require.Len(t, rows[0], 1, "row must have exactly one column") @@ -311,7 +312,7 @@ func TestHandler_ExecuteStatement_FormatRecordsAsIgnoredForDML(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasFormatted := resp["formattedRecords"] assert.False(t, hasFormatted, "formattedRecords must not appear for a DML statement") @@ -336,7 +337,7 @@ func TestHandler_ExecuteStatement_FormatRecordsAsInvalid(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) } @@ -357,7 +358,7 @@ func TestHandler_ExecuteStatement_ColumnMetadataFullShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cols, ok := resp["columnMetadata"].([]any) require.True(t, ok) @@ -421,7 +422,7 @@ func TestHandler_ExecuteStatement_ArrayParameterRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) } @@ -472,7 +473,7 @@ func TestHandler_ExecuteStatement_ResultSetOptions_LongReturnType(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records := resp["records"].([]any) require.Len(t, records, 1) @@ -531,7 +532,7 @@ func TestHandler_ExecuteStatement_ResultSetOptions_DecimalReturnType(t *testing. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records := resp["records"].([]any) require.Len(t, records, 1) @@ -570,7 +571,7 @@ func TestHandler_ExecuteStatement_ResultSetOptions_InvalidEnum(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) }) } @@ -675,7 +676,7 @@ func TestHandler_BatchExecuteStatement_EmptyParamSets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["updateResults"] require.True(t, ok, "updateResults key must exist") @@ -703,7 +704,7 @@ func TestHandler_BatchExecuteStatement_ArrayParameterRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) } @@ -746,7 +747,7 @@ func TestHandler_BatchExecuteStatement_MultipleParamSets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["updateResults"].([]any) assert.Len(t, results, 3) } @@ -795,7 +796,7 @@ func TestHandler_BatchExecuteStatement_OneResultPerParamSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["updateResults"].([]any) require.True(t, ok, "updateResults must be an array") diff --git a/services/rdsdata/transactions_test.go b/services/rdsdata/transactions_test.go index 7c69ab5127..f2c85b1bdc 100644 --- a/services/rdsdata/transactions_test.go +++ b/services/rdsdata/transactions_test.go @@ -2,7 +2,7 @@ package rdsdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rdsdata" ) @@ -81,7 +82,7 @@ func TestHandler_BeginTransaction_ReturnsTransactionID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) txID, ok := resp["transactionId"].(string) require.True(t, ok) assert.NotEmpty(t, txID) @@ -103,7 +104,7 @@ func TestHandler_BeginTransaction_UniqueIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) txID, ok := resp["transactionId"].(string) require.True(t, ok) @@ -169,7 +170,7 @@ func TestHandler_CommitTransaction(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rec = doRDSDataRequest(t, h, "/CommitTransaction", map[string]any{ @@ -247,7 +248,7 @@ func TestHandler_RollbackTransaction(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rec = doRDSDataRequest(t, h, "/RollbackTransaction", map[string]any{ @@ -286,7 +287,7 @@ func TestHandler_TransactionLifecycle(t *testing.T) { assert.Equal(t, 1, rdsdata.TransactionCount(b)) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) // Execute @@ -308,7 +309,7 @@ func TestHandler_TransactionLifecycle(t *testing.T) { assert.Equal(t, 0, rdsdata.TransactionCount(b)) var commitResp map[string]any - require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp)) + require.NoError(t, json.Unmarshal(commitRec.Body.Bytes(), &commitResp, jsonx.V1())) assert.Equal(t, "Transaction committed", commitResp["transactionStatus"]) } @@ -325,7 +326,7 @@ func TestHandler_TransactionRollbackLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rollbackRec := doRDSDataRequest(t, h, "/RollbackTransaction", map[string]any{ @@ -336,7 +337,7 @@ func TestHandler_TransactionRollbackLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rollbackRec.Code) var rollbackResp map[string]any - require.NoError(t, json.Unmarshal(rollbackRec.Body.Bytes(), &rollbackResp)) + require.NoError(t, json.Unmarshal(rollbackRec.Body.Bytes(), &rollbackResp, jsonx.V1())) assert.Equal(t, "Transaction rolled back", rollbackResp["transactionStatus"]) } @@ -353,7 +354,7 @@ func TestHandler_CommitAfterRollback_Fails(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) // Rollback first @@ -401,7 +402,7 @@ func TestHandler_CommitThenReuse(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) commitRec := doRDSDataRequest(t, h, "/CommitTransaction", map[string]any{ @@ -421,7 +422,7 @@ func TestHandler_CommitThenReuse(t *testing.T) { "path %s: reusing committed txID must fail", tt.path) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "TransactionNotFoundException", errResp["__type"]) }) } @@ -463,7 +464,7 @@ func TestHandler_ExecuteAfterTransactionClose(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) // Execute within transaction — should succeed. @@ -508,7 +509,7 @@ func TestHandler_BatchExecuteWithTransaction(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rec := doRDSDataRequest(t, h, "/BatchExecute", map[string]any{ @@ -558,7 +559,7 @@ func TestHandler_TransactionStatusConstants(t *testing.T) { require.Equal(t, http.StatusOK, beginRec.Code) var beginResp map[string]any - require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp)) + require.NoError(t, json.Unmarshal(beginRec.Body.Bytes(), &beginResp, jsonx.V1())) txID := beginResp["transactionId"].(string) rec := doRDSDataRequest(t, h, tt.path, map[string]any{ @@ -569,7 +570,7 @@ func TestHandler_TransactionStatusConstants(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantStatus, resp["transactionStatus"], "transactionStatus must match exact AWS string") }) @@ -608,7 +609,7 @@ func TestHandler_TransactionNotFoundErrorType(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TransactionNotFoundException", resp["__type"], "path %s: error type must be TransactionNotFoundException", tt.path) }) @@ -629,7 +630,7 @@ func TestHandler_TransactionNotFoundErrorShape(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "TransactionNotFoundException", errResp["__type"]) assert.NotEmpty(t, errResp["message"]) } diff --git a/services/rdsdata/typehints.go b/services/rdsdata/typehints.go index b8b05bac86..4e082b335d 100644 --- a/services/rdsdata/typehints.go +++ b/services/rdsdata/typehints.go @@ -1,11 +1,13 @@ package rdsdata import ( - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "regexp" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // SqlParameter.TypeHint enum values (rdsdata@v1.35.4 types/enums.go's @@ -89,7 +91,7 @@ func validateTypeHintFormat(hint, value string) error { return fmt.Errorf("%w: %s requires a decimal number", errBadTypeHintValue, typeHintDecimal) } case typeHintJSON: - if !json.Valid([]byte(value)) { + if !jsontext.Value([]byte(value)).IsValid(jsonx.V1()) { return fmt.Errorf("%w: %s requires valid JSON", errBadTypeHintValue, typeHintJSON) } case typeHintUUID: diff --git a/services/redshift/handler_serverless.go b/services/redshift/handler_serverless.go index e08b248748..6effc32229 100644 --- a/services/redshift/handler_serverless.go +++ b/services/redshift/handler_serverless.go @@ -2,7 +2,8 @@ package redshift import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strings" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/awstime" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -197,7 +199,7 @@ func (h *ServerlessHandler) ExtractResource(c *echo.Context) string { WorkgroupName string `json:"workgroupName"` } - if json.Unmarshal(body, &probe) != nil { + if json.Unmarshal(body, &probe, jsonx.V1()) != nil { return "" } @@ -348,7 +350,7 @@ func (h *ServerlessHandler) handleCreateNamespace(c *echo.Context, body []byte) ManageAdminPassword bool `json:"manageAdminPassword"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -382,7 +384,7 @@ func (h *ServerlessHandler) handleGetNamespace(c *echo.Context, body []byte) err NamespaceName string `json:"namespaceName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -401,7 +403,7 @@ func (h *ServerlessHandler) handleListNamespaces(c *echo.Context, body []byte) e } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -429,7 +431,7 @@ func (h *ServerlessHandler) handleUpdateNamespace(c *echo.Context, body []byte) LogExports []string `json:"logExports"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -457,7 +459,7 @@ func (h *ServerlessHandler) handleDeleteNamespace(c *echo.Context, body []byte) FinalSnapshotRetentionPeriod int `json:"finalSnapshotRetentionPeriod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -514,7 +516,7 @@ func (r slWorkgroupReq) toParams() WorkgroupParams { func (h *ServerlessHandler) handleCreateWorkgroup(c *echo.Context, body []byte) error { var req slWorkgroupReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -535,7 +537,7 @@ func (h *ServerlessHandler) handleGetWorkgroup(c *echo.Context, body []byte) err WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -555,7 +557,7 @@ func (h *ServerlessHandler) handleListWorkgroups(c *echo.Context, body []byte) e } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -573,7 +575,7 @@ func (h *ServerlessHandler) handleListWorkgroups(c *echo.Context, body []byte) e func (h *ServerlessHandler) handleUpdateWorkgroup(c *echo.Context, body []byte) error { var req slWorkgroupReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -590,7 +592,7 @@ func (h *ServerlessHandler) handleDeleteWorkgroup(c *echo.Context, body []byte) WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -610,7 +612,7 @@ func (h *ServerlessHandler) handleGetCredentials(c *echo.Context, body []byte) e DurationSeconds int `json:"durationSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -659,7 +661,7 @@ func (h *ServerlessHandler) handleCreateSnapshot(c *echo.Context, body []byte) e RetentionPeriod int `json:"retentionPeriod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -680,7 +682,7 @@ func (h *ServerlessHandler) handleGetSnapshot(c *echo.Context, body []byte) erro OwnerAccount string `json:"ownerAccount"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -709,7 +711,7 @@ func (h *ServerlessHandler) handleListSnapshots(c *echo.Context, body []byte) er } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -737,7 +739,7 @@ func (h *ServerlessHandler) handleDeleteSnapshot(c *echo.Context, body []byte) e SnapshotName string `json:"snapshotName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -755,7 +757,7 @@ func (h *ServerlessHandler) handleUpdateSnapshot(c *echo.Context, body []byte) e SnapshotName string `json:"snapshotName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -784,7 +786,7 @@ func (h *ServerlessHandler) handleCreateUsageLimit(c *echo.Context, body []byte) Amount int64 `json:"amount"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -807,7 +809,7 @@ func (h *ServerlessHandler) handleGetUsageLimit(c *echo.Context, body []byte) er UsageLimitID string `json:"usageLimitId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -828,7 +830,7 @@ func (h *ServerlessHandler) handleListUsageLimits(c *echo.Context, body []byte) } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -850,7 +852,7 @@ func (h *ServerlessHandler) handleUpdateUsageLimit(c *echo.Context, body []byte) Amount int64 `json:"amount"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -867,7 +869,7 @@ func (h *ServerlessHandler) handleDeleteUsageLimit(c *echo.Context, body []byte) UsageLimitID string `json:"usageLimitId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -892,17 +894,17 @@ func (h *ServerlessHandler) handleDeleteUsageLimit(c *echo.Context, body []byte) // conversion at the response boundary, same pattern as // applicationautoscaling's epochSecondsPtr. type slScheduledActionWire struct { - StartTime *float64 `json:"startTime,omitempty"` - EndTime *float64 `json:"endTime,omitempty"` - NamespaceName string `json:"namespaceName,omitempty"` - RoleArn string `json:"roleArn,omitempty"` - ScheduledActionDescription string `json:"scheduledActionDescription,omitempty"` - ScheduledActionName string `json:"scheduledActionName"` - ScheduledActionUUID string `json:"scheduledActionUuid,omitempty"` - State string `json:"state"` - NextInvocations []float64 `json:"nextInvocations,omitempty"` - Schedule json.RawMessage `json:"schedule,omitempty"` - TargetAction json.RawMessage `json:"targetAction,omitempty"` + StartTime *float64 `json:"startTime,omitempty"` + EndTime *float64 `json:"endTime,omitempty"` + NamespaceName string `json:"namespaceName,omitempty"` + RoleArn string `json:"roleArn,omitempty"` + ScheduledActionDescription string `json:"scheduledActionDescription,omitempty"` + ScheduledActionName string `json:"scheduledActionName"` + ScheduledActionUUID string `json:"scheduledActionUuid,omitempty"` + State string `json:"state"` + NextInvocations []float64 `json:"nextInvocations,omitempty"` + Schedule jsontext.Value `json:"schedule,omitempty"` + TargetAction jsontext.Value `json:"targetAction,omitempty"` } func slEpochPtr(t time.Time) *float64 { @@ -933,18 +935,18 @@ func toScheduledActionWire(sa *ServerlessScheduledAction) *slScheduledActionWire func (h *ServerlessHandler) handleCreateScheduledAction(c *echo.Context, body []byte) error { var req struct { - Enabled *bool `json:"enabled"` - StartTime *float64 `json:"startTime"` - EndTime *float64 `json:"endTime"` - ScheduledActionName string `json:"scheduledActionName"` - NamespaceName string `json:"namespaceName"` - RoleArn string `json:"roleArn"` - ScheduledActionDescription string `json:"scheduledActionDescription"` - Schedule json.RawMessage `json:"schedule"` - TargetAction json.RawMessage `json:"targetAction"` - } - - if err := json.Unmarshal(body, &req); err != nil { + Enabled *bool `json:"enabled"` + StartTime *float64 `json:"startTime"` + EndTime *float64 `json:"endTime"` + ScheduledActionName string `json:"scheduledActionName"` + NamespaceName string `json:"namespaceName"` + RoleArn string `json:"roleArn"` + ScheduledActionDescription string `json:"scheduledActionDescription"` + Schedule jsontext.Value `json:"schedule"` + TargetAction jsontext.Value `json:"targetAction"` + } + + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -983,7 +985,7 @@ func (h *ServerlessHandler) handleGetScheduledAction(c *echo.Context, body []byt ScheduledActionName string `json:"scheduledActionName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1014,7 +1016,7 @@ func (h *ServerlessHandler) handleListScheduledActions(c *echo.Context, body []b } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -1040,17 +1042,17 @@ func (h *ServerlessHandler) handleListScheduledActions(c *echo.Context, body []b func (h *ServerlessHandler) handleUpdateScheduledAction(c *echo.Context, body []byte) error { var req struct { - ScheduledActionDescription *string `json:"scheduledActionDescription"` - Enabled *bool `json:"enabled"` - StartTime *float64 `json:"startTime"` - EndTime *float64 `json:"endTime"` - ScheduledActionName string `json:"scheduledActionName"` - RoleArn string `json:"roleArn"` - Schedule json.RawMessage `json:"schedule"` - TargetAction json.RawMessage `json:"targetAction"` + ScheduledActionDescription *string `json:"scheduledActionDescription"` + Enabled *bool `json:"enabled"` + StartTime *float64 `json:"startTime"` + EndTime *float64 `json:"endTime"` + ScheduledActionName string `json:"scheduledActionName"` + RoleArn string `json:"roleArn"` + Schedule jsontext.Value `json:"schedule"` + TargetAction jsontext.Value `json:"targetAction"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1075,7 +1077,7 @@ func (h *ServerlessHandler) handleDeleteScheduledAction(c *echo.Context, body [] ScheduledActionName string `json:"scheduledActionName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1096,7 +1098,7 @@ func (h *ServerlessHandler) handleGetTrack(c *echo.Context, body []byte) error { TrackName string `json:"trackName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1119,7 +1121,7 @@ func (h *ServerlessHandler) handleListTracks(c *echo.Context, body []byte) error } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -1148,7 +1150,7 @@ func (h *ServerlessHandler) handleUpdateLakehouseConfiguration(c *echo.Context, DryRun bool `json:"dryRun"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1180,7 +1182,7 @@ func (h *ServerlessHandler) handleGetIdentityCenterAuthTokenSL(c *echo.Context, WorkgroupNames []string `json:"workgroupNames"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1209,7 +1211,7 @@ func (h *ServerlessHandler) handleCreateReservation(c *echo.Context, body []byte Capacity int32 `json:"capacity"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1226,7 +1228,7 @@ func (h *ServerlessHandler) handleGetReservation(c *echo.Context, body []byte) e ReservationID string `json:"reservationId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1245,7 +1247,7 @@ func (h *ServerlessHandler) handleListReservations(c *echo.Context, body []byte) } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -1265,7 +1267,7 @@ func (h *ServerlessHandler) handleGetReservationOffering(c *echo.Context, body [ OfferingID string `json:"offeringId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -1284,7 +1286,7 @@ func (h *ServerlessHandler) handleListReservationOfferings(c *echo.Context, body } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } diff --git a/services/redshift/handler_serverless_custom_domains.go b/services/redshift/handler_serverless_custom_domains.go index 87d206127f..16bebe65b2 100644 --- a/services/redshift/handler_serverless_custom_domains.go +++ b/services/redshift/handler_serverless_custom_domains.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Create/Get/UpdateCustomDomainAssociationResponse all serialize the @@ -22,7 +24,7 @@ func (h *ServerlessHandler) handleCreateCustomDomainAssociation(c *echo.Context, WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -46,7 +48,7 @@ func (h *ServerlessHandler) handleGetCustomDomainAssociation(c *echo.Context, bo WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -67,7 +69,7 @@ func (h *ServerlessHandler) handleListCustomDomainAssociations(c *echo.Context, } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -91,7 +93,7 @@ func (h *ServerlessHandler) handleUpdateCustomDomainAssociation(c *echo.Context, WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -115,7 +117,7 @@ func (h *ServerlessHandler) handleDeleteCustomDomainAssociation(c *echo.Context, WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } diff --git a/services/redshift/handler_serverless_custom_domains_test.go b/services/redshift/handler_serverless_custom_domains_test.go index b51fe9013c..b27e0ee913 100644 --- a/services/redshift/handler_serverless_custom_domains_test.go +++ b/services/redshift/handler_serverless_custom_domains_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestServerless_CustomDomainAssociationCRUD covers Create/Get/List/Update/ @@ -29,7 +32,7 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) assert.Equal(t, "db.example.com", createResp["customDomainName"]) assert.Equal(t, "cd-wg", createResp["workgroupName"]) assert.NotContains(t, createResp, "association", "response is flat, not wrapped in an envelope key") @@ -39,7 +42,7 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var wgResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&wgResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &wgResp, jsonx.V1())) wgData, _ := wgResp["workgroup"].(map[string]any) require.NotNil(t, wgData) assert.Equal(t, "db.example.com", wgData["customDomainName"]) @@ -56,7 +59,7 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) assocs, _ := listResp["associations"].([]any) require.Len(t, assocs, 1) @@ -65,7 +68,7 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var credResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&credResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &credResp, jsonx.V1())) dbUser, _ := credResp["dbUser"].(string) assert.NotEmpty(t, dbUser) @@ -77,7 +80,7 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) assert.Equal(t, "arn:aws:acm:us-east-1:000000000000:certificate/def", updateResp["customDomainCertificateArn"]) rec = doServerlessOp(t, h, "DeleteCustomDomainAssociation", map[string]any{ @@ -87,13 +90,13 @@ func TestServerless_CustomDomainAssociationCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&deleteResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &deleteResp, jsonx.V1())) assert.Empty(t, deleteResp, "DeleteCustomDomainAssociationResponse has zero members on the real wire") // The mirrored workgroup fields are cleared too. rec = doServerlessOp(t, h, "GetWorkgroup", map[string]any{"workgroupName": "cd-wg"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.NewDecoder(rec.Body).Decode(&wgResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &wgResp, jsonx.V1())) wgData, _ = wgResp["workgroup"].(map[string]any) assert.NotContains(t, wgData, "customDomainName") @@ -143,7 +146,7 @@ func TestServerless_CustomDomainAssociation_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -172,7 +175,7 @@ func TestServerless_CustomDomainAssociation_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) }) @@ -185,7 +188,7 @@ func TestServerless_CustomDomainAssociation_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) }) @@ -198,7 +201,7 @@ func TestServerless_CustomDomainAssociation_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) }) } diff --git a/services/redshift/handler_serverless_endpoint_access.go b/services/redshift/handler_serverless_endpoint_access.go index 7e6e8c360a..52a84a61ee 100644 --- a/services/redshift/handler_serverless_endpoint_access.go +++ b/services/redshift/handler_serverless_endpoint_access.go @@ -1,11 +1,13 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // slVpcSecurityGroupMembership mirrors types.VpcSecurityGroupMembership -- @@ -61,7 +63,7 @@ func (h *ServerlessHandler) handleCreateEndpointAccessSL(c *echo.Context, body [ VpcSecurityGroupIDs []string `json:"vpcSecurityGroupIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -80,7 +82,7 @@ func (h *ServerlessHandler) handleGetEndpointAccessSL(c *echo.Context, body []by EndpointName string `json:"endpointName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -108,7 +110,7 @@ func (h *ServerlessHandler) handleListEndpointAccessSL(c *echo.Context, body []b } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -135,7 +137,7 @@ func (h *ServerlessHandler) handleUpdateEndpointAccessSL(c *echo.Context, body [ VpcSecurityGroupIDs []string `json:"vpcSecurityGroupIds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -152,7 +154,7 @@ func (h *ServerlessHandler) handleDeleteEndpointAccessSL(c *echo.Context, body [ EndpointName string `json:"endpointName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -175,7 +177,7 @@ func (h *ServerlessHandler) handleListManagedWorkgroups(c *echo.Context, body [] } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } diff --git a/services/redshift/handler_serverless_endpoint_access_test.go b/services/redshift/handler_serverless_endpoint_access_test.go index aab95da2f0..d54f9e2917 100644 --- a/services/redshift/handler_serverless_endpoint_access_test.go +++ b/services/redshift/handler_serverless_endpoint_access_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_EndpointAccess_CRUD(t *testing.T) { @@ -27,7 +30,7 @@ func TestServerless_EndpointAccess_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) ep, _ := createResp["endpoint"].(map[string]any) require.NotNil(t, ep) assert.Equal(t, "ea-endpoint", ep["endpointName"]) @@ -46,7 +49,7 @@ func TestServerless_EndpointAccess_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) got, _ := getResp["endpoint"].(map[string]any) require.NotNil(t, got) assert.Equal(t, "ea-endpoint", got["endpointName"]) @@ -55,7 +58,7 @@ func TestServerless_EndpointAccess_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) list, _ := listResp["endpoints"].([]any) require.Len(t, list, 1) @@ -66,7 +69,7 @@ func TestServerless_EndpointAccess_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) updated, _ := updateResp["endpoint"].(map[string]any) require.NotNil(t, updated) groups, _ = updated["vpcSecurityGroups"].([]any) @@ -76,7 +79,7 @@ func TestServerless_EndpointAccess_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&deleteResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &deleteResp, jsonx.V1())) deleted, _ := deleteResp["endpoint"].(map[string]any) require.NotNil(t, deleted, "DeleteEndpointAccessResponse echoes the deleted object on the real wire") assert.Equal(t, "ea-endpoint", deleted["endpointName"]) @@ -149,7 +152,7 @@ func TestServerless_EndpointAccess_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -173,7 +176,7 @@ func TestServerless_EndpointAccess_DuplicateName(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) } @@ -186,7 +189,7 @@ func TestServerless_ListManagedWorkgroups_AlwaysEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) list, ok := resp["managedWorkgroups"].([]any) require.True(t, ok, "managedWorkgroups must be a correctly-shaped (empty) array, not absent") assert.Empty(t, list) diff --git a/services/redshift/handler_serverless_gaps_test.go b/services/redshift/handler_serverless_gaps_test.go index fe8b4e9af7..b005ec26ba 100644 --- a/services/redshift/handler_serverless_gaps_test.go +++ b/services/redshift/handler_serverless_gaps_test.go @@ -1,7 +1,8 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshift" ) @@ -36,7 +38,7 @@ func TestServerless_UpdateNamespace_DBNameNotMutated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) ns, _ := resp["namespace"].(map[string]any) require.NotNil(t, ns) assert.Equal(t, "original", ns["dbName"], "UpdateNamespace's dbName must be silently ignored, not applied") @@ -64,7 +66,7 @@ func TestServerless_Namespace_AdminUserPassword_NeverEchoed(t *testing.T) { assert.NotContains(t, body, "s3cr3t-Passw0rd") var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) ns, _ := createResp["namespace"].(map[string]any) require.NotNil(t, ns) _, hasPassword := ns["adminUserPassword"] @@ -155,7 +157,7 @@ func TestServerless_ListSnapshots_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var nsResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&nsResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &nsResp, jsonx.V1())) ns, _ := nsResp["namespace"].(map[string]any) require.NotNil(t, ns) nsArn, _ := ns["namespaceArn"].(string) @@ -165,7 +167,7 @@ func TestServerless_ListSnapshots_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var allResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&allResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &allResp, jsonx.V1())) allSnaps, _ := allResp["snapshots"].([]any) require.Len(t, allSnaps, 3, "sanity: three snapshots exist before filtering") @@ -173,7 +175,7 @@ func TestServerless_ListSnapshots_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var filteredResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&filteredResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &filteredResp, jsonx.V1())) filtered, _ := filteredResp["snapshots"].([]any) assert.Len(t, filtered, 2, "namespaceArn filter must narrow to only lsf-ns-a's snapshots") @@ -186,7 +188,7 @@ func TestServerless_ListSnapshots_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var otherAcctResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&otherAcctResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &otherAcctResp, jsonx.V1())) otherAcctSnaps, _ := otherAcctResp["snapshots"].([]any) assert.Empty(t, otherAcctSnaps, "no snapshot in a single-account backend can be owned by another account") @@ -194,7 +196,7 @@ func TestServerless_ListSnapshots_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var ownAcctResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ownAcctResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ownAcctResp, jsonx.V1())) ownAcctSnaps, _ := ownAcctResp["snapshots"].([]any) assert.Len(t, ownAcctSnaps, 3) } @@ -220,7 +222,7 @@ func TestServerless_GetSnapshot_OwnerAccount(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -239,7 +241,7 @@ func TestServerless_ListWorkgroups_OwnerAccount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var ownResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&ownResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &ownResp, jsonx.V1())) own, _ := ownResp["workgroups"].([]any) require.Len(t, own, 2, "sanity: two workgroups exist and match this backend's own account") @@ -247,7 +249,7 @@ func TestServerless_ListWorkgroups_OwnerAccount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var otherResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&otherResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &otherResp, jsonx.V1())) other, _ := otherResp["workgroups"].([]any) assert.Empty(t, other, "ownerAccount filter must narrow to zero for an account this backend never owns") } @@ -275,7 +277,7 @@ func TestServerless_ListUsageLimits_UsageType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var allResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&allResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &allResp, jsonx.V1())) all, _ := allResp["usageLimits"].([]any) require.Len(t, all, 2, "sanity: two usage limits exist before filtering") @@ -283,7 +285,7 @@ func TestServerless_ListUsageLimits_UsageType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var filteredResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&filteredResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &filteredResp, jsonx.V1())) filtered, _ := filteredResp["usageLimits"].([]any) require.Len(t, filtered, 1, "usageType filter must narrow to the single matching limit") got, _ := filtered[0].(map[string]any) diff --git a/services/redshift/handler_serverless_idc_token_test.go b/services/redshift/handler_serverless_idc_token_test.go index 1eed87a897..bd8a95be45 100644 --- a/services/redshift/handler_serverless_idc_token_test.go +++ b/services/redshift/handler_serverless_idc_token_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_GetIdentityCenterAuthToken(t *testing.T) { @@ -28,7 +31,7 @@ func TestServerless_GetIdentityCenterAuthToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) token1, _ := resp["token"].(string) require.NotEmpty(t, token1) @@ -40,7 +43,7 @@ func TestServerless_GetIdentityCenterAuthToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp2 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp2, jsonx.V1())) token2, _ := resp2["token"].(string) require.NotEmpty(t, token2) @@ -86,7 +89,7 @@ func TestServerless_GetIdentityCenterAuthToken_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -113,6 +116,6 @@ func TestServerless_GetIdentityCenterAuthToken_OneUnknownAmongMany(t *testing.T) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } diff --git a/services/redshift/handler_serverless_lakehouse_test.go b/services/redshift/handler_serverless_lakehouse_test.go index 8eb1b09501..734613e0d3 100644 --- a/services/redshift/handler_serverless_lakehouse_test.go +++ b/services/redshift/handler_serverless_lakehouse_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_UpdateLakehouseConfiguration_Errors(t *testing.T) { @@ -42,7 +45,7 @@ func TestServerless_UpdateLakehouseConfiguration_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -68,14 +71,14 @@ func TestServerless_UpdateLakehouseConfiguration_DryRun(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "DryRunException", errResp["__type"]) rec = doServerlessOp(t, h, "GetNamespace", map[string]any{"namespaceName": "lh-dryrun-ns"}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) ns, _ := getResp["namespace"].(map[string]any) require.NotNil(t, ns) assert.Empty(t, ns["catalogArn"], "dry run must not mutate the namespace's catalogArn") @@ -104,7 +107,7 @@ func TestServerless_UpdateLakehouseConfiguration_RegisterAndAssociate(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "lh-ns", resp["namespaceName"]) assert.Contains(t, resp["catalogArn"], "mycatalog") assert.Equal(t, "Registered", resp["lakehouseRegistrationStatus"]) @@ -114,7 +117,7 @@ func TestServerless_UpdateLakehouseConfiguration_RegisterAndAssociate(t *testing require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) ns, _ := getResp["namespace"].(map[string]any) require.NotNil(t, ns) assert.Contains(t, ns["catalogArn"], "mycatalog") @@ -131,7 +134,7 @@ func TestServerless_UpdateLakehouseConfiguration_RegisterAndAssociate(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp2 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp2, jsonx.V1())) assert.Equal(t, "Deregistered", resp2["lakehouseRegistrationStatus"]) assert.Equal(t, "arn:aws:sso::000000000000:application/idc-app-1", resp2["lakehouseIdcApplicationArn"]) @@ -143,6 +146,6 @@ func TestServerless_UpdateLakehouseConfiguration_RegisterAndAssociate(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp3 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp3)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp3, jsonx.V1())) assert.NotContains(t, resp3, "lakehouseIdcApplicationArn") } diff --git a/services/redshift/handler_serverless_recovery.go b/services/redshift/handler_serverless_recovery.go index f60c2f48c4..712ad998c8 100644 --- a/services/redshift/handler_serverless_recovery.go +++ b/services/redshift/handler_serverless_recovery.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *ServerlessHandler) handleGetRecoveryPoint(c *echo.Context, body []byte) error { @@ -12,7 +14,7 @@ func (h *ServerlessHandler) handleGetRecoveryPoint(c *echo.Context, body []byte) RecoveryPointID string `json:"recoveryPointId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -39,7 +41,7 @@ func (h *ServerlessHandler) handleListRecoveryPoints(c *echo.Context, body []byt } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } @@ -69,7 +71,7 @@ func (h *ServerlessHandler) handleRestoreFromRecoveryPoint(c *echo.Context, body WorkgroupName string `json:"workgroupName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } diff --git a/services/redshift/handler_serverless_recovery_test.go b/services/redshift/handler_serverless_recovery_test.go index 27357e2920..a4c2b5cc2a 100644 --- a/services/redshift/handler_serverless_recovery_test.go +++ b/services/redshift/handler_serverless_recovery_test.go @@ -1,13 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshift" ) @@ -31,7 +33,7 @@ func seedNamespaceAndWorkgroup( require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) points, _ := listResp["recoveryPoints"].([]any) require.Len(t, points, 1, "CreateWorkgroup must generate exactly one recovery point") @@ -57,7 +59,7 @@ func TestServerless_RecoveryPoint_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) got, _ := getResp["recoveryPoint"].(map[string]any) require.NotNil(t, got) assert.Equal(t, recoveryPointID, got["recoveryPointId"]) @@ -70,7 +72,7 @@ func TestServerless_RecoveryPoint_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var restoreResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&restoreResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &restoreResp, jsonx.V1())) assert.Equal(t, recoveryPointID, restoreResp["recoveryPointId"]) ns, _ := restoreResp["namespace"].(map[string]any) require.NotNil(t, ns) @@ -129,7 +131,7 @@ func TestServerless_RecoveryPoint_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -154,7 +156,7 @@ func TestServerless_RestoreFromRecoveryPoint_WorkgroupNamespaceMismatch(t *testi require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) points, _ := listResp["recoveryPoints"].([]any) require.Len(t, points, 1) rp, _ := points[0].(map[string]any) @@ -168,6 +170,6 @@ func TestServerless_RestoreFromRecoveryPoint_WorkgroupNamespaceMismatch(t *testi require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) } diff --git a/services/redshift/handler_serverless_resource_policy.go b/services/redshift/handler_serverless_resource_policy.go index cec9c04f2b..18a039986a 100644 --- a/services/redshift/handler_serverless_resource_policy.go +++ b/services/redshift/handler_serverless_resource_policy.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *ServerlessHandler) handleGetResourcePolicySL(c *echo.Context, body []byte) error { @@ -12,7 +14,7 @@ func (h *ServerlessHandler) handleGetResourcePolicySL(c *echo.Context, body []by ResourceArn string `json:"resourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -34,7 +36,7 @@ func (h *ServerlessHandler) handlePutResourcePolicySL(c *echo.Context, body []by Policy string `json:"policy"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -55,7 +57,7 @@ func (h *ServerlessHandler) handleDeleteResourcePolicySL(c *echo.Context, body [ ResourceArn string `json:"resourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } diff --git a/services/redshift/handler_serverless_resource_policy_test.go b/services/redshift/handler_serverless_resource_policy_test.go index 8769de09bf..60f753262f 100644 --- a/services/redshift/handler_serverless_resource_policy_test.go +++ b/services/redshift/handler_serverless_resource_policy_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_ResourcePolicy_CRUD(t *testing.T) { @@ -23,7 +26,7 @@ func TestServerless_ResourcePolicy_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&putResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &putResp, jsonx.V1())) rp, _ := putResp["resourcePolicy"].(map[string]any) require.NotNil(t, rp) assert.Equal(t, resourceArn, rp["resourceArn"]) @@ -33,7 +36,7 @@ func TestServerless_ResourcePolicy_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) rp, _ = getResp["resourcePolicy"].(map[string]any) require.NotNil(t, rp) assert.Equal(t, policy, rp["policy"]) @@ -42,7 +45,7 @@ func TestServerless_ResourcePolicy_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&deleteResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &deleteResp, jsonx.V1())) assert.Empty(t, deleteResp, "DeleteResourcePolicyResponse has zero members on the real wire") rec = doServerlessOp(t, h, "GetResourcePolicy", map[string]any{"resourceArn": resourceArn}) @@ -105,7 +108,7 @@ func TestServerless_ResourcePolicy_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } diff --git a/services/redshift/handler_serverless_restore.go b/services/redshift/handler_serverless_restore.go index 6736681278..efd10066a4 100644 --- a/services/redshift/handler_serverless_restore.go +++ b/services/redshift/handler_serverless_restore.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *ServerlessHandler) handleRestoreFromSnapshot(c *echo.Context, body []byte) error { @@ -19,7 +21,7 @@ func (h *ServerlessHandler) handleRestoreFromSnapshot(c *echo.Context, body []by ManageAdminPassword bool `json:"manageAdminPassword"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -64,7 +66,7 @@ func (h *ServerlessHandler) handleConvertRecoveryPointToSnapshot(c *echo.Context RetentionPeriod int `json:"retentionPeriod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } diff --git a/services/redshift/handler_serverless_restore_test.go b/services/redshift/handler_serverless_restore_test.go index a859a476ca..7b2b95ea90 100644 --- a/services/redshift/handler_serverless_restore_test.go +++ b/services/redshift/handler_serverless_restore_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_RestoreFromSnapshot(t *testing.T) { @@ -26,7 +29,7 @@ func TestServerless_RestoreFromSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "rfs-snap", resp["snapshotName"]) ns, _ := resp["namespace"].(map[string]any) require.NotNil(t, ns) @@ -76,7 +79,7 @@ func TestServerless_RestoreFromSnapshot_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -104,7 +107,7 @@ func TestServerless_RestoreFromSnapshot_WorkgroupNamespaceMismatch(t *testing.T) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) } @@ -123,7 +126,7 @@ func TestServerless_ConvertRecoveryPointToSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) snap, _ := resp["snapshot"].(map[string]any) require.NotNil(t, snap) assert.Equal(t, "crp-snap", snap["snapshotName"]) @@ -167,7 +170,7 @@ func TestServerless_ConvertRecoveryPointToSnapshot_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -191,6 +194,6 @@ func TestServerless_ConvertRecoveryPointToSnapshot_DuplicateName(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) } diff --git a/services/redshift/handler_serverless_snapshot_copy_config.go b/services/redshift/handler_serverless_snapshot_copy_config.go index 60a0c02140..0ed92be44d 100644 --- a/services/redshift/handler_serverless_snapshot_copy_config.go +++ b/services/redshift/handler_serverless_snapshot_copy_config.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *ServerlessHandler) handleCreateSnapshotCopyConfigurationSL(c *echo.Context, body []byte) error { @@ -15,7 +17,7 @@ func (h *ServerlessHandler) handleCreateSnapshotCopyConfigurationSL(c *echo.Cont SnapshotRetentionPeriod int `json:"snapshotRetentionPeriod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -39,7 +41,7 @@ func (h *ServerlessHandler) handleUpdateSnapshotCopyConfigurationSL(c *echo.Cont SnapshotRetentionPeriod int `json:"snapshotRetentionPeriod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -62,7 +64,7 @@ func (h *ServerlessHandler) handleDeleteSnapshotCopyConfigurationSL(c *echo.Cont SnapshotCopyConfigurationID string `json:"snapshotCopyConfigurationId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -89,7 +91,7 @@ func (h *ServerlessHandler) handleListSnapshotCopyConfigurationsSL(c *echo.Conte } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } diff --git a/services/redshift/handler_serverless_snapshot_copy_config_test.go b/services/redshift/handler_serverless_snapshot_copy_config_test.go index 9642aad5c9..f318a6aafb 100644 --- a/services/redshift/handler_serverless_snapshot_copy_config_test.go +++ b/services/redshift/handler_serverless_snapshot_copy_config_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_SnapshotCopyConfiguration_CRUD(t *testing.T) { @@ -23,7 +26,7 @@ func TestServerless_SnapshotCopyConfiguration_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) cfg, _ := createResp["snapshotCopyConfiguration"].(map[string]any) require.NotNil(t, cfg) assert.Equal(t, "scc-ns", cfg["namespaceName"]) @@ -37,7 +40,7 @@ func TestServerless_SnapshotCopyConfiguration_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) list, _ := listResp["snapshotCopyConfigurations"].([]any) require.Len(t, list, 1) @@ -48,7 +51,7 @@ func TestServerless_SnapshotCopyConfiguration_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) cfg, _ = updateResp["snapshotCopyConfiguration"].(map[string]any) require.NotNil(t, cfg) assert.InEpsilon(t, float64(30), cfg["snapshotRetentionPeriod"], 0) @@ -59,14 +62,14 @@ func TestServerless_SnapshotCopyConfiguration_CRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&deleteResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &deleteResp, jsonx.V1())) cfg, _ = deleteResp["snapshotCopyConfiguration"].(map[string]any) require.NotNil(t, cfg, "DeleteSnapshotCopyConfigurationResponse echoes the deleted object on the real wire") assert.Equal(t, id, cfg["snapshotCopyConfigurationId"]) rec = doServerlessOp(t, h, "ListSnapshotCopyConfigurations", map[string]any{"namespaceName": "scc-ns"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) list, _ = listResp["snapshotCopyConfigurations"].([]any) assert.Empty(t, list) } @@ -114,7 +117,7 @@ func TestServerless_SnapshotCopyConfiguration_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } diff --git a/services/redshift/handler_serverless_table_restore.go b/services/redshift/handler_serverless_table_restore.go index a063770ca7..0b42f554f8 100644 --- a/services/redshift/handler_serverless_table_restore.go +++ b/services/redshift/handler_serverless_table_restore.go @@ -1,10 +1,12 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // slTableRestoreStatusWire is the wire shape for ServerlessTableRestoreStatus @@ -73,7 +75,7 @@ func (r slTableRestoreReq) toParams() RestoreTableFromSnapshotParams { func (h *ServerlessHandler) handleRestoreTableFromSnapshot(c *echo.Context, body []byte) error { var req slTableRestoreReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -96,7 +98,7 @@ func (h *ServerlessHandler) handleRestoreTableFromSnapshot(c *echo.Context, body func (h *ServerlessHandler) handleRestoreTableFromRecoveryPoint(c *echo.Context, body []byte) error { var req slTableRestoreReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -121,7 +123,7 @@ func (h *ServerlessHandler) handleGetTableRestoreStatus(c *echo.Context, body [] TableRestoreRequestID string `json:"tableRestoreRequestId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -146,7 +148,7 @@ func (h *ServerlessHandler) handleListTableRestoreStatus(c *echo.Context, body [ } if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } } diff --git a/services/redshift/handler_serverless_table_restore_test.go b/services/redshift/handler_serverless_table_restore_test.go index e9e5fff896..6fcadcb5b8 100644 --- a/services/redshift/handler_serverless_table_restore_test.go +++ b/services/redshift/handler_serverless_table_restore_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_TableRestore_FromSnapshotAndRecoveryPoint(t *testing.T) { @@ -32,7 +35,7 @@ func TestServerless_TableRestore_FromSnapshotAndRecoveryPoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fromSnapResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fromSnapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fromSnapResp, jsonx.V1())) status1, _ := fromSnapResp["tableRestoreStatus"].(map[string]any) require.NotNil(t, status1) assert.Equal(t, "SUCCEEDED", status1["status"]) @@ -53,7 +56,7 @@ func TestServerless_TableRestore_FromSnapshotAndRecoveryPoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var fromRPResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&fromRPResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &fromRPResp, jsonx.V1())) status2, _ := fromRPResp["tableRestoreStatus"].(map[string]any) require.NotNil(t, status2) assert.Equal(t, recoveryPointID, status2["recoveryPointId"]) @@ -65,7 +68,7 @@ func TestServerless_TableRestore_FromSnapshotAndRecoveryPoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) got, _ := getResp["tableRestoreStatus"].(map[string]any) require.NotNil(t, got) assert.Equal(t, requestID1, got["tableRestoreRequestId"]) @@ -74,7 +77,7 @@ func TestServerless_TableRestore_FromSnapshotAndRecoveryPoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) list, _ := listResp["tableRestoreStatuses"].([]any) assert.Len(t, list, 2) } @@ -149,7 +152,7 @@ func TestServerless_TableRestore_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } diff --git a/services/redshift/handler_serverless_tagging.go b/services/redshift/handler_serverless_tagging.go index c8486e2849..f0a9ee7a5f 100644 --- a/services/redshift/handler_serverless_tagging.go +++ b/services/redshift/handler_serverless_tagging.go @@ -1,11 +1,13 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // slTagWire is the wire shape of a single Redshift Serverless tag -- a @@ -56,7 +58,7 @@ func (h *ServerlessHandler) handleTagResource(c *echo.Context, body []byte) erro Tags []slTagWire `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -77,7 +79,7 @@ func (h *ServerlessHandler) handleUntagResource(c *echo.Context, body []byte) er TagKeys []string `json:"tagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } @@ -97,7 +99,7 @@ func (h *ServerlessHandler) handleListTagsForResource(c *echo.Context, body []by ResourceArn string `json:"resourceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return slBadRequest(c, "invalid request body") } diff --git a/services/redshift/handler_serverless_tagging_test.go b/services/redshift/handler_serverless_tagging_test.go index 33564331a0..ea6254f83e 100644 --- a/services/redshift/handler_serverless_tagging_test.go +++ b/services/redshift/handler_serverless_tagging_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestServerless_TagResource_RoundTrip proves creation-time Tags on @@ -28,7 +31,7 @@ func TestServerless_TagResource_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) nsData, _ := createResp["namespace"].(map[string]any) require.NotNil(t, nsData) nsArn, _ := nsData["namespaceArn"].(string) @@ -42,7 +45,7 @@ func TestServerless_TagResource_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) tagList, _ := listResp["tags"].([]any) require.Len(t, tagList, 1) @@ -61,7 +64,7 @@ func TestServerless_TagResource_RoundTrip(t *testing.T) { rec = doServerlessOp(t, h, "ListTagsForResource", map[string]any{"resourceArn": nsArn}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) tagList, _ = listResp["tags"].([]any) assert.Len(t, tagList, 2) @@ -73,7 +76,7 @@ func TestServerless_TagResource_RoundTrip(t *testing.T) { rec = doServerlessOp(t, h, "ListTagsForResource", map[string]any{"resourceArn": nsArn}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) tagList, _ = listResp["tags"].([]any) require.Len(t, tagList, 1) @@ -99,7 +102,7 @@ func TestServerless_TagResource_WorkgroupAndSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var wgResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&wgResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &wgResp, jsonx.V1())) wgData, _ := wgResp["workgroup"].(map[string]any) wgArn, _ := wgData["workgroupArn"].(string) require.NotEmpty(t, wgArn) @@ -108,7 +111,7 @@ func TestServerless_TagResource_WorkgroupAndSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) tagList, _ := listResp["tags"].([]any) require.Len(t, tagList, 1) @@ -120,14 +123,14 @@ func TestServerless_TagResource_WorkgroupAndSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var snapResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&snapResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &snapResp, jsonx.V1())) snapData, _ := snapResp["snapshot"].(map[string]any) snapArn, _ := snapData["snapshotArn"].(string) require.NotEmpty(t, snapArn) rec = doServerlessOp(t, h, "ListTagsForResource", map[string]any{"resourceArn": snapArn}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) tagList, _ = listResp["tags"].([]any) assert.Len(t, tagList, 1) } @@ -174,7 +177,7 @@ func TestServerless_TagResource_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) }) } @@ -190,7 +193,7 @@ func TestServerless_TagResource_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) }) @@ -205,7 +208,7 @@ func TestServerless_TagResource_Errors(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) }) } diff --git a/services/redshift/handler_serverless_test.go b/services/redshift/handler_serverless_test.go index cb961f6311..2d26eaf7af 100644 --- a/services/redshift/handler_serverless_test.go +++ b/services/redshift/handler_serverless_test.go @@ -2,7 +2,8 @@ package redshift_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshift" ) @@ -34,7 +36,7 @@ func doServerlessOp( var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) } else { @@ -108,7 +110,7 @@ func TestServerless_NamespaceCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) nsData, _ := createResp["namespace"].(map[string]any) require.NotNil(t, nsData) assert.Equal(t, "arn:aws:iam::000000000000:role/default", nsData["defaultIamRoleArn"]) @@ -132,7 +134,7 @@ func TestServerless_NamespaceCRUD(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -155,7 +157,7 @@ func TestServerless_DeleteNamespace_WithFinalSnapshot(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) snap, _ := resp["snapshot"].(map[string]any) require.NotNil(t, snap) assert.InEpsilon(t, float64(14), snap["snapshotRetentionPeriod"], 0) @@ -182,7 +184,7 @@ func TestServerless_WorkgroupCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) wgData, _ := createResp["workgroup"].(map[string]any) require.NotNil(t, wgData) assert.InEpsilon(t, float64(64), wgData["maxCapacity"], 0) @@ -200,7 +202,7 @@ func TestServerless_WorkgroupCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var credResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&credResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &credResp, jsonx.V1())) // Expiration is wire-encoded as a JSON number (epoch seconds), not an // RFC3339 string -- see the wire-shape audit note in handler_serverless.go. _, isNumber := credResp["expiration"].(float64) @@ -247,7 +249,7 @@ func TestServerless_SnapshotCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) updated, _ := updateResp["snapshot"].(map[string]any) require.NotNil(t, updated) assert.InEpsilon(t, float64(30), updated["snapshotRetentionPeriod"], 0) @@ -256,7 +258,7 @@ func TestServerless_SnapshotCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) got, _ := getResp["snapshot"].(map[string]any) require.NotNil(t, got) assert.InEpsilon(t, float64(30), got["snapshotRetentionPeriod"], 0, @@ -285,7 +287,7 @@ func TestServerless_UsageLimitsCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) ulData, _ := createResp["usageLimit"].(map[string]any) ulID := "" @@ -333,7 +335,7 @@ func TestServerless_ScheduledActionCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&createResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &createResp, jsonx.V1())) saData, _ := createResp["scheduledAction"].(map[string]any) require.NotNil(t, saData) assert.Equal(t, "DISABLED", saData["state"], "state (not status) is the real wire key") @@ -362,7 +364,7 @@ func TestServerless_ScheduledActionCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&updateResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &updateResp, jsonx.V1())) updated, _ := updateResp["scheduledAction"].(map[string]any) require.NotNil(t, updated) assert.Equal(t, "ACTIVE", updated["state"]) diff --git a/services/redshift/handler_serverless_tracks_test.go b/services/redshift/handler_serverless_tracks_test.go index bde435ea76..70a0603c1a 100644 --- a/services/redshift/handler_serverless_tracks_test.go +++ b/services/redshift/handler_serverless_tracks_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_GetTrack(t *testing.T) { @@ -55,7 +58,7 @@ func TestServerless_GetTrack(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) if tt.wantFound { track, _ := resp["track"].(map[string]any) @@ -80,7 +83,7 @@ func TestServerless_ListTracks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) tracks, _ := resp["tracks"].([]any) require.Len(t, tracks, 2, "real Redshift Serverless exposes exactly two maintenance tracks") @@ -105,7 +108,7 @@ func TestServerless_ListTracks_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&page1)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &page1, jsonx.V1())) tracks1, _ := page1["tracks"].([]any) require.Len(t, tracks1, 1) @@ -117,7 +120,7 @@ func TestServerless_ListTracks_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&page2)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &page2, jsonx.V1())) tracks2, _ := page2["tracks"].([]any) require.Len(t, tracks2, 1) diff --git a/services/redshift/handler_serverless_update_snapshot_test.go b/services/redshift/handler_serverless_update_snapshot_test.go index 1d9f741653..12ec5f3e04 100644 --- a/services/redshift/handler_serverless_update_snapshot_test.go +++ b/services/redshift/handler_serverless_update_snapshot_test.go @@ -1,12 +1,15 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestServerless_UpdateSnapshot_Errors(t *testing.T) { @@ -42,7 +45,7 @@ func TestServerless_UpdateSnapshot_Errors(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -70,7 +73,7 @@ func TestServerless_UpdateSnapshot_OmittedRetentionPeriodUnchanged(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) snap, _ := resp["snapshot"].(map[string]any) require.NotNil(t, snap) assert.InEpsilon(t, float64(14), snap["snapshotRetentionPeriod"], 0) diff --git a/services/redshift/multi_region_test.go b/services/redshift/multi_region_test.go index ff5d188dd0..999acf08be 100644 --- a/services/redshift/multi_region_test.go +++ b/services/redshift/multi_region_test.go @@ -1,7 +1,8 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshift" ) @@ -129,9 +131,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/redshift/persistence.go b/services/redshift/persistence.go index 3585be85c0..3703325374 100644 --- a/services/redshift/persistence.go +++ b/services/redshift/persistence.go @@ -2,9 +2,11 @@ package redshift import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -34,7 +36,7 @@ const redshiftSnapshotVersion = 1 // each is keyed externally by clusterID rather than by a field on the value // itself), plus backend-level scalar configuration. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ActiveResizes map[string]*ResizeProgress `json:"activeResizes"` SnapshotCopyConfigs map[string]*SnapshotCopyConfig `json:"snapshotCopyConfigs"` LoggingStatuses map[string]*LoggingStatus `json:"loggingStatuses"` @@ -84,7 +86,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "redshift: failed to marshal snapshot", "error", err) diff --git a/services/redshift/persistence_test.go b/services/redshift/persistence_test.go index e2c497e10a..a43db5f883 100644 --- a/services/redshift/persistence_test.go +++ b/services/redshift/persistence_test.go @@ -1,7 +1,8 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshift" ) @@ -334,8 +336,8 @@ func TestInMemoryBackend_FullStateRoundTrip(t *testing.T) { ScheduledActionName: "rt-slscheduledaction", NamespaceName: "rt-namespace", RoleArn: "arn:aws:iam::000000000000:role/scheduler", - Schedule: json.RawMessage(`{"at":1893456000}`), - TargetAction: json.RawMessage( + Schedule: jsontext.Value(`{"at":1893456000}`), + TargetAction: jsontext.Value( `{"createSnapshot":{"namespaceName":"rt-namespace","snapshotName":"rt-slsnapshot2"}}`, ), StartTime: time.Now(), @@ -661,8 +663,8 @@ func TestPersistence_ScheduledActionWindowSurvivesRestore(t *testing.T) { ScheduledActionName: "sa-rt-action", NamespaceName: "sa-rt-ns", RoleArn: "arn:aws:iam::000000000000:role/scheduler", - Schedule: json.RawMessage(`{"cron":"0 10 ? * MON *"}`), - TargetAction: json.RawMessage( + Schedule: jsontext.Value(`{"cron":"0 10 ? * MON *"}`), + TargetAction: jsontext.Value( `{"createSnapshot":{"namespaceName":"sa-rt-ns","snapshotName":"sa-rt-snap"}}`, ), StartTime: tt.startTime, @@ -686,7 +688,7 @@ func TestPersistence_ScheduledActionWindowSurvivesRestore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) saData, _ := resp["scheduledAction"].(map[string]any) require.NotNil(t, saData) diff --git a/services/redshift/schedule.go b/services/redshift/schedule.go index f1867e9c02..ce7b195268 100644 --- a/services/redshift/schedule.go +++ b/services/redshift/schedule.go @@ -1,12 +1,13 @@ package redshift import ( - "encoding/json" + "encoding/json/v2" "strings" "time" "github.com/blackbirdworks/gopherstack/pkgs/awscron" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxNextInvocations bounds how many upcoming ScheduledActionTime entries this @@ -133,7 +134,7 @@ func slNextInvocations(sa *ServerlessScheduledAction, now time.Time) []float64 { Cron string `json:"cron"` } - if json.Unmarshal(sa.Schedule, &sched) != nil { + if json.Unmarshal(sa.Schedule, &sched, jsonx.V1()) != nil { return nil } diff --git a/services/redshift/serverless.go b/services/redshift/serverless.go index 63ff14b396..ffa73f7439 100644 --- a/services/redshift/serverless.go +++ b/services/redshift/serverless.go @@ -3,7 +3,7 @@ package redshift import ( "crypto/rand" "encoding/hex" - "encoding/json" + "encoding/json/jsontext" "errors" "strconv" "time" @@ -253,16 +253,16 @@ type ServerlessUsageLimit struct { // unlike opensearch's DataSourceAttachment) and the registry marshals the live // struct with its own tags (gopherstack-n746d). type ServerlessScheduledAction struct { - StartTime time.Time `json:"startTime,omitzero"` - EndTime time.Time `json:"endTime,omitzero"` - NamespaceName string `json:"namespaceName,omitempty"` - RoleArn string `json:"roleArn,omitempty"` - ScheduledActionDescription string `json:"scheduledActionDescription,omitempty"` - ScheduledActionName string `json:"scheduledActionName"` - ScheduledActionUUID string `json:"scheduledActionUuid,omitempty"` - State string `json:"state"` - Schedule json.RawMessage `json:"schedule,omitempty"` - TargetAction json.RawMessage `json:"targetAction,omitempty"` + StartTime time.Time `json:"startTime,omitzero"` + EndTime time.Time `json:"endTime,omitzero"` + NamespaceName string `json:"namespaceName,omitempty"` + RoleArn string `json:"roleArn,omitempty"` + ScheduledActionDescription string `json:"scheduledActionDescription,omitempty"` + ScheduledActionName string `json:"scheduledActionName"` + ScheduledActionUUID string `json:"scheduledActionUuid,omitempty"` + State string `json:"state"` + Schedule jsontext.Value `json:"schedule,omitempty"` + TargetAction jsontext.Value `json:"targetAction,omitempty"` } // ServerlessCustomDomainAssociation represents a Redshift Serverless custom diff --git a/services/redshift/serverless_index_test.go b/services/redshift/serverless_index_test.go index b5325daeac..2ca8122b65 100644 --- a/services/redshift/serverless_index_test.go +++ b/services/redshift/serverless_index_test.go @@ -1,7 +1,7 @@ package redshift_test import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" "testing" @@ -254,8 +254,8 @@ func TestServerlessScheduledActionIndex_OrderedWithFilter(t *testing.T) { ScheduledActionName: s.name, NamespaceName: s.ns, RoleArn: "arn:aws:iam::000000000000:role/scheduler", - Schedule: json.RawMessage(`{"cron":"0 10 ? * MON *"}`), - TargetAction: json.RawMessage( + Schedule: jsontext.Value(`{"cron":"0 10 ? * MON *"}`), + TargetAction: jsontext.Value( `{"createSnapshot":{"namespaceName":"` + s.ns + `","snapshotName":"snap"}}`, ), StartTime: start, diff --git a/services/redshift/serverless_scheduled_actions.go b/services/redshift/serverless_scheduled_actions.go index 31b0134829..a7a7178a4c 100644 --- a/services/redshift/serverless_scheduled_actions.go +++ b/services/redshift/serverless_scheduled_actions.go @@ -1,7 +1,7 @@ package redshift import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "strconv" "time" @@ -23,8 +23,8 @@ type CreateScheduledActionParams struct { NamespaceName string RoleArn string ScheduledActionDescription string - Schedule json.RawMessage - TargetAction json.RawMessage + Schedule jsontext.Value + TargetAction jsontext.Value } // UpdateScheduledActionParams holds the mutable fields accepted by @@ -35,8 +35,8 @@ type UpdateScheduledActionParams struct { ScheduledActionDescription *string Enabled *bool RoleArn string - Schedule json.RawMessage - TargetAction json.RawMessage + Schedule jsontext.Value + TargetAction jsontext.Value } // CreateServerlessScheduledAction creates a serverless scheduled action. @@ -220,11 +220,11 @@ func (b *InMemoryBackend) DeleteServerlessScheduledAction( func cloneServerlessScheduledAction(sa *ServerlessScheduledAction) *ServerlessScheduledAction { cp := *sa if sa.Schedule != nil { - cp.Schedule = append(json.RawMessage(nil), sa.Schedule...) + cp.Schedule = append(jsontext.Value(nil), sa.Schedule...) } if sa.TargetAction != nil { - cp.TargetAction = append(json.RawMessage(nil), sa.TargetAction...) + cp.TargetAction = append(jsontext.Value(nil), sa.TargetAction...) } return &cp diff --git a/services/redshiftdata/engine.go b/services/redshiftdata/engine.go index 9d415b17ac..1df1644fe6 100644 --- a/services/redshiftdata/engine.go +++ b/services/redshiftdata/engine.go @@ -2,11 +2,13 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // EngineLogin identifies the master login of a cluster's live SQL engine. @@ -196,7 +198,7 @@ func resultSize(rs *ResultSet) int64 { return 0 } - raw, err := json.Marshal(rs.Rows) + raw, err := json.Marshal(rs.Rows, jsonx.V1()) if err != nil { return 0 } diff --git a/services/redshiftdata/engine_pgx.go b/services/redshiftdata/engine_pgx.go index b170f4ff37..607fd12a5a 100644 --- a/services/redshiftdata/engine_pgx.go +++ b/services/redshiftdata/engine_pgx.go @@ -4,7 +4,7 @@ import ( "context" "database/sql" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "math" @@ -16,7 +16,9 @@ import ( "time" "github.com/jackc/pgx/v5/pgconn" - _ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver + _ "github.com/jackc/pgx/v5/stdlib" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" // registers the "pgx" database/sql driver ) const ( @@ -314,7 +316,7 @@ func bytesField(dbType string, b []byte) Field { func compositeString(v any) string { switch reflect.ValueOf(v).Kind() { case reflect.Map, reflect.Slice, reflect.Array, reflect.Struct: - if raw, err := json.Marshal(v); err == nil { + if raw, err := json.Marshal(v, jsonx.V1()); err == nil { return string(raw) } default: diff --git a/services/redshiftdata/engine_result.go b/services/redshiftdata/engine_result.go index 19b066b898..7a282ac192 100644 --- a/services/redshiftdata/engine_result.go +++ b/services/redshiftdata/engine_result.go @@ -4,9 +4,11 @@ import ( "bytes" "context" "encoding/csv" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -45,7 +47,7 @@ func (h *Handler) engineStatementResult( keyColumnMetadata: rs.Columns, keyTotalNumRows: int64(len(rs.Rows)), keyNextToken: "", - }) + }, jsonx.V1()) } func renderCSVResult(rs *ResultSet) ([]byte, error) { @@ -76,7 +78,7 @@ func renderCSVResult(rs *ResultSet) ([]byte, error) { keyTotalNumRows: int64(len(rs.Rows)), keyResultFormat: resultFormatCSV, keyNextToken: "", - }) + }, jsonx.V1()) } func csvCell(f Field) string { diff --git a/services/redshiftdata/handler.go b/services/redshiftdata/handler.go index d20a4f3750..025ee8d4b5 100644 --- a/services/redshiftdata/handler.go +++ b/services/redshiftdata/handler.go @@ -2,7 +2,7 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -178,7 +179,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -262,7 +263,7 @@ func writeInternalServerError(c *echo.Context) error { payload, err := json.Marshal(map[string]string{ keyTypeField: "InternalServerException", keyMessageField: "internal server error", - }) + }, jsonx.V1()) if err != nil { return err } @@ -271,15 +272,12 @@ func writeInternalServerError(c *echo.Context) error { } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, ErrNotFound): payload, _ := json.Marshal(map[string]string{ keyTypeField: "ResourceNotFoundException", keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrTerminalState), @@ -288,7 +286,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: errValidationException, keyMessageField: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, errUnknownAction): @@ -297,7 +295,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { keyMessageField: err.Error(), }) case errors.Is(err, errInvalidRequest), errors.Is(err, errMissingID), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyTypeField: errValidationException, keyMessageField: err.Error(), diff --git a/services/redshiftdata/handler_databases.go b/services/redshiftdata/handler_databases.go index 31bcb0ffce..38b254465e 100644 --- a/services/redshiftdata/handler_databases.go +++ b/services/redshiftdata/handler_databases.go @@ -2,8 +2,10 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListDatabases(ctx context.Context, body []byte) ([]byte, error) { @@ -17,7 +19,7 @@ func (h *Handler) handleListDatabases(ctx context.Context, body []byte) ([]byte, MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -40,7 +42,7 @@ func (h *Handler) handleListDatabases(ctx context.Context, body []byte) ([]byte, resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleListSchemas(ctx context.Context, body []byte) ([]byte, error) { @@ -62,7 +64,7 @@ func (h *Handler) handleListSchemas(ctx context.Context, body []byte) ([]byte, e MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -90,7 +92,7 @@ func (h *Handler) handleListSchemas(ctx context.Context, body []byte) ([]byte, e resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // paginateStrings applies cursor-based pagination to a sorted string slice. diff --git a/services/redshiftdata/handler_databases_test.go b/services/redshiftdata/handler_databases_test.go index f025636bf1..c7f35e6ad6 100644 --- a/services/redshiftdata/handler_databases_test.go +++ b/services/redshiftdata/handler_databases_test.go @@ -1,12 +1,14 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListDatabases(t *testing.T) { @@ -17,7 +19,7 @@ func TestHandler_ListDatabases(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Databases"]) } @@ -38,7 +40,7 @@ func TestHandler_ListSchemas(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Schemas"]) } @@ -59,7 +61,7 @@ func TestHandler_ListDatabases_ReturnsNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dbs, ok := resp["Databases"].([]any) require.True(t, ok) @@ -74,7 +76,7 @@ func TestHandler_ListDatabases_NextTokenOmittedWhenComplete(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["NextToken"] assert.False(t, ok, "NextToken should be omitted when the demo database list fits on one page") @@ -88,7 +90,7 @@ func TestHandler_ListDatabases_MaxResults1_PaginatesWithToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dbs, ok := resp["Databases"].([]any) require.True(t, ok) @@ -117,7 +119,7 @@ func TestHandler_ListDatabases_NextToken_ResumesFromCursor(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) token, _ := page1["NextToken"].(string) require.NotEmpty(t, token) @@ -127,7 +129,7 @@ func TestHandler_ListDatabases_NextToken_ResumesFromCursor(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) dbs2, _ := page2["Databases"].([]any) dbs1, _ := page1["Databases"].([]any) @@ -143,7 +145,7 @@ func TestHandler_ListSchemas_ReturnsNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas, ok := resp["Schemas"].([]any) require.True(t, ok) @@ -175,7 +177,7 @@ func TestHandler_ListSchemas_SchemaPattern_WildcardMatchesAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas, ok := resp["Schemas"].([]any) require.True(t, ok) @@ -195,7 +197,7 @@ func TestHandler_ListSchemas_SchemaPattern_NoMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas, _ := resp["Schemas"].([]any) assert.Empty(t, schemas, "non-matching pattern should return empty schemas") @@ -237,7 +239,7 @@ func TestHandler_ListSchemas_SQLLike_UnderscoreWildcard(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas, _ := resp["Schemas"].([]any) if tt.want { @@ -262,7 +264,7 @@ func TestListDatabases_ReturnsDemoData(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dbs, ok := resp["Databases"].([]any) require.True(t, ok) @@ -283,7 +285,7 @@ func TestListSchemas_ReturnsDemoData(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas, ok := resp["Schemas"].([]any) require.True(t, ok) @@ -303,7 +305,7 @@ func TestListDatabases_HasNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) token, ok := resp["NextToken"] assert.True(t, ok, "NextToken should be present when more pages remain") diff --git a/services/redshiftdata/handler_sessions.go b/services/redshiftdata/handler_sessions.go index 2529ca95d9..fa48d11e72 100644 --- a/services/redshiftdata/handler_sessions.go +++ b/services/redshiftdata/handler_sessions.go @@ -2,8 +2,10 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleListSessions handles ListSessions. Field names verified against @@ -22,7 +24,7 @@ func (h *Handler) handleListSessions(ctx context.Context, body []byte) ([]byte, MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -59,7 +61,7 @@ func (h *Handler) handleListSessions(ctx context.Context, body []byte) ([]byte, resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // sessionToListItem converts a derived SessionData to the SessionData wire shape diff --git a/services/redshiftdata/handler_statements.go b/services/redshiftdata/handler_statements.go index 2af3f445f5..13a793e35b 100644 --- a/services/redshiftdata/handler_statements.go +++ b/services/redshiftdata/handler_statements.go @@ -2,11 +2,13 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // handleExecuteStatement: a positive SessionKeepAliveSeconds without SessionId mints a session @@ -29,7 +31,7 @@ func (h *Handler) handleExecuteStatement(ctx context.Context, body []byte) ([]by WithEvent bool `json:"WithEvent"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -50,7 +52,7 @@ func (h *Handler) handleExecuteStatement(ctx context.Context, body []byte) ([]by if id, ok := h.lookupIdempotentStatement(tokenKey); ok { if stmt, descErr := h.Backend.DescribeStatement(ctx, id); descErr == nil { - return json.Marshal(statementCreateResponse(stmt)) + return json.Marshal(statementCreateResponse(stmt), jsonx.V1()) } } @@ -78,7 +80,7 @@ func (h *Handler) handleExecuteStatement(ctx context.Context, body []byte) ([]by } } - return json.Marshal(statementCreateResponse(stmt)) + return json.Marshal(statementCreateResponse(stmt), jsonx.V1()) } const maxSessionKeepAliveSeconds = 24 * 60 * 60 @@ -117,7 +119,7 @@ func (h *Handler) handleBatchExecuteStatement(ctx context.Context, body []byte) WithEvent bool `json:"WithEvent"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -138,7 +140,7 @@ func (h *Handler) handleBatchExecuteStatement(ctx context.Context, body []byte) if id, ok := h.lookupIdempotentStatement(tokenKey); ok { if stmt, descErr := h.Backend.DescribeStatement(ctx, id); descErr == nil { - return json.Marshal(statementCreateResponse(stmt)) + return json.Marshal(statementCreateResponse(stmt), jsonx.V1()) } } @@ -166,7 +168,7 @@ func (h *Handler) handleBatchExecuteStatement(ctx context.Context, body []byte) } } - return json.Marshal(statementCreateResponse(stmt)) + return json.Marshal(statementCreateResponse(stmt), jsonx.V1()) } // statementCreateResponse builds the shared ExecuteStatementOutput/ @@ -205,7 +207,7 @@ func (h *Handler) handleDescribeStatement(ctx context.Context, body []byte) ([]b WaitTimeSeconds int32 `json:"WaitTimeSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -222,7 +224,7 @@ func (h *Handler) handleDescribeStatement(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(statementToDescribeResponse(stmt)) + return json.Marshal(statementToDescribeResponse(stmt), jsonx.V1()) } func (h *Handler) handleGetStatementResult(ctx context.Context, body []byte) ([]byte, error) { @@ -232,7 +234,7 @@ func (h *Handler) handleGetStatementResult(ctx context.Context, body []byte) ([] WaitTimeSeconds int32 `json:"WaitTimeSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -282,7 +284,7 @@ func (h *Handler) handleGetStatementResult(ctx context.Context, body []byte) ([] }, keyTotalNumRows: int64(1), keyNextToken: "", - }) + }, jsonx.V1()) } func (h *Handler) handleGetStatementResultV2(ctx context.Context, body []byte) ([]byte, error) { @@ -292,7 +294,7 @@ func (h *Handler) handleGetStatementResultV2(ctx context.Context, body []byte) ( WaitTimeSeconds int32 `json:"WaitTimeSeconds"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -348,7 +350,7 @@ func (h *Handler) handleGetStatementResultV2(ctx context.Context, body []byte) ( keyTotalNumRows: int64(1), keyResultFormat: resultFormatCSV, keyNextToken: "", - }) + }, jsonx.V1()) } func (h *Handler) handleListStatements(ctx context.Context, body []byte) ([]byte, error) { @@ -363,7 +365,7 @@ func (h *Handler) handleListStatements(ctx context.Context, body []byte) ([]byte MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -410,7 +412,7 @@ func (h *Handler) handleListStatements(ctx context.Context, body []byte) ([]byte resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleCancelStatement(ctx context.Context, body []byte) ([]byte, error) { @@ -418,7 +420,7 @@ func (h *Handler) handleCancelStatement(ctx context.Context, body []byte) ([]byt ID string `json:"Id"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -432,7 +434,7 @@ func (h *Handler) handleCancelStatement(ctx context.Context, body []byte) ([]byt return json.Marshal(map[string]any{ keyStatusField: true, - }) + }, jsonx.V1()) } // epochSeconds converts a [time.Time] to Unix epoch seconds as float64, diff --git a/services/redshiftdata/handler_statements_lifecycle_test.go b/services/redshiftdata/handler_statements_lifecycle_test.go index 9f604016dc..123834f347 100644 --- a/services/redshiftdata/handler_statements_lifecycle_test.go +++ b/services/redshiftdata/handler_statements_lifecycle_test.go @@ -2,7 +2,7 @@ package redshiftdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -27,7 +28,7 @@ func TestCancelStatement_SuccessStatusBoolean(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) status, ok := resp["Status"].(bool) require.True(t, ok, "Status should be a boolean") @@ -50,7 +51,7 @@ func TestBatchExecuteStatement_QueryStringIsFirstSQL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -58,7 +59,7 @@ func TestBatchExecuteStatement_QueryStringIsFirstSQL(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SELECT 1", resp["QueryString"], "QueryString should equal the first SQL") } @@ -78,7 +79,7 @@ func TestDescribeStatement_ResultSizeAndRows(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -86,7 +87,7 @@ func TestDescribeStatement_ResultSizeAndRows(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["ResultRows"], "ResultRows should be present") assert.NotNil(t, resp["ResultSize"], "ResultSize should be present") @@ -109,7 +110,7 @@ func TestDescribeStatement_SubStatements(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -117,7 +118,7 @@ func TestDescribeStatement_SubStatements(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) subs, ok := resp["SubStatements"].([]any) require.True(t, ok, "SubStatements should be present") @@ -143,7 +144,7 @@ func TestGetStatementResult_ReturnsDemoRow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -151,7 +152,7 @@ func TestGetStatementResult_ReturnsDemoRow(t *testing.T) { require.Equal(t, http.StatusOK, resultRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(resultRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(resultRec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["Records"].([]any) require.True(t, ok, "Records should be a slice") @@ -191,7 +192,7 @@ func TestListStatements_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) assert.Len(t, stmts, testMaxResultsLimit, "should be truncated to MaxResults") @@ -212,7 +213,7 @@ func TestListStatements_MaxResultsTooLarge(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -239,7 +240,7 @@ func TestWithEvent_AcceptedButNotEchoed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotContains(t, createResp, "WithEvent") id := createResp["Id"].(string) @@ -248,7 +249,7 @@ func TestWithEvent_AcceptedButNotEchoed(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "WithEvent") } @@ -270,7 +271,7 @@ func TestListStatements_StatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) require.Len(t, stmts, 1) @@ -373,7 +374,7 @@ func TestListStatements_WorkgroupFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) require.Len(t, stmts, 1, "should only return statements for wg-a") @@ -396,7 +397,7 @@ func TestGetStatementResultV2_DemoRow(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -404,7 +405,7 @@ func TestGetStatementResultV2_DemoRow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["Records"].([]any) require.True(t, ok, "Records should be present") @@ -427,7 +428,7 @@ func TestCancelStatement_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -442,7 +443,7 @@ func TestGetStatementResult_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -460,7 +461,7 @@ func TestBatchExecuteStatement_EmptySqls(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -475,7 +476,7 @@ func TestDescribeStatement_MissingID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -494,7 +495,7 @@ func TestDescribeStatement_RedshiftQueryId(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -502,7 +503,7 @@ func TestDescribeStatement_RedshiftQueryId(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["RedshiftQueryId"] assert.True(t, ok, "RedshiftQueryId should be present in DescribeStatement response") @@ -547,7 +548,7 @@ func TestGetStatementResult_HasNextToken(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -555,7 +556,7 @@ func TestGetStatementResult_HasNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["NextToken"] assert.True(t, ok, "NextToken field should always be present in GetStatementResult response") diff --git a/services/redshiftdata/handler_statements_semantics_test.go b/services/redshiftdata/handler_statements_semantics_test.go index 7b7fe90ee0..88b5c09225 100644 --- a/services/redshiftdata/handler_statements_semantics_test.go +++ b/services/redshiftdata/handler_statements_semantics_test.go @@ -1,13 +1,15 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -63,14 +65,14 @@ func TestResultFormatControlsResultAPI(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp, jsonx.V1())) rec = doRequest(t, h, tt.getOperation, map[string]any{"Id": execResp["Id"]}) assert.Equal(t, tt.wantStatus, rec.Code) if tt.wantResultFmt != "" { var resultResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resultResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resultResp, jsonx.V1())) assert.Equal(t, tt.wantResultFmt, resultResp["ResultFormat"]) } }) @@ -109,13 +111,13 @@ func TestResultFormatMetadataAndValidation(t *testing.T) { } var execResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp, jsonx.V1())) rec = doRequest(t, h, "DescribeStatement", map[string]any{"Id": execResp["Id"]}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) wantFormat := tt.format if wantFormat == "" { wantFormat = "JSON" @@ -159,7 +161,7 @@ func TestListStatementsFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Statements"], tt.wantCount) }) } @@ -181,7 +183,7 @@ func TestListStatementsNextToken(t *testing.T) { require.Equal(t, http.StatusOK, first.Code) var firstResp map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &firstResp, jsonx.V1())) token, ok := firstResp["NextToken"].(string) require.True(t, ok) @@ -252,7 +254,7 @@ func TestHasResultSet_BySQL(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -260,7 +262,7 @@ func TestHasResultSet_BySQL(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantResultSet, descResp["HasResultSet"], "SQL %q: HasResultSet mismatch", tt.sql) @@ -298,7 +300,7 @@ func TestGetStatementResult_RequiresResultSet(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -308,7 +310,7 @@ func TestGetStatementResult_RequiresResultSet(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } }) @@ -373,7 +375,7 @@ func TestParameters_AcceptedAndStored(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"], "Id should be returned") // DescribeStatementOutput.QueryParameters must round-trip whatever @@ -385,7 +387,7 @@ func TestParameters_AcceptedAndStored(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) if len(tt.params) == 0 { assert.Nil(t, descResp["QueryParameters"], @@ -430,13 +432,13 @@ func TestBatchExecuteStatement_ParametersAcceptedAndStored(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) descRec := doRequest(t, h, "DescribeStatement", map[string]any{"Id": createResp["Id"]}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) gotParams, ok := descResp["QueryParameters"].([]any) require.True(t, ok, "QueryParameters should be a list") @@ -470,21 +472,21 @@ func TestSessionID_EchoedByExecuteStatement(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp, jsonx.V1())) assert.Equal(t, "sess-abc123", execResp["SessionId"]) descRec := doRequest(t, h, "DescribeStatement", map[string]any{"Id": execResp["Id"]}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "sess-abc123", descResp["SessionId"]) listRec := doRequest(t, h, "ListStatements", map[string]any{"Status": "ALL"}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) stmts, ok := listResp["Statements"].([]any) require.True(t, ok) @@ -505,14 +507,14 @@ func TestSessionID_EchoedByExecuteStatement(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp, jsonx.V1())) assert.Nil(t, execResp["SessionId"], "SessionId should be omitted, not empty-string, when not supplied") descRec := doRequest(t, h, "DescribeStatement", map[string]any{"Id": execResp["Id"]}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Nil(t, descResp["SessionId"]) }) } @@ -533,14 +535,14 @@ func TestSessionID_EchoedByBatchExecuteStatement(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &execResp, jsonx.V1())) assert.Equal(t, "sess-batch-1", execResp["SessionId"]) descRec := doRequest(t, h, "DescribeStatement", map[string]any{"Id": execResp["Id"]}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "sess-batch-1", descResp["SessionId"]) } @@ -574,7 +576,7 @@ func TestExecuteStatement_CaseInsensitiveSQL(t *testing.T) { require.Equal(t, http.StatusOK, execRec.Code) var execResp map[string]any - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) id := execResp["Id"].(string) @@ -582,7 +584,7 @@ func TestExecuteStatement_CaseInsensitiveSQL(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, tt.wantResultSet, descResp["HasResultSet"], "SQL %q: HasResultSet mismatch", tt.sql) @@ -619,9 +621,9 @@ func TestListStatements_NoFabricatedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Statements []map[string]json.RawMessage `json:"Statements"` + Statements []map[string]jsontext.Value `json:"Statements"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.Statements) assert.NotContains(t, resp.Statements[0], field) }) diff --git a/services/redshiftdata/handler_statements_test.go b/services/redshiftdata/handler_statements_test.go index fa38c42830..67422bd7ff 100644 --- a/services/redshiftdata/handler_statements_test.go +++ b/services/redshiftdata/handler_statements_test.go @@ -2,13 +2,14 @@ package redshiftdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -64,7 +65,7 @@ func TestHandler_ExecuteStatement(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) } }) @@ -107,7 +108,7 @@ func TestHandler_BatchExecuteStatement(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["Id"]) } }) @@ -134,7 +135,7 @@ func TestHandler_DescribeStatement(t *testing.T) { "Database": "testdb", }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Id"].(string) }, @@ -171,7 +172,7 @@ func TestHandler_DescribeStatement(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantStatus2 != "" { assert.Equal(t, tt.wantStatus2, resp["Status"]) @@ -201,7 +202,7 @@ func TestHandler_GetStatementResult(t *testing.T) { "Database": "testdb", }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Id"].(string) }, @@ -225,7 +226,7 @@ func TestHandler_GetStatementResult(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Records"]) } }) @@ -252,7 +253,7 @@ func TestHandler_GetStatementResultV2(t *testing.T) { "ResultFormat": "CSV", }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Id"].(string) }, @@ -291,7 +292,7 @@ func TestHandler_GetStatementResultV2(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.checkRecords { assert.NotNil(t, resp["Records"]) @@ -349,7 +350,7 @@ func TestHandler_ListStatements(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["Statements"].([]any) require.True(t, ok) @@ -399,7 +400,7 @@ func TestHandler_CancelStatement(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) }) } @@ -419,7 +420,7 @@ func TestHandler_CancelStatement_AlreadyFinished(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id := resp["Id"].(string) @@ -428,7 +429,7 @@ func TestHandler_CancelStatement_AlreadyFinished(t *testing.T) { assert.Equal(t, http.StatusBadRequest, cancelRec.Code) var cancelResp map[string]any - require.NoError(t, json.Unmarshal(cancelRec.Body.Bytes(), &cancelResp)) + require.NoError(t, json.Unmarshal(cancelRec.Body.Bytes(), &cancelResp, jsonx.V1())) assert.Equal(t, "ValidationException", cancelResp["__type"]) } @@ -456,7 +457,7 @@ func TestHandler_ListStatements_WithFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) assert.Len(t, stmts, 1) @@ -484,7 +485,7 @@ func TestHandler_ListStatements_WithWorkgroupFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) assert.Len(t, stmts, 1) @@ -507,7 +508,7 @@ func TestHandler_DescribeStatement_AllFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -515,7 +516,7 @@ func TestHandler_DescribeStatement_AllFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, id, resp["Id"]) assert.Equal(t, "FINISHED", resp["Status"]) @@ -545,7 +546,7 @@ func TestHandler_BatchExecuteStatement_AllFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -553,7 +554,7 @@ func TestHandler_BatchExecuteStatement_AllFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, id, resp["Id"]) // IsBatchStatement/QueryStrings are real StatementData (ListStatements @@ -569,7 +570,7 @@ func TestHandler_BatchExecuteStatement_AllFields(t *testing.T) { var listResp struct { Statements []map[string]any `json:"Statements"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.NotEmpty(t, listResp.Statements) assert.Equal(t, true, listResp.Statements[0]["IsBatchStatement"]) @@ -595,7 +596,7 @@ func TestHandler_ListStatements_WithSecretARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) require.Len(t, stmts, 1) @@ -782,7 +783,7 @@ func TestHandler_ListSessions(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantErrType != "" { assert.Equal(t, tt.wantErrType, resp["__type"]) diff --git a/services/redshiftdata/handler_statements_validation_test.go b/services/redshiftdata/handler_statements_validation_test.go index 620a72f2af..7a3c0ab92c 100644 --- a/services/redshiftdata/handler_statements_validation_test.go +++ b/services/redshiftdata/handler_statements_validation_test.go @@ -2,7 +2,7 @@ package redshiftdata_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -210,7 +211,7 @@ func TestHandler_ListStatements_MaxResults_Paginates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, _ := resp["Statements"].([]any) assert.Len(t, stmts, 2) @@ -336,14 +337,14 @@ func TestGetStatementResult_NoResultSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp, jsonx.V1())) id := batchResp["Id"].(string) rec = doRequest(t, h, "GetStatementResult", map[string]any{"Id": id}) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -362,14 +363,14 @@ func TestGetStatementResultV2_NoResultSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &batchResp, jsonx.V1())) id := batchResp["Id"].(string) rec = doRequest(t, h, "GetStatementResultV2", map[string]any{"Id": id}) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -389,14 +390,14 @@ func TestGetStatementResultV2_ResultFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) rec = doRequest(t, h, "GetStatementResultV2", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CSV", resp["ResultFormat"]) assert.EqualValues(t, 1, resp["TotalNumRows"]) assert.NotNil(t, resp["Records"]) @@ -417,7 +418,7 @@ func TestCancelStatement_AbortedIsTerminal(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -435,7 +436,7 @@ func TestCancelStatement_FailedIsTerminal(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -459,7 +460,7 @@ func TestListStatements_SortedNewestFirst(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["Statements"].([]any) require.Len(t, stmts, 3) @@ -487,7 +488,7 @@ func TestExecuteStatement_HasResultSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -495,7 +496,7 @@ func TestExecuteStatement_HasResultSet(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, true, descResp["HasResultSet"]) } @@ -513,7 +514,7 @@ func TestBatchExecuteStatement_HasNoResultSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Id"].(string) @@ -521,7 +522,7 @@ func TestBatchExecuteStatement_HasNoResultSet(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, false, descResp["HasResultSet"]) } diff --git a/services/redshiftdata/handler_tables.go b/services/redshiftdata/handler_tables.go index 881fdcb86f..3936c63313 100644 --- a/services/redshiftdata/handler_tables.go +++ b/services/redshiftdata/handler_tables.go @@ -2,9 +2,11 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListTables(ctx context.Context, body []byte) ([]byte, error) { @@ -25,7 +27,7 @@ func (h *Handler) handleListTables(ctx context.Context, body []byte) ([]byte, er MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -49,7 +51,7 @@ func (h *Handler) handleListTables(ctx context.Context, body []byte) ([]byte, er resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // filterDemoTables applies SchemaPattern and TablePattern filters to the demo table list. @@ -99,7 +101,7 @@ func (h *Handler) handleDescribeTable(ctx context.Context, body []byte) ([]byte, MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -130,7 +132,7 @@ func (h *Handler) handleDescribeTable(ctx context.Context, body []byte) ([]byte, resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // paginateMaps applies cursor-based pagination to a slice of maps keyed by "name". diff --git a/services/redshiftdata/handler_tables_test.go b/services/redshiftdata/handler_tables_test.go index 07fa661a52..943767167d 100644 --- a/services/redshiftdata/handler_tables_test.go +++ b/services/redshiftdata/handler_tables_test.go @@ -1,12 +1,14 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListTables(t *testing.T) { @@ -17,7 +19,7 @@ func TestHandler_ListTables(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Tables"]) } @@ -38,7 +40,7 @@ func TestHandler_DescribeTable(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["ColumnList"]) } @@ -59,7 +61,7 @@ func TestHandler_ListTables_ReturnsNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, ok := resp["Tables"].([]any) require.True(t, ok) @@ -77,7 +79,7 @@ func TestHandler_ListTables_SchemaPattern_WildcardMatchesAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, ok := resp["Tables"].([]any) require.True(t, ok) @@ -95,7 +97,7 @@ func TestHandler_ListTables_TablePattern_WildcardMatchesAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, ok := resp["Tables"].([]any) require.True(t, ok) @@ -113,7 +115,7 @@ func TestHandler_ListTables_TablePattern_PrefixMatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, _ := resp["Tables"].([]any) require.NotEmpty(t, tables, "user% should match 'users'") @@ -141,7 +143,7 @@ func TestHandler_ListTables_MaxResults1_Paginates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, ok := resp["Tables"].([]any) require.True(t, ok) @@ -166,7 +168,7 @@ func TestDescribeTable_ReturnsDemoColumns(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cols, ok := resp["ColumnList"].([]any) require.True(t, ok, "ColumnList should be a slice") @@ -192,7 +194,7 @@ func TestListTables_ReturnsDemoData(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tables, ok := resp["Tables"].([]any) require.True(t, ok) diff --git a/services/redshiftdata/handler_test.go b/services/redshiftdata/handler_test.go index 9ff56e5773..52e639db20 100644 --- a/services/redshiftdata/handler_test.go +++ b/services/redshiftdata/handler_test.go @@ -3,7 +3,7 @@ package redshiftdata_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -37,7 +38,7 @@ func doRequest(t *testing.T, h *redshiftdata.Handler, op string, body any) *http if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -257,7 +258,7 @@ func TestHandler_UnknownOperation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -272,7 +273,7 @@ func TestUnknownOperation_Returns400(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } diff --git a/services/redshiftdata/idempotency_test.go b/services/redshiftdata/idempotency_test.go index c806124d77..f30e30f553 100644 --- a/services/redshiftdata/idempotency_test.go +++ b/services/redshiftdata/idempotency_test.go @@ -1,12 +1,14 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestExecuteStatement_ClientToken_ReplaysOnRetry verifies that retrying an @@ -35,13 +37,13 @@ func TestExecuteStatement_ClientToken_ReplaysOnRetry(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rec2 := doRequest(t, h, "ExecuteStatement", req) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1["Id"], out2["Id"], "retry with the same ClientToken must replay the same statement Id") @@ -51,7 +53,7 @@ func TestExecuteStatement_ClientToken_ReplaysOnRetry(t *testing.T) { var list struct { Statements []map[string]any `json:"Statements"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list, jsonx.V1())) assert.Len(t, list.Statements, 1, "exactly one statement should actually be created") } @@ -74,13 +76,13 @@ func TestExecuteStatement_NoClientToken_CreatesDistinctStatements(t *testing.T) require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rec2 := doRequest(t, h, "ExecuteStatement", req) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.NotEqual(t, out1["Id"], out2["Id"], "without a ClientToken each call must create a distinct statement") } @@ -105,13 +107,13 @@ func TestBatchExecuteStatement_ClientToken_ReplaysOnRetry(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rec2 := doRequest(t, h, "BatchExecuteStatement", req) require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1["Id"], out2["Id"], "retry with the same ClientToken must replay the same batch statement Id") } diff --git a/services/redshiftdata/persistence.go b/services/redshiftdata/persistence.go index a39f8d820f..c64f021e3f 100644 --- a/services/redshiftdata/persistence.go +++ b/services/redshiftdata/persistence.go @@ -2,8 +2,9 @@ package redshiftdata import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -72,7 +73,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.defaultRegion, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "redshiftdata: failed to marshal snapshot", "error", err) diff --git a/services/redshiftdata/persistence_test.go b/services/redshiftdata/persistence_test.go index 6d0a03793a..ecd6a85ad8 100644 --- a/services/redshiftdata/persistence_test.go +++ b/services/redshiftdata/persistence_test.go @@ -2,12 +2,14 @@ package redshiftdata //nolint:testpackage // needs the unexported region ctx key import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const persistenceTestAccountID = "000000000000" @@ -155,10 +157,10 @@ func runVersionMismatchCase(t *testing.T, mutate func(raw map[string]any)) { require.NotNil(t, snap) var raw map[string]any - require.NoError(t, json.Unmarshal(snap, &raw)) + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) mutate(raw) - data, err := json.Marshal(raw) + data, err := json.Marshal(raw, jsonx.V1()) require.NoError(t, err) require.NoError(t, target.Restore(t.Context(), data)) diff --git a/services/redshiftdata/s3_copy.go b/services/redshiftdata/s3_copy.go index 2855f8ab00..3ff848bd2e 100644 --- a/services/redshiftdata/s3_copy.go +++ b/services/redshiftdata/s3_copy.go @@ -6,7 +6,8 @@ import ( "compress/gzip" "context" "database/sql" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,7 @@ import ( "github.com/jackc/pgx/v5/stdlib" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -166,7 +168,7 @@ func (r *s3Runner) manifestObjects(ctx context.Context, bucket, key string) ([]s } `json:"entries"` } - if err = json.Unmarshal(raw, &m); err != nil { + if err = json.Unmarshal(raw, &m, jsonx.V1()); err != nil { return nil, stmtErrorf("Manifest file is not in correct json format") } @@ -331,12 +333,11 @@ func appendJSON( return err } - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() + dec := jsontext.NewDecoder(bytes.NewReader(data)) for { var rec any - if err = dec.Decode(&rec); errors.Is(err, io.EOF) { + if err = json.UnmarshalDecode(dec, &rec, jsonx.V1(), jsonx.UseNumber()); errors.Is(err, io.EOF) { return nil } else if err != nil { return stmtErrorf("Invalid JSON record in S3 object: %v", err) @@ -379,7 +380,7 @@ func jsonPathsFor(s *copySpec, cols []string, fetch func(string) ([]byte, error) JSONPaths []string `json:"jsonpaths"` } - if err = json.Unmarshal(raw, &doc); err != nil { + if err = json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return nil, stmtErrorf("The JSONPaths file is not valid JSON: %v", err) } @@ -504,14 +505,14 @@ func textCell(v any) *string { return nil case string: s = x - case json.Number: + case jsonx.Number: s = x.String() case bool: s = strconv.FormatBool(x) case int64, float64, int32, int: s = fmt.Sprint(x) default: - raw, err := json.Marshal(x) + raw, err := json.Marshal(x, jsonx.V1()) if err != nil { s = fmt.Sprint(x) } else { diff --git a/services/redshiftdata/s3_unload.go b/services/redshiftdata/s3_unload.go index 1cc9be978f..dc134f53ce 100644 --- a/services/redshiftdata/s3_unload.go +++ b/services/redshiftdata/s3_unload.go @@ -7,12 +7,13 @@ import ( "encoding/base64" "encoding/csv" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net/url" "strconv" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -402,12 +403,12 @@ func encodeJSONLines(cols []ColumnMetadata, rows [][]Field) ([]byte, error) { buf.WriteByte('{') for i, f := range row { - name, err := json.Marshal(cols[i].Name) + name, err := json.Marshal(cols[i].Name, jsonx.V1()) if err != nil { return nil, stmtErrorf("could not write JSON: %v", err) } - val, err := json.Marshal(jsonValue(f)) + val, err := json.Marshal(jsonValue(f), jsonx.V1()) if err != nil { return nil, stmtErrorf("could not write JSON: %v", err) } @@ -559,7 +560,7 @@ func unloadManifest(s *unloadSpec, rs *ResultSet, files []unloadFile) []byte { doc["schema"] = map[string]any{"elements": elems} } - raw, err := json.Marshal(doc) + raw, err := json.Marshal(doc, jsonx.V1()) if err != nil { return []byte("{}") } diff --git a/services/redshiftdata/session_keepalive_test.go b/services/redshiftdata/session_keepalive_test.go index ab0cfda77e..6420108f43 100644 --- a/services/redshiftdata/session_keepalive_test.go +++ b/services/redshiftdata/session_keepalive_test.go @@ -1,7 +1,7 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSessionKeepAlive_Expiry(t *testing.T) { @@ -82,7 +84,7 @@ func decodeBody(t *testing.T, rec interface{ Bytes() []byte }) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(rec.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/redshiftdata/wire_sdk_roundtrip_test.go b/services/redshiftdata/wire_sdk_roundtrip_test.go index e874bebf33..e845b0db11 100644 --- a/services/redshiftdata/wire_sdk_roundtrip_test.go +++ b/services/redshiftdata/wire_sdk_roundtrip_test.go @@ -1,7 +1,8 @@ package redshiftdata_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/redshiftdata" ) @@ -219,13 +221,13 @@ func TestDescribeStatement_NoFabricatedFields(t *testing.T) { var execResp struct { ID string `json:"Id"` } - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) rec := doRequest(t, h, "DescribeStatement", map[string]any{"Id": execResp.ID}) require.Equal(t, http.StatusOK, rec.Code) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, tt.field) }) } diff --git a/services/rekognition/datasets.go b/services/rekognition/datasets.go index 8fd91ba972..c05e49d956 100644 --- a/services/rekognition/datasets.go +++ b/services/rekognition/datasets.go @@ -2,7 +2,8 @@ package rekognition import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" @@ -11,6 +12,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (b *InMemoryBackend) datasetARN(projectARN, datasetType string) string { @@ -161,8 +164,8 @@ func matchesDatasetEntryFilter(entry string, filter ListDatasetEntriesFilter) bo // name found across its "-metadata" blocks, plus whether it carried at // least one such block (i.e. is "labeled"). func entryLabels(entry string) ([]string, bool) { - var obj map[string]json.RawMessage - if err := json.Unmarshal([]byte(entry), &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal([]byte(entry), &obj, jsonx.V1()); err != nil { return nil, false } @@ -186,8 +189,8 @@ func entryLabels(entry string) ([]string, bool) { // entrySourceRef parses one JSON-lines dataset entry and returns its // "source-ref" field (the image's S3 location), or "" if absent/malformed. func entrySourceRef(entry string) string { - var obj map[string]json.RawMessage - if err := json.Unmarshal([]byte(entry), &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal([]byte(entry), &obj, jsonx.V1()); err != nil { return "" } @@ -197,7 +200,7 @@ func entrySourceRef(entry string) string { } var ref string - _ = json.Unmarshal(raw, &ref) + _ = json.Unmarshal(raw, &ref, jsonx.V1()) return ref } @@ -292,9 +295,9 @@ func computeDatasetStats(entries []string) DatasetStats { } // labelNamesFromMeta parses a -metadata block and returns its label names. -func labelNamesFromMeta(raw json.RawMessage) []string { - var meta map[string]json.RawMessage - if err := json.Unmarshal(raw, &meta); err != nil { +func labelNamesFromMeta(raw jsontext.Value) []string { + var meta map[string]jsontext.Value + if err := json.Unmarshal(raw, &meta, jsonx.V1()); err != nil { return nil } @@ -303,15 +306,15 @@ func labelNamesFromMeta(raw json.RawMessage) []string { // Single-label: "class-name" if cn, ok := meta["class-name"]; ok { var name string - if err := json.Unmarshal(cn, &name); err == nil && name != "" { + if err := json.Unmarshal(cn, &name, jsonx.V1()); err == nil && name != "" { names = append(names, name) } } // Multi-label: "class-map": {"LabelA": ..., "LabelB": ...} if cm, ok := meta["class-map"]; ok { - var classMap map[string]json.RawMessage - if err := json.Unmarshal(cm, &classMap); err == nil { + var classMap map[string]jsontext.Value + if err := json.Unmarshal(cm, &classMap, jsonx.V1()); err == nil { for name := range classMap { names = append(names, name) } @@ -333,7 +336,7 @@ func decodeDatasetPageToken(token string) int { } var tok datasetPaginationToken - if err = json.Unmarshal(decoded, &tok); err != nil || tok.Offset <= 0 { + if err = json.Unmarshal(decoded, &tok, jsonx.V1()); err != nil || tok.Offset <= 0 { return 0 } @@ -395,7 +398,7 @@ func (b *InMemoryBackend) ListDatasetLabels( var outToken string if end < len(names) { - tok, _ := json.Marshal(datasetPaginationToken{Offset: end}) + tok, _ := json.Marshal(datasetPaginationToken{Offset: end}, jsonx.V1()) outToken = base64.RawURLEncoding.EncodeToString(tok) } diff --git a/services/rekognition/handler.go b/services/rekognition/handler.go index ce06aa2530..4b04241d02 100644 --- a/services/rekognition/handler.go +++ b/services/rekognition/handler.go @@ -2,7 +2,7 @@ package rekognition import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -140,7 +141,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { diff --git a/services/rekognition/handler_async_video_fields_test.go b/services/rekognition/handler_async_video_fields_test.go index b47437d86d..97b5cf7fc0 100644 --- a/services/rekognition/handler_async_video_fields_test.go +++ b/services/rekognition/handler_async_video_fields_test.go @@ -1,13 +1,15 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -80,7 +82,7 @@ func TestAsyncVideoJob_JobTagAndVideoRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, tc.startAction) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) @@ -88,7 +90,7 @@ func TestAsyncVideoJob_JobTagAndVideoRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, tc.getAction) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-job-tag", getResp["JobTag"]) video, _ := getResp["Video"].(map[string]any) @@ -111,7 +113,7 @@ func TestAsyncVideoJob_NoVideoOmitsVideoField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) @@ -119,7 +121,7 @@ func TestAsyncVideoJob_NoVideoOmitsVideoField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.NotContains(t, getResp, "Video") assert.NotContains(t, getResp, "JobTag") } @@ -142,7 +144,7 @@ func TestGetSegmentDetection_SelectedSegmentTypesEchoesRequest(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) @@ -150,7 +152,7 @@ func TestGetSegmentDetection_SelectedSegmentTypesEchoesRequest(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) selected, ok := getResp["SelectedSegmentTypes"].([]any) require.True(t, ok) require.Len(t, selected, 2) @@ -199,7 +201,7 @@ func TestGetLabelDetection_GetRequestMetadata(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) @@ -210,7 +212,7 @@ func TestGetLabelDetection_GetRequestMetadata(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) metadata, _ := getResp["GetRequestMetadata"].(map[string]any) require.NotNil(t, metadata) assert.Equal(t, tc.wantSortBy, metadata["SortBy"]) @@ -233,7 +235,7 @@ func TestGetContentModeration_GetRequestMetadataDefaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) @@ -241,7 +243,7 @@ func TestGetContentModeration_GetRequestMetadataDefaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) metadata, _ := getResp["GetRequestMetadata"].(map[string]any) require.NotNil(t, metadata) assert.Equal(t, "TIMESTAMP", metadata["SortBy"]) diff --git a/services/rekognition/handler_celebrities_test.go b/services/rekognition/handler_celebrities_test.go index 0ecdeedcfa..1896aa676c 100644 --- a/services/rekognition/handler_celebrities_test.go +++ b/services/rekognition/handler_celebrities_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCelebrities_ImageAnalysis(t *testing.T) { @@ -29,7 +31,7 @@ func TestCelebrities_ImageAnalysis(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["CelebrityFaces"]) }, }, @@ -41,7 +43,7 @@ func TestCelebrities_ImageAnalysis(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["Name"]) assert.NotNil(t, resp["KnownGender"]) }, @@ -76,7 +78,7 @@ func TestAsyncVideoJobs_CelebrityRecognition(t *testing.T) { //nolint:parallelte require.Equal(t, http.StatusOK, rec.Code, "StartCelebrityRecognition") var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -86,7 +88,7 @@ func TestAsyncVideoJobs_CelebrityRecognition(t *testing.T) { //nolint:parallelte require.Equal(t, http.StatusOK, rec.Code, "GetCelebrityRecognition") var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED @@ -94,7 +96,7 @@ func TestAsyncVideoJobs_CelebrityRecognition(t *testing.T) { //nolint:parallelte require.Equal(t, http.StatusOK, rec.Code, "GetCelebrityRecognition") var secondResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", secondResp["JobStatus"]) assert.NotNil(t, secondResp["Celebrities"]) } diff --git a/services/rekognition/handler_collections_test.go b/services/rekognition/handler_collections_test.go index 133e8a8155..397d9d6cde 100644 --- a/services/rekognition/handler_collections_test.go +++ b/services/rekognition/handler_collections_test.go @@ -1,7 +1,8 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -31,7 +33,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["CollectionArn"], "arn:aws:rekognition:") assert.Equal(t, "7.0", resp["FaceModelVersion"]) }, @@ -47,7 +49,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ResourceAlreadyExistsException", resp["__type"]) }, }, @@ -62,7 +64,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.InDelta(t, float64(200), resp["StatusCode"], 0) }, }, @@ -74,7 +76,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }, }, @@ -89,7 +91,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["CollectionARN"], "arn:aws:rekognition:") assert.InDelta(t, float64(0), resp["FaceCount"], 0) }, @@ -102,7 +104,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) ids, _ := resp["CollectionIds"].([]any) assert.Empty(t, ids) }, @@ -118,7 +120,7 @@ func TestRekognition_Collections(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) ids, _ := resp["CollectionIds"].([]any) assert.Len(t, ids, 1) assert.Equal(t, "list-coll", ids[0]) @@ -165,7 +167,7 @@ func TestListCollections_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) ids1, _ := page1["CollectionIds"].([]any) require.Len(t, ids1, 2) @@ -180,7 +182,7 @@ func TestListCollections_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) ids2, _ := page2["CollectionIds"].([]any) require.Len(t, ids2, 1) @@ -205,7 +207,7 @@ func TestDeleteCollection_CascadesToFaces(t *testing.T) { rec := doRequest(t, h, "ListFaces", map[string]any{"CollectionId": "cascade-coll"}) require.Equal(t, http.StatusOK, rec.Code) var lf map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lf)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lf, jsonx.V1())) faces, _ := lf["Faces"].([]any) require.Len(t, faces, 2) @@ -218,7 +220,7 @@ func TestDeleteCollection_CascadesToFaces(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -234,7 +236,7 @@ func TestDescribeCollection_NotFound_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -344,13 +346,13 @@ func TestListCollections_EmptyReturnsSlices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) // Decode raw to check for non-null slice presence. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasIDs := raw["CollectionIds"] assert.True(t, hasIDs, "CollectionIds must be present") var ids []any - require.NoError(t, json.Unmarshal(raw["CollectionIds"], &ids)) + require.NoError(t, json.Unmarshal(raw["CollectionIds"], &ids, jsonx.V1())) assert.NotNil(t, ids, "CollectionIds must not be null") } diff --git a/services/rekognition/handler_custom_labels_test.go b/services/rekognition/handler_custom_labels_test.go index dbbeb4bee9..8eb25cdb9d 100644 --- a/services/rekognition/handler_custom_labels_test.go +++ b/services/rekognition/handler_custom_labels_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetectCustomLabels_ReturnsEmptyList(t *testing.T) { @@ -20,6 +22,6 @@ func TestDetectCustomLabels_ReturnsEmptyList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["CustomLabels"]) } diff --git a/services/rekognition/handler_datasets_test.go b/services/rekognition/handler_datasets_test.go index 12012eb510..3493972cd3 100644 --- a/services/rekognition/handler_datasets_test.go +++ b/services/rekognition/handler_datasets_test.go @@ -2,12 +2,14 @@ package rekognition_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractLabels extracts the label list from a ListDatasetLabels response @@ -18,7 +20,7 @@ func extractLabels(t *testing.T, body []byte) []any { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) v, _ := resp["DatasetLabelDescriptions"].([]any) @@ -36,7 +38,7 @@ func TestListDatasetLabels_SingleLabel(t *testing.T) { //nolint:paralleltest // rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "lbl-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateDataset", map[string]any{ @@ -45,7 +47,7 @@ func TestListDatasetLabels_SingleLabel(t *testing.T) { //nolint:paralleltest // }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) dsARN := dsResp["DatasetArn"].(string) // Add two entries: cat appears twice, dog once @@ -83,7 +85,7 @@ func TestListDatasetLabels_MultiLabel(t *testing.T) { //nolint:paralleltest // s rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "ml-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) rec = doRequest(t, h, "CreateDataset", map[string]any{ "ProjectArn": projResp["ProjectArn"].(string), @@ -91,7 +93,7 @@ func TestListDatasetLabels_MultiLabel(t *testing.T) { //nolint:paralleltest // s }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) dsARN := dsResp["DatasetArn"].(string) // Multi-label entry: sunglasses + hat @@ -121,7 +123,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "page-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) rec = doRequest(t, h, "CreateDataset", map[string]any{ "ProjectArn": projResp["ProjectArn"].(string), @@ -129,7 +131,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) dsARN := dsResp["DatasetArn"].(string) // Add 3 entries with distinct labels @@ -137,7 +139,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // entry, _ := json.Marshal(map[string]any{ "source-ref": "s3://b/img" + string(rune('0'+i)) + ".jpg", "labels-metadata": map[string]any{"class-name": lbl}, - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateDatasetEntries", map[string]any{ "DatasetArn": dsARN, "Changes": map[string]any{"GroundTruth": entry}, @@ -156,7 +158,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // require.Len(t, firstPageLabels, 2) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) nextToken, hasToken := page1["NextToken"].(string) require.True(t, hasToken, "expected NextToken for more pages") @@ -166,7 +168,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // decoded, err := base64.RawURLEncoding.DecodeString(nextToken) require.NoError(t, err) var tok map[string]any - require.NoError(t, json.Unmarshal(decoded, &tok)) + require.NoError(t, json.Unmarshal(decoded, &tok, jsonx.V1())) assert.InDelta(t, float64(2), tok["o"], 0) // Second page @@ -181,7 +183,7 @@ func TestListDatasetLabels_OpaqueToken(t *testing.T) { //nolint:paralleltest // require.Len(t, secondPageLabels, 1, "expected 1 label on second page") var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) _, hasMore := page2["NextToken"].(string) assert.False(t, hasMore, "should not have next token on last page") } @@ -192,7 +194,7 @@ func TestListDatasetLabels_InvalidToken(t *testing.T) { //nolint:paralleltest // rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "inv-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) rec = doRequest(t, h, "CreateDataset", map[string]any{ "ProjectArn": projResp["ProjectArn"].(string), @@ -200,7 +202,7 @@ func TestListDatasetLabels_InvalidToken(t *testing.T) { //nolint:paralleltest // }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) // Invalid token treated as offset 0 (returns from start, no error) rec = doRequest(t, h, "ListDatasetLabels", map[string]any{ @@ -220,7 +222,7 @@ func TestDistributeDatasetEntries_SetsInProgress(t *testing.T) { //nolint:parall rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "dist-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateDataset", map[string]any{ @@ -229,7 +231,7 @@ func TestDistributeDatasetEntries_SetsInProgress(t *testing.T) { //nolint:parall }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) dsARN := dsResp["DatasetArn"].(string) rec = doRequest(t, h, "DistributeDatasetEntries", map[string]any{ @@ -244,7 +246,7 @@ func TestDistributeDatasetEntries_SetsInProgress(t *testing.T) { //nolint:parall require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) desc := descResp["DatasetDescription"].(map[string]any) assert.Equal(t, "UPDATE_IN_PROGRESS", desc["Status"]) } @@ -260,7 +262,7 @@ func TestDeleteDataset_WhileUpdating_Rejected(t *testing.T) { //nolint:parallelt rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "del-ds-proj"}) require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateDataset", map[string]any{ @@ -269,7 +271,7 @@ func TestDeleteDataset_WhileUpdating_Rejected(t *testing.T) { //nolint:parallelt }) require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) dsARN := dsResp["DatasetArn"].(string) rec = doRequest(t, h, "DistributeDatasetEntries", map[string]any{ @@ -283,7 +285,7 @@ func TestDeleteDataset_WhileUpdating_Rejected(t *testing.T) { //nolint:parallelt require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceInUseException", errResp["__type"]) } @@ -308,7 +310,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) tests := []struct { @@ -329,7 +331,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) string { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) arn := resp["DatasetArn"].(string) assert.Contains(t, arn, "arn:aws:rekognition:") @@ -362,7 +364,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) desc := resp["DatasetDescription"].(map[string]any) assert.Equal(t, "CREATE_COMPLETE", desc["Status"]) assert.Equal(t, "TRAIN", desc["DatasetType"]) @@ -388,7 +390,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["DatasetEntries"]) }) @@ -403,7 +405,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["DatasetLabelDescriptions"]) }) @@ -429,7 +431,7 @@ func TestDatasets(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var dsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dsResp, jsonx.V1())) freshARN := dsResp["DatasetArn"].(string) rec = doRequest(t, h, "DeleteDataset", map[string]any{"DatasetArn": freshARN}) @@ -456,7 +458,7 @@ func TestCreateDataset_DuplicateProjectAndType_Rejected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateDataset", map[string]any{ @@ -473,7 +475,7 @@ func TestCreateDataset_DuplicateProjectAndType_Rejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceAlreadyExistsException", errResp["__type"]) // Same project, different DatasetType -> allowed. diff --git a/services/rekognition/handler_face_liveness_test.go b/services/rekognition/handler_face_liveness_test.go index d7869673e5..cb98ad81b9 100644 --- a/services/rekognition/handler_face_liveness_test.go +++ b/services/rekognition/handler_face_liveness_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ============================================================================= @@ -25,14 +27,14 @@ func TestFaceLiveness_ConfidenceRange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) sessionID := createResp["SessionId"].(string) rec = doRequest(t, h, "GetFaceLivenessSessionResults", map[string]any{"SessionId": sessionID}) require.Equal(t, http.StatusOK, rec.Code) var resultResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resultResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resultResp, jsonx.V1())) confidence := resultResp["Confidence"].(float64) assert.GreaterOrEqual(t, confidence, float64(75), "confidence must be >= 75") assert.Less(t, confidence, float64(100), "confidence must be < 100") @@ -47,7 +49,7 @@ func TestFaceLiveness_TwoSessionsDifferentConfidence(t *testing.T) { //nolint:pa rec := doRequest(t, h, "GetFaceLivenessSessionResults", map[string]any{"SessionId": sessionID}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Confidence"].(float64) } @@ -58,7 +60,7 @@ func TestFaceLiveness_TwoSessionsDifferentConfidence(t *testing.T) { //nolint:pa rec := doRequest(t, h, "CreateFaceLivenessSession", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) c := getConfidence(resp["SessionId"].(string)) confidences[c] = true } @@ -84,7 +86,7 @@ func TestFaceLiveness(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["SessionId"]) }, }, @@ -103,7 +105,7 @@ func TestFaceLiveness(t *testing.T) { //nolint:paralleltest // existing issue. if tc.action == "CreateFaceLivenessSession" && rec.Code == http.StatusOK { var resp map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &resp) + _ = json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) sessionID = resp["SessionId"].(string) } }) @@ -114,7 +116,7 @@ func TestFaceLiveness(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["Status"]) assert.Equal(t, sessionID, resp["SessionId"]) }) diff --git a/services/rekognition/handler_faces_test.go b/services/rekognition/handler_faces_test.go index 473a3cba4c..a91482ca8a 100644 --- a/services/rekognition/handler_faces_test.go +++ b/services/rekognition/handler_faces_test.go @@ -1,13 +1,15 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -33,7 +35,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) records, _ := resp["FaceRecords"].([]any) assert.Len(t, records, 1) }, @@ -46,7 +48,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }, }, @@ -62,7 +64,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) faces, _ := resp["Faces"].([]any) assert.Len(t, faces, 1) }, @@ -82,7 +84,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["DeletedFaces"]) }, }, @@ -100,7 +102,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) }, }, @@ -116,7 +118,7 @@ func TestRekognition_Faces(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) matches, _ := resp["FaceMatches"].([]any) assert.Len(t, matches, 1) }, @@ -167,7 +169,7 @@ func TestListFaces_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) faces1, _ := page1["Faces"].([]any) require.Len(t, faces1, 2) @@ -183,7 +185,7 @@ func TestListFaces_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) faces2, _ := page2["Faces"].([]any) require.Len(t, faces2, 1) @@ -216,7 +218,7 @@ func TestSearchFaces_RealFaceId_ReturnsMatches(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var idx1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx1, jsonx.V1())) records, _ := idx1["FaceRecords"].([]any) require.Len(t, records, 1) rec1, _ := records[0].(map[string]any) @@ -241,7 +243,7 @@ func TestSearchFaces_RealFaceId_ReturnsMatches(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var sf map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sf)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sf, jsonx.V1())) matches, _ := sf["FaceMatches"].([]any) assert.Len(t, matches, 2) assert.Equal(t, faceID, sf["SearchedFaceId"]) @@ -264,7 +266,7 @@ func TestSearchFaces_UnknownFaceId_Returns404(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -286,7 +288,7 @@ func TestDeleteFaces_BySpecificIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var idx map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx, jsonx.V1())) records, _ := idx["FaceRecords"].([]any) rec0, _ := records[0].(map[string]any) face, _ := rec0["Face"].(map[string]any) @@ -301,7 +303,7 @@ func TestDeleteFaces_BySpecificIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &delResp, jsonx.V1())) deleted, _ := delResp["DeletedFaces"].([]any) assert.Len(t, deleted, 2) @@ -310,7 +312,7 @@ func TestDeleteFaces_BySpecificIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var lf map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lf)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &lf, jsonx.V1())) remaining, _ := lf["Faces"].([]any) require.Len(t, remaining, 1) remainFace, _ := remaining[0].(map[string]any) @@ -329,7 +331,7 @@ func TestListFaces_UnknownCollection_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -346,14 +348,14 @@ func TestListFaces_EmptyCollection_ReturnsNonNullSlice(t *testing.T) { rec := doRequest(t, h, "ListFaces", map[string]any{"CollectionId": "empty-faces-coll"}) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasFaces := raw["Faces"] assert.True(t, hasFaces, "Faces field must be present") var faces []any - require.NoError(t, json.Unmarshal(raw["Faces"], &faces)) + require.NoError(t, json.Unmarshal(raw["Faces"], &faces, jsonx.V1())) assert.NotNil(t, faces, "Faces must not be null") } @@ -374,7 +376,7 @@ func TestIndexFaces_ExternalImageId_RoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var idx map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &idx, jsonx.V1())) records, _ := idx["FaceRecords"].([]any) require.Len(t, records, 1) rec0, _ := records[0].(map[string]any) @@ -386,7 +388,7 @@ func TestIndexFaces_ExternalImageId_RoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var lf map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &lf)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &lf, jsonx.V1())) faces, _ := lf["Faces"].([]any) require.Len(t, faces, 1) f0, _ := faces[0].(map[string]any) @@ -404,7 +406,7 @@ func decodeFaceIDs(t *testing.T, body []byte) []string { } `json:"Face"` } `json:"FaceRecords"` } - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) ids := make([]string, 0, len(resp.FaceRecords)) for _, r := range resp.FaceRecords { @@ -437,7 +439,7 @@ func TestIndexFaces_ConfidenceDeterministicAndPlausible(t *testing.T) { } `json:"Face"` } `json:"FaceRecords"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.FaceRecords, 1) conf := resp.FaceRecords[0].Face.Confidence @@ -487,7 +489,7 @@ func TestSearchFaces_SimilarityDeterministic(t *testing.T) { Similarity float64 `json:"Similarity"` } `json:"FaceMatches"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.FaceMatches, 1) return resp.FaceMatches[0].Similarity @@ -522,7 +524,7 @@ func TestSearchFaces_SameExternalImageId_ScoresExactMatch(t *testing.T) { Similarity float64 `json:"Similarity"` } `json:"FaceMatches"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.FaceMatches, 1) assert.InDelta(t, 100.0, resp.FaceMatches[0].Similarity, 1e-9, "faces sharing an ExternalImageId must score an exact match") @@ -549,7 +551,7 @@ func TestSearchFacesByImage_SimilarityDependsOnImage(t *testing.T) { Similarity float64 `json:"Similarity"` } `json:"FaceMatches"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.FaceMatches, 1) return resp.FaceMatches[0].Similarity @@ -587,7 +589,7 @@ func TestFaceRoundTrip_IndexSearchListDelete(t *testing.T) { FaceID string `json:"FaceId"` } `json:"Faces"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &list, jsonx.V1())) require.Len(t, list.Faces, 2) // SearchFaces from id1 finds id2. FaceMatchThreshold explicitly 0: this @@ -608,7 +610,7 @@ func TestFaceRoundTrip_IndexSearchListDelete(t *testing.T) { } `json:"Face"` } `json:"FaceMatches"` } - require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &search)) + require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &search, jsonx.V1())) require.Len(t, search.FaceMatches, 1) assert.Equal(t, id2, search.FaceMatches[0].Face.FaceID) @@ -621,9 +623,9 @@ func TestFaceRoundTrip_IndexSearchListDelete(t *testing.T) { require.Equal(t, http.StatusOK, searchRec2.Code) var search2 struct { - FaceMatches []json.RawMessage `json:"FaceMatches"` + FaceMatches []jsontext.Value `json:"FaceMatches"` } - require.NoError(t, json.Unmarshal(searchRec2.Body.Bytes(), &search2)) + require.NoError(t, json.Unmarshal(searchRec2.Body.Bytes(), &search2, jsonx.V1())) assert.Empty(t, search2.FaceMatches) // SearchFaces for the deleted id returns ResourceNotFoundException. @@ -647,7 +649,7 @@ func TestImageAnalysis_CompareFaces(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["FaceMatches"]) assert.NotNil(t, resp["SourceImageFace"]) } @@ -660,7 +662,7 @@ func TestImageAnalysis_DetectFaces(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["FaceDetails"]) } @@ -713,7 +715,7 @@ func TestImageAnalysis_EnumValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) }) } @@ -779,7 +781,7 @@ func TestAsyncVideoJobs_Faces(t *testing.T) { //nolint:paralleltest // stateful checkGet: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["JobStatus"]) assert.NotNil(t, resp["Faces"]) }, @@ -791,7 +793,7 @@ func TestAsyncVideoJobs_Faces(t *testing.T) { //nolint:paralleltest // stateful checkGet: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["JobStatus"]) assert.NotNil(t, resp["Persons"]) }, @@ -805,7 +807,7 @@ func TestAsyncVideoJobs_Faces(t *testing.T) { //nolint:paralleltest // stateful require.Equal(t, http.StatusOK, rec.Code, flow.startAction) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -815,7 +817,7 @@ func TestAsyncVideoJobs_Faces(t *testing.T) { //nolint:paralleltest // stateful require.Equal(t, http.StatusOK, rec.Code, flow.getAction) var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED diff --git a/services/rekognition/handler_labels_test.go b/services/rekognition/handler_labels_test.go index 1b5cb1b78f..2a80a9dc7f 100644 --- a/services/rekognition/handler_labels_test.go +++ b/services/rekognition/handler_labels_test.go @@ -1,13 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -32,7 +33,7 @@ func TestDetectLabels_ReturnsEmptyList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Labels"]) } @@ -44,7 +45,7 @@ func TestAsyncVideoJobs_LabelDetection(t *testing.T) { //nolint:paralleltest // require.Equal(t, http.StatusOK, rec.Code, "StartLabelDetection") var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -54,7 +55,7 @@ func TestAsyncVideoJobs_LabelDetection(t *testing.T) { //nolint:paralleltest // require.Equal(t, http.StatusOK, rec.Code, "GetLabelDetection") var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED @@ -62,7 +63,7 @@ func TestAsyncVideoJobs_LabelDetection(t *testing.T) { //nolint:paralleltest // require.Equal(t, http.StatusOK, rec.Code, "GetLabelDetection") var secondResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", secondResp["JobStatus"]) assert.NotNil(t, secondResp["Labels"]) } diff --git a/services/rekognition/handler_media_analysis_test.go b/services/rekognition/handler_media_analysis_test.go index 3d5ba8ac89..fdc33a3478 100644 --- a/services/rekognition/handler_media_analysis_test.go +++ b/services/rekognition/handler_media_analysis_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ============================================================================= @@ -36,7 +38,7 @@ func TestMediaAnalysisJob_Lifecycle(t *testing.T) { //nolint:paralleltest // sta require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -46,7 +48,7 @@ func TestMediaAnalysisJob_Lifecycle(t *testing.T) { //nolint:paralleltest // sta require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, jobID, getResp["JobId"]) assert.NotEmpty(t, getResp["Status"]) @@ -73,7 +75,7 @@ func TestMediaAnalysisJob_Lifecycle(t *testing.T) { //nolint:paralleltest // sta require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) jobs, ok := listResp["MediaAnalysisJobs"].([]any) require.True(t, ok) require.GreaterOrEqual(t, len(jobs), 1) @@ -168,7 +170,7 @@ func TestAsyncVideoJobs_PersonTrackingAndSegmentDetection(t *testing.T) { //noli checkGet: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["JobStatus"]) assert.NotNil(t, resp["Persons"]) }, @@ -180,7 +182,7 @@ func TestAsyncVideoJobs_PersonTrackingAndSegmentDetection(t *testing.T) { //noli checkGet: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["JobStatus"]) assert.NotNil(t, resp["Segments"]) }, @@ -194,7 +196,7 @@ func TestAsyncVideoJobs_PersonTrackingAndSegmentDetection(t *testing.T) { //noli require.Equal(t, http.StatusOK, rec.Code, flow.startAction) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -204,7 +206,7 @@ func TestAsyncVideoJobs_PersonTrackingAndSegmentDetection(t *testing.T) { //noli require.Equal(t, http.StatusOK, rec.Code, flow.getAction) var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED @@ -265,7 +267,7 @@ func TestMediaAnalysisJobs(t *testing.T) { //nolint:paralleltest // existing iss require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"].(string) assert.NotEmpty(t, jobID) @@ -275,7 +277,7 @@ func TestMediaAnalysisJobs(t *testing.T) { //nolint:paralleltest // existing iss require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, jobID, resp["JobId"]) assert.Equal(t, "my-analysis", resp["JobName"]) assert.Equal(t, "SUCCEEDED", resp["Status"]) @@ -287,7 +289,7 @@ func TestMediaAnalysisJobs(t *testing.T) { //nolint:paralleltest // existing iss require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs, ok := resp["MediaAnalysisJobs"].([]any) require.True(t, ok) assert.Len(t, jobs, 1) diff --git a/services/rekognition/handler_moderation_test.go b/services/rekognition/handler_moderation_test.go index 18fbb736ad..ceac653a91 100644 --- a/services/rekognition/handler_moderation_test.go +++ b/services/rekognition/handler_moderation_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestModeration_ImageAnalysis(t *testing.T) { @@ -29,7 +31,7 @@ func TestModeration_ImageAnalysis(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["ModerationLabels"]) }, }, @@ -41,7 +43,7 @@ func TestModeration_ImageAnalysis(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotNil(t, resp["Persons"]) }, }, @@ -125,7 +127,7 @@ func TestDetectProtectiveEquipment_SummarizationAttributesValidation(t *testing. if tc.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) } }) @@ -140,7 +142,7 @@ func TestAsyncVideoJobs_ContentModeration(t *testing.T) { //nolint:paralleltest require.Equal(t, http.StatusOK, rec.Code, "StartContentModeration") var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -150,7 +152,7 @@ func TestAsyncVideoJobs_ContentModeration(t *testing.T) { //nolint:paralleltest require.Equal(t, http.StatusOK, rec.Code, "GetContentModeration") var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED @@ -158,7 +160,7 @@ func TestAsyncVideoJobs_ContentModeration(t *testing.T) { //nolint:paralleltest require.Equal(t, http.StatusOK, rec.Code, "GetContentModeration") var secondResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", secondResp["JobStatus"]) assert.NotNil(t, secondResp["ModerationLabels"]) } diff --git a/services/rekognition/handler_project_versions.go b/services/rekognition/handler_project_versions.go index fd63079794..74a72e8e3f 100644 --- a/services/rekognition/handler_project_versions.go +++ b/services/rekognition/handler_project_versions.go @@ -2,7 +2,7 @@ package rekognition import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -53,8 +53,8 @@ type createProjectVersionReq struct { VersionName string `json:"VersionName"` KmsKeyID string `json:"KmsKeyId"` VersionDescription string `json:"VersionDescription"` - TrainingData json.RawMessage `json:"TrainingData"` - TestingData json.RawMessage `json:"TestingData"` + TrainingData jsontext.Value `json:"TrainingData"` + TestingData jsontext.Value `json:"TestingData"` } type createProjectVersionResp struct { diff --git a/services/rekognition/handler_project_versions_test.go b/services/rekognition/handler_project_versions_test.go index 0d43d9474b..075dc12e5c 100644 --- a/services/rekognition/handler_project_versions_test.go +++ b/services/rekognition/handler_project_versions_test.go @@ -1,7 +1,7 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -31,7 +32,7 @@ func TestProjectVersions(t *testing.T) { //nolint:paralleltest // existing issue rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "ver-proj"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ProjectArn"].(string) }, @@ -39,7 +40,7 @@ func TestProjectVersions(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["ProjectVersionArn"], "arn:aws:rekognition:") }, }, @@ -55,7 +56,7 @@ func TestProjectVersions(t *testing.T) { //nolint:paralleltest // existing issue rec := doRequest(t, h, "CreateProject", map[string]any{"ProjectName": "no-output-config-proj"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ProjectArn"].(string) }, @@ -97,7 +98,7 @@ func TestProjectVersion_Lifecycle(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) // Create version @@ -109,7 +110,7 @@ func TestProjectVersion_Lifecycle(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp, jsonx.V1())) versionARN := verResp["ProjectVersionArn"].(string) // DescribeProjectVersions @@ -117,7 +118,7 @@ func TestProjectVersion_Lifecycle(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) assert.Len(t, versions, 1) @@ -129,7 +130,7 @@ func TestProjectVersion_Lifecycle(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.Equal(t, "RUNNING", startResp["Status"]) // StopProjectVersion @@ -139,7 +140,7 @@ func TestProjectVersion_Lifecycle(t *testing.T) { //nolint:paralleltest // exist require.Equal(t, http.StatusOK, rec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Equal(t, "STOPPED", stopResp["Status"]) // DeleteProjectVersion @@ -167,7 +168,7 @@ func TestProjectVersion_StateTransitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -178,13 +179,13 @@ func TestProjectVersion_StateTransitions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp, jsonx.V1())) versionARN := verResp["ProjectVersionArn"].(string) status := func() string { out := doRequest(t, h, "DescribeProjectVersions", map[string]any{"ProjectArn": projectARN}) var m map[string]any - require.NoError(t, json.Unmarshal(out.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(out.Body.Bytes(), &m, jsonx.V1())) return m["ProjectVersionDescriptions"].([]any)[0].(map[string]any)["Status"].(string) } @@ -192,7 +193,7 @@ func TestProjectVersion_StateTransitions(t *testing.T) { out := doRequest(t, h, action, body) require.Equal(t, http.StatusBadRequest, out.Code) var m map[string]any - require.NoError(t, json.Unmarshal(out.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(out.Body.Bytes(), &m, jsonx.V1())) return m["__type"].(string) } @@ -239,7 +240,7 @@ func TestCreateProjectVersion_FullFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -256,14 +257,14 @@ func TestCreateProjectVersion_FullFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp, jsonx.V1())) versionARN := verResp["ProjectVersionArn"].(string) rec = doRequest(t, h, "DescribeProjectVersions", map[string]any{"ProjectArn": projectARN}) require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, versions, 1) @@ -282,7 +283,7 @@ func TestCreateProjectVersion_FullFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags, _ := tagsResp["Tags"].(map[string]any) assert.Equal(t, "vision", tags["team"]) } @@ -295,7 +296,7 @@ func TestCopyProjectVersion(t *testing.T) { //nolint:paralleltest // existing is require.Equal(t, http.StatusOK, rec.Code) var srcProjResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &srcProjResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &srcProjResp, jsonx.V1())) srcProjectARN := srcProjResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -306,7 +307,7 @@ func TestCopyProjectVersion(t *testing.T) { //nolint:paralleltest // existing is require.Equal(t, http.StatusOK, rec.Code) var srcVerResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &srcVerResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &srcVerResp, jsonx.V1())) sourceVersionARN := srcVerResp["ProjectVersionArn"].(string) // Create destination project @@ -314,7 +315,7 @@ func TestCopyProjectVersion(t *testing.T) { //nolint:paralleltest // existing is require.Equal(t, http.StatusOK, rec.Code) var dstProjResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dstProjResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dstProjResp, jsonx.V1())) dstProjectARN := dstProjResp["ProjectArn"].(string) // Copy version fails when SourceProjectArn doesn't match the project @@ -339,7 +340,7 @@ func TestCopyProjectVersion(t *testing.T) { //nolint:paralleltest // existing is require.Equal(t, http.StatusOK, rec.Code) var copyResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ©Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ©Resp, jsonx.V1())) assert.Contains(t, copyResp["ProjectVersionArn"], "dst-proj") // SourceProjectVersionArn and OutputConfig are echoed back on the @@ -348,7 +349,7 @@ func TestCopyProjectVersion(t *testing.T) { //nolint:paralleltest // existing is require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, versions, 1) copied := versions[0].(map[string]any) @@ -421,7 +422,7 @@ func TestCreateProjectVersion_FeatureConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -438,7 +439,7 @@ func TestCreateProjectVersion_FeatureConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, versions, 1) @@ -507,7 +508,7 @@ func TestCreateProjectVersion_TrainingTestingDataMustBothBeSpecified(t *testing. require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) body := map[string]any{ @@ -536,7 +537,7 @@ func TestStartProjectVersion_MaxInferenceUnitsRoundTrip(t *testing.T) { //nolint require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -547,7 +548,7 @@ func TestStartProjectVersion_MaxInferenceUnitsRoundTrip(t *testing.T) { //nolint require.Equal(t, http.StatusOK, rec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp, jsonx.V1())) versionARN := verResp["ProjectVersionArn"].(string) rec = doRequest(t, h, "StartProjectVersion", map[string]any{ @@ -561,7 +562,7 @@ func TestStartProjectVersion_MaxInferenceUnitsRoundTrip(t *testing.T) { //nolint require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, versions, 1) desc := versions[0].(map[string]any) diff --git a/services/rekognition/handler_projects_test.go b/services/rekognition/handler_projects_test.go index 47d4906388..fbf03de8ff 100644 --- a/services/rekognition/handler_projects_test.go +++ b/services/rekognition/handler_projects_test.go @@ -1,13 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -28,7 +29,7 @@ func TestProjects(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["ProjectArn"], "arn:aws:rekognition:") assert.Contains(t, resp["ProjectArn"], "project/my-project") }, @@ -51,7 +52,7 @@ func TestProjects(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["message"]) }, }, @@ -72,7 +73,7 @@ func TestProjects(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) descriptions, ok := resp["ProjectDescriptions"].([]any) require.True(t, ok) assert.GreaterOrEqual(t, len(descriptions), 1) @@ -86,7 +87,7 @@ func TestProjects(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) descriptions, ok := resp["ProjectDescriptions"].([]any) require.True(t, ok) assert.Empty(t, descriptions) @@ -119,7 +120,7 @@ func TestProject_DeleteSuccess(t *testing.T) { //nolint:paralleltest // existing require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) projectARN := createResp["ProjectArn"].(string) // Delete it @@ -127,7 +128,7 @@ func TestProject_DeleteSuccess(t *testing.T) { //nolint:paralleltest // existing assert.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp, jsonx.V1())) assert.Equal(t, "DELETING", deleteResp["Status"]) // DescribeProjects should no longer return it @@ -135,7 +136,7 @@ func TestProject_DeleteSuccess(t *testing.T) { //nolint:paralleltest // existing require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) descriptions := descResp["ProjectDescriptions"].([]any) assert.Empty(t, descriptions) } @@ -153,7 +154,7 @@ func TestProject_DeleteWithVersions_Rejected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -167,7 +168,7 @@ func TestProject_DeleteWithVersions_Rejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceInUseException", errResp["__type"]) } @@ -179,7 +180,7 @@ func TestProjectPolicies(t *testing.T) { //nolint:paralleltest // existing issue require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) tests := []struct { @@ -201,7 +202,7 @@ func TestProjectPolicies(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.NotEmpty(t, resp["PolicyRevisionId"]) }, }, @@ -213,7 +214,7 @@ func TestProjectPolicies(t *testing.T) { //nolint:paralleltest // existing issue check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) policies, ok := resp["ProjectPolicies"].([]any) require.True(t, ok) assert.Len(t, policies, 1) @@ -254,7 +255,7 @@ func TestDeleteProject_CascadesProjectPolicies(t *testing.T) { //nolint:parallel require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "PutProjectPolicy", map[string]any{ @@ -271,7 +272,7 @@ func TestDeleteProject_CascadesProjectPolicies(t *testing.T) { //nolint:parallel require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) policies, ok := listResp["ProjectPolicies"].([]any) require.True(t, ok) assert.Empty(t, policies, "ProjectPolicies must be cascade-deleted with the project") diff --git a/services/rekognition/handler_stream_processors_test.go b/services/rekognition/handler_stream_processors_test.go index 4d11a1fd83..132b434e4c 100644 --- a/services/rekognition/handler_stream_processors_test.go +++ b/services/rekognition/handler_stream_processors_test.go @@ -1,7 +1,8 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -31,7 +33,7 @@ func TestRekognition_StreamProcessors(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Contains(t, resp["StreamProcessorArn"], "arn:aws:rekognition:") }, }, @@ -46,7 +48,7 @@ func TestRekognition_StreamProcessors(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) // AWS reports a duplicate stream processor name as // ResourceInUseException, not ResourceAlreadyExistsException // (verified against aws-sdk-go-v2/service/rekognition's @@ -65,7 +67,7 @@ func TestRekognition_StreamProcessors(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "STOPPED", resp["Status"]) assert.Contains(t, resp["StreamProcessorArn"], "arn:aws:rekognition:") }, @@ -81,7 +83,7 @@ func TestRekognition_StreamProcessors(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) procs, _ := resp["StreamProcessors"].([]any) assert.Len(t, procs, 1) }, @@ -122,7 +124,7 @@ func TestRekognition_StreamProcessors(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }, }, @@ -176,7 +178,7 @@ func TestListStreamProcessors_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) procs1, _ := page1["StreamProcessors"].([]any) require.Len(t, procs1, 2) @@ -189,7 +191,7 @@ func TestListStreamProcessors_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) procs2, _ := page2["StreamProcessors"].([]any) require.Len(t, procs2, 1) @@ -207,14 +209,14 @@ func TestListStreamProcessors_EmptyReturnsNonNullSlice(t *testing.T) { rec := doRequest(t, h, "ListStreamProcessors", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasProcs := raw["StreamProcessors"] assert.True(t, hasProcs, "StreamProcessors field must be present") var procs []any - require.NoError(t, json.Unmarshal(raw["StreamProcessors"], &procs)) + require.NoError(t, json.Unmarshal(raw["StreamProcessors"], &procs, jsonx.V1())) assert.NotNil(t, procs, "StreamProcessors must not be null") } @@ -237,7 +239,7 @@ func TestStopStreamProcessor_AlreadyStopped_IsIdempotent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "STOPPED", desc["Status"]) } @@ -253,7 +255,7 @@ func TestStartStreamProcessor_Unknown_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -269,7 +271,7 @@ func TestUpdateStreamProcessor_Unknown_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -287,7 +289,7 @@ func TestStreamProcessor_StatusTransitions(t *testing.T) { rec := doRequest(t, h, "DescribeStreamProcessor", map[string]any{"Name": "status-proc"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["Status"].(string) } @@ -423,7 +425,7 @@ func TestCreateStreamProcessor_FullFieldsRoundTripThroughDescribe(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "arn:aws:kms:us-east-1:000000000000:key/abc", resp["KmsKeyId"]) @@ -488,7 +490,7 @@ func TestUpdateStreamProcessor_AppliesFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -566,7 +568,7 @@ func TestUpdateStreamProcessor_RegionsOfInterestForUpdate_Replaces(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rois, _ := resp["RegionsOfInterest"].([]any) assert.Len(t, rois, 2) diff --git a/services/rekognition/handler_tags_test.go b/services/rekognition/handler_tags_test.go index 48632affae..2988826b99 100644 --- a/services/rekognition/handler_tags_test.go +++ b/services/rekognition/handler_tags_test.go @@ -1,7 +1,7 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -29,7 +30,7 @@ func TestRekognition_Tags(t *testing.T) { setup: func(h *rekognition.Handler) string { rec := doRequest(t, h, "CreateCollection", map[string]any{"CollectionId": "tag-coll"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["CollectionArn"].(string) }, @@ -49,7 +50,7 @@ func TestRekognition_Tags(t *testing.T) { map[string]any{"CollectionId": "ltfr-coll", "Tags": map[string]string{"k": "v"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["CollectionArn"].(string) }, @@ -60,7 +61,7 @@ func TestRekognition_Tags(t *testing.T) { check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) tags, _ := resp["Tags"].(map[string]any) assert.Equal(t, "v", tags["k"]) }, @@ -76,7 +77,7 @@ func TestRekognition_Tags(t *testing.T) { map[string]any{"CollectionId": "untag-coll", "Tags": map[string]string{"k": "v"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["CollectionArn"].(string) doRequest(t, h, "TagResource", map[string]any{"ResourceArn": arn, "Tags": map[string]string{"k": "v"}}) @@ -125,7 +126,7 @@ func TestUntagResource_UnknownARN_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -144,7 +145,7 @@ func TestListTagsForResource_StreamProcessor_ReturnsTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["StreamProcessorArn"].(string) // Tag the stream processor. @@ -158,7 +159,7 @@ func TestListTagsForResource_StreamProcessor_ReturnsTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp, jsonx.V1())) tags, _ := tagResp["Tags"].(map[string]any) assert.Equal(t, "staging", tags["env"]) assert.Equal(t, "ml", tags["team"]) @@ -222,7 +223,7 @@ func TestTagResource_KeyValueValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["CollectionArn"].(string) rec = doRequest(t, h, "TagResource", map[string]any{"ResourceArn": arn, "Tags": tc.tags}) @@ -239,7 +240,7 @@ func TestTagResource_KeyValidation_ErrorType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["CollectionArn"].(string) rec = doRequest(t, h, "TagResource", map[string]any{ @@ -249,7 +250,7 @@ func TestTagResource_KeyValidation_ErrorType(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) } @@ -265,7 +266,7 @@ func TestTagResource_CountLimit_Enforced(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["CollectionArn"].(string) // Add 200 tags in batches of 50 (keys are "tag-000" through "tag-199"). @@ -297,7 +298,7 @@ func TestTagResource_UpdateExisting_DoesNotCountAgain(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["CollectionArn"].(string) // Add one tag, then update it — should not fail due to count. @@ -322,7 +323,7 @@ func TestTagResource_UnknownARN_Returns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -341,7 +342,7 @@ func TestTagResource_StreamProcessor_TagsValidated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["StreamProcessorArn"].(string) // Valid tag. diff --git a/services/rekognition/handler_test.go b/services/rekognition/handler_test.go index 501a15517e..f94e25a1e5 100644 --- a/services/rekognition/handler_test.go +++ b/services/rekognition/handler_test.go @@ -2,7 +2,7 @@ package rekognition_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -40,7 +41,7 @@ func doRequest(t *testing.T, h *rekognition.Handler, action string, body any) *h if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -65,6 +66,6 @@ func TestRekognition_UnknownOperation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "UnknownOperationException", resp["__type"]) } diff --git a/services/rekognition/handler_text_detection_test.go b/services/rekognition/handler_text_detection_test.go index 7b4ca8f2aa..0d7734d15f 100644 --- a/services/rekognition/handler_text_detection_test.go +++ b/services/rekognition/handler_text_detection_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestDetectText_ReturnsEmptyList(t *testing.T) { @@ -17,7 +19,7 @@ func TestDetectText_ReturnsEmptyList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["TextDetections"]) } @@ -29,7 +31,7 @@ func TestAsyncVideoJobs_TextDetection(t *testing.T) { //nolint:paralleltest // s require.Equal(t, http.StatusOK, rec.Code, "StartTextDetection") var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID, ok := startResp["JobId"].(string) require.True(t, ok) assert.NotEmpty(t, jobID) @@ -39,7 +41,7 @@ func TestAsyncVideoJobs_TextDetection(t *testing.T) { //nolint:paralleltest // s require.Equal(t, http.StatusOK, rec.Code, "GetTextDetection") var firstResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &firstResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", firstResp["JobStatus"]) // Second poll returns SUCCEEDED @@ -47,7 +49,7 @@ func TestAsyncVideoJobs_TextDetection(t *testing.T) { //nolint:paralleltest // s require.Equal(t, http.StatusOK, rec.Code, "GetTextDetection") var secondResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &secondResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", secondResp["JobStatus"]) assert.NotNil(t, secondResp["TextDetections"]) } diff --git a/services/rekognition/handler_users_test.go b/services/rekognition/handler_users_test.go index ca9142f337..a6d2252259 100644 --- a/services/rekognition/handler_users_test.go +++ b/services/rekognition/handler_users_test.go @@ -1,12 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestUsers(t *testing.T) { //nolint:paralleltest // existing issue. @@ -43,7 +45,7 @@ func TestUsers(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) users, ok := resp["Users"].([]any) require.True(t, ok) assert.Len(t, users, 1) @@ -91,7 +93,7 @@ func TestAssociateFaces(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var indexResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &indexResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &indexResp, jsonx.V1())) faceRecords := indexResp["FaceRecords"].([]any) require.Len(t, faceRecords, 1) faceID := faceRecords[0].(map[string]any)["Face"].(map[string]any)["FaceId"].(string) @@ -109,7 +111,7 @@ func TestAssociateFaces(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) associated, ok := resp["AssociatedFaces"].([]any) require.True(t, ok) assert.Len(t, associated, 1) @@ -125,7 +127,7 @@ func TestAssociateFaces(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unsuccessful, ok := resp["UnsuccessfulFaceAssociations"].([]any) require.True(t, ok) assert.Len(t, unsuccessful, 1) @@ -141,7 +143,7 @@ func TestAssociateFaces(t *testing.T) { //nolint:paralleltest // existing issue. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) disassociated, ok := resp["DisassociatedFaces"].([]any) require.True(t, ok) assert.Len(t, disassociated, 1) @@ -179,7 +181,7 @@ func TestSearchUsers(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, faceModelVersion, resp["FaceModelVersion"]) matches, ok := resp["UserMatches"].([]any) require.True(t, ok) @@ -201,7 +203,7 @@ func TestSearchUsers(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) assert.Equal(t, faceModelVersion, resp["FaceModelVersion"]) matches, ok := resp["UserMatches"].([]any) require.True(t, ok) @@ -220,7 +222,7 @@ func TestSearchUsers(t *testing.T) { //nolint:paralleltest // existing issue. check: func(t *testing.T, body []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) matches, ok := resp["UserMatches"].([]any) require.True(t, ok) assert.Len(t, matches, 2) diff --git a/services/rekognition/job_notification.go b/services/rekognition/job_notification.go index dc70b2a528..29df224f8e 100644 --- a/services/rekognition/job_notification.go +++ b/services/rekognition/job_notification.go @@ -2,10 +2,11 @@ package rekognition import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sns" @@ -94,7 +95,7 @@ func buildJobNotification(jobID string, p StartAsyncJobParams) jobNotification { "Timestamp": time.Now().UnixMilli(), "Video": map[string]string{"S3ObjectName": p.VideoS3Name, "S3Bucket": p.VideoS3Bucket}, } - data, _ := json.Marshal(msg) + data, _ := json.Marshal(msg, jsonx.V1()) return jobNotification{topic: p.NotificationTopicARN, message: data} } diff --git a/services/rekognition/job_notification_test.go b/services/rekognition/job_notification_test.go index 2890de65b4..fa5d64ffa4 100644 --- a/services/rekognition/job_notification_test.go +++ b/services/rekognition/job_notification_test.go @@ -1,7 +1,7 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -99,7 +100,7 @@ func TestStartJobNotificationChannel(t *testing.T) { } var start map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &start, jsonx.V1())) if !tt.wantNotify { assert.Empty(t, n.messages) @@ -111,7 +112,7 @@ func TestStartJobNotificationChannel(t *testing.T) { assert.Equal(t, topic, n.topics[0]) var msg map[string]any - require.NoError(t, json.Unmarshal([]byte(n.messages[0]), &msg)) + require.NoError(t, json.Unmarshal([]byte(n.messages[0]), &msg, jsonx.V1())) assert.Equal(t, start["JobId"], msg["JobId"]) assert.Equal(t, "SUCCEEDED", msg["Status"]) assert.Equal(t, tt.wantAPI, msg["API"]) @@ -122,7 +123,7 @@ func TestStartJobNotificationChannel(t *testing.T) { require.Equal(t, http.StatusOK, get.Code) var got map[string]any - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &got, jsonx.V1())) assert.Equal(t, "SUCCEEDED", got["JobStatus"]) }) } diff --git a/services/rekognition/multi_region_test.go b/services/rekognition/multi_region_test.go index 31c654b1a2..5b20a48f67 100644 --- a/services/rekognition/multi_region_test.go +++ b/services/rekognition/multi_region_test.go @@ -2,7 +2,8 @@ package rekognition_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -168,8 +170,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/rekognition/omission_defaults_test.go b/services/rekognition/omission_defaults_test.go index 7dfd34e884..5398d1f3bd 100644 --- a/services/rekognition/omission_defaults_test.go +++ b/services/rekognition/omission_defaults_test.go @@ -1,13 +1,15 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListProjectPolicies_DefaultPageSize locks in the real SDK's documented @@ -24,7 +26,7 @@ func TestListProjectPolicies_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) //nolint:forcetypeassert // test for i := range 6 { @@ -40,7 +42,7 @@ func TestListProjectPolicies_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, _ := resp["ProjectPolicies"].([]any) assert.Len(t, policies, 5, "ListProjectPolicies omits MaxResults => real SDK defaults to 5 per response") diff --git a/services/rekognition/persistence.go b/services/rekognition/persistence.go index 25e2ae52b4..555c00adb5 100644 --- a/services/rekognition/persistence.go +++ b/services/rekognition/persistence.go @@ -2,7 +2,7 @@ package rekognition import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "slices" @@ -35,7 +35,7 @@ const rekognitionSnapshotVersion = 1 // a snapshot from an incompatible (older/newer/absent) build of this backend // as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` DatasetEntries map[string][]string `json:"datasetEntries"` AccountID string `json:"accountId"` diff --git a/services/rekognition/persistence_test.go b/services/rekognition/persistence_test.go index 535689e6c2..c5233379ad 100644 --- a/services/rekognition/persistence_test.go +++ b/services/rekognition/persistence_test.go @@ -1,13 +1,14 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -346,7 +347,7 @@ func TestSnapshotRestore_PreservesAllState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.InDelta(t, float64(1), descResp["FaceCount"], 0) // Verify face survives. @@ -354,7 +355,7 @@ func TestSnapshotRestore_PreservesAllState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var facesResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &facesResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &facesResp, jsonx.V1())) faces, _ := facesResp["Faces"].([]any) assert.Len(t, faces, 1) @@ -382,7 +383,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var projResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &projResp, jsonx.V1())) projectARN := projResp["ProjectArn"].(string) rec = doRequest(t, h, "CreateProjectVersion", map[string]any{ @@ -396,7 +397,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var verResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &verResp, jsonx.V1())) versionARN := verResp["ProjectVersionArn"].(string) rec = doRequest(t, h, "StartProjectVersion", map[string]any{ @@ -410,7 +411,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var dstProjResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dstProjResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &dstProjResp, jsonx.V1())) dstProjectARN := dstProjResp["ProjectArn"].(string) rec = doRequest(t, h, "CopyProjectVersion", map[string]any{ @@ -432,7 +433,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"].(string) snap := backend.Snapshot(t.Context()) @@ -446,7 +447,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) versions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, versions, 1) desc := versions[0].(map[string]any) @@ -461,7 +462,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { rec = doRequest(t, h2, "DescribeProjectVersions", map[string]any{"ProjectArn": dstProjectARN}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) dstVersions := descResp["ProjectVersionDescriptions"].([]any) require.Len(t, dstVersions, 1) assert.Equal(t, versionARN, dstVersions[0].(map[string]any)["SourceProjectVersionArn"]) @@ -470,7 +471,7 @@ func TestSnapshotRestore_ProjectVersionAndAsyncJobNewFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "persist-tag", getResp["JobTag"]) video, _ := getResp["Video"].(map[string]any) @@ -493,7 +494,7 @@ func TestSnapshotRestore_TagsSurvive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["CollectionArn"].(string) doRequest(t, h, "TagResource", map[string]any{ @@ -511,7 +512,7 @@ func TestSnapshotRestore_TagsSurvive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagResp, jsonx.V1())) tags, _ := tagResp["Tags"].(map[string]any) assert.Equal(t, "val1", tags["key1"]) assert.Equal(t, "val2", tags["key2"]) diff --git a/services/rekognition/realism_test.go b/services/rekognition/realism_test.go index 61f629651a..ed724ff305 100644 --- a/services/rekognition/realism_test.go +++ b/services/rekognition/realism_test.go @@ -1,7 +1,7 @@ package rekognition_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -17,7 +18,7 @@ func decodeMap(t *testing.T, body []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(body, &m)) + require.NoError(t, json.Unmarshal(body, &m, jsonx.V1())) return m } diff --git a/services/rekognition/s3_object_test.go b/services/rekognition/s3_object_test.go index ec2378aecf..2b572afcae 100644 --- a/services/rekognition/s3_object_test.go +++ b/services/rekognition/s3_object_test.go @@ -2,7 +2,7 @@ package rekognition_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rekognition" ) @@ -82,7 +83,7 @@ func TestImageOps_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doRequest(t, h, tt.action, map[string]any{ @@ -148,7 +149,7 @@ func TestSearchByImageOps_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doRequest(t, h, tt.action, map[string]any{ @@ -191,7 +192,7 @@ func TestStartVideoOps_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doRequest(t, h, tt.action, map[string]any{ @@ -221,7 +222,7 @@ func TestStartMediaAnalysisJob_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doRequest(t, h, "StartMediaAnalysisJob", body("good-bucket")) diff --git a/services/resiliencehub/handler.go b/services/resiliencehub/handler.go index e5bd8b8c90..804005a026 100644 --- a/services/resiliencehub/handler.go +++ b/services/resiliencehub/handler.go @@ -2,7 +2,7 @@ package resiliencehub import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -283,7 +284,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { status, errType = http.StatusNotFound, "ResourceNotFoundException" } - payload, _ := json.Marshal(body) + payload, _ := json.Marshal(body, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) @@ -395,7 +396,7 @@ func decodeJSONBody(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validationError("malformed request body: " + err.Error()) } @@ -405,7 +406,7 @@ func decodeJSONBody(body []byte, v any) error { // marshalResponse marshals v, wrapping any error as an internal failure // (marshaling our own well-typed wire structs should never fail). func marshalResponse(v any) ([]byte, error) { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, fmt.Errorf("resiliencehub: marshal response: %w", err) } diff --git a/services/resiliencehub/multi_region_test.go b/services/resiliencehub/multi_region_test.go index a551f69200..2f1d7c066e 100644 --- a/services/resiliencehub/multi_region_test.go +++ b/services/resiliencehub/multi_region_test.go @@ -2,7 +2,8 @@ package resiliencehub_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/resiliencehub" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/resiliencehub/persistence.go b/services/resiliencehub/persistence.go index b12bf6f188..2aeb85ae28 100644 --- a/services/resiliencehub/persistence.go +++ b/services/resiliencehub/persistence.go @@ -2,7 +2,7 @@ package resiliencehub import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -20,10 +20,10 @@ const resiliencehubSnapshotVersion = 1 // backendSnapshot is the top-level on-disk shape for the Resilience Hub // backend. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountId"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountId"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/resourceexplorer2/catalog.go b/services/resourceexplorer2/catalog.go index 0e6e55fed1..65058ea066 100644 --- a/services/resourceexplorer2/catalog.go +++ b/services/resourceexplorer2/catalog.go @@ -2,7 +2,7 @@ package resourceexplorer2 import ( _ "embed" // documented resource type list - "encoding/json" + "encoding/json/v2" "slices" "strings" "sync" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -93,7 +94,7 @@ var supportedTypes = sync.OnceValue(func() []SupportedType { //nolint:gochecknog Types []string `json:"types"` } - if err := json.Unmarshal(documentedTypesJSON, &documented); err != nil { + if err := json.Unmarshal(documentedTypesJSON, &documented, jsonx.V1()); err != nil { panic("resourceexplorer2: embedded supported types are invalid: " + err.Error()) } diff --git a/services/resourceexplorer2/persistence.go b/services/resourceexplorer2/persistence.go index b15d542242..5e3052b481 100644 --- a/services/resourceexplorer2/persistence.go +++ b/services/resourceexplorer2/persistence.go @@ -2,7 +2,7 @@ package resourceexplorer2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/resourceexplorer2/types_catalog_test.go b/services/resourceexplorer2/types_catalog_test.go index 8fcbbd829a..c3b2560d58 100644 --- a/services/resourceexplorer2/types_catalog_test.go +++ b/services/resourceexplorer2/types_catalog_test.go @@ -2,12 +2,14 @@ package resourceexplorer2_test import ( _ "embed" - "encoding/json" + "encoding/json/v2" "slices" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed supported_types.json @@ -21,7 +23,7 @@ func TestDocumentedTypesCatalog(t *testing.T) { Types []string `json:"types"` } - require.NoError(t, json.Unmarshal(documentedTypes, &c)) + require.NoError(t, json.Unmarshal(documentedTypes, &c, jsonx.V1())) tests := []struct { check func(t *testing.T) diff --git a/services/resourcegroups/groups.go b/services/resourcegroups/groups.go index 8e448d40da..20678349cc 100644 --- a/services/resourcegroups/groups.go +++ b/services/resourcegroups/groups.go @@ -2,7 +2,8 @@ package resourcegroups import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "regexp" "slices" @@ -11,6 +12,7 @@ import ( "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -147,8 +149,8 @@ func validateResourceQuery(q *ResourceQuery) error { return fmt.Errorf("%w: ResourceQuery.Query must be a non-empty JSON string", ErrValidation) } - var raw json.RawMessage - if err := json.Unmarshal([]byte(q.Query), &raw); err != nil { + var raw jsontext.Value + if err := json.Unmarshal([]byte(q.Query), &raw, jsonx.V1()); err != nil { return fmt.Errorf( "%w: ResourceQuery.Query is not valid JSON: %s", ErrValidation, diff --git a/services/resourcegroups/handler.go b/services/resourcegroups/handler.go index c432a7fd47..cbc8812630 100644 --- a/services/resourcegroups/handler.go +++ b/services/resourcegroups/handler.go @@ -3,7 +3,7 @@ package resourcegroups import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +16,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -258,7 +259,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req extractResourceNameInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.Name != "" { return req.Name @@ -339,7 +340,7 @@ func mergeListGroupsQuery(body []byte, q url.Values) ([]byte, error) { doc := map[string]any{} if len(bytes.TrimSpace(body)) > 0 { - if err := json.Unmarshal(body, &doc); err != nil { + if err := json.Unmarshal(body, &doc, jsonx.V1()); err != nil { return nil, err } } @@ -357,7 +358,7 @@ func mergeListGroupsQuery(body []byte, q url.Values) ([]byte, error) { doc["NextToken"] = token } - return json.Marshal(doc) + return json.Marshal(doc, jsonx.V1()) } func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]byte, error) { @@ -371,7 +372,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // amznErrorTypeHeader carries the modeled exception type for the restjson1 @@ -388,15 +389,12 @@ const errTypeBadRequest = "BadRequestException" // NotFoundException, BadRequestException, ForbiddenException, // InternalServerErrorException, MethodNotAllowedException, TooManyRequestsException). func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - code := http.StatusInternalServerError wireType := "InternalServerErrorException" switch { case errors.Is(err, errInvalidRequest), errors.Is(err, ErrUnknownOperation), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): code, wireType = http.StatusBadRequest, errTypeBadRequest case errors.Is(err, ErrAlreadyExists): code, wireType = http.StatusBadRequest, errTypeBadRequest diff --git a/services/resourcegroups/handler_groups_config_test.go b/services/resourcegroups/handler_groups_config_test.go index 3bc43c7fd5..6b19a50221 100644 --- a/services/resourcegroups/handler_groups_config_test.go +++ b/services/resourcegroups/handler_groups_config_test.go @@ -1,13 +1,14 @@ package resourcegroups_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -102,7 +103,7 @@ func TestGetGroupQuery_ConfigVsQueryGroup(t *testing.T) { } `json:"ResourceQuery"` } `json:"GroupQuery"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotNil(t, out.GroupQuery.ResourceQuery) }) } @@ -141,7 +142,7 @@ func TestResourceGroupsHandler_GetGroupConfiguration_Status(t *testing.T) { Status string `json:"Status"` } `json:"GroupConfiguration"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "UPDATE_COMPLETE", out.GroupConfiguration.Status) assert.NotContains(t, rec.Body.String(), "GroupName") } @@ -542,7 +543,7 @@ func TestCreateGroup_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) group, ok := out["Group"].(map[string]any) require.True(t, ok) diff --git a/services/resourcegroups/handler_groups_test.go b/services/resourcegroups/handler_groups_test.go index 5e764c8cfa..dc4b7e16f5 100644 --- a/services/resourcegroups/handler_groups_test.go +++ b/services/resourcegroups/handler_groups_test.go @@ -2,7 +2,7 @@ package resourcegroups_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -230,7 +231,7 @@ func TestListGroups_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) groups1 := out1["Groups"].([]any) assert.Len(t, groups1, 3) token1, _ := out1["NextToken"].(string) @@ -244,7 +245,7 @@ func TestListGroups_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) groups2 := out2["Groups"].([]any) assert.Len(t, groups2, 3) assert.Empty(t, out2["NextToken"]) @@ -766,7 +767,7 @@ func TestResourceGroupsHandler_DeleteGroup_EchoesGroup(t *testing.T) { Description string `json:"Description"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "echo-group", out.Group.Name) assert.Equal(t, "echo desc", out.Group.Description) } @@ -791,7 +792,7 @@ func TestResourceGroupsHandler_ListGroups_IdentifierFields(t *testing.T) { var out struct { GroupIdentifiers []map[string]any `json:"GroupIdentifiers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.GroupIdentifiers, 1) assert.Equal(t, "Ident Group", out.GroupIdentifiers[0]["DisplayName"]) criticality, ok := out.GroupIdentifiers[0]["Criticality"].(float64) diff --git a/services/resourcegroups/handler_groups_validation_test.go b/services/resourcegroups/handler_groups_validation_test.go index d3a15bf87f..ee04712fda 100644 --- a/services/resourcegroups/handler_groups_validation_test.go +++ b/services/resourcegroups/handler_groups_validation_test.go @@ -1,7 +1,7 @@ package resourcegroups_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -396,7 +397,7 @@ func TestListGroupsOutputShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) groups, ok := out["Groups"].([]any) require.True(t, ok, "Groups must be a list") @@ -506,7 +507,7 @@ func TestOwnerId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) group, ok := out["Group"].(map[string]any) require.True(t, ok) @@ -532,7 +533,7 @@ func TestCreateGroupIdentityFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) group, ok := out["Group"].(map[string]any) require.True(t, ok) @@ -555,7 +556,7 @@ func TestListGroupsGroupIdentifiersShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) identifiers := out["GroupIdentifiers"].([]any) require.Len(t, identifiers, 1) diff --git a/services/resourcegroups/handler_query_test.go b/services/resourcegroups/handler_query_test.go index 1e0be1e46e..beecad7322 100644 --- a/services/resourcegroups/handler_query_test.go +++ b/services/resourcegroups/handler_query_test.go @@ -1,7 +1,7 @@ package resourcegroups_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -88,7 +89,7 @@ func TestSearchResources_QueryErrorsShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out, "QueryErrors", "QueryErrors must be omitted when empty") } @@ -137,7 +138,7 @@ func TestSearchResources_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) ids1 := out1["ResourceIdentifiers"].([]any) assert.Len(t, ids1, 3) tok1, _ := out1["NextToken"].(string) @@ -148,7 +149,7 @@ func TestSearchResources_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) ids2 := out2["ResourceIdentifiers"].([]any) assert.Len(t, ids2, 2) assert.Empty(t, out2["NextToken"]) diff --git a/services/resourcegroups/handler_resources_test.go b/services/resourcegroups/handler_resources_test.go index 4e9c1bd287..0191ad94ed 100644 --- a/services/resourcegroups/handler_resources_test.go +++ b/services/resourcegroups/handler_resources_test.go @@ -1,7 +1,7 @@ package resourcegroups_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -154,7 +155,7 @@ func TestGroupResources_InvalidARNReturnsFailed(t *testing.T) { ErrorMessage string `json:"ErrorMessage"` } `json:"Failed"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len( t, @@ -195,7 +196,7 @@ func TestGroupResources_InvalidARNNotAddedToGroup(t *testing.T) { } `json:"Identifier"` } `json:"Resources"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Resources, 1, "only the valid ARN should be in group") assert.Equal(t, "arn:aws:s3:::real-bucket", out.Resources[0].Identifier.ResourceArn) @@ -318,7 +319,7 @@ func TestUngroupResourcesFailures(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) succeeded, _ := out["Succeeded"].([]any) failed, _ := out["Failed"].([]any) @@ -480,14 +481,14 @@ func TestListGroupResources_ResourceIdentifiersDeprecatedField(t *testing.T) { ResourceType string `json:"ResourceType"` } `json:"ResourceIdentifiers"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ResourceIdentifiers, 1) assert.Equal(t, out.Resources[0].Identifier.ResourceArn, out.ResourceIdentifiers[0].ResourceArn) assert.Equal(t, out.Resources[0].Identifier.ResourceType, out.ResourceIdentifiers[0].ResourceType) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.NotContains(t, raw, "QueryErrors", "QueryErrors must be omitted when empty") } @@ -543,7 +544,7 @@ func TestListGroupResources_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) resources1 := out1["Resources"].([]any) assert.Len(t, resources1, 2) token1, _ := out1["NextToken"].(string) @@ -557,7 +558,7 @@ func TestListGroupResources_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) resources2 := out2["Resources"].([]any) assert.Len(t, resources2, 3) assert.Empty(t, out2["NextToken"]) @@ -684,7 +685,7 @@ func TestResourceGroupsHandler_GroupingStatuses_UpdatedAtIsEpochSeconds(t *testi var out struct { GroupingStatuses []map[string]any `json:"GroupingStatuses"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.GroupingStatuses, 1) _, isNumber := out.GroupingStatuses[0]["UpdatedAt"].(float64) assert.True(t, isNumber, "ListGroupingStatuses UpdatedAt must be a JSON number: %s", rec.Body.String()) @@ -713,7 +714,7 @@ func TestListGroupingStatuses_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) statuses1 := out1["GroupingStatuses"].([]any) assert.Len(t, statuses1, 3) tok1, _ := out1["NextToken"].(string) @@ -727,7 +728,7 @@ func TestListGroupingStatuses_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) statuses2 := out2["GroupingStatuses"].([]any) assert.Len(t, statuses2, 2) assert.Empty(t, out2["NextToken"]) diff --git a/services/resourcegroups/handler_tags.go b/services/resourcegroups/handler_tags.go index a22dd6417d..464ee129ca 100644 --- a/services/resourcegroups/handler_tags.go +++ b/services/resourcegroups/handler_tags.go @@ -2,7 +2,7 @@ package resourcegroups import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -38,7 +39,7 @@ func (h *Handler) handleTagRequest(ctx context.Context, c *echo.Context, log *sl var in tagResourceInput - if err = json.Unmarshal(body, &in); err != nil { + if err = json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.handleError(ctx, c, "Tag", errInvalidRequest) } @@ -96,7 +97,7 @@ func (h *Handler) extractUntagKeys(ctx context.Context, c *echo.Context, log *sl } var in untagResourceInput - if err = json.Unmarshal(body, &in); err != nil { + if err = json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, errInvalidRequest } @@ -138,7 +139,7 @@ func (h *Handler) handleResourceTags(ctx context.Context, c *echo.Context) error var in untagResourceInput - if err = json.Unmarshal(body, &in); err != nil { + if err = json.Unmarshal(body, &in, jsonx.V1()); err != nil { return h.handleError(ctx, c, "Untag", errInvalidRequest) } diff --git a/services/resourcegroups/handler_tags_test.go b/services/resourcegroups/handler_tags_test.go index 42b6b055f6..344b1f9f37 100644 --- a/services/resourcegroups/handler_tags_test.go +++ b/services/resourcegroups/handler_tags_test.go @@ -2,7 +2,7 @@ package resourcegroups_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -36,7 +37,7 @@ func TestResourceGroupsHandler_GetTags(t *testing.T) { GroupArn string `json:"GroupArn"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.Group.GroupArn }, @@ -95,7 +96,7 @@ func TestResourceGroupsHandler_Tag(t *testing.T) { GroupArn string `json:"GroupArn"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) groupARN = out.Group.GroupArn } else { groupARN = "arn:aws:resource-groups:us-east-1:000000000000:group/nonexistent" @@ -142,7 +143,7 @@ func TestResourceGroupsHandler_Untag(t *testing.T) { GroupArn string `json:"GroupArn"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) groupARN = out.Group.GroupArn } else { groupARN = "arn:aws:resource-groups:us-east-1:000000000000:group/nonexistent" @@ -170,7 +171,7 @@ func TestUntagViaDeleteVerb(t *testing.T) { // DELETE /resources/{Arn}/tags with JSON body. e := echo.New() - bodyBytes, _ := json.Marshal(map[string]any{"Keys": []string{"env"}}) + bodyBytes, _ := json.Marshal(map[string]any{"Keys": []string{"env"}}, jsonx.V1()) req := httptest.NewRequest( http.MethodDelete, "/resources/"+g.ARN+"/tags", diff --git a/services/resourcegroups/handler_tagsync_test.go b/services/resourcegroups/handler_tagsync_test.go index 4f3ec883a4..d571050bbb 100644 --- a/services/resourcegroups/handler_tagsync_test.go +++ b/services/resourcegroups/handler_tagsync_test.go @@ -1,7 +1,7 @@ package resourcegroups_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -182,7 +183,7 @@ func TestResourceGroupsHandler_GetTagSyncTask(t *testing.T) { var out struct { TaskArn string `json:"TaskArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.TaskArn }, @@ -252,7 +253,7 @@ func TestResourceGroupsHandler_CancelTagSyncTask(t *testing.T) { var out struct { TaskArn string `json:"TaskArn"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.TaskArn }, @@ -315,7 +316,7 @@ func TestCancelTagSyncTaskState(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) taskARN := startOut["TaskArn"].(string) cancelRec := doResourceGroupsRequest( @@ -441,7 +442,7 @@ func TestListTagSyncTasks_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) tasks1 := out1["TagSyncTasks"].([]any) assert.Len(t, tasks1, 2) tok1, _ := out1["NextToken"].(string) @@ -454,7 +455,7 @@ func TestListTagSyncTasks_PaginationViaHandler(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) tasks2 := out2["TagSyncTasks"].([]any) assert.Len(t, tasks2, 2) assert.Empty(t, out2["NextToken"]) @@ -480,13 +481,13 @@ func TestResourceGroupsHandler_TagSyncTask_CreatedAtIsEpochSeconds(t *testing.T) var startOut struct { TaskArn string `json:"TaskArn"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startOut, jsonx.V1())) getRec := doResourceGroupsRequest(t, h, "GetTagSyncTask", map[string]any{"TaskArn": startOut.TaskArn}) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) _, isNumber := getOut["CreatedAt"].(float64) assert.True(t, isNumber, "GetTagSyncTask CreatedAt must be a JSON number: %s", getRec.Body.String()) @@ -496,7 +497,7 @@ func TestResourceGroupsHandler_TagSyncTask_CreatedAtIsEpochSeconds(t *testing.T) var listOut struct { TagSyncTasks []map[string]any `json:"TagSyncTasks"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.TagSyncTasks, 1) _, isNumber = listOut.TagSyncTasks[0]["CreatedAt"].(float64) assert.True(t, isNumber, "ListTagSyncTasks CreatedAt must be a JSON number: %s", listRec.Body.String()) diff --git a/services/resourcegroups/handler_test.go b/services/resourcegroups/handler_test.go index 30d178f8f9..cd50022c83 100644 --- a/services/resourcegroups/handler_test.go +++ b/services/resourcegroups/handler_test.go @@ -2,7 +2,7 @@ package resourcegroups_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -34,7 +35,7 @@ func doResourceGroupsRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -88,7 +89,7 @@ func doResourceTagsRequest( var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) } else { @@ -122,7 +123,7 @@ func doResourceGroupsRESTRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") diff --git a/services/resourcegroups/handler_untag_rejection_test.go b/services/resourcegroups/handler_untag_rejection_test.go index bc6e23e978..498a5683b7 100644 --- a/services/resourcegroups/handler_untag_rejection_test.go +++ b/services/resourcegroups/handler_untag_rejection_test.go @@ -2,7 +2,7 @@ package resourcegroups_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -89,7 +90,7 @@ func TestResourceGroupsHandler_Untag_RejectionNotBypassed(t *testing.T) { GroupArn string `json:"GroupArn"` } `json:"Group"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) groupARN := created.Group.GroupArn untagRec := doResourceTagsRequestRaw(t, h, http.MethodDelete, groupARN, tt.body) @@ -98,7 +99,7 @@ func TestResourceGroupsHandler_Untag_RejectionNotBypassed(t *testing.T) { var resp map[string]any require.NoError( - t, json.Unmarshal(untagRec.Body.Bytes(), &resp), + t, json.Unmarshal(untagRec.Body.Bytes(), &resp, jsonx.V1()), "response body must be a single well-formed JSON document, not two concatenated: %s", untagRec.Body.String(), ) @@ -109,7 +110,7 @@ func TestResourceGroupsHandler_Untag_RejectionNotBypassed(t *testing.T) { var tagsResp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) assert.Equal(t, map[string]string{"env": "prod"}, tagsResp.Tags, "rejected Untag must not remove any tags") }) } diff --git a/services/resourcegroups/persistence.go b/services/resourcegroups/persistence.go index b01d1f8762..661566e9e3 100644 --- a/services/resourcegroups/persistence.go +++ b/services/resourcegroups/persistence.go @@ -2,7 +2,7 @@ package resourcegroups import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -108,7 +108,7 @@ func buildPersistenceDTORegistry() (*store.Registry, *store.Table[groupSnapshot] // strings, or status records), so there is nothing for store.Table to key on, // and each is persisted here directly instead. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` GroupConfigurations map[string]map[string][]GroupConfigurationItem `json:"groupConfigurations"` GroupResources map[string]map[string][]string `json:"groupResources"` GroupingStatuses map[string]map[string][]GroupingStatusItem `json:"groupingStatuses"` @@ -217,7 +217,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreGroups rebuilds the "dirty" groups store.Table from snap's DTO // table, factored out of Restore to keep Restore's own cognitive complexity // low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreGroups(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreGroups(tables map[string]jsontext.Value) error { dtoReg, groupDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("resourcegroups: restore snapshot groups table: %w", err) diff --git a/services/resourcegroups/persistence_test.go b/services/resourcegroups/persistence_test.go index 93b7d2586d..399744c748 100644 --- a/services/resourcegroups/persistence_test.go +++ b/services/resourcegroups/persistence_test.go @@ -2,12 +2,14 @@ package resourcegroups_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/blackbirdworks/gopherstack/services/resourcegroups" ) @@ -295,8 +297,8 @@ func Test_PersistenceFullStateRoundTrip(t *testing.T) { snap := b.Snapshot(t.Context()) require.NotNil(t, snap) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &raw, jsonx.V1())) assert.Contains(t, raw, "version") b2 := resourcegroups.NewInMemoryBackend("123456789012", "us-east-1") diff --git a/services/resourcegroups/query.go b/services/resourcegroups/query.go index 01baa5e124..f4e5cfe62e 100644 --- a/services/resourcegroups/query.go +++ b/services/resourcegroups/query.go @@ -2,10 +2,12 @@ package resourcegroups import ( "context" - "encoding/json" + "encoding/json/v2" "slices" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // arnSplitParts is the number of colon-separated segments in a well-formed AWS ARN. @@ -126,7 +128,7 @@ var arnServiceTypeMap = map[string]string{ //nolint:gochecknoglobals,gosec // st // The special value "AWS::AllSupported" means match all types and returns nil. func parseResourceTypeFilters(queryJSON string) map[string]bool { var tfq tagFilterQuery - if err := json.Unmarshal([]byte(queryJSON), &tfq); err != nil { + if err := json.Unmarshal([]byte(queryJSON), &tfq, jsonx.V1()); err != nil { return nil } diff --git a/services/resourcegroups/query_validation.go b/services/resourcegroups/query_validation.go index bd076b6b91..b3d635615a 100644 --- a/services/resourcegroups/query_validation.go +++ b/services/resourcegroups/query_validation.go @@ -2,9 +2,11 @@ package resourcegroups import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -42,7 +44,7 @@ func validateQueryShape(queryType, query string) error { func validateTagFilterQuery(raw []byte) error { var q tagFilterQuery - if err := json.Unmarshal(raw, &q); err != nil { + if err := json.Unmarshal(raw, &q, jsonx.V1()); err != nil { return fmt.Errorf("%w: ResourceQuery.Query is not a valid TAG_FILTERS_1_0 query: %w", ErrValidation, err) } @@ -62,7 +64,7 @@ func validateTagFilterQuery(raw []byte) error { func validateStackQuery(raw []byte) error { var q cfnQuery - if err := json.Unmarshal(raw, &q); err != nil { + if err := json.Unmarshal(raw, &q, jsonx.V1()); err != nil { return fmt.Errorf( "%w: ResourceQuery.Query is not a valid CLOUDFORMATION_STACK_1_0 query: %w", ErrValidation, err) } diff --git a/services/resourcegroups/source.go b/services/resourcegroups/source.go index 78f0209f8c..fdba608019 100644 --- a/services/resourcegroups/source.go +++ b/services/resourcegroups/source.go @@ -2,10 +2,11 @@ package resourcegroups import ( "context" - "encoding/json" + "encoding/json/v2" "slices" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/cloudformation" "github.com/blackbirdworks/gopherstack/services/resourcegroupstaggingapi" @@ -167,7 +168,7 @@ func typeAllowed(want map[string]bool, resType string) bool { func evalTagFilterQuery(ctx context.Context, src ResourceSource, queryJSON string) []ResourceIdentifier { var q tagFilterQuery - if err := json.Unmarshal([]byte(queryJSON), &q); err != nil { + if err := json.Unmarshal([]byte(queryJSON), &q, jsonx.V1()); err != nil { return nil } @@ -190,7 +191,7 @@ func evalStackQuery( ctx context.Context, src ResourceSource, queryJSON string, ) ([]ResourceIdentifier, []queryErrorWire) { var q cfnQuery - if err := json.Unmarshal([]byte(queryJSON), &q); err != nil { + if err := json.Unmarshal([]byte(queryJSON), &q, jsonx.V1()); err != nil { return nil, nil } diff --git a/services/resourcegroupstaggingapi/compliance.go b/services/resourcegroupstaggingapi/compliance.go index 46dc942cd9..991ed58cc5 100644 --- a/services/resourcegroupstaggingapi/compliance.go +++ b/services/resourcegroupstaggingapi/compliance.go @@ -2,10 +2,11 @@ package resourcegroupstaggingapi import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -189,7 +190,7 @@ type tagPolicyStringListAssign struct { // fabricate an unverified mapping. func requiredTagsFromPolicy(policyJSON string) []RequiredTag { var doc tagPolicyDocument - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return nil } diff --git a/services/resourcegroupstaggingapi/compliance_test.go b/services/resourcegroupstaggingapi/compliance_test.go index 58d086e8f5..48fa5c3d39 100644 --- a/services/resourcegroupstaggingapi/compliance_test.go +++ b/services/resourcegroupstaggingapi/compliance_test.go @@ -2,13 +2,14 @@ package resourcegroupstaggingapi_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroupstaggingapi" ) @@ -184,7 +185,7 @@ func TestGetComplianceSummaryJSONShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["SummaryList"].([]any) require.True(t, ok, "SummaryList should be a JSON array") @@ -312,7 +313,7 @@ func TestListRequiredTagsJSONShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["RequiredTags"].([]any) require.True(t, ok, "RequiredTags should be a JSON array") diff --git a/services/resourcegroupstaggingapi/get_resources_test.go b/services/resourcegroupstaggingapi/get_resources_test.go index ffaedbaa37..aa1a10ecc7 100644 --- a/services/resourcegroupstaggingapi/get_resources_test.go +++ b/services/resourcegroupstaggingapi/get_resources_test.go @@ -2,7 +2,8 @@ package resourcegroupstaggingapi_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroupstaggingapi" ) @@ -668,7 +670,7 @@ func TestGetResources_TagsPerPage_SplitsPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out resourcegroupstaggingapi.GetResourcesOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) require.NotNil(t, out.PaginationToken, "TagsPerPage must force an early page break") assert.LessOrEqual(t, len(out.ResourceTagMappingList), 2, @@ -699,7 +701,7 @@ func TestGetResources_TagsPerPage_OversizedFirstResourceStillReturnedAlone(t *te require.Equal(t, http.StatusOK, rec.Code) var out resourcegroupstaggingapi.GetResourcesOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) // GetResources never splits a single resource and its tags across pages, so the // oversized resource is still returned alone rather than yielding zero results. @@ -729,7 +731,7 @@ func TestGetResources_NoTagsPerPage_Unconstrained(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out resourcegroupstaggingapi.GetResourcesOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.ResourceTagMappingList, 5, "without TagsPerPage all resources fit on one page") assert.Nil(t, out.PaginationToken) @@ -768,7 +770,7 @@ func TestGetResources_ResourceARNList_FiltersToSpecificARNs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["ResourceTagMappingList"].([]any) require.True(t, ok) @@ -809,7 +811,7 @@ func TestGetResources_ResourceARNList_EmptyReturnsAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["ResourceTagMappingList"].([]any) require.True(t, ok) @@ -1097,7 +1099,7 @@ func TestComplianceDetailsFieldName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) list, ok := out["ResourceTagMappingList"].([]any) require.True(t, ok) @@ -1140,7 +1142,7 @@ func TestHandler_GetResources_IncludeComplianceDetails(t *testing.T) { } `json:"ResourceTagMappingList"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &body, jsonx.V1())) require.Len(t, body.ResourceTagMappingList, 1) require.NotNil(t, body.ResourceTagMappingList[0].ComplianceDetails) assert.True(t, body.ResourceTagMappingList[0].ComplianceDetails.ComplianceStatus) diff --git a/services/resourcegroupstaggingapi/handler.go b/services/resourcegroupstaggingapi/handler.go index 87a5ea964e..b3a4697da7 100644 --- a/services/resourcegroupstaggingapi/handler.go +++ b/services/resourcegroupstaggingapi/handler.go @@ -2,7 +2,7 @@ package resourcegroupstaggingapi import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -140,13 +141,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - code := http.StatusInternalServerError errType := "InternalFailure" @@ -166,7 +164,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, ErrPaginationTokenExpired): code = http.StatusBadRequest errType = "PaginationTokenExpiredException" - case errors.As(err, &syntaxErr), errors.As(err, &typeErr): + case jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): // Malformed request bodies are a protocol-level failure, not a modeled // operation error; the AWS JSON 1.1 protocol reports these as // SerializationException (matches services/organizations' convention for @@ -178,7 +176,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: err.Error(), - }) + }, jsonx.V1()) c.Response().Header().Set("Content-Type", "application/x-amz-json-1.1") diff --git a/services/resourcegroupstaggingapi/handler_test.go b/services/resourcegroupstaggingapi/handler_test.go index 2ec70fcd56..5f489062f4 100644 --- a/services/resourcegroupstaggingapi/handler_test.go +++ b/services/resourcegroupstaggingapi/handler_test.go @@ -3,7 +3,8 @@ package resourcegroupstaggingapi_test import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/resourcegroupstaggingapi" ) @@ -102,7 +104,7 @@ func doTaggingRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -598,7 +600,7 @@ func TestValidationFailures_UseInvalidParameterException(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, "body: %s", rec.Body.String()) var body map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &body, jsonx.V1())) assert.Equal(t, "InvalidParameterException", body["__type"], "real resourcegroupstaggingapi has no ValidationException shape") assert.NotContains(t, rec.Body.String(), "ValidationException") @@ -631,7 +633,7 @@ func TestMalformedBody_UsesSerializationException(t *testing.T) { assert.Contains(t, rec.Body.String(), "SerializationException") var body map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &body, jsonx.V1())) assert.Equal(t, "SerializationException", body["__type"]) }) } @@ -772,7 +774,7 @@ func TestHandler_ValidationError_HasInvalidParameterExceptionBody(t *testing.T) require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &body, jsonx.V1())) // Real resourcegroupstaggingapi has no ValidationException shape; parameter // validation failures are modeled as InvalidParameterException. assert.Equal(t, "InvalidParameterException", body["__type"]) diff --git a/services/resourcegroupstaggingapi/persistence.go b/services/resourcegroupstaggingapi/persistence.go index cc7c495d56..fd3a56c7a7 100644 --- a/services/resourcegroupstaggingapi/persistence.go +++ b/services/resourcegroupstaggingapi/persistence.go @@ -2,7 +2,7 @@ package resourcegroupstaggingapi import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -98,10 +98,10 @@ func buildPersistenceDTORegistry() (*store.Registry, *store.Table[reportStateSna // resource cache is likewise never persisted -- it is a rebuildable TTL // cache, not part of durable state. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. @@ -198,7 +198,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // store_setup.go's registerAllTables doc) from tables via the ephemeral DTO // registry, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTables(ctx context.Context, tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTables(ctx context.Context, tables map[string]jsontext.Value) error { dtoReg, reportStateDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("resourcegroupstaggingapi: restore snapshot DTO tables: %w", err) diff --git a/services/resourcegroupstaggingapi/report_test.go b/services/resourcegroupstaggingapi/report_test.go index b87022aaa2..ecc47a77a3 100644 --- a/services/resourcegroupstaggingapi/report_test.go +++ b/services/resourcegroupstaggingapi/report_test.go @@ -2,7 +2,7 @@ package resourcegroupstaggingapi_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/resourcegroupstaggingapi" ) @@ -92,7 +93,7 @@ func TestStartReportCreationInput_HasNoS3BucketRegionField(t *testing.T) { // A request body containing S3BucketRegion (as some non-AWS client might send) must // simply be ignored as an unknown field, not silently accepted as a modeled member. - marshaled, err := json.Marshal(resourcegroupstaggingapi.StartReportCreationInput{S3Bucket: "b"}) + marshaled, err := json.Marshal(resourcegroupstaggingapi.StartReportCreationInput{S3Bucket: "b"}, jsonx.V1()) require.NoError(t, err) assert.NotContains(t, string(marshaled), "S3BucketRegion") } @@ -331,7 +332,7 @@ func TestDescribeReportCreationJSONShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "SUCCEEDED", out["Status"]) assert.Equal(t, "s3://bkt/path.csv", out["S3Location"]) diff --git a/services/rolesanywhere/handler.go b/services/rolesanywhere/handler.go index 78edc33d9b..b024dfcfc1 100644 --- a/services/rolesanywhere/handler.go +++ b/services/rolesanywhere/handler.go @@ -2,7 +2,7 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -227,7 +228,7 @@ func (h *Handler) handleREST(c *echo.Context) error { return c.JSON(statusCode, struct{}{}) } - data, jsonErr := json.Marshal(result) + data, jsonErr := json.Marshal(result, jsonx.V1()) if jsonErr != nil { return c.JSON(http.StatusInternalServerError, errBody("InternalFailure", "serialization failed")) } diff --git a/services/rolesanywhere/handler_attribute_mappings.go b/services/rolesanywhere/handler_attribute_mappings.go index 924558c7fd..79ff16ced0 100644 --- a/services/rolesanywhere/handler_attribute_mappings.go +++ b/services/rolesanywhere/handler_attribute_mappings.go @@ -2,10 +2,12 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Attribute mapping handlers ---- @@ -18,7 +20,7 @@ func (h *Handler) handlePutAttributeMapping(ctx context.Context, path string, bo MappingRules []MappingRule `json:"mappingRules"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_attribute_mappings_test.go b/services/rolesanywhere/handler_attribute_mappings_test.go index 9e1b0326bf..4ddba6fbd7 100644 --- a/services/rolesanywhere/handler_attribute_mappings_test.go +++ b/services/rolesanywhere/handler_attribute_mappings_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Attribute Mapping HTTP ---- @@ -38,7 +40,7 @@ func TestHandler_AttributeMapping_CRUD(t *testing.T) { require.Equal(t, http.StatusCreated, recProfile.Code) var profileResp map[string]any - require.NoError(t, json.Unmarshal(recProfile.Body.Bytes(), &profileResp)) + require.NoError(t, json.Unmarshal(recProfile.Body.Bytes(), &profileResp, jsonx.V1())) p := profileResp["profile"].(map[string]any) profileID := p["profileId"].(string) @@ -56,7 +58,7 @@ func TestHandler_AttributeMapping_CRUD(t *testing.T) { assert.Equal(t, tt.wantStatus, recPut.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp, jsonx.V1())) profileInResp := putResp["profile"].(map[string]any) assert.Equal(t, profileID, profileInResp["profileId"]) diff --git a/services/rolesanywhere/handler_crls.go b/services/rolesanywhere/handler_crls.go index 53d9d8f7ef..96123f2d32 100644 --- a/services/rolesanywhere/handler_crls.go +++ b/services/rolesanywhere/handler_crls.go @@ -2,9 +2,11 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- CRL handlers ---- @@ -18,7 +20,7 @@ func (h *Handler) handleImportCrl(ctx context.Context, body []byte) (any, int, e Tags []TagEntry `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -84,7 +86,7 @@ func (h *Handler) handleUpdateCrl(ctx context.Context, path string, body []byte) CrlData []byte `json:"crlData"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_crls_test.go b/services/rolesanywhere/handler_crls_test.go index 2e21d0af4b..3cc129e9bd 100644 --- a/services/rolesanywhere/handler_crls_test.go +++ b/services/rolesanywhere/handler_crls_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- CRL HTTP CRUD ---- @@ -44,7 +46,7 @@ func TestHandler_CRL_CRUD(t *testing.T) { assert.Equal(t, tt.wantCreate, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) crl := createResp["crl"].(map[string]any) id := crl["crlId"].(string) assert.NotEmpty(t, id) @@ -205,8 +207,8 @@ func TestHandler_CRL_DuplicateNameAllowed(t *testing.T) { assert.Equal(t, tt.wantStatus, rec2.Code) var resp1, resp2 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) c1 := resp1["crl"].(map[string]any) c2 := resp2["crl"].(map[string]any) diff --git a/services/rolesanywhere/handler_notification_settings.go b/services/rolesanywhere/handler_notification_settings.go index 88d9266d9f..c79cf80f2d 100644 --- a/services/rolesanywhere/handler_notification_settings.go +++ b/services/rolesanywhere/handler_notification_settings.go @@ -2,8 +2,10 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Notification settings handlers ---- @@ -14,7 +16,7 @@ func (h *Handler) handlePutNotificationSettings(ctx context.Context, body []byte NotificationSettings []NotificationSetting `json:"notificationSettings"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -32,7 +34,7 @@ func (h *Handler) handleResetNotificationSettings(ctx context.Context, body []by NotificationSettingKeys []NotificationSettingKey `json:"notificationSettingKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_notification_settings_test.go b/services/rolesanywhere/handler_notification_settings_test.go index 3b517c5256..4767c8d4d0 100644 --- a/services/rolesanywhere/handler_notification_settings_test.go +++ b/services/rolesanywhere/handler_notification_settings_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Notification Settings HTTP ---- @@ -38,7 +40,7 @@ func TestHandler_NotificationSettings_PutReset(t *testing.T) { require.Equal(t, http.StatusCreated, recTA.Code) var taResp map[string]any - require.NoError(t, json.Unmarshal(recTA.Body.Bytes(), &taResp)) + require.NoError(t, json.Unmarshal(recTA.Body.Bytes(), &taResp, jsonx.V1())) ta := taResp["trustAnchor"].(map[string]any) taID := ta["trustAnchorId"].(string) @@ -52,7 +54,7 @@ func TestHandler_NotificationSettings_PutReset(t *testing.T) { assert.Equal(t, tt.wantStatus, recPut.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp, jsonx.V1())) assert.Contains(t, putResp, "trustAnchor") // Reset notification settings. @@ -91,7 +93,7 @@ func TestHandler_NotificationSettings_ConfiguredBy(t *testing.T) { require.Equal(t, http.StatusCreated, recTA.Code) var taResp map[string]any - require.NoError(t, json.Unmarshal(recTA.Body.Bytes(), &taResp)) + require.NoError(t, json.Unmarshal(recTA.Body.Bytes(), &taResp, jsonx.V1())) ta := taResp["trustAnchor"].(map[string]any) taID := ta["trustAnchorId"].(string) @@ -104,7 +106,7 @@ func TestHandler_NotificationSettings_ConfiguredBy(t *testing.T) { require.Equal(t, http.StatusOK, recPut.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putResp, jsonx.V1())) updatedTA := putResp["trustAnchor"].(map[string]any) settings := updatedTA["notificationSettings"].([]any) diff --git a/services/rolesanywhere/handler_pagination_restart_test.go b/services/rolesanywhere/handler_pagination_restart_test.go index e993867812..2788766812 100644 --- a/services/rolesanywhere/handler_pagination_restart_test.go +++ b/services/rolesanywhere/handler_pagination_restart_test.go @@ -1,12 +1,14 @@ package rolesanywhere_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListTrustAnchors_Pagination_DeletedMidPage proves that deleting @@ -29,7 +31,7 @@ func TestHandler_ListTrustAnchors_Pagination_DeletedMidPage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1, jsonx.V1())) items1, _ := resp1["trustAnchors"].([]any) require.Len(t, items1, 2) @@ -50,7 +52,7 @@ func TestHandler_ListTrustAnchors_Pagination_DeletedMidPage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2, jsonx.V1())) items2, _ := resp2["trustAnchors"].([]any) for _, item := range items2 { @@ -90,7 +92,7 @@ func TestHandler_ListTrustAnchors_Pagination_TiedNamesTotalOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["trustAnchors"].([]any) for _, item := range items { diff --git a/services/rolesanywhere/handler_profiles.go b/services/rolesanywhere/handler_profiles.go index 86dd4071a0..7ccb59b026 100644 --- a/services/rolesanywhere/handler_profiles.go +++ b/services/rolesanywhere/handler_profiles.go @@ -2,9 +2,11 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Profile handlers ---- @@ -22,7 +24,7 @@ func (h *Handler) handleCreateProfile(ctx context.Context, body []byte) (any, in RequireInstanceProperties bool `json:"requireInstanceProperties"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -104,7 +106,7 @@ func (h *Handler) handleUpdateProfile(ctx context.Context, path string, body []b ManagedPolicyArns []string `json:"managedPolicyArns"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_profiles_test.go b/services/rolesanywhere/handler_profiles_test.go index caeb1debbb..6bac1bbd8f 100644 --- a/services/rolesanywhere/handler_profiles_test.go +++ b/services/rolesanywhere/handler_profiles_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Profile HTTP CRUD ---- @@ -43,7 +45,7 @@ func TestHandler_Profile_CRUD(t *testing.T) { assert.Equal(t, tt.wantCreate, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) p := createResp["profile"].(map[string]any) id := p["profileId"].(string) assert.NotEmpty(t, id) @@ -240,8 +242,8 @@ func TestHandler_Profile_DuplicateNameAllowed(t *testing.T) { assert.Equal(t, tt.wantStatus, rec2.Code) var resp1, resp2 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) p1 := resp1["profile"].(map[string]any) p2 := resp2["profile"].(map[string]any) @@ -284,7 +286,7 @@ func TestHandler_CreateProfile_EnabledFieldHonored(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) p := resp["profile"].(map[string]any) assert.Equal(t, tt.wantEnabled, p["enabled"]) }) @@ -307,7 +309,7 @@ func TestHandler_Profile_AcceptRoleSessionName(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) p := resp["profile"].(map[string]any) require.Equal(t, true, p["acceptRoleSessionName"]) @@ -319,7 +321,7 @@ func TestHandler_Profile_AcceptRoleSessionName(t *testing.T) { require.Equal(t, http.StatusOK, recUpdate.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(recUpdate.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(recUpdate.Body.Bytes(), &updateResp, jsonx.V1())) updated := updateResp["profile"].(map[string]any) assert.NotContains(t, updated, "acceptRoleSessionName", "false is the zero value and is omitted, matching requireInstanceProperties' existing convention") @@ -339,7 +341,7 @@ func TestHandler_Profile_CreatedBy(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) p := resp["profile"].(map[string]any) assert.Equal(t, "000000000000", p["createdBy"]) } @@ -360,7 +362,7 @@ func TestHandler_Profile_NoTagsFieldOnResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) p := resp["profile"].(map[string]any) assert.NotContains(t, p, "tags") } @@ -388,7 +390,7 @@ func TestHandler_ListProfiles_PageSizeQueryParam(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["profiles"].([]any) assert.Len(t, items, 1, "pageSize=1 must truncate the page to 1 item") } diff --git a/services/rolesanywhere/handler_tags.go b/services/rolesanywhere/handler_tags.go index e6bb6da809..70f5745808 100644 --- a/services/rolesanywhere/handler_tags.go +++ b/services/rolesanywhere/handler_tags.go @@ -2,9 +2,11 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Tag handlers ---- @@ -15,7 +17,7 @@ func (h *Handler) handleTagResource(ctx context.Context, body []byte) (any, int, Tags []TagEntry `json:"tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -39,7 +41,7 @@ func (h *Handler) handleUntagResource(ctx context.Context, body []byte) (any, in TagKeys []string `json:"tagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_tags_test.go b/services/rolesanywhere/handler_tags_test.go index 1e2b94c184..96ced2460e 100644 --- a/services/rolesanywhere/handler_tags_test.go +++ b/services/rolesanywhere/handler_tags_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rolesanywhere" ) @@ -31,7 +32,7 @@ func createTestTrustAnchor(t *testing.T, h *rolesanywhere.Handler) string { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ta, ok := resp["trustAnchor"].(map[string]any) require.True(t, ok, "response missing trustAnchor: %s", rec.Body.String()) @@ -76,7 +77,7 @@ func TestHandler_Tags_HTTP(t *testing.T) { assert.Equal(t, tt.wantListStatus, recList.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["tags"].([]any) assert.Len(t, tags, 2) @@ -102,7 +103,7 @@ func TestHandler_Tags_HTTP(t *testing.T) { "/ListTagsForResource?resourceArn="+resARN, nil, ) - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listResp, jsonx.V1())) tags2 := listResp["tags"].([]any) assert.Len(t, tags2, 1) }) @@ -169,7 +170,7 @@ func TestHandler_Tags_UnknownResource(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }) } @@ -188,7 +189,7 @@ func TestHandler_Tags_EmptyList(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].([]any) assert.Empty(t, tags) } diff --git a/services/rolesanywhere/handler_test.go b/services/rolesanywhere/handler_test.go index aba4ab88cd..ab479a61eb 100644 --- a/services/rolesanywhere/handler_test.go +++ b/services/rolesanywhere/handler_test.go @@ -11,7 +11,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rolesanywhere" ) @@ -44,7 +45,7 @@ func doREST( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -94,7 +95,7 @@ func TestHandler_Reset(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["trustAnchors"].([]any) assert.Empty(t, items) } @@ -458,7 +459,7 @@ func TestHandler_CreateTrustAnchor_EnabledFalse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ta := resp["trustAnchor"].(map[string]any) assert.Equal(t, tt.wantEnabled, ta["enabled"]) }) @@ -476,14 +477,14 @@ func TestHandler_DeleteTrustAnchor_ReturnsResource(t *testing.T) { require.Equal(t, http.StatusCreated, recCreate.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["trustAnchor"].(map[string]any)["trustAnchorId"].(string) recDelete := doREST(t, h, http.MethodDelete, "/trustanchor/"+id, nil) require.Equal(t, http.StatusOK, recDelete.Code) var deleteResp map[string]any - require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &deleteResp, jsonx.V1())) ta, ok := deleteResp["trustAnchor"].(map[string]any) require.True(t, ok, "DeleteTrustAnchor response must carry the deleted trustAnchor, got: %s", recDelete.Body.String()) @@ -501,14 +502,14 @@ func TestHandler_DeleteProfile_ReturnsResource(t *testing.T) { require.Equal(t, http.StatusCreated, recCreate.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["profile"].(map[string]any)["profileId"].(string) recDelete := doREST(t, h, http.MethodDelete, "/profile/"+id, nil) require.Equal(t, http.StatusOK, recDelete.Code) var deleteResp map[string]any - require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &deleteResp, jsonx.V1())) p, ok := deleteResp["profile"].(map[string]any) require.True(t, ok, "DeleteProfile response must carry the deleted profile, got: %s", recDelete.Body.String()) assert.Equal(t, id, p["profileId"]) @@ -538,7 +539,7 @@ func TestHandler_GetTrustAnchor_ShowsNotificationSettings(t *testing.T) { require.Equal(t, http.StatusCreated, recCreate.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["trustAnchor"].(map[string]any)["trustAnchorId"].(string) recPut := doREST(t, h, http.MethodPatch, "/put-notifications-settings", map[string]any{ @@ -556,7 +557,7 @@ func TestHandler_GetTrustAnchor_ShowsNotificationSettings(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp, jsonx.V1())) ta := getResp["trustAnchor"].(map[string]any) settings, ok := ta["notificationSettings"].([]any) require.True(t, ok, "GetTrustAnchor response must carry notificationSettings, got: %s", recGet.Body.String()) @@ -567,7 +568,7 @@ func TestHandler_GetTrustAnchor_ShowsNotificationSettings(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["trustAnchors"].([]any) require.Len(t, items, 1) listedTA := items[0].(map[string]any) @@ -585,7 +586,7 @@ func TestHandler_GetProfile_ShowsAttributeMappings(t *testing.T) { require.Equal(t, http.StatusCreated, recCreate.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["profile"].(map[string]any)["profileId"].(string) recPut := doREST(t, h, http.MethodPut, "/profiles/"+id+"/mappings", map[string]any{ @@ -601,7 +602,7 @@ func TestHandler_GetProfile_ShowsAttributeMappings(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp, jsonx.V1())) p := getResp["profile"].(map[string]any) mappings, ok := p["attributeMappings"].([]any) require.True(t, ok, "GetProfile response must carry attributeMappings, got: %s", recGet.Body.String()) @@ -612,7 +613,7 @@ func TestHandler_GetProfile_ShowsAttributeMappings(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp, jsonx.V1())) items := listResp["profiles"].([]any) require.Len(t, items, 1) listedProfile := items[0].(map[string]any) diff --git a/services/rolesanywhere/handler_trust_anchors.go b/services/rolesanywhere/handler_trust_anchors.go index 1b7d9c1b4a..7df589eb13 100644 --- a/services/rolesanywhere/handler_trust_anchors.go +++ b/services/rolesanywhere/handler_trust_anchors.go @@ -2,9 +2,11 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Trust Anchor handlers ---- @@ -18,7 +20,7 @@ func (h *Handler) handleCreateTrustAnchor(ctx context.Context, body []byte) (any NotificationSettings []NotificationSetting `json:"notificationSettings"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } @@ -90,7 +92,7 @@ func (h *Handler) handleUpdateTrustAnchor(ctx context.Context, path string, body Name string `json:"name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, 0, ErrValidation } diff --git a/services/rolesanywhere/handler_trust_anchors_test.go b/services/rolesanywhere/handler_trust_anchors_test.go index a85dce9782..7c770115ba 100644 --- a/services/rolesanywhere/handler_trust_anchors_test.go +++ b/services/rolesanywhere/handler_trust_anchors_test.go @@ -2,7 +2,7 @@ package rolesanywhere_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Trust Anchor HTTP CRUD ---- @@ -45,7 +47,7 @@ func TestHandler_TrustAnchor_CRUD(t *testing.T) { assert.Equal(t, tt.wantCreate, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) ta := createResp["trustAnchor"].(map[string]any) id := ta["trustAnchorId"].(string) assert.NotEmpty(t, id) @@ -220,8 +222,8 @@ func TestHandler_TrustAnchor_DuplicateNameAllowed(t *testing.T) { assert.Equal(t, tt.wantStatus, rec2.Code) var resp1, resp2 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) ta1 := resp1["trustAnchor"].(map[string]any) ta2 := resp2["trustAnchor"].(map[string]any) @@ -246,7 +248,7 @@ func TestHandler_TrustAnchor_NoTagsFieldOnResponse(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ta := resp["trustAnchor"].(map[string]any) assert.NotContains(t, ta, "tags") @@ -256,7 +258,7 @@ func TestHandler_TrustAnchor_NoTagsFieldOnResponse(t *testing.T) { require.Equal(t, http.StatusOK, recTags.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(recTags.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["tags"].([]any) require.Len(t, tags, 1) tag := tags[0].(map[string]any) @@ -282,7 +284,7 @@ func TestHandler_CreateTrustAnchor_NotificationSettings(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ta := resp["trustAnchor"].(map[string]any) settings, ok := ta["notificationSettings"].([]any) @@ -323,7 +325,7 @@ func TestHandler_ListTrustAnchors_Pagination(t *testing.T) { rec := doREST(t, h, http.MethodGet, "/trustanchors"+tt.query, nil) assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["trustAnchors"].([]any) assert.Len(t, items, tt.wantCount) }) diff --git a/services/rolesanywhere/persistence.go b/services/rolesanywhere/persistence.go index c24c2d0828..005b2022d1 100644 --- a/services/rolesanywhere/persistence.go +++ b/services/rolesanywhere/persistence.go @@ -2,7 +2,7 @@ package rolesanywhere import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -72,7 +72,7 @@ func buildPersistenceDTORegistry() ( // maps left unconverted by Phase 3.3 (see store_setup.go) and are persisted // here directly, as before. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string][]TagEntry `json:"tags"` AttributeMappings map[string]map[string][]AttributeMapping `json:"attributeMappings"` NotificationSettings map[string]map[string][]NotificationSetting `json:"notificationSettings"` @@ -181,7 +181,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // profiles, crls, subjects) from tables via the ephemeral DTO registry, // factored out of Restore to keep Restore's own cognitive complexity low. // Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, taDTOs, profileDTOs, crlDTOs, subjectDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("rolesanywhere: restore snapshot resource tables: %w", err) diff --git a/services/rolesanywhere/persistence_test.go b/services/rolesanywhere/persistence_test.go index 1e86b77a2d..7d64e0c75a 100644 --- a/services/rolesanywhere/persistence_test.go +++ b/services/rolesanywhere/persistence_test.go @@ -5,11 +5,13 @@ package rolesanywhere //nolint:testpackage // needs unexported Subject.region ac import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestPersistence_SnapshotRestoreRoundTrip proves that a full Snapshot → @@ -247,10 +249,10 @@ func TestPersistence_RestoreVersionMismatch(t *testing.T) { require.NoError(t, err) var snapMap map[string]any - require.NoError(t, json.Unmarshal(donor.Snapshot(ctx), &snapMap)) + require.NoError(t, json.Unmarshal(donor.Snapshot(ctx), &snapMap, jsonx.V1())) tt.mutate(snapMap) - mutatedSnap, err := json.Marshal(snapMap) + mutatedSnap, err := json.Marshal(snapMap, jsonx.V1()) require.NoError(t, err) // The restore target starts with its own, different state so we diff --git a/services/route53/persistence.go b/services/route53/persistence.go index a2ff297afe..3767382c02 100644 --- a/services/route53/persistence.go +++ b/services/route53/persistence.go @@ -2,9 +2,11 @@ package route53 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -51,7 +53,7 @@ func zoneDataSnapshotKey(zs *zoneDataSnapshot) string { return zs.Zone.ID } // newer) build of this backend as though it were the current shape; see // Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TrafficPolicies map[string][]*TrafficPolicy `json:"trafficPolicies,omitempty"` VPCAssociations map[string][]vpcAssociation `json:"vpcAssociations,omitempty"` VPCAssocAuthorizations map[string][]VPCAssociationAuthorization `json:"vpcAssocAuthorizations,omitempty"` @@ -108,7 +110,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Tags: b.tags, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "route53 Snapshot failed", "error", err) @@ -157,7 +159,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // silently produce zero-valued garbage (every entry keying to the same // empty zone ID). zones is restored separately below via its own DTO // registry, so it is excluded here. - cleanTables := make(map[string]json.RawMessage, len(snap.Tables)) + cleanTables := make(map[string]jsontext.Value, len(snap.Tables)) for name, raw := range snap.Tables { if name == "zones" { diff --git a/services/route53recoverycluster/misc_test.go b/services/route53recoverycluster/misc_test.go index 127e6aee29..d9ac0c4011 100644 --- a/services/route53recoverycluster/misc_test.go +++ b/services/route53recoverycluster/misc_test.go @@ -1,7 +1,7 @@ package route53recoverycluster_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdkcheck" cluster "github.com/blackbirdworks/gopherstack/services/route53recoverycluster" ) @@ -96,7 +97,7 @@ func TestErrorBodyShape(t *testing.T) { assert.GreaterOrEqual(t, rec.Code, http.StatusBadRequest) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body["message"]) assert.Equal(t, body["message"], body["Message"]) assert.False( diff --git a/services/route53recoverycluster/ops.go b/services/route53recoverycluster/ops.go index e9b0857b66..fad4437ed4 100644 --- a/services/route53recoverycluster/ops.go +++ b/services/route53recoverycluster/ops.go @@ -2,9 +2,10 @@ package route53recoverycluster import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/restroute" cc "github.com/blackbirdworks/gopherstack/services/route53recoverycontrolconfig" ) @@ -48,7 +49,7 @@ func (h *Handler) dispatch(_ context.Context, action, clusterID string, body []b return nil, err } - return json.Marshal(out) + return json.Marshal(out, jsonx.V1()) } func decode(body []byte, v any) error { @@ -56,7 +57,7 @@ func decode(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return restroute.Validation("request body is not valid JSON for this operation") } diff --git a/services/route53recoverycontrolconfig/misc_test.go b/services/route53recoverycontrolconfig/misc_test.go index 4be704046e..2bb4f6d4ca 100644 --- a/services/route53recoverycontrolconfig/misc_test.go +++ b/services/route53recoverycontrolconfig/misc_test.go @@ -2,7 +2,7 @@ package route53recoverycontrolconfig_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdkcheck" cc "github.com/blackbirdworks/gopherstack/services/route53recoverycontrolconfig" ) @@ -156,7 +157,7 @@ func TestErrorBodyShape(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Header().Get("X-Amzn-Errortype")) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body["message"]) assert.Equal(t, body["message"], body["Message"]) assert.False( diff --git a/services/route53recoverycontrolconfig/persistence.go b/services/route53recoverycontrolconfig/persistence.go index 865a6b511d..853018e5ff 100644 --- a/services/route53recoverycontrolconfig/persistence.go +++ b/services/route53recoverycontrolconfig/persistence.go @@ -2,7 +2,7 @@ package route53recoverycontrolconfig import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -13,9 +13,9 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Tokens map[string]string `json:"tokens,omitempty"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Tokens map[string]string `json:"tokens,omitempty"` + Version int `json:"version"` } // Snapshot serialises the backend state. It implements persistence.Persistable. diff --git a/services/route53recoveryreadiness/misc_test.go b/services/route53recoveryreadiness/misc_test.go index 50b1aa7d2f..b77c0257b2 100644 --- a/services/route53recoveryreadiness/misc_test.go +++ b/services/route53recoveryreadiness/misc_test.go @@ -1,7 +1,7 @@ package route53recoveryreadiness_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdkcheck" rr "github.com/blackbirdworks/gopherstack/services/route53recoveryreadiness" ) @@ -174,7 +175,7 @@ func TestErrorBodyShape(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Header().Get("X-Amzn-Errortype")) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.NotEmpty(t, body["message"]) assert.Equal(t, body["message"], body["Message"]) assert.False(t, strings.HasPrefix(body["message"], tt.wantCode)) diff --git a/services/route53recoveryreadiness/persistence.go b/services/route53recoveryreadiness/persistence.go index 169f339698..403d50fe68 100644 --- a/services/route53recoveryreadiness/persistence.go +++ b/services/route53recoveryreadiness/persistence.go @@ -2,7 +2,7 @@ package route53recoveryreadiness import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -13,8 +13,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. It implements persistence.Persistable. diff --git a/services/route53resolver/configs_test.go b/services/route53resolver/configs_test.go index fabb04c2c4..4257c9bd29 100644 --- a/services/route53resolver/configs_test.go +++ b/services/route53resolver/configs_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -90,7 +91,7 @@ func TestResolverDnssecConfig_StatusValues(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["ResolverDNSSECConfig"].(map[string]any) assert.Equal(t, tt.wantStatus, cfg["ValidationStatus"]) } @@ -108,7 +109,7 @@ func TestFirewallConfig_NoArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["FirewallConfig"].(map[string]any) // AWS does not return Arn for FirewallConfig. @@ -629,7 +630,7 @@ func TestListFirewallConfigs_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListFirewallConfigs", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) cfgs, _ := out["FirewallConfigs"].([]any) assert.Len(t, cfgs, tt.wantLen) if tt.wantNextToken { @@ -681,7 +682,7 @@ func TestListResolverConfigs_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverConfigs", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) cfgs, _ := out["ResolverConfigs"].([]any) assert.Len(t, cfgs, tt.wantLen) if tt.wantNextToken { @@ -733,7 +734,7 @@ func TestListResolverDnssecConfigs_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverDnssecConfigs", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) cfgs, _ := out["ResolverDnssecConfigs"].([]any) assert.Len(t, cfgs, tt.wantLen) if tt.wantNextToken { @@ -764,7 +765,7 @@ func TestResolverDnssecConfig_ValidationField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) cfg, ok := out["ResolverDNSSECConfig"].(map[string]any) require.True(t, ok, "ResolverDNSSECConfig must be present") diff --git a/services/route53resolver/dns_querylog.go b/services/route53resolver/dns_querylog.go index e33858d796..de280ec157 100644 --- a/services/route53resolver/dns_querylog.go +++ b/services/route53resolver/dns_querylog.go @@ -2,13 +2,14 @@ package route53resolver import ( "context" - "encoding/json" + "encoding/json/v2" "net" "strings" "time" "github.com/miekg/dns" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" cwlogsbackend "github.com/blackbirdworks/gopherstack/services/cloudwatchlogs" ) @@ -152,7 +153,7 @@ func (b *InMemoryBackend) queryLogJSON(e queryLogEntry) string { }) } - out, _ := json.Marshal(rec) + out, _ := json.Marshal(rec, jsonx.V1()) return string(out) } diff --git a/services/route53resolver/dns_resolver_log_destinations_test.go b/services/route53resolver/dns_resolver_log_destinations_test.go index fbd2b0a11b..a6ba049b1a 100644 --- a/services/route53resolver/dns_resolver_log_destinations_test.go +++ b/services/route53resolver/dns_resolver_log_destinations_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "regexp" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" ) @@ -147,7 +148,7 @@ func TestDNSResolverQueryLogS3Destination(t *testing.T) { for _, l := range lines { var rec map[string]any - require.NoError(t, json.Unmarshal([]byte(l), &rec)) + require.NoError(t, json.Unmarshal([]byte(l), &rec, jsonx.V1())) assert.Equal(t, vpc1, rec["vpc_id"]) names = append(names, rec["query_name"].(string)) } @@ -205,7 +206,7 @@ func TestDNSResolverQueryLogFirehoseDestination(t *testing.T) { assert.True(t, bytes.HasSuffix(rec.data, []byte("\n"))) var body map[string]any - require.NoError(t, json.Unmarshal(rec.data, &body)) + require.NoError(t, json.Unmarshal(rec.data, &body, jsonx.V1())) assert.Equal(t, "q.example.", body["query_name"]) assert.Equal(t, vpc1, body["vpc_id"]) }) diff --git a/services/route53resolver/dns_resolver_log_test.go b/services/route53resolver/dns_resolver_log_test.go index cb5f2f5a29..02523d24ab 100644 --- a/services/route53resolver/dns_resolver_log_test.go +++ b/services/route53resolver/dns_resolver_log_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "net" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ec2backend "github.com/blackbirdworks/gopherstack/services/ec2" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -117,7 +118,7 @@ func TestDNSResolverQueryLogging(t *testing.T) { } var rec map[string]any - require.NoError(t, json.Unmarshal([]byte(msgs[0]), &rec)) + require.NoError(t, json.Unmarshal([]byte(msgs[0]), &rec, jsonx.V1())) assert.Equal(t, vpc1, rec["vpc_id"]) assert.Equal(t, "q.example.", rec["query_name"]) assert.Equal(t, "A", rec["query_type"]) diff --git a/services/route53resolver/firewall_domain_lists_test.go b/services/route53resolver/firewall_domain_lists_test.go index 6c8d7373aa..5ca48a369b 100644 --- a/services/route53resolver/firewall_domain_lists_test.go +++ b/services/route53resolver/firewall_domain_lists_test.go @@ -1,13 +1,14 @@ package route53resolver_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -22,7 +23,7 @@ func TestFirewallDomainList_ManagedOwnerName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dl := resp["FirewallDomainList"].(map[string]any) // ManagedOwnerName should be empty for user-created domain lists. @@ -78,7 +79,7 @@ func TestCreateFirewallDomainList(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dl, ok := resp["FirewallDomainList"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, dl["Name"]) @@ -108,7 +109,7 @@ func TestDeleteFirewallDomainList(t *testing.T) { rec := doRequest(t, h, "CreateFirewallDomainList", map[string]any{"Name": "dl-del"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["FirewallDomainList"].(map[string]any)["Id"].(string) }, @@ -149,7 +150,7 @@ func TestDeleteFirewallDomainList(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dl, ok := resp["FirewallDomainList"].(map[string]any) require.True(t, ok) assert.Equal(t, id, dl["Id"]) @@ -170,7 +171,7 @@ func TestListFirewallDomains_Pagination(t *testing.T) { dlRec := doRequest(t, h, "CreateFirewallDomainList", map[string]any{"Name": "dl-paginate"}) require.Equal(t, http.StatusOK, dlRec.Code) var dlOut map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlOut)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlOut, jsonx.V1())) dlID := dlOut["FirewallDomainList"].(map[string]any)["Id"].(string) domains := []string{"example.com", "foo.com", "bar.com", "baz.com"} @@ -207,7 +208,7 @@ func TestListFirewallDomains_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListFirewallDomains", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) domList, _ := out["Domains"].([]any) assert.Len(t, domList, tt.wantLen) if tt.wantNextToken { @@ -296,7 +297,7 @@ func TestListFirewallDomainLists_NoOverwideLeak(t *testing.T) { var raw struct { FirewallDomainLists []map[string]any `json:"FirewallDomainLists"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.FirewallDomainLists, 1) item := raw.FirewallDomainLists[0] diff --git a/services/route53resolver/firewall_rule_groups_test.go b/services/route53resolver/firewall_rule_groups_test.go index 849495e23b..756f1e89c6 100644 --- a/services/route53resolver/firewall_rule_groups_test.go +++ b/services/route53resolver/firewall_rule_groups_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -24,7 +25,7 @@ func TestFirewallRuleGroup_ShareStatusAndTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rg := resp["FirewallRuleGroup"].(map[string]any) assert.Equal(t, "NOT_SHARED", rg["ShareStatus"]) @@ -80,7 +81,7 @@ func TestFirewallRuleGroupAssociation_MutationProtection(t *testing.T) { ) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocBody := map[string]any{ @@ -98,7 +99,7 @@ func TestFirewallRuleGroupAssociation_MutationProtection(t *testing.T) { if tt.wantAssocCode == http.StatusOK && tt.tryDisassociate { var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) assocID := assocResp["FirewallRuleGroupAssociation"].(map[string]any)["Id"].(string) disassocRec := doRequest(t, h, "DisassociateFirewallRuleGroup", map[string]any{ @@ -139,7 +140,7 @@ func TestUpdateFirewallRuleGroupAssociation_MutationProtection(t *testing.T) { ) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateFirewallRuleGroup", map[string]any{ @@ -150,7 +151,7 @@ func TestUpdateFirewallRuleGroupAssociation_MutationProtection(t *testing.T) { }) require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) assocID := assocResp["FirewallRuleGroupAssociation"].(map[string]any)["Id"].(string) rec := doRequest(t, h, "UpdateFirewallRuleGroupAssociation", map[string]any{ @@ -161,7 +162,7 @@ func TestUpdateFirewallRuleGroupAssociation_MutationProtection(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc := resp["FirewallRuleGroupAssociation"].(map[string]any) assert.Equal(t, tt.mutationProtection, assoc["MutationProtection"]) } @@ -184,7 +185,7 @@ func TestUpdateFirewallRuleGroupAssociation_RejectedMutationProtectionLeavesStat grpRec := doRequest(t, h, "CreateFirewallRuleGroup", map[string]any{"Name": "upd-mp-partial-grp"}) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateFirewallRuleGroup", map[string]any{ @@ -195,7 +196,7 @@ func TestUpdateFirewallRuleGroupAssociation_RejectedMutationProtectionLeavesStat }) require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) assocID := assocResp["FirewallRuleGroupAssociation"].(map[string]any)["Id"].(string) updateRec := doRequest(t, h, "UpdateFirewallRuleGroupAssociation", map[string]any{ @@ -211,7 +212,7 @@ func TestUpdateFirewallRuleGroupAssociation_RejectedMutationProtectionLeavesStat }) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assoc := getResp["FirewallRuleGroupAssociation"].(map[string]any) assert.Equal(t, "original-name", assoc["Name"]) assert.InDelta(t, float64(100), assoc["Priority"], 0) @@ -227,7 +228,7 @@ func TestFirewallRuleGroupAssociation_CreatorAndTimestamps(t *testing.T) { grpRec := doRequest(t, h, "CreateFirewallRuleGroup", map[string]any{"Name": "assoc-ts-grp"}) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateFirewallRuleGroup", map[string]any{ @@ -240,7 +241,7 @@ func TestFirewallRuleGroupAssociation_CreatorAndTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, assocRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &resp, jsonx.V1())) assoc := resp["FirewallRuleGroupAssociation"].(map[string]any) assert.Equal(t, "req-assoc-ts-1", assoc["CreatorRequestId"]) @@ -314,7 +315,7 @@ func TestListFirewallRuleGroups_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, _ := resp["FirewallRuleGroups"].([]any) assert.Len(t, groups, tt.wantLen) nextToken, _ := resp["NextToken"].(string) @@ -362,7 +363,7 @@ func TestCreateFirewallRuleGroup(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) grp, ok := resp["FirewallRuleGroup"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, grp["Name"]) @@ -393,7 +394,7 @@ func TestAssociateFirewallRuleGroup(t *testing.T) { rec := doRequest(t, h, "CreateFirewallRuleGroup", map[string]any{"Name": "grp-assoc"}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["FirewallRuleGroup"].(map[string]any)["Id"].(string) }, @@ -449,7 +450,7 @@ func TestAssociateFirewallRuleGroup(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc, ok := resp["FirewallRuleGroupAssociation"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantStatus, assoc["Status"]) @@ -511,7 +512,7 @@ func TestListFirewallRuleGroupAssociations_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, grpRec.Code) var grpOut map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpOut)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpOut, jsonx.V1())) grpID := grpOut["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateFirewallRuleGroup", map[string]any{ @@ -548,7 +549,7 @@ func TestListFirewallRuleGroupAssociations_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListFirewallRuleGroupAssociations", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assocs, _ := out["FirewallRuleGroupAssociations"].([]any) assert.Len(t, assocs, tt.wantLen) if tt.wantNextToken { @@ -575,7 +576,7 @@ func TestListFirewallRuleGroupAssociations_PriorityStatusFilters(t *testing.T) { }) require.Equal(t, http.StatusOK, grpRec.Code) var grpOut map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpOut)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpOut, jsonx.V1())) grpID := grpOut["FirewallRuleGroup"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateFirewallRuleGroup", map[string]any{ @@ -603,7 +604,7 @@ func TestListFirewallRuleGroupAssociations_PriorityStatusFilters(t *testing.T) { listRec := doRequest(t, h, "ListFirewallRuleGroupAssociations", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assocs, _ := out["FirewallRuleGroupAssociations"].([]any) assert.Len(t, assocs, tt.wantLen) }) diff --git a/services/route53resolver/firewall_rules_test.go b/services/route53resolver/firewall_rules_test.go index b59d118db8..6eb64cd7d8 100644 --- a/services/route53resolver/firewall_rules_test.go +++ b/services/route53resolver/firewall_rules_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -135,7 +136,7 @@ func TestFirewallRule_BlockOverrideFields(t *testing.T) { ) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec := doRequest( @@ -146,7 +147,7 @@ func TestFirewallRule_BlockOverrideFields(t *testing.T) { ) require.Equal(t, http.StatusOK, dlRec.Code) var dlResp map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp, jsonx.V1())) dlID := dlResp["FirewallDomainList"].(map[string]any)["Id"].(string) rec := doRequest(t, h, "CreateFirewallRule", tt.body(groupID, dlID)) @@ -154,7 +155,7 @@ func TestFirewallRule_BlockOverrideFields(t *testing.T) { if tt.wantCode == http.StatusOK && tt.checkFn != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["FirewallRule"].(map[string]any) tt.checkFn(t, rule) } @@ -215,13 +216,13 @@ func TestUpdateFirewallRule_ExtendedFields(t *testing.T) { ) require.Equal(t, http.StatusOK, grpRec2.Code) var grpR2 map[string]any - require.NoError(t, json.Unmarshal(grpRec2.Body.Bytes(), &grpR2)) + require.NoError(t, json.Unmarshal(grpRec2.Body.Bytes(), &grpR2, jsonx.V1())) gID := grpR2["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec2 := doRequest(t, h2, "CreateFirewallDomainList", map[string]any{"Name": "upd-dl"}) require.Equal(t, http.StatusOK, dlRec2.Code) var dlR2 map[string]any - require.NoError(t, json.Unmarshal(dlRec2.Body.Bytes(), &dlR2)) + require.NoError(t, json.Unmarshal(dlRec2.Body.Bytes(), &dlR2, jsonx.V1())) dID := dlR2["FirewallDomainList"].(map[string]any)["Id"].(string) createRec2 := doRequest(t, h2, "CreateFirewallRule", map[string]any{ @@ -240,7 +241,7 @@ func TestUpdateFirewallRule_ExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["FirewallRule"].(map[string]any) tt.checkFn(t, rule) }) @@ -257,13 +258,13 @@ func TestFirewallRule_MetadataFields(t *testing.T) { grpRec := doRequest(t, h, "CreateFirewallRuleGroup", map[string]any{"Name": "meta-grp"}) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec := doRequest(t, h, "CreateFirewallDomainList", map[string]any{"Name": "meta-dl"}) require.Equal(t, http.StatusOK, dlRec.Code) var dlResp map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp, jsonx.V1())) dlID := dlResp["FirewallDomainList"].(map[string]any)["Id"].(string) createRec := doRequest(t, h, "CreateFirewallRule", map[string]any{ @@ -277,7 +278,7 @@ func TestFirewallRule_MetadataFields(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["FirewallRule"].(map[string]any) assert.Equal(t, "req-fw-rule-1", rule["CreatorRequestId"]) @@ -347,7 +348,7 @@ func TestFirewallRule_BlockResponseStoredOnCreate(t *testing.T) { ) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec := doRequest( @@ -358,7 +359,7 @@ func TestFirewallRule_BlockResponseStoredOnCreate(t *testing.T) { ) require.Equal(t, http.StatusOK, dlRec.Code) var dlResp map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp, jsonx.V1())) dlID := dlResp["FirewallDomainList"].(map[string]any)["Id"].(string) body := map[string]any{ @@ -377,7 +378,7 @@ func TestFirewallRule_BlockResponseStoredOnCreate(t *testing.T) { if tt.wantCode == http.StatusOK && tt.blockResponse != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["FirewallRule"].(map[string]any) assert.Equal(t, tt.blockResponse, rule["BlockResponse"]) } @@ -414,7 +415,7 @@ func TestCreateFirewallRule_ActionValidation(t *testing.T) { require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) grpID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) rec := doRequest(t, h, "CreateFirewallRule", map[string]any{ @@ -447,13 +448,13 @@ func TestCreateFirewallRule_NoIdOrArnInOutput(t *testing.T) { require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) grpID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec := doRequest(t, h, "CreateFirewallDomainList", map[string]any{"Name": "id-test-dl"}) require.Equal(t, http.StatusOK, dlRec.Code) var dlResp map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp, jsonx.V1())) dlID := dlResp["FirewallDomainList"].(map[string]any)["Id"].(string) ruleRec := doRequest(t, h, "CreateFirewallRule", map[string]any{ @@ -466,7 +467,7 @@ func TestCreateFirewallRule_NoIdOrArnInOutput(t *testing.T) { require.Equal(t, http.StatusOK, ruleRec.Code) var ruleResp map[string]any - require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp)) + require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp, jsonx.V1())) rule, ok := ruleResp["FirewallRule"].(map[string]any) require.True(t, ok) _, hasID := rule["Id"] @@ -488,7 +489,7 @@ func TestCreateFirewallRule_IncrementsRuleCount(t *testing.T) { require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) grp := grpResp["FirewallRuleGroup"].(map[string]any) grpID := grp["Id"].(string) assert.InDelta(t, 0, grp["RuleCount"], 0) @@ -526,13 +527,13 @@ func TestCreateFirewallRule(t *testing.T) { grpRec := doRequest(t, h, "CreateFirewallRuleGroup", map[string]any{"Name": "grp-rule"}) require.Equal(t, http.StatusOK, grpRec.Code) var grpResp map[string]any - require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp)) + require.NoError(t, json.Unmarshal(grpRec.Body.Bytes(), &grpResp, jsonx.V1())) groupID := grpResp["FirewallRuleGroup"].(map[string]any)["Id"].(string) dlRec := doRequest(t, h, "CreateFirewallDomainList", map[string]any{"Name": "dl-for-rule"}) require.Equal(t, http.StatusOK, dlRec.Code) var dlResp map[string]any - require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp)) + require.NoError(t, json.Unmarshal(dlRec.Body.Bytes(), &dlResp, jsonx.V1())) dlID := dlResp["FirewallDomainList"].(map[string]any)["Id"].(string) return groupID, dlID @@ -600,7 +601,7 @@ func TestCreateFirewallRule(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule, ok := resp["FirewallRule"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantAction, rule["Action"]) diff --git a/services/route53resolver/handler.go b/services/route53resolver/handler.go index ecf37d0fa3..54743e838b 100644 --- a/services/route53resolver/handler.go +++ b/services/route53resolver/handler.go @@ -2,7 +2,7 @@ package route53resolver import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/collections" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -121,7 +122,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } var req extractResolverResourceInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.Name } @@ -153,14 +154,11 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { msg := wireMessage(err) - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, ErrNotFound): payload := errorPayload("ResourceNotFoundException", msg) @@ -188,7 +186,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err // FirewallRule ops model ValidationException (see ErrBatchValidation) -- // left untyped rather than guessing which family reached this path. case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{keyMessageField: msg}) default: // InternalServiceErrorException is modeled on all 72 operations @@ -309,7 +307,7 @@ func updateSimpleConfig[TConfig, TOutput any]( // errorPayload carries the message under both casings: schema-driven SDK deserializers // (route53resolver v1.53+) only match the modeled member name "Message". func errorPayload(errType, msg string) []byte { - payload, _ := json.Marshal(map[string]string{"__type": errType, "message": msg, "Message": msg}) + payload, _ := json.Marshal(map[string]string{"__type": errType, "message": msg, "Message": msg}, jsonx.V1()) return payload } diff --git a/services/route53resolver/handler_error_type_internal_test.go b/services/route53resolver/handler_error_type_internal_test.go index 9c8958e356..9925628592 100644 --- a/services/route53resolver/handler_error_type_internal_test.go +++ b/services/route53resolver/handler_error_type_internal_test.go @@ -2,7 +2,7 @@ package route53resolver import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -43,6 +44,6 @@ func TestHandleError_GenericErrorSurfacesInternalServiceErrorException(t *testin assert.Equal(t, http.StatusInternalServerError, rec.Code) var payload service.JSONErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload, jsonx.V1())) assert.Equal(t, "InternalServiceErrorException", payload.Type) } diff --git a/services/route53resolver/handler_firewall_rules.go b/services/route53resolver/handler_firewall_rules.go index eba373348d..2cfc82b74d 100644 --- a/services/route53resolver/handler_firewall_rules.go +++ b/services/route53resolver/handler_firewall_rules.go @@ -2,7 +2,7 @@ package route53resolver import ( "context" - "encoding/json" + "encoding/json/jsontext" "errors" "fmt" "sort" @@ -40,9 +40,9 @@ type dnsThreatProtectionRuleTypeConfigInput struct { type firewallRuleTypeInput struct { DNSThreatProtection *dnsThreatProtectionRuleTypeConfigInput `json:"DnsThreatProtection,omitempty"` - FirewallAdvancedContentCategory json.RawMessage `json:"FirewallAdvancedContentCategory,omitempty"` - FirewallAdvancedThreatCategory json.RawMessage `json:"FirewallAdvancedThreatCategory,omitempty"` - PartnerThreatProtection json.RawMessage `json:"PartnerThreatProtection,omitempty"` + FirewallAdvancedContentCategory jsontext.Value `json:"FirewallAdvancedContentCategory,omitempty"` + FirewallAdvancedThreatCategory jsontext.Value `json:"FirewallAdvancedThreatCategory,omitempty"` + PartnerThreatProtection jsontext.Value `json:"PartnerThreatProtection,omitempty"` } // resolveFirewallRuleType validates a FirewallRuleType tagged union (exactly diff --git a/services/route53resolver/handler_test.go b/services/route53resolver/handler_test.go index 39ef2b21bd..ac3844ac73 100644 --- a/services/route53resolver/handler_test.go +++ b/services/route53resolver/handler_test.go @@ -2,7 +2,8 @@ package route53resolver_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -34,7 +36,7 @@ func doRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -309,7 +311,7 @@ func TestHandlerReset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, ok := resp["ResolverEndpoints"].([]any) require.True(t, ok) assert.Empty(t, endpoints) @@ -326,7 +328,7 @@ func decodeJSON(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &m, jsonx.V1())) return m } diff --git a/services/route53resolver/outpost_resolvers_test.go b/services/route53resolver/outpost_resolvers_test.go index 374137af65..987ccb105b 100644 --- a/services/route53resolver/outpost_resolvers_test.go +++ b/services/route53resolver/outpost_resolvers_test.go @@ -1,13 +1,15 @@ package route53resolver_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOutpostResolverCRUD(t *testing.T) { @@ -143,7 +145,7 @@ func TestCreateOutpostResolver_DefaultInstanceCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resolver, ok := resp["OutpostResolver"].(map[string]any) require.True(t, ok) assert.InDelta(t, 4, resolver["InstanceCount"], 0) @@ -213,7 +215,7 @@ func TestCreateOutpostResolver(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) r, ok := resp["OutpostResolver"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, r["Name"]) @@ -336,7 +338,7 @@ func TestListOutpostResolvers_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListOutpostResolvers", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) resolvers, _ := out["OutpostResolvers"].([]any) assert.Len(t, resolvers, tt.wantLen) if tt.wantNextToken { @@ -389,7 +391,7 @@ func TestListOutpostResolvers_OutpostArnFilter(t *testing.T) { listRec := doRequest(t, h, "ListOutpostResolvers", map[string]any{"OutpostArn": tt.outpostArn}) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) resolvers, _ := out["OutpostResolvers"].([]any) assert.Len(t, resolvers, tt.wantLen) }) diff --git a/services/route53resolver/persistence.go b/services/route53resolver/persistence.go index f83005c724..2684925934 100644 --- a/services/route53resolver/persistence.go +++ b/services/route53resolver/persistence.go @@ -2,9 +2,11 @@ package route53resolver import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -21,7 +23,7 @@ import ( const route53resolverSnapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string][]svcTags.KV `json:"tags"` FirewallRuleGroupPolicies map[string]map[string]string `json:"firewallRuleGroupPolicies"` QueryLogConfigPolicies map[string]map[string]string `json:"queryLogConfigPolicies"` @@ -59,7 +61,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "route53resolver: failed to snapshot backend", "error", err) diff --git a/services/route53resolver/persistence_test.go b/services/route53resolver/persistence_test.go index 084af0dcd5..55267d80e7 100644 --- a/services/route53resolver/persistence_test.go +++ b/services/route53resolver/persistence_test.go @@ -2,13 +2,14 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" svcTags "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -322,7 +323,7 @@ func TestPersistenceRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, epRec.Code) var epResp map[string]any - require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp)) + require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp, jsonx.V1())) ep := epResp["ResolverEndpoint"].(map[string]any) epARN := ep["Arn"].(string) @@ -347,7 +348,7 @@ func TestPersistenceRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) assert.Len(t, tags, 1) } diff --git a/services/route53resolver/query_log_associations_test.go b/services/route53resolver/query_log_associations_test.go index 381741bac6..92ddda93bd 100644 --- a/services/route53resolver/query_log_associations_test.go +++ b/services/route53resolver/query_log_associations_test.go @@ -1,7 +1,7 @@ package route53resolver_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -23,7 +24,7 @@ func TestResolverQueryLogConfigAssociation_Fields(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cfgID := createResp["ResolverQueryLogConfig"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateResolverQueryLogConfig", map[string]any{ @@ -33,7 +34,7 @@ func TestResolverQueryLogConfigAssociation_Fields(t *testing.T) { require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) assoc := assocResp["ResolverQueryLogConfigAssociation"].(map[string]any) assert.NotEmpty(t, assoc["Id"]) @@ -163,7 +164,7 @@ func TestAssociateResolverQueryLogConfig(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ResolverQueryLogConfig"].(map[string]any)["Id"].(string) }, @@ -214,7 +215,7 @@ func TestAssociateResolverQueryLogConfig(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc, ok := resp["ResolverQueryLogConfigAssociation"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantStatus, assoc["Status"]) @@ -286,7 +287,7 @@ func TestListResolverQueryLogConfigAssociations_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, cfgRec.Code) var cfgOut map[string]any - require.NoError(t, json.Unmarshal(cfgRec.Body.Bytes(), &cfgOut)) + require.NoError(t, json.Unmarshal(cfgRec.Body.Bytes(), &cfgOut, jsonx.V1())) cfgID := cfgOut["ResolverQueryLogConfig"].(map[string]any)["Id"].(string) for i := range 3 { @@ -323,7 +324,7 @@ func TestListResolverQueryLogConfigAssociations_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverQueryLogConfigAssociations", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assocs, _ := out["ResolverQueryLogConfigAssociations"].([]any) assert.Len(t, assocs, tt.wantLen) if tt.wantNextToken { @@ -348,7 +349,7 @@ func TestListResolverQueryLogConfigAssociations_Filters(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ResolverQueryLogConfig"].(map[string]any)["Id"].(string) } @@ -413,7 +414,7 @@ func TestListResolverQueryLogConfigAssociations_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assocs, _ := resp["ResolverQueryLogConfigAssociations"].([]any) gotResIDs := make([]string, len(assocs)) for i, a := range assocs { @@ -567,6 +568,6 @@ func TestListResolverQueryLogConfigAssociations_UnknownFilterNameRejected(t *tes require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } diff --git a/services/route53resolver/query_log_configs_test.go b/services/route53resolver/query_log_configs_test.go index 28387dbdbb..b02b5b6229 100644 --- a/services/route53resolver/query_log_configs_test.go +++ b/services/route53resolver/query_log_configs_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -25,7 +26,7 @@ func TestResolverQueryLogConfig_AssociationCount(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cfg := createResp["ResolverQueryLogConfig"].(map[string]any) cfgID := cfg["Id"].(string) assert.EqualValues(t, 0, cfg["AssociationCount"]) @@ -55,7 +56,7 @@ func TestResolverQueryLogConfig_AssociationCount(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) cfg = getResp["ResolverQueryLogConfig"].(map[string]any) assert.EqualValues(t, 2, cfg["AssociationCount"]) } @@ -133,7 +134,7 @@ func TestResolverQueryLogConfig_AssociationCountDecrement(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) cfgID := createResp["ResolverQueryLogConfig"].(map[string]any)["Id"].(string) // Associate. @@ -160,7 +161,7 @@ func TestResolverQueryLogConfig_AssociationCountDecrement(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) cfg := getResp["ResolverQueryLogConfig"].(map[string]any) assert.EqualValues(t, 0, cfg["AssociationCount"]) } @@ -410,7 +411,7 @@ func TestCreateResolverQueryLogConfig(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfg, ok := resp["ResolverQueryLogConfig"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, cfg["Name"]) @@ -465,7 +466,7 @@ func TestListResolverQueryLogConfigs_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverQueryLogConfigs", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) cfgs, _ := out["ResolverQueryLogConfigs"].([]any) assert.Len(t, cfgs, tt.wantLen) if tt.wantNextToken { @@ -538,7 +539,7 @@ func TestListResolverQueryLogConfigs_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfgs, _ := resp["ResolverQueryLogConfigs"].([]any) gotNames := make([]string, len(cfgs)) for i, c := range cfgs { @@ -698,6 +699,6 @@ func TestListResolverQueryLogConfigs_UnknownFilterNameRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } diff --git a/services/route53resolver/resolver_endpoints_test.go b/services/route53resolver/resolver_endpoints_test.go index 1cfe201b57..a449e75abf 100644 --- a/services/route53resolver/resolver_endpoints_test.go +++ b/services/route53resolver/resolver_endpoints_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -77,7 +78,7 @@ func TestResolverEndpoint_IPv6IPAddress(t *testing.T) { if tt.wantCode == http.StatusOK && tt.checkFn != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) _, hasIPs := ep["IpAddresses"] assert.False(t, hasIPs, "ResolverEndpoint response must not carry an IpAddresses field") @@ -88,7 +89,7 @@ func TestResolverEndpoint_IPv6IPAddress(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ips, _ := listResp["IpAddresses"].([]any) tt.checkFn(t, ips) } @@ -148,7 +149,7 @@ func TestResolverEndpoint_Protocols(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) assert.Equal(t, tt.wantProtocols, ep["Protocols"]) } @@ -196,7 +197,7 @@ func TestResolverEndpoint_OutpostFields(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) if outpostArn, ok := tt.body["OutpostArn"]; ok { @@ -222,7 +223,7 @@ func TestResolverEndpoint_CreatorRequestIdAndTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) assert.Equal(t, "req-abc-123", ep["CreatorRequestId"]) @@ -265,7 +266,7 @@ func TestResolverEndpoint_TypeValidation(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) if tt.epType == "" { assert.Equal(t, "IPV4", ep["ResolverEndpointType"]) @@ -334,7 +335,7 @@ func TestUpdateResolverEndpoint_Extended(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) epID := createResp["ResolverEndpoint"].(map[string]any)["Id"].(string) tt.updateBody["ResolverEndpointId"] = epID @@ -343,7 +344,7 @@ func TestUpdateResolverEndpoint_Extended(t *testing.T) { if tt.wantCode == http.StatusOK && tt.checkFn != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) tt.checkFn(t, ep) } @@ -367,7 +368,7 @@ func TestUpdateResolverEndpoint_RejectedTypeLeavesNameUnchanged(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) epID := createResp["ResolverEndpoint"].(map[string]any)["Id"].(string) updateRec := doRequest(t, h, "UpdateResolverEndpoint", map[string]any{ @@ -380,7 +381,7 @@ func TestUpdateResolverEndpoint_RejectedTypeLeavesNameUnchanged(t *testing.T) { getRec := doRequest(t, h, "GetResolverEndpoint", map[string]any{"ResolverEndpointId": epID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ep := getResp["ResolverEndpoint"].(map[string]any) assert.Equal(t, "orig-ep-partial", ep["Name"]) } @@ -615,7 +616,7 @@ func TestAssociateResolverEndpointIpAddress_IPv6(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) epID := createResp["ResolverEndpoint"].(map[string]any)["Id"].(string) assocRec := doRequest(t, h, "AssociateResolverEndpointIpAddress", map[string]any{ @@ -626,7 +627,7 @@ func TestAssociateResolverEndpointIpAddress_IPv6(t *testing.T) { if tt.wantCode == http.StatusOK && tt.checkFn != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) _, hasIPs := ep["IpAddresses"] assert.False(t, hasIPs, "ResolverEndpoint response must not carry an IpAddresses field") @@ -636,7 +637,7 @@ func TestAssociateResolverEndpointIpAddress_IPv6(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ips, _ := listResp["IpAddresses"].([]any) tt.checkFn(t, ips) } @@ -985,7 +986,7 @@ func TestCreateResolverEndpoint_HostVPCIdAndSecurityGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep, ok := resp["ResolverEndpoint"].(map[string]any) require.True(t, ok) assert.Equal(t, "vpc-abc123", ep["HostVPCId"]) @@ -1009,7 +1010,7 @@ func TestListResolverEndpoints_SortedByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, ok := resp["ResolverEndpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 3) @@ -1044,7 +1045,7 @@ func TestCreateResolverEndpoint_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep := resp["ResolverEndpoint"].(map[string]any) epARN := ep["Arn"].(string) @@ -1052,7 +1053,7 @@ func TestCreateResolverEndpoint_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) require.True(t, ok) assert.Len(t, tags, 1) @@ -1084,7 +1085,7 @@ func TestAssociateResolverEndpointIPAddress_Success(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ep := createResp["ResolverEndpoint"].(map[string]any) epID := ep["Id"].(string) @@ -1098,7 +1099,7 @@ func TestAssociateResolverEndpointIPAddress_Success(t *testing.T) { require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) updatedEP := assocResp["ResolverEndpoint"].(map[string]any) _, hasIPs := updatedEP["IpAddresses"] assert.False(t, hasIPs, "ResolverEndpoint response must not carry an IpAddresses field") @@ -1108,7 +1109,7 @@ func TestAssociateResolverEndpointIPAddress_Success(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ips, ok := listResp["IpAddresses"].([]any) require.True(t, ok) assert.Len(t, ips, 1) @@ -1142,7 +1143,7 @@ func TestListResolverEndpoints_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eps, _ := resp["ResolverEndpoints"].([]any) assert.Len(t, eps, tt.wantLen) nextToken, _ := resp["NextToken"].(string) @@ -1166,7 +1167,7 @@ func TestListResolverEndpoints_NextTokenContinuation(t *testing.T) { rec1 := doRequest(t, h, "ListResolverEndpoints", map[string]any{"MaxResults": 2}) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) eps1, _ := resp1["ResolverEndpoints"].([]any) require.Len(t, eps1, 2) nextToken, _ := resp1["NextToken"].(string) @@ -1178,7 +1179,7 @@ func TestListResolverEndpoints_NextTokenContinuation(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) eps2, _ := resp2["ResolverEndpoints"].([]any) assert.NotEmpty(t, eps2) @@ -1227,7 +1228,7 @@ func TestDeleteResolverEndpoint_CascadeDeletesRules(t *testing.T) { require.Equal(t, http.StatusOK, epRec.Code) var epResp map[string]any - require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp)) + require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp, jsonx.V1())) ep := epResp["ResolverEndpoint"].(map[string]any) epID := ep["Id"].(string) @@ -1254,7 +1255,7 @@ func TestDeleteResolverEndpoint_CascadeDeletesRules(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) rules := listResp["ResolverRules"].([]any) assert.Len(t, rules, tt.wantRulesAfter) }) @@ -1306,7 +1307,7 @@ func TestAssociateResolverEndpointIpAddress(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpointID = resp["ResolverEndpoint"].(map[string]any)["Id"].(string) } @@ -1318,7 +1319,7 @@ func TestAssociateResolverEndpointIpAddress(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep, ok := resp["ResolverEndpoint"].(map[string]any) require.True(t, ok) _, hasIPs := ep["IpAddresses"] @@ -1329,7 +1330,7 @@ func TestAssociateResolverEndpointIpAddress(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) ips, _ := listResp["IpAddresses"].([]any) assert.Len(t, ips, tt.wantIPCount) } @@ -1353,7 +1354,7 @@ func TestListResolverEndpointIpAddresses_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) epID := createOut["ResolverEndpoint"].(map[string]any)["Id"].(string) for i := 2; i <= 4; i++ { @@ -1393,7 +1394,7 @@ func TestListResolverEndpointIpAddresses_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverEndpointIpAddresses", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) ips, _ := out["IpAddresses"].([]any) assert.Len(t, ips, tt.wantLen) if tt.wantNextToken { @@ -1419,7 +1420,7 @@ func TestCreateResolverEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ep, ok := resp["ResolverEndpoint"].(map[string]any) require.True(t, ok) assert.Contains(t, ep["Arn"], "arn:aws:route53resolver:") @@ -1437,7 +1438,7 @@ func TestGetResolverEndpoint(t *testing.T) { "Direction": "OUTBOUND", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ep := createResp["ResolverEndpoint"].(map[string]any) id := ep["Id"].(string) @@ -1447,7 +1448,7 @@ func TestGetResolverEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) got := resp["ResolverEndpoint"].(map[string]any) assert.Equal(t, id, got["Id"]) } @@ -1468,7 +1469,7 @@ func TestListResolverEndpoints(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, ok := resp["ResolverEndpoints"].([]any) require.True(t, ok) assert.Len(t, endpoints, 2) @@ -1545,7 +1546,7 @@ func TestListResolverEndpoints_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eps, _ := resp["ResolverEndpoints"].([]any) gotNames := make([]string, len(eps)) for i, e := range eps { @@ -1576,7 +1577,7 @@ func TestListResolverEndpoints_FiltersANDedTogether(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) eps, _ := resp["ResolverEndpoints"].([]any) require.Len(t, eps, 1) assert.Equal(t, "in-vpc2", eps[0].(map[string]any)["Name"]) @@ -1596,7 +1597,7 @@ func TestListResolverEndpoints_UnknownFilterNameRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } @@ -1609,7 +1610,7 @@ func TestDeleteResolverEndpoint(t *testing.T) { "Direction": "INBOUND", }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ep := createResp["ResolverEndpoint"].(map[string]any) id := ep["Id"].(string) diff --git a/services/route53resolver/resolver_rules_test.go b/services/route53resolver/resolver_rules_test.go index e69b3934f1..9fc0729af6 100644 --- a/services/route53resolver/resolver_rules_test.go +++ b/services/route53resolver/resolver_rules_test.go @@ -2,13 +2,14 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -69,7 +70,7 @@ func TestResolverRule_CreatorAndTimestamps(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["ResolverRule"].(map[string]any) assert.Equal(t, "req-rule-001", rule["CreatorRequestId"]) @@ -307,7 +308,7 @@ func TestUpdateResolverRule(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ResolverRule"].(map[string]any)["Id"].(string) }, @@ -445,7 +446,7 @@ func TestListResolverRules_SortedByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, ok := resp["ResolverRules"].([]any) require.True(t, ok) require.Len(t, rules, 2) @@ -469,7 +470,7 @@ func TestDeleteResolverRule_CascadesAssociations(t *testing.T) { require.Equal(t, http.StatusOK, ruleRec.Code) var ruleResp map[string]any - require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp)) + require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp, jsonx.V1())) ruleID := ruleResp["ResolverRule"].(map[string]any)["Id"].(string) // Associate with a VPC. @@ -531,7 +532,7 @@ func TestListResolverRules_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, _ := resp["ResolverRules"].([]any) assert.Len(t, rules, tt.wantLen) nextToken, _ := resp["NextToken"].(string) @@ -585,7 +586,7 @@ func TestCreateResolverRule_EndpointValidation(t *testing.T) { require.Equal(t, http.StatusOK, epRec.Code) var epResp map[string]any - require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp)) + require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp, jsonx.V1())) ep := epResp["ResolverEndpoint"].(map[string]any) endpointID = ep["Id"].(string) } @@ -615,7 +616,7 @@ func TestCreateResolverRule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule, ok := resp["ResolverRule"].(map[string]any) require.True(t, ok) assert.Contains(t, rule["Arn"], "arn:aws:route53resolver:") @@ -681,7 +682,7 @@ func TestListResolverRules(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, ok := resp["ResolverRules"].([]any) require.True(t, ok) assert.Len(t, rules, 2) @@ -748,7 +749,7 @@ func TestListResolverRules_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, _ := resp["ResolverRules"].([]any) gotNames := make([]string, len(rules)) for i, r := range rules { @@ -775,7 +776,7 @@ func TestListResolverRules_UnknownFilterNameRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } @@ -790,7 +791,7 @@ func TestDeleteResolverRule(t *testing.T) { "TargetIps": []map[string]any{{"Ip": "10.0.0.1", "Port": 53}}, }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rule := createResp["ResolverRule"].(map[string]any) id := rule["Id"].(string) @@ -811,7 +812,7 @@ func TestGetResolverRule(t *testing.T) { "TargetIps": []map[string]any{{"Ip": "10.0.0.1", "Port": 53}}, }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rule := createResp["ResolverRule"].(map[string]any) id := rule["Id"].(string) @@ -821,7 +822,7 @@ func TestGetResolverRule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) got, ok := resp["ResolverRule"].(map[string]any) require.True(t, ok) assert.Equal(t, id, got["Id"]) diff --git a/services/route53resolver/rule_associations_test.go b/services/route53resolver/rule_associations_test.go index c06ab7ed85..ad6399c3c6 100644 --- a/services/route53resolver/rule_associations_test.go +++ b/services/route53resolver/rule_associations_test.go @@ -1,7 +1,7 @@ package route53resolver_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -174,7 +175,7 @@ func TestAssociateResolverRule(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["ResolverRule"].(map[string]any)["Id"].(string) }, @@ -226,7 +227,7 @@ func TestAssociateResolverRule(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assoc, ok := resp["ResolverRuleAssociation"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantStatus, assoc["Status"]) @@ -254,7 +255,7 @@ func TestListResolverRuleAssociations_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, ruleRec.Code) var ruleOut map[string]any - require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleOut)) + require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleOut, jsonx.V1())) ruleID := ruleOut["ResolverRule"].(map[string]any)["Id"].(string) for i := range 3 { @@ -292,7 +293,7 @@ func TestListResolverRuleAssociations_Pagination(t *testing.T) { listRec := doRequest(t, h, "ListResolverRuleAssociations", tt.body) require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) assocs, _ := out["ResolverRuleAssociations"].([]any) assert.Len(t, assocs, tt.wantLen) if tt.wantNextToken { @@ -318,7 +319,7 @@ func TestListResolverRuleAssociations_Filters(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ResolverRule"].(map[string]any)["Id"].(string) } @@ -390,7 +391,7 @@ func TestListResolverRuleAssociations_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assocs, _ := resp["ResolverRuleAssociations"].([]any) gotNames := make([]string, len(assocs)) for i, a := range assocs { @@ -413,6 +414,6 @@ func TestListResolverRuleAssociations_UnknownFilterNameRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } diff --git a/services/route53resolver/store_test.go b/services/route53resolver/store_test.go index 7ad5af5bda..f78decb005 100644 --- a/services/route53resolver/store_test.go +++ b/services/route53resolver/store_test.go @@ -2,7 +2,7 @@ package route53resolver_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/route53resolver" ) @@ -29,7 +30,7 @@ func TestFullCRUDLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, epRec.Code) var epResp map[string]any - require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp)) + require.NoError(t, json.Unmarshal(epRec.Body.Bytes(), &epResp, jsonx.V1())) ep := epResp["ResolverEndpoint"].(map[string]any) epID := ep["Id"].(string) assert.NotEmpty(t, ep["CreationTime"]) @@ -48,7 +49,7 @@ func TestFullCRUDLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, ruleRec.Code) var ruleResp map[string]any - require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp)) + require.NoError(t, json.Unmarshal(ruleRec.Body.Bytes(), &ruleResp, jsonx.V1())) rule := ruleResp["ResolverRule"].(map[string]any) ruleID := rule["Id"].(string) assert.Equal(t, "req-rule-lifecycle", rule["CreatorRequestId"]) @@ -61,7 +62,7 @@ func TestFullCRUDLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, qlcRec.Code) var qlcResp map[string]any - require.NoError(t, json.Unmarshal(qlcRec.Body.Bytes(), &qlcResp)) + require.NoError(t, json.Unmarshal(qlcRec.Body.Bytes(), &qlcResp, jsonx.V1())) qlc := qlcResp["ResolverQueryLogConfig"].(map[string]any) qlcID := qlc["Id"].(string) assert.EqualValues(t, 0, qlc["AssociationCount"]) @@ -79,7 +80,7 @@ func TestFullCRUDLifecycle(t *testing.T) { ) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.EqualValues(t, 1, getResp["ResolverQueryLogConfig"].(map[string]any)["AssociationCount"]) // 5. Firewall rule group with timestamps. @@ -89,7 +90,7 @@ func TestFullCRUDLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, frgRec.Code) var frgResp map[string]any - require.NoError(t, json.Unmarshal(frgRec.Body.Bytes(), &frgResp)) + require.NoError(t, json.Unmarshal(frgRec.Body.Bytes(), &frgResp, jsonx.V1())) frg := frgResp["FirewallRuleGroup"].(map[string]any) frgID := frg["Id"].(string) assert.Equal(t, "NOT_SHARED", frg["ShareStatus"]) diff --git a/services/route53resolver/tags_test.go b/services/route53resolver/tags_test.go index 339a806bab..ff85d1dbbc 100644 --- a/services/route53resolver/tags_test.go +++ b/services/route53resolver/tags_test.go @@ -1,12 +1,14 @@ package route53resolver_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTagResource(t *testing.T) { @@ -72,7 +74,7 @@ func TestListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ep := createResp["ResolverEndpoint"].(map[string]any) epARN := ep["Arn"].(string) @@ -90,7 +92,7 @@ func TestListTagsForResource(t *testing.T) { assert.Equal(t, tt.wantCode, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].([]any) assert.Len(t, tags, tt.wantTags) }) @@ -115,7 +117,7 @@ func TestListTagsForResource_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) epARN := createResp["ResolverEndpoint"].(map[string]any)["Arn"].(string) tagRec := doRequest(t, h, "TagResource", map[string]any{ @@ -134,7 +136,7 @@ func TestListTagsForResource_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, page1Rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1, jsonx.V1())) page1Tags := page1["Tags"].([]any) assert.Len(t, page1Tags, 2) nextToken, ok := page1["NextToken"].(string) @@ -148,7 +150,7 @@ func TestListTagsForResource_Pagination(t *testing.T) { }) require.Equal(t, http.StatusOK, page2Rec.Code) var page2 map[string]any - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2, jsonx.V1())) page2Tags := page2["Tags"].([]any) assert.Len(t, page2Tags, 1) _, hasNext := page2["NextToken"] @@ -192,7 +194,7 @@ func TestUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ep := createResp["ResolverEndpoint"].(map[string]any) epARN := ep["Arn"].(string) @@ -220,7 +222,7 @@ func TestUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].([]any) assert.Len(t, tags, tt.wantTags) }) diff --git a/services/rum/events.go b/services/rum/events.go index 88d70ec2fd..c0c3af5ef8 100644 --- a/services/rum/events.go +++ b/services/rum/events.go @@ -3,12 +3,14 @@ package rum import ( "cmp" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/restroute" @@ -79,11 +81,11 @@ func validateEvents(in *PutEventsInput) error { return invalid("RumEvents[%d] requires id, type and a timestamp", i) } - if !json.Valid([]byte(e.Details)) { + if !jsontext.Value([]byte(e.Details)).IsValid(jsonx.V1()) { return invalid("RumEvents[%d].details must be valid JSON", i) } - if e.Metadata != "" && !json.Valid([]byte(e.Metadata)) { + if e.Metadata != "" && !jsontext.Value([]byte(e.Metadata)).IsValid(jsonx.V1()) { return invalid("RumEvents[%d].metadata must be valid JSON", i) } } @@ -98,7 +100,7 @@ func decodeJSON(s string) any { var v any - _ = json.Unmarshal([]byte(s), &v) + _ = json.Unmarshal([]byte(s), &v, jsonx.V1()) return v } @@ -202,7 +204,7 @@ func (b *InMemoryBackend) storeEvents(in *PutEventsInput) (delivery, error) { doc := eventDoc(m, in, e) - raw, merr := json.Marshal(doc) + raw, merr := json.Marshal(doc, jsonx.V1()) if merr != nil { return delivery{}, internalError("could not encode event %s", e.ID) } diff --git a/services/rum/metrics.go b/services/rum/metrics.go index c19985d6b6..15e5fea410 100644 --- a/services/rum/metrics.go +++ b/services/rum/metrics.go @@ -3,13 +3,14 @@ package rum import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "errors" "slices" "strings" "github.com/google/uuid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/restroute" ) @@ -184,7 +185,7 @@ func (b *InMemoryBackend) ListRumMetricsDestinations( func jsonObjectOf(s string) (map[string]any, error) { var out map[string]any - if err := json.Unmarshal([]byte(s), &out); err != nil || out == nil { + if err := json.Unmarshal([]byte(s), &out, jsonx.V1()); err != nil || out == nil { return nil, invalid("EventPattern must be a JSON object") } diff --git a/services/rum/pattern.go b/services/rum/pattern.go index dcbf6f5110..c9da1400e6 100644 --- a/services/rum/pattern.go +++ b/services/rum/pattern.go @@ -1,13 +1,14 @@ package rum import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/eventpattern" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // matchPattern reports whether doc satisfies an EventBridge-style event pattern. @@ -176,7 +177,7 @@ func pathString(doc map[string]any, path string) (string, bool) { func parseObject(s string) (map[string]any, error) { var out map[string]any - if err := json.Unmarshal([]byte(s), &out); err != nil || out == nil { + if err := json.Unmarshal([]byte(s), &out, jsonx.V1()); err != nil || out == nil { return nil, fmt.Errorf("%w: %q", errNotObject, s) } diff --git a/services/rum/pattern_test.go b/services/rum/pattern_test.go index 3692f0295b..e3569071f0 100644 --- a/services/rum/pattern_test.go +++ b/services/rum/pattern_test.go @@ -1,12 +1,13 @@ package rum_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/rum" ) @@ -42,14 +43,14 @@ func TestMatchPattern(t *testing.T) { } var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(event), &doc)) + require.NoError(t, json.Unmarshal([]byte(event), &doc, jsonx.V1())) for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { t.Parallel() var pattern map[string]any - require.NoError(t, json.Unmarshal([]byte(tc.pattern), &pattern)) + require.NoError(t, json.Unmarshal([]byte(tc.pattern), &pattern, jsonx.V1())) assert.Equal(t, tc.want, rum.MatchPattern(pattern, doc)) }) } diff --git a/services/rum/persistence.go b/services/rum/persistence.go index a44c7f3227..0d0e27f1e3 100644 --- a/services/rum/persistence.go +++ b/services/rum/persistence.go @@ -2,7 +2,7 @@ package rum import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,11 +12,11 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Seq int64 `json:"seq"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Seq int64 `json:"seq"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/rum/policies.go b/services/rum/policies.go index 6af42d3703..e62550a6a8 100644 --- a/services/rum/policies.go +++ b/services/rum/policies.go @@ -2,9 +2,11 @@ package rum import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutResourcePolicy attaches or replaces the resource policy of an app monitor. @@ -16,10 +18,10 @@ func (b *InMemoryBackend) PutResourcePolicy( } var parsed struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if doc == "" || json.Unmarshal([]byte(doc), &parsed) != nil || len(parsed.Statement) == 0 { + if doc == "" || json.Unmarshal([]byte(doc), &parsed, jsonx.V1()) != nil || len(parsed.Statement) == 0 { return "", "", malformedPolicy("PolicyDocument must be a JSON policy with a Statement") } diff --git a/services/rum/realclient_helpers_test.go b/services/rum/realclient_helpers_test.go index 8feffb1fdc..d1b3d58bce 100644 --- a/services/rum/realclient_helpers_test.go +++ b/services/rum/realclient_helpers_test.go @@ -2,7 +2,7 @@ package rum_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net" "net/http" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/services/rum" ) @@ -250,7 +251,7 @@ func mustJSON(t *testing.T, s string) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal([]byte(s), &m)) + require.NoError(t, json.Unmarshal([]byte(s), &m, jsonx.V1())) return m } diff --git a/services/s3/authz.go b/services/s3/authz.go index 7787606535..6082f8ccac 100644 --- a/services/s3/authz.go +++ b/services/s3/authz.go @@ -2,11 +2,12 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Data-plane access control. This file evaluates the stored bucket policy + ACL @@ -109,7 +110,7 @@ func (h *S3Handler) evaluateBucketPolicy( } var doc bucketPolicyDocument - if uErr := json.Unmarshal([]byte(arn.Canonical(policyJSON)), &doc); uErr != nil { + if uErr := json.Unmarshal([]byte(arn.Canonical(policyJSON)), &doc, jsonx.V1()); uErr != nil { return effectDefault } diff --git a/services/s3/bucket_ops_acl_policy.go b/services/s3/bucket_ops_acl_policy.go index f4418ed9b6..06f2d2662f 100644 --- a/services/s3/bucket_ops_acl_policy.go +++ b/services/s3/bucket_ops_acl_policy.go @@ -2,7 +2,8 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "errors" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validCannedACLs is the complete set of canned ACL strings that AWS S3 accepts @@ -153,7 +155,7 @@ func (h *S3Handler) putBucketPolicy( // Real S3 rejects a policy body that isn't valid JSON with 400 // MalformedPolicy before ever persisting it. - if !json.Valid(body) { + if !jsontext.Value(body).IsValid(jsonx.V1()) { WriteError(ctx, w, r, ErrMalformedPolicy) return @@ -501,7 +503,7 @@ func (h *S3Handler) handleGetBucketPolicyStatus( // contains an Allow statement that grants s3:GetObject to the wildcard principal "*". func policyGrantsPublicGetObject(policyJSON string) bool { var doc policyDoc - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return false } diff --git a/services/s3/bucket_policy_validation.go b/services/s3/bucket_policy_validation.go index 27ebc6ecc2..90c19f72f3 100644 --- a/services/s3/bucket_policy_validation.go +++ b/services/s3/bucket_policy_validation.go @@ -2,7 +2,11 @@ package s3 import ( "bytes" - "encoding/json" + "encoding/json/v2" + + "encoding/json/jsontext" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validateBucketPolicyDocument checks a PutBucketPolicy request body against the @@ -20,8 +24,8 @@ import ( // else *ErrorResponse{Code: "MalformedPolicy"} describing the first violation // (real S3's fail-fast behavior). func validateBucketPolicyDocument(body []byte) *ErrorResponse { - var top map[string]json.RawMessage - if err := json.Unmarshal(body, &top); err != nil { + var top map[string]jsontext.Value + if err := json.Unmarshal(body, &top, jsonx.V1()); err != nil { // json.Valid() already gated non-JSON bodies before this is called; // this branch covers valid-JSON-but-not-an-object bodies (e.g. a bare // JSON array, string, or number), which real S3 also rejects. @@ -61,14 +65,14 @@ func validateBucketPolicyDocument(body []byte) *ErrorResponse { // validatePolicyVersion validates the optional top-level Version element. AWS // accepts a policy with no Version at all (version_block is marked `?` in the // grammar), but if present it must be exactly "2008-10-17" or "2012-10-17". -func validatePolicyVersion(top map[string]json.RawMessage) *ErrorResponse { +func validatePolicyVersion(top map[string]jsontext.Value) *ErrorResponse { raw, ok := top["Version"] if !ok { return nil } var version string - if err := json.Unmarshal(raw, &version); err != nil { + if err := json.Unmarshal(raw, &version, jsonx.V1()); err != nil { return &ErrorResponse{ Code: errMalformedPolicy, Message: "The policy must contain a valid version string.", @@ -88,7 +92,7 @@ func validatePolicyVersion(top map[string]json.RawMessage) *ErrorResponse { // decodePolicyStatements decodes the "Statement" value, which per the IAM // grammar convention may be either a single statement object or a JSON array // of statement objects. -func decodePolicyStatements(raw json.RawMessage) ([]map[string]json.RawMessage, *ErrorResponse) { +func decodePolicyStatements(raw jsontext.Value) ([]map[string]jsontext.Value, *ErrorResponse) { trimmed := bytes.TrimSpace(raw) shapeErr := &ErrorResponse{ Code: errMalformedPolicy, @@ -100,27 +104,27 @@ func decodePolicyStatements(raw json.RawMessage) ([]map[string]json.RawMessage, } if trimmed[0] == '[' { - var arr []map[string]json.RawMessage - if err := json.Unmarshal(trimmed, &arr); err != nil { + var arr []map[string]jsontext.Value + if err := json.Unmarshal(trimmed, &arr, jsonx.V1()); err != nil { return nil, shapeErr } return arr, nil } - var single map[string]json.RawMessage - if err := json.Unmarshal(trimmed, &single); err != nil { + var single map[string]jsontext.Value + if err := json.Unmarshal(trimmed, &single, jsonx.V1()); err != nil { return nil, shapeErr } - return []map[string]json.RawMessage{single}, nil + return []map[string]jsontext.Value{single}, nil } // validatePolicyStatementShape validates a single statement object against // the required grammar elements for a resource-based (bucket) // policy: Effect, Principal/NotPrincipal, Action/NotAction, and // Resource/NotResource. -func validatePolicyStatementShape(stmt map[string]json.RawMessage) *ErrorResponse { +func validatePolicyStatementShape(stmt map[string]jsontext.Value) *ErrorResponse { if effectErr := validatePolicyEffect(stmt); effectErr != nil { return effectErr } @@ -150,14 +154,14 @@ func validatePolicyStatementShape(stmt map[string]json.RawMessage) *ErrorRespons } // validatePolicyEffect validates the required Effect element of a statement. -func validatePolicyEffect(stmt map[string]json.RawMessage) *ErrorResponse { +func validatePolicyEffect(stmt map[string]jsontext.Value) *ErrorResponse { effectRaw, ok := stmt["Effect"] if !ok { return &ErrorResponse{Code: errMalformedPolicy, Message: "Missing required field Effect"} } var effect string - if err := json.Unmarshal(effectRaw, &effect); err != nil || (effect != "Allow" && effect != "Deny") { + if err := json.Unmarshal(effectRaw, &effect, jsonx.V1()); err != nil || (effect != "Allow" && effect != "Deny") { return &ErrorResponse{ Code: errMalformedPolicy, Message: "Invalid effect: " + string(effectRaw), diff --git a/services/s3/express_session.go b/services/s3/express_session.go index 11582ee7f0..4c39c08fed 100644 --- a/services/s3/express_session.go +++ b/services/s3/express_session.go @@ -5,7 +5,7 @@ import ( "crypto/rand" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -13,6 +13,8 @@ import ( "time" "github.com/aws/aws-sdk-go-v2/service/s3/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // s3ExpressSessionTTL matches real S3 Express One Zone: CreateSession @@ -254,7 +256,7 @@ func validateSessionEncryptionContext(encoded, bucket string) error { } var kv map[string]string - if err = json.Unmarshal(raw, &kv); err != nil { + if err = json.Unmarshal(raw, &kv, jsonx.V1()); err != nil { return fmt.Errorf("%w: encryption context must be a JSON object of strings", ErrInvalidArgument) } diff --git a/services/s3/golden_perf_test.go b/services/s3/golden_perf_test.go index 5d0548b539..cc8b47a66d 100644 --- a/services/s3/golden_perf_test.go +++ b/services/s3/golden_perf_test.go @@ -11,7 +11,8 @@ package s3_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/xml" "net/http" "net/http/httptest" @@ -23,6 +24,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -35,9 +37,9 @@ func goldenPath(name string) string { func checkGolden(t *testing.T, name string, got []byte) { t.Helper() - var buf bytes.Buffer - require.NoError(t, json.Indent(&buf, got, "", " ")) - pretty := buf.Bytes() + indented := jsontext.Value(bytes.Clone(got)) + require.NoError(t, indented.Indent(jsonx.V1(), jsontext.WithIndent(" "))) + pretty := []byte(indented) path := goldenPath(name) if os.Getenv("S3_GOLDEN_UPDATE") != "" { @@ -79,7 +81,7 @@ func snapshotResponse(rec *httptest.ResponseRecorder, headerNames []string) gold func marshalGolden(t *testing.T, v any) []byte { t.Helper() - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return data diff --git a/services/s3/notification.go b/services/s3/notification.go index 583cb795e5..54678cb210 100644 --- a/services/s3/notification.go +++ b/services/s3/notification.go @@ -2,7 +2,7 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/v2" "encoding/xml" "fmt" "strings" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // notificationConfiguration mirrors the AWS S3 XML notification configuration @@ -204,7 +205,7 @@ func buildS3EventPayload( } envelope := map[string]any{"Records": []s3EventRecord{record}} - b, err := json.Marshal(envelope) + b, err := json.Marshal(envelope, jsonx.V1()) if err != nil { return "", err } @@ -249,7 +250,7 @@ func buildEventBridgeDetail(bucket, key, etag, reason string, size int64) (strin Reason: reason, } - b, err := json.Marshal(detail) + b, err := json.Marshal(detail, jsonx.V1()) if err != nil { return "", err } diff --git a/services/s3/object_lambda.go b/services/s3/object_lambda.go index d9c5d136ba..a705247ae9 100644 --- a/services/s3/object_lambda.go +++ b/services/s3/object_lambda.go @@ -2,7 +2,7 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -191,7 +192,7 @@ func (h *S3Handler) handleObjectLambdaGetObject( OutputRoute: "gopherstack", OutputToken: token, } - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { h.pendingObjectLambdaRequests.Delete(token) WriteError(ctx, w, r, err) diff --git a/services/s3/object_lambda_features_test.go b/services/s3/object_lambda_features_test.go index be8abb4878..582adff6c8 100644 --- a/services/s3/object_lambda_features_test.go +++ b/services/s3/object_lambda_features_test.go @@ -2,7 +2,7 @@ package s3_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -118,7 +119,7 @@ func TestObjectLambdaEventUserIdentity(t *testing.T) { select { case p := <-rec.payload: - require.NoError(t, json.Unmarshal(p, &event)) + require.NoError(t, json.Unmarshal(p, &event, jsonx.V1())) case <-t.Context().Done(): t.Fatal("lambda not invoked") } diff --git a/services/s3/object_lambda_head_list.go b/services/s3/object_lambda_head_list.go index dd74360ca2..c6612da5e4 100644 --- a/services/s3/object_lambda_head_list.go +++ b/services/s3/object_lambda_head_list.go @@ -2,7 +2,7 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -137,7 +138,7 @@ func (h *S3Handler) invokeObjectLambda(ctx context.Context, lambdaARN string, ev return nil, ErrNoSuchKey } - payload, err := json.Marshal(ev) + payload, err := json.Marshal(ev, jsonx.V1()) if err != nil { return nil, err } @@ -200,7 +201,7 @@ func (h *S3Handler) callObjectLambda( var res objectLambdaResult out, err := h.invokeObjectLambda(ctx, route.lambdaARN, ev) - if err != nil || json.Unmarshal(out, &res) != nil || res.StatusCode == 0 || + if err != nil || json.Unmarshal(out, &res, jsonx.V1()) != nil || res.StatusCode == 0 || (res.ListResultXML != "" && res.ListBucketResult != nil) { WriteError(ctx, w, r, errObjectLambdaFailed) diff --git a/services/s3/object_lambda_head_list_test.go b/services/s3/object_lambda_head_list_test.go index 0adf068c16..6579bb6d41 100644 --- a/services/s3/object_lambda_head_list_test.go +++ b/services/s3/object_lambda_head_list_test.go @@ -2,7 +2,7 @@ package s3_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -23,7 +24,7 @@ type recordingObjectLambda struct { func (l *recordingObjectLambda) InvokeFunction(_ context.Context, _, _ string, payload []byte) ([]byte, int, error) { var ev map[string]any - _ = json.Unmarshal(payload, &ev) + _ = json.Unmarshal(payload, &ev, jsonx.V1()) l.mu.Lock() l.events = append(l.events, ev) diff --git a/services/s3/object_lambda_test.go b/services/s3/object_lambda_test.go index a65e2c99d7..d631e2019c 100644 --- a/services/s3/object_lambda_test.go +++ b/services/s3/object_lambda_test.go @@ -2,7 +2,7 @@ package s3_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -42,7 +43,7 @@ func (l *staticObjectLambda) InvokeFunction( OutputToken string `json:"outputToken"` } `json:"getObjectContext"` } - if err := json.Unmarshal(payload, &event); err != nil { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err != nil { return nil, 0, err } diff --git a/services/s3/persistence.go b/services/s3/persistence.go index 6a3c554175..f7b7757461 100644 --- a/services/s3/persistence.go +++ b/services/s3/persistence.go @@ -2,11 +2,13 @@ package s3 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" @@ -32,10 +34,10 @@ const s3SnapshotVersion = 1 // unexported, so encoding/json already skips them. Restore re-initialises those // skipped fields via reinitBucketMutexes/reinitUploadMutexes below. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Tags map[string][]types.Tag `json:"tags"` - DefaultRegion string `json:"defaultRegion"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Tags map[string][]types.Tag `json:"tags"` + DefaultRegion string `json:"defaultRegion"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -175,7 +177,7 @@ func (bucket *StoredBucket) MarshalJSON() ([]byte, error) { bucket.mu.RLock("Snapshot") defer bucket.mu.RUnlock() - return json.Marshal((*storedBucketAlias)(bucket)) + return json.Marshal((*storedBucketAlias)(bucket), jsonx.V1()) } // storedObjectAlias avoids infinite recursion from StoredObject.MarshalJSON. @@ -187,7 +189,7 @@ func (obj *StoredObject) MarshalJSON() ([]byte, error) { obj.mu.RLock("Snapshot") defer obj.mu.RUnlock() - return json.Marshal((*storedObjectAlias)(obj)) + return json.Marshal((*storedObjectAlias)(obj), jsonx.V1()) } // storedMultipartUploadAlias avoids infinite recursion from @@ -200,7 +202,7 @@ func (u *StoredMultipartUpload) MarshalJSON() ([]byte, error) { u.mu.RLock("Snapshot") defer u.mu.RUnlock() - return json.Marshal((*storedMultipartUploadAlias)(u)) + return json.Marshal((*storedMultipartUploadAlias)(u), jsonx.V1()) } // Snapshot implements persistence.Persistable by delegating to the backend. diff --git a/services/s3/realclient_bucket_config_and_object_ops_test.go b/services/s3/realclient_bucket_config_and_object_ops_test.go index 0f07fdb6cf..c87b14972f 100644 --- a/services/s3/realclient_bucket_config_and_object_ops_test.go +++ b/services/s3/realclient_bucket_config_and_object_ops_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "crypto/sha256" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -1136,7 +1137,7 @@ func (l *typedWriteGetObjectResponseLambda) InvokeFunction( OutputToken string `json:"outputToken"` } `json:"getObjectContext"` } - if err := json.Unmarshal(payload, &event); err != nil { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err != nil { l.setResult(true, err) return nil, 0, err diff --git a/services/s3/select_csv.go b/services/s3/select_csv.go index c810961071..7cf29a2716 100644 --- a/services/s3/select_csv.go +++ b/services/s3/select_csv.go @@ -3,11 +3,13 @@ package s3 import ( "bytes" "encoding/csv" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errMissingSQLColumn = errors.New("MissingSQLColumn") @@ -205,7 +207,7 @@ func serializeCSVRowsAsJSON(rows []map[string]string, jsonOut *selectJSONOutput) var buf bytes.Buffer for _, row := range rows { - jsonBytes, err := json.Marshal(mapStringToAny(row)) + jsonBytes, err := json.Marshal(mapStringToAny(row), jsonx.V1()) if err != nil { return nil, err } diff --git a/services/s3/select_json.go b/services/s3/select_json.go index e226781c65..64bdaea521 100644 --- a/services/s3/select_json.go +++ b/services/s3/select_json.go @@ -3,10 +3,12 @@ package s3 import ( "bufio" "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "io" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // evaluateJSONQuery reads JSON from data, applies the SQL query, and streams results. @@ -52,7 +54,7 @@ func evaluateJSONLinesQuery( } var row map[string]any - if err := json.Unmarshal(line, &row); err != nil { + if err := json.Unmarshal(line, &row, jsonx.V1()); err != nil { return 0, fmt.Errorf("parsing JSON line: %w", err) } @@ -95,7 +97,7 @@ func evaluateJSONDocumentQuery( req *selectRequest, ) (int64, error) { var doc any - if err := json.Unmarshal(data, &doc); err != nil { + if err := json.Unmarshal(data, &doc, jsonx.V1()); err != nil { return 0, fmt.Errorf("parsing JSON document: %w", err) } @@ -192,7 +194,7 @@ func serializeJSONRows(rows []map[string]any, jsonOut *selectJSONOutput) ([]byte var buf bytes.Buffer for _, row := range rows { - jsonBytes, err := json.Marshal(row) + jsonBytes, err := json.Marshal(row, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/s3control/handler_access_points.go b/services/s3control/handler_access_points.go index e8707a74eb..7caac15787 100644 --- a/services/s3control/handler_access_points.go +++ b/services/s3control/handler_access_points.go @@ -1,7 +1,7 @@ package s3control import ( - "encoding/json" + "encoding/json/jsontext" "encoding/xml" "net/http" "slices" @@ -9,6 +9,8 @@ import ( "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -421,7 +423,7 @@ func (h *Handler) handlePutAccessPointPolicy(c *echo.Context) error { return writeXMLErrorCode(c, http.StatusBadRequest, "MalformedXML", "invalid request body") } - if !json.Valid([]byte(body.Policy)) { + if !jsontext.Value([]byte(body.Policy)).IsValid(jsonx.V1()) { return writeXMLErrorCode(c, http.StatusBadRequest, "MalformedPolicy", "Policy is not valid JSON") } diff --git a/services/s3control/persistence.go b/services/s3control/persistence.go index a18e4984bb..56cbf29618 100644 --- a/services/s3control/persistence.go +++ b/services/s3control/persistence.go @@ -2,10 +2,12 @@ package s3control import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -72,7 +74,7 @@ func newDirtyDTORegistry() ( // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` // batch2 additions (raw, non-*T maps -- never converted to store.Table) BucketReplication map[string]string `json:"bucketReplication"` StorageLensConfigs map[string]string `json:"storageLensConfigs"` @@ -153,7 +155,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NextID: b.nextID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "s3control: failed to snapshot backend", "error", err) @@ -341,7 +343,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreDirtyTablesLocked restores the "dirty" tables (mrapRequests, // accessPointPABs) from tables via the ephemeral DTO registry, converting // each DTO back to its live type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, mrapDTOs, pabDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/s3files/file_systems.go b/services/s3files/file_systems.go index 27464785e8..fe0651a5e2 100644 --- a/services/s3files/file_systems.go +++ b/services/s3files/file_systems.go @@ -2,7 +2,8 @@ package s3files import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" @@ -10,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -287,8 +289,8 @@ func validatePolicy(policy string) error { return validation("Policy must be between 1 and 20480 bytes") } - var doc map[string]json.RawMessage - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + var doc map[string]jsontext.Value + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return validation("Policy is not a valid JSON document") } diff --git a/services/s3files/handler.go b/services/s3files/handler.go index 759ea63e04..5c7e92cfe4 100644 --- a/services/s3files/handler.go +++ b/services/s3files/handler.go @@ -2,7 +2,7 @@ package s3files import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -285,7 +286,7 @@ func decode(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validation("malformed request body") } diff --git a/services/s3files/persistence.go b/services/s3files/persistence.go index 213c401a5a..adc74ec5d9 100644 --- a/services/s3files/persistence.go +++ b/services/s3files/persistence.go @@ -2,7 +2,7 @@ package s3files import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -13,10 +13,10 @@ import ( const s3filesSnapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/s3tables/handler.go b/services/s3tables/handler.go index 17839dc3f9..ef785435a9 100644 --- a/services/s3tables/handler.go +++ b/services/s3tables/handler.go @@ -2,7 +2,7 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -530,7 +531,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ "message": msg, - }) + }, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) diff --git a/services/s3tables/handler_namespaces.go b/services/s3tables/handler_namespaces.go index 0425243eb2..d47716290b 100644 --- a/services/s3tables/handler_namespaces.go +++ b/services/s3tables/handler_namespaces.go @@ -2,10 +2,11 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -23,7 +24,7 @@ func (h *Handler) handleCreateNamespace(ctx context.Context, r *http.Request, bo bucketARN := segs[1] var req createNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -42,7 +43,7 @@ func (h *Handler) handleCreateNamespace(ctx context.Context, r *http.Request, bo return json.Marshal(map[string]any{ keyNamespace: ns.Namespace, keyTableBucketARN: ns.TableBucketARN, - }) + }, jsonx.V1()) } func (h *Handler) handleGetNamespace(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -73,7 +74,7 @@ func (h *Handler) handleGetNamespace(ctx context.Context, r *http.Request, _ []b keyCreatedBy: ns.CreatedBy, keyOwnerAccountID: ns.OwnerAccountID, keyNamespaceID: ns.NamespaceID, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteNamespace(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -143,5 +144,5 @@ func (h *Handler) handleListNamespaces(ctx context.Context, r *http.Request, _ [ resp[keyContinuationToken] = pg.Next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/s3tables/handler_namespaces_test.go b/services/s3tables/handler_namespaces_test.go index 08b4f54d45..73bbd59550 100644 --- a/services/s3tables/handler_namespaces_test.go +++ b/services/s3tables/handler_namespaces_test.go @@ -1,13 +1,15 @@ package s3tables_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Namespace_CRUD(t *testing.T) { @@ -153,7 +155,7 @@ func TestHandler_ListNamespacesIncludesTableBucketId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) namespaces, ok := out["namespaces"].([]any) require.True(t, ok) diff --git a/services/s3tables/handler_replication.go b/services/s3tables/handler_replication.go index 04c9a74988..1aba17cb07 100644 --- a/services/s3tables/handler_replication.go +++ b/services/s3tables/handler_replication.go @@ -2,10 +2,11 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -60,7 +61,7 @@ func (h *Handler) handleGetTableRecordExpirationConfiguration( return json.Marshal(map[string]any{ keyConfiguration: configuration, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableReplication(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -83,7 +84,7 @@ func (h *Handler) handleGetTableReplication(ctx context.Context, r *http.Request "rules": cfg.Rules, }, keyVersionToken: cfg.VersionToken, - }) + }, jsonx.V1()) } // putTableReplicationRequest is the request body for PutTableReplication. @@ -100,7 +101,7 @@ func (h *Handler) handlePutTableReplication(ctx context.Context, r *http.Request versionToken := r.URL.Query().Get(keyVersionToken) var req putTableReplicationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +118,7 @@ func (h *Handler) handlePutTableReplication(ctx context.Context, r *http.Request return json.Marshal(map[string]any{ keyStatusField: replicationStatusCompleted, keyVersionToken: cfg.VersionToken, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableReplicationStatus(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -149,7 +150,7 @@ func (h *Handler) handleGetTableReplicationStatus(ctx context.Context, r *http.R return json.Marshal(map[string]any{ "sourceTableArn": tableArn, "destinations": destinations, - }) + }, jsonx.V1()) } // putTableRecordExpirationRequest is the request body for PutTableRecordExpirationConfiguration. @@ -168,7 +169,7 @@ func (h *Handler) handlePutTableRecordExpirationConfiguration( } var req putTableRecordExpirationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -225,5 +226,5 @@ func (h *Handler) handleGetTableRecordExpirationJobStatus( return json.Marshal(map[string]any{ keyStatusField: status, - }) + }, jsonx.V1()) } diff --git a/services/s3tables/handler_table_bucket_config_test.go b/services/s3tables/handler_table_bucket_config_test.go index 906f19a6bf..1c6bd2730c 100644 --- a/services/s3tables/handler_table_bucket_config_test.go +++ b/services/s3tables/handler_table_bucket_config_test.go @@ -1,7 +1,7 @@ package s3tables_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3tables" ) @@ -227,7 +228,7 @@ func TestHandler_ListTableBucketsIncludesType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) buckets, ok := out["tableBuckets"].([]any) require.True(t, ok) @@ -274,7 +275,7 @@ func TestHandler_GetTableBucketReplication_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) _, hasTopLevelDests := out["destinations"] _, hasFabricatedWrapper := out["replicationConfiguration"] diff --git a/services/s3tables/handler_table_buckets.go b/services/s3tables/handler_table_buckets.go index fd6e08c0b6..4f2bcd7b67 100644 --- a/services/s3tables/handler_table_buckets.go +++ b/services/s3tables/handler_table_buckets.go @@ -2,11 +2,12 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -23,7 +24,7 @@ type createTableBucketRequest struct { func (h *Handler) handleCreateTableBucket(ctx context.Context, _ *http.Request, body []byte) ([]byte, error) { var req createTableBucketRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -45,7 +46,7 @@ func (h *Handler) handleCreateTableBucket(ctx context.Context, _ *http.Request, return json.Marshal(map[string]string{ keyArn: tb.ARN, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableBucket(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -71,7 +72,7 @@ func (h *Handler) handleGetTableBucket(ctx context.Context, r *http.Request, _ [ keyCreatedAt: tb.CreatedAt.UTC().Format("2006-01-02T15:04:05.999Z"), keyType: bucketTypeCustomer, keyTableBucketID: tb.BucketID, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteTableBucket(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -137,7 +138,7 @@ func (h *Handler) handleListTableBuckets(ctx context.Context, r *http.Request, _ resp[keyContinuationToken] = pg.Next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleGetTableBucketMaintenanceConfiguration( @@ -167,7 +168,7 @@ func (h *Handler) handleGetTableBucketMaintenanceConfiguration( return json.Marshal(map[string]any{ keyTableBucketARN: bucketARN, keyConfiguration: cfg, - }) + }, jsonx.V1()) } // putTableBucketMaintenanceRequest is the request body for PutTableBucketMaintenanceConfiguration. @@ -189,7 +190,7 @@ func (h *Handler) handlePutTableBucketMaintenanceConfiguration( maintenanceType := segs[3] var req putTableBucketMaintenanceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -244,7 +245,7 @@ func (h *Handler) handleGetTableBucketEncryption(ctx context.Context, r *http.Re return json.Marshal(map[string]any{ "encryptionConfiguration": tb.Encryption, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteTableBucketEncryption(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -292,7 +293,7 @@ func (h *Handler) handleGetTableBucketMetricsConfiguration( resp["id"] = configID } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleDeleteTableBucketMetricsConfiguration( @@ -347,7 +348,7 @@ func (h *Handler) handleGetTableBucketStorageClass(ctx context.Context, r *http. "storageClassConfiguration": map[string]any{ "storageClass": sc, }, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableBucketReplication(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -370,7 +371,7 @@ func (h *Handler) handleGetTableBucketReplication(ctx context.Context, r *http.R "rules": cfg.Rules, }, keyVersionToken: cfg.VersionToken, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteTableBucketReplication(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -409,7 +410,7 @@ func (h *Handler) handleGetTableBucketPolicy(ctx context.Context, r *http.Reques return json.Marshal(map[string]string{ "resourcePolicy": policy, - }) + }, jsonx.V1()) } // putTableBucketPolicyRequest is the request body for PutTableBucketPolicy. @@ -426,7 +427,7 @@ func (h *Handler) handlePutTableBucketPolicy(ctx context.Context, r *http.Reques bucketARN := segs[1] var req putTableBucketPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -476,7 +477,7 @@ func (h *Handler) handlePutTableBucketEncryption(ctx context.Context, r *http.Re bucketARN := segs[1] var req putTableBucketEncryptionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -530,7 +531,7 @@ func (h *Handler) handlePutTableBucketStorageClass(ctx context.Context, r *http. bucketARN := segs[1] var req putTableBucketStorageClassRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -563,7 +564,7 @@ func (h *Handler) handlePutTableBucketReplication(ctx context.Context, r *http.R versionToken := r.URL.Query().Get(keyVersionToken) var req putTableBucketReplicationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -580,5 +581,5 @@ func (h *Handler) handlePutTableBucketReplication(ctx context.Context, r *http.R return json.Marshal(map[string]any{ keyStatusField: replicationStatusCompleted, keyVersionToken: cfg.VersionToken, - }) + }, jsonx.V1()) } diff --git a/services/s3tables/handler_table_maintenance_test.go b/services/s3tables/handler_table_maintenance_test.go index 21e030bb96..841f74e807 100644 --- a/services/s3tables/handler_table_maintenance_test.go +++ b/services/s3tables/handler_table_maintenance_test.go @@ -1,13 +1,16 @@ package s3tables_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/url" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_MaintenanceConfiguration(t *testing.T) { @@ -329,12 +332,12 @@ func TestHandler_MetadataLocationVsUpdate(t *testing.T) { updateBody, err := json.Marshal(map[string]string{ "metadataLocation": tt.metaLocation, "versionToken": table["versionToken"].(string), - }) + }, jsonx.V1()) require.NoError(t, err) rec := doS3TablesRequest(t, h, http.MethodPut, "/tables/"+encodedARN+"/ns1/t1/metadata-location", - json.RawMessage(updateBody)) + jsontext.Value(updateBody)) require.Equal(t, http.StatusOK, rec.Code) rec2 := doS3TablesRequest(t, h, http.MethodGet, diff --git a/services/s3tables/handler_tables.go b/services/s3tables/handler_tables.go index 95ddfd2166..8c96c648c3 100644 --- a/services/s3tables/handler_tables.go +++ b/services/s3tables/handler_tables.go @@ -2,10 +2,11 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -48,7 +49,7 @@ func (h *Handler) handleGetTableMaintenanceJobStatus( return json.Marshal(map[string]any{ keyTableARN: table.ARN, keyStatusField: jobStatus, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableMetadataLocation(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -73,7 +74,7 @@ func (h *Handler) handleGetTableMetadataLocation(ctx context.Context, r *http.Re keyVersionToken: table.VersionToken, "warehouseLocation": table.WarehouseLocation, keyMetadataLocation: table.MetadataLocation, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableEncryption(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -96,7 +97,7 @@ func (h *Handler) handleGetTableEncryption(ctx context.Context, r *http.Request, return json.Marshal(map[string]any{ "encryptionConfiguration": encCfg, - }) + }, jsonx.V1()) } // createTableRequest is the request body for CreateTable. @@ -123,7 +124,7 @@ func (h *Handler) handleCreateTable(ctx context.Context, r *http.Request, body [ nsName := segs[2] var req createTableRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -155,7 +156,7 @@ func (h *Handler) handleCreateTable(ctx context.Context, r *http.Request, body [ return json.Marshal(map[string]string{ keyTableARN: table.ARN, keyVersionToken: table.VersionToken, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTable(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -211,7 +212,7 @@ func (h *Handler) handleGetTable(ctx context.Context, r *http.Request, _ []byte) keyCreatedBy: table.OwnerAccountID, "modifiedBy": table.OwnerAccountID, keyOwnerAccountID: table.OwnerAccountID, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteTable(ctx context.Context, r *http.Request, _ []byte) ([]byte, error) { @@ -286,7 +287,7 @@ func (h *Handler) handleListTables(ctx context.Context, r *http.Request, _ []byt resp[keyContinuationToken] = pg.Next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // renameTableRequest is the request body for RenameTable. @@ -307,7 +308,7 @@ func (h *Handler) handleRenameTable(ctx context.Context, r *http.Request, body [ name := segs[3] var req renameTableRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -353,7 +354,7 @@ func (h *Handler) handleUpdateTableMetadataLocation(ctx context.Context, r *http name := segs[3] var req updateTableMetadataLocationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -387,7 +388,7 @@ func (h *Handler) handleUpdateTableMetadataLocation(ctx context.Context, r *http keyNamespace: table.Namespace, keyVersionToken: table.VersionToken, keyMetadataLocation: table.MetadataLocation, - }) + }, jsonx.V1()) } func (h *Handler) handleGetTableMaintenanceConfiguration( @@ -419,7 +420,7 @@ func (h *Handler) handleGetTableMaintenanceConfiguration( return json.Marshal(map[string]any{ keyTableARN: tableARN, keyConfiguration: cfg, - }) + }, jsonx.V1()) } // putTableMaintenanceRequest is the request body for PutTableMaintenanceConfiguration. @@ -443,7 +444,7 @@ func (h *Handler) handlePutTableMaintenanceConfiguration( maintenanceType := segs[5] var req putTableMaintenanceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -500,7 +501,7 @@ func (h *Handler) handleGetTablePolicy(ctx context.Context, r *http.Request, _ [ return json.Marshal(map[string]string{ "resourcePolicy": policy, - }) + }, jsonx.V1()) } // putTablePolicyRequest is the request body for PutTablePolicy. @@ -519,7 +520,7 @@ func (h *Handler) handlePutTablePolicy(ctx context.Context, r *http.Request, bod name := segs[3] var req putTablePolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -579,5 +580,5 @@ func (h *Handler) handleGetTableStorageClass(ctx context.Context, r *http.Reques "storageClassConfiguration": map[string]any{ "storageClass": sc, }, - }) + }, jsonx.V1()) } diff --git a/services/s3tables/handler_tables_test.go b/services/s3tables/handler_tables_test.go index 04fe46da34..880a2b86ed 100644 --- a/services/s3tables/handler_tables_test.go +++ b/services/s3tables/handler_tables_test.go @@ -1,7 +1,7 @@ package s3tables_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/url" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Table_Create(t *testing.T) { @@ -518,7 +520,7 @@ func TestHandler_ListTablesResponseUsesLowercaseArns(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tables, ok := out["tables"].([]any) require.True(t, ok) diff --git a/services/s3tables/handler_tags.go b/services/s3tables/handler_tags.go index e9e5b3276e..551bf60571 100644 --- a/services/s3tables/handler_tags.go +++ b/services/s3tables/handler_tags.go @@ -2,10 +2,11 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -27,7 +28,7 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, r *http.Request return json.Marshal(map[string]any{ "tags": tags, - }) + }, jsonx.V1()) } // tagResourceRequest is the request body for TagResource. @@ -44,7 +45,7 @@ func (h *Handler) handleTagResource(ctx context.Context, r *http.Request, body [ resourceArn := segs[1] var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/s3tables/handler_test.go b/services/s3tables/handler_test.go index 40f8002b1a..861b966b0b 100644 --- a/services/s3tables/handler_test.go +++ b/services/s3tables/handler_test.go @@ -2,7 +2,8 @@ package s3tables_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/s3tables" ) @@ -46,7 +48,7 @@ func doS3TablesRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -68,7 +70,7 @@ func parseResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var result map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&result)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &result, jsonx.V1())) return result } diff --git a/services/s3tables/metadata_writer.go b/services/s3tables/metadata_writer.go index 4e4ab31f52..25933b799c 100644 --- a/services/s3tables/metadata_writer.go +++ b/services/s3tables/metadata_writer.go @@ -2,7 +2,7 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "time" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/iceberg" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -181,7 +182,7 @@ func buildIcebergTableMetadata(t *Table, now time.Time) (*iceberg.TableMetadata, return nil, err } - orderJSON, err := json.Marshal(order) + orderJSON, err := json.Marshal(order, jsonx.V1()) if err != nil { return nil, err } @@ -203,10 +204,10 @@ func buildIcebergTableMetadata(t *Table, now time.Time) (*iceberg.TableMetadata, } func roundTrip(in map[string]any, out any) error { - b, err := json.Marshal(in) + b, err := json.Marshal(in, jsonx.V1()) if err != nil { return err } - return json.Unmarshal(b, out) + return json.Unmarshal(b, out, jsonx.V1()) } diff --git a/services/s3tables/multi_region_test.go b/services/s3tables/multi_region_test.go index cd88cdb18f..f7963aeed4 100644 --- a/services/s3tables/multi_region_test.go +++ b/services/s3tables/multi_region_test.go @@ -2,7 +2,8 @@ package s3tables_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/s3tables" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/s3tables/persistence.go b/services/s3tables/persistence.go index a166d4f092..fc4ddf8946 100644 --- a/services/s3tables/persistence.go +++ b/services/s3tables/persistence.go @@ -2,7 +2,7 @@ package s3tables import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -87,7 +87,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // against decoding a snapshot from an incompatible (older or newer) build // of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -198,7 +198,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold every mutex. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { if err := b.registry.RestoreAll(tables); err != nil { return fmt.Errorf("s3tables: restore clean tables: %w", err) } diff --git a/services/s3tables/validation.go b/services/s3tables/validation.go index 5ec7dda3bd..bed100b367 100644 --- a/services/s3tables/validation.go +++ b/services/s3tables/validation.go @@ -1,10 +1,12 @@ package s3tables import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Real S3 Tables naming rules, confirmed against @@ -133,7 +135,7 @@ func validateNamespaceParts(namespace []string) error { // validatePolicyDocument rejects a resource policy that is not a JSON object. func validatePolicyDocument(policy string) error { var doc map[string]any - if err := json.Unmarshal([]byte(policy), &doc); err != nil || doc == nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil || doc == nil { return fmt.Errorf("%w: resourcePolicy must be a valid JSON policy document", errInvalidRequest) } diff --git a/services/s3vectors/buckets.go b/services/s3vectors/buckets.go index 333cb8e18e..116733a8e5 100644 --- a/services/s3vectors/buckets.go +++ b/services/s3vectors/buckets.go @@ -2,11 +2,12 @@ package s3vectors import ( "cmp" - "encoding/json" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -238,7 +239,7 @@ func (b *InMemoryBackend) putBucketPolicy(sc scope, in *putPolicyIn) (any, error return nil, invalid("policy is required") } - if err := json.Unmarshal([]byte(in.Policy), &doc); err != nil || doc.Statement == nil { + if err := json.Unmarshal([]byte(in.Policy), &doc, jsonx.V1()); err != nil || doc.Statement == nil { return nil, invalid("policy must be a JSON policy document with a Statement") } diff --git a/services/s3vectors/models.go b/services/s3vectors/models.go index bbcd2594ac..5c4728a1f2 100644 --- a/services/s3vectors/models.go +++ b/services/s3vectors/models.go @@ -3,10 +3,12 @@ package s3vectors import ( "encoding/base64" "encoding/binary" - "encoding/json" + "encoding/json/v2" "errors" "math" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // f32s stores a vector as float32 and serialises as base64 little-endian bytes, 4 bytes per dimension. @@ -23,13 +25,13 @@ func (v f32s) MarshalJSON() ([]byte, error) { binary.LittleEndian.PutUint32(buf[bytesPerFloat*i:], math.Float32bits(f)) } - return json.Marshal(base64.StdEncoding.EncodeToString(buf)) + return json.Marshal(base64.StdEncoding.EncodeToString(buf), jsonx.V1()) } // UnmarshalJSON implements json.Unmarshaler. func (v *f32s) UnmarshalJSON(data []byte) error { var s string - if err := json.Unmarshal(data, &s); err != nil { + if err := json.Unmarshal(data, &s, jsonx.V1()); err != nil { return err } diff --git a/services/s3vectors/persistence.go b/services/s3vectors/persistence.go index cc414f37ba..a045579e09 100644 --- a/services/s3vectors/persistence.go +++ b/services/s3vectors/persistence.go @@ -2,7 +2,7 @@ package s3vectors import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/s3vectors/vectors.go b/services/s3vectors/vectors.go index 9920f587bc..f304d79f14 100644 --- a/services/s3vectors/vectors.go +++ b/services/s3vectors/vectors.go @@ -1,11 +1,12 @@ package s3vectors import ( - "encoding/json" + "encoding/json/v2" "hash/fnv" "maps" "slices" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -51,7 +52,7 @@ func validateMetadata(ix *Index, meta any) (map[string]any, error) { return nil, err } - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) total += len(k) + len(raw) if ix.filterable(k) { @@ -136,7 +137,7 @@ func (b *InMemoryBackend) putVectors(sc scope, in *putVectorsIn) (any, error) { } func itoa(i int) string { - b, _ := json.Marshal(i) + b, _ := json.Marshal(i, jsonx.V1()) return string(b) } diff --git a/services/sagemaker/ai_benchmark_jobs.go b/services/sagemaker/ai_benchmark_jobs.go index cbbe082e70..81634fc004 100644 --- a/services/sagemaker/ai_benchmark_jobs.go +++ b/services/sagemaker/ai_benchmark_jobs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -49,9 +51,9 @@ type AIBenchmarkJob struct { AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` RoleArn string `json:"RoleArn"` FailureReason string `json:"FailureReason,omitempty"` - BenchmarkTarget json.RawMessage `json:"BenchmarkTarget"` - OutputConfig json.RawMessage `json:"OutputConfig"` - NetworkConfig json.RawMessage `json:"NetworkConfig,omitempty"` + BenchmarkTarget jsontext.Value `json:"BenchmarkTarget"` + OutputConfig jsontext.Value `json:"OutputConfig"` + NetworkConfig jsontext.Value `json:"NetworkConfig,omitempty"` } // MarshalJSON emits CreationTime/StartTime/EndTime as AWS awsjson1.1 @@ -75,7 +77,7 @@ func (j *AIBenchmarkJob) MarshalJSON() ([]byte, error) { StartTime: epochSecondsPtr(j.StartTime), EndTime: epochSecondsPtr(j.EndTime), Tags: toTagObjects(j.Tags), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [AIBenchmarkJob.MarshalJSON], used by @@ -90,7 +92,7 @@ func (j *AIBenchmarkJob) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -104,9 +106,9 @@ func (j *AIBenchmarkJob) UnmarshalJSON(data []byte) error { func cloneAIBenchmarkJob(j *AIBenchmarkJob) *AIBenchmarkJob { cp := *j cp.Tags = maps.Clone(j.Tags) - cp.BenchmarkTarget = append(json.RawMessage(nil), j.BenchmarkTarget...) - cp.OutputConfig = append(json.RawMessage(nil), j.OutputConfig...) - cp.NetworkConfig = append(json.RawMessage(nil), j.NetworkConfig...) + cp.BenchmarkTarget = append(jsontext.Value(nil), j.BenchmarkTarget...) + cp.OutputConfig = append(jsontext.Value(nil), j.OutputConfig...) + cp.NetworkConfig = append(jsontext.Value(nil), j.NetworkConfig...) if j.StartTime != nil { t := *j.StartTime @@ -152,9 +154,9 @@ type CreateAIBenchmarkJobOptions struct { AIBenchmarkJobName string AIWorkloadConfigIdentifier string RoleArn string - BenchmarkTarget json.RawMessage - OutputConfig json.RawMessage - NetworkConfig json.RawMessage + BenchmarkTarget jsontext.Value + OutputConfig jsontext.Value + NetworkConfig jsontext.Value } // CreateAIBenchmarkJob creates an AI benchmark job and schedules its diff --git a/services/sagemaker/ai_recommendation_jobs.go b/services/sagemaker/ai_recommendation_jobs.go index f7dc069dfd..503eff4eec 100644 --- a/services/sagemaker/ai_recommendation_jobs.go +++ b/services/sagemaker/ai_recommendation_jobs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -53,12 +55,12 @@ type AIRecommendationJob struct { AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` RoleArn string `json:"RoleArn"` FailureReason string `json:"FailureReason,omitempty"` - ModelSource json.RawMessage `json:"ModelSource"` - OutputConfig json.RawMessage `json:"OutputConfig"` - PerformanceTarget json.RawMessage `json:"PerformanceTarget,omitempty"` - ComputeSpec json.RawMessage `json:"ComputeSpec,omitempty"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification,omitempty"` - AdapterSource json.RawMessage `json:"AdapterSource,omitempty"` + ModelSource jsontext.Value `json:"ModelSource"` + OutputConfig jsontext.Value `json:"OutputConfig"` + PerformanceTarget jsontext.Value `json:"PerformanceTarget,omitempty"` + ComputeSpec jsontext.Value `json:"ComputeSpec,omitempty"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification,omitempty"` + AdapterSource jsontext.Value `json:"AdapterSource,omitempty"` } // MarshalJSON emits CreationTime/StartTime/EndTime as AWS awsjson1.1 @@ -83,7 +85,7 @@ func (j *AIRecommendationJob) MarshalJSON() ([]byte, error) { StartTime: epochSecondsPtr(j.StartTime), EndTime: epochSecondsPtr(j.EndTime), Tags: toTagObjects(j.Tags), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [AIRecommendationJob.MarshalJSON], used by @@ -98,7 +100,7 @@ func (j *AIRecommendationJob) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -112,12 +114,12 @@ func (j *AIRecommendationJob) UnmarshalJSON(data []byte) error { func cloneAIRecommendationJob(j *AIRecommendationJob) *AIRecommendationJob { cp := *j cp.Tags = maps.Clone(j.Tags) - cp.ModelSource = append(json.RawMessage(nil), j.ModelSource...) - cp.OutputConfig = append(json.RawMessage(nil), j.OutputConfig...) - cp.PerformanceTarget = append(json.RawMessage(nil), j.PerformanceTarget...) - cp.ComputeSpec = append(json.RawMessage(nil), j.ComputeSpec...) - cp.InferenceSpecification = append(json.RawMessage(nil), j.InferenceSpecification...) - cp.AdapterSource = append(json.RawMessage(nil), j.AdapterSource...) + cp.ModelSource = append(jsontext.Value(nil), j.ModelSource...) + cp.OutputConfig = append(jsontext.Value(nil), j.OutputConfig...) + cp.PerformanceTarget = append(jsontext.Value(nil), j.PerformanceTarget...) + cp.ComputeSpec = append(jsontext.Value(nil), j.ComputeSpec...) + cp.InferenceSpecification = append(jsontext.Value(nil), j.InferenceSpecification...) + cp.AdapterSource = append(jsontext.Value(nil), j.AdapterSource...) if j.StartTime != nil { t := *j.StartTime @@ -169,12 +171,12 @@ type CreateAIRecommendationJobOptions struct { AIRecommendationJobName string AIWorkloadConfigIdentifier string RoleArn string - ModelSource json.RawMessage - OutputConfig json.RawMessage - PerformanceTarget json.RawMessage - ComputeSpec json.RawMessage - InferenceSpecification json.RawMessage - AdapterSource json.RawMessage + ModelSource jsontext.Value + OutputConfig jsontext.Value + PerformanceTarget jsontext.Value + ComputeSpec jsontext.Value + InferenceSpecification jsontext.Value + AdapterSource jsontext.Value } // CreateAIRecommendationJob creates an AI recommendation job and schedules diff --git a/services/sagemaker/ai_workload_configs.go b/services/sagemaker/ai_workload_configs.go index 1b03a81c39..44fa4c4c1e 100644 --- a/services/sagemaker/ai_workload_configs.go +++ b/services/sagemaker/ai_workload_configs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -49,8 +51,8 @@ type AIWorkloadConfig struct { Tags map[string]string `json:"Tags,omitempty"` AIWorkloadConfigName string `json:"AIWorkloadConfigName"` AIWorkloadConfigArn string `json:"AIWorkloadConfigArn"` - WorkloadSpec json.RawMessage `json:"AIWorkloadConfigs,omitempty"` - DatasetConfig json.RawMessage `json:"DatasetConfig,omitempty"` + WorkloadSpec jsontext.Value `json:"AIWorkloadConfigs,omitempty"` + DatasetConfig jsontext.Value `json:"DatasetConfig,omitempty"` } // MarshalJSON emits CreationTime as an AWS awsjson1.1 epoch-seconds number @@ -69,7 +71,7 @@ func (c *AIWorkloadConfig) MarshalJSON() ([]byte, error) { alias: (*alias)(c), Tags: toTagObjects(c.Tags), CreationTime: epochSeconds(c.CreationTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [AIWorkloadConfig.MarshalJSON], used by @@ -82,7 +84,7 @@ func (c *AIWorkloadConfig) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(c)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -94,8 +96,8 @@ func (c *AIWorkloadConfig) UnmarshalJSON(data []byte) error { func cloneAIWorkloadConfig(c *AIWorkloadConfig) *AIWorkloadConfig { cp := *c cp.Tags = maps.Clone(c.Tags) - cp.WorkloadSpec = append(json.RawMessage(nil), c.WorkloadSpec...) - cp.DatasetConfig = append(json.RawMessage(nil), c.DatasetConfig...) + cp.WorkloadSpec = append(jsontext.Value(nil), c.WorkloadSpec...) + cp.DatasetConfig = append(jsontext.Value(nil), c.DatasetConfig...) return &cp } @@ -170,8 +172,8 @@ func (b *InMemoryBackend) aiWorkloadConfigARNIndexStoreRO(r string) map[string]s type CreateAIWorkloadConfigOptions struct { Tags map[string]string AIWorkloadConfigName string - WorkloadSpec json.RawMessage - DatasetConfig json.RawMessage + WorkloadSpec jsontext.Value + DatasetConfig jsontext.Value } // CreateAIWorkloadConfig creates an AI workload configuration. diff --git a/services/sagemaker/algorithms.go b/services/sagemaker/algorithms.go index 519f2870c4..9aba6255aa 100644 --- a/services/sagemaker/algorithms.go +++ b/services/sagemaker/algorithms.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -22,9 +22,9 @@ type CreateAlgorithmOptions struct { Tags map[string]string AlgorithmName string AlgorithmDescription string - TrainingSpecification json.RawMessage - InferenceSpecification json.RawMessage - ValidationSpecification json.RawMessage + TrainingSpecification jsontext.Value + InferenceSpecification jsontext.Value + ValidationSpecification jsontext.Value CertifyForMarketplace bool } diff --git a/services/sagemaker/app_image_configs.go b/services/sagemaker/app_image_configs.go index b6cf47d81e..624e139573 100644 --- a/services/sagemaker/app_image_configs.go +++ b/services/sagemaker/app_image_configs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrAppImageConfigNotFound is returned when an app image config does not exist. @@ -32,17 +34,17 @@ type AppImageConfig struct { Tags map[string]string `json:"Tags,omitempty"` AppImageConfigName string `json:"AppImageConfigName"` AppImageConfigArn string `json:"AppImageConfigArn"` - KernelGatewayImageConfig json.RawMessage `json:"KernelGatewayImageConfig,omitempty"` - JupyterLabAppImageConfig json.RawMessage `json:"JupyterLabAppImageConfig,omitempty"` - CodeEditorAppImageConfig json.RawMessage `json:"CodeEditorAppImageConfig,omitempty"` + KernelGatewayImageConfig jsontext.Value `json:"KernelGatewayImageConfig,omitempty"` + JupyterLabAppImageConfig jsontext.Value `json:"JupyterLabAppImageConfig,omitempty"` + CodeEditorAppImageConfig jsontext.Value `json:"CodeEditorAppImageConfig,omitempty"` } func cloneAppImageConfig(a *AppImageConfig) *AppImageConfig { cp := *a cp.Tags = maps.Clone(a.Tags) - cp.KernelGatewayImageConfig = append(json.RawMessage(nil), a.KernelGatewayImageConfig...) - cp.JupyterLabAppImageConfig = append(json.RawMessage(nil), a.JupyterLabAppImageConfig...) - cp.CodeEditorAppImageConfig = append(json.RawMessage(nil), a.CodeEditorAppImageConfig...) + cp.KernelGatewayImageConfig = append(jsontext.Value(nil), a.KernelGatewayImageConfig...) + cp.JupyterLabAppImageConfig = append(jsontext.Value(nil), a.JupyterLabAppImageConfig...) + cp.CodeEditorAppImageConfig = append(jsontext.Value(nil), a.CodeEditorAppImageConfig...) return &cp } @@ -61,7 +63,7 @@ func (a *AppImageConfig) MarshalJSON() ([]byte, error) { alias: (*alias)(a), CreationTime: epochSeconds(a.CreationTime), LastModifiedTime: epochSeconds(a.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [AppImageConfig.MarshalJSON], read by @@ -75,7 +77,7 @@ func (a *AppImageConfig) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(a)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -90,9 +92,9 @@ func (a *AppImageConfig) UnmarshalJSON(data []byte) error { type CreateAppImageConfigOptions struct { AppImageConfigName string Tags map[string]string - KernelGatewayImageConfig json.RawMessage - JupyterLabAppImageConfig json.RawMessage - CodeEditorAppImageConfig json.RawMessage + KernelGatewayImageConfig jsontext.Value + JupyterLabAppImageConfig jsontext.Value + CodeEditorAppImageConfig jsontext.Value } // CreateAppImageConfig creates an app image config. @@ -154,9 +156,9 @@ func (b *InMemoryBackend) DescribeAppImageConfig(ctx context.Context, name strin // an image's kernel/container/filesystem config had every field silently // dropped -- the same "accept and drop" bug class as UpdateTrainingJob. type UpdateAppImageConfigOptions struct { - KernelGatewayImageConfig json.RawMessage - JupyterLabAppImageConfig json.RawMessage - CodeEditorAppImageConfig json.RawMessage + KernelGatewayImageConfig jsontext.Value + JupyterLabAppImageConfig jsontext.Value + CodeEditorAppImageConfig jsontext.Value } // UpdateAppImageConfig updates an app image config's kernel/container diff --git a/services/sagemaker/apps.go b/services/sagemaker/apps.go index 7af757fe6f..434272f753 100644 --- a/services/sagemaker/apps.go +++ b/services/sagemaker/apps.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -50,14 +50,14 @@ type App struct { AppName string `json:"AppName"` AppArn string `json:"AppArn"` Status string `json:"Status"` - ResourceSpec json.RawMessage `json:"ResourceSpec,omitempty"` + ResourceSpec jsontext.Value `json:"ResourceSpec,omitempty"` RecoveryMode bool `json:"RecoveryMode,omitempty"` } func cloneApp(a *App) *App { cp := *a cp.Tags = maps.Clone(a.Tags) - cp.ResourceSpec = append(json.RawMessage(nil), a.ResourceSpec...) + cp.ResourceSpec = append(jsontext.Value(nil), a.ResourceSpec...) return &cp } @@ -65,7 +65,7 @@ func cloneApp(a *App) *App { // CreateAppOptions bundles CreateApp's optional fields. type CreateAppOptions struct { SpaceName string - ResourceSpec json.RawMessage + ResourceSpec jsontext.Value RecoveryMode bool } diff --git a/services/sagemaker/automl.go b/services/sagemaker/automl.go index 069e3b042f..1163878579 100644 --- a/services/sagemaker/automl.go +++ b/services/sagemaker/automl.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -100,17 +102,17 @@ type AutoMLJob struct { AutoMLJobName string `json:"AutoMLJobName"` InputDataConfig []AutoMLChannel `json:"InputDataConfig"` AutoMLJobInputDataConfig []AutoMLJobChannel `json:"AutoMLJobInputDataConfig,omitempty"` - AutoMLProblemTypeConfig json.RawMessage `json:"AutoMLProblemTypeConfig,omitempty"` + AutoMLProblemTypeConfig jsontext.Value `json:"AutoMLProblemTypeConfig,omitempty"` } // AutoMLV1Options holds the V1 CreateAutoMLJob members that only round-trip // through DescribeAutoMLJob; none of them drives a simulated training run. type AutoMLV1Options struct { - ProblemType string `json:"ProblemType,omitempty"` - Mode string `json:"Mode,omitempty"` - CandidateGenerationConfig json.RawMessage `json:"CandidateGenerationConfig,omitempty"` - CompletionCriteria json.RawMessage `json:"CompletionCriteria,omitempty"` - GenerateCandidateDefinitionsOnly bool `json:"GenerateCandidateDefinitionsOnly,omitempty"` + ProblemType string `json:"ProblemType,omitempty"` + Mode string `json:"Mode,omitempty"` + CandidateGenerationConfig jsontext.Value `json:"CandidateGenerationConfig,omitempty"` + CompletionCriteria jsontext.Value `json:"CompletionCriteria,omitempty"` + GenerateCandidateDefinitionsOnly bool `json:"GenerateCandidateDefinitionsOnly,omitempty"` } // SetAutoMLJobV1Options stores the V1-only round-trip members on a created job. @@ -157,13 +159,13 @@ func cloneAutoMLJob(j *AutoMLJob) *AutoMLJob { if j.V1Options != nil { v1 := *j.V1Options - v1.CandidateGenerationConfig = append(json.RawMessage(nil), v1.CandidateGenerationConfig...) - v1.CompletionCriteria = append(json.RawMessage(nil), v1.CompletionCriteria...) + v1.CandidateGenerationConfig = append(jsontext.Value(nil), v1.CandidateGenerationConfig...) + v1.CompletionCriteria = append(jsontext.Value(nil), v1.CompletionCriteria...) cp.V1Options = &v1 } if j.AutoMLProblemTypeConfig != nil { - cp.AutoMLProblemTypeConfig = append(json.RawMessage{}, j.AutoMLProblemTypeConfig...) + cp.AutoMLProblemTypeConfig = append(jsontext.Value{}, j.AutoMLProblemTypeConfig...) } if j.AutoMLComputeConfig != nil { @@ -205,7 +207,7 @@ func (j *AutoMLJob) MarshalJSON() ([]byte, error) { EndTime: epochSecondsPtr(j.EndTime), CreationTime: epochSeconds(j.CreationTime), LastModifiedTime: epochSeconds(j.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [AutoMLJob.MarshalJSON], read by @@ -220,7 +222,7 @@ func (j *AutoMLJob) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/automl_search.go b/services/sagemaker/automl_search.go index 8500ec2765..540c7eedf3 100644 --- a/services/sagemaker/automl_search.go +++ b/services/sagemaker/automl_search.go @@ -2,13 +2,15 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Resource-type / property-name string constants shared by Search, @@ -69,7 +71,7 @@ func (c *AutoMLCandidate) MarshalJSON() ([]byte, error) { alias: (*alias)(c), CreationTime: epochSeconds(c.CreationTime), LastModifiedTime: epochSeconds(c.LastModifiedTime), - }) + }, jsonx.V1()) } // generateAutoMLCandidates deterministically derives a set of candidates for @@ -361,13 +363,13 @@ func matchesSearchFilter(flat map[string]any, f SearchFilter) bool { // []map[string]any via a JSON round trip, so its fields can be addressed by // the JSON dotted path a NestedFilters entry documents. func toObjectList(raw any) ([]map[string]any, bool) { - b, marshalErr := json.Marshal(raw) + b, marshalErr := json.Marshal(raw, jsonx.V1()) if marshalErr != nil { return nil, false } var items []map[string]any - if unmarshalErr := json.Unmarshal(b, &items); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(b, &items, jsonx.V1()); unmarshalErr != nil { return nil, false } diff --git a/services/sagemaker/automl_v2.go b/services/sagemaker/automl_v2.go index a5765d30bf..fb08f0c0ce 100644 --- a/services/sagemaker/automl_v2.go +++ b/services/sagemaker/automl_v2.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AutoMLJobChannel is a named input source for CreateAutoMLJobV2/ @@ -63,13 +66,13 @@ var automlProblemTypeConfigNames = map[string]string{ // automlProblemTypeConfigName derives AutoMLProblemTypeConfigName from the // single member key present in an opaque AutoMLProblemTypeConfig payload. -func automlProblemTypeConfigName(raw json.RawMessage) string { +func automlProblemTypeConfigName(raw jsontext.Value) string { if len(raw) == 0 { return "" } - var members map[string]json.RawMessage - if err := json.Unmarshal(raw, &members); err != nil { + var members map[string]jsontext.Value + if err := json.Unmarshal(raw, &members, jsonx.V1()); err != nil { return "" } @@ -85,7 +88,7 @@ func automlProblemTypeConfigName(raw json.RawMessage) string { // AutoMLJobV2Extras bundles the CreateAutoMLJobV2-only fields set after the // shared CreateAutoMLJob record is created. type AutoMLJobV2Extras struct { - AutoMLProblemTypeConfig json.RawMessage + AutoMLProblemTypeConfig jsontext.Value OutputDataConfig *AutoMLOutputDataConfig AutoMLJobObjective *AutoMLJobObjective AutoMLComputeConfig *AutoMLComputeConfig @@ -113,7 +116,7 @@ func (b *InMemoryBackend) SetAutoMLJobV2Extras(ctx context.Context, name string, j.AutoMLJobInputDataConfig = append([]AutoMLJobChannel(nil), extras.AutoMLJobInputDataConfig...) if extras.AutoMLProblemTypeConfig != nil { - j.AutoMLProblemTypeConfig = append(json.RawMessage(nil), extras.AutoMLProblemTypeConfig...) + j.AutoMLProblemTypeConfig = append(jsontext.Value(nil), extras.AutoMLProblemTypeConfig...) } if extras.OutputDataConfig != nil { diff --git a/services/sagemaker/code_repositories.go b/services/sagemaker/code_repositories.go index 12babd9ec7..8453584687 100644 --- a/services/sagemaker/code_repositories.go +++ b/services/sagemaker/code_repositories.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrCodeRepositoryNotFound is returned when a code repository does not exist. @@ -55,7 +56,7 @@ func (r *CodeRepository) MarshalJSON() ([]byte, error) { alias: (*alias)(r), CreationTime: epochSeconds(r.CreationTime), LastModifiedTime: epochSeconds(r.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [CodeRepository.MarshalJSON], read by @@ -69,7 +70,7 @@ func (r *CodeRepository) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(r)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/compilation_jobs.go b/services/sagemaker/compilation_jobs.go index 9367943c1e..ca56d54625 100644 --- a/services/sagemaker/compilation_jobs.go +++ b/services/sagemaker/compilation_jobs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -87,9 +89,9 @@ type CompilationJob struct { // DescribeCompilationJobOutput (api_op_DescribeCompilationJob.go:67-69) // even though it is legitimately empty for every non-failed job -- the // common case. - FailureReason string `json:"FailureReason"` - ModelPackageVersionArn string `json:"ModelPackageVersionArn,omitempty"` - VpcConfig json.RawMessage `json:"VpcConfig,omitempty"` + FailureReason string `json:"FailureReason"` + ModelPackageVersionArn string `json:"ModelPackageVersionArn,omitempty"` + VpcConfig jsontext.Value `json:"VpcConfig,omitempty"` } func cloneCompilationJob(j *CompilationJob) *CompilationJob { @@ -121,7 +123,7 @@ func cloneCompilationJob(j *CompilationJob) *CompilationJob { cp.ModelArtifacts = &ma } - cp.VpcConfig = append(json.RawMessage(nil), j.VpcConfig...) + cp.VpcConfig = append(jsontext.Value(nil), j.VpcConfig...) if j.CompilationStartTime != nil { t := *j.CompilationStartTime @@ -155,7 +157,7 @@ func (j *CompilationJob) MarshalJSON() ([]byte, error) { LastModifiedTime: epochSeconds(j.LastModifiedTime), CompilationStartTime: epochSecondsPtr(j.CompilationStartTime), CompilationEndTime: epochSecondsPtr(j.CompilationEndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [CompilationJob.MarshalJSON], read by @@ -171,7 +173,7 @@ func (j *CompilationJob) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -431,7 +433,7 @@ func (b *InMemoryBackend) SetCompilationJobExtras( outputConfig *CompilationOutputConfig, stoppingCondition *StoppingCondition, modelPackageVersionArn string, - vpcConfig json.RawMessage, + vpcConfig jsontext.Value, ) error { b.mu.Lock("SetCompilationJobExtras") defer b.mu.Unlock() diff --git a/services/sagemaker/device_fleets.go b/services/sagemaker/device_fleets.go index 1abc1a9e37..cccb94320a 100644 --- a/services/sagemaker/device_fleets.go +++ b/services/sagemaker/device_fleets.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -76,7 +77,7 @@ func (f *DeviceFleet) MarshalJSON() ([]byte, error) { alias: (*alias)(f), CreationTime: epochSeconds(f.CreationTime), LastModifiedTime: epochSeconds(f.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [DeviceFleet.MarshalJSON], read by @@ -90,7 +91,7 @@ func (f *DeviceFleet) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(f)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -379,7 +380,7 @@ func (d *Device) MarshalJSON() ([]byte, error) { alias: (*alias)(d), RegistrationTime: epochSeconds(d.RegistrationTime), LastModifiedTime: epochSeconds(d.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [Device.MarshalJSON], read by @@ -393,7 +394,7 @@ func (d *Device) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(d)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/domains.go b/services/sagemaker/domains.go index 0e56cc0652..38b4360ae5 100644 --- a/services/sagemaker/domains.go +++ b/services/sagemaker/domains.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -43,18 +43,18 @@ type Domain struct { VpcID string `json:"VpcId,omitempty"` TagPropagation string `json:"TagPropagation,omitempty"` SubnetIDs []string `json:"SubnetIds,omitempty"` - DefaultUserSettings json.RawMessage `json:"DefaultUserSettings,omitempty"` - DefaultSpaceSettings json.RawMessage `json:"DefaultSpaceSettings,omitempty"` - DomainSettings json.RawMessage `json:"DomainSettings,omitempty"` + DefaultUserSettings jsontext.Value `json:"DefaultUserSettings,omitempty"` + DefaultSpaceSettings jsontext.Value `json:"DefaultSpaceSettings,omitempty"` + DomainSettings jsontext.Value `json:"DomainSettings,omitempty"` } func cloneDomain(d *Domain) *Domain { cp := *d cp.Tags = maps.Clone(d.Tags) cp.SubnetIDs = append([]string(nil), d.SubnetIDs...) - cp.DefaultUserSettings = append(json.RawMessage(nil), d.DefaultUserSettings...) - cp.DefaultSpaceSettings = append(json.RawMessage(nil), d.DefaultSpaceSettings...) - cp.DomainSettings = append(json.RawMessage(nil), d.DomainSettings...) + cp.DefaultUserSettings = append(jsontext.Value(nil), d.DefaultUserSettings...) + cp.DefaultSpaceSettings = append(jsontext.Value(nil), d.DefaultSpaceSettings...) + cp.DomainSettings = append(jsontext.Value(nil), d.DomainSettings...) return &cp } @@ -72,9 +72,9 @@ type CreateDomainOptions struct { VpcID string TagPropagation string SubnetIDs []string - DefaultUserSettings json.RawMessage - DefaultSpaceSettings json.RawMessage - DomainSettings json.RawMessage + DefaultUserSettings jsontext.Value + DefaultSpaceSettings jsontext.Value + DomainSettings jsontext.Value } // CreateDomain creates a new SageMaker Studio domain. @@ -198,9 +198,9 @@ type UpdateDomainOptions struct { TagPropagation string VpcID string SubnetIDs []string - DefaultUserSettings json.RawMessage - DefaultSpaceSettings json.RawMessage - DomainSettingsForUpdate json.RawMessage + DefaultUserSettings jsontext.Value + DefaultSpaceSettings jsontext.Value + DomainSettingsForUpdate jsontext.Value } // applyUpdateDomainOptions overwrites d's overridable fields with any diff --git a/services/sagemaker/edge_deployment.go b/services/sagemaker/edge_deployment.go index 61441d1d36..d9388eb908 100644 --- a/services/sagemaker/edge_deployment.go +++ b/services/sagemaker/edge_deployment.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -43,20 +43,20 @@ type EdgeDeploymentModelConfig struct { // device selection and deployment configs are stored opaquely (as submitted) // since this emulator does not act on them beyond round-tripping. type EdgeDeploymentStage struct { - StageName string `json:"StageName"` - DeploymentStatus string `json:"DeploymentStatus"` - DeviceSelectionConfig json.RawMessage `json:"DeviceSelectionConfig,omitempty"` - DeploymentConfig json.RawMessage `json:"DeploymentConfig,omitempty"` + StageName string `json:"StageName"` + DeploymentStatus string `json:"DeploymentStatus"` + DeviceSelectionConfig jsontext.Value `json:"DeviceSelectionConfig,omitempty"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig,omitempty"` } func cloneEdgeDeploymentStage(s *EdgeDeploymentStage) *EdgeDeploymentStage { cp := *s if s.DeviceSelectionConfig != nil { - cp.DeviceSelectionConfig = append(json.RawMessage(nil), s.DeviceSelectionConfig...) + cp.DeviceSelectionConfig = append(jsontext.Value(nil), s.DeviceSelectionConfig...) } if s.DeploymentConfig != nil { - cp.DeploymentConfig = append(json.RawMessage(nil), s.DeploymentConfig...) + cp.DeploymentConfig = append(jsontext.Value(nil), s.DeploymentConfig...) } return &cp @@ -96,8 +96,8 @@ func cloneEdgeDeploymentPlan(p *EdgeDeploymentPlan) *EdgeDeploymentPlan { // CreateEdgeDeploymentPlan or CreateEdgeDeploymentStage. type EdgeDeploymentStageInput struct { StageName string - DeviceSelectionConfig json.RawMessage - DeploymentConfig json.RawMessage + DeviceSelectionConfig jsontext.Value + DeploymentConfig jsontext.Value } func buildEdgeDeploymentStages(inputs []EdgeDeploymentStageInput) []*EdgeDeploymentStage { diff --git a/services/sagemaker/endpoint_configs.go b/services/sagemaker/endpoint_configs.go index 1e83328fa2..9fb6ddadb6 100644 --- a/services/sagemaker/endpoint_configs.go +++ b/services/sagemaker/endpoint_configs.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -143,7 +143,7 @@ func (b *InMemoryBackend) SetEndpointConfigExtras( kmsKeyID string, shadowProductionVariants []ProductionVariant, enableNetworkIsolation bool, - explainerConfig, metricsConfig json.RawMessage, + explainerConfig, metricsConfig jsontext.Value, ) error { b.mu.Lock("SetEndpointConfigExtras") defer b.mu.Unlock() @@ -177,11 +177,11 @@ func (b *InMemoryBackend) SetEndpointConfigExtras( ec.EnableNetworkIsolation = enableNetworkIsolation if len(explainerConfig) > 0 { - ec.ExplainerConfig = append(json.RawMessage(nil), explainerConfig...) + ec.ExplainerConfig = append(jsontext.Value(nil), explainerConfig...) } if len(metricsConfig) > 0 { - ec.MetricsConfig = append(json.RawMessage(nil), metricsConfig...) + ec.MetricsConfig = append(jsontext.Value(nil), metricsConfig...) } if len(shadowProductionVariants) > 0 { diff --git a/services/sagemaker/endpoints.go b/services/sagemaker/endpoints.go index 35f6bf0395..1eb2edd2a3 100644 --- a/services/sagemaker/endpoints.go +++ b/services/sagemaker/endpoints.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "slices" @@ -40,7 +40,7 @@ type Endpoint struct { FailureReason string `json:"FailureReason,omitempty"` ProductionVariants []ProductionVariantSummary `json:"ProductionVariants,omitempty"` ShadowProductionVariants []ProductionVariantSummary `json:"ShadowProductionVariants,omitempty"` - DeploymentConfig json.RawMessage `json:"DeploymentConfig,omitempty"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig,omitempty"` } // ProductionVariantStatus describes the current deployment stage of a @@ -172,7 +172,7 @@ type CreateEndpointOptions struct { Tags map[string]string Name string EndpointConfigName string - DeploymentConfig json.RawMessage + DeploymentConfig jsontext.Value } // CreateEndpoint creates a new SageMaker endpoint. @@ -379,7 +379,7 @@ func (b *InMemoryBackend) finishEndpointDelete(region, name string) { // DataCaptureConfig is endpoint-wide here, not per-variant, so that // VariantPropertyType value has no effect to exclude. type UpdateEndpointOptions struct { - DeploymentConfig json.RawMessage + DeploymentConfig jsontext.Value EndpointConfigName string ExcludeRetainedVariantProperties []string RetainAllVariantProperties bool diff --git a/services/sagemaker/engine_async_test.go b/services/sagemaker/engine_async_test.go index c9c950688f..797cf4c414 100644 --- a/services/sagemaker/engine_async_test.go +++ b/services/sagemaker/engine_async_test.go @@ -1,13 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -137,7 +138,7 @@ func TestEngineAsync_ResultsAndNotifications(t *testing.T) { assert.Contains(t, string(data), tt.wantOutValue) var note map[string]any - require.NoError(t, json.Unmarshal([]byte(rig.sns.messages(tt.wantTopic)[0]), ¬e)) + require.NoError(t, json.Unmarshal([]byte(rig.sns.messages(tt.wantTopic)[0]), ¬e, jsonx.V1())) assert.Equal(t, tt.wantStatus, note["invocationStatus"]) assert.Equal(t, tt.req.InferenceID, note["inferenceId"]) assert.Equal(t, "us-east-1", note["awsRegion"]) diff --git a/services/sagemaker/engine_files.go b/services/sagemaker/engine_files.go index 8c1d08278f..0f3527e7fe 100644 --- a/services/sagemaker/engine_files.go +++ b/services/sagemaker/engine_files.go @@ -5,7 +5,8 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,8 @@ import ( "path/filepath" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -254,8 +257,8 @@ func stageManifest(ctx context.Context, store ObjectStore, bucket, key, dir stri return fmt.Errorf("read manifest s3://%s/%s: %w", bucket, key, err) } - var entries []json.RawMessage - if err = json.Unmarshal(raw, &entries); err != nil { + var entries []jsontext.Value + if err = json.Unmarshal(raw, &entries, jsonx.V1()); err != nil { return fmt.Errorf("parse manifest s3://%s/%s: %w", bucket, key, err) } @@ -263,14 +266,14 @@ func stageManifest(ctx context.Context, store ObjectStore, bucket, key, dir stri for i, ent := range entries { var obj map[string]string - if json.Unmarshal(ent, &obj) == nil { + if json.Unmarshal(ent, &obj, jsonx.V1()) == nil { prefix = obj[manifestPrefixK] continue } var name string - if err = json.Unmarshal(ent, &name); err != nil || prefix == "" { + if err = json.Unmarshal(ent, &name, jsonx.V1()); err != nil || prefix == "" { return fmt.Errorf("manifest s3://%s/%s: entry %d: %w", bucket, key, i, errManifestEntry) } @@ -397,7 +400,7 @@ func getS3URI(ctx context.Context, store ObjectStore, uri string) ([]byte, error // writeJSONFile marshals v to dir/name. func writeJSONFile(dir, name string, v any) error { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Errorf("marshal %s: %w", name, err) } diff --git a/services/sagemaker/engine_invoke.go b/services/sagemaker/engine_invoke.go index 71a2f49a3f..c060f98b43 100644 --- a/services/sagemaker/engine_invoke.go +++ b/services/sagemaker/engine_invoke.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -12,6 +12,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxResponseBytes = 25 << 20 @@ -315,7 +316,7 @@ func (b *InMemoryBackend) notifyAsync( msg["eventSource"] = "aws:sagemaker" msg["eventName"] = "InferenceResult" - data, err := json.Marshal(msg) + data, err := json.Marshal(msg, jsonx.V1()) if err != nil { return } diff --git a/services/sagemaker/engine_jobs_test.go b/services/sagemaker/engine_jobs_test.go index 95310d7c70..c0dbec6043 100644 --- a/services/sagemaker/engine_jobs_test.go +++ b/services/sagemaker/engine_jobs_test.go @@ -5,7 +5,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "os" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -215,11 +216,17 @@ func TestEngineTraining_ConfigFilesAndStop(t *testing.T) { cfg := filepath.Join(mountSource(spec, "/opt/ml/input"), "config") var res map[string]any - require.NoError(t, json.Unmarshal([]byte(readFileOrEmpty(filepath.Join(cfg, "resourceconfig.json"))), &res)) + require.NoError( + t, + json.Unmarshal([]byte(readFileOrEmpty(filepath.Join(cfg, "resourceconfig.json"))), &res, jsonx.V1()), + ) assert.Equal(t, "algo-1", res["current_host"]) var chans map[string]map[string]string - require.NoError(t, json.Unmarshal([]byte(readFileOrEmpty(filepath.Join(cfg, "inputdataconfig.json"))), &chans)) + require.NoError( + t, + json.Unmarshal([]byte(readFileOrEmpty(filepath.Join(cfg, "inputdataconfig.json"))), &chans, jsonx.V1()), + ) assert.Equal(t, "text/csv", chans["train"]["ContentType"]) assert.Equal(t, "File", chans["train"]["TrainingInputMode"]) diff --git a/services/sagemaker/engine_training.go b/services/sagemaker/engine_training.go index 1a4572e393..cbeb40ee24 100644 --- a/services/sagemaker/engine_training.go +++ b/services/sagemaker/engine_training.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "os" @@ -11,6 +11,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -94,7 +95,7 @@ func (b *InMemoryBackend) trainingImage(region string, spec AlgorithmSpecificati TrainingImage string `json:"TrainingImage"` } - if err := json.Unmarshal(alg.TrainingSpecification, &ts); err != nil || ts.TrainingImage == "" { + if err := json.Unmarshal(alg.TrainingSpecification, &ts, jsonx.V1()); err != nil || ts.TrainingImage == "" { return "", fmt.Errorf("%w: %s", errAlgorithmNoImage, spec.AlgorithmName) } diff --git a/services/sagemaker/flow_definitions.go b/services/sagemaker/flow_definitions.go index 6db6dcec01..67359b2a6c 100644 --- a/services/sagemaker/flow_definitions.go +++ b/services/sagemaker/flow_definitions.go @@ -2,13 +2,14 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrFlowDefinitionNotFound is returned when a flow definition does not exist. @@ -128,7 +129,7 @@ func (f *FlowDefinition) MarshalJSON() ([]byte, error) { } } - return json.Marshal(aux) + return json.Marshal(aux, jsonx.V1()) } // UnmarshalJSON is the inverse of [FlowDefinition.MarshalJSON], read by @@ -145,7 +146,7 @@ func (f *FlowDefinition) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(f)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/handler.go b/services/sagemaker/handler.go index 267516f8eb..850a15de22 100644 --- a/services/sagemaker/handler.go +++ b/services/sagemaker/handler.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -908,7 +909,7 @@ func writeInternalServerError(c *echo.Context) error { payload, err := json.Marshal(map[string]string{ keyTypeField: "InternalFailure", keyMessageField: "internal server error", - }) + }, jsonx.V1()) if err != nil { return err } @@ -925,15 +926,12 @@ func wireMessage(err error) string { } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrInvalidParameter): payload, _ := json.Marshal(map[string]string{ keyTypeField: errValidationException, keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrResourceNotFound): @@ -945,14 +943,14 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: "ResourceNotFound", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, awserr.ErrNotFound): payload, _ := json.Marshal(map[string]string{ keyTypeField: errValidationException, keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, ErrConflictException): @@ -964,21 +962,21 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: "ConflictException", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, awserr.ErrConflict): payload, _ := json.Marshal(map[string]string{ keyTypeField: "ResourceInUse", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) - case errors.Is(err, errInvalidRequest), errors.As(err, &syntaxErr), errors.As(err, &typeErr): + case errors.Is(err, errInvalidRequest), jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): payload, _ := json.Marshal(map[string]string{ keyTypeField: errValidationException, keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) case errors.Is(err, errUnknownAction): @@ -1072,5 +1070,5 @@ func listResp(key string, items []map[string]any, nextToken string) ([]byte, err resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_ai_benchmark_jobs.go b/services/sagemaker/handler_ai_benchmark_jobs.go index 4f47d79673..088b23c7d1 100644 --- a/services/sagemaker/handler_ai_benchmark_jobs.go +++ b/services/sagemaker/handler_ai_benchmark_jobs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aiBenchmarkJobOpsSupported returns the operations handled by @@ -51,19 +54,19 @@ func (h *Handler) dispatchAIBenchmarkJobOps( // createAIBenchmarkJobInput mirrors CreateAIBenchmarkJobInput // (api_op_CreateAIBenchmarkJob.go:33-73). type createAIBenchmarkJobInput struct { - BenchmarkTarget json.RawMessage `json:"BenchmarkTarget"` - OutputConfig json.RawMessage `json:"OutputConfig"` - NetworkConfig json.RawMessage `json:"NetworkConfig"` - AIBenchmarkJobName string `json:"AIBenchmarkJobName"` - AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` - RoleArn string `json:"RoleArn"` - Tags []tagObject `json:"Tags"` + BenchmarkTarget jsontext.Value `json:"BenchmarkTarget"` + OutputConfig jsontext.Value `json:"OutputConfig"` + NetworkConfig jsontext.Value `json:"NetworkConfig"` + AIBenchmarkJobName string `json:"AIBenchmarkJobName"` + AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` + RoleArn string `json:"RoleArn"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateAIBenchmarkJob(ctx context.Context, body []byte) ([]byte, error) { var req createAIBenchmarkJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -84,7 +87,7 @@ func (h *Handler) handleCreateAIBenchmarkJob(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]string{keyAIBenchmarkJobArn: j.AIBenchmarkJobArn}) + return json.Marshal(map[string]string{keyAIBenchmarkJobArn: j.AIBenchmarkJobArn}, jsonx.V1()) } // describeAIBenchmarkJobInput mirrors DescribeAIBenchmarkJobInput @@ -96,7 +99,7 @@ type describeAIBenchmarkJobInput struct { func (h *Handler) handleDescribeAIBenchmarkJob(ctx context.Context, body []byte) ([]byte, error) { var req describeAIBenchmarkJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -109,7 +112,7 @@ func (h *Handler) handleDescribeAIBenchmarkJob(ctx context.Context, body []byte) return nil, err } - return json.Marshal(j) + return json.Marshal(j, jsonx.V1()) } // deleteAIBenchmarkJobInput mirrors DeleteAIBenchmarkJobInput @@ -121,7 +124,7 @@ type deleteAIBenchmarkJobInput struct { func (h *Handler) handleDeleteAIBenchmarkJob(ctx context.Context, body []byte) ([]byte, error) { var req deleteAIBenchmarkJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -134,7 +137,7 @@ func (h *Handler) handleDeleteAIBenchmarkJob(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]string{keyAIBenchmarkJobArn: jobARN}) + return json.Marshal(map[string]string{keyAIBenchmarkJobArn: jobARN}, jsonx.V1()) } // stopAIBenchmarkJobInput mirrors StopAIBenchmarkJobInput @@ -146,7 +149,7 @@ type stopAIBenchmarkJobInput struct { func (h *Handler) handleStopAIBenchmarkJob(ctx context.Context, body []byte) ([]byte, error) { var req stopAIBenchmarkJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -159,7 +162,7 @@ func (h *Handler) handleStopAIBenchmarkJob(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]string{keyAIBenchmarkJobArn: jobARN}) + return json.Marshal(map[string]string{keyAIBenchmarkJobArn: jobARN}, jsonx.V1()) } // listAIBenchmarkJobsInput mirrors ListAIBenchmarkJobsInput @@ -178,7 +181,7 @@ type listAIBenchmarkJobsInput struct { func (h *Handler) handleListAIBenchmarkJobs(ctx context.Context, body []byte) ([]byte, error) { var req listAIBenchmarkJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_ai_recommendation_jobs.go b/services/sagemaker/handler_ai_recommendation_jobs.go index 6c4114078b..af4b151d5a 100644 --- a/services/sagemaker/handler_ai_recommendation_jobs.go +++ b/services/sagemaker/handler_ai_recommendation_jobs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aiRecommendationJobOpsSupported returns the operations handled by @@ -51,23 +54,23 @@ func (h *Handler) dispatchAIRecommendationJobOps( // createAIRecommendationJobInput mirrors CreateAIRecommendationJobInput // (api_op_CreateAIRecommendationJob.go:30-90). type createAIRecommendationJobInput struct { - ModelSource json.RawMessage `json:"ModelSource"` - OutputConfig json.RawMessage `json:"OutputConfig"` - PerformanceTarget json.RawMessage `json:"PerformanceTarget"` - ComputeSpec json.RawMessage `json:"ComputeSpec"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification"` - AdapterSource json.RawMessage `json:"AdapterSource"` - OptimizeModel *bool `json:"OptimizeModel"` - AIRecommendationJobName string `json:"AIRecommendationJobName"` - AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` - RoleArn string `json:"RoleArn"` - Tags []tagObject `json:"Tags"` + ModelSource jsontext.Value `json:"ModelSource"` + OutputConfig jsontext.Value `json:"OutputConfig"` + PerformanceTarget jsontext.Value `json:"PerformanceTarget"` + ComputeSpec jsontext.Value `json:"ComputeSpec"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification"` + AdapterSource jsontext.Value `json:"AdapterSource"` + OptimizeModel *bool `json:"OptimizeModel"` + AIRecommendationJobName string `json:"AIRecommendationJobName"` + AIWorkloadConfigIdentifier string `json:"AIWorkloadConfigIdentifier"` + RoleArn string `json:"RoleArn"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateAIRecommendationJob(ctx context.Context, body []byte) ([]byte, error) { var req createAIRecommendationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -92,7 +95,7 @@ func (h *Handler) handleCreateAIRecommendationJob(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]string{keyAIRecommendationJobArn: j.AIRecommendationJobArn}) + return json.Marshal(map[string]string{keyAIRecommendationJobArn: j.AIRecommendationJobArn}, jsonx.V1()) } // describeAIRecommendationJobInput mirrors DescribeAIRecommendationJobInput @@ -104,7 +107,7 @@ type describeAIRecommendationJobInput struct { func (h *Handler) handleDescribeAIRecommendationJob(ctx context.Context, body []byte) ([]byte, error) { var req describeAIRecommendationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +120,7 @@ func (h *Handler) handleDescribeAIRecommendationJob(ctx context.Context, body [] return nil, err } - return json.Marshal(j) + return json.Marshal(j, jsonx.V1()) } // deleteAIRecommendationJobInput mirrors DeleteAIRecommendationJobInput @@ -129,7 +132,7 @@ type deleteAIRecommendationJobInput struct { func (h *Handler) handleDeleteAIRecommendationJob(ctx context.Context, body []byte) ([]byte, error) { var req deleteAIRecommendationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -142,7 +145,7 @@ func (h *Handler) handleDeleteAIRecommendationJob(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]string{keyAIRecommendationJobArn: jobARN}) + return json.Marshal(map[string]string{keyAIRecommendationJobArn: jobARN}, jsonx.V1()) } // stopAIRecommendationJobInput mirrors StopAIRecommendationJobInput @@ -154,7 +157,7 @@ type stopAIRecommendationJobInput struct { func (h *Handler) handleStopAIRecommendationJob(ctx context.Context, body []byte) ([]byte, error) { var req stopAIRecommendationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -167,7 +170,7 @@ func (h *Handler) handleStopAIRecommendationJob(ctx context.Context, body []byte return nil, err } - return json.Marshal(map[string]string{keyAIRecommendationJobArn: jobARN}) + return json.Marshal(map[string]string{keyAIRecommendationJobArn: jobARN}, jsonx.V1()) } // listAIRecommendationJobsInput mirrors ListAIRecommendationJobsInput @@ -186,7 +189,7 @@ type listAIRecommendationJobsInput struct { func (h *Handler) handleListAIRecommendationJobs(ctx context.Context, body []byte) ([]byte, error) { var req listAIRecommendationJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_ai_workload_configs.go b/services/sagemaker/handler_ai_workload_configs.go index 17ea80b720..2fa8fe35c1 100644 --- a/services/sagemaker/handler_ai_workload_configs.go +++ b/services/sagemaker/handler_ai_workload_configs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aiWorkloadConfigOpsSupported returns the operations handled by @@ -44,16 +47,16 @@ func (h *Handler) dispatchAIWorkloadConfigOps( } type createAIWorkloadConfigRequest struct { - WorkloadSpec json.RawMessage `json:"AIWorkloadConfigs"` - DatasetConfig json.RawMessage `json:"DatasetConfig"` - AIWorkloadConfigName string `json:"AIWorkloadConfigName"` - Tags []tagObject `json:"Tags"` + WorkloadSpec jsontext.Value `json:"AIWorkloadConfigs"` + DatasetConfig jsontext.Value `json:"DatasetConfig"` + AIWorkloadConfigName string `json:"AIWorkloadConfigName"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateAIWorkloadConfig(ctx context.Context, body []byte) ([]byte, error) { var req createAIWorkloadConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -71,7 +74,7 @@ func (h *Handler) handleCreateAIWorkloadConfig(ctx context.Context, body []byte) return nil, err } - return json.Marshal(map[string]string{keyAIWorkloadConfigArn: c.AIWorkloadConfigArn}) + return json.Marshal(map[string]string{keyAIWorkloadConfigArn: c.AIWorkloadConfigArn}, jsonx.V1()) } type describeAIWorkloadConfigRequest struct { @@ -81,7 +84,7 @@ type describeAIWorkloadConfigRequest struct { func (h *Handler) handleDescribeAIWorkloadConfig(ctx context.Context, body []byte) ([]byte, error) { var req describeAIWorkloadConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -94,7 +97,7 @@ func (h *Handler) handleDescribeAIWorkloadConfig(ctx context.Context, body []byt return nil, err } - return json.Marshal(c) + return json.Marshal(c, jsonx.V1()) } type deleteAIWorkloadConfigRequest struct { @@ -104,7 +107,7 @@ type deleteAIWorkloadConfigRequest struct { func (h *Handler) handleDeleteAIWorkloadConfig(ctx context.Context, body []byte) ([]byte, error) { var req deleteAIWorkloadConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +120,7 @@ func (h *Handler) handleDeleteAIWorkloadConfig(ctx context.Context, body []byte) return nil, err } - return json.Marshal(map[string]string{keyAIWorkloadConfigArn: configARN}) + return json.Marshal(map[string]string{keyAIWorkloadConfigArn: configARN}, jsonx.V1()) } type listAIWorkloadConfigsRequest struct { @@ -133,7 +136,7 @@ type listAIWorkloadConfigsRequest struct { func (h *Handler) handleListAIWorkloadConfigs(ctx context.Context, body []byte) ([]byte, error) { var req listAIWorkloadConfigsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_algorithms.go b/services/sagemaker/handler_algorithms.go index 50a8ea696a..31eb49941a 100644 --- a/services/sagemaker/handler_algorithms.go +++ b/services/sagemaker/handler_algorithms.go @@ -2,26 +2,28 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) // createAlgorithmRequest is the request body for CreateAlgorithm. type createAlgorithmRequest struct { - TrainingSpecification json.RawMessage `json:"TrainingSpecification,omitempty"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification,omitempty"` - ValidationSpecification json.RawMessage `json:"ValidationSpecification,omitempty"` - AlgorithmName string `json:"AlgorithmName"` - AlgorithmDescription string `json:"AlgorithmDescription,omitempty"` - Tags []tagObject `json:"Tags"` - CertifyForMarketplace bool `json:"CertifyForMarketplace,omitempty"` + TrainingSpecification jsontext.Value `json:"TrainingSpecification,omitempty"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification,omitempty"` + ValidationSpecification jsontext.Value `json:"ValidationSpecification,omitempty"` + AlgorithmName string `json:"AlgorithmName"` + AlgorithmDescription string `json:"AlgorithmDescription,omitempty"` + Tags []tagObject `json:"Tags"` + CertifyForMarketplace bool `json:"CertifyForMarketplace,omitempty"` } func (h *Handler) handleCreateAlgorithm(ctx context.Context, body []byte) ([]byte, error) { var req createAlgorithmRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -55,7 +57,7 @@ func (h *Handler) handleCreateAlgorithm(ctx context.Context, body []byte) ([]byt log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created algorithm", "name", al.AlgorithmName) - return json.Marshal(map[string]string{"AlgorithmArn": al.AlgorithmArn}) + return json.Marshal(map[string]string{"AlgorithmArn": al.AlgorithmArn}, jsonx.V1()) } // describeAlgorithmResponse is the response body for DescribeAlgorithm. @@ -71,9 +73,9 @@ type describeAlgorithmResponse struct { AlgorithmDescription string `json:"AlgorithmDescription,omitempty"` ProductID string `json:"ProductId,omitempty"` AlgorithmStatusDetails AlgorithmStatusDetails `json:"AlgorithmStatusDetails"` - TrainingSpecification json.RawMessage `json:"TrainingSpecification"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification,omitempty"` - ValidationSpecification json.RawMessage `json:"ValidationSpecification,omitempty"` + TrainingSpecification jsontext.Value `json:"TrainingSpecification"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification,omitempty"` + ValidationSpecification jsontext.Value `json:"ValidationSpecification,omitempty"` CreationTime float64 `json:"CreationTime"` CertifyForMarketplace bool `json:"CertifyForMarketplace,omitempty"` } @@ -86,7 +88,7 @@ type describeAlgorithmRequest struct { func (h *Handler) handleDescribeAlgorithm(ctx context.Context, body []byte) ([]byte, error) { var req describeAlgorithmRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -111,7 +113,7 @@ func (h *Handler) handleDescribeAlgorithm(ctx context.Context, body []byte) ([]b TrainingSpecification: al.TrainingSpecification, InferenceSpecification: al.InferenceSpecification, ValidationSpecification: al.ValidationSpecification, - }) + }, jsonx.V1()) } // deleteAlgorithmRequest is the request body for DeleteAlgorithm. @@ -122,7 +124,7 @@ type deleteAlgorithmRequest struct { func (h *Handler) handleDeleteAlgorithm(ctx context.Context, body []byte) error { var req deleteAlgorithmRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -136,7 +138,7 @@ func (h *Handler) handleDeleteAlgorithm(ctx context.Context, body []byte) error func (h *Handler) handleListAlgorithms(ctx context.Context, body []byte) ([]byte, error) { var req nameTimeListRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_algorithms_test.go b/services/sagemaker/handler_algorithms_test.go index 1cb68c2ce7..d1a996bc73 100644 --- a/services/sagemaker/handler_algorithms_test.go +++ b/services/sagemaker/handler_algorithms_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -52,7 +53,7 @@ func TestHandler_DescribeAlgorithm(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-algo", resp["AlgorithmName"]) assert.Equal(t, "a description", resp["AlgorithmDescription"]) assert.Equal(t, "Completed", resp["AlgorithmStatus"]) @@ -114,7 +115,7 @@ func TestHandler_ListAlgorithms(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["AlgorithmSummaryList"]) doSageMakerRequest(t, h, "CreateAlgorithm", map[string]any{ @@ -129,7 +130,7 @@ func TestHandler_ListAlgorithms(t *testing.T) { rec = doSageMakerRequest(t, h, "ListAlgorithms", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["AlgorithmSummaryList"].([]any) require.True(t, ok) assert.Len(t, list, 2) @@ -196,7 +197,7 @@ func TestCreateAlgorithm_TagsPresent(t *testing.T) { if tt.wantTags { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arnStr := resp["AlgorithmArn"] require.NotEmpty(t, arnStr) @@ -272,7 +273,7 @@ func TestHandler_CreateAlgorithm(t *testing.T) { if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["AlgorithmArn"], "arn:aws:sagemaker") assert.Contains(t, resp["AlgorithmArn"], "algorithm/") } @@ -303,7 +304,7 @@ func TestHandler_ListAlgorithms_FilterSort(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["AlgorithmSummaryList"].([]any) require.True(t, ok) @@ -357,6 +358,6 @@ func TestHandler_ListAlgorithms_CreationTimeAfterExclusive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["AlgorithmSummaryList"]) } diff --git a/services/sagemaker/handler_app_image_configs.go b/services/sagemaker/handler_app_image_configs.go index 246193557c..9895958987 100644 --- a/services/sagemaker/handler_app_image_configs.go +++ b/services/sagemaker/handler_app_image_configs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -13,17 +16,17 @@ import ( // createAppImageConfigInput mirrors CreateAppImageConfigInput // (api_op_CreateAppImageConfig.go:28-52). type createAppImageConfigInput struct { - AppImageConfigName string `json:"AppImageConfigName"` - KernelGatewayImageConfig json.RawMessage `json:"KernelGatewayImageConfig"` - JupyterLabAppImageConfig json.RawMessage `json:"JupyterLabAppImageConfig"` - CodeEditorAppImageConfig json.RawMessage `json:"CodeEditorAppImageConfig"` - Tags []tagObject `json:"Tags"` + AppImageConfigName string `json:"AppImageConfigName"` + KernelGatewayImageConfig jsontext.Value `json:"KernelGatewayImageConfig"` + JupyterLabAppImageConfig jsontext.Value `json:"JupyterLabAppImageConfig"` + CodeEditorAppImageConfig jsontext.Value `json:"CodeEditorAppImageConfig"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateAppImageConfig(ctx context.Context, body []byte) ([]byte, error) { var req createAppImageConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -42,7 +45,7 @@ func (h *Handler) handleCreateAppImageConfig(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]any{keyAppImageConfigArn: result.AppImageConfigArn}) + return json.Marshal(map[string]any{keyAppImageConfigArn: result.AppImageConfigArn}, jsonx.V1()) } // describeAppImageConfigInput mirrors DescribeAppImageConfigInput @@ -54,7 +57,7 @@ type describeAppImageConfigInput struct { func (h *Handler) handleDescribeAppImageConfig(ctx context.Context, body []byte) ([]byte, error) { var req describeAppImageConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -67,7 +70,7 @@ func (h *Handler) handleDescribeAppImageConfig(ctx context.Context, body []byte) return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteAppImageConfigInput mirrors DeleteAppImageConfigInput @@ -79,7 +82,7 @@ type deleteAppImageConfigInput struct { func (h *Handler) handleDeleteAppImageConfig(ctx context.Context, body []byte) error { var req deleteAppImageConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -93,16 +96,16 @@ func (h *Handler) handleDeleteAppImageConfig(ctx context.Context, body []byte) e // updateAppImageConfigInput mirrors UpdateAppImageConfigInput // (api_op_UpdateAppImageConfig.go:28-45). type updateAppImageConfigInput struct { - AppImageConfigName string `json:"AppImageConfigName"` - KernelGatewayImageConfig json.RawMessage `json:"KernelGatewayImageConfig"` - JupyterLabAppImageConfig json.RawMessage `json:"JupyterLabAppImageConfig"` - CodeEditorAppImageConfig json.RawMessage `json:"CodeEditorAppImageConfig"` + AppImageConfigName string `json:"AppImageConfigName"` + KernelGatewayImageConfig jsontext.Value `json:"KernelGatewayImageConfig"` + JupyterLabAppImageConfig jsontext.Value `json:"JupyterLabAppImageConfig"` + CodeEditorAppImageConfig jsontext.Value `json:"CodeEditorAppImageConfig"` } func (h *Handler) handleUpdateAppImageConfig(ctx context.Context, body []byte) ([]byte, error) { var req updateAppImageConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -119,7 +122,7 @@ func (h *Handler) handleUpdateAppImageConfig(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]any{keyAppImageConfigArn: result.AppImageConfigArn}) + return json.Marshal(map[string]any{keyAppImageConfigArn: result.AppImageConfigArn}, jsonx.V1()) } // listAppImageConfigsInput mirrors ListAppImageConfigsInput @@ -139,7 +142,7 @@ type listAppImageConfigsInput struct { func (h *Handler) handleListAppImageConfigs(ctx context.Context, body []byte) ([]byte, error) { var req listAppImageConfigsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_app_image_configs_test.go b/services/sagemaker/handler_app_image_configs_test.go index 084dd70e97..5289ff9ca8 100644 --- a/services/sagemaker/handler_app_image_configs_test.go +++ b/services/sagemaker/handler_app_image_configs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAppImageConfig(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_CreateAppImageConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["AppImageConfigArn"], "my-config") } @@ -37,7 +39,7 @@ func TestHandler_DescribeAppImageConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "aic-1", resp["AppImageConfigName"]) } @@ -64,7 +66,7 @@ func TestHandler_UpdateAppImageConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["AppImageConfigArn"], "aic-upd") } @@ -81,7 +83,7 @@ func TestHandler_ListAppImageConfigs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["AppImageConfigs"]) doSageMakerRequest(t, h, "CreateAppImageConfig", map[string]any{ @@ -89,7 +91,7 @@ func TestHandler_ListAppImageConfigs(t *testing.T) { }) rec = doSageMakerRequest(t, h, "ListAppImageConfigs", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs := resp["AppImageConfigs"].([]any) assert.Len(t, configs, 1) c := configs[0].(map[string]any) diff --git a/services/sagemaker/handler_apps.go b/services/sagemaker/handler_apps.go index ec378570c0..21c935d782 100644 --- a/services/sagemaker/handler_apps.go +++ b/services/sagemaker/handler_apps.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -16,20 +18,20 @@ import ( // wire-field-audit tooling that only inspects named types can see it — see // gopherstack-oc9v). type createAppInput struct { - DomainID string `json:"DomainId"` - UserProfileName string `json:"UserProfileName"` - SpaceName string `json:"SpaceName"` - AppType string `json:"AppType"` - AppName string `json:"AppName"` - ResourceSpec json.RawMessage `json:"ResourceSpec"` - Tags []tagObject `json:"Tags"` - RecoveryMode bool `json:"RecoveryMode"` + DomainID string `json:"DomainId"` + UserProfileName string `json:"UserProfileName"` + SpaceName string `json:"SpaceName"` + AppType string `json:"AppType"` + AppName string `json:"AppName"` + ResourceSpec jsontext.Value `json:"ResourceSpec"` + Tags []tagObject `json:"Tags"` + RecoveryMode bool `json:"RecoveryMode"` } func (h *Handler) handleCreateApp(ctx context.Context, body []byte) ([]byte, error) { var req createAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -81,7 +83,7 @@ func (h *Handler) handleCreateApp(ctx context.Context, body []byte) ([]byte, err logger.Load(ctx).InfoContext(ctx, "sagemaker: created app", "name", a.AppName) - return json.Marshal(map[string]string{keyAppArn: a.AppArn}) + return json.Marshal(map[string]string{keyAppArn: a.AppArn}, jsonx.V1()) } type describeAppInput struct { @@ -95,7 +97,7 @@ type describeAppInput struct { func (h *Handler) handleDescribeApp(ctx context.Context, body []byte) ([]byte, error) { var req describeAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -138,7 +140,7 @@ func (h *Handler) handleDescribeApp(ctx context.Context, body []byte) ([]byte, e resp["ResourceSpec"] = a.ResourceSpec } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type appSummary struct { @@ -165,7 +167,7 @@ type listAppsInput struct { func (h *Handler) handleListApps(ctx context.Context, body []byte) ([]byte, error) { var req listAppsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +203,7 @@ func (h *Handler) handleListApps(ctx context.Context, body []byte) ([]byte, erro resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type deleteAppInput struct { @@ -215,7 +217,7 @@ type deleteAppInput struct { func (h *Handler) handleDeleteApp(ctx context.Context, body []byte) error { var req deleteAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_apps_test.go b/services/sagemaker/handler_apps_test.go index 5ee8a3f949..234be4e334 100644 --- a/services/sagemaker/handler_apps_test.go +++ b/services/sagemaker/handler_apps_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AppLifecycle(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_AppLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) recUser := doSageMakerRequest(t, h, "CreateUserProfile", map[string]any{ @@ -43,7 +45,7 @@ func TestHandler_AppLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["AppArn"]) // Describe app. @@ -60,7 +62,7 @@ func TestHandler_AppLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["Apps"].([]any), 1) // Delete app. @@ -117,7 +119,7 @@ func TestHandler_CreateApp_SpaceOwned(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) doSageMakerRequest(t, h, "CreateSpace", map[string]any{"DomainId": domainID, "SpaceName": "app-space"}) @@ -142,7 +144,7 @@ func TestHandler_CreateApp_SpaceOwned(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "app-space", descOut["SpaceName"]) assert.Nil(t, descOut["UserProfileName"]) @@ -167,7 +169,7 @@ func TestHandler_ListApps_FiltersAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) doSageMakerRequest(t, h, "CreateUserProfile", map[string]any{"DomainId": domainID, "UserProfileName": "u1"}) @@ -198,7 +200,7 @@ func TestHandler_ListApps_FiltersAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Apps"].([]any), 2) }) @@ -212,7 +214,7 @@ func TestHandler_ListApps_FiltersAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Apps"].([]any), 1, "MaxResults must cap the page, not just be parsed and ignored") assert.NotEmpty(t, out["NextToken"]) }) diff --git a/services/sagemaker/handler_automl.go b/services/sagemaker/handler_automl.go index 9b3537f11d..d4e17f6f61 100644 --- a/services/sagemaker/handler_automl.go +++ b/services/sagemaker/handler_automl.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -16,8 +19,8 @@ type autoMLJobConfigRequest struct { DataSplitConfig *AutoMLDataSplitConfig `json:"DataSplitConfig,omitempty"` SecurityConfig *AutoMLSecurityConfig `json:"SecurityConfig,omitempty"` Mode string `json:"Mode,omitempty"` - CandidateGenerationConfig json.RawMessage `json:"CandidateGenerationConfig,omitempty"` - CompletionCriteria json.RawMessage `json:"CompletionCriteria,omitempty"` + CandidateGenerationConfig jsontext.Value `json:"CandidateGenerationConfig,omitempty"` + CompletionCriteria jsontext.Value `json:"CompletionCriteria,omitempty"` } type createAutoMLJobRequest struct { @@ -37,7 +40,7 @@ type createAutoMLJobRequest struct { func (h *Handler) handleCreateAutoMLJob(ctx context.Context, body []byte) ([]byte, error) { var req createAutoMLJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -97,7 +100,7 @@ func (h *Handler) handleCreateAutoMLJob(ctx context.Context, body []byte) ([]byt return nil, optErr } - return json.Marshal(map[string]any{keyAutoMLJobArn: result.AutoMLJobArn}) + return json.Marshal(map[string]any{keyAutoMLJobArn: result.AutoMLJobArn}, jsonx.V1()) } type describeAutoMLJobRequest struct { @@ -107,7 +110,7 @@ type describeAutoMLJobRequest struct { func (h *Handler) handleDescribeAutoMLJob(ctx context.Context, body []byte) ([]byte, error) { var req describeAutoMLJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -154,7 +157,7 @@ func (h *Handler) handleDescribeAutoMLJob(ctx context.Context, body []byte) ([]b describeAutoMLV1Config(resp, j) - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type stopAutoMLJobRequest struct { @@ -164,7 +167,7 @@ type stopAutoMLJobRequest struct { func (h *Handler) handleStopAutoMLJob(ctx context.Context, body []byte) error { var req stopAutoMLJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -191,7 +194,7 @@ type listAutoMLJobsRequest struct { func (h *Handler) handleListAutoMLJobs(ctx context.Context, body []byte) ([]byte, error) { var req listAutoMLJobsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -228,7 +231,7 @@ func (h *Handler) handleListAutoMLJobs(ctx context.Context, body []byte) ([]byte return json.Marshal(map[string]any{ "AutoMLJobSummaries": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } func describeAutoMLV1Config(resp map[string]any, j *AutoMLJob) { diff --git a/services/sagemaker/handler_automl_search.go b/services/sagemaker/handler_automl_search.go index 89c691b69b..19aa3060c2 100644 --- a/services/sagemaker/handler_automl_search.go +++ b/services/sagemaker/handler_automl_search.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // automlSearchExtOpsSupported returns the real stateful operations @@ -66,7 +68,7 @@ type listCandidatesForAutoMLJobInput struct { func (h *Handler) handleListCandidatesForAutoMLJob(ctx context.Context, body []byte) ([]byte, error) { var req listCandidatesForAutoMLJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -88,7 +90,7 @@ func (h *Handler) handleListCandidatesForAutoMLJob(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]any{"Candidates": candidates, keyNextToken: next}) + return json.Marshal(map[string]any{"Candidates": candidates, keyNextToken: next}, jsonx.V1()) } // searchInput mirrors SearchInput (api_op_Search.go:27-63). VisibilityConditions @@ -108,7 +110,7 @@ type searchInput struct { func (h *Handler) handleSearch(ctx context.Context, body []byte) ([]byte, error) { var req searchInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -133,7 +135,7 @@ func (h *Handler) handleSearch(ctx context.Context, body []byte) ([]byte, error) "Results": results, "TotalHits": map[string]any{"Value": total, "Relation": "EqualTo"}, keyNextToken: next, - }) + }, jsonx.V1()) } // listModelMetadataInput mirrors ListModelMetadataInput @@ -149,7 +151,7 @@ type listModelMetadataInput struct { func (h *Handler) handleListModelMetadata(body []byte) ([]byte, error) { var req listModelMetadataInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -166,7 +168,7 @@ func (h *Handler) handleListModelMetadata(body []byte) ([]byte, error) { }) } - return json.Marshal(map[string]any{"ModelMetadataSummaries": summaries, keyNextToken: next}) + return json.Marshal(map[string]any{"ModelMetadataSummaries": summaries, keyNextToken: next}, jsonx.V1()) } // getSearchSuggestionsInput mirrors GetSearchSuggestionsInput @@ -183,7 +185,7 @@ type getSearchSuggestionsInput struct { func (h *Handler) handleGetSearchSuggestions(_ context.Context, body []byte) ([]byte, error) { var req getSearchSuggestionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +203,7 @@ func (h *Handler) handleGetSearchSuggestions(_ context.Context, body []byte) ([] suggestions = append(suggestions, map[string]string{"PropertyName": n}) } - return json.Marshal(map[string]any{"PropertyNameSuggestions": suggestions}) + return json.Marshal(map[string]any{"PropertyNameSuggestions": suggestions}, jsonx.V1()) } // getScalingConfigurationRecommendationInput mirrors @@ -220,7 +222,7 @@ type getScalingConfigurationRecommendationInput struct { func (h *Handler) handleGetScalingConfigurationRecommendation(ctx context.Context, body []byte) ([]byte, error) { var req getScalingConfigurationRecommendationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -256,5 +258,5 @@ func (h *Handler) handleGetScalingConfigurationRecommendation(ctx context.Contex resp["ScalingPolicyObjective"] = req.ScalingPolicyObjective } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_automl_search_test.go b/services/sagemaker/handler_automl_search_test.go index 585954efb8..41489b6aa0 100644 --- a/services/sagemaker/handler_automl_search_test.go +++ b/services/sagemaker/handler_automl_search_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListCandidatesForAutoMLJob(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_ListCandidatesForAutoMLJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) candidates, ok := resp["Candidates"].([]any) require.True(t, ok) assert.Len(t, candidates, 3) @@ -76,7 +78,7 @@ func TestHandler_Search_TrainingJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["Results"].([]any) require.True(t, ok) require.Len(t, results, 1) @@ -98,7 +100,7 @@ func TestHandler_Search_TrainingJob(t *testing.T) { }) var noMatchResp map[string]any - require.NoError(t, json.Unmarshal(noMatchRec.Body.Bytes(), &noMatchResp)) + require.NoError(t, json.Unmarshal(noMatchRec.Body.Bytes(), &noMatchResp, jsonx.V1())) assert.Empty(t, noMatchResp["Results"]) } @@ -122,7 +124,7 @@ func TestHandler_ListModelMetadata(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["ModelMetadataSummaries"].([]any) require.True(t, ok) assert.NotEmpty(t, summaries) @@ -134,7 +136,7 @@ func TestHandler_ListModelMetadata(t *testing.T) { }) var filteredResp map[string]any - require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp)) + require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp, jsonx.V1())) filtered, ok := filteredResp["ModelMetadataSummaries"].([]any) require.True(t, ok) require.Len(t, filtered, 1) @@ -157,7 +159,7 @@ func TestHandler_GetSearchSuggestions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) suggestions, ok := resp["PropertyNameSuggestions"].([]any) require.True(t, ok) require.Len(t, suggestions, 1) @@ -185,7 +187,7 @@ func TestHandler_GetScalingConfigurationRecommendation(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InEpsilon(t, float64(60), resp["TargetCpuUtilizationPerCore"], 0.001) dyn, ok := resp["DynamicScalingConfiguration"].(map[string]any) require.True(t, ok) @@ -220,7 +222,7 @@ func TestHandler_ListCandidatesForAutoMLJob_SortByStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) candidates := resp["Candidates"].([]any) require.Len(t, candidates, 3) diff --git a/services/sagemaker/handler_automl_test.go b/services/sagemaker/handler_automl_test.go index a843e27cfc..2b0c5fb9fb 100644 --- a/services/sagemaker/handler_automl_test.go +++ b/services/sagemaker/handler_automl_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // autoMLJobRequestBody returns a minimal-but-complete CreateAutoMLJob request @@ -46,7 +48,7 @@ func TestHandler_CreateAutoMLJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["AutoMLJobArn"], "my-job") } @@ -106,7 +108,7 @@ func TestHandler_CreateAutoMLJob_InputDataConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) channels, ok := descResp["InputDataConfig"].([]any) require.True(t, ok, "DescribeAutoMLJob must always emit InputDataConfig (required field)") @@ -134,7 +136,7 @@ func TestHandler_DescribeAutoMLJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "job-1", resp["AutoMLJobName"]) assert.Equal(t, "InProgress", resp["AutoMLJobStatus"]) } @@ -154,7 +156,7 @@ func TestHandler_DescribeAutoMLJob_ModelDeployConfigRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deployConfig, ok := resp["ModelDeployConfig"].(map[string]any) require.True(t, ok, "DescribeAutoMLJob must return ModelDeployConfig when set") @@ -221,7 +223,7 @@ func TestHandler_StopAutoMLJob(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeAutoMLJob", map[string]any{"AutoMLJobName": "job-stop"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Stopping", resp["AutoMLJobStatus"]) } @@ -237,7 +239,7 @@ func TestHandler_ListAutoMLJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["AutoMLJobSummaries"].([]any) assert.Len(t, items, 2) } @@ -257,7 +259,7 @@ func TestHandler_ListAutoMLJobs_FilterSort(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["AutoMLJobSummaries"].([]any) require.Len(t, items, 1) assert.Equal(t, "job-alpha", items[0].(map[string]any)["AutoMLJobName"]) @@ -267,7 +269,7 @@ func TestHandler_ListAutoMLJobs_FilterSort(t *testing.T) { "SortOrder": "Descending", }) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items = resp["AutoMLJobSummaries"].([]any) require.Len(t, items, 2) assert.Equal(t, "job-beta", items[0].(map[string]any)["AutoMLJobName"]) @@ -308,7 +310,7 @@ func TestAutoMLJob_OutputDataConfigRoundtrip(t *testing.T) { MetricName string `json:"MetricName"` } `json:"AutoMLJobObjective"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.OutputDataConfig, "OutputDataConfig must be returned by DescribeAutoMLJob") assert.Equal(t, "s3://my-bucket/automl-output/", out.OutputDataConfig.S3OutputPath) @@ -334,7 +336,7 @@ func TestAutoMLJob_InitialStatus_InProgress(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InProgress", resp["AutoMLJobStatus"]) } diff --git a/services/sagemaker/handler_automl_v2.go b/services/sagemaker/handler_automl_v2.go index a34aa13582..d821e63324 100644 --- a/services/sagemaker/handler_automl_v2.go +++ b/services/sagemaker/handler_automl_v2.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -23,7 +26,7 @@ import ( // enforced. type createAutoMLJobV2Input struct { Tags []tagObject `json:"Tags"` - AutoMLProblemTypeConfig json.RawMessage `json:"AutoMLProblemTypeConfig"` + AutoMLProblemTypeConfig jsontext.Value `json:"AutoMLProblemTypeConfig"` OutputDataConfig *AutoMLOutputDataConfig `json:"OutputDataConfig"` AutoMLJobObjective *AutoMLJobObjective `json:"AutoMLJobObjective"` AutoMLComputeConfig *AutoMLComputeConfig `json:"AutoMLComputeConfig"` @@ -38,7 +41,7 @@ type createAutoMLJobV2Input struct { func (h *Handler) handleCreateAutoMLJobV2(ctx context.Context, body []byte) ([]byte, error) { var req createAutoMLJobV2Input - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -85,7 +88,7 @@ func (h *Handler) handleCreateAutoMLJobV2(ctx context.Context, body []byte) ([]b return nil, extErr } - return json.Marshal(map[string]any{keyAutoMLJobArn: result.AutoMLJobArn}) + return json.Marshal(map[string]any{keyAutoMLJobArn: result.AutoMLJobArn}, jsonx.V1()) } // describeAutoMLJobV2Input mirrors DescribeAutoMLJobV2Input @@ -98,7 +101,7 @@ type describeAutoMLJobV2Input struct { func (h *Handler) handleDescribeAutoMLJobV2(ctx context.Context, body []byte) ([]byte, error) { var req describeAutoMLJobV2Input - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -163,5 +166,5 @@ func (h *Handler) handleDescribeAutoMLJobV2(ctx context.Context, body []byte) ([ resp["ModelDeployConfig"] = j.ModelDeployConfig } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_automl_v2_test.go b/services/sagemaker/handler_automl_v2_test.go index d99d7d6a04..5a18c11dcb 100644 --- a/services/sagemaker/handler_automl_v2_test.go +++ b/services/sagemaker/handler_automl_v2_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAutoMLJobV2_RoundTrip(t *testing.T) { @@ -61,7 +63,7 @@ func TestHandler_CreateAutoMLJobV2_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) channels, ok := out["AutoMLJobInputDataConfig"].([]any) require.True(t, ok, "DescribeAutoMLJobV2 must always emit AutoMLJobInputDataConfig") @@ -170,7 +172,7 @@ func TestHandler_DescribeAutoMLJobV1_OmitsV2Fields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) _, hasV2Field := out["AutoMLJobInputDataConfig"] assert.False(t, hasV2Field, "DescribeAutoMLJob (V1) must not emit the V2-only AutoMLJobInputDataConfig field") diff --git a/services/sagemaker/handler_cluster.go b/services/sagemaker/handler_cluster.go index aa6bad0f67..4effff5279 100644 --- a/services/sagemaker/handler_cluster.go +++ b/services/sagemaker/handler_cluster.go @@ -2,10 +2,12 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -109,7 +111,7 @@ type startClusterHealthCheckInput struct { func (h *Handler) handleStartClusterHealthCheck(ctx context.Context, body []byte) ([]byte, error) { var req startClusterHealthCheckInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -126,7 +128,7 @@ func (h *Handler) handleStartClusterHealthCheck(ctx context.Context, body []byte return nil, err } - return json.Marshal(map[string]string{keyClusterArn: clusterARN}) + return json.Marshal(map[string]string{keyClusterArn: clusterARN}, jsonx.V1()) } // clusterInstanceGroupRequest is the wire shape for a @@ -310,7 +312,7 @@ type createClusterRequest struct { func (h *Handler) handleCreateCluster(ctx context.Context, body []byte) ([]byte, error) { var req createClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -338,7 +340,7 @@ func (h *Handler) handleCreateCluster(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: created cluster", "name", c.ClusterName) - return json.Marshal(map[string]string{keyClusterArn: c.ClusterArn}) + return json.Marshal(map[string]string{keyClusterArn: c.ClusterArn}, jsonx.V1()) } // clusterAutoScalingStatusInService is the (only) status this emulator @@ -396,7 +398,7 @@ func (h *Handler) describeClusterResponse(c *Cluster) []byte { resp["RestrictedInstanceGroupsConfig"] = rc } - b, _ := json.Marshal(resp) + b, _ := json.Marshal(resp, jsonx.V1()) return b } @@ -410,7 +412,7 @@ type describeClusterInput struct { func (h *Handler) handleDescribeCluster(ctx context.Context, body []byte) ([]byte, error) { var req describeClusterInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -451,7 +453,7 @@ type listClustersInput struct { func (h *Handler) handleListClusters(ctx context.Context, body []byte) ([]byte, error) { var req listClustersInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -480,7 +482,7 @@ func (h *Handler) handleListClusters(ctx context.Context, body []byte) ([]byte, resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteClusterInput is DeleteCluster's request shape @@ -492,7 +494,7 @@ type deleteClusterInput struct { func (h *Handler) handleDeleteCluster(ctx context.Context, body []byte) ([]byte, error) { var req deleteClusterInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -507,7 +509,7 @@ func (h *Handler) handleDeleteCluster(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted cluster", "name", req.ClusterName) - return json.Marshal(map[string]string{keyClusterArn: clusterArn}) + return json.Marshal(map[string]string{keyClusterArn: clusterArn}, jsonx.V1()) } // updateClusterRequest is the request body for UpdateCluster. @@ -527,7 +529,7 @@ type updateClusterRequest struct { func (h *Handler) handleUpdateCluster(ctx context.Context, body []byte) ([]byte, error) { var req updateClusterRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -554,7 +556,7 @@ func (h *Handler) handleUpdateCluster(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: updated cluster", "name", c.ClusterName) - return json.Marshal(map[string]string{keyClusterArn: c.ClusterArn}) + return json.Marshal(map[string]string{keyClusterArn: c.ClusterArn}, jsonx.V1()) } // updateClusterSoftwareInstanceGroupRequest is the wire shape for one entry @@ -569,7 +571,7 @@ type updateClusterSoftwareInstanceGroupRequest struct { // updateClusterSoftwareInput mirrors api_op_UpdateClusterSoftware.go:28-63; // DeploymentConfig/ImageId are decoded but have no state to act on. type updateClusterSoftwareInput struct { - DeploymentConfig json.RawMessage `json:"DeploymentConfig"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig"` ClusterName string `json:"ClusterName"` ImageID string `json:"ImageId"` InstanceGroups []updateClusterSoftwareInstanceGroupRequest `json:"InstanceGroups"` @@ -578,7 +580,7 @@ type updateClusterSoftwareInput struct { func (h *Handler) handleUpdateClusterSoftware(ctx context.Context, body []byte) ([]byte, error) { var req updateClusterSoftwareInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -599,7 +601,7 @@ func (h *Handler) handleUpdateClusterSoftware(ctx context.Context, body []byte) logger.Load(ctx). InfoContext(ctx, "sagemaker: updated cluster software", "name", req.ClusterName) - return json.Marshal(map[string]string{keyClusterArn: clusterArn}) + return json.Marshal(map[string]string{keyClusterArn: clusterArn}, jsonx.V1()) } // clusterInstanceStatusDetails mirrors the AWS ClusterInstanceStatusDetails shape. @@ -661,7 +663,7 @@ type describeClusterNodeInput struct { func (h *Handler) handleDescribeClusterNode(ctx context.Context, body []byte) ([]byte, error) { var req describeClusterNodeInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -678,7 +680,7 @@ func (h *Handler) handleDescribeClusterNode(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(map[string]any{"NodeDetails": toClusterNodeDetails(n)}) + return json.Marshal(map[string]any{"NodeDetails": toClusterNodeDetails(n)}, jsonx.V1()) } // clusterNodeSummary is the wire shape for a ListClusterNodes entry @@ -720,7 +722,7 @@ type listClusterNodesInput struct { func (h *Handler) handleListClusterNodes(ctx context.Context, body []byte) ([]byte, error) { var req listClusterNodesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -760,7 +762,7 @@ func (h *Handler) handleListClusterNodes(ctx context.Context, body []byte) ([]by resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // describeClusterEventInput is DescribeClusterEvent's request shape @@ -773,7 +775,7 @@ type describeClusterEventInput struct { func (h *Handler) handleDescribeClusterEvent(ctx context.Context, body []byte) ([]byte, error) { var req describeClusterEventInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -791,7 +793,7 @@ func (h *Handler) handleDescribeClusterEvent(ctx context.Context, body []byte) ( // Unreachable in practice: DescribeClusterEvent always errors above because // this emulator never generates cluster events. - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // listClusterEventsInput is ListClusterEvents' request shape @@ -816,7 +818,7 @@ type listClusterEventsInput struct { func (h *Handler) handleListClusterEvents(ctx context.Context, body []byte) ([]byte, error) { var req listClusterEventsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -828,7 +830,7 @@ func (h *Handler) handleListClusterEvents(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{"Events": []any{}}) + return json.Marshal(map[string]any{"Events": []any{}}, jsonx.V1()) } // detachClusterNodeVolumeRequest is the request body for DetachClusterNodeVolume. @@ -840,7 +842,7 @@ type detachClusterNodeVolumeRequest struct { func (h *Handler) handleDetachClusterNodeVolume(ctx context.Context, body []byte) ([]byte, error) { var req detachClusterNodeVolumeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -861,7 +863,7 @@ func (h *Handler) handleDetachClusterNodeVolume(ctx context.Context, body []byte "DeviceName": dv.DeviceName, keyStatus: dv.Status, "AttachTime": epochSeconds(dv.AttachTime), - }) + }, jsonx.V1()) } // attachClusterNodeVolumeRequest is the request body for @@ -882,7 +884,7 @@ type attachClusterNodeNetworkInterfaceRequest struct { func (h *Handler) handleAttachClusterNodeNetworkInterface(ctx context.Context, body []byte) ([]byte, error) { var req attachClusterNodeNetworkInterfaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -904,12 +906,12 @@ func (h *Handler) handleAttachClusterNodeNetworkInterface(ctx context.Context, b keyNodeID: out.NodeID, "NetworkInterfaceId": out.NetworkInterfaceID, "AttachmentId": out.AttachmentID, - }) + }, jsonx.V1()) } func (h *Handler) handleAttachClusterNodeVolume(ctx context.Context, body []byte) ([]byte, error) { var req attachClusterNodeVolumeRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -942,7 +944,7 @@ func (h *Handler) handleAttachClusterNodeVolume(ctx context.Context, body []byte "DeviceName": av.DeviceName, keyStatus: av.Status, "AttachTime": epochSeconds(av.AttachTime), - }) + }, jsonx.V1()) } // batchAddClusterNodesError mirrors types.BatchAddClusterNodesError @@ -1058,7 +1060,7 @@ type batchAddClusterNodesRequest struct { func (h *Handler) handleBatchAddClusterNodes(ctx context.Context, body []byte) ([]byte, error) { var req batchAddClusterNodesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1104,7 +1106,7 @@ func (h *Handler) handleBatchAddClusterNodes(ctx context.Context, body []byte) ( return json.Marshal(map[string]any{ keyFailed: failedResults, statusSuccessful: successResults, - }) + }, jsonx.V1()) } // batchNodeIDsRequest is the request body shared by BatchDeleteClusterNodes, @@ -1213,7 +1215,7 @@ func (h *Handler) handleBatchNodeIDsOp( buildFailedLogical func(nodeLogicalID string) any, ) ([]byte, error) { var req batchNodeIDsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1246,7 +1248,7 @@ func (h *Handler) handleBatchNodeIDsOp( resp["SuccessfulNodeLogicalIds"] = successfulLogicalResults } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleBatchDeleteClusterNodes(ctx context.Context, body []byte) ([]byte, error) { diff --git a/services/sagemaker/handler_cluster_test.go b/services/sagemaker/handler_cluster_test.go index 899c52fb9a..b930244ed8 100644 --- a/services/sagemaker/handler_cluster_test.go +++ b/services/sagemaker/handler_cluster_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -38,7 +39,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) clusterArn := createResp["ClusterArn"] assert.Contains(t, clusterArn, "arn:aws:sagemaker") assert.Contains(t, clusterArn, "cluster/my-cluster") @@ -48,7 +49,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-cluster", descResp["ClusterName"]) assert.Equal(t, "InService", descResp["ClusterStatus"]) assert.Equal(t, "Automatic", descResp["NodeRecovery"]) @@ -70,7 +71,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["ClusterSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -80,7 +81,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var nodesResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodesResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodesResp, jsonx.V1())) nodeSummaries, ok := nodesResp["ClusterNodeSummaries"].([]any) require.True(t, ok) require.Len(t, nodeSummaries, 2) @@ -102,7 +103,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var nodeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodeResp, jsonx.V1())) nodeDetails, ok := nodeResp["NodeDetails"].(map[string]any) require.True(t, ok) assert.Equal(t, nodeID, nodeDetails["InstanceId"]) @@ -121,7 +122,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeCluster", map[string]any{"ClusterName": "my-cluster"}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "None", descResp["NodeRecovery"]) groups, ok = descResp["InstanceGroups"].([]any) require.True(t, ok) @@ -134,7 +135,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var softwareResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &softwareResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &softwareResp, jsonx.V1())) assert.Equal(t, clusterArn, softwareResp["ClusterArn"]) // ListClusterEvents / DescribeClusterEvent: correct empty shape, no events ever exist. @@ -142,7 +143,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var eventsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &eventsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &eventsResp, jsonx.V1())) events, ok := eventsResp["Events"].([]any) require.True(t, ok) assert.Empty(t, events) @@ -162,7 +163,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var attachResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &attachResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &attachResp, jsonx.V1())) assert.Equal(t, clusterArn, attachResp["ClusterArn"]) assert.Equal(t, nodeID, attachResp["NodeId"]) assert.Equal(t, "vol-123", attachResp["VolumeId"]) @@ -178,7 +179,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var detachResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detachResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &detachResp, jsonx.V1())) assert.Equal(t, clusterArn, detachResp["ClusterArn"]) assert.Equal(t, nodeID, detachResp["NodeId"]) assert.Equal(t, "vol-123", detachResp["VolumeId"]) @@ -198,7 +199,7 @@ func TestHandler_ClusterLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp, jsonx.V1())) assert.Equal(t, clusterArn, deleteResp["ClusterArn"]) // Verify deleted. @@ -225,7 +226,7 @@ func TestHandler_CreateCluster_ClusterRoleAndVpcConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "arn:aws:iam::000000000000:role/HyperPodClusterRole", descResp["ClusterRole"]) vpcConfig, ok := descResp["VpcConfig"].(map[string]any) @@ -309,7 +310,7 @@ func TestHandler_UpdateCluster_DeleteInstanceGroup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["InstanceGroups"].([]any) require.True(t, ok) assert.Len(t, groups, 1) @@ -318,7 +319,7 @@ func TestHandler_UpdateCluster_DeleteInstanceGroup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var nodesResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodesResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &nodesResp, jsonx.V1())) nodes, ok := nodesResp["ClusterNodeSummaries"].([]any) require.True(t, ok) assert.Len(t, nodes, 2) // only group-a's 2 nodes remain @@ -427,7 +428,7 @@ func TestHandler_ListClusters_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["ClusterSummaries"].([]any) require.True(t, ok) @@ -463,7 +464,7 @@ func TestHandler_ListClusters_NameContains(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["ClusterSummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 1) @@ -672,7 +673,7 @@ func TestHandler_AttachClusterNodeVolume(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ClusterArn"], "arn:aws:sagemaker") assert.Equal(t, "node-1", resp["NodeId"]) assert.Equal(t, "vol-1", resp["VolumeId"]) @@ -761,7 +762,7 @@ func TestHandler_BatchAddClusterNodes(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "ClusterArn") assert.IsType(t, []any{}, resp["Failed"]) assert.IsType(t, []any{}, resp["Successful"]) @@ -844,7 +845,7 @@ func TestHandler_BatchDeleteClusterNodes(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "ClusterArn") assert.Contains(t, resp, "Failed") assert.Contains(t, resp, "Successful") @@ -924,7 +925,7 @@ func TestHandler_BatchRebootClusterNodes(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "ClusterArn") assert.Contains(t, resp, "Failed") assert.Contains(t, resp, "Successful") @@ -1004,7 +1005,7 @@ func TestHandler_BatchReplaceClusterNodes(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "ClusterArn") assert.Contains(t, resp, "Failed") assert.Contains(t, resp, "Successful") @@ -1154,7 +1155,7 @@ func TestHandler_CreateCluster_OrchestratorValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) }) } @@ -1433,7 +1434,7 @@ func TestHandler_CreateCluster_InstanceStorageConfigUnion_Validation(t *testing. require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) }) } @@ -1489,7 +1490,7 @@ func TestHandler_CreateCluster_RestrictedInstanceGroupsConfig_Validation(t *test require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) }) } @@ -1548,7 +1549,7 @@ func TestHandler_StartClusterHealthCheck(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ClusterArn"], "hc-cluster") } }) diff --git a/services/sagemaker/handler_code_repositories.go b/services/sagemaker/handler_code_repositories.go index cafe8f86e3..8e756a614f 100644 --- a/services/sagemaker/handler_code_repositories.go +++ b/services/sagemaker/handler_code_repositories.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -21,7 +23,7 @@ type createCodeRepositoryInput struct { func (h *Handler) handleCreateCodeRepository(ctx context.Context, body []byte) ([]byte, error) { var req createCodeRepositoryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -34,7 +36,7 @@ func (h *Handler) handleCreateCodeRepository(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]any{keyCodeRepositoryArn: result.CodeRepositoryArn}) + return json.Marshal(map[string]any{keyCodeRepositoryArn: result.CodeRepositoryArn}, jsonx.V1()) } // describeCodeRepositoryInput mirrors DescribeCodeRepositoryInput @@ -46,7 +48,7 @@ type describeCodeRepositoryInput struct { func (h *Handler) handleDescribeCodeRepository(ctx context.Context, body []byte) ([]byte, error) { var req describeCodeRepositoryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -59,7 +61,7 @@ func (h *Handler) handleDescribeCodeRepository(ctx context.Context, body []byte) return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // updateCodeRepositoryInput mirrors UpdateCodeRepositoryInput @@ -76,7 +78,7 @@ type updateCodeRepositoryInput struct { func (h *Handler) handleUpdateCodeRepository(ctx context.Context, body []byte) ([]byte, error) { var req updateCodeRepositoryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -89,7 +91,7 @@ func (h *Handler) handleUpdateCodeRepository(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]any{keyCodeRepositoryArn: result.CodeRepositoryArn}) + return json.Marshal(map[string]any{keyCodeRepositoryArn: result.CodeRepositoryArn}, jsonx.V1()) } // deleteCodeRepositoryInput mirrors DeleteCodeRepositoryInput @@ -101,7 +103,7 @@ type deleteCodeRepositoryInput struct { func (h *Handler) handleDeleteCodeRepository(ctx context.Context, body []byte) error { var req deleteCodeRepositoryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -129,7 +131,7 @@ type listCodeRepositoriesInput struct { func (h *Handler) handleListCodeRepositories(ctx context.Context, body []byte) ([]byte, error) { var req listCodeRepositoriesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -162,5 +164,5 @@ func (h *Handler) handleListCodeRepositories(ctx context.Context, body []byte) ( return json.Marshal(map[string]any{ "CodeRepositorySummaryList": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } diff --git a/services/sagemaker/handler_code_repositories_test.go b/services/sagemaker/handler_code_repositories_test.go index d4d5e93c17..b56247354a 100644 --- a/services/sagemaker/handler_code_repositories_test.go +++ b/services/sagemaker/handler_code_repositories_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateCodeRepository(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_CreateCodeRepository(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["CodeRepositoryArn"], "my-repo") } @@ -73,7 +75,7 @@ func TestHandler_DescribeCodeRepository(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "repo-1", resp["CodeRepositoryName"]) // The awsjson1.1 protocol encodes timestamps as epoch-seconds numbers, not @@ -108,12 +110,12 @@ func TestHandler_UpdateCodeRepository(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["CodeRepositoryArn"], "repo-upd") descRec := doSageMakerRequest(t, h, "DescribeCodeRepository", map[string]any{"CodeRepositoryName": "repo-upd"}) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) gitConfig, ok := descResp["GitConfig"].(map[string]any) require.True(t, ok, "GitConfig must be present") assert.Equal(t, "https://github.com/test/repo", gitConfig["RepositoryUrl"], @@ -155,7 +157,7 @@ func TestHandler_ListCodeRepositories(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["CodeRepositorySummaryList"].([]any) assert.Len(t, items, 2) } diff --git a/services/sagemaker/handler_compilation_jobs.go b/services/sagemaker/handler_compilation_jobs.go index 3bd98e551f..2a79925690 100644 --- a/services/sagemaker/handler_compilation_jobs.go +++ b/services/sagemaker/handler_compilation_jobs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -19,14 +22,14 @@ type createCompilationJobInput struct { CompilationJobName string `json:"CompilationJobName"` RoleArn string `json:"RoleArn"` ModelPackageVersionArn string `json:"ModelPackageVersionArn"` - VpcConfig json.RawMessage `json:"VpcConfig"` + VpcConfig jsontext.Value `json:"VpcConfig"` Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateCompilationJob(ctx context.Context, body []byte) ([]byte, error) { var req createCompilationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -75,7 +78,7 @@ func (h *Handler) handleCreateCompilationJob(ctx context.Context, body []byte) ( return nil, extErr } - return json.Marshal(map[string]any{"CompilationJobArn": result.CompilationJobArn}) + return json.Marshal(map[string]any{"CompilationJobArn": result.CompilationJobArn}, jsonx.V1()) } // describeCompilationJobInput mirrors DescribeCompilationJobInput @@ -87,7 +90,7 @@ type describeCompilationJobInput struct { func (h *Handler) handleDescribeCompilationJob(ctx context.Context, body []byte) ([]byte, error) { var req describeCompilationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -100,7 +103,7 @@ func (h *Handler) handleDescribeCompilationJob(ctx context.Context, body []byte) return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteCompilationJobInput mirrors DeleteCompilationJobInput @@ -112,7 +115,7 @@ type deleteCompilationJobInput struct { func (h *Handler) handleDeleteCompilationJob(ctx context.Context, body []byte) error { var req deleteCompilationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -132,7 +135,7 @@ type stopCompilationJobInput struct { func (h *Handler) handleStopCompilationJob(ctx context.Context, body []byte) error { var req stopCompilationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -161,7 +164,7 @@ type listCompilationJobsInput struct { func (h *Handler) handleListCompilationJobs(ctx context.Context, body []byte) ([]byte, error) { var req listCompilationJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -214,7 +217,7 @@ func (h *Handler) handleListCompilationJobs(ctx context.Context, body []byte) ([ return json.Marshal(map[string]any{ "CompilationJobSummaries": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } func compilationTargetPlatform(j *CompilationJob) *CompilationTargetPlatform { diff --git a/services/sagemaker/handler_compilation_jobs_test.go b/services/sagemaker/handler_compilation_jobs_test.go index d55ccad4ac..91ae896818 100644 --- a/services/sagemaker/handler_compilation_jobs_test.go +++ b/services/sagemaker/handler_compilation_jobs_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -32,7 +33,7 @@ func TestHandler_CreateCompilationJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["CompilationJobArn"], "my-compile") } @@ -103,7 +104,7 @@ func TestHandler_DescribeCompilationJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "cj-1", resp["CompilationJobName"]) assert.Equal(t, "INPROGRESS", resp["CompilationJobStatus"]) } @@ -138,14 +139,14 @@ func TestHandler_StopCompilationJob(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeCompilationJob", map[string]any{"CompilationJobName": "cj-stop"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "STOPPING", resp["CompilationJobStatus"]) time.Sleep(time.Second) synctest.Wait() rec = doSageMakerRequest(t, h, "DescribeCompilationJob", map[string]any{"CompilationJobName": "cj-stop"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "STOPPED", resp["CompilationJobStatus"]) }) } @@ -174,7 +175,7 @@ func TestHandler_ListCompilationJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["CompilationJobSummaries"].([]any) assert.Len(t, items, 2) } @@ -264,7 +265,7 @@ func TestCompilationJob_HandlerCapturesInputOutputConfig(t *testing.T) { MaxRuntimeInSeconds int32 `json:"MaxRuntimeInSeconds"` } `json:"StoppingCondition"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) require.NotNil(t, out.InputConfig, "InputConfig must be returned by DescribeCompilationJob") assert.Equal(t, "s3://bucket/model.tar.gz", out.InputConfig.S3Uri) @@ -301,7 +302,7 @@ func TestCompilationJob_InitialStatus_InProgress(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "INPROGRESS", resp["CompilationJobStatus"]) } @@ -384,7 +385,7 @@ func TestHandler_AIBenchmarkJobLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["AIBenchmarkJobArn"], "bench-2") rec = doSageMakerRequest( @@ -396,7 +397,7 @@ func TestHandler_AIBenchmarkJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "InProgress", descResp["AIBenchmarkJobStatus"]) assert.Equal(t, "wc-1", descResp["AIWorkloadConfigIdentifier"]) assert.NotEmpty(t, descResp["BenchmarkTarget"]) @@ -411,7 +412,7 @@ func TestHandler_AIBenchmarkJobLifecycle(t *testing.T) { "DescribeAIBenchmarkJob", map[string]any{"AIBenchmarkJobName": "bench-2"}, ) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopping", descResp["AIBenchmarkJobStatus"]) }, }, @@ -472,7 +473,7 @@ func TestHandler_AIBenchmarkJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["AIBenchmarkJobs"].([]any) require.Len(t, items, 1) item := items[0].(map[string]any) diff --git a/services/sagemaker/handler_device_fleets.go b/services/sagemaker/handler_device_fleets.go index eb35eb3dec..de5df622aa 100644 --- a/services/sagemaker/handler_device_fleets.go +++ b/services/sagemaker/handler_device_fleets.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -45,7 +47,7 @@ type createDeviceFleetInput struct { func (h *Handler) handleCreateDeviceFleet(ctx context.Context, body []byte) ([]byte, error) { var req createDeviceFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -71,7 +73,7 @@ func (h *Handler) handleCreateDeviceFleet(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type describeDeviceFleetInput struct { @@ -81,7 +83,7 @@ type describeDeviceFleetInput struct { func (h *Handler) handleDescribeDeviceFleet(ctx context.Context, body []byte) ([]byte, error) { var req describeDeviceFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -90,7 +92,7 @@ func (h *Handler) handleDescribeDeviceFleet(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(f) + return json.Marshal(f, jsonx.V1()) } // listDeviceFleetsInput is ListDeviceFleets' request shape @@ -110,7 +112,7 @@ type listDeviceFleetsInput struct { func (h *Handler) handleListDeviceFleets(ctx context.Context, body []byte) ([]byte, error) { var req listDeviceFleetsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -150,7 +152,7 @@ type updateDeviceFleetInput struct { func (h *Handler) handleUpdateDeviceFleet(ctx context.Context, body []byte) ([]byte, error) { var req updateDeviceFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -165,7 +167,7 @@ func (h *Handler) handleUpdateDeviceFleet(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type deleteDeviceFleetInput struct { @@ -175,7 +177,7 @@ type deleteDeviceFleetInput struct { func (h *Handler) handleDeleteDeviceFleet(ctx context.Context, body []byte) ([]byte, error) { var req deleteDeviceFleetInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -183,7 +185,7 @@ func (h *Handler) handleDeleteDeviceFleet(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -213,7 +215,7 @@ type registerDevicesInput struct { func (h *Handler) handleRegisterDevices(ctx context.Context, body []byte) ([]byte, error) { var req registerDevicesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -226,7 +228,7 @@ func (h *Handler) handleRegisterDevices(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type deregisterDevicesInput struct { @@ -237,7 +239,7 @@ type deregisterDevicesInput struct { func (h *Handler) handleDeregisterDevices(ctx context.Context, body []byte) ([]byte, error) { var req deregisterDevicesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -245,7 +247,7 @@ func (h *Handler) handleDeregisterDevices(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // describeDeviceInput is DescribeDevice's request shape @@ -262,7 +264,7 @@ type describeDeviceInput struct { func (h *Handler) handleDescribeDevice(ctx context.Context, body []byte) ([]byte, error) { var req describeDeviceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -271,7 +273,7 @@ func (h *Handler) handleDescribeDevice(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(d) + return json.Marshal(d, jsonx.V1()) } // listDevicesInput is ListDevices' request shape (api_op_ListDevices.go: @@ -288,7 +290,7 @@ type listDevicesInput struct { func (h *Handler) handleListDevices(ctx context.Context, body []byte) ([]byte, error) { var req listDevicesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } diff --git a/services/sagemaker/handler_device_fleets_test.go b/services/sagemaker/handler_device_fleets_test.go index 85363f5f82..58d7e11531 100644 --- a/services/sagemaker/handler_device_fleets_test.go +++ b/services/sagemaker/handler_device_fleets_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DeviceFleetLifecycle(t *testing.T) { @@ -30,7 +32,7 @@ func TestHandler_DeviceFleetLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Empty(t, createResp) // Describe @@ -40,7 +42,7 @@ func TestHandler_DeviceFleetLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-fleet", descResp["DeviceFleetName"]) assert.Equal(t, "test fleet", descResp["Description"]) assert.Contains(t, descResp["DeviceFleetArn"], "my-fleet") @@ -56,7 +58,7 @@ func TestHandler_DeviceFleetLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["DeviceFleetSummaries"].([]any) assert.Len(t, summaries, 1) @@ -73,7 +75,7 @@ func TestHandler_DeviceFleetLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeDeviceFleet", map[string]any{ "DeviceFleetName": "my-fleet", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "updated description", descResp["Description"]) outCfg, ok = descResp["OutputConfig"].(map[string]any) require.True(t, ok) @@ -151,7 +153,7 @@ func TestHandler_DeviceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "dev-1", descResp["DeviceName"]) assert.Equal(t, "fleet-a", descResp["DeviceFleetName"]) @@ -162,7 +164,7 @@ func TestHandler_DeviceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["DeviceSummaries"].([]any) assert.Len(t, summaries, 2) @@ -175,7 +177,7 @@ func TestHandler_DeviceLifecycle(t *testing.T) { // Verify only one remains rec = doSageMakerRequest(t, h, "ListDevices", map[string]any{"DeviceFleetName": "fleet-a"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries = listResp["DeviceSummaries"].([]any) assert.Len(t, summaries, 1) } @@ -207,7 +209,7 @@ func TestHandler_ListDevices_NoFleetFilter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["DeviceSummaries"].([]any) assert.Len(t, summaries, 2) } diff --git a/services/sagemaker/handler_domains.go b/services/sagemaker/handler_domains.go index 78d735f2cd..7d4a0af87e 100644 --- a/services/sagemaker/handler_domains.go +++ b/services/sagemaker/handler_domains.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -18,26 +20,26 @@ import ( // are carried as opaque json.RawMessage passthrough per this file's // established convention (algorithms.go, ai_workload_configs.go). type createDomainInput struct { - DomainName string `json:"DomainName"` - AuthMode string `json:"AuthMode"` - AppNetworkAccessType string `json:"AppNetworkAccessType"` - AppSecurityGroupManagement string `json:"AppSecurityGroupManagement"` - HomeEfsFileSystemCreation string `json:"HomeEfsFileSystemCreation"` - KmsKeyID string `json:"KmsKeyId"` - HomeEfsFileSystemKmsKeyID string `json:"HomeEfsFileSystemKmsKeyId"` - VpcID string `json:"VpcId"` - TagPropagation string `json:"TagPropagation"` - SubnetIDs []string `json:"SubnetIds"` - DefaultUserSettings json.RawMessage `json:"DefaultUserSettings"` - DefaultSpaceSettings json.RawMessage `json:"DefaultSpaceSettings"` - DomainSettings json.RawMessage `json:"DomainSettings"` - Tags []tagObject `json:"Tags"` + DomainName string `json:"DomainName"` + AuthMode string `json:"AuthMode"` + AppNetworkAccessType string `json:"AppNetworkAccessType"` + AppSecurityGroupManagement string `json:"AppSecurityGroupManagement"` + HomeEfsFileSystemCreation string `json:"HomeEfsFileSystemCreation"` + KmsKeyID string `json:"KmsKeyId"` + HomeEfsFileSystemKmsKeyID string `json:"HomeEfsFileSystemKmsKeyId"` + VpcID string `json:"VpcId"` + TagPropagation string `json:"TagPropagation"` + SubnetIDs []string `json:"SubnetIds"` + DefaultUserSettings jsontext.Value `json:"DefaultUserSettings"` + DefaultSpaceSettings jsontext.Value `json:"DefaultSpaceSettings"` + DomainSettings jsontext.Value `json:"DomainSettings"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateDomain(ctx context.Context, body []byte) ([]byte, error) { var req createDomainInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -76,7 +78,7 @@ func (h *Handler) handleCreateDomain(ctx context.Context, body []byte) ([]byte, InfoContext(ctx, "sagemaker: created domain", "name", d.DomainName, "id", d.DomainID) return json.Marshal( - map[string]string{keyDomainArn: d.DomainArn, keyDomainID: d.DomainID, keyURL: d.URL}, + map[string]string{keyDomainArn: d.DomainArn, keyDomainID: d.DomainID, keyURL: d.URL}, jsonx.V1(), ) } @@ -87,7 +89,7 @@ type describeDomainInput struct { func (h *Handler) handleDescribeDomain(ctx context.Context, body []byte) ([]byte, error) { var req describeDomainInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -155,7 +157,7 @@ func (h *Handler) handleDescribeDomain(ctx context.Context, body []byte) ([]byte resp["DomainSettings"] = d.DomainSettings } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type domainSummary struct { @@ -174,7 +176,7 @@ type listDomainsInput struct { func (h *Handler) handleListDomains(ctx context.Context, body []byte) ([]byte, error) { var req listDomainsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -196,7 +198,7 @@ func (h *Handler) handleListDomains(ctx context.Context, body []byte) ([]byte, e resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type deleteDomainInput struct { @@ -209,7 +211,7 @@ type deleteDomainInput struct { func (h *Handler) handleDeleteDomain(ctx context.Context, body []byte) error { var req deleteDomainInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -237,22 +239,22 @@ func (h *Handler) handleDeleteDomain(ctx context.Context, body []byte) error { // distinct, separately-shaped type from Create's DomainSettings, so it gets // its own opaque passthrough field on the wire. type updateDomainInput struct { - DomainID string `json:"DomainId"` - AppNetworkAccessType string `json:"AppNetworkAccessType"` - AppSecurityGroupManagement string `json:"AppSecurityGroupManagement"` - HomeEfsFileSystemCreation string `json:"HomeEfsFileSystemCreation"` - TagPropagation string `json:"TagPropagation"` - VpcID string `json:"VpcId"` - SubnetIDs []string `json:"SubnetIds"` - DefaultUserSettings json.RawMessage `json:"DefaultUserSettings"` - DefaultSpaceSettings json.RawMessage `json:"DefaultSpaceSettings"` - DomainSettingsForUpdate json.RawMessage `json:"DomainSettingsForUpdate"` + DomainID string `json:"DomainId"` + AppNetworkAccessType string `json:"AppNetworkAccessType"` + AppSecurityGroupManagement string `json:"AppSecurityGroupManagement"` + HomeEfsFileSystemCreation string `json:"HomeEfsFileSystemCreation"` + TagPropagation string `json:"TagPropagation"` + VpcID string `json:"VpcId"` + SubnetIDs []string `json:"SubnetIds"` + DefaultUserSettings jsontext.Value `json:"DefaultUserSettings"` + DefaultSpaceSettings jsontext.Value `json:"DefaultSpaceSettings"` + DomainSettingsForUpdate jsontext.Value `json:"DomainSettingsForUpdate"` } func (h *Handler) handleUpdateDomain(ctx context.Context, body []byte) ([]byte, error) { var req updateDomainInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -281,5 +283,5 @@ func (h *Handler) handleUpdateDomain(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: updated domain", "id", req.DomainID) - return json.Marshal(map[string]string{keyDomainArn: d.DomainArn}) + return json.Marshal(map[string]string{keyDomainArn: d.DomainArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_domains_test.go b/services/sagemaker/handler_domains_test.go index 824e38851e..72347207cf 100644 --- a/services/sagemaker/handler_domains_test.go +++ b/services/sagemaker/handler_domains_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateDomain(t *testing.T) { @@ -50,7 +52,7 @@ func TestHandler_CreateDomain(t *testing.T) { if tt.wantID { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["DomainId"]) assert.NotEmpty(t, resp["Url"]) } @@ -76,7 +78,7 @@ func TestHandler_DomainLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) domainID := createOut["DomainId"].(string) // Describe domain by ID — the fields accepted on Create must round-trip, @@ -86,7 +88,7 @@ func TestHandler_DomainLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "test-domain", descOut["DomainName"]) assert.Equal(t, "VpcOnly", descOut["AppNetworkAccessType"]) assert.Equal(t, "vpc-1", descOut["VpcId"]) @@ -98,7 +100,7 @@ func TestHandler_DomainLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["Domains"].([]any), 1) // Update domain — a partial update must apply the overridable field @@ -113,7 +115,7 @@ func TestHandler_DomainLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDescAfterUpdate.Code) var descAfterUpdate map[string]any - require.NoError(t, json.Unmarshal(recDescAfterUpdate.Body.Bytes(), &descAfterUpdate)) + require.NoError(t, json.Unmarshal(recDescAfterUpdate.Body.Bytes(), &descAfterUpdate, jsonx.V1())) assert.Equal(t, "PublicInternetOnly", descAfterUpdate["AppNetworkAccessType"]) assert.Equal(t, "vpc-1", descAfterUpdate["VpcId"]) @@ -170,7 +172,7 @@ func TestHandler_ListDomains_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Domains"].([]any), 2, "MaxResults must cap the page, not just be parsed and ignored") assert.NotEmpty(t, out["NextToken"]) } diff --git a/services/sagemaker/handler_edge_deployment.go b/services/sagemaker/handler_edge_deployment.go index 106ea8028b..13d33a486a 100644 --- a/services/sagemaker/handler_edge_deployment.go +++ b/services/sagemaker/handler_edge_deployment.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // edge deployment operation name constants. @@ -105,9 +108,9 @@ func (h *Handler) dispatchEdgeDeploymentOps( // --------------------------------------------------------------------------- type edgeDeploymentStageRequest struct { - StageName string `json:"StageName"` - DeviceSelectionConfig json.RawMessage `json:"DeviceSelectionConfig,omitempty"` - DeploymentConfig json.RawMessage `json:"DeploymentConfig,omitempty"` + StageName string `json:"StageName"` + DeviceSelectionConfig jsontext.Value `json:"DeviceSelectionConfig,omitempty"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig,omitempty"` } func toEdgeDeploymentStageInputs(reqs []edgeDeploymentStageRequest) []EdgeDeploymentStageInput { @@ -133,7 +136,7 @@ type createEdgeDeploymentPlanInput struct { func (h *Handler) handleCreateEdgeDeploymentPlan(ctx context.Context, body []byte) ([]byte, error) { var req createEdgeDeploymentPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -156,7 +159,7 @@ func (h *Handler) handleCreateEdgeDeploymentPlan(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]string{keyEdgeDeploymentPlanArn: p.EdgeDeploymentPlanArn}) + return json.Marshal(map[string]string{keyEdgeDeploymentPlanArn: p.EdgeDeploymentPlanArn}, jsonx.V1()) } // stageStatusSummary builds the DeploymentStageStatusSummary shape for a @@ -193,7 +196,7 @@ type describeEdgeDeploymentPlanInput struct { func (h *Handler) handleDescribeEdgeDeploymentPlan(ctx context.Context, body []byte) ([]byte, error) { var req describeEdgeDeploymentPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -234,7 +237,7 @@ func (h *Handler) handleDescribeEdgeDeploymentPlan(ctx context.Context, body []b resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type deleteEdgeDeploymentPlanInput struct { @@ -244,7 +247,7 @@ type deleteEdgeDeploymentPlanInput struct { func (h *Handler) handleDeleteEdgeDeploymentPlan(ctx context.Context, body []byte) error { var req deleteEdgeDeploymentPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -267,7 +270,7 @@ type listEdgeDeploymentPlansInput struct { func (h *Handler) handleListEdgeDeploymentPlans(ctx context.Context, body []byte) ([]byte, error) { var req listEdgeDeploymentPlansInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -313,7 +316,7 @@ type createEdgeDeploymentStageInput struct { func (h *Handler) handleCreateEdgeDeploymentStage(ctx context.Context, body []byte) error { var req createEdgeDeploymentStageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -328,7 +331,7 @@ type deleteEdgeDeploymentStageInput struct { func (h *Handler) handleDeleteEdgeDeploymentStage(ctx context.Context, body []byte) error { var req deleteEdgeDeploymentStageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -343,7 +346,7 @@ type startEdgeDeploymentStageInput struct { func (h *Handler) handleStartEdgeDeploymentStage(ctx context.Context, body []byte) error { var req startEdgeDeploymentStageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -358,7 +361,7 @@ type stopEdgeDeploymentStageInput struct { func (h *Handler) handleStopEdgeDeploymentStage(ctx context.Context, body []byte) error { var req stopEdgeDeploymentStageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -376,7 +379,7 @@ type getDeviceFleetReportInput struct { func (h *Handler) handleGetDeviceFleetReport(ctx context.Context, body []byte) ([]byte, error) { var req getDeviceFleetReportInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -410,7 +413,7 @@ func (h *Handler) handleGetDeviceFleetReport(ctx context.Context, body []byte) ( resp["OutputConfig"] = outputConfig } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type listStageDevicesInput struct { @@ -424,7 +427,7 @@ type listStageDevicesInput struct { func (h *Handler) handleListStageDevices(ctx context.Context, body []byte) ([]byte, error) { var req listStageDevicesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -470,7 +473,7 @@ type updateDevicesInput struct { func (h *Handler) handleUpdateDevices(ctx context.Context, body []byte) error { var req updateDevicesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_edge_deployment_test.go b/services/sagemaker/handler_edge_deployment_test.go index 08f133fd23..34f47447e9 100644 --- a/services/sagemaker/handler_edge_deployment_test.go +++ b/services/sagemaker/handler_edge_deployment_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -49,7 +50,7 @@ func TestHandler_EdgeDeploymentPlanLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["EdgeDeploymentPlanArn"], "my-plan") // Describe @@ -59,7 +60,7 @@ func TestHandler_EdgeDeploymentPlanLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-plan", descResp["EdgeDeploymentPlanName"]) assert.Equal(t, "plan-fleet", descResp["DeviceFleetName"]) @@ -91,7 +92,7 @@ func TestHandler_EdgeDeploymentPlanLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["EdgeDeploymentPlanSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -181,7 +182,7 @@ func TestHandler_EdgeDeploymentStageLifecycle(t *testing.T) { "EdgeDeploymentPlanName": "stage-plan", }) var resp map[string]any - require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(descResp.Body.Bytes(), &resp, jsonx.V1())) return resp } @@ -293,7 +294,7 @@ func TestHandler_GetDeviceFleetReport(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "report-fleet", resp["DeviceFleetName"]) assert.Contains(t, resp["DeviceFleetArn"], "report-fleet") assert.Equal(t, "fleet for reports", resp["Description"]) @@ -353,7 +354,7 @@ func TestHandler_ListStageDevices(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["DeviceDeploymentSummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 2) @@ -422,7 +423,7 @@ func TestHandler_UpdateDevices(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "updated", resp["Description"]) assert.Equal(t, "thing-1", resp["IotThingName"]) } @@ -478,7 +479,7 @@ func TestHandler_EdgeDeploymentPlan_SnapshotRestore(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["EdgeDeploymentPlanSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, tt.wantCount) @@ -493,7 +494,7 @@ func TestHandler_EdgeDeploymentPlan_SnapshotRestore(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "persist-fleet", descResp["DeviceFleetName"]) stages, ok := descResp["Stages"].([]any) diff --git a/services/sagemaker/handler_edge_packaging_jobs.go b/services/sagemaker/handler_edge_packaging_jobs.go index 279fc8da47..5232504cc2 100644 --- a/services/sagemaker/handler_edge_packaging_jobs.go +++ b/services/sagemaker/handler_edge_packaging_jobs.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -34,7 +36,7 @@ type createEdgePackagingJobRequest struct { func (h *Handler) handleCreateEdgePackagingJob(ctx context.Context, body []byte) ([]byte, error) { var req createEdgePackagingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -81,7 +83,7 @@ func (h *Handler) handleCreateEdgePackagingJob(ctx context.Context, body []byte) return nil, err } - return json.Marshal(map[string]string{keyEdgePackagingJobArn: j.EdgePackagingJobArn}) + return json.Marshal(map[string]string{keyEdgePackagingJobArn: j.EdgePackagingJobArn}, jsonx.V1()) } type describeEdgePackagingJobRequest struct { @@ -91,7 +93,7 @@ type describeEdgePackagingJobRequest struct { func (h *Handler) handleDescribeEdgePackagingJob(ctx context.Context, body []byte) ([]byte, error) { var req describeEdgePackagingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -137,7 +139,7 @@ func (h *Handler) handleDescribeEdgePackagingJob(ctx context.Context, body []byt resp["ModelArtifact"] = j.ModelArtifact } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type stopEdgePackagingJobRequest struct { @@ -147,7 +149,7 @@ type stopEdgePackagingJobRequest struct { func (h *Handler) handleStopEdgePackagingJob(ctx context.Context, body []byte) error { var req stopEdgePackagingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -186,7 +188,7 @@ type listEdgePackagingJobsRequest struct { func (h *Handler) handleListEdgePackagingJobs(ctx context.Context, body []byte) ([]byte, error) { var req listEdgePackagingJobsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -222,5 +224,5 @@ func (h *Handler) handleListEdgePackagingJobs(ctx context.Context, body []byte) resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_edge_packaging_jobs_test.go b/services/sagemaker/handler_edge_packaging_jobs_test.go index 14a71cabfa..852f960061 100644 --- a/services/sagemaker/handler_edge_packaging_jobs_test.go +++ b/services/sagemaker/handler_edge_packaging_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_DescribeEdgePackagingJob_FailureReasonNotOnWire proves @@ -28,7 +30,7 @@ func TestHandler_DescribeEdgePackagingJob_FailureReasonNotOnWire(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) _, present := out["FailureReason"] assert.False(t, present, "FailureReason is not a real DescribeEdgePackagingJobOutput field") } @@ -55,7 +57,7 @@ func TestHandler_EdgePackagingJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["EdgePackagingJobArn"], "my-edge-job") // Describe @@ -65,7 +67,7 @@ func TestHandler_EdgePackagingJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-edge-job", descResp["EdgePackagingJobName"]) assert.Equal(t, "my-model", descResp["ModelName"]) assert.Equal(t, "1.0", descResp["ModelVersion"]) @@ -80,7 +82,7 @@ func TestHandler_EdgePackagingJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["EdgePackagingJobSummaries"].([]any) assert.Len(t, summaries, 1) @@ -95,7 +97,7 @@ func TestHandler_EdgePackagingJobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeEdgePackagingJob", map[string]any{ "EdgePackagingJobName": "my-edge-job", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "STOPPING", descResp["EdgePackagingJobStatus"]) // Confirm it actually reaches STOPPED. @@ -105,7 +107,7 @@ func TestHandler_EdgePackagingJobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeEdgePackagingJob", map[string]any{ "EdgePackagingJobName": "my-edge-job", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "STOPPED", descResp["EdgePackagingJobStatus"]) }) } @@ -137,7 +139,7 @@ func TestHandler_EdgePackagingJob_ReachesCompleted(t *testing.T) { "EdgePackagingJobName": "edge-job-completes", }) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "COMPLETED", out["EdgePackagingJobStatus"]) assert.Equal(t, "s3://bucket/edge-out/model.tar.gz", out["ModelArtifact"], "ModelArtifact must be derived from OutputConfig.S3OutputLocation once the job completes") @@ -227,7 +229,7 @@ func TestHandler_ListEdgePackagingJobs_StatusFilter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["EdgePackagingJobSummaries"].([]any) assert.Len(t, summaries, 1) } @@ -248,7 +250,7 @@ func TestHandler_ListEdgePackagingJobs_FilterSort(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["EdgePackagingJobSummaries"].([]any)) // SortBy=NAME, SortOrder=Descending reverses this backend's ascending @@ -258,7 +260,7 @@ func TestHandler_ListEdgePackagingJobs_FilterSort(t *testing.T) { "SortOrder": "Descending", }) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["EdgePackagingJobSummaries"].([]any) require.Len(t, summaries, 2) assert.Equal(t, "job-beta", summaries[0].(map[string]any)["EdgePackagingJobName"]) @@ -316,7 +318,7 @@ func TestHandler_JobLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["JobArn"], "job-2") rec = doSageMakerRequest(t, h, "DescribeJob", map[string]any{ @@ -325,7 +327,7 @@ func TestHandler_JobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "InProgress", descResp["JobStatus"]) assert.Equal(t, "AgentRFT", descResp["JobCategory"]) assert.NotEmpty(t, descResp["SecondaryStatusTransitions"]) @@ -346,7 +348,7 @@ func TestHandler_JobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeJob", map[string]any{ "JobCategory": "AgentRFT", "JobName": "job-2", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopping", descResp["JobStatus"]) }, }, @@ -403,7 +405,7 @@ func TestHandler_JobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["JobSummaries"].([]any) require.Len(t, items, 1) assert.Equal(t, "job-cat-a", items[0].(map[string]any)["JobName"]) @@ -440,7 +442,7 @@ func TestHandler_JobSchemaVersionLookups(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "1.0", resp["JobConfigSchemaVersion"]) assert.NotEmpty(t, resp["JobConfigSchema"]) }, @@ -472,7 +474,7 @@ func TestHandler_JobSchemaVersionLookups(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["JobConfigSchemas"].([]any) require.Len(t, items, 1) assert.Equal(t, "1.0", items[0].(map[string]any)["JobConfigSchemaVersion"]) diff --git a/services/sagemaker/handler_endpoint_configs.go b/services/sagemaker/handler_endpoint_configs.go index 97f293fe29..f026a0a3e8 100644 --- a/services/sagemaker/handler_endpoint_configs.go +++ b/services/sagemaker/handler_endpoint_configs.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -13,8 +15,8 @@ type createEndpointConfigRequest struct { DataCaptureConfig *DataCaptureConfig `json:"DataCaptureConfig,omitempty"` AsyncInferenceConfig *AsyncInferenceConfig `json:"AsyncInferenceConfig,omitempty"` VpcConfig *VpcConfig `json:"VpcConfig,omitempty"` - ExplainerConfig json.RawMessage `json:"ExplainerConfig,omitempty"` - MetricsConfig json.RawMessage `json:"MetricsConfig,omitempty"` + ExplainerConfig jsontext.Value `json:"ExplainerConfig,omitempty"` + MetricsConfig jsontext.Value `json:"MetricsConfig,omitempty"` EndpointConfigName string `json:"EndpointConfigName"` ExecutionRoleArn string `json:"ExecutionRoleArn,omitempty"` KmsKeyID string `json:"KmsKeyId,omitempty"` @@ -36,8 +38,8 @@ type describeEndpointConfigResponse struct { DataCaptureConfig *DataCaptureConfig `json:"DataCaptureConfig,omitempty"` AsyncInferenceConfig *AsyncInferenceConfig `json:"AsyncInferenceConfig,omitempty"` VpcConfig *VpcConfig `json:"VpcConfig,omitempty"` - ExplainerConfig json.RawMessage `json:"ExplainerConfig,omitempty"` - MetricsConfig json.RawMessage `json:"MetricsConfig,omitempty"` + ExplainerConfig jsontext.Value `json:"ExplainerConfig,omitempty"` + MetricsConfig jsontext.Value `json:"MetricsConfig,omitempty"` EndpointConfigArn string `json:"EndpointConfigArn"` EndpointConfigName string `json:"EndpointConfigName"` ExecutionRoleArn string `json:"ExecutionRoleArn,omitempty"` @@ -50,7 +52,7 @@ type describeEndpointConfigResponse struct { func (h *Handler) handleCreateEndpointConfig(ctx context.Context, body []byte) ([]byte, error) { var req createEndpointConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -91,7 +93,7 @@ func (h *Handler) handleCreateEndpointConfig(ctx context.Context, body []byte) ( log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created endpoint config", "name", ec.EndpointConfigName) - return json.Marshal(map[string]string{"EndpointConfigArn": ec.EndpointConfigARN}) + return json.Marshal(map[string]string{"EndpointConfigArn": ec.EndpointConfigARN}, jsonx.V1()) } // describeEndpointConfigRequest is the request body for DescribeEndpointConfig. @@ -102,7 +104,7 @@ type describeEndpointConfigRequest struct { func (h *Handler) handleDescribeEndpointConfig(ctx context.Context, body []byte) ([]byte, error) { var req describeEndpointConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -139,13 +141,13 @@ func (h *Handler) handleDescribeEndpointConfig(ctx context.Context, body []byte) resp.ShadowProductionVariants = nil } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleListEndpointConfigs(ctx context.Context, body []byte) ([]byte, error) { var req nameTimeListRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -171,7 +173,7 @@ func (h *Handler) handleListEndpointConfigs(ctx context.Context, body []byte) ([ resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteEndpointConfigRequest is the request body for DeleteEndpointConfig. @@ -182,7 +184,7 @@ type deleteEndpointConfigRequest struct { func (h *Handler) handleDeleteEndpointConfig(ctx context.Context, body []byte) error { var req deleteEndpointConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_endpoint_configs_test.go b/services/sagemaker/handler_endpoint_configs_test.go index 38307aa447..749c714761 100644 --- a/services/sagemaker/handler_endpoint_configs_test.go +++ b/services/sagemaker/handler_endpoint_configs_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -60,7 +61,7 @@ func TestHandler_CreateEndpointConfig(t *testing.T) { if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["EndpointConfigArn"], "arn:aws:sagemaker") } }) @@ -111,7 +112,7 @@ func TestHandler_DescribeEndpointConfig(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["EndpointConfigName"]) } }) @@ -250,7 +251,7 @@ func TestHandler_ListEndpointConfigs(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs, ok := resp["EndpointConfigs"].([]any) require.True(t, ok) @@ -281,7 +282,7 @@ func TestHandler_Tags_EndpointConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].([]any) require.True(t, ok) @@ -334,7 +335,7 @@ func TestHandler_ListEndpointConfigsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs, configsOK := resp["EndpointConfigs"].([]any) require.True(t, configsOK) @@ -355,7 +356,7 @@ func TestHandler_ListEndpointConfigsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) configs2, configs2OK := resp2["EndpointConfigs"].([]any) require.True(t, configs2OK) @@ -444,7 +445,7 @@ func TestCreateEndpointConfig_RequiresProductionVariants(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) msg, _ := errResp["message"].(string) assert.Contains(t, msg, "ProductionVariant", "error message must mention ProductionVariant") @@ -525,7 +526,7 @@ func TestHandler_ListEndpointConfigs_FilterSort(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["EndpointConfigs"].([]any) require.True(t, ok) @@ -597,7 +598,7 @@ func TestHandler_ListEndpointConfigs_CreationTimeAfterInclusive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs, ok := resp["EndpointConfigs"].([]any) require.True(t, ok) require.Len(t, configs, 1) diff --git a/services/sagemaker/handler_endpoints.go b/services/sagemaker/handler_endpoints.go index fde3085066..78b733b463 100644 --- a/services/sagemaker/handler_endpoints.go +++ b/services/sagemaker/handler_endpoints.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -14,15 +16,15 @@ import ( // createEndpointInput mirrors CreateEndpointInput (api_op_CreateEndpoint.go:1-49). type createEndpointInput struct { - DeploymentConfig json.RawMessage `json:"DeploymentConfig"` - EndpointName string `json:"EndpointName"` - EndpointConfigName string `json:"EndpointConfigName"` - Tags []tagObject `json:"Tags"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig"` + EndpointName string `json:"EndpointName"` + EndpointConfigName string `json:"EndpointConfigName"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateEndpointFSM(ctx context.Context, body []byte) ([]byte, error) { var req createEndpointInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.EndpointName == "" { @@ -48,24 +50,24 @@ func (h *Handler) handleCreateEndpointFSM(ctx context.Context, body []byte) ([]b log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created endpoint (FSM)", "name", ep.EndpointName) - return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}) + return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}, jsonx.V1()) } // updateEndpointInput mirrors UpdateEndpointInput (api_op_UpdateEndpoint.go:1-56). type updateEndpointInput struct { - DeploymentConfig json.RawMessage `json:"DeploymentConfig"` - EndpointConfigName string `json:"EndpointConfigName"` - EndpointName string `json:"EndpointName"` - ExcludeRetainedVariantProperties []string `json:"ExcludeRetainedVariantProperties"` - RetainAllVariantProperties bool `json:"RetainAllVariantProperties"` - RetainDeploymentConfig bool `json:"RetainDeploymentConfig"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig"` + EndpointConfigName string `json:"EndpointConfigName"` + EndpointName string `json:"EndpointName"` + ExcludeRetainedVariantProperties []string `json:"ExcludeRetainedVariantProperties"` + RetainAllVariantProperties bool `json:"RetainAllVariantProperties"` + RetainDeploymentConfig bool `json:"RetainDeploymentConfig"` } // handleUpdateEndpointFSM replaces the basic UpdateEndpoint handler with one // that properly drives Updating → InService via the lifecycle simulator. func (h *Handler) handleUpdateEndpointFSM(ctx context.Context, body []byte) ([]byte, error) { var req updateEndpointInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.EndpointName == "" { @@ -86,7 +88,7 @@ func (h *Handler) handleUpdateEndpointFSM(ctx context.Context, body []byte) ([]b log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: updated endpoint (FSM)", "name", ep.EndpointName) - return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}) + return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -105,7 +107,7 @@ func (h *Handler) handleUpdateEndpointWeightsAndCapacitiesFull( body []byte, ) ([]byte, error) { var req updateEndpointWeightsAndCapacitiesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.EndpointName == "" { @@ -129,7 +131,7 @@ func (h *Handler) handleUpdateEndpointWeightsAndCapacitiesFull( req.EndpointName, ) - return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}) + return json.Marshal(map[string]string{keyEndpointArn: ep.EndpointArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -199,7 +201,7 @@ func endpointResponseMap(ep *Endpoint) map[string]any { func (h *Handler) handleDescribeEndpoint(ctx context.Context, body []byte) ([]byte, error) { var req describeEndpointInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -212,7 +214,7 @@ func (h *Handler) handleDescribeEndpoint(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(endpointResponseMap(ep)) + return json.Marshal(endpointResponseMap(ep), jsonx.V1()) } type endpointSummary struct { @@ -240,7 +242,7 @@ type listEndpointsInput struct { func (h *Handler) handleListEndpoints(ctx context.Context, body []byte) ([]byte, error) { var req listEndpointsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -273,7 +275,7 @@ func (h *Handler) handleListEndpoints(ctx context.Context, body []byte) ([]byte, resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteEndpointInput mirrors DeleteEndpointInput (api_op_DeleteEndpoint.go:29-37). @@ -284,7 +286,7 @@ type deleteEndpointInput struct { func (h *Handler) handleDeleteEndpoint(ctx context.Context, body []byte) error { var req deleteEndpointInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_endpoints_test.go b/services/sagemaker/handler_endpoints_test.go index 8f3c1622bb..f838980949 100644 --- a/services/sagemaker/handler_endpoints_test.go +++ b/services/sagemaker/handler_endpoints_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DescribeEndpoint_FullResponse(t *testing.T) { @@ -44,7 +46,7 @@ func TestHandler_DescribeEndpoint_FullResponse(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "ep1", descResp["EndpointName"]) assert.NotEmpty(t, descResp["EndpointArn"]) // Status is Creating initially (FSM transitions async) @@ -94,7 +96,7 @@ func TestHandler_DescribeEndpoint_DataCaptureAndAsyncInferenceConfig(t *testing. require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dcc, ok := resp["DataCaptureConfig"].(map[string]any) require.True(t, ok, "DataCaptureConfig must be surfaced from the active EndpointConfig") @@ -137,7 +139,7 @@ func TestHandler_CreateEndpoint_DeploymentConfigEchoedOnDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) lastDeploymentConfig, ok := resp["LastDeploymentConfig"].(map[string]any) require.True(t, ok, "LastDeploymentConfig must echo the DeploymentConfig sent to Create/UpdateEndpoint") @@ -186,7 +188,7 @@ func TestHandler_UpdateEndpoint_RetainAllVariantProperties(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeEndpoint", map[string]any{"EndpointName": "ep-retain"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) variant := resp["ProductionVariants"].([]any)[0].(map[string]any) assert.InDelta(t, float64(5), variant["DesiredInstanceCount"], 0) assert.InDelta(t, 9.0, variant["DesiredWeight"], 0.0001) @@ -207,7 +209,7 @@ func TestHandler_UpdateEndpoint_RetainAllVariantProperties(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeEndpoint", map[string]any{"EndpointName": "ep-retain-true"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) variant := resp["ProductionVariants"].([]any)[0].(map[string]any) assert.InDelta(t, float64(1), variant["DesiredInstanceCount"], 0) assert.InDelta(t, 1.0, variant["DesiredWeight"], 0.0001) @@ -229,7 +231,7 @@ func TestHandler_UpdateEndpoint_RetainAllVariantProperties(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeEndpoint", map[string]any{"EndpointName": "ep-retain-exclude"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) variant := resp["ProductionVariants"].([]any)[0].(map[string]any) // Excluded, so takes the new config's value instead of retaining. assert.InDelta(t, float64(5), variant["DesiredInstanceCount"], 0) @@ -298,7 +300,7 @@ func TestHandler_ListEndpoints_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, _ := resp["Endpoints"].([]any) assert.Len(t, endpoints, tc.wantCount) }) @@ -329,7 +331,7 @@ func TestHandler_ListEndpoints_SortByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, ok := resp["Endpoints"].([]any) require.True(t, ok) require.Len(t, endpoints, 2) @@ -348,7 +350,7 @@ func TestHandler_CreateEndpoint_UnknownEndpointConfig(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) rec = doSageMakerRequest(t, h, "DescribeEndpoint", map[string]any{ @@ -389,7 +391,7 @@ func TestHandler_DescribeEndpoint_EventuallyInService(t *testing.T) { rec := doSageMakerRequest(t, h, "DescribeEndpoint", map[string]any{ "EndpointName": "ep2", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) }) require.Equal(t, "InService", descResp["EndpointStatus"]) @@ -434,7 +436,7 @@ func TestHandler_EndpointLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["EndpointArn"]) // Describe endpoint. @@ -451,7 +453,7 @@ func TestHandler_EndpointLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["Endpoints"].([]any), 1) // Update endpoint. diff --git a/services/sagemaker/handler_experiments.go b/services/sagemaker/handler_experiments.go index b2534a1e6d..c16dab54c0 100644 --- a/services/sagemaker/handler_experiments.go +++ b/services/sagemaker/handler_experiments.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -24,7 +25,7 @@ type createExperimentInput struct { func (h *Handler) handleCreateExperiment(ctx context.Context, body []byte) ([]byte, error) { var req createExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -41,7 +42,7 @@ func (h *Handler) handleCreateExperiment(ctx context.Context, body []byte) ([]by logger.Load(ctx).InfoContext(ctx, "sagemaker: created experiment", "name", e.ExperimentName) - return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}) + return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}, jsonx.V1()) } // describeExperimentInput mirrors DescribeExperimentInput @@ -53,7 +54,7 @@ type describeExperimentInput struct { func (h *Handler) handleDescribeExperiment(ctx context.Context, body []byte) ([]byte, error) { var req describeExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -85,7 +86,7 @@ func (h *Handler) handleDescribeExperiment(ctx context.Context, body []byte) ([] resp["LastModifiedBy"] = e.LastModifiedBy } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type experimentSummary struct { @@ -110,7 +111,7 @@ type listExperimentsInput struct { func (h *Handler) handleListExperiments(ctx context.Context, body []byte) ([]byte, error) { var req listExperimentsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -138,7 +139,7 @@ func (h *Handler) handleListExperiments(ctx context.Context, body []byte) ([]byt resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteExperimentInput mirrors DeleteExperimentInput @@ -150,7 +151,7 @@ type deleteExperimentInput struct { func (h *Handler) handleDeleteExperiment(ctx context.Context, body []byte) ([]byte, error) { var req deleteExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -165,7 +166,7 @@ func (h *Handler) handleDeleteExperiment(ctx context.Context, body []byte) ([]by logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted experiment", "name", req.ExperimentName) - return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}) + return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -186,7 +187,7 @@ type updateExperimentInput struct { func (h *Handler) handleUpdateExperiment(ctx context.Context, body []byte) ([]byte, error) { var req updateExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,5 +202,5 @@ func (h *Handler) handleUpdateExperiment(ctx context.Context, body []byte) ([]by logger.Load(ctx).InfoContext(ctx, "sagemaker: updated experiment", "name", e.ExperimentName) - return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}) + return json.Marshal(map[string]string{keyExperimentArn: e.ExperimentArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_experiments_test.go b/services/sagemaker/handler_experiments_test.go index 84a75405ce..7981a6f2a5 100644 --- a/services/sagemaker/handler_experiments_test.go +++ b/services/sagemaker/handler_experiments_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ExperimentLifecycle(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_ExperimentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["ExperimentArn"]) // Describe experiment. @@ -39,7 +41,7 @@ func TestHandler_ExperimentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["ExperimentSummaries"].([]any), 1) // Delete experiment. @@ -114,7 +116,7 @@ func TestHandler_UpdateExperiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["ExperimentArn"]) // Describe returns updated fields @@ -122,7 +124,7 @@ func TestHandler_UpdateExperiment(t *testing.T) { "ExperimentName": "my-exp", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "My Experiment", descResp["DisplayName"]) assert.Equal(t, "A test experiment", descResp["Description"]) } @@ -152,7 +154,7 @@ func TestHandler_Tags_Experiment(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) expARN := createResp["ExperimentArn"] require.NotEmpty(t, expARN) @@ -162,7 +164,7 @@ func TestHandler_Tags_Experiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "project", tags[0].(map[string]any)["Key"]) @@ -186,7 +188,7 @@ func TestHandler_CreateExperiment_DisplayNameAndDescription(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Friendly Name", descResp["DisplayName"]) assert.Equal(t, "An experiment created with a display name", descResp["Description"]) @@ -194,7 +196,7 @@ func TestHandler_CreateExperiment_DisplayNameAndDescription(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["ExperimentSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "Friendly Name", summaries[0].(map[string]any)["DisplayName"]) diff --git a/services/sagemaker/handler_feature_groups.go b/services/sagemaker/handler_feature_groups.go index dcd850c718..b3008e8acd 100644 --- a/services/sagemaker/handler_feature_groups.go +++ b/services/sagemaker/handler_feature_groups.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -33,7 +34,7 @@ type createFeatureGroupInput struct { func (h *Handler) handleCreateFeatureGroup(ctx context.Context, body []byte) ([]byte, error) { var req createFeatureGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -72,7 +73,7 @@ func (h *Handler) handleCreateFeatureGroup(ctx context.Context, body []byte) ([] logger.Load(ctx). InfoContext(ctx, "sagemaker: created feature group", "name", fg.FeatureGroupName) - return json.Marshal(map[string]string{keyFeatureGroupArn: fg.FeatureGroupArn}) + return json.Marshal(map[string]string{keyFeatureGroupArn: fg.FeatureGroupArn}, jsonx.V1()) } // describeFeatureGroupInput mirrors DescribeFeatureGroupInput @@ -89,7 +90,7 @@ type describeFeatureGroupInput struct { func (h *Handler) handleDescribeFeatureGroup(ctx context.Context, body []byte) ([]byte, error) { var req describeFeatureGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -146,7 +147,7 @@ func (h *Handler) handleDescribeFeatureGroup(ctx context.Context, body []byte) ( resp["LastUpdateStatus"] = fg.LastUpdateStatus } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type featureGroupSummary struct { @@ -175,7 +176,7 @@ type listFeatureGroupsInput struct { func (h *Handler) handleListFeatureGroups(ctx context.Context, body []byte) ([]byte, error) { var req listFeatureGroupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -206,7 +207,7 @@ func (h *Handler) handleListFeatureGroups(ctx context.Context, body []byte) ([]b resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteFeatureGroupInput mirrors DeleteFeatureGroupInput @@ -218,7 +219,7 @@ type deleteFeatureGroupInput struct { func (h *Handler) handleDeleteFeatureGroup(ctx context.Context, body []byte) error { var req deleteFeatureGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -254,7 +255,7 @@ type updateFeatureGroupInput struct { func (h *Handler) handleUpdateFeatureGroup(ctx context.Context, body []byte) ([]byte, error) { var req updateFeatureGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -273,5 +274,5 @@ func (h *Handler) handleUpdateFeatureGroup(ctx context.Context, body []byte) ([] logger.Load(ctx).InfoContext(ctx, "sagemaker: updated feature group", "name", fg.FeatureGroupName) - return json.Marshal(map[string]string{keyFeatureGroupArn: fg.FeatureGroupArn}) + return json.Marshal(map[string]string{keyFeatureGroupArn: fg.FeatureGroupArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_feature_groups_stores_test.go b/services/sagemaker/handler_feature_groups_stores_test.go index 6b3c0f8729..e8945fb515 100644 --- a/services/sagemaker/handler_feature_groups_stores_test.go +++ b/services/sagemaker/handler_feature_groups_stores_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateFeatureGroup_StoreConfigsRoundTrip(t *testing.T) { @@ -49,7 +51,7 @@ func TestHandler_CreateFeatureGroup_StoreConfigsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) onlineCfg, ok := out["OnlineStoreConfig"].(map[string]any) require.True(t, ok, "OnlineStoreConfig must round-trip") @@ -96,7 +98,7 @@ func TestHandler_CreateFeatureGroup_NoStoreConfigsOmitsFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) _, hasOnline := out["OnlineStoreConfig"] _, hasOffline := out["OfflineStoreConfig"] diff --git a/services/sagemaker/handler_feature_groups_test.go b/services/sagemaker/handler_feature_groups_test.go index 75eae57f28..7e572763bf 100644 --- a/services/sagemaker/handler_feature_groups_test.go +++ b/services/sagemaker/handler_feature_groups_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_FeatureGroupLifecycle(t *testing.T) { @@ -34,7 +36,7 @@ func TestHandler_FeatureGroupLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code, recCreate.Body.String()) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["FeatureGroupArn"]) // Describe feature group. @@ -48,7 +50,7 @@ func TestHandler_FeatureGroupLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["FeatureGroupSummaries"].([]any), 1) // Delete feature group. @@ -125,7 +127,7 @@ func TestHandler_UpdateFeatureGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["FeatureGroupArn"]) // Describe should show 2 features now @@ -135,7 +137,7 @@ func TestHandler_UpdateFeatureGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) defs := descResp["FeatureDefinitions"].([]any) assert.Len(t, defs, 2) } @@ -170,7 +172,7 @@ func TestHandler_Tags_FeatureGroup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) fgARN := createResp["FeatureGroupArn"] require.NotEmpty(t, fgARN) @@ -181,7 +183,7 @@ func TestHandler_Tags_FeatureGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "env", tags[0].(map[string]any)["Key"]) @@ -210,7 +212,7 @@ func TestHandler_CreateFeatureGroup_RoleArnAndDescription(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "arn:aws:iam::000000000000:role/FeatureStoreRole", descResp["RoleArn"]) assert.Equal(t, "A feature group with a role", descResp["Description"]) } diff --git a/services/sagemaker/handler_feature_metadata.go b/services/sagemaker/handler_feature_metadata.go index cffbd96b02..f6ae578c25 100644 --- a/services/sagemaker/handler_feature_metadata.go +++ b/services/sagemaker/handler_feature_metadata.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -52,7 +54,7 @@ type describeFeatureMetadataInput struct { func (h *Handler) handleDescribeFeatureMetadata(ctx context.Context, body []byte) ([]byte, error) { var req describeFeatureMetadataInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -101,7 +103,7 @@ func (h *Handler) handleDescribeFeatureMetadata(ctx context.Context, body []byte resp["Parameters"] = featureParametersToWire(meta.Parameters) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateFeatureMetadataInput mirrors UpdateFeatureMetadataInput @@ -123,7 +125,7 @@ type updateFeatureMetadataInput struct { func (h *Handler) handleUpdateFeatureMetadata(ctx context.Context, body []byte) ([]byte, error) { var req updateFeatureMetadataInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -161,7 +163,7 @@ func (h *Handler) handleUpdateFeatureMetadata(ctx context.Context, body []byte) return nil, updateErr } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // featureExistsInGroup reports whether featureName is one of fg's defined features. diff --git a/services/sagemaker/handler_feature_metadata_test.go b/services/sagemaker/handler_feature_metadata_test.go index 1be34e3fa0..c58c87ef01 100644 --- a/services/sagemaker/handler_feature_metadata_test.go +++ b/services/sagemaker/handler_feature_metadata_test.go @@ -2,13 +2,14 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -45,7 +46,7 @@ func TestHandler_UpdateAndDescribeFeatureMetadata(t *testing.T) { assert.Equal(t, http.StatusOK, recDescribe.Code) var describeOut map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &describeOut)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &describeOut, jsonx.V1())) assert.Equal(t, "the record id", describeOut["Description"]) assert.Equal(t, "id", describeOut["FeatureName"]) assert.Equal(t, "Integral", describeOut["FeatureType"]) @@ -90,7 +91,7 @@ func TestHandler_UpdateFeatureMetadata_ParameterRemovals(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) params, ok := out["Parameters"].([]any) require.True(t, ok) @@ -124,7 +125,7 @@ func TestHandler_DescribeFeatureMetadata_LastModifiedTimeDefaultsToGroupCreation require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, out["CreationTime"], out["LastModifiedTime"], "a never-updated feature's LastModifiedTime falls back to the group's CreationTime") diff --git a/services/sagemaker/handler_flow_definitions.go b/services/sagemaker/handler_flow_definitions.go index 2210e8b723..ec92feda9a 100644 --- a/services/sagemaker/handler_flow_definitions.go +++ b/services/sagemaker/handler_flow_definitions.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -48,7 +50,7 @@ type createFlowDefinitionInput struct { func (h *Handler) handleCreateFlowDefinition(ctx context.Context, body []byte) ([]byte, error) { var req createFlowDefinitionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -97,7 +99,7 @@ func (h *Handler) handleCreateFlowDefinition(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(map[string]any{keyFlowDefinitionArn: result.FlowDefinitionArn}) + return json.Marshal(map[string]any{keyFlowDefinitionArn: result.FlowDefinitionArn}, jsonx.V1()) } // describeFlowDefinitionInput mirrors DescribeFlowDefinitionInput @@ -109,7 +111,7 @@ type describeFlowDefinitionInput struct { func (h *Handler) handleDescribeFlowDefinition(ctx context.Context, body []byte) ([]byte, error) { var req describeFlowDefinitionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -122,7 +124,7 @@ func (h *Handler) handleDescribeFlowDefinition(ctx context.Context, body []byte) return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteFlowDefinitionInput mirrors DeleteFlowDefinitionInput @@ -134,7 +136,7 @@ type deleteFlowDefinitionInput struct { func (h *Handler) handleDeleteFlowDefinition(ctx context.Context, body []byte) error { var req deleteFlowDefinitionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -163,7 +165,7 @@ type listFlowDefinitionsInput struct { func (h *Handler) handleListFlowDefinitions(ctx context.Context, body []byte) ([]byte, error) { var req listFlowDefinitionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_flow_definitions_test.go b/services/sagemaker/handler_flow_definitions_test.go index 4b57454038..a844285745 100644 --- a/services/sagemaker/handler_flow_definitions_test.go +++ b/services/sagemaker/handler_flow_definitions_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func createFlowDefinitionRequest(name string) map[string]any { @@ -29,7 +31,7 @@ func TestHandler_CreateFlowDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["FlowDefinitionArn"], "my-flow") } @@ -77,7 +79,7 @@ func TestHandler_DescribeFlowDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "flow-1", resp["FlowDefinitionName"]) } @@ -152,13 +154,13 @@ func TestHandler_ListFlowDefinitions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["FlowDefinitionSummaries"]) doSageMakerRequest(t, h, "CreateFlowDefinition", createFlowDefinitionRequest("my-flow")) rec = doSageMakerRequest(t, h, "ListFlowDefinitions", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) defs := resp["FlowDefinitionSummaries"].([]any) assert.Len(t, defs, 1) d := defs[0].(map[string]any) diff --git a/services/sagemaker/handler_hp_tuning_jobs.go b/services/sagemaker/handler_hp_tuning_jobs.go index 005d212c7f..6717d846f0 100644 --- a/services/sagemaker/handler_hp_tuning_jobs.go +++ b/services/sagemaker/handler_hp_tuning_jobs.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -30,13 +32,13 @@ type hpResourceLimitsRequest struct { // one Unmarshal pass — encoding/json drops both silently on that ambiguity — // hence the second decode.) type createHPTuningJobRequest struct { - HyperParameterTuningJobName string `json:"HyperParameterTuningJobName"` - HyperParameterTuningJobConfig json.RawMessage `json:"HyperParameterTuningJobConfig"` - Autotune json.RawMessage `json:"Autotune"` - WarmStartConfig json.RawMessage `json:"WarmStartConfig"` - TrainingJobDefinition json.RawMessage `json:"TrainingJobDefinition"` - TrainingJobDefinitions json.RawMessage `json:"TrainingJobDefinitions"` - Tags []tagObject `json:"Tags"` + HyperParameterTuningJobName string `json:"HyperParameterTuningJobName"` + HyperParameterTuningJobConfig jsontext.Value `json:"HyperParameterTuningJobConfig"` + Autotune jsontext.Value `json:"Autotune"` + WarmStartConfig jsontext.Value `json:"WarmStartConfig"` + TrainingJobDefinition jsontext.Value `json:"TrainingJobDefinition"` + TrainingJobDefinitions jsontext.Value `json:"TrainingJobDefinitions"` + Tags []tagObject `json:"Tags"` } // hpTuningJobConfigStrategyAndLimits mirrors the Strategy/ResourceLimits @@ -51,7 +53,7 @@ func (h *Handler) handleCreateHyperParameterTuningJob( body []byte, ) ([]byte, error) { var req createHPTuningJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -64,7 +66,7 @@ func (h *Handler) handleCreateHyperParameterTuningJob( } var config hpTuningJobConfigStrategyAndLimits - if err := json.Unmarshal(req.HyperParameterTuningJobConfig, &config); err != nil { + if err := json.Unmarshal(req.HyperParameterTuningJobConfig, &config, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -93,7 +95,7 @@ func (h *Handler) handleCreateHyperParameterTuningJob( log.InfoContext(ctx, "sagemaker: created HP tuning job", "name", j.HyperParameterTuningJobName) return json.Marshal( - map[string]string{"HyperParameterTuningJobArn": j.HyperParameterTuningJobArn}, + map[string]string{"HyperParameterTuningJobArn": j.HyperParameterTuningJobArn}, jsonx.V1(), ) } @@ -109,7 +111,7 @@ func (h *Handler) handleDescribeHyperParameterTuningJob( ) ([]byte, error) { var req describeHPTuningJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -153,7 +155,7 @@ func (h *Handler) handleDescribeHyperParameterTuningJob( resp["HyperParameterTuningEndTime"] = epochSeconds(*j.HyperParameterTuningEndTime) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type hpTuningJobSummary struct { @@ -187,7 +189,7 @@ type listHPTuningJobsInput struct { func (h *Handler) handleListHyperParameterTuningJobs(ctx context.Context, body []byte) ([]byte, error) { var req listHPTuningJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -228,7 +230,7 @@ func (h *Handler) handleListHyperParameterTuningJobs(ctx context.Context, body [ resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // stopHPTuningJobInput mirrors StopHyperParameterTuningJobInput @@ -240,7 +242,7 @@ type stopHPTuningJobInput struct { func (h *Handler) handleStopHyperParameterTuningJob(ctx context.Context, body []byte) error { var req stopHPTuningJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -272,7 +274,7 @@ type deleteHPTuningJobInput struct { func (h *Handler) handleDeleteHyperParameterTuningJob(ctx context.Context, body []byte) error { var req deleteHPTuningJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -328,7 +330,7 @@ func (h *Handler) handleListTrainingJobsForHyperParameterTuningJob( ) ([]byte, error) { var req listTrainingJobsForHPTuningJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -371,5 +373,5 @@ func (h *Handler) handleListTrainingJobsForHyperParameterTuningJob( resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_hp_tuning_jobs_test.go b/services/sagemaker/handler_hp_tuning_jobs_test.go index d84ac73093..441f013ed6 100644 --- a/services/sagemaker/handler_hp_tuning_jobs_test.go +++ b/services/sagemaker/handler_hp_tuning_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -93,7 +94,7 @@ func TestHandler_ListTrainingJobsForHyperParameterTuningJob(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TrainingJobSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, tt.wantSummaries) @@ -125,7 +126,7 @@ func TestHandler_DescribeHyperParameterTuningJob_WireShape(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Real AWS nests Strategy/ResourceLimits inside HyperParameterTuningJobConfig // rather than emitting a flat top-level Strategy field — a client reading @@ -179,7 +180,7 @@ func TestHandler_ListHyperParameterTuningJobs_WireShape(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["HyperParameterTuningJobSummaries"].([]any) require.True(t, ok) @@ -217,7 +218,7 @@ func TestHandler_HyperParameterTuningJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["HyperParameterTuningJobArn"]) // Describe. @@ -231,7 +232,7 @@ func TestHandler_HyperParameterTuningJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["HyperParameterTuningJobSummaries"].([]any), 1) // Stop. @@ -279,7 +280,7 @@ func TestHandler_StopHyperParameterTuningJob_ReachesStopped(t *testing.T) { "HyperParameterTuningJobName": "hpt-stop-reaches", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopping", descResp["HyperParameterTuningJobStatus"]) time.Sleep(time.Second) @@ -288,7 +289,7 @@ func TestHandler_StopHyperParameterTuningJob_ReachesStopped(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeHyperParameterTuningJob", map[string]any{ "HyperParameterTuningJobName": "hpt-stop-reaches", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopped", descResp["HyperParameterTuningJobStatus"]) }) } @@ -319,7 +320,7 @@ func TestHandler_CreateHyperParameterTuningJob_ReachesCompleted(t *testing.T) { "HyperParameterTuningJobName": "hpt-create-reaches-completed", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "InProgress", descResp["HyperParameterTuningJobStatus"]) time.Sleep(time.Second) @@ -328,7 +329,7 @@ func TestHandler_CreateHyperParameterTuningJob_ReachesCompleted(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeHyperParameterTuningJob", map[string]any{ "HyperParameterTuningJobName": "hpt-create-reaches-completed", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Completed", descResp["HyperParameterTuningJobStatus"]) }) } diff --git a/services/sagemaker/handler_hub.go b/services/sagemaker/handler_hub.go index a3e05e6831..d2c73bfb51 100644 --- a/services/sagemaker/handler_hub.go +++ b/services/sagemaker/handler_hub.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -155,7 +156,7 @@ type createHubInput struct { func (h *Handler) handleCreateHub(ctx context.Context, body []byte) ([]byte, error) { var req createHubInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -182,7 +183,7 @@ func (h *Handler) handleCreateHub(ctx context.Context, body []byte) ([]byte, err logger.Load(ctx).InfoContext(ctx, "sagemaker: created hub", "name", hub.HubName) - return json.Marshal(map[string]string{keyHubArn: hub.HubArn}) + return json.Marshal(map[string]string{keyHubArn: hub.HubArn}, jsonx.V1()) } func hubToDescribeResponse(hub *Hub) map[string]any { @@ -226,7 +227,7 @@ type describeHubInput struct { func (h *Handler) handleDescribeHub(ctx context.Context, body []byte) ([]byte, error) { var req describeHubInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -239,7 +240,7 @@ func (h *Handler) handleDescribeHub(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(hubToDescribeResponse(hub)) + return json.Marshal(hubToDescribeResponse(hub), jsonx.V1()) } type hubInfoSummary struct { @@ -270,7 +271,7 @@ type listHubsInput struct { func (h *Handler) handleListHubs(ctx context.Context, body []byte) ([]byte, error) { var req listHubsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -305,7 +306,7 @@ func (h *Handler) handleListHubs(ctx context.Context, body []byte) ([]byte, erro resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateHubInput is the UpdateHub request shape (named, not inline — see @@ -320,7 +321,7 @@ type updateHubInput struct { func (h *Handler) handleUpdateHub(ctx context.Context, body []byte) ([]byte, error) { var req updateHubInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -339,7 +340,7 @@ func (h *Handler) handleUpdateHub(ctx context.Context, body []byte) ([]byte, err return nil, err } - return json.Marshal(map[string]string{keyHubArn: hub.HubArn}) + return json.Marshal(map[string]string{keyHubArn: hub.HubArn}, jsonx.V1()) } // deleteHubInput is the DeleteHub request shape (named, not inline — see @@ -351,7 +352,7 @@ type deleteHubInput struct { func (h *Handler) handleDeleteHub(ctx context.Context, body []byte) error { var req deleteHubInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -393,7 +394,7 @@ type importHubContentInput struct { func (h *Handler) handleImportHubContent(ctx context.Context, body []byte) ([]byte, error) { var req importHubContentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -423,7 +424,7 @@ func (h *Handler) handleImportHubContent(ctx context.Context, body []byte) ([]by logger.Load(ctx).InfoContext(ctx, "sagemaker: imported hub content", "hub", hc.HubName, "name", hc.HubContentName, "version", hc.HubContentVersion) - return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}) + return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}, jsonx.V1()) } // requireImportHubContentFields returns the name of the first missing required @@ -535,7 +536,7 @@ type describeHubContentInput struct { func (h *Handler) handleDescribeHubContent(ctx context.Context, body []byte) ([]byte, error) { var req describeHubContentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -552,7 +553,7 @@ func (h *Handler) handleDescribeHubContent(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(hubContentToDescribeResponse(hc)) + return json.Marshal(hubContentToDescribeResponse(hc), jsonx.V1()) } type hubContentInfoSummary struct { @@ -613,7 +614,7 @@ type listHubContentsInput struct { func (h *Handler) handleListHubContents(ctx context.Context, body []byte) ([]byte, error) { var req listHubContentsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -642,7 +643,7 @@ func (h *Handler) handleListHubContents(ctx context.Context, body []byte) ([]byt resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listHubContentVersionsInput is the ListHubContentVersions request shape @@ -665,7 +666,7 @@ type listHubContentVersionsInput struct { func (h *Handler) handleListHubContentVersions(ctx context.Context, body []byte) ([]byte, error) { var req listHubContentVersionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -698,7 +699,7 @@ func (h *Handler) handleListHubContentVersions(ctx context.Context, body []byte) resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteHubContentInput is the DeleteHubContent request shape (named, not @@ -714,7 +715,7 @@ type deleteHubContentInput struct { func (h *Handler) handleDeleteHubContent(ctx context.Context, body []byte) error { var req deleteHubContentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -750,7 +751,7 @@ type createHubContentReferenceInput struct { func (h *Handler) handleCreateHubContentReference(ctx context.Context, body []byte) ([]byte, error) { var req createHubContentReferenceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -768,7 +769,7 @@ func (h *Handler) handleCreateHubContentReference(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}) + return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}, jsonx.V1()) } // deleteHubContentReferenceInput is the DeleteHubContentReference request @@ -783,7 +784,7 @@ type deleteHubContentReferenceInput struct { func (h *Handler) handleDeleteHubContentReference(ctx context.Context, body []byte) error { var req deleteHubContentReferenceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -814,7 +815,7 @@ type updateHubContentInput struct { func (h *Handler) handleUpdateHubContent(ctx context.Context, body []byte) ([]byte, error) { var req updateHubContentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -838,7 +839,7 @@ func (h *Handler) handleUpdateHubContent(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}) + return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}, jsonx.V1()) } // updateHubContentReferenceInput is the UpdateHubContentReference request @@ -854,7 +855,7 @@ type updateHubContentReferenceInput struct { func (h *Handler) handleUpdateHubContentReference(ctx context.Context, body []byte) ([]byte, error) { var req updateHubContentReferenceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -871,7 +872,7 @@ func (h *Handler) handleUpdateHubContentReference(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}) + return json.Marshal(map[string]string{keyHubArn: hc.HubArn, keyHubContentArn: hc.HubContentArn}, jsonx.V1()) } // presignedURLAccessConfigJSON is the wire shape of PresignedUrlAccessConfig @@ -898,7 +899,7 @@ type createHubContentPresignedURLsInput struct { func (h *Handler) handleCreateHubContentPresignedURLs(ctx context.Context, body []byte) ([]byte, error) { var req createHubContentPresignedURLsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -938,5 +939,5 @@ func (h *Handler) handleCreateHubContentPresignedURLs(ctx context.Context, body resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_hub_test.go b/services/sagemaker/handler_hub_test.go index 83b52c0540..f743f6a524 100644 --- a/services/sagemaker/handler_hub_test.go +++ b/services/sagemaker/handler_hub_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -55,7 +57,7 @@ func TestHandler_CreateHub(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["HubArn"], "hub/my-hub") } }) @@ -95,7 +97,7 @@ func TestHandler_HubLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "lifecycle-hub", desc["HubName"]) assert.Equal(t, "InService", desc["HubStatus"]) assert.Equal(t, "initial description", desc["HubDescription"]) @@ -117,7 +119,7 @@ func TestHandler_HubLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc2.Code) var desc2 map[string]any - require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &desc2)) + require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &desc2, jsonx.V1())) assert.Equal(t, "updated description", desc2["HubDescription"]) // Untouched field should be preserved. assert.Equal(t, "Lifecycle Hub", desc2["HubDisplayName"]) @@ -164,7 +166,7 @@ func TestHandler_ListHubs(t *testing.T) { var resp struct { HubSummaries []map[string]any `json:"HubSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.HubSummaries, 3) // NameContains filter. @@ -174,7 +176,7 @@ func TestHandler_ListHubs(t *testing.T) { var filtered struct { HubSummaries []map[string]any `json:"HubSummaries"` } - require.NoError(t, json.Unmarshal(recFiltered.Body.Bytes(), &filtered)) + require.NoError(t, json.Unmarshal(recFiltered.Body.Bytes(), &filtered, jsonx.V1())) require.Len(t, filtered.HubSummaries, 1) assert.Equal(t, "beta-hub", filtered.HubSummaries[0]["HubName"]) } @@ -363,7 +365,7 @@ func TestHandler_ImportHubContent(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["HubArn"]) assert.Contains(t, resp["HubContentArn"], "hub-content/content-hub/Model/my-model") } @@ -428,7 +430,7 @@ func TestHandler_DescribeHubContent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-model", resp["HubContentName"]) assert.Equal(t, "2.0.0", resp["HubContentVersion"]) assert.Equal(t, "Model", resp["HubContentType"]) @@ -486,7 +488,7 @@ func TestHandler_HubContent_ListsAndVersions(t *testing.T) { var listResp struct { HubContentSummaries []map[string]any `json:"HubContentSummaries"` } - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.HubContentSummaries, 2) // ListHubContentVersions returns every version of one named content. @@ -498,7 +500,7 @@ func TestHandler_HubContent_ListsAndVersions(t *testing.T) { var versionsResp struct { HubContentSummaries []map[string]any `json:"HubContentSummaries"` } - require.NoError(t, json.Unmarshal(recVersions.Body.Bytes(), &versionsResp)) + require.NoError(t, json.Unmarshal(recVersions.Body.Bytes(), &versionsResp, jsonx.V1())) require.Len(t, versionsResp.HubContentSummaries, 3) } @@ -735,7 +737,7 @@ func TestHandler_HubContentReference_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recCreate.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createResp, jsonx.V1())) assert.NotEmpty(t, createResp["HubArn"]) assert.Contains(t, createResp["HubContentArn"], "hub-content/ref-hub/ModelReference/huggingface-model") @@ -746,7 +748,7 @@ func TestHandler_HubContentReference_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var desc map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, publicArn, desc["SageMakerPublicHubContentArn"]) // Duplicate reference is rejected. @@ -805,7 +807,7 @@ func TestHandler_CreateHubContentPresignedUrls(t *testing.T) { var resp struct { AuthorizedURLConfigs []map[string]string `json:"AuthorizedUrlConfigs"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.AuthorizedURLConfigs, 1) assert.Contains(t, resp.AuthorizedURLConfigs[0]["Url"], "https://") assert.NotEmpty(t, resp.AuthorizedURLConfigs[0]["LocalPath"]) @@ -919,7 +921,7 @@ func TestHandler_UpdateHubContent(t *testing.T) { "HubName": "my-hub2", "HubContentName": "model-a", "HubContentType": "Model", }) var out map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "new description", out["HubContentDescription"]) } @@ -942,7 +944,7 @@ func TestHandler_UpdateHubContentReference(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["HubContentArn"]) } diff --git a/services/sagemaker/handler_human_task_ui.go b/services/sagemaker/handler_human_task_ui.go index 9d6a3b1b70..7bccf8a7d4 100644 --- a/services/sagemaker/handler_human_task_ui.go +++ b/services/sagemaker/handler_human_task_ui.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -25,7 +27,7 @@ type createHumanTaskUIInput struct { func (h *Handler) handleCreateHumanTaskUI(ctx context.Context, body []byte) ([]byte, error) { var req createHumanTaskUIInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -44,7 +46,7 @@ func (h *Handler) handleCreateHumanTaskUI(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{keyHumanTaskUIArn: result.HumanTaskUIArn}) + return json.Marshal(map[string]any{keyHumanTaskUIArn: result.HumanTaskUIArn}, jsonx.V1()) } // describeHumanTaskUIInput mirrors DescribeHumanTaskUiInput @@ -56,7 +58,7 @@ type describeHumanTaskUIInput struct { func (h *Handler) handleDescribeHumanTaskUI(ctx context.Context, body []byte) ([]byte, error) { var req describeHumanTaskUIInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -69,7 +71,7 @@ func (h *Handler) handleDescribeHumanTaskUI(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteHumanTaskUIInput mirrors DeleteHumanTaskUiInput @@ -81,7 +83,7 @@ type deleteHumanTaskUIInput struct { func (h *Handler) handleDeleteHumanTaskUI(ctx context.Context, body []byte) error { var req deleteHumanTaskUIInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -107,7 +109,7 @@ type listHumanTaskUIsInput struct { func (h *Handler) handleListHumanTaskUIs(ctx context.Context, body []byte) ([]byte, error) { var req listHumanTaskUIsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_human_task_ui_test.go b/services/sagemaker/handler_human_task_ui_test.go index 61f6e890f1..ad63e71695 100644 --- a/services/sagemaker/handler_human_task_ui_test.go +++ b/services/sagemaker/handler_human_task_ui_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateHumanTaskUI(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_CreateHumanTaskUI(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["HumanTaskUiArn"], "my-ui") } @@ -61,7 +63,7 @@ func TestHandler_DescribeHumanTaskUI(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ui-1", resp["HumanTaskUiName"]) } @@ -110,7 +112,7 @@ func TestHandler_ListHumanTaskUIs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["HumanTaskUiSummaries"]) doSageMakerRequest(t, h, "CreateHumanTaskUi", map[string]any{ @@ -119,7 +121,7 @@ func TestHandler_ListHumanTaskUIs(t *testing.T) { }) rec = doSageMakerRequest(t, h, "ListHumanTaskUis", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) uis := resp["HumanTaskUiSummaries"].([]any) assert.Len(t, uis, 1) u := uis[0].(map[string]any) diff --git a/services/sagemaker/handler_hyperpod_scheduling.go b/services/sagemaker/handler_hyperpod_scheduling.go index 289e90b251..e205007dff 100644 --- a/services/sagemaker/handler_hyperpod_scheduling.go +++ b/services/sagemaker/handler_hyperpod_scheduling.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -21,7 +23,7 @@ type createClusterSchedulerConfigInput struct { func (h *Handler) handleCreateClusterSchedulerConfig(ctx context.Context, body []byte) ([]byte, error) { var req createClusterSchedulerConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -39,7 +41,7 @@ func (h *Handler) handleCreateClusterSchedulerConfig(ctx context.Context, body [ return json.Marshal(map[string]any{ keyClusterSchedulerConfigArn: c.ClusterSchedulerConfigArn, keyClusterSchedulerConfigID: c.ClusterSchedulerConfigID, - }) + }, jsonx.V1()) } type describeClusterSchedulerConfigInput struct { @@ -50,7 +52,7 @@ type describeClusterSchedulerConfigInput struct { func (h *Handler) handleDescribeClusterSchedulerConfig(ctx context.Context, body []byte) ([]byte, error) { var req describeClusterSchedulerConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -61,7 +63,7 @@ func (h *Handler) handleDescribeClusterSchedulerConfig(ctx context.Context, body return nil, err } - return json.Marshal(c) + return json.Marshal(c, jsonx.V1()) } type listClusterSchedulerConfigsInput struct { @@ -79,7 +81,7 @@ type listClusterSchedulerConfigsInput struct { func (h *Handler) handleListClusterSchedulerConfigs(ctx context.Context, body []byte) ([]byte, error) { var req listClusterSchedulerConfigsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -122,7 +124,7 @@ type updateClusterSchedulerConfigInput struct { func (h *Handler) handleUpdateClusterSchedulerConfig(ctx context.Context, body []byte) ([]byte, error) { var req updateClusterSchedulerConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -142,7 +144,7 @@ func (h *Handler) handleUpdateClusterSchedulerConfig(ctx context.Context, body [ return json.Marshal(map[string]any{ keyClusterSchedulerConfigArn: c.ClusterSchedulerConfigArn, keyClusterSchedulerConfigVersion: c.ClusterSchedulerConfigVersion, - }) + }, jsonx.V1()) } type deleteClusterSchedulerConfigInput struct { @@ -152,7 +154,7 @@ type deleteClusterSchedulerConfigInput struct { func (h *Handler) handleDeleteClusterSchedulerConfig(ctx context.Context, body []byte) ([]byte, error) { var req deleteClusterSchedulerConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -160,7 +162,7 @@ func (h *Handler) handleDeleteClusterSchedulerConfig(ctx context.Context, body [ return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -180,7 +182,7 @@ type createComputeQuotaInput struct { func (h *Handler) handleCreateComputeQuota(ctx context.Context, body []byte) ([]byte, error) { var req createComputeQuotaInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -200,7 +202,7 @@ func (h *Handler) handleCreateComputeQuota(ctx context.Context, body []byte) ([] return json.Marshal(map[string]any{ keyComputeQuotaArn: q.ComputeQuotaArn, keyComputeQuotaID: q.ComputeQuotaID, - }) + }, jsonx.V1()) } type describeComputeQuotaInput struct { @@ -211,7 +213,7 @@ type describeComputeQuotaInput struct { func (h *Handler) handleDescribeComputeQuota(ctx context.Context, body []byte) ([]byte, error) { var req describeComputeQuotaInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -220,7 +222,7 @@ func (h *Handler) handleDescribeComputeQuota(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(q) + return json.Marshal(q, jsonx.V1()) } type listComputeQuotasInput struct { @@ -238,7 +240,7 @@ type listComputeQuotasInput struct { func (h *Handler) handleListComputeQuotas(ctx context.Context, body []byte) ([]byte, error) { var req listComputeQuotasInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -286,7 +288,7 @@ type updateComputeQuotaInput struct { func (h *Handler) handleUpdateComputeQuota(ctx context.Context, body []byte) ([]byte, error) { var req updateComputeQuotaInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -307,7 +309,7 @@ func (h *Handler) handleUpdateComputeQuota(ctx context.Context, body []byte) ([] return json.Marshal(map[string]any{ keyComputeQuotaArn: q.ComputeQuotaArn, keyComputeQuotaVersion: q.ComputeQuotaVersion, - }) + }, jsonx.V1()) } type deleteComputeQuotaInput struct { @@ -317,7 +319,7 @@ type deleteComputeQuotaInput struct { func (h *Handler) handleDeleteComputeQuota(ctx context.Context, body []byte) ([]byte, error) { var req deleteComputeQuotaInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, err } @@ -325,5 +327,5 @@ func (h *Handler) handleDeleteComputeQuota(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/sagemaker/handler_images.go b/services/sagemaker/handler_images.go index 87d4012ce5..55618dda53 100644 --- a/services/sagemaker/handler_images.go +++ b/services/sagemaker/handler_images.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -21,7 +23,7 @@ type createImageInput struct { func (h *Handler) handleCreateImage(ctx context.Context, body []byte) ([]byte, error) { var req createImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -36,7 +38,7 @@ func (h *Handler) handleCreateImage(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]any{"ImageArn": result.ImageArn}) + return json.Marshal(map[string]any{"ImageArn": result.ImageArn}, jsonx.V1()) } type describeImageInput struct { @@ -46,7 +48,7 @@ type describeImageInput struct { func (h *Handler) handleDescribeImage(ctx context.Context, body []byte) ([]byte, error) { var req describeImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -59,7 +61,7 @@ func (h *Handler) handleDescribeImage(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } type deleteImageInput struct { @@ -69,7 +71,7 @@ type deleteImageInput struct { func (h *Handler) handleDeleteImage(ctx context.Context, body []byte) error { var req deleteImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -95,7 +97,7 @@ type listImagesInput struct { func (h *Handler) handleListImages(ctx context.Context, body []byte) ([]byte, error) { var req listImagesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -135,7 +137,7 @@ func (h *Handler) handleListImages(ctx context.Context, body []byte) ([]byte, er return json.Marshal(map[string]any{ "Images": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } type updateImageInput struct { @@ -149,7 +151,7 @@ type updateImageInput struct { func (h *Handler) handleUpdateImage(ctx context.Context, body []byte) ([]byte, error) { var req updateImageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -167,7 +169,7 @@ func (h *Handler) handleUpdateImage(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]any{keyImageArn: result.ImageArn}) + return json.Marshal(map[string]any{keyImageArn: result.ImageArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -191,7 +193,7 @@ type createImageVersionInput struct { func (h *Handler) handleCreateImageVersion(ctx context.Context, body []byte) ([]byte, error) { var req createImageVersionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -214,7 +216,7 @@ func (h *Handler) handleCreateImageVersion(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{"ImageVersionArn": result.ImageVersionArn}) + return json.Marshal(map[string]any{"ImageVersionArn": result.ImageVersionArn}, jsonx.V1()) } type describeImageVersionInput struct { @@ -226,7 +228,7 @@ type describeImageVersionInput struct { func (h *Handler) handleDescribeImageVersion(ctx context.Context, body []byte) ([]byte, error) { var req describeImageVersionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -241,7 +243,7 @@ func (h *Handler) handleDescribeImageVersion(ctx context.Context, body []byte) ( result.ClientToken = "" - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } type deleteImageVersionInput struct { @@ -253,7 +255,7 @@ type deleteImageVersionInput struct { func (h *Handler) handleDeleteImageVersion(ctx context.Context, body []byte) error { var req deleteImageVersionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -279,7 +281,7 @@ type listImageVersionsInput struct { func (h *Handler) handleListImageVersions(ctx context.Context, body []byte) ([]byte, error) { var req listImageVersionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -313,7 +315,7 @@ func (h *Handler) handleListImageVersions(ctx context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "ImageVersions": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } type updateImageVersionInput struct { @@ -334,7 +336,7 @@ type updateImageVersionInput struct { func (h *Handler) handleUpdateImageVersion(ctx context.Context, body []byte) ([]byte, error) { var req updateImageVersionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -358,7 +360,7 @@ func (h *Handler) handleUpdateImageVersion(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{keyImageVersionArn: result.ImageVersionArn}) + return json.Marshal(map[string]any{keyImageVersionArn: result.ImageVersionArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -376,7 +378,7 @@ type listAliasesInput struct { func (h *Handler) handleListAliases(ctx context.Context, body []byte) ([]byte, error) { var req listAliasesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -396,5 +398,5 @@ func (h *Handler) handleListAliases(ctx context.Context, body []byte) ([]byte, e resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_images_test.go b/services/sagemaker/handler_images_test.go index 0f342f0064..c327c2b132 100644 --- a/services/sagemaker/handler_images_test.go +++ b/services/sagemaker/handler_images_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateImage(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_CreateImage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ImageArn"], "my-image") } @@ -40,7 +42,7 @@ func TestHandler_DescribeImage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "img-1", resp["ImageName"]) assert.Equal(t, "CREATED", resp["ImageStatus"]) } @@ -70,7 +72,7 @@ func TestHandler_ListImages(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Images"].([]any) assert.Len(t, items, 2) } @@ -92,7 +94,7 @@ func TestHandler_CreateImageVersion(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ImageVersionArn"], "img-ver") } @@ -110,7 +112,7 @@ func TestHandler_DescribeImageVersion(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InEpsilon(t, float64(1), resp["Version"], 0.001) assert.Equal(t, "CREATED", resp["ImageVersionStatus"]) } @@ -132,7 +134,7 @@ func TestHandler_ListImageVersions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ImageVersions"].([]any) assert.Len(t, items, 2) } @@ -208,7 +210,7 @@ func TestHandler_ListAliases(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) aliases, _ := out["SageMakerImageVersionAliases"].([]any) assert.ElementsMatch(t, []any{"latest", "stable"}, aliases) } @@ -249,7 +251,7 @@ func TestHandler_UpdateImage(t *testing.T) { }) var resp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "updated", resp["Description"]) assert.Equal(t, "My Image", resp["DisplayName"]) @@ -264,7 +266,7 @@ func TestHandler_UpdateImage(t *testing.T) { }) var resp2 map[string]any - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Empty(t, resp2["Description"]) } @@ -307,7 +309,7 @@ func TestHandler_UpdateImageVersion(t *testing.T) { }) var resp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PyTorch 2.0", resp["MLFramework"]) aliases, ok := resp["Aliases"].([]any) require.True(t, ok) @@ -326,7 +328,7 @@ func TestHandler_UpdateImageVersion(t *testing.T) { }) var resp2 map[string]any - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &resp2, jsonx.V1())) aliases2, ok := resp2["Aliases"].([]any) require.True(t, ok) assert.Len(t, aliases2, 1) diff --git a/services/sagemaker/handler_inference_components.go b/services/sagemaker/handler_inference_components.go index 2664af7272..15d04a535d 100644 --- a/services/sagemaker/handler_inference_components.go +++ b/services/sagemaker/handler_inference_components.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -25,7 +28,7 @@ type createInferenceComponentInput struct { func (h *Handler) handleCreateInferenceComponent(ctx context.Context, body []byte) ([]byte, error) { var req createInferenceComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -57,7 +60,7 @@ func (h *Handler) handleCreateInferenceComponent(ctx context.Context, body []byt return json.Marshal(map[string]any{ keyInferenceComponentArn: c.InferenceComponentArn, - }) + }, jsonx.V1()) } // inferenceComponentResponseMap builds the DescribeInferenceComponentOutput @@ -123,7 +126,7 @@ type describeInferenceComponentInput struct { func (h *Handler) handleDescribeInferenceComponent(ctx context.Context, body []byte) ([]byte, error) { var req describeInferenceComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -132,7 +135,7 @@ func (h *Handler) handleDescribeInferenceComponent(ctx context.Context, body []b return nil, err } - return json.Marshal(inferenceComponentResponseMap(c)) + return json.Marshal(inferenceComponentResponseMap(c), jsonx.V1()) } // listInferenceComponentsInput mirrors ListInferenceComponentsInput @@ -155,7 +158,7 @@ type listInferenceComponentsInput struct { func (h *Handler) handleListInferenceComponents(ctx context.Context, body []byte) ([]byte, error) { var req listInferenceComponentsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -200,7 +203,7 @@ func (h *Handler) handleListInferenceComponents(ctx context.Context, body []byte // (api_op_UpdateInferenceComponent.go:24-53). The real op has no VariantName // member — a production variant is fixed at Create time. type updateInferenceComponentInput struct { - DeploymentConfig json.RawMessage `json:"DeploymentConfig"` + DeploymentConfig jsontext.Value `json:"DeploymentConfig"` RuntimeConfig *InferenceComponentRuntimeConfigInput `json:"RuntimeConfig"` InferenceComponentName string `json:"InferenceComponentName"` Specification *InferenceComponentSpecification `json:"Specification"` @@ -210,7 +213,7 @@ type updateInferenceComponentInput struct { func (h *Handler) handleUpdateInferenceComponent(ctx context.Context, body []byte) ([]byte, error) { var req updateInferenceComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -234,7 +237,7 @@ func (h *Handler) handleUpdateInferenceComponent(ctx context.Context, body []byt return json.Marshal(map[string]any{ keyInferenceComponentArn: c.InferenceComponentArn, - }) + }, jsonx.V1()) } // updateInferenceComponentRuntimeConfigInput mirrors @@ -247,7 +250,7 @@ type updateInferenceComponentRuntimeConfigInput struct { func (h *Handler) handleUpdateInferenceComponentRuntimeConfig(ctx context.Context, body []byte) ([]byte, error) { var req updateInferenceComponentRuntimeConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -272,7 +275,7 @@ func (h *Handler) handleUpdateInferenceComponentRuntimeConfig(ctx context.Contex return json.Marshal(map[string]any{ keyInferenceComponentArn: c.InferenceComponentArn, - }) + }, jsonx.V1()) } // deleteInferenceComponentInput mirrors DeleteInferenceComponentInput @@ -284,7 +287,7 @@ type deleteInferenceComponentInput struct { func (h *Handler) handleDeleteInferenceComponent(ctx context.Context, body []byte) ([]byte, error) { var req deleteInferenceComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -292,5 +295,5 @@ func (h *Handler) handleDeleteInferenceComponent(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/sagemaker/handler_inference_components_test.go b/services/sagemaker/handler_inference_components_test.go index 9da5a15ba0..9409304470 100644 --- a/services/sagemaker/handler_inference_components_test.go +++ b/services/sagemaker/handler_inference_components_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_InferenceComponentLifecycle(t *testing.T) { @@ -32,7 +34,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["InferenceComponentArn"], "my-component") // Describe @@ -42,7 +44,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-component", descResp["InferenceComponentName"]) assert.Equal(t, "my-endpoint", descResp["EndpointName"]) assert.Contains(t, descResp["EndpointArn"], "endpoint/my-endpoint") @@ -62,7 +64,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeInferenceComponent", map[string]any{ "InferenceComponentName": "my-component", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "InService", descResp["InferenceComponentStatus"]) runtimeConfig, ok = descResp["RuntimeConfig"].(map[string]any) @@ -74,7 +76,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) components := listResp["InferenceComponents"].([]any) require.Len(t, components, 1) @@ -91,7 +93,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Contains(t, updateResp["InferenceComponentArn"], "my-component") // Update component: DeploymentConfig is opaque and echoed back verbatim @@ -110,7 +112,7 @@ func TestHandler_InferenceComponentLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeInferenceComponent", map[string]any{ "InferenceComponentName": "my-component", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Updating", descResp["InferenceComponentStatus"]) lastDeploymentConfig, ok := descResp["LastDeploymentConfig"].(map[string]any) @@ -203,7 +205,7 @@ func TestHandler_CreateInferenceComponent_SpecificationContainerImage(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) spec, ok := resp["Specification"].(map[string]any) require.True(t, ok) @@ -255,7 +257,7 @@ func TestHandler_ListInferenceComponents_Filters(t *testing.T) { rec := doSageMakerRequest(t, h, "ListInferenceComponents", map[string]any{"StatusEquals": "InService"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) components, _ := resp["InferenceComponents"].([]any) require.Len(t, components, 2) @@ -289,7 +291,7 @@ func TestHandler_ListInferenceComponents_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) components, _ := resp["InferenceComponents"].([]any) assert.Len(t, components, tc.wantCount) }) @@ -314,7 +316,7 @@ func TestHandler_ListInferenceComponents_SortByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) components, ok := resp["InferenceComponents"].([]any) require.True(t, ok) require.Len(t, components, 2) @@ -356,7 +358,7 @@ func TestHandler_ListInferenceComponents_EndpointFilter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) components := resp["InferenceComponents"].([]any) assert.Len(t, components, 1) } diff --git a/services/sagemaker/handler_inference_experiments.go b/services/sagemaker/handler_inference_experiments.go index e9df5afd74..c20181158f 100644 --- a/services/sagemaker/handler_inference_experiments.go +++ b/services/sagemaker/handler_inference_experiments.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -35,7 +37,7 @@ type createInferenceExperimentInput struct { func (h *Handler) handleCreateInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req createInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -69,7 +71,7 @@ func (h *Handler) handleCreateInferenceExperiment(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}) + return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}, jsonx.V1()) } // describeInferenceExperimentInput mirrors DescribeInferenceExperimentInput @@ -81,7 +83,7 @@ type describeInferenceExperimentInput struct { func (h *Handler) handleDescribeInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req describeInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -94,7 +96,7 @@ func (h *Handler) handleDescribeInferenceExperiment(ctx context.Context, body [] return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // stopInferenceExperimentInput mirrors StopInferenceExperimentInput @@ -115,7 +117,7 @@ type stopInferenceExperimentInput struct { func (h *Handler) handleStopInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req stopInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -133,7 +135,7 @@ func (h *Handler) handleStopInferenceExperiment(ctx context.Context, body []byte return nil, err } - return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}) + return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}, jsonx.V1()) } // deleteInferenceExperimentInput mirrors DeleteInferenceExperimentInput @@ -149,7 +151,7 @@ type deleteInferenceExperimentInput struct { func (h *Handler) handleDeleteInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req deleteInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -162,7 +164,7 @@ func (h *Handler) handleDeleteInferenceExperiment(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]any{keyInferenceExperimentArn: arn}) + return json.Marshal(map[string]any{keyInferenceExperimentArn: arn}, jsonx.V1()) } // startInferenceExperimentInput mirrors StartInferenceExperimentInput @@ -174,7 +176,7 @@ type startInferenceExperimentInput struct { func (h *Handler) handleStartInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req startInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -187,7 +189,7 @@ func (h *Handler) handleStartInferenceExperiment(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}) + return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}, jsonx.V1()) } // updateInferenceExperimentInput mirrors UpdateInferenceExperimentInput @@ -205,7 +207,7 @@ type updateInferenceExperimentInput struct { func (h *Handler) handleUpdateInferenceExperiment(ctx context.Context, body []byte) ([]byte, error) { var req updateInferenceExperimentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -224,7 +226,7 @@ func (h *Handler) handleUpdateInferenceExperiment(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}) + return json.Marshal(map[string]any{keyInferenceExperimentArn: result.Arn}, jsonx.V1()) } // listInferenceExperimentsInput mirrors ListInferenceExperimentsInput @@ -249,7 +251,7 @@ type listInferenceExperimentsInput struct { func (h *Handler) handleListInferenceExperiments(ctx context.Context, body []byte) ([]byte, error) { var req listInferenceExperimentsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_inference_experiments_test.go b/services/sagemaker/handler_inference_experiments_test.go index 9a5a9979dd..be75919bc8 100644 --- a/services/sagemaker/handler_inference_experiments_test.go +++ b/services/sagemaker/handler_inference_experiments_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func minimalInferenceExperimentBody(name string) map[string]any { @@ -35,7 +37,7 @@ func TestHandler_CreateInferenceExperiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["InferenceExperimentArn"], "my-exp") } @@ -80,7 +82,7 @@ func TestHandler_DescribeInferenceExperiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "exp-1", resp["Name"]) assert.Contains(t, resp, "EndpointMetadata") assert.Contains(t, resp, "ModelVariants") @@ -99,7 +101,7 @@ func TestHandler_StopInferenceExperiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["InferenceExperimentArn"], "exp-stop") } @@ -113,7 +115,7 @@ func TestHandler_DeleteInferenceExperiment(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["InferenceExperimentArn"], "exp-del") rec = doSageMakerRequest(t, h, "DescribeInferenceExperiment", map[string]any{"Name": "exp-del"}) @@ -141,7 +143,7 @@ func TestHandler_InferenceExperiment_StartAndUpdate(t *testing.T) { recDescribe := doSageMakerRequest(t, h, "DescribeInferenceExperiment", map[string]any{"Name": "inf-exp"}) var out map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "Running", out["Status"]) assert.Equal(t, "updated", out["Description"]) } @@ -174,7 +176,7 @@ func TestHandler_ListInferenceExperiments(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["InferenceExperiments"]) body := minimalInferenceExperimentBody("my-exp") @@ -182,7 +184,7 @@ func TestHandler_ListInferenceExperiments(t *testing.T) { doSageMakerRequest(t, h, "CreateInferenceExperiment", body) rec = doSageMakerRequest(t, h, "ListInferenceExperiments", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) exps := resp["InferenceExperiments"].([]any) assert.Len(t, exps, 1) e := exps[0].(map[string]any) diff --git a/services/sagemaker/handler_inference_recommendations_jobs.go b/services/sagemaker/handler_inference_recommendations_jobs.go index 04de314f37..b5ebcd9343 100644 --- a/services/sagemaker/handler_inference_recommendations_jobs.go +++ b/services/sagemaker/handler_inference_recommendations_jobs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -13,20 +16,20 @@ import ( // createInferenceRecommendationsJobInput mirrors // CreateInferenceRecommendationsJobInput (api_op_CreateInferenceRecommendationsJob.go:1-58). type createInferenceRecommendationsJobInput struct { - JobName string `json:"JobName"` - JobType string `json:"JobType,omitempty"` - JobDescription string `json:"JobDescription,omitempty"` - RoleArn string `json:"RoleArn,omitempty"` - InputConfig json.RawMessage `json:"InputConfig,omitempty"` - OutputConfig json.RawMessage `json:"OutputConfig,omitempty"` - StoppingConditions json.RawMessage `json:"StoppingConditions,omitempty"` - Tags []tagObject `json:"Tags,omitempty"` + JobName string `json:"JobName"` + JobType string `json:"JobType,omitempty"` + JobDescription string `json:"JobDescription,omitempty"` + RoleArn string `json:"RoleArn,omitempty"` + InputConfig jsontext.Value `json:"InputConfig,omitempty"` + OutputConfig jsontext.Value `json:"OutputConfig,omitempty"` + StoppingConditions jsontext.Value `json:"StoppingConditions,omitempty"` + Tags []tagObject `json:"Tags,omitempty"` } func (h *Handler) handleCreateInferenceRecommendationsJob(ctx context.Context, body []byte) ([]byte, error) { var req createInferenceRecommendationsJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -52,7 +55,7 @@ func (h *Handler) handleCreateInferenceRecommendationsJob(ctx context.Context, b return nil, err } - return json.Marshal(map[string]string{keyJobArn: j.JobArn}) + return json.Marshal(map[string]string{keyJobArn: j.JobArn}, jsonx.V1()) } // describeInferenceRecommendationsJobInput mirrors @@ -64,7 +67,7 @@ type describeInferenceRecommendationsJobInput struct { func (h *Handler) handleDescribeInferenceRecommendationsJob(ctx context.Context, body []byte) ([]byte, error) { var req describeInferenceRecommendationsJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -103,7 +106,7 @@ func (h *Handler) handleDescribeInferenceRecommendationsJob(ctx context.Context, resp["StoppingConditions"] = j.StoppingConditions } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // stopInferenceRecommendationsJobInput mirrors @@ -115,7 +118,7 @@ type stopInferenceRecommendationsJobInput struct { func (h *Handler) handleStopInferenceRecommendationsJob(ctx context.Context, body []byte) error { var req stopInferenceRecommendationsJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -157,7 +160,7 @@ type listInferenceRecommendationsJobsInput struct { func (h *Handler) handleListInferenceRecommendationsJobs(ctx context.Context, body []byte) ([]byte, error) { var req listInferenceRecommendationsJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -198,7 +201,7 @@ func (h *Handler) handleListInferenceRecommendationsJobs(ctx context.Context, bo resp[keyNextToken] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listInferenceRecommendationsJobStepsInput mirrors @@ -218,7 +221,7 @@ type listInferenceRecommendationsJobStepsInput struct { func (h *Handler) handleListInferenceRecommendationsJobSteps(ctx context.Context, body []byte) ([]byte, error) { var req listInferenceRecommendationsJobStepsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -230,5 +233,5 @@ func (h *Handler) handleListInferenceRecommendationsJobSteps(ctx context.Context return nil, err } - return json.Marshal(map[string]any{"Steps": []any{}}) + return json.Marshal(map[string]any{"Steps": []any{}}, jsonx.V1()) } diff --git a/services/sagemaker/handler_inference_recommendations_jobs_test.go b/services/sagemaker/handler_inference_recommendations_jobs_test.go index d9498ca705..e282418017 100644 --- a/services/sagemaker/handler_inference_recommendations_jobs_test.go +++ b/services/sagemaker/handler_inference_recommendations_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -12,6 +12,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { @@ -34,7 +36,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["JobArn"], "my-rec-job") // Describe @@ -44,7 +46,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-rec-job", descResp["JobName"]) assert.Equal(t, "IN_PROGRESS", descResp["Status"]) assert.Equal(t, "Default", descResp["JobType"]) @@ -56,7 +58,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["InferenceRecommendationsJobs"].([]any) assert.Len(t, summaries, 1) @@ -67,7 +69,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var stepsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stepsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stepsResp, jsonx.V1())) steps := stepsResp["Steps"].([]any) assert.Empty(t, steps) @@ -80,7 +82,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeInferenceRecommendationsJob", map[string]any{ "JobName": "my-rec-job", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "STOPPING", descResp["Status"]) // Correct immediately after Stop, but an assertion that only checks this @@ -92,7 +94,7 @@ func TestHandler_InferenceRecommendationsJobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeInferenceRecommendationsJob", map[string]any{ "JobName": "my-rec-job", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "STOPPED", descResp["Status"]) }) } @@ -121,7 +123,7 @@ func TestHandler_InferenceRecommendationsJob_ReachesCompleted(t *testing.T) { "JobName": "rec-job-completes", }) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "COMPLETED", out["Status"]) }) } @@ -150,7 +152,7 @@ func TestHandler_CreateInferenceRecommendationsJob_InputConfigRoundTrip(t *testi require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) inputConfig, ok := descResp["InputConfig"].(map[string]any) require.True(t, ok, "DescribeInferenceRecommendationsJob must return the accepted InputConfig") @@ -211,7 +213,7 @@ func TestHandler_CreateInferenceRecommendationsJob_JobTypeDefault(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Default", resp["JobType"]) } @@ -353,7 +355,7 @@ func TestHandler_AIRecommendationJobLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["AIRecommendationJobArn"], "rec-2") rec = doSageMakerRequest(t, h, "DescribeAIRecommendationJob", map[string]any{ @@ -362,7 +364,7 @@ func TestHandler_AIRecommendationJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "InProgress", descResp["AIRecommendationJobStatus"]) assert.Empty(t, descResp["Recommendations"]) }, @@ -385,7 +387,7 @@ func TestHandler_AIRecommendationJobLifecycle(t *testing.T) { "AIRecommendationJobName": "rec-stop", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopping", descResp["AIRecommendationJobStatus"]) }, }, @@ -422,7 +424,7 @@ func TestHandler_AIRecommendationJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["AIRecommendationJobs"].([]any) require.Len(t, items, 1) assert.Equal(t, "rec-list", items[0].(map[string]any)["AIRecommendationJobName"]) diff --git a/services/sagemaker/handler_jobs.go b/services/sagemaker/handler_jobs.go index a32e9cae97..4c70ce6de4 100644 --- a/services/sagemaker/handler_jobs.go +++ b/services/sagemaker/handler_jobs.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // aiAndGenericJobOpsSupported aggregates the operation lists for the four @@ -87,7 +89,7 @@ type createJobInput struct { func (h *Handler) handleCreateJob(ctx context.Context, body []byte) ([]byte, error) { var req createJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -103,7 +105,7 @@ func (h *Handler) handleCreateJob(ctx context.Context, body []byte) ([]byte, err return nil, err } - return json.Marshal(map[string]string{keyJobArn: j.JobArn}) + return json.Marshal(map[string]string{keyJobArn: j.JobArn}, jsonx.V1()) } // describeJobInput mirrors DescribeJobInput (api_op_DescribeJob.go:27-38): @@ -116,7 +118,7 @@ type describeJobInput struct { func (h *Handler) handleDescribeJob(ctx context.Context, body []byte) ([]byte, error) { var req describeJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -139,13 +141,13 @@ func (h *Handler) handleDescribeJob(ctx context.Context, body []byte) ([]byte, e // had any tags at all. Round-trips through Job.MarshalJSON (for its // epoch-seconds time handling) then substitutes the Tags shape. func marshalJobResponse(j *Job) ([]byte, error) { - raw, err := json.Marshal(j) + raw, err := json.Marshal(j, jsonx.V1()) if err != nil { return nil, err } var resp map[string]any - if unmarshalErr := json.Unmarshal(raw, &resp); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(raw, &resp, jsonx.V1()); unmarshalErr != nil { return nil, unmarshalErr } @@ -155,7 +157,7 @@ func marshalJobResponse(j *Job) ([]byte, error) { delete(resp, "Tags") } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteJobInput mirrors DeleteJobInput (api_op_DeleteJob.go:27-38): both @@ -168,7 +170,7 @@ type deleteJobInput struct { func (h *Handler) handleDeleteJob(ctx context.Context, body []byte) error { var req deleteJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -189,7 +191,7 @@ type stopJobInput struct { func (h *Handler) handleStopJob(ctx context.Context, body []byte) error { var req stopJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -222,7 +224,7 @@ type listJobsInput struct { func (h *Handler) handleListJobs(ctx context.Context, body []byte) ([]byte, error) { var req listJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -278,7 +280,7 @@ type describeJobSchemaVersionInput struct { func (h *Handler) handleDescribeJobSchemaVersion(ctx context.Context, body []byte) ([]byte, error) { var req describeJobSchemaVersionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -295,7 +297,7 @@ func (h *Handler) handleDescribeJobSchemaVersion(ctx context.Context, body []byt "JobCategory": req.JobCategory, "JobConfigSchema": info.JobConfigSchema, "JobConfigSchemaVersion": info.JobConfigSchemaVersion, - }) + }, jsonx.V1()) } // listJobSchemaVersionsInput mirrors ListJobSchemaVersionsInput @@ -310,7 +312,7 @@ type listJobSchemaVersionsInput struct { func (h *Handler) handleListJobSchemaVersions(ctx context.Context, body []byte) ([]byte, error) { var req listJobSchemaVersionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_labeling.go b/services/sagemaker/handler_labeling.go index 2dc833e00d..fd56a14517 100644 --- a/services/sagemaker/handler_labeling.go +++ b/services/sagemaker/handler_labeling.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // labelingOpsSupported returns the labeling-job / workteam-subscription @@ -93,7 +95,7 @@ type createLabelingJobRequest struct { func (h *Handler) handleCreateLabelingJob(ctx context.Context, body []byte) ([]byte, error) { var req createLabelingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -137,7 +139,7 @@ func (h *Handler) handleCreateLabelingJob(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{keyLabelingJobArn: result.LabelingJobArn}) + return json.Marshal(map[string]any{keyLabelingJobArn: result.LabelingJobArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -201,7 +203,7 @@ type describeLabelingJobInput struct { func (h *Handler) handleDescribeLabelingJob(ctx context.Context, body []byte) ([]byte, error) { var req describeLabelingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -214,7 +216,7 @@ func (h *Handler) handleDescribeLabelingJob(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(labelingJobResponseMap(result)) + return json.Marshal(labelingJobResponseMap(result), jsonx.V1()) } // --------------------------------------------------------------------------- @@ -229,7 +231,7 @@ type stopLabelingJobInput struct { func (h *Handler) handleStopLabelingJob(ctx context.Context, body []byte) ([]byte, error) { var req stopLabelingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -241,7 +243,7 @@ func (h *Handler) handleStopLabelingJob(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -280,7 +282,7 @@ type listLabelingJobsInput struct { func (h *Handler) handleListLabelingJobs(ctx context.Context, body []byte) ([]byte, error) { var req listLabelingJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -319,7 +321,7 @@ func (h *Handler) handleListLabelingJobs(ctx context.Context, body []byte) ([]by resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -353,7 +355,7 @@ type listLabelingJobsForWorkteamInput struct { func (h *Handler) handleListLabelingJobsForWorkteam(ctx context.Context, body []byte) ([]byte, error) { var req listLabelingJobsForWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -395,7 +397,7 @@ func (h *Handler) handleListLabelingJobsForWorkteam(ctx context.Context, body [] resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -422,11 +424,11 @@ type listSubscribedWorkteamsInput struct { func (h *Handler) handleListSubscribedWorkteams(_ context.Context, body []byte) ([]byte, error) { var req listSubscribedWorkteamsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } - return json.Marshal(map[string]any{"SubscribedWorkteams": []any{}}) + return json.Marshal(map[string]any{"SubscribedWorkteams": []any{}}, jsonx.V1()) } // describeSubscribedWorkteamInput mirrors DescribeSubscribedWorkteamInput @@ -438,7 +440,7 @@ type describeSubscribedWorkteamInput struct { func (h *Handler) handleDescribeSubscribedWorkteam(_ context.Context, body []byte) error { var req describeSubscribedWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_labeling_test.go b/services/sagemaker/handler_labeling_test.go index 9c0ec7027d..92bc73eea0 100644 --- a/services/sagemaker/handler_labeling_test.go +++ b/services/sagemaker/handler_labeling_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -52,7 +54,7 @@ func TestHandler_CreateLabelingJob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["LabelingJobArn"], "labeling-job/job-1") } @@ -73,7 +75,7 @@ func TestHandler_CreateLabelingJob_TagsRoundTripThroughDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].([]any) require.True(t, ok, "DescribeLabelingJob must return Tags") require.Len(t, tags, 1) @@ -135,7 +137,7 @@ func TestHandler_DescribeLabelingJob_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "job-lifecycle", resp["LabelingJobName"]) assert.Equal(t, "Initializing", resp["LabelingJobStatus"]) assert.NotEmpty(t, resp["JobReferenceCode"]) @@ -148,7 +150,7 @@ func TestHandler_DescribeLabelingJob_Lifecycle(t *testing.T) { synctest.Wait() rec = doSageMakerRequest(t, h, "DescribeLabelingJob", map[string]any{"LabelingJobName": "job-lifecycle"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Completed", resp["LabelingJobStatus"]) }) } @@ -162,7 +164,7 @@ func TestHandler_DescribeLabelingJob_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -186,14 +188,14 @@ func TestHandler_StopLabelingJob(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeLabelingJob", map[string]any{"LabelingJobName": "job-stop"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, []any{"Stopping", "Stopped"}, resp["LabelingJobStatus"]) time.Sleep(time.Second) synctest.Wait() rec = doSageMakerRequest(t, h, "DescribeLabelingJob", map[string]any{"LabelingJobName": "job-stop"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Stopped", resp["LabelingJobStatus"]) }) } @@ -229,7 +231,7 @@ func TestHandler_ListLabelingJobs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["LabelingJobSummaryList"].([]any) require.True(t, ok) assert.Len(t, items, 2) @@ -240,7 +242,7 @@ func TestHandler_ListLabelingJobs(t *testing.T) { // NameContains filter. rec = doSageMakerRequest(t, h, "ListLabelingJobs", map[string]any{"NameContains": "list-job-a"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ = resp["LabelingJobSummaryList"].([]any) assert.Len(t, items, 1) } @@ -269,7 +271,7 @@ func TestHandler_ListLabelingJobsForWorkteam(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["LabelingJobSummaryList"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -308,7 +310,7 @@ func TestHandler_ListLabelingJobs_ResponseIncludesInputConfigAndOutput(t *testin require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["LabelingJobSummaryList"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -322,7 +324,7 @@ func TestHandler_ListLabelingJobs_ResponseIncludesInputConfigAndOutput(t *testin synctest.Wait() rec = doSageMakerRequest(t, h, "ListLabelingJobs", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok = resp["LabelingJobSummaryList"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -378,7 +380,7 @@ func TestHandler_ListLabelingJobs_TimeFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["LabelingJobSummaryList"].([]any) assert.Len(t, items, tc.wantCount) }) @@ -429,7 +431,7 @@ func TestHandler_ListLabelingJobs_SortBy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["LabelingJobSummaryList"].([]any) require.True(t, ok) require.Len(t, items, 2) @@ -454,7 +456,7 @@ func TestHandler_ListLabelingJobsForWorkteam_Filters(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) jobReferenceCode, ok := describeResp["JobReferenceCode"].(string) require.True(t, ok) require.NotEmpty(t, jobReferenceCode) @@ -490,7 +492,7 @@ func TestHandler_ListLabelingJobsForWorkteam_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["LabelingJobSummaryList"].([]any) assert.Len(t, items, tc.wantCount) }) @@ -512,7 +514,7 @@ func TestHandler_ListWorkforces(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Workforces"].([]any) require.True(t, ok) require.Len(t, items, 1) @@ -563,7 +565,7 @@ func TestHandler_DeleteWorkforce_ResourceInUse(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceInUse", resp["__type"]) } @@ -591,7 +593,7 @@ func TestHandler_UpdateWorkforce_WithSourceIPConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wf, ok := resp["Workforce"].(map[string]any) require.True(t, ok) @@ -623,7 +625,7 @@ func TestHandler_CreateWorkteam_WithWorkforceName(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeWorkteam", map[string]any{"WorkteamName": "team-link"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wt, ok := resp["Workteam"].(map[string]any) require.True(t, ok) assert.Contains(t, wt["WorkforceArn"], "workforce/wf-link") @@ -662,7 +664,7 @@ func TestHandler_UpdateWorkteam(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wt, ok := resp["Workteam"].(map[string]any) require.True(t, ok) assert.Equal(t, "after", wt["Description"]) @@ -689,7 +691,7 @@ func TestHandler_DeleteWorkteam_ReturnsSuccess(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, true, resp["Success"]) } @@ -706,7 +708,7 @@ func TestHandler_ListSubscribedWorkteams_AlwaysEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["SubscribedWorkteams"].([]any) require.True(t, ok) assert.Empty(t, items) @@ -724,7 +726,7 @@ func TestHandler_DescribeSubscribedWorkteam_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -782,7 +784,7 @@ func TestLabelingFamily_SnapshotRestore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var wtResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &wtResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &wtResp, jsonx.V1())) wt, ok := wtResp["Workteam"].(map[string]any) require.True(t, ok) assert.Contains(t, wt["WorkforceArn"], "workforce/persist-wf") @@ -791,6 +793,6 @@ func TestLabelingFamily_SnapshotRestore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var jobResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &jobResp, jsonx.V1())) assert.Equal(t, "persist-job", jobResp["LabelingJobName"]) } diff --git a/services/sagemaker/handler_lineage.go b/services/sagemaker/handler_lineage.go index 8127595339..9a1076831a 100644 --- a/services/sagemaker/handler_lineage.go +++ b/services/sagemaker/handler_lineage.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -174,7 +175,7 @@ type createArtifactInput struct { func (h *Handler) handleCreateArtifact(ctx context.Context, body []byte) ([]byte, error) { var req createArtifactInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +202,7 @@ func (h *Handler) handleCreateArtifact(ctx context.Context, body []byte) ([]byte logger.Load(ctx).InfoContext(ctx, "sagemaker: created artifact", "arn", ar.ArtifactArn) - return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}) + return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}, jsonx.V1()) } // describeArtifactInput is the DescribeArtifact request shape (named, not @@ -213,7 +214,7 @@ type describeArtifactInput struct { func (h *Handler) handleDescribeArtifact(ctx context.Context, body []byte) ([]byte, error) { var req describeArtifactInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -245,7 +246,7 @@ func (h *Handler) handleDescribeArtifact(ctx context.Context, body []byte) ([]by resp["MetadataProperties"] = toMetadataProperties(ar.MetadataProperties) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateArtifactInput is the UpdateArtifact request shape (named, not @@ -260,7 +261,7 @@ type updateArtifactInput struct { func (h *Handler) handleUpdateArtifact(ctx context.Context, body []byte) ([]byte, error) { var req updateArtifactInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -275,7 +276,7 @@ func (h *Handler) handleUpdateArtifact(ctx context.Context, body []byte) ([]byte logger.Load(ctx).InfoContext(ctx, "sagemaker: updated artifact", "arn", ar.ArtifactArn) - return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}) + return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}, jsonx.V1()) } // deleteArtifactInput is the DeleteArtifact request shape (named, not @@ -290,7 +291,7 @@ type deleteArtifactInput struct { func (h *Handler) handleDeleteArtifact(ctx context.Context, body []byte) ([]byte, error) { var req deleteArtifactInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -307,7 +308,7 @@ func (h *Handler) handleDeleteArtifact(ctx context.Context, body []byte) ([]byte logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted artifact", "arn", ar.ArtifactArn) - return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}) + return json.Marshal(map[string]string{keyArtifactArn: ar.ArtifactArn}, jsonx.V1()) } type artifactSummary struct { @@ -332,7 +333,7 @@ func marshalSummaryPage[T, S any](key, nextToken string, items []*T, conv func(* resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listArtifactsInput is the ListArtifacts request shape (named, not inline — @@ -351,7 +352,7 @@ type listArtifactsInput struct { func (h *Handler) handleListArtifacts(ctx context.Context, body []byte) ([]byte, error) { var req listArtifactsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -412,7 +413,7 @@ type createContextInput struct { func (h *Handler) handleCreateContext(ctx context.Context, body []byte) ([]byte, error) { var req createContextInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -443,7 +444,7 @@ func (h *Handler) handleCreateContext(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: created context", "name", c.ContextName) - return json.Marshal(map[string]string{keyContextArn: c.ContextArn}) + return json.Marshal(map[string]string{keyContextArn: c.ContextArn}, jsonx.V1()) } // describeContextInput is the DescribeContext request shape (named, not @@ -455,7 +456,7 @@ type describeContextInput struct { func (h *Handler) handleDescribeContext(ctx context.Context, body []byte) ([]byte, error) { var req describeContextInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -484,7 +485,7 @@ func (h *Handler) handleDescribeContext(ctx context.Context, body []byte) ([]byt resp["Properties"] = c.Properties } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateContextInput is the UpdateContext request shape (named, not @@ -499,7 +500,7 @@ type updateContextInput struct { func (h *Handler) handleUpdateContext(ctx context.Context, body []byte) ([]byte, error) { var req updateContextInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -514,7 +515,7 @@ func (h *Handler) handleUpdateContext(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: updated context", "name", c.ContextName) - return json.Marshal(map[string]string{keyContextArn: c.ContextArn}) + return json.Marshal(map[string]string{keyContextArn: c.ContextArn}, jsonx.V1()) } // deleteContextInput is the DeleteContext request shape (named, not @@ -526,7 +527,7 @@ type deleteContextInput struct { func (h *Handler) handleDeleteContext(ctx context.Context, body []byte) ([]byte, error) { var req deleteContextInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -541,7 +542,7 @@ func (h *Handler) handleDeleteContext(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted context", "name", req.ContextName) - return json.Marshal(map[string]string{keyContextArn: c.ContextArn}) + return json.Marshal(map[string]string{keyContextArn: c.ContextArn}, jsonx.V1()) } type contextSummary struct { @@ -569,7 +570,7 @@ type listContextsInput struct { func (h *Handler) handleListContexts(ctx context.Context, body []byte) ([]byte, error) { var req listContextsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -611,7 +612,7 @@ type describeActionInput struct { func (h *Handler) handleDescribeAction(ctx context.Context, body []byte) ([]byte, error) { var req describeActionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -651,7 +652,7 @@ func (h *Handler) handleDescribeAction(ctx context.Context, body []byte) ([]byte resp["MetadataProperties"] = toMetadataProperties(a.MetadataProperties) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateActionInput is the UpdateAction request shape (named, not @@ -667,7 +668,7 @@ type updateActionInput struct { func (h *Handler) handleUpdateAction(ctx context.Context, body []byte) ([]byte, error) { var req updateActionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -684,7 +685,7 @@ func (h *Handler) handleUpdateAction(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: updated action", "name", a.ActionName) - return json.Marshal(map[string]string{keyActionArn: a.ActionArn}) + return json.Marshal(map[string]string{keyActionArn: a.ActionArn}, jsonx.V1()) } // deleteActionInput is the DeleteAction request shape (named, not @@ -696,7 +697,7 @@ type deleteActionInput struct { func (h *Handler) handleDeleteAction(ctx context.Context, body []byte) ([]byte, error) { var req deleteActionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -711,7 +712,7 @@ func (h *Handler) handleDeleteAction(ctx context.Context, body []byte) ([]byte, logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted action", "name", req.ActionName) - return json.Marshal(map[string]string{keyActionArn: a.ActionArn}) + return json.Marshal(map[string]string{keyActionArn: a.ActionArn}, jsonx.V1()) } type actionSummary struct { @@ -740,7 +741,7 @@ type listActionsInput struct { func (h *Handler) handleListActions(ctx context.Context, body []byte) ([]byte, error) { var req listActionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -784,7 +785,7 @@ type deleteAssociationInput struct { func (h *Handler) handleDeleteAssociation(ctx context.Context, body []byte) ([]byte, error) { var req deleteAssociationInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -803,7 +804,7 @@ func (h *Handler) handleDeleteAssociation(ctx context.Context, body []byte) ([]b logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted association", "source", req.SourceArn, "destination", req.DestinationArn) - return json.Marshal(map[string]string{"SourceArn": req.SourceArn, "DestinationArn": req.DestinationArn}) + return json.Marshal(map[string]string{"SourceArn": req.SourceArn, "DestinationArn": req.DestinationArn}, jsonx.V1()) } // associationSummary mirrors types.AssociationSummary (types.go:157-188). @@ -839,7 +840,7 @@ type listAssociationsInput struct { func (h *Handler) handleListAssociations(ctx context.Context, body []byte) ([]byte, error) { var req listAssociationsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -888,7 +889,7 @@ type describeLineageGroupInput struct { func (h *Handler) handleDescribeLineageGroup(ctx context.Context, body []byte) ([]byte, error) { var req describeLineageGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -906,7 +907,7 @@ func (h *Handler) handleDescribeLineageGroup(ctx context.Context, body []byte) ( "LineageGroupName": req.LineageGroupName, keyCreationTime: epochSeconds(createdAt), keyLastModifiedTime: epochSeconds(createdAt), - }) + }, jsonx.V1()) } // listLineageGroupsInput is the ListLineageGroups request shape (named, not @@ -923,7 +924,7 @@ type listLineageGroupsInput struct { func (h *Handler) handleListLineageGroups(ctx context.Context, body []byte) ([]byte, error) { var req listLineageGroupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -951,7 +952,7 @@ func (h *Handler) handleListLineageGroups(ctx context.Context, body []byte) ([]b resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // getLineageGroupPolicyInput is the GetLineageGroupPolicy request shape @@ -963,7 +964,7 @@ type getLineageGroupPolicyInput struct { func (h *Handler) handleGetLineageGroupPolicy(ctx context.Context, body []byte) ([]byte, error) { var req getLineageGroupPolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1007,7 +1008,7 @@ type queryLineageInput struct { func (h *Handler) handleQueryLineage(ctx context.Context, body []byte) ([]byte, error) { var req queryLineageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1056,7 +1057,7 @@ func (h *Handler) handleQueryLineage(ctx context.Context, body []byte) ([]byte, resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // fromQueryFilters converts the wire Filters object to backend QueryLineageFilters. @@ -1087,7 +1088,7 @@ type addAssociationRequest struct { func (h *Handler) handleAddAssociation(ctx context.Context, body []byte) ([]byte, error) { var req addAssociationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1118,7 +1119,7 @@ func (h *Handler) handleAddAssociation(ctx context.Context, body []byte) ([]byte return json.Marshal(map[string]string{ "SourceArn": req.SourceArn, "DestinationArn": req.DestinationArn, - }) + }, jsonx.V1()) } // associateTrialComponentRequest is the request body for AssociateTrialComponent. @@ -1129,7 +1130,7 @@ type associateTrialComponentRequest struct { func (h *Handler) handleAssociateTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req associateTrialComponentRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1153,7 +1154,7 @@ func (h *Handler) handleAssociateTrialComponent(ctx context.Context, body []byte return json.Marshal(map[string]string{ "TrialArn": assoc.TrialArn, "TrialComponentArn": assoc.TrialComponentArn, - }) + }, jsonx.V1()) } // actionSourceRequest is the source for a CreateAction request. @@ -1180,7 +1181,7 @@ type createActionRequest struct { func (h *Handler) handleCreateAction(ctx context.Context, body []byte) ([]byte, error) { var req createActionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -1212,5 +1213,5 @@ func (h *Handler) handleCreateAction(ctx context.Context, body []byte) ([]byte, log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created action", "name", a.ActionName) - return json.Marshal(map[string]string{"ActionArn": a.ActionArn}) + return json.Marshal(map[string]string{"ActionArn": a.ActionArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_lineage_test.go b/services/sagemaker/handler_lineage_test.go index e2875ef159..123c2e8a57 100644 --- a/services/sagemaker/handler_lineage_test.go +++ b/services/sagemaker/handler_lineage_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -34,7 +35,7 @@ func TestHandler_ArtifactLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) artifactArn, _ := createOut["ArtifactArn"].(string) require.NotEmpty(t, artifactArn) assert.Contains(t, artifactArn, "artifact/") @@ -44,7 +45,7 @@ func TestHandler_ArtifactLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "my-artifact", descOut["ArtifactName"]) assert.Equal(t, "DataSet", descOut["ArtifactType"]) assert.NotZero(t, descOut["CreationTime"]) @@ -59,7 +60,7 @@ func TestHandler_ArtifactLifecycle(t *testing.T) { recDesc2 := doSageMakerRequest(t, h, "DescribeArtifact", map[string]any{"ArtifactArn": artifactArn}) var descOut2 map[string]any - require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2, jsonx.V1())) assert.Equal(t, "renamed-artifact", descOut2["ArtifactName"]) props, _ := descOut2["Properties"].(map[string]any) assert.Equal(t, "final", props["stage"]) @@ -70,7 +71,7 @@ func TestHandler_ArtifactLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["ArtifactSummaries"].([]any), 1) // Delete. @@ -79,7 +80,7 @@ func TestHandler_ArtifactLifecycle(t *testing.T) { recList2 := doSageMakerRequest(t, h, "ListArtifacts", map[string]any{}) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2, jsonx.V1())) assert.Empty(t, listOut2["ArtifactSummaries"].([]any)) } @@ -140,7 +141,7 @@ func TestHandler_ListArtifacts_FilterByType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["ArtifactSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "a2", summaries[0].(map[string]any)["ArtifactName"]) @@ -300,7 +301,7 @@ func TestHandler_ContextLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) contextArn, _ := createOut["ContextArn"].(string) require.NotEmpty(t, contextArn) assert.Contains(t, contextArn, "context/my-context") @@ -309,7 +310,7 @@ func TestHandler_ContextLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "Endpoint", descOut["ContextType"]) recUpdate := doSageMakerRequest(t, h, "UpdateContext", map[string]any{ @@ -320,12 +321,12 @@ func TestHandler_ContextLifecycle(t *testing.T) { recDesc2 := doSageMakerRequest(t, h, "DescribeContext", map[string]any{"ContextName": "my-context"}) var descOut2 map[string]any - require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2, jsonx.V1())) assert.Equal(t, "updated", descOut2["Description"]) recList := doSageMakerRequest(t, h, "ListContexts", map[string]any{}) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["ContextSummaries"].([]any), 1) recDelete := doSageMakerRequest(t, h, "DeleteContext", map[string]any{"ContextName": "my-context"}) @@ -428,7 +429,7 @@ func TestHandler_ActionLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "ModelDeployment", descOut["ActionType"]) assert.Equal(t, "InProgress", descOut["Status"]) @@ -440,12 +441,12 @@ func TestHandler_ActionLifecycle(t *testing.T) { recDesc2 := doSageMakerRequest(t, h, "DescribeAction", map[string]any{"ActionName": "my-action"}) var descOut2 map[string]any - require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2)) + require.NoError(t, json.Unmarshal(recDesc2.Body.Bytes(), &descOut2, jsonx.V1())) assert.Equal(t, "Completed", descOut2["Status"]) recList := doSageMakerRequest(t, h, "ListActions", map[string]any{}) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["ActionSummaries"].([]any), 1) recDelete := doSageMakerRequest(t, h, "DeleteAction", map[string]any{"ActionName": "my-action"}) @@ -552,7 +553,7 @@ func TestHandler_AssociationLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) summaries := listOut["AssociationSummaries"].([]any) require.Len(t, summaries, 1) assoc := summaries[0].(map[string]any) @@ -568,7 +569,7 @@ func TestHandler_AssociationLifecycle(t *testing.T) { recList2 := doSageMakerRequest(t, h, "ListAssociations", map[string]any{}) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2, jsonx.V1())) assert.Empty(t, listOut2["AssociationSummaries"].([]any)) } @@ -595,7 +596,7 @@ func TestHandler_ListAssociations_ResolvesEntityNames(t *testing.T) { "Source": map[string]any{"SourceUri": "arn:aws:sagemaker:us-east-1:0:endpoint/e"}, }) var actionOut map[string]any - require.NoError(t, json.Unmarshal(recAction.Body.Bytes(), &actionOut)) + require.NoError(t, json.Unmarshal(recAction.Body.Bytes(), &actionOut, jsonx.V1())) actionArn := actionOut["ActionArn"].(string) recArtifact := doSageMakerRequest(t, h, "CreateArtifact", map[string]any{ @@ -604,7 +605,7 @@ func TestHandler_ListAssociations_ResolvesEntityNames(t *testing.T) { "Source": map[string]any{"SourceUri": "s3://bucket/data"}, }) var artifactOut map[string]any - require.NoError(t, json.Unmarshal(recArtifact.Body.Bytes(), &artifactOut)) + require.NoError(t, json.Unmarshal(recArtifact.Body.Bytes(), &artifactOut, jsonx.V1())) artifactArn := artifactOut["ArtifactArn"].(string) doSageMakerRequest(t, h, "AddAssociation", map[string]any{ @@ -615,7 +616,7 @@ func TestHandler_ListAssociations_ResolvesEntityNames(t *testing.T) { rec := doSageMakerRequest(t, h, "ListAssociations", map[string]any{}) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assoc := out["AssociationSummaries"].([]any)[0].(map[string]any) assert.Equal(t, "src-action", assoc["SourceName"]) assert.Equal(t, "ModelDeployment", assoc["SourceType"]) @@ -656,7 +657,7 @@ func listAssociationSourceArns(t *testing.T, body []byte) []string { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) summaries, _ := out["AssociationSummaries"].([]any) arns := make([]string, 0, len(summaries)) @@ -787,7 +788,7 @@ func TestHandler_ListAssociations_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries, _ := out["AssociationSummaries"].([]any) require.Len(t, summaries, 1, "MaxResults=1 should return exactly one association out of two") @@ -802,7 +803,7 @@ func TestHandler_ListAssociations_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) summaries2, _ := out2["AssociationSummaries"].([]any) require.Len(t, summaries2, 1, "second page should return the remaining association") @@ -844,7 +845,7 @@ func TestHandler_QueryLineage_Traversal(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) vertices := out["Vertices"].([]any) arns := make([]string, 0, len(vertices)) @@ -884,7 +885,7 @@ func TestHandler_QueryLineage_MaxDepth(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) vertices := out["Vertices"].([]any) arns := make([]string, 0, len(vertices)) @@ -917,7 +918,7 @@ func TestHandler_QueryLineage_UnknownArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) vertices := out["Vertices"].([]any) require.Len(t, vertices, 1) assert.Empty(t, vertices[0].(map[string]any)["Type"]) @@ -1042,7 +1043,7 @@ func TestHandler_DescribeLineageGroup(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out["LineageGroupArn"], "lineage-group/sagemaker-default-lineage-group") } @@ -1064,7 +1065,7 @@ func TestHandler_ListLineageGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) summaries := out["LineageGroupSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "sagemaker-default-lineage-group", summaries[0].(map[string]any)["LineageGroupName"]) @@ -1154,7 +1155,7 @@ func createTestContext(t *testing.T, h *sagemaker.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ContextArn"].(string) } @@ -1170,7 +1171,7 @@ func createTestAction(t *testing.T, h *sagemaker.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ActionArn"].(string) } @@ -1186,7 +1187,7 @@ func createTestArtifact(t *testing.T, h *sagemaker.Handler, name string) string require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out["ArtifactArn"].(string) } @@ -1256,7 +1257,7 @@ func TestCreateAction_TagsPresent(t *testing.T) { if tt.wantTags { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arnStr := resp["ActionArn"] require.NotEmpty(t, arnStr) @@ -1265,7 +1266,7 @@ func TestCreateAction_TagsPresent(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) require.Len(t, tags, 1) @@ -1339,7 +1340,7 @@ func TestHandler_AddAssociation(t *testing.T) { if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["SourceArn"], "arn:aws:sagemaker") assert.Contains(t, resp["DestinationArn"], "arn:aws:sagemaker") } @@ -1439,7 +1440,7 @@ func TestHandler_AssociateTrialComponent(t *testing.T) { if tt.wantArns { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["TrialArn"], "arn:aws:sagemaker") assert.Contains(t, resp["TrialComponentArn"], "arn:aws:sagemaker") } @@ -1527,7 +1528,7 @@ func TestHandler_CreateAction(t *testing.T) { if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ActionArn"], "arn:aws:sagemaker") assert.Contains(t, resp["ActionArn"], "action/") } diff --git a/services/sagemaker/handler_list_notebook_filters_test.go b/services/sagemaker/handler_list_notebook_filters_test.go index 70f37bfafe..9f36e748cb 100644 --- a/services/sagemaker/handler_list_notebook_filters_test.go +++ b/services/sagemaker/handler_list_notebook_filters_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListNotebookInstances_Filters verifies that ListNotebookInstances honors @@ -65,7 +67,7 @@ func TestListNotebookInstances_Filters(t *testing.T) { } `json:"NotebookInstances"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) gotNames := make([]string, 0, len(resp.NotebookInstances)) for _, nb := range resp.NotebookInstances { diff --git a/services/sagemaker/handler_mlflow.go b/services/sagemaker/handler_mlflow.go index b69c44da27..262d363dd2 100644 --- a/services/sagemaker/handler_mlflow.go +++ b/services/sagemaker/handler_mlflow.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -28,7 +30,7 @@ type createMlflowTrackingServerInput struct { func (h *Handler) handleCreateMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req createMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -67,7 +69,7 @@ func (h *Handler) handleCreateMlflowTrackingServer(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]any{keyTrackingServerArn: result.TrackingServerArn}) + return json.Marshal(map[string]any{keyTrackingServerArn: result.TrackingServerArn}, jsonx.V1()) } // describeMlflowTrackingServerInput is DescribeMlflowTrackingServer's request @@ -104,7 +106,7 @@ type describeMlflowTrackingServerResponse struct { func (h *Handler) handleDescribeMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req describeMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -135,7 +137,7 @@ func (h *Handler) handleDescribeMlflowTrackingServer(ctx context.Context, body [ S3BucketOwnerVerification: result.S3BucketOwnerVerification, CreationTime: epochSeconds(result.CreationTime), LastModifiedTime: epochSeconds(result.LastModifiedTime), - }) + }, jsonx.V1()) } // deleteMlflowTrackingServerInput is DeleteMlflowTrackingServer's request @@ -147,7 +149,7 @@ type deleteMlflowTrackingServerInput struct { func (h *Handler) handleDeleteMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req deleteMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -160,7 +162,7 @@ func (h *Handler) handleDeleteMlflowTrackingServer(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}) + return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}, jsonx.V1()) } // startMlflowTrackingServerInput is StartMlflowTrackingServer's request shape @@ -172,7 +174,7 @@ type startMlflowTrackingServerInput struct { func (h *Handler) handleStartMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req startMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -185,7 +187,7 @@ func (h *Handler) handleStartMlflowTrackingServer(ctx context.Context, body []by return nil, err } - return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}) + return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}, jsonx.V1()) } // stopMlflowTrackingServerInput is StopMlflowTrackingServer's request shape @@ -197,7 +199,7 @@ type stopMlflowTrackingServerInput struct { func (h *Handler) handleStopMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req stopMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -210,7 +212,7 @@ func (h *Handler) handleStopMlflowTrackingServer(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}) + return json.Marshal(map[string]any{keyTrackingServerArn: arnStr}, jsonx.V1()) } // createPresignedMlflowTrackingServerURLInput is @@ -226,7 +228,7 @@ type createPresignedMlflowTrackingServerURLInput struct { func (h *Handler) handleCreatePresignedMlflowTrackingServerURL(ctx context.Context, body []byte) ([]byte, error) { var req createPresignedMlflowTrackingServerURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -243,7 +245,7 @@ func (h *Handler) handleCreatePresignedMlflowTrackingServerURL(ctx context.Conte return nil, err } - return json.Marshal(map[string]string{keyAuthorizedURL: url}) + return json.Marshal(map[string]string{keyAuthorizedURL: url}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -266,7 +268,7 @@ type createMlflowAppInput struct { func (h *Handler) handleCreateMlflowApp(ctx context.Context, body []byte) ([]byte, error) { var req createMlflowAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -288,7 +290,7 @@ func (h *Handler) handleCreateMlflowApp(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyGenericArn: result.Arn}) + return json.Marshal(map[string]any{keyGenericArn: result.Arn}, jsonx.V1()) } // describeMlflowAppResponse is the response body for DescribeMlflowApp. @@ -319,7 +321,7 @@ type describeMlflowAppInput struct { func (h *Handler) handleDescribeMlflowApp(ctx context.Context, body []byte) ([]byte, error) { var req describeMlflowAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -345,7 +347,7 @@ func (h *Handler) handleDescribeMlflowApp(ctx context.Context, body []byte) ([]b DefaultDomainIDList: result.DefaultDomainIDList, CreationTime: epochSeconds(result.CreationTime), LastModifiedTime: epochSeconds(result.LastModifiedTime), - }) + }, jsonx.V1()) } // deleteMlflowAppInput is DeleteMlflowApp's request shape @@ -357,7 +359,7 @@ type deleteMlflowAppInput struct { func (h *Handler) handleDeleteMlflowApp(ctx context.Context, body []byte) ([]byte, error) { var req deleteMlflowAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -369,7 +371,7 @@ func (h *Handler) handleDeleteMlflowApp(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyGenericArn: req.Arn}) + return json.Marshal(map[string]any{keyGenericArn: req.Arn}, jsonx.V1()) } // updateMlflowAppInput is UpdateMlflowApp's request shape @@ -389,7 +391,7 @@ type updateMlflowAppInput struct { func (h *Handler) handleUpdateMlflowApp(ctx context.Context, body []byte) ([]byte, error) { var req updateMlflowAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -409,7 +411,7 @@ func (h *Handler) handleUpdateMlflowApp(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyGenericArn: result.Arn}) + return json.Marshal(map[string]any{keyGenericArn: result.Arn}, jsonx.V1()) } // listMlflowAppsInput is ListMlflowApps' request shape @@ -430,7 +432,7 @@ type listMlflowAppsInput struct { func (h *Handler) handleListMlflowApps(ctx context.Context, body []byte) ([]byte, error) { var req listMlflowAppsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -474,7 +476,7 @@ type createPresignedMlflowAppURLInput struct { func (h *Handler) handleCreatePresignedMlflowAppURL(ctx context.Context, body []byte) ([]byte, error) { var req createPresignedMlflowAppURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -491,7 +493,7 @@ func (h *Handler) handleCreatePresignedMlflowAppURL(ctx context.Context, body [] return nil, err } - return json.Marshal(map[string]string{keyAuthorizedURL: url}) + return json.Marshal(map[string]string{keyAuthorizedURL: url}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -514,7 +516,7 @@ type listMlflowTrackingServersInput struct { func (h *Handler) handleListMlflowTrackingServers(ctx context.Context, body []byte) ([]byte, error) { var req listMlflowTrackingServersInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -566,7 +568,7 @@ type updateMlflowTrackingServerInput struct { func (h *Handler) handleUpdateMlflowTrackingServer(ctx context.Context, body []byte) ([]byte, error) { var req updateMlflowTrackingServerInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -579,5 +581,5 @@ func (h *Handler) handleUpdateMlflowTrackingServer(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]string{keyTrackingServerArn: s.TrackingServerArn}) + return json.Marshal(map[string]string{keyTrackingServerArn: s.TrackingServerArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_mlflow_test.go b/services/sagemaker/handler_mlflow_test.go index dedecc3731..0bde3ad443 100644 --- a/services/sagemaker/handler_mlflow_test.go +++ b/services/sagemaker/handler_mlflow_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateMlflowTrackingServer(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_CreateMlflowTrackingServer(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["TrackingServerArn"], "my-server") } @@ -38,7 +40,7 @@ func TestHandler_DescribeMlflowTrackingServer(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ts-1", resp["TrackingServerName"]) } @@ -53,14 +55,14 @@ func TestHandler_StartStopMlflowTrackingServer(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.Contains(t, startResp["TrackingServerArn"], "ts-ss") rec = doSageMakerRequest(t, h, "StopMlflowTrackingServer", map[string]any{"TrackingServerName": "ts-ss"}) assert.Equal(t, http.StatusOK, rec.Code) var stopResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &stopResp, jsonx.V1())) assert.Contains(t, stopResp["TrackingServerArn"], "ts-ss") } @@ -120,7 +122,7 @@ func TestHandler_DeleteMlflowTrackingServer(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var deleteResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &deleteResp, jsonx.V1())) assert.Contains(t, deleteResp["TrackingServerArn"], "ts-del") rec = doSageMakerRequest(t, h, "DescribeMlflowTrackingServer", map[string]any{"TrackingServerName": "ts-del"}) @@ -313,7 +315,7 @@ func TestHandler_CreatePresignedMlflowTrackingServerUrl(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["AuthorizedUrl"], "ts-1") } @@ -345,7 +347,7 @@ func TestHandler_MlflowApp_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) appARN := createResp["Arn"] require.Contains(t, appARN, "mlflow-app/app-1") @@ -353,7 +355,7 @@ func TestHandler_MlflowApp_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, describeRec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "app-1", describeResp["Name"]) assert.Equal(t, "Created", describeResp["Status"]) assert.Equal(t, "s3://bucket/path", describeResp["ArtifactStoreUri"]) @@ -365,21 +367,21 @@ func TestHandler_MlflowApp_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, updateRec.Code) describeRec = doSageMakerRequest(t, h, "DescribeMlflowApp", map[string]any{"Arn": appARN}) - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "s3://bucket/new-path", describeResp["ArtifactStoreUri"]) presignRec := doSageMakerRequest(t, h, "CreatePresignedMlflowAppUrl", map[string]any{"Arn": appARN}) assert.Equal(t, http.StatusOK, presignRec.Code) var presignResp map[string]string - require.NoError(t, json.Unmarshal(presignRec.Body.Bytes(), &presignResp)) + require.NoError(t, json.Unmarshal(presignRec.Body.Bytes(), &presignResp, jsonx.V1())) assert.Contains(t, presignResp["AuthorizedUrl"], "app-1") listRec := doSageMakerRequest(t, h, "ListMlflowApps", map[string]any{}) assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["Summaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -388,7 +390,7 @@ func TestHandler_MlflowApp_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, deleteRec.Code) var deleteResp map[string]string - require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp)) + require.NoError(t, json.Unmarshal(deleteRec.Body.Bytes(), &deleteResp, jsonx.V1())) assert.Equal(t, appARN, deleteResp["Arn"]) describeRec = doSageMakerRequest(t, h, "DescribeMlflowApp", map[string]any{"Arn": appARN}) @@ -586,7 +588,7 @@ func TestHandler_ListMlflowTrackingServers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["TrackingServerSummaries"]) // Create one @@ -600,7 +602,7 @@ func TestHandler_ListMlflowTrackingServers(t *testing.T) { rec = doSageMakerRequest(t, h, "ListMlflowTrackingServers", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["TrackingServerSummaries"].([]any) assert.Len(t, summaries, 1) @@ -631,7 +633,7 @@ func TestHandler_UpdateMlflowTrackingServer(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["TrackingServerArn"]) } @@ -663,7 +665,7 @@ func TestHandler_UpdateMlflowTrackingServer_MlflowVersionNotOnWire(t *testing.T) "TrackingServerName": "my-server", }) var resp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal( t, "2.0.0", resp["MlflowVersion"], "MlflowVersion is not a real UpdateMlflowTrackingServerInput field and must not change", diff --git a/services/sagemaker/handler_model_cards.go b/services/sagemaker/handler_model_cards.go index ea0d85e3b0..10dddc50af 100644 --- a/services/sagemaker/handler_model_cards.go +++ b/services/sagemaker/handler_model_cards.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -24,7 +26,7 @@ type createModelCardInput struct { func (h *Handler) handleCreateModelCard(ctx context.Context, body []byte) ([]byte, error) { var req createModelCardInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -43,7 +45,7 @@ func (h *Handler) handleCreateModelCard(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyModelCardArn: result.ModelCardArn}) + return json.Marshal(map[string]any{keyModelCardArn: result.ModelCardArn}, jsonx.V1()) } // describeModelCardInput mirrors DescribeModelCardInput @@ -58,7 +60,7 @@ type describeModelCardInput struct { func (h *Handler) handleDescribeModelCard(ctx context.Context, body []byte) ([]byte, error) { var req describeModelCardInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -71,7 +73,7 @@ func (h *Handler) handleDescribeModelCard(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // updateModelCardInput mirrors UpdateModelCardInput (api_op_UpdateModelCard.go:31-59): @@ -86,7 +88,7 @@ type updateModelCardInput struct { func (h *Handler) handleUpdateModelCard(ctx context.Context, body []byte) ([]byte, error) { var req updateModelCardInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -99,7 +101,7 @@ func (h *Handler) handleUpdateModelCard(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyModelCardArn: result.ModelCardArn}) + return json.Marshal(map[string]any{keyModelCardArn: result.ModelCardArn}, jsonx.V1()) } // deleteModelCardInput mirrors DeleteModelCardInput (api_op_DeleteModelCard.go:27-33): @@ -111,7 +113,7 @@ type deleteModelCardInput struct { func (h *Handler) handleDeleteModelCard(ctx context.Context, body []byte) error { var req deleteModelCardInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -142,7 +144,7 @@ type listModelCardsInput struct { func (h *Handler) handleListModelCards(ctx context.Context, body []byte) ([]byte, error) { var req listModelCardsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -199,7 +201,7 @@ type listModelCardVersionsInput struct { func (h *Handler) handleListModelCardVersions(ctx context.Context, body []byte) ([]byte, error) { var req listModelCardVersionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -224,7 +226,7 @@ func (h *Handler) handleListModelCardVersions(ctx context.Context, body []byte) }) } - return json.Marshal(map[string]any{"ModelCardVersionSummaryList": summaries}) + return json.Marshal(map[string]any{"ModelCardVersionSummaryList": summaries}, jsonx.V1()) } func modelCardVersionMatchesFilter(card *ModelCard, req listModelCardVersionsInput) bool { @@ -262,7 +264,7 @@ type listModelCardExportJobsInput struct { func (h *Handler) handleListModelCardExportJobs(ctx context.Context, body []byte) ([]byte, error) { var req listModelCardExportJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_model_cards_test.go b/services/sagemaker/handler_model_cards_test.go index 2c5f12287f..be1de9e354 100644 --- a/services/sagemaker/handler_model_cards_test.go +++ b/services/sagemaker/handler_model_cards_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateModelCard(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_CreateModelCard(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ModelCardArn"], "my-card") } @@ -51,7 +53,7 @@ func TestHandler_DescribeModelCard(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "card-1", resp["ModelCardName"]) } @@ -70,7 +72,7 @@ func TestHandler_UpdateModelCard(t *testing.T) { // Verify version incremented rec = doSageMakerRequest(t, h, "DescribeModelCard", map[string]any{"ModelCardName": "card-upd"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.InDelta(t, float64(2), resp["ModelCardVersion"], 0) } @@ -101,7 +103,7 @@ func TestHandler_ListModelCards(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["ModelCardSummaries"]) // Create one @@ -113,7 +115,7 @@ func TestHandler_ListModelCards(t *testing.T) { rec = doSageMakerRequest(t, h, "ListModelCards", map[string]any{}) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["ModelCardSummaries"].([]any) assert.Len(t, summaries, 1) @@ -142,7 +144,7 @@ func TestHandler_ListModelCardVersions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions := resp["ModelCardVersionSummaryList"].([]any) assert.Len(t, versions, 1) @@ -178,7 +180,7 @@ func TestHandler_ListModelCardExportJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobs := resp["ModelCardExportJobSummaries"].([]any) assert.Empty(t, jobs) } diff --git a/services/sagemaker/handler_model_packages.go b/services/sagemaker/handler_model_packages.go index ded5c4aa85..d508211da6 100644 --- a/services/sagemaker/handler_model_packages.go +++ b/services/sagemaker/handler_model_packages.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -27,23 +30,23 @@ type createModelPackageInput struct { ModelApprovalStatus string `json:"ModelApprovalStatus"` ModelPackageGroupName string `json:"ModelPackageGroupName"` ModelPackageName string `json:"ModelPackageName"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification"` - ValidationSpecification json.RawMessage `json:"ValidationSpecification"` - DriftCheckBaselines json.RawMessage `json:"DriftCheckBaselines"` - ModelMetrics json.RawMessage `json:"ModelMetrics"` - ModelCard json.RawMessage `json:"ModelCard"` - ModelLifeCycle json.RawMessage `json:"ModelLifeCycle"` - MetadataProperties json.RawMessage `json:"MetadataProperties"` - SecurityConfig json.RawMessage `json:"SecurityConfig"` - AdditionalInferenceSpecifications json.RawMessage `json:"AdditionalInferenceSpecifications"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification"` + ValidationSpecification jsontext.Value `json:"ValidationSpecification"` + DriftCheckBaselines jsontext.Value `json:"DriftCheckBaselines"` + ModelMetrics jsontext.Value `json:"ModelMetrics"` + ModelCard jsontext.Value `json:"ModelCard"` + ModelLifeCycle jsontext.Value `json:"ModelLifeCycle"` + MetadataProperties jsontext.Value `json:"MetadataProperties"` + SecurityConfig jsontext.Value `json:"SecurityConfig"` + AdditionalInferenceSpecifications jsontext.Value `json:"AdditionalInferenceSpecifications"` Tags []tagObject `json:"Tags"` - SourceAlgorithmSpecification json.RawMessage `json:"SourceAlgorithmSpecification"` + SourceAlgorithmSpecification jsontext.Value `json:"SourceAlgorithmSpecification"` } func (h *Handler) handleCreateModelPackage(ctx context.Context, body []byte) ([]byte, error) { var req createModelPackageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -92,7 +95,7 @@ func (h *Handler) handleCreateModelPackage(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{keyModelPackageArn: result.ModelPackageArn}) + return json.Marshal(map[string]any{keyModelPackageArn: result.ModelPackageArn}, jsonx.V1()) } // describeModelPackageInput is the wire request body for @@ -106,7 +109,7 @@ type describeModelPackageInput struct { func (h *Handler) handleDescribeModelPackage(ctx context.Context, body []byte) ([]byte, error) { var req describeModelPackageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -119,7 +122,7 @@ func (h *Handler) handleDescribeModelPackage(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteModelPackageInput is the wire request body for DeleteModelPackage @@ -131,7 +134,7 @@ type deleteModelPackageInput struct { func (h *Handler) handleDeleteModelPackage(ctx context.Context, body []byte) error { var req deleteModelPackageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -160,7 +163,7 @@ type listModelPackagesInput struct { func (h *Handler) handleListModelPackages(ctx context.Context, body []byte) ([]byte, error) { var req listModelPackagesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -205,7 +208,7 @@ func (h *Handler) handleListModelPackages(ctx context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "ModelPackageSummaryList": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -225,7 +228,7 @@ type createModelPackageGroupInput struct { func (h *Handler) handleCreateModelPackageGroup(ctx context.Context, body []byte) ([]byte, error) { var req createModelPackageGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -247,7 +250,7 @@ func (h *Handler) handleCreateModelPackageGroup(ctx context.Context, body []byte return nil, err } - return json.Marshal(map[string]any{keyModelPackageGroupArn: result.ModelPackageGroupArn}) + return json.Marshal(map[string]any{keyModelPackageGroupArn: result.ModelPackageGroupArn}, jsonx.V1()) } // describeModelPackageGroupInput is the wire request body for @@ -260,7 +263,7 @@ type describeModelPackageGroupInput struct { func (h *Handler) handleDescribeModelPackageGroup(ctx context.Context, body []byte) ([]byte, error) { var req describeModelPackageGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -273,7 +276,7 @@ func (h *Handler) handleDescribeModelPackageGroup(ctx context.Context, body []by return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteModelPackageGroupInput is the wire request body for @@ -286,7 +289,7 @@ type deleteModelPackageGroupInput struct { func (h *Handler) handleDeleteModelPackageGroup(ctx context.Context, body []byte) error { var req deleteModelPackageGroupInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -314,7 +317,7 @@ type listModelPackageGroupsInput struct { func (h *Handler) handleListModelPackageGroups(ctx context.Context, body []byte) ([]byte, error) { var req listModelPackageGroupsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -353,7 +356,7 @@ func (h *Handler) handleListModelPackageGroups(ctx context.Context, body []byte) return json.Marshal(map[string]any{ "ModelPackageGroupSummaryList": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } // getModelPackageGroupPolicyInput is the wire request body for @@ -366,7 +369,7 @@ type getModelPackageGroupPolicyInput struct { func (h *Handler) handleGetModelPackageGroupPolicy(ctx context.Context, body []byte) ([]byte, error) { var req getModelPackageGroupPolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -379,7 +382,7 @@ func (h *Handler) handleGetModelPackageGroupPolicy(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]string{"ResourcePolicy": policy}) + return json.Marshal(map[string]string{"ResourcePolicy": policy}, jsonx.V1()) } // putModelPackageGroupPolicyInput is the wire request body for @@ -393,7 +396,7 @@ type putModelPackageGroupPolicyInput struct { func (h *Handler) handlePutModelPackageGroupPolicy(ctx context.Context, body []byte) ([]byte, error) { var req putModelPackageGroupPolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -410,7 +413,7 @@ func (h *Handler) handlePutModelPackageGroupPolicy(ctx context.Context, body []b return nil, err } - return json.Marshal(map[string]string{keyModelPackageGroupArn: g.ModelPackageGroupArn}) + return json.Marshal(map[string]string{keyModelPackageGroupArn: g.ModelPackageGroupArn}, jsonx.V1()) } // deleteModelPackageGroupPolicyInput is the wire request body for @@ -423,7 +426,7 @@ type deleteModelPackageGroupPolicyInput struct { func (h *Handler) handleDeleteModelPackageGroupPolicy(ctx context.Context, body []byte) error { var req deleteModelPackageGroupPolicyInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -452,16 +455,16 @@ type updateModelPackageInput struct { SourceURI string `json:"SourceUri"` CustomerMetadataProperties map[string]string `json:"CustomerMetadataProperties"` CustomerMetadataPropertiesToRemove []string `json:"CustomerMetadataPropertiesToRemove"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification"` - ModelCard json.RawMessage `json:"ModelCard"` - ModelLifeCycle json.RawMessage `json:"ModelLifeCycle"` - AdditionalInferenceSpecificationsToAdd json.RawMessage `json:"AdditionalInferenceSpecificationsToAdd"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification"` + ModelCard jsontext.Value `json:"ModelCard"` + ModelLifeCycle jsontext.Value `json:"ModelLifeCycle"` + AdditionalInferenceSpecificationsToAdd jsontext.Value `json:"AdditionalInferenceSpecificationsToAdd"` } func (h *Handler) handleUpdateModelPackage(ctx context.Context, body []byte) ([]byte, error) { var req updateModelPackageInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -489,7 +492,7 @@ func (h *Handler) handleUpdateModelPackage(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]string{keyModelPackageArn: mp.ModelPackageArn}) + return json.Marshal(map[string]string{keyModelPackageArn: mp.ModelPackageArn}, jsonx.V1()) } // batchDescribeModelPackageRequest is the request body for BatchDescribeModelPackage. @@ -519,7 +522,7 @@ type batchDescribeModelPackageError struct { func (h *Handler) handleBatchDescribeModelPackage(ctx context.Context, body []byte) ([]byte, error) { var req batchDescribeModelPackageRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -551,5 +554,5 @@ func (h *Handler) handleBatchDescribeModelPackage(ctx context.Context, body []by return json.Marshal(map[string]any{ "ModelPackageSummaries": modelPackageMap, "BatchDescribeModelPackageErrorMap": errorsMap, - }) + }, jsonx.V1()) } diff --git a/services/sagemaker/handler_model_packages_test.go b/services/sagemaker/handler_model_packages_test.go index 649850fbae..bfea04fb51 100644 --- a/services/sagemaker/handler_model_packages_test.go +++ b/services/sagemaker/handler_model_packages_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -27,7 +28,7 @@ func TestHandler_CreateModelPackage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ModelPackageArn"], "my-pkg") } @@ -42,7 +43,7 @@ func TestHandler_DescribeModelPackage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "pkg-1", resp["ModelPackageName"]) } @@ -71,7 +72,7 @@ func TestHandler_ListModelPackages(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ModelPackageSummaryList"].([]any) assert.Len(t, items, 2) } @@ -91,7 +92,7 @@ func TestHandler_CreateModelPackageGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ModelPackageGroupArn"], "my-group") } @@ -106,7 +107,7 @@ func TestHandler_DescribeModelPackageGroup(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "grp-1", resp["ModelPackageGroupName"]) assert.Equal(t, "Completed", resp["ModelPackageGroupStatus"]) } @@ -136,7 +137,7 @@ func TestHandler_ListModelPackageGroups(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ModelPackageGroupSummaryList"].([]any) assert.Len(t, items, 2) } @@ -294,7 +295,7 @@ func TestAddTags_ModelPackage(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) tags := resp["Tags"].([]any) require.Len(t, tags, 1) @@ -382,7 +383,7 @@ func TestHandler_ModelPackageGroupPolicy_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recPut.Code) var putOut map[string]any - require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(recPut.Body.Bytes(), &putOut, jsonx.V1())) assert.NotEmpty(t, putOut["ModelPackageGroupArn"]) recGet2 := doSageMakerRequest(t, h, "GetModelPackageGroupPolicy", map[string]any{ @@ -391,7 +392,7 @@ func TestHandler_ModelPackageGroupPolicy_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recGet2.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(recGet2.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(recGet2.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, policy, getOut["ResourcePolicy"]) recDelete := doSageMakerRequest(t, h, "DeleteModelPackageGroupPolicy", map[string]any{ @@ -479,7 +480,7 @@ func TestHandler_UpdateModelPackage(t *testing.T) { }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) pkgArn := createResp["ModelPackageArn"] require.NotEmpty(t, pkgArn) @@ -490,7 +491,7 @@ func TestHandler_UpdateModelPackage(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, pkgArn, resp["ModelPackageArn"]) // Describe and verify approval status @@ -498,7 +499,7 @@ func TestHandler_UpdateModelPackage(t *testing.T) { "ModelPackageName": "my-pkg", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Approved", descResp["ModelApprovalStatus"]) } @@ -593,7 +594,7 @@ func TestHandler_BatchDescribeModelPackage(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ModelPackageSummaries") assert.Contains(t, resp, "BatchDescribeModelPackageErrorMap") } @@ -624,7 +625,7 @@ func TestHandler_BatchDescribeModelPackage_ExistingAndMissing(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["ModelPackageSummaries"].(map[string]any) require.True(t, ok) diff --git a/services/sagemaker/handler_modelcard_export.go b/services/sagemaker/handler_modelcard_export.go index cf31e66fa7..0279690320 100644 --- a/services/sagemaker/handler_modelcard_export.go +++ b/services/sagemaker/handler_modelcard_export.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // modelCardExportOpsSupported returns the real stateful operations @@ -53,7 +55,7 @@ type createModelCardExportJobInput struct { func (h *Handler) handleCreateModelCardExportJob(ctx context.Context, body []byte) ([]byte, error) { var req createModelCardExportJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -68,7 +70,7 @@ func (h *Handler) handleCreateModelCardExportJob(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyModelCardExportJobArn: job.ModelCardExportJobArn}) + return json.Marshal(map[string]any{keyModelCardExportJobArn: job.ModelCardExportJobArn}, jsonx.V1()) } // describeModelCardExportJobInput mirrors DescribeModelCardExportJobInput @@ -81,7 +83,7 @@ type describeModelCardExportJobInput struct { func (h *Handler) handleDescribeModelCardExportJob(ctx context.Context, body []byte) ([]byte, error) { var req describeModelCardExportJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -104,5 +106,5 @@ func (h *Handler) handleDescribeModelCardExportJob(ctx context.Context, body []b keyStatus: job.Status, keyOutputConfig: map[string]any{"S3OutputPath": job.S3OutputPath}, "ExportArtifacts": map[string]any{"S3ExportArtifacts": job.S3ExportArtifacts}, - }) + }, jsonx.V1()) } diff --git a/services/sagemaker/handler_modelcard_export_test.go b/services/sagemaker/handler_modelcard_export_test.go index 30857b0415..47f462f683 100644 --- a/services/sagemaker/handler_modelcard_export_test.go +++ b/services/sagemaker/handler_modelcard_export_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ModelCardExportJob_Lifecycle(t *testing.T) { @@ -27,7 +29,7 @@ func TestHandler_ModelCardExportJob_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) jobArn, _ := createResp["ModelCardExportJobArn"].(string) require.NotEmpty(t, jobArn) @@ -37,7 +39,7 @@ func TestHandler_ModelCardExportJob_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, describeRec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "Completed", describeResp["Status"]) assert.Equal(t, "export-1", describeResp["ModelCardExportJobName"]) assert.Equal(t, "my-card", describeResp["ModelCardName"]) @@ -48,7 +50,7 @@ func TestHandler_ModelCardExportJob_Lifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["ModelCardExportJobSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) diff --git a/services/sagemaker/handler_modelmonitor_test.go b/services/sagemaker/handler_modelmonitor_test.go index 3574c9322d..c7dc988e4f 100644 --- a/services/sagemaker/handler_modelmonitor_test.go +++ b/services/sagemaker/handler_modelmonitor_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -46,7 +47,7 @@ func TestHandler_ListDataQualityJobDefinitions(t *testing.T) { var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.JobDefinitionSummaries, 3) } @@ -67,7 +68,7 @@ func TestHandler_ListDataQualityJobDefinitions_FilterByEndpointName(t *testing.T var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.JobDefinitionSummaries, 2) for _, s := range resp.JobDefinitionSummaries { @@ -94,7 +95,7 @@ func TestHandler_ListDataQualityJobDefinitions_NameContainsAndSort(t *testing.T) var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.JobDefinitionSummaries, 2) assert.Equal(t, "alpha-job", resp.JobDefinitionSummaries[0]["MonitoringJobDefinitionName"]) assert.Equal(t, "alpha-other", resp.JobDefinitionSummaries[1]["MonitoringJobDefinitionName"]) @@ -120,7 +121,7 @@ func TestHandler_ListDataQualityJobDefinitions_Pagination(t *testing.T) { NextToken string `json:"NextToken"` JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page1, jsonx.V1())) require.Len(t, page1.JobDefinitionSummaries, 2) require.NotEmpty(t, page1.NextToken) @@ -134,7 +135,7 @@ func TestHandler_ListDataQualityJobDefinitions_Pagination(t *testing.T) { var page2 struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &page2, jsonx.V1())) assert.Len(t, page2.JobDefinitionSummaries, 1) } @@ -149,7 +150,7 @@ func TestHandler_ListModelBiasJobDefinitions_Empty(t *testing.T) { var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.JobDefinitionSummaries) } @@ -168,7 +169,7 @@ func TestHandler_ListModelQualityJobDefinitions_ReturnsCreated(t *testing.T) { var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.JobDefinitionSummaries, 1) assert.Equal(t, "mq-list-1", resp.JobDefinitionSummaries[0]["MonitoringJobDefinitionName"]) } @@ -188,7 +189,7 @@ func TestHandler_ListModelExplainabilityJobDefinitions_ReturnsCreated(t *testing var resp struct { JobDefinitionSummaries []map[string]any `json:"JobDefinitionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.JobDefinitionSummaries, 1) assert.Equal(t, "me-list-1", resp.JobDefinitionSummaries[0]["MonitoringJobDefinitionName"]) } @@ -230,7 +231,7 @@ func TestHandler_UpdateMonitoringAlert_CreatesThenUpdates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["MonitoringScheduleArn"], "mm-sched") assert.Equal(t, "alert-1", resp["MonitoringAlertName"]) @@ -251,7 +252,7 @@ func TestHandler_UpdateMonitoringAlert_CreatesThenUpdates(t *testing.T) { var listResp struct { MonitoringAlertSummaries []map[string]any `json:"MonitoringAlertSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.MonitoringAlertSummaries, 1) assert.InEpsilon(t, float64(5), listResp.MonitoringAlertSummaries[0]["DatapointsToAlert"], 0) assert.InEpsilon(t, float64(6), listResp.MonitoringAlertSummaries[0]["EvaluationPeriod"], 0) @@ -335,7 +336,7 @@ func TestHandler_ListMonitoringAlerts_MaxResults(t *testing.T) { NextToken string `json:"NextToken"` MonitoringAlertSummaries []map[string]any `json:"MonitoringAlertSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.MonitoringAlertSummaries, 2) assert.NotEmpty(t, resp.NextToken) } @@ -369,7 +370,7 @@ func TestHandler_ListMonitoringAlerts_EmptyForFreshSchedule(t *testing.T) { var resp struct { MonitoringAlertSummaries []map[string]any `json:"MonitoringAlertSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.MonitoringAlertSummaries) } @@ -403,7 +404,7 @@ func TestHandler_ListMonitoringAlertHistory_FiltersByScheduleAndStatus(t *testin var resp struct { MonitoringAlertHistory []map[string]any `json:"MonitoringAlertHistory"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.MonitoringAlertHistory, 1) assert.Equal(t, "sched-1", resp.MonitoringAlertHistory[0]["MonitoringScheduleName"]) assert.Equal(t, "InAlert", resp.MonitoringAlertHistory[0]["AlertStatus"]) @@ -446,7 +447,7 @@ func TestHandler_ListMonitoringAlertHistory_SortByStatus(t *testing.T) { var defaultResp struct { MonitoringAlertHistory []map[string]any `json:"MonitoringAlertHistory"` } - require.NoError(t, json.Unmarshal(defaultRec.Body.Bytes(), &defaultResp)) + require.NoError(t, json.Unmarshal(defaultRec.Body.Bytes(), &defaultResp, jsonx.V1())) require.Len(t, defaultResp.MonitoringAlertHistory, 2) assert.Equal(t, "InAlert", defaultResp.MonitoringAlertHistory[0]["AlertStatus"]) @@ -462,7 +463,7 @@ func TestHandler_ListMonitoringAlertHistory_SortByStatus(t *testing.T) { var statusResp struct { MonitoringAlertHistory []map[string]any `json:"MonitoringAlertHistory"` } - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp, jsonx.V1())) require.Len(t, statusResp.MonitoringAlertHistory, 2) assert.Equal(t, "OK", statusResp.MonitoringAlertHistory[0]["AlertStatus"], "SortBy=Status must be honored") } @@ -501,7 +502,7 @@ func TestHandler_ListMonitoringExecutions_FiltersByScheduleAndStatus(t *testing. var resp struct { MonitoringExecutionSummaries []map[string]any `json:"MonitoringExecutionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.MonitoringExecutionSummaries, 1) assert.Equal(t, "sched-a", resp.MonitoringExecutionSummaries[0]["MonitoringScheduleName"]) assert.Equal(t, "Completed", resp.MonitoringExecutionSummaries[0]["MonitoringExecutionStatus"]) @@ -518,6 +519,6 @@ func TestHandler_ListMonitoringExecutions_EmptyWhenNoneSeeded(t *testing.T) { var resp struct { MonitoringExecutionSummaries []map[string]any `json:"MonitoringExecutionSummaries"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.MonitoringExecutionSummaries) } diff --git a/services/sagemaker/handler_models.go b/services/sagemaker/handler_models.go index 688b77a9be..5380f27c90 100644 --- a/services/sagemaker/handler_models.go +++ b/services/sagemaker/handler_models.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -42,7 +43,7 @@ type describeModelResponse struct { func (h *Handler) handleCreateModel(ctx context.Context, body []byte) ([]byte, error) { var req createModelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -96,7 +97,7 @@ func (h *Handler) handleCreateModel(ctx context.Context, body []byte) ([]byte, e log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created model", "name", m.ModelName) - return json.Marshal(map[string]string{"ModelArn": m.ModelARN}) + return json.Marshal(map[string]string{"ModelArn": m.ModelARN}, jsonx.V1()) } // describeModelRequest is the request body for DescribeModel. @@ -107,7 +108,7 @@ type describeModelRequest struct { func (h *Handler) handleDescribeModel(ctx context.Context, body []byte) ([]byte, error) { var req describeModelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -136,13 +137,13 @@ func (h *Handler) handleDescribeModel(ctx context.Context, body []byte) ([]byte, resp.Containers = nil } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleListModels(ctx context.Context, body []byte) ([]byte, error) { var req nameTimeListRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -168,7 +169,7 @@ func (h *Handler) handleListModels(ctx context.Context, body []byte) ([]byte, er resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteModelRequest is the request body for DeleteModel. @@ -179,7 +180,7 @@ type deleteModelRequest struct { func (h *Handler) handleDeleteModel(ctx context.Context, body []byte) error { var req deleteModelRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_models_test.go b/services/sagemaker/handler_models_test.go index 063a02233a..460e378bf8 100644 --- a/services/sagemaker/handler_models_test.go +++ b/services/sagemaker/handler_models_test.go @@ -3,7 +3,7 @@ package sagemaker_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -62,7 +63,7 @@ func TestHandler_CreateModel(t *testing.T) { if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("not-json") @@ -82,7 +83,7 @@ func TestHandler_CreateModel(t *testing.T) { if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ModelArn"], "arn:aws:sagemaker") assert.Contains(t, resp["ModelArn"], "model/my-model") } @@ -140,7 +141,7 @@ func TestHandler_DescribeModel(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["ModelName"]) } }) @@ -176,7 +177,7 @@ func TestHandler_ListModels(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) models, ok := resp["Models"].([]any) require.True(t, ok) @@ -277,7 +278,7 @@ func TestHandler_ListModelsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) models, modelsOK := resp["Models"].([]any) require.True(t, modelsOK) @@ -298,7 +299,7 @@ func TestHandler_ListModelsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) models2, models2OK := resp2["Models"].([]any) require.True(t, models2OK) @@ -432,7 +433,7 @@ func TestHandler_ListModels_FilterSort(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) list, ok := resp["Models"].([]any) require.True(t, ok) @@ -497,7 +498,7 @@ func TestHandler_ListModels_CreationTimeAfterInclusive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) models, ok := resp["Models"].([]any) require.True(t, ok) require.Len(t, models, 1) diff --git a/services/sagemaker/handler_monitoring.go b/services/sagemaker/handler_monitoring.go index 79d4201acb..f6096905bc 100644 --- a/services/sagemaker/handler_monitoring.go +++ b/services/sagemaker/handler_monitoring.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -21,7 +23,7 @@ type updateMonitoringAlertRequest struct { func (h *Handler) handleUpdateMonitoringAlert(ctx context.Context, body []byte) ([]byte, error) { var req updateMonitoringAlertRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -51,7 +53,7 @@ func (h *Handler) handleUpdateMonitoringAlert(ctx context.Context, body []byte) return json.Marshal(map[string]any{ keyMonitoringScheduleArn: scheduleArn, keyMonitoringAlertName: alert.MonitoringAlertName, - }) + }, jsonx.V1()) } // listMonitoringAlertsRequest is the request body for ListMonitoringAlerts. @@ -64,7 +66,7 @@ type listMonitoringAlertsRequest struct { func (h *Handler) handleListMonitoringAlerts(ctx context.Context, body []byte) ([]byte, error) { var req listMonitoringAlertsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -97,7 +99,7 @@ func (h *Handler) handleListMonitoringAlerts(ctx context.Context, body []byte) ( resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listMonitoringAlertHistoryRequest is the request body for ListMonitoringAlertHistory. @@ -116,7 +118,7 @@ type listMonitoringAlertHistoryRequest struct { func (h *Handler) handleListMonitoringAlertHistory(ctx context.Context, body []byte) ([]byte, error) { var req listMonitoringAlertHistoryRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -148,7 +150,7 @@ func (h *Handler) handleListMonitoringAlertHistory(ctx context.Context, body []b resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listMonitoringExecutionsRequest is the parsed representation of a @@ -192,13 +194,13 @@ func (r listMonitoringExecutionsRequest) toFilter() MonitoringExecutionFilter { func (h *Handler) handleListMonitoringExecutions(ctx context.Context, body []byte) ([]byte, error) { var req listMonitoringExecutionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } items, next := h.Backend.ListMonitoringExecutions(ctx, req.NextToken, req.toFilter()) - return json.Marshal(buildMonitoringExecutionListResponse(items, next)) + return json.Marshal(buildMonitoringExecutionListResponse(items, next), jsonx.V1()) } func buildMonitoringExecutionListResponse(items []*MonitoringExecution, next string) map[string]any { diff --git a/services/sagemaker/handler_monitoring_job_definitions.go b/services/sagemaker/handler_monitoring_job_definitions.go index d655702a7d..0ea8372743 100644 --- a/services/sagemaker/handler_monitoring_job_definitions.go +++ b/services/sagemaker/handler_monitoring_job_definitions.go @@ -2,10 +2,13 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -27,7 +30,7 @@ import ( // JobInput/JobOutputConfig blocks plus the shared JobResources/NetworkConfig/ // StoppingCondition/BaselineConfig) is kept verbatim in Config. type jobDefRequest struct { - Config map[string]json.RawMessage + Config map[string]jsontext.Value Tags map[string]string JobDefinitionName string RoleArn string @@ -38,26 +41,26 @@ type jobDefRequest struct { // wire field name of the type's JobInput block (e.g. "DataQualityJobInput"), // used to derive EndpointName for List filtering/summaries. func parseJobDefRequest(body []byte, jobInputKey string) (jobDefRequest, error) { - var raw map[string]json.RawMessage - if err := json.Unmarshal(body, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(body, &raw, jsonx.V1()); err != nil { return jobDefRequest{}, fmt.Errorf("%w: %w", errInvalidRequest, err) } - req := jobDefRequest{Config: make(map[string]json.RawMessage, len(raw))} + req := jobDefRequest{Config: make(map[string]jsontext.Value, len(raw))} for k, v := range raw { switch k { case keyJobDefinitionName: - if err := json.Unmarshal(v, &req.JobDefinitionName); err != nil { + if err := json.Unmarshal(v, &req.JobDefinitionName, jsonx.V1()); err != nil { return jobDefRequest{}, fmt.Errorf("%w: %w", errInvalidRequest, err) } case "RoleArn": - if err := json.Unmarshal(v, &req.RoleArn); err != nil { + if err := json.Unmarshal(v, &req.RoleArn, jsonx.V1()); err != nil { return jobDefRequest{}, fmt.Errorf("%w: %w", errInvalidRequest, err) } case keyTagsField: var tags []tagObject - if err := json.Unmarshal(v, &tags); err != nil { + if err := json.Unmarshal(v, &tags, jsonx.V1()); err != nil { return jobDefRequest{}, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -83,7 +86,7 @@ func parseJobDefRequest(body []byte, jobInputKey string) (jobDefRequest, error) // AppSpecification/JobInput/JobOutputConfig, whose wire names share the // type's name prefix derived from jobInputKey (e.g. "DataQualityJobInput" -> // "DataQuality"). Returns the decoded JobInput block on success. -func validateJobDefRequest(req jobDefRequest, jobInputKey string) (json.RawMessage, error) { +func validateJobDefRequest(req jobDefRequest, jobInputKey string) (jsontext.Value, error) { if req.JobDefinitionName == "" { return nil, fmt.Errorf("%w: JobDefinitionName is required", errInvalidRequest) } @@ -117,14 +120,14 @@ func validateJobDefRequest(req jobDefRequest, jobInputKey string) (json.RawMessa // extractEndpointName pulls EndpointInput.EndpointName out of a job input // block (DataQualityJobInput / ModelBiasJobInput / ModelQualityJobInput / // ModelExplainabilityJobInput all share this shape). -func extractEndpointName(jobInput json.RawMessage) string { +func extractEndpointName(jobInput jsontext.Value) string { var in struct { EndpointInput *struct { EndpointName string `json:"EndpointName"` } `json:"EndpointInput"` } - if err := json.Unmarshal(jobInput, &in); err != nil || in.EndpointInput == nil { + if err := json.Unmarshal(jobInput, &in, jsonx.V1()); err != nil || in.EndpointInput == nil { return "" } @@ -144,7 +147,7 @@ type jobDefinitionNameInput struct { func parseJobDefinitionName(body []byte) (string, error) { var req jobDefinitionNameInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return "", fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +204,7 @@ type jobDefinitionListInput struct { func parseJobDefinitionListRequest(body []byte) (jobDefListRequest, error) { var req jobDefinitionListInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return jobDefListRequest{}, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -268,7 +271,7 @@ func (h *Handler) handleCreateDataQualityJobDefinition(ctx context.Context, body return nil, err } - return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}) + return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}, jsonx.V1()) } func (h *Handler) handleDescribeDataQualityJobDefinition(ctx context.Context, body []byte) ([]byte, error) { @@ -282,7 +285,7 @@ func (h *Handler) handleDescribeDataQualityJobDefinition(ctx context.Context, bo return nil, err } - return json.Marshal(buildJobDefinitionResponse(result)) + return json.Marshal(buildJobDefinitionResponse(result), jsonx.V1()) } func (h *Handler) handleDeleteDataQualityJobDefinition(ctx context.Context, body []byte) error { @@ -302,7 +305,7 @@ func (h *Handler) handleListDataQualityJobDefinitions(ctx context.Context, body items, next := h.Backend.ListDataQualityJobDefinitions(ctx, req.NextToken, req.Filter) - return json.Marshal(buildJobDefinitionListResponse(items, next)) + return json.Marshal(buildJobDefinitionListResponse(items, next), jsonx.V1()) } // --------------------------------------------------------------------------- @@ -322,7 +325,7 @@ func (h *Handler) handleCreateModelBiasJobDefinition(ctx context.Context, body [ return nil, err } - return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}) + return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}, jsonx.V1()) } func (h *Handler) handleDescribeModelBiasJobDefinition(ctx context.Context, body []byte) ([]byte, error) { @@ -336,7 +339,7 @@ func (h *Handler) handleDescribeModelBiasJobDefinition(ctx context.Context, body return nil, err } - return json.Marshal(buildJobDefinitionResponse(result)) + return json.Marshal(buildJobDefinitionResponse(result), jsonx.V1()) } func (h *Handler) handleDeleteModelBiasJobDefinition(ctx context.Context, body []byte) error { @@ -356,7 +359,7 @@ func (h *Handler) handleListModelBiasJobDefinitions(ctx context.Context, body [] items, next := h.Backend.ListModelBiasJobDefinitions(ctx, req.NextToken, req.Filter) - return json.Marshal(buildJobDefinitionListResponse(items, next)) + return json.Marshal(buildJobDefinitionListResponse(items, next), jsonx.V1()) } // --------------------------------------------------------------------------- @@ -376,7 +379,7 @@ func (h *Handler) handleCreateModelQualityJobDefinition(ctx context.Context, bod return nil, err } - return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}) + return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}, jsonx.V1()) } func (h *Handler) handleDescribeModelQualityJobDefinition(ctx context.Context, body []byte) ([]byte, error) { @@ -390,7 +393,7 @@ func (h *Handler) handleDescribeModelQualityJobDefinition(ctx context.Context, b return nil, err } - return json.Marshal(buildJobDefinitionResponse(result)) + return json.Marshal(buildJobDefinitionResponse(result), jsonx.V1()) } func (h *Handler) handleDeleteModelQualityJobDefinition(ctx context.Context, body []byte) error { @@ -410,7 +413,7 @@ func (h *Handler) handleListModelQualityJobDefinitions(ctx context.Context, body items, next := h.Backend.ListModelQualityJobDefinitions(ctx, req.NextToken, req.Filter) - return json.Marshal(buildJobDefinitionListResponse(items, next)) + return json.Marshal(buildJobDefinitionListResponse(items, next), jsonx.V1()) } // --------------------------------------------------------------------------- @@ -430,7 +433,7 @@ func (h *Handler) handleCreateModelExplainabilityJobDefinition(ctx context.Conte return nil, err } - return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}) + return json.Marshal(map[string]any{keyJobDefinitionArn: result.JobDefinitionArn}, jsonx.V1()) } func (h *Handler) handleDescribeModelExplainabilityJobDefinition(ctx context.Context, body []byte) ([]byte, error) { @@ -444,7 +447,7 @@ func (h *Handler) handleDescribeModelExplainabilityJobDefinition(ctx context.Con return nil, err } - return json.Marshal(buildJobDefinitionResponse(result)) + return json.Marshal(buildJobDefinitionResponse(result), jsonx.V1()) } func (h *Handler) handleDeleteModelExplainabilityJobDefinition(ctx context.Context, body []byte) error { @@ -464,5 +467,5 @@ func (h *Handler) handleListModelExplainabilityJobDefinitions(ctx context.Contex items, next := h.Backend.ListModelExplainabilityJobDefinitions(ctx, req.NextToken, req.Filter) - return json.Marshal(buildJobDefinitionListResponse(items, next)) + return json.Marshal(buildJobDefinitionListResponse(items, next), jsonx.V1()) } diff --git a/services/sagemaker/handler_monitoring_job_definitions_test.go b/services/sagemaker/handler_monitoring_job_definitions_test.go index dadb14c3d1..b1b559ed71 100644 --- a/services/sagemaker/handler_monitoring_job_definitions_test.go +++ b/services/sagemaker/handler_monitoring_job_definitions_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // minimalJobDefinitionFixture builds a structurally valid Create*JobDefinition @@ -41,7 +43,7 @@ func TestHandler_CreateDataQualityJobDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["JobDefinitionArn"], "dq-def-1") } @@ -59,7 +61,7 @@ func TestHandler_DescribeDataQualityJobDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "dq-def-2", resp["JobDefinitionName"]) assert.Equal(t, "arn:aws:iam::000000000000:role/monitor", resp["RoleArn"]) assert.NotNil(t, resp["DataQualityAppSpecification"]) @@ -99,7 +101,7 @@ func TestHandler_CreateDataQualityJobDefinition_DuplicateReturnsResourceInUse(t assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceInUse", resp["__type"]) } @@ -117,7 +119,7 @@ func TestHandler_CreateModelBiasJobDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["JobDefinitionArn"], "mb-def-1") } @@ -153,7 +155,7 @@ func TestHandler_CreateModelQualityJobDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["JobDefinitionArn"], "mq-def-1") } @@ -184,7 +186,7 @@ func TestHandler_CreateModelExplainabilityJobDefinition(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["JobDefinitionArn"], "me-def-1") } diff --git a/services/sagemaker/handler_monitoring_schedules.go b/services/sagemaker/handler_monitoring_schedules.go index 90b5f2f887..a15144978f 100644 --- a/services/sagemaker/handler_monitoring_schedules.go +++ b/services/sagemaker/handler_monitoring_schedules.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -22,7 +24,7 @@ type createMonitoringScheduleInput struct { func (h *Handler) handleCreateMonitoringSchedule(ctx context.Context, body []byte) ([]byte, error) { var req createMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -37,7 +39,7 @@ func (h *Handler) handleCreateMonitoringSchedule(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyMonitoringScheduleArn: result.MonitoringScheduleArn}) + return json.Marshal(map[string]any{keyMonitoringScheduleArn: result.MonitoringScheduleArn}, jsonx.V1()) } // describeMonitoringScheduleInput mirrors DescribeMonitoringScheduleInput @@ -49,7 +51,7 @@ type describeMonitoringScheduleInput struct { func (h *Handler) handleDescribeMonitoringSchedule(ctx context.Context, body []byte) ([]byte, error) { var req describeMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -62,7 +64,7 @@ func (h *Handler) handleDescribeMonitoringSchedule(ctx context.Context, body []b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteMonitoringScheduleInput mirrors DeleteMonitoringScheduleInput @@ -74,7 +76,7 @@ type deleteMonitoringScheduleInput struct { func (h *Handler) handleDeleteMonitoringSchedule(ctx context.Context, body []byte) error { var req deleteMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -94,7 +96,7 @@ type stopMonitoringScheduleInput struct { func (h *Handler) handleStopMonitoringSchedule(ctx context.Context, body []byte) error { var req stopMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -114,7 +116,7 @@ type startMonitoringScheduleInput struct { func (h *Handler) handleStartMonitoringSchedule(ctx context.Context, body []byte) error { var req startMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -135,7 +137,7 @@ type updateMonitoringScheduleInput struct { func (h *Handler) handleUpdateMonitoringSchedule(ctx context.Context, body []byte) ([]byte, error) { var req updateMonitoringScheduleInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -148,7 +150,7 @@ func (h *Handler) handleUpdateMonitoringSchedule(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]any{keyMonitoringScheduleArn: result.MonitoringScheduleArn}) + return json.Marshal(map[string]any{keyMonitoringScheduleArn: result.MonitoringScheduleArn}, jsonx.V1()) } // listMonitoringSchedulesInput mirrors ListMonitoringSchedulesInput @@ -175,7 +177,7 @@ type listMonitoringSchedulesInput struct { func (h *Handler) handleListMonitoringSchedules(ctx context.Context, body []byte) ([]byte, error) { var req listMonitoringSchedulesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -225,5 +227,5 @@ func (h *Handler) handleListMonitoringSchedules(ctx context.Context, body []byte return json.Marshal(map[string]any{ "MonitoringScheduleSummaries": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } diff --git a/services/sagemaker/handler_monitoring_schedules_test.go b/services/sagemaker/handler_monitoring_schedules_test.go index fac766d234..143be00437 100644 --- a/services/sagemaker/handler_monitoring_schedules_test.go +++ b/services/sagemaker/handler_monitoring_schedules_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateMonitoringSchedule(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_CreateMonitoringSchedule(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["MonitoringScheduleArn"], "my-schedule") } @@ -53,7 +55,7 @@ func TestHandler_DescribeMonitoringSchedule(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "sched-1", resp["MonitoringScheduleName"]) assert.Equal(t, "Scheduled", resp["MonitoringScheduleStatus"]) assert.Contains(t, resp, "MonitoringScheduleConfig") @@ -73,7 +75,7 @@ func TestHandler_StopMonitoringSchedule(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeMonitoringSchedule", map[string]any{"MonitoringScheduleName": "sched-stop"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Stopped", resp["MonitoringScheduleStatus"]) } @@ -97,7 +99,7 @@ func TestHandler_StartMonitoringSchedule(t *testing.T) { map[string]any{"MonitoringScheduleName": "sched-start"}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Scheduled", resp["MonitoringScheduleStatus"]) } @@ -135,7 +137,7 @@ func TestHandler_ListMonitoringSchedules(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["MonitoringScheduleSummaries"].([]any) assert.Len(t, items, 2) } diff --git a/services/sagemaker/handler_notebook_instances.go b/services/sagemaker/handler_notebook_instances.go index 61ae26c482..7c0a8ae54c 100644 --- a/services/sagemaker/handler_notebook_instances.go +++ b/services/sagemaker/handler_notebook_instances.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -28,7 +29,7 @@ func (h *Handler) handleCreateNotebookInstanceLifecycleConfig( body []byte, ) ([]byte, error) { var req createNotebookLifecycleConfigRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -62,7 +63,7 @@ func (h *Handler) handleCreateNotebookInstanceLifecycleConfig( log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created notebook lifecycle config", "name", lc.Name) - return json.Marshal(map[string]string{keyNotebookLifecycleConfigArn: lc.ARN}) + return json.Marshal(map[string]string{keyNotebookLifecycleConfigArn: lc.ARN}, jsonx.V1()) } // describeNotebookInstanceLifecycleConfigInput is @@ -77,7 +78,7 @@ func (h *Handler) handleDescribeNotebookInstanceLifecycleConfig( body []byte, ) ([]byte, error) { var req describeNotebookInstanceLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.NotebookInstanceLifecycleConfigName == "" { @@ -111,7 +112,7 @@ func (h *Handler) handleDescribeNotebookInstanceLifecycleConfig( "OnStart": onStart, keyCreationTime: epochSeconds(lc.CreationTime), keyLastModifiedTime: epochSeconds(lc.LastModifiedTime), - }) + }, jsonx.V1()) } // updateNotebookInstanceLifecycleConfigInput is @@ -128,7 +129,7 @@ func (h *Handler) handleUpdateNotebookInstanceLifecycleConfig( body []byte, ) ([]byte, error) { var req updateNotebookInstanceLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.NotebookInstanceLifecycleConfigName == "" { @@ -163,7 +164,7 @@ func (h *Handler) handleUpdateNotebookInstanceLifecycleConfig( return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // deleteNotebookInstanceLifecycleConfigInput is @@ -178,7 +179,7 @@ func (h *Handler) handleDeleteNotebookInstanceLifecycleConfig( body []byte, ) error { var req deleteNotebookInstanceLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.NotebookInstanceLifecycleConfigName == "" { @@ -227,7 +228,7 @@ type listNotebookInstanceLifecycleConfigsInput struct { func (h *Handler) handleListNotebookInstanceLifecycleConfigs(ctx context.Context, body []byte) ([]byte, error) { var req listNotebookInstanceLifecycleConfigsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -258,7 +259,7 @@ func (h *Handler) handleListNotebookInstanceLifecycleConfigs(ctx context.Context resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -302,7 +303,7 @@ func (h *Handler) handleCreateNotebookInstanceFull( body []byte, ) ([]byte, error) { var req createNotebookInstanceFullRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -352,7 +353,7 @@ func (h *Handler) handleCreateNotebookInstanceFull( log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created notebook instance (full)", "name", nb.NotebookInstanceName) - return json.Marshal(map[string]string{keyNotebookInstanceArn: nb.NotebookInstanceArn}) + return json.Marshal(map[string]string{keyNotebookInstanceArn: nb.NotebookInstanceArn}, jsonx.V1()) } // describeNotebookInstanceInput is DescribeNotebookInstance's request shape @@ -367,7 +368,7 @@ func (h *Handler) handleDescribeNotebookInstanceFull( body []byte, ) ([]byte, error) { var req describeNotebookInstanceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.NotebookInstanceName == "" { @@ -390,7 +391,7 @@ func (h *Handler) handleDescribeNotebookInstanceFull( } addNotebookOptionalFields(resp, nb) - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // addNotebookOptionalFields adds every describable optional field. @@ -477,7 +478,7 @@ type updateNotebookInstanceInput struct { // handleUpdateNotebookInstanceFull supports all mutable fields (#1 update coverage). func (h *Handler) handleUpdateNotebookInstanceFull(ctx context.Context, body []byte) error { var req updateNotebookInstanceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.NotebookInstanceName == "" { @@ -558,7 +559,7 @@ type listNotebookInstancesInput struct { func (h *Handler) handleListNotebookInstances(ctx context.Context, body []byte) ([]byte, error) { var req listNotebookInstancesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -599,7 +600,7 @@ func (h *Handler) handleListNotebookInstances(ctx context.Context, body []byte) resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteNotebookInstanceInput is DeleteNotebookInstance's request shape @@ -611,7 +612,7 @@ type deleteNotebookInstanceInput struct { func (h *Handler) handleDeleteNotebookInstance(ctx context.Context, body []byte) error { var req deleteNotebookInstanceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -638,7 +639,7 @@ type startNotebookInstanceInput struct { func (h *Handler) handleStartNotebookInstance(ctx context.Context, body []byte) error { var req startNotebookInstanceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -665,7 +666,7 @@ type stopNotebookInstanceInput struct { func (h *Handler) handleStopNotebookInstance(ctx context.Context, body []byte) error { var req stopNotebookInstanceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -698,7 +699,7 @@ func (h *Handler) handleCreatePresignedNotebookInstanceURL( ) ([]byte, error) { var req createPresignedNotebookInstanceURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -715,5 +716,5 @@ func (h *Handler) handleCreatePresignedNotebookInstanceURL( return nil, err } - return json.Marshal(map[string]string{"AuthorizedUrl": url}) + return json.Marshal(map[string]string{"AuthorizedUrl": url}, jsonx.V1()) } diff --git a/services/sagemaker/handler_notebook_instances_test.go b/services/sagemaker/handler_notebook_instances_test.go index 1ea6b4e57f..12bfaee9ac 100644 --- a/services/sagemaker/handler_notebook_instances_test.go +++ b/services/sagemaker/handler_notebook_instances_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_NotebookInstanceLifecycle(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_NotebookInstanceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["NotebookInstanceArn"]) // Describe. @@ -39,7 +41,7 @@ func TestHandler_NotebookInstanceLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["NotebookInstances"].([]any), 1) // Start. @@ -129,7 +131,7 @@ func TestHandler_NotebookInstance_EventuallyInService(t *testing.T) { assert.Equal(t, http.StatusOK, recDesc.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(recDesc.Body.Bytes(), &descOut, jsonx.V1())) assert.NotEmpty(t, descOut["NotebookInstanceStatus"]) }) } diff --git a/services/sagemaker/handler_optimization_jobs.go b/services/sagemaker/handler_optimization_jobs.go index 5be37defb9..3ace41657d 100644 --- a/services/sagemaker/handler_optimization_jobs.go +++ b/services/sagemaker/handler_optimization_jobs.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -15,10 +18,10 @@ import ( // OutputConfig/VpcConfig are decoded as json.RawMessage — see // OptimizationJob's doc comment in optimization_jobs.go for why. type createOptimizationJobInput struct { - ModelSource json.RawMessage `json:"ModelSource"` - OptimizationConfigs json.RawMessage `json:"OptimizationConfigs"` - OutputConfig json.RawMessage `json:"OutputConfig"` - VpcConfig json.RawMessage `json:"VpcConfig"` + ModelSource jsontext.Value `json:"ModelSource"` + OptimizationConfigs jsontext.Value `json:"OptimizationConfigs"` + OutputConfig jsontext.Value `json:"OutputConfig"` + VpcConfig jsontext.Value `json:"VpcConfig"` StoppingCondition *StoppingCondition `json:"StoppingCondition"` OptimizationEnvironment map[string]string `json:"OptimizationEnvironment"` OptimizationJobName string `json:"OptimizationJobName"` @@ -32,7 +35,7 @@ type createOptimizationJobInput struct { func (h *Handler) handleCreateOptimizationJob(ctx context.Context, body []byte) ([]byte, error) { var req createOptimizationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -58,7 +61,7 @@ func (h *Handler) handleCreateOptimizationJob(ctx context.Context, body []byte) return nil, err } - return json.Marshal(map[string]any{keyOptimizationJobArn: result.OptimizationJobArn}) + return json.Marshal(map[string]any{keyOptimizationJobArn: result.OptimizationJobArn}, jsonx.V1()) } // describeOptimizationJobInput mirrors DescribeOptimizationJobInput @@ -126,7 +129,7 @@ func optimizationJobResponseMap(j *OptimizationJob) map[string]any { func (h *Handler) handleDescribeOptimizationJob(ctx context.Context, body []byte) ([]byte, error) { var req describeOptimizationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -139,7 +142,7 @@ func (h *Handler) handleDescribeOptimizationJob(ctx context.Context, body []byte return nil, err } - return json.Marshal(optimizationJobResponseMap(result)) + return json.Marshal(optimizationJobResponseMap(result), jsonx.V1()) } // deleteOptimizationJobInput mirrors DeleteOptimizationJobInput @@ -151,7 +154,7 @@ type deleteOptimizationJobInput struct { func (h *Handler) handleDeleteOptimizationJob(ctx context.Context, body []byte) error { var req deleteOptimizationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -171,7 +174,7 @@ type stopOptimizationJobInput struct { func (h *Handler) handleStopOptimizationJob(ctx context.Context, body []byte) error { var req stopOptimizationJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -201,7 +204,7 @@ type listOptimizationJobsInput struct { func (h *Handler) handleListOptimizationJobs(ctx context.Context, body []byte) ([]byte, error) { var req listOptimizationJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_optimization_jobs_test.go b/services/sagemaker/handler_optimization_jobs_test.go index 4a15775518..13086f0c4e 100644 --- a/services/sagemaker/handler_optimization_jobs_test.go +++ b/services/sagemaker/handler_optimization_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validOptimizationJobBody returns a CreateOptimizationJob request carrying @@ -50,7 +52,7 @@ func TestHandler_CreateOptimizationJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["OptimizationJobArn"], "my-opt-job") } @@ -96,7 +98,7 @@ func TestHandler_DescribeOptimizationJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "opt-1", resp["OptimizationJobName"]) assert.Equal(t, "ml.g5.2xlarge", resp["DeploymentInstanceType"]) } @@ -177,14 +179,14 @@ func TestHandler_ListOptimizationJobs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["OptimizationJobSummaries"]) // Create and list doSageMakerRequest(t, h, "CreateOptimizationJob", validOptimizationJobBody("my-opt-job")) rec = doSageMakerRequest(t, h, "ListOptimizationJobs", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["OptimizationJobSummaries"].([]any) assert.Len(t, summaries, 1) s := summaries[0].(map[string]any) @@ -296,7 +298,7 @@ func TestHandler_AIWorkloadConfigLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["AIWorkloadConfigArn"], "cfg-1") rec = doSageMakerRequest(t, h, "DescribeAIWorkloadConfig", map[string]any{ @@ -305,7 +307,7 @@ func TestHandler_AIWorkloadConfigLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "cfg-1", descResp["AIWorkloadConfigName"]) assert.NotEmpty(t, descResp["CreationTime"]) }, @@ -336,7 +338,7 @@ func TestHandler_AIWorkloadConfigLifecycle(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ResourceNotFound", out["__type"]) }, }, @@ -371,7 +373,7 @@ func TestHandler_AIWorkloadConfigLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["AIWorkloadConfigs"].([]any) assert.Len(t, items, 1) assert.Equal(t, "cfg-list", items[0].(map[string]any)["AIWorkloadConfigName"]) diff --git a/services/sagemaker/handler_partner_apps.go b/services/sagemaker/handler_partner_apps.go index 50fcdc7823..c47f961a6c 100644 --- a/services/sagemaker/handler_partner_apps.go +++ b/services/sagemaker/handler_partner_apps.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -23,7 +26,7 @@ type createPartnerAppInput struct { Tier string `json:"Tier,omitempty"` KmsKeyID string `json:"KmsKeyId,omitempty"` Tags []tagObject `json:"Tags"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig,omitempty"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig,omitempty"` EnableAutoMinorVersionUpgrade bool `json:"EnableAutoMinorVersionUpgrade,omitempty"` EnableIamSessionBasedIdentity bool `json:"EnableIamSessionBasedIdentity,omitempty"` } @@ -31,7 +34,7 @@ type createPartnerAppInput struct { func (h *Handler) handleCreatePartnerApp(ctx context.Context, body []byte) ([]byte, error) { var req createPartnerAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -72,7 +75,7 @@ func (h *Handler) handleCreatePartnerApp(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]any{keyGenericArn: result.Arn}) + return json.Marshal(map[string]any{keyGenericArn: result.Arn}, jsonx.V1()) } // describePartnerAppResponse is the response body for DescribePartnerApp @@ -94,7 +97,7 @@ type describePartnerAppResponse struct { KmsKeyID string `json:"KmsKeyId,omitempty"` Status string `json:"Status"` Name string `json:"Name"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig,omitempty"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig,omitempty"` CreationTime float64 `json:"CreationTime"` LastModifiedTime float64 `json:"LastModifiedTime"` EnableAutoMinorVersionUpgrade bool `json:"EnableAutoMinorVersionUpgrade,omitempty"` @@ -114,7 +117,7 @@ type describePartnerAppInput struct { func (h *Handler) handleDescribePartnerApp(ctx context.Context, body []byte) ([]byte, error) { var req describePartnerAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -143,7 +146,7 @@ func (h *Handler) handleDescribePartnerApp(ctx context.Context, body []byte) ([] EnableIamSessionBasedIdentity: result.EnableIamSessionBasedIdentity, CreationTime: epochSeconds(result.CreationTime), LastModifiedTime: epochSeconds(result.LastModifiedTime), - }) + }, jsonx.V1()) } // deletePartnerAppInput mirrors DeletePartnerAppInput @@ -156,7 +159,7 @@ type deletePartnerAppInput struct { func (h *Handler) handleDeletePartnerApp(ctx context.Context, body []byte) ([]byte, error) { var req deletePartnerAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -168,7 +171,7 @@ func (h *Handler) handleDeletePartnerApp(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]string{keyGenericArn: req.Arn}) + return json.Marshal(map[string]string{keyGenericArn: req.Arn}, jsonx.V1()) } // updatePartnerAppInput mirrors UpdatePartnerAppInput @@ -184,13 +187,13 @@ type updatePartnerAppInput struct { AppVersion string `json:"AppVersion,omitempty"` Tier string `json:"Tier,omitempty"` Tags []tagObject `json:"Tags"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig,omitempty"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig,omitempty"` } func (h *Handler) handleUpdatePartnerApp(ctx context.Context, body []byte) ([]byte, error) { var req updatePartnerAppInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -211,7 +214,7 @@ func (h *Handler) handleUpdatePartnerApp(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]any{keyGenericArn: result.Arn}) + return json.Marshal(map[string]any{keyGenericArn: result.Arn}, jsonx.V1()) } // listPartnerAppsInput mirrors ListPartnerAppsInput @@ -224,7 +227,7 @@ type listPartnerAppsInput struct { func (h *Handler) handleListPartnerApps(ctx context.Context, body []byte) ([]byte, error) { var req listPartnerAppsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -257,7 +260,7 @@ type createPartnerAppPresignedURLInput struct { func (h *Handler) handleCreatePartnerAppPresignedURL(ctx context.Context, body []byte) ([]byte, error) { var req createPartnerAppPresignedURLInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -274,5 +277,5 @@ func (h *Handler) handleCreatePartnerAppPresignedURL(ctx context.Context, body [ return nil, err } - return json.Marshal(map[string]string{keyURL: url}) + return json.Marshal(map[string]string{keyURL: url}, jsonx.V1()) } diff --git a/services/sagemaker/handler_partner_apps_test.go b/services/sagemaker/handler_partner_apps_test.go index d041e8d295..d8383af0f8 100644 --- a/services/sagemaker/handler_partner_apps_test.go +++ b/services/sagemaker/handler_partner_apps_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreatePartnerApp(t *testing.T) { @@ -27,7 +29,7 @@ func TestHandler_CreatePartnerApp(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["Arn"], "my-app") } @@ -44,13 +46,13 @@ func TestHandler_DescribePartnerApp(t *testing.T) { "Tier": "small", }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doSageMakerRequest(t, h, "DescribePartnerApp", map[string]any{"Arn": createResp["Arn"]}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "app-1", resp["Name"]) } @@ -67,7 +69,7 @@ func TestHandler_DeletePartnerApp(t *testing.T) { "Tier": "small", }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doSageMakerRequest(t, h, "DeletePartnerApp", map[string]any{"Arn": createResp["Arn"]}) assert.Equal(t, http.StatusOK, rec.Code) @@ -95,14 +97,14 @@ func TestHandler_PartnerApp_ExtendedLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) appARN := createResp["Arn"] describeRec := doSageMakerRequest(t, h, "DescribePartnerApp", map[string]any{"Arn": appARN}) assert.Equal(t, http.StatusOK, describeRec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "papp-1", describeResp["Name"]) assert.Equal(t, "comet", describeResp["Type"]) assert.Equal(t, "arn:aws:iam::000000000000:role/partner", describeResp["ExecutionRoleArn"]) @@ -115,14 +117,14 @@ func TestHandler_PartnerApp_ExtendedLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, updateRec.Code) describeRec = doSageMakerRequest(t, h, "DescribePartnerApp", map[string]any{"Arn": appARN}) - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "large", describeResp["Tier"]) listRec := doSageMakerRequest(t, h, "ListPartnerApps", map[string]any{}) assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["Summaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -131,7 +133,7 @@ func TestHandler_PartnerApp_ExtendedLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, presignRec.Code) var presignResp map[string]string - require.NoError(t, json.Unmarshal(presignRec.Body.Bytes(), &presignResp)) + require.NoError(t, json.Unmarshal(presignRec.Body.Bytes(), &presignResp, jsonx.V1())) assert.Contains(t, presignResp["Url"], "papp-1") } @@ -176,7 +178,7 @@ func TestHandler_ListPartnerApps_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Summaries"]) } @@ -193,13 +195,13 @@ func TestHandler_DeletePartnerApp_ReturnsArn(t *testing.T) { "Tier": "small", }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doSageMakerRequest(t, h, "DeletePartnerApp", map[string]any{"Arn": createResp["Arn"]}) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, createResp["Arn"], resp["Arn"]) } diff --git a/services/sagemaker/handler_pipeline_versions.go b/services/sagemaker/handler_pipeline_versions.go index a19504f69d..d80a3413bb 100644 --- a/services/sagemaker/handler_pipeline_versions.go +++ b/services/sagemaker/handler_pipeline_versions.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -49,7 +51,7 @@ type listPipelineVersionsRequest struct { func (h *Handler) handleListPipelineVersions(ctx context.Context, body []byte) ([]byte, error) { var req listPipelineVersionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -103,7 +105,7 @@ type updatePipelineVersionRequest struct { func (h *Handler) handleUpdatePipelineVersion(ctx context.Context, body []byte) ([]byte, error) { var req updatePipelineVersionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -125,7 +127,7 @@ func (h *Handler) handleUpdatePipelineVersion(ctx context.Context, body []byte) return json.Marshal(map[string]any{ keyPipelineArn: v.PipelineArn, "PipelineVersionId": v.PipelineVersionID, - }) + }, jsonx.V1()) } type describePipelineDefinitionForExecutionRequest struct { @@ -135,7 +137,7 @@ type describePipelineDefinitionForExecutionRequest struct { func (h *Handler) handleDescribePipelineDefinitionForExecution(ctx context.Context, body []byte) ([]byte, error) { var req describePipelineDefinitionForExecutionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -151,7 +153,7 @@ func (h *Handler) handleDescribePipelineDefinitionForExecution(ctx context.Conte return json.Marshal(map[string]any{ keyPipelineDefinition: definition, keyCreationTime: epochSeconds(creationTime), - }) + }, jsonx.V1()) } type updatePipelineExecutionRequest struct { @@ -164,7 +166,7 @@ type updatePipelineExecutionRequest struct { func (h *Handler) handleUpdatePipelineExecution(ctx context.Context, body []byte) ([]byte, error) { var req updatePipelineExecutionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -183,5 +185,5 @@ func (h *Handler) handleUpdatePipelineExecution(ctx context.Context, body []byte return nil, err } - return json.Marshal(map[string]string{keyPipelineExecutionArn: pe.PipelineExecutionArn}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: pe.PipelineExecutionArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_pipeline_versions_test.go b/services/sagemaker/handler_pipeline_versions_test.go index e556fa2792..182a012376 100644 --- a/services/sagemaker/handler_pipeline_versions_test.go +++ b/services/sagemaker/handler_pipeline_versions_test.go @@ -1,13 +1,15 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) versions, _ := listOut["PipelineVersionSummaries"].([]any) require.Len(t, versions, 1) assert.InDelta(t, float64(1), versions[0].(map[string]any)["PipelineVersionId"], 0) @@ -36,7 +38,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recList2.Code) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2, jsonx.V1())) versions2, _ := listOut2["PipelineVersionSummaries"].([]any) require.Len(t, versions2, 2) // Newest first. @@ -49,7 +51,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recAsc.Code) var ascOut map[string]any - require.NoError(t, json.Unmarshal(recAsc.Body.Bytes(), &ascOut)) + require.NoError(t, json.Unmarshal(recAsc.Body.Bytes(), &ascOut, jsonx.V1())) ascVersions, _ := ascOut["PipelineVersionSummaries"].([]any) require.Len(t, ascVersions, 2) assert.InDelta(t, float64(1), ascVersions[0].(map[string]any)["PipelineVersionId"], 0) @@ -63,7 +65,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recFuture.Code) var futureOut map[string]any - require.NoError(t, json.Unmarshal(recFuture.Body.Bytes(), &futureOut)) + require.NoError(t, json.Unmarshal(recFuture.Body.Bytes(), &futureOut, jsonx.V1())) futureVersions, _ := futureOut["PipelineVersionSummaries"].([]any) assert.Empty(t, futureVersions, "CreatedAfter in the future must exclude every version") @@ -74,13 +76,13 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recPast.Code) var pastOut map[string]any - require.NoError(t, json.Unmarshal(recPast.Body.Bytes(), &pastOut)) + require.NoError(t, json.Unmarshal(recPast.Body.Bytes(), &pastOut, jsonx.V1())) pastVersions, _ := pastOut["PipelineVersionSummaries"].([]any) assert.Empty(t, pastVersions, "CreatedBefore in the past must exclude every version") recDescribe := doSageMakerRequest(t, h, "DescribePipeline", map[string]any{"PipelineName": "ver-pipeline"}) var pipelineOut map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &pipelineOut)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &pipelineOut, jsonx.V1())) pipelineArn, _ := pipelineOut["PipelineArn"].(string) require.NotEmpty(t, pipelineArn) @@ -93,7 +95,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recStart.Code) var startOut map[string]any - require.NoError(t, json.Unmarshal(recStart.Body.Bytes(), &startOut)) + require.NoError(t, json.Unmarshal(recStart.Body.Bytes(), &startOut, jsonx.V1())) execArn, _ := startOut["PipelineExecutionArn"].(string) require.NotEmpty(t, execArn) @@ -103,7 +105,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDefinition.Code) var defOut map[string]any - require.NoError(t, json.Unmarshal(recDefinition.Body.Bytes(), &defOut)) + require.NoError(t, json.Unmarshal(recDefinition.Body.Bytes(), &defOut, jsonx.V1())) assert.JSONEq(t, `{"Version":"v2"}`, defOut["PipelineDefinition"].(string)) recUpdateExec := doSageMakerRequest(t, h, "UpdatePipelineExecution", map[string]any{ @@ -112,7 +114,7 @@ func TestHandler_PipelineVersions_Lifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recUpdateExec.Code) var updateExecOut map[string]any - require.NoError(t, json.Unmarshal(recUpdateExec.Body.Bytes(), &updateExecOut)) + require.NoError(t, json.Unmarshal(recUpdateExec.Body.Bytes(), &updateExecOut, jsonx.V1())) assert.Equal(t, execArn, updateExecOut["PipelineExecutionArn"]) } diff --git a/services/sagemaker/handler_pipelines.go b/services/sagemaker/handler_pipelines.go index 183984216d..74ab158598 100644 --- a/services/sagemaker/handler_pipelines.go +++ b/services/sagemaker/handler_pipelines.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -36,7 +37,7 @@ type retryPipelineExecutionInput struct { func (h *Handler) handleRetryPipelineExecution(ctx context.Context, body []byte) ([]byte, error) { var req retryPipelineExecutionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.PipelineExecutionArn == "" { @@ -51,7 +52,7 @@ func (h *Handler) handleRetryPipelineExecution(ctx context.Context, body []byte) log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: retried pipeline execution", "arn", exec.PipelineExecutionArn) - return json.Marshal(map[string]string{keyPipelineExecutionArn: exec.PipelineExecutionArn}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: exec.PipelineExecutionArn}, jsonx.V1()) } // stopPipelineExecutionInput mirrors StopPipelineExecutionInput @@ -63,7 +64,7 @@ type stopPipelineExecutionInput struct { func (h *Handler) handleStopPipelineExecution(ctx context.Context, body []byte) ([]byte, error) { var req stopPipelineExecutionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.PipelineExecutionArn == "" { @@ -78,7 +79,7 @@ func (h *Handler) handleStopPipelineExecution(ctx context.Context, body []byte) log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: stopped pipeline execution", "arn", exec.PipelineExecutionArn) - return json.Marshal(map[string]string{keyPipelineExecutionArn: exec.PipelineExecutionArn}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: exec.PipelineExecutionArn}, jsonx.V1()) } // sendPipelineExecutionStepSuccessInput mirrors SendPipelineExecutionStepSuccessInput @@ -98,7 +99,7 @@ func (h *Handler) handleSendPipelineExecutionStepSuccess( body []byte, ) ([]byte, error) { var req sendPipelineExecutionStepSuccessInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.CallbackToken == "" { @@ -116,7 +117,7 @@ func (h *Handler) handleSendPipelineExecutionStepSuccess( // backend's execution-ARN convention, so it doubles as the real // response's PipelineExecutionArn (SendPipelineExecutionStepSuccessOutput, // api_op_SendPipelineExecutionStepSuccess.go:48-50). - return json.Marshal(map[string]string{keyPipelineExecutionArn: req.CallbackToken}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: req.CallbackToken}, jsonx.V1()) } // sendPipelineExecutionStepFailureInput mirrors SendPipelineExecutionStepFailureInput @@ -134,7 +135,7 @@ func (h *Handler) handleSendPipelineExecutionStepFailure( body []byte, ) ([]byte, error) { var req sendPipelineExecutionStepFailureInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.CallbackToken == "" { @@ -148,7 +149,7 @@ func (h *Handler) handleSendPipelineExecutionStepFailure( log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: sent pipeline step failure", "token", req.CallbackToken) - return json.Marshal(map[string]string{keyPipelineExecutionArn: req.CallbackToken}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: req.CallbackToken}, jsonx.V1()) } // pipelineStepCallbackMetadata mirrors types.CallbackStepMetadata @@ -191,7 +192,7 @@ type listPipelineExecutionStepsInput struct { func (h *Handler) handleListPipelineExecutionSteps(ctx context.Context, body []byte) ([]byte, error) { var req listPipelineExecutionStepsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.PipelineExecutionArn == "" { @@ -234,7 +235,7 @@ func (h *Handler) handleListPipelineExecutionSteps(ctx context.Context, body []b resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -258,7 +259,7 @@ type createPipelineInput struct { func (h *Handler) handleCreatePipelineFull(ctx context.Context, body []byte) ([]byte, error) { var req createPipelineInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -293,7 +294,7 @@ func (h *Handler) handleCreatePipelineFull(ctx context.Context, body []byte) ([] logger.Load(ctx).InfoContext(ctx, "sagemaker: created pipeline (full)", "name", p.PipelineName) - return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}) + return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}, jsonx.V1()) } // updatePipelineInput mirrors UpdatePipelineInput (api_op_UpdatePipeline.go: @@ -311,7 +312,7 @@ type updatePipelineInput struct { func (h *Handler) handleUpdatePipelineFull(ctx context.Context, body []byte) ([]byte, error) { var req updatePipelineInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -345,7 +346,7 @@ func (h *Handler) handleUpdatePipelineFull(ctx context.Context, body []byte) ([] logger.Load(ctx).InfoContext(ctx, "sagemaker: updated pipeline (full)", "name", p.PipelineName) - return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}) + return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}, jsonx.V1()) } // startPipelineExecutionInput mirrors StartPipelineExecutionInput @@ -371,7 +372,7 @@ func (h *Handler) handleStartPipelineExecutionFull( ) ([]byte, error) { var req startPipelineExecutionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -391,7 +392,7 @@ func (h *Handler) handleStartPipelineExecutionFull( pe.PipelineExecutionArn, ) - return json.Marshal(map[string]string{keyPipelineExecutionArn: pe.PipelineExecutionArn}) + return json.Marshal(map[string]string{keyPipelineExecutionArn: pe.PipelineExecutionArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -413,7 +414,7 @@ func (h *Handler) handleListPipelineParametersForExecution( ) ([]byte, error) { var req listPipelineParametersForExecutionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -438,7 +439,7 @@ func (h *Handler) handleListPipelineParametersForExecution( resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -455,7 +456,7 @@ type describePipelineInput struct { func (h *Handler) handleDescribePipeline(ctx context.Context, body []byte) ([]byte, error) { var req describePipelineInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -506,7 +507,7 @@ func (h *Handler) handleDescribePipeline(ctx context.Context, body []byte) ([]by } } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // pipelineSummary mirrors PipelineSummary (types.go:17593-17620, @@ -539,7 +540,7 @@ type listPipelinesInput struct { func (h *Handler) handleListPipelines(ctx context.Context, body []byte) ([]byte, error) { var req listPipelinesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -577,7 +578,7 @@ func (h *Handler) handleListPipelines(ctx context.Context, body []byte) ([]byte, resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deletePipelineInput mirrors DeletePipelineInput (api_op_DeletePipeline.go: @@ -590,7 +591,7 @@ type deletePipelineInput struct { func (h *Handler) handleDeletePipeline(ctx context.Context, body []byte) ([]byte, error) { var req deletePipelineInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -605,7 +606,7 @@ func (h *Handler) handleDeletePipeline(ctx context.Context, body []byte) ([]byte logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted pipeline", "name", req.PipelineName) - return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}) + return json.Marshal(map[string]string{keyPipelineArn: p.PipelineArn}, jsonx.V1()) } // describePipelineExecutionInput mirrors DescribePipelineExecutionInput @@ -617,7 +618,7 @@ type describePipelineExecutionInput struct { func (h *Handler) handleDescribePipelineExecution(ctx context.Context, body []byte) ([]byte, error) { var req describePipelineExecutionInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -661,7 +662,7 @@ func (h *Handler) handleDescribePipelineExecution(ctx context.Context, body []by resp["MLflowConfig"] = map[string]string{"MlflowExperimentName": pe.MlflowExperimentName} } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type pipelineExecutionSummary struct { @@ -688,7 +689,7 @@ type listPipelineExecutionsInput struct { func (h *Handler) handleListPipelineExecutions(ctx context.Context, body []byte) ([]byte, error) { var req listPipelineExecutionsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -723,5 +724,5 @@ func (h *Handler) handleListPipelineExecutions(ctx context.Context, body []byte) resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_pipelines_test.go b/services/sagemaker/handler_pipelines_test.go index cd351a471e..c6b666db63 100644 --- a/services/sagemaker/handler_pipelines_test.go +++ b/services/sagemaker/handler_pipelines_test.go @@ -3,7 +3,7 @@ package sagemaker_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -68,7 +69,7 @@ func TestHandler_CreatePipeline_FullFields(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "My Pipeline", descResp["PipelineDisplayName"]) assert.Equal(t, "A test pipeline", descResp["PipelineDescription"]) assert.NotNil(t, descResp["ParallelismConfiguration"]) @@ -95,7 +96,7 @@ func TestHandler_UpdatePipeline_FullFields(t *testing.T) { "PipelineName": "my-pipeline", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Updated Display", descResp["PipelineDisplayName"]) assert.Equal(t, "Updated desc", descResp["PipelineDescription"]) } @@ -128,7 +129,7 @@ func TestHandler_CreatePipeline_S3Location_UnreadableRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) rec = doSageMakerRequest(t, h, "DescribePipeline", map[string]any{"PipelineName": "s3-def-pipeline"}) @@ -155,7 +156,7 @@ func TestHandler_UpdatePipeline_S3Location_UnreadableRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } @@ -270,7 +271,7 @@ func TestHandler_StartPipelineExecution_WithParams(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["PipelineExecutionArn"] assert.NotEmpty(t, execArn) @@ -281,7 +282,7 @@ func TestHandler_StartPipelineExecution_WithParams(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Run 1", descResp["PipelineExecutionDisplayName"]) assert.Equal(t, "First run", descResp["PipelineExecutionDescription"]) params := descResp["PipelineParameters"].([]any) @@ -314,7 +315,7 @@ func TestHandler_StartPipelineExecution_ParallelismAndSelectiveExecution(t *test require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["PipelineExecutionArn"] require.NotEmpty(t, execArn) @@ -324,7 +325,7 @@ func TestHandler_StartPipelineExecution_ParallelismAndSelectiveExecution(t *test require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) parallelism, ok := descResp["ParallelismConfiguration"].(map[string]any) require.True(t, ok, "ParallelismConfiguration must be present in DescribePipelineExecution") @@ -367,7 +368,7 @@ func TestHandler_ListPipelineParametersForExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execArn := startResp["PipelineExecutionArn"] require.NotEmpty(t, execArn) @@ -383,7 +384,7 @@ func TestHandler_ListPipelineParametersForExecution(t *testing.T) { Value string `json:"Value"` } `json:"PipelineParameters"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.PipelineParameters, 2) names := make(map[string]string) @@ -409,7 +410,7 @@ func TestHandler_ListPipelineParametersForExecution_Empty(t *testing.T) { "PipelineName": "empty-param-pipe", }) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) rec2 := doSageMakerRequest(t, h, "ListPipelineParametersForExecution", map[string]any{ "PipelineExecutionArn": startResp["PipelineExecutionArn"], @@ -419,7 +420,7 @@ func TestHandler_ListPipelineParametersForExecution_Empty(t *testing.T) { var listResp struct { PipelineParameters []any `json:"PipelineParameters"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listResp, jsonx.V1())) assert.NotNil(t, listResp.PipelineParameters) assert.Empty(t, listResp.PipelineParameters) } @@ -449,7 +450,7 @@ func TestHandler_PipelineLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["PipelineArn"]) // Describe pipeline. @@ -466,7 +467,7 @@ func TestHandler_PipelineLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["PipelineSummaries"].([]any), 1) // Update pipeline. @@ -483,7 +484,7 @@ func TestHandler_PipelineLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recExec.Code) var execOut map[string]any - require.NoError(t, json.Unmarshal(recExec.Body.Bytes(), &execOut)) + require.NoError(t, json.Unmarshal(recExec.Body.Bytes(), &execOut, jsonx.V1())) execArn := execOut["PipelineExecutionArn"].(string) assert.NotEmpty(t, execArn) @@ -553,7 +554,7 @@ func TestHandler_DeletePipeline_RunningExecution(t *testing.T) { require.Equal(t, http.StatusBadRequest, recDelete.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(recDelete.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) // Once the execution reaches Succeeded, the delete is allowed. @@ -640,7 +641,7 @@ func TestHandler_PipelineExecutionSteps(t *testing.T) { require.Equal(t, http.StatusOK, recExec.Code) var execOut map[string]any - require.NoError(t, json.Unmarshal(recExec.Body.Bytes(), &execOut)) + require.NoError(t, json.Unmarshal(recExec.Body.Bytes(), &execOut, jsonx.V1())) execArn := execOut["PipelineExecutionArn"].(string) // ListPipelineExecutionSteps. diff --git a/services/sagemaker/handler_pipelines_versionid_test.go b/services/sagemaker/handler_pipelines_versionid_test.go index 99c8837356..3816453bf2 100644 --- a/services/sagemaker/handler_pipelines_versionid_test.go +++ b/services/sagemaker/handler_pipelines_versionid_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DescribePipeline_PipelineVersionId(t *testing.T) { @@ -59,7 +61,7 @@ func TestHandler_DescribePipeline_PipelineVersionId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantDef, out["PipelineDefinition"]) }) } @@ -81,7 +83,7 @@ func TestHandler_DescribePipeline_LastRunTime(t *testing.T) { require.Equal(t, http.StatusOK, beforeRec.Code, beforeRec.Body.String()) var beforeOut map[string]any - require.NoError(t, json.Unmarshal(beforeRec.Body.Bytes(), &beforeOut)) + require.NoError(t, json.Unmarshal(beforeRec.Body.Bytes(), &beforeOut, jsonx.V1())) _, hasLastRunTime := beforeOut["LastRunTime"] assert.False(t, hasLastRunTime, "a pipeline that has never run must not emit LastRunTime") @@ -96,7 +98,7 @@ func TestHandler_DescribePipeline_LastRunTime(t *testing.T) { require.Equal(t, http.StatusOK, afterRec.Code, afterRec.Body.String()) var afterOut map[string]any - require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut)) + require.NoError(t, json.Unmarshal(afterRec.Body.Bytes(), &afterOut, jsonx.V1())) lastRunTime, ok := afterOut["LastRunTime"].(float64) require.True(t, ok, "a pipeline that has run must emit LastRunTime") diff --git a/services/sagemaker/handler_presigned_session.go b/services/sagemaker/handler_presigned_session.go index 4b06eb5631..f64a4781df 100644 --- a/services/sagemaker/handler_presigned_session.go +++ b/services/sagemaker/handler_presigned_session.go @@ -2,11 +2,13 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -108,7 +110,7 @@ type createPresignedDomainURLRequest struct { func (h *Handler) handleCreatePresignedDomainURL(ctx context.Context, body []byte) ([]byte, error) { var req createPresignedDomainURLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -133,7 +135,7 @@ func (h *Handler) handleCreatePresignedDomainURL(ctx context.Context, body []byt return nil, err } - return json.Marshal(map[string]string{keyAuthorizedURL: url}) + return json.Marshal(map[string]string{keyAuthorizedURL: url}, jsonx.V1()) } // templateVarPattern matches simple Liquid-style "{{ task.input. }}" @@ -162,7 +164,7 @@ type renderUITemplateRequest struct { func (h *Handler) handleRenderUITemplate(ctx context.Context, body []byte) ([]byte, error) { var req renderUITemplateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -195,7 +197,7 @@ func (h *Handler) handleRenderUITemplate(ctx context.Context, body []byte) ([]by return json.Marshal(map[string]any{ "RenderedContent": rendered, "Errors": []any{}, - }) + }, jsonx.V1()) } // renderUITemplateContent substitutes "{{ task.input. }}" variables in @@ -206,7 +208,7 @@ func renderUITemplateContent(content, taskInput string) string { } var fields map[string]any - if err := json.Unmarshal([]byte(taskInput), &fields); err != nil { + if err := json.Unmarshal([]byte(taskInput), &fields, jsonx.V1()); err != nil { return content } @@ -233,7 +235,7 @@ type startSessionRequest struct { func (h *Handler) handleStartSession(ctx context.Context, body []byte) ([]byte, error) { var req startSessionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -250,5 +252,5 @@ func (h *Handler) handleStartSession(ctx context.Context, body []byte) ([]byte, "SessionId": result.SessionID, "StreamUrl": result.StreamURL, "TokenValue": result.TokenValue, - }) + }, jsonx.V1()) } diff --git a/services/sagemaker/handler_presigned_session_test.go b/services/sagemaker/handler_presigned_session_test.go index aacc381360..8a58cdfa28 100644 --- a/services/sagemaker/handler_presigned_session_test.go +++ b/services/sagemaker/handler_presigned_session_test.go @@ -1,13 +1,15 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_RenderUiTemplate(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_RenderUiTemplate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "

      hello world

      ", out["RenderedContent"]) assert.Empty(t, out["Errors"]) } @@ -70,7 +72,7 @@ func TestHandler_StartSession(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["SessionId"]) assert.NotEmpty(t, out["StreamUrl"]) assert.NotEmpty(t, out["TokenValue"]) @@ -95,7 +97,7 @@ func TestHandler_CreatePresignedDomainUrl(t *testing.T) { "DefaultUserSettings": map[string]any{}, }) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID, _ := domainOut["DomainId"].(string) require.NotEmpty(t, domainID) @@ -109,7 +111,7 @@ func TestHandler_CreatePresignedDomainUrl(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["AuthorizedUrl"]) } diff --git a/services/sagemaker/handler_processing_jobs.go b/services/sagemaker/handler_processing_jobs.go index 4cbc569ae0..63fd7023e1 100644 --- a/services/sagemaker/handler_processing_jobs.go +++ b/services/sagemaker/handler_processing_jobs.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -248,7 +249,7 @@ type createProcessingJobRequest struct { func (h *Handler) handleCreateProcessingJob(ctx context.Context, body []byte) ([]byte, error) { var req createProcessingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.ProcessingJobName == "" { @@ -312,7 +313,7 @@ func (h *Handler) handleCreateProcessingJob(ctx context.Context, body []byte) ([ log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created processing job", "name", pj.ProcessingJobName) - return json.Marshal(map[string]string{keyProcessingJobArn: pj.ProcessingJobArn}) + return json.Marshal(map[string]string{keyProcessingJobArn: pj.ProcessingJobArn}, jsonx.V1()) } type describeProcessingJobRequest struct { @@ -321,7 +322,7 @@ type describeProcessingJobRequest struct { func (h *Handler) handleDescribeProcessingJob(ctx context.Context, body []byte) ([]byte, error) { var req describeProcessingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.ProcessingJobName == "" { @@ -367,7 +368,7 @@ func (h *Handler) handleDescribeProcessingJob(ctx context.Context, body []byte) resp["Environment"] = pj.Environment } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type stopProcessingJobRequest struct { @@ -376,7 +377,7 @@ type stopProcessingJobRequest struct { func (h *Handler) handleStopProcessingJob(ctx context.Context, body []byte) error { var req stopProcessingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.ProcessingJobName == "" { @@ -399,7 +400,7 @@ type deleteProcessingJobRequest struct { func (h *Handler) handleDeleteProcessingJob(ctx context.Context, body []byte) error { var req deleteProcessingJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.ProcessingJobName == "" { @@ -440,7 +441,7 @@ type listProcessingJobsRequest struct { func (h *Handler) handleListProcessingJobs(ctx context.Context, body []byte) ([]byte, error) { var req listProcessingJobsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -477,5 +478,5 @@ func (h *Handler) handleListProcessingJobs(ctx context.Context, body []byte) ([] resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_processing_jobs_test.go b/services/sagemaker/handler_processing_jobs_test.go index 65da75075a..06a085de42 100644 --- a/services/sagemaker/handler_processing_jobs_test.go +++ b/services/sagemaker/handler_processing_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -12,6 +12,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DeleteProcessingJob(t *testing.T) { @@ -233,7 +235,7 @@ func TestHandler_ListProcessingJobs_FilterSort(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["ProcessingJobSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "pj-beta", summaries[0].(map[string]any)["ProcessingJobName"]) @@ -243,7 +245,7 @@ func TestHandler_ListProcessingJobs_FilterSort(t *testing.T) { "SortOrder": "Descending", }) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries = resp["ProcessingJobSummaries"].([]any) require.Len(t, summaries, 2) assert.Equal(t, "pj-beta", summaries[0].(map[string]any)["ProcessingJobName"]) diff --git a/services/sagemaker/handler_projects.go b/services/sagemaker/handler_projects.go index 7bf40101d9..0b6e777c06 100644 --- a/services/sagemaker/handler_projects.go +++ b/services/sagemaker/handler_projects.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -12,17 +15,17 @@ import ( // createProjectInput mirrors CreateProjectInput (api_op_CreateProject.go:30-59). type createProjectInput struct { - ServiceCatalogProvisioningDetails json.RawMessage `json:"ServiceCatalogProvisioningDetails"` - TemplateProviders json.RawMessage `json:"TemplateProviders"` - ProjectName string `json:"ProjectName"` - ProjectDescription string `json:"ProjectDescription"` - Tags []tagObject `json:"Tags"` + ServiceCatalogProvisioningDetails jsontext.Value `json:"ServiceCatalogProvisioningDetails"` + TemplateProviders jsontext.Value `json:"TemplateProviders"` + ProjectName string `json:"ProjectName"` + ProjectDescription string `json:"ProjectDescription"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateProject(ctx context.Context, body []byte) ([]byte, error) { var req createProjectInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -44,7 +47,7 @@ func (h *Handler) handleCreateProject(ctx context.Context, body []byte) ([]byte, return json.Marshal(map[string]any{ keyProjectArn: result.ProjectArn, keyProjectID: result.ProjectID, - }) + }, jsonx.V1()) } // describeProjectInput mirrors DescribeProjectInput (api_op_DescribeProject.go:29-34). @@ -100,7 +103,7 @@ func projectResponseMap(p *Project) map[string]any { func (h *Handler) handleDescribeProject(ctx context.Context, body []byte) ([]byte, error) { var req describeProjectInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -113,7 +116,7 @@ func (h *Handler) handleDescribeProject(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(projectResponseMap(result)) + return json.Marshal(projectResponseMap(result), jsonx.V1()) } // deleteProjectInput mirrors DeleteProjectInput (api_op_DeleteProject.go:27-32). @@ -124,7 +127,7 @@ type deleteProjectInput struct { func (h *Handler) handleDeleteProject(ctx context.Context, body []byte) error { var req deleteProjectInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -149,7 +152,7 @@ type listProjectsInput struct { func (h *Handler) handleListProjects(ctx context.Context, body []byte) ([]byte, error) { var req listProjectsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -183,7 +186,7 @@ func (h *Handler) handleListProjects(ctx context.Context, body []byte) ([]byte, resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -202,7 +205,7 @@ type updateProjectInput struct { func (h *Handler) handleUpdateProject(ctx context.Context, body []byte) ([]byte, error) { var req updateProjectInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -228,5 +231,5 @@ func (h *Handler) handleUpdateProject(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyProjectArn: p.ProjectArn}) + return json.Marshal(map[string]string{keyProjectArn: p.ProjectArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_projects_test.go b/services/sagemaker/handler_projects_test.go index 17fb110c3c..734d171a12 100644 --- a/services/sagemaker/handler_projects_test.go +++ b/services/sagemaker/handler_projects_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateProject(t *testing.T) { @@ -23,7 +25,7 @@ func TestHandler_CreateProject(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ProjectArn"], "my-project") assert.NotEmpty(t, resp["ProjectId"]) } @@ -39,7 +41,7 @@ func TestHandler_DescribeProject(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "proj-1", resp["ProjectName"]) assert.Equal(t, "CreateCompleted", resp["ProjectStatus"]) } @@ -69,7 +71,7 @@ func TestHandler_ListProjects(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ProjectSummaryList"].([]any) assert.Len(t, items, 2) } @@ -104,7 +106,7 @@ func TestHandler_ListProjects_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ProjectSummaryList"].([]any) require.Len(t, items, len(tc.wantNames)) @@ -135,7 +137,7 @@ func TestHandler_DescribeProject_NoTagsLeak(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "Tags") assert.NotZero(t, resp["LastModifiedTime"]) } @@ -185,7 +187,7 @@ func TestHandler_UpdateProject(t *testing.T) { require.Equal(t, http.StatusOK, recDescribe.Code) var out map[string]any - require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(recDescribe.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "updated description", out["ProjectDescription"]) } diff --git a/services/sagemaker/handler_servicecatalog.go b/services/sagemaker/handler_servicecatalog.go index c72befbb23..ecbae1207a 100644 --- a/services/sagemaker/handler_servicecatalog.go +++ b/services/sagemaker/handler_servicecatalog.go @@ -2,7 +2,9 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -35,11 +37,11 @@ func (h *Handler) dispatchServicecatalogOps( return []byte("{}"), true, nil case "GetSagemakerServicecatalogPortfolioStatus": status := h.Backend.GetSagemakerServicecatalogPortfolioStatus(ctx) - r, err := json.Marshal(map[string]string{keyStatus: status}) + r, err := json.Marshal(map[string]string{keyStatus: status}, jsonx.V1()) return r, true, err case "ListResourceCatalogs": - r, err := json.Marshal(map[string]any{"ResourceCatalogs": h.Backend.ListResourceCatalogs()}) + r, err := json.Marshal(map[string]any{"ResourceCatalogs": h.Backend.ListResourceCatalogs()}, jsonx.V1()) return r, true, err } diff --git a/services/sagemaker/handler_servicecatalog_test.go b/services/sagemaker/handler_servicecatalog_test.go index b8c341f10b..bacff5951f 100644 --- a/services/sagemaker/handler_servicecatalog_test.go +++ b/services/sagemaker/handler_servicecatalog_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ServicecatalogPortfolio_Toggle(t *testing.T) { @@ -19,7 +21,7 @@ func TestHandler_ServicecatalogPortfolio_Toggle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, want, out["Status"]) } @@ -47,7 +49,7 @@ func TestHandler_ListResourceCatalogs_Empty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["ResourceCatalogs"]) } diff --git a/services/sagemaker/handler_spaces.go b/services/sagemaker/handler_spaces.go index 2982a9e202..9bdc4f1d00 100644 --- a/services/sagemaker/handler_spaces.go +++ b/services/sagemaker/handler_spaces.go @@ -2,8 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -16,19 +19,19 @@ import ( // carried as opaque json.RawMessage passthrough per this file's established // convention. type createSpaceInput struct { - DomainID string `json:"DomainId"` - SpaceName string `json:"SpaceName"` - SpaceDisplayName string `json:"SpaceDisplayName"` - OwnershipSettings json.RawMessage `json:"OwnershipSettings"` - SpaceSettings json.RawMessage `json:"SpaceSettings"` - SpaceSharingSettings json.RawMessage `json:"SpaceSharingSettings"` - Tags []tagObject `json:"Tags"` + DomainID string `json:"DomainId"` + SpaceName string `json:"SpaceName"` + SpaceDisplayName string `json:"SpaceDisplayName"` + OwnershipSettings jsontext.Value `json:"OwnershipSettings"` + SpaceSettings jsontext.Value `json:"SpaceSettings"` + SpaceSharingSettings jsontext.Value `json:"SpaceSharingSettings"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateSpace(ctx context.Context, body []byte) ([]byte, error) { var req createSpaceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -54,7 +57,7 @@ func (h *Handler) handleCreateSpace(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]any{"SpaceArn": result.SpaceArn}) + return json.Marshal(map[string]any{"SpaceArn": result.SpaceArn}, jsonx.V1()) } type describeSpaceInput struct { @@ -65,7 +68,7 @@ type describeSpaceInput struct { func (h *Handler) handleDescribeSpace(ctx context.Context, body []byte) ([]byte, error) { var req describeSpaceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -82,7 +85,7 @@ func (h *Handler) handleDescribeSpace(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } type deleteSpaceInput struct { @@ -93,7 +96,7 @@ type deleteSpaceInput struct { func (h *Handler) handleDeleteSpace(ctx context.Context, body []byte) error { var req deleteSpaceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -120,7 +123,7 @@ type listSpacesInput struct { func (h *Handler) handleListSpaces(ctx context.Context, body []byte) ([]byte, error) { var req listSpacesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -147,21 +150,21 @@ func (h *Handler) handleListSpaces(ctx context.Context, body []byte) ([]byte, er return json.Marshal(map[string]any{ "Spaces": summaries, keyNextToken: next, - }) + }, jsonx.V1()) } // updateSpaceInput mirrors UpdateSpaceInput (api_op_UpdateSpace.go:27-42). type updateSpaceInput struct { - DomainID string `json:"DomainId"` - SpaceName string `json:"SpaceName"` - SpaceDisplayName string `json:"SpaceDisplayName"` - SpaceSettings json.RawMessage `json:"SpaceSettings"` + DomainID string `json:"DomainId"` + SpaceName string `json:"SpaceName"` + SpaceDisplayName string `json:"SpaceDisplayName"` + SpaceSettings jsontext.Value `json:"SpaceSettings"` } func (h *Handler) handleUpdateSpace(ctx context.Context, body []byte) ([]byte, error) { var req updateSpaceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -185,5 +188,5 @@ func (h *Handler) handleUpdateSpace(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]string{keySpaceArn: s.SpaceArn}) + return json.Marshal(map[string]string{keySpaceArn: s.SpaceArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_spaces_test.go b/services/sagemaker/handler_spaces_test.go index 579dcc1a2e..be593eb580 100644 --- a/services/sagemaker/handler_spaces_test.go +++ b/services/sagemaker/handler_spaces_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateSpace(t *testing.T) { @@ -21,7 +23,7 @@ func TestHandler_CreateSpace(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["SpaceArn"], "my-space") } @@ -36,7 +38,7 @@ func TestHandler_DescribeSpace(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "space-1", resp["SpaceName"]) assert.Equal(t, "InService", resp["Status"]) } @@ -67,7 +69,7 @@ func TestHandler_ListSpaces(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Spaces"].([]any) assert.Len(t, items, 2) } @@ -91,7 +93,7 @@ func TestHandler_ListSpaces_NameContainsAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Spaces"].([]any), 2) }) @@ -105,7 +107,7 @@ func TestHandler_ListSpaces_NameContainsAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Spaces"].([]any), 1, "MaxResults must cap the page, not just be parsed and ignored") assert.NotEmpty(t, resp["NextToken"]) }) @@ -127,7 +129,7 @@ func TestHandler_CreateSpace_DisplayNameRoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "My Display Name", resp["SpaceDisplayName"]) } @@ -148,7 +150,7 @@ func TestHandler_UpdateSpace(t *testing.T) { var domainResp map[string]any rec := doSageMakerRequest(t, h, "ListDomains", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &domainResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &domainResp, jsonx.V1())) domains := domainResp["Domains"].([]any) require.Len(t, domains, 1) domainID := domains[0].(map[string]any)["DomainId"].(string) @@ -165,7 +167,7 @@ func TestHandler_UpdateSpace(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["SpaceArn"]) } diff --git a/services/sagemaker/handler_studio_lifecycle_configs.go b/services/sagemaker/handler_studio_lifecycle_configs.go index dba90be8fe..67040238b1 100644 --- a/services/sagemaker/handler_studio_lifecycle_configs.go +++ b/services/sagemaker/handler_studio_lifecycle_configs.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -22,7 +24,7 @@ type createStudioLifecycleConfigInput struct { func (h *Handler) handleCreateStudioLifecycleConfig(ctx context.Context, body []byte) ([]byte, error) { var req createStudioLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -42,7 +44,7 @@ func (h *Handler) handleCreateStudioLifecycleConfig(ctx context.Context, body [] return nil, err } - return json.Marshal(map[string]any{keyStudioLifecycleConfigArn: result.StudioLifecycleConfigArn}) + return json.Marshal(map[string]any{keyStudioLifecycleConfigArn: result.StudioLifecycleConfigArn}, jsonx.V1()) } // describeStudioLifecycleConfigInput mirrors DescribeStudioLifecycleConfigInput @@ -54,7 +56,7 @@ type describeStudioLifecycleConfigInput struct { func (h *Handler) handleDescribeStudioLifecycleConfig(ctx context.Context, body []byte) ([]byte, error) { var req describeStudioLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -67,7 +69,7 @@ func (h *Handler) handleDescribeStudioLifecycleConfig(ctx context.Context, body return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // deleteStudioLifecycleConfigInput mirrors DeleteStudioLifecycleConfigInput @@ -79,7 +81,7 @@ type deleteStudioLifecycleConfigInput struct { func (h *Handler) handleDeleteStudioLifecycleConfig(ctx context.Context, body []byte) error { var req deleteStudioLifecycleConfigInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -110,7 +112,7 @@ type listStudioLifecycleConfigsInput struct { func (h *Handler) handleListStudioLifecycleConfigs(ctx context.Context, body []byte) ([]byte, error) { var req listStudioLifecycleConfigsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_studio_lifecycle_configs_test.go b/services/sagemaker/handler_studio_lifecycle_configs_test.go index e24af8cc23..2c512db2f2 100644 --- a/services/sagemaker/handler_studio_lifecycle_configs_test.go +++ b/services/sagemaker/handler_studio_lifecycle_configs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateStudioLifecycleConfig(t *testing.T) { @@ -25,7 +27,7 @@ func TestHandler_CreateStudioLifecycleConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["StudioLifecycleConfigArn"], "my-lc") } @@ -45,7 +47,7 @@ func TestHandler_DescribeStudioLifecycleConfig(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "lc-1", resp["StudioLifecycleConfigName"]) } @@ -67,7 +69,7 @@ func TestHandler_CreateStudioLifecycleConfig_Content(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "IyEvYmluL2Jhc2g=", resp["StudioLifecycleConfigContent"]) } @@ -134,7 +136,7 @@ func TestHandler_ListStudioLifecycleConfigs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["StudioLifecycleConfigs"]) doSageMakerRequest(t, h, "CreateStudioLifecycleConfig", map[string]any{ @@ -144,7 +146,7 @@ func TestHandler_ListStudioLifecycleConfigs(t *testing.T) { }) rec = doSageMakerRequest(t, h, "ListStudioLifecycleConfigs", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs := resp["StudioLifecycleConfigs"].([]any) assert.Len(t, configs, 1) c := configs[0].(map[string]any) diff --git a/services/sagemaker/handler_tags.go b/services/sagemaker/handler_tags.go index e925d9cce8..2d366166e5 100644 --- a/services/sagemaker/handler_tags.go +++ b/services/sagemaker/handler_tags.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -29,7 +30,7 @@ type deleteTagsRequest struct { func (h *Handler) handleAddTags(ctx context.Context, body []byte) ([]byte, error) { var req addTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -55,12 +56,12 @@ func (h *Handler) handleAddTags(ctx context.Context, body []byte) ([]byte, error return nil, err } - return json.Marshal(map[string]any{"Tags": toTagObjects(allTags)}) + return json.Marshal(map[string]any{"Tags": toTagObjects(allTags)}, jsonx.V1()) } func (h *Handler) handleListTags(ctx context.Context, body []byte) ([]byte, error) { var req listTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -80,12 +81,12 @@ func (h *Handler) handleListTags(ctx context.Context, body []byte) ([]byte, erro resp["NextToken"] = outToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleDeleteTags(ctx context.Context, body []byte) error { var req deleteTagsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/sagemaker/handler_tags_test.go b/services/sagemaker/handler_tags_test.go index 4bdbeb828c..8999f8f465 100644 --- a/services/sagemaker/handler_tags_test.go +++ b/services/sagemaker/handler_tags_test.go @@ -2,12 +2,14 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_Tags(t *testing.T) { @@ -34,7 +36,7 @@ func TestHandler_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var addResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &addResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &addResp, jsonx.V1())) addTags, ok := addResp["Tags"].([]any) require.True(t, ok, "AddTags response body: %s", rec.Body.String()) @@ -47,7 +49,7 @@ func TestHandler_Tags(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].([]any) require.True(t, ok) @@ -64,7 +66,7 @@ func TestHandler_Tags(t *testing.T) { rec = doSageMakerRequest(t, h, "ListTags", map[string]any{ "ResourceArn": m.ModelARN, }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, ok = resp["Tags"].([]any) require.True(t, ok) @@ -203,7 +205,7 @@ func TestHandler_ListTags_MaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) page, ok := resp["Tags"].([]any) require.True(t, ok) diff --git a/services/sagemaker/handler_test.go b/services/sagemaker/handler_test.go index f627737373..2089a2d263 100644 --- a/services/sagemaker/handler_test.go +++ b/services/sagemaker/handler_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -32,7 +33,7 @@ func doSageMakerRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -246,7 +247,7 @@ func TestHandler_SageMakerReset(t *testing.T) { require.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) require.NotEmpty(t, listOut["Models"]) // Reset. @@ -257,7 +258,7 @@ func TestHandler_SageMakerReset(t *testing.T) { require.Equal(t, http.StatusOK, recList2.Code) var listOut2 map[string]any - require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2)) + require.NoError(t, json.Unmarshal(recList2.Body.Bytes(), &listOut2, jsonx.V1())) assert.Empty(t, listOut2["Models"]) // Feature groups gone. @@ -265,7 +266,7 @@ func TestHandler_SageMakerReset(t *testing.T) { require.Equal(t, http.StatusOK, recFG.Code) var fgOut map[string]any - require.NoError(t, json.Unmarshal(recFG.Body.Bytes(), &fgOut)) + require.NoError(t, json.Unmarshal(recFG.Body.Bytes(), &fgOut, jsonx.V1())) assert.Empty(t, fgOut["FeatureGroupSummaries"]) } diff --git a/services/sagemaker/handler_training_jobs.go b/services/sagemaker/handler_training_jobs.go index 2c2f37a5ad..f5eda7cac6 100644 --- a/services/sagemaker/handler_training_jobs.go +++ b/services/sagemaker/handler_training_jobs.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -43,7 +45,7 @@ type createTrainingJobFullRequest struct { func (h *Handler) handleCreateTrainingJobFull(ctx context.Context, body []byte) ([]byte, error) { var req createTrainingJobFullRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.TrainingJobName == "" { @@ -110,7 +112,7 @@ func (h *Handler) handleCreateTrainingJobFull(ctx context.Context, body []byte) log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: created training job (full)", "name", tj.TrainingJobName) - return json.Marshal(map[string]string{keyTrainingJobArn: tj.TrainingJobArn}) + return json.Marshal(map[string]string{keyTrainingJobArn: tj.TrainingJobArn}, jsonx.V1()) } // describeTrainingJobInput mirrors DescribeTrainingJobInput (api_op_DescribeTrainingJob.go:29-36). @@ -127,18 +129,18 @@ func trainingJobPassthroughKeys() []string { } } -func trainingJobPassthroughConfigs(body []byte) (map[string]json.RawMessage, error) { - var all map[string]json.RawMessage - if err := json.Unmarshal(body, &all); err != nil { +func trainingJobPassthroughConfigs(body []byte) (map[string]jsontext.Value, error) { + var all map[string]jsontext.Value + if err := json.Unmarshal(body, &all, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } - var out map[string]json.RawMessage + var out map[string]jsontext.Value for _, k := range trainingJobPassthroughKeys() { if v, ok := all[k]; ok && string(v) != "null" { if out == nil { - out = make(map[string]json.RawMessage) + out = make(map[string]jsontext.Value) } out[k] = v @@ -150,7 +152,7 @@ func trainingJobPassthroughConfigs(body []byte) (map[string]json.RawMessage, err func (h *Handler) handleDescribeTrainingJobFull(ctx context.Context, body []byte) ([]byte, error) { var req describeTrainingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.TrainingJobName == "" { @@ -181,7 +183,7 @@ func (h *Handler) handleDescribeTrainingJobFull(ctx context.Context, body []byte } addTrainingJobOptionalFields(resp, tj) - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func addTrainingJobOptionalFields(resp map[string]any, tj *TrainingJob) { @@ -252,7 +254,7 @@ type stopTrainingJobInput struct { func (h *Handler) handleStopTrainingJobFSM(ctx context.Context, body []byte) error { var req stopTrainingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } if req.TrainingJobName == "" { @@ -287,7 +289,7 @@ type listTrainingJobsInput struct { func (h *Handler) handleListTrainingJobsFiltered(ctx context.Context, body []byte) ([]byte, error) { var req listTrainingJobsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -328,7 +330,7 @@ func (h *Handler) handleListTrainingJobsFiltered(ctx context.Context, body []byt resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -356,7 +358,7 @@ type deleteTrainingJobInput struct { func (h *Handler) handleDeleteTrainingJob(ctx context.Context, body []byte) error { var req deleteTrainingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -392,15 +394,15 @@ type resourceConfigForUpdate struct { type updateTrainingJobInput struct { ResourceConfig *resourceConfigForUpdate `json:"ResourceConfig"` TrainingJobName string `json:"TrainingJobName"` - ProfilerConfig json.RawMessage `json:"ProfilerConfig"` - ProfilerRuleConfigurations json.RawMessage `json:"ProfilerRuleConfigurations"` - RemoteDebugConfig json.RawMessage `json:"RemoteDebugConfig"` + ProfilerConfig jsontext.Value `json:"ProfilerConfig"` + ProfilerRuleConfigurations jsontext.Value `json:"ProfilerRuleConfigurations"` + RemoteDebugConfig jsontext.Value `json:"RemoteDebugConfig"` } func (h *Handler) handleUpdateTrainingJob(ctx context.Context, body []byte) ([]byte, error) { var req updateTrainingJobInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -421,5 +423,5 @@ func (h *Handler) handleUpdateTrainingJob(ctx context.Context, body []byte) ([]b log := logger.Load(ctx) log.InfoContext(ctx, "sagemaker: updated training job", "name", req.TrainingJobName) - return json.Marshal(map[string]string{keyTrainingJobArn: tj.TrainingJobArn}) + return json.Marshal(map[string]string{keyTrainingJobArn: tj.TrainingJobArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_training_jobs_test.go b/services/sagemaker/handler_training_jobs_test.go index 7efd37761f..f326328281 100644 --- a/services/sagemaker/handler_training_jobs_test.go +++ b/services/sagemaker/handler_training_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -12,6 +12,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TrainingJobLifecycle(t *testing.T) { @@ -43,7 +45,7 @@ func testHandlerTrainingJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recCreate.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(recCreate.Body.Bytes(), &createOut, jsonx.V1())) assert.NotEmpty(t, createOut["TrainingJobArn"]) // Describe training job. @@ -58,7 +60,7 @@ func testHandlerTrainingJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["TrainingJobSummaries"].([]any), 1) // StopTrainingJob. diff --git a/services/sagemaker/handler_training_plan.go b/services/sagemaker/handler_training_plan.go index fc79577bf0..72986bda32 100644 --- a/services/sagemaker/handler_training_plan.go +++ b/services/sagemaker/handler_training_plan.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // trainingPlanExtOpsSupported returns the real stateful operations implemented @@ -150,7 +152,7 @@ type listTrainingPlansInput struct { func (h *Handler) handleListTrainingPlans(ctx context.Context, body []byte) ([]byte, error) { var req listTrainingPlansInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -207,7 +209,7 @@ type searchTrainingPlanOfferingsInput struct { func (h *Handler) handleSearchTrainingPlanOfferings(ctx context.Context, body []byte) ([]byte, error) { var req searchTrainingPlanOfferingsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -241,7 +243,7 @@ func (h *Handler) handleSearchTrainingPlanOfferings(ctx context.Context, body [] return json.Marshal(map[string]any{ "TrainingPlanOfferings": items, "TrainingPlanExtensionOfferings": extOfferings, - }) + }, jsonx.V1()) } // extendTrainingPlanInput mirrors ExtendTrainingPlanInput @@ -254,7 +256,7 @@ type extendTrainingPlanInput struct { func (h *Handler) handleExtendTrainingPlan(ctx context.Context, body []byte) ([]byte, error) { var req extendTrainingPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -267,7 +269,7 @@ func (h *Handler) handleExtendTrainingPlan(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{"TrainingPlanExtensions": extensions}) + return json.Marshal(map[string]any{"TrainingPlanExtensions": extensions}, jsonx.V1()) } // describeTrainingPlanExtensionHistoryInput mirrors @@ -283,7 +285,7 @@ type describeTrainingPlanExtensionHistoryInput struct { func (h *Handler) handleDescribeTrainingPlanExtensionHistory(ctx context.Context, body []byte) ([]byte, error) { var req describeTrainingPlanExtensionHistoryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -298,7 +300,7 @@ func (h *Handler) handleDescribeTrainingPlanExtensionHistory(ctx context.Context return nil, err } - return json.Marshal(map[string]any{"TrainingPlanExtensions": extensions, keyNextToken: next}) + return json.Marshal(map[string]any{"TrainingPlanExtensions": extensions, keyNextToken: next}, jsonx.V1()) } // describeReservedCapacityInput mirrors DescribeReservedCapacityInput @@ -311,7 +313,7 @@ type describeReservedCapacityInput struct { func (h *Handler) handleDescribeReservedCapacity(ctx context.Context, body []byte) ([]byte, error) { var req describeReservedCapacityInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -324,7 +326,7 @@ func (h *Handler) handleDescribeReservedCapacity(ctx context.Context, body []byt return nil, err } - return json.Marshal(rc) + return json.Marshal(rc, jsonx.V1()) } // listUltraServersByReservedCapacityInput mirrors @@ -340,7 +342,7 @@ type listUltraServersByReservedCapacityInput struct { func (h *Handler) handleListUltraServersByReservedCapacity(ctx context.Context, body []byte) ([]byte, error) { var req listUltraServersByReservedCapacityInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -355,5 +357,5 @@ func (h *Handler) handleListUltraServersByReservedCapacity(ctx context.Context, return nil, err } - return json.Marshal(map[string]any{"UltraServers": servers, keyNextToken: next}) + return json.Marshal(map[string]any{"UltraServers": servers, keyNextToken: next}, jsonx.V1()) } diff --git a/services/sagemaker/handler_training_plan_test.go b/services/sagemaker/handler_training_plan_test.go index 8454478e5e..2660952f2d 100644 --- a/services/sagemaker/handler_training_plan_test.go +++ b/services/sagemaker/handler_training_plan_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, searchRec.Code) var searchResp map[string]any - require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &searchResp)) + require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &searchResp, jsonx.V1())) offerings, ok := searchResp["TrainingPlanOfferings"].([]any) require.True(t, ok) require.NotEmpty(t, offerings) @@ -46,7 +48,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, describeRec.Code) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) assert.Equal(t, "Scheduled", describeResp["Status"]) assert.InEpsilon(t, float64(720), describeResp["DurationHours"], 0.001) @@ -68,7 +70,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rcRec.Code) var rcResp map[string]any - require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcResp)) + require.NoError(t, json.Unmarshal(rcRec.Body.Bytes(), &rcResp, jsonx.V1())) assert.Equal(t, "ml.p5.48xlarge", rcResp["InstanceType"]) assert.InEpsilon(t, float64(8), rcResp["TotalInstanceCount"], 0.001) @@ -77,7 +79,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries, ok := listResp["TrainingPlanSummaries"].([]any) require.True(t, ok) assert.Len(t, summaries, 1) @@ -89,7 +91,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, extSearchRec.Code) var extSearchResp map[string]any - require.NoError(t, json.Unmarshal(extSearchRec.Body.Bytes(), &extSearchResp)) + require.NoError(t, json.Unmarshal(extSearchRec.Body.Bytes(), &extSearchResp, jsonx.V1())) extOfferings, ok := extSearchResp["TrainingPlanExtensionOfferings"].([]any) require.True(t, ok) require.NotEmpty(t, extOfferings) @@ -105,7 +107,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, extendRec.Code) var extendResp map[string]any - require.NoError(t, json.Unmarshal(extendRec.Body.Bytes(), &extendResp)) + require.NoError(t, json.Unmarshal(extendRec.Body.Bytes(), &extendResp, jsonx.V1())) extensions, ok := extendResp["TrainingPlanExtensions"].([]any) require.True(t, ok) assert.Len(t, extensions, 1) @@ -116,7 +118,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, historyRec.Code) var historyResp map[string]any - require.NoError(t, json.Unmarshal(historyRec.Body.Bytes(), &historyResp)) + require.NoError(t, json.Unmarshal(historyRec.Body.Bytes(), &historyResp, jsonx.V1())) historyExtensions, ok := historyResp["TrainingPlanExtensions"].([]any) require.True(t, ok) assert.Len(t, historyExtensions, 1) @@ -127,7 +129,7 @@ func TestHandler_TrainingPlan_OfferingLifecycle(t *testing.T) { }) var describeAfterResp map[string]any - require.NoError(t, json.Unmarshal(describeAfterRec.Body.Bytes(), &describeAfterResp)) + require.NoError(t, json.Unmarshal(describeAfterRec.Body.Bytes(), &describeAfterResp, jsonx.V1())) assert.Greater(t, describeAfterResp["DurationHours"], describeResp["DurationHours"]) } @@ -141,7 +143,7 @@ func TestHandler_TrainingPlan_UltraServerOffering(t *testing.T) { }) var searchResp map[string]any - require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &searchResp)) + require.NoError(t, json.Unmarshal(searchRec.Body.Bytes(), &searchResp, jsonx.V1())) offerings, ok := searchResp["TrainingPlanOfferings"].([]any) require.True(t, ok) require.NotEmpty(t, offerings) @@ -160,7 +162,7 @@ func TestHandler_TrainingPlan_UltraServerOffering(t *testing.T) { }) var describeResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &describeResp, jsonx.V1())) rcSummaries, ok := describeResp["ReservedCapacitySummaries"].([]any) require.True(t, ok) require.Len(t, rcSummaries, 1) @@ -176,7 +178,7 @@ func TestHandler_TrainingPlan_UltraServerOffering(t *testing.T) { assert.Equal(t, http.StatusOK, ultraRec.Code) var ultraResp map[string]any - require.NoError(t, json.Unmarshal(ultraRec.Body.Bytes(), &ultraResp)) + require.NoError(t, json.Unmarshal(ultraRec.Body.Bytes(), &ultraResp, jsonx.V1())) servers, ok := ultraResp["UltraServers"].([]any) require.True(t, ok) assert.Len(t, servers, 1) diff --git a/services/sagemaker/handler_training_plans.go b/services/sagemaker/handler_training_plans.go index 27a815b67d..735943b5ac 100644 --- a/services/sagemaker/handler_training_plans.go +++ b/services/sagemaker/handler_training_plans.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -25,7 +27,7 @@ type createTrainingPlanInput struct { func (h *Handler) handleCreateTrainingPlan(ctx context.Context, body []byte) ([]byte, error) { var req createTrainingPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -45,7 +47,7 @@ func (h *Handler) handleCreateTrainingPlan(ctx context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{keyTrainingPlanArn: result.TrainingPlanArn}) + return json.Marshal(map[string]any{keyTrainingPlanArn: result.TrainingPlanArn}, jsonx.V1()) } // describeTrainingPlanInput mirrors DescribeTrainingPlanInput @@ -58,7 +60,7 @@ type describeTrainingPlanInput struct { func (h *Handler) handleDescribeTrainingPlan(ctx context.Context, body []byte) ([]byte, error) { var req describeTrainingPlanInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -71,5 +73,5 @@ func (h *Handler) handleDescribeTrainingPlan(ctx context.Context, body []byte) ( return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } diff --git a/services/sagemaker/handler_training_plans_test.go b/services/sagemaker/handler_training_plans_test.go index 1ea544a645..0968dd25c5 100644 --- a/services/sagemaker/handler_training_plans_test.go +++ b/services/sagemaker/handler_training_plans_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateTrainingPlan(t *testing.T) { @@ -21,7 +23,7 @@ func TestHandler_CreateTrainingPlan(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["TrainingPlanArn"], "my-plan") } @@ -38,7 +40,7 @@ func TestHandler_DescribeTrainingPlan(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "plan-1", resp["TrainingPlanName"]) // TargetResources/TotalInstanceCount/UpfrontFee were previously tagged diff --git a/services/sagemaker/handler_transform_jobs.go b/services/sagemaker/handler_transform_jobs.go index 62026d07e6..3f986c4f67 100644 --- a/services/sagemaker/handler_transform_jobs.go +++ b/services/sagemaker/handler_transform_jobs.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -32,7 +33,7 @@ type createTransformJobRequest struct { func (h *Handler) handleCreateTransformJob(ctx context.Context, body []byte) ([]byte, error) { var req createTransformJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -94,7 +95,7 @@ func (h *Handler) handleCreateTransformJob(ctx context.Context, body []byte) ([] logger.Load(ctx).InfoContext(ctx, "sagemaker: created transform job", "name", tj.TransformJobName) - return json.Marshal(map[string]string{"TransformJobArn": tj.TransformJobArn}) + return json.Marshal(map[string]string{"TransformJobArn": tj.TransformJobArn}, jsonx.V1()) } type describeTransformJobRequest struct { @@ -104,7 +105,7 @@ type describeTransformJobRequest struct { func (h *Handler) handleDescribeTransformJob(ctx context.Context, body []byte) ([]byte, error) { var req describeTransformJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -156,7 +157,7 @@ func (h *Handler) handleDescribeTransformJob(ctx context.Context, body []byte) ( resp["ModelClientConfig"] = tj.ModelClientConfig } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type stopTransformJobRequest struct { @@ -166,7 +167,7 @@ type stopTransformJobRequest struct { func (h *Handler) handleStopTransformJob(ctx context.Context, body []byte) error { var req stopTransformJobRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -212,7 +213,7 @@ type listTransformJobsRequest struct { func (h *Handler) handleListTransformJobs(ctx context.Context, body []byte) ([]byte, error) { var req listTransformJobsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -252,5 +253,5 @@ func (h *Handler) handleListTransformJobs(ctx context.Context, body []byte) ([]b resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_transform_jobs_test.go b/services/sagemaker/handler_transform_jobs_test.go index edf1955d24..3e93533214 100644 --- a/services/sagemaker/handler_transform_jobs_test.go +++ b/services/sagemaker/handler_transform_jobs_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -50,7 +51,7 @@ func TestHandler_TransformJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotEmpty(t, createResp["TransformJobArn"]) // Describe — InProgress initially @@ -60,7 +61,7 @@ func TestHandler_TransformJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "my-transform", descResp["TransformJobName"]) assert.Equal(t, "my-model", descResp["ModelName"]) assert.Equal(t, "InProgress", descResp["TransformJobStatus"]) @@ -71,7 +72,7 @@ func TestHandler_TransformJobLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["TransformJobSummaries"].([]any) assert.Len(t, summaries, 1) @@ -81,7 +82,7 @@ func TestHandler_TransformJobLifecycle(t *testing.T) { rec = doSageMakerRequest(t, h, "DescribeTransformJob", map[string]any{ "TransformJobName": "my-transform", }) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Completed", descResp["TransformJobStatus"]) }) } @@ -147,7 +148,7 @@ func TestHandler_CreateTransformJob_ModelNotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFound", errResp["__type"]) rec = doSageMakerRequest(t, h, "DescribeTransformJob", map[string]any{ @@ -185,7 +186,7 @@ func TestHandler_StopTransformJob(t *testing.T) { "TransformJobName": "stop-me", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Stopping", descResp["TransformJobStatus"]) } @@ -219,7 +220,7 @@ func TestHandler_ListTransformJobs_StatusFilter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["TransformJobSummaries"].([]any) assert.Len(t, summaries, 1) assert.Equal(t, "tj-2", summaries[0].(map[string]any)["TransformJobName"]) @@ -253,7 +254,7 @@ func TestHandler_ListTransformJobs_SortByName(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["TransformJobSummaries"].([]any) require.Len(t, summaries, 2) assert.Equal(t, "tj-alpha", summaries[0].(map[string]any)["TransformJobName"]) @@ -341,7 +342,7 @@ func TestHandler_CreateTransformJob_RoleArnNotPartOfWireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) _, present := descResp["RoleArn"] assert.False(t, present, "RoleArn is not a real CreateTransformJobInput/DescribeTransformJobOutput field") } @@ -482,7 +483,7 @@ func TestHandler_Tags_TransformJob(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobARN := createResp["TransformJobArn"] require.NotEmpty(t, jobARN) @@ -492,7 +493,7 @@ func TestHandler_Tags_TransformJob(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) require.Len(t, tags, 1) assert.Equal(t, "owner", tags[0].(map[string]any)["Key"]) diff --git a/services/sagemaker/handler_trial_components.go b/services/sagemaker/handler_trial_components.go index 6f5f5b0bd6..723ba00523 100644 --- a/services/sagemaker/handler_trial_components.go +++ b/services/sagemaker/handler_trial_components.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -31,7 +32,7 @@ type createTrialComponentInput struct { func (h *Handler) handleCreateTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req createTrialComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -58,7 +59,7 @@ func (h *Handler) handleCreateTrialComponent(ctx context.Context, body []byte) ( logger.Load(ctx). InfoContext(ctx, "sagemaker: created trial component", "name", tc.TrialComponentName) - return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}) + return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}, jsonx.V1()) } // describeTrialComponentInput mirrors DescribeTrialComponentInput @@ -78,7 +79,7 @@ type describeTrialComponentInput struct { func (h *Handler) handleDescribeTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req describeTrialComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -129,7 +130,7 @@ func (h *Handler) handleDescribeTrialComponent(ctx context.Context, body []byte) resp["LastModifiedBy"] = tc.LastModifiedBy } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteTrialComponentInput mirrors DeleteTrialComponentInput @@ -142,7 +143,7 @@ type deleteTrialComponentInput struct { func (h *Handler) handleDeleteTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req deleteTrialComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -158,7 +159,7 @@ func (h *Handler) handleDeleteTrialComponent(ctx context.Context, body []byte) ( logger.Load(ctx). InfoContext(ctx, "sagemaker: deleted trial component", "name", req.TrialComponentName) - return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}) + return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}, jsonx.V1()) } // --------------------------------------------------------------------------- @@ -176,7 +177,7 @@ type disassociateTrialComponentInput struct { func (h *Handler) handleDisassociateTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req disassociateTrialComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -198,7 +199,7 @@ func (h *Handler) handleDisassociateTrialComponent(ctx context.Context, body []b return json.Marshal(map[string]string{ keyTrialArn: trialArn, keyTrialComponentArn: trialComponentArn, - }) + }, jsonx.V1()) } // listTrialComponentsInput mirrors ListTrialComponentsInput @@ -220,7 +221,7 @@ type listTrialComponentsInput struct { func (h *Handler) handleListTrialComponents(ctx context.Context, body []byte) ([]byte, error) { var req listTrialComponentsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -283,7 +284,7 @@ type updateTrialComponentInput struct { func (h *Handler) handleUpdateTrialComponent(ctx context.Context, body []byte) ([]byte, error) { var req updateTrialComponentInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -316,5 +317,5 @@ func (h *Handler) handleUpdateTrialComponent(ctx context.Context, body []byte) ( tc.TrialComponentName, ) - return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}) + return json.Marshal(map[string]string{keyTrialComponentArn: tc.TrialComponentArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_trial_components_test.go b/services/sagemaker/handler_trial_components_test.go index 8f753730e7..cc7c647a12 100644 --- a/services/sagemaker/handler_trial_components_test.go +++ b/services/sagemaker/handler_trial_components_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { @@ -31,7 +33,7 @@ func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { require.Equal(t, http.StatusOK, recByTrial.Code) var byTrial map[string]any - require.NoError(t, json.Unmarshal(recByTrial.Body.Bytes(), &byTrial)) + require.NoError(t, json.Unmarshal(recByTrial.Body.Bytes(), &byTrial, jsonx.V1())) summaries, _ := byTrial["TrialComponentSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "tc-a", summaries[0].(map[string]any)["TrialComponentName"]) @@ -41,7 +43,7 @@ func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { require.Equal(t, http.StatusOK, recByExp.Code) var byExp map[string]any - require.NoError(t, json.Unmarshal(recByExp.Body.Bytes(), &byExp)) + require.NoError(t, json.Unmarshal(recByExp.Body.Bytes(), &byExp, jsonx.V1())) expSummaries, _ := byExp["TrialComponentSummaries"].([]any) require.Len(t, expSummaries, 1) @@ -50,7 +52,7 @@ func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { require.Equal(t, http.StatusOK, recAll.Code) var all map[string]any - require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &all)) + require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &all, jsonx.V1())) allSummaries, _ := all["TrialComponentSummaries"].([]any) assert.Len(t, allSummaries, 2) @@ -61,7 +63,7 @@ func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { require.Equal(t, http.StatusOK, recDisassoc.Code) var disassocOut map[string]any - require.NoError(t, json.Unmarshal(recDisassoc.Body.Bytes(), &disassocOut)) + require.NoError(t, json.Unmarshal(recDisassoc.Body.Bytes(), &disassocOut, jsonx.V1())) assert.NotEmpty(t, disassocOut["TrialArn"]) assert.NotEmpty(t, disassocOut["TrialComponentArn"]) @@ -69,7 +71,7 @@ func TestHandler_ListAndDisassociateTrialComponents(t *testing.T) { require.Equal(t, http.StatusOK, recByTrial2.Code) var byTrial2 map[string]any - require.NoError(t, json.Unmarshal(recByTrial2.Body.Bytes(), &byTrial2)) + require.NoError(t, json.Unmarshal(recByTrial2.Body.Bytes(), &byTrial2, jsonx.V1())) assert.Empty(t, byTrial2["TrialComponentSummaries"]) } @@ -87,7 +89,7 @@ func TestHandler_DisassociateTrialComponent_Idempotent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out["TrialArn"], "never-existed") } @@ -173,7 +175,7 @@ func TestHandler_UpdateTrialComponent(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["TrialComponentArn"]) // Describe returns updated fields @@ -181,7 +183,7 @@ func TestHandler_UpdateTrialComponent(t *testing.T) { "TrialComponentName": "my-tc", }) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "TC Display", descResp["DisplayName"]) assert.Equal(t, "InProgress", descResp["Status"].(map[string]any)["PrimaryStatus"]) assert.NotNil(t, descResp["Parameters"]) @@ -218,7 +220,7 @@ func TestHandler_CreateTrialComponent_FullFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Training Run 1", descResp["DisplayName"]) assert.InEpsilon(t, float64(1700000000), descResp["StartTime"], 0) assert.InEpsilon(t, float64(1700003600), descResp["EndTime"], 0) diff --git a/services/sagemaker/handler_trials.go b/services/sagemaker/handler_trials.go index 8f605e9eff..4ff655bacc 100644 --- a/services/sagemaker/handler_trials.go +++ b/services/sagemaker/handler_trials.go @@ -2,9 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -24,7 +25,7 @@ type createTrialInput struct { func (h *Handler) handleCreateTrial(ctx context.Context, body []byte) ([]byte, error) { var req createTrialInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -41,7 +42,7 @@ func (h *Handler) handleCreateTrial(ctx context.Context, body []byte) ([]byte, e logger.Load(ctx).InfoContext(ctx, "sagemaker: created trial", "name", t.TrialName) - return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}) + return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}, jsonx.V1()) } // describeTrialInput mirrors DescribeTrialInput (api_op_DescribeTrial.go:29-36). @@ -52,7 +53,7 @@ type describeTrialInput struct { func (h *Handler) handleDescribeTrial(ctx context.Context, body []byte) ([]byte, error) { var req describeTrialInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -86,7 +87,7 @@ func (h *Handler) handleDescribeTrial(ctx context.Context, body []byte) ([]byte, resp["LastModifiedBy"] = t.LastModifiedBy } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type trialSummary struct { @@ -112,7 +113,7 @@ type listTrialsInput struct { func (h *Handler) handleListTrials(ctx context.Context, body []byte) ([]byte, error) { var req listTrialsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -142,7 +143,7 @@ func (h *Handler) handleListTrials(ctx context.Context, body []byte) ([]byte, er resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // deleteTrialInput mirrors DeleteTrialInput (api_op_DeleteTrial.go:30-37). @@ -153,7 +154,7 @@ type deleteTrialInput struct { func (h *Handler) handleDeleteTrial(ctx context.Context, body []byte) ([]byte, error) { var req deleteTrialInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -168,7 +169,7 @@ func (h *Handler) handleDeleteTrial(ctx context.Context, body []byte) ([]byte, e logger.Load(ctx).InfoContext(ctx, "sagemaker: deleted trial", "name", req.TrialName) - return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}) + return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}, jsonx.V1()) } // updateTrialInput mirrors UpdateTrialInput (api_op_UpdateTrial.go:27-39). @@ -180,7 +181,7 @@ type updateTrialInput struct { func (h *Handler) handleUpdateTrial(ctx context.Context, body []byte) ([]byte, error) { var req updateTrialInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -195,5 +196,5 @@ func (h *Handler) handleUpdateTrial(ctx context.Context, body []byte) ([]byte, e logger.Load(ctx).InfoContext(ctx, "sagemaker: updated trial", "name", t.TrialName) - return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}) + return json.Marshal(map[string]string{keyTrialArn: t.TrialArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_trials_test.go b/services/sagemaker/handler_trials_test.go index acbede9677..267027f82f 100644 --- a/services/sagemaker/handler_trials_test.go +++ b/services/sagemaker/handler_trials_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TrialLifecycle(t *testing.T) { @@ -44,7 +46,7 @@ func TestHandler_TrialLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["TrialSummaries"].([]any), 1) // Delete trial. @@ -70,13 +72,13 @@ func TestHandler_UpdateTrial(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["TrialArn"]) // Describe returns updated DisplayName rec = doSageMakerRequest(t, h, "DescribeTrial", map[string]any{"TrialName": "my-trial"}) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "Trial Display", descResp["DisplayName"]) } @@ -98,14 +100,14 @@ func TestHandler_CreateTrial_DisplayName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, "My Trial", descResp["DisplayName"]) rec = doSageMakerRequest(t, h, "ListTrials", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["TrialSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "My Trial", summaries[0].(map[string]any)["DisplayName"]) @@ -264,7 +266,7 @@ func TestHandler_ListTrials_TrialComponentName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["TrialSummaries"].([]any) require.Len(t, summaries, 1) assert.Equal(t, "trial-with-tc", summaries[0].(map[string]any)["TrialName"]) diff --git a/services/sagemaker/handler_user_profiles.go b/services/sagemaker/handler_user_profiles.go index d59665daca..43d576b06a 100644 --- a/services/sagemaker/handler_user_profiles.go +++ b/services/sagemaker/handler_user_profiles.go @@ -2,9 +2,11 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -17,18 +19,18 @@ import ( // it — see gopherstack-oc9v). UserSettings is carried as opaque // json.RawMessage passthrough per this file's established convention. type createUserProfileInput struct { - DomainID string `json:"DomainId"` - UserProfileName string `json:"UserProfileName"` - SingleSignOnUserIdentifier string `json:"SingleSignOnUserIdentifier"` - SingleSignOnUserValue string `json:"SingleSignOnUserValue"` - UserSettings json.RawMessage `json:"UserSettings"` - Tags []tagObject `json:"Tags"` + DomainID string `json:"DomainId"` + UserProfileName string `json:"UserProfileName"` + SingleSignOnUserIdentifier string `json:"SingleSignOnUserIdentifier"` + SingleSignOnUserValue string `json:"SingleSignOnUserValue"` + UserSettings jsontext.Value `json:"UserSettings"` + Tags []tagObject `json:"Tags"` } func (h *Handler) handleCreateUserProfile(ctx context.Context, body []byte) ([]byte, error) { var req createUserProfileInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -61,7 +63,7 @@ func (h *Handler) handleCreateUserProfile(ctx context.Context, body []byte) ([]b logger.Load(ctx).InfoContext(ctx, "sagemaker: created user profile", "name", up.UserProfileName) - return json.Marshal(map[string]string{keyUserProfileArn: up.UserProfileArn}) + return json.Marshal(map[string]string{keyUserProfileArn: up.UserProfileArn}, jsonx.V1()) } type describeUserProfileInput struct { @@ -72,7 +74,7 @@ type describeUserProfileInput struct { func (h *Handler) handleDescribeUserProfile(ctx context.Context, body []byte) ([]byte, error) { var req describeUserProfileInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -110,7 +112,7 @@ func (h *Handler) handleDescribeUserProfile(ctx context.Context, body []byte) ([ resp["UserSettings"] = up.UserSettings } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type userProfileSummary struct { @@ -133,7 +135,7 @@ type listUserProfilesInput struct { func (h *Handler) handleListUserProfiles(ctx context.Context, body []byte) ([]byte, error) { var req listUserProfilesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -155,7 +157,7 @@ func (h *Handler) handleListUserProfiles(ctx context.Context, body []byte) ([]by resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type deleteUserProfileInput struct { @@ -166,7 +168,7 @@ type deleteUserProfileInput struct { func (h *Handler) handleDeleteUserProfile(ctx context.Context, body []byte) error { var req deleteUserProfileInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -191,15 +193,15 @@ func (h *Handler) handleDeleteUserProfile(ctx context.Context, body []byte) erro // updateUserProfileInput mirrors UpdateUserProfileInput // (api_op_UpdateUserProfile.go:26-38). type updateUserProfileInput struct { - DomainID string `json:"DomainId"` - UserProfileName string `json:"UserProfileName"` - UserSettings json.RawMessage `json:"UserSettings"` + DomainID string `json:"DomainId"` + UserProfileName string `json:"UserProfileName"` + UserSettings jsontext.Value `json:"UserSettings"` } func (h *Handler) handleUpdateUserProfile(ctx context.Context, body []byte) ([]byte, error) { var req updateUserProfileInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -222,5 +224,5 @@ func (h *Handler) handleUpdateUserProfile(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]string{keyUserProfileArn: up.UserProfileArn}) + return json.Marshal(map[string]string{keyUserProfileArn: up.UserProfileArn}, jsonx.V1()) } diff --git a/services/sagemaker/handler_user_profiles_test.go b/services/sagemaker/handler_user_profiles_test.go index bae48b909e..5006a94570 100644 --- a/services/sagemaker/handler_user_profiles_test.go +++ b/services/sagemaker/handler_user_profiles_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_UserProfileLifecycle(t *testing.T) { @@ -24,7 +26,7 @@ func TestHandler_UserProfileLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) // Create user profile. @@ -51,7 +53,7 @@ func TestHandler_UserProfileLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, recList.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(recList.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut["UserProfiles"].([]any), 1) // Delete user profile. @@ -75,7 +77,7 @@ func TestHandler_UserProfile_NotFound(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) for _, op := range []string{"DescribeUserProfile", "DeleteUserProfile"} { @@ -104,7 +106,7 @@ func TestHandler_UpdateUserProfile(t *testing.T) { var domainResp map[string]any rec := doSageMakerRequest(t, h, "ListDomains", map[string]any{}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &domainResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &domainResp, jsonx.V1())) domains := domainResp["Domains"].([]any) require.Len(t, domains, 1) domainID := domains[0].(map[string]any)["DomainId"].(string) @@ -121,7 +123,7 @@ func TestHandler_UpdateUserProfile(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["UserProfileArn"]) } @@ -137,7 +139,7 @@ func TestHandler_ListUserProfiles_NameContainsAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) for _, name := range []string{"alpha-user", "beta-user", "alpha-other"} { @@ -158,7 +160,7 @@ func TestHandler_ListUserProfiles_NameContainsAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["UserProfiles"].([]any), 2) }) @@ -172,7 +174,7 @@ func TestHandler_ListUserProfiles_NameContainsAndMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["UserProfiles"].([]any), 1, "MaxResults must cap the page, not just be parsed and ignored") assert.NotEmpty(t, out["NextToken"]) }) @@ -191,7 +193,7 @@ func TestHandler_CreateUserProfile_SSOFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recDomain.Code) var domainOut map[string]any - require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut)) + require.NoError(t, json.Unmarshal(recDomain.Body.Bytes(), &domainOut, jsonx.V1())) domainID := domainOut["DomainId"].(string) rec := doSageMakerRequest(t, h, "CreateUserProfile", map[string]any{ @@ -209,7 +211,7 @@ func TestHandler_CreateUserProfile_SSOFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "UserName", out["SingleSignOnUserIdentifier"]) assert.Equal(t, "jdoe", out["SingleSignOnUserValue"]) } diff --git a/services/sagemaker/handler_workforces.go b/services/sagemaker/handler_workforces.go index a807595820..92632138c0 100644 --- a/services/sagemaker/handler_workforces.go +++ b/services/sagemaker/handler_workforces.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -96,7 +98,7 @@ type createWorkforceInput struct { func (h *Handler) handleCreateWorkforce(ctx context.Context, body []byte) ([]byte, error) { var req createWorkforceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +119,7 @@ func (h *Handler) handleCreateWorkforce(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{keyWorkforceArn: result.WorkforceArn}) + return json.Marshal(map[string]any{keyWorkforceArn: result.WorkforceArn}, jsonx.V1()) } // describeWorkforceInput mirrors DescribeWorkforceInput (api_op_DescribeWorkforce.go:34-42). @@ -128,7 +130,7 @@ type describeWorkforceInput struct { func (h *Handler) handleDescribeWorkforce(ctx context.Context, body []byte) ([]byte, error) { var req describeWorkforceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -141,7 +143,7 @@ func (h *Handler) handleDescribeWorkforce(ctx context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]any{"Workforce": workforceResponseMap(result)}) + return json.Marshal(map[string]any{"Workforce": workforceResponseMap(result)}, jsonx.V1()) } // updateWorkforceInput mirrors UpdateWorkforceInput (api_op_UpdateWorkforce.go:65-93). @@ -156,7 +158,7 @@ type updateWorkforceInput struct { func (h *Handler) handleUpdateWorkforce(ctx context.Context, body []byte) ([]byte, error) { var req updateWorkforceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -175,7 +177,7 @@ func (h *Handler) handleUpdateWorkforce(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{"Workforce": workforceResponseMap(result)}) + return json.Marshal(map[string]any{"Workforce": workforceResponseMap(result)}, jsonx.V1()) } // deleteWorkforceInput mirrors DeleteWorkforceInput (api_op_DeleteWorkforce.go:39-44). @@ -186,7 +188,7 @@ type deleteWorkforceInput struct { func (h *Handler) handleDeleteWorkforce(ctx context.Context, body []byte) ([]byte, error) { var req deleteWorkforceInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -198,7 +200,7 @@ func (h *Handler) handleDeleteWorkforce(ctx context.Context, body []byte) ([]byt return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } // listWorkforcesInput mirrors ListWorkforcesInput (api_op_ListWorkforces.go:31-48). @@ -213,7 +215,7 @@ type listWorkforcesInput struct { func (h *Handler) handleListWorkforces(ctx context.Context, body []byte) ([]byte, error) { var req listWorkforcesInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -234,5 +236,5 @@ func (h *Handler) handleListWorkforces(ctx context.Context, body []byte) ([]byte resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_workforces_test.go b/services/sagemaker/handler_workforces_test.go index b5c903db27..dccc49422d 100644 --- a/services/sagemaker/handler_workforces_test.go +++ b/services/sagemaker/handler_workforces_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateWorkforce(t *testing.T) { @@ -20,7 +22,7 @@ func TestHandler_CreateWorkforce(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["WorkforceArn"], "my-workforce") } @@ -34,7 +36,7 @@ func TestHandler_DescribeWorkforce(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Workforce"]) } @@ -48,7 +50,7 @@ func TestHandler_UpdateWorkforce(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Workforce"]) } @@ -66,7 +68,7 @@ func TestHandler_CreateWorkforce_IPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wf := resp["Workforce"].(map[string]any) assert.Equal(t, "dualstack", wf["IpAddressType"]) } @@ -88,7 +90,7 @@ func TestHandler_UpdateWorkforce_IPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wf := resp["Workforce"].(map[string]any) assert.Equal(t, "dualstack", wf["IpAddressType"]) } @@ -118,7 +120,7 @@ func TestHandler_ListWorkforces_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["Workforces"].([]any) assert.Len(t, items, tc.wantCount) }) diff --git a/services/sagemaker/handler_workteams.go b/services/sagemaker/handler_workteams.go index bee8920421..f8bb19d0a7 100644 --- a/services/sagemaker/handler_workteams.go +++ b/services/sagemaker/handler_workteams.go @@ -2,8 +2,10 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -59,7 +61,7 @@ type createWorkteamInput struct { func (h *Handler) handleCreateWorkteam(ctx context.Context, body []byte) ([]byte, error) { var req createWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -91,7 +93,7 @@ func (h *Handler) handleCreateWorkteam(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(map[string]any{"WorkteamArn": result.WorkteamArn}) + return json.Marshal(map[string]any{"WorkteamArn": result.WorkteamArn}, jsonx.V1()) } // describeWorkteamInput mirrors DescribeWorkteamInput (api_op_DescribeWorkteam.go:31-36). @@ -102,7 +104,7 @@ type describeWorkteamInput struct { func (h *Handler) handleDescribeWorkteam(ctx context.Context, body []byte) ([]byte, error) { var req describeWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -115,7 +117,7 @@ func (h *Handler) handleDescribeWorkteam(ctx context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]any{"Workteam": workteamResponseMap(result)}) + return json.Marshal(map[string]any{"Workteam": workteamResponseMap(result)}, jsonx.V1()) } // updateWorkteamInput mirrors UpdateWorkteamInput (api_op_UpdateWorkteam.go:28-70). @@ -130,7 +132,7 @@ type updateWorkteamInput struct { func (h *Handler) handleUpdateWorkteam(ctx context.Context, body []byte) ([]byte, error) { var req updateWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -149,7 +151,7 @@ func (h *Handler) handleUpdateWorkteam(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(map[string]any{"Workteam": workteamResponseMap(result)}) + return json.Marshal(map[string]any{"Workteam": workteamResponseMap(result)}, jsonx.V1()) } // deleteWorkteamInput mirrors DeleteWorkteamInput (api_op_DeleteWorkteam.go:27-32). @@ -160,7 +162,7 @@ type deleteWorkteamInput struct { func (h *Handler) handleDeleteWorkteam(ctx context.Context, body []byte) ([]byte, error) { var req deleteWorkteamInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -172,7 +174,7 @@ func (h *Handler) handleDeleteWorkteam(ctx context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(map[string]any{"Success": true}) + return json.Marshal(map[string]any{"Success": true}, jsonx.V1()) } // listWorkteamsInput mirrors ListWorkteamsInput (api_op_ListWorkteams.go:31-51). @@ -187,7 +189,7 @@ type listWorkteamsInput struct { func (h *Handler) handleListWorkteams(ctx context.Context, body []byte) ([]byte, error) { var req listWorkteamsInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -208,5 +210,5 @@ func (h *Handler) handleListWorkteams(ctx context.Context, body []byte) ([]byte, resp[keyNextToken] = next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/sagemaker/handler_workteams_test.go b/services/sagemaker/handler_workteams_test.go index 233de8cd5a..545f838d48 100644 --- a/services/sagemaker/handler_workteams_test.go +++ b/services/sagemaker/handler_workteams_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // defaultMemberDefinitions returns a minimal, real-shaped MemberDefinitions @@ -33,7 +35,7 @@ func TestHandler_CreateWorkteam(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["WorkteamArn"], "my-team") } @@ -50,7 +52,7 @@ func TestHandler_DescribeWorkteam(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wt := resp["Workteam"].(map[string]any) assert.Equal(t, "team-1", wt["WorkteamName"]) } @@ -86,7 +88,7 @@ func TestHandler_ListWorkteams(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Workteams"].([]any) assert.Len(t, items, 2) } @@ -130,7 +132,7 @@ func TestHandler_ListWorkteams_Filters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["Workteams"].([]any) require.Len(t, items, len(tc.wantNames)) @@ -166,7 +168,7 @@ func TestHandler_CreateWorkteam_NotificationAndWorkerAccessConfig(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wt := resp["Workteam"].(map[string]any) nc := wt["NotificationConfiguration"].(map[string]any) @@ -196,7 +198,7 @@ func TestHandler_UpdateWorkteam_NotificationConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wt := resp["Workteam"].(map[string]any) nc := wt["NotificationConfiguration"].(map[string]any) assert.Equal(t, "arn:aws:sns:us-east-1:123456789012:updated", nc["NotificationTopicArn"]) diff --git a/services/sagemaker/hp_tuning_jobs.go b/services/sagemaker/hp_tuning_jobs.go index 79432ecd40..6e3c972480 100644 --- a/services/sagemaker/hp_tuning_jobs.go +++ b/services/sagemaker/hp_tuning_jobs.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -68,11 +68,11 @@ type HyperParameterTuningJob struct { Strategy string `json:"Strategy,omitempty"` HyperParameterTuningJobStatus string `json:"HyperParameterTuningJobStatus"` HyperParameterTuningJobArn string `json:"HyperParameterTuningJobArn"` - HyperParameterTuningJobConfig json.RawMessage `json:"HyperParameterTuningJobConfig,omitempty"` - TrainingJobDefinitions json.RawMessage `json:"TrainingJobDefinitions,omitempty"` - TrainingJobDefinition json.RawMessage `json:"TrainingJobDefinition,omitempty"` - WarmStartConfig json.RawMessage `json:"WarmStartConfig,omitempty"` - Autotune json.RawMessage `json:"Autotune,omitempty"` + HyperParameterTuningJobConfig jsontext.Value `json:"HyperParameterTuningJobConfig,omitempty"` + TrainingJobDefinitions jsontext.Value `json:"TrainingJobDefinitions,omitempty"` + TrainingJobDefinition jsontext.Value `json:"TrainingJobDefinition,omitempty"` + WarmStartConfig jsontext.Value `json:"WarmStartConfig,omitempty"` + Autotune jsontext.Value `json:"Autotune,omitempty"` TrainingJobStatusCounters HPTrainingJobStatusCounters `json:"TrainingJobStatusCounters"` ResourceLimits HPResourceLimits `json:"ResourceLimits"` ObjectiveStatusCounters HPObjectiveStatusCounters `json:"ObjectiveStatusCounters"` @@ -82,11 +82,11 @@ type HyperParameterTuningJob struct { func cloneHPTuningJob(j *HyperParameterTuningJob) *HyperParameterTuningJob { cp := *j cp.Tags = maps.Clone(j.Tags) - cp.HyperParameterTuningJobConfig = append(json.RawMessage(nil), j.HyperParameterTuningJobConfig...) - cp.Autotune = append(json.RawMessage(nil), j.Autotune...) - cp.WarmStartConfig = append(json.RawMessage(nil), j.WarmStartConfig...) - cp.TrainingJobDefinition = append(json.RawMessage(nil), j.TrainingJobDefinition...) - cp.TrainingJobDefinitions = append(json.RawMessage(nil), j.TrainingJobDefinitions...) + cp.HyperParameterTuningJobConfig = append(jsontext.Value(nil), j.HyperParameterTuningJobConfig...) + cp.Autotune = append(jsontext.Value(nil), j.Autotune...) + cp.WarmStartConfig = append(jsontext.Value(nil), j.WarmStartConfig...) + cp.TrainingJobDefinition = append(jsontext.Value(nil), j.TrainingJobDefinition...) + cp.TrainingJobDefinitions = append(jsontext.Value(nil), j.TrainingJobDefinitions...) return &cp } @@ -101,11 +101,11 @@ type CreateHyperParameterTuningJobOptions struct { Tags map[string]string Name string Strategy string - HyperParameterTuningJobConfig json.RawMessage - Autotune json.RawMessage - WarmStartConfig json.RawMessage - TrainingJobDefinition json.RawMessage - TrainingJobDefinitions json.RawMessage + HyperParameterTuningJobConfig jsontext.Value + Autotune jsontext.Value + WarmStartConfig jsontext.Value + TrainingJobDefinition jsontext.Value + TrainingJobDefinitions jsontext.Value Limits HPResourceLimits } diff --git a/services/sagemaker/human_task_ui.go b/services/sagemaker/human_task_ui.go index 04e396bdc9..001bddf387 100644 --- a/services/sagemaker/human_task_ui.go +++ b/services/sagemaker/human_task_ui.go @@ -4,13 +4,14 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrHumanTaskUINotFound is returned when a human task UI does not exist. @@ -63,7 +64,7 @@ func (h *HumanTaskUI) MarshalJSON() ([]byte, error) { alias: (*alias)(h), CreationTime: epochSeconds(h.CreationTime), UITemplate: uiTemplateInfo{ContentSha256: h.UITemplateContentSha256}, - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [HumanTaskUI.MarshalJSON], read by @@ -77,7 +78,7 @@ func (h *HumanTaskUI) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(h)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/hyperpod_scheduling.go b/services/sagemaker/hyperpod_scheduling.go index cf9eec7b5f..ee76f13e4f 100644 --- a/services/sagemaker/hyperpod_scheduling.go +++ b/services/sagemaker/hyperpod_scheduling.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -10,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -105,7 +106,7 @@ func (c *ClusterSchedulerConfig) MarshalJSON() ([]byte, error) { alias: (*alias)(c), CreationTime: epochSeconds(c.CreationTime), LastModifiedTime: epochSeconds(c.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ClusterSchedulerConfig.MarshalJSON], read @@ -119,7 +120,7 @@ func (c *ClusterSchedulerConfig) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(c)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -595,7 +596,7 @@ func (q *ComputeQuota) MarshalJSON() ([]byte, error) { alias: (*alias)(q), CreationTime: epochSeconds(q.CreationTime), LastModifiedTime: epochSeconds(q.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ComputeQuota.MarshalJSON], read by @@ -609,7 +610,7 @@ func (q *ComputeQuota) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(q)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/images.go b/services/sagemaker/images.go index c344e8000e..45108cc057 100644 --- a/services/sagemaker/images.go +++ b/services/sagemaker/images.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -66,7 +67,7 @@ func (img *SMImage) MarshalJSON() ([]byte, error) { alias: (*alias)(img), CreationTime: epochSeconds(img.CreationTime), LastModifiedTime: epochSeconds(img.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [SMImage.MarshalJSON], read by @@ -80,7 +81,7 @@ func (img *SMImage) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(img)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -358,7 +359,7 @@ func (v *ImageVersion) MarshalJSON() ([]byte, error) { alias: (*alias)(v), CreationTime: epochSeconds(v.CreationTime), LastModifiedTime: epochSeconds(v.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ImageVersion.MarshalJSON], read by @@ -372,7 +373,7 @@ func (v *ImageVersion) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(v)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/inference_components.go b/services/sagemaker/inference_components.go index acc20b2c20..8edb7fffed 100644 --- a/services/sagemaker/inference_components.go +++ b/services/sagemaker/inference_components.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -35,7 +35,7 @@ type InferenceComponentContainerSpec struct { Environment map[string]string `json:"Environment,omitempty"` ArtifactURL string `json:"ArtifactUrl,omitempty"` Image string `json:"Image,omitempty"` - ContainerMetricsConfig json.RawMessage `json:"ContainerMetricsConfig,omitempty"` + ContainerMetricsConfig jsontext.Value `json:"ContainerMetricsConfig,omitempty"` } // InferenceComponentSpecification mirrors types.InferenceComponentSpecification @@ -52,10 +52,10 @@ type InferenceComponentSpecification struct { BaseInferenceComponentName string `json:"BaseInferenceComponentName,omitempty"` InstanceType string `json:"InstanceType,omitempty"` ModelName string `json:"ModelName,omitempty"` - ComputeResourceRequirements json.RawMessage `json:"ComputeResourceRequirements,omitempty"` - DataCacheConfig json.RawMessage `json:"DataCacheConfig,omitempty"` - SchedulingConfig json.RawMessage `json:"SchedulingConfig,omitempty"` - StartupParameters json.RawMessage `json:"StartupParameters,omitempty"` + ComputeResourceRequirements jsontext.Value `json:"ComputeResourceRequirements,omitempty"` + DataCacheConfig jsontext.Value `json:"DataCacheConfig,omitempty"` + SchedulingConfig jsontext.Value `json:"SchedulingConfig,omitempty"` + StartupParameters jsontext.Value `json:"StartupParameters,omitempty"` } // inferenceComponentSpecificationSummary builds the InferenceComponentSpecificationSummary @@ -129,7 +129,7 @@ type InferenceComponent struct { VariantName string InferenceComponentStatus string FailureReason string - DeploymentConfig json.RawMessage + DeploymentConfig jsontext.Value Specifications []InferenceComponentSpecification CopyCount int32 CurrentCopyCount int32 @@ -369,7 +369,7 @@ func (b *InMemoryBackend) ListInferenceComponents( // VariantName member on the real input — a production variant is fixed at // Create time and cannot be moved via Update. type UpdateInferenceComponentOptions struct { - DeploymentConfig json.RawMessage + DeploymentConfig jsontext.Value RuntimeConfig *InferenceComponentRuntimeConfigInput Specification *InferenceComponentSpecification Specifications []InferenceComponentSpecification diff --git a/services/sagemaker/inference_experiments.go b/services/sagemaker/inference_experiments.go index 60eb9095a8..03a3bdba31 100644 --- a/services/sagemaker/inference_experiments.go +++ b/services/sagemaker/inference_experiments.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -10,6 +10,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrInferenceExperimentNotFound is returned when an inference experiment does not exist. @@ -206,7 +207,7 @@ func (e *InferenceExperiment) MarshalJSON() ([]byte, error) { CreationTime: epochSeconds(e.CreationTime), LastModifiedTime: epochSeconds(e.LastModifiedTime), ModelVariants: modelVariantConfigSummaries(e.ModelVariants), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [InferenceExperiment.MarshalJSON], read by @@ -221,7 +222,7 @@ func (e *InferenceExperiment) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(e)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/inference_recommendations_jobs.go b/services/sagemaker/inference_recommendations_jobs.go index 6bfe9a2d16..7c28918440 100644 --- a/services/sagemaker/inference_recommendations_jobs.go +++ b/services/sagemaker/inference_recommendations_jobs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -50,17 +52,17 @@ type InferenceRecommendationsJob struct { JobDescription string `json:"JobDescription,omitempty"` Status string `json:"Status"` RoleArn string `json:"RoleArn,omitempty"` - InputConfig json.RawMessage `json:"InputConfig,omitempty"` - OutputConfig json.RawMessage `json:"OutputConfig,omitempty"` - StoppingConditions json.RawMessage `json:"StoppingConditions,omitempty"` + InputConfig jsontext.Value `json:"InputConfig,omitempty"` + OutputConfig jsontext.Value `json:"OutputConfig,omitempty"` + StoppingConditions jsontext.Value `json:"StoppingConditions,omitempty"` } func cloneInferenceRecommendationsJob(j *InferenceRecommendationsJob) *InferenceRecommendationsJob { cp := *j cp.Tags = maps.Clone(j.Tags) - cp.InputConfig = append(json.RawMessage(nil), j.InputConfig...) - cp.OutputConfig = append(json.RawMessage(nil), j.OutputConfig...) - cp.StoppingConditions = append(json.RawMessage(nil), j.StoppingConditions...) + cp.InputConfig = append(jsontext.Value(nil), j.InputConfig...) + cp.OutputConfig = append(jsontext.Value(nil), j.OutputConfig...) + cp.StoppingConditions = append(jsontext.Value(nil), j.StoppingConditions...) return &cp } @@ -74,10 +76,10 @@ type inputConfigModelIdentity struct { ModelPackageVersionArn string `json:"ModelPackageVersionArn"` } -func decodeInputConfigModelIdentity(raw json.RawMessage) inputConfigModelIdentity { +func decodeInputConfigModelIdentity(raw jsontext.Value) inputConfigModelIdentity { var id inputConfigModelIdentity - _ = json.Unmarshal(raw, &id) + _ = json.Unmarshal(raw, &id, jsonx.V1()) return id } @@ -89,9 +91,9 @@ type CreateInferenceRecommendationsJobOptions struct { JobType string JobDescription string RoleArn string - InputConfig json.RawMessage - OutputConfig json.RawMessage - StoppingConditions json.RawMessage + InputConfig jsontext.Value + OutputConfig jsontext.Value + StoppingConditions jsontext.Value } // CreateInferenceRecommendationsJob creates an inference recommendations job. diff --git a/services/sagemaker/interfaces.go b/services/sagemaker/interfaces.go index 6b51700497..6863c90e7a 100644 --- a/services/sagemaker/interfaces.go +++ b/services/sagemaker/interfaces.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" ) // StorageBackend defines the interface for SageMaker backend implementations. @@ -47,7 +47,7 @@ type StorageBackend interface { kmsKeyID string, shadowProductionVariants []ProductionVariant, enableNetworkIsolation bool, - explainerConfig, metricsConfig json.RawMessage, + explainerConfig, metricsConfig jsontext.Value, ) error AddTags(ctx context.Context, resourceARN string, tags map[string]string) error diff --git a/services/sagemaker/jobs.go b/services/sagemaker/jobs.go index 8f5a37de82..69bb4270be 100644 --- a/services/sagemaker/jobs.go +++ b/services/sagemaker/jobs.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -74,7 +75,7 @@ func (t JobSecondaryStatusTransition) MarshalJSON() ([]byte, error) { alias: (*alias)(&t), StartTime: epochSeconds(t.StartTime), EndTime: epochSecondsPtr(t.EndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [JobSecondaryStatusTransition.MarshalJSON], @@ -88,7 +89,7 @@ func (t *JobSecondaryStatusTransition) UnmarshalJSON(data []byte) error { StartTime float64 `json:"StartTime"` }{alias: (*alias)(t)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -135,7 +136,7 @@ func (j *Job) MarshalJSON() ([]byte, error) { CreationTime: epochSeconds(j.CreationTime), LastModifiedTime: epochSeconds(j.LastModifiedTime), EndTime: epochSecondsPtr(j.EndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [Job.MarshalJSON], used by persistence.go's @@ -150,7 +151,7 @@ func (j *Job) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/list_summary_shapes_test.go b/services/sagemaker/list_summary_shapes_test.go index d0111aa6bf..2a6d061ccc 100644 --- a/services/sagemaker/list_summary_shapes_test.go +++ b/services/sagemaker/list_summary_shapes_test.go @@ -1,13 +1,15 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" sagemakersdk "github.com/aws/aws-sdk-go-v2/service/sagemaker" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListSummaries_MemberRoundTrips drives each op's Create then List @@ -199,7 +201,7 @@ func TestListInferenceExperiments_SummaryOmitsArn(t *testing.T) { var resp struct { InferenceExperiments []map[string]any `json:"InferenceExperiments"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.InferenceExperiments, 1) _, hasArn := resp.InferenceExperiments[0]["Arn"] @@ -244,7 +246,7 @@ func TestListTransformJobs_SummaryOmitsModelName(t *testing.T) { var resp struct { TransformJobSummaries []map[string]any `json:"TransformJobSummaries"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.TransformJobSummaries, 1) _, hasModelName := resp.TransformJobSummaries[0]["ModelName"] diff --git a/services/sagemaker/mlflow.go b/services/sagemaker/mlflow.go index 3789cf7aea..79a17e9ae2 100644 --- a/services/sagemaker/mlflow.go +++ b/services/sagemaker/mlflow.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -64,7 +65,7 @@ func (s *MlflowTrackingServer) MarshalJSON() ([]byte, error) { alias: (*alias)(s), CreationTime: epochSeconds(s.CreationTime), LastModifiedTime: epochSeconds(s.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [MlflowTrackingServer.MarshalJSON], read by @@ -78,7 +79,7 @@ func (s *MlflowTrackingServer) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(s)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/model_cards.go b/services/sagemaker/model_cards.go index ac0203308d..9075ffa174 100644 --- a/services/sagemaker/model_cards.go +++ b/services/sagemaker/model_cards.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "slices" @@ -12,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrModelCardNotFound is returned when a model card does not exist. @@ -83,7 +85,7 @@ func (c *ModelCard) MarshalJSON() ([]byte, error) { alias: (*alias)(c), CreationTime: epochSeconds(c.CreationTime), LastModifiedTime: epochSeconds(c.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ModelCard.MarshalJSON], read by @@ -97,7 +99,7 @@ func (c *ModelCard) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(c)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -222,22 +224,22 @@ var modelCardMetadataOnlyPaths = [][2]string{ // object sanitizes to "{}", since a non-object document trivially has none // of the preserved paths. func sanitizeModelCardContent(content string) string { - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - out := map[string]map[string]json.RawMessage{} + out := map[string]map[string]jsontext.Value{} - if unmarshalErr := json.Unmarshal([]byte(content), &doc); unmarshalErr == nil { + if unmarshalErr := json.Unmarshal([]byte(content), &doc, jsonx.V1()); unmarshalErr == nil { for _, path := range modelCardMetadataOnlyPaths { section, value := path[0], path[1] - var fields map[string]json.RawMessage - if json.Unmarshal(doc[section], &fields) != nil { + var fields map[string]jsontext.Value + if json.Unmarshal(doc[section], &fields, jsonx.V1()) != nil { continue } if v, ok := fields[value]; ok { if out[section] == nil { - out[section] = map[string]json.RawMessage{} + out[section] = map[string]jsontext.Value{} } out[section][value] = v @@ -245,7 +247,7 @@ func sanitizeModelCardContent(content string) string { } } - sanitized, err := json.Marshal(out) + sanitized, err := json.Marshal(out, jsonx.V1()) if err != nil { return "{}" } diff --git a/services/sagemaker/model_packages.go b/services/sagemaker/model_packages.go index 964609449e..a2be19ab5c 100644 --- a/services/sagemaker/model_packages.go +++ b/services/sagemaker/model_packages.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -12,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -128,7 +130,7 @@ func (g *ModelPackageGroup) MarshalJSON() ([]byte, error) { }{ alias: (*alias)(g), CreationTime: epochSeconds(g.CreationTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ModelPackageGroup.MarshalJSON], read by @@ -141,7 +143,7 @@ func (g *ModelPackageGroup) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(g)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -405,16 +407,16 @@ type CreateModelPackageOptions struct { ApprovalStatus string Tags map[string]string CustomerMetadataProperties map[string]string - InferenceSpecification json.RawMessage - SourceAlgorithmSpecification json.RawMessage - ValidationSpecification json.RawMessage - DriftCheckBaselines json.RawMessage - ModelMetrics json.RawMessage - ModelCard json.RawMessage - ModelLifeCycle json.RawMessage - MetadataProperties json.RawMessage - SecurityConfig json.RawMessage - AdditionalInferenceSpecifications json.RawMessage + InferenceSpecification jsontext.Value + SourceAlgorithmSpecification jsontext.Value + ValidationSpecification jsontext.Value + DriftCheckBaselines jsontext.Value + ModelMetrics jsontext.Value + ModelCard jsontext.Value + ModelLifeCycle jsontext.Value + MetadataProperties jsontext.Value + SecurityConfig jsontext.Value + AdditionalInferenceSpecifications jsontext.Value CertifyForMarketplace bool } @@ -698,10 +700,10 @@ type UpdateModelPackageOptions struct { SourceURI string CustomerMetadataProperties map[string]string CustomerMetadataPropertiesToRemove []string - InferenceSpecification json.RawMessage - ModelCard json.RawMessage - ModelLifeCycle json.RawMessage - AdditionalInferenceSpecificationsToAdd json.RawMessage + InferenceSpecification jsontext.Value + ModelCard jsontext.Value + ModelLifeCycle jsontext.Value + AdditionalInferenceSpecificationsToAdd jsontext.Value } // UpdateModelPackage updates a model package identified by its ARN (the sole @@ -776,22 +778,22 @@ func (b *InMemoryBackend) UpdateModelPackage( // the existing array". Both are opaque json.RawMessage passthrough (see // ModelPackage's own doc comment), so this manipulates them as raw JSON // arrays rather than unmarshaling into a typed element. -func appendInferenceSpecifications(existing, toAdd json.RawMessage) json.RawMessage { - var newItems []json.RawMessage - if err := json.Unmarshal(toAdd, &newItems); err != nil { +func appendInferenceSpecifications(existing, toAdd jsontext.Value) jsontext.Value { + var newItems []jsontext.Value + if err := json.Unmarshal(toAdd, &newItems, jsonx.V1()); err != nil { return existing } - existingItems := make([]json.RawMessage, 0, len(newItems)) + existingItems := make([]jsontext.Value, 0, len(newItems)) if len(existing) > 0 { - if err := json.Unmarshal(existing, &existingItems); err != nil { + if err := json.Unmarshal(existing, &existingItems, jsonx.V1()); err != nil { return existing } } existingItems = append(existingItems, newItems...) - out, err := json.Marshal(existingItems) + out, err := json.Marshal(existingItems, jsonx.V1()) if err != nil { return existing } diff --git a/services/sagemaker/models.go b/services/sagemaker/models.go index 041486e2e7..80be4bee14 100644 --- a/services/sagemaker/models.go +++ b/services/sagemaker/models.go @@ -1,10 +1,13 @@ package sagemaker import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ImageConfig specifies where SageMaker should pull the container image from. @@ -139,7 +142,7 @@ func (pv *ProductionVariant) UnmarshalJSON(data []byte) error { type plain ProductionVariant aux := plain{InitialVariantWeight: defaultVariantWeight} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -157,7 +160,7 @@ func (pv ProductionVariant) MarshalJSON() ([]byte, error) { plain InitialVariantWeight float64 `json:"InitialVariantWeight"` - }{plain: plain(pv), InitialVariantWeight: pv.InitialVariantWeight}) + }{plain: plain(pv), InitialVariantWeight: pv.InitialVariantWeight}, jsonx.V1()) } // DataCaptureConfig specifies real-time data capture for an endpoint config. @@ -219,8 +222,8 @@ type EndpointConfig struct { VpcConfig *VpcConfig `json:"VpcConfig,omitempty"` DataCaptureConfig *DataCaptureConfig `json:"DataCaptureConfig,omitempty"` AsyncInferenceConfig *AsyncInferenceConfig `json:"AsyncInferenceConfig,omitempty"` - ExplainerConfig json.RawMessage `json:"ExplainerConfig,omitempty"` - MetricsConfig json.RawMessage `json:"MetricsConfig,omitempty"` + ExplainerConfig jsontext.Value `json:"ExplainerConfig,omitempty"` + MetricsConfig jsontext.Value `json:"MetricsConfig,omitempty"` EndpointConfigName string `json:"EndpointConfigName"` EndpointConfigARN string `json:"EndpointConfigARN"` ExecutionRoleArn string `json:"ExecutionRoleArn,omitempty"` @@ -275,8 +278,8 @@ func cloneEndpointConfig(ec *EndpointConfig) *EndpointConfig { aic := *ec.AsyncInferenceConfig cp.AsyncInferenceConfig = &aic } - cp.ExplainerConfig = append(json.RawMessage(nil), ec.ExplainerConfig...) - cp.MetricsConfig = append(json.RawMessage(nil), ec.MetricsConfig...) + cp.ExplainerConfig = append(jsontext.Value(nil), ec.ExplainerConfig...) + cp.MetricsConfig = append(jsontext.Value(nil), ec.MetricsConfig...) return &cp } @@ -360,9 +363,9 @@ type Algorithm struct { AlgorithmStatus string `json:"AlgorithmStatus"` ProductID string `json:"ProductId,omitempty"` AlgorithmStatusDetails AlgorithmStatusDetails `json:"AlgorithmStatusDetails"` - TrainingSpecification json.RawMessage `json:"TrainingSpecification,omitempty"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification,omitempty"` - ValidationSpecification json.RawMessage `json:"ValidationSpecification,omitempty"` + TrainingSpecification jsontext.Value `json:"TrainingSpecification,omitempty"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification,omitempty"` + ValidationSpecification jsontext.Value `json:"ValidationSpecification,omitempty"` CertifyForMarketplace bool `json:"CertifyForMarketplace,omitempty"` } @@ -370,9 +373,9 @@ type Algorithm struct { func cloneAlgorithm(al *Algorithm) *Algorithm { cp := *al cp.Tags = maps.Clone(al.Tags) - cp.TrainingSpecification = append(json.RawMessage(nil), al.TrainingSpecification...) - cp.InferenceSpecification = append(json.RawMessage(nil), al.InferenceSpecification...) - cp.ValidationSpecification = append(json.RawMessage(nil), al.ValidationSpecification...) + cp.TrainingSpecification = append(jsontext.Value(nil), al.TrainingSpecification...) + cp.InferenceSpecification = append(jsontext.Value(nil), al.InferenceSpecification...) + cp.ValidationSpecification = append(jsontext.Value(nil), al.ValidationSpecification...) cp.AlgorithmStatusDetails.ImageScanStatuses = append( []AlgorithmStatusItem(nil), al.AlgorithmStatusDetails.ImageScanStatuses..., ) @@ -847,18 +850,18 @@ type ModelPackage struct { LastModifiedTime time.Time `json:"LastModifiedTime,omitzero"` Tags map[string]string `json:"Tags,omitempty"` CustomerMetadataProperties map[string]string `json:"CustomerMetadataProperties,omitempty"` - InferenceSpecification json.RawMessage `json:"InferenceSpecification,omitempty"` - SourceAlgorithmSpecification json.RawMessage `json:"SourceAlgorithmSpecification,omitempty"` - ValidationSpecification json.RawMessage `json:"ValidationSpecification,omitempty"` - DriftCheckBaselines json.RawMessage `json:"DriftCheckBaselines,omitempty"` - ModelMetrics json.RawMessage `json:"ModelMetrics,omitempty"` - ModelCard json.RawMessage `json:"ModelCard,omitempty"` - ModelLifeCycle json.RawMessage `json:"ModelLifeCycle,omitempty"` + InferenceSpecification jsontext.Value `json:"InferenceSpecification,omitempty"` + SourceAlgorithmSpecification jsontext.Value `json:"SourceAlgorithmSpecification,omitempty"` + ValidationSpecification jsontext.Value `json:"ValidationSpecification,omitempty"` + DriftCheckBaselines jsontext.Value `json:"DriftCheckBaselines,omitempty"` + ModelMetrics jsontext.Value `json:"ModelMetrics,omitempty"` + ModelCard jsontext.Value `json:"ModelCard,omitempty"` + ModelLifeCycle jsontext.Value `json:"ModelLifeCycle,omitempty"` CreatedBy *UserContext `json:"CreatedBy,omitempty"` LastModifiedBy *UserContext `json:"LastModifiedBy,omitempty"` - MetadataProperties json.RawMessage `json:"MetadataProperties,omitempty"` - SecurityConfig json.RawMessage `json:"SecurityConfig,omitempty"` - AdditionalInferenceSpecifications json.RawMessage `json:"AdditionalInferenceSpecifications,omitempty"` + MetadataProperties jsontext.Value `json:"MetadataProperties,omitempty"` + SecurityConfig jsontext.Value `json:"SecurityConfig,omitempty"` + AdditionalInferenceSpecifications jsontext.Value `json:"AdditionalInferenceSpecifications,omitempty"` ModelPackageName string `json:"ModelPackageName"` ModelPackageArn string `json:"ModelPackageArn"` ModelPackageGroupName string `json:"ModelPackageGroupName,omitempty"` @@ -891,16 +894,16 @@ func cloneModelPackage(mp *ModelPackage) *ModelPackage { cp.ModelPackageStatusDetails.ImageScanStatuses = append( []ModelPackageStatusItem{}, mp.ModelPackageStatusDetails.ImageScanStatuses..., ) - cp.InferenceSpecification = append(json.RawMessage(nil), mp.InferenceSpecification...) - cp.SourceAlgorithmSpecification = append(json.RawMessage(nil), mp.SourceAlgorithmSpecification...) - cp.ValidationSpecification = append(json.RawMessage(nil), mp.ValidationSpecification...) - cp.DriftCheckBaselines = append(json.RawMessage(nil), mp.DriftCheckBaselines...) - cp.ModelMetrics = append(json.RawMessage(nil), mp.ModelMetrics...) - cp.ModelCard = append(json.RawMessage(nil), mp.ModelCard...) - cp.ModelLifeCycle = append(json.RawMessage(nil), mp.ModelLifeCycle...) - cp.MetadataProperties = append(json.RawMessage(nil), mp.MetadataProperties...) - cp.SecurityConfig = append(json.RawMessage(nil), mp.SecurityConfig...) - cp.AdditionalInferenceSpecifications = append(json.RawMessage(nil), mp.AdditionalInferenceSpecifications...) + cp.InferenceSpecification = append(jsontext.Value(nil), mp.InferenceSpecification...) + cp.SourceAlgorithmSpecification = append(jsontext.Value(nil), mp.SourceAlgorithmSpecification...) + cp.ValidationSpecification = append(jsontext.Value(nil), mp.ValidationSpecification...) + cp.DriftCheckBaselines = append(jsontext.Value(nil), mp.DriftCheckBaselines...) + cp.ModelMetrics = append(jsontext.Value(nil), mp.ModelMetrics...) + cp.ModelCard = append(jsontext.Value(nil), mp.ModelCard...) + cp.ModelLifeCycle = append(jsontext.Value(nil), mp.ModelLifeCycle...) + cp.MetadataProperties = append(jsontext.Value(nil), mp.MetadataProperties...) + cp.SecurityConfig = append(jsontext.Value(nil), mp.SecurityConfig...) + cp.AdditionalInferenceSpecifications = append(jsontext.Value(nil), mp.AdditionalInferenceSpecifications...) return &cp } @@ -923,7 +926,7 @@ func (mp *ModelPackage) MarshalJSON() ([]byte, error) { aux.LastModifiedTime = epochSeconds(mp.LastModifiedTime) } - return json.Marshal(aux) + return json.Marshal(aux, jsonx.V1()) } // UnmarshalJSON is the inverse of [ModelPackage.MarshalJSON], read by @@ -937,7 +940,7 @@ func (mp *ModelPackage) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(mp)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/monitoring_job_definitions.go b/services/sagemaker/monitoring_job_definitions.go index 5374f4ccc3..327b496bf0 100644 --- a/services/sagemaker/monitoring_job_definitions.go +++ b/services/sagemaker/monitoring_job_definitions.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -46,14 +46,14 @@ var ( // StoppingCondition/BaselineConfig blocks, so Describe echoes back exactly // what Create received. type JobDefinition struct { - CreationTime time.Time `json:"CreationTime"` - Tags map[string]string `json:"Tags,omitempty"` - Config map[string]json.RawMessage `json:"Config,omitempty"` - JobDefinitionName string `json:"JobDefinitionName"` - JobDefinitionArn string `json:"JobDefinitionArn"` - JobDefinitionType string `json:"JobDefinitionType"` - RoleArn string `json:"RoleArn,omitempty"` - EndpointName string `json:"EndpointName,omitempty"` + CreationTime time.Time `json:"CreationTime"` + Tags map[string]string `json:"Tags,omitempty"` + Config map[string]jsontext.Value `json:"Config,omitempty"` + JobDefinitionName string `json:"JobDefinitionName"` + JobDefinitionArn string `json:"JobDefinitionArn"` + JobDefinitionType string `json:"JobDefinitionType"` + RoleArn string `json:"RoleArn,omitempty"` + EndpointName string `json:"EndpointName,omitempty"` } func cloneJobDefinition(j *JobDefinition) *JobDefinition { @@ -71,7 +71,7 @@ func (b *InMemoryBackend) createJobDefinition( ctx context.Context, storeFn func(string) *store.Table[JobDefinition], defType, name, roleArn, endpointName string, - config map[string]json.RawMessage, + config map[string]jsontext.Value, tags map[string]string, resourceType string, alreadyExists error, @@ -227,7 +227,7 @@ func (b *InMemoryBackend) listJobDefinitions( func (b *InMemoryBackend) CreateDataQualityJobDefinition( ctx context.Context, name, roleArn, endpointName string, - config map[string]json.RawMessage, + config map[string]jsontext.Value, tags map[string]string, ) (*JobDefinition, error) { return b.createJobDefinition( @@ -266,7 +266,7 @@ func (b *InMemoryBackend) ListDataQualityJobDefinitions( func (b *InMemoryBackend) CreateModelBiasJobDefinition( ctx context.Context, name, roleArn, endpointName string, - config map[string]json.RawMessage, + config map[string]jsontext.Value, tags map[string]string, ) (*JobDefinition, error) { return b.createJobDefinition( @@ -305,7 +305,7 @@ func (b *InMemoryBackend) ListModelBiasJobDefinitions( func (b *InMemoryBackend) CreateModelQualityJobDefinition( ctx context.Context, name, roleArn, endpointName string, - config map[string]json.RawMessage, + config map[string]jsontext.Value, tags map[string]string, ) (*JobDefinition, error) { return b.createJobDefinition( @@ -344,7 +344,7 @@ func (b *InMemoryBackend) ListModelQualityJobDefinitions( func (b *InMemoryBackend) CreateModelExplainabilityJobDefinition( ctx context.Context, name, roleArn, endpointName string, - config map[string]json.RawMessage, + config map[string]jsontext.Value, tags map[string]string, ) (*JobDefinition, error) { return b.createJobDefinition( diff --git a/services/sagemaker/monitoring_schedules.go b/services/sagemaker/monitoring_schedules.go index 10e0acb1e6..0ef320fc15 100644 --- a/services/sagemaker/monitoring_schedules.go +++ b/services/sagemaker/monitoring_schedules.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -45,7 +47,7 @@ type MonitoringScheduleConfig struct { ScheduleConfig *MonitoringScheduleSchedule `json:"ScheduleConfig,omitempty"` MonitoringJobDefinitionName string `json:"MonitoringJobDefinitionName,omitempty"` MonitoringType string `json:"MonitoringType,omitempty"` - MonitoringJobDefinition json.RawMessage `json:"MonitoringJobDefinition,omitempty"` + MonitoringJobDefinition jsontext.Value `json:"MonitoringJobDefinition,omitempty"` } // MonitoringSchedule represents a SageMaker monitoring schedule. @@ -67,7 +69,7 @@ func cloneMonitoringSchedule(ms *MonitoringSchedule) *MonitoringSchedule { if ms.MonitoringScheduleConfig != nil { cfg := *ms.MonitoringScheduleConfig cfg.MonitoringJobDefinition = append( - json.RawMessage(nil), + jsontext.Value(nil), ms.MonitoringScheduleConfig.MonitoringJobDefinition...) if ms.MonitoringScheduleConfig.ScheduleConfig != nil { @@ -106,7 +108,7 @@ func (ms *MonitoringSchedule) MarshalJSON() ([]byte, error) { CreationTime: epochSeconds(ms.CreationTime), LastModifiedTime: epochSeconds(ms.LastModifiedTime), MonitoringType: monitoringType, - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [MonitoringSchedule.MarshalJSON], read by @@ -120,7 +122,7 @@ func (ms *MonitoringSchedule) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(ms)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -141,7 +143,7 @@ func (ms *MonitoringSchedule) UnmarshalJSON(data []byte) error { // raw is empty, unparseable, or has no endpoint input (e.g. a batch // transform monitoring job, or a schedule referencing a job definition by // name only). -func monitoringEndpointNameFromJobDefinition(raw json.RawMessage) string { +func monitoringEndpointNameFromJobDefinition(raw jsontext.Value) string { var doc struct { MonitoringInputs []struct { EndpointInput *struct { @@ -150,7 +152,7 @@ func monitoringEndpointNameFromJobDefinition(raw json.RawMessage) string { } `json:"MonitoringInputs"` } - if len(raw) == 0 || json.Unmarshal(raw, &doc) != nil { + if len(raw) == 0 || json.Unmarshal(raw, &doc, jsonx.V1()) != nil { return "" } diff --git a/services/sagemaker/notebook_url_test.go b/services/sagemaker/notebook_url_test.go index 9bc0279bf0..c0f774b0cf 100644 --- a/services/sagemaker/notebook_url_test.go +++ b/services/sagemaker/notebook_url_test.go @@ -1,13 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -42,7 +43,7 @@ func TestNotebookInstance_UrlHost(t *testing.T) { var out struct { URL string `json:"Url"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.want, out.URL) }) } diff --git a/services/sagemaker/optimization_jobs.go b/services/sagemaker/optimization_jobs.go index 11f89df379..aa681ae3b6 100644 --- a/services/sagemaker/optimization_jobs.go +++ b/services/sagemaker/optimization_jobs.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrOptimizationJobNotFound is returned when an optimization job does not exist. @@ -45,7 +47,7 @@ func optimizationConfigTypeName(key string) (string, bool) { // optimizationTypesOf derives OptimizationJobSummary's required // OptimizationTypes from the raw OptimizationConfigs the client sent, by // checking which union member keys appear in the JSON. -func optimizationTypesOf(rawConfigs json.RawMessage) []string { +func optimizationTypesOf(rawConfigs jsontext.Value) []string { // Every OptimizationConfig union member's wire key, in the same order // optimizationConfigTypeName recognizes them. wireKeys := [...]string{ @@ -84,11 +86,11 @@ type OptimizationJob struct { OptimizationJobArn string `json:"OptimizationJobArn"` RoleArn string `json:"RoleArn,omitempty"` DeploymentInstanceType string `json:"DeploymentInstanceType,omitempty"` - OutputConfig json.RawMessage `json:"OutputConfig,omitempty"` - VpcConfig json.RawMessage `json:"VpcConfig,omitempty"` - OptimizationConfigs json.RawMessage `json:"OptimizationConfigs,omitempty"` + OutputConfig jsontext.Value `json:"OutputConfig,omitempty"` + VpcConfig jsontext.Value `json:"VpcConfig,omitempty"` + OptimizationConfigs jsontext.Value `json:"OptimizationConfigs,omitempty"` TrainingPlanArns []string `json:"TrainingPlanArns,omitempty"` - ModelSource json.RawMessage `json:"ModelSource,omitempty"` + ModelSource jsontext.Value `json:"ModelSource,omitempty"` MaxInstanceCount int32 `json:"MaxInstanceCount,omitempty"` } @@ -96,10 +98,10 @@ func cloneOptimizationJob(j *OptimizationJob) *OptimizationJob { cp := *j cp.Tags = maps.Clone(j.Tags) cp.OptimizationEnvironment = maps.Clone(j.OptimizationEnvironment) - cp.ModelSource = append(json.RawMessage(nil), j.ModelSource...) - cp.OptimizationConfigs = append(json.RawMessage(nil), j.OptimizationConfigs...) - cp.OutputConfig = append(json.RawMessage(nil), j.OutputConfig...) - cp.VpcConfig = append(json.RawMessage(nil), j.VpcConfig...) + cp.ModelSource = append(jsontext.Value(nil), j.ModelSource...) + cp.OptimizationConfigs = append(jsontext.Value(nil), j.OptimizationConfigs...) + cp.OutputConfig = append(jsontext.Value(nil), j.OutputConfig...) + cp.VpcConfig = append(jsontext.Value(nil), j.VpcConfig...) cp.TrainingPlanArns = append([]string(nil), j.TrainingPlanArns...) if j.StoppingCondition != nil { @@ -128,7 +130,7 @@ func (j *OptimizationJob) MarshalJSON() ([]byte, error) { LastModifiedTime: epochSeconds(j.LastModifiedTime), OptimizationStartTime: epochSecondsPtr(j.OptimizationStartTime), OptimizationEndTime: epochSecondsPtr(j.OptimizationEndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [OptimizationJob.MarshalJSON], read by @@ -144,7 +146,7 @@ func (j *OptimizationJob) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(j)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -165,10 +167,10 @@ type CreateOptimizationJobOptions struct { Name string RoleArn string DeploymentInstanceType string - ModelSource json.RawMessage - OptimizationConfigs json.RawMessage - OutputConfig json.RawMessage - VpcConfig json.RawMessage + ModelSource jsontext.Value + OptimizationConfigs jsontext.Value + OutputConfig jsontext.Value + VpcConfig jsontext.Value TrainingPlanArns []string MaxInstanceCount int32 } diff --git a/services/sagemaker/partner_apps.go b/services/sagemaker/partner_apps.go index b7e5eb976a..797570fafa 100644 --- a/services/sagemaker/partner_apps.go +++ b/services/sagemaker/partner_apps.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -40,7 +40,7 @@ type PartnerApp struct { Tier string `json:"Tier,omitempty"` KmsKeyID string `json:"KmsKeyId,omitempty"` BaseURL string `json:"-"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig,omitempty"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig,omitempty"` EnableAutoMinorVersionUpgrade bool `json:"EnableAutoMinorVersionUpgrade,omitempty"` EnableIamSessionBasedIdentity bool `json:"EnableIamSessionBasedIdentity,omitempty"` } @@ -48,7 +48,7 @@ type PartnerApp struct { func clonePartnerApp(p *PartnerApp) *PartnerApp { cp := *p cp.Tags = maps.Clone(p.Tags) - cp.ApplicationConfig = append(json.RawMessage(nil), p.ApplicationConfig...) + cp.ApplicationConfig = append(jsontext.Value(nil), p.ApplicationConfig...) if p.MaintenanceConfig != nil { mc := *p.MaintenanceConfig @@ -81,7 +81,7 @@ type CreatePartnerAppOptions struct { AuthType string Tier string KmsKeyID string - ApplicationConfig json.RawMessage + ApplicationConfig jsontext.Value EnableAutoMinorVersionUpgrade bool EnableIamSessionBasedIdentity bool } @@ -178,7 +178,7 @@ type UpdatePartnerAppOptions struct { EnableIamSessionBasedIdentity *bool Arn string Tier string - ApplicationConfig json.RawMessage + ApplicationConfig jsontext.Value } // UpdatePartnerApp updates a partner app's mutable fields. diff --git a/services/sagemaker/persistence.go b/services/sagemaker/persistence.go index d583803c30..c43d0ce8db 100644 --- a/services/sagemaker/persistence.go +++ b/services/sagemaker/persistence.go @@ -2,11 +2,13 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -158,7 +160,7 @@ func hubContentKeyString(k hubContentKey) string { // each one doesn't fit the Table[V] keyed-by-string-derived-from-V model — // so they are persisted directly here instead of via Tables. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ImageVersions map[string]map[string]map[int]*ImageVersion `json:"imageVersions,omitempty"` ImageVersionCounts map[string]map[string]int `json:"imageVersionCounts,omitempty"` MonitoringAlertHistory map[string][]*MonitoringAlertHistoryEntry `json:"monitoringAlertHistory,omitempty"` @@ -193,7 +195,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { dtos[i] = toPersistedCluster(c) } - data, marshalErr := json.Marshal(dtos) + data, marshalErr := json.Marshal(dtos, jsonx.V1()) if marshalErr != nil { logger.Load(ctx).WarnContext(ctx, "sagemaker: snapshot cluster table marshal failed", "region", region, "error", marshalErr) @@ -256,7 +258,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // b.clusters here; RestoreAll's "reset tables absent from data" behavior // (since we've stripped every "clusters:*" key from snap.Tables) clears // any such region's table if it was already registered. - clusterTables := make(map[string]json.RawMessage) + clusterTables := make(map[string]jsontext.Value) for name, raw := range snap.Tables { if region, ok := strings.CutPrefix(name, clusterTablePrefix); ok { @@ -281,7 +283,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { for region, raw := range clusterTables { var dtos []*persistedCluster - if err := json.Unmarshal(raw, &dtos); err != nil { + if err := json.Unmarshal(raw, &dtos, jsonx.V1()); err != nil { return fmt.Errorf("sagemaker: restore cluster table %q: %w", region, err) } @@ -543,7 +545,7 @@ var tableRegistrars = map[string]func(*InMemoryBackend, string){ // key present in raw — see tableRegistrars — so the subsequent // registry.RestoreAll call actually receives every table the snapshot // contains, not just whichever ones happen to already be registered. -func (b *InMemoryBackend) ensureTablesRegistered(raw map[string]json.RawMessage) { +func (b *InMemoryBackend) ensureTablesRegistered(raw map[string]jsontext.Value) { for name := range raw { field, region, cut := strings.Cut(name, ":") if !cut { diff --git a/services/sagemaker/persistence_test.go b/services/sagemaker/persistence_test.go index be88ff4fd6..62705bb02c 100644 --- a/services/sagemaker/persistence_test.go +++ b/services/sagemaker/persistence_test.go @@ -2,7 +2,7 @@ package sagemaker_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -104,19 +105,19 @@ func TestPersistenceRoundtrip_PolicyCatalogAndPipelineVersions(t *testing.T) { require.Equal(t, http.StatusOK, recPolicy.Code) var policyOut map[string]any - require.NoError(t, json.Unmarshal(recPolicy.Body.Bytes(), &policyOut)) + require.NoError(t, json.Unmarshal(recPolicy.Body.Bytes(), &policyOut, jsonx.V1())) assert.JSONEq(t, `{"Version":"2012-10-17"}`, policyOut["ResourcePolicy"].(string)) recStatus := doSageMakerRequest(t, h2, "GetSagemakerServicecatalogPortfolioStatus", map[string]any{}) var statusOut map[string]any - require.NoError(t, json.Unmarshal(recStatus.Body.Bytes(), &statusOut)) + require.NoError(t, json.Unmarshal(recStatus.Body.Bytes(), &statusOut, jsonx.V1())) assert.Equal(t, "Enabled", statusOut["Status"]) recVersions := doSageMakerRequest(t, h2, "ListPipelineVersions", map[string]any{"PipelineName": "persist-pipeline"}) require.Equal(t, http.StatusOK, recVersions.Code) var versionsOut map[string]any - require.NoError(t, json.Unmarshal(recVersions.Body.Bytes(), &versionsOut)) + require.NoError(t, json.Unmarshal(recVersions.Body.Bytes(), &versionsOut, jsonx.V1())) versions, _ := versionsOut["PipelineVersionSummaries"].([]any) assert.Len(t, versions, 2) } @@ -201,7 +202,7 @@ func TestPersistenceRoundtrip_ClusterFullFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "arn:aws:iam::000000000000:role/HyperPodClusterRole", resp["ClusterRole"]) @@ -297,7 +298,7 @@ func TestPersistenceRoundtrip_PipelineDefinitionFromS3(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.JSONEq(t, `{"Version":"2020-12-01","Steps":[{"Name":"Step1"}]}`, resp["PipelineDefinition"].(string)) } @@ -434,7 +435,7 @@ func TestPersistenceRoundtrip_AIAndGenericJobFamilies(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantValue, out[tt.wantField]) }) } @@ -458,7 +459,7 @@ func TestPersistenceRoundtrip_Domain(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) domainID := createOut["DomainId"].(string) snap := h1.Snapshot(t.Context()) @@ -471,7 +472,7 @@ func TestPersistenceRoundtrip_Domain(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, descRec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "VpcOnly", out["AppNetworkAccessType"]) assert.ElementsMatch(t, []any{"subnet-1"}, out["SubnetIds"]) assert.NotEmpty(t, out["DefaultUserSettings"]) diff --git a/services/sagemaker/pipeline_executions.go b/services/sagemaker/pipeline_executions.go index 8dd1fa1ef0..b673c27ca4 100644 --- a/services/sagemaker/pipeline_executions.go +++ b/services/sagemaker/pipeline_executions.go @@ -2,11 +2,13 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -285,7 +287,7 @@ func pipelineDefinitionSteps(definition string) []definedPipelineStep { Steps []definedPipelineStep `json:"Steps"` } - if json.Unmarshal([]byte(definition), &doc) != nil { + if json.Unmarshal([]byte(definition), &doc, jsonx.V1()) != nil { return nil } diff --git a/services/sagemaker/projects.go b/services/sagemaker/projects.go index 8bc3b60086..29547d98c5 100644 --- a/services/sagemaker/projects.go +++ b/services/sagemaker/projects.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrProjectNotFound is returned when a project does not exist. @@ -37,8 +39,8 @@ type Project struct { ProjectStatus string `json:"ProjectStatus"` ProjectDescription string `json:"ProjectDescription,omitempty"` ProvisionedProductID string `json:"ProvisionedProductId,omitempty"` - ServiceCatalogProvisioningDetails json.RawMessage `json:"ServiceCatalogProvisioningDetails,omitempty"` - TemplateProviders json.RawMessage `json:"TemplateProviders,omitempty"` + ServiceCatalogProvisioningDetails jsontext.Value `json:"ServiceCatalogProvisioningDetails,omitempty"` + TemplateProviders jsontext.Value `json:"TemplateProviders,omitempty"` } func cloneProject(p *Project) *Project { @@ -46,8 +48,8 @@ func cloneProject(p *Project) *Project { cp.Tags = maps.Clone(p.Tags) cp.CreatedBy = cloneUserContext(p.CreatedBy) cp.LastModifiedBy = cloneUserContext(p.LastModifiedBy) - cp.ServiceCatalogProvisioningDetails = append(json.RawMessage(nil), p.ServiceCatalogProvisioningDetails...) - cp.TemplateProviders = append(json.RawMessage(nil), p.TemplateProviders...) + cp.ServiceCatalogProvisioningDetails = append(jsontext.Value(nil), p.ServiceCatalogProvisioningDetails...) + cp.TemplateProviders = append(jsontext.Value(nil), p.TemplateProviders...) return &cp } @@ -68,7 +70,7 @@ func (p *Project) MarshalJSON() ([]byte, error) { alias: (*alias)(p), CreationTime: epochSeconds(p.CreationTime), LastModifiedTime: epochSeconds(p.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [Project.MarshalJSON], read by @@ -82,7 +84,7 @@ func (p *Project) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(p)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -97,8 +99,8 @@ type CreateProjectOptions struct { Tags map[string]string Name string Description string - ServiceCatalogProvisioningDetails json.RawMessage - TemplateProviders json.RawMessage + ServiceCatalogProvisioningDetails jsontext.Value + TemplateProviders jsontext.Value } // CreateProject creates a SageMaker project. diff --git a/services/sagemaker/projects_update.go b/services/sagemaker/projects_update.go index 085ce2e530..0811944eed 100644 --- a/services/sagemaker/projects_update.go +++ b/services/sagemaker/projects_update.go @@ -1,8 +1,11 @@ package sagemaker import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // UpdateProjectOptions holds the parameters for UpdateProject. @@ -35,7 +38,7 @@ type updateTemplateProviderInput struct { // applyProvisioningUpdate merges ServiceCatalogProvisioningUpdateDetails // (ProvisioningArtifactId, ProvisioningParameters) into the stored details. -func applyProvisioningUpdate(stored json.RawMessage, upd *serviceCatalogUpdateDetails) (json.RawMessage, error) { +func applyProvisioningUpdate(stored jsontext.Value, upd *serviceCatalogUpdateDetails) (jsontext.Value, error) { if upd == nil { return stored, nil } @@ -47,7 +50,7 @@ func applyProvisioningUpdate(stored json.RawMessage, upd *serviceCatalogUpdateDe } var details map[string]any - if err := json.Unmarshal(stored, &details); err != nil { + if err := json.Unmarshal(stored, &details, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: stored provisioning details: %w", ErrValidation, err) } @@ -59,22 +62,22 @@ func applyProvisioningUpdate(stored json.RawMessage, upd *serviceCatalogUpdateDe details["ProvisioningParameters"] = upd.ProvisioningParameters } - return json.Marshal(details) + return json.Marshal(details, jsonx.V1()) } // applyTemplateProviderUpdates replaces TemplateURL/Parameters of each stored // CfnTemplateProvider matched by TemplateName. func applyTemplateProviderUpdates( - stored json.RawMessage, + stored jsontext.Value, updates []cfnUpdateTemplateProvider, -) (json.RawMessage, error) { +) (jsontext.Value, error) { if len(updates) == 0 { return stored, nil } var providers []map[string]map[string]any if len(stored) > 0 { - if err := json.Unmarshal(stored, &providers); err != nil { + if err := json.Unmarshal(stored, &providers, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: stored template providers: %w", ErrValidation, err) } } @@ -85,7 +88,7 @@ func applyTemplateProviderUpdates( } } - return json.Marshal(providers) + return json.Marshal(providers, jsonx.V1()) } func updateOneTemplateProvider(providers []map[string]map[string]any, u cfnUpdateTemplateProvider) bool { @@ -108,9 +111,9 @@ func updateOneTemplateProvider(providers []map[string]map[string]any, u cfnUpdat // templateProviderDetails converts stored CreateTemplateProvider entries to the // TemplateProviderDetail wire shape (CfnTemplateProviderDetail key). -func templateProviderDetails(stored json.RawMessage) []map[string]any { +func templateProviderDetails(stored jsontext.Value) []map[string]any { var providers []map[string]map[string]any - if err := json.Unmarshal(stored, &providers); err != nil { + if err := json.Unmarshal(stored, &providers, jsonx.V1()); err != nil { return nil } diff --git a/services/sagemaker/request_realism_test.go b/services/sagemaker/request_realism_test.go index ac36d79e39..47017fde73 100644 --- a/services/sagemaker/request_realism_test.go +++ b/services/sagemaker/request_realism_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const realismRole = "arn:aws:iam::000000000000:role/r" @@ -37,7 +39,7 @@ func errorOf(t *testing.T, body []byte) (string, string) { t.Helper() var out map[string]string - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out["__type"], out["message"] } @@ -188,7 +190,7 @@ func TestRequestRealism_TrainingSecondaryStatusProgression(t *testing.T) { r := doSageMakerRequest(t, h, "DescribeTrainingJob", map[string]any{"TrainingJobName": "progress"}) got.SecondaryStatusTransitions = nil - return json.Unmarshal(r.Body.Bytes(), &got) == nil && got.TrainingJobStatus == "Completed" + return json.Unmarshal(r.Body.Bytes(), &got, jsonx.V1()) == nil && got.TrainingJobStatus == "Completed" }, 5*time.Second, 5*time.Millisecond) statuses := make([]string, 0, len(got.SecondaryStatusTransitions)) @@ -217,7 +219,7 @@ func TestRequestRealism_StopCompletedTrainingJobIsNoop(t *testing.T) { } r := doSageMakerRequest(t, h, "DescribeTrainingJob", map[string]any{"TrainingJobName": "done"}) - return json.Unmarshal(r.Body.Bytes(), &out) == nil && out.TrainingJobStatus == "Completed" + return json.Unmarshal(r.Body.Bytes(), &out, jsonx.V1()) == nil && out.TrainingJobStatus == "Completed" }, 5*time.Second, 5*time.Millisecond) require.Equal(t, http.StatusOK, @@ -227,7 +229,7 @@ func TestRequestRealism_StopCompletedTrainingJobIsNoop(t *testing.T) { TrainingJobStatus string `json:"TrainingJobStatus"` } r := doSageMakerRequest(t, h, "DescribeTrainingJob", map[string]any{"TrainingJobName": "done"}) - require.NoError(t, json.Unmarshal(r.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(r.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "Completed", out.TrainingJobStatus) }) } @@ -254,7 +256,7 @@ func TestRequestRealism_StopFinishedProcessingJobKeepsStatus(t *testing.T) { ProcessingJobStatus string `json:"ProcessingJobStatus"` } r := doSageMakerRequest(t, h, "DescribeProcessingJob", map[string]any{"ProcessingJobName": "pj"}) - _ = json.Unmarshal(r.Body.Bytes(), &out) + _ = json.Unmarshal(r.Body.Bytes(), &out, jsonx.V1()) return out.ProcessingJobStatus } diff --git a/services/sagemaker/request_validation.go b/services/sagemaker/request_validation.go index 60d2d10076..f6c428b0f5 100644 --- a/services/sagemaker/request_validation.go +++ b/services/sagemaker/request_validation.go @@ -1,13 +1,14 @@ package sagemaker import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strconv" "strings" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -152,7 +153,7 @@ func validateListPaging(op string, body []byte) error { NextToken string `json:"NextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if m := req.MaxResults; m != nil && (*m < minListMaxResults || *m > maxListMaxResults) { return fmt.Errorf( diff --git a/services/sagemaker/shape_validation.go b/services/sagemaker/shape_validation.go index 0d0483532f..51efcee9af 100644 --- a/services/sagemaker/shape_validation.go +++ b/services/sagemaker/shape_validation.go @@ -3,12 +3,15 @@ package sagemaker import ( "bytes" _ "embed" // shape_table.json - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "reflect" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errShapeInvalid = errors.New("invalid document") @@ -34,7 +37,7 @@ type shapeTableDoc struct { //nolint:gochecknoglobals // lazily parsed read-only schema var loadShapeTable = sync.OnceValue(func() shapeTableDoc { var doc shapeTableDoc - if err := json.Unmarshal(shapeTableJSON, &doc); err != nil { + if err := json.Unmarshal(shapeTableJSON, &doc, jsonx.V1()); err != nil { panic(fmt.Sprintf("sagemaker: invalid shape_table.json: %v", err)) } @@ -49,7 +52,7 @@ func validateRequestShapes(op string, req any) error { for i := range v.NumField() { f := v.Type().Field(i) - if f.Type != reflect.TypeFor[json.RawMessage]() { + if f.Type != reflect.TypeFor[jsontext.Value]() { continue } @@ -60,7 +63,7 @@ func validateRequestShapes(op string, req any) error { continue } - raw, _ := reflect.TypeAssert[json.RawMessage](v.Field(i)) + raw, _ := reflect.TypeAssert[jsontext.Value](v.Field(i)) if isAbsentJSON(raw) { continue } @@ -73,13 +76,13 @@ func validateRequestShapes(op string, req any) error { return nil } -func isAbsentJSON(raw json.RawMessage) bool { +func isAbsentJSON(raw jsontext.Value) bool { t := bytes.TrimSpace(raw) return len(t) == 0 || bytes.Equal(t, []byte("null")) } -func validateShape(table shapeTableDoc, raw json.RawMessage, shape, path string) error { +func validateShape(table shapeTableDoc, raw jsontext.Value, shape, path string) error { rule, ok := table.Shapes[shape] if !ok { return nil @@ -89,8 +92,8 @@ func validateShape(table shapeTableDoc, raw json.RawMessage, shape, path string) return validateShapeList(table, raw, rule.List, path) } - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil { return fmt.Errorf("%w: %s must be an object", errShapeInvalid, path) } @@ -115,7 +118,7 @@ func validateShape(table shapeTableDoc, raw json.RawMessage, shape, path string) return nil } -func validateShapeMember(table shapeTableDoc, raw json.RawMessage, shape, path string) error { +func validateShapeMember(table shapeTableDoc, raw jsontext.Value, shape, path string) error { if isAbsentJSON(raw) { return nil } @@ -123,9 +126,9 @@ func validateShapeMember(table shapeTableDoc, raw json.RawMessage, shape, path s return validateShape(table, raw, shape, path) } -func validateShapeList(table shapeTableDoc, raw json.RawMessage, elem, path string) error { - var items []json.RawMessage - if err := json.Unmarshal(raw, &items); err != nil { +func validateShapeList(table shapeTableDoc, raw jsontext.Value, elem, path string) error { + var items []jsontext.Value + if err := json.Unmarshal(raw, &items, jsonx.V1()); err != nil { return fmt.Errorf("%w: %s must be a list", errShapeInvalid, path) } diff --git a/services/sagemaker/spaces.go b/services/sagemaker/spaces.go index 1053928181..08aebe306e 100644 --- a/services/sagemaker/spaces.go +++ b/services/sagemaker/spaces.go @@ -2,7 +2,8 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrSpaceNotFound is returned when a space does not exist. @@ -34,17 +36,17 @@ type Space struct { DomainID string `json:"DomainId"` SpaceStatus string `json:"Status"` SpaceDisplayName string `json:"SpaceDisplayName,omitempty"` - OwnershipSettings json.RawMessage `json:"OwnershipSettings,omitempty"` - SpaceSettings json.RawMessage `json:"SpaceSettings,omitempty"` - SpaceSharingSettings json.RawMessage `json:"SpaceSharingSettings,omitempty"` + OwnershipSettings jsontext.Value `json:"OwnershipSettings,omitempty"` + SpaceSettings jsontext.Value `json:"SpaceSettings,omitempty"` + SpaceSharingSettings jsontext.Value `json:"SpaceSharingSettings,omitempty"` } func cloneSpace(s *Space) *Space { cp := *s cp.Tags = maps.Clone(s.Tags) - cp.OwnershipSettings = append(json.RawMessage(nil), s.OwnershipSettings...) - cp.SpaceSettings = append(json.RawMessage(nil), s.SpaceSettings...) - cp.SpaceSharingSettings = append(json.RawMessage(nil), s.SpaceSharingSettings...) + cp.OwnershipSettings = append(jsontext.Value(nil), s.OwnershipSettings...) + cp.SpaceSettings = append(jsontext.Value(nil), s.SpaceSettings...) + cp.SpaceSharingSettings = append(jsontext.Value(nil), s.SpaceSharingSettings...) return &cp } @@ -63,7 +65,7 @@ func (s *Space) MarshalJSON() ([]byte, error) { alias: (*alias)(s), CreationTime: epochSeconds(s.CreationTime), LastModifiedTime: epochSeconds(s.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [Space.MarshalJSON], read by @@ -77,7 +79,7 @@ func (s *Space) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(s)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -94,9 +96,9 @@ func spaceKey(domainID, spaceName string) string { // CreateSpaceOptions bundles CreateSpace's optional fields. type CreateSpaceOptions struct { SpaceDisplayName string - OwnershipSettings json.RawMessage - SpaceSettings json.RawMessage - SpaceSharingSettings json.RawMessage + OwnershipSettings jsontext.Value + SpaceSettings jsontext.Value + SpaceSharingSettings jsontext.Value } // CreateSpace creates a SageMaker Studio space. @@ -249,7 +251,7 @@ func (b *InMemoryBackend) ListSpaces(ctx context.Context, params ListSpacesParam // unset, so only a non-empty value is applied. type UpdateSpaceOptions struct { SpaceDisplayName string - SpaceSettings json.RawMessage + SpaceSettings jsontext.Value } // UpdateSpace updates a space in a domain. Returns the updated space. diff --git a/services/sagemaker/studio_lifecycle_configs.go b/services/sagemaker/studio_lifecycle_configs.go index 8897a80c12..b5da90e117 100644 --- a/services/sagemaker/studio_lifecycle_configs.go +++ b/services/sagemaker/studio_lifecycle_configs.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +11,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrStudioLifecycleConfigNotFound is returned when a studio lifecycle config does not exist. @@ -52,7 +53,7 @@ func (s *StudioLifecycleConfig) MarshalJSON() ([]byte, error) { alias: (*alias)(s), CreationTime: epochSeconds(s.CreationTime), LastModifiedTime: epochSeconds(s.LastModifiedTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [StudioLifecycleConfig.MarshalJSON], read @@ -66,7 +67,7 @@ func (s *StudioLifecycleConfig) UnmarshalJSON(data []byte) error { LastModifiedTime float64 `json:"LastModifiedTime"` }{alias: (*alias)(s)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/training_jobs.go b/services/sagemaker/training_jobs.go index 088367887e..5313610b3a 100644 --- a/services/sagemaker/training_jobs.go +++ b/services/sagemaker/training_jobs.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -21,7 +21,7 @@ var ( ) // rawConfigMap holds CreateTrainingJob members stored verbatim. -type rawConfigMap = map[string]json.RawMessage +type rawConfigMap = map[string]jsontext.Value type TrainingJob struct { PassthroughConfigs rawConfigMap `json:"PassthroughConfigs,omitempty"` diff --git a/services/sagemaker/training_plan.go b/services/sagemaker/training_plan.go index ef9480ac76..758063d4a9 100644 --- a/services/sagemaker/training_plan.go +++ b/services/sagemaker/training_plan.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // trainingPlanStatusScheduled mirrors AWS's TrainingPlanStatus "Scheduled" @@ -126,7 +127,7 @@ func (rc *ReservedCapacity) MarshalJSON() ([]byte, error) { StartTime: epochSeconds(rc.StartTime), EndTime: epochSeconds(rc.EndTime), UltraServerSummary: rc.ultraServerSummary(), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ReservedCapacity.MarshalJSON], read by @@ -140,7 +141,7 @@ func (rc *ReservedCapacity) UnmarshalJSON(data []byte) error { EndTime float64 `json:"EndTime"` }{alias: (*alias)(rc)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -478,7 +479,7 @@ func (o TrainingPlanExtensionOffering) MarshalJSON() ([]byte, error) { alias: alias(o), StartDate: epochSeconds(o.StartDate), EndDate: epochSeconds(o.EndDate), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [TrainingPlanExtensionOffering.MarshalJSON]. @@ -491,7 +492,7 @@ func (o *TrainingPlanExtensionOffering) UnmarshalJSON(data []byte) error { EndDate float64 `json:"EndDate"` }{alias: (*alias)(o)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/training_plans.go b/services/sagemaker/training_plans.go index 54c17dcc4f..c043dc6333 100644 --- a/services/sagemaker/training_plans.go +++ b/services/sagemaker/training_plans.go @@ -2,13 +2,14 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrTrainingPlanNotFound is returned when a training plan does not exist. @@ -48,7 +49,7 @@ func (r *ReservedCapacitySummary) MarshalJSON() ([]byte, error) { alias: (*alias)(r), StartTime: epochSecondsPtr(r.StartTime), EndTime: epochSecondsPtr(r.EndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [ReservedCapacitySummary.MarshalJSON], @@ -62,7 +63,7 @@ func (r *ReservedCapacitySummary) UnmarshalJSON(data []byte) error { EndTime *float64 `json:"EndTime,omitempty"` }{alias: (*alias)(r)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -142,7 +143,7 @@ func (e TrainingPlanExtension) MarshalJSON() ([]byte, error) { ExtendedAt: epochSeconds(e.ExtendedAt), StartDate: epochSeconds(e.StartDate), EndDate: epochSeconds(e.EndDate), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [TrainingPlanExtension.MarshalJSON], read @@ -157,7 +158,7 @@ func (e *TrainingPlanExtension) UnmarshalJSON(data []byte) error { EndDate float64 `json:"EndDate"` }{alias: (*alias)(e)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } @@ -184,7 +185,7 @@ func (t *TrainingPlan) MarshalJSON() ([]byte, error) { CreationTime: epochSeconds(t.CreationTime), StartTime: epochSecondsPtr(t.StartTime), EndTime: epochSecondsPtr(t.EndTime), - }) + }, jsonx.V1()) } // UnmarshalJSON is the inverse of [TrainingPlan.MarshalJSON], read by @@ -199,7 +200,7 @@ func (t *TrainingPlan) UnmarshalJSON(data []byte) error { CreationTime float64 `json:"CreationTime"` }{alias: (*alias)(t)} - if err := json.Unmarshal(data, &aux); err != nil { + if err := json.Unmarshal(data, &aux, jsonx.V1()); err != nil { return err } diff --git a/services/sagemaker/user_profiles.go b/services/sagemaker/user_profiles.go index c9b472ff08..14755b725d 100644 --- a/services/sagemaker/user_profiles.go +++ b/services/sagemaker/user_profiles.go @@ -2,7 +2,7 @@ package sagemaker import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -45,13 +45,13 @@ type UserProfile struct { Status string `json:"Status"` SingleSignOnUserIdentifier string `json:"SingleSignOnUserIdentifier,omitempty"` SingleSignOnUserValue string `json:"SingleSignOnUserValue,omitempty"` - UserSettings json.RawMessage `json:"UserSettings,omitempty"` + UserSettings jsontext.Value `json:"UserSettings,omitempty"` } func cloneUserProfile(up *UserProfile) *UserProfile { cp := *up cp.Tags = maps.Clone(up.Tags) - cp.UserSettings = append(json.RawMessage(nil), up.UserSettings...) + cp.UserSettings = append(jsontext.Value(nil), up.UserSettings...) return &cp } @@ -60,7 +60,7 @@ func cloneUserProfile(up *UserProfile) *UserProfile { type CreateUserProfileOptions struct { SingleSignOnUserIdentifier string SingleSignOnUserValue string - UserSettings json.RawMessage + UserSettings jsontext.Value } // CreateUserProfile creates a new user profile in a domain. @@ -226,7 +226,7 @@ func (b *InMemoryBackend) DeleteUserProfile(ctx context.Context, domainID, name // (api_op_UpdateUserProfile.go:26-38). UserSettings is omitted from the // request when unset, so only a non-empty value is applied. type UpdateUserProfileOptions struct { - UserSettings json.RawMessage + UserSettings jsontext.Value } // UpdateUserProfile updates a user profile in a domain. Returns the updated profile. diff --git a/services/sagemaker/variant_weight_default_test.go b/services/sagemaker/variant_weight_default_test.go index 89758544d6..5e94114547 100644 --- a/services/sagemaker/variant_weight_default_test.go +++ b/services/sagemaker/variant_weight_default_test.go @@ -1,13 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemaker" ) @@ -73,7 +74,7 @@ func TestEndpointConfig_VariantWeightDefaultsToOne(t *testing.T) { DesiredWeight float64 `json:"DesiredWeight"` } `json:"ProductionVariants"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ep)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &ep, jsonx.V1())) require.Len(t, ep.ProductionVariants, 1) assert.InDelta(t, tt.want, ep.ProductionVariants[0].DesiredWeight, 0.0001) @@ -85,7 +86,7 @@ func TestEndpointConfig_VariantWeightDefaultsToOne(t *testing.T) { InitialVariantWeight float64 `json:"InitialVariantWeight"` } `json:"ProductionVariants"` } - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &cfg)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &cfg, jsonx.V1())) require.Len(t, cfg.ProductionVariants, 1) assert.InDelta(t, tt.want, cfg.ProductionVariants[0].InitialVariantWeight, 0.0001) }) diff --git a/services/sagemaker/wire_field_fixes_respsweep2_test.go b/services/sagemaker/wire_field_fixes_respsweep2_test.go index 019f58c0b6..b7d4a1cf11 100644 --- a/services/sagemaker/wire_field_fixes_respsweep2_test.go +++ b/services/sagemaker/wire_field_fixes_respsweep2_test.go @@ -1,7 +1,7 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -11,6 +11,8 @@ import ( smtypes "github.com/aws/aws-sdk-go-v2/service/sagemaker/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateEndpointConfig_DataCaptureConfig proves @@ -83,7 +85,7 @@ func TestCreateEndpointConfig_VpcConfigSurvivesEmptyArrays(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) vpc, ok := resp["VpcConfig"].(map[string]any) require.True(t, ok, "VpcConfig key must be present") @@ -128,7 +130,7 @@ func TestCreateTrainingJob_ModelArtifactsRequiredWhileInProgress(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.Equal(t, "InProgress", resp["TrainingJobStatus"]) artifacts, ok := resp["ModelArtifacts"].(map[string]any) @@ -267,7 +269,7 @@ func TestCreatePipeline_ParallelismConfigurationSurvivesZero(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) pc, ok := resp["ParallelismConfiguration"].(map[string]any) require.True(t, ok, "ParallelismConfiguration key must be present") @@ -301,7 +303,7 @@ func TestCreateProcessingJob_OutputsSurvivesEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) poc, ok := resp["ProcessingOutputConfig"].(map[string]any) require.True(t, ok) @@ -337,7 +339,7 @@ func TestDescribeAutoMLJob_RequiredFieldsSurviveEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) outCfg, ok := resp["OutputDataConfig"].(map[string]any) require.True(t, ok) @@ -421,7 +423,7 @@ func TestCreateCompilationJob_InputConfigOrModelPackageVersionArnRequired(t *tes require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) inCfg, ok := resp["InputConfig"].(map[string]any) require.True(t, ok) s3uri, ok := inCfg["S3Uri"] @@ -472,7 +474,7 @@ func TestListTrainingJobsForHPTuningJob_TunedHyperParametersSurvivesEmpty(t *tes require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TrainingJobSummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 1) diff --git a/services/sagemaker/wire_field_fixes_respsweep_test.go b/services/sagemaker/wire_field_fixes_respsweep_test.go index 22773e74bb..49a99186a8 100644 --- a/services/sagemaker/wire_field_fixes_respsweep_test.go +++ b/services/sagemaker/wire_field_fixes_respsweep_test.go @@ -1,12 +1,14 @@ package sagemaker_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCompilationJob_RequiredOutputMembersSurviveInProgress drives @@ -47,7 +49,7 @@ func TestCompilationJob_RequiredOutputMembersSurviveInProgress(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) require.Equal( t, "INPROGRESS", resp["CompilationJobStatus"], @@ -86,7 +88,7 @@ func TestModelCard_ContentSurvivesEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rr.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp, jsonx.V1())) content, ok := resp["Content"] assert.True(t, ok, "Content key must be present even when empty") diff --git a/services/sagemakerruntime/endpoint_validation_test.go b/services/sagemakerruntime/endpoint_validation_test.go index 002af55518..d6eb33d23a 100644 --- a/services/sagemakerruntime/endpoint_validation_test.go +++ b/services/sagemakerruntime/endpoint_validation_test.go @@ -2,7 +2,7 @@ package sagemakerruntime_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sagemaker" "github.com/blackbirdworks/gopherstack/services/sagemakerruntime" @@ -88,7 +89,7 @@ func TestHandler_EndpointValidation(t *testing.T) { if want == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationError", body["__type"]) assert.Contains(t, body["message"], tt.endpointName) } diff --git a/services/sagemakerruntime/handler.go b/services/sagemakerruntime/handler.go index 70301fd784..98e75a3e34 100644 --- a/services/sagemakerruntime/handler.go +++ b/services/sagemakerruntime/handler.go @@ -3,7 +3,7 @@ package sagemakerruntime import ( "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "hash/crc32" "math" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -266,7 +267,7 @@ func (h *Handler) handleInvokeEndpointAsync( acc.FailureLocation, ) - out, err := json.Marshal(map[string]string{"InferenceId": acc.InferenceID}) + out, err := json.Marshal(map[string]string{"InferenceId": acc.InferenceID}, jsonx.V1()) if err != nil { return err } diff --git a/services/sagemakerruntime/handler_test.go b/services/sagemakerruntime/handler_test.go index e160516882..2cbd724645 100644 --- a/services/sagemakerruntime/handler_test.go +++ b/services/sagemakerruntime/handler_test.go @@ -2,7 +2,7 @@ package sagemakerruntime_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sagemakerruntime" @@ -54,7 +55,7 @@ func doRequestWithHeaders( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -294,7 +295,7 @@ func TestHandler_ErrorCodes(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantType, body["__type"]) }) } diff --git a/services/sagemakerruntime/invoke_endpoint_async_test.go b/services/sagemakerruntime/invoke_endpoint_async_test.go index cbb85c7940..c4a95f990c 100644 --- a/services/sagemakerruntime/invoke_endpoint_async_test.go +++ b/services/sagemakerruntime/invoke_endpoint_async_test.go @@ -1,7 +1,7 @@ package sagemakerruntime_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,8 @@ import ( sagemakerruntimesdk "github.com/aws/aws-sdk-go-v2/service/sagemakerruntime" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --- InvokeEndpointAsync tests --- @@ -41,7 +43,7 @@ func TestHandler_InvokeEndpointAsync(t *testing.T) { assert.Equal(t, http.StatusAccepted, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["InferenceId"]) assert.NotContains(t, out, "OutputLocation") assert.NotContains(t, out, "FailureLocation") @@ -351,7 +353,7 @@ func TestAsyncInvocation_BodyInputLocationMutualExclusion(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "ValidationError", out["__type"]) assert.Contains(t, out["message"], "mutually exclusive") } diff --git a/services/sagemakerruntime/invoke_errors_test.go b/services/sagemakerruntime/invoke_errors_test.go index 0925f80743..bbabac3562 100644 --- a/services/sagemakerruntime/invoke_errors_test.go +++ b/services/sagemakerruntime/invoke_errors_test.go @@ -1,7 +1,7 @@ package sagemakerruntime_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sagemakerruntime" ) @@ -36,7 +37,7 @@ func TestInvoke_NoContainerBackend_NeverFabricatesOutput(t *testing.T) { require.Equal(t, http.StatusServiceUnavailable, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ServiceUnavailable", body["__type"]) assert.NotContains(t, rec.Body.String(), "mock") assert.Empty(t, h.Backend.ListInvocations(), "a failed invoke must not be recorded") @@ -95,7 +96,7 @@ func TestInvoke_ErrorMapping(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, tt.wantType, body["__type"]) }) } diff --git a/services/sagemakerruntime/multi_region_test.go b/services/sagemakerruntime/multi_region_test.go index ae59a72123..08f71637ea 100644 --- a/services/sagemakerruntime/multi_region_test.go +++ b/services/sagemakerruntime/multi_region_test.go @@ -2,7 +2,8 @@ package sagemakerruntime_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sagemaker" "github.com/blackbirdworks/gopherstack/services/sagemakerruntime" @@ -152,8 +154,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/sagemakerruntime/persistence.go b/services/sagemakerruntime/persistence.go index 1a80643607..e7dc4c3f60 100644 --- a/services/sagemakerruntime/persistence.go +++ b/services/sagemakerruntime/persistence.go @@ -2,9 +2,11 @@ package sagemakerruntime import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -32,10 +34,10 @@ const sagemakerruntimeSnapshotVersion = 1 // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Invocations []*Invocation `json:"invocations"` - NextID uint64 `json:"nextId"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Invocations []*Invocation `json:"invocations"` + NextID uint64 `json:"nextId"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. @@ -64,7 +66,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NextID: b.nextID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "sagemakerruntime: failed to marshal snapshot", "error", err) diff --git a/services/scheduler/handler.go b/services/scheduler/handler.go index 61753a3150..6f7fcddab8 100644 --- a/services/scheduler/handler.go +++ b/services/scheduler/handler.go @@ -3,7 +3,8 @@ package scheduler import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -16,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -266,7 +268,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } var req scheduleNameInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.Name } @@ -443,13 +445,13 @@ func (h *Handler) enrichRESTBody(action, name string, body []byte, q url.Values) enrichTagsPath(m, name, action, q) } - result, _ := json.Marshal(m) + result, _ := json.Marshal(m, jsonx.V1()) return result } // enrichScheduleByPath injects Name from the URL path and GroupName from the query string. -func enrichScheduleByPath(m map[string]json.RawMessage, name string, q url.Values) { +func enrichScheduleByPath(m map[string]jsontext.Value, name string, q url.Values) { if name != "" { setJSONString(m, "Name", name) } @@ -460,7 +462,7 @@ func enrichScheduleByPath(m map[string]json.RawMessage, name string, q url.Value } // enrichListSchedulesQuery injects ListSchedules query parameters into the JSON map. -func enrichListSchedulesQuery(m map[string]json.RawMessage, q url.Values) { +func enrichListSchedulesQuery(m map[string]jsontext.Value, q url.Values) { if sg := q.Get("ScheduleGroup"); sg != "" { setJSONString(m, "GroupName", sg) } @@ -478,7 +480,7 @@ func enrichListSchedulesQuery(m map[string]json.RawMessage, q url.Values) { } // enrichListScheduleGroupsQuery injects ListScheduleGroups query parameters into the JSON map. -func enrichListScheduleGroupsQuery(m map[string]json.RawMessage, q url.Values) { +func enrichListScheduleGroupsQuery(m map[string]jsontext.Value, q url.Values) { for _, qk := range []struct{ query, json string }{ {keyNamePrefix, keyNamePrefix}, {keyNextToken, keyNextToken}, @@ -494,7 +496,7 @@ func enrichListScheduleGroupsQuery(m map[string]json.RawMessage, q url.Values) { // string. UntagResource sends TagKeys as a repeated query parameter // (?TagKeys=a&TagKeys=b, see awsRestjson1_serializeOpHttpBindingsUntagResourceInput's // encoder.AddQuery("TagKeys", ...)), not a single comma-separated value. -func enrichTagsPath(m map[string]json.RawMessage, name, action string, q url.Values) { +func enrichTagsPath(m map[string]jsontext.Value, name, action string, q url.Values) { if name != "" { setJSONString(m, "ResourceArn", name) } @@ -504,34 +506,34 @@ func enrichTagsPath(m map[string]json.RawMessage, name, action string, q url.Val } if keys := q["TagKeys"]; len(keys) > 0 { - keysJSON, _ := json.Marshal(keys) - m["TagKeys"] = json.RawMessage(keysJSON) + keysJSON, _ := json.Marshal(keys, jsonx.V1()) + m["TagKeys"] = jsontext.Value(keysJSON) } } // unmarshalOrEmpty parses body as a JSON object, returning an empty map on failure. -func unmarshalOrEmpty(body []byte) map[string]json.RawMessage { - var m map[string]json.RawMessage +func unmarshalOrEmpty(body []byte) map[string]jsontext.Value { + var m map[string]jsontext.Value if len(body) > 0 { - if err := json.Unmarshal(body, &m); err != nil { - return make(map[string]json.RawMessage) + if err := json.Unmarshal(body, &m, jsonx.V1()); err != nil { + return make(map[string]jsontext.Value) } return m } - return make(map[string]json.RawMessage) + return make(map[string]jsontext.Value) } // setJSONString encodes value as a JSON string and sets it on key in the map, // unless key is already present. -func setJSONString(m map[string]json.RawMessage, key, value string) { +func setJSONString(m map[string]jsontext.Value, key, value string) { if _, exists := m[key]; exists { return } - quoted, _ := json.Marshal(value) - m[key] = json.RawMessage(quoted) + quoted, _ := json.Marshal(value, jsonx.V1()) + m[key] = jsontext.Value(quoted) } // buildOps constructs the dispatch map once at handler creation time. @@ -563,33 +565,30 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, ErrNotFound): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ResourceNotFoundException", Message: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusNotFound, payload) case errors.Is(err, ErrAlreadyExists): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "ConflictException", Message: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusConflict, payload) case errors.Is(err, ErrValidation): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errCodeValidation, Message: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) // scheduler@v1.20.4 deserializers.go models ValidationException and @@ -597,18 +596,18 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err // scanning every awsRestjson1_deserializeOpError* switch), so both are safe // blanket fallbacks regardless of which operation reached this path. case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): payload, _ := json.Marshal(service.JSONErrorResponse{ Type: errCodeValidation, Message: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) default: payload, _ := json.Marshal(service.JSONErrorResponse{ Type: "InternalServerException", Message: errMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusInternalServerError, payload) } diff --git a/services/scheduler/handler_error_type_internal_test.go b/services/scheduler/handler_error_type_internal_test.go index ae609beac6..b2049e1c32 100644 --- a/services/scheduler/handler_error_type_internal_test.go +++ b/services/scheduler/handler_error_type_internal_test.go @@ -2,7 +2,7 @@ package scheduler import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -42,6 +43,6 @@ func TestHandleError_GenericErrorSurfacesInternalServerException(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, rec.Code) var payload service.JSONErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &payload, jsonx.V1())) assert.Equal(t, "InternalServerException", payload.Type) } diff --git a/services/scheduler/handler_test.go b/services/scheduler/handler_test.go index 4742ce7448..8740822c23 100644 --- a/services/scheduler/handler_test.go +++ b/services/scheduler/handler_test.go @@ -2,7 +2,7 @@ package scheduler_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/scheduler" ) @@ -27,7 +28,7 @@ func doSchedulerRequest(t *testing.T, h *scheduler.Handler, action string, body var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -78,7 +79,7 @@ func doRESTRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/scheduler/idempotency_test.go b/services/scheduler/idempotency_test.go index 1cdf337e9a..7e78e6cf66 100644 --- a/services/scheduler/idempotency_test.go +++ b/services/scheduler/idempotency_test.go @@ -1,13 +1,15 @@ package scheduler_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateSchedule_ClientToken_ReplaysOnRetry verifies that retrying a @@ -32,13 +34,13 @@ func TestCreateSchedule_ClientToken_ReplaysOnRetry(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rec2 := doSchedulerRequest(t, h, "CreateSchedule", req) require.Equal(t, http.StatusOK, rec2.Code, "retry with the same ClientToken must replay, not 409") var out2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1["ScheduleArn"], out2["ScheduleArn"]) @@ -49,7 +51,7 @@ func TestCreateSchedule_ClientToken_ReplaysOnRetry(t *testing.T) { var list struct { Schedules []map[string]any `json:"Schedules"` } - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &list)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &list, jsonx.V1())) assert.Len(t, list.Schedules, 1) } @@ -120,13 +122,13 @@ func TestCreateScheduleGroup_ClientToken_ReplaysOnRetry(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rec2 := doSchedulerRequest(t, h, "CreateScheduleGroup", req) require.Equal(t, http.StatusOK, rec2.Code, "retry with the same ClientToken must replay, not 409") var out2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1["ScheduleGroupArn"], out2["ScheduleGroupArn"]) } diff --git a/services/scheduler/persistence.go b/services/scheduler/persistence.go index 72bf0df938..6bb035af08 100644 --- a/services/scheduler/persistence.go +++ b/services/scheduler/persistence.go @@ -2,7 +2,7 @@ package scheduler import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "time" @@ -82,10 +82,10 @@ func persistedScheduleGroupKeyFn(v *persistedScheduleGroup) string { return v.AR // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // buildPersistenceDTORegistry constructs the ephemeral DTO registry used by both @@ -260,7 +260,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds the schedules and scheduleGroups store.Table // values from snap's per-table JSON, factored out of Restore to keep Restore's // own cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { dtoReg, scheduleDTOs, groupDTOs := buildPersistenceDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/scheduler/runner.go b/services/scheduler/runner.go index df181480ea..74bf9b7636 100644 --- a/services/scheduler/runner.go +++ b/services/scheduler/runner.go @@ -2,12 +2,13 @@ package scheduler import ( "context" - "encoding/json" + "encoding/json/v2" "strings" "sync" "time" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" @@ -598,7 +599,7 @@ func buildSchedulerPayload(s *Schedule) []byte { ScheduleName: s.Name, } - b, _ := json.Marshal(p) + b, _ := json.Marshal(p, jsonx.V1()) return b } diff --git a/services/scheduler/schedule_groups_test.go b/services/scheduler/schedule_groups_test.go index 83b15936c4..194b48261c 100644 --- a/services/scheduler/schedule_groups_test.go +++ b/services/scheduler/schedule_groups_test.go @@ -2,7 +2,8 @@ package scheduler_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/scheduler" ) @@ -60,7 +62,7 @@ func TestSchedulerHandler_CreateScheduleGroup(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) if tt.wantARN { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ScheduleGroupArn"], "arn:aws:scheduler:") assert.Contains(t, resp["ScheduleGroupArn"], "schedule-group/my-group") } @@ -125,7 +127,7 @@ func TestCreateScheduleGroup_DescriptionNotAccepted(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) _, hasDescription := resp["Description"] assert.False(t, hasDescription, "GetScheduleGroupOutput has no Description member on real AWS") } @@ -172,7 +174,7 @@ func TestSchedulerHandler_GetScheduleGroup(t *testing.T) { if tt.wantName != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantName, resp["Name"]) assert.Contains(t, resp["Arn"], "schedule-group/"+tt.wantName) assert.Equal(t, "ACTIVE", resp["State"]) @@ -192,7 +194,7 @@ func TestGetScheduleGroup_ReturnsCreationDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["CreationDate"]) assert.NotEmpty(t, resp["LastModificationDate"]) } @@ -206,11 +208,11 @@ func TestGetScheduleGroup_TimestampsAreEpochSeconds(t *testing.T) { rec := doSchedulerRequest(t, h, "GetScheduleGroup", map[string]any{"Name": "default"}) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) var cd float64 - require.NoError(t, json.Unmarshal(out["CreationDate"], &cd), "CreationDate must be a JSON number") + require.NoError(t, json.Unmarshal(out["CreationDate"], &cd, jsonx.V1()), "CreationDate must be a JSON number") assert.Greater(t, cd, float64(0)) } @@ -232,19 +234,19 @@ func TestGetScheduleGroup_OmitsTags(t *testing.T) { rec2 := doSchedulerRequest(t, h, "GetScheduleGroup", map[string]any{"Name": "grp-with-tags"}) require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) _, hasTags := out["Tags"] assert.False(t, hasTags, "GetScheduleGroup must not include a Tags field (not in real GetScheduleGroupOutput)") var groupARN string - require.NoError(t, json.Unmarshal(out["Arn"], &groupARN)) + require.NoError(t, json.Unmarshal(out["Arn"], &groupARN, jsonx.V1())) listRec := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": groupARN}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagsMap := wireTagsToMap(t, listResp["Tags"]) assert.Equal(t, "test", tagsMap["env"]) } @@ -371,7 +373,7 @@ func TestSchedulerHandler_ListScheduleGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ScheduleGroups") groups, ok := resp["ScheduleGroups"].([]any) require.True(t, ok) @@ -395,7 +397,7 @@ func TestListScheduleGroups_FilterByNamePrefix(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ScheduleGroups"].([]any) require.Len(t, groups, 1) @@ -417,7 +419,7 @@ func TestListScheduleGroups_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ScheduleGroups"].([]any) names := make([]string, len(groups)) @@ -441,13 +443,13 @@ func TestListScheduleGroups_TimestampsAreEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out struct { - ScheduleGroups []map[string]json.RawMessage `json:"ScheduleGroups"` + ScheduleGroups []map[string]jsontext.Value `json:"ScheduleGroups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.ScheduleGroups) var cd float64 - require.NoError(t, json.Unmarshal(out.ScheduleGroups[0]["CreationDate"], &cd)) + require.NoError(t, json.Unmarshal(out.ScheduleGroups[0]["CreationDate"], &cd, jsonx.V1())) assert.Greater(t, cd, float64(0)) } @@ -469,13 +471,13 @@ func TestListScheduleGroups_OmitsTags(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out struct { - ScheduleGroups []map[string]json.RawMessage `json:"ScheduleGroups"` + ScheduleGroups []map[string]jsontext.Value `json:"ScheduleGroups"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) for _, g := range out.ScheduleGroups { var name string - require.NoError(t, json.Unmarshal(g["Name"], &name)) + require.NoError(t, json.Unmarshal(g["Name"], &name, jsonx.V1())) if name == "list-grp-tags" { _, hasTags := g["Tags"] @@ -503,15 +505,15 @@ func TestListScheduleGroups_MaxResultsPagination(t *testing.T) { rec := doSchedulerRequest(t, h, "ListScheduleGroups", map[string]any{"MaxResults": "2"}) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) - var groups []json.RawMessage - require.NoError(t, json.Unmarshal(out["ScheduleGroups"], &groups)) + var groups []jsontext.Value + require.NoError(t, json.Unmarshal(out["ScheduleGroups"], &groups, jsonx.V1())) assert.Len(t, groups, 2) var token string - require.NoError(t, json.Unmarshal(out["NextToken"], &token)) + require.NoError(t, json.Unmarshal(out["NextToken"], &token, jsonx.V1())) assert.NotEmpty(t, token) } @@ -527,7 +529,7 @@ func TestRESTListScheduleGroups(t *testing.T) { var out struct { ScheduleGroups []map[string]any `json:"ScheduleGroups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.ScheduleGroups, "default group should always be present") } @@ -551,7 +553,7 @@ func TestSchedulerHandler_ScheduleGroup_RESTRouting(t *testing.T) { require.NoError(t, err) assert.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-group", getResp["Name"]) req3 := httptest.NewRequest(http.MethodGet, "/schedule-groups", nil) diff --git a/services/scheduler/schedules_list_test.go b/services/scheduler/schedules_list_test.go index 3d48eac0d7..c13ad8093f 100644 --- a/services/scheduler/schedules_list_test.go +++ b/services/scheduler/schedules_list_test.go @@ -2,13 +2,15 @@ package scheduler_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/scheduler" ) @@ -39,7 +41,7 @@ func TestSchedulerHandler_ListSchedules(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Schedules") schedules, ok := resp["Schedules"].([]any) require.True(t, ok) @@ -64,7 +66,7 @@ func TestListSchedules_FilterByGroupName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedules := resp["Schedules"].([]any) require.Len(t, schedules, 1) @@ -84,7 +86,7 @@ func TestListSchedules_FilterByNamePrefix(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedules := resp["Schedules"].([]any) assert.Len(t, schedules, 2) @@ -108,7 +110,7 @@ func TestListSchedules_FilterByState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedules := resp["Schedules"].([]any) require.Len(t, schedules, 1) @@ -128,7 +130,7 @@ func TestListSchedules_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedules := resp["Schedules"].([]any) require.Len(t, schedules, 3) @@ -152,7 +154,7 @@ func TestListSchedules_IncludesGroupNameAndDates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schedules := resp["Schedules"].([]any) require.Len(t, schedules, 1) @@ -174,13 +176,13 @@ func TestListSchedules_TimestampsAreEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out struct { - Schedules []map[string]json.RawMessage `json:"Schedules"` + Schedules []map[string]jsontext.Value `json:"Schedules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.Schedules) var cd float64 - require.NoError(t, json.Unmarshal(out.Schedules[0]["CreationDate"], &cd)) + require.NoError(t, json.Unmarshal(out.Schedules[0]["CreationDate"], &cd, jsonx.V1())) assert.Greater(t, cd, float64(0)) } @@ -198,7 +200,7 @@ func TestListSchedules_NextTokenOmittedWhenComplete(t *testing.T) { NextToken string `json:"NextToken"` Schedules []any `json:"Schedules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // NextToken should be empty when all results fit. assert.Empty(t, out.NextToken) } @@ -217,26 +219,26 @@ func TestListSchedules_MaxResultsPagination(t *testing.T) { rec1 := doSchedulerRequest(t, h, "ListSchedules", map[string]any{"MaxResults": "2"}) require.Equal(t, http.StatusOK, rec1.Code) - var page1 map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1)) + var page1 map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &page1, jsonx.V1())) - var schedules1 []json.RawMessage - require.NoError(t, json.Unmarshal(page1["Schedules"], &schedules1)) + var schedules1 []jsontext.Value + require.NoError(t, json.Unmarshal(page1["Schedules"], &schedules1, jsonx.V1())) require.Len(t, schedules1, 2) var nextToken string - require.NoError(t, json.Unmarshal(page1["NextToken"], &nextToken)) + require.NoError(t, json.Unmarshal(page1["NextToken"], &nextToken, jsonx.V1())) assert.NotEmpty(t, nextToken) // Get second page using the token. rec2 := doSchedulerRequest(t, h, "ListSchedules", map[string]any{"MaxResults": "2", "NextToken": nextToken}) require.Equal(t, http.StatusOK, rec2.Code) - var page2 map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2)) + var page2 map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &page2, jsonx.V1())) - var schedules2 []json.RawMessage - require.NoError(t, json.Unmarshal(page2["Schedules"], &schedules2)) + var schedules2 []jsontext.Value + require.NoError(t, json.Unmarshal(page2["Schedules"], &schedules2, jsonx.V1())) assert.Len(t, schedules2, 2) } @@ -254,11 +256,11 @@ func TestListSchedules_NoTokenReturnsAll(t *testing.T) { rec := doSchedulerRequest(t, h, "ListSchedules", map[string]any{}) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) - var schedules []json.RawMessage - require.NoError(t, json.Unmarshal(out["Schedules"], &schedules)) + var schedules []jsontext.Value + require.NoError(t, json.Unmarshal(out["Schedules"], &schedules, jsonx.V1())) assert.Len(t, schedules, 3) assert.Nil(t, out["NextToken"]) } @@ -286,9 +288,9 @@ func TestListSchedules_IncludesTargetSummary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out struct { - Schedules []map[string]json.RawMessage `json:"Schedules"` + Schedules []map[string]jsontext.Value `json:"Schedules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Schedules, 1) item := out.Schedules[0] @@ -298,13 +300,13 @@ func TestListSchedules_IncludesTargetSummary(t *testing.T) { var target struct { Arn string `json:"Arn"` } - require.NoError(t, json.Unmarshal(targetRaw, &target)) + require.NoError(t, json.Unmarshal(targetRaw, &target, jsonx.V1())) assert.Equal(t, "arn:aws:lambda:us-east-1:123:function:fn", target.Arn) // Real AWS's TargetSummary has no RoleArn field; assert gopherstack doesn't // invent one on the wire. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(targetRaw, &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(targetRaw, &raw, jsonx.V1())) _, hasRoleArn := raw["RoleArn"] assert.False(t, hasRoleArn, "ListSchedules Target summary must not include RoleArn (not in real TargetSummary)") } @@ -338,7 +340,7 @@ func TestListSchedules_TargetMatchesGetSchedule(t *testing.T) { } `json:"Target"` } `json:"Schedules"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Schedules, 1) assert.Equal(t, targetArn, listOut.Schedules[0].Target.Arn) } diff --git a/services/scheduler/schedules_rest_test.go b/services/scheduler/schedules_rest_test.go index 728eb6d98f..321d0528e0 100644 --- a/services/scheduler/schedules_rest_test.go +++ b/services/scheduler/schedules_rest_test.go @@ -1,12 +1,15 @@ package scheduler_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestRESTGetScheduleByPath verifies GET /schedules/{name} works with REST routing. @@ -20,7 +23,7 @@ func TestRESTGetScheduleByPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "rest-sched", out["Name"]) } @@ -37,7 +40,7 @@ func TestRESTGetScheduleWithGroupName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "grp-sched", out["Name"]) assert.Equal(t, "default", out["GroupName"]) } @@ -99,7 +102,7 @@ func TestRESTUpdateSchedule(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "rate(10 minutes)", out["ScheduleExpression"]) } @@ -124,7 +127,7 @@ func TestRESTListSchedulesWithGroupNameFilter(t *testing.T) { var out struct { Schedules []map[string]any `json:"Schedules"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Schedules, 1) assert.Equal(t, "s-grp", out.Schedules[0]["Name"]) } @@ -143,7 +146,7 @@ func TestRESTCreateScheduleByPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["ScheduleArn"]) // Verify it can be retrieved. @@ -166,11 +169,11 @@ func TestRESTListSchedules_MaxResultsQueryParam(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) - var schedules []json.RawMessage - require.NoError(t, json.Unmarshal(out["Schedules"], &schedules)) + var schedules []jsontext.Value + require.NoError(t, json.Unmarshal(out["Schedules"], &schedules, jsonx.V1())) assert.Len(t, schedules, 2) } diff --git a/services/scheduler/schedules_target_test.go b/services/scheduler/schedules_target_test.go index c185a8c45c..137037e999 100644 --- a/services/scheduler/schedules_target_test.go +++ b/services/scheduler/schedules_target_test.go @@ -1,12 +1,15 @@ package scheduler_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateSchedule_RetryPolicyRoundTrip verifies RetryPolicy fields round-trip. @@ -33,14 +36,14 @@ func TestCreateSchedule_RetryPolicyRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-retry"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var rp map[string]int - require.NoError(t, json.Unmarshal(target["RetryPolicy"], &rp)) + require.NoError(t, json.Unmarshal(target["RetryPolicy"], &rp, jsonx.V1())) assert.Equal(t, 3600, rp["MaximumEventAgeInSeconds"]) assert.Equal(t, 10, rp["MaximumRetryAttempts"]) } @@ -131,14 +134,14 @@ func TestUpdateSchedule_RetryPolicyPersisted(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "retry-update"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var rp map[string]int - require.NoError(t, json.Unmarshal(target["RetryPolicy"], &rp)) + require.NoError(t, json.Unmarshal(target["RetryPolicy"], &rp, jsonx.V1())) assert.Equal(t, 5, rp["MaximumRetryAttempts"]) } @@ -167,14 +170,14 @@ func TestCreateSchedule_DeadLetterConfigRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-dlq"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var dlc map[string]string - require.NoError(t, json.Unmarshal(target["DeadLetterConfig"], &dlc)) + require.NoError(t, json.Unmarshal(target["DeadLetterConfig"], &dlc, jsonx.V1())) assert.Equal(t, dlqARN, dlc["Arn"]) } @@ -224,14 +227,14 @@ func TestCreateSchedule_EventBridgeParametersRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-eb"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var ebParams map[string]string - require.NoError(t, json.Unmarshal(target["EventBridgeParameters"], &ebParams)) + require.NoError(t, json.Unmarshal(target["EventBridgeParameters"], &ebParams, jsonx.V1())) assert.Equal(t, "MyDetailType", ebParams["DetailType"]) assert.Equal(t, "com.example.app", ebParams["Source"]) } @@ -299,14 +302,14 @@ func TestCreateSchedule_KinesisParametersRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-kinesis"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var kp map[string]string - require.NoError(t, json.Unmarshal(target["KinesisParameters"], &kp)) + require.NoError(t, json.Unmarshal(target["KinesisParameters"], &kp, jsonx.V1())) assert.Equal(t, "my-partition-key", kp["PartitionKey"]) } @@ -357,14 +360,14 @@ func TestCreateSchedule_SqsParametersMessageGroupIdRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-fifo"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var sqsP map[string]string - require.NoError(t, json.Unmarshal(target["SqsParameters"], &sqsP)) + require.NoError(t, json.Unmarshal(target["SqsParameters"], &sqsP, jsonx.V1())) assert.Equal(t, "grp-1", sqsP["MessageGroupId"]) } @@ -395,17 +398,17 @@ func TestCreateSchedule_SageMakerPipelineParametersRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-sm"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) - var smParams map[string]json.RawMessage - require.NoError(t, json.Unmarshal(target["SageMakerPipelineParameters"], &smParams)) + var smParams map[string]jsontext.Value + require.NoError(t, json.Unmarshal(target["SageMakerPipelineParameters"], &smParams, jsonx.V1())) var paramList []map[string]string - require.NoError(t, json.Unmarshal(smParams["PipelineParameterList"], ¶mList)) + require.NoError(t, json.Unmarshal(smParams["PipelineParameterList"], ¶mList, jsonx.V1())) require.Len(t, paramList, 2) assert.Equal(t, "param1", paramList[0]["Name"]) assert.Equal(t, "val1", paramList[0]["Value"]) @@ -436,21 +439,21 @@ func TestCreateSchedule_EcsParametersRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-ecs"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) - var ecsP map[string]json.RawMessage - require.NoError(t, json.Unmarshal(target["EcsParameters"], &ecsP)) + var ecsP map[string]jsontext.Value + require.NoError(t, json.Unmarshal(target["EcsParameters"], &ecsP, jsonx.V1())) var tdArn string - require.NoError(t, json.Unmarshal(ecsP["TaskDefinitionArn"], &tdArn)) + require.NoError(t, json.Unmarshal(ecsP["TaskDefinitionArn"], &tdArn, jsonx.V1())) assert.Equal(t, "arn:aws:ecs:us-east-1:000000000000:task-definition/my-td:1", tdArn) var launchType string - require.NoError(t, json.Unmarshal(ecsP["LaunchType"], &launchType)) + require.NoError(t, json.Unmarshal(ecsP["LaunchType"], &launchType, jsonx.V1())) assert.Equal(t, "FARGATE", launchType) } @@ -519,7 +522,7 @@ func TestCreateSchedule_EcsParametersNetworkConfigurationRoundtrip(t *testing.T) } `json:"EcsParameters"` } `json:"Target"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) cfg := out.Target.EcsParameters.NetworkConfiguration.AwsvpcConfiguration assert.Equal(t, []string{"subnet-aaa", "subnet-bbb"}, cfg.Subnets) @@ -564,7 +567,7 @@ func TestCreateSchedule_EcsParametersCapacityProviderStrategyRoundtrip(t *testin } `json:"EcsParameters"` } `json:"Target"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) strategy := out.Target.EcsParameters.CapacityProviderStrategy require.Len(t, strategy, 2) @@ -616,7 +619,7 @@ func TestCreateSchedule_EcsParametersPlacementConstraintsRoundtrip(t *testing.T) } `json:"EcsParameters"` } `json:"Target"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) constraints := out.Target.EcsParameters.PlacementConstraints require.Len(t, constraints, 1) @@ -666,7 +669,7 @@ func TestCreateSchedule_EcsParametersTaskTagsRoundtrip(t *testing.T) { } `json:"EcsParameters"` } `json:"Target"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) ecsTags := out.Target.EcsParameters.Tags require.Len(t, ecsTags, 2) @@ -704,11 +707,11 @@ func TestCreateSchedule_InputTransformerNotEchoed(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "sched-transformer"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) _, present := target["InputTransformer"] assert.False(t, present, "InputTransformer is not a real Scheduler Target member and must not be echoed back") @@ -753,13 +756,13 @@ func TestFullTarget_UpdateRoundTrip(t *testing.T) { get := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "full-target"}) require.Equal(t, http.StatusOK, get.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(get.Body.Bytes(), &out, jsonx.V1())) - var target map[string]json.RawMessage - require.NoError(t, json.Unmarshal(out["Target"], &target)) + var target map[string]jsontext.Value + require.NoError(t, json.Unmarshal(out["Target"], &target, jsonx.V1())) var kp map[string]string - require.NoError(t, json.Unmarshal(target["KinesisParameters"], &kp)) + require.NoError(t, json.Unmarshal(target["KinesisParameters"], &kp, jsonx.V1())) assert.Equal(t, "updated-key", kp["PartitionKey"]) } diff --git a/services/scheduler/schedules_test.go b/services/scheduler/schedules_test.go index 6bc19fb18d..da5443a977 100644 --- a/services/scheduler/schedules_test.go +++ b/services/scheduler/schedules_test.go @@ -2,7 +2,8 @@ package scheduler_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "net/http" "strings" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/scheduler" ) @@ -73,7 +75,7 @@ func TestSchedulerHandler_CreateSchedule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ScheduleArn"], "arn:aws:scheduler:") } @@ -114,7 +116,7 @@ func TestSchedulerHandler_CreateScheduleDefaultState(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ENABLED", resp["State"]) } @@ -139,7 +141,7 @@ func TestCreateSchedule_DefaultStateEnabled(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ENABLED", resp["State"]) } @@ -404,7 +406,7 @@ func TestCreateSchedule_ScheduleExpression_Validation(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -805,7 +807,7 @@ func TestCreateSchedule_FlexibleModeRequiresMaximumWindowInMinutes(t *testing.T) if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) } }) @@ -835,7 +837,7 @@ func TestCreateSchedule_FlexibleWindowRoundtrip(t *testing.T) { MaximumWindowInMinutes int `json:"MaximumWindowInMinutes"` } `json:"FlexibleTimeWindow"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "FLEXIBLE", out.FlexibleTimeWindow.Mode) assert.Equal(t, 20, out.FlexibleTimeWindow.MaximumWindowInMinutes) } @@ -864,7 +866,7 @@ func TestCreateSchedule_FlexibleTimeWindowMaximumWindowInMinutes(t *testing.T) { MaximumWindowInMinutes int `json:"MaximumWindowInMinutes"` } `json:"FlexibleTimeWindow"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "FLEXIBLE", out.FlexibleTimeWindow.Mode) assert.Equal(t, 15, out.FlexibleTimeWindow.MaximumWindowInMinutes) } @@ -884,7 +886,7 @@ func TestSchedulerHandler_GetSchedule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "my-schedule", resp["Name"]) assert.Equal(t, "rate(5 minutes)", resp["ScheduleExpression"]) assert.Contains(t, resp, "Target") @@ -913,7 +915,7 @@ func TestGetSchedule_ReturnsGroupNameAndDates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "mygroup", resp["GroupName"]) assert.Equal(t, "test description", resp["Description"]) @@ -938,7 +940,7 @@ func TestGetSchedule_ReturnsARNWithGroupName(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) assert.Contains(t, createResp["ScheduleArn"], "schedule/my-group/grouped-sched") } @@ -968,18 +970,18 @@ func TestGetSchedule_TimestampsAreEpochSeconds(t *testing.T) { rec2 := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "ts-schedule"}) require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) // CreationDate must be a JSON number (float64), not a string. var creationDate float64 - require.NoError(t, json.Unmarshal(out["CreationDate"], &creationDate), "CreationDate must be a number") + require.NoError(t, json.Unmarshal(out["CreationDate"], &creationDate, jsonx.V1()), "CreationDate must be a number") assert.Greater(t, creationDate, float64(0), "CreationDate must be a positive epoch value") var lastModDate float64 require.NoError( t, - json.Unmarshal(out["LastModificationDate"], &lastModDate), + json.Unmarshal(out["LastModificationDate"], &lastModDate, jsonx.V1()), "LastModificationDate must be a number", ) assert.GreaterOrEqual(t, lastModDate, creationDate) @@ -1006,11 +1008,11 @@ func TestCreateSchedule_EpochSecondsConvertBack(t *testing.T) { rec2 := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "epoch-test"}) require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) var startDate float64 - require.NoError(t, json.Unmarshal(out["StartDate"], &startDate)) + require.NoError(t, json.Unmarshal(out["StartDate"], &startDate, jsonx.V1())) // The stored epoch should round-trip back to the same second. assert.InDelta(t, epoch, startDate, 1.0) } @@ -1037,7 +1039,7 @@ func TestCreateSchedule_ActionAfterCompletion(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "DELETE", out["ActionAfterCompletion"]) } @@ -1061,7 +1063,7 @@ func TestCreateSchedule_KmsKeyArn(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, kmsARN, out["KmsKeyArn"]) } @@ -1086,8 +1088,8 @@ func TestCreateSchedule_StartDateEndDate(t *testing.T) { rec2 := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "dated-sched"}) require.Equal(t, http.StatusOK, rec2.Code) - var out map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + var out map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) _, hasStart := out["StartDate"] _, hasEnd := out["EndDate"] @@ -1113,7 +1115,7 @@ func TestCreateSchedule_ScheduleExpressionTimezone(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "America/New_York", resp["ScheduleExpressionTimezone"]) } @@ -1152,7 +1154,7 @@ func TestCreateSchedule_ScheduleExpressionTimezone_Validation(t *testing.T) { if tt.wantCode != http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } }) @@ -1183,7 +1185,7 @@ func TestUpdateSchedule_ScheduleExpressionTimezone_Validation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -1261,13 +1263,13 @@ func TestSchedulerHandler_UpdateSchedule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["ScheduleArn"], "arn:aws:scheduler:") // Verify the update getRec := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "my-schedule"}) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "rate(10 minutes)", getResp["ScheduleExpression"]) assert.Equal(t, "DISABLED", getResp["State"]) } @@ -1355,7 +1357,7 @@ func TestUpdateSchedule_WithActionAfterCompletion(t *testing.T) { rec2 := doSchedulerRequest(t, h, "GetSchedule", map[string]any{"Name": "upd-aac"}) var out map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "NONE", out["ActionAfterCompletion"]) } @@ -1440,7 +1442,7 @@ func TestUpdateSchedule_RequiredFieldValidation(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) } }) @@ -1490,7 +1492,7 @@ func TestUpdateSchedule_ScheduleExpression_SemanticValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) }) } @@ -1523,7 +1525,7 @@ func TestUpdateSchedule_DoesNotBlankFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) assert.Equal(t, "rate(10 minutes)", out["ScheduleExpression"]) @@ -1582,7 +1584,7 @@ func TestUpdateSchedule_ClearsOmittedOptionalFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.NewDecoder(getRec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(getRec.Body), &out, jsonx.V1())) assert.NotContains(t, out, tc.field, "%s should be cleared after an update that omits it", tc.field) }) diff --git a/services/scheduler/tags_test.go b/services/scheduler/tags_test.go index 21f0569cef..0acd8ce1e7 100644 --- a/services/scheduler/tags_test.go +++ b/services/scheduler/tags_test.go @@ -2,7 +2,7 @@ package scheduler_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/scheduler" ) @@ -30,7 +31,7 @@ func TestSchedulerHandler_TagResource(t *testing.T) { "FlexibleTimeWindow": map[string]any{"Mode": "OFF"}, }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["ScheduleArn"] rec := doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -56,7 +57,7 @@ func TestSchedulerHandler_ListTagsForResource(t *testing.T) { "FlexibleTimeWindow": map[string]any{"Mode": "OFF"}, }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn := createResp["ScheduleArn"] doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -68,7 +69,7 @@ func TestSchedulerHandler_ListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Tags") tags := wireTagsToMap(t, resp["Tags"]) assert.Equal(t, "prod", tags["env"]) @@ -88,7 +89,7 @@ func TestTagResource_AndListTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) schedARN := createResp["ScheduleArn"] tagRec := doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -101,7 +102,7 @@ func TestTagResource_AndListTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := wireTagsToMap(t, tagsResp["Tags"]) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -178,7 +179,7 @@ func TestSchedulerHandler_UntagResource(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) resourceARN = createResp["ScheduleArn"] if len(tt.setupTags) > 0 { @@ -201,7 +202,7 @@ func TestSchedulerHandler_UntagResource(t *testing.T) { listRec := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": resourceARN}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) remaining := wireTagsToMap(t, listResp["Tags"]) for _, key := range tt.wantRemoved { assert.NotContains(t, remaining, key) @@ -233,7 +234,7 @@ func TestUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := wireTagsToMap(t, tagsResp["Tags"]) assert.NotContains(t, tags, "k1") assert.Contains(t, tags, "k2") @@ -252,7 +253,7 @@ func TestSchedulerHandler_UntagResource_ScheduleGroup(t *testing.T) { getRec := doSchedulerRequest(t, h, "GetScheduleGroup", map[string]any{"Name": "tagged-group"}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) groupARN, _ := getResp["Arn"].(string) require.NotEmpty(t, groupARN) @@ -265,7 +266,7 @@ func TestSchedulerHandler_UntagResource_ScheduleGroup(t *testing.T) { listRec := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": groupARN}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) remaining := wireTagsToMap(t, listResp["Tags"]) assert.NotContains(t, remaining, "env") assert.Contains(t, remaining, "team") @@ -279,7 +280,7 @@ func TestSchedulerHandler_TagResource_ScheduleGroup(t *testing.T) { doSchedulerRequest(t, h, "CreateScheduleGroup", map[string]any{"Name": "tag-group"}) getRec := doSchedulerRequest(t, h, "GetScheduleGroup", map[string]any{"Name": "tag-group"}) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) groupARN, _ := getResp["Arn"].(string) rec := doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -291,7 +292,7 @@ func TestSchedulerHandler_TagResource_ScheduleGroup(t *testing.T) { listRec := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": groupARN}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tagsMap := wireTagsToMap(t, listResp["Tags"]) assert.Equal(t, "team-a", tagsMap["owner"]) } @@ -312,7 +313,7 @@ func TestRESTTagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) schedARN := createOut["ScheduleArn"] require.NotEmpty(t, schedARN) @@ -327,7 +328,7 @@ func TestRESTTagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut, jsonx.V1())) tags := wireTagsToMap(t, tagsOut["Tags"]) assert.Equal(t, "prod", tags["env"]) assert.Equal(t, "platform", tags["team"]) @@ -349,7 +350,7 @@ func TestRESTListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) schedARN := createOut["ScheduleArn"] // Tag the resource first via the standard operation. @@ -362,7 +363,7 @@ func TestRESTListTagsForResource(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &tagsOut, jsonx.V1())) tags := wireTagsToMap(t, tagsOut["Tags"]) assert.Equal(t, "val1", tags["key1"]) } @@ -382,7 +383,7 @@ func TestRESTUntagResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) schedARN := createOut["ScheduleArn"] _ = doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -397,7 +398,7 @@ func TestRESTUntagResource(t *testing.T) { rec3 := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": schedARN}) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut, jsonx.V1())) tags := wireTagsToMap(t, tagsOut["Tags"]) assert.NotContains(t, tags, "key1") assert.Equal(t, "val2", tags["key2"]) @@ -422,7 +423,7 @@ func TestRESTUntagResourceMultipleTagKeys(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) schedARN := createOut["ScheduleArn"] _ = doSchedulerRequest(t, h, "TagResource", map[string]any{ @@ -440,7 +441,7 @@ func TestRESTUntagResourceMultipleTagKeys(t *testing.T) { rec3 := doSchedulerRequest(t, h, "ListTagsForResource", map[string]any{"ResourceArn": schedARN}) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &tagsOut, jsonx.V1())) tags := wireTagsToMap(t, tagsOut["Tags"]) assert.NotContains(t, tags, "key1") assert.NotContains(t, tags, "key2") diff --git a/services/scheduler/whitebox_test.go b/services/scheduler/whitebox_test.go index 07263154cb..e85f7045fe 100644 --- a/services/scheduler/whitebox_test.go +++ b/services/scheduler/whitebox_test.go @@ -3,7 +3,7 @@ package scheduler import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,12 +12,14 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doWhiteboxRequest(t *testing.T, h *Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() diff --git a/services/secretsmanager/batchgetsecretvalue_test.go b/services/secretsmanager/batchgetsecretvalue_test.go index 65768f0536..369f892d18 100644 --- a/services/secretsmanager/batchgetsecretvalue_test.go +++ b/services/secretsmanager/batchgetsecretvalue_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -334,7 +335,7 @@ func TestBatchGetSecretValue_SecretIDListTooLong_HTTP(t *testing.T) { if tt.wantType != "" { var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp.Type) } }) @@ -358,7 +359,7 @@ func TestBatchGetSecretValue_SecretIdListAndFiltersRejected(t *testing.T) { "BatchGetSecretValue with both SecretIdList and Filters must return 400; body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", resp["__type"]) } @@ -386,7 +387,7 @@ func TestBatchGetSecretValue_FilterUsesPrefix(t *testing.T) { var out struct { SecretValues []map[string]any `json:"SecretValues"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecretValues, 2, "real AWS: BatchGetSecretValue filter uses prefix matching; body: %s", rec.Body.String()) } @@ -426,7 +427,7 @@ func TestBatchGetSecretValue_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.BatchGetSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecretValues, 2) assert.Empty(t, out.Errors) }, @@ -446,7 +447,7 @@ func TestBatchGetSecretValue_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.BatchGetSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecretValues, 1) assert.Len(t, out.Errors, 1) assert.Equal(t, "ResourceNotFoundException", out.Errors[0].ErrorCode) @@ -473,7 +474,7 @@ func TestBatchGetSecretValue_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.BatchGetSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecretValues, 2) }, }, diff --git a/services/secretsmanager/cancelrotatesecret_test.go b/services/secretsmanager/cancelrotatesecret_test.go index dcd207842b..4c37034866 100644 --- a/services/secretsmanager/cancelrotatesecret_test.go +++ b/services/secretsmanager/cancelrotatesecret_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -128,7 +129,7 @@ func TestCancelRotateSecret_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.CancelRotateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "cancel-rot", out.Name) assert.NotEmpty(t, out.ARN) }, diff --git a/services/secretsmanager/createsecret_test.go b/services/secretsmanager/createsecret_test.go index f038db032a..acc1ad7c4c 100644 --- a/services/secretsmanager/createsecret_test.go +++ b/services/secretsmanager/createsecret_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -100,7 +101,7 @@ func TestCreateSecret_NameAWSPrefixHTTP(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) } @@ -227,7 +228,7 @@ func TestCreateSecret_DuplicateHTTPStatus(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceExistsException", errResp.Type) } @@ -459,7 +460,7 @@ func TestCreateSecret_ReplicaRegionsAddedIsReadableInReplicaRegion(t *testing.T) require.Equal(t, http.StatusOK, getRec.Code) var out secretsmanager.GetSecretValueOutput - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "secret-value", out.SecretString) } @@ -513,12 +514,12 @@ func TestCreateSecret_ReplicaRegionsAddedHTTP(t *testing.T) { "AddReplicaRegions": []map[string]string{ {"Region": "eu-central-1"}, }, - }) + }, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.CreateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ReplicationStatus, 1) assert.Equal(t, "eu-central-1", out.ReplicationStatus[0].Region) } @@ -540,7 +541,7 @@ func TestCreateSecret_ReplicaRegionsAddedMultipleHTTP(t *testing.T) { {"Region": "eu-north-1"}, {"Region": "ap-east-1"}, }, - }) + }, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -548,7 +549,7 @@ func TestCreateSecret_ReplicaRegionsAddedMultipleHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Len(t, desc.ReplicationStatus, 3) } @@ -801,7 +802,7 @@ func TestCreateSecret_DeletedNameCollision_HTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) }) } @@ -1007,7 +1008,7 @@ func TestCreateSecret_NameValidation(t *testing.T) { t.Cleanup(b.StopRotationScheduler) h := secretsmanager.NewHandler(b) - body, _ := json.Marshal(map[string]string{"Name": tt.secretName, "SecretString": "v"}) + body, _ := json.Marshal(map[string]string{"Name": tt.secretName, "SecretString": "v"}, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) }) @@ -1033,7 +1034,7 @@ func TestCreateSecret_CreateDescribeRoundtrip(t *testing.T) { }, } - body, _ := json.Marshal(createBody) + body, _ := json.Marshal(createBody, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -1041,7 +1042,7 @@ func TestCreateSecret_CreateDescribeRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "roundtrip/secret", desc.Name) assert.Equal(t, "roundtrip test", desc.Description) assert.Equal(t, "alias/roundtrip", desc.KmsKeyID) diff --git a/services/secretsmanager/deletesecret_test.go b/services/secretsmanager/deletesecret_test.go index 8e2144fb1b..f3f9436d5f 100644 --- a/services/secretsmanager/deletesecret_test.go +++ b/services/secretsmanager/deletesecret_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -283,7 +284,7 @@ func TestDeleteSecret_ForceAndRecoveryWindowHTTPErrorType(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) assert.Equal(t, "InvalidParameterException", rec.Header().Get("X-Amzn-Errortype"), "error response must echo the error code in X-Amzn-Errortype") @@ -501,7 +502,7 @@ func TestDeleteSecret_RecoveryWindowInDaysHTTP(t *testing.T) { // Create the secret(s) needed for the test. for _, name := range []string{"recover-test", "recover-test2"} { - body, _ := json.Marshal(map[string]string{"Name": name, "SecretString": "v"}) + body, _ := json.Marshal(map[string]string{"Name": name, "SecretString": "v"}, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) } @@ -511,7 +512,7 @@ func TestDeleteSecret_RecoveryWindowInDaysHTTP(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.checkForward != nil { var out secretsmanager.DeleteSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tt.checkForward(t, out.DeletionDate) } }) diff --git a/services/secretsmanager/describesecret_test.go b/services/secretsmanager/describesecret_test.go index c64a0540cf..fc1369a959 100644 --- a/services/secretsmanager/describesecret_test.go +++ b/services/secretsmanager/describesecret_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -251,7 +252,7 @@ func TestDescribeSecret_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "alias/http-key", out.KmsKeyID) } @@ -282,7 +283,7 @@ func TestDescribeSecret_HasAllFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "full-meta", desc.Name) assert.Equal(t, "full metadata", desc.Description) assert.Equal(t, "alias/mykey", desc.KmsKeyID) @@ -306,7 +307,7 @@ func TestDescribeSecret_HasCreatedDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.NotNil(t, desc.CreatedDate) assert.Greater(t, *desc.CreatedDate, float64(0)) } diff --git a/services/secretsmanager/explicit_empty.go b/services/secretsmanager/explicit_empty.go index 706cfb0b1f..40843d9c2e 100644 --- a/services/secretsmanager/explicit_empty.go +++ b/services/secretsmanager/explicit_empty.go @@ -1,15 +1,18 @@ package secretsmanager import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // rejectExplicitEmpty fails when any named member is present as "": the SDK // models them as *string with a min length, so omitted keeps and "" is invalid. func rejectExplicitEmpty(data []byte, op string, members ...string) error { - var probe map[string]json.RawMessage - if err := json.Unmarshal(data, &probe); err != nil { + var probe map[string]jsontext.Value + if err := json.Unmarshal(data, &probe, jsonx.V1()); err != nil { return err } @@ -32,7 +35,7 @@ func (in *PutSecretValueInput) UnmarshalJSON(data []byte) error { return err } - return json.Unmarshal(data, (*putSecretValueInputAlias)(in)) + return json.Unmarshal(data, (*putSecretValueInputAlias)(in), jsonx.V1()) } type updateSecretInputAlias UpdateSecretInput @@ -43,7 +46,7 @@ func (in *UpdateSecretInput) UnmarshalJSON(data []byte) error { return err } - return json.Unmarshal(data, (*updateSecretInputAlias)(in)) + return json.Unmarshal(data, (*updateSecretInputAlias)(in), jsonx.V1()) } type updateSecretVersionStageInputAlias UpdateSecretVersionStageInput @@ -56,5 +59,5 @@ func (in *UpdateSecretVersionStageInput) UnmarshalJSON(data []byte) error { return err } - return json.Unmarshal(data, (*updateSecretVersionStageInputAlias)(in)) + return json.Unmarshal(data, (*updateSecretVersionStageInputAlias)(in), jsonx.V1()) } diff --git a/services/secretsmanager/getrandompassword_test.go b/services/secretsmanager/getrandompassword_test.go index 079e84e981..cb26545e4c 100644 --- a/services/secretsmanager/getrandompassword_test.go +++ b/services/secretsmanager/getrandompassword_test.go @@ -1,7 +1,7 @@ package secretsmanager_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -381,7 +382,7 @@ func TestGetRandomPassword_Handler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.GetRandomPasswordOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, []rune(out.RandomPassword), 32) }, }, @@ -392,7 +393,7 @@ func TestGetRandomPassword_Handler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.GetRandomPasswordOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, []rune(out.RandomPassword), 20) }, }, @@ -403,7 +404,7 @@ func TestGetRandomPassword_Handler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) }, }, @@ -414,7 +415,7 @@ func TestGetRandomPassword_Handler(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.GetRandomPasswordOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, []rune(out.RandomPassword), 50) for _, ch := range out.RandomPassword { assert.NotContains(t, "0123456789", string(ch)) @@ -497,7 +498,7 @@ func TestGetRandomPassword_RandomRunesOptimized(t *testing.T) { RandomPassword string `json:"RandomPassword"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.RandomPassword), tt.minLen) }) } diff --git a/services/secretsmanager/getsecretvalue_test.go b/services/secretsmanager/getsecretvalue_test.go index 9437c72ec4..bc191863a1 100644 --- a/services/secretsmanager/getsecretvalue_test.go +++ b/services/secretsmanager/getsecretvalue_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -38,7 +39,7 @@ func TestGetSecretValue_NotFoundHTTP(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type) } @@ -74,7 +75,7 @@ func TestGetSecretValue_DeletedHTTPStatus(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errResp.Type) } @@ -230,12 +231,12 @@ func TestGetSecretValue_VersionMismatchHTTPErrorType(t *testing.T) { "SecretId": "mismatch-http", "VersionId": "v1", "VersionStage": secretsmanager.StagingLabelPrevious, - }) + }, jsonx.V1()) rec = doR1Request(t, h, "secretsmanager.GetSecretValue", string(body)) require.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type, "HTTP error body must carry ResourceNotFoundException") } @@ -371,7 +372,7 @@ func TestGetSecretValue_LastAccessedDateTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc1 secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc1, jsonx.V1())) assert.Nil(t, desc1.LastAccessedDate) // GetSecretValue should update LastAccessedDate. @@ -383,7 +384,7 @@ func TestGetSecretValue_LastAccessedDateTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc2 secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc2, jsonx.V1())) require.NotNil(t, desc2.LastAccessedDate) // The LastAccessedDate should be today (day-granularity as AWS does). accessTime := time.Unix(int64(*desc2.LastAccessedDate), 0).UTC() diff --git a/services/secretsmanager/handler.go b/services/secretsmanager/handler.go index babd9c8b0e..c14933502b 100644 --- a/services/secretsmanager/handler.go +++ b/services/secretsmanager/handler.go @@ -2,7 +2,7 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/worker" @@ -188,7 +189,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -226,7 +227,7 @@ type smActionFn func(ctx context.Context, region string, body []byte) (any, erro func decodeAction[I any](fn func(ctx context.Context, input *I) (any, error)) smActionFn { return func(ctx context.Context, _ string, body []byte) (any, error) { var input I - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } @@ -250,7 +251,7 @@ func (h *Handler) dispatch(ctx context.Context, r *http.Request, action string, return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a structured error response for a Secrets Manager operation failure. @@ -307,7 +308,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin payload, _ := json.Marshal(ErrorResponse{ Type: errorType, Message: awserr.StripCode(errorType, reqErr.Error()), - }) + }, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/secretsmanager/handler_dispatch_test.go b/services/secretsmanager/handler_dispatch_test.go index 4f4a0ce3e9..bf93794c67 100644 --- a/services/secretsmanager/handler_dispatch_test.go +++ b/services/secretsmanager/handler_dispatch_test.go @@ -7,7 +7,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -47,7 +48,7 @@ func TestHandler_Dispatch(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.CreateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "test-secret", out.Name) }, }, @@ -66,7 +67,7 @@ func TestHandler_Dispatch(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.GetSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "the-value", out.SecretString) }, }, @@ -78,7 +79,7 @@ func TestHandler_Dispatch(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "UnknownOperationException", errResp.Type) }, }, @@ -96,7 +97,7 @@ func TestHandler_Dispatch(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.Contains(t, ops, "CreateSecret") }, }, @@ -188,7 +189,7 @@ func TestHandler_FullCycle(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var listOut secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) assert.Len(t, listOut.SecretList, 1) // UpdateSecret @@ -402,7 +403,7 @@ func TestHandler_ErrorCases(t *testing.T) { assert.Equal(t, tt.expectedStatus, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.expectedErrTyp, errResp.Type) }) } @@ -762,7 +763,7 @@ func TestHandler_ErrorResponseAmznErrortypeHeader(t *testing.T) { require.GreaterOrEqual(t, rec.Code, http.StatusBadRequest) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp.Type, "body __type") assert.Equal(t, tt.wantType, rec.Header().Get("X-Amzn-Errortype"), "X-Amzn-Errortype header must equal body __type") diff --git a/services/secretsmanager/handler_random_password.go b/services/secretsmanager/handler_random_password.go index 95a71454e0..dd0c4d1559 100644 --- a/services/secretsmanager/handler_random_password.go +++ b/services/secretsmanager/handler_random_password.go @@ -2,14 +2,16 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) smRandomPasswordActions() map[string]smActionFn { return map[string]smActionFn{ "GetRandomPassword": func(_ context.Context, _ string, b []byte) (any, error) { var input GetRandomPasswordInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/secretsmanager/handler_rotation.go b/services/secretsmanager/handler_rotation.go index f4f2522862..46c6b0fe3a 100644 --- a/services/secretsmanager/handler_rotation.go +++ b/services/secretsmanager/handler_rotation.go @@ -2,10 +2,11 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -13,7 +14,7 @@ func (h *Handler) smRotationActions() map[string]smActionFn { return map[string]smActionFn{ "RotateSecret": func(ctx context.Context, region string, b []byte) (any, error) { var input RotateSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -21,7 +22,7 @@ func (h *Handler) smRotationActions() map[string]smActionFn { }, "CancelRotateSecret": func(ctx context.Context, _ string, b []byte) (any, error) { var input CancelRotateSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -57,7 +58,7 @@ func buildRotationStepEvent(secretID, token, step string) ([]byte, error) { rotationEventSecretIDKey: secretID, rotationEventTokenKey: token, rotationEventStepKey: step, - }) + }, jsonx.V1()) } // extractFunctionNameFromARN extracts the bare function name from a Lambda ARN. diff --git a/services/secretsmanager/handler_secrets.go b/services/secretsmanager/handler_secrets.go index 668708a041..158521b6c2 100644 --- a/services/secretsmanager/handler_secrets.go +++ b/services/secretsmanager/handler_secrets.go @@ -2,8 +2,9 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/v2" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -11,7 +12,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { return map[string]smActionFn{ "CreateSecret": func(ctx context.Context, region string, b []byte) (any, error) { var input CreateSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } input.Region = region @@ -23,7 +24,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, "GetSecretValue": func(ctx context.Context, _ string, b []byte) (any, error) { var input GetSecretValueInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -31,7 +32,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, "PutSecretValue": func(ctx context.Context, _ string, b []byte) (any, error) { var input PutSecretValueInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -39,7 +40,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, "DeleteSecret": func(ctx context.Context, _ string, b []byte) (any, error) { var input DeleteSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -47,7 +48,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, opListSecrets: func(ctx context.Context, _ string, b []byte) (any, error) { var input ListSecretsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -55,7 +56,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, opDescribeSecret: func(ctx context.Context, _ string, b []byte) (any, error) { var input DescribeSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -63,7 +64,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, "UpdateSecret": func(ctx context.Context, _ string, b []byte) (any, error) { var input UpdateSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -71,7 +72,7 @@ func (h *Handler) smSecretsActions() map[string]smActionFn { }, "RestoreSecret": func(ctx context.Context, _ string, b []byte) (any, error) { var input RestoreSecretInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/secretsmanager/handler_tags.go b/services/secretsmanager/handler_tags.go index 7de93cc5d5..bb264275ad 100644 --- a/services/secretsmanager/handler_tags.go +++ b/services/secretsmanager/handler_tags.go @@ -2,9 +2,10 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -12,7 +13,7 @@ func (h *Handler) smTagActions() map[string]smActionFn { return map[string]smActionFn{ "TagResource": func(ctx context.Context, _ string, b []byte) (any, error) { var input TagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -26,7 +27,7 @@ func (h *Handler) smTagActions() map[string]smActionFn { }, "UntagResource": func(ctx context.Context, _ string, b []byte) (any, error) { var input UntagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/secretsmanager/listsecrets_test.go b/services/secretsmanager/listsecrets_test.go index 46554b236f..638ec99d30 100644 --- a/services/secretsmanager/listsecrets_test.go +++ b/services/secretsmanager/listsecrets_test.go @@ -5,7 +5,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -658,7 +659,7 @@ func TestListSecrets_OwningServiceHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.SecretList, "owning-service=rds must match neither om-1 nor om-2") } @@ -924,7 +925,7 @@ func TestListSecrets_FilterByNameHTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.SecretList, 2) } @@ -969,7 +970,7 @@ func TestListSecrets_SortOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.SecretList, 3) assert.Equal(t, "gamma", out.SecretList[0].Name) assert.Equal(t, "alpha", out.SecretList[2].Name) @@ -987,7 +988,7 @@ func TestListSecrets_FilterAll(t *testing.T) { "Name": "findme/secret", "Description": "unique-token", "SecretString": "v", - }) + }, jsonx.V1()) rec := doR1Request(t, h, "secretsmanager.CreateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -1001,7 +1002,7 @@ func TestListSecrets_FilterAll(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.SecretList, 1) assert.Equal(t, "findme/secret", out.SecretList[0].Name) } @@ -1025,7 +1026,7 @@ func TestListSecrets_EntryHasRotationFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.SecretList, 1) entry := out.SecretList[0] @@ -1056,7 +1057,7 @@ func TestListSecrets_EntryHasCreatedAndRotatedDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.SecretList, 1) assert.NotNil(t, out.SecretList[0].CreatedDate) assert.NotNil(t, out.SecretList[0].LastRotatedDate) diff --git a/services/secretsmanager/listsecretversionids_test.go b/services/secretsmanager/listsecretversionids_test.go index c959855911..b6c3357415 100644 --- a/services/secretsmanager/listsecretversionids_test.go +++ b/services/secretsmanager/listsecretversionids_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -280,7 +281,7 @@ func TestListSecretVersionIds_HTTPDispatchTable(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.ListSecretVersionIDsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "lsvi-secret", out.Name) assert.NotEmpty(t, out.Versions) }, @@ -481,7 +482,7 @@ func TestListSecretVersionIds_ViaHandler(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ListSecretVersionIDsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "handler-lsv", out.Name) assert.NotEmpty(t, out.Versions) } diff --git a/services/secretsmanager/persistence.go b/services/secretsmanager/persistence.go index a4b8acbd20..dfcaf33998 100644 --- a/services/secretsmanager/persistence.go +++ b/services/secretsmanager/persistence.go @@ -2,7 +2,7 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -67,7 +67,7 @@ func secretSnapshotKeyFn(ss *secretSnapshot) string { // from an incompatible (older or newer) build of this backend as though it // were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourcePolicies map[string]map[string]string `json:"resourcePolicies,omitempty"` ReplicationConfigs map[string]map[string][]ReplicationStatusType `json:"replicationConfigs,omitempty"` AccountID string `json:"accountID"` diff --git a/services/secretsmanager/putsecretvalue_test.go b/services/secretsmanager/putsecretvalue_test.go index 7df8364aab..6718342bb5 100644 --- a/services/secretsmanager/putsecretvalue_test.go +++ b/services/secretsmanager/putsecretvalue_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -486,7 +487,7 @@ func TestPutSecretValue_Idempotency(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out1 secretsmanager.PutSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1, jsonx.V1())) assert.Equal(t, token, out1.VersionID) // Second put with same token + content: should return the existing version. @@ -494,7 +495,7 @@ func TestPutSecretValue_Idempotency(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out2 secretsmanager.PutSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, token, out2.VersionID) assert.Equal(t, out1.VersionID, out2.VersionID) } diff --git a/services/secretsmanager/replica_write_guard_test.go b/services/secretsmanager/replica_write_guard_test.go index 71b97b2dbf..9690c4026a 100644 --- a/services/secretsmanager/replica_write_guard_test.go +++ b/services/secretsmanager/replica_write_guard_test.go @@ -13,13 +13,14 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -97,7 +98,7 @@ func TestReplicaWriteGuard_BlockedOnReplica(t *testing.T) { var out struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "InvalidRequestException", out.Type) }) } diff --git a/services/secretsmanager/replication_test.go b/services/secretsmanager/replication_test.go index 1f9fc790f4..657b649076 100644 --- a/services/secretsmanager/replication_test.go +++ b/services/secretsmanager/replication_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -180,7 +181,7 @@ func TestReplication_ReplicaSecretReadableInReplicaRegion(t *testing.T) { "replica region must serve the replicated secret, got: %s", getRec.Body.String()) var getOut secretsmanager.GetSecretValueOutput - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) assert.Equal(t, "replicated-value", getOut.SecretString) descRec := doSMRequestInRegion(t, h, "us-west-2", "secretsmanager.DescribeSecret", @@ -188,7 +189,7 @@ func TestReplication_ReplicaSecretReadableInReplicaRegion(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, secretsmanager.MockRegion, descOut.PrimaryRegion) assert.Contains(t, descOut.ARN, "us-west-2") } @@ -251,7 +252,7 @@ func TestReplication_Operations(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.ReplicateSecretToRegionsOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.ARN) require.Len(t, out.ReplicationStatus, 1) assert.Equal(t, "us-west-2", out.ReplicationStatus[0].Region) @@ -279,7 +280,7 @@ func TestReplication_Operations(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.RemoveRegionsFromReplicationOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.ReplicationStatus, 1) assert.Equal(t, "ap-east-1", out.ReplicationStatus[0].Region) }, @@ -305,7 +306,7 @@ func TestReplication_Operations(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.StopReplicationToReplicaOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.ARN) }, }, @@ -474,7 +475,7 @@ func TestReplicateSecretToRegions_ExistingRegionErrorType_WireCode(t *testing.T) var body struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidRequestException", body.Type) assert.NotEqual(t, "ResourceExistsException", body.Type) } diff --git a/services/secretsmanager/resource_policy.go b/services/secretsmanager/resource_policy.go index 728d6a941a..3d3d75e57e 100644 --- a/services/secretsmanager/resource_policy.go +++ b/services/secretsmanager/resource_policy.go @@ -2,9 +2,12 @@ package secretsmanager import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // GetResourcePolicy retrieves the resource-based policy for a secret. @@ -142,8 +145,8 @@ func (b *InMemoryBackend) ValidateResourcePolicy( } func validateResourcePolicyDocument(policyStr string) []PolicyValidationException { - var policy map[string]json.RawMessage - if err := json.Unmarshal([]byte(policyStr), &policy); err != nil { + var policy map[string]jsontext.Value + if err := json.Unmarshal([]byte(policyStr), &policy, jsonx.V1()); err != nil { return []PolicyValidationException{ { CheckName: "SyntaxCheck", @@ -172,25 +175,25 @@ func validateResourcePolicyDocument(policyStr string) []PolicyValidationExceptio } type policyStatement struct { - Effect string `json:"Effect"` - Principal json.RawMessage `json:"Principal"` - Condition json.RawMessage `json:"Condition"` + Effect string `json:"Effect"` + Principal jsontext.Value `json:"Principal"` + Condition jsontext.Value `json:"Condition"` } // policyAllowsPublicAccess reports whether an unconditioned Allow statement // grants a wildcard principal. func policyAllowsPublicAccess(policyStr string) bool { var doc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if json.Unmarshal([]byte(policyStr), &doc) != nil { + if json.Unmarshal([]byte(policyStr), &doc, jsonx.V1()) != nil { return false } var stmts []policyStatement - if json.Unmarshal(doc.Statement, &stmts) != nil { + if json.Unmarshal(doc.Statement, &stmts, jsonx.V1()) != nil { var one policyStatement - if json.Unmarshal(doc.Statement, &one) != nil { + if json.Unmarshal(doc.Statement, &one, jsonx.V1()) != nil { return false } @@ -206,14 +209,14 @@ func policyAllowsPublicAccess(policyStr string) bool { return false } -func principalIsWildcard(raw json.RawMessage) bool { +func principalIsWildcard(raw jsontext.Value) bool { var s string - if json.Unmarshal(raw, &s) == nil { + if json.Unmarshal(raw, &s, jsonx.V1()) == nil { return s == "*" } - var m map[string]json.RawMessage - if json.Unmarshal(raw, &m) != nil { + var m map[string]jsontext.Value + if json.Unmarshal(raw, &m, jsonx.V1()) != nil { return false } @@ -222,11 +225,11 @@ func principalIsWildcard(raw json.RawMessage) bool { return false } - if json.Unmarshal(aws, &s) == nil { + if json.Unmarshal(aws, &s, jsonx.V1()) == nil { return s == "*" } var list []string - return json.Unmarshal(aws, &list) == nil && slices.Contains(list, "*") + return json.Unmarshal(aws, &list, jsonx.V1()) == nil && slices.Contains(list, "*") } diff --git a/services/secretsmanager/resource_policy_test.go b/services/secretsmanager/resource_policy_test.go index 0c47c2156b..1e64e3a7ca 100644 --- a/services/secretsmanager/resource_policy_test.go +++ b/services/secretsmanager/resource_policy_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -360,7 +361,7 @@ func TestGetResourcePolicy_DeletedSecret_HTTP(t *testing.T) { assert.Equal(t, tt.expectedStatus, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.expectedType, errResp.Type) }) } @@ -398,7 +399,7 @@ func TestResourcePolicy_Cycle(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.PutResourcePolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "policy-secret", out.Name) assert.NotEmpty(t, out.ARN) }, @@ -424,7 +425,7 @@ func TestResourcePolicy_Cycle(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.GetResourcePolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "get-policy", out.Name) assert.Contains(t, out.ResourcePolicy, "2012-10-17") }, @@ -450,7 +451,7 @@ func TestResourcePolicy_Cycle(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.DeleteResourcePolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "del-policy", out.Name) }, }, @@ -690,7 +691,7 @@ func TestValidateResourcePolicy_HTTP(t *testing.T) { if tt.wantStatus == http.StatusOK { var out secretsmanager.ValidateResourcePolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantPassed, out.PolicyValidationPassed) if tt.wantErrCount > 0 { @@ -720,12 +721,12 @@ func TestValidateResourcePolicy_HTTP_SecretExists(t *testing.T) { body, _ := json.Marshal(map[string]string{ "SecretId": "validate-test", "ResourcePolicy": validPolicy, - }) + }, jsonx.V1()) rec = doR1Request(t, h, "secretsmanager.ValidateResourcePolicy", string(body)) require.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.ValidateResourcePolicyOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.True(t, out.PolicyValidationPassed) } diff --git a/services/secretsmanager/rotatesecret_test.go b/services/secretsmanager/rotatesecret_test.go index c12929cdf6..83d59c2a9c 100644 --- a/services/secretsmanager/rotatesecret_test.go +++ b/services/secretsmanager/rotatesecret_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -280,7 +281,7 @@ func TestRotateSecret_Backend(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.RotateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "rotate-secret", out.Name) assert.NotEmpty(t, out.VersionID) @@ -335,7 +336,7 @@ func TestRotateSecret_WithLambda(t *testing.T) { assert.Equal(t, "my-rotator", call.name) assert.Equal(t, "RequestResponse", call.invocationType) var event map[string]string - require.NoError(t, json.Unmarshal(call.payload, &event)) + require.NoError(t, json.Unmarshal(call.payload, &event, jsonx.V1())) assert.Equal(t, "lambda-rotate-secret", event["SecretId"]) assert.Equal(t, steps[i], event["Step"]) assert.NotEmpty(t, event["ClientRequestToken"]) @@ -394,7 +395,7 @@ func TestRotateSecret_OmittedARNUsesStoredLambda(t *testing.T) { assert.Equal(t, "my-rotator", call.name) assert.Equal(t, steps[i], func() string { var event map[string]string - require.NoError(t, json.Unmarshal(call.payload, &event)) + require.NoError(t, json.Unmarshal(call.payload, &event, jsonx.V1())) return event["Step"] }()) @@ -448,7 +449,7 @@ func TestRotateSecret_RotateImmediatelyFalseWithLambdaRunsTestSecretProbe(t *tes assert.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.RotateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out.VersionID, "no permanent version is created by a test probe") // Exactly one Lambda invocation: the testSecret step. @@ -456,7 +457,7 @@ func TestRotateSecret_RotateImmediatelyFalseWithLambdaRunsTestSecretProbe(t *tes assert.Equal(t, "probe-rotator", mock.calls[0].name) var event map[string]string - require.NoError(t, json.Unmarshal(mock.calls[0].payload, &event)) + require.NoError(t, json.Unmarshal(mock.calls[0].payload, &event, jsonx.V1())) assert.Equal(t, "probe-secret", event["SecretId"]) assert.Equal(t, "testSecret", event["Step"]) @@ -546,7 +547,7 @@ func TestRotateSecret_NoLambdaInvoker(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out secretsmanager.RotateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.VersionID) } @@ -668,7 +669,7 @@ func TestRotateSecret_InvalidDays(t *testing.T) { rotBody, _ := json.Marshal(map[string]any{ "SecretId": "days-validation", "RotationRules": map[string]any{"AutomaticallyAfterDays": tt.days}, - }) + }, jsonx.V1()) rotRec := doR1Request(t, h, "secretsmanager.RotateSecret", string(rotBody)) assert.Equal(t, http.StatusBadRequest, rotRec.Code) }) diff --git a/services/secretsmanager/secret_versions_test.go b/services/secretsmanager/secret_versions_test.go index b6172cadee..0dd30d7d57 100644 --- a/services/secretsmanager/secret_versions_test.go +++ b/services/secretsmanager/secret_versions_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -302,7 +303,7 @@ func TestSecretSizeValidation_Handler(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp.Type) } @@ -388,7 +389,7 @@ func TestPutSecretValueLabelRotation(t *testing.T) { putBody, _ := json.Marshal(map[string]string{ "SecretId": "rotate-test", "SecretString": "v2", - }) + }, jsonx.V1()) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(putBody))) req.Header.Set("X-Amz-Target", "secretsmanager.PutSecretValue") rec := httptest.NewRecorder() @@ -396,7 +397,7 @@ func TestPutSecretValueLabelRotation(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var putOut secretsmanager.PutSecretValueOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putOut, jsonx.V1())) assert.Contains(t, putOut.VersionStages, secretsmanager.StagingLabelCurrent) // Current should be v2 diff --git a/services/secretsmanager/updatesecret_test.go b/services/secretsmanager/updatesecret_test.go index 37653fd01e..b9d3a08ee5 100644 --- a/services/secretsmanager/updatesecret_test.go +++ b/services/secretsmanager/updatesecret_test.go @@ -6,7 +6,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -235,7 +236,7 @@ func TestUpdateSecret_KmsKeyID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var desc secretsmanager.DescribeSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "arn:aws:kms:us-east-1:123456789012:key/test-key-id", desc.KmsKeyID) } @@ -257,17 +258,17 @@ func TestUpdateSecret_ClientRequestTokenIdempotency(t *testing.T) { "SecretId": "update-idempotent", "SecretString": "updated-value", "ClientRequestToken": token, - }) + }, jsonx.V1()) rec = doR1Request(t, h, "secretsmanager.UpdateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) var out1 secretsmanager.UpdateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out1, jsonx.V1())) rec = doR1Request(t, h, "secretsmanager.UpdateSecret", string(body)) require.Equal(t, http.StatusOK, rec.Code) var out2 secretsmanager.UpdateSecretOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out2, jsonx.V1())) assert.Equal(t, out1.VersionID, out2.VersionID) } diff --git a/services/secretsmanager/updatesecretversionstage_test.go b/services/secretsmanager/updatesecretversionstage_test.go index 5614330ad7..0f9422bd9f 100644 --- a/services/secretsmanager/updatesecretversionstage_test.go +++ b/services/secretsmanager/updatesecretversionstage_test.go @@ -2,7 +2,7 @@ package secretsmanager_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/secretsmanager" ) @@ -515,7 +516,7 @@ func TestUpdateSecretVersionStage_CannotRemoveAWSCURRENT_HTTP(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var errResp secretsmanager.ErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) }) } @@ -560,7 +561,7 @@ func TestUpdateSecretVersionStage_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.UpdateSecretVersionStageOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "stage-secret", out.Name) assert.NotEmpty(t, out.ARN) }, @@ -592,7 +593,7 @@ func TestUpdateSecretVersionStage_HTTP(t *testing.T) { checkFn: func(t *testing.T, rec *httptest.ResponseRecorder) { t.Helper() var out secretsmanager.UpdateSecretVersionStageOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "stage-remove", out.Name) }, }, diff --git a/services/securityhub/action_targets_test.go b/services/securityhub/action_targets_test.go index 007002f241..8df6e34370 100644 --- a/services/securityhub/action_targets_test.go +++ b/services/securityhub/action_targets_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -27,7 +28,7 @@ func TestCreateActionTargetPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["ActionTargetArn"].(string) assert.NotEmpty(t, arn) @@ -51,7 +52,7 @@ func TestDescribeActionTargetsIsPOSTActionTargetsGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, _ := resp["ActionTargets"].([]any) assert.Len(t, targets, 1) @@ -74,7 +75,7 @@ func TestDeleteActionTargetIsDELETEActionTargetsArn(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arn, _ := createResp["ActionTargetArn"].(string) @@ -82,7 +83,7 @@ func TestDeleteActionTargetIsDELETEActionTargetsArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deletedArn, _ := resp["ActionTargetArn"].(string) assert.Equal(t, arn, deletedArn, "DeleteActionTarget must return the deleted ActionTargetArn") diff --git a/services/securityhub/aggregators_v2_test.go b/services/securityhub/aggregators_v2_test.go index 0a150de588..3439bc1b9a 100644 --- a/services/securityhub/aggregators_v2_test.go +++ b/services/securityhub/aggregators_v2_test.go @@ -1,12 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestAggregatorV2(t *testing.T) { @@ -90,7 +92,7 @@ func TestAggregatorV2(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -111,7 +113,7 @@ func TestHandler_UpdateAggregatorV2(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["AggregatorV2Arn"].(string) rec2 := doRequest(t, h, http.MethodPatch, "/aggregatorv2/update/"+arn, map[string]any{ @@ -120,7 +122,7 @@ func TestHandler_UpdateAggregatorV2(t *testing.T) { }) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) require.Equal(t, "SPECIFIED_REGIONS", resp2["RegionLinkingMode"]) }) @@ -135,7 +137,7 @@ func TestHandler_UpdateAggregatorV2(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["AggregatorV2Arn"].(string) rec2 := doRequest(t, h, http.MethodDelete, "/aggregatorv2/delete/"+arn, nil) @@ -164,7 +166,7 @@ func TestCreateAggregatorV2_LinkedRegionsAndTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["AggregatorV2Arn"].(string) require.NotEmpty(t, arn) @@ -175,7 +177,7 @@ func TestCreateAggregatorV2_LinkedRegionsAndTags(t *testing.T) { require.Equal(t, http.StatusOK, tagRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp, jsonx.V1())) tags, _ := tagResp["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) } diff --git a/services/securityhub/analytics_filters_test.go b/services/securityhub/analytics_filters_test.go index 27d323170b..b7a9319912 100644 --- a/services/securityhub/analytics_filters_test.go +++ b/services/securityhub/analytics_filters_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -48,7 +49,7 @@ func decodeMap(t *testing.T, body []byte) map[string]any { t.Helper() var out map[string]any - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out } diff --git a/services/securityhub/automation_rules_test.go b/services/securityhub/automation_rules_test.go index 94afdf48cf..22ed7faee3 100644 --- a/services/securityhub/automation_rules_test.go +++ b/services/securityhub/automation_rules_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -29,7 +30,7 @@ func TestCreateAutomationRulePath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ruleArn, _ := resp["RuleArn"].(string) assert.NotEmpty(t, ruleArn) @@ -55,7 +56,7 @@ func TestListAutomationRulesIsGETAutomationrulesList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, _ := resp["AutomationRulesMetadata"].([]any) assert.Len(t, rules, 1) @@ -81,7 +82,7 @@ func TestBatchGetAutomationRulesPath(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ruleArn, _ := createResp["RuleArn"].(string) rec := doRequest(t, h, http.MethodPost, "/automationrules/get", map[string]any{ @@ -91,7 +92,7 @@ func TestBatchGetAutomationRulesPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, _ := resp["Rules"].([]any) assert.Len(t, rules, 1) @@ -117,7 +118,7 @@ func TestBatchDeleteAutomationRulesPath(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ruleArn, _ := createResp["RuleArn"].(string) rec := doRequest(t, h, http.MethodPost, "/automationrules/delete", map[string]any{ @@ -127,7 +128,7 @@ func TestBatchDeleteAutomationRulesPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ProcessedAutomationRules") assert.Contains(t, resp, "UnprocessedAutomationRules") @@ -156,7 +157,7 @@ func TestCreateAutomationRule_ResponseFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["RuleArn"], "RuleArn must be present") assert.NotEmpty(t, resp["CreatedAt"], "CreatedAt must be present") assert.Equal(t, "my-rule", resp["RuleName"]) @@ -184,7 +185,7 @@ func TestCreateAutomationRule_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ruleArn, _ := resp["RuleArn"].(string) require.NotEmpty(t, ruleArn) @@ -192,7 +193,7 @@ func TestCreateAutomationRule_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, tagRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp, jsonx.V1())) tags, _ := tagResp["Tags"].(map[string]any) assert.Equal(t, "sec", tags["team"]) } @@ -215,7 +216,7 @@ func TestBatchUpdateAutomationRules_CriteriaAndActions(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ruleArn := createResp["RuleArn"].(string) // Update its Criteria and Actions @@ -240,7 +241,7 @@ func TestBatchUpdateAutomationRules_CriteriaAndActions(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules, _ := getResp["Rules"].([]any) require.Len(t, rules, 1) @@ -272,7 +273,7 @@ func TestUpdateAutomationRuleV2_ActionsApplied(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) identifier, _ := createResp["RuleId"].(string) require.NotEmpty(t, identifier) @@ -289,7 +290,7 @@ func TestUpdateAutomationRuleV2_ActionsApplied(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) actions, _ := updateResp["Actions"].([]any) require.Len(t, actions, 1, "Actions update must be applied, not silently dropped") @@ -378,7 +379,7 @@ func TestHandler_BatchUpdateAutomationRules(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) ruleArn, _ := createResp["RuleArn"].(string) require.NotEmpty(t, ruleArn) @@ -581,7 +582,7 @@ func TestAutomationRulesV2(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -654,7 +655,7 @@ func TestBatchImportFindings_AutomationRuleFires(t *testing.T) { var resp struct { Findings []map[string]any `json:"Findings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Findings, 1) severity, _ := resp.Findings[0]["Severity"].(map[string]any) diff --git a/services/securityhub/configuration_policies_test.go b/services/securityhub/configuration_policies_test.go index ea58727798..a7b36ca85c 100644 --- a/services/securityhub/configuration_policies_test.go +++ b/services/securityhub/configuration_policies_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -422,7 +423,7 @@ func TestConfigurationPolicy(t *testing.T) { rec := doRequest(t, h, s.method, s.path, substitutePolicyID(s.body, policyID)) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if id := s.check(t, rec.Code, resp); id != "" { policyID = id } @@ -478,7 +479,7 @@ func TestConfigurationPolicyAssociation_TargetTypeDerived(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID, _ := createResp["Id"].(string) require.NotEmpty(t, policyID) @@ -495,7 +496,7 @@ func TestConfigurationPolicyAssociation_TargetTypeDerived(t *testing.T) { require.Equal(t, http.StatusOK, assocRec.Code) var assocResp map[string]any - require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp)) + require.NoError(t, json.Unmarshal(assocRec.Body.Bytes(), &assocResp, jsonx.V1())) assert.Equal( t, tc.wantTargetType, @@ -517,7 +518,7 @@ func TestConfigurationPolicyAssociation_TargetTypeDerived(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tc.wantTargetType, getResp["TargetType"]) }) } @@ -541,7 +542,7 @@ func TestCreateConfigurationPolicy_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policyArn, _ := resp["Arn"].(string) require.NotEmpty(t, policyArn) @@ -549,7 +550,7 @@ func TestCreateConfigurationPolicy_TagsReachTagStore(t *testing.T) { require.Equal(t, http.StatusOK, tagRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(tagRec.Body.Bytes(), &tagResp, jsonx.V1())) tags, _ := tagResp["Tags"].(map[string]any) assert.Equal(t, "sec", tags["team"]) } diff --git a/services/securityhub/connectors_v2_test.go b/services/securityhub/connectors_v2_test.go index 109b44ebed..d591b2b36a 100644 --- a/services/securityhub/connectors_v2_test.go +++ b/services/securityhub/connectors_v2_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -148,7 +149,7 @@ func TestConnectorsV2(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -217,7 +218,7 @@ func TestTicketV2(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) connectorID, _ := created["ConnectorId"].(string) require.NotEmpty(t, connectorID) @@ -584,7 +585,7 @@ func TestConnectors(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/controls_test.go b/services/securityhub/controls_test.go index 0233babd92..c6cc0ba356 100644 --- a/services/securityhub/controls_test.go +++ b/services/securityhub/controls_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -23,7 +24,7 @@ func TestListSecurityControlDefinitionsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) defs, _ := resp["SecurityControlDefinitions"].([]any) assert.NotEmpty(t, defs) @@ -51,7 +52,7 @@ func TestGetSecurityControlDefinitionPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) def, _ := resp["SecurityControlDefinition"].(map[string]any) assert.Equal(t, "CloudTrail.1", def["SecurityControlId"]) @@ -70,7 +71,7 @@ func TestBatchGetSecurityControlsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) controls, _ := resp["SecurityControls"].([]any) assert.Len(t, controls, 2) diff --git a/services/securityhub/exportjobs_v2.go b/services/securityhub/exportjobs_v2.go index 13549c7258..184b5383c7 100644 --- a/services/securityhub/exportjobs_v2.go +++ b/services/securityhub/exportjobs_v2.go @@ -4,7 +4,8 @@ import ( "bytes" "context" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "path" @@ -20,6 +21,7 @@ import ( shtypes "github.com/aws/aws-sdk-go-v2/service/securityhub/types" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -195,9 +197,9 @@ func (b *InMemoryBackend) renderExportLocked(job *ExportJobV2) ([]byte, string, if job.Format == exportFormatOCSFJSON { var buf bytes.Buffer - enc := json.NewEncoder(&buf) + enc := jsontext.NewEncoder(&buf, jsonx.V1()) for _, f := range findings { - if err := enc.Encode(f); err != nil { + if err := json.MarshalEncode(enc, f); err != nil { return nil, "", fmt.Errorf("encode finding: %w", err) } } diff --git a/services/securityhub/finding_aggregators_test.go b/services/securityhub/finding_aggregators_test.go index a2c3c6bd54..657e5f0753 100644 --- a/services/securityhub/finding_aggregators_test.go +++ b/services/securityhub/finding_aggregators_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -157,7 +158,7 @@ func TestFindingAggregator(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/findings.go b/services/securityhub/findings.go index beee5a999b..46307e7f9d 100644 --- a/services/securityhub/findings.go +++ b/services/securityhub/findings.go @@ -1,7 +1,7 @@ package securityhub import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -9,6 +9,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // findingCustomerManagedFields lists ASFF fields that AWS documents as @@ -304,7 +305,7 @@ func findingSortValue(f map[string]any, field string) string { return s } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return fmt.Sprintf("%v", v) } @@ -649,7 +650,7 @@ func historyValueString(v any) *string { return &s } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { s := fmt.Sprintf("%v", v) diff --git a/services/securityhub/findings_test.go b/services/securityhub/findings_test.go index 37438817d5..4710a20ea7 100644 --- a/services/securityhub/findings_test.go +++ b/services/securityhub/findings_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -25,7 +26,7 @@ func TestGetFindingsIsPOSTFindings(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasFindings := resp["Findings"] assert.True(t, hasFindings, "GetFindings must return 'Findings' key") @@ -59,7 +60,7 @@ func TestBatchImportFindingsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "SuccessCount") assert.Contains(t, resp, "FailedCount") @@ -108,7 +109,7 @@ func TestBatchUpdateFindingsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ProcessedFindings") assert.Contains(t, resp, "UnprocessedFindings") @@ -145,7 +146,7 @@ func TestGetFindingHistoryPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Records") } @@ -274,7 +275,7 @@ func TestBatchImportFindings_RequiredFields(t *testing.T) { SuccessCount int `json:"SuccessCount"` FailedCount int `json:"FailedCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantSuccess, resp.SuccessCount, "SuccessCount") assert.Equal(t, tc.wantFailed, resp.FailedCount, "FailedCount") @@ -308,7 +309,7 @@ func TestBatchImportFindings_MixedValidity(t *testing.T) { SuccessCount int `json:"SuccessCount"` FailedCount int `json:"FailedCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 2, resp.SuccessCount) assert.Equal(t, 1, resp.FailedCount) assert.Len(t, resp.FailedFindings, 1) @@ -329,7 +330,7 @@ func TestBatchImportFindings_EmptyFindingsList(t *testing.T) { SuccessCount int `json:"SuccessCount"` FailedCount int `json:"FailedCount"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, 0, resp.SuccessCount) assert.Equal(t, 0, resp.FailedCount) } @@ -452,7 +453,7 @@ func TestGetFindings_FiltersApplied(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) assert.Len(t, findings, tt.wantCount) }) @@ -497,7 +498,7 @@ func TestGetFindings_MultipleFilterCombinations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) assert.Len(t, findings, 1) @@ -546,7 +547,7 @@ func TestGetFindings_MultiValueSameFieldCombination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) gotIDs := make([]string, 0, len(findings)) @@ -589,7 +590,7 @@ func TestGetFindings_MultiValueSameFieldCombination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) gotIDs := make([]string, 0, len(findings)) @@ -875,7 +876,7 @@ func TestGetFindingHistory_RecordsChanges(t *testing.T) { var resp struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Records, 3, "creation + 2 field-change events") @@ -914,6 +915,6 @@ func TestGetFindingHistory_UnknownFinding(t *testing.T) { var resp struct { Records []map[string]any `json:"Records"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.Records) } diff --git a/services/securityhub/findings_v2_test.go b/services/securityhub/findings_v2_test.go index 3db52a1e3d..d714f3a33b 100644 --- a/services/securityhub/findings_v2_test.go +++ b/services/securityhub/findings_v2_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -90,7 +91,7 @@ func TestGetFindingsV2_ReturnsSameStoreAsV1(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) assert.NotEmpty(t, findings) } @@ -213,7 +214,7 @@ func TestGetFindingsV2_CompositeFilters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) assert.Len(t, findings, tc.wantCount) }) @@ -573,7 +574,7 @@ func TestGetFindingsV2_CompositeFilters_DateMapIPBooleanNested(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) findings, _ := resp["Findings"].([]any) assert.Len(t, findings, tc.wantCount) @@ -652,7 +653,7 @@ func TestBatchUpdateFindingsV2_WireShape(t *testing.T) { ProcessedFindings []map[string]any `json:"ProcessedFindings"` UnprocessedFindings []map[string]any `json:"UnprocessedFindings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ProcessedFindings, 1, "matching identifier must process") assert.Empty(t, resp.UnprocessedFindings) @@ -674,7 +675,7 @@ func TestBatchUpdateFindingsV2_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) findings, _ := getResp["Findings"].([]any) require.Len(t, findings, 1) @@ -718,7 +719,7 @@ func TestBatchUpdateFindingsV2_UnmatchedIdentifiers(t *testing.T) { ProcessedFindings []map[string]any `json:"ProcessedFindings"` UnprocessedFindings []map[string]any `json:"UnprocessedFindings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.ProcessedFindings) require.Len(t, resp.UnprocessedFindings, 2) @@ -749,7 +750,7 @@ func TestBatchUpdateFindingsV2_MetadataUids(t *testing.T) { } `json:"metadata"` } `json:"Findings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &got, jsonx.V1())) require.Len(t, got.Findings, 1) uid := got.Findings[0].Metadata.UID require.NotEmpty(t, uid) @@ -764,7 +765,7 @@ func TestBatchUpdateFindingsV2_MetadataUids(t *testing.T) { ProcessedFindings []map[string]any `json:"ProcessedFindings"` UnprocessedFindings []map[string]any `json:"UnprocessedFindings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.ProcessedFindings, 1) assert.Equal(t, uid, resp.ProcessedFindings[0]["MetadataUid"]) require.Len(t, resp.UnprocessedFindings, 1) diff --git a/services/securityhub/handler.go b/services/securityhub/handler.go index 6af5cce26e..cb17f85531 100644 --- a/services/securityhub/handler.go +++ b/services/securityhub/handler.go @@ -1,7 +1,8 @@ package securityhub import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strconv" @@ -12,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -569,7 +571,12 @@ func decodeJSONBody(c *echo.Context) (map[string]any, error) { var body map[string]any if c.Request().ContentLength != 0 { - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && err.Error() != "EOF" { + if err := json.UnmarshalDecode( + jsontext.NewDecoder(c.Request().Body), + &body, + jsonx.V1(), + ); err != nil && + err.Error() != "EOF" { return nil, errInvalidJSONBody } } diff --git a/services/securityhub/handler_malformed_body_test.go b/services/securityhub/handler_malformed_body_test.go index 0c9726e12b..6bfe66ac54 100644 --- a/services/securityhub/handler_malformed_body_test.go +++ b/services/securityhub/handler_malformed_body_test.go @@ -2,7 +2,7 @@ package securityhub_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -77,6 +78,6 @@ func TestMalformedJSONBody_DoesNotDoubleWrite(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]any - err := json.Unmarshal(rec.Body.Bytes(), &body) + err := json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1()) require.NoError(t, err, "a single write must produce one well-formed JSON body, got: %s", rec.Body.String()) } diff --git a/services/securityhub/handler_test.go b/services/securityhub/handler_test.go index 16e8d9fc57..ca62e3017d 100644 --- a/services/securityhub/handler_test.go +++ b/services/securityhub/handler_test.go @@ -2,7 +2,7 @@ package securityhub_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -29,7 +30,7 @@ func doRequest(t *testing.T, h *securityhub.Handler, method, path string, body a if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/securityhub/hub_test.go b/services/securityhub/hub_test.go index edce2bedfd..a3548a8b9e 100644 --- a/services/securityhub/hub_test.go +++ b/services/securityhub/hub_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "sync" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -24,7 +25,7 @@ func TestEnableSecurityHubPath(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // EnableSecurityHub returns an empty object, not a hub object assert.NotContains(t, resp, "HubArn", "EnableSecurityHub must return empty body") } @@ -41,7 +42,7 @@ func TestDescribeHubIsGETAccounts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "HubArn") assert.Contains(t, resp, "SubscribedAt") @@ -97,7 +98,7 @@ func TestUpdateSecurityHubConfigurationIsPATCHAccounts(t *testing.T) { // Verify the change rec2 := doRequest(t, h, http.MethodGet, "/accounts", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, false, resp["AutoEnableControls"]) assert.Equal(t, "NONE", resp["AutoEnableStandards"]) @@ -115,7 +116,7 @@ func TestHubArnFormat(t *testing.T) { rec := doRequest(t, h, http.MethodGet, "/accounts", nil) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hubArn, _ := resp["HubArn"].(string) assert.Equal(t, "arn:aws:securityhub:eu-west-1:123456789012:hub/default", hubArn) @@ -214,7 +215,7 @@ func TestHubV2(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -404,7 +405,7 @@ func TestHubV2Features(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/insights_test.go b/services/securityhub/insights_test.go index 89e6962324..a1097c96d1 100644 --- a/services/securityhub/insights_test.go +++ b/services/securityhub/insights_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -27,7 +28,7 @@ func TestCreateInsightPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["InsightArn"].(string) assert.NotEmpty(t, arn) @@ -47,7 +48,7 @@ func TestGetInsightsIsPOSTInsightsGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Insights") } @@ -67,7 +68,7 @@ func TestGetInsightResultsIsGETInsightsResults(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) insightArn, _ := createResp["InsightArn"].(string) require.NotEmpty(t, insightArn) @@ -76,7 +77,7 @@ func TestGetInsightResultsIsGETInsightsResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Response is wrapped in InsightResults key insightResults, hasWrapper := resp["InsightResults"] @@ -103,7 +104,7 @@ func TestUpdateInsightIsPATCHInsightsArn(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) insightArn, _ := createResp["InsightArn"].(string) require.NotEmpty(t, insightArn) @@ -129,7 +130,7 @@ func TestDeleteInsightIsDELETEInsightsArn(t *testing.T) { }) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) insightArn, _ := createResp["InsightArn"].(string) require.NotEmpty(t, insightArn) @@ -138,7 +139,7 @@ func TestDeleteInsightIsDELETEInsightsArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deletedArn, _ := resp["InsightArn"].(string) assert.Equal(t, insightArn, deletedArn, "DeleteInsight must return the deleted InsightArn") diff --git a/services/securityhub/invitations_test.go b/services/securityhub/invitations_test.go index 40c945ec34..1f6fa9dcb3 100644 --- a/services/securityhub/invitations_test.go +++ b/services/securityhub/invitations_test.go @@ -1,13 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -176,7 +177,7 @@ func TestInvitations(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -375,7 +376,7 @@ func TestHandler_DeclineDeleteInvitations(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/members_only_associated_test.go b/services/securityhub/members_only_associated_test.go index 91858b60d5..f770b4c89a 100644 --- a/services/securityhub/members_only_associated_test.go +++ b/services/securityhub/members_only_associated_test.go @@ -1,12 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListMembers_OnlyAssociated(t *testing.T) { @@ -43,7 +45,7 @@ func TestListMembers_OnlyAssociated(t *testing.T) { InvitationID string `json:"InvitationId"` } `json:"Invitations"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inv)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &inv, jsonx.V1())) require.Len(t, inv.Invitations, 1) require.Equal(t, http.StatusOK, doRequest(t, h, http.MethodPost, "/administrator", map[string]any{ @@ -59,7 +61,7 @@ func TestListMembers_OnlyAssociated(t *testing.T) { MemberStatus string `json:"MemberStatus"` } `json:"Members"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Members, tt.wantCount) if tt.accept { diff --git a/services/securityhub/members_test.go b/services/securityhub/members_test.go index 6302e69ced..dcc3716295 100644 --- a/services/securityhub/members_test.go +++ b/services/securityhub/members_test.go @@ -1,12 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestMembers(t *testing.T) { @@ -196,7 +198,7 @@ func TestMembers(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) @@ -242,7 +244,7 @@ func TestInviteMembers_UnknownAccountUnprocessed(t *testing.T) { require.Equal(t, http.StatusOK, inviteRec.Code) var inviteResp map[string]any - require.NoError(t, json.Unmarshal(inviteRec.Body.Bytes(), &inviteResp)) + require.NoError(t, json.Unmarshal(inviteRec.Body.Bytes(), &inviteResp, jsonx.V1())) unprocessed, _ := inviteResp["UnprocessedAccounts"].([]any) assert.Len(t, unprocessed, tc.wantUnproc) @@ -252,7 +254,7 @@ func TestInviteMembers_UnknownAccountUnprocessed(t *testing.T) { require.Equal(t, http.StatusOK, membersRec.Code) var membersResp map[string]any - require.NoError(t, json.Unmarshal(membersRec.Body.Bytes(), &membersResp)) + require.NoError(t, json.Unmarshal(membersRec.Body.Bytes(), &membersResp, jsonx.V1())) members, _ := membersResp["Members"].([]any) require.Len(t, members, 1) diff --git a/services/securityhub/multi_region_test.go b/services/securityhub/multi_region_test.go index 07a6fd9aa7..d1c4f3b66c 100644 --- a/services/securityhub/multi_region_test.go +++ b/services/securityhub/multi_region_test.go @@ -2,7 +2,7 @@ package securityhub_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/securityhub/organizations_test.go b/services/securityhub/organizations_test.go index c9c92ddbdf..71cb1c983b 100644 --- a/services/securityhub/organizations_test.go +++ b/services/securityhub/organizations_test.go @@ -1,12 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestOrganization(t *testing.T) { @@ -133,7 +135,7 @@ func TestOrganization(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/persistence_test.go b/services/securityhub/persistence_test.go index 933d687449..1b35e47c82 100644 --- a/services/securityhub/persistence_test.go +++ b/services/securityhub/persistence_test.go @@ -1,12 +1,14 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -285,12 +287,12 @@ func TestInMemoryBackend_SnapshotRestore_FullState(t *testing.T) { assert.Equal(t, "finding-metadata-uid-1", ticketV2.FindingMetadataUid) var snapOut struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` } - require.NoError(t, json.Unmarshal(snap, &snapOut)) + require.NoError(t, json.Unmarshal(snap, &snapOut, jsonx.V1())) var restoredTickets []securityhub.TicketV2 - require.NoError(t, json.Unmarshal(snapOut.Tables["ticketsV2"], &restoredTickets)) + require.NoError(t, json.Unmarshal(snapOut.Tables["ticketsV2"], &restoredTickets, jsonx.V1())) require.Len(t, restoredTickets, 1) assert.Equal(t, ticketV2.TicketId, restoredTickets[0].TicketId) assert.Equal(t, connV2.ConnectorId, restoredTickets[0].ConnectorId) diff --git a/services/securityhub/products_test.go b/services/securityhub/products_test.go index c16355686f..fe99496c0d 100644 --- a/services/securityhub/products_test.go +++ b/services/securityhub/products_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -24,7 +25,7 @@ func TestDescribeProductsIsGETProducts(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) products, _ := resp["Products"].([]any) assert.NotEmpty(t, products) @@ -49,7 +50,7 @@ func TestEnableImportFindingsForProductPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) subArn, _ := resp["ProductSubscriptionArn"].(string) assert.NotEmpty(t, subArn) @@ -69,7 +70,7 @@ func TestListEnabledProductsForImportIsGETProductSubscriptions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) subs, _ := resp["ProductSubscriptions"].([]any) assert.Len(t, subs, 1) @@ -170,7 +171,7 @@ func TestHandler_DisableImportFindingsForProduct(t *testing.T) { require.Equal(t, http.StatusOK, enableRec.Code) var enableResp map[string]any - require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp)) + require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp, jsonx.V1())) subArn, _ := enableResp["ProductSubscriptionArn"].(string) require.NotEmpty(t, subArn) @@ -308,7 +309,7 @@ func TestRecommendedPolicyV2(t *testing.T) { rec := doRequest(t, h, s.method, s.path, s.body) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s.check(t, rec.Code, resp) } }) diff --git a/services/securityhub/resources_v2_test.go b/services/securityhub/resources_v2_test.go index 365c7caeeb..a9376cd268 100644 --- a/services/securityhub/resources_v2_test.go +++ b/services/securityhub/resources_v2_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -23,7 +24,7 @@ func TestGetResourcesV2_Empty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, _ := resp["Resources"].([]any) assert.Empty(t, resources) } diff --git a/services/securityhub/standards_test.go b/services/securityhub/standards_test.go index b5a83bbb6e..1c9a8f12e1 100644 --- a/services/securityhub/standards_test.go +++ b/services/securityhub/standards_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/securityhub" ) @@ -30,7 +31,7 @@ func TestBatchEnableStandardsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) subs, _ := resp["StandardsSubscriptions"].([]any) assert.Len(t, subs, 1) @@ -55,7 +56,7 @@ func TestBatchEnableStandardsPath(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) gotSubs, _ := getResp["StandardsSubscriptions"].([]any) require.Len(t, gotSubs, 1) @@ -76,7 +77,7 @@ func TestBatchDisableStandardsPath(t *testing.T) { }) var enableResp map[string]any - require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp)) + require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp, jsonx.V1())) subs, _ := enableResp["StandardsSubscriptions"].([]any) require.Len(t, subs, 1) @@ -89,7 +90,7 @@ func TestBatchDisableStandardsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) disabledSubs, _ := resp["StandardsSubscriptions"].([]any) assert.Len(t, disabledSubs, 1) @@ -113,7 +114,7 @@ func TestGetEnabledStandardsIsPOSTStandardsGet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "StandardsSubscriptions") } @@ -128,7 +129,7 @@ func TestDescribeStandardsIsGETStandards(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) standards, _ := resp["Standards"].([]any) assert.NotEmpty(t, standards, "DescribeStandards must return built-in standards") @@ -157,7 +158,7 @@ func TestDescribeStandardsControlsPath(t *testing.T) { }) var enableResp map[string]any - require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp)) + require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp, jsonx.V1())) subs, _ := enableResp["StandardsSubscriptions"].([]any) subArn, _ := subs[0].(map[string]any)["StandardsSubscriptionArn"].(string) @@ -166,7 +167,7 @@ func TestDescribeStandardsControlsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) controls, _ := resp["Controls"].([]any) assert.NotEmpty(t, controls) @@ -192,7 +193,7 @@ func TestUpdateStandardsControlPath(t *testing.T) { }) var enableResp map[string]any - require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp)) + require.NoError(t, json.Unmarshal(enableRec.Body.Bytes(), &enableResp, jsonx.V1())) subs, _ := enableResp["StandardsSubscriptions"].([]any) subArn, _ := subs[0].(map[string]any)["StandardsSubscriptionArn"].(string) @@ -253,7 +254,7 @@ func TestListStandardsControlAssociationsIsGETAssociations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assocs, _ := resp["StandardsControlAssociationSummaries"].([]any) assert.NotEmpty(t, assocs) @@ -282,7 +283,7 @@ func TestBatchGetStdCtlAssociationsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "StandardsControlAssociationDetails") assert.Contains(t, resp, "UnprocessedAssociations") @@ -308,7 +309,7 @@ func TestBatchUpdateStdCtlAssociationsPath(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "UnprocessedAssociationUpdates") } @@ -332,7 +333,7 @@ func TestBatchDisableStandards_StatusIsDeleting(t *testing.T) { require.Equal(t, http.StatusOK, enRec.Code) var enResp map[string]any - require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp)) + require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp, jsonx.V1())) subs, _ := enResp["StandardsSubscriptions"].([]any) require.NotEmpty(t, subs) @@ -346,7 +347,7 @@ func TestBatchDisableStandards_StatusIsDeleting(t *testing.T) { require.Equal(t, http.StatusOK, disRec.Code) var disResp map[string]any - require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp)) + require.NoError(t, json.Unmarshal(disRec.Body.Bytes(), &disResp, jsonx.V1())) disabledSubs, _ := disResp["StandardsSubscriptions"].([]any) require.NotEmpty(t, disabledSubs) @@ -375,7 +376,7 @@ func TestUpdateStandardsControl_StatusValidation(t *testing.T) { require.Equal(t, http.StatusOK, enRec.Code) var enResp map[string]any - require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp)) + require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp, jsonx.V1())) subs, _ := enResp["StandardsSubscriptions"].([]any) require.NotEmpty(t, subs) @@ -454,7 +455,7 @@ func TestBatchUpdateStdCtlAssociations_Persisted(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) unprocessed, _ := updateResp["UnprocessedAssociationUpdates"].([]any) assert.Empty(t, unprocessed, "update must succeed without unprocessed items") @@ -470,7 +471,7 @@ func TestBatchUpdateStdCtlAssociations_Persisted(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) details, _ := getResp["StandardsControlAssociationDetails"].([]any) require.Len(t, details, 1) @@ -503,7 +504,7 @@ func TestStandardsSubscriptions_IncludesStandardsStatusReason(t *testing.T) { require.Equal(t, http.StatusOK, enRec.Code) var enResp map[string]any - require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp)) + require.NoError(t, json.Unmarshal(enRec.Body.Bytes(), &enResp, jsonx.V1())) subs, _ := enResp["StandardsSubscriptions"].([]any) require.NotEmpty(t, subs) @@ -516,7 +517,7 @@ func TestStandardsSubscriptions_IncludesStandardsStatusReason(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) getSubs, _ := getResp["StandardsSubscriptions"].([]any) require.NotEmpty(t, getSubs) _, hasStatusReasonGet := getSubs[0].(map[string]any)["StandardsStatusReason"] @@ -544,7 +545,7 @@ func TestBatchGetStdCtlAssociations_MissingFields(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) details, _ := resp["StandardsControlAssociationDetails"].([]any) require.Len(t, details, 1) diff --git a/services/securityhub/store.go b/services/securityhub/store.go index 91f8855b2e..6c78a2da4a 100644 --- a/services/securityhub/store.go +++ b/services/securityhub/store.go @@ -2,7 +2,7 @@ package securityhub import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "strconv" @@ -229,9 +229,9 @@ type snapshot struct { OrgAdminAccounts map[string]string `json:"orgAdminAccounts"` OrgAdminAccountFeatures map[string]string `json:"orgAdminAccountFeatures,omitempty"` // V2 - HubV2 *HubV2 `json:"hubV2"` - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + HubV2 *HubV2 `json:"hubV2"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` StandardsSeq int `json:"standardsSeq"` ActionTargetSeq int `json:"actionTargetSeq"` diff --git a/services/securityhub/tags_test.go b/services/securityhub/tags_test.go index 2a03bc6b18..e1775d28e1 100644 --- a/services/securityhub/tags_test.go +++ b/services/securityhub/tags_test.go @@ -1,7 +1,7 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -9,6 +9,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Batch-1 accuracy gap: TagResource is POST /tags/{ResourceArn}. @@ -40,7 +42,7 @@ func TestListTagsForResourceIsGETTagsArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["Tags"].(map[string]any) assert.Equal(t, "prod", tags["env"]) @@ -71,7 +73,7 @@ func TestUntagResourceIsDELETETagsArn(t *testing.T) { // Verify tag removed getRec := doRequest(t, h, http.MethodGet, "/tags/"+testArn, nil) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["Tags"].(map[string]any) _, hasEnv := tags["env"] diff --git a/services/securityhub/ticket_v2_client_token_test.go b/services/securityhub/ticket_v2_client_token_test.go index e025a37104..16f83719c2 100644 --- a/services/securityhub/ticket_v2_client_token_test.go +++ b/services/securityhub/ticket_v2_client_token_test.go @@ -1,13 +1,15 @@ package securityhub_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateTicketV2_ClientToken(t *testing.T) { @@ -43,7 +45,7 @@ func TestCreateTicketV2_ClientToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var conn map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &conn)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &conn, jsonx.V1())) create := func(token, uid string) *httptest.ResponseRecorder { body := map[string]any{"ConnectorId": conn["ConnectorId"], "FindingMetadataUid": uid} @@ -64,8 +66,8 @@ func TestCreateTicketV2_ClientToken(t *testing.T) { } var a, b map[string]any - require.NoError(t, json.Unmarshal(first.Body.Bytes(), &a)) - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b)) + require.NoError(t, json.Unmarshal(first.Body.Bytes(), &a, jsonx.V1())) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &b, jsonx.V1())) assert.Equal(t, tt.wantSame, a["TicketId"] == b["TicketId"]) }) } diff --git a/services/serverlessrepo/handler.go b/services/serverlessrepo/handler.go index db8f90cc83..1ddefb91c4 100644 --- a/services/serverlessrepo/handler.go +++ b/services/serverlessrepo/handler.go @@ -3,7 +3,7 @@ package serverlessrepo import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -18,6 +18,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -412,34 +413,31 @@ func (h *Handler) dispatchPolicyAndMiscOps( } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrNotFound): // json.Marshal on map[string]string never returns an error; _ is intentional. payload, _ := json.Marshal(map[string]string{ keyTypeField: "NotFoundException", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusNotFound, payload) case errors.Is(err, awserr.ErrConflict): payload, _ := json.Marshal(map[string]string{ keyTypeField: "ConflictException", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusConflict, payload) case errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): payload, _ := json.Marshal(map[string]string{ keyTypeField: "BadRequestException", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) default: @@ -452,7 +450,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: "InternalServerErrorException", keyMessageField: wireMessage(err), - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusInternalServerError, payload) } diff --git a/services/serverlessrepo/handler_application_dependencies.go b/services/serverlessrepo/handler_application_dependencies.go index 6b5ee859fe..ff10b8b17a 100644 --- a/services/serverlessrepo/handler_application_dependencies.go +++ b/services/serverlessrepo/handler_application_dependencies.go @@ -1,8 +1,10 @@ package serverlessrepo import ( - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleListApplicationDependencies(req *http.Request) ([]byte, error) { @@ -60,5 +62,5 @@ func (h *Handler) handleListApplicationDependencies(req *http.Request) ([]byte, resp["nextToken"] = encodePageToken(deps[end-1].ApplicationID) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/serverlessrepo/handler_application_dependencies_test.go b/services/serverlessrepo/handler_application_dependencies_test.go index ef4312c455..e1de9bc828 100644 --- a/services/serverlessrepo/handler_application_dependencies_test.go +++ b/services/serverlessrepo/handler_application_dependencies_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -44,7 +45,7 @@ func TestHandler_ListApplicationDependencies(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, ok := resp["dependencies"].([]any) require.True(t, ok) assert.Empty(t, deps) @@ -64,7 +65,7 @@ func TestListApplicationDependencies_EmptyList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps, ok := resp["dependencies"].([]any) require.True(t, ok, "dependencies must be an array (not nil)") assert.Empty(t, deps) @@ -91,7 +92,7 @@ func TestListApplicationDependencies_NoSemanticVersion_ReturnsEmpty(t *testing.T require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) deps := resp["dependencies"].([]any) assert.Empty(t, deps) } @@ -139,7 +140,7 @@ func TestListApplicationDependencies_PersistedState(t *testing.T) { var response struct { Dependencies []serverlessrepo.ApplicationDependency `json:"dependencies"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response, jsonx.V1())) assert.ElementsMatch(t, tests, response.Dependencies) } @@ -171,7 +172,7 @@ func TestListApplicationDependencies_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp1, jsonx.V1())) page1, ok := resp1["dependencies"].([]any) require.True(t, ok) assert.Len(t, page1, 2) @@ -186,7 +187,7 @@ func TestListApplicationDependencies_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) page2, ok := resp2["dependencies"].([]any) require.True(t, ok) assert.Len(t, page2, 1) @@ -214,7 +215,7 @@ func TestListApplicationDependencies_MaxItemsDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) page, ok := resp["dependencies"].([]any) require.True(t, ok) assert.Len(t, page, 3) @@ -243,7 +244,7 @@ func TestListApplicationDependencies_DeterministicOrder(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) page, ok := resp["dependencies"].([]any) require.True(t, ok) require.Len(t, page, 3) diff --git a/services/serverlessrepo/handler_application_policy.go b/services/serverlessrepo/handler_application_policy.go index 92b55284d7..14867354f6 100644 --- a/services/serverlessrepo/handler_application_policy.go +++ b/services/serverlessrepo/handler_application_policy.go @@ -2,10 +2,11 @@ package serverlessrepo import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -33,7 +34,7 @@ func (h *Handler) handleGetApplicationPolicy(req *http.Request) ([]byte, error) return nil, backendErr } - return json.Marshal(map[string]any{"statements": toPolicyStatementsResponse(stmts)}) + return json.Marshal(map[string]any{"statements": toPolicyStatementsResponse(stmts)}, jsonx.V1()) } func (h *Handler) handlePutApplicationPolicy(ctx context.Context, req *http.Request, body []byte) ([]byte, error) { @@ -43,7 +44,7 @@ func (h *Handler) handlePutApplicationPolicy(ctx context.Context, req *http.Requ } var putReq putApplicationPolicyRequest - if jsonErr := json.Unmarshal(body, &putReq); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &putReq, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, jsonErr) } @@ -65,7 +66,7 @@ func (h *Handler) handlePutApplicationPolicy(ctx context.Context, req *http.Requ log := logger.Load(ctx) log.InfoContext(ctx, "serverlessrepo: updated application policy", "app", appName) - return json.Marshal(map[string]any{"statements": toPolicyStatementsResponse(result)}) + return json.Marshal(map[string]any{"statements": toPolicyStatementsResponse(result)}, jsonx.V1()) } func toPolicyStatementsResponse(stmts []*ApplicationPolicyStatement) []map[string]any { diff --git a/services/serverlessrepo/handler_application_policy_test.go b/services/serverlessrepo/handler_application_policy_test.go index 56d4e38805..9eff5ad563 100644 --- a/services/serverlessrepo/handler_application_policy_test.go +++ b/services/serverlessrepo/handler_application_policy_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -62,7 +63,7 @@ func TestHandler_GetApplicationPolicy(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok) assert.Len(t, stmts, tt.wantLen) @@ -82,7 +83,7 @@ func TestGetApplicationPolicy_EmptyForNewApp(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok, "statements must be an array") assert.Empty(t, stmts, "new app should have empty policy statements") @@ -99,7 +100,7 @@ func TestGetApplicationPolicy_EmptyPolicy_ReturnsEmptyStatements(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["statements"].([]any) assert.Empty(t, stmts) } @@ -125,7 +126,7 @@ func TestGetApplicationPolicy_ARNForm_Routing(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok) assert.Len(t, stmts, 1) @@ -198,7 +199,7 @@ func TestHandler_PutApplicationPolicy(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok) assert.Len(t, stmts, tt.wantLen) @@ -334,7 +335,7 @@ func TestErrValidation_MapsTo400(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) } @@ -357,7 +358,7 @@ func TestPutApplicationPolicy_AutoGeneratesStatementID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok) require.Len(t, stmts, 1) @@ -382,7 +383,7 @@ func TestPolicyResponse_NonNilSlices(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts, ok := resp["statements"].([]any) require.True(t, ok) @@ -419,7 +420,7 @@ func TestPutApplicationPolicy_PrincipalOrgIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) stmts := putResp["statements"].([]any) stmt := stmts[0].(map[string]any) orgIDs := stmt["principalOrgIDs"].([]any) @@ -431,7 +432,7 @@ func TestPutApplicationPolicy_PrincipalOrgIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) stmts2 := getResp["statements"].([]any) stmt2 := stmts2[0].(map[string]any) orgIDs2 := stmt2["principalOrgIDs"].([]any) @@ -466,7 +467,7 @@ func TestPutApplicationPolicy_ReplacesExistingStatements(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stmts := resp["statements"].([]any) require.Len(t, stmts, 1, "policy should have exactly 1 statement after replacement") assert.Equal(t, "s3", stmts[0].(map[string]any)["statementId"]) diff --git a/services/serverlessrepo/handler_application_versions.go b/services/serverlessrepo/handler_application_versions.go index 9ac76253e0..cb0019dc31 100644 --- a/services/serverlessrepo/handler_application_versions.go +++ b/services/serverlessrepo/handler_application_versions.go @@ -2,10 +2,11 @@ package serverlessrepo import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -32,7 +33,7 @@ func (h *Handler) handleCreateApplicationVersion(ctx context.Context, req *http. } var createReq createApplicationVersionRequest - if jsonErr := json.Unmarshal(body, &createReq); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &createReq, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, jsonErr) } @@ -66,7 +67,7 @@ func (h *Handler) handleCreateApplicationVersion(ctx context.Context, req *http. log.InfoContext(ctx, "serverlessrepo: created application version", "app", appName, "version", v.SemanticVersion) - b, marshalErr := json.Marshal(toVersionResponse(v)) + b, marshalErr := json.Marshal(toVersionResponse(v), jsonx.V1()) if marshalErr != nil { return nil, marshalErr } @@ -154,7 +155,7 @@ func (h *Handler) handleListApplicationVersions(req *http.Request) ([]byte, erro resp["nextToken"] = encodePageToken(versions[end-1].SemanticVersion) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // toVersionResponse converts an ApplicationVersion to a map matching the AWS SAR Version shape. diff --git a/services/serverlessrepo/handler_application_versions_test.go b/services/serverlessrepo/handler_application_versions_test.go index be50a10f44..8fb701489d 100644 --- a/services/serverlessrepo/handler_application_versions_test.go +++ b/services/serverlessrepo/handler_application_versions_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -69,7 +70,7 @@ func TestHandler_CreateApplicationVersion(t *testing.T) { if tt.wantCode == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "1.0.0", resp["semanticVersion"]) assert.NotNil(t, resp["parameterDefinitions"]) assert.NotNil(t, resp["requiredCapabilities"]) @@ -104,7 +105,7 @@ func TestCreateApplicationVersion_HasRequiredFields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["parameterDefinitions"], "parameterDefinitions must be present") assert.NotNil(t, resp["requiredCapabilities"], "requiredCapabilities must be present") assert.Equal(t, true, resp["resourcesSupported"]) @@ -157,7 +158,7 @@ func TestCreateApplicationVersion_ArchiveURL(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var response map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response, jsonx.V1())) assert.Equal(t, "s3://bucket/archive.zip", response["sourceCodeArchiveUrl"]) assert.NotEmpty(t, response["templateUrl"]) }) @@ -177,7 +178,7 @@ func TestCreateApplicationVersion_TemplateURLOnly(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "s3://bucket/tmpl.yaml", resp["templateUrl"]) } @@ -227,7 +228,7 @@ func TestCreateApplicationVersion_TemplateBody(t *testing.T) { if tt.wantCode == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["templateUrl"]) } }) @@ -251,7 +252,7 @@ func TestCreateApplicationVersion_DuplicateReturns409(t *testing.T) { assert.Equal(t, http.StatusConflict, rec2.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) } @@ -297,7 +298,7 @@ func TestCreateApplicationVersion_GeneratesTemplateURL(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["templateUrl"], "templateUrl should be auto-generated from sourceCodeUrl") } @@ -321,7 +322,7 @@ func TestCreateApplicationVersion_UpdatesLatestVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) version, ok := resp["version"].(map[string]any) require.True(t, ok, "version field must be present") assert.Equal(t, "2.0.0", version["semanticVersion"], "should return latest created version") @@ -341,7 +342,7 @@ func TestCreateApplicationVersion_FullVersionDataInGetApplication(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) version, ok := resp["version"].(map[string]any) require.True(t, ok, "version must be embedded in GetApplication response") assert.Equal(t, "3.1.4", version["semanticVersion"]) @@ -400,7 +401,7 @@ func TestHandler_ListApplicationVersions(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) assert.Len(t, versions, tt.wantLen) @@ -425,7 +426,7 @@ func TestListApplicationVersions_SemanticVersionFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) assert.Len(t, versions, 1, "filter should return only 1 matching version") @@ -448,7 +449,7 @@ func TestListApplicationVersions_MaxItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) assert.Len(t, versions, 2) @@ -472,7 +473,7 @@ func TestListApplicationVersions_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) v1 := r1["versions"].([]any) assert.Len(t, v1, 2) nt, ok := r1["nextToken"].(string) @@ -487,7 +488,7 @@ func TestListApplicationVersions_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) v2 := r2["versions"].([]any) assert.Len(t, v2, 2) assert.Nil(t, r2["nextToken"]) @@ -513,7 +514,7 @@ func TestListApplicationVersions_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) require.Len(t, versions, 1) @@ -543,7 +544,7 @@ func TestListApplicationVersions_ARNForm(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["versions"].([]any) require.True(t, ok) assert.Len(t, versions, 1) diff --git a/services/serverlessrepo/handler_applications.go b/services/serverlessrepo/handler_applications.go index f57d1d61d2..8c9d10a22b 100644 --- a/services/serverlessrepo/handler_applications.go +++ b/services/serverlessrepo/handler_applications.go @@ -2,10 +2,11 @@ package serverlessrepo import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -153,7 +154,7 @@ func toEmbeddedVersionResponse(v *ApplicationVersion) *versionResponse { func (h *Handler) handleCreateApplication(ctx context.Context, body []byte) ([]byte, error) { var req createApplicationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -205,7 +206,7 @@ func (h *Handler) handleCreateApplication(ctx context.Context, body []byte) ([]b resp.Version = toEmbeddedVersionResponse(v) } - b, marshalErr := json.Marshal(resp) + b, marshalErr := json.Marshal(resp, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } @@ -244,7 +245,7 @@ func (h *Handler) handleGetApplication(req *http.Request) ([]byte, error) { } } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleListApplications(req *http.Request) ([]byte, error) { @@ -300,7 +301,7 @@ func (h *Handler) handleListApplications(req *http.Request) ([]byte, error) { resp["nextToken"] = encodePageToken(apps[end-1].Name) } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateApplicationRequest is the request body for UpdateApplication. @@ -320,7 +321,7 @@ func (h *Handler) handleUpdateApplication(ctx context.Context, req *http.Request } var updateReq updateApplicationRequest - if err := json.Unmarshal(body, &updateReq); err != nil { + if err := json.Unmarshal(body, &updateReq, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -365,7 +366,7 @@ func (h *Handler) handleUpdateApplication(ctx context.Context, req *http.Request } } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleDeleteApplication(ctx context.Context, req *http.Request) error { @@ -396,7 +397,7 @@ func (h *Handler) handleUnshareApplication(ctx context.Context, req *http.Reques } var unshareReq unshareApplicationRequest - if jsonErr := json.Unmarshal(body, &unshareReq); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &unshareReq, jsonx.V1()); jsonErr != nil { return fmt.Errorf("%w: %w", errInvalidRequest, jsonErr) } diff --git a/services/serverlessrepo/handler_applications_list_test.go b/services/serverlessrepo/handler_applications_list_test.go index 5a7004cad4..44427f46b2 100644 --- a/services/serverlessrepo/handler_applications_list_test.go +++ b/services/serverlessrepo/handler_applications_list_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -50,7 +51,7 @@ func TestHandler_ListApplications(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps, ok := resp["applications"].([]any) require.True(t, ok) @@ -70,7 +71,7 @@ func TestListApplications_IncludesLabels(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps, ok := resp["applications"].([]any) require.True(t, ok) require.Len(t, apps, 1) @@ -96,7 +97,7 @@ func TestListApplications_PageBoundaryExact(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) apps1 := r1["applications"].([]any) assert.Len(t, apps1, 2) nt := r1["nextToken"].(string) @@ -106,7 +107,7 @@ func TestListApplications_PageBoundaryExact(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2, jsonx.V1())) apps2 := r2["applications"].([]any) assert.Len(t, apps2, 2) assert.Nil(t, r2["nextToken"], "no more pages when exactly on boundary") @@ -126,7 +127,7 @@ func TestListApplications_Pagination_MaxItems(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apps, ok := resp["applications"].([]any) require.True(t, ok) assert.Len(t, apps, 2, "maxItems=2 should return 2 items") @@ -148,7 +149,7 @@ func TestListApplications_Pagination_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) nextToken, ok := resp1["nextToken"].(string) require.True(t, ok, "nextToken should be a string") @@ -157,7 +158,7 @@ func TestListApplications_Pagination_NextToken(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) apps, ok := resp2["applications"].([]any) require.True(t, ok) assert.Len(t, apps, 1, "second page should have 1 remaining item") diff --git a/services/serverlessrepo/handler_applications_test.go b/services/serverlessrepo/handler_applications_test.go index cb1bd90980..59a4f36e2d 100644 --- a/services/serverlessrepo/handler_applications_test.go +++ b/services/serverlessrepo/handler_applications_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -73,7 +74,7 @@ func TestHandler_CreateApplication(t *testing.T) { if tt.wantARN { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["applicationId"]) assert.Equal(t, tt.body["name"], resp["name"]) } @@ -104,7 +105,7 @@ func TestCreateApplication_MissingAuthor(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "Author is required") } @@ -119,7 +120,7 @@ func TestCreateApplication_MissingDescription(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "Description is required") } @@ -136,7 +137,7 @@ func TestCreateApplication_WithLabels(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) labels, ok := resp["labels"].([]any) require.True(t, ok) @@ -156,7 +157,7 @@ func TestCreateApplication_WithHomePageURL(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "https://github.com/example/my-app", resp["homePageUrl"]) } @@ -193,7 +194,7 @@ func TestApplicationResponse_LabelsField(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // SAR uses "labels" ([]string), not "tags" (map[string]string) labels, ok := resp["labels"].([]any) @@ -214,7 +215,7 @@ func TestApplication_ARNFormat(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) appID := resp["applicationId"].(string) assert.Contains(t, appID, "arn:aws:serverlessrepo:") assert.Contains(t, appID, ":applications/arn-check-app") @@ -234,7 +235,7 @@ func TestCreateApplication_TemplateURLOnly_CreatesVersion(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) version := resp["version"].(map[string]any) assert.Equal(t, "s3://bucket/template.yaml", version["templateUrl"]) assert.Equal(t, "1.0.0", version["semanticVersion"]) @@ -256,7 +257,7 @@ func TestCreateApplication_InlineVersion_FullResponseFields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "MIT", resp["spdxLicenseId"]) version, ok := resp["version"].(map[string]any) @@ -339,7 +340,7 @@ func TestApplicationMetadata(t *testing.T) { assert.Contains(t, []int{http.StatusCreated, http.StatusOK}, rec.Code) var response map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &response, jsonx.V1())) tt.check(t, response) }) } @@ -393,7 +394,7 @@ func TestHandler_GetApplication(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "existing-app", resp["name"]) } }) @@ -429,7 +430,7 @@ func TestGetApplication_WithSemanticVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versionObj, ok := resp["version"].(map[string]any) require.True(t, ok, "version field must be present when semanticVersion is requested") assert.Equal(t, "1.2.3", versionObj["semanticVersion"]) @@ -464,7 +465,7 @@ func TestGetApplication_VersionEmbedFromStore_IncludesTemplateURL(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) version := resp["version"].(map[string]any) assert.Equal(t, "1.5.0", version["semanticVersion"]) assert.Equal(t, "s3://my-bucket/tmpl.yaml", version["templateUrl"]) @@ -491,7 +492,7 @@ func TestGetApplication_ResponseFieldCompleteness(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "full-resp-app", resp["name"]) assert.Equal(t, "A full response app", resp["description"]) assert.Equal(t, "test-author", resp["author"]) @@ -576,7 +577,7 @@ func TestUpdateApplication_EmbedCurrentVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) version, ok := resp["version"].(map[string]any) require.True(t, ok, "version must be embedded in UpdateApplication response when current version exists") @@ -597,7 +598,7 @@ func TestUpdateApplication_NoVersionWhenNoneCreated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Nil(t, resp["version"], "version should be absent when no version has been created") } @@ -768,7 +769,7 @@ func TestApplication_ARNFormRouting(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -867,7 +868,7 @@ func TestCreateApplication_BodyVariants(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -910,7 +911,7 @@ func TestUpdateApplication_ReadmeBody(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["readmeUrl"]) } }) diff --git a/services/serverlessrepo/handler_applications_validation_test.go b/services/serverlessrepo/handler_applications_validation_test.go index cdc958b9dd..122c4fc8bc 100644 --- a/services/serverlessrepo/handler_applications_validation_test.go +++ b/services/serverlessrepo/handler_applications_validation_test.go @@ -1,13 +1,15 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestCreateApplication_NameLength(t *testing.T) { @@ -36,7 +38,7 @@ func TestCreateApplication_NameLength(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "Name must be at most") } }) @@ -108,7 +110,7 @@ func TestCreateApplication_AuthorLength(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "Author must be at most") } }) @@ -141,7 +143,7 @@ func TestCreateApplication_DescriptionLength(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "Description must be at most") } }) @@ -266,7 +268,7 @@ func TestCreateApplication_LabelsValidation(t *testing.T) { if tt.wantMessage != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], tt.wantMessage) } }) diff --git a/services/serverlessrepo/handler_cloud_formation.go b/services/serverlessrepo/handler_cloud_formation.go index a39f505d81..c32d30fd17 100644 --- a/services/serverlessrepo/handler_cloud_formation.go +++ b/services/serverlessrepo/handler_cloud_formation.go @@ -2,11 +2,12 @@ package serverlessrepo import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -26,7 +27,7 @@ func (h *Handler) handleCreateCloudFormationTemplate( } var createReq createCFTemplateRequest - if jsonErr := json.Unmarshal(body, &createReq); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &createReq, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, jsonErr) } @@ -51,7 +52,7 @@ func (h *Handler) handleCreateCloudFormationTemplate( resp[keySemanticVersion] = t.SemanticVersion } - b, marshalErr := json.Marshal(resp) + b, marshalErr := json.Marshal(resp, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } @@ -96,7 +97,7 @@ func (h *Handler) handleGetCloudFormationTemplate(req *http.Request) ([]byte, er resp[keySemanticVersion] = t.SemanticVersion } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // createCFChangeSetRequest is the request body for CreateCloudFormationChangeSet. @@ -120,7 +121,7 @@ func (h *Handler) handleCreateCloudFormationChangeSet( } var createReq createCFChangeSetRequest - if jsonErr := json.Unmarshal(body, &createReq); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &createReq, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, jsonErr) } @@ -162,7 +163,7 @@ func (h *Handler) handleCreateCloudFormationChangeSet( csResp[keySemanticVersion] = cs.SemanticVersion } - b, marshalErr := json.Marshal(csResp) + b, marshalErr := json.Marshal(csResp, jsonx.V1()) if marshalErr != nil { return nil, marshalErr } diff --git a/services/serverlessrepo/handler_cloud_formation_test.go b/services/serverlessrepo/handler_cloud_formation_test.go index 4fe44e7257..c2645d97a8 100644 --- a/services/serverlessrepo/handler_cloud_formation_test.go +++ b/services/serverlessrepo/handler_cloud_formation_test.go @@ -1,13 +1,14 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -52,7 +53,7 @@ func TestHandler_CreateCloudFormationTemplate(t *testing.T) { if tt.wantCode == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["templateId"]) assert.Equal(t, "ACTIVE", resp["status"]) } @@ -86,7 +87,7 @@ func TestCreateCloudFormationTemplate_HasTemplateURL(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["templateUrl"]) assert.NotEmpty(t, resp["expirationTime"]) } @@ -103,7 +104,7 @@ func TestCreateCloudFormationTemplate_OmitsSemanticVersionWhenEmpty(t *testing.T require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasSV := resp["semanticVersion"] assert.False(t, hasSV, "semanticVersion must be absent from response when not provided") assert.NotEmpty(t, resp["templateId"]) @@ -124,7 +125,7 @@ func TestCreateCloudFormationTemplate_IncludesSemanticVersionWhenProvided(t *tes require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "2.0.0", resp["semanticVersion"]) } @@ -186,7 +187,7 @@ func TestHandler_GetCloudFormationTemplate(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["templateId"]) assert.Equal(t, "ACTIVE", resp["status"]) } @@ -205,7 +206,7 @@ func TestGetCloudFormationTemplate_ActiveStatus(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) templateID := createResp["templateId"].(string) rec2 := doServerlessRepoRequest(t, h, http.MethodGet, @@ -213,7 +214,7 @@ func TestGetCloudFormationTemplate_ActiveStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "ACTIVE", getResp["status"]) } @@ -229,7 +230,7 @@ func TestGetCloudFormationTemplate_OmitsSemanticVersionWhenEmpty(t *testing.T) { require.Equal(t, http.StatusCreated, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) templateID := createResp["templateId"].(string) getRec := doServerlessRepoRequest(t, h, http.MethodGet, @@ -237,7 +238,7 @@ func TestGetCloudFormationTemplate_OmitsSemanticVersionWhenEmpty(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) _, hasSV := getResp["semanticVersion"] assert.False(t, hasSV, "semanticVersion must be absent from GetCloudFormationTemplate when not set") } @@ -258,7 +259,7 @@ func TestGetCloudFormationTemplate_ExpiredStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "EXPIRED", resp["status"]) assert.Equal(t, "1.0.0", resp["semanticVersion"]) } @@ -278,7 +279,7 @@ func TestGetCloudFormationTemplate_Fields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) templateID := createResp["templateId"].(string) rec2 := doServerlessRepoRequest(t, h, http.MethodGet, @@ -286,7 +287,7 @@ func TestGetCloudFormationTemplate_Fields(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "ACTIVE", getResp["status"]) assert.Equal(t, "1.0.0", getResp["semanticVersion"]) assert.NotEmpty(t, getResp["templateUrl"]) @@ -357,7 +358,7 @@ func TestHandler_CreateCloudFormationChangeSet(t *testing.T) { if tt.wantCode == http.StatusCreated { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["changeSetId"]) assert.NotEmpty(t, resp["stackId"]) } @@ -392,7 +393,7 @@ func TestCreateCloudFormationChangeSet_CustomName(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["changeSetId"].(string), "my-custom-changeset") } @@ -477,7 +478,7 @@ func TestCreateCloudFormationChangeSet_TemplateID(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) }) @@ -514,7 +515,7 @@ func TestCreateCloudFormationChangeSet_OmitsSemanticVersionWhenEmpty(t *testing. require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasSV := resp["semanticVersion"] assert.False(t, hasSV, "semanticVersion must be absent from response when not provided") assert.NotEmpty(t, resp["changeSetId"]) @@ -535,7 +536,7 @@ func TestCreateCloudFormationChangeSet_IncludesSemanticVersionWhenProvided(t *te require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "3.1.4", resp["semanticVersion"]) } @@ -557,7 +558,7 @@ func TestCreateCloudFormationChangeSet_ResponseFields(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["changeSetId"]) assert.NotEmpty(t, resp["stackId"]) assert.Equal(t, "1.0.0", resp["semanticVersion"]) @@ -579,7 +580,7 @@ func TestCreateCloudFormationChangeSet_ARNForm(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["changeSetId"].(string), "cloudformation", "changeSetId should be a CloudFormation ARN") assert.Contains(t, resp["stackId"].(string), "cloudformation", "stackId should be a CloudFormation ARN") } diff --git a/services/serverlessrepo/handler_pagination_restart_test.go b/services/serverlessrepo/handler_pagination_restart_test.go index e2a6942467..2e6fb60569 100644 --- a/services/serverlessrepo/handler_pagination_restart_test.go +++ b/services/serverlessrepo/handler_pagination_restart_test.go @@ -2,13 +2,14 @@ package serverlessrepo_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -30,7 +31,7 @@ func TestListApplications_Pagination_DeletedMidPage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) nextToken, ok := r1["nextToken"].(string) require.True(t, ok) require.NotEmpty(t, nextToken) @@ -43,7 +44,7 @@ func TestListApplications_Pagination_DeletedMidPage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r2, jsonx.V1())) apps2, _ := r2["applications"].([]any) restarted := false @@ -78,7 +79,7 @@ func TestListApplicationVersions_Pagination_StaleTokenDoesNotRestart(t *testing. require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) v1, _ := r1["versions"].([]any) require.Len(t, v1, 2) @@ -96,7 +97,7 @@ func TestListApplicationVersions_Pagination_StaleTokenDoesNotRestart(t *testing. require.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) v2, _ := r2["versions"].([]any) for _, item := range v2 { @@ -137,7 +138,7 @@ func TestListApplicationDependencies_Pagination_StaleTokenDoesNotRestart(t *test require.Equal(t, http.StatusOK, rec.Code) var r1 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &r1, jsonx.V1())) page1, _ := r1["dependencies"].([]any) require.Len(t, page1, 2) @@ -154,7 +155,7 @@ func TestListApplicationDependencies_Pagination_StaleTokenDoesNotRestart(t *test require.Equal(t, http.StatusOK, rec2.Code) var r2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) page2, _ := r2["dependencies"].([]any) for _, item := range page2 { diff --git a/services/serverlessrepo/handler_test.go b/services/serverlessrepo/handler_test.go index 5cf76f6bd8..b087f2c8e9 100644 --- a/services/serverlessrepo/handler_test.go +++ b/services/serverlessrepo/handler_test.go @@ -2,7 +2,7 @@ package serverlessrepo_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -38,7 +39,7 @@ func doServerlessRepoRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -77,7 +78,7 @@ func doServerlessRepoRequestEncoded( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -275,7 +276,7 @@ func TestHandler_UnexpectedError_ReturnsInternalServerErrorException(t *testing. assert.Equal(t, http.StatusInternalServerError, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // The aws-sdk-go-v2 restjson1 error deserializer only recognizes the exact string // "InternalServerErrorException" (case-insensitively) in the __type field to build a // typed types.InternalServerErrorException; any other spelling (e.g. @@ -298,7 +299,7 @@ func TestErrorShape_NotFound(t *testing.T) { require.Equal(t, http.StatusNotFound, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "NotFoundException", resp["__type"]) assert.NotEmpty(t, resp["message"]) } @@ -316,7 +317,7 @@ func TestErrorShape_Conflict(t *testing.T) { require.Equal(t, http.StatusConflict, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ConflictException", resp["__type"]) } @@ -332,6 +333,6 @@ func TestErrorShape_BadRequest(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "BadRequestException", resp["__type"]) } diff --git a/services/serverlessrepo/multi_region_test.go b/services/serverlessrepo/multi_region_test.go index c6101e08f1..e540de25cd 100644 --- a/services/serverlessrepo/multi_region_test.go +++ b/services/serverlessrepo/multi_region_test.go @@ -2,7 +2,8 @@ package serverlessrepo_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/serverlessrepo" ) @@ -176,8 +178,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/serverlessrepo/persistence.go b/services/serverlessrepo/persistence.go index 7687858168..5a86458e0b 100644 --- a/services/serverlessrepo/persistence.go +++ b/services/serverlessrepo/persistence.go @@ -2,10 +2,12 @@ package serverlessrepo import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -80,7 +82,7 @@ func newDirtyDTORegistry() ( // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` AppPolicies map[string][]*ApplicationPolicyStatement `json:"appPolicies"` AppDependencies map[string]map[string][]*ApplicationDependency `json:"appDependencies"` AccountID string `json:"accountID"` @@ -157,7 +159,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "serverlessrepo: failed to marshal snapshot", "error", err) @@ -225,7 +227,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // cfTemplates, cfChangeSets) from tables via the ephemeral DTO registry, // converting each DTO back to its live type. The caller MUST hold b.mu for // writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, vDTOs, tDTOs, csDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/serverlessrepo/wire_sdk_roundtrip_test.go b/services/serverlessrepo/wire_sdk_roundtrip_test.go index fc2ac4f7af..afad95c3c3 100644 --- a/services/serverlessrepo/wire_sdk_roundtrip_test.go +++ b/services/serverlessrepo/wire_sdk_roundtrip_test.go @@ -1,7 +1,7 @@ package serverlessrepo_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/serverlessrepo" @@ -96,7 +97,7 @@ func TestCreateApplication_NoTopLevelSourceCodeURL_SDKRoundTrip(t *testing.T) { require.NoError(t, err) var raw map[string]any - require.NoError(t, json.Unmarshal(rawBody, &raw)) + require.NoError(t, json.Unmarshal(rawBody, &raw, jsonx.V1())) _, hasTopLevelSourceCodeURL := raw["sourceCodeUrl"] require.False(t, hasTopLevelSourceCodeURL, diff --git a/services/servicecatalog/constraints.go b/services/servicecatalog/constraints.go index e1bce0dbdc..7ba042002b 100644 --- a/services/servicecatalog/constraints.go +++ b/services/servicecatalog/constraints.go @@ -3,9 +3,11 @@ package servicecatalog import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const maxNotificationARNs = 5 @@ -28,7 +30,7 @@ func constraintDetail(c *Constraint) *ConstraintDetail { // validateConstraintParameters checks the JSON a constraint type requires. func validateConstraintParameters(typ, params string) error { var doc map[string]any - if err := json.Unmarshal([]byte(params), &doc); err != nil { + if err := json.Unmarshal([]byte(params), &doc, jsonx.V1()); err != nil { return invalid("Parameters is not a valid JSON object") } diff --git a/services/servicecatalog/handler.go b/services/servicecatalog/handler.go index 3dfee978b3..0ffa3f8522 100644 --- a/services/servicecatalog/handler.go +++ b/services/servicecatalog/handler.go @@ -3,7 +3,7 @@ package servicecatalog import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -35,7 +36,7 @@ func op[I, O any](fn func(context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, invalid("malformed request body: %v", err) } } diff --git a/services/servicecatalog/helpers_test.go b/services/servicecatalog/helpers_test.go index 3d7ac34ef0..0ebae9de99 100644 --- a/services/servicecatalog/helpers_test.go +++ b/services/servicecatalog/helpers_test.go @@ -2,7 +2,7 @@ package servicecatalog_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/sdktest" "github.com/blackbirdworks/gopherstack/services/servicecatalog" ) @@ -103,7 +104,7 @@ type fakeTemplate struct { func (f *fakeEngine) InspectTemplate(_ context.Context, body string) (servicecatalog.TemplateInfo, error) { var t fakeTemplate - if err := json.Unmarshal([]byte(body), &t); err != nil { + if err := json.Unmarshal([]byte(body), &t, jsonx.V1()); err != nil { return servicecatalog.TemplateInfo{}, err } @@ -145,7 +146,7 @@ func sortedMapKeys[V any](m map[string]V) []string { func (f *fakeEngine) outputsOf(template string) []servicecatalog.Output { var t fakeTemplate - _ = json.Unmarshal([]byte(template), &t) + _ = json.Unmarshal([]byte(template), &t, jsonx.V1()) out := make([]servicecatalog.Output, 0, len(t.Outputs)) for _, k := range sortedMapKeys(t.Outputs) { diff --git a/services/servicecatalog/persistence.go b/services/servicecatalog/persistence.go index d6d742ac43..f7d03d5b8b 100644 --- a/services/servicecatalog/persistence.go +++ b/services/servicecatalog/persistence.go @@ -2,7 +2,7 @@ package servicecatalog import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/servicecatalog/rules.go b/services/servicecatalog/rules.go index b82f6557f3..2b55490aa6 100644 --- a/services/servicecatalog/rules.go +++ b/services/servicecatalog/rules.go @@ -2,9 +2,11 @@ package servicecatalog import ( "context" - "encoding/json" + "encoding/json/v2" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const pairArgs = 2 @@ -58,13 +60,13 @@ func isRuleFunc(fn string) bool { // validateTemplateRules rejects a Rules document CloudFormation would not accept. func validateTemplateRules(rules map[string]any) error { - raw, err := json.Marshal(map[string]any{"Rules": rules}) + raw, err := json.Marshal(map[string]any{"Rules": rules}, jsonx.V1()) if err != nil { return invalid("Rules is not valid JSON") } var doc ruleDoc - if err = json.Unmarshal(raw, &doc); err != nil { + if err = json.Unmarshal(raw, &doc, jsonx.V1()); err != nil { return invalid("Rules is malformed: %v", err) } @@ -131,7 +133,7 @@ func validateRuleExpr(rule string, expr any) error { func checkTemplateRules(env *ruleEnv, constraintParams []string) error { for _, raw := range constraintParams { var doc ruleDoc - if err := json.Unmarshal([]byte(raw), &doc); err != nil { + if err := json.Unmarshal([]byte(raw), &doc, jsonx.V1()); err != nil { continue } @@ -435,7 +437,7 @@ func toStr(v any) string { return "false" case float64: - b, _ := json.Marshal(s) + b, _ := json.Marshal(s, jsonx.V1()) return string(b) } diff --git a/services/servicecatalog/serviceactions.go b/services/servicecatalog/serviceactions.go index a5da1f4eb3..d3b4fa6923 100644 --- a/services/servicecatalog/serviceactions.go +++ b/services/servicecatalog/serviceactions.go @@ -3,8 +3,10 @@ package servicecatalog import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -47,7 +49,7 @@ func parseActionParams(def map[string]string) ([]actionParam, error) { } var ps []actionParam - if err := json.Unmarshal([]byte(raw), &ps); err != nil { + if err := json.Unmarshal([]byte(raw), &ps, jsonx.V1()); err != nil { return nil, invalid("Definition Parameters is not a valid JSON list of {Name, Type}") } diff --git a/services/servicecatalog/util.go b/services/servicecatalog/util.go index 36a18ca856..d0df67925a 100644 --- a/services/servicecatalog/util.go +++ b/services/servicecatalog/util.go @@ -2,7 +2,7 @@ package servicecatalog import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "maps" "slices" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func sortedKeys[V any](m map[string]V) []string { @@ -91,6 +92,6 @@ func idemReplay[T any](b *InMemoryBackend, opName, token string, req any, do fun return res, err } -func jsonUnmarshal(s string, v any) error { return json.Unmarshal([]byte(s), v) } +func jsonUnmarshal(s string, v any) error { return json.Unmarshal([]byte(s), v, jsonx.V1()) } func awsmetaCaller(ctx context.Context) string { return awsmeta.CallerArn(ctx) } diff --git a/services/servicediscovery/discovery_test.go b/services/servicediscovery/discovery_test.go index 9a167497fb..1c1b617675 100644 --- a/services/servicediscovery/discovery_test.go +++ b/services/servicediscovery/discovery_test.go @@ -1,13 +1,14 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -20,14 +21,14 @@ func TestHandler_DiscoverInstances(t *testing.T) { require.Equal(t, http.StatusOK, nsRec.Code) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) opID := nsResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) operation := opResp["Operation"].(map[string]any) targets := operation["Targets"].(map[string]any) nsID := targets["NAMESPACE"].(string) @@ -39,7 +40,7 @@ func TestHandler_DiscoverInstances(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcData := svcResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -174,11 +175,11 @@ func TestHandler_DiscoverInstancesHealthStatusFilter(t *testing.T) { nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-discover-health"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{ @@ -187,7 +188,7 @@ func TestHandler_DiscoverInstancesHealthStatusFilter(t *testing.T) { "HealthCheckCustomConfig": map[string]any{"FailureThreshold": 1}, }) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -212,7 +213,7 @@ func TestHandler_DiscoverInstancesHealthStatusFilter(t *testing.T) { require.Equal(t, 200, recHealthy.Code) var respH map[string]any - require.NoError(t, json.Unmarshal(recHealthy.Body.Bytes(), &respH)) + require.NoError(t, json.Unmarshal(recHealthy.Body.Bytes(), &respH, jsonx.V1())) assert.Len(t, respH["Instances"].([]any), 1) assert.Equal(t, "healthy-i", respH["Instances"].([]any)[0].(map[string]any)["InstanceId"]) @@ -223,7 +224,7 @@ func TestHandler_DiscoverInstancesHealthStatusFilter(t *testing.T) { "HealthStatus": "ALL", }) var respAll map[string]any - require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &respAll)) + require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &respAll, jsonx.V1())) assert.Len(t, respAll["Instances"].([]any), 2) } @@ -235,16 +236,16 @@ func TestHandler_DiscoverInstancesQueryParameters(t *testing.T) { nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-qp"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-qp", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -264,7 +265,7 @@ func TestHandler_DiscoverInstancesQueryParameters(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insts := resp["Instances"].([]any) assert.Len(t, insts, 1) assert.Equal(t, "i-web", insts[0].(map[string]any)["InstanceId"]) @@ -287,16 +288,16 @@ func TestHandler_DiscoverInstancesOptionalParameters(t *testing.T) { nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-optparams"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-optparams", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -325,7 +326,7 @@ func TestHandler_DiscoverInstancesOptionalParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insts := resp["Instances"].([]any) require.Len(t, insts, 1, "only the instance matching both QueryParameters and OptionalParameters") assert.Equal(t, "i-blue-web", insts[0].(map[string]any)["InstanceId"]) @@ -345,7 +346,7 @@ func TestHandler_DiscoverInstancesOptionalParameters(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insts := resp["Instances"].([]any) assert.Len(t, insts, 2, "no instance matches OptionalParameters, so it's ignored") }) @@ -364,7 +365,7 @@ func TestHandler_DiscoverInstancesUnhealthyFilter(t *testing.T) { "HealthCheckCustomConfig": map[string]any{"FailureThreshold": 1}, }) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -383,7 +384,7 @@ func TestHandler_DiscoverInstancesUnhealthyFilter(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Instances"].([]any), 1) } @@ -405,7 +406,7 @@ func TestHandler_DiscoverInstancesHealthStatusIgnoredWithoutHealthCheck(t *testi "NamespaceId": nsID, }) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -420,7 +421,7 @@ func TestHandler_DiscoverInstancesHealthStatusIgnoredWithoutHealthCheck(t *testi require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["Instances"].([]any), 1, "HealthStatus must be ignored when the service has no health check") } @@ -437,7 +438,7 @@ func TestHandler_DiscoverInstancesEmptyWhenNamespaceNotFound(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["Instances"].([]any)) } @@ -471,11 +472,11 @@ func TestHandler_DiscoverInstancesRevision(t *testing.T) { createNsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "rev-ns"}) require.Equal(t, http.StatusOK, createNsRec.Code) var nsOut map[string]any - require.NoError(t, json.Unmarshal(createNsRec.Body.Bytes(), &nsOut)) + require.NoError(t, json.Unmarshal(createNsRec.Body.Bytes(), &nsOut, jsonx.V1())) opID := nsOut["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) nsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) createSvcRec := doSDRequest(t, h, "CreateService", map[string]any{ @@ -510,13 +511,13 @@ func TestHandler_DiscoverInstancesRevision(t *testing.T) { _ = nsOut var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) rev1 := out1["InstancesRevision"].(float64) // Register an instance to bump revision createSvcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "bump-svc"}) var svcOut map[string]any - require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut, jsonx.V1())) svcID := svcOut["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -532,7 +533,7 @@ func TestHandler_DiscoverInstancesRevision(t *testing.T) { }) assert.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) rev2 := out2["InstancesRevision"].(float64) assert.Greater(t, rev2, rev1) diff --git a/services/servicediscovery/dns_registrar_test.go b/services/servicediscovery/dns_registrar_test.go index 0b36407694..23ddf5549d 100644 --- a/services/servicediscovery/dns_registrar_test.go +++ b/services/servicediscovery/dns_registrar_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( gopherDNS "github.com/blackbirdworks/gopherstack/pkgs/dns" "github.com/blackbirdworks/gopherstack/pkgs/dns/dnstest" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -58,7 +59,7 @@ func createPublicDNSNamespace(t *testing.T, h *servicediscovery.Handler, name st require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) opID, ok := resp["OperationId"].(string) require.True(t, ok) @@ -66,7 +67,7 @@ func createPublicDNSNamespace(t *testing.T, h *servicediscovery.Handler, name st require.Equal(t, http.StatusOK, opRec.Code, opRec.Body.String()) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) targets := opResp["Operation"].(map[string]any)["Targets"].(map[string]any) @@ -100,7 +101,7 @@ func TestRegisterInstance_DNS_RealResolution(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code, svcRec.Body.String()) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) hostname := "svc-dns-resolve.ns-dns-resolve" @@ -146,19 +147,19 @@ func TestRegisterInstance_HTTPNamespace_NoDNSRegistration(t *testing.T) { require.Equal(t, http.StatusOK, nsRec.Code, nsRec.Body.String()) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) opID := nsResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) nsID := opResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-http", "NamespaceId": nsID}) require.Equal(t, http.StatusOK, svcRec.Code, svcRec.Body.String()) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) regRec := doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -198,7 +199,7 @@ func TestDeregisterInstance_DNS_ResyncKeepsSibling(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code, svcRec.Body.String()) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) hostname := "svc-multi.ns-multi." diff --git a/services/servicediscovery/handler.go b/services/servicediscovery/handler.go index 7ed2277ec7..3a31e66094 100644 --- a/services/servicediscovery/handler.go +++ b/services/servicediscovery/handler.go @@ -3,7 +3,7 @@ package servicediscovery import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -17,6 +17,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -90,7 +91,7 @@ func marshalPagedResponse(key string, items []map[string]any, nextToken string) resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // Handler is the HTTP handler for the AWS Cloud Map service discovery API. @@ -197,7 +198,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -434,10 +435,7 @@ var sentinelErrorCodes = sync.OnceValue(func() []struct { // just like errInvalidRequest but isn't itself a sentinel in // sentinelErrorCodes. func isMalformedRequest(err error) bool { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - - return errors.Is(err, errInvalidRequest) || errors.As(err, &syntaxErr) || errors.As(err, &typeErr) + return errors.Is(err, errInvalidRequest) || jsonx.IsSyntaxError(err) || jsonx.IsTypeError(err) } func (h *Handler) handleError(c *echo.Context, err error) error { @@ -468,7 +466,7 @@ func (h *Handler) errorResponse(c *echo.Context, errType string, err error) erro payload, _ := json.Marshal(map[string]string{ keyTypeField: errType, keyMessageField: msg, - }) + }, jsonx.V1()) return c.JSONBlob(http.StatusBadRequest, payload) } diff --git a/services/servicediscovery/handler_discovery.go b/services/servicediscovery/handler_discovery.go index baa7b789f3..5a0338de5d 100644 --- a/services/servicediscovery/handler_discovery.go +++ b/services/servicediscovery/handler_discovery.go @@ -2,8 +2,10 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type discoverInstancesRequest struct { @@ -17,7 +19,7 @@ type discoverInstancesRequest struct { func (h *Handler) handleDiscoverInstances(_ context.Context, body []byte) ([]byte, error) { var req discoverInstancesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -68,7 +70,7 @@ func (h *Handler) handleDiscoverInstances(_ context.Context, body []byte) ([]byt return json.Marshal(map[string]any{ "Instances": items, "InstancesRevision": revision, - }) + }, jsonx.V1()) } type discoverInstancesRevisionRequest struct { @@ -78,7 +80,7 @@ type discoverInstancesRevisionRequest struct { func (h *Handler) handleDiscoverInstancesRevision(_ context.Context, body []byte) ([]byte, error) { var req discoverInstancesRevisionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -97,5 +99,5 @@ func (h *Handler) handleDiscoverInstancesRevision(_ context.Context, body []byte return json.Marshal(map[string]any{ "InstancesRevision": revision, - }) + }, jsonx.V1()) } diff --git a/services/servicediscovery/handler_instances.go b/services/servicediscovery/handler_instances.go index 758891660e..5d57a7268f 100644 --- a/services/servicediscovery/handler_instances.go +++ b/services/servicediscovery/handler_instances.go @@ -2,10 +2,11 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type registerInstanceRequest struct { @@ -17,7 +18,7 @@ type registerInstanceRequest struct { func (h *Handler) handleRegisterInstance(_ context.Context, body []byte) ([]byte, error) { var req registerInstanceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -46,7 +47,7 @@ func (h *Handler) handleRegisterInstance(_ context.Context, body []byte) ([]byte return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type deregisterInstanceRequest struct { @@ -56,7 +57,7 @@ type deregisterInstanceRequest struct { func (h *Handler) handleDeregisterInstance(_ context.Context, body []byte) ([]byte, error) { var req deregisterInstanceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -73,7 +74,7 @@ func (h *Handler) handleDeregisterInstance(_ context.Context, body []byte) ([]by return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type getInstanceRequest struct { @@ -83,7 +84,7 @@ type getInstanceRequest struct { func (h *Handler) handleGetInstance(_ context.Context, body []byte) ([]byte, error) { var req getInstanceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -105,7 +106,7 @@ func (h *Handler) handleGetInstance(_ context.Context, body []byte) ([]byte, err "Id": inst.ID, keyAttributes: inst.Attributes, }, - }) + }, jsonx.V1()) } type listInstancesRequest struct { @@ -116,7 +117,7 @@ type listInstancesRequest struct { func (h *Handler) handleListInstances(_ context.Context, body []byte) ([]byte, error) { var req listInstancesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -156,7 +157,7 @@ func (h *Handler) handleListInstances(_ context.Context, body []byte) ([]byte, e resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type getInstancesHealthStatusRequest struct { @@ -170,7 +171,7 @@ type getInstancesHealthStatusRequest struct { // Instances without a recorded custom status default to HEALTHY. func (h *Handler) handleGetInstancesHealthStatus(_ context.Context, body []byte) ([]byte, error) { var req getInstancesHealthStatusRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -206,7 +207,7 @@ func (h *Handler) handleGetInstancesHealthStatus(_ context.Context, body []byte) resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type updateInstanceCustomHealthStatusRequest struct { @@ -217,7 +218,7 @@ type updateInstanceCustomHealthStatusRequest struct { func (h *Handler) handleUpdateInstanceCustomHealthStatus(_ context.Context, body []byte) error { var req updateInstanceCustomHealthStatusRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/servicediscovery/handler_list_summary_test.go b/services/servicediscovery/handler_list_summary_test.go index e0f5b05fff..ebe02a3689 100644 --- a/services/servicediscovery/handler_list_summary_test.go +++ b/services/servicediscovery/handler_list_summary_test.go @@ -1,11 +1,13 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListServices_SummaryShape locks that ListServices emits the @@ -27,7 +29,7 @@ func TestHandler_ListServices_SummaryShape(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["Services"].([]any) require.True(t, ok) require.Len(t, items, 1) diff --git a/services/servicediscovery/handler_namespaces.go b/services/servicediscovery/handler_namespaces.go index 717c37c05c..e4a54f1736 100644 --- a/services/servicediscovery/handler_namespaces.go +++ b/services/servicediscovery/handler_namespaces.go @@ -2,10 +2,11 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type dnsPropertiesRequest struct { @@ -23,7 +24,7 @@ type createHTTPNamespaceRequest struct { func (h *Handler) handleCreateHTTPNamespace(_ context.Context, body []byte) ([]byte, error) { var req createHTTPNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -44,7 +45,7 @@ func (h *Handler) handleCreateHTTPNamespace(_ context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type createPrivateDNSNamespaceRequest struct { @@ -60,7 +61,7 @@ type createPrivateDNSNamespaceRequest struct { func (h *Handler) handleCreatePrivateDNSNamespace(_ context.Context, body []byte) ([]byte, error) { var req createPrivateDNSNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -86,7 +87,7 @@ func (h *Handler) handleCreatePrivateDNSNamespace(_ context.Context, body []byte return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type createPublicDNSNamespaceRequest struct { @@ -101,7 +102,7 @@ type createPublicDNSNamespaceRequest struct { func (h *Handler) handleCreatePublicDNSNamespace(_ context.Context, body []byte) ([]byte, error) { var req createPublicDNSNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -127,7 +128,7 @@ func (h *Handler) handleCreatePublicDNSNamespace(_ context.Context, body []byte) return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type deleteNamespaceRequest struct { @@ -136,7 +137,7 @@ type deleteNamespaceRequest struct { func (h *Handler) handleDeleteNamespace(_ context.Context, body []byte) ([]byte, error) { var req deleteNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -149,7 +150,7 @@ func (h *Handler) handleDeleteNamespace(_ context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type getNamespaceRequest struct { @@ -158,7 +159,7 @@ type getNamespaceRequest struct { func (h *Handler) handleGetNamespace(_ context.Context, body []byte) ([]byte, error) { var req getNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -173,7 +174,7 @@ func (h *Handler) handleGetNamespace(_ context.Context, body []byte) ([]byte, er return json.Marshal(map[string]any{ "Namespace": namespaceToMap(ns, h.Backend.AccountID()), - }) + }, jsonx.V1()) } type namespaceFilter struct { @@ -218,7 +219,7 @@ func buildNamespacesFilter(filters []namespaceFilter) ListNamespacesFilter { func (h *Handler) handleListNamespaces(_ context.Context, body []byte) ([]byte, error) { var req listNamespacesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -306,7 +307,7 @@ type updateHTTPNamespaceRequest struct { func (h *Handler) handleUpdateHTTPNamespace(_ context.Context, body []byte) ([]byte, error) { var req updateHTTPNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -319,7 +320,7 @@ func (h *Handler) handleUpdateHTTPNamespace(_ context.Context, body []byte) ([]b return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } // dnsNamespacePropertiesChangeRequest mirrors types.PrivateDnsNamespacePropertiesChange @@ -355,7 +356,7 @@ type updatePrivateDNSNamespaceRequest struct { func (h *Handler) handleUpdatePrivateDNSNamespace(_ context.Context, body []byte) ([]byte, error) { var req updatePrivateDNSNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -370,7 +371,7 @@ func (h *Handler) handleUpdatePrivateDNSNamespace(_ context.Context, body []byte return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type updatePublicDNSNamespaceRequest struct { @@ -381,7 +382,7 @@ type updatePublicDNSNamespaceRequest struct { func (h *Handler) handleUpdatePublicDNSNamespace(_ context.Context, body []byte) ([]byte, error) { var req updatePublicDNSNamespaceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -396,7 +397,7 @@ func (h *Handler) handleUpdatePublicDNSNamespace(_ context.Context, body []byte) return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } func applyPaginationNamespaces(items []Namespace, nextToken string, maxResults int) ([]Namespace, string) { diff --git a/services/servicediscovery/handler_operations.go b/services/servicediscovery/handler_operations.go index 444bffb216..2aeff5699d 100644 --- a/services/servicediscovery/handler_operations.go +++ b/services/servicediscovery/handler_operations.go @@ -2,12 +2,13 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "time" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type getOperationRequest struct { @@ -16,7 +17,7 @@ type getOperationRequest struct { func (h *Handler) handleGetOperation(_ context.Context, body []byte) ([]byte, error) { var req getOperationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +32,7 @@ func (h *Handler) handleGetOperation(_ context.Context, body []byte) ([]byte, er return json.Marshal(map[string]any{ "Operation": operationToMap(op), - }) + }, jsonx.V1()) } type operationFilter struct { @@ -106,7 +107,7 @@ func buildOperationsFilter(filters []operationFilter) ListOperationsFilter { func (h *Handler) handleListOperations(_ context.Context, body []byte) ([]byte, error) { var req listOperationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/servicediscovery/handler_services.go b/services/servicediscovery/handler_services.go index 7c9ccaa5e1..a1489a772d 100644 --- a/services/servicediscovery/handler_services.go +++ b/services/servicediscovery/handler_services.go @@ -2,10 +2,11 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type dnsRecordRequest struct { @@ -124,7 +125,7 @@ func validateHealthCheckConfigEnum(hc *HealthCheckConfig) error { func (h *Handler) handleCreateService(_ context.Context, body []byte) ([]byte, error) { var req createServiceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -173,7 +174,7 @@ func (h *Handler) handleCreateService(_ context.Context, body []byte) ([]byte, e return json.Marshal(map[string]any{ keyService: serviceToMap(svc, h.Backend.AccountID()), - }) + }, jsonx.V1()) } type deleteServiceRequest struct { @@ -187,7 +188,7 @@ type deleteServiceRequest struct { // enforces this (returns ErrResourceInUse). func (h *Handler) handleDeleteService(_ context.Context, body []byte) error { var req deleteServiceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -204,7 +205,7 @@ type getServiceRequest struct { func (h *Handler) handleGetService(_ context.Context, body []byte) ([]byte, error) { var req getServiceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -219,7 +220,7 @@ func (h *Handler) handleGetService(_ context.Context, body []byte) ([]byte, erro return json.Marshal(map[string]any{ keyService: serviceToMap(svc, h.Backend.AccountID()), - }) + }, jsonx.V1()) } type serviceFilter struct { @@ -260,7 +261,7 @@ func buildServicesFilter(filters []serviceFilter) ListServicesFilter { func (h *Handler) handleListServices(_ context.Context, body []byte) ([]byte, error) { var req listServicesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -288,7 +289,7 @@ func (h *Handler) handleListServices(_ context.Context, body []byte) ([]byte, er resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // serviceToMap converts a Service to a JSON-serialisable map including DNS and @@ -373,7 +374,7 @@ type updateServiceRequest struct { func (h *Handler) handleUpdateService(_ context.Context, body []byte) ([]byte, error) { var req updateServiceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -401,7 +402,7 @@ func (h *Handler) handleUpdateService(_ context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]string{keyOperationID: opID}) + return json.Marshal(map[string]string{keyOperationID: opID}, jsonx.V1()) } type getServiceAttributesRequest struct { @@ -410,7 +411,7 @@ type getServiceAttributesRequest struct { func (h *Handler) handleGetServiceAttributes(_ context.Context, body []byte) ([]byte, error) { var req getServiceAttributesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -431,7 +432,7 @@ func (h *Handler) handleGetServiceAttributes(_ context.Context, body []byte) ([] "ServiceArn": arn, keyAttributes: attrs, }, - }) + }, jsonx.V1()) } type updateServiceAttributesRequest struct { @@ -441,7 +442,7 @@ type updateServiceAttributesRequest struct { func (h *Handler) handleUpdateServiceAttributes(_ context.Context, body []byte) error { var req updateServiceAttributesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -463,7 +464,7 @@ type deleteServiceAttributesRequest struct { func (h *Handler) handleDeleteServiceAttributes(_ context.Context, body []byte) error { var req deleteServiceAttributesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/servicediscovery/handler_tags.go b/services/servicediscovery/handler_tags.go index 9628901781..a0e45695ff 100644 --- a/services/servicediscovery/handler_tags.go +++ b/services/servicediscovery/handler_tags.go @@ -2,10 +2,11 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listTagsForResourceRequest struct { @@ -14,7 +15,7 @@ type listTagsForResourceRequest struct { func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]byte, error) { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -31,7 +32,7 @@ func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]b return json.Marshal(map[string]any{ keyTags: tagList, - }) + }, jsonx.V1()) } type tagResourceRequest struct { @@ -41,7 +42,7 @@ type tagResourceRequest struct { func (h *Handler) handleTagResource(_ context.Context, body []byte) ([]byte, error) { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -67,7 +68,7 @@ type untagResourceRequest struct { func (h *Handler) handleUntagResource(_ context.Context, body []byte) ([]byte, error) { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/servicediscovery/handler_test.go b/services/servicediscovery/handler_test.go index 19dc5708d9..ab894e6d16 100644 --- a/services/servicediscovery/handler_test.go +++ b/services/servicediscovery/handler_test.go @@ -2,7 +2,7 @@ package servicediscovery_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -29,7 +30,7 @@ func doSDRequest(t *testing.T, h *servicediscovery.Handler, op string, body any) if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -215,7 +216,7 @@ func TestHandler_ExtractResource(t *testing.T) { h := newTestHandler(t) e := echo.New() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -288,7 +289,7 @@ func TestServiceDiscovery_Handler_Reset(t *testing.T) { var out struct { Namespaces []any `json:"Namespaces"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Namespaces, tt.wantAfter) }) } @@ -358,13 +359,13 @@ func createNamespaceHelper(t *testing.T, h *servicediscovery.Handler, name strin require.Equal(t, 200, nsRec.Code) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) opID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) return nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) } diff --git a/services/servicediscovery/input_realism_test.go b/services/servicediscovery/input_realism_test.go index dfc81aafa9..841f1b1793 100644 --- a/services/servicediscovery/input_realism_test.go +++ b/services/servicediscovery/input_realism_test.go @@ -1,13 +1,15 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_NameAndAddressValidation(t *testing.T) { @@ -110,7 +112,7 @@ func extractFirstID(t *testing.T, body string) string { ID string `json:"Id"` } `json:"Namespaces"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) require.NotEmpty(t, out.Namespaces) return out.Namespaces[0].ID @@ -124,7 +126,7 @@ func extractServiceID(t *testing.T, body string) string { ID string `json:"Id"` } `json:"Service"` } - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) return out.Service.ID } diff --git a/services/servicediscovery/instances_test.go b/services/servicediscovery/instances_test.go index 6dbfb840a7..da227f6df5 100644 --- a/services/servicediscovery/instances_test.go +++ b/services/servicediscovery/instances_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -64,7 +65,7 @@ func TestHandler_RegisterInstance(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -160,7 +161,7 @@ func TestHandler_RegisterInstance_AttributeQuota(t *testing.T) { createRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "attr-quota-svc"}) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcID := createResp["Service"].(map[string]any)["Id"].(string) rec := doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -228,7 +229,7 @@ func TestHandler_RegisterInstance_InitHealthStatus(t *testing.T) { createRec := doSDRequest(t, h, "CreateService", body) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcID := createResp["Service"].(map[string]any)["Id"].(string) regRec := doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -239,7 +240,7 @@ func TestHandler_RegisterInstance_InitHealthStatus(t *testing.T) { statusRec := doSDRequest(t, h, "GetInstancesHealthStatus", map[string]any{"ServiceId": svcID}) require.Equal(t, http.StatusOK, statusRec.Code) var statusResp map[string]any - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp, jsonx.V1())) statuses := statusResp["Status"].(map[string]any) assert.Equal(t, tt.wantStatus, statuses["i-init-health"]) }) @@ -255,7 +256,7 @@ func TestHandler_GetInstance(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -317,7 +318,7 @@ func TestHandler_ListInstances(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -371,7 +372,7 @@ func TestHandler_DeregisterInstance(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -445,7 +446,7 @@ func TestHandler_GetInstancesHealthStatus(t *testing.T) { require.Equal(t, http.StatusOK, svcRec.Code) var svcOut map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcOut, jsonx.V1())) svc := svcOut["Service"].(map[string]any) return svc["Id"].(string) @@ -481,7 +482,7 @@ func TestHandler_GetInstancesHealthStatus(t *testing.T) { if len(tt.wantFields) > 0 { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) for _, field := range tt.wantFields { assert.Contains(t, out, field) } @@ -550,16 +551,16 @@ func TestHandler_RegisterInstanceRealOperationID(t *testing.T) { // Create namespace and service first. nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-reg"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-reg", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) // Register instance. @@ -571,7 +572,7 @@ func TestHandler_RegisterInstanceRealOperationID(t *testing.T) { require.Equal(t, 200, regRec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(regRec.Body.Bytes(), ®Resp, jsonx.V1())) opID := regResp["OperationId"].(string) assert.NotEqual(t, "op-register", opID, "must not be hardcoded op ID") @@ -582,7 +583,7 @@ func TestHandler_RegisterInstanceRealOperationID(t *testing.T) { require.Equal(t, 200, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) assert.Equal(t, "REGISTER_INSTANCE", opResp["Operation"].(map[string]any)["Type"]) } @@ -596,16 +597,16 @@ func TestHandler_DeregisterInstanceRealOperationID(t *testing.T) { // Setup. nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-dereg"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-dereg", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -622,7 +623,7 @@ func TestHandler_DeregisterInstanceRealOperationID(t *testing.T) { require.Equal(t, 200, deregRec.Code) var deregResp map[string]any - require.NoError(t, json.Unmarshal(deregRec.Body.Bytes(), &deregResp)) + require.NoError(t, json.Unmarshal(deregRec.Body.Bytes(), &deregResp, jsonx.V1())) opID := deregResp["OperationId"].(string) assert.NotEqual(t, "op-deregister", opID) @@ -632,7 +633,7 @@ func TestHandler_DeregisterInstanceRealOperationID(t *testing.T) { require.Equal(t, 200, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) assert.Equal(t, "DEREGISTER_INSTANCE", opResp["Operation"].(map[string]any)["Type"]) } @@ -646,11 +647,11 @@ func TestHandler_GetInstancesHealthStatusStoredValue(t *testing.T) { // Setup service and instances. nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-health"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{ @@ -659,7 +660,7 @@ func TestHandler_GetInstancesHealthStatusStoredValue(t *testing.T) { "HealthCheckCustomConfig": map[string]any{"FailureThreshold": 1}, }) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -683,7 +684,7 @@ func TestHandler_GetInstancesHealthStatusStoredValue(t *testing.T) { require.Equal(t, 200, statusRec.Code) var statusResp map[string]any - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp, jsonx.V1())) statuses := statusResp["Status"].(map[string]any) assert.Equal(t, "HEALTHY", statuses["inst-healthy"]) @@ -698,16 +699,16 @@ func TestHandler_GetInstancesHealthStatusFilterByIDs(t *testing.T) { nsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-filter-health"}) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) nsOpID := nsResp["OperationId"].(string) nsOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": nsOpID}) var nsOpResp map[string]any - require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp)) + require.NoError(t, json.Unmarshal(nsOpRec.Body.Bytes(), &nsOpResp, jsonx.V1())) nsID := nsOpResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-filter", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) for _, iid := range []string{"a", "b", "c"} { @@ -724,7 +725,7 @@ func TestHandler_GetInstancesHealthStatusFilterByIDs(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) statuses := resp["Status"].(map[string]any) assert.Len(t, statuses, 2) @@ -777,7 +778,7 @@ func TestHandler_GetInstancesHealthStatusUnknownInstanceID(t *testing.T) { svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-unknown-inst"}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) registerRec := doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -793,7 +794,7 @@ func TestHandler_GetInstancesHealthStatusUnknownInstanceID(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InstanceNotFound", errResp["__type"]) } }) @@ -809,7 +810,7 @@ func TestListInstances_Pagination(t *testing.T) { createSvcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-inst-page"}) require.Equal(t, http.StatusOK, createSvcRec.Code) var svcOut map[string]any - require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut, jsonx.V1())) svcID := svcOut["Service"].(map[string]any)["Id"].(string) for i := range 4 { @@ -849,7 +850,7 @@ func TestListInstances_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) insts := out["Instances"].([]any) assert.Len(t, insts, tt.wantLen) if tt.wantNextToken { @@ -896,7 +897,7 @@ func TestHandler_UpdateInstanceCustomHealthStatus(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) svcID := out["Service"].(map[string]any)["Id"].(string) regRec := doSDRequest(t, h, "RegisterInstance", map[string]any{ "ServiceId": svcID, diff --git a/services/servicediscovery/multi_region_test.go b/services/servicediscovery/multi_region_test.go index 276dc0bae1..59441204fc 100644 --- a/services/servicediscovery/multi_region_test.go +++ b/services/servicediscovery/multi_region_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -39,7 +40,7 @@ func regionCall(t *testing.T, h *servicediscovery.Handler, region, op, body stri require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/servicediscovery/namespaces_test.go b/services/servicediscovery/namespaces_test.go index 4aa28383d7..3b859cda19 100644 --- a/services/servicediscovery/namespaces_test.go +++ b/services/servicediscovery/namespaces_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -207,7 +208,7 @@ func TestHandler_GetNamespace(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) @@ -215,7 +216,7 @@ func TestHandler_GetNamespace(t *testing.T) { require.Equal(t, http.StatusOK, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) operation := opResp["Operation"].(map[string]any) targets := operation["Targets"].(map[string]any) @@ -277,14 +278,14 @@ func TestHandler_DeleteNamespace(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) operation := opResp["Operation"].(map[string]any) targets := operation["Targets"].(map[string]any) nsID := targets["NAMESPACE"].(string) @@ -336,13 +337,13 @@ func TestHandler_NamespaceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) nsID := opResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) // GetNamespace has CreateDate but never a Tags field. @@ -350,7 +351,7 @@ func TestHandler_NamespaceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ns := getResp["Namespace"].(map[string]any) assert.NotZero(t, ns["CreateDate"], "CreateDate must be present in GetNamespace response") @@ -361,7 +362,7 @@ func TestHandler_NamespaceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, tagsRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) assert.Len(t, tags, 2, "expected 2 tags") @@ -386,7 +387,7 @@ func TestHandler_ListNamespacesOmitsTags(t *testing.T) { require.Equal(t, 200, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nsList := resp["Namespaces"].([]any) require.Len(t, nsList, 1) @@ -431,13 +432,13 @@ func TestNamespace_ServiceCount(t *testing.T) { createNsRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "ns-parity"}) require.Equal(t, http.StatusOK, createNsRec.Code) var nsOp map[string]string - require.NoError(t, json.Unmarshal(createNsRec.Body.Bytes(), &nsOp)) + require.NoError(t, json.Unmarshal(createNsRec.Body.Bytes(), &nsOp, jsonx.V1())) opID := nsOp["OperationId"] opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, opRec.Code) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) nsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) for i := range tt.servicesBefore { @@ -452,7 +453,7 @@ func TestNamespace_ServiceCount(t *testing.T) { getRec := doSDRequest(t, h, "GetNamespace", map[string]any{"Id": nsID}) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) ns := getOut["Namespace"].(map[string]any) assert.Equal(t, tt.wantCount, int(ns["ServiceCount"].(float64)), "GetNamespace ServiceCount") @@ -460,7 +461,7 @@ func TestNamespace_ServiceCount(t *testing.T) { listRec := doSDRequest(t, h, "ListNamespaces", map[string]any{}) require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) nsList := listOut["Namespaces"].([]any) require.Len(t, nsList, 1) gotListCount := int(nsList[0].(map[string]any)["ServiceCount"].(float64)) @@ -512,7 +513,7 @@ func TestListNamespaces_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) nsList := out["Namespaces"].([]any) assert.Len(t, nsList, tt.wantLen) if tt.wantNextToken { @@ -559,7 +560,7 @@ func TestListNamespaces_TypeFilter(t *testing.T) { rec := doSDRequest(t, h, "ListNamespaces", req) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) nsList := out["Namespaces"].([]any) assert.Len(t, nsList, tt.wantLen, "filterType=%s", tt.filterType) }) @@ -600,7 +601,7 @@ func TestListNamespaces_HTTPNameFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Namespaces"].([]any), tt.wantLen) }) } @@ -638,7 +639,7 @@ func TestListNamespaces_ResourceOwnerFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Namespaces"].([]any), tt.wantLen) }) } @@ -663,7 +664,7 @@ func TestListNamespaces_NameBeginsWithFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Namespaces"].([]any), 2) } @@ -694,11 +695,11 @@ func TestHandler_UpdateHttpNamespace(t *testing.T) { createRec := doSDRequest(t, h, "CreateHttpNamespace", map[string]any{"Name": "http-ns"}) require.Equal(t, http.StatusOK, createRec.Code) var nsOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &nsOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &nsOut, jsonx.V1())) opID := nsOut["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) nsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) rec := doSDRequest(t, h, "UpdateHttpNamespace", map[string]any{ @@ -726,11 +727,11 @@ func TestHandler_UpdateHttpNamespace(t *testing.T) { createRec := doSDRequest(t, h, "CreatePrivateDnsNamespace", map[string]any{"Name": "private-ns"}) require.Equal(t, http.StatusOK, createRec.Code) var nsOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &nsOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &nsOut, jsonx.V1())) opID := nsOut["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) privateNsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) rec := doSDRequest(t, h, "UpdateHttpNamespace", map[string]any{ @@ -771,11 +772,11 @@ func TestHandler_UpdatePrivateDnsNamespace(t *testing.T) { case "success": createRec := doSDRequest(t, h, "CreatePrivateDnsNamespace", map[string]any{"Name": "private-ns"}) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) opID := out["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) nsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) rec := doSDRequest(t, h, "UpdatePrivateDnsNamespace", map[string]any{ "Id": nsID, @@ -825,11 +826,11 @@ func TestHandler_UpdatePublicDnsNamespace(t *testing.T) { case "success": createRec := doSDRequest(t, h, "CreatePublicDnsNamespace", map[string]any{"Name": "public-ns"}) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) opID := out["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opOut map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opOut, jsonx.V1())) nsID := opOut["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) rec := doSDRequest(t, h, "UpdatePublicDnsNamespace", map[string]any{ "Id": nsID, diff --git a/services/servicediscovery/operations_test.go b/services/servicediscovery/operations_test.go index a5c8082937..84a3755a92 100644 --- a/services/servicediscovery/operations_test.go +++ b/services/servicediscovery/operations_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -60,7 +61,7 @@ func TestHandler_GetOperation(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) rec = doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) @@ -100,7 +101,7 @@ func TestOperationCountIncrementsOnRegisterDeregister(t *testing.T) { nsID := createNamespaceHelper(t, h, "ns-opcount") svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-opcount", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) opsBefore := servicediscovery.OperationCount(b) @@ -158,7 +159,7 @@ func TestListOperations_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ops := out["Operations"].([]any) assert.Len(t, ops, tt.wantLen) if tt.wantNextToken { @@ -187,7 +188,7 @@ func TestListOperations_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ops := out["Operations"].([]any) require.Len(t, ops, 1) @@ -219,7 +220,7 @@ func TestListOperations_NamespaceAndServiceIDFilters(t *testing.T) { svcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-op-filter", "NamespaceId": nsID}) var svcResp map[string]any - require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp)) + require.NoError(t, json.Unmarshal(svcRec.Body.Bytes(), &svcResp, jsonx.V1())) svcID := svcResp["Service"].(map[string]any)["Id"].(string) doSDRequest(t, h, "RegisterInstance", map[string]any{ @@ -232,7 +233,7 @@ func TestListOperations_NamespaceAndServiceIDFilters(t *testing.T) { require.Equal(t, http.StatusOK, nsFilterRec.Code) var nsOut map[string]any - require.NoError(t, json.Unmarshal(nsFilterRec.Body.Bytes(), &nsOut)) + require.NoError(t, json.Unmarshal(nsFilterRec.Body.Bytes(), &nsOut, jsonx.V1())) assert.Len(t, nsOut["Operations"].([]any), 1, "only CREATE_NAMESPACE targets this namespace") svcFilterRec := doSDRequest(t, h, "ListOperations", map[string]any{ @@ -241,7 +242,7 @@ func TestListOperations_NamespaceAndServiceIDFilters(t *testing.T) { require.Equal(t, http.StatusOK, svcFilterRec.Code) var svcOut map[string]any - require.NoError(t, json.Unmarshal(svcFilterRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(svcFilterRec.Body.Bytes(), &svcOut, jsonx.V1())) assert.Len(t, svcOut["Operations"].([]any), 1, "only REGISTER_INSTANCE targets this service") } @@ -263,7 +264,7 @@ func TestListOperations_TypeFilterIN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Operations"].([]any), 2) } @@ -291,7 +292,7 @@ func TestListOperations_UpdateDateBetweenFilter(t *testing.T) { require.Equal(t, http.StatusOK, inRangeRec.Code) var inRangeOut map[string]any - require.NoError(t, json.Unmarshal(inRangeRec.Body.Bytes(), &inRangeOut)) + require.NoError(t, json.Unmarshal(inRangeRec.Body.Bytes(), &inRangeOut, jsonx.V1())) assert.Len(t, inRangeOut["Operations"].([]any), 1) outOfRangeRec := doSDRequest(t, h, "ListOperations", map[string]any{ @@ -309,7 +310,7 @@ func TestListOperations_UpdateDateBetweenFilter(t *testing.T) { require.Equal(t, http.StatusOK, outOfRangeRec.Code) var outOfRangeOut map[string]any - require.NoError(t, json.Unmarshal(outOfRangeRec.Body.Bytes(), &outOfRangeOut)) + require.NoError(t, json.Unmarshal(outOfRangeRec.Body.Bytes(), &outOfRangeOut, jsonx.V1())) assert.Empty(t, outOfRangeOut["Operations"].([]any)) } @@ -345,7 +346,7 @@ func TestListOperations_StatusFilter(t *testing.T) { rec := doSDRequest(t, h, "ListOperations", req) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ops := out["Operations"].([]any) assert.Len(t, ops, tt.wantLen, "filterStatus=%s", tt.filterStatus) }) diff --git a/services/servicediscovery/persistence.go b/services/servicediscovery/persistence.go index 9ca25c121d..6850445b95 100644 --- a/services/servicediscovery/persistence.go +++ b/services/servicediscovery/persistence.go @@ -2,9 +2,11 @@ package servicediscovery import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -32,7 +34,7 @@ const servicediscoverySnapshotVersion = 1 // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ServiceAttributes map[string]map[string]string `json:"serviceAttributes"` InstanceHealthStatuses map[string]string `json:"instanceHealthStatuses"` AccountID string `json:"accountID"` @@ -74,7 +76,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { OpCounter: b.opCounter, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "servicediscovery: snapshot marshal failed", "error", err) diff --git a/services/servicediscovery/persistence_test.go b/services/servicediscovery/persistence_test.go index 52ecf60c82..d02c4938e4 100644 --- a/services/servicediscovery/persistence_test.go +++ b/services/servicediscovery/persistence_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -322,7 +323,7 @@ func TestHandler_SnapshotRestore_ServiceAttributesAndHealth(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) svc := createOut["Service"].(map[string]any) svcID := svc["Id"].(string) svcARN := svc["Arn"].(string) @@ -359,7 +360,7 @@ func TestHandler_SnapshotRestore_ServiceAttributesAndHealth(t *testing.T) { getRec := doSDRequest(t, h2, "GetServiceAttributes", map[string]any{"ServiceId": svcID}) assert.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) attrs := getOut["ServiceAttributes"].(map[string]any)["Attributes"].(map[string]any) assert.Equal(t, "test", attrs["stage"]) assert.Equal(t, svcARN, getOut["ServiceAttributes"].(map[string]any)["ServiceArn"]) diff --git a/services/servicediscovery/services_test.go b/services/servicediscovery/services_test.go index 5f3d9fbf68..1d172c2d20 100644 --- a/services/servicediscovery/services_test.go +++ b/services/servicediscovery/services_test.go @@ -1,7 +1,7 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicediscovery" ) @@ -105,7 +106,7 @@ func TestHandler_GetService(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -161,7 +162,7 @@ func TestHandler_DeleteService(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcData := createResp["Service"].(map[string]any) svcID := svcData["Id"].(string) @@ -270,7 +271,7 @@ func TestHandler_ServiceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svc := createResp["Service"].(map[string]any) assert.NotContains(t, svc, "Tags", "real CreateService never returns a Tags field") @@ -282,7 +283,7 @@ func TestHandler_ServiceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) svcGet := getResp["Service"].(map[string]any) assert.NotContains(t, svcGet, "Tags", "real GetService never returns a Tags field") @@ -291,7 +292,7 @@ func TestHandler_ServiceTagsViaListTagsForResource(t *testing.T) { require.Equal(t, 200, tagsRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) assert.Len(t, tags, 1) @@ -316,7 +317,7 @@ func TestHandler_ListServicesNamespaceFilter(t *testing.T) { // List without filter - should return all 3. recAll := doSDRequest(t, h, "ListServices", map[string]any{}) var respAll map[string]any - require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &respAll)) + require.NoError(t, json.Unmarshal(recAll.Body.Bytes(), &respAll, jsonx.V1())) assert.Len(t, respAll["Services"].([]any), 3) // List with NAMESPACE_ID filter - should return only 2. @@ -328,7 +329,7 @@ func TestHandler_ListServicesNamespaceFilter(t *testing.T) { require.Equal(t, 200, recFiltered.Code) var respFiltered map[string]any - require.NoError(t, json.Unmarshal(recFiltered.Body.Bytes(), &respFiltered)) + require.NoError(t, json.Unmarshal(recFiltered.Body.Bytes(), &respFiltered, jsonx.V1())) assert.Len(t, respFiltered["Services"].([]any), 2) } @@ -450,7 +451,7 @@ func TestHandler_ListServicesResourceOwnerFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out["Services"].([]any), tt.wantLen) }) } @@ -464,13 +465,13 @@ func createPrivateDNSNamespaceHelper(t *testing.T, h *servicediscovery.Handler, require.Equal(t, http.StatusOK, nsRec.Code) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) opID := nsResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) return opResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) } @@ -555,7 +556,7 @@ func TestUpdateService_ReturnsOperationId(t *testing.T) { createRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-parity"}) require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) svcID := created["Service"].(map[string]any)["Id"].(string) rec := doSDRequest(t, h, "UpdateService", map[string]any{ @@ -565,7 +566,7 @@ func TestUpdateService_ReturnsOperationId(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tt.wantOpID { assert.NotEmpty(t, out["OperationId"], "should contain OperationId") } @@ -606,7 +607,7 @@ func TestService_InstanceCount(t *testing.T) { createSvcRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-count"}) require.Equal(t, http.StatusOK, createSvcRec.Code) var svcOut map[string]any - require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut)) + require.NoError(t, json.Unmarshal(createSvcRec.Body.Bytes(), &svcOut, jsonx.V1())) svcID := svcOut["Service"].(map[string]any)["Id"].(string) for i := range tt.instancesBefore { @@ -622,7 +623,7 @@ func TestService_InstanceCount(t *testing.T) { getRec := doSDRequest(t, h, "GetService", map[string]any{"Id": svcID}) require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) svc := getOut["Service"].(map[string]any) assert.Equal(t, tt.wantCount, int(svc["InstanceCount"].(float64)), "GetService InstanceCount") @@ -630,7 +631,7 @@ func TestService_InstanceCount(t *testing.T) { listRec := doSDRequest(t, h, "ListServices", map[string]any{}) require.Equal(t, http.StatusOK, listRec.Code) var listOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) svcs := listOut["Services"].([]any) require.Len(t, svcs, 1) gotListCount := int(svcs[0].(map[string]any)["InstanceCount"].(float64)) @@ -682,7 +683,7 @@ func TestListServices_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svcs := out["Services"].([]any) assert.Len(t, svcs, tt.wantLen) if tt.wantNextToken { @@ -703,7 +704,7 @@ func TestUpdateService_CreatesOperation(t *testing.T) { createRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "svc-op-check"}) require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) svcID := created["Service"].(map[string]any)["Id"].(string) updateRec := doSDRequest(t, h, "UpdateService", map[string]any{ @@ -713,14 +714,14 @@ func TestUpdateService_CreatesOperation(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateOut map[string]string - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateOut, jsonx.V1())) opID := updateOut["OperationId"] require.NotEmpty(t, opID) getOpRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, getOpRec.Code) var opOut map[string]any - require.NoError(t, json.Unmarshal(getOpRec.Body.Bytes(), &opOut)) + require.NoError(t, json.Unmarshal(getOpRec.Body.Bytes(), &opOut, jsonx.V1())) op := opOut["Operation"].(map[string]any) assert.Equal(t, "UPDATE_SERVICE", op["Type"]) assert.Equal(t, "SUCCESS", op["Status"]) @@ -774,7 +775,7 @@ func TestUpdateService_OmittedConfigDeletesIt(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &created, jsonx.V1())) svcID := created["Service"].(map[string]any)["Id"].(string) updateRec := doSDRequest(t, h, "UpdateService", map[string]any{ @@ -786,7 +787,7 @@ func TestUpdateService_OmittedConfigDeletesIt(t *testing.T) { getRec := doSDRequest(t, h, "GetService", map[string]any{"Id": svcID}) require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) svc := out["Service"].(map[string]any) if tt.wantDNS { @@ -835,7 +836,7 @@ func TestHandler_UpdateService(t *testing.T) { case "success": createRec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "my-svc"}) var out map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &out, jsonx.V1())) svcID := out["Service"].(map[string]any)["Id"].(string) rec := doSDRequest(t, h, "UpdateService", map[string]any{ "Id": svcID, @@ -898,7 +899,7 @@ func TestHandler_ServiceAttributes(t *testing.T) { rec := doSDRequest(t, h, "CreateService", map[string]any{"Name": "attrs-svc"}) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) svc := out["Service"].(map[string]any) return svc["Id"].(string), svc["Arn"].(string) @@ -917,7 +918,7 @@ func TestHandler_ServiceAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) sa := getOut["ServiceAttributes"].(map[string]any) attrs := sa["Attributes"].(map[string]any) assert.Equal(t, "prod", attrs["env"]) @@ -973,7 +974,7 @@ func TestHandler_ServiceAttributes(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) attrs := getOut["ServiceAttributes"].(map[string]any)["Attributes"].(map[string]any) assert.NotContains(t, attrs, "env") assert.Equal(t, "yes", attrs["keep"]) @@ -1003,7 +1004,7 @@ func TestHandler_ServiceAttributes(t *testing.T) { assert.Equal(t, tt.wantCode, getRec.Code, "body: %s", getRec.Body.String()) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) attrs := getOut["ServiceAttributes"].(map[string]any)["Attributes"] assert.Empty(t, attrs) @@ -1026,7 +1027,7 @@ func TestHandler_ServiceAttributes(t *testing.T) { assert.Equal(t, tt.wantCode, getRec.Code, "body: %s", getRec.Body.String()) var getOut map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getOut, jsonx.V1())) attrs := getOut["ServiceAttributes"].(map[string]any)["Attributes"] assert.Empty(t, attrs) } @@ -1096,7 +1097,7 @@ func TestHandler_UpdateServiceAttributesQuota(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcID := createResp["Service"].(map[string]any)["Id"].(string) if tt.presetTo > 0 { @@ -1120,7 +1121,7 @@ func TestHandler_UpdateServiceAttributesQuota(t *testing.T) { if tt.wantType != "" { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) } }) diff --git a/services/servicediscovery/tags_test.go b/services/servicediscovery/tags_test.go index 8efed4427f..8687fa2550 100644 --- a/services/servicediscovery/tags_test.go +++ b/services/servicediscovery/tags_test.go @@ -1,13 +1,15 @@ package servicediscovery_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagsLifecycle(t *testing.T) { @@ -22,14 +24,14 @@ func TestHandler_TagsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) operation := opResp["Operation"].(map[string]any) targets := operation["Targets"].(map[string]any) nsID := targets["NAMESPACE"].(string) @@ -38,7 +40,7 @@ func TestHandler_TagsLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, nsRec.Code) var nsResp map[string]any - require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp)) + require.NoError(t, json.Unmarshal(nsRec.Body.Bytes(), &nsResp, jsonx.V1())) arn := nsResp["Namespace"].(map[string]any)["Arn"].(string) rec := doSDRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) @@ -142,21 +144,21 @@ func TestHandler_TagResource_TooManyTags_Merged(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) opID := createResp["OperationId"].(string) opRec := doSDRequest(t, h, "GetOperation", map[string]any{"OperationId": opID}) require.Equal(t, http.StatusOK, opRec.Code) var opResp map[string]any - require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp)) + require.NoError(t, json.Unmarshal(opRec.Body.Bytes(), &opResp, jsonx.V1())) nsID := opResp["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) getRec := doSDRequest(t, h, "GetNamespace", map[string]any{"Id": nsID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) arn := getResp["Namespace"].(map[string]any)["Arn"].(string) firstBatch := make([]map[string]string, 0, 40) @@ -197,14 +199,14 @@ func TestMapToTagEntriesSorted(t *testing.T) { require.Equal(t, 200, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) svcARN := createResp["Service"].(map[string]any)["Arn"].(string) tagsRec := doSDRequest(t, h, "ListTagsForResource", map[string]any{"ResourceARN": svcARN}) require.Equal(t, 200, tagsRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tags := tagsResp["Tags"].([]any) require.Len(t, tags, 3) @@ -226,7 +228,7 @@ func TestHandler_ErrResourceNotFoundTagging(t *testing.T) { assert.Equal(t, 400, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } diff --git a/services/servicequotas/autonotify.go b/services/servicequotas/autonotify.go index edc4064cc4..5086969443 100644 --- a/services/servicequotas/autonotify.go +++ b/services/servicequotas/autonotify.go @@ -2,11 +2,12 @@ package servicequotas import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -151,7 +152,7 @@ func (b *InMemoryBackend) noticeFor( body, _ := json.Marshal(map[string]any{ "account": am.Account, "region": am.Region, "serviceCode": serviceCode, "quotaCode": def.Code, "quotaName": def.Name, "utilization": util, "threshold": level, "optInType": am.OptInType, - }) + }, jsonx.V1()) return pendingNotice{ topicArn: am.NotificationArn, diff --git a/services/servicequotas/catalog.go b/services/servicequotas/catalog.go index 88d1222800..ede079c8a6 100644 --- a/services/servicequotas/catalog.go +++ b/services/servicequotas/catalog.go @@ -4,11 +4,13 @@ import ( "bytes" "compress/gzip" _ "embed" // quota catalog - "encoding/json" + "encoding/json/v2" "io" "slices" "strings" "sync" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed catalog.json @@ -62,7 +64,7 @@ type Catalog struct { var defaultCatalog = sync.OnceValue(func() *Catalog { //nolint:gochecknoglobals // immutable embedded data var svcs []ServiceDef - if err := json.Unmarshal(catalogJSON, &svcs); err != nil { + if err := json.Unmarshal(catalogJSON, &svcs, jsonx.V1()); err != nil { panic("servicequotas: embedded catalog is invalid: " + err.Error()) } @@ -72,7 +74,7 @@ var defaultCatalog = sync.OnceValue(func() *Catalog { //nolint:gochecknoglobals } var docs []ServiceDef - if err = json.Unmarshal(raw, &docs); err != nil { + if err = json.Unmarshal(raw, &docs, jsonx.V1()); err != nil { panic("servicequotas: embedded docs catalog is invalid: " + err.Error()) } diff --git a/services/servicequotas/docs_catalog_test.go b/services/servicequotas/docs_catalog_test.go index d2cf99ee43..177bfb5495 100644 --- a/services/servicequotas/docs_catalog_test.go +++ b/services/servicequotas/docs_catalog_test.go @@ -4,7 +4,8 @@ import ( "bytes" "compress/gzip" _ "embed" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "regexp" "testing" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/servicequotas" ) @@ -30,7 +32,7 @@ func TestDocsCatalog_Provenance(t *testing.T) { require.NoError(t, err) var svcs []servicequotas.ServiceDef - require.NoError(t, json.Unmarshal(docsQuotas, &svcs)) + require.NoError(t, json.Unmarshal(docsQuotas, &svcs, jsonx.V1())) codeRe := regexp.MustCompile(`^L-[0-9A-F]{8}$`) seen := map[string]bool{} @@ -55,7 +57,7 @@ func TestDocsCatalog_Provenance(t *testing.T) { seen[s.Code] = true } - canon, err := json.MarshalIndent(svcs, "", " ") + canon, err := json.Marshal(svcs, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) require.NoError(t, err) assert.True(t, bytes.Equal(append(canon, '\n'), docsQuotas), "docs_quotas.json.gz is not in generator output form") } diff --git a/services/servicequotas/handler.go b/services/servicequotas/handler.go index 2a4e9bbd23..89a245723e 100644 --- a/services/servicequotas/handler.go +++ b/services/servicequotas/handler.go @@ -2,7 +2,7 @@ package servicequotas import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/worker" @@ -39,7 +40,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, fail(ErrIllegalArgument, "malformed request body: %v", err) } } diff --git a/services/servicequotas/persistence.go b/services/servicequotas/persistence.go index 4e17ce5c2a..3a18c22313 100644 --- a/services/servicequotas/persistence.go +++ b/services/servicequotas/persistence.go @@ -2,7 +2,7 @@ package servicequotas import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,11 +12,11 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Seq int64 `json:"seq"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Seq int64 `json:"seq"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/ses/deep_flows_sdk_test.go b/services/ses/deep_flows_sdk_test.go index ad57b0be1c..d6a77d33e7 100644 --- a/services/ses/deep_flows_sdk_test.go +++ b/services/ses/deep_flows_sdk_test.go @@ -1,7 +1,7 @@ package ses_test import ( - "encoding/json" + "encoding/json/v2" "sync" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -199,8 +200,8 @@ func TestEventDestination_SendAndDeliveryEvents_SDK(t *testing.T) { require.Len(t, pub.messages, 2) var send, delivery map[string]any - require.NoError(t, json.Unmarshal([]byte(pub.messages[0]), &send)) - require.NoError(t, json.Unmarshal([]byte(pub.messages[1]), &delivery)) + require.NoError(t, json.Unmarshal([]byte(pub.messages[0]), &send, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(pub.messages[1]), &delivery, jsonx.V1())) assert.Equal(t, "Send", send["eventType"]) assert.Contains(t, send, "send") assert.Equal(t, "Delivery", delivery["eventType"]) diff --git a/services/ses/email_sending.go b/services/ses/email_sending.go index 82b4653142..6f0f6f0fa7 100644 --- a/services/ses/email_sending.go +++ b/services/ses/email_sending.go @@ -1,13 +1,15 @@ package ses import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxRecipientsPerMessage is the AWS SES limit on the combined number of @@ -637,7 +639,7 @@ func (b *InMemoryBackend) SendBulkTemplatedEmail(in SendBulkTemplatedEmailInput) return nil, err } - mergedJSON, err := json.Marshal(merged) + mergedJSON, err := json.Marshal(merged, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: failed to encode template data", ErrInvalidParameter) } diff --git a/services/ses/identities.go b/services/ses/identities.go index 6bb2813d70..3b3fa11a10 100644 --- a/services/ses/identities.go +++ b/services/ses/identities.go @@ -1,12 +1,13 @@ package ses import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "net/mail" "strings" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -226,7 +227,7 @@ func (b *InMemoryBackend) PutIdentityPolicy(identity, policyName, policy string) return fmt.Errorf("%w: Policy is required", ErrInvalidParameter) } - if !json.Valid([]byte(policy)) { + if !jsontext.Value([]byte(policy)).IsValid(jsonx.V1()) { return fmt.Errorf("%w: Policy must be a valid JSON policy document", ErrInvalidPolicy) } diff --git a/services/ses/inbound_actions.go b/services/ses/inbound_actions.go index bc8f5d44b4..837d4dad23 100644 --- a/services/ses/inbound_actions.go +++ b/services/ses/inbound_actions.go @@ -3,7 +3,7 @@ package ses import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/mail" @@ -12,6 +12,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -337,7 +338,7 @@ func (r *inboundRun) lambdaAction(ctx context.Context, a ReceiptAction) (ruleFlo payload, err := json.Marshal(lambdaEvent{Records: []lambdaRecord{{ EventSource: "aws:ses", EventVersion: "1.0", SES: lambdaSES{Receipt: n.Receipt, Mail: n.Mail}, - }}}) + }}}, jsonx.V1()) if err != nil { return flowContinue, fmt.Errorf("marshal lambda event: %w", err) } @@ -356,7 +357,7 @@ func (r *inboundRun) lambdaAction(ctx context.Context, a ReceiptAction) (ruleFlo Disposition string `json:"disposition"` } - _ = json.Unmarshal(out, &resp) + _ = json.Unmarshal(out, &resp, jsonx.V1()) switch strings.ToUpper(resp.Disposition) { case "STOP_RULE": @@ -428,7 +429,7 @@ func (r *inboundRun) notify(topicARN string, n receiptNotification) error { return errInboundNoSNS } - body, err := json.Marshal(n) + body, err := json.Marshal(n, jsonx.V1()) if err != nil { return fmt.Errorf("marshal notification: %w", err) } diff --git a/services/ses/inbound_auth_test.go b/services/ses/inbound_auth_test.go index 6d1f12710c..82d6206d5a 100644 --- a/services/ses/inbound_auth_test.go +++ b/services/ses/inbound_auth_test.go @@ -9,7 +9,7 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/textproto" @@ -19,6 +19,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errNXDomain = errors.New("nxdomain") @@ -249,7 +251,7 @@ func TestInboundAuthVerdicts(t *testing.T) { } `json:"receipt"` } - require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n)) + require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n, jsonx.V1())) assert.Equal(t, tc.wantSPF, n.Receipt.SPF.Status) assert.Equal(t, tc.wantDKIM, n.Receipt.DKIM.Status) assert.Equal(t, tc.wantDMARC, n.Receipt.DMARC.Status) diff --git a/services/ses/inbound_dsn_kms_test.go b/services/ses/inbound_dsn_kms_test.go index 25720f4b99..b5a3a86c11 100644 --- a/services/ses/inbound_dsn_kms_test.go +++ b/services/ses/inbound_dsn_kms_test.go @@ -5,7 +5,7 @@ import ( "crypto/aes" "crypto/cipher" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "mime" "mime/multipart" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -173,7 +174,7 @@ func TestInboundS3KMS(t *testing.T) { assert.NotContains(t, string(ct), "body line") var mat map[string]string - require.NoError(t, json.Unmarshal([]byte(meta["x-amz-matdesc"]), &mat)) + require.NoError(t, json.Unmarshal([]byte(meta["x-amz-matdesc"]), &mat, jsonx.V1())) assert.Equal(t, "r", mat["aws:ses:rule-name"]) assert.Equal(t, log[0].MessageID, mat["aws:ses:message-id"]) diff --git a/services/ses/inbound_kms.go b/services/ses/inbound_kms.go index 389c5c2b82..ceaabe14d6 100644 --- a/services/ses/inbound_kms.go +++ b/services/ses/inbound_kms.go @@ -6,9 +6,11 @@ import ( "crypto/cipher" "crypto/rand" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -61,7 +63,7 @@ func sealEnvelope( return nil, nil, fmt.Errorf("iv: %w", err) } - matdesc, err := json.Marshal(encCtx) + matdesc, err := json.Marshal(encCtx, jsonx.V1()) if err != nil { return nil, nil, fmt.Errorf("matdesc: %w", err) } diff --git a/services/ses/inbound_spf_test.go b/services/ses/inbound_spf_test.go index 93bdfc4bc3..6ea079e483 100644 --- a/services/ses/inbound_spf_test.go +++ b/services/ses/inbound_spf_test.go @@ -2,7 +2,7 @@ package ses_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/netip" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -94,7 +95,7 @@ func deliver(t *testing.T, dns ses.InboundTXTResolver, mailFrom, msg string) ver } `json:"receipt"` } - require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n)) + require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n, jsonx.V1())) return verdictSet{spf: n.Receipt.SPF.Status, dmarc: n.Receipt.DMARC.Status} } diff --git a/services/ses/inbound_test.go b/services/ses/inbound_test.go index 4a51fc3ec1..fd1f649857 100644 --- a/services/ses/inbound_test.go +++ b/services/ses/inbound_test.go @@ -5,7 +5,7 @@ import ( "context" "crypto/tls" "encoding/base64" - "encoding/json" + "encoding/json/v2" "maps" "net/smtp" "net/textproto" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -364,7 +365,7 @@ func TestInboundNotificationShape(t *testing.T) { } `json:"receipt"` } - require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n)) + require.NoError(t, json.Unmarshal([]byte(snsF.msgs["arn:t"][0]), &n, jsonx.V1())) assert.Equal(t, "Received", n.NotificationType) assert.Equal(t, "sender@sender.test", n.Mail.Source) assert.Equal(t, []string{"user@example.com"}, n.Mail.Destination) @@ -400,7 +401,7 @@ func TestInboundNotificationShape(t *testing.T) { } `json:"Records"` } - require.NoError(t, json.Unmarshal(lam.payloads[0], &ev)) + require.NoError(t, json.Unmarshal(lam.payloads[0], &ev, jsonx.V1())) require.Len(t, ev.Records, 1) assert.Equal(t, "aws:ses", ev.Records[0].EventSource) assert.Equal(t, "Lambda", ev.Records[0].SES.Receipt.Action.Type) diff --git a/services/ses/multi_region_test.go b/services/ses/multi_region_test.go index a766d038cd..91479af8b0 100644 --- a/services/ses/multi_region_test.go +++ b/services/ses/multi_region_test.go @@ -1,7 +1,8 @@ package ses_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ses" ) @@ -161,9 +163,9 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(t.Context()) - var doc map[string]json.RawMessage + var doc map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &doc)) + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) _, hasRegions := doc["regions"] assert.Equal(t, tc.wantRegions, hasRegions) diff --git a/services/ses/notifications.go b/services/ses/notifications.go index 24d3b7c752..f73baacd34 100644 --- a/services/ses/notifications.go +++ b/services/ses/notifications.go @@ -1,10 +1,12 @@ package ses import ( - "encoding/json" + "encoding/json/v2" "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // sesNotificationMail is the "mail" object of an SES SNS notification. @@ -100,7 +102,7 @@ func buildSESNotificationPayload( } // map[string]any marshaling of these concrete field types cannot fail. - bs, _ := json.Marshal(data) + bs, _ := json.Marshal(data, jsonx.V1()) return bs } diff --git a/services/ses/persistence.go b/services/ses/persistence.go index 537f698a19..74e3c159da 100644 --- a/services/ses/persistence.go +++ b/services/ses/persistence.go @@ -2,11 +2,13 @@ package ses import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -88,7 +90,7 @@ func newDirtyDTORegistry() ( // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Policies map[string]map[string]string `json:"policies,omitempty"` ActiveRuleSet string `json:"activeRuleSet,omitempty"` Region string `json:"region,omitempty"` @@ -159,7 +161,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { AccountID: b.accountID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ses: failed to marshal snapshot", "error", err) @@ -234,7 +236,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // configSets, trackingOptions, eventDestinations) from tables via the // ephemeral DTO registry, converting each DTO back to its live type. The // caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, idDTOs, csDTOs, toDTOs, edDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/ses/templates.go b/services/ses/templates.go index f283d2072e..41d793596b 100644 --- a/services/ses/templates.go +++ b/services/ses/templates.go @@ -1,12 +1,13 @@ package ses import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "strings" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -117,7 +118,7 @@ func parseTemplateData(templateData string) (map[string]string, error) { } raw := map[string]any{} - if err := json.Unmarshal([]byte(templateData), &raw); err != nil { + if err := json.Unmarshal([]byte(templateData), &raw, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: TemplateData must be valid JSON", ErrInvalidParameter) } diff --git a/services/sesv2/account_test.go b/services/sesv2/account_test.go index e9a58c31bf..91d0da0095 100644 --- a/services/sesv2/account_test.go +++ b/services/sesv2/account_test.go @@ -1,7 +1,7 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,8 @@ import ( sesv2types "github.com/aws/aws-sdk-go-v2/service/sesv2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestGetAccount tests the GetAccount operation. @@ -114,7 +116,7 @@ func TestGetBlacklistReports(t *testing.T) { var out struct { BlacklistReport map[string][]string `json:"BlacklistReport"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out.BlacklistReport, "1.2.3.4") assert.Contains(t, out.BlacklistReport, "5.6.7.8") assert.Empty(t, out.BlacklistReport["1.2.3.4"]) diff --git a/services/sesv2/configuration_sets_test.go b/services/sesv2/configuration_sets_test.go index 7b816d8ab9..91d9fa8fb1 100644 --- a/services/sesv2/configuration_sets_test.go +++ b/services/sesv2/configuration_sets_test.go @@ -1,13 +1,14 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -33,7 +34,7 @@ func TestConfigSetTrackingOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tracking, ok := out["TrackingOptions"].(map[string]any) require.True(t, ok, "TrackingOptions should be present in GetConfigurationSet response") @@ -74,7 +75,7 @@ func TestConfigSetDeliveryOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) delivery, ok := out["DeliveryOptions"].(map[string]any) require.True(t, ok, "DeliveryOptions should be present") @@ -113,7 +114,7 @@ func TestConfigSetSendingOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) sending, ok := out["SendingOptions"].(map[string]any) require.True(t, ok, "SendingOptions should be present") @@ -150,7 +151,7 @@ func TestConfigSetReputationOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) rep, ok := out["ReputationOptions"].(map[string]any) require.True(t, ok, "ReputationOptions should be present") @@ -187,7 +188,7 @@ func TestConfigSetSuppressionOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) supp, ok := out["SuppressionOptions"].(map[string]any) require.True(t, ok, "SuppressionOptions should be present") @@ -234,7 +235,7 @@ func TestGetConfigurationSetDefaultSendingEnabled(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) sending, ok := out["SendingOptions"].(map[string]any) require.True(t, ok, "SendingOptions always present in GetConfigurationSet") @@ -265,7 +266,7 @@ func TestConfigSetMultipleOptions(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "multi-cs", out["ConfigurationSetName"]) assert.NotNil(t, out["TrackingOptions"]) @@ -635,7 +636,7 @@ func TestGetConfigurationSet(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.csName, out["ConfigurationSetName"]) } }) @@ -668,7 +669,7 @@ func TestListConfigurationSets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) sets, ok := out["ConfigurationSets"].([]any) require.True(t, ok) diff --git a/services/sesv2/deep_flows_sdk_test.go b/services/sesv2/deep_flows_sdk_test.go index 322781aacf..c8c7f0fdb6 100644 --- a/services/sesv2/deep_flows_sdk_test.go +++ b/services/sesv2/deep_flows_sdk_test.go @@ -1,7 +1,7 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "sync" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -125,8 +126,8 @@ func TestSendEmail_SNSEventDestination_SDK(t *testing.T) { assert.Equal(t, []string{topic, topic}, pub.topics) var send, delivery map[string]any - require.NoError(t, json.Unmarshal([]byte(pub.messages[0]), &send)) - require.NoError(t, json.Unmarshal([]byte(pub.messages[1]), &delivery)) + require.NoError(t, json.Unmarshal([]byte(pub.messages[0]), &send, jsonx.V1())) + require.NoError(t, json.Unmarshal([]byte(pub.messages[1]), &delivery, jsonx.V1())) assert.Equal(t, "Send", send["eventType"]) assert.Equal(t, "Delivery", delivery["eventType"]) diff --git a/services/sesv2/deliverability_test.go b/services/sesv2/deliverability_test.go index c313bc92ff..503ab7b08f 100644 --- a/services/sesv2/deliverability_test.go +++ b/services/sesv2/deliverability_test.go @@ -1,7 +1,7 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -95,7 +96,7 @@ func TestPutDeliverabilityDashboardOption(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, true, out["DashboardEnabled"]) assert.Equal(t, "ACTIVE", out["AccountStatus"]) @@ -138,7 +139,7 @@ func TestGetDeliverabilityTestReport(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) reportID := createResp["ReportId"].(string) rec := doReq(t, h, http.MethodGet, "/v2/email/deliverability-dashboard/test-reports/"+reportID, nil) @@ -188,7 +189,7 @@ func TestGetDomainDeliverabilityCampaign(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) campaign, ok := out["DomainDeliverabilityCampaign"].(map[string]any) require.True(t, ok, "response missing DomainDeliverabilityCampaign wrapper: %s", rec.Body) @@ -267,7 +268,7 @@ func TestGetEmailAddressInsights(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) validation, ok := out["MailboxValidation"].(map[string]any) require.True(t, ok, "response missing MailboxValidation: %s", rec.Body) diff --git a/services/sesv2/email_identities_test.go b/services/sesv2/email_identities_test.go index a7a48b5bb0..0eeea5880e 100644 --- a/services/sesv2/email_identities_test.go +++ b/services/sesv2/email_identities_test.go @@ -1,7 +1,7 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -32,7 +33,7 @@ func TestPutEmailIdentityConfigurationSetAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "my-cs", out["ConfigurationSetName"]) } @@ -67,7 +68,7 @@ func TestPutEmailIdentityDkimAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) dkim, ok := out["DkimAttributes"].(map[string]any) require.True(t, ok, "DkimAttributes should be present") @@ -145,7 +146,7 @@ func TestPutEmailIdentityDkimSigningAttributes(t *testing.T) { DkimStatus string `json:"DkimStatus"` DkimTokens []string `json:"DkimTokens"` } - err := json.Unmarshal(rec.Body.Bytes(), &resp) + err := json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1()) require.NoError(t, err) assert.Equal(t, tt.wantDkimStat, resp.DkimStatus) if tt.wantTokens { @@ -177,7 +178,7 @@ func TestPutEmailIdentityFeedbackAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, false, out["FeedbackForwardingStatus"]) } @@ -214,7 +215,7 @@ func TestPutEmailIdentityMailFromAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) mailFrom, ok := out["MailFromAttributes"].(map[string]any) require.True(t, ok, "MailFromAttributes should be present after setting mail-from domain") @@ -256,7 +257,7 @@ func TestPutEmailIdentityMailFromClear(t *testing.T) { rec := doReq(t, h, http.MethodGet, "/v2/email/identities/mfclear%40example.com", nil) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // MailFromAttributes should be absent when domain is empty. assert.Nil(t, out["MailFromAttributes"]) @@ -277,7 +278,7 @@ func TestGetEmailIdentityDefaults(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out, "EmailIdentity") assert.Equal(t, "EMAIL_ADDRESS", out["IdentityType"]) @@ -304,7 +305,7 @@ func TestGetEmailIdentityDomainHasDkimTokens(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "DOMAIN", out["IdentityType"]) @@ -335,7 +336,7 @@ func TestGetEmailIdentityEmailAddressNoDkimTokens(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) dkim, ok := out["DkimAttributes"].(map[string]any) require.True(t, ok) @@ -357,7 +358,7 @@ func TestCreateEmailIdentityWithConfigSet(t *testing.T) { rec = doReq(t, h, http.MethodGet, "/v2/email/identities/tagged%40example.com", nil) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "my-cs", out["ConfigurationSetName"]) } @@ -378,7 +379,7 @@ func TestCreateEmailIdentityWithTags(t *testing.T) { rec = doReq(t, h, http.MethodGet, "/v2/email/identities/tagged2%40example.com", nil) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tags, ok := out["Tags"].([]any) require.True(t, ok, "Tags should be returned") @@ -397,7 +398,7 @@ func TestCreateDomainIdentityReturnsDkimAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Domain identities should return DkimAttributes with tokens in create response. dkim, ok := out["DkimAttributes"].(map[string]any) @@ -420,7 +421,7 @@ func TestCreateEmailAddressDoesNotReturnDkimAttributes(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Email addresses should not return DkimAttributes in create response. assert.Nil(t, out["DkimAttributes"], "Email address CreateEmailIdentity should omit DkimAttributes") @@ -442,7 +443,7 @@ func TestGetEmailIdentityPoliciesIncludedInGet(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) policies, ok := out["Policies"].(map[string]any) require.True(t, ok, "Policies should be returned in GetEmailIdentity") @@ -943,7 +944,7 @@ func TestCreateEmailIdentity(t *testing.T) { if tt.wantType != "" { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantType, out["IdentityType"]) assert.Equal(t, true, out["VerifiedForSendingStatus"]) } @@ -994,7 +995,7 @@ func TestGetEmailIdentity(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out, "EmailIdentity") } }) @@ -1027,7 +1028,7 @@ func TestListEmailIdentities(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) identities, ok := out["EmailIdentities"].([]any) require.True(t, ok) diff --git a/services/sesv2/email_templates.go b/services/sesv2/email_templates.go index 828f141b12..947dce07dc 100644 --- a/services/sesv2/email_templates.go +++ b/services/sesv2/email_templates.go @@ -1,7 +1,7 @@ package sesv2 import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -9,6 +9,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -187,7 +188,7 @@ func parseTemplateVars(data string) (map[string]string, error) { } raw := map[string]any{} - if err := json.Unmarshal([]byte(data), &raw); err != nil { + if err := json.Unmarshal([]byte(data), &raw, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: TemplateData must be valid JSON", ErrInvalidInput) } diff --git a/services/sesv2/email_templates_test.go b/services/sesv2/email_templates_test.go index 964c99b6fe..09d89eb958 100644 --- a/services/sesv2/email_templates_test.go +++ b/services/sesv2/email_templates_test.go @@ -1,13 +1,14 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -141,7 +142,7 @@ func TestGetEmailTemplate_RendersTags(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Tags, 1) assert.Equal(t, "team", resp.Tags[0].Key) assert.Equal(t, "sec", resp.Tags[0].Value) diff --git a/services/sesv2/event_publishing.go b/services/sesv2/event_publishing.go index dfd17277df..1d40b9f1f7 100644 --- a/services/sesv2/event_publishing.go +++ b/services/sesv2/event_publishing.go @@ -1,10 +1,12 @@ package sesv2 import ( - "encoding/json" + "encoding/json/v2" "net/mail" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type eventMail struct { @@ -63,7 +65,7 @@ func (b *InMemoryBackend) publishSendEvents(email Email) { } if slices.Contains(d.MatchingEventTypes, "SEND") { - payload, _ := json.Marshal(map[string]any{"eventType": "Send", "mail": m, "send": struct{}{}}) + payload, _ := json.Marshal(map[string]any{"eventType": "Send", "mail": m, "send": struct{}{}}, jsonx.V1()) _ = pub.PublishToTopic(d.SnsDestination.TopicArn, string(payload)) } @@ -71,7 +73,7 @@ func (b *InMemoryBackend) publishSendEvents(email Email) { payload, _ := json.Marshal(map[string]any{ "eventType": "Delivery", "mail": m, "delivery": eventDelivery{Timestamp: ts, Recipients: email.To}, - }) + }, jsonx.V1()) _ = pub.PublishToTopic(d.SnsDestination.TopicArn, string(payload)) } } diff --git a/services/sesv2/export_jobs_test.go b/services/sesv2/export_jobs_test.go index e82ea88f07..b9e24e9f08 100644 --- a/services/sesv2/export_jobs_test.go +++ b/services/sesv2/export_jobs_test.go @@ -1,13 +1,14 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -127,7 +128,7 @@ func TestGetExportJob(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp["JobId"].(string) rec := doRequest(t, h, http.MethodGet, "/v2/email/export-jobs/"+jobID, nil) @@ -249,7 +250,7 @@ func TestCreateExportJobWireShape(t *testing.T) { } var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID, ok := createResp["JobId"].(string) require.True(t, ok) @@ -257,7 +258,7 @@ func TestCreateExportJobWireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.wantSource, getResp["ExportSourceType"]) }) } @@ -285,7 +286,7 @@ func TestCancelExportJobAfterCreate(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp["JobId"].(string) rec := doRequest(t, h, http.MethodPut, "/v2/email/export-jobs/"+jobID+"/cancel", nil) diff --git a/services/sesv2/handler_account.go b/services/sesv2/handler_account.go index 6994f49515..1548c71be3 100644 --- a/services/sesv2/handler_account.go +++ b/services/sesv2/handler_account.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // account handlers @@ -45,7 +48,7 @@ func (h *Handler) handlePutAccountDedicatedIPWarmupAttributes(c *echo.Context) ( AutoWarmupEnabled bool `json:"AutoWarmupEnabled"` } - _ = json.NewDecoder(c.Request().Body).Decode(&in) + _ = json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()) if err := h.Backend.PutAccountDedicatedIPWarmupAttributes(in.AutoWarmupEnabled); err != nil { return nil, err @@ -67,7 +70,7 @@ type putAccountDetailsInput struct { func (h *Handler) handlePutAccountDetails(c *echo.Context) (any, error) { var in putAccountDetailsInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -90,7 +93,7 @@ type putAccountSendingInput struct { func (h *Handler) handlePutAccountSendingAttributes(c *echo.Context) (any, error) { var in putAccountSendingInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -107,7 +110,7 @@ func (h *Handler) handlePutAccountPricingAttributes(c *echo.Context) (any, error Plan string `json:"Plan"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -123,7 +126,7 @@ func (h *Handler) handlePutAccountSuppressionAttributes(c *echo.Context) (any, e SuppressedReasons []string `json:"SuppressedReasons"` } - _ = json.NewDecoder(c.Request().Body).Decode(&in) + _ = json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()) if err := h.Backend.PutAccountSuppressionAttributes(in.SuppressedReasons); err != nil { return nil, err diff --git a/services/sesv2/handler_configuration_sets.go b/services/sesv2/handler_configuration_sets.go index 35e426ea45..8acac37d63 100644 --- a/services/sesv2/handler_configuration_sets.go +++ b/services/sesv2/handler_configuration_sets.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createConfigurationSetInput struct { @@ -203,7 +206,7 @@ type listConfigurationSetsOutput struct { func (h *Handler) handleCreateConfigurationSet(c *echo.Context) (any, error) { var in createConfigurationSetInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidParameter, err.Error()) } @@ -313,7 +316,7 @@ func (h *Handler) handlePutConfigurationSetArchivingOptions( ArchiveARN string `json:"ArchiveArn"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -332,7 +335,7 @@ func (h *Handler) handlePutConfigurationSetDeliveryOptions( TLSPolicy string `json:"TlsPolicy"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -351,7 +354,7 @@ func (h *Handler) handlePutConfigurationSetReputationOptions( ReputationMetricsEnabled bool `json:"ReputationMetricsEnabled"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -369,7 +372,7 @@ func (h *Handler) handlePutConfigurationSetSendingOptions( SendingEnabled bool `json:"SendingEnabled"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -382,7 +385,7 @@ func (h *Handler) handlePutConfigurationSetSuppressionOptions( ) (any, error) { var in suppressionOptionsInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -403,7 +406,7 @@ func (h *Handler) handlePutConfigurationSetTrackingOptions( HTTPSPolicy string `json:"HttpsPolicy"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_contact_lists.go b/services/sesv2/handler_contact_lists.go index 3e81a74f9c..9c746c9a00 100644 --- a/services/sesv2/handler_contact_lists.go +++ b/services/sesv2/handler_contact_lists.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // topicInput mirrors types.Topic. @@ -38,7 +41,7 @@ type createContactListInput struct { func (h *Handler) handleCreateContactList(c *echo.Context) (any, error) { var in createContactListInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -78,7 +81,7 @@ type updateContactListInput struct { func (h *Handler) handleUpdateContactList(c *echo.Context, name string) (any, error) { var in updateContactListInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_contacts.go b/services/sesv2/handler_contacts.go index 0e4c7ee5cd..7515241c9e 100644 --- a/services/sesv2/handler_contacts.go +++ b/services/sesv2/handler_contacts.go @@ -1,12 +1,15 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/url" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createContactInput struct { @@ -19,7 +22,7 @@ type createContactInput struct { func (h *Handler) handleCreateContact(c *echo.Context, contactListName string) (any, error) { var in createContactInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -106,7 +109,7 @@ func (h *Handler) handleUpdateContact(c *echo.Context, contactListName string) ( var in updateContactInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -136,7 +139,7 @@ type listContactsInput struct { func (h *Handler) handleListContacts(c *echo.Context, contactListName string) (any, error) { var in listContactsInput - _ = json.NewDecoder(c.Request().Body).Decode(&in) + _ = json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()) var filter ContactFilter if in.Filter != nil { diff --git a/services/sesv2/handler_custom_verification_email_templates.go b/services/sesv2/handler_custom_verification_email_templates.go index c11aad56fb..c879df6040 100644 --- a/services/sesv2/handler_custom_verification_email_templates.go +++ b/services/sesv2/handler_custom_verification_email_templates.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createCustomVerificationEmailTemplateInput struct { @@ -19,7 +22,7 @@ type createCustomVerificationEmailTemplateInput struct { func (h *Handler) handleCreateCustomVerificationEmailTemplate(c *echo.Context) (any, error) { var in createCustomVerificationEmailTemplateInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -72,7 +75,7 @@ func (h *Handler) handleUpdateCustomVerificationEmailTemplate( ) (any, error) { var in updateCustomVerificationEmailTemplateInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_dedicated_ip_pools.go b/services/sesv2/handler_dedicated_ip_pools.go index 17dad99596..5bea4486f8 100644 --- a/services/sesv2/handler_dedicated_ip_pools.go +++ b/services/sesv2/handler_dedicated_ip_pools.go @@ -1,11 +1,14 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createDedicatedIPPoolInput struct { @@ -17,7 +20,7 @@ type createDedicatedIPPoolInput struct { func (h *Handler) handleCreateDedicatedIPPool(c *echo.Context) (any, error) { var in createDedicatedIPPoolInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -73,7 +76,7 @@ func (h *Handler) handlePutDedicatedIPPoolScalingAttributes( ) (any, error) { var in putDedicatedIPPoolScalingInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_dedicated_ips.go b/services/sesv2/handler_dedicated_ips.go index a2b91fdff0..f57365ccb8 100644 --- a/services/sesv2/handler_dedicated_ips.go +++ b/services/sesv2/handler_dedicated_ips.go @@ -1,11 +1,14 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetDedicatedIP(ip string) (any, error) { @@ -41,7 +44,7 @@ type putDedicatedIPInPoolInput struct { func (h *Handler) handlePutDedicatedIPInPool(c *echo.Context, ip string) (any, error) { var in putDedicatedIPInPoolInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -59,7 +62,7 @@ type putDedicatedIPWarmupInput struct { func (h *Handler) handlePutDedicatedIPWarmupAttributes(c *echo.Context, ip string) (any, error) { var in putDedicatedIPWarmupInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_deliverability.go b/services/sesv2/handler_deliverability.go index e46169d814..8f71204485 100644 --- a/services/sesv2/handler_deliverability.go +++ b/services/sesv2/handler_deliverability.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createDeliverabilityTestReportInput struct { @@ -20,7 +23,7 @@ type createDeliverabilityTestReportOutput struct { func (h *Handler) handleCreateDeliverabilityTestReport(c *echo.Context) (any, error) { var in createDeliverabilityTestReportInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -245,7 +248,7 @@ func (h *Handler) handleUpdateReputationEntityCustomerManagedStatus( ) (any, error) { var in updateReputationEntityCustomerManagedStatusInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -270,7 +273,7 @@ func (h *Handler) handleUpdateReputationEntityPolicy( ) (any, error) { var in updateReputationEntityPolicyInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_email_identities.go b/services/sesv2/handler_email_identities.go index 98bf818707..18707a512f 100644 --- a/services/sesv2/handler_email_identities.go +++ b/services/sesv2/handler_email_identities.go @@ -1,12 +1,15 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/url" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- request types ---- @@ -71,7 +74,7 @@ type listEmailIdentitiesOutput struct { func (h *Handler) handleCreateEmailIdentity(c *echo.Context) (any, error) { var in createEmailIdentityInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidParameter, err.Error()) } @@ -178,7 +181,7 @@ func (h *Handler) handleCreateEmailIdentityPolicy(c *echo.Context, identity stri var in createEmailIdentityPolicyInput - if decErr := json.NewDecoder(c.Request().Body).Decode(&in); decErr != nil { + if decErr := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); decErr != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, decErr.Error()) } @@ -233,7 +236,7 @@ func (h *Handler) handleUpdateEmailIdentityPolicy(c *echo.Context, identity stri var in createEmailIdentityPolicyInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -254,7 +257,7 @@ func (h *Handler) handlePutEmailIdentityConfigurationSetAttributes( ConfigurationSetName string `json:"ConfigurationSetName"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -272,7 +275,7 @@ func (h *Handler) handlePutEmailIdentityDkimAttributes( SigningEnabled bool `json:"SigningEnabled"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -307,7 +310,7 @@ func (h *Handler) handlePutEmailIdentityFeedbackAttributes( EmailForwardingEnabled bool `json:"EmailForwardingEnabled"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -326,7 +329,7 @@ func (h *Handler) handlePutEmailIdentityMailFromAttributes( BehaviorOnMxFailure string `json:"BehaviorOnMxFailure"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_email_templates.go b/services/sesv2/handler_email_templates.go index 25bae5f9cc..60df1ca005 100644 --- a/services/sesv2/handler_email_templates.go +++ b/services/sesv2/handler_email_templates.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createEmailTemplateInput struct { @@ -16,7 +19,7 @@ type createEmailTemplateInput struct { func (h *Handler) handleCreateEmailTemplate(c *echo.Context) (any, error) { var in createEmailTemplateInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -54,7 +57,7 @@ type updateEmailTemplateInput struct { func (h *Handler) handleUpdateEmailTemplate(c *echo.Context, name string) (any, error) { var in updateEmailTemplateInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -87,7 +90,7 @@ type testRenderEmailTemplateInput struct { func (h *Handler) handleTestRenderEmailTemplate(c *echo.Context, name string) (any, error) { var in testRenderEmailTemplateInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_event_destinations.go b/services/sesv2/handler_event_destinations.go index 607045887c..c5628bedb2 100644 --- a/services/sesv2/handler_event_destinations.go +++ b/services/sesv2/handler_event_destinations.go @@ -1,12 +1,15 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/url" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // eventDestinationDefinitionInput mirrors types.EventDestinationDefinition. @@ -87,7 +90,7 @@ func (h *Handler) handleCreateConfigurationSetEventDestination( ) (any, error) { var in createConfigurationSetEventDestinationInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -156,7 +159,7 @@ func (h *Handler) handleUpdateConfigurationSetEventDestination( var in updateConfigurationSetEventDestinationInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_export_jobs.go b/services/sesv2/handler_export_jobs.go index 0c13805e75..dc7092473a 100644 --- a/services/sesv2/handler_export_jobs.go +++ b/services/sesv2/handler_export_jobs.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCancelExportJob(jobID string) (any, error) { @@ -25,8 +28,8 @@ func (h *Handler) handleCancelExportJob(jobID string) (any, error) { // accepted opaquely via json.RawMessage rather than decoded into a typed // shape -- only which branch was set is used, to derive ExportSourceType. type exportDataSourceInput struct { - MetricsDataSource json.RawMessage `json:"MetricsDataSource,omitempty"` - MessageInsightsDataSource json.RawMessage `json:"MessageInsightsDataSource,omitempty"` + MetricsDataSource jsontext.Value `json:"MetricsDataSource,omitempty"` + MessageInsightsDataSource jsontext.Value `json:"MessageInsightsDataSource,omitempty"` } // sourceType validates that exactly one branch is set (real SES v2 requires @@ -65,7 +68,7 @@ type createExportJobInput struct { func (h *Handler) handleCreateExportJob(c *echo.Context) (any, error) { var in createExportJobInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_identity_certificates.go b/services/sesv2/handler_identity_certificates.go index 3a04ad1f3e..1e7a64261f 100644 --- a/services/sesv2/handler_identity_certificates.go +++ b/services/sesv2/handler_identity_certificates.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type identityCertificateOutput struct { @@ -19,7 +22,7 @@ type listEmailIdentityCertificatesOutput struct { } func decodeBody(c *echo.Context, in any) error { - if err := json.NewDecoder(c.Request().Body).Decode(in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), in, jsonx.V1()); err != nil { return fmt.Errorf("%w: invalid request body: %s", ErrInvalidParameter, err.Error()) } diff --git a/services/sesv2/handler_import_jobs.go b/services/sesv2/handler_import_jobs.go index c5fa97bcfe..3aa9e24806 100644 --- a/services/sesv2/handler_import_jobs.go +++ b/services/sesv2/handler_import_jobs.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // importDataSourceInput mirrors types.ImportDataSource. Both members are @@ -85,7 +88,7 @@ type createImportJobInput struct { func (h *Handler) handleCreateImportJob(c *echo.Context) (any, error) { var in createImportJobInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_message_insights.go b/services/sesv2/handler_message_insights.go index 250dbb23dd..df874d0538 100644 --- a/services/sesv2/handler_message_insights.go +++ b/services/sesv2/handler_message_insights.go @@ -1,13 +1,15 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type batchGetMetricDataInput struct { @@ -49,7 +51,7 @@ func epochSecondsToTime(f float64) time.Time { func (h *Handler) handleBatchGetMetricData(c *echo.Context) (any, error) { var in batchGetMetricDataInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_multi_region_endpoints.go b/services/sesv2/handler_multi_region_endpoints.go index d823ca2a58..2a4473dcbd 100644 --- a/services/sesv2/handler_multi_region_endpoints.go +++ b/services/sesv2/handler_multi_region_endpoints.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // multi-region endpoint handlers @@ -22,7 +25,7 @@ type createMultiRegionEndpointInput struct { func (h *Handler) handleCreateMultiRegionEndpoint(c *echo.Context) (any, error) { var in createMultiRegionEndpointInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_page_size.go b/services/sesv2/handler_page_size.go index f6b141a8c5..e7b3d82bcc 100644 --- a/services/sesv2/handler_page_size.go +++ b/services/sesv2/handler_page_size.go @@ -1,11 +1,14 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strconv" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func queryPageSize(c *echo.Context) int { @@ -36,7 +39,7 @@ func listRequestParams(c *echo.Context) listParams { PageSize int `json:"PageSize"` } - _ = json.NewDecoder(c.Request().Body).Decode(&in) + _ = json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()) return listParams{Filter: in.Filter, NextToken: in.NextToken, PageSize: max(in.PageSize, 0)} } diff --git a/services/sesv2/handler_send_email.go b/services/sesv2/handler_send_email.go index 3cb7ae87e4..4627213428 100644 --- a/services/sesv2/handler_send_email.go +++ b/services/sesv2/handler_send_email.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type sendEmailInput struct { @@ -69,7 +72,7 @@ type sendEmailOutput struct { func (h *Handler) handleSendEmail(c *echo.Context) (any, error) { var in sendEmailInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidParameter, err.Error()) } @@ -137,7 +140,7 @@ type sendBulkEmailInput struct { func (h *Handler) handleSendBulkEmail(c *echo.Context) (any, error) { var in sendBulkEmailInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } @@ -168,7 +171,7 @@ type sendCustomVerificationEmailInput struct { func (h *Handler) handleSendCustomVerificationEmail(c *echo.Context) (any, error) { var in sendCustomVerificationEmailInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_suppression.go b/services/sesv2/handler_suppression.go index c07f037d17..65c097e61c 100644 --- a/services/sesv2/handler_suppression.go +++ b/services/sesv2/handler_suppression.go @@ -1,12 +1,15 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strconv" "time" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // suppressed destination handlers @@ -20,7 +23,7 @@ type putSuppressedDestinationInput struct { func (h *Handler) handlePutSuppressedDestination(c *echo.Context) (any, error) { var in putSuppressedDestinationInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_tags.go b/services/sesv2/handler_tags.go index df8a19dd0b..e12af4d07d 100644 --- a/services/sesv2/handler_tags.go +++ b/services/sesv2/handler_tags.go @@ -1,11 +1,14 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type listTagsOutput struct { @@ -38,7 +41,7 @@ type tagResourceInput struct { func (h *Handler) handleTagResource(c *echo.Context) (any, error) { var in tagResourceInput - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid body", ErrInvalidInput) } diff --git a/services/sesv2/handler_tenants.go b/services/sesv2/handler_tenants.go index 7640713565..78e80d42b4 100644 --- a/services/sesv2/handler_tenants.go +++ b/services/sesv2/handler_tenants.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Tenant handlers. @@ -18,7 +21,7 @@ import ( // no {Placeholder} segments for this family at all). func decodeSESv2Body(c *echo.Context, v any) error { - if err := json.NewDecoder(c.Request().Body).Decode(v); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), v, jsonx.V1()); err != nil { return fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/handler_test.go b/services/sesv2/handler_test.go index f40cc54d34..d2d8b6cbe5 100644 --- a/services/sesv2/handler_test.go +++ b/services/sesv2/handler_test.go @@ -2,7 +2,7 @@ package sesv2_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -34,7 +35,7 @@ func doRequest( var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) @@ -366,7 +367,7 @@ func TestSESv2Handler_ErrorResponseIncludesType(t *testing.T) { assert.Equal(t, http.StatusNotFound, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal( t, "NotFoundException", @@ -399,7 +400,7 @@ func TestSESv2Handler_URLEncodedIdentity(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotContains(t, out, "EmailIdentity") // DELETE using percent-encoded path. diff --git a/services/sesv2/handler_update_configuration_set.go b/services/sesv2/handler_update_configuration_set.go index 2d33455ed8..a81d484a9a 100644 --- a/services/sesv2/handler_update_configuration_set.go +++ b/services/sesv2/handler_update_configuration_set.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // messageSecurityOptions mirrors types.MessageSecurityOptions: SigningScheme is @@ -55,7 +58,7 @@ func (h *Handler) handleUpdateConfigurationSet(c *echo.Context) (any, error) { ConfigurationSetName string `json:"ConfigurationSetName"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidParameter, err.Error()) } diff --git a/services/sesv2/handler_vdm.go b/services/sesv2/handler_vdm.go index a669266bfe..f9fa3979e3 100644 --- a/services/sesv2/handler_vdm.go +++ b/services/sesv2/handler_vdm.go @@ -1,10 +1,13 @@ package sesv2 import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handlePutAccountVdmAttributes(c *echo.Context) (any, error) { @@ -12,7 +15,7 @@ func (h *Handler) handlePutAccountVdmAttributes(c *echo.Context) (any, error) { VdmAttributes map[string]any `json:"VdmAttributes"` } - _ = json.NewDecoder(c.Request().Body).Decode(&in) + _ = json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()) if err := h.Backend.PutAccountVdmAttributes(in.VdmAttributes); err != nil { return nil, err @@ -32,7 +35,7 @@ func (h *Handler) handlePutConfigurationSetVdmOptions( } `json:"VdmOptions"` } - if err := json.NewDecoder(c.Request().Body).Decode(&in); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &in, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid request body: %s", ErrInvalidInput, err.Error()) } diff --git a/services/sesv2/import_jobs_test.go b/services/sesv2/import_jobs_test.go index e27e72f29a..8d948989c2 100644 --- a/services/sesv2/import_jobs_test.go +++ b/services/sesv2/import_jobs_test.go @@ -1,12 +1,14 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestCreateImportJob tests the CreateImportJob operation. @@ -48,7 +50,7 @@ func TestGetImportJob(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) jobID := createResp["JobId"].(string) rec := doRequest(t, h, http.MethodGet, "/v2/email/import-jobs/"+jobID, nil) @@ -175,7 +177,7 @@ func TestCreateImportJobWireShape(t *testing.T) { } var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) jobID, ok := createResp["JobId"].(string) require.True(t, ok) @@ -183,7 +185,7 @@ func TestCreateImportJobWireShape(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) dest, ok := getResp["ImportDestination"].(map[string]any) require.True(t, ok) diff --git a/services/sesv2/message_insights_test.go b/services/sesv2/message_insights_test.go index 61db9bebbd..6fc0528984 100644 --- a/services/sesv2/message_insights_test.go +++ b/services/sesv2/message_insights_test.go @@ -2,7 +2,7 @@ package sesv2_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -123,7 +124,7 @@ func TestGetMessageInsights(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp, jsonx.V1())) messageID, _ := sendResp["MessageId"].(string) require.NotEmpty(t, messageID) @@ -131,7 +132,7 @@ func TestGetMessageInsights(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, messageID, out["MessageId"]) assert.Equal(t, "sender@example.com", out["FromEmailAddress"]) diff --git a/services/sesv2/multi_region_test.go b/services/sesv2/multi_region_test.go index 67b72d4a12..21a1f1ce1c 100644 --- a/services/sesv2/multi_region_test.go +++ b/services/sesv2/multi_region_test.go @@ -2,7 +2,7 @@ package sesv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -38,7 +39,7 @@ func regionCall(t *testing.T, h *sesv2.Handler, region, method, path, body strin out := map[string]any{} if rec.Body.Len() > 0 { - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) } return out diff --git a/services/sesv2/persistence.go b/services/sesv2/persistence.go index ee03c7a1a0..9f5118d926 100644 --- a/services/sesv2/persistence.go +++ b/services/sesv2/persistence.go @@ -2,9 +2,11 @@ package sesv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -29,7 +31,7 @@ const sesv2SnapshotVersion = 1 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` EmailIdentityPolicies map[string]map[string]string `json:"emailIdentityPolicies"` ResourceTags map[string]map[string]string `json:"resourceTags"` MultiRegionEndpoints map[string]map[string]any `json:"multiRegionEndpoints"` @@ -101,7 +103,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { DeliverabilityDashboardDomains: b.deliverabilityDashboardDomains, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "sesv2: failed to marshal snapshot", "error", err) diff --git a/services/sesv2/realism_test.go b/services/sesv2/realism_test.go index 6c46e6a502..0334b717f4 100644 --- a/services/sesv2/realism_test.go +++ b/services/sesv2/realism_test.go @@ -1,13 +1,15 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func errBody(t *testing.T, body []byte) (string, string) { @@ -17,7 +19,7 @@ func errBody(t *testing.T, body []byte) (string, string) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out.Type, out.Message } diff --git a/services/sesv2/send_email_test.go b/services/sesv2/send_email_test.go index b9fe48c4c1..c8a8670c9f 100644 --- a/services/sesv2/send_email_test.go +++ b/services/sesv2/send_email_test.go @@ -1,7 +1,7 @@ package sesv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -408,7 +409,7 @@ func TestSendEmail(t *testing.T) { if tt.wantCode == http.StatusOK { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["MessageId"]) emails := h.Backend.ListEmails() diff --git a/services/sesv2/smtp_relay_test.go b/services/sesv2/smtp_relay_test.go index cebb0f6820..409ee3562c 100644 --- a/services/sesv2/smtp_relay_test.go +++ b/services/sesv2/smtp_relay_test.go @@ -3,7 +3,7 @@ package sesv2_test import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "log/slog" "mime" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/smtprelay/smtptest" "github.com/blackbirdworks/gopherstack/services/sesv2" @@ -147,7 +148,7 @@ func TestSMTPRelayDelivery(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) sess := nextSession(t, srv) msg, err := mail.ReadMessage(strings.NewReader(sess.Data)) @@ -195,7 +196,7 @@ func TestSMTPRelayRespectsRejectionAndFailure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["MessageId"]) _ = nextSession(t, srv) diff --git a/services/sesv2/store_test.go b/services/sesv2/store_test.go index dbcca5bfec..748064e0d0 100644 --- a/services/sesv2/store_test.go +++ b/services/sesv2/store_test.go @@ -2,7 +2,8 @@ package sesv2_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http/httptest" "testing" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sesv2" ) @@ -79,7 +81,7 @@ func doReq( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -110,7 +112,7 @@ func doReqQuery( var buf bytes.Buffer if body != nil { - require.NoError(t, json.NewEncoder(&buf).Encode(body)) + require.NoError(t, json.MarshalEncode(jsontext.NewEncoder(&buf, jsonx.V1()), body)) } req := httptest.NewRequest(method, path, &buf) @@ -140,7 +142,7 @@ func decodeJSON(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &m, jsonx.V1())) return m } diff --git a/services/sesv2/whitebox_test.go b/services/sesv2/whitebox_test.go index 20a9888ce3..2a1dd59e84 100644 --- a/services/sesv2/whitebox_test.go +++ b/services/sesv2/whitebox_test.go @@ -2,7 +2,7 @@ package sesv2 import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "reflect" @@ -12,6 +12,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // wantCreationTimeTagValue is the tag value newTaggableTenant/ @@ -82,7 +84,7 @@ func TestCreateOpsWithTags_CreationTimeTagsRoundTrip(t *testing.T) { func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body any) *httptest.ResponseRecorder { t.Helper() - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(method, path, bytes.NewReader(b)) diff --git a/services/shield/errors_test.go b/services/shield/errors_test.go index bb798b64f5..96b7c5c17f 100644 --- a/services/shield/errors_test.go +++ b/services/shield/errors_test.go @@ -1,7 +1,7 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -20,7 +21,7 @@ func wireErrorType(t *testing.T, body []byte) string { var env struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(body, &env)) + require.NoError(t, json.Unmarshal(body, &env, jsonx.V1())) return env.Type } diff --git a/services/shield/handler.go b/services/shield/handler.go index d95464abcb..a5fdd10c27 100644 --- a/services/shield/handler.go +++ b/services/shield/handler.go @@ -3,7 +3,7 @@ package shield import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -394,10 +395,7 @@ func shieldErrorRules() []shieldErrorRule { // treated the same as InvalidParameterException since they never reach a specific handler's own // validation. Unrecognized errors fall back to InternalErrorException/500. func classifyShieldError(err error) (string, int) { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - - if errors.As(err, &syntaxErr) || errors.As(err, &typeErr) { + if jsonx.IsSyntaxError(err) || jsonx.IsTypeError(err) { return codeInvalidParameterException, http.StatusBadRequest } @@ -415,7 +413,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: code, keyMessageField: messageWithoutCode(code, err), - }) + }, jsonx.V1()) return c.JSONBlob(status, payload) } @@ -452,7 +450,7 @@ func decodeOffsetToken(token string) (int, error) { } var t offsetToken - if unmarshalErr := json.Unmarshal(raw, &t); unmarshalErr != nil || t.O < 0 { + if unmarshalErr := json.Unmarshal(raw, &t, jsonx.V1()); unmarshalErr != nil || t.O < 0 { return 0, errInvalidPaginationToken } @@ -461,7 +459,7 @@ func decodeOffsetToken(token string) (int, error) { // encodeOffsetToken encodes an integer cursor as an opaque base64url(JSON) string. func encodeOffsetToken(offset int) string { - data, _ := json.Marshal(offsetToken{O: offset}) + data, _ := json.Marshal(offsetToken{O: offset}, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(data) } diff --git a/services/shield/handler_application_layer_automatic_response.go b/services/shield/handler_application_layer_automatic_response.go index 7803e2a560..8046c95013 100644 --- a/services/shield/handler_application_layer_automatic_response.go +++ b/services/shield/handler_application_layer_automatic_response.go @@ -1,8 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // alarAction is the nested action object in ALAR requests. @@ -31,7 +33,7 @@ func alarActionString(a alarAction) (string, error) { func (h *Handler) handleEnableApplicationLayerAutomaticResponse(body []byte) error { var req alarRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -54,7 +56,7 @@ type disableALARRequest struct { func (h *Handler) handleDisableApplicationLayerAutomaticResponse(body []byte) error { var req disableALARRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -67,7 +69,7 @@ func (h *Handler) handleDisableApplicationLayerAutomaticResponse(body []byte) er func (h *Handler) handleUpdateApplicationLayerAutomaticResponse(body []byte) error { var req alarRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/shield/handler_attacks.go b/services/shield/handler_attacks.go index 816fb1f272..c364887bf5 100644 --- a/services/shield/handler_attacks.go +++ b/services/shield/handler_attacks.go @@ -1,8 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // listAttacksTimeRange mirrors the AWS Shield TimeRange wire format for ListAttacks. @@ -24,7 +26,7 @@ type listAttacksRequest struct { func (h *Handler) handleListAttacks(body []byte) ([]byte, error) { var req listAttacksRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -89,7 +91,7 @@ func (h *Handler) handleListAttacks(body []byte) ([]byte, error) { resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // simulateAttackRequest is the request body for the __SimulateAttack endpoint (gap 25). @@ -101,7 +103,7 @@ type simulateAttackRequest struct { // handleSimulateAttack creates a synthetic attack record via the chaos endpoint (gap 25/10). func (h *Handler) handleSimulateAttack(body []byte) ([]byte, error) { var req simulateAttackRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -119,7 +121,7 @@ func (h *Handler) handleSimulateAttack(body []byte) ([]byte, error) { keyResourceArn: attack.ResourceARN, keyStartTime: floatSeconds(attack.StartTime), keyEndTime: floatSeconds(attack.EndTime), - }) + }, jsonx.V1()) } // describeAttackRequest is the request body for DescribeAttack. @@ -129,7 +131,7 @@ type describeAttackRequest struct { func (h *Handler) handleDescribeAttack(body []byte) ([]byte, error) { var req describeAttackRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -174,7 +176,7 @@ func (h *Handler) handleDescribeAttack(body []byte) ([]byte, error) { "AttackCounters": counters, "Mitigations": mitigations, }, - }) + }, jsonx.V1()) } func (h *Handler) handleDescribeAttackStatistics() ([]byte, error) { @@ -187,5 +189,5 @@ func (h *Handler) handleDescribeAttackStatistics() ([]byte, error) { "ToExclusive": float64(stats.TimeRange.ToExclusive), }, "DataItems": stats.DataItems, - }) + }, jsonx.V1()) } diff --git a/services/shield/handler_attacks_test.go b/services/shield/handler_attacks_test.go index 1d9da2956c..ba648aa825 100644 --- a/services/shield/handler_attacks_test.go +++ b/services/shield/handler_attacks_test.go @@ -1,7 +1,7 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -25,7 +26,7 @@ func TestHandler_DescribeAttackStatisticsFlatResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasWrapper := resp["AttackStatistics"] assert.False(t, hasWrapper, "response must NOT be wrapped in 'AttackStatistics'") @@ -48,7 +49,7 @@ func TestHandler_DescribeAttackStatisticsTimeRangeIsFloat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tr := resp["TimeRange"].(map[string]any) @@ -83,7 +84,7 @@ func TestHandler_ListAttacksStartTimeRangeObject(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Len(t, summaries, 1, "StartTime TimeRange object must be accepted") @@ -107,7 +108,7 @@ func TestHandler_ListAttacksEndTimeRangeObject(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Len(t, summaries, 1, "EndTime TimeRange object must be accepted") @@ -131,7 +132,7 @@ func TestHandler_ListAttacksEndTimeRangeFiltersOut(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Empty(t, summaries, "attacks after ToExclusive must be excluded") @@ -157,7 +158,7 @@ func TestHandler_ListAttacksEndTimeExclusiveBoundary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Empty(t, summaries, "an attack starting exactly at ToExclusive must be excluded, not included") @@ -181,7 +182,7 @@ func TestHandler_ListAttacksDefaultMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Len(t, summaries, 20, "omitted MaxResults must default to 20 per the documented default") @@ -209,7 +210,7 @@ func TestHandler_ListAttacksOpaquePageToken(t *testing.T) { NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.NextToken) offset := opaqueOffset(t, out.NextToken) @@ -274,7 +275,7 @@ func TestHandler_DescribeAttack(t *testing.T) { if tt.wantFields { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) attack, ok := result["Attack"].(map[string]any) require.True(t, ok) assert.Equal(t, id, attack["AttackId"]) @@ -323,7 +324,7 @@ func TestHandler_DescribeAttackStatistics(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) items, ok := result["DataItems"].([]any) require.True(t, ok) @@ -350,7 +351,7 @@ func TestHandler_AttackRichFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // No "AttackVectors" key: types.AttackDetail (shield@v1.37.4 types/types.go) // has no such member -- that's AttackSummary's field (ListAttacks), see @@ -379,7 +380,7 @@ func TestHandler_ListAttacksMultipleARNs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Len(t, summaries, 2) @@ -404,7 +405,7 @@ func TestHandler_ListAttacksPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) assert.Len(t, summaries, 2) @@ -427,7 +428,7 @@ func TestHandler_DescribeAttackStatisticsWithVolume(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["TimeRange"]) assert.NotNil(t, resp["DataItems"]) @@ -447,7 +448,7 @@ func TestHandler_DescribeAttackStatisticsEmptyWhenNoAttacks(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["DataItems"].([]any) assert.Len(t, items, 1) @@ -467,7 +468,7 @@ func TestHandler_AttackTimestampIsFloat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) atk := raw["Attack"].(map[string]any) st, ok := atk["StartTime"].(float64) @@ -494,7 +495,7 @@ func TestHandler_SimulateAttackHTTPEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["AttackId"]) assert.Equal(t, 1, shield.AttackCount(b)) @@ -533,7 +534,7 @@ func TestHandler_AttackSimulationEndToEnd(t *testing.T) { require.Equal(t, http.StatusOK, simRec.Code) var simResp map[string]any - require.NoError(t, json.Unmarshal(simRec.Body.Bytes(), &simResp)) + require.NoError(t, json.Unmarshal(simRec.Body.Bytes(), &simResp, jsonx.V1())) attackID := simResp["AttackId"].(string) // ListAttacks must show it. @@ -541,7 +542,7 @@ func TestHandler_AttackSimulationEndToEnd(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) summaries := listResp["AttackSummaries"].([]any) require.Len(t, summaries, 1) @@ -550,7 +551,7 @@ func TestHandler_AttackSimulationEndToEnd(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) atk := descResp["Attack"].(map[string]any) _, hasVectors := atk["AttackVectors"] assert.False(t, hasVectors, "types.AttackDetail has no AttackVectors member") @@ -562,7 +563,7 @@ func TestHandler_AttackSimulationEndToEnd(t *testing.T) { require.Equal(t, http.StatusOK, statsRec.Code) var statsResp map[string]any - require.NoError(t, json.Unmarshal(statsRec.Body.Bytes(), &statsResp)) + require.NoError(t, json.Unmarshal(statsRec.Body.Bytes(), &statsResp, jsonx.V1())) items := statsResp["DataItems"].([]any) require.NotEmpty(t, items) @@ -585,7 +586,7 @@ func TestHandler_ListAttacksIncludesVectors(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["AttackSummaries"].([]any) require.Len(t, summaries, 1) diff --git a/services/shield/handler_drt.go b/services/shield/handler_drt.go index 9483764cc8..5fd8dd55a6 100644 --- a/services/shield/handler_drt.go +++ b/services/shield/handler_drt.go @@ -1,8 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // associateDRTLogBucketRequest is the request body for AssociateDRTLogBucket. @@ -12,7 +14,7 @@ type associateDRTLogBucketRequest struct { func (h *Handler) handleAssociateDRTLogBucket(body []byte) error { var req associateDRTLogBucketRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -34,7 +36,7 @@ type disassociateDRTLogBucketRequest struct { func (h *Handler) handleDisassociateDRTLogBucket(body []byte) error { var req disassociateDRTLogBucketRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -52,7 +54,7 @@ type associateDRTRoleRequest struct { func (h *Handler) handleAssociateDRTRole(body []byte) error { var req associateDRTRoleRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -83,5 +85,5 @@ func (h *Handler) handleDescribeDRTAccess() ([]byte, error) { resp["RoleArn"] = access.RoleArn } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/shield/handler_drt_test.go b/services/shield/handler_drt_test.go index b813bc4507..d6abb5cee4 100644 --- a/services/shield/handler_drt_test.go +++ b/services/shield/handler_drt_test.go @@ -1,13 +1,14 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -150,7 +151,7 @@ func TestHandler_DescribeDRTAccess(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) if tt.wantRoleArn != "" { assert.Equal(t, tt.wantRoleArn, result["RoleArn"]) diff --git a/services/shield/handler_emergency_contacts.go b/services/shield/handler_emergency_contacts.go index a6fcb098ae..07b707d3dc 100644 --- a/services/shield/handler_emergency_contacts.go +++ b/services/shield/handler_emergency_contacts.go @@ -1,8 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // emergencyContactItem represents a single emergency contact in the API request/response. @@ -19,7 +21,7 @@ type associateProactiveEngagementRequest struct { func (h *Handler) handleAssociateProactiveEngagementDetails(body []byte) error { var req associateProactiveEngagementRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -57,7 +59,7 @@ type updateEmergencyContactSettingsRequest struct { func (h *Handler) handleUpdateEmergencyContactSettings(body []byte) error { var req updateEmergencyContactSettingsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -80,5 +82,5 @@ func (h *Handler) handleDescribeEmergencyContactSettings() ([]byte, error) { return json.Marshal(map[string]any{ "EmergencyContactList": items, - }) + }, jsonx.V1()) } diff --git a/services/shield/handler_health_checks.go b/services/shield/handler_health_checks.go index 30b61d4f09..5a84873fda 100644 --- a/services/shield/handler_health_checks.go +++ b/services/shield/handler_health_checks.go @@ -1,9 +1,11 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // validateHealthCheckARN checks that the ARN is a Route 53 health check ARN. @@ -27,7 +29,7 @@ type associateHealthCheckRequest struct { func (h *Handler) handleAssociateHealthCheck(body []byte) error { var req associateHealthCheckRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -54,7 +56,7 @@ type disassociateHealthCheckRequest struct { func (h *Handler) handleDisassociateHealthCheck(body []byte) error { var req disassociateHealthCheckRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/shield/handler_protection_groups.go b/services/shield/handler_protection_groups.go index 98bf2ae4c3..24e820c1ee 100644 --- a/services/shield/handler_protection_groups.go +++ b/services/shield/handler_protection_groups.go @@ -1,9 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -19,7 +20,7 @@ type createProtectionGroupRequest struct { func (h *Handler) handleCreateProtectionGroup(body []byte) error { var req createProtectionGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -50,7 +51,7 @@ type describeProtectionGroupRequest struct { func (h *Handler) handleDescribeProtectionGroup(body []byte) ([]byte, error) { var req describeProtectionGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -65,7 +66,7 @@ func (h *Handler) handleDescribeProtectionGroup(body []byte) ([]byte, error) { return json.Marshal(map[string]any{ "ProtectionGroup": protectionGroupToMap(pg), - }) + }, jsonx.V1()) } // listProtectionGroupsRequest is the request body for ListProtectionGroups. @@ -83,7 +84,7 @@ type listProtectionGroupsRequest struct { func (h *Handler) handleListProtectionGroups(body []byte) ([]byte, error) { var req listProtectionGroupsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -108,7 +109,7 @@ func (h *Handler) handleListProtectionGroups(body []byte) ([]byte, error) { } if start >= len(groups) { - return json.Marshal(map[string]any{"ProtectionGroups": []map[string]any{}}) + return json.Marshal(map[string]any{"ProtectionGroups": []map[string]any{}}, jsonx.V1()) } end := start + maxResults @@ -134,7 +135,7 @@ func (h *Handler) handleListProtectionGroups(body []byte) ([]byte, error) { resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // protectionGroupMatchesFilters returns true if pg passes all filter sets. @@ -200,7 +201,7 @@ type updateProtectionGroupRequest struct { func (h *Handler) handleUpdateProtectionGroup(body []byte) error { var req updateProtectionGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -246,7 +247,7 @@ type deleteProtectionGroupRequest struct { func (h *Handler) handleDeleteProtectionGroup(body []byte) error { var req deleteProtectionGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -266,7 +267,7 @@ type listResourcesInProtectionGroupRequest struct { func (h *Handler) handleListResourcesInProtectionGroup(body []byte) ([]byte, error) { var req listResourcesInProtectionGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -287,7 +288,7 @@ func (h *Handler) handleListResourcesInProtectionGroup(body []byte) ([]byte, err } if start >= len(arns) { - return json.Marshal(map[string]any{"ResourceArns": []string{}}) + return json.Marshal(map[string]any{"ResourceArns": []string{}}, jsonx.V1()) } end := start + maxResults @@ -306,5 +307,5 @@ func (h *Handler) handleListResourcesInProtectionGroup(body []byte) ([]byte, err resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/shield/handler_protection_groups_test.go b/services/shield/handler_protection_groups_test.go index ed5475512b..5dcd3e3a21 100644 --- a/services/shield/handler_protection_groups_test.go +++ b/services/shield/handler_protection_groups_test.go @@ -1,7 +1,7 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -181,7 +182,7 @@ func TestHandler_ListProtectionGroupsOpaquePageToken(t *testing.T) { NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.NextToken) offset := opaqueOffset(t, out.NextToken) @@ -213,7 +214,7 @@ func TestHandler_ListProtectionGroupsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ProtectionGroups"].([]any) assert.Len(t, groups, 2) @@ -247,7 +248,7 @@ func TestHandler_ListProtectionGroupsDefaultMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ProtectionGroups"].([]any) assert.Len(t, groups, 20, "omitted MaxResults must default to 20 per the documented default") @@ -281,7 +282,7 @@ func TestHandler_ListProtectionGroupsInclusionFilterByPattern(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ProtectionGroups"].([]any) assert.Len(t, groups, 1) @@ -311,7 +312,7 @@ func TestHandler_ListProtectionGroupsInclusionFilterByAggregation(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["ProtectionGroups"].([]any) assert.Len(t, groups, 1) @@ -346,7 +347,7 @@ func TestHandler_ListResourcesInProtectionGroupPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arns := resp["ResourceArns"].([]any) assert.Len(t, arns, 20, "omitted MaxResults must default to 20 per the documented default") @@ -363,7 +364,7 @@ func TestHandler_ListResourcesInProtectionGroupPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2["ResourceArns"].([]any), 5, "the remaining 5 of 25 members must be on the next page") assert.NotContains(t, resp2, "NextToken", "no further page should be signaled once all members are returned") } diff --git a/services/shield/handler_protections.go b/services/shield/handler_protections.go index ee5f27a0e1..022985f656 100644 --- a/services/shield/handler_protections.go +++ b/services/shield/handler_protections.go @@ -2,10 +2,11 @@ package shield import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -57,7 +58,7 @@ type createProtectionRequest struct { func (h *Handler) handleCreateProtection(ctx context.Context, body []byte) ([]byte, error) { var req createProtectionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -89,7 +90,7 @@ func (h *Handler) handleCreateProtection(ctx context.Context, body []byte) ([]by return json.Marshal(map[string]string{ "ProtectionId": p.ID, - }) + }, jsonx.V1()) } // describeProtectionRequest is the request body for DescribeProtection. @@ -100,7 +101,7 @@ type describeProtectionRequest struct { func (h *Handler) handleDescribeProtection(body []byte) ([]byte, error) { var req describeProtectionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +118,7 @@ func (h *Handler) handleDescribeProtection(body []byte) ([]byte, error) { return json.Marshal(map[string]any{ "Protection": protectionToMap(p, alarCfg), - }) + }, jsonx.V1()) } // deleteProtectionRequest is the request body for DeleteProtection. @@ -127,7 +128,7 @@ type deleteProtectionRequest struct { func (h *Handler) handleDeleteProtection(ctx context.Context, body []byte) error { var req deleteProtectionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -159,7 +160,7 @@ type listProtectionsRequest struct { func (h *Handler) handleListProtections(body []byte) ([]byte, error) { var req listProtectionsRequest if len(body) > 0 { - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } } @@ -183,7 +184,7 @@ func (h *Handler) handleListProtections(body []byte) ([]byte, error) { } if start >= len(protections) { - return json.Marshal(map[string]any{"Protections": []map[string]any{}}) + return json.Marshal(map[string]any{"Protections": []map[string]any{}}, jsonx.V1()) } end := start + maxResults @@ -210,7 +211,7 @@ func (h *Handler) handleListProtections(body []byte) ([]byte, error) { resp["NextToken"] = nextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // protectionMatchesFilters returns true if p passes all inclusion filter sets. diff --git a/services/shield/handler_protections_test.go b/services/shield/handler_protections_test.go index 1ac0442782..eac841da60 100644 --- a/services/shield/handler_protections_test.go +++ b/services/shield/handler_protections_test.go @@ -2,7 +2,7 @@ package shield_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -78,7 +79,7 @@ func TestHandler_CreateProtection(t *testing.T) { if tt.wantID { var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.NotEmpty(t, result["ProtectionId"]) } }) @@ -156,7 +157,7 @@ func TestHandler_DescribeProtection(t *testing.T) { if tt.wantName != "" { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) prot, ok := result["Protection"].(map[string]any) require.True(t, ok) assert.Equal(t, tt.wantName, prot["Name"]) @@ -256,7 +257,7 @@ func TestHandler_ListProtections(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) protections, ok := result["Protections"].([]any) require.True(t, ok) @@ -285,7 +286,7 @@ func TestHandler_ListProtectionsOpaquePageToken(t *testing.T) { NextToken string `json:"NextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.NotEmpty(t, out.NextToken) offset := opaqueOffset(t, out.NextToken) @@ -319,7 +320,7 @@ func TestHandler_ApplyProtectionFiltersNoBacking(t *testing.T) { Protections []map[string]any `json:"Protections"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtered)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &filtered, jsonx.V1())) assert.Len(t, filtered.Protections, 1) // Unfiltered list must still return all three. @@ -330,7 +331,7 @@ func TestHandler_ApplyProtectionFiltersNoBacking(t *testing.T) { Protections []map[string]any `json:"Protections"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &all)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &all, jsonx.V1())) assert.Len(t, all.Protections, 3) } @@ -351,7 +352,7 @@ func TestHandler_ProtectionResponseIncludesALAR(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prot := resp["Protection"].(map[string]any) alarRaw, ok := prot["ApplicationLayerAutomaticResponseConfiguration"] @@ -378,7 +379,7 @@ func TestHandler_ProtectionWithoutALARHasNoConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prot := resp["Protection"].(map[string]any) _, hasALAR := prot["ApplicationLayerAutomaticResponseConfiguration"] @@ -410,7 +411,7 @@ func TestHandler_ListProtectionsPagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prots := resp["Protections"].([]any) assert.Len(t, prots, 2) @@ -445,7 +446,7 @@ func TestHandler_ListProtectionsDefaultMaxResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prots := resp["Protections"].([]any) assert.Len(t, prots, 20, "omitted MaxResults must default to 20 per the documented default") @@ -475,7 +476,7 @@ func TestHandler_ListProtectionsNextPage(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) token := resp1["NextToken"].(string) // Second page. @@ -486,7 +487,7 @@ func TestHandler_ListProtectionsNextPage(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) prots2 := resp2["Protections"].([]any) assert.Len(t, prots2, 2) @@ -516,7 +517,7 @@ func TestHandler_ListProtectionsInclusionFilterByARN(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prots := resp["Protections"].([]any) assert.Len(t, prots, 2) @@ -542,7 +543,7 @@ func TestHandler_ListProtectionsInclusionFilterByName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prots := resp["Protections"].([]any) assert.Len(t, prots, 1) @@ -643,7 +644,7 @@ func TestHandler_ALARInListProtections(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) prots := resp["Protections"].([]any) require.Len(t, prots, 1) diff --git a/services/shield/handler_subscription.go b/services/shield/handler_subscription.go index d7d81351a6..af2c76d01b 100644 --- a/services/shield/handler_subscription.go +++ b/services/shield/handler_subscription.go @@ -2,12 +2,13 @@ package shield import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -91,7 +92,7 @@ func (h *Handler) handleDescribeSubscription() ([]byte, error) { "Limits": subscriptionResourceLimits(), "SubscriptionLimits": subscriptionLimits(), }, - }) + }, jsonx.V1()) } // updateSubscriptionRequest is the request body for UpdateSubscription. @@ -101,7 +102,7 @@ type updateSubscriptionRequest struct { func (h *Handler) handleUpdateSubscription(body []byte) error { var req updateSubscriptionRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -117,7 +118,7 @@ func (h *Handler) handleGetSubscriptionState() ([]byte, error) { return json.Marshal(map[string]string{ "SubscriptionState": state, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteSubscription() error { diff --git a/services/shield/handler_subscription_test.go b/services/shield/handler_subscription_test.go index 5ed4973029..bd4722540b 100644 --- a/services/shield/handler_subscription_test.go +++ b/services/shield/handler_subscription_test.go @@ -1,7 +1,7 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -79,7 +80,7 @@ func TestHandler_DescribeSubscription(t *testing.T) { if tt.wantField != "" { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Contains(t, result, tt.wantField) } }) @@ -102,7 +103,7 @@ func TestHandler_DescribeSubscription_TimeCommitmentInSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) sub, ok := result["Subscription"].(map[string]any) require.True(t, ok, "response must include a Subscription object") @@ -148,7 +149,7 @@ func TestHandler_GetSubscriptionState(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, tt.wantState, result["SubscriptionState"]) }) } @@ -202,7 +203,7 @@ func TestHandler_DescribeSubscriptionFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sub := resp["Subscription"].(map[string]any) assert.NotNil(t, sub["ProactiveEngagementStatus"]) @@ -233,7 +234,7 @@ func TestHandler_SubscriptionLimitsStructure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sub := resp["Subscription"].(map[string]any) limits := sub["SubscriptionLimits"].(map[string]any) @@ -255,7 +256,7 @@ func TestHandler_SubscriptionTimestampIsFloat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) sub := raw["Subscription"].(map[string]any) st, ok := sub["StartTime"].(float64) @@ -275,7 +276,7 @@ func TestHandler_SubscriptionArnFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sub := resp["Subscription"].(map[string]any) arn := sub["SubscriptionArn"].(string) @@ -397,7 +398,7 @@ func TestHandler_UpdateSubscriptionOmitAutoRenewPreservesExistingValue(t *testin require.Equal(t, 200, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) sub, ok := result["Subscription"].(map[string]any) require.True(t, ok) assert.Equal(t, shield.AutoRenewDisabled, sub["AutoRenew"]) @@ -415,7 +416,7 @@ func TestHandler_DescribeSubscriptionIncludesArn(t *testing.T) { require.Equal(t, 200, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) sub, ok := result["Subscription"].(map[string]any) require.True(t, ok) assert.Contains(t, sub, "SubscriptionArn") diff --git a/services/shield/handler_tags.go b/services/shield/handler_tags.go index fa905d7621..919ef508f9 100644 --- a/services/shield/handler_tags.go +++ b/services/shield/handler_tags.go @@ -1,9 +1,10 @@ package shield import ( - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -15,7 +16,7 @@ type tagResourceRequest struct { func (h *Handler) handleTagResource(body []byte) error { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -37,7 +38,7 @@ type listTagsForResourceRequest struct { func (h *Handler) handleListTagsForResource(body []byte) ([]byte, error) { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -52,7 +53,7 @@ func (h *Handler) handleListTagsForResource(body []byte) ([]byte, error) { return json.Marshal(map[string]any{ "Tags": tags.MapToKV(tagsMap), - }) + }, jsonx.V1()) } // untagResourceRequest is the request body for UntagResource. @@ -63,7 +64,7 @@ type untagResourceRequest struct { func (h *Handler) handleUntagResource(body []byte) error { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/shield/handler_test.go b/services/shield/handler_test.go index bb33f0b518..d39c01996d 100644 --- a/services/shield/handler_test.go +++ b/services/shield/handler_test.go @@ -3,7 +3,7 @@ package shield_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/shield" ) @@ -59,7 +60,7 @@ func doShieldRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -89,7 +90,7 @@ func opaqueOffset(t *testing.T, token string) int { O int `json:"o"` } - require.NoError(t, json.Unmarshal(raw, &obj), "token must be JSON with 'o' key") + require.NoError(t, json.Unmarshal(raw, &obj, jsonx.V1()), "token must be JSON with 'o' key") return obj.O } diff --git a/services/shield/persistence.go b/services/shield/persistence.go index 2754518c3d..265d12b363 100644 --- a/services/shield/persistence.go +++ b/services/shield/persistence.go @@ -2,7 +2,7 @@ package shield import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -41,15 +41,15 @@ type alarConfigDTO struct { // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Subscription *Subscription `json:"subscription,omitempty"` - DRTAccess *DRTAccess `json:"drtAccess,omitempty"` - AccountID string `json:"accountID"` - Region string `json:"region"` - ProactiveEngagementStatus string `json:"proactiveEngagementStatus,omitempty"` - ALARConfigs []alarConfigDTO `json:"alarConfigs,omitempty"` - EmergencyContacts []EmergencyContact `json:"emergencyContacts,omitempty"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Subscription *Subscription `json:"subscription,omitempty"` + DRTAccess *DRTAccess `json:"drtAccess,omitempty"` + AccountID string `json:"accountID"` + Region string `json:"region"` + ProactiveEngagementStatus string `json:"proactiveEngagementStatus,omitempty"` + ALARConfigs []alarConfigDTO `json:"alarConfigs,omitempty"` + EmergencyContacts []EmergencyContact `json:"emergencyContacts,omitempty"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/shield/request_validation_test.go b/services/shield/request_validation_test.go index cca6e7183e..7fd4065c56 100644 --- a/services/shield/request_validation_test.go +++ b/services/shield/request_validation_test.go @@ -1,13 +1,15 @@ package shield_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_RequestValidation(t *testing.T) { @@ -158,7 +160,7 @@ func TestHandler_RequestValidation(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantCode, out.Type) assert.Contains(t, out.Message, tt.wantMsg) }) @@ -215,7 +217,7 @@ func TestHandler_ErrorMessagesOmitCode(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantCode, out.Type) assert.NotContains(t, out.Message, tt.wantCode) assert.NotContains(t, out.Message, "invalid request:") diff --git a/services/signin/handler.go b/services/signin/handler.go index 58f0f5f6b4..128357d7d2 100644 --- a/services/signin/handler.go +++ b/services/signin/handler.go @@ -2,7 +2,7 @@ package signin import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strconv" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -310,7 +311,7 @@ func decode(body []byte, v any) error { return nil } - if err := json.Unmarshal(body, v); err != nil { + if err := json.Unmarshal(body, v, jsonx.V1()); err != nil { return validation("malformed request body") } diff --git a/services/signin/persistence.go b/services/signin/persistence.go index 119ed24a6c..313a23815a 100644 --- a/services/signin/persistence.go +++ b/services/signin/persistence.go @@ -3,7 +3,7 @@ package signin import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -14,11 +14,11 @@ import ( const signinSnapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - SigningKey string `json:"signingKey"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + SigningKey string `json:"signingKey"` + Version int `json:"version"` } // Snapshot serialises the backend state to JSON. diff --git a/services/signin/tokens.go b/services/signin/tokens.go index c5dbefb04b..1ffae56faf 100644 --- a/services/signin/tokens.go +++ b/services/signin/tokens.go @@ -7,7 +7,7 @@ import ( "crypto/sha256" "crypto/subtle" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/url" "strings" "time" @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -107,7 +108,7 @@ func (b *InMemoryBackend) sign(payload string) string { func (b *InMemoryBackend) makeJWT(claims map[string]any) string { enc := base64.RawURLEncoding head := enc.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`)) - raw, _ := json.Marshal(claims) + raw, _ := json.Marshal(claims, jsonx.V1()) body := enc.EncodeToString(raw) return head + "." + body + "." + b.sign(head+"."+body) @@ -133,7 +134,7 @@ func (b *InMemoryBackend) parseJWT(tok string) (string, bool) { JTI string `json:"jti"` } - if json.Unmarshal(raw, &claims) != nil || claims.JTI == "" { + if json.Unmarshal(raw, &claims, jsonx.V1()) != nil || claims.JTI == "" { return "", false } diff --git a/services/sns/archive.go b/services/sns/archive.go index 722bafa24e..b018033976 100644 --- a/services/sns/archive.go +++ b/services/sns/archive.go @@ -1,12 +1,13 @@ package sns import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "time" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseReplayFromTimestamp parses the replayFromTimestamp field from a ReplayPolicy JSON string. @@ -20,7 +21,7 @@ func parseReplayFromTimestamp(replayPolicy string) (time.Time, error) { ReplayFromTimestamp string `json:"replayFromTimestamp"` } - if err := json.Unmarshal([]byte(replayPolicy), &p); err != nil { + if err := json.Unmarshal([]byte(replayPolicy), &p, jsonx.V1()); err != nil { return time.Time{}, fmt.Errorf( "%w: ReplayPolicy is not valid JSON: %s", ErrInvalidParameter, diff --git a/services/sns/archive_test.go b/services/sns/archive_test.go index 61e4e3a5a0..0383673c3d 100644 --- a/services/sns/archive_test.go +++ b/services/sns/archive_test.go @@ -1,7 +1,7 @@ package sns_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -228,7 +229,7 @@ func TestReplayPolicyTriggersLambdaReplay(t *testing.T) { // Verify all archived messages were replayed, in original publish order. for i, invocation := range lambda.All() { var envelope map[string]any - require.NoError(t, json.Unmarshal(invocation.Payload, &envelope)) + require.NoError(t, json.Unmarshal(invocation.Payload, &envelope, jsonx.V1())) records, _ := envelope["Records"].([]any) require.Len(t, records, 1) record, _ := records[0].(map[string]any) @@ -316,7 +317,7 @@ func TestReplayPolicyDeliversToA2AProtocols(t *testing.T) { require.Equal(t, 1, lambda.Count(), "lambda function was never invoked") var envelope map[string]any - require.NoError(t, json.Unmarshal(lambda.Last().Payload, &envelope)) + require.NoError(t, json.Unmarshal(lambda.Last().Payload, &envelope, jsonx.V1())) records, _ := envelope["Records"].([]any) require.Len(t, records, 1) record, _ := records[0].(map[string]any) @@ -345,7 +346,7 @@ func TestReplayPolicyDeliversToA2AProtocols(t *testing.T) { require.Len(t, firehose.RecordsFor(streamName), 1, "firehose stream received no record") var envelope map[string]any - require.NoError(t, json.Unmarshal(firehose.RecordsFor(streamName)[0], &envelope)) + require.NoError(t, json.Unmarshal(firehose.RecordsFor(streamName)[0], &envelope, jsonx.V1())) assert.Equal(t, archivedMessage, envelope["Message"]) }, } diff --git a/services/sns/confirmation.go b/services/sns/confirmation.go index 67ecd49aa3..2807314728 100644 --- a/services/sns/confirmation.go +++ b/services/sns/confirmation.go @@ -5,13 +5,15 @@ import ( "context" "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "strings" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -101,7 +103,7 @@ func (b *InMemoryBackend) deliverSubscriptionConfirmation( SignatureVersion: version, Signature: b.signer.signWithVersion(canonical, version), SigningCertURL: certURL, - }) + }, jsonx.V1()) if err != nil { return } diff --git a/services/sns/delivery.go b/services/sns/delivery.go index 528e3de581..4ee786458b 100644 --- a/services/sns/delivery.go +++ b/services/sns/delivery.go @@ -2,11 +2,12 @@ package sns import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -16,7 +17,7 @@ func parseTopicEffectivePolicy(topicEffectivePolicy, protocol string) *int { NumRetries *int `json:"numRetries"` } `json:"defaultHealthyRetryPolicy"` } - if err := json.Unmarshal([]byte(topicEffectivePolicy), &tp); err == nil { + if err := json.Unmarshal([]byte(topicEffectivePolicy), &tp, jsonx.V1()); err == nil { pKey := protocol if pKey == protocolHTTPS { pKey = protocolHTTP @@ -35,7 +36,7 @@ func parseSubPolicy(subPolicy string) *int { NumRetries *int `json:"numRetries"` } `json:"healthyRetryPolicy"` } - if err := json.Unmarshal([]byte(subPolicy), &sp); err == nil { + if err := json.Unmarshal([]byte(subPolicy), &sp, jsonx.V1()); err == nil { return sp.HealthyRetryPolicy.NumRetries } @@ -183,7 +184,7 @@ func buildHTTPDeliveryPayload(d httpDelivery) string { env.Subject = d.subject } - if enc, err := json.Marshal(env); err == nil { + if enc, err := json.Marshal(env, jsonx.V1()); err == nil { body = string(enc) } } @@ -256,7 +257,7 @@ func sendSubscriptionDLQ(ctx context.Context, d httpDelivery) { DeadLetterTargetArn string `json:"deadLetterTargetArn"` } - if err := json.Unmarshal([]byte(d.redrivePolicy), &policy); err != nil { + if err := json.Unmarshal([]byte(d.redrivePolicy), &policy, jsonx.V1()); err != nil { return } diff --git a/services/sns/delivery_test.go b/services/sns/delivery_test.go index b22939b1cb..86399dfd39 100644 --- a/services/sns/delivery_test.go +++ b/services/sns/delivery_test.go @@ -3,7 +3,7 @@ package sns_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "sync" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -259,7 +260,7 @@ func TestHTTPDeliveryFailureSendsToDLQ(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": dlqARN, - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err) diff --git a/services/sns/filter_match.go b/services/sns/filter_match.go index 01962ba4ec..e13f5a25ef 100644 --- a/services/sns/filter_match.go +++ b/services/sns/filter_match.go @@ -1,10 +1,13 @@ package sns import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // matchesFilterPolicyMessageBody evaluates a parsed filter policy against the @@ -15,8 +18,8 @@ func matchesFilterPolicyMessageBody(policy parsedFilterPolicy, message string) b return true } - var body map[string]json.RawMessage - if err := json.Unmarshal([]byte(message), &body); err != nil { + var body map[string]jsontext.Value + if err := json.Unmarshal([]byte(message), &body, jsonx.V1()); err != nil { return false } @@ -42,9 +45,9 @@ func matchesFilterPolicyMessageBody(policy parsedFilterPolicy, message string) b // are expanded so the condition is satisfied when ANY element matches, mirroring // AWS message-body array handling. func matchesBodyKeyConditions( - body map[string]json.RawMessage, + body map[string]jsontext.Value, key string, - conditions []json.RawMessage, + conditions []jsontext.Value, ) bool { if subPolicy, nested := nestedSubPolicy(conditions); nested { return matchesNestedBody(body[key], subPolicy) @@ -66,7 +69,7 @@ func matchesBodyKeyConditions( // matchesNestedBody applies a nested sub-policy to an object value, or to any // element when the value is an array of objects. -func matchesNestedBody(raw json.RawMessage, subPolicyJSON string) bool { +func matchesNestedBody(raw jsontext.Value, subPolicyJSON string) bool { if len(raw) == 0 { return false } @@ -76,8 +79,8 @@ func matchesNestedBody(raw json.RawMessage, subPolicyJSON string) bool { return false } - var arr []json.RawMessage - if json.Unmarshal(raw, &arr) == nil { + var arr []jsontext.Value + if json.Unmarshal(raw, &arr, jsonx.V1()) == nil { for _, elem := range arr { if matchesFilterPolicyMessageBody(sub, string(elem)) { return true @@ -94,13 +97,13 @@ func matchesNestedBody(raw json.RawMessage, subPolicyJSON string) bool { // body value: a string, number, or boolean yields one candidate; a JSON array of // scalars yields one candidate per element. A value that cannot be reduced to a // scalar yields no candidates (the key is then treated as non-matching). -func bodyMatchValues(raw json.RawMessage) []string { +func bodyMatchValues(raw jsontext.Value) []string { if v, ok := scalarBodyValue(raw); ok { return []string{v} } - var arr []json.RawMessage - if err := json.Unmarshal(raw, &arr); err == nil { + var arr []jsontext.Value + if err := json.Unmarshal(raw, &arr, jsonx.V1()); err == nil { out := make([]string, 0, len(arr)) for _, elem := range arr { if v, ok := scalarBodyValue(elem); ok { @@ -116,19 +119,19 @@ func bodyMatchValues(raw json.RawMessage) []string { // scalarBodyValue converts a single JSON scalar (string, number, or boolean) to // its string form for filter matching. It reports false for non-scalar values. -func scalarBodyValue(raw json.RawMessage) (string, bool) { +func scalarBodyValue(raw jsontext.Value) (string, bool) { var s string - if err := json.Unmarshal(raw, &s); err == nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err == nil { return s, true } - var n json.Number - if err := json.Unmarshal(raw, &n); err == nil { + var n jsonx.Number + if err := json.Unmarshal(raw, &n, jsonx.V1()); err == nil { return n.String(), true } var b bool - if err := json.Unmarshal(raw, &b); err == nil { + if err := json.Unmarshal(raw, &b, jsonx.V1()); err == nil { return strconv.FormatBool(b), true } @@ -137,7 +140,7 @@ func scalarBodyValue(raw json.RawMessage) (string, bool) { // matchesOrBody evaluates a recognised "$or" operator against a JSON message // body: it returns true when AT LEAST ONE sub-policy fully matches. -func matchesOrBody(subPolicies []json.RawMessage, message string) bool { +func matchesOrBody(subPolicies []jsontext.Value, message string) bool { for _, raw := range subPolicies { sub, err := parseFilterPolicy(string(raw)) if err != nil { @@ -183,7 +186,7 @@ func matchesParsedFilterPolicy(policy parsedFilterPolicy, attrs map[string]Messa // matched independently and the condition is satisfied if ANY element matches // (OR across elements), mirroring AWS String.Array handling. func matchesAttributeConditions( - key string, conditions []json.RawMessage, attrs map[string]MessageAttribute, + key string, conditions []jsontext.Value, attrs map[string]MessageAttribute, ) bool { attr, attrExists := attrs[key] @@ -208,7 +211,7 @@ func attributeMatchValues(attr MessageAttribute, attrExists bool) []string { if attr.DataType == "String.Array" { var elems []string - if err := json.Unmarshal([]byte(attr.StringValue), &elems); err == nil && len(elems) > 0 { + if err := json.Unmarshal([]byte(attr.StringValue), &elems, jsonx.V1()); err == nil && len(elems) > 0 { return elems } } @@ -218,7 +221,7 @@ func attributeMatchValues(attr MessageAttribute, attrExists bool) []string { // matchesOrAttributes evaluates a recognised "$or" operator against message // attributes: it returns true when AT LEAST ONE sub-policy fully matches. -func matchesOrAttributes(subPolicies []json.RawMessage, attrs map[string]MessageAttribute) bool { +func matchesOrAttributes(subPolicies []jsontext.Value, attrs map[string]MessageAttribute) bool { for _, raw := range subPolicies { sub, err := parseFilterPolicy(string(raw)) if err != nil { @@ -236,7 +239,7 @@ func matchesOrAttributes(subPolicies []json.RawMessage, attrs map[string]Message // matchObjectCondition evaluates a single JSON-object SNS filter condition such as // {"prefix": "order-"}, {"suffix": ".jpg"}, {"anything-but": [...]}, // {"equals-ignore-case": "OrderId"}, {"exists": true}, or {"numeric": [">", 0]}. -func matchObjectCondition(value string, attrExists bool, obj map[string]json.RawMessage) bool { +func matchObjectCondition(value string, attrExists bool, obj map[string]jsontext.Value) bool { // String-operand operators share the same shape: decode a single string // operand and apply a predicate. They require the attribute to exist. stringOps := map[string]func(value, operand string) bool{ @@ -254,7 +257,7 @@ func matchObjectCondition(value string, attrExists bool, obj map[string]json.Raw } var operand string - if err := json.Unmarshal(raw, &operand); err != nil { + if err := json.Unmarshal(raw, &operand, jsonx.V1()); err != nil { return false } @@ -263,7 +266,7 @@ func matchObjectCondition(value string, attrExists bool, obj map[string]json.Raw if existsRaw, ok := obj["exists"]; ok { var existsVal bool - if err := json.Unmarshal(existsRaw, &existsVal); err == nil { + if err := json.Unmarshal(existsRaw, &existsVal, jsonx.V1()); err == nil { return attrExists == existsVal } @@ -355,32 +358,32 @@ func matchCIDR(value, cidr string) bool { // // In every case the operator is satisfied only when the attribute exists and the // value does NOT match the negated condition. -func matchAnythingBut(value string, attrExists bool, raw json.RawMessage) bool { +func matchAnythingBut(value string, attrExists bool, raw jsontext.Value) bool { if !attrExists { return false } // Try as string literal. var s string - if errStr := json.Unmarshal(raw, &s); errStr == nil { + if errStr := json.Unmarshal(raw, &s, jsonx.V1()); errStr == nil { return value != s } // Try as number literal. - var n json.Number - if errNum := json.Unmarshal(raw, &n); errNum == nil { + var n jsonx.Number + if errNum := json.Unmarshal(raw, &n, jsonx.V1()); errNum == nil { return value != n.String() } // Try as array of literals. - var arr []json.RawMessage - if errArr := json.Unmarshal(raw, &arr); errArr == nil { + var arr []jsontext.Value + if errArr := json.Unmarshal(raw, &arr, jsonx.V1()); errArr == nil { return matchAnythingButArray(value, arr) } // Try as nested operator object: {"anything-but": {"prefix"|"suffix"|...: ...}}. - var obj map[string]json.RawMessage - if errObj := json.Unmarshal(raw, &obj); errObj == nil { + var obj map[string]jsontext.Value + if errObj := json.Unmarshal(raw, &obj, jsonx.V1()); errObj == nil { return matchAnythingButObject(value, obj) } @@ -390,10 +393,10 @@ func matchAnythingBut(value string, attrExists bool, raw json.RawMessage) bool { // matchAnythingButObject negates a nested string operator inside an // "anything-but" condition. It returns true when the value does NOT satisfy the // inner operator. -func matchAnythingButObject(value string, obj map[string]json.RawMessage) bool { +func matchAnythingButObject(value string, obj map[string]jsontext.Value) bool { if prefixRaw, ok := obj["prefix"]; ok { var prefix string - if err := json.Unmarshal(prefixRaw, &prefix); err == nil { + if err := json.Unmarshal(prefixRaw, &prefix, jsonx.V1()); err == nil { return !strings.HasPrefix(value, prefix) } @@ -402,7 +405,7 @@ func matchAnythingButObject(value string, obj map[string]json.RawMessage) bool { if suffixRaw, ok := obj["suffix"]; ok { var suffix string - if err := json.Unmarshal(suffixRaw, &suffix); err == nil { + if err := json.Unmarshal(suffixRaw, &suffix, jsonx.V1()); err == nil { return !strings.HasSuffix(value, suffix) } @@ -411,7 +414,7 @@ func matchAnythingButObject(value string, obj map[string]json.RawMessage) bool { if eqICaseRaw, ok := obj["equals-ignore-case"]; ok { var want string - if err := json.Unmarshal(eqICaseRaw, &want); err == nil { + if err := json.Unmarshal(eqICaseRaw, &want, jsonx.V1()); err == nil { return !strings.EqualFold(value, want) } @@ -420,7 +423,7 @@ func matchAnythingButObject(value string, obj map[string]json.RawMessage) bool { if wildcardRaw, ok := obj["wildcard"]; ok { var pattern string - if err := json.Unmarshal(wildcardRaw, &pattern); err == nil { + if err := json.Unmarshal(wildcardRaw, &pattern, jsonx.V1()); err == nil { return !matchWildcard(value, pattern) } @@ -431,10 +434,10 @@ func matchAnythingButObject(value string, obj map[string]json.RawMessage) bool { } // matchAnythingButArray checks that value does not equal any element in the "anything-but" array. -func matchAnythingButArray(value string, arr []json.RawMessage) bool { +func matchAnythingButArray(value string, arr []jsontext.Value) bool { for _, item := range arr { var sv string - if errI := json.Unmarshal(item, &sv); errI == nil { + if errI := json.Unmarshal(item, &sv, jsonx.V1()); errI == nil { if value == sv { return false } @@ -442,8 +445,8 @@ func matchAnythingButArray(value string, arr []json.RawMessage) bool { continue } - var nv json.Number - if errN := json.Unmarshal(item, &nv); errN == nil && value == nv.String() { + var nv jsonx.Number + if errN := json.Unmarshal(item, &nv, jsonx.V1()); errN == nil && value == nv.String() { return false } } @@ -453,25 +456,25 @@ func matchAnythingButArray(value string, arr []json.RawMessage) bool { // matchNumericCondition evaluates {"numeric": [op, num, ...]} conditions. // Conditions are pairs of [operator, number] and ALL pairs must be satisfied (AND semantics). -func matchNumericCondition(value string, raw json.RawMessage) bool { +func matchNumericCondition(value string, raw jsontext.Value) bool { valFloat, errParse := strconv.ParseFloat(value, 64) if errParse != nil { return false } - var conditions []json.RawMessage - if errUnm := json.Unmarshal(raw, &conditions); errUnm != nil { + var conditions []jsontext.Value + if errUnm := json.Unmarshal(raw, &conditions, jsonx.V1()); errUnm != nil { return false } for i := 0; i+1 < len(conditions); i += 2 { var op string - if errOp := json.Unmarshal(conditions[i], &op); errOp != nil { + if errOp := json.Unmarshal(conditions[i], &op, jsonx.V1()); errOp != nil { return false } - var num json.Number - if errNum := json.Unmarshal(conditions[i+1], &num); errNum != nil { + var num jsonx.Number + if errNum := json.Unmarshal(conditions[i+1], &num, jsonx.V1()); errNum != nil { return false } @@ -509,22 +512,22 @@ func numericOpMatches(op string, value, threshold float64) bool { } } -func matchCondition(value string, attrExists bool, raw json.RawMessage) bool { +func matchCondition(value string, attrExists bool, raw jsontext.Value) bool { // Object conditions: prefix, exists, anything-but, numeric. - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err == nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err == nil { return matchObjectCondition(value, attrExists, obj) } // String exact match — attribute must exist. var s string - if err := json.Unmarshal(raw, &s); err == nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err == nil { return attrExists && value == s } // Number exact match — attribute must exist. - var n json.Number - if err := json.Unmarshal(raw, &n); err == nil { + var n jsonx.Number + if err := json.Unmarshal(raw, &n, jsonx.V1()); err == nil { return attrExists && value == n.String() } @@ -532,7 +535,7 @@ func matchCondition(value string, attrExists bool, raw json.RawMessage) bool { } // matchesConditions returns true if value/existence satisfies at least one condition in the list. -func matchesConditions(value string, attrExists bool, conditions []json.RawMessage) bool { +func matchesConditions(value string, attrExists bool, conditions []jsontext.Value) bool { for _, raw := range conditions { if matchCondition(value, attrExists, raw) { return true diff --git a/services/sns/filter_match_test.go b/services/sns/filter_match_test.go index 5703f82e93..ecda758620 100644 --- a/services/sns/filter_match_test.go +++ b/services/sns/filter_match_test.go @@ -1,7 +1,7 @@ package sns_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -46,7 +47,7 @@ func TestFilterPolicyAnythingButMatchDelivery(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "blue-msg", env.Message) } case <-time.After(2 * time.Second): @@ -127,7 +128,7 @@ func TestFilterPolicyPrefixMatch(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "order-msg", env.Message) } case <-time.After(2 * time.Second): @@ -138,7 +139,7 @@ func TestFilterPolicyPrefixMatch(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { t.Fatalf("non-matching message was delivered: %s", env.Message) } case <-time.After(300 * time.Millisecond): @@ -175,7 +176,7 @@ func TestFilterPolicySuffixMatch(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "log-msg", env.Message) } case <-time.After(2 * time.Second): @@ -212,7 +213,7 @@ func TestFilterPolicyEqualsIgnoreCase(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "prod-msg", env.Message) } case <-time.After(2 * time.Second): diff --git a/services/sns/filter_policy.go b/services/sns/filter_policy.go index 4346c69d49..1b5700f154 100644 --- a/services/sns/filter_policy.go +++ b/services/sns/filter_policy.go @@ -1,11 +1,14 @@ package sns import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // parseFilterPolicy parses and validates a FilterPolicy JSON string. It returns @@ -46,8 +49,8 @@ func parseFilterPolicy(filterPolicy string) (parsedFilterPolicy, error) { ) } - var rawPolicy map[string]json.RawMessage - if err := json.Unmarshal([]byte(filterPolicy), &rawPolicy); err != nil { + var rawPolicy map[string]jsontext.Value + if err := json.Unmarshal([]byte(filterPolicy), &rawPolicy, jsonx.V1()); err != nil { return nil, fmt.Errorf( "%w: FilterPolicy is not valid JSON: %s", ErrInvalidParameter, @@ -89,15 +92,15 @@ const nestedPolicyKey = "$nestedPolicy" // parseFilterPolicyKey validates one top-level FilterPolicy key and returns its // stored conditions plus how many count toward the total-condition budget. -func parseFilterPolicyKey(key string, rawConditions json.RawMessage) ([]json.RawMessage, int, error) { +func parseFilterPolicyKey(key string, rawConditions jsontext.Value) ([]jsontext.Value, int, error) { if isNestedPolicyValue(rawConditions) { nested, err := parseNestedFilterPolicy(key, rawConditions) return nested, 0, err } - var conditions []json.RawMessage - if err := json.Unmarshal(rawConditions, &conditions); err != nil { + var conditions []jsontext.Value + if err := json.Unmarshal(rawConditions, &conditions, jsonx.V1()); err != nil { return nil, 0, fmt.Errorf( "%w: FilterPolicy attribute %q must be a JSON array", ErrInvalidParameter, key, @@ -119,7 +122,7 @@ func parseFilterPolicyKey(key string, rawConditions json.RawMessage) ([]json.Raw return conditions, len(conditions), validateConditionShapes(key, conditions) } -func isNestedPolicyValue(raw json.RawMessage) bool { +func isNestedPolicyValue(raw jsontext.Value) bool { return strings.HasPrefix(strings.TrimSpace(string(raw)), "{") } @@ -134,27 +137,27 @@ func checkConditionBudget(total int) error { return nil } -func parseNestedFilterPolicy(key string, raw json.RawMessage) ([]json.RawMessage, error) { +func parseNestedFilterPolicy(key string, raw jsontext.Value) ([]jsontext.Value, error) { if _, err := parseFilterPolicy(string(raw)); err != nil { return nil, fmt.Errorf("%w (nested key %q)", err, key) } - wrapped, err := json.Marshal(map[string]json.RawMessage{nestedPolicyKey: raw}) + wrapped, err := json.Marshal(map[string]jsontext.Value{nestedPolicyKey: raw}, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: FilterPolicy attribute %q: %s", ErrInvalidParameter, key, err.Error()) } - return []json.RawMessage{wrapped}, nil + return []jsontext.Value{wrapped}, nil } // nestedSubPolicy returns the nested sub-policy JSON stored by parseNestedFilterPolicy. -func nestedSubPolicy(conditions []json.RawMessage) (string, bool) { +func nestedSubPolicy(conditions []jsontext.Value) (string, bool) { if len(conditions) != 1 { return "", false } - var wrapper map[string]json.RawMessage - if err := json.Unmarshal(conditions[0], &wrapper); err != nil { + var wrapper map[string]jsontext.Value + if err := json.Unmarshal(conditions[0], &wrapper, jsonx.V1()); err != nil { return "", false } @@ -177,14 +180,14 @@ const minOrOperatorElems = 2 // - no element uses a reserved operator keyword as a top-level field name. // // When any rule is violated, AWS treats "$or" as an ordinary attribute key. -func isRecognisedOrOperator(elems []json.RawMessage) bool { +func isRecognisedOrOperator(elems []jsontext.Value) bool { if len(elems) < minOrOperatorElems { return false } for _, elem := range elems { - var obj map[string]json.RawMessage - if err := json.Unmarshal(elem, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(elem, &obj, jsonx.V1()); err != nil { return false } @@ -206,7 +209,7 @@ func isRecognisedOrOperator(elems []json.RawMessage) bool { // array, rejecting malformed operators or numeric operands. It returns the total // number of conditions contained across all sub-policies so the caller can // enforce the global condition cap. -func validateOrSubPolicies(elems []json.RawMessage) (int, error) { +func validateOrSubPolicies(elems []jsontext.Value) (int, error) { total := 0 for _, elem := range elems { @@ -244,10 +247,10 @@ var knownFilterPolicyOperators = map[string]struct{}{ // attribute and rejects unknown operator names and malformed numeric operand // structures. Scalar conditions (plain strings, numbers, booleans, null) and // known object operators are tolerated as-is and matched lazily at evaluation. -func validateConditionShapes(key string, conditions []json.RawMessage) error { +func validateConditionShapes(key string, conditions []jsontext.Value) error { for _, raw := range conditions { - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil { // Scalar conditions (e.g. plain strings) are valid; skip object-only checks. continue } @@ -281,9 +284,9 @@ func validateConditionShapes(key string, conditions []json.RawMessage) error { // containing a valid IPv4/IPv6 address (bare host route) or CIDR block, // rejecting it eagerly at Subscribe/SetSubscriptionAttributes time rather // than letting it silently never match at evaluation (matchCIDR). -func validateCIDROperand(key string, raw json.RawMessage) error { +func validateCIDROperand(key string, raw jsontext.Value) error { var operand string - if err := json.Unmarshal(raw, &operand); err != nil { + if err := json.Unmarshal(raw, &operand, jsonx.V1()); err != nil { return fmt.Errorf( "%w: FilterPolicy attribute %q cidr operand must be a string", ErrInvalidParameter, key, @@ -313,9 +316,9 @@ func validateCIDROperand(key string, raw json.RawMessage) error { // validateNumericOperands enforces that a "numeric" condition operand is a JSON // array of even length where each pair is (operator-string, number). -func validateNumericOperands(key string, raw json.RawMessage) error { - var operands []json.RawMessage - if err := json.Unmarshal(raw, &operands); err != nil { +func validateNumericOperands(key string, raw jsontext.Value) error { + var operands []jsontext.Value + if err := json.Unmarshal(raw, &operands, jsonx.V1()); err != nil { return fmt.Errorf( "%w: FilterPolicy attribute %q numeric operand must be a JSON array", ErrInvalidParameter, key, @@ -338,7 +341,7 @@ func validateNumericOperands(key string, raw json.RawMessage) error { for i := 0; i+1 < len(operands); i += 2 { var op string - if err := json.Unmarshal(operands[i], &op); err != nil { + if err := json.Unmarshal(operands[i], &op, jsonx.V1()); err != nil { return fmt.Errorf( "%w: FilterPolicy attribute %q numeric operator must be a string", ErrInvalidParameter, key, @@ -352,8 +355,8 @@ func validateNumericOperands(key string, raw json.RawMessage) error { ) } - var num json.Number - if err := json.Unmarshal(operands[i+1], &num); err != nil { + var num jsonx.Number + if err := json.Unmarshal(operands[i+1], &num, jsonx.V1()); err != nil { return fmt.Errorf( "%w: FilterPolicy attribute %q numeric threshold must be a number", ErrInvalidParameter, key, @@ -378,7 +381,7 @@ func validateRedrivePolicy(policy string) error { DeadLetterTargetArn string `json:"deadLetterTargetArn"` } - if err := json.Unmarshal([]byte(policy), &parsed); err != nil { + if err := json.Unmarshal([]byte(policy), &parsed, jsonx.V1()); err != nil { return fmt.Errorf( "%w: RedrivePolicy is not valid JSON: %s", ErrInvalidParameter, @@ -414,7 +417,7 @@ func (b *InMemoryBackend) checkDLQExists(policy string) error { } // Shape is already validated by validateRedrivePolicy, so an unmarshal failure // here cannot happen for a well-formed policy; ignore it and skip verification. - _ = json.Unmarshal([]byte(policy), &parsed) + _ = json.Unmarshal([]byte(policy), &parsed, jsonx.V1()) if parsed.DeadLetterTargetArn == "" { return nil } diff --git a/services/sns/golden_perf_mixed_test.go b/services/sns/golden_perf_mixed_test.go index 45d492c204..013aee3493 100644 --- a/services/sns/golden_perf_mixed_test.go +++ b/services/sns/golden_perf_mixed_test.go @@ -19,7 +19,7 @@ package sns_test // To regenerate: SNS_GOLDEN_UPDATE=1 go test -run TestGolden ./services/sns/... import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -109,7 +110,7 @@ func TestSignature_SharedAcrossHTTPSubscribers(t *testing.T) { select { case body := <-received: var env map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &env)) + require.NoError(t, json.Unmarshal([]byte(body), &env, jsonx.V1())) envelopes = append(envelopes, env) case <-time.After(2 * time.Second): t.Fatal("HTTP delivery did not arrive in time") diff --git a/services/sns/golden_perf_test.go b/services/sns/golden_perf_test.go index cd2963a7d3..d714c753b4 100644 --- a/services/sns/golden_perf_test.go +++ b/services/sns/golden_perf_test.go @@ -12,7 +12,8 @@ package sns_test // To regenerate: SNS_GOLDEN_UPDATE=1 go test -run TestGolden ./services/sns/... import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/url" @@ -24,6 +25,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -94,7 +96,7 @@ func redactDeliveredEnvelope(t *testing.T, body []byte) []byte { t.Helper() var env map[string]any - require.NoError(t, json.Unmarshal(body, &env)) + require.NoError(t, json.Unmarshal(body, &env, jsonx.V1())) for _, k := range []string{"MessageId", "Timestamp", "Signature", "UnsubscribeURL"} { if _, ok := env[k]; ok { @@ -102,7 +104,7 @@ func redactDeliveredEnvelope(t *testing.T, body []byte) []byte { } } - out, err := json.MarshalIndent(env, "", " ") + out, err := json.Marshal(env, jsonx.V1(), jsontext.Multiline(true), jsontext.WithIndent(" ")) require.NoError(t, err) return out diff --git a/services/sns/handler_test.go b/services/sns/handler_test.go index 1c563a9279..6fbe6392f7 100644 --- a/services/sns/handler_test.go +++ b/services/sns/handler_test.go @@ -2,7 +2,7 @@ package sns_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -70,7 +71,7 @@ func extractSNSHTTPMessage(body string) string { Message string `json:"Message"` Type string `json:"Type"` } - if err := json.Unmarshal([]byte(body), &env); err == nil && env.Type == "Notification" { + if err := json.Unmarshal([]byte(body), &env, jsonx.V1()); err == nil && env.Type == "Notification" { return env.Message } diff --git a/services/sns/lambda_firehose_delivery.go b/services/sns/lambda_firehose_delivery.go index 0d146e9756..e10a0ee433 100644 --- a/services/sns/lambda_firehose_delivery.go +++ b/services/sns/lambda_firehose_delivery.go @@ -2,13 +2,14 @@ package sns import ( "context" - "encoding/json" + "encoding/json/v2" "strings" "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -87,7 +88,7 @@ func buildLambdaPayload( }, } - payload, err := json.Marshal(map[string]any{"Records": []any{record}}) + payload, err := json.Marshal(map[string]any{"Records": []any{record}}, jsonx.V1()) if err != nil { return []byte(`{"Records":[]}`) } @@ -115,7 +116,7 @@ func buildFirehoseEnvelope(ev *events.SNSPublishedEvent, sub events.SNSSubscript env.Subject = ev.Subject } - enc, err := json.Marshal(env) + enc, err := json.Marshal(env, jsonx.V1()) if err != nil { return []byte(sub.Body(ev.Message)) } @@ -357,7 +358,12 @@ func sendLambdaDLQ(ctx context.Context, sender SQSSender, redrivePolicy, body st var policy struct { DeadLetterTargetArn string `json:"deadLetterTargetArn"` } - if err := json.Unmarshal([]byte(redrivePolicy), &policy); err != nil || policy.DeadLetterTargetArn == "" { + if err := json.Unmarshal( + []byte(redrivePolicy), + &policy, + jsonx.V1(), + ); err != nil || + policy.DeadLetterTargetArn == "" { return } _ = sender.SendMessageToQueue(ctx, policy.DeadLetterTargetArn, body) diff --git a/services/sns/lambda_firehose_delivery_test.go b/services/sns/lambda_firehose_delivery_test.go index e901472d7a..56e380f843 100644 --- a/services/sns/lambda_firehose_delivery_test.go +++ b/services/sns/lambda_firehose_delivery_test.go @@ -2,7 +2,7 @@ package sns_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/url" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -149,7 +150,7 @@ func TestSNS_LambdaDelivery_InvokesFunction(t *testing.T) { // Verify payload is valid AWS SNS → Lambda envelope. var envelope map[string]any - err = json.Unmarshal(inv.Payload, &envelope) + err = json.Unmarshal(inv.Payload, &envelope, jsonx.V1()) require.NoError(t, err) records, ok := envelope["Records"].([]any) @@ -255,7 +256,7 @@ func TestSNS_FirehoseDelivery_PutsRecord(t *testing.T) { // subscription created above never sets it), so the delivered record is the // full SNS Notification JSON envelope, not the bare message body. var envelope map[string]any - require.NoError(t, json.Unmarshal(records[0], &envelope)) + require.NoError(t, json.Unmarshal(records[0], &envelope, jsonx.V1())) assert.Equal(t, "Notification", envelope["Type"]) assert.Equal(t, "firehose-message", envelope["Message"]) assert.Equal(t, topicARN, envelope["TopicArn"]) @@ -501,7 +502,7 @@ func TestFirehoseDeliveryFailureSendsToDLQ(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": dlqARN, - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err) @@ -534,7 +535,7 @@ func TestFirehoseDeliveryFailureNoSQSSenderNoError(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": "arn:aws:sqs:us-east-1:123456789012:dlq", - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err) @@ -623,7 +624,7 @@ func TestLambdaDeliveryFailureSendsToDLQ(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": dlqARN, - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err) @@ -656,7 +657,7 @@ func TestLambdaDeliveryFailureNoSenderNoError(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": "arn:aws:sqs:us-east-1:123456789012:dlq", - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err) diff --git a/services/sns/message_structure_protocols_test.go b/services/sns/message_structure_protocols_test.go index a8af37806e..8cd7ed84f0 100644 --- a/services/sns/message_structure_protocols_test.go +++ b/services/sns/message_structure_protocols_test.go @@ -1,7 +1,7 @@ package sns_test import ( - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "time" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -86,7 +87,7 @@ func receiveBody(t *testing.T, sqsClient *sqssdk.Client, queueURL string, raw bo Message string `json:"Message"` } - require.NoError(t, json.Unmarshal([]byte(body), &env)) + require.NoError(t, json.Unmarshal([]byte(body), &env, jsonx.V1())) return env.Message } @@ -222,7 +223,7 @@ func TestMessageStructureJSON_AllProtocols(t *testing.T) { } `json:"Records"` } - require.NoError(t, json.Unmarshal(lambda.Last().Payload, &lenv)) + require.NoError(t, json.Unmarshal(lambda.Last().Payload, &lenv, jsonx.V1())) require.Len(t, lenv.Records, 1) assert.Equal(t, tt.want["lambda"], lenv.Records[0].Sns.Message) @@ -237,7 +238,7 @@ func TestMessageStructureJSON_AllProtocols(t *testing.T) { Message string `json:"Message"` } - require.NoError(t, json.Unmarshal(envRecs[0], &fenv)) + require.NoError(t, json.Unmarshal(envRecs[0], &fenv, jsonx.V1())) assert.Equal(t, tt.want["firehose-env"], fenv.Message) got := map[string]string{} @@ -353,7 +354,7 @@ func TestMessageStructureJSON_Replay(t *testing.T) { } require.Equal(t, 1, lambda.Count()) - require.NoError(t, json.Unmarshal(lambda.Last().Payload, &env)) + require.NoError(t, json.Unmarshal(lambda.Last().Payload, &env, jsonx.V1())) assert.Equal(t, tt.want, env.Records[0].Sns.Message) }) }) diff --git a/services/sns/metrics.go b/services/sns/metrics.go index 3d34bed3e1..31885ed144 100644 --- a/services/sns/metrics.go +++ b/services/sns/metrics.go @@ -1,10 +1,12 @@ package sns import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "github.com/blackbirdworks/gopherstack/pkgs/cwmetric" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // AWS/SNS metrics per docs.aws.amazon.com/sns/latest/dg/sns-monitoring-using-cloudwatch.html (dimension TopicName). @@ -64,7 +66,7 @@ func classifyAttributeRejection(attrs map[string]MessageAttribute) filterRejecti } var elems []any - if json.Unmarshal([]byte(a.StringValue), &elems) != nil { + if json.Unmarshal([]byte(a.StringValue), &elems, jsonx.V1()) != nil { return rejectInvalidAttributes } } @@ -74,8 +76,8 @@ func classifyAttributeRejection(attrs map[string]MessageAttribute) filterRejecti // classifyBodyRejection names why message failed a body-scope filter policy. func classifyBodyRejection(message string) filterRejection { - var body map[string]json.RawMessage - if json.Unmarshal([]byte(message), &body) != nil { + var body map[string]jsontext.Value + if json.Unmarshal([]byte(message), &body, jsonx.V1()) != nil { return rejectInvalidBody } diff --git a/services/sns/models.go b/services/sns/models.go index 33d9d2e090..0b1a76991d 100644 --- a/services/sns/models.go +++ b/services/sns/models.go @@ -3,7 +3,7 @@ package sns import ( "context" "crypto/rsa" - "encoding/json" + "encoding/json/jsontext" "encoding/xml" "net/http" "sync" @@ -718,7 +718,7 @@ type publishTargets struct { filteredOut filteredCounts } -type parsedFilterPolicy map[string][]json.RawMessage +type parsedFilterPolicy map[string][]jsontext.Value // snsHTTPNotification is the SNS notification JSON envelope sent to HTTP/HTTPS subscribers. // When RawMessageDelivery is false, this struct is serialised as the POST body. diff --git a/services/sns/persistence.go b/services/sns/persistence.go index ac866341bc..c7e92a5cdf 100644 --- a/services/sns/persistence.go +++ b/services/sns/persistence.go @@ -2,7 +2,7 @@ package sns import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -32,7 +32,7 @@ const snsSnapshotVersion = 1 // type is not a pure keyed identity or is slice/scalar-valued -- see the // comment on registerAllTables in store_setup.go for why each one. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TopicTags map[string]*svcTags.Tags `json:"topicTags"` OptedOutPhoneNumbers map[string]bool `json:"optedOutPhoneNumbers,omitempty"` SMSAttributes map[string]string `json:"smsAttributes,omitempty"` diff --git a/services/sns/platform_endpoints.go b/services/sns/platform_endpoints.go index a9328c33b9..b1b7d80b9f 100644 --- a/services/sns/platform_endpoints.go +++ b/services/sns/platform_endpoints.go @@ -1,7 +1,7 @@ package sns import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "sort" @@ -11,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // CreatePlatformEndpoint registers a device token as an endpoint for a platform application. @@ -267,6 +268,6 @@ func (b *InMemoryBackend) fireEndpointEvent(appArn, eventAttr string, payload ma return } - msg, _ := json.Marshal(payload) + msg, _ := json.Marshal(payload, jsonx.V1()) _, _ = b.Publish(topicArn, string(msg), "", "", nil) } diff --git a/services/sns/publish.go b/services/sns/publish.go index 9694d5b40a..ec4595e797 100644 --- a/services/sns/publish.go +++ b/services/sns/publish.go @@ -2,7 +2,7 @@ package sns import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // buildMessageResolver returns a function that picks the correct message body for a given protocol, @@ -152,7 +153,7 @@ func validateStructuredMessage(message, messageStructure string) error { } var pm map[string]string - if err := json.Unmarshal([]byte(message), &pm); err != nil { + if err := json.Unmarshal([]byte(message), &pm, jsonx.V1()); err != nil { return fmt.Errorf( "%w: Invalid JSON in Message when MessageStructure is json: %s", ErrInvalidParameter, @@ -179,7 +180,7 @@ func parsePerProtocolMessages(message, messageStructure string) map[string]strin } var pm map[string]string - if err := json.Unmarshal([]byte(message), &pm); err != nil { + if err := json.Unmarshal([]byte(message), &pm, jsonx.V1()); err != nil { return nil } diff --git a/services/sns/publish_test.go b/services/sns/publish_test.go index 249191fce2..b450eb51bb 100644 --- a/services/sns/publish_test.go +++ b/services/sns/publish_test.go @@ -1,7 +1,7 @@ package sns_test import ( - "encoding/json" + "encoding/json/v2" "encoding/xml" "fmt" "io" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -742,7 +743,7 @@ func TestBatchMessageStructureJSON(t *testing.T) { case raw := <-received: // The delivered body should be the http-protocol-specific value. var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "http-specific", env.Message) } else { assert.Equal(t, "http-specific", raw) @@ -784,7 +785,7 @@ func TestBatchMessageStructureDefault(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "plain-text", env.Message) } else { assert.Equal(t, "plain-text", raw) @@ -988,7 +989,7 @@ func TestMessageStructureJSONSinglePublish(t *testing.T) { select { case raw := <-received: var env snsNotificationEnvelope - if json.Unmarshal([]byte(raw), &env) == nil { + if json.Unmarshal([]byte(raw), &env, jsonx.V1()) == nil { assert.Equal(t, "http-only", env.Message) } case <-time.After(2 * time.Second): diff --git a/services/sns/realism_sdk_test.go b/services/sns/realism_sdk_test.go index d5fdd1b650..843c02ebe1 100644 --- a/services/sns/realism_sdk_test.go +++ b/services/sns/realism_sdk_test.go @@ -1,7 +1,7 @@ package sns_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -298,7 +299,7 @@ func newConfirmationEndpoint(out chan<- map[string]string) *httptest.Server { body, _ := io.ReadAll(r.Body) var m map[string]string - if json.Unmarshal(body, &m) == nil && m["Type"] == "SubscriptionConfirmation" { + if json.Unmarshal(body, &m, jsonx.V1()) == nil && m["Type"] == "SubscriptionConfirmation" { select { case out <- m: default: diff --git a/services/sns/signing_channels_test.go b/services/sns/signing_channels_test.go index 89b691e275..4c2336e28e 100644 --- a/services/sns/signing_channels_test.go +++ b/services/sns/signing_channels_test.go @@ -7,7 +7,7 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "sync" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -66,7 +67,7 @@ func TestPublishSignaturesVerifyOnEveryChannel(t *testing.T) { body, _ := io.ReadAll(r.Body) var env snsNotificationEnvelope - if json.Unmarshal(body, &env) == nil { + if json.Unmarshal(body, &env, jsonx.V1()) == nil { httpEnvs <- env } diff --git a/services/sns/signing_test.go b/services/sns/signing_test.go index 3af027acd3..a86ebae249 100644 --- a/services/sns/signing_test.go +++ b/services/sns/signing_test.go @@ -7,7 +7,7 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "io" "net/http" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -76,7 +77,7 @@ func parseNotificationEnvelope(t *testing.T, body string) snsNotificationEnvelop t.Helper() var env snsNotificationEnvelope - require.NoError(t, json.Unmarshal([]byte(body), &env), "invalid SNS notification envelope") + require.NoError(t, json.Unmarshal([]byte(body), &env, jsonx.V1()), "invalid SNS notification envelope") return env } diff --git a/services/sns/subscription_attributes_test.go b/services/sns/subscription_attributes_test.go index a81f372ff7..10e8636f66 100644 --- a/services/sns/subscription_attributes_test.go +++ b/services/sns/subscription_attributes_test.go @@ -2,7 +2,7 @@ package sns_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/url" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sns" ) @@ -300,7 +301,7 @@ func TestSetSubscriptionAttributesDLQExistenceCheck(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": tt.dlqARN, - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) if tt.wantErr { @@ -327,7 +328,7 @@ func TestSetSubscriptionAttributesDLQNoCheckerSkips(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]string{ "deadLetterTargetArn": "arn:aws:sqs:us-east-1:123456789012:any-dlq", - }) + }, jsonx.V1()) err = b.SetSubscriptionAttributes(sub.SubscriptionArn, "RedrivePolicy", string(redrivePolicy)) require.NoError(t, err, "no checker means existence check is skipped") } diff --git a/services/sns/topic_attributes.go b/services/sns/topic_attributes.go index 4bd19e0e2d..229a164028 100644 --- a/services/sns/topic_attributes.go +++ b/services/sns/topic_attributes.go @@ -1,13 +1,16 @@ package sns import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "regexp" "sort" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // GetTopicAttributes returns the attributes of a topic. @@ -89,9 +92,9 @@ func (b *InMemoryBackend) GetTopicAttributes(topicArn string) (map[string]string // policyDocument mirrors the shape of an SNS access-control policy document // (docs.aws.amazon.com/sns/latest/dg/sns-access-policy-use-cases.html). type policyDocument struct { - Version string `json:"Version"` - ID string `json:"Id,omitempty"` - Statement []json.RawMessage `json:"Statement"` + Version string `json:"Version"` + ID string `json:"Id,omitempty"` + Statement []jsontext.Value `json:"Statement"` } // policyStatement is a single Allow statement built from an AddPermission grant. @@ -120,7 +123,7 @@ func mergePermissionsIntoPolicy(basePolicy, topicArn string, perms map[string]*T } var doc policyDocument - if err := json.Unmarshal([]byte(basePolicy), &doc); err != nil || doc.Version == "" { + if err := json.Unmarshal([]byte(basePolicy), &doc, jsonx.V1()); err != nil || doc.Version == "" { doc.Version = "2012-10-17" } @@ -131,13 +134,13 @@ func mergePermissionsIntoPolicy(basePolicy, topicArn string, perms map[string]*T sort.Strings(labels) - kept := make([]json.RawMessage, 0, len(doc.Statement)) + kept := make([]jsontext.Value, 0, len(doc.Statement)) for _, raw := range doc.Statement { var sid struct { Sid string `json:"Sid"` } - if err := json.Unmarshal(raw, &sid); err == nil { + if err := json.Unmarshal(raw, &sid, jsonx.V1()); err == nil { if _, isPermission := perms[sid.Sid]; isPermission { continue } @@ -147,7 +150,7 @@ func mergePermissionsIntoPolicy(basePolicy, topicArn string, perms map[string]*T } for _, label := range labels { - raw, err := json.Marshal(permissionStatement(topicArn, perms[label])) + raw, err := json.Marshal(permissionStatement(topicArn, perms[label]), jsonx.V1()) if err != nil { continue } @@ -157,7 +160,7 @@ func mergePermissionsIntoPolicy(basePolicy, topicArn string, perms map[string]*T doc.Statement = kept - out, err := json.Marshal(doc) + out, err := json.Marshal(doc, jsonx.V1()) if err != nil { return basePolicy } @@ -478,8 +481,8 @@ func validateDataProtectionPolicy(policy string) error { ) } - var doc map[string]json.RawMessage - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + var doc map[string]jsontext.Value + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return fmt.Errorf("%w: DataProtectionPolicy must be a valid JSON object", ErrInvalidParameter) } diff --git a/services/sqs/bench_protocol_test.go b/services/sqs/bench_protocol_test.go index 59280edf57..abc316e193 100644 --- a/services/sqs/bench_protocol_test.go +++ b/services/sqs/bench_protocol_test.go @@ -2,7 +2,7 @@ package sqs_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "net/url" @@ -13,6 +13,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -82,7 +83,7 @@ func jsonSendBody(b *testing.B, qURL string) []byte { "attr-one": map[string]any{"DataType": "String", "StringValue": "value-one"}, "attr-two": map[string]any{"DataType": "Number", "StringValue": "42"}, }, - }) + }, jsonx.V1()) if err != nil { b.Fatalf("marshal send body: %v", err) } @@ -144,7 +145,7 @@ func BenchmarkJSONSendMessageBatch10(b *testing.B) { } } - body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "Entries": entries}) + body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "Entries": entries}, jsonx.V1()) if err != nil { b.Fatalf("marshal batch body: %v", err) } @@ -196,7 +197,7 @@ func BenchmarkJSONReceiveMessage10_Depth10000(b *testing.B) { h := sqs.NewHandler(backend) qURL := setupReceiveDepthQueue(b, backend, "bench-json-recv-q") - body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "MaxNumberOfMessages": 10}) + body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "MaxNumberOfMessages": 10}, jsonx.V1()) if err != nil { b.Fatalf("marshal receive body: %v", err) } @@ -271,7 +272,7 @@ func BenchmarkJSONReceiveMessage10_FIFOManyGroups(b *testing.B) { h := sqs.NewHandler(backend) qURL := setupFIFOManyGroups(b, backend, "bench-json-fifo-recv-q", 1000, 10) - body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "MaxNumberOfMessages": 10}) + body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "MaxNumberOfMessages": 10}, jsonx.V1()) if err != nil { b.Fatalf("marshal receive body: %v", err) } @@ -332,7 +333,7 @@ func BenchmarkJSONDeleteMessage(b *testing.B) { bodies := make([][]byte, len(handles)) for i, rh := range handles { - body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "ReceiptHandle": rh}) + body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "ReceiptHandle": rh}, jsonx.V1()) if err != nil { b.Fatalf("marshal delete body: %v", err) } @@ -385,7 +386,7 @@ func BenchmarkJSONDeleteMessageBatch10(b *testing.B) { for i, m := range recv.Messages { entries[i] = map[string]any{"Id": strconv.Itoa(i), "ReceiptHandle": m.ReceiptHandle} } - body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "Entries": entries}) + body, err := json.Marshal(map[string]any{"QueueUrl": qURL, "Entries": entries}, jsonx.V1()) if err != nil { b.Fatalf("marshal delete batch body: %v", err) } diff --git a/services/sqs/checksums_test.go b/services/sqs/checksums_test.go index 38dfd87a18..450f01380b 100644 --- a/services/sqs/checksums_test.go +++ b/services/sqs/checksums_test.go @@ -1,12 +1,13 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -190,7 +191,7 @@ func TestComputeMD5OfMessageAttributes_FullSetUsesPrecomputed(t *testing.T) { require.Equal(t, 200, recvRec.Code) var recvResp recvResponse - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) // The MD5 must be non-empty when attributes are returned. @@ -261,7 +262,7 @@ func TestReceiveMessage_MD5Consistency(t *testing.T) { require.Equal(t, 200, recvRec.Code) var recvResp recvMD5Only - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) assert.Equal(t, tt.wantMD5, recvResp.Messages[0].MD5OfMessageAttributes, diff --git a/services/sqs/dead_letter.go b/services/sqs/dead_letter.go index bdc508a915..4273e2322e 100644 --- a/services/sqs/dead_letter.go +++ b/services/sqs/dead_letter.go @@ -1,20 +1,21 @@ package sqs import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "slices" "sort" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) // redrivePolicy represents the JSON structure of an SQS RedrivePolicy attribute. type redrivePolicy struct { - DeadLetterTargetArn string `json:"deadLetterTargetArn"` - MaxReceiveCount json.Number `json:"maxReceiveCount"` + DeadLetterTargetArn string `json:"deadLetterTargetArn"` + MaxReceiveCount jsonx.Number `json:"maxReceiveCount"` } // applyRedrivePolicy parses the RedrivePolicy attribute and wires up DLQ fields on q. @@ -32,7 +33,7 @@ func applyRedrivePolicy(q *Queue, attrs map[string]string, backend *InMemoryBack var pol redrivePolicy - if err := json.Unmarshal([]byte(raw), &pol); err != nil { + if err := json.Unmarshal([]byte(raw), &pol, jsonx.V1()); err != nil { return &InvalidParameterError{Message: "Invalid value for the parameter RedrivePolicy."} } @@ -134,7 +135,7 @@ func checkRedriveAllowPolicy(dlq *Queue, srcArn string) error { // never left with a malformed value; treat it permissively rather than // blocking on a defensive parse error. //nolint:nilerr // intentional fail-open on a defensive parse error, see comment above - if json.Unmarshal([]byte(raw), &policy) != nil { + if json.Unmarshal([]byte(raw), &policy, jsonx.V1()) != nil { return nil } @@ -178,7 +179,7 @@ func (b *InMemoryBackend) ListDeadLetterSourceQueues( } var pol redrivePolicy - if err := json.Unmarshal([]byte(raw), &pol); err != nil { + if err := json.Unmarshal([]byte(raw), &pol, jsonx.V1()); err != nil { continue } diff --git a/services/sqs/dead_letter_test.go b/services/sqs/dead_letter_test.go index 8bd599ee53..dc4ed7f088 100644 --- a/services/sqs/dead_letter_test.go +++ b/services/sqs/dead_letter_test.go @@ -1,7 +1,7 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "strconv" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -29,7 +30,7 @@ func TestRedriveAllowPolicy(t *testing.T) { rap, _ := json.Marshal(map[string]any{ "redrivePermission": "byQueue", "sourceQueueArns": []string{dlqARN}, - }) + }, jsonx.V1()) _, err = b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "src", @@ -54,7 +55,7 @@ func TestRedrivePolicy_MovesToDLQAfterMaxReceiveCount(t *testing.T) { redriveJSON, _ := json.Marshal(map[string]any{ "deadLetterTargetArn": dlqARN, "maxReceiveCount": 2, - }) + }, jsonx.V1()) srcURL, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "src-with-dlq", @@ -104,7 +105,7 @@ func TestRedrivePolicy_SetViaSetQueueAttributes(t *testing.T) { redriveJSON, _ := json.Marshal(map[string]any{ "deadLetterTargetArn": dlqARN, "maxReceiveCount": 3, - }) + }, jsonx.V1()) err := b.SetQueueAttributes(&sqs.SetQueueAttributesInput{ QueueURL: srcURL, @@ -117,7 +118,7 @@ func TestRedrivePolicy_SetViaSetQueueAttributes(t *testing.T) { // Verify round-trip via GetQueueAttributes attrs := b2getAttrs(t, b, srcURL, "RedrivePolicy") var pol map[string]any - require.NoError(t, json.Unmarshal([]byte(attrs["RedrivePolicy"]), &pol)) + require.NoError(t, json.Unmarshal([]byte(attrs["RedrivePolicy"]), &pol, jsonx.V1())) assert.Equal(t, dlqARN, pol["deadLetterTargetArn"]) } @@ -130,7 +131,7 @@ func TestListDeadLetterSourceQueues_SingleSource(t *testing.T) { dlqARN := dlqAttrs["QueueArn"] makeRedriveAttr := func(arn string, count int) string { - v, _ := json.Marshal(map[string]any{"deadLetterTargetArn": arn, "maxReceiveCount": count}) + v, _ := json.Marshal(map[string]any{"deadLetterTargetArn": arn, "maxReceiveCount": count}, jsonx.V1()) return string(v) } @@ -178,7 +179,7 @@ func TestRedriveAllowPolicy_AllowAll(t *testing.T) { t.Parallel() b := b2newBackend(t) - policy, _ := json.Marshal(map[string]any{"redrivePermission": "allowAll"}) + policy, _ := json.Marshal(map[string]any{"redrivePermission": "allowAll"}, jsonx.V1()) _, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "rap-allow-all", @@ -194,7 +195,7 @@ func TestRedriveAllowPolicy_DenyAll(t *testing.T) { t.Parallel() b := b2newBackend(t) - policy, _ := json.Marshal(map[string]any{"redrivePermission": "denyAll"}) + policy, _ := json.Marshal(map[string]any{"redrivePermission": "denyAll"}, jsonx.V1()) _, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "rap-deny-all", @@ -213,7 +214,7 @@ func TestRedriveAllowPolicy_ByQueue(t *testing.T) { policy, _ := json.Marshal(map[string]any{ "redrivePermission": "byQueue", "sourceQueueArns": []string{"arn:aws:sqs:us-east-1:123456789012:src-queue"}, - }) + }, jsonx.V1()) _, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "rap-by-queue", @@ -232,7 +233,7 @@ func TestRedriveAllowPolicy_AllowAllWithArns_Rejected(t *testing.T) { policy, _ := json.Marshal(map[string]any{ "redrivePermission": "allowAll", "sourceQueueArns": []string{"arn:aws:sqs:us-east-1:123456789012:q"}, - }) + }, jsonx.V1()) _, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "rap-invalid", @@ -255,7 +256,7 @@ func TestRedriveAllowPolicy_ByQueueTooManyArns_Rejected(t *testing.T) { policy, _ := json.Marshal(map[string]any{ "redrivePermission": "byQueue", "sourceQueueArns": arns, - }) + }, jsonx.V1()) _, err := b.CreateQueue(&sqs.CreateQueueInput{ QueueName: "rap-toomany", @@ -271,7 +272,7 @@ func TestRedriveAllowPolicy_RoundTrip(t *testing.T) { t.Parallel() b := b2newBackend(t) - policy, _ := json.Marshal(map[string]any{"redrivePermission": "denyAll"}) + policy, _ := json.Marshal(map[string]any{"redrivePermission": "denyAll"}, jsonx.V1()) qURL := b2createQueue(t, b, "rap-roundtrip") require.NoError(t, b.SetQueueAttributes(&sqs.SetQueueAttributesInput{ @@ -700,7 +701,7 @@ func TestSQS_DLQRedrive_DefaultDestination(t *testing.T) { redrivePolicy, _ := json.Marshal(map[string]any{ "deadLetterTargetArn": dlqARN, "maxReceiveCount": 3, - }) + }, jsonx.V1()) _, err = b.CreateQueue(&sqs.CreateQueueInput{ QueueName: srcName, @@ -824,7 +825,7 @@ func makeRedrivePolicy(dlqARN string, maxReceiveCount int) string { b, _ := json.Marshal(map[string]any{ "deadLetterTargetArn": dlqARN, "maxReceiveCount": maxReceiveCount, - }) + }, jsonx.V1()) return string(b) } diff --git a/services/sqs/errsweep_wire_shape_test.go b/services/sqs/errsweep_wire_shape_test.go index 07d8b0515f..40d200236f 100644 --- a/services/sqs/errsweep_wire_shape_test.go +++ b/services/sqs/errsweep_wire_shape_test.go @@ -3,7 +3,7 @@ package sqs_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -17,6 +17,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/sqs" @@ -56,7 +57,7 @@ func TestSDK_GetQueueUrl_NonExistentQueue_TypedError(t *testing.T) { rawBody := rawSQSErrorBody(t, rawURL, "GetQueueUrl", `{"QueueName":"does-not-exist"}`) var decoded map[string]any - require.NoError(t, json.Unmarshal(rawBody, &decoded)) + require.NoError(t, json.Unmarshal(rawBody, &decoded, jsonx.V1())) require.Equal(t, "com.amazonaws.sqs#QueueDoesNotExist", decoded["__type"], "raw response body must carry __type; got: %s", rawBody) _, hasBareCode := decoded["code"] diff --git a/services/sqs/fifo_test.go b/services/sqs/fifo_test.go index 3a17d94fe3..a98685c0c1 100644 --- a/services/sqs/fifo_test.go +++ b/services/sqs/fifo_test.go @@ -2,7 +2,8 @@ package sqs_test import ( "encoding/hex" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -201,7 +203,7 @@ func TestSetQueueAttributesFifoQueueRejectedViaHandler(t *testing.T) { Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Contains(t, errResp.Type, "InvalidAttributeName") } @@ -344,8 +346,8 @@ func TestSendMessage_Standard_SequenceNumberAbsent(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) // Unmarshal into a raw map so we can check key presence, not just value. - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasSeqNum := raw["SequenceNumber"] assert.False(t, hasSeqNum, "standard queue SendMessage response must not contain SequenceNumber") @@ -371,7 +373,7 @@ func TestSendMessage_FIFO_SequenceNumberPresent(t *testing.T) { var createResp struct { QueueURL string `json:"QueueUrl"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rec := doRequest(t, h, "SendMessage", map[string]any{ "QueueUrl": createResp.QueueURL, @@ -380,14 +382,14 @@ func TestSendMessage_FIFO_SequenceNumberPresent(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) rawSeq, hasSeqNum := raw["SequenceNumber"] require.True(t, hasSeqNum, "FIFO queue SendMessage response must contain SequenceNumber") var seq string - require.NoError(t, json.Unmarshal(rawSeq, &seq)) + require.NoError(t, json.Unmarshal(rawSeq, &seq, jsonx.V1())) assert.NotEmpty(t, seq, "SequenceNumber must be non-empty for FIFO queue") assert.Len(t, seq, 20, "SequenceNumber must be 20 digits") } diff --git a/services/sqs/handler.go b/services/sqs/handler.go index b6f9bc4d47..d87a14964b 100644 --- a/services/sqs/handler.go +++ b/services/sqs/handler.go @@ -2,7 +2,7 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "strings" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/endpointstrategy" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -293,7 +294,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var req extractQueueURLInput - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -368,7 +369,7 @@ func (h *Handler) sqsRoute( return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // handleError writes an SQS error response using the standard error details mapping. @@ -386,7 +387,7 @@ func (h *Handler) sqsRoute( func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { errType, message, status := errorDetails(err) - payload, marshalErr := json.Marshal(jsonSQSError{Type: errType, Message: message}) + payload, marshalErr := json.Marshal(jsonSQSError{Type: errType, Message: message}, jsonx.V1()) if marshalErr != nil { return marshalErr } diff --git a/services/sqs/handler_dead_letter.go b/services/sqs/handler_dead_letter.go index 9e6747ddb8..c909c17dec 100644 --- a/services/sqs/handler_dead_letter.go +++ b/services/sqs/handler_dead_letter.go @@ -2,8 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonListDeadLetterSourceQueuesReq struct { @@ -23,7 +25,7 @@ func (h *Handler) handleListDeadLetterSourceQueues( body []byte, ) (any, error) { var req jsonListDeadLetterSourceQueuesReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_dead_letter_test.go b/services/sqs/handler_dead_letter_test.go index 6ef6f501e0..a6922bbe39 100644 --- a/services/sqs/handler_dead_letter_test.go +++ b/services/sqs/handler_dead_letter_test.go @@ -1,13 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -36,7 +37,7 @@ func TestHandlerActions_ListDeadLetterSourceQueues(t *testing.T) { var attrResp struct { Attributes map[string]string `json:"Attributes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &attrResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &attrResp, jsonx.V1())) dlqARN := attrResp.Attributes["QueueArn"] policy := `{"deadLetterTargetArn":"` + dlqARN + `","maxReceiveCount":3}` @@ -97,7 +98,7 @@ func TestHandlerActions_ListDeadLetterSourceQueues(t *testing.T) { NextToken string `json:"NextToken"` QueueURLs []string `json:"queueUrls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.QueueURLs, tt.wantURLCount) } }) diff --git a/services/sqs/handler_message_move_tasks.go b/services/sqs/handler_message_move_tasks.go index cf32fbc95c..92b5668ee5 100644 --- a/services/sqs/handler_message_move_tasks.go +++ b/services/sqs/handler_message_move_tasks.go @@ -2,8 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonStartMessageMoveTaskReq struct { @@ -54,7 +56,7 @@ func (h *Handler) handleStartMessageMoveTask( body []byte, ) (any, error) { var req jsonStartMessageMoveTaskReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -76,7 +78,7 @@ func (h *Handler) handleCancelMessageMoveTask( body []byte, ) (any, error) { var req jsonCancelMessageMoveTaskReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -99,7 +101,7 @@ func (h *Handler) handleListMessageMoveTasks( ) (any, error) { var req jsonListMessageMoveTasksReq // Body may be empty; ignore unmarshal errors. - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) out, err := h.Backend.ListMessageMoveTasks(&ListMessageMoveTasksInput{ SourceArn: req.SourceArn, diff --git a/services/sqs/handler_message_visibility.go b/services/sqs/handler_message_visibility.go index f782b511ab..bba39f76db 100644 --- a/services/sqs/handler_message_visibility.go +++ b/services/sqs/handler_message_visibility.go @@ -2,8 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonChangeVisibilityReq struct { @@ -29,7 +31,7 @@ func (h *Handler) handleChangeMessageVisibility( body []byte, ) (any, error) { var req jsonChangeVisibilityReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -52,7 +54,7 @@ func (h *Handler) handleChangeMessageVisibilityBatch( body []byte, ) (any, error) { var req jsonChangeVisibilityBatchReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_message_visibility_test.go b/services/sqs/handler_message_visibility_test.go index 348fb69c2e..b5d4e73273 100644 --- a/services/sqs/handler_message_visibility_test.go +++ b/services/sqs/handler_message_visibility_test.go @@ -1,12 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSQSHandler_ChangeMessageVisibility_InvalidJSON(t *testing.T) { @@ -73,7 +75,7 @@ func TestSQSHandler_ChangeMessageVisibility_Success(t *testing.T) { } `json:"Messages"` } - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) rec := doRequest(t, h, "ChangeMessageVisibility", map[string]any{ @@ -107,7 +109,7 @@ func TestHandlerActions_ChangeMessageVisibility(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) receipt := recvResp.Messages[0].ReceiptHandle @@ -162,7 +164,7 @@ func TestHandlerActions_ChangeMessageVisibilityBatch(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rcvRec.Body.Bytes(), &rcvResp)) + require.NoError(t, json.Unmarshal(rcvRec.Body.Bytes(), &rcvResp, jsonx.V1())) require.Len(t, rcvResp.Messages, 1) handle := rcvResp.Messages[0].ReceiptHandle @@ -213,7 +215,7 @@ func TestHandlerActions_ChangeMessageVisibilityBatch(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rcvRec.Body.Bytes(), &rcvResp)) + require.NoError(t, json.Unmarshal(rcvRec.Body.Bytes(), &rcvResp, jsonx.V1())) require.Len(t, rcvResp.Messages, 2) rec := doRequest(t, h, "ChangeMessageVisibilityBatch", map[string]any{ @@ -236,7 +238,7 @@ func TestHandlerActions_ChangeMessageVisibilityBatch(t *testing.T) { SenderFault bool `json:"SenderFault"` } `json:"Failed"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.Successful, 2) assert.ElementsMatch(t, []string{"good-1", "good-2"}, []string{body.Successful[0].ID, body.Successful[1].ID}) @@ -261,7 +263,7 @@ func TestHandlerActions_ChangeMessageVisibilityBatch(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(reRcvRec.Body.Bytes(), &reRcvResp)) + require.NoError(t, json.Unmarshal(reRcvRec.Body.Bytes(), &reRcvResp, jsonx.V1())) assert.Len(t, reRcvResp.Messages, 2) }) } diff --git a/services/sqs/handler_messages.go b/services/sqs/handler_messages.go index 599a40f6be..1168cc632e 100644 --- a/services/sqs/handler_messages.go +++ b/services/sqs/handler_messages.go @@ -2,9 +2,11 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonMsgAttr struct { @@ -113,7 +115,7 @@ func (h *Handler) handleSendMessage( body []byte, ) (any, error) { var req jsonSendMessageReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -146,7 +148,7 @@ func (h *Handler) handleReceiveMessage( body []byte, ) (any, error) { var req jsonReceiveMessageReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -237,7 +239,7 @@ func (h *Handler) handleDeleteMessage( body []byte, ) (any, error) { var req jsonDeleteMessageReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -258,7 +260,7 @@ func (h *Handler) handleSendMessageBatch( body []byte, ) (any, error) { var req jsonSendMessageBatchReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -314,7 +316,7 @@ func (h *Handler) handleDeleteMessageBatch( body []byte, ) (any, error) { var req jsonDeleteMessageBatchReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_messages_test.go b/services/sqs/handler_messages_test.go index 017633eab3..afd2341246 100644 --- a/services/sqs/handler_messages_test.go +++ b/services/sqs/handler_messages_test.go @@ -1,7 +1,7 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -28,7 +29,7 @@ func TestHandlerActions_SendMessage(t *testing.T) { MessageID string `json:"MessageId"` MD5OfMessageBody string `json:"MD5OfMessageBody"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.MessageID) assert.NotEmpty(t, resp.MD5OfMessageBody) } @@ -59,7 +60,7 @@ func TestHandlerActions_ReceiveMessage(t *testing.T) { Body string `json:"Body"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Messages, 1) assert.Equal(t, "hello", resp.Messages[0].Body) }) @@ -86,7 +87,7 @@ func TestHandlerActions_ReceiveMessage(t *testing.T) { Body string `json:"Body"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Messages, 1) }) } @@ -153,7 +154,7 @@ func TestHandlerActions_ReceiveMessageAttributeNamesFilter(t *testing.T) { MessageAttributes map[string]map[string]any `json:"MessageAttributes"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Messages, 1) assert.Len(t, resp.Messages[0].MessageAttributes, tt.wantAttrNamesLen) for _, name := range tt.wantAttrNames { @@ -181,7 +182,7 @@ func sendForMD5(t *testing.T, h *sqs.Handler, queueURL string, attrs map[string] var resp struct { MD5OfMessageAttributes string `json:"MD5OfMessageAttributes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp.MD5OfMessageAttributes } @@ -261,7 +262,7 @@ func TestHandlerActions_ReceiveMessageMD5OverSubset(t *testing.T) { MD5OfMessageAttributes string `json:"MD5OfMessageAttributes"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Messages, 1) if tt.wantEmptyMD5 { @@ -305,7 +306,7 @@ func TestHandlerActions_DeleteMessage(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) receipt := recvResp.Messages[0].ReceiptHandle @@ -354,7 +355,7 @@ func TestHandlerActions_SendMessageBatch(t *testing.T) { ID string `json:"Id"` } `json:"Successful"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Successful, 2) }) @@ -370,7 +371,7 @@ func TestHandlerActions_SendMessageBatch(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "com.amazonaws.sqs#QueueDoesNotExist", errResp.Type) }) @@ -387,7 +388,7 @@ func TestHandlerActions_SendMessageBatch(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "com.amazonaws.sqs#EmptyBatchRequest", errResp.Type) }) @@ -416,7 +417,7 @@ func TestHandlerActions_SendMessageBatch(t *testing.T) { ID string `json:"Id"` } `json:"Successful"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Successful, 10) }) } @@ -442,7 +443,7 @@ func TestHandlerActions_DeleteMessageBatch(t *testing.T) { ReceiptHandle string `json:"ReceiptHandle"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp)) + require.NoError(t, json.Unmarshal(recvRec.Body.Bytes(), &recvResp, jsonx.V1())) require.Len(t, recvResp.Messages, 1) receipt := recvResp.Messages[0].ReceiptHandle @@ -458,7 +459,7 @@ func TestHandlerActions_DeleteMessageBatch(t *testing.T) { ID string `json:"Id"` } `json:"Successful"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Successful, 1) }) @@ -474,7 +475,7 @@ func TestHandlerActions_DeleteMessageBatch(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "com.amazonaws.sqs#QueueDoesNotExist", errResp.Type) }) @@ -495,7 +496,7 @@ func TestHandlerActions_DeleteMessageBatch(t *testing.T) { ID string `json:"Id"` } `json:"Failed"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Failed, 1) }) @@ -512,7 +513,7 @@ func TestHandlerActions_DeleteMessageBatch(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "com.amazonaws.sqs#EmptyBatchRequest", errResp.Type) }) } diff --git a/services/sqs/handler_permissions.go b/services/sqs/handler_permissions.go index b77f678b52..b1c84e2292 100644 --- a/services/sqs/handler_permissions.go +++ b/services/sqs/handler_permissions.go @@ -2,8 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonAddPermissionReq struct { @@ -24,7 +26,7 @@ func (h *Handler) handleAddPermission( body []byte, ) (any, error) { var req jsonAddPermissionReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -47,7 +49,7 @@ func (h *Handler) handleRemovePermission( body []byte, ) (any, error) { var req jsonRemovePermissionReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_queue_attributes.go b/services/sqs/handler_queue_attributes.go index de8c6898ae..3b44edb589 100644 --- a/services/sqs/handler_queue_attributes.go +++ b/services/sqs/handler_queue_attributes.go @@ -2,8 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type jsonGetQueueAttributesReq struct { @@ -26,7 +28,7 @@ func (h *Handler) handleGetQueueAttributes( body []byte, ) (any, error) { var req jsonGetQueueAttributesReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -53,7 +55,7 @@ func (h *Handler) handleSetQueueAttributes( body []byte, ) (any, error) { var req jsonSetQueueAttributesReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_queues.go b/services/sqs/handler_queues.go index c3f09df6da..8dfceaf053 100644 --- a/services/sqs/handler_queues.go +++ b/services/sqs/handler_queues.go @@ -2,10 +2,11 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -46,7 +47,7 @@ func (h *Handler) handleCreateQueue( body []byte, ) (any, error) { var req jsonCreateQueueReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -92,7 +93,7 @@ func (h *Handler) handleDeleteQueue( body []byte, ) (any, error) { var req jsonQueueURLReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -112,7 +113,7 @@ func (h *Handler) handleListQueues( ) (any, error) { var req jsonListQueuesReq // ListQueues body may be empty; ignore unmarshal errors - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) region := h.requestScope(r) @@ -140,7 +141,7 @@ func (h *Handler) handleGetQueueURL( body []byte, ) (any, error) { var req jsonGetQueueURLReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -162,7 +163,7 @@ func (h *Handler) handlePurgeQueue( body []byte, ) (any, error) { var req jsonQueueURLReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_queues_test.go b/services/sqs/handler_queues_test.go index d4e847b974..53926a7edf 100644 --- a/services/sqs/handler_queues_test.go +++ b/services/sqs/handler_queues_test.go @@ -1,13 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -150,7 +151,7 @@ func TestHandlerActions_ListQueues(t *testing.T) { NextToken string `json:"NextToken"` QueueURLs []string `json:"QueueUrls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.QueueURLs, tt.wantURLCount) }) } @@ -180,7 +181,7 @@ func TestHandlerActions_ListQueues_PaginationRoundTrip(t *testing.T) { NextToken string `json:"NextToken"` QueueURLs []string `json:"QueueUrls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) allURLs = append(allURLs, resp.QueueURLs...) nextToken = resp.NextToken @@ -281,7 +282,7 @@ func TestHandlerActions_QueueManagement(t *testing.T) { var resp struct { Attributes map[string]string `json:"Attributes"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.Attributes) }) diff --git a/services/sqs/handler_tags.go b/services/sqs/handler_tags.go index 290910ad2f..2b0fc99b00 100644 --- a/services/sqs/handler_tags.go +++ b/services/sqs/handler_tags.go @@ -2,9 +2,10 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -30,7 +31,7 @@ func (h *Handler) handleTagQueue( body []byte, ) (any, error) { var req jsonTagQueueReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -51,7 +52,7 @@ func (h *Handler) handleUntagQueue( body []byte, ) (any, error) { var req jsonUntagQueueReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } @@ -72,7 +73,7 @@ func (h *Handler) handleListQueueTags( body []byte, ) (any, error) { var req jsonQueueURLReq - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, ErrUnknownAction } diff --git a/services/sqs/handler_tags_test.go b/services/sqs/handler_tags_test.go index 7e9983a23a..5cddbc4b66 100644 --- a/services/sqs/handler_tags_test.go +++ b/services/sqs/handler_tags_test.go @@ -1,12 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestSQSHandler_UntagQueue_InvalidJSON(t *testing.T) { @@ -132,7 +134,7 @@ func TestHandlerActions_TagOps(t *testing.T) { var resp struct { Tags map[string]string `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp.Tags) }) diff --git a/services/sqs/handler_test.go b/services/sqs/handler_test.go index b49869fc95..e3dc1fc0ac 100644 --- a/services/sqs/handler_test.go +++ b/services/sqs/handler_test.go @@ -2,7 +2,7 @@ package sqs_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "errors" "log/slog" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -73,7 +74,7 @@ func TestSQSHandler_Reset(t *testing.T) { QueueURLs []string `json:"QueueUrls"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp.QueueURLs, tt.name) }) } @@ -156,7 +157,7 @@ func doRequest(t *testing.T, h *sqs.Handler, action string, body any) *httptest. var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -189,7 +190,7 @@ func doCreateQueue(t *testing.T, h *sqs.Handler, name string) string { QueueURL string `json:"QueueUrl"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp.QueueURL } diff --git a/services/sqs/message_move_tasks.go b/services/sqs/message_move_tasks.go index 18f01847e9..f2a0fb6b39 100644 --- a/services/sqs/message_move_tasks.go +++ b/services/sqs/message_move_tasks.go @@ -2,7 +2,7 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "sort" "sync" "time" @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // moveTaskVisibilityTimeoutSecs is the visibility timeout used when receiving @@ -87,7 +88,7 @@ func (b *InMemoryBackend) findDefaultMoveDestinationLocked(dlqARN string) (strin var pol redrivePolicy - if err := json.Unmarshal([]byte(raw), &pol); err != nil { + if err := json.Unmarshal([]byte(raw), &pol, jsonx.V1()); err != nil { continue } diff --git a/services/sqs/message_move_tasks_test.go b/services/sqs/message_move_tasks_test.go index 5dea157ef9..8a3ced4d0b 100644 --- a/services/sqs/message_move_tasks_test.go +++ b/services/sqs/message_move_tasks_test.go @@ -1,7 +1,7 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -539,7 +540,7 @@ func TestSQS_MessageMoveTasks_Handler(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) handle, _ := startResp["TaskHandle"].(string) require.NotEmpty(t, handle) diff --git a/services/sqs/message_visibility_test.go b/services/sqs/message_visibility_test.go index 4e52f1d57c..f4b304c68c 100644 --- a/services/sqs/message_visibility_test.go +++ b/services/sqs/message_visibility_test.go @@ -1,7 +1,7 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "log/slog" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -239,7 +240,7 @@ func TestReceiveMessage_VisibilityTimeout_OutOfRange(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrType, errResp.Type) }) } @@ -282,7 +283,7 @@ func TestReceiveMessage_VisibilityTimeout_ValidBoundaries(t *testing.T) { Body string `json:"Body"` } `json:"Messages"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Messages, 1) }) } diff --git a/services/sqs/messages_test.go b/services/sqs/messages_test.go index 9dbe179c20..5e44c65d1a 100644 --- a/services/sqs/messages_test.go +++ b/services/sqs/messages_test.go @@ -3,7 +3,7 @@ package sqs_test import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "encoding/xml" "fmt" "maps" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/tags" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -1335,7 +1336,7 @@ func TestReceiveMessage_MaxNumberOfMessages_Validation(t *testing.T) { if tt.wantType != "" { var resp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp.Type) } }) diff --git a/services/sqs/permissions.go b/services/sqs/permissions.go index d3ebd9a774..3c9a2c424e 100644 --- a/services/sqs/permissions.go +++ b/services/sqs/permissions.go @@ -1,11 +1,12 @@ package sqs import ( - "encoding/json" + "encoding/json/v2" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // iamPolicyDocument represents the IAM resource policy document stored in the @@ -81,7 +82,7 @@ func buildQueueIAMPolicy(q *Queue) { Statement: stmts, } - raw, err := json.Marshal(doc) + raw, err := json.Marshal(doc, jsonx.V1()) if err != nil { return } diff --git a/services/sqs/permissions_test.go b/services/sqs/permissions_test.go index 031b31980d..1b8f0842a7 100644 --- a/services/sqs/permissions_test.go +++ b/services/sqs/permissions_test.go @@ -1,13 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -253,7 +254,7 @@ func TestAddPermission_UpdatesPolicyAttribute(t *testing.T) { assert.NotEmpty(t, policyJSON) var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(policyJSON), &doc)) + require.NoError(t, json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1())) assert.Equal(t, "2012-10-17", doc["Version"]) stmts := doc["Statement"].([]any) @@ -279,7 +280,7 @@ func TestAddPermission_WildcardAction(t *testing.T) { attrs := b2getAttrs(t, b, qURL, "Policy") var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc)) + require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc, jsonx.V1())) stmts := doc["Statement"].([]any) stmt := stmts[0].(map[string]any) actions := stmt["Action"].([]any) @@ -330,7 +331,7 @@ func TestAddPermission_MultipleStatements(t *testing.T) { attrs := b2getAttrs(t, b, qURL, "Policy") var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc)) + require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc, jsonx.V1())) stmts := doc["Statement"].([]any) assert.Len(t, stmts, 2) } @@ -357,7 +358,7 @@ func TestRemovePermission_PartialRemoval(t *testing.T) { attrs := b2getAttrs(t, b, qURL, "Policy") var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc)) + require.NoError(t, json.Unmarshal([]byte(attrs["Policy"]), &doc, jsonx.V1())) stmts := doc["Statement"].([]any) assert.Len(t, stmts, 1) stmt := stmts[0].(map[string]any) diff --git a/services/sqs/persistence.go b/services/sqs/persistence.go index a93409205d..918b8245a5 100644 --- a/services/sqs/persistence.go +++ b/services/sqs/persistence.go @@ -2,10 +2,12 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -94,21 +96,21 @@ type backendSnapshot struct { // wait-before-recreate rule for any queue deleted just before the // snapshot. Keyed by queueKey(region, name) since the deleted queue no // longer has a live Queue struct to attach this to. - RecentlyDeleted map[string]int64 `json:"recentlyDeleted,omitempty"` - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + RecentlyDeleted map[string]int64 `json:"recentlyDeleted,omitempty"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // marshalQueuesLocked marshals each queue's DTO to JSON while q.mu is held, then reassembles the JSON array. // queues must already be sorted, as [store.Table.Snapshot] returns them, to keep the wire format unchanged. -func marshalQueuesLocked(queues []*Queue) (json.RawMessage, error) { +func marshalQueuesLocked(queues []*Queue) (jsontext.Value, error) { if len(queues) == 0 { - return json.RawMessage("null"), nil + return jsontext.Value("null"), nil } - parts := make([]json.RawMessage, len(queues)) + parts := make([]jsontext.Value, len(queues)) for i, q := range queues { q.mu.Lock() @@ -135,7 +137,7 @@ func marshalQueuesLocked(queues []*Queue) (json.RawMessage, error) { IsFIFO: q.IsFIFO, FifoSeqCounter: q.fifoSeqCounter, LastPurgedAtUnixMilli: lastPurgedAtMillis, - }) + }, jsonx.V1()) q.mu.Unlock() @@ -146,7 +148,7 @@ func marshalQueuesLocked(queues []*Queue) (json.RawMessage, error) { parts[i] = data } - return json.Marshal(parts) + return json.Marshal(parts, jsonx.V1()) } // Snapshot serialises the backend state to JSON. diff --git a/services/sqs/queue_attributes.go b/services/sqs/queue_attributes.go index 51fd419c3d..8ea9aca476 100644 --- a/services/sqs/queue_attributes.go +++ b/services/sqs/queue_attributes.go @@ -1,9 +1,11 @@ package sqs import ( - "encoding/json" + "encoding/json/v2" "slices" "strconv" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // GetQueueAttributes returns queue attributes, computing dynamic ones on the fly. @@ -205,7 +207,7 @@ func validateRedriveAllowPolicy(raw string) error { SourceQueueArns []string `json:"sourceQueueArns"` } - if err := json.Unmarshal([]byte(raw), &policy); err != nil { + if err := json.Unmarshal([]byte(raw), &policy, jsonx.V1()); err != nil { return ErrInvalidAttribute } diff --git a/services/sqs/queues_test.go b/services/sqs/queues_test.go index 37666b250b..4aed59eeeb 100644 --- a/services/sqs/queues_test.go +++ b/services/sqs/queues_test.go @@ -1,7 +1,7 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -640,7 +641,7 @@ func TestCreateQueue_NameValidation(t *testing.T) { if tt.wantType != "" { var resp jsonErr - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp.Type) } }) diff --git a/services/sqs/sns_delivery.go b/services/sqs/sns_delivery.go index 85c6f24914..c92732f62d 100644 --- a/services/sqs/sns_delivery.go +++ b/services/sqs/sns_delivery.go @@ -2,7 +2,7 @@ package sqs import ( "context" - "encoding/json" + "encoding/json/v2" "strings" "time" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -145,7 +146,7 @@ func (b *InMemoryBackend) deliverToDLQ( DeadLetterTargetArn string `json:"deadLetterTargetArn"` } - if err := json.Unmarshal([]byte(redrivePolicy), &policy); err != nil { + if err := json.Unmarshal([]byte(redrivePolicy), &policy, jsonx.V1()); err != nil { return } @@ -262,7 +263,7 @@ func buildSNSEnvelope(ev *events.SNSPublishedEvent, sub events.SNSSubscriptionSn } } - b, err := json.Marshal(env) + b, err := json.Marshal(env, jsonx.V1()) if err != nil { return sub.Body(ev.Message) } diff --git a/services/sqs/sns_delivery_test.go b/services/sqs/sns_delivery_test.go index d1053453d2..793de684e0 100644 --- a/services/sqs/sns_delivery_test.go +++ b/services/sqs/sns_delivery_test.go @@ -1,13 +1,14 @@ package sqs_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/events" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" snsbackend "github.com/blackbirdworks/gopherstack/services/sns" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -147,7 +148,7 @@ func TestSNSToSQSDelivery(t *testing.T) { if tt.wantEnvType != "" { var env map[string]string - require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env)) + require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env, jsonx.V1())) assert.Equal(t, tt.wantEnvType, env["Type"]) assert.Equal(t, topic.TopicArn, env["TopicArn"]) assert.Equal(t, tt.wantEnvMessage, env["Message"]) @@ -224,7 +225,7 @@ func TestSNSToSQSRawMessageDelivery(t *testing.T) { // Ensure the body is NOT an SNS envelope (no "Type": "Notification" wrapper). var env map[string]any - if jsonErr := json.Unmarshal([]byte(out.Messages[0].Body), &env); jsonErr == nil { + if jsonErr := json.Unmarshal([]byte(out.Messages[0].Body), &env, jsonx.V1()); jsonErr == nil { assert.NotEqual(t, "Notification", env["Type"], "raw delivery body must not be SNS envelope") } @@ -313,7 +314,7 @@ func TestSNSToSQSDLQ(t *testing.T) { // DLQ receives the same body that was attempted to the failed queue. // Without RawMessageDelivery, that is the SNS envelope JSON. var env map[string]string - require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env)) + require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env, jsonx.V1())) assert.Equal(t, "Notification", env["Type"]) assert.Equal(t, tt.publishMessage, env["Message"]) } else { diff --git a/services/sqs/sns_envelope_test.go b/services/sqs/sns_envelope_test.go index 42792efe6f..9728465cc2 100644 --- a/services/sqs/sns_envelope_test.go +++ b/services/sqs/sns_envelope_test.go @@ -3,13 +3,14 @@ package sqs_test import ( "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/pem" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" snsbackend "github.com/blackbirdworks/gopherstack/services/sns" "github.com/blackbirdworks/gopherstack/services/sqs" ) @@ -46,7 +47,7 @@ func receiveOneEnvelope(t *testing.T, snsBk *snsbackend.InMemoryBackend, sqsBk * require.Len(t, out.Messages, 1) var env snsEnvelopeFields - require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env)) + require.NoError(t, json.Unmarshal([]byte(out.Messages[0].Body), &env, jsonx.V1())) return env } diff --git a/services/ssm/activations_test.go b/services/ssm/activations_test.go index 43f1f91132..d43e8d192e 100644 --- a/services/ssm/activations_test.go +++ b/services/ssm/activations_test.go @@ -2,7 +2,8 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -86,7 +88,7 @@ func TestResourceDataSync_CRUD(t *testing.T) { SyncType string `json:"SyncType"` } `json:"ResourceDataSyncItems"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&listResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &listResp, jsonx.V1())) require.Len(t, listResp.ResourceDataSyncItems, 1) item := listResp.ResourceDataSyncItems[0] assert.Equal(t, "SyncFromSource", item.SyncType) @@ -369,7 +371,7 @@ func TestStubOps_DeleteActivation(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"ActivationId": act.ActivationID}) + body, _ := json.Marshal(map[string]any{"ActivationId": act.ActivationID}, jsonx.V1()) rec := doRequest(t, h, "DeleteActivation", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -425,7 +427,7 @@ func TestCreateActivation_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateActivationOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.ActivationID) assert.NotEmpty(t, resp.ActivationCode) assert.True(t, strings.HasPrefix(resp.ActivationID, "act-")) @@ -545,18 +547,18 @@ func TestCreateActivationWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp ssm.CreateActivationOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.ActivationID) listBody, _ := json.Marshal(map[string]any{ "ResourceType": "Activation", "ResourceId": resp.ActivationID, - }) + }, jsonx.V1()) listRec := doRequest(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var tagResp ssm.ListTagsForResourceOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagResp, jsonx.V1())) assert.Len(t, tagResp.TagList, tt.tagCount) }) } @@ -839,7 +841,7 @@ func TestDeleteActivation_TableDriven(t *testing.T) { activationID = act.ActivationID } - body, _ := json.Marshal(map[string]any{"ActivationId": activationID}) + body, _ := json.Marshal(map[string]any{"ActivationId": activationID}, jsonx.V1()) rec := doRequest(t, h, "DeleteActivation", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) @@ -864,7 +866,7 @@ func TestDescribeInstanceProperties_DerivedFromActivations(t *testing.T) { var activation struct { ActivationID string `json:"ActivationId"` } - require.NoError(t, json.Unmarshal(actResp.Body.Bytes(), &activation)) + require.NoError(t, json.Unmarshal(actResp.Body.Bytes(), &activation, jsonx.V1())) require.NotEmpty(t, activation.ActivationID) propsResp := doRequest(t, h, "DescribeInstanceProperties", `{}`) diff --git a/services/ssm/agent_messages.go b/services/ssm/agent_messages.go index 21928cdf1e..bd7bb6e3cb 100644 --- a/services/ssm/agent_messages.go +++ b/services/ssm/agent_messages.go @@ -3,7 +3,7 @@ package ssm import ( "cmp" "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strconv" @@ -11,6 +11,8 @@ import ( "time" "gopkg.in/yaml.v3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // The ec2messages wire shapes below follow the open-source amazon-ssm-agent @@ -244,7 +246,10 @@ func (b *InMemoryBackend) queueAgentCancelLocked(region string, inv CommandInvoc return } - raw, _ := json.Marshal(map[string]string{"CancelMessageId": sendMessageID(inv.CommandID, inv.InstanceID)}) + raw, _ := json.Marshal( + map[string]string{"CancelMessageId": sendMessageID(inv.CommandID, inv.InstanceID)}, + jsonx.V1(), + ) q.push(&agentEnvelope{msg: AgentMessage{ CreatedDate: messageNow(), Destination: inv.InstanceID, @@ -278,7 +283,7 @@ func (b *InMemoryBackend) sendCommandPayload(region string, input *SendCommandIn payload["CloudWatchLogGroupName"] = cw.CloudWatchLogGroupName } - raw, _ := json.Marshal(payload) + raw, _ := json.Marshal(payload, jsonx.V1()) return string(raw) } @@ -290,7 +295,7 @@ func documentAsJSON(content, format string) any { if format == documentFormatYAML { err = yaml.Unmarshal([]byte(content), &doc) } else { - err = json.Unmarshal([]byte(content), &doc) + err = json.Unmarshal([]byte(content), &doc, jsonx.V1()) } if err != nil { @@ -496,7 +501,7 @@ func (b *InMemoryBackend) AgentSendReply(ctx context.Context, messageID, payload } var reply agentReply - if uerr := json.Unmarshal([]byte(payload), &reply); uerr != nil { + if uerr := json.Unmarshal([]byte(payload), &reply, jsonx.V1()); uerr != nil { return fmt.Errorf("%w: Payload is not a valid reply document", ErrValidationException) } diff --git a/services/ssm/agent_messages_test.go b/services/ssm/agent_messages_test.go index 909d276c2e..3f59f64f01 100644 --- a/services/ssm/agent_messages_test.go +++ b/services/ssm/agent_messages_test.go @@ -1,7 +1,7 @@ package ssm_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -39,7 +40,7 @@ type getMessagesResp struct { func agentCall(t *testing.T, h *ssm.Handler, op string, body any) *httptest.ResponseRecorder { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(raw))) @@ -61,7 +62,7 @@ func agentGetMessages(t *testing.T, h *ssm.Handler) getMessagesResp { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out getMessagesResp - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } @@ -84,7 +85,7 @@ func replyPayload(t *testing.T, docStatus string, plugin map[string]any) string "DocumentStatus": docStatus, "DocumentTraceOutput": "", "RuntimeStatus": map[string]any{"aws:runShellScript": plugin}, - }) + }, jsonx.V1()) require.NoError(t, err) return string(raw) @@ -161,7 +162,7 @@ func TestAgentPollingRunsCommandEndToEnd(t *testing.T) { } `json:"mainSteps"` } `json:"DocumentContent"` } - require.NoError(t, json.Unmarshal([]byte(msg.Payload), &payload)) + require.NoError(t, json.Unmarshal([]byte(msg.Payload), &payload, jsonx.V1())) assert.Equal(t, cmdID, payload.CommandID) assert.Equal(t, "AWS-RunShellScript", payload.DocumentName) assert.Equal(t, []string{"echo hello"}, payload.Parameters["commands"]) diff --git a/services/ssm/associations_test.go b/services/ssm/associations_test.go index ae1c265f63..6b4a5cdd16 100644 --- a/services/ssm/associations_test.go +++ b/services/ssm/associations_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -241,7 +242,7 @@ func TestStubOps_DeleteAssociation(t *testing.T) { require.NoError(t, err) body, _ := json.Marshal( - map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, + map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, jsonx.V1(), ) rec := doRequest(t, h, "DeleteAssociation", string(body)) assert.Equal(t, http.StatusOK, rec.Code) @@ -260,7 +261,7 @@ func TestStubOps_DescribeAssociation(t *testing.T) { require.NoError(t, err) body, _ := json.Marshal( - map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, + map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, jsonx.V1(), ) rec := doRequest(t, h, "DescribeAssociation", string(body)) assert.Equal(t, http.StatusOK, rec.Code) @@ -279,7 +280,7 @@ func TestStubOps_UpdateAssociation(t *testing.T) { require.NoError(t, err) body, _ := json.Marshal( - map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, + map[string]any{"AssociationId": assoc.AssociationDescription.AssociationID}, jsonx.V1(), ) rec := doRequest(t, h, "UpdateAssociation", string(body)) assert.Equal(t, http.StatusOK, rec.Code) @@ -356,7 +357,7 @@ func TestCreateAssociation_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateAssociationOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.AssociationDescription.AssociationID) assert.Equal(t, "MyDoc", resp.AssociationDescription.Name) assert.Equal(t, 1, backend.AssociationCount()) @@ -423,7 +424,7 @@ func TestCreateAssociationBatch(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateAssociationBatchOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.Successful, tt.wantSuccessful) assert.Len(t, resp.Failed, tt.wantFailed) assert.Equal(t, tt.wantSuccessful, backend.AssociationCount()) @@ -703,7 +704,7 @@ func TestDeleteAssociation_TableDriven(t *testing.T) { assocID = assoc.AssociationDescription.AssociationID } - body, _ := json.Marshal(map[string]any{"AssociationId": assocID}) + body, _ := json.Marshal(map[string]any{"AssociationId": assocID}, jsonx.V1()) rec := doRequest(t, h, "DeleteAssociation", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) diff --git a/services/ssm/automation_exec.go b/services/ssm/automation_exec.go index 5635f61fa9..b84ee1af0c 100644 --- a/services/ssm/automation_exec.go +++ b/services/ssm/automation_exec.go @@ -1,10 +1,12 @@ package ssm import ( - "encoding/json" + "encoding/json/v2" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // automationDoc is the minimal shape of an SSM automation (schemaVersion 0.3) @@ -117,7 +119,7 @@ func parseAutomationDocSteps(content string) []automationDocStep { } var doc automationDoc - if err := json.Unmarshal([]byte(content), &doc); err != nil { + if err := json.Unmarshal([]byte(content), &doc, jsonx.V1()); err != nil { return nil } diff --git a/services/ssm/automations_test.go b/services/ssm/automations_test.go index b382417165..c84e0d249b 100644 --- a/services/ssm/automations_test.go +++ b/services/ssm/automations_test.go @@ -2,7 +2,8 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -54,7 +56,7 @@ func TestChangeRequest(t *testing.T) { var startResp struct { AutomationExecutionID string `json:"AutomationExecutionId"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&startResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &startResp, jsonx.V1())) // Runbooks must round-trip on GetAutomationExecution. rec = doRequest(t, h, "GetAutomationExecution", @@ -69,7 +71,7 @@ func TestChangeRequest(t *testing.T) { } `json:"Runbooks"` } `json:"AutomationExecution"` } - require.NoError(t, json.NewDecoder(rec.Body).Decode(&getResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &getResp, jsonx.V1())) require.Len(t, getResp.AutomationExecution.Runbooks, 1) assert.Equal(t, "AWS-RunShellScript", getResp.AutomationExecution.Runbooks[0].DocumentName) assert.Equal(t, "1", getResp.AutomationExecution.Runbooks[0].MaxConcurrency) @@ -412,17 +414,17 @@ func TestAutomationExecution_ParametersRoundTrip(t *testing.T) { "DocumentName": "AWS-RunShellScript", "Parameters": tt.parameters, "Mode": tt.mode, - }) + }, jsonx.V1()) rec := doRequest(t, h, "StartAutomationExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execID := startResp["AutomationExecutionId"].(string) assert.NotEmpty(t, execID) // GetAutomationExecution should return parameters. - body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}) + body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}, jsonx.V1()) rec = doRequest(t, h, "GetAutomationExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -444,19 +446,19 @@ func TestAutomationApprovals_ApproveSignal(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execID := startResp["AutomationExecutionId"].(string) // Send Approve signal. body, _ := json.Marshal(map[string]any{ "AutomationExecutionId": execID, "SignalType": "Approve", - }) + }, jsonx.V1()) rec = doRequest(t, h, "SendAutomationSignal", string(body)) require.Equal(t, http.StatusOK, rec.Code) // GetAutomationExecution should show Approved status. - body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}) + body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}, jsonx.V1()) rec = doRequest(t, h, "GetAutomationExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "Approved") @@ -470,17 +472,17 @@ func TestAutomationApprovals_RejectSignal(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) execID := startResp["AutomationExecutionId"].(string) body, _ := json.Marshal(map[string]any{ "AutomationExecutionId": execID, "SignalType": "Reject", - }) + }, jsonx.V1()) rec = doRequest(t, h, "SendAutomationSignal", string(body)) require.Equal(t, http.StatusOK, rec.Code) - body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}) + body, _ = json.Marshal(map[string]any{"AutomationExecutionId": execID}, jsonx.V1()) rec = doRequest(t, h, "GetAutomationExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "Rejected") @@ -524,7 +526,7 @@ func TestAutomationExecution_WarningMessageAbsentFromWire(t *testing.T) { require.Equal(t, http.StatusOK, start.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(start.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(start.Body.Bytes(), &startResp, jsonx.V1())) execID, _ := startResp["AutomationExecutionId"].(string) require.NotEmpty(t, execID) @@ -542,7 +544,7 @@ func TestGetCalendarState_MissingDocumentReturnsError(t *testing.T) { body, _ := json.Marshal(map[string]any{ "CalendarNames": []string{"DoesNotExist"}, - }) + }, jsonx.V1()) rec := doRequest(t, h, "GetCalendarState", string(body)) assert.NotEqual(t, http.StatusOK, rec.Code, "missing calendar should return error") } diff --git a/services/ssm/client_token_bound_test.go b/services/ssm/client_token_bound_test.go index 92fcce6e3b..4e6e187e8b 100644 --- a/services/ssm/client_token_bound_test.go +++ b/services/ssm/client_token_bound_test.go @@ -1,13 +1,15 @@ package ssm_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -49,10 +51,10 @@ func TestClientTokenMemoIsBounded(t *testing.T) { } var snap struct { - Idempotency map[string]map[string]json.RawMessage `json:"idempotency"` + Idempotency map[string]map[string]jsontext.Value `json:"idempotency"` } - require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &snap)) + require.NoError(t, json.Unmarshal(b.Snapshot(t.Context()), &snap, jsonx.V1())) for _, recs := range snap.Idempotency { assert.LessOrEqual(t, len(recs), 1024) diff --git a/services/ssm/cloud_connector_test.go b/services/ssm/cloud_connector_test.go index 593ee62c24..22414efffd 100644 --- a/services/ssm/cloud_connector_test.go +++ b/services/ssm/cloud_connector_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -370,7 +371,7 @@ func Test_CloudConnector_HandlerDispatch(t *testing.T) { }, "DisplayName": "my-connector", "RoleArn": "arn:aws:iam::123456789012:role/r", - }) + }, jsonx.V1()) rec := doRequest(t, h, "CreateCloudConnector", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) @@ -378,15 +379,15 @@ func Test_CloudConnector_HandlerDispatch(t *testing.T) { var createResp struct { CloudConnectorID string `json:"CloudConnectorId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) require.NotEmpty(t, createResp.CloudConnectorID) - getBody, _ := json.Marshal(map[string]any{"CloudConnectorId": createResp.CloudConnectorID}) + getBody, _ := json.Marshal(map[string]any{"CloudConnectorId": createResp.CloudConnectorID}, jsonx.V1()) rec = doRequest(t, h, "GetCloudConnector", string(getBody)) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "my-connector", getResp["DisplayName"]) // CreatedAt/UpdatedAt must serialize as epoch-seconds numbers, not ISO8601 strings. _, isNumber := getResp["CreatedAt"].(float64) @@ -398,10 +399,10 @@ func Test_CloudConnector_HandlerDispatch(t *testing.T) { var errResp struct { Type string `json:"__type"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp.Type) - deleteBody, _ := json.Marshal(map[string]any{"CloudConnectorId": createResp.CloudConnectorID}) + deleteBody, _ := json.Marshal(map[string]any{"CloudConnectorId": createResp.CloudConnectorID}, jsonx.V1()) rec = doRequest(t, h, "DeleteCloudConnector", string(deleteBody)) require.Equal(t, http.StatusOK, rec.Code) } diff --git a/services/ssm/command_run_doc.go b/services/ssm/command_run_doc.go index 04d642f502..31dc383d91 100644 --- a/services/ssm/command_run_doc.go +++ b/services/ssm/command_run_doc.go @@ -2,7 +2,7 @@ package ssm import ( "cmp" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "regexp" @@ -10,6 +10,8 @@ import ( "strings" "gopkg.in/yaml.v3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -68,7 +70,7 @@ func parseScriptSteps(content, format string, params map[string][]string) ([]scr if format == documentFormatYAML { err = yaml.Unmarshal([]byte(content), &doc) } else { - err = json.Unmarshal([]byte(content), &doc) + err = json.Unmarshal([]byte(content), &doc, jsonx.V1()) } if err != nil { diff --git a/services/ssm/commands_test.go b/services/ssm/commands_test.go index d648c6b4ed..9ab8802523 100644 --- a/services/ssm/commands_test.go +++ b/services/ssm/commands_test.go @@ -2,7 +2,8 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -385,7 +387,7 @@ func TestCancelCommand_Success(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp, jsonx.V1())) cmd, ok := sendResp["Command"].(map[string]any) require.True(t, ok) @@ -454,13 +456,13 @@ func TestCancelCommand_CancelsInvocations(t *testing.T) { h, _ := newTestHandler(t) - instanceIDsJSON, _ := json.Marshal(tt.instanceIDs) + instanceIDsJSON, _ := json.Marshal(tt.instanceIDs, jsonx.V1()) sendBody := `{"DocumentName":"AWS-RunShellScript","InstanceIds":` + string(instanceIDsJSON) + `}` sendRec := doRequest(t, h, "SendCommand", sendBody) require.Equal(t, http.StatusOK, sendRec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp, jsonx.V1())) cmd := sendResp["Command"].(map[string]any) cmdID := cmd["CommandId"].(string) @@ -473,7 +475,7 @@ func TestCancelCommand_CancelsInvocations(t *testing.T) { require.Equal(t, http.StatusOK, invRec.Code) var invResp map[string]any - require.NoError(t, json.Unmarshal(invRec.Body.Bytes(), &invResp)) + require.NoError(t, json.Unmarshal(invRec.Body.Bytes(), &invResp, jsonx.V1())) assert.Equal(t, tt.wantInvocStatus, invResp["Status"]) assert.Equal(t, tt.wantInvocStatus, invResp["StatusDetails"]) } @@ -498,7 +500,7 @@ func TestCancelCommand_ScopedToInstanceIDs(t *testing.T) { require.Equal(t, http.StatusOK, sendRec.Code) var sendResp map[string]any - require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp)) + require.NoError(t, json.Unmarshal(sendRec.Body.Bytes(), &sendResp, jsonx.V1())) cmdID := sendResp["Command"].(map[string]any)["CommandId"].(string) cancelRec := doRequest(t, h, "CancelCommand", `{"CommandId":"`+cmdID+`","InstanceIds":["i-001"]}`) @@ -508,14 +510,14 @@ func TestCancelCommand_ScopedToInstanceIDs(t *testing.T) { require.Equal(t, http.StatusOK, invRec.Code) var cancelledInv map[string]any - require.NoError(t, json.Unmarshal(invRec.Body.Bytes(), &cancelledInv)) + require.NoError(t, json.Unmarshal(invRec.Body.Bytes(), &cancelledInv, jsonx.V1())) assert.Equal(t, "Cancelled", cancelledInv["Status"]) otherRec := doRequest(t, h, "GetCommandInvocation", `{"CommandId":"`+cmdID+`","InstanceId":"i-002"}`) require.Equal(t, http.StatusOK, otherRec.Code) var otherInv map[string]any - require.NoError(t, json.Unmarshal(otherRec.Body.Bytes(), &otherInv)) + require.NoError(t, json.Unmarshal(otherRec.Body.Bytes(), &otherInv, jsonx.V1())) assert.NotEqual(t, "Cancelled", otherInv["Status"], "un-named instance's invocation must not be cancelled") } @@ -887,7 +889,7 @@ func TestHandler_SendCommand(t *testing.T) { if tt.wantStatus == http.StatusOK { var out ssm.SendCommandOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.NotEmpty(t, out.Command.CommandID) assert.Equal(t, "AWS-RunShellScript", out.Command.DocumentName) } @@ -936,7 +938,7 @@ func TestHandler_ListCommands(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out ssm.ListCommandsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.Commands, tt.wantCount) }) } @@ -957,7 +959,7 @@ func TestHandler_GetCommandInvocation(t *testing.T) { t.Helper() rec := doRequest(t, h, "SendCommand", `{"DocumentName":"AWS-RunShellScript","InstanceIDs":["i-abc"]}`) var out ssm.SendCommandOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) return out.Command.CommandID }, @@ -973,7 +975,7 @@ func TestHandler_GetCommandInvocation(t *testing.T) { t.Helper() rec := doRequest(t, h, "SendCommand", `{"DocumentName":"AWS-RunShellScript","InstanceIDs":["i-abc"]}`) var out ssm.SendCommandOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) return out.Command.CommandID }, @@ -1007,7 +1009,7 @@ func TestHandler_GetCommandInvocation(t *testing.T) { if tt.wantCommandStatus != "" { var out ssm.GetCommandInvocationOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantCommandStatus, out.Status) assert.Equal(t, tt.wantCommandStatus, out.StatusDetails) } @@ -1055,7 +1057,7 @@ func TestHandler_ListCommandInvocations(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out ssm.ListCommandInvocationsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.CommandInvocations, tt.wantCount) }) } diff --git a/services/ssm/document_metadata_test.go b/services/ssm/document_metadata_test.go index e25b922b7d..7476a7b700 100644 --- a/services/ssm/document_metadata_test.go +++ b/services/ssm/document_metadata_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -143,12 +144,12 @@ func Test_DescribeDocument_OmitsContentAndHonorsVersionSelector(t *testing.T) { // "Content" field at all — assert this at the JSON level since a Go // zero-value string would round-trip identically to "field absent" in a // struct-based comparison. - createJSON, marshalErr := json.Marshal(createOut.DocumentDescription) + createJSON, marshalErr := json.Marshal(createOut.DocumentDescription, jsonx.V1()) require.NoError(t, marshalErr) assert.NotContains(t, string(createJSON), "Content", "CreateDocumentOutput.DocumentDescription must not serialize a Content field") - updateJSON, marshalErr := json.Marshal(updateOut.DocumentDescription) + updateJSON, marshalErr := json.Marshal(updateOut.DocumentDescription, jsonx.V1()) require.NoError(t, marshalErr) assert.NotContains(t, string(updateJSON), "Content", "UpdateDocumentOutput.DocumentDescription must not serialize a Content field") @@ -172,7 +173,7 @@ func Test_DescribeDocument_OmitsContentAndHonorsVersionSelector(t *testing.T) { require.NoError(t, describeErr) assert.Equal(t, tc.wantVersion, describeOut.Document.DocumentVersion) - describeJSON, jsonErr := json.Marshal(describeOut.Document) + describeJSON, jsonErr := json.Marshal(describeOut.Document, jsonx.V1()) require.NoError(t, jsonErr) assert.NotContains(t, string(describeJSON), "Content", "DescribeDocumentOutput.Document must not serialize a Content field") @@ -639,7 +640,7 @@ func TestDocumentVersions_IsDefaultVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["DocumentVersions"].([]any) require.True(t, ok, "DocumentVersions must be an array") @@ -649,7 +650,7 @@ func TestDocumentVersions_IsDefaultVersion(t *testing.T) { body, _ := json.Marshal(map[string]any{ "Name": "MyDoc", "DocumentVersion": "2", - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateDocumentDefaultVersion", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -657,7 +658,7 @@ func TestDocumentVersions_IsDefaultVersion(t *testing.T) { rec = doRequest(t, h, "ListDocumentVersions", `{"Name":"MyDoc"}`) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions = resp["DocumentVersions"].([]any) var defaultFound bool @@ -723,7 +724,7 @@ func TestDocumentVersions_TableDriven(t *testing.T) { body, _ := json.Marshal(map[string]any{ "Name": "td-doc-" + tt.name, "DocumentVersion": tt.setDefault, - }) + }, jsonx.V1()) rec := doRequest(t, h, "UpdateDocumentDefaultVersion", string(body)) require.Equal(t, http.StatusOK, rec.Code) } @@ -733,7 +734,7 @@ func TestDocumentVersions_TableDriven(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions := resp["DocumentVersions"].([]any) assert.GreaterOrEqual(t, len(versions), tt.wantVersions) diff --git a/services/ssm/document_parameters.go b/services/ssm/document_parameters.go index c033542299..79054369b0 100644 --- a/services/ssm/document_parameters.go +++ b/services/ssm/document_parameters.go @@ -1,11 +1,13 @@ package ssm import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "gopkg.in/yaml.v3" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // DocumentParameter is one declared document parameter (types.DocumentParameter). @@ -37,7 +39,7 @@ func parseDocumentParameters(content, format string) []DocumentParameter { if format == documentFormatYAML { err = yaml.Unmarshal([]byte(content), &doc) } else { - err = json.Unmarshal([]byte(content), &doc) + err = json.Unmarshal([]byte(content), &doc, jsonx.V1()) } if err != nil || len(doc.Parameters) == 0 { @@ -69,7 +71,7 @@ func documentDefaultString(v any) string { case string: return val default: - if b, err := json.Marshal(val); err == nil { + if b, err := json.Marshal(val, jsonx.V1()); err == nil { return string(b) } diff --git a/services/ssm/document_permissions_test.go b/services/ssm/document_permissions_test.go index d5dab4a8cf..c40b9bed1c 100644 --- a/services/ssm/document_permissions_test.go +++ b/services/ssm/document_permissions_test.go @@ -2,13 +2,15 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -165,7 +167,7 @@ func TestDistributorPackage_TableDriven(t *testing.T) { "Filters": []map[string]any{ {"Key": "DocumentType", "Values": []string{tt.filterType}}, }, - }) + }, jsonx.V1()) rec := doRequest(t, h, "ListDocuments", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -213,7 +215,7 @@ func TestHandler_CreateDocument(t *testing.T) { if tt.wantName != "" { var out ssm.CreateDocumentOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantName, out.DocumentDescription.Name) assert.Equal(t, "1", out.DocumentDescription.DocumentVersion) } @@ -319,7 +321,7 @@ func TestHandler_UpdateDocument(t *testing.T) { if tt.wantVer != "" { var out ssm.UpdateDocumentOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantVer, out.DocumentDescription.DocumentVersion) } }) @@ -367,7 +369,7 @@ func TestHandler_DescribeDocumentPermission(t *testing.T) { if tt.wantStatus == http.StatusOK { var out ssm.DescribeDocumentPermissionOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.AccountIDs, tt.wantLen) } }) @@ -467,7 +469,7 @@ func TestHandler_ListDocumentVersions(t *testing.T) { if tt.wantCount > 0 { var out ssm.ListDocumentVersionsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Len(t, out.DocumentVersions, tt.wantCount) } }) diff --git a/services/ssm/document_test.go b/services/ssm/document_test.go index 927f94b09c..a57c97e5f1 100644 --- a/services/ssm/document_test.go +++ b/services/ssm/document_test.go @@ -2,7 +2,8 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -458,7 +460,7 @@ func TestGetCalendarState_WithCalendarDocument(t *testing.T) { // GetCalendarState with the calendar name should succeed. body, _ := json.Marshal(map[string]any{ "CalendarNames": []string{"MyCalendar"}, - }) + }, jsonx.V1()) rec := doRequest(t, h, "GetCalendarState", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "OPEN") @@ -478,7 +480,7 @@ func TestGetCalendarState_NonCalendarDocumentReturnsError(t *testing.T) { body, _ := json.Marshal(map[string]any{ "CalendarNames": []string{"NotACalendar"}, - }) + }, jsonx.V1()) rec := doRequest(t, h, "GetCalendarState", string(body)) assert.NotEqual(t, http.StatusOK, rec.Code, "non-ChangeCalendar doc should return error") } @@ -495,7 +497,7 @@ func TestHandler_CreateDocument_Duplicate(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var errResp map[string]string - require.NoError(t, json.NewDecoder(rec2.Body).Decode(&errResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec2.Body), &errResp, jsonx.V1())) assert.Contains(t, errResp["__type"], "DocumentAlreadyExists") } func TestHandler_GetDocument(t *testing.T) { @@ -549,7 +551,7 @@ func TestHandler_GetDocument(t *testing.T) { if tt.wantDoc != "" { var out ssm.GetDocumentOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantDoc, out.Name) } }) @@ -596,7 +598,7 @@ func TestHandler_DescribeDocument(t *testing.T) { if tt.wantDoc != "" { var out ssm.DescribeDocumentOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.Equal(t, tt.wantDoc, out.Document.Name) } }) @@ -643,7 +645,7 @@ func TestHandler_ListDocuments(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out ssm.ListDocumentsOutput - require.NoError(t, json.NewDecoder(rec.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &out, jsonx.V1())) assert.GreaterOrEqual(t, len(out.DocumentIdentifiers), tt.wantMin) }) } diff --git a/services/ssm/documents.go b/services/ssm/documents.go index df1ac7fb23..3f3e8d56c4 100644 --- a/services/ssm/documents.go +++ b/services/ssm/documents.go @@ -2,7 +2,7 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -12,6 +12,7 @@ import ( "gopkg.in/yaml.v3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -1139,7 +1140,7 @@ func validateDocumentContent(docType, format, content string) error { if format == documentFormatYAML { err = yaml.Unmarshal([]byte(content), &doc) } else { - err = json.Unmarshal([]byte(content), &doc) + err = json.Unmarshal([]byte(content), &doc, jsonx.V1()) } if err != nil || doc == nil { diff --git a/services/ssm/epoch_seconds_wire_shape_test.go b/services/ssm/epoch_seconds_wire_shape_test.go index 05c94246b2..6c75f41da2 100644 --- a/services/ssm/epoch_seconds_wire_shape_test.go +++ b/services/ssm/epoch_seconds_wire_shape_test.go @@ -26,13 +26,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "regexp" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -54,7 +55,7 @@ func TestEpochSecondsWireShape_AssociationExecution(t *testing.T) { body, err := json.Marshal(ssm.AssociationExecution{ AssociationID: "assoc-1", ExecutionID: "exec-1", Status: "Success", ExecutionDate: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "ExecutionDate") } @@ -65,7 +66,7 @@ func TestEpochSecondsWireShape_MaintenanceWindowExecution(t *testing.T) { body, err := json.Marshal(ssm.MaintenanceWindowExecution{ WindowID: "mw-1", WindowExecutionID: "mwexec-1", Status: "SUCCESS", StartTime: 1_700_000_000, EndTime: 1_700_003_600, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "StartTime") numericJSONField(t, body, "EndTime") @@ -76,7 +77,7 @@ func TestEpochSecondsWireShape_InstanceInformation(t *testing.T) { body, err := json.Marshal(ssm.InstanceInformation{ InstanceID: "i-1", PingStatus: "Online", RegistrationDate: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "RegistrationDate") } @@ -86,7 +87,7 @@ func TestEpochSecondsWireShape_InstanceAssociationStatusInfo(t *testing.T) { body, err := json.Marshal(ssm.InstanceAssociationStatusInfo{ AssociationID: "assoc-1", Name: "MyDoc", Status: "Success", ExecutionDate: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "ExecutionDate") } @@ -96,7 +97,7 @@ func TestEpochSecondsWireShape_InstancePatchState(t *testing.T) { body, err := json.Marshal(ssm.InstancePatchState{ InstanceID: "i-1", PatchGroup: "grp1", Operation: "Scan", OperationStartTime: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "OperationStartTime") } @@ -106,7 +107,7 @@ func TestEpochSecondsWireShape_PatchComplianceData(t *testing.T) { body, err := json.Marshal(ssm.PatchComplianceData{ Title: "KB123", State: "INSTALLED", InstalledTime: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "InstalledTime") } @@ -117,7 +118,7 @@ func TestEpochSecondsWireShape_ResourceDataSync(t *testing.T) { body, err := json.Marshal(ssm.ResourceDataSync{ SyncName: "sync-1", SyncType: "SyncToDestination", LastStatus: "InProgress", SyncCreatedTime: 1_700_000_000, LastSyncTime: 1_700_000_100, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "SyncCreatedTime") numericJSONField(t, body, "LastSyncTime") @@ -129,7 +130,7 @@ func TestEpochSecondsWireShape_InventoryDeletion(t *testing.T) { body, err := json.Marshal(ssm.InventoryDeletion{ DeletionID: "deletion-1", TypeName: "AWS:Application", LastStatus: "Complete", DeletionStartTime: 1_700_000_000, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "DeletionStartTime") } @@ -140,7 +141,7 @@ func TestEpochSecondsWireShape_Node(t *testing.T) { body, err := json.Marshal(ssm.Node{ ID: "i-1", CaptureTime: 1_700_000_000, NodeType: &ssm.NodeType{Instance: &ssm.NodeInstanceInfo{PlatformType: "Linux"}}, - }) + }, jsonx.V1()) require.NoError(t, err) numericJSONField(t, body, "CaptureTime") } diff --git a/services/ssm/handler.go b/services/ssm/handler.go index 95dff1eac0..e7a2dea719 100644 --- a/services/ssm/handler.go +++ b/services/ssm/handler.go @@ -2,7 +2,7 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -132,7 +133,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -185,7 +186,7 @@ type ssmActionFn func(context.Context, []byte) (any, error) func jsonOp[I, O any](fn func(context.Context, *I) (O, error), checks ...func(*I) error) ssmActionFn { return func(ctx context.Context, b []byte) (any, error) { var input I - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -239,7 +240,7 @@ func (h *Handler) ssmTagOps() map[string]ssmActionFn { return map[string]ssmActionFn{ "AddTagsToResource": func(ctx context.Context, b []byte) (any, error) { var input AddTagsToResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -247,7 +248,7 @@ func (h *Handler) ssmTagOps() map[string]ssmActionFn { }, "RemoveTagsFromResource": func(ctx context.Context, b []byte) (any, error) { var input RemoveTagsFromResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -316,7 +317,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // classifySSMError maps a backend error to an HTTP status code and error type string. @@ -562,7 +563,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin Message: reqErr.Error(), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } diff --git a/services/ssm/handler_agent.go b/services/ssm/handler_agent.go index 75f095eb6e..737b6b037d 100644 --- a/services/ssm/handler_agent.go +++ b/services/ssm/handler_agent.go @@ -2,13 +2,14 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" "slices" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -42,7 +43,7 @@ func (h *Handler) agentOps() map[string]ssmActionFn { return map[string]ssmActionFn{ "GetEndpoint": func(ctx context.Context, body []byte) (any, error) { var in agentGetEndpointInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } @@ -56,7 +57,7 @@ func (h *Handler) agentOps() map[string]ssmActionFn { }, "GetMessages": func(ctx context.Context, body []byte) (any, error) { var in AgentGetMessagesInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } @@ -77,7 +78,7 @@ func (h *Handler) agentOps() map[string]ssmActionFn { }), "SendReply": func(ctx context.Context, body []byte) (any, error) { var in agentSendReplyInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } @@ -89,7 +90,7 @@ func (h *Handler) agentOps() map[string]ssmActionFn { func agentMessageOp(fn func(context.Context, *agentMessageIDInput) error) ssmActionFn { return func(ctx context.Context, body []byte) (any, error) { var in agentMessageIDInput - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } @@ -117,7 +118,7 @@ func (h *Handler) handleAgent(ctx context.Context, c *echo.Context) error { return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) }, h.handleError, ) diff --git a/services/ssm/handler_parameters_test.go b/services/ssm/handler_parameters_test.go index cf757e93b8..c9839cdb64 100644 --- a/services/ssm/handler_parameters_test.go +++ b/services/ssm/handler_parameters_test.go @@ -2,7 +2,8 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -620,9 +622,9 @@ func TestHandlerParameterListingOperations(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var out struct { - Parameters []json.RawMessage `json:"Parameters"` + Parameters []jsontext.Value `json:"Parameters"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Parameters, tt.wantCount) }) } @@ -659,7 +661,7 @@ func TestTagOperations(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var listOut ssm.ListTagsForResourceOutput - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.TagList, 2) assert.Equal(t, "env", listOut.TagList[0].Key) assert.Equal(t, "prod", listOut.TagList[0].Value) diff --git a/services/ssm/handler_test.go b/services/ssm/handler_test.go index 95b2483da7..c9a84f6e31 100644 --- a/services/ssm/handler_test.go +++ b/services/ssm/handler_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -255,7 +256,7 @@ func TestHandler_ErrorCases(t *testing.T) { if tt.wantErrTyp != "" { var errResp service.JSONErrorResponse - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantErrTyp, errResp.Type) } }) @@ -362,7 +363,7 @@ func TestHandler_GetParametersByPathViaHTTP(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out ssm.GetParametersByPathOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Parameters, 2) } @@ -381,7 +382,7 @@ func TestHandler_DescribeParametersViaHTTP(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var out ssm.DescribeParametersOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Parameters, 2) } diff --git a/services/ssm/idempotency.go b/services/ssm/idempotency.go index 11750c0697..e33fed7f7a 100644 --- a/services/ssm/idempotency.go +++ b/services/ssm/idempotency.go @@ -3,9 +3,11 @@ package ssm import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxIdempotencyRecords caps remembered tokens per region; the oldest are evicted first. @@ -20,19 +22,19 @@ type idempotencyRecord struct { } func idempotencyFingerprint(req any) string { - raw, err := json.Marshal(req) + raw, err := json.Marshal(req, jsonx.V1()) if err != nil { return "" } var m map[string]any - if json.Unmarshal(raw, &m) != nil { + if json.Unmarshal(raw, &m, jsonx.V1()) != nil { return "" } delete(m, "ClientToken") - canonical, err := json.Marshal(m) + canonical, err := json.Marshal(m, jsonx.V1()) if err != nil { return "" } diff --git a/services/ssm/inventory_test.go b/services/ssm/inventory_test.go index 3cd6ea8176..6b1b32966e 100644 --- a/services/ssm/inventory_test.go +++ b/services/ssm/inventory_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -1050,7 +1051,7 @@ func TestComplianceSummaries_AggregateByCType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ComplianceSummaryItems"].([]any) assert.NotEmpty(t, items, "should have compliance summary items") @@ -1087,7 +1088,7 @@ func TestResourceComplianceSummaries_PerResource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items := resp["ResourceComplianceSummaryItems"].([]any) assert.NotEmpty(t, items) @@ -1125,7 +1126,7 @@ func TestResourceComplianceSummaries_NonCompliantStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) for _, item := range resp["ResourceComplianceSummaryItems"].([]any) { m := item.(map[string]any) @@ -1143,7 +1144,7 @@ func TestGetInventorySchema_ReturnsBuiltInTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) schemas := resp["Schemas"].([]any) assert.NotEmpty(t, schemas, "GetInventorySchema should return built-in schema types") @@ -1187,7 +1188,7 @@ func TestGetInventorySchema_FilterByTypeName(t *testing.T) { h, _ := newTestHandler(t) - body, _ := json.Marshal(map[string]any{"TypeName": tt.typeName}) + body, _ := json.Marshal(map[string]any{"TypeName": tt.typeName}, jsonx.V1()) rec := doRequest(t, h, "GetInventorySchema", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), tt.wantContains) @@ -1219,7 +1220,7 @@ func TestInventory_TypeMergeAndLookup(t *testing.T) { body, _ := json.Marshal(map[string]any{ "InstanceId": "i-inv001", "TypeName": "AWS:Application", - }) + }, jsonx.V1()) rec := doRequest(t, h, "ListInventoryEntries", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "aws-cli") @@ -1257,7 +1258,7 @@ func TestInventory_TypeMergeAndLookup(t *testing.T) { body, _ = json.Marshal(map[string]any{ "InstanceId": "i-inv001", "TypeName": "AWS:Application", - }) + }, jsonx.V1()) rec = doRequest(t, h, "ListInventoryEntries", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "2.1") diff --git a/services/ssm/janitor.go b/services/ssm/janitor.go index 2b50f2c0c8..0843e4bdf0 100644 --- a/services/ssm/janitor.go +++ b/services/ssm/janitor.go @@ -2,10 +2,11 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "time" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/telemetry" "github.com/blackbirdworks/gopherstack/pkgs/worker" @@ -303,7 +304,7 @@ func parameterExpiresAt(policiesJSON string) (time.Time, bool) { } var policies []parameterExpirationPolicy - if err := json.Unmarshal([]byte(policiesJSON), &policies); err != nil { + if err := json.Unmarshal([]byte(policiesJSON), &policies, jsonx.V1()); err != nil { return time.Time{}, false } diff --git a/services/ssm/maintenance_window_execution_test.go b/services/ssm/maintenance_window_execution_test.go index 8f211e14e2..9b195b790f 100644 --- a/services/ssm/maintenance_window_execution_test.go +++ b/services/ssm/maintenance_window_execution_test.go @@ -2,13 +2,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -195,7 +196,7 @@ func TestCancelMaintenanceWindowExecution(t *testing.T) { body := tt.makeBody(t, b) var reqBody map[string]string - require.NoError(t, json.Unmarshal([]byte(body), &reqBody)) + require.NoError(t, json.Unmarshal([]byte(body), &reqBody, jsonx.V1())) wantExecID := reqBody["WindowExecutionId"] rec := doRequest(t, h, "CancelMaintenanceWindowExecution", body) @@ -207,7 +208,7 @@ func TestCancelMaintenanceWindowExecution(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, wantExecID, resp["WindowExecutionId"]) }) } diff --git a/services/ssm/maintenance_window_lifecycle_test.go b/services/ssm/maintenance_window_lifecycle_test.go index c6bb6d3753..953fd272c4 100644 --- a/services/ssm/maintenance_window_lifecycle_test.go +++ b/services/ssm/maintenance_window_lifecycle_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -189,7 +190,7 @@ func TestStubOps_DeleteMaintenanceWindow(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID}) + body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID}, jsonx.V1()) rec := doRequest(t, h, "DeleteMaintenanceWindow", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -208,7 +209,7 @@ func TestStubOps_GetMaintenanceWindow(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID}) + body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID}, jsonx.V1()) rec := doRequest(t, h, "GetMaintenanceWindow", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -227,7 +228,7 @@ func TestStubOps_UpdateMaintenanceWindow(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID, "Name": "updated-window"}) + body, _ := json.Marshal(map[string]any{"WindowId": mw.WindowID, "Name": "updated-window"}, jsonx.V1()) rec := doRequest(t, h, "UpdateMaintenanceWindow", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -263,7 +264,7 @@ func TestCreateMaintenanceWindow_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateMaintenanceWindowOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.WindowID) assert.True(t, strings.HasPrefix(resp.WindowID, "mw-")) assert.Equal(t, 1, backend.MaintenanceWindowCount()) @@ -296,7 +297,7 @@ func TestMaintenanceWindow_ScheduleFieldsRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var created ssm.CreateMaintenanceWindowOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) out, err := b.GetMaintenanceWindow(context.Background(), &ssm.GetMaintenanceWindowInput{WindowID: created.WindowID}) require.NoError(t, err) @@ -750,7 +751,7 @@ func TestMaintenanceWindowsForTarget_FindsByTarget(t *testing.T) { "Targets": []map[string]any{ {"Key": "InstanceIds", "Values": []string{"i-aabbcc112233"}}, }, - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterTargetWithMaintenanceWindow", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -760,7 +761,7 @@ func TestMaintenanceWindowsForTarget_FindsByTarget(t *testing.T) { "Targets": []map[string]any{ {"Key": "InstanceIds", "Values": []string{"i-aabbcc112233"}}, }, - }) + }, jsonx.V1()) rec = doRequest(t, h, "DescribeMaintenanceWindowsForTarget", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), mw.WindowID) diff --git a/services/ssm/maintenance_window_targets_test.go b/services/ssm/maintenance_window_targets_test.go index 585da73657..257aa6aa1a 100644 --- a/services/ssm/maintenance_window_targets_test.go +++ b/services/ssm/maintenance_window_targets_test.go @@ -2,13 +2,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -32,7 +33,7 @@ func TestStubOps_RegisterTargetWithMaintenanceWindow(t *testing.T) { "Targets": []map[string]any{ {"Key": "InstanceIds", "Values": []string{"i-1234567890abcdef0"}}, }, - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterTargetWithMaintenanceWindow", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -55,7 +56,7 @@ func TestStubOps_RegisterTaskWithMaintenanceWindow(t *testing.T) { "WindowId": mw.WindowID, "TaskType": "RUN_COMMAND", "TaskArn": "AWS-RunShellScript", - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterTaskWithMaintenanceWindow", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -104,19 +105,19 @@ func TestMaintenanceWindowTask_ServiceRoleArn(t *testing.T) { "ServiceRoleArn": tt.serviceRoleArn, "MaxConcurrency": tt.maxConcurrency, "MaxErrors": tt.maxErrors, - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterTaskWithMaintenanceWindow", string(body)) require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) taskID := regResp["WindowTaskId"].(string) // GetMaintenanceWindowTask should return ServiceRoleArn. body, _ = json.Marshal(map[string]any{ "WindowId": mw.WindowID, "WindowTaskId": taskID, - }) + }, jsonx.V1()) rec = doRequest(t, h, "GetMaintenanceWindowTask", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -147,12 +148,12 @@ func TestMaintenanceWindowTask_UpdateServiceRoleArn(t *testing.T) { "WindowId": mw.WindowID, "TaskType": "RUN_COMMAND", "TaskArn": "AWS-RunShellScript", - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterTaskWithMaintenanceWindow", string(body)) require.Equal(t, http.StatusOK, rec.Code) var regResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), ®Resp, jsonx.V1())) taskID := regResp["WindowTaskId"].(string) // Update with ServiceRoleArn. @@ -160,7 +161,7 @@ func TestMaintenanceWindowTask_UpdateServiceRoleArn(t *testing.T) { "WindowId": mw.WindowID, "WindowTaskId": taskID, "ServiceRoleArn": "arn:aws:iam::123456789012:role/UpdatedRole", - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateMaintenanceWindowTask", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "UpdatedRole") @@ -230,13 +231,13 @@ func TestDeregisterTargetFromMaintenanceWindow_TableDriven(t *testing.T) { body, _ := json.Marshal(map[string]any{ "WindowId": mw.WindowID, "WindowTargetId": windowTargetID, - }) + }, jsonx.V1()) rec := doRequest(t, h, "DeregisterTargetFromMaintenanceWindow", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantWindowID { assert.Equal(t, mw.WindowID, resp["WindowId"]) } @@ -310,13 +311,13 @@ func TestDeregisterTaskFromMaintenanceWindow_TableDriven(t *testing.T) { body, _ := json.Marshal(map[string]any{ "WindowId": mw.WindowID, "WindowTaskId": windowTaskID, - }) + }, jsonx.V1()) rec := doRequest(t, h, "DeregisterTaskFromMaintenanceWindow", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantWindowID { assert.Equal(t, mw.WindowID, resp["WindowId"]) } diff --git a/services/ssm/maintenance_window_test.go b/services/ssm/maintenance_window_test.go index f371bf910f..fd53c7eea8 100644 --- a/services/ssm/maintenance_window_test.go +++ b/services/ssm/maintenance_window_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -165,7 +166,7 @@ func TestPatchBaseline_DefaultOS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp ssm.CreatePatchBaselineOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.NotEmpty(t, resp.BaselineID) bl := backend.GetPatchBaselineInternal(resp.BaselineID) @@ -734,12 +735,12 @@ func TestMaintenanceWindowsForTarget_NoMatchReturnsEmpty(t *testing.T) { "Targets": []map[string]any{ {"Key": "InstanceIds", "Values": []string{"i-notregistered"}}, }, - }) + }, jsonx.V1()) rec := doRequest(t, h, "DescribeMaintenanceWindowsForTarget", string(body)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) identities := resp["WindowIdentities"].([]any) assert.Empty(t, identities) diff --git a/services/ssm/ops_items_test.go b/services/ssm/ops_items_test.go index c886985060..3dbad0e73f 100644 --- a/services/ssm/ops_items_test.go +++ b/services/ssm/ops_items_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -30,7 +31,7 @@ func TestStubOps_DeleteOpsItem(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "DeleteOpsItem", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -59,7 +60,7 @@ func TestStubOps_GetOpsItem(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "GetOpsItem", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -79,7 +80,7 @@ func TestStubOps_UpdateOpsItem(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID, "Title": "updated-item"}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID, "Title": "updated-item"}, jsonx.V1()) rec := doRequest(t, h, "UpdateOpsItem", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -114,7 +115,7 @@ func TestCreateOpsItem_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateOpsItemOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.OpsItemID) assert.NotEmpty(t, resp.OpsItemArn) assert.True(t, strings.HasPrefix(resp.OpsItemID, "oi-")) @@ -201,7 +202,7 @@ func TestAssociateOpsItemRelatedItem(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp ssm.CreateOpsItemOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) body = `{"OpsItemId":"` + createResp.OpsItemID + `","AssociationType":"RelatesTo","ResourceType":"AWS::EC2::Instance",` + @@ -215,7 +216,7 @@ func TestAssociateOpsItemRelatedItem(t *testing.T) { assert.Contains(t, rec.Body.String(), tt.wantErr) } else { var resp ssm.AssociateOpsItemRelatedItemOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.AssociationID) } }) @@ -901,7 +902,7 @@ func TestOpsItem_OperationalData_CreateAndUpdate(t *testing.T) { require.NoError(t, err) // GetOpsItem should have initial OperationalData. - body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "GetOpsItem", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "/aws/resources") @@ -915,12 +916,12 @@ func TestOpsItem_OperationalData_CreateAndUpdate(t *testing.T) { "Value": `[{"automationId":"auto-123"}]`, }, }, - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateOpsItem", string(body)) require.Equal(t, http.StatusOK, rec.Code) // GetOpsItem should have both keys. - body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec = doRequest(t, h, "GetOpsItem", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "/aws/resources") @@ -974,11 +975,11 @@ func TestOpsItem_OperationalData_TableDriven(t *testing.T) { body, _ := json.Marshal(map[string]any{ "OpsItemId": item.OpsItemID, "OperationalData": tt.updateData, - }) + }, jsonx.V1()) rec := doRequest(t, h, "UpdateOpsItem", string(body)) require.Equal(t, http.StatusOK, rec.Code) - body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec = doRequest(t, h, "GetOpsItem", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -1001,12 +1002,12 @@ func TestOpsItemEvents_TrackCreates(t *testing.T) { require.NoError(t, err) // ListOpsItemEvents for this item should return at least one event. - body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "ListOpsItemEvents", string(body)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["Summaries"].([]any) assert.NotEmpty(t, summaries, "should have at least one event after create") @@ -1027,16 +1028,16 @@ func TestOpsItemEvents_TrackUpdates(t *testing.T) { body, _ := json.Marshal(map[string]any{ "OpsItemId": item.OpsItemID, "Description": "Updated description", - }) + }, jsonx.V1()) doRequest(t, h, "UpdateOpsItem", string(body)) // ListOpsItemEvents should have multiple events now. - body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}) + body, _ = json.Marshal(map[string]any{"OpsItemId": item.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "ListOpsItemEvents", string(body)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries := resp["Summaries"].([]any) assert.GreaterOrEqual(t, len(summaries), 2, "create + update should each produce an event") @@ -1054,7 +1055,7 @@ func TestOpsItemEvents_FilterByOpsItemID(t *testing.T) { require.NoError(t, err) // Filter by item1 — should only get item1 events. - body, _ := json.Marshal(map[string]any{"OpsItemId": item1.OpsItemID}) + body, _ := json.Marshal(map[string]any{"OpsItemId": item1.OpsItemID}, jsonx.V1()) rec := doRequest(t, h, "ListOpsItemEvents", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), item1.OpsItemID) @@ -1109,7 +1110,7 @@ func TestUpdateOpsItem_TableDriven(t *testing.T) { payload := map[string]any{"OpsItemId": opsItemID} maps.Copy(payload, tt.update) - body, _ := json.Marshal(payload) + body, _ := json.Marshal(payload, jsonx.V1()) rec := doRequest(t, h, "UpdateOpsItem", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) diff --git a/services/ssm/ops_metadata_test.go b/services/ssm/ops_metadata_test.go index 8f1e2a8abf..a97328e026 100644 --- a/services/ssm/ops_metadata_test.go +++ b/services/ssm/ops_metadata_test.go @@ -2,13 +2,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -45,7 +46,7 @@ func TestStubOps_DeleteOpsMetadata(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec := doRequest(t, h, "DeleteOpsMetadata", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -61,7 +62,7 @@ func TestStubOps_GetOpsMetadata(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec := doRequest(t, h, "GetOpsMetadata", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -77,7 +78,7 @@ func TestStubOps_UpdateOpsMetadata(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec := doRequest(t, h, "UpdateOpsMetadata", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -111,7 +112,7 @@ func TestCreateOpsMetadata_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreateOpsMetadataOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.OpsMetadataArn) assert.Contains(t, resp.OpsMetadataArn, "arn:aws:ssm:") assert.Equal(t, 1, backend.OpsMetadataCount()) @@ -566,7 +567,7 @@ func TestClassifySSMErrorExtended(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantErrType, resp["__type"]) }) } @@ -592,7 +593,7 @@ func TestOpsMetadata_FullCRUD(t *testing.T) { assert.Contains(t, rec.Body.String(), "OpsMetadataList") // Get. - body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ := json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec = doRequest(t, h, "GetOpsMetadata", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "production") @@ -604,19 +605,19 @@ func TestOpsMetadata_FullCRUD(t *testing.T) { "MetadataToUpdate": map[string]any{ "version": map[string]any{"Value": "2"}, }, - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateOpsMetadata", string(body)) require.Equal(t, http.StatusOK, rec.Code) // Get updated — both keys should be present. - body, _ = json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ = json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec = doRequest(t, h, "GetOpsMetadata", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "production") assert.Contains(t, rec.Body.String(), "version") // Delete. - body, _ = json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}) + body, _ = json.Marshal(map[string]any{"OpsMetadataArn": meta.OpsMetadataArn}, jsonx.V1()) rec = doRequest(t, h, "DeleteOpsMetadata", string(body)) require.Equal(t, http.StatusOK, rec.Code) } diff --git a/services/ssm/parameter_encryption_test.go b/services/ssm/parameter_encryption_test.go index b1672cd327..589d1b4dde 100644 --- a/services/ssm/parameter_encryption_test.go +++ b/services/ssm/parameter_encryption_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -493,7 +494,7 @@ func TestSSMHandler_GetParameters(t *testing.T) { t.Helper() var out ssm.GetParametersOutput - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.Len(t, out.Parameters, 2) assert.Empty(t, out.InvalidParameters) }, @@ -512,7 +513,7 @@ func TestSSMHandler_GetParameters(t *testing.T) { t.Helper() var out ssm.GetParametersOutput - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.Len(t, out.Parameters, 1) assert.Len(t, out.InvalidParameters, 1) assert.Equal(t, "/absent", out.InvalidParameters[0]) @@ -533,7 +534,7 @@ func TestSSMHandler_GetParameters(t *testing.T) { t.Helper() var out ssm.GetParametersOutput - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) assert.Len(t, out.Parameters, 1) assert.Equal(t, "topsecret", out.Parameters[0].Value) }, @@ -708,7 +709,7 @@ func TestSecureStringHistory_WithDecryption(t *testing.T) { body, _ := json.Marshal(map[string]any{ "Name": "/secure/pwd", "WithDecryption": tt.withDecryption, - }) + }, jsonx.V1()) rec := doRequest(t, h, "GetParameterHistory", string(body)) require.Equal(t, http.StatusOK, rec.Code) diff --git a/services/ssm/parameter_labels_test.go b/services/ssm/parameter_labels_test.go index 1d8838c8fb..9a2cad438c 100644 --- a/services/ssm/parameter_labels_test.go +++ b/services/ssm/parameter_labels_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -393,7 +394,7 @@ func TestParameterLabels_VersionSpecific(t *testing.T) { "Name": "/app/key", "Labels": []string{"stable"}, "ParameterVersion": 1, - }) + }, jsonx.V1()) rec := doRequest(t, h, "LabelParameterVersion", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "ParameterVersion") @@ -403,7 +404,7 @@ func TestParameterLabels_VersionSpecific(t *testing.T) { "Name": "/app/key", "Labels": []string{"latest"}, "ParameterVersion": 2, - }) + }, jsonx.V1()) rec = doRequest(t, h, "LabelParameterVersion", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -464,7 +465,7 @@ func TestParameterLabels_UnlabelSpecificVersion(t *testing.T) { "Name": "/app/ver", "Labels": []string{"prod", "stable"}, "ParameterVersion": 1, - }) + }, jsonx.V1()) doRequest(t, h, "LabelParameterVersion", string(body)) // Remove one label. @@ -472,7 +473,7 @@ func TestParameterLabels_UnlabelSpecificVersion(t *testing.T) { "Name": "/app/ver", "Labels": []string{"prod"}, "ParameterVersion": 1, - }) + }, jsonx.V1()) rec := doRequest(t, h, "UnlabelParameterVersion", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "RemovedLabels") diff --git a/services/ssm/parameter_policy_notifications.go b/services/ssm/parameter_policy_notifications.go index 6f94899c82..1fac2e9867 100644 --- a/services/ssm/parameter_policy_notifications.go +++ b/services/ssm/parameter_policy_notifications.go @@ -2,11 +2,13 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "sort" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ParameterPolicyNotifier receives Parameter Store policy-action @@ -67,7 +69,7 @@ func parseParameterPolicies(policiesJSON string) []parameterStorePolicy { } var policies []parameterStorePolicy - if err := json.Unmarshal([]byte(policiesJSON), &policies); err != nil { + if err := json.Unmarshal([]byte(policiesJSON), &policies, jsonx.V1()); err != nil { return nil } @@ -93,7 +95,7 @@ func parameterPoliciesToWire(policiesJSON string, lastModified float64, now time wire := make([]ParameterInlinePolicy, 0, len(parsed)) for _, p := range parsed { - text, err := json.Marshal(p) + text, err := json.Marshal(p, jsonx.V1()) if err != nil { continue } diff --git a/services/ssm/parameters_handler_test.go b/services/ssm/parameters_handler_test.go index a6e5b26a4b..928b0cb2b0 100644 --- a/services/ssm/parameters_handler_test.go +++ b/services/ssm/parameters_handler_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -14,6 +14,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -77,7 +78,7 @@ func TestSSMHandler_UnknownOperation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["__type"], "UnknownOperationException") } func TestSSMHandler_InternalError(t *testing.T) { @@ -198,7 +199,7 @@ func TestSSMHandler_ValidationError(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ParameterPatternMismatchException", resp["__type"]) } @@ -216,7 +217,7 @@ func TestSSMHandler_ErrInvalidKeyID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["__type"], "UnknownOperationException") } @@ -328,14 +329,14 @@ func TestDeepCopy_Association(t *testing.T) { doRequest(t, h, "CreateDocument", `{"Name":"`+tt.docName+`","Content":"{\"schemaVersion\":\"2.2\"}"}`) - paramsJSON, _ := json.Marshal(tt.params) + paramsJSON, _ := json.Marshal(tt.params, jsonx.V1()) createBody := `{"Name":"` + tt.docName + `","Parameters":` + string(paramsJSON) + `}` rec := doRequest(t, h, "CreateAssociation", createBody) require.Equal(t, http.StatusOK, rec.Code) var createResp ssm.CreateAssociationOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) originalCmds := createResp.AssociationDescription.Parameters[tt.mutateKey] // Verify original value was stored correctly @@ -600,7 +601,7 @@ func TestAdvancedTier_AcceptsLargeValue(t *testing.T) { "Value": string(largeVal), "Type": "String", "Tier": "Advanced", - }) + }, jsonx.V1()) rec := doRequest(t, h, "PutParameter", string(body)) assert.Equal(t, http.StatusOK, rec.Code, "Advanced tier should accept 5KiB value") } @@ -620,7 +621,7 @@ func TestStandardTier_RejectsLargeValue(t *testing.T) { "Value": string(largeVal), "Type": "String", "Tier": "Standard", - }) + }, jsonx.V1()) rec := doRequest(t, h, "PutParameter", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code, "Standard tier should reject 5KiB value") } diff --git a/services/ssm/parameters_test.go b/services/ssm/parameters_test.go index f92ca2dcaf..10e5f7d32f 100644 --- a/services/ssm/parameters_test.go +++ b/services/ssm/parameters_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/kms" "github.com/blackbirdworks/gopherstack/services/ssm" @@ -557,13 +558,13 @@ func TestDeleteParameter_RegionCleanup(t *testing.T) { func postJSON(t *testing.T, h *ssm.Handler, op string, body any) (int, map[string]any) { t.Helper() - payload, err := json.Marshal(body) + payload, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, op, string(payload)) var out map[string]any - _ = json.Unmarshal(rec.Body.Bytes(), &out) + _ = json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1()) return rec.Code, out } diff --git a/services/ssm/patch_baseline_approval_rules_test.go b/services/ssm/patch_baseline_approval_rules_test.go index f5d328cad0..b9b1dcead2 100644 --- a/services/ssm/patch_baseline_approval_rules_test.go +++ b/services/ssm/patch_baseline_approval_rules_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -400,7 +401,7 @@ func TestSendCommand_RunPatchBaseline_ApprovalRules_Compliance(t *testing.T) { var created struct { BaselineID string `json:"BaselineId"` } - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) regResp := doRequest(t, h, "RegisterPatchBaselineForPatchGroup", `{ "BaselineId":"`+created.BaselineID+`","PatchGroup":"rule-group" @@ -423,7 +424,7 @@ func TestSendCommand_RunPatchBaseline_ApprovalRules_Compliance(t *testing.T) { State string `json:"State"` } `json:"Patches"` } - require.NoError(t, json.Unmarshal(patchesResp.Body.Bytes(), &patches)) + require.NoError(t, json.Unmarshal(patchesResp.Body.Bytes(), &patches, jsonx.V1())) states := map[string]string{} for _, p := range patches.Patches { diff --git a/services/ssm/patch_baselines_lifecycle_test.go b/services/ssm/patch_baselines_lifecycle_test.go index dab2db2cee..652d6edd63 100644 --- a/services/ssm/patch_baselines_lifecycle_test.go +++ b/services/ssm/patch_baselines_lifecycle_test.go @@ -2,13 +2,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -241,7 +242,7 @@ func TestPatchBaseline_OSFilter(t *testing.T) { "Filters": []map[string]any{ {"Key": "OPERATING_SYSTEM", "Values": []string{"AMAZON_LINUX_2"}}, }, - }) + }, jsonx.V1()) rec := doRequest(t, h, "DescribePatchBaselines", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "linux-baseline") @@ -252,7 +253,7 @@ func TestPatchBaseline_OSFilter(t *testing.T) { "Filters": []map[string]any{ {"Key": "OPERATING_SYSTEM", "Values": []string{"WINDOWS"}}, }, - }) + }, jsonx.V1()) rec = doRequest(t, h, "DescribePatchBaselines", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.NotContains(t, rec.Body.String(), "linux-baseline") @@ -286,7 +287,7 @@ func TestPatchBaseline_ComplianceLevelRoundTrip(t *testing.T) { require.NoError(t, err) // GetPatchBaseline should return the compliance level. - body, _ := json.Marshal(map[string]any{"BaselineId": bl.BaselineID}) + body, _ := json.Marshal(map[string]any{"BaselineId": bl.BaselineID}, jsonx.V1()) rec := doRequest(t, h, "GetPatchBaseline", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), tt.complianceLevel) @@ -295,7 +296,7 @@ func TestPatchBaseline_ComplianceLevelRoundTrip(t *testing.T) { body, _ = json.Marshal(map[string]any{ "BaselineId": bl.BaselineID, "ApprovedPatchesComplianceLevel": "LOW", - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdatePatchBaseline", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "LOW") @@ -318,7 +319,7 @@ func TestPatchGroups_RegisterAndLookup(t *testing.T) { body, _ := json.Marshal(map[string]any{ "BaselineId": bl.BaselineID, "PatchGroup": "ubuntu-servers", - }) + }, jsonx.V1()) rec := doRequest(t, h, "RegisterPatchBaselineForPatchGroup", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -328,7 +329,7 @@ func TestPatchGroups_RegisterAndLookup(t *testing.T) { assert.Contains(t, rec.Body.String(), "ubuntu-servers") // GetPatchBaselineForPatchGroup should return the baseline. - body, _ = json.Marshal(map[string]any{"PatchGroup": "ubuntu-servers"}) + body, _ = json.Marshal(map[string]any{"PatchGroup": "ubuntu-servers"}, jsonx.V1()) rec = doRequest(t, h, "GetPatchBaselineForPatchGroup", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), bl.BaselineID) @@ -337,7 +338,7 @@ func TestPatchGroups_RegisterAndLookup(t *testing.T) { body, _ = json.Marshal(map[string]any{ "BaselineId": bl.BaselineID, "PatchGroup": "ubuntu-servers", - }) + }, jsonx.V1()) rec = doRequest(t, h, "DeregisterPatchBaselineForPatchGroup", string(body)) require.Equal(t, http.StatusOK, rec.Code) } @@ -380,14 +381,14 @@ func TestDeregisterPatchBaselineForPatchGroup_TableDriven(t *testing.T) { body, _ := json.Marshal(map[string]any{ "BaselineId": tt.baselineID, "PatchGroup": tt.patchGroup, - }) + }, jsonx.V1()) rec := doRequest(t, h, "DeregisterPatchBaselineForPatchGroup", string(body)) require.Equal(t, tt.wantStatus, rec.Code) if tt.wantStatus == http.StatusOK && tt.wantBaselineID != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantBaselineID, resp["BaselineId"]) assert.Equal(t, tt.wantPatchGroup, resp["PatchGroup"]) } @@ -408,7 +409,7 @@ func TestDescribeAvailablePatches_SeededCatalog(t *testing.T) { Name string `json:"Name"` } `json:"Patches"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out.Patches, "the catalog must be seeded with real built-in patches") } @@ -432,7 +433,7 @@ func TestSendCommand_RunPatchBaseline_PopulatesInstanceState(t *testing.T) { var created struct { BaselineID string `json:"BaselineId"` } - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &created, jsonx.V1())) require.NotEmpty(t, created.BaselineID) regResp := doRequest(t, h, "RegisterPatchBaselineForPatchGroup", `{ @@ -457,7 +458,7 @@ func TestSendCommand_RunPatchBaseline_PopulatesInstanceState(t *testing.T) { PatchGroup string `json:"PatchGroup"` } `json:"InstancePatchStates"` } - require.NoError(t, json.Unmarshal(stateResp.Body.Bytes(), &states)) + require.NoError(t, json.Unmarshal(stateResp.Body.Bytes(), &states, jsonx.V1())) require.Len(t, states.InstancePatchStates, 1) assert.Equal(t, "i-patchtest", states.InstancePatchStates[0].InstanceID) assert.Equal(t, created.BaselineID, states.InstancePatchStates[0].BaselineID) @@ -472,7 +473,7 @@ func TestSendCommand_RunPatchBaseline_PopulatesInstanceState(t *testing.T) { State string `json:"State"` } `json:"Patches"` } - require.NoError(t, json.Unmarshal(patchesResp.Body.Bytes(), &patches)) + require.NoError(t, json.Unmarshal(patchesResp.Body.Bytes(), &patches, jsonx.V1())) require.NotEmpty(t, patches.Patches) var sawInstalled bool diff --git a/services/ssm/patch_baselines_test.go b/services/ssm/patch_baselines_test.go index 48a9b10245..c0875b469f 100644 --- a/services/ssm/patch_baselines_test.go +++ b/services/ssm/patch_baselines_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -295,7 +296,7 @@ func TestStubOps_DeletePatchBaseline(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID}) + body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID}, jsonx.V1()) rec := doRequest(t, h, "DeletePatchBaseline", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -344,7 +345,7 @@ func TestStubOps_GetPatchBaseline(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID}) + body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID}, jsonx.V1()) rec := doRequest(t, h, "GetPatchBaseline", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -361,7 +362,7 @@ func TestStubOps_UpdatePatchBaseline(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID, "Name": "updated-baseline"}) + body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID, "Name": "updated-baseline"}, jsonx.V1()) rec := doRequest(t, h, "UpdatePatchBaseline", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -378,7 +379,7 @@ func TestStubOps_RegisterPatchBaselineForPatchGroup(t *testing.T) { }) require.NoError(t, err) - body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID, "PatchGroup": "test-group"}) + body, _ := json.Marshal(map[string]any{"BaselineId": pb.BaselineID, "PatchGroup": "test-group"}, jsonx.V1()) rec := doRequest(t, h, "RegisterPatchBaselineForPatchGroup", string(body)) assert.Equal(t, http.StatusOK, rec.Code) } @@ -498,7 +499,7 @@ func TestCreatePatchBaseline_Success(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp ssm.CreatePatchBaselineOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp.BaselineID) assert.True(t, strings.HasPrefix(resp.BaselineID, "pb-")) assert.Equal(t, 1, backend.PatchBaselineCount()) @@ -540,7 +541,7 @@ func TestPatchBaseline_ApprovalRulesGlobalFiltersSourcesRoundTrip(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var created ssm.CreatePatchBaselineOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) out, err := b.GetPatchBaseline(context.Background(), &ssm.GetPatchBaselineInput{BaselineID: created.BaselineID}) require.NoError(t, err) @@ -577,7 +578,7 @@ func TestCreatePatchBaseline_DefaultsGlobalFiltersAndApprovalRulesNonNil(t *test require.Equal(t, http.StatusOK, rec.Code) var created ssm.CreatePatchBaselineOutput - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) out, err := b.GetPatchBaseline(context.Background(), &ssm.GetPatchBaselineInput{BaselineID: created.BaselineID}) require.NoError(t, err) @@ -591,7 +592,7 @@ func TestCreatePatchBaseline_DefaultsGlobalFiltersAndApprovalRulesNonNil(t *test require.Equal(t, http.StatusOK, rawRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rawRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rawRec.Body.Bytes(), &raw, jsonx.V1())) assert.Contains(t, raw, "GlobalFilters", "GlobalFilters key must be present, not omitted") assert.Contains(t, raw, "ApprovalRules", "ApprovalRules key must be present, not omitted") } diff --git a/services/ssm/persistence.go b/services/ssm/persistence.go index 9ddfc360a8..401de17991 100644 --- a/services/ssm/persistence.go +++ b/services/ssm/persistence.go @@ -2,10 +2,12 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/tags" @@ -37,7 +39,7 @@ const ssmSnapshotVersion = 1 // store_setup.go's package doc for why each one doesn't fit Table's // func(*V) string keying requirement. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` History map[string]map[string][]ParameterHistory `json:"history"` Tags map[string]map[string]*tags.Tags `json:"tags"` DocumentVersions map[string]map[string][]DocumentVersion `json:"document_versions"` @@ -221,7 +223,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NotifiedParameterPolicies: b.notifiedParameterPolicies, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ssm: failed to marshal snapshot", "error", err) @@ -240,7 +242,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { // silently dropped instead of restored. Each table name has the shape // "/" (see store_setup.go's getOrCreateTable); regions // never contain "/", so splitting on the first one recovers both parts. -func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]json.RawMessage) { +func (b *InMemoryBackend) preRegisterSnapshotTables(tables map[string]jsontext.Value) { for key := range tables { name, region, found := strings.Cut(key, "/") if !found { diff --git a/services/ssm/public_parameters.go b/services/ssm/public_parameters.go index c839819e23..b847b4ef92 100644 --- a/services/ssm/public_parameters.go +++ b/services/ssm/public_parameters.go @@ -2,7 +2,7 @@ package ssm import ( _ "embed" // public_parameters.json - "encoding/json" + "encoding/json/v2" "slices" "sort" "strconv" @@ -10,6 +10,7 @@ import ( "sync" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) //go:embed public_parameters.json @@ -45,7 +46,7 @@ type publicCatalog struct { //nolint:gochecknoglobals // read-only catalog built once from embedded data var loadPublicCatalog = sync.OnceValue(func() *publicCatalog { var f publicParametersFile - if err := json.Unmarshal(publicParametersJSON, &f); err != nil { + if err := json.Unmarshal(publicParametersJSON, &f, jsonx.V1()); err != nil { panic("ssm: corrupt embedded public_parameters.json: " + err.Error()) } diff --git a/services/ssm/public_parameters_sdk_test.go b/services/ssm/public_parameters_sdk_test.go index 2068b233b8..bb3f045e88 100644 --- a/services/ssm/public_parameters_sdk_test.go +++ b/services/ssm/public_parameters_sdk_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "strings" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -60,7 +61,7 @@ func TestGetParameter_PublicCatalog_SDK(t *testing.T) { t.Helper() var doc map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(p.Value)), &doc)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(p.Value)), &doc, jsonx.V1())) assert.Contains(t, doc, "image_id") assert.Contains(t, doc, "ecs_agent_version") }}, @@ -474,7 +475,7 @@ func TestSecretsManagerReference_SDK(t *testing.T) { assert.Contains(t, aws.ToString(p.ARN), ":parameter/aws/reference/secretsmanager/") var src map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(p.SourceResult)), &src)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(p.SourceResult)), &src, jsonx.V1())) assert.Equal(t, secretARN, src["ARN"]) assert.Equal(t, "db", src["Name"]) assert.Equal(t, tc.wantValue, src["SecretString"]) diff --git a/services/ssm/resource_policies_test.go b/services/ssm/resource_policies_test.go index d646e65ae4..ba020167d1 100644 --- a/services/ssm/resource_policies_test.go +++ b/services/ssm/resource_policies_test.go @@ -1,7 +1,7 @@ package ssm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -69,19 +70,19 @@ func TestResourcePolicies_FullCRUD(t *testing.T) { body, _ := json.Marshal(map[string]any{ "ResourceArn": tt.resourceArn, "Policy": tt.policy, - }) + }, jsonx.V1()) rec := doRequest(t, h, "PutResourcePolicy", string(body)) require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) policyID := putResp["PolicyId"].(string) policyHash := putResp["PolicyHash"].(string) assert.NotEmpty(t, policyID) assert.NotEmpty(t, policyHash) // Get policies. - body, _ = json.Marshal(map[string]any{"ResourceArn": tt.resourceArn}) + body, _ = json.Marshal(map[string]any{"ResourceArn": tt.resourceArn}, jsonx.V1()) rec = doRequest(t, h, "GetResourcePolicies", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), policyID) @@ -91,12 +92,12 @@ func TestResourcePolicies_FullCRUD(t *testing.T) { "ResourceArn": tt.resourceArn, "PolicyId": policyID, "PolicyHash": policyHash, - }) + }, jsonx.V1()) rec = doRequest(t, h, "DeleteResourcePolicy", string(body)) require.Equal(t, http.StatusOK, rec.Code) // Get policies — should be empty. - body, _ = json.Marshal(map[string]any{"ResourceArn": tt.resourceArn}) + body, _ = json.Marshal(map[string]any{"ResourceArn": tt.resourceArn}, jsonx.V1()) rec = doRequest(t, h, "GetResourcePolicies", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), `"Policies":[]`) diff --git a/services/ssm/secret_references.go b/services/ssm/secret_references.go index 50993458ff..8a8636678e 100644 --- a/services/ssm/secret_references.go +++ b/services/ssm/secret_references.go @@ -2,7 +2,7 @@ package ssm import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "regexp" @@ -10,6 +10,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -146,7 +147,7 @@ func (b *InMemoryBackend) getSecretReference( value = string(secret.SecretBinary) } - source, err := json.Marshal(secretSourceResult(*secret)) + source, err := json.Marshal(secretSourceResult(*secret), jsonx.V1()) if err != nil { return ParameterOutput{}, fmt.Errorf("marshal secret source result: %w", err) } diff --git a/services/ssm/service_settings_test.go b/services/ssm/service_settings_test.go index be11b23c97..7f25ac3ee1 100644 --- a/services/ssm/service_settings_test.go +++ b/services/ssm/service_settings_test.go @@ -1,7 +1,7 @@ package ssm_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -101,7 +102,7 @@ func TestServiceSettings_LifecycleRoundTrip(t *testing.T) { h, _ := newTestHandler(t) // Default state. - body, _ := json.Marshal(map[string]any{"SettingId": tt.settingID}) + body, _ := json.Marshal(map[string]any{"SettingId": tt.settingID}, jsonx.V1()) rec := doRequest(t, h, "GetServiceSetting", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "Default") @@ -110,24 +111,24 @@ func TestServiceSettings_LifecycleRoundTrip(t *testing.T) { body, _ = json.Marshal(map[string]any{ "SettingId": tt.settingID, "SettingValue": tt.setValue, - }) + }, jsonx.V1()) rec = doRequest(t, h, "UpdateServiceSetting", string(body)) require.Equal(t, http.StatusOK, rec.Code) // Get updated. - body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}) + body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}, jsonx.V1()) rec = doRequest(t, h, "GetServiceSetting", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), tt.setValue) assert.Contains(t, rec.Body.String(), "Customized") // Reset. - body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}) + body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}, jsonx.V1()) rec = doRequest(t, h, "ResetServiceSetting", string(body)) require.Equal(t, http.StatusOK, rec.Code) // Default again. - body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}) + body, _ = json.Marshal(map[string]any{"SettingId": tt.settingID}, jsonx.V1()) rec = doRequest(t, h, "GetServiceSetting", string(body)) require.Equal(t, http.StatusOK, rec.Code) assert.Contains(t, rec.Body.String(), "Default") diff --git a/services/ssm/sessions_test.go b/services/ssm/sessions_test.go index 23dcd2f217..c9be4a9702 100644 --- a/services/ssm/sessions_test.go +++ b/services/ssm/sessions_test.go @@ -2,7 +2,7 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -108,7 +109,7 @@ func TestStartSession_DefaultsToStandardAccessType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) sessions := out["Sessions"].([]any) require.Len(t, sessions, 1) assert.Equal(t, "Standard", sessions[0].(map[string]any)["AccessType"]) @@ -208,12 +209,12 @@ func TestSession_Parameters_RoundTrip(t *testing.T) { body, _ := json.Marshal(map[string]any{ "Target": "i-1234567890abcdef0", "Parameters": tt.parameters, - }) + }, jsonx.V1()) rec := doRequest(t, h, "StartSession", string(body)) require.Equal(t, http.StatusOK, rec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) assert.NotEmpty(t, startResp["SessionId"]) // DescribeSessions should show the session, but never a @@ -250,7 +251,7 @@ func TestSession_StateFilter(t *testing.T) { assert.NotContains(t, rec.Body.String(), sess.SessionID) // Terminate session. - body, _ := json.Marshal(map[string]any{"SessionId": sess.SessionID}) + body, _ := json.Marshal(map[string]any{"SessionId": sess.SessionID}, jsonx.V1()) doRequest(t, h, "TerminateSession", string(body)) // Filter by Active — should NOT find the terminated session. diff --git a/services/ssm/ssmmessages_port_test.go b/services/ssm/ssmmessages_port_test.go index a0d658b3c1..22ee923f9f 100644 --- a/services/ssm/ssmmessages_port_test.go +++ b/services/ssm/ssmmessages_port_test.go @@ -3,7 +3,7 @@ package ssm_test import ( "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "io" "net" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -79,7 +80,7 @@ func portHandshake(t *testing.T, c *dcClient, acked map[int64]bool, wantProps ma require.Equal(t, ssm.PayloadHandshakeRequest, req.PayloadType) var hr ssm.HandshakeRequestPayload - require.NoError(t, json.Unmarshal(req.Payload, &hr)) + require.NoError(t, json.Unmarshal(req.Payload, &hr, jsonx.V1())) require.Len(t, hr.RequestedClientActions, 1) assert.Equal(t, "2.3.0.0", hr.AgentVersion) assert.Equal(t, "Port", hr.RequestedClientActions[0].ActionParameters["SessionType"]) @@ -88,7 +89,7 @@ func portHandshake(t *testing.T, c *dcClient, acked map[int64]bool, wantProps ma resp, _ := json.Marshal(ssm.HandshakeResponsePayload{ ClientVersion: "1.2.0.0", ProcessedClientActions: []ssm.ProcessedClientAction{{ActionType: "SessionType", ActionStatus: 1}}, - }) + }, jsonx.V1()) c.input(ssm.PayloadHandshakeResponse, resp) done := c.nextNonAck(acked) @@ -291,7 +292,7 @@ func TestSessionPortForwardingErrors(t *testing.T) { resp, _ := json.Marshal(ssm.HandshakeResponsePayload{ ProcessedClientActions: []ssm.ProcessedClientAction{{ActionType: "SessionType", ActionStatus: 1}}, - }) + }, jsonx.V1()) c.input(ssm.PayloadHandshakeResponse, resp) done := c.nextNonAck(map[int64]bool{}) diff --git a/services/ssm/ssmmessages_server.go b/services/ssm/ssmmessages_server.go index 2a376d9b47..72fb314e54 100644 --- a/services/ssm/ssmmessages_server.go +++ b/services/ssm/ssmmessages_server.go @@ -3,7 +3,7 @@ package ssm import ( "context" "encoding/binary" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net" @@ -16,6 +16,7 @@ import ( "github.com/gorilla/websocket" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -107,7 +108,7 @@ func (d *dataChannel) serve(parent context.Context) { _ = d.ws.SetReadDeadline(time.Time{}) var open OpenDataChannelInput - if jerr := json.Unmarshal(raw, &open); jerr != nil { + if jerr := json.Unmarshal(raw, &open, jsonx.V1()); jerr != nil { d.reject("malformed OpenDataChannel request") return @@ -228,7 +229,7 @@ func (d *dataChannel) process(ctx context.Context, m *StreamMessage) bool { return d.completeHandshake(ctx, m.Payload) case PayloadSize: var sz SizePayload - if json.Unmarshal(m.Payload, &sz) == nil && sz.Cols > 0 && sz.Rows > 0 { + if json.Unmarshal(m.Payload, &sz, jsonx.V1()) == nil && sz.Cols > 0 && sz.Rows > 0 { d.cols, d.rows = sz.Cols, sz.Rows if d.shell != nil { _ = d.shell.Resize(ctx, sz.Cols, sz.Rows) @@ -270,14 +271,14 @@ func (d *dataChannel) sendHandshakeRequest() error { "Properties": props, }, }}, - }) + }, jsonx.V1()) return d.sendOutput(PayloadHandshakeRequest, body) } func (d *dataChannel) completeHandshake(ctx context.Context, payload []byte) bool { var resp HandshakeResponsePayload - if err := json.Unmarshal(payload, &resp); err != nil { + if err := json.Unmarshal(payload, &resp, jsonx.V1()); err != nil { d.endSession("Malformed handshake response.") return true @@ -291,7 +292,7 @@ func (d *dataChannel) completeHandshake(ctx context.Context, payload []byte) boo } } - done, _ := json.Marshal(HandshakeCompletePayload{HandshakeTimeToComplete: int64(time.Since(d.started))}) + done, _ := json.Marshal(HandshakeCompletePayload{HandshakeTimeToComplete: int64(time.Since(d.started))}, jsonx.V1()) if d.sendOutput(PayloadHandshakeComplete, done) != nil { return true } @@ -392,7 +393,7 @@ func (d *dataChannel) finish(reason string) { SessionID: d.sessionID, SchemaVersion: msgSchemaVersion, Output: reason, - }) + }, jsonx.V1()) _ = d.send(NewStreamMessage(MsgChannelClosed, 0, 0, body)) d.closeNormal() @@ -410,7 +411,7 @@ func (d *dataChannel) sendAck(m *StreamMessage) error { body, _ := json.Marshal(AckPayload{ MessageType: m.MessageType, MessageID: m.MessageID.String(), SequenceNumber: m.SequenceNumber, IsSequentialMessage: true, - }) + }, jsonx.V1()) ack := NewStreamMessage(MsgAcknowledge, 0, 0, body) ack.Flags = ackFlags diff --git a/services/ssm/ssmmessages_test.go b/services/ssm/ssmmessages_test.go index 7cb7bec9d3..99ebd3fc1e 100644 --- a/services/ssm/ssmmessages_test.go +++ b/services/ssm/ssmmessages_test.go @@ -4,7 +4,8 @@ import ( "context" "crypto/sha256" "encoding/binary" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -188,7 +190,7 @@ func newServer(t *testing.T, withShell bool) *httptest.Server { func ssmCall(t *testing.T, srv *httptest.Server, op string, in any) map[string]any { t.Helper() - body, err := json.Marshal(in) + body, err := json.Marshal(in, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, srv.URL, strings.NewReader(string(body))) @@ -202,7 +204,7 @@ func ssmCall(t *testing.T, srv *httptest.Server, op string, in any) map[string]a defer resp.Body.Close() var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) return out } @@ -232,7 +234,7 @@ func (c *dcClient) open(token string) { b, _ := json.Marshal(ssm.OpenDataChannelInput{ MessageSchemaVersion: "1.0", RequestID: uuid.NewString(), TokenValue: token, ClientID: uuid.NewString(), ClientVersion: "1.2.0.0", - }) + }, jsonx.V1()) require.NoError(c.t, c.ws.WriteMessage(websocket.TextMessage, b)) } @@ -280,7 +282,7 @@ func (c *dcClient) nextNonAck(acked map[int64]bool) *ssm.StreamMessage { } var a ssm.AckPayload - require.NoError(c.t, json.Unmarshal(m.Payload, &a)) + require.NoError(c.t, json.Unmarshal(m.Payload, &a, jsonx.V1())) acked[a.SequenceNumber] = true } } @@ -296,7 +298,7 @@ func (c *dcClient) handshake(acked map[int64]bool) { resp, _ := json.Marshal(ssm.HandshakeResponsePayload{ ClientVersion: "1.2.0.0", ProcessedClientActions: []ssm.ProcessedClientAction{{ActionType: "SessionType", ActionStatus: 1}}, - }) + }, jsonx.V1()) c.input(ssm.PayloadHandshakeResponse, resp) done := c.nextNonAck(acked) diff --git a/services/ssm/tags_test.go b/services/ssm/tags_test.go index 046a820d67..89475cb661 100644 --- a/services/ssm/tags_test.go +++ b/services/ssm/tags_test.go @@ -2,13 +2,14 @@ package ssm_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/ssm" ) @@ -49,7 +50,7 @@ func TestTagsForNonParameterResources(t *testing.T) { "ResourceType": tt.resourceType, "ResourceId": tt.resourceID, "Tags": tt.tags, - }) + }, jsonx.V1()) addRec := doRequest(t, h, "AddTagsToResource", string(addBody)) require.Equal(t, http.StatusOK, addRec.Code) @@ -57,13 +58,13 @@ func TestTagsForNonParameterResources(t *testing.T) { listBody, _ := json.Marshal(map[string]any{ "ResourceType": tt.resourceType, "ResourceId": tt.resourceID, - }) + }, jsonx.V1()) listRec := doRequest(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var listResp ssm.ListTagsForResourceOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp.TagList, tt.wantTagCount) }) } @@ -109,25 +110,25 @@ func TestRemoveTagsForNonParameter(t *testing.T) { "ResourceType": tt.resourceType, "ResourceId": tt.resourceID, "Tags": tt.addTags, - }) + }, jsonx.V1()) require.Equal(t, http.StatusOK, doRequest(t, h, "AddTagsToResource", string(addBody)).Code) removeBody, _ := json.Marshal(map[string]any{ "ResourceType": tt.resourceType, "ResourceId": tt.resourceID, "TagKeys": tt.removeKeys, - }) + }, jsonx.V1()) require.Equal(t, http.StatusOK, doRequest(t, h, "RemoveTagsFromResource", string(removeBody)).Code) listBody, _ := json.Marshal(map[string]any{ "ResourceType": tt.resourceType, "ResourceId": tt.resourceID, - }) + }, jsonx.V1()) listRec := doRequest(t, h, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var resp ssm.ListTagsForResourceOutput - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp.TagList, tt.wantRemain) }) } diff --git a/services/ssoadmin/application_auth_methods.go b/services/ssoadmin/application_auth_methods.go index 59d91248ff..e3244c4804 100644 --- a/services/ssoadmin/application_auth_methods.go +++ b/services/ssoadmin/application_auth_methods.go @@ -1,7 +1,7 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" @@ -32,7 +32,7 @@ func (b *InMemoryBackend) DeleteApplicationAuthenticationMethod(applicationArn, // authMethodType must be IAM; body is the full AuthenticationMethod JSON object. func (b *InMemoryBackend) PutApplicationAuthenticationMethod( applicationArn, authMethodType string, - body json.RawMessage, + body jsontext.Value, ) error { b.mu.Lock("PutApplicationAuthenticationMethod") defer b.mu.Unlock() @@ -45,10 +45,10 @@ func (b *InMemoryBackend) PutApplicationAuthenticationMethod( return ErrApplicationNotFound } if b.applicationAuthMethods[applicationArn] == nil { - b.applicationAuthMethods[applicationArn] = make(map[string]json.RawMessage) + b.applicationAuthMethods[applicationArn] = make(map[string]jsontext.Value) } if len(body) == 0 { - body = json.RawMessage("null") + body = jsontext.Value("null") } b.applicationAuthMethods[applicationArn][authMethodType] = body @@ -66,7 +66,7 @@ func (b *InMemoryBackend) ListApplicationAuthenticationMethods(applicationArn st methods := b.applicationAuthMethods[applicationArn] result := make([]AuthMethod, 0, len(methods)) for mType, body := range methods { - bodyCopy := make(json.RawMessage, len(body)) + bodyCopy := make(jsontext.Value, len(body)) copy(bodyCopy, body) result = append(result, AuthMethod{AuthMethodType: mType, Body: bodyCopy}) } @@ -78,7 +78,7 @@ func (b *InMemoryBackend) ListApplicationAuthenticationMethods(applicationArn st // GetApplicationAuthenticationMethod returns a specific auth method body. func (b *InMemoryBackend) GetApplicationAuthenticationMethod( applicationArn, authMethodType string, -) (json.RawMessage, error) { +) (jsontext.Value, error) { b.mu.RLock("GetApplicationAuthenticationMethod") defer b.mu.RUnlock() @@ -93,7 +93,7 @@ func (b *InMemoryBackend) GetApplicationAuthenticationMethod( if !exists { return nil, ErrAuthMethodNotFound } - result := make(json.RawMessage, len(body)) + result := make(jsontext.Value, len(body)) copy(result, body) return result, nil diff --git a/services/ssoadmin/application_grants.go b/services/ssoadmin/application_grants.go index 6032a1c4b0..25f6183235 100644 --- a/services/ssoadmin/application_grants.go +++ b/services/ssoadmin/application_grants.go @@ -1,7 +1,7 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" "fmt" "sort" @@ -22,7 +22,7 @@ func isValidGrantType(grantType string) bool { } // PutApplicationGrant stores a typed grant with its full body. -func (b *InMemoryBackend) PutApplicationGrant(applicationArn, grantType string, body json.RawMessage) error { +func (b *InMemoryBackend) PutApplicationGrant(applicationArn, grantType string, body jsontext.Value) error { b.mu.Lock("PutApplicationGrant") defer b.mu.Unlock() @@ -35,10 +35,10 @@ func (b *InMemoryBackend) PutApplicationGrant(applicationArn, grantType string, return ErrApplicationNotFound } if b.applicationGrants[applicationArn] == nil { - b.applicationGrants[applicationArn] = make(map[string]json.RawMessage) + b.applicationGrants[applicationArn] = make(map[string]jsontext.Value) } if len(body) == 0 { - body = json.RawMessage("null") + body = jsontext.Value("null") } b.applicationGrants[applicationArn][grantType] = body @@ -76,7 +76,7 @@ func (b *InMemoryBackend) ListApplicationGrants(applicationArn string) ([]Applic grants := b.applicationGrants[applicationArn] result := make([]ApplicationGrant, 0, len(grants)) for gType, body := range grants { - bodyCopy := make(json.RawMessage, len(body)) + bodyCopy := make(jsontext.Value, len(body)) copy(bodyCopy, body) result = append(result, ApplicationGrant{GrantType: gType, Grant: bodyCopy}) } @@ -86,7 +86,7 @@ func (b *InMemoryBackend) ListApplicationGrants(applicationArn string) ([]Applic } // GetApplicationGrant returns a specific grant body. -func (b *InMemoryBackend) GetApplicationGrant(applicationArn, grantType string) (json.RawMessage, error) { +func (b *InMemoryBackend) GetApplicationGrant(applicationArn, grantType string) (jsontext.Value, error) { b.mu.RLock("GetApplicationGrant") defer b.mu.RUnlock() @@ -101,7 +101,7 @@ func (b *InMemoryBackend) GetApplicationGrant(applicationArn, grantType string) if !exists { return nil, ErrGrantNotFound } - result := make(json.RawMessage, len(body)) + result := make(jsontext.Value, len(body)) copy(result, body) return result, nil diff --git a/services/ssoadmin/handler.go b/services/ssoadmin/handler.go index 5d71526cd3..235d5ab5a8 100644 --- a/services/ssoadmin/handler.go +++ b/services/ssoadmin/handler.go @@ -2,7 +2,7 @@ package ssoadmin import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -94,7 +95,7 @@ func listApplicationItems[T any]( ApplicationArn string `json:"ApplicationArn"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -232,7 +233,7 @@ func listProvisioningStatusMetadata[T any]( NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -268,7 +269,7 @@ func listPermissionSetSubItems[T any]( NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -427,7 +428,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { var req struct { InstanceArn string `json:"InstanceArn"` } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -736,7 +737,7 @@ func toPermissionSetProvisioningStatusMetadataView(s *ProvisioningStatus) permis } func writeJSON(c *echo.Context, status int, v any) error { - data, err := json.Marshal(v) + data, err := json.Marshal(v, jsonx.V1()) if err != nil { return err } @@ -754,7 +755,7 @@ func checkPaging(body []byte) string { NextToken *string `json:"NextToken"` } - if json.Unmarshal(body, &req) != nil { + if json.Unmarshal(body, &req, jsonx.V1()) != nil { return "" } diff --git a/services/ssoadmin/handler_account_assignments.go b/services/ssoadmin/handler_account_assignments.go index 95939f8e4f..d5df8bb8c6 100644 --- a/services/ssoadmin/handler_account_assignments.go +++ b/services/ssoadmin/handler_account_assignments.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type assignmentView struct { @@ -23,7 +25,7 @@ func (h *Handler) handleCreateAccountAssignment(c *echo.Context, body []byte) er PrincipalID string `json:"PrincipalId"` PrincipalType string `json:"PrincipalType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -71,7 +73,7 @@ func (h *Handler) handleDescribeAccountAssignmentCreationStatus(c *echo.Context, InstanceArn string `json:"InstanceArn"` AccountAssignmentCreationRequestID string `json:"AccountAssignmentCreationRequestId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -97,7 +99,7 @@ func (h *Handler) handleDeleteAccountAssignment(c *echo.Context, body []byte) er PrincipalID string `json:"PrincipalId"` PrincipalType string `json:"PrincipalType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.PrincipalType != "" && req.PrincipalType != principalTypeUser && req.PrincipalType != principalTypeGroup { @@ -130,7 +132,7 @@ func (h *Handler) handleDescribeAccountAssignmentDeletionStatus(c *echo.Context, InstanceArn string `json:"InstanceArn"` AccountAssignmentDeletionRequestID string `json:"AccountAssignmentDeletionRequestId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -155,7 +157,7 @@ func (h *Handler) handleListAccountAssignments(c *echo.Context, body []byte) err NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -212,7 +214,7 @@ func (h *Handler) handleListAccountAssignmentsForPrincipal(c *echo.Context, body NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_application_access_scopes.go b/services/ssoadmin/handler_application_access_scopes.go index 2356be03a5..e2155be79b 100644 --- a/services/ssoadmin/handler_application_access_scopes.go +++ b/services/ssoadmin/handler_application_access_scopes.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDeleteApplicationAccessScope(c *echo.Context, body []byte) error { @@ -12,7 +14,7 @@ func (h *Handler) handleDeleteApplicationAccessScope(c *echo.Context, body []byt ApplicationArn string `json:"ApplicationArn"` Scope string `json:"Scope"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -29,7 +31,7 @@ func (h *Handler) handleListApplicationAccessScopes(c *echo.Context, body []byte NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } scopes, err := h.Backend.ListApplicationAccessScopes(req.ApplicationArn) @@ -53,7 +55,7 @@ func (h *Handler) handlePutApplicationAccessScope(c *echo.Context, body []byte) Scope string `json:"Scope"` AuthorizedTargets []string `json:"AuthorizedTargets"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if err := h.Backend.PutApplicationAccessScope(req.ApplicationArn, req.Scope, req.AuthorizedTargets); err != nil { @@ -68,7 +70,7 @@ func (h *Handler) handleGetApplicationAccessScope(c *echo.Context, body []byte) ApplicationArn string `json:"ApplicationArn"` Scope string `json:"Scope"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { diff --git a/services/ssoadmin/handler_application_assignments.go b/services/ssoadmin/handler_application_assignments.go index 2aedb891ec..666318d4b1 100644 --- a/services/ssoadmin/handler_application_assignments.go +++ b/services/ssoadmin/handler_application_assignments.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateApplicationAssignment(c *echo.Context, body []byte) error { @@ -13,7 +15,7 @@ func (h *Handler) handleCreateApplicationAssignment(c *echo.Context, body []byte PrincipalID string `json:"PrincipalId"` PrincipalType string `json:"PrincipalType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -34,7 +36,7 @@ func (h *Handler) handleDeleteApplicationAssignment(c *echo.Context, body []byte PrincipalID string `json:"PrincipalId"` PrincipalType string `json:"PrincipalType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -55,7 +57,7 @@ func (h *Handler) handleDescribeApplicationAssignment(c *echo.Context, body []by PrincipalID string `json:"PrincipalId"` PrincipalType string `json:"PrincipalType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -82,7 +84,7 @@ func (h *Handler) handleListApplicationAssignments(c *echo.Context, body []byte) NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } assignments, err := h.Backend.ListApplicationAssignments(req.ApplicationArn) @@ -121,7 +123,7 @@ func (h *Handler) handlePutApplicationAssignmentConfiguration(c *echo.Context, b ApplicationArn string `json:"ApplicationArn"` AssignmentRequired bool `json:"AssignmentRequired"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -142,7 +144,7 @@ func (h *Handler) handlePutApplicationSessionConfiguration(c *echo.Context, body ApplicationArn string `json:"ApplicationArn"` UserBackgroundSessionApplicationStatus string `json:"UserBackgroundSessionApplicationStatus"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if err := h.Backend.PutApplicationSessionConfiguration( @@ -158,7 +160,7 @@ func (h *Handler) handleGetApplicationAssignmentConfiguration(c *echo.Context, b var req struct { ApplicationArn string `json:"ApplicationArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { @@ -178,7 +180,7 @@ func (h *Handler) handleGetApplicationSessionConfiguration(c *echo.Context, body var req struct { ApplicationArn string `json:"ApplicationArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { @@ -209,7 +211,7 @@ func (h *Handler) handleListApplicationAssignmentsForPrincipal(c *echo.Context, NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_application_auth_methods.go b/services/ssoadmin/handler_application_auth_methods.go index 60902b2b95..1a11703e35 100644 --- a/services/ssoadmin/handler_application_auth_methods.go +++ b/services/ssoadmin/handler_application_auth_methods.go @@ -1,10 +1,13 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDeleteApplicationAuthenticationMethod(c *echo.Context, body []byte) error { @@ -12,7 +15,7 @@ func (h *Handler) handleDeleteApplicationAuthenticationMethod(c *echo.Context, b ApplicationArn string `json:"ApplicationArn"` AuthMethodType string `json:"AuthenticationMethodType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -35,12 +38,12 @@ func (h *Handler) handleListApplicationAuthenticationMethods(c *echo.Context, bo func (h *Handler) handlePutApplicationAuthenticationMethod(c *echo.Context, body []byte) error { var req struct { - ApplicationArn string `json:"ApplicationArn"` - AuthMethodType string `json:"AuthenticationMethodType"` - AuthenticationType string `json:"AuthenticationType"` - AuthenticationMethod json.RawMessage `json:"AuthenticationMethod"` + ApplicationArn string `json:"ApplicationArn"` + AuthMethodType string `json:"AuthenticationMethodType"` + AuthenticationType string `json:"AuthenticationType"` + AuthenticationMethod jsontext.Value `json:"AuthenticationMethod"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } methodType := req.AuthMethodType @@ -61,7 +64,7 @@ func (h *Handler) handleGetApplicationAuthenticationMethod(c *echo.Context, body ApplicationArn string `json:"ApplicationArn"` AuthenticationMethodType string `json:"AuthenticationMethodType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { diff --git a/services/ssoadmin/handler_application_auth_methods_test.go b/services/ssoadmin/handler_application_auth_methods_test.go index a21abc9868..a898327ee6 100644 --- a/services/ssoadmin/handler_application_auth_methods_test.go +++ b/services/ssoadmin/handler_application_auth_methods_test.go @@ -1,12 +1,15 @@ package ssoadmin_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestApplicationAuthMethodStructured verifies PutApplicationAuthenticationMethod stores structured body. @@ -41,13 +44,13 @@ func TestApplicationAuthMethodStructured(t *testing.T) { instanceArn := createInstance(t, h, "auth-method-inst") appArn := createApplication(t, h, instanceArn, "AuthMethodApp") - bodyBytes, err := json.Marshal(tt.authBody) + bodyBytes, err := json.Marshal(tt.authBody, jsonx.V1()) require.NoError(t, err) rec := doRequest(t, h, "PutApplicationAuthenticationMethod", map[string]any{ "ApplicationArn": appArn, "AuthenticationMethodType": tt.authMethodType, - "AuthenticationMethod": json.RawMessage(bodyBytes), + "AuthenticationMethod": jsontext.Value(bodyBytes), }) assert.Equal(t, tt.wantStatus, rec.Code) }) diff --git a/services/ssoadmin/handler_application_grants.go b/services/ssoadmin/handler_application_grants.go index 9e99fced9c..a6d7b99445 100644 --- a/services/ssoadmin/handler_application_grants.go +++ b/services/ssoadmin/handler_application_grants.go @@ -1,10 +1,13 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDeleteApplicationGrant(c *echo.Context, body []byte) error { @@ -12,7 +15,7 @@ func (h *Handler) handleDeleteApplicationGrant(c *echo.Context, body []byte) err ApplicationArn string `json:"ApplicationArn"` GrantType string `json:"GrantType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if err := h.Backend.DeleteApplicationGrant(req.ApplicationArn, req.GrantType); err != nil { @@ -34,11 +37,11 @@ func (h *Handler) handleListApplicationGrants(c *echo.Context, body []byte) erro func (h *Handler) handlePutApplicationGrant(c *echo.Context, body []byte) error { var req struct { - ApplicationArn string `json:"ApplicationArn"` - GrantType string `json:"GrantType"` - Grant json.RawMessage `json:"Grant"` + ApplicationArn string `json:"ApplicationArn"` + GrantType string `json:"GrantType"` + Grant jsontext.Value `json:"Grant"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if err := h.Backend.PutApplicationGrant(req.ApplicationArn, req.GrantType, req.Grant); err != nil { @@ -53,7 +56,7 @@ func (h *Handler) handleGetApplicationGrant(c *echo.Context, body []byte) error ApplicationArn string `json:"ApplicationArn"` GrantType string `json:"GrantType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { diff --git a/services/ssoadmin/handler_applications.go b/services/ssoadmin/handler_applications.go index 3d1bda9f02..525f499c87 100644 --- a/services/ssoadmin/handler_applications.go +++ b/services/ssoadmin/handler_applications.go @@ -1,12 +1,14 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type applicationView struct { @@ -40,7 +42,7 @@ func (h *Handler) handleCreateApplication(c *echo.Context, body []byte) error { ClientToken string `json:"ClientToken"` Tags []tagView `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -101,7 +103,7 @@ func (h *Handler) handleDeleteApplication(c *echo.Context, body []byte) error { var req struct { ApplicationArn string `json:"ApplicationArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.ApplicationArn == "" { @@ -119,7 +121,7 @@ func (h *Handler) handleDescribeApplication(c *echo.Context, body []byte) error var req struct { ApplicationArn string `json:"ApplicationArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -163,7 +165,7 @@ func (h *Handler) handleDescribeApplicationProvider(c *echo.Context, body []byte var req struct { ApplicationProviderArn string `json:"ApplicationProviderArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -184,7 +186,7 @@ func (h *Handler) handleListApplicationProviders(c *echo.Context, body []byte) e NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -221,7 +223,7 @@ func (h *Handler) handleListApplications(c *echo.Context, body []byte) error { NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } apps := h.Backend.ListApplications(req.InstanceArn) @@ -276,7 +278,7 @@ func (h *Handler) handleUpdateApplication(c *echo.Context, body []byte) error { Description string `json:"Description"` Status string `json:"Status"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/ssoadmin/handler_inline_policies.go b/services/ssoadmin/handler_inline_policies.go index e737873cc0..a9bb68673c 100644 --- a/services/ssoadmin/handler_inline_policies.go +++ b/services/ssoadmin/handler_inline_policies.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handlePutInlinePolicyToPermissionSet(c *echo.Context, body []byte) error { @@ -13,7 +15,7 @@ func (h *Handler) handlePutInlinePolicyToPermissionSet(c *echo.Context, body []b PermissionSetArn string `json:"PermissionSetArn"` InlinePolicy string `json:"InlinePolicy"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -33,7 +35,7 @@ func (h *Handler) handleGetInlinePolicyForPermissionSet(c *echo.Context, body [] InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -52,7 +54,7 @@ func (h *Handler) handleDeleteInlinePolicyFromPermissionSet(c *echo.Context, bod InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/ssoadmin/handler_instance_access_control.go b/services/ssoadmin/handler_instance_access_control.go index d71ff604e0..c9cdcb1fed 100644 --- a/services/ssoadmin/handler_instance_access_control.go +++ b/services/ssoadmin/handler_instance_access_control.go @@ -1,11 +1,13 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleCreateInstanceAccessControlAttributeConfiguration(c *echo.Context, body []byte) error { @@ -20,7 +22,7 @@ func (h *Handler) handleCreateInstanceAccessControlAttributeConfiguration(c *ech } `json:"AccessControlAttributes"` } `json:"InstanceAccessControlAttributeConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -52,7 +54,7 @@ func (h *Handler) handleDeleteInstanceAccessControlAttributeConfiguration(c *ech var req struct { InstanceArn string `json:"InstanceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if err := h.Backend.DeleteInstanceAccessControlAttributeConfiguration(req.InstanceArn); err != nil { @@ -66,7 +68,7 @@ func (h *Handler) handleDescribeInstanceAccessControlAttributeConfiguration(c *e var req struct { InstanceArn string `json:"InstanceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } cfg, err := h.Backend.DescribeInstanceAccessControlAttributeConfiguration(req.InstanceArn) @@ -105,7 +107,7 @@ func (h *Handler) handleUpdateInstanceAccessControlAttributeConfiguration(c *ech } `json:"AccessControlAttributes"` } `json:"InstanceAccessControlAttributeConfiguration"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_instances.go b/services/ssoadmin/handler_instances.go index 34f221512d..a30948a3ff 100644 --- a/services/ssoadmin/handler_instances.go +++ b/services/ssoadmin/handler_instances.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type instanceView struct { @@ -34,7 +36,7 @@ func (h *Handler) handleListInstances(c *echo.Context, body []byte) error { } // Body is optional for ListInstances; ignore unmarshal errors on empty/garbage. if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } instances := h.Backend.ListInstances() @@ -78,7 +80,7 @@ func (h *Handler) handleCreateInstance(c *echo.Context, body []byte) error { ClientToken string `json:"ClientToken"` Tags []tagView `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -105,7 +107,7 @@ func (h *Handler) handleDescribeInstance(c *echo.Context, body []byte) error { var req struct { InstanceArn string `json:"InstanceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -162,7 +164,7 @@ func (h *Handler) handleDeleteInstance(c *echo.Context, body []byte) error { var req struct { InstanceArn string `json:"InstanceArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -186,7 +188,7 @@ func (h *Handler) handleUpdateInstance(c *echo.Context, body []byte) error { InstanceArn string `json:"InstanceArn"` Name string `json:"Name"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_managed_policies.go b/services/ssoadmin/handler_managed_policies.go index 65560d35aa..ddf0837cf7 100644 --- a/services/ssoadmin/handler_managed_policies.go +++ b/services/ssoadmin/handler_managed_policies.go @@ -1,11 +1,13 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type managedPolicyView struct { @@ -19,7 +21,7 @@ func (h *Handler) handleAttachManagedPolicyToPermissionSet(c *echo.Context, body PermissionSetArn string `json:"PermissionSetArn"` ManagedPolicyArn string `json:"ManagedPolicyArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -59,7 +61,7 @@ func (h *Handler) handleDetachManagedPolicyFromPermissionSet(c *echo.Context, bo PermissionSetArn string `json:"PermissionSetArn"` ManagedPolicyArn string `json:"ManagedPolicyArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -106,7 +108,7 @@ func (h *Handler) handleAttachCustomerManagedPolicyReferenceToPermissionSet(c *e PermissionSetArn string `json:"PermissionSetArn"` CustomerManagedPolicyReference customerManagedPolicyReferenceView `json:"CustomerManagedPolicyReference"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -152,7 +154,7 @@ func (h *Handler) handleDetachCustomerManagedPolicyReferenceFromPermissionSet( PermissionSetArn string `json:"PermissionSetArn"` CustomerManagedPolicyReference customerManagedPolicyReferenceView `json:"CustomerManagedPolicyReference"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_permission_sets.go b/services/ssoadmin/handler_permission_sets.go index acf5ebefd6..2753d7dbf1 100644 --- a/services/ssoadmin/handler_permission_sets.go +++ b/services/ssoadmin/handler_permission_sets.go @@ -1,12 +1,14 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type permissionSetView struct { @@ -27,7 +29,7 @@ func (h *Handler) handleCreatePermissionSet(c *echo.Context, body []byte) error RelayState string `json:"RelayState"` Tags []tagView `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -85,7 +87,7 @@ func (h *Handler) handleDescribePermissionSet(c *echo.Context, body []byte) erro InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -112,7 +114,7 @@ func (h *Handler) handleListPermissionSets(c *echo.Context, body []byte) error { NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -139,7 +141,7 @@ func (h *Handler) handleDeletePermissionSet(c *echo.Context, body []byte) error InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -167,7 +169,7 @@ func (h *Handler) handleUpdatePermissionSet(c *echo.Context, body []byte) error SessionDuration string `json:"SessionDuration"` RelayState string `json:"RelayState"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -191,7 +193,7 @@ func (h *Handler) handleProvisionPermissionSet(c *echo.Context, body []byte) err TargetType string `json:"TargetType"` TargetID string `json:"TargetId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -248,7 +250,7 @@ func (h *Handler) handleDescribePermissionSetProvisioningStatus( InstanceArn string `json:"InstanceArn"` ProvisionPermissionSetRequestID string `json:"ProvisionPermissionSetRequestId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -290,7 +292,7 @@ func (h *Handler) handleListPermissionSetsProvisionedToAccount(c *echo.Context, NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -338,7 +340,7 @@ func (h *Handler) handleListAccountsForProvisionedPermissionSet( NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_permissions_boundary.go b/services/ssoadmin/handler_permissions_boundary.go index 9122b2b3f9..045651695f 100644 --- a/services/ssoadmin/handler_permissions_boundary.go +++ b/services/ssoadmin/handler_permissions_boundary.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handlePutPermissionsBoundaryToPermissionSet(c *echo.Context, body []byte) error { @@ -19,7 +21,7 @@ func (h *Handler) handlePutPermissionsBoundaryToPermissionSet(c *echo.Context, b InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -49,7 +51,7 @@ func (h *Handler) handleGetPermissionsBoundaryForPermissionSet(c *echo.Context, InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -79,7 +81,7 @@ func (h *Handler) handleDeletePermissionsBoundaryFromPermissionSet(c *echo.Conte InstanceArn string `json:"InstanceArn"` PermissionSetArn string `json:"PermissionSetArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_regions.go b/services/ssoadmin/handler_regions.go index c055a88e99..566180910e 100644 --- a/services/ssoadmin/handler_regions.go +++ b/services/ssoadmin/handler_regions.go @@ -1,10 +1,12 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleAddRegion(c *echo.Context, body []byte) error { @@ -12,7 +14,7 @@ func (h *Handler) handleAddRegion(c *echo.Context, body []byte) error { InstanceArn string `json:"InstanceArn"` RegionName string `json:"RegionName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -31,7 +33,7 @@ func (h *Handler) handleRemoveRegion(c *echo.Context, body []byte) error { InstanceArn string `json:"InstanceArn"` RegionName string `json:"RegionName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -56,7 +58,7 @@ func (h *Handler) handleListRegions(c *echo.Context, body []byte) error { NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -100,7 +102,7 @@ func (h *Handler) handleDescribeRegion(c *echo.Context, body []byte) error { InstanceArn string `json:"InstanceArn"` RegionName string `json:"RegionName"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { diff --git a/services/ssoadmin/handler_tags.go b/services/ssoadmin/handler_tags.go index 099f2ab0bc..6463dad0b4 100644 --- a/services/ssoadmin/handler_tags.go +++ b/services/ssoadmin/handler_tags.go @@ -1,12 +1,14 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "sort" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { @@ -15,7 +17,7 @@ func (h *Handler) handleTagResource(c *echo.Context, body []byte) error { ResourceArn string `json:"ResourceArn"` Tags []tagView `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -42,7 +44,7 @@ func (h *Handler) handleUntagResource(c *echo.Context, body []byte) error { ResourceArn string `json:"ResourceArn"` TagKeys []string `json:"TagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -59,7 +61,7 @@ func (h *Handler) handleListTagsForResource(c *echo.Context, body []byte) error ResourceArn string `json:"ResourceArn"` NextToken string `json:"NextToken"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/ssoadmin/handler_test.go b/services/ssoadmin/handler_test.go index 6cb7a7dcdd..c6635e08c5 100644 --- a/services/ssoadmin/handler_test.go +++ b/services/ssoadmin/handler_test.go @@ -2,7 +2,7 @@ package ssoadmin_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/ssoadmin" ) @@ -33,7 +34,7 @@ func doRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -53,7 +54,7 @@ func doRequest( func parseResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -444,7 +445,7 @@ func TestHandler_ExtractResource(t *testing.T) { var bodyBytes []byte if tt.body != nil { var err error - bodyBytes, err = json.Marshal(tt.body) + bodyBytes, err = json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/ssoadmin/handler_trusted_token_issuers.go b/services/ssoadmin/handler_trusted_token_issuers.go index fd1dfb54ec..0d37f2c0a0 100644 --- a/services/ssoadmin/handler_trusted_token_issuers.go +++ b/services/ssoadmin/handler_trusted_token_issuers.go @@ -1,11 +1,13 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // trustedTokenIssuerView is the wire shape for types.TrustedTokenIssuerMetadata @@ -34,7 +36,7 @@ func (h *Handler) handleCreateTrustedTokenIssuer(c *echo.Context, body []byte) e ClientToken string `json:"ClientToken"` Tags []tagView `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.InstanceArn == "" { @@ -93,7 +95,7 @@ func (h *Handler) handleDeleteTrustedTokenIssuer(c *echo.Context, body []byte) e var req struct { TrustedTokenIssuerArn string `json:"TrustedTokenIssuerArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } if req.TrustedTokenIssuerArn == "" { @@ -110,7 +112,7 @@ func (h *Handler) handleDescribeTrustedTokenIssuer(c *echo.Context, body []byte) var req struct { TrustedTokenIssuerArn string `json:"TrustedTokenIssuerArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } @@ -153,7 +155,7 @@ func (h *Handler) handleListTrustedTokenIssuers(c *echo.Context, body []byte) er NextToken string `json:"NextToken"` MaxResults int `json:"MaxResults"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } issuers := h.Backend.ListTrustedTokenIssuers(req.InstanceArn) @@ -189,7 +191,7 @@ func (h *Handler) handleUpdateTrustedTokenIssuer(c *echo.Context, body []byte) e Name string `json:"Name"` TrustedTokenIssuerType string `json:"TrustedTokenIssuerType"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return writeError(c, http.StatusBadRequest, "ValidationException", "invalid request body") } diff --git a/services/ssoadmin/interfaces.go b/services/ssoadmin/interfaces.go index 2643333c8e..3dd9aa1c0a 100644 --- a/services/ssoadmin/interfaces.go +++ b/services/ssoadmin/interfaces.go @@ -2,7 +2,7 @@ package ssoadmin import ( "context" - "encoding/json" + "encoding/json/jsontext" ) // StorageBackend is the interface for SSO Admin storage operations. @@ -74,9 +74,9 @@ type StorageBackend interface { PutApplicationAccessScope(applicationArn, scope string, authorizedTargets []string) error PutApplicationAssignmentConfiguration(applicationArn string, assignmentRequired bool) error // PutApplicationAuthenticationMethod stores a structured auth method body; authMethodType must be IAM. - PutApplicationAuthenticationMethod(applicationArn, authMethodType string, body json.RawMessage) error + PutApplicationAuthenticationMethod(applicationArn, authMethodType string, body jsontext.Value) error // PutApplicationGrant stores a structured grant body; grantType must be a valid AWS grant type enum value. - PutApplicationGrant(applicationArn, grantType string, body json.RawMessage) error + PutApplicationGrant(applicationArn, grantType string, body jsontext.Value) error // PutApplicationSessionConfiguration sets the UserBackgroundSessionApplicationStatus // (ENABLED or DISABLED) for an application. Matches the real // PutApplicationSessionConfigurationInput wire shape -- this is NOT a @@ -116,8 +116,8 @@ type StorageBackend interface { GetApplicationAssignmentConfiguration(applicationArn string) (bool, error) GetApplicationSessionConfiguration(applicationArn string) (string, error) GetApplicationAccessScope(applicationArn, scope string) ([]string, error) - GetApplicationAuthenticationMethod(applicationArn, authMethodType string) (json.RawMessage, error) - GetApplicationGrant(applicationArn, grantType string) (json.RawMessage, error) + GetApplicationAuthenticationMethod(applicationArn, authMethodType string) (jsontext.Value, error) + GetApplicationGrant(applicationArn, grantType string) (jsontext.Value, error) ListCustomerManagedPolicyReferencesInPermissionSet( instanceArn, permissionSetArn string, ) ([]CustomerManagedPolicyReference, error) diff --git a/services/ssoadmin/models.go b/services/ssoadmin/models.go index b39cb1d11e..e9b98cefd4 100644 --- a/services/ssoadmin/models.go +++ b/services/ssoadmin/models.go @@ -1,7 +1,7 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" "regexp" "time" ) @@ -348,12 +348,12 @@ type ScopeDetails struct { // AuthMethod holds a typed authentication method with its full structured body. type AuthMethod struct { - AuthMethodType string `json:"AuthenticationMethodType"` - Body json.RawMessage `json:"AuthenticationMethod"` + AuthMethodType string `json:"AuthenticationMethodType"` + Body jsontext.Value `json:"AuthenticationMethod"` } // ApplicationGrant holds a typed grant with its structured body. type ApplicationGrant struct { - GrantType string `json:"GrantType"` - Grant json.RawMessage `json:"Grant"` + GrantType string `json:"GrantType"` + Grant jsontext.Value `json:"Grant"` } diff --git a/services/ssoadmin/multi_region_test.go b/services/ssoadmin/multi_region_test.go index 6cc2def6c8..dca0aee1fa 100644 --- a/services/ssoadmin/multi_region_test.go +++ b/services/ssoadmin/multi_region_test.go @@ -2,7 +2,8 @@ package ssoadmin_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/ssoadmin" ) @@ -172,8 +174,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/ssoadmin/persistence.go b/services/ssoadmin/persistence.go index 840e985b40..0b944935a3 100644 --- a/services/ssoadmin/persistence.go +++ b/services/ssoadmin/persistence.go @@ -2,11 +2,13 @@ package ssoadmin import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -74,7 +76,7 @@ func newDirtyDTORegistry() ( // newer) build of this backend as though it were the current shape; see // Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Assignments map[string][]*AccountAssignment `json:"assignments"` AssignmentCreationIDs map[string]string `json:"assignmentCreationIDs"` ProvisionedAt map[string]time.Time `json:"provisionedAt"` @@ -82,8 +84,8 @@ type backendSnapshot struct { CustomerManagedPolicies map[string][]CustomerManagedPolicyReference `json:"customerManagedPolicies"` ApplicationAssignments map[string][]*ApplicationAssignment `json:"applicationAssignments"` ApplicationScopes map[string]map[string][]string `json:"applicationScopes"` - ApplicationAuthMethods map[string]map[string]json.RawMessage `json:"applicationAuthMethods"` - ApplicationGrants map[string]map[string]json.RawMessage `json:"applicationGrants"` + ApplicationAuthMethods map[string]map[string]jsontext.Value `json:"applicationAuthMethods"` + ApplicationGrants map[string]map[string]jsontext.Value `json:"applicationGrants"` ApplicationAssignConfig map[string]bool `json:"applicationAssignConfig"` ApplicationSessions map[string]string `json:"applicationSessions"` AccountID string `json:"accountID"` @@ -140,7 +142,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Region: b.region, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "ssoadmin: failed to marshal snapshot", "error", err) @@ -182,8 +184,8 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { b.customerManagedPolicies = make(map[string][]CustomerManagedPolicyReference) b.applicationAssignments = make(map[string][]*ApplicationAssignment) b.applicationScopes = make(map[string]map[string][]string) - b.applicationAuthMethods = make(map[string]map[string]json.RawMessage) - b.applicationGrants = make(map[string]map[string]json.RawMessage) + b.applicationAuthMethods = make(map[string]map[string]jsontext.Value) + b.applicationGrants = make(map[string]map[string]jsontext.Value) b.applicationAssignConfig = make(map[string]bool) b.applicationSessions = make(map[string]string) b.seedDefaultInstance() @@ -222,7 +224,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // permissionBoundaries) from tables via the ephemeral DTO registry, // converting each DTO back to its live type. The caller MUST hold b.mu for // writing. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtoReg, acaDTOs, pbDTOs := newDirtyDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { diff --git a/services/ssoadmin/store.go b/services/ssoadmin/store.go index ed35b44a08..ce79de0a4b 100644 --- a/services/ssoadmin/store.go +++ b/services/ssoadmin/store.go @@ -1,7 +1,7 @@ package ssoadmin import ( - "encoding/json" + "encoding/json/jsontext" "time" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -34,9 +34,9 @@ type InMemoryBackend struct { applicationAssignments map[string][]*ApplicationAssignment applicationScopes map[string]map[string][]string // applicationAuthMethods stores per-app authentication methods: appArn → methodType → full JSON body. - applicationAuthMethods map[string]map[string]json.RawMessage + applicationAuthMethods map[string]map[string]jsontext.Value // applicationGrants stores per-app grants: appArn → grantType → full JSON body. - applicationGrants map[string]map[string]json.RawMessage + applicationGrants map[string]map[string]jsontext.Value applicationAssignConfig map[string]bool applicationSessions map[string]string instanceACAs *store.Table[ABACConfig] @@ -81,8 +81,8 @@ func NewInMemoryBackend(accountID, region string) *InMemoryBackend { customerManagedPolicies: make(map[string][]CustomerManagedPolicyReference), applicationAssignments: make(map[string][]*ApplicationAssignment), applicationScopes: make(map[string]map[string][]string), - applicationAuthMethods: make(map[string]map[string]json.RawMessage), - applicationGrants: make(map[string]map[string]json.RawMessage), + applicationAuthMethods: make(map[string]map[string]jsontext.Value), + applicationGrants: make(map[string]map[string]jsontext.Value), applicationAssignConfig: make(map[string]bool), applicationSessions: make(map[string]string), mu: lockmetrics.New("ssoadmin"), @@ -115,8 +115,8 @@ func (b *InMemoryBackend) Reset() { b.customerManagedPolicies = make(map[string][]CustomerManagedPolicyReference) b.applicationAssignments = make(map[string][]*ApplicationAssignment) b.applicationScopes = make(map[string]map[string][]string) - b.applicationAuthMethods = make(map[string]map[string]json.RawMessage) - b.applicationGrants = make(map[string]map[string]json.RawMessage) + b.applicationAuthMethods = make(map[string]map[string]jsontext.Value) + b.applicationGrants = make(map[string]map[string]jsontext.Value) b.applicationAssignConfig = make(map[string]bool) b.applicationSessions = make(map[string]string) // Re-seed the default instance. diff --git a/services/ssooidc/handler.go b/services/ssooidc/handler.go index a51f5b51e0..3db3cd1c0d 100644 --- a/services/ssooidc/handler.go +++ b/services/ssooidc/handler.go @@ -1,7 +1,7 @@ package ssooidc import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -151,7 +152,7 @@ func decodeBody(c *echo.Context, v any) *APIError { return nil } - if json.Unmarshal(body, v) != nil { + if json.Unmarshal(body, v, jsonx.V1()) != nil { return errInvalidRequest("the request body is not valid JSON") } diff --git a/services/ssooidc/persistence.go b/services/ssooidc/persistence.go index 61ed403621..8d0624a1ac 100644 --- a/services/ssooidc/persistence.go +++ b/services/ssooidc/persistence.go @@ -2,7 +2,7 @@ package ssooidc import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,8 +12,8 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + Version int `json:"version"` } // Snapshot serializes the backend state. It implements persistence.Persistable. diff --git a/services/stepfunctions/aliases_test.go b/services/stepfunctions/aliases_test.go index 876b30c698..bf1bd81bdb 100644 --- a/services/stepfunctions/aliases_test.go +++ b/services/stepfunctions/aliases_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -29,7 +30,7 @@ func createSFNStateMachineCov( require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn, _ := resp["stateMachineArn"].(string) require.NotEmpty(t, arn) @@ -299,14 +300,14 @@ func TestCreateStateMachineAlias_RoutingViaHandler(t *testing.T) { "routingConfiguration": []map[string]any{ {"stateMachineVersionArn": "arn:fake:version:1", "weight": 50}, }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachineAlias", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // CHANGED (orphan-code sweep, gopherstack-yatn): this assertion previously // checked for "InvalidRoutingConfiguration", which is not a real sfn SDK // error type -- CreateStateMachineAlias's own deserializeOpError switch diff --git a/services/stepfunctions/asl/distributed_scope.go b/services/stepfunctions/asl/distributed_scope.go index e6d7ab3298..40517f53bc 100644 --- a/services/stepfunctions/asl/distributed_scope.go +++ b/services/stepfunctions/asl/distributed_scope.go @@ -1,11 +1,13 @@ package asl import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "regexp" "slices" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var varRefRe = regexp.MustCompile( @@ -30,13 +32,13 @@ func checkDistributedScope(mapName string, states map[string]*State, outer map[s continue } - b, err := json.Marshal(st) + b, err := json.Marshal(st, jsonx.V1()) if err != nil { return fmt.Errorf("%w: state %q: %w", ErrParseError, name, err) } var doc any - if err = json.Unmarshal(b, &doc); err != nil { + if err = json.Unmarshal(b, &doc, jsonx.V1()); err != nil { return fmt.Errorf("%w: state %q: %w", ErrParseError, name, err) } diff --git a/services/stepfunctions/asl/executor.go b/services/stepfunctions/asl/executor.go index c1071f55c4..dcd5de891d 100644 --- a/services/stepfunctions/asl/executor.go +++ b/services/stepfunctions/asl/executor.go @@ -7,7 +7,8 @@ import ( cryptorand "crypto/rand" "encoding/base64" "encoding/csv" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -26,6 +27,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/arn" "github.com/blackbirdworks/gopherstack/pkgs/awstime" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/roleauth" ) @@ -747,7 +749,7 @@ func (e *Executor) Execute( ) (*ExecutionResult, error) { var input any if inputJSON != "" { - if err := json.Unmarshal([]byte(inputJSON), &input); err != nil { + if err := json.Unmarshal([]byte(inputJSON), &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid input JSON: %w", err) } } @@ -981,7 +983,7 @@ func (e *Executor) executeState( func (e *Executor) executePass(state *State, input any) (string, any, error) { if len(state.Result) > 0 { var result any - if err := json.Unmarshal(state.Result, &result); err != nil { + if err := json.Unmarshal(state.Result, &result, jsonx.V1()); err != nil { return "", nil, fmt.Errorf("invalid Pass Result: %w", err) } @@ -1381,7 +1383,7 @@ func (e *Executor) invokeTaskAttempt( func parseCallbackOutput(output string) any { var result any if output != "" { - if err := json.Unmarshal([]byte(output), &result); err == nil { + if err := json.Unmarshal([]byte(output), &result, jsonx.V1()); err == nil { return result } } @@ -1679,7 +1681,7 @@ func (e *Executor) invokeActivityTask(ctx context.Context, state *State, input a } var result any - if unmarshalErr := json.Unmarshal([]byte(output), &result); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal([]byte(output), &result, jsonx.V1()); unmarshalErr != nil { // Non-JSON output is valid; return the raw string. Intentionally ignoring unmarshalErr. return output, nil //nolint:nilerr // non-JSON activity output is valid; return as string } @@ -1697,7 +1699,7 @@ func (e *Executor) invokeLambdaTask(ctx context.Context, state *State, input any return nil, err } - payload, err := json.Marshal(input) + payload, err := json.Marshal(input, jsonx.V1()) if err != nil { return nil, fmt.Errorf("failed to marshal task input: %w", err) } @@ -1723,7 +1725,7 @@ func (e *Executor) invokeLambdaTask(ctx context.Context, state *State, input any var result any // Non-JSON Lambda responses are valid; fall back to raw string. - if json.Unmarshal(respBytes, &result) != nil { + if json.Unmarshal(respBytes, &result, jsonx.V1()) != nil { result = string(respBytes) } @@ -2538,7 +2540,7 @@ func batchItems(items []any, maxItemsPerBatch, maxInputBytesPerBatch int) []any return batches } -func (e *Executor) batchInput(b *ItemBatcher) json.RawMessage { +func (e *Executor) batchInput(b *ItemBatcher) jsontext.Value { if e.jxMapCfg != nil { return e.jxMapCfg.batchInput } @@ -2552,10 +2554,10 @@ func (e *Executor) batchInput(b *ItemBatcher) json.RawMessage { // input-output-itembatcher.html, "Batch input"). Previously each batch was // passed through as a bare array, which is not the shape AWS sends to child // executions. -func wrapItemBatcherBatches(rawBatches []any, batchInput json.RawMessage) ([]any, error) { +func wrapItemBatcherBatches(rawBatches []any, batchInput jsontext.Value) ([]any, error) { var decodedBatchInput any if len(batchInput) > 0 { - if err := json.Unmarshal(batchInput, &decodedBatchInput); err != nil { + if err := json.Unmarshal(batchInput, &decodedBatchInput, jsonx.V1()); err != nil { return nil, fmt.Errorf("ItemBatcher.BatchInput error: %w", err) } } @@ -2576,7 +2578,7 @@ func wrapItemBatcherBatches(rawBatches []any, batchInput json.RawMessage) ([]any func applyMapItemSelector( slot *atomic.Pointer[parsedTemplate], - itemSelector json.RawMessage, + itemSelector jsontext.Value, items []any, vars varFunc, ) ([]any, error) { @@ -2984,7 +2986,7 @@ func (e *Executor) resolveS3InventoryManifest( cfg *ReaderConfig, ) ([]any, error) { var manifest s3InventoryManifest - if err := json.Unmarshal(manifestData, &manifest); err != nil { + if err := json.Unmarshal(manifestData, &manifest, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: manifest.json: %w", ErrItemReaderInvalidData, err) } @@ -3078,7 +3080,7 @@ func decodeJSONItems(data []byte, cfg *ReaderConfig) ([]any, error) { } var doc any - if err := json.Unmarshal(data, &doc); err != nil { + if err := json.Unmarshal(data, &doc, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrItemReaderInvalidData, err) } @@ -3155,7 +3157,7 @@ func stepJSONPointer(cur any, tok string) (any, error) { func decodeJSONAuto(data []byte) ([]any, error) { var arr []any - if jsonErr := json.Unmarshal(data, &arr); jsonErr == nil { + if jsonErr := json.Unmarshal(data, &arr, jsonx.V1()); jsonErr == nil { return arr, nil } @@ -3174,7 +3176,7 @@ func decodeJSONLines(data []byte) ([]any, error) { } var item any - if jsonErr := json.Unmarshal([]byte(line), &item); jsonErr != nil { + if jsonErr := json.Unmarshal([]byte(line), &item, jsonx.V1()); jsonErr != nil { return nil, fmt.Errorf("%w: %w", ErrItemReaderInvalidData, jsonErr) } @@ -4469,7 +4471,7 @@ func marshalInput(v any) string { return "{}" } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "{}" } @@ -4485,13 +4487,13 @@ type parsedTemplate struct { } // loadTemplate returns the slot's parsed template, decoding raw on first use. -func loadTemplate(slot *atomic.Pointer[parsedTemplate], raw json.RawMessage) *parsedTemplate { +func loadTemplate(slot *atomic.Pointer[parsedTemplate], raw jsontext.Value) *parsedTemplate { if pt := slot.Load(); pt != nil { return pt } pt := &parsedTemplate{usesContext: bytes.Contains(raw, []byte("$$"))} - if err := json.Unmarshal(raw, &pt.tmpl); err != nil { + if err := json.Unmarshal(raw, &pt.tmpl, jsonx.V1()); err != nil { pt.err = fmt.Errorf("invalid template: %w", err) } diff --git a/services/stepfunctions/asl/executor_test.go b/services/stepfunctions/asl/executor_test.go index 3535599a67..c654d4d0b5 100644 --- a/services/stepfunctions/asl/executor_test.go +++ b/services/stepfunctions/asl/executor_test.go @@ -2,7 +2,7 @@ package asl_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync/atomic" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -2112,7 +2113,7 @@ func TestExecutor_UnknownStateType(t *testing.T) { // Parse will succeed but execute will fail on unknown type. var sm asl.StateMachine - require.NoError(t, json.Unmarshal([]byte(tt.def), &sm)) + require.NoError(t, json.Unmarshal([]byte(tt.def), &sm, jsonx.V1())) exec := asl.NewExecutor(&sm, nil, nil) _, err := exec.Execute(t.Context(), "test", tt.input) require.Error(t, err) diff --git a/services/stepfunctions/asl/intrinsics.go b/services/stepfunctions/asl/intrinsics.go index ac8b113e46..8988b9b6bc 100644 --- a/services/stepfunctions/asl/intrinsics.go +++ b/services/stepfunctions/asl/intrinsics.go @@ -6,7 +6,7 @@ import ( "crypto/sha256" "encoding/base64" "encoding/hex" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "hash" @@ -15,6 +15,8 @@ import ( "slices" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Sentinel errors for intrinsic function evaluation. @@ -260,7 +262,7 @@ func intrinsicFormat(args []any) (any, error) { case nil: result.WriteString("null") default: - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, fmt.Errorf("States.Format: cannot serialize argument: %w", err) } @@ -289,7 +291,7 @@ func intrinsicStringToJSON(args []any) (any, error) { } var result any - if err := json.Unmarshal([]byte(s), &result); err != nil { + if err := json.Unmarshal([]byte(s), &result, jsonx.V1()); err != nil { return nil, fmt.Errorf("States.StringToJson: invalid JSON: %w", err) } @@ -302,7 +304,7 @@ func intrinsicJSONToString(args []any) (any, error) { return nil, ErrStatesJSONToStringRequiresArg } - b, err := json.Marshal(args[0]) + b, err := json.Marshal(args[0], jsonx.V1()) if err != nil { return nil, fmt.Errorf("States.JsonToString: cannot serialize: %w", err) } diff --git a/services/stepfunctions/asl/item_reader_parquet.go b/services/stepfunctions/asl/item_reader_parquet.go index f98cec716a..2f6dde0f6e 100644 --- a/services/stepfunctions/asl/item_reader_parquet.go +++ b/services/stepfunctions/asl/item_reader_parquet.go @@ -2,10 +2,11 @@ package asl import ( "encoding/binary" - "encoding/json" + "encoding/json/v2" "errors" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -66,13 +67,13 @@ func decodeParquetItems(data []byte) ([]any, error) { // normalizeJSONNumbers round-trips items so numbers carry the float64 type // every other ItemReader decoder yields. func normalizeJSONNumbers(items []any) ([]any, error) { - raw, err := json.Marshal(items) + raw, err := json.Marshal(items, jsonx.V1()) if err != nil { return nil, fmt.Errorf("%w: %w", ErrItemReaderInvalidData, err) } var out []any - if err = json.Unmarshal(raw, &out); err != nil { + if err = json.Unmarshal(raw, &out, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrItemReaderInvalidData, err) } diff --git a/services/stepfunctions/asl/jsonata.go b/services/stepfunctions/asl/jsonata.go index 978adea651..2349a97a6a 100644 --- a/services/stepfunctions/asl/jsonata.go +++ b/services/stepfunctions/asl/jsonata.go @@ -2,7 +2,7 @@ package asl import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -11,6 +11,8 @@ import ( "time" "github.com/recolabs/gnata" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -114,13 +116,13 @@ func normalizeJSONata(v any) (any, error) { return v, nil } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return nil, queryEvalError(fmt.Errorf("%w: result is not valid JSON: %w", errJSONataEval, err)) } var out any - if err = json.Unmarshal(b, &out); err != nil { + if err = json.Unmarshal(b, &out, jsonx.V1()); err != nil { return nil, queryEvalError(err) } diff --git a/services/stepfunctions/asl/jsonata_exec.go b/services/stepfunctions/asl/jsonata_exec.go index 4aa9ad90a8..ed6736a581 100644 --- a/services/stepfunctions/asl/jsonata_exec.go +++ b/services/stepfunctions/asl/jsonata_exec.go @@ -2,13 +2,16 @@ package asl import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" "math" "slices" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // runJSONataState runs one JSONata-mode state (Arguments, body, then the @@ -396,7 +399,7 @@ func (e *Executor) jxItemSelector(state *State, items []any) ([]any, error) { type jxMapConfig struct { readerParams map[string]any writerParams map[string]any - batchInput json.RawMessage + batchInput jsontext.Value maxItems int maxBytes int } @@ -445,7 +448,7 @@ func (s *jxScope) resolveBatcher(b *ItemBatcher, cfg *jxMapConfig) error { return err } - if cfg.batchInput, err = json.Marshal(v); err != nil { + if cfg.batchInput, err = json.Marshal(v, jsonx.V1()); err != nil { return queryEvalError(err) } diff --git a/services/stepfunctions/asl/jsonata_validate.go b/services/stepfunctions/asl/jsonata_validate.go index c0517b57c5..d6603a346f 100644 --- a/services/stepfunctions/asl/jsonata_validate.go +++ b/services/stepfunctions/asl/jsonata_validate.go @@ -1,12 +1,15 @@ package asl import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "regexp" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -144,20 +147,20 @@ func walkNested(name string, st *State, lang string, inner map[string]struct{}) return nil } -func decodeAssign(raw json.RawMessage) (map[string]any, error) { +func decodeAssign(raw jsontext.Value) (map[string]any, error) { if len(raw) == 0 { return nil, nil //nolint:nilnil // field absent } var m map[string]any - if err := json.Unmarshal(raw, &m); err != nil || m == nil { + if err := json.Unmarshal(raw, &m, jsonx.V1()); err != nil || m == nil { return nil, fmt.Errorf("%w: Assign must be a JSON object", ErrParseError) } return m, nil } -func assignNames(raw json.RawMessage, into map[string]struct{}) error { +func assignNames(raw jsontext.Value, into map[string]struct{}) error { m, err := decodeAssign(raw) if err != nil { return err @@ -373,9 +376,9 @@ func rejectJSONPathFields(name string, st *State) error { return nil } -func decodeRaw(name, field string, raw json.RawMessage) (any, error) { +func decodeRaw(name, field string, raw jsontext.Value) (any, error) { var v any - if err := json.Unmarshal(raw, &v); err != nil { + if err := json.Unmarshal(raw, &v, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: state %q: invalid %s: %w", ErrParseError, name, field, err) } @@ -487,7 +490,7 @@ func (j *jxState) prepareFields(name string, st *State) error { dst *any set *bool field string - raw json.RawMessage + raw jsontext.Value ctx exprCtx }{ {&j.args, &j.hasArgs, "Arguments", st.Arguments, plain}, @@ -519,7 +522,7 @@ func (j *jxState) prepareFields(name string, st *State) error { return j.prepareRest(name, st, exprCtx{result: hasResult}) } -func readerArguments(st *State) json.RawMessage { +func readerArguments(st *State) jsontext.Value { if st.ItemReader == nil { return nil } @@ -527,7 +530,7 @@ func readerArguments(st *State) json.RawMessage { return st.ItemReader.Arguments } -func writerArguments(st *State) json.RawMessage { +func writerArguments(st *State) jsontext.Value { if st.ResultWriter == nil { return nil } @@ -535,7 +538,7 @@ func writerArguments(st *State) json.RawMessage { return st.ResultWriter.Arguments } -func batchInputRaw(st *State) json.RawMessage { +func batchInputRaw(st *State) jsontext.Value { if st.ItemBatcher == nil { return nil } diff --git a/services/stepfunctions/asl/mock.go b/services/stepfunctions/asl/mock.go index 82ff496a15..23d2d4c4ff 100644 --- a/services/stepfunctions/asl/mock.go +++ b/services/stepfunctions/asl/mock.go @@ -1,7 +1,8 @@ package asl import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "os" @@ -9,6 +10,8 @@ import ( "strconv" "strings" "sync/atomic" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Mock config errors. @@ -29,7 +32,7 @@ type MockConfig struct { type mockStep struct { throw *mockThrow - ret json.RawMessage + ret jsontext.Value lo int hi int } @@ -40,8 +43,8 @@ type mockThrow struct { } type mockFileStep struct { - Throw *mockThrow `json:"Throw"` - Return json.RawMessage `json:"Return"` + Throw *mockThrow `json:"Throw"` + Return jsontext.Value `json:"Return"` } type mockFile struct { @@ -64,7 +67,7 @@ func LoadMockConfig(path string) (*MockConfig, error) { // ParseMockConfig validates mock configuration JSON. func ParseMockConfig(data []byte) (*MockConfig, error) { var f mockFile - if err := json.Unmarshal(data, &f); err != nil { + if err := json.Unmarshal(data, &f, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrMockConfigInvalid, err) } @@ -204,7 +207,7 @@ func (r *MockRun) invoke(stateName string) (any, bool, error) { } var out any - if uerr := json.Unmarshal(s.ret, &out); uerr != nil { + if uerr := json.Unmarshal(s.ret, &out, jsonx.V1()); uerr != nil { return nil, true, &FailError{ErrCode: errCodeStatesRuntime, Cause: uerr.Error()} } diff --git a/services/stepfunctions/asl/parser.go b/services/stepfunctions/asl/parser.go index 864f7de619..f96daa3cb0 100644 --- a/services/stepfunctions/asl/parser.go +++ b/services/stepfunctions/asl/parser.go @@ -4,10 +4,13 @@ package asl import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "sync/atomic" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrParseError is returned when the state machine definition cannot be parsed. @@ -70,37 +73,37 @@ type ItemBatcher struct { maxItemsExpr string maxBytesExpr string // BatchInput is fixed JSON merged into every batch (input-output-itembatcher.html). - BatchInput json.RawMessage `json:"BatchInput,omitempty"` + BatchInput jsontext.Value `json:"BatchInput,omitempty"` // MaxItemsPerBatch and MaxInputBytesPerBatch: zero means no limit. MaxItemsPerBatch int `json:"MaxItemsPerBatch,omitempty"` MaxInputBytesPerBatch int `json:"MaxInputBytesPerBatch,omitempty"` } type itemBatcherWire struct { - MaxItemsPerBatchPath string `json:"MaxItemsPerBatchPath,omitempty"` - MaxInputBytesPerBatchPath string `json:"MaxInputBytesPerBatchPath,omitempty"` - MaxItemsPerBatch json.RawMessage `json:"MaxItemsPerBatch,omitempty"` - MaxInputBytesPerBatch json.RawMessage `json:"MaxInputBytesPerBatch,omitempty"` - BatchInput json.RawMessage `json:"BatchInput,omitempty"` + MaxItemsPerBatchPath string `json:"MaxItemsPerBatchPath,omitempty"` + MaxInputBytesPerBatchPath string `json:"MaxInputBytesPerBatchPath,omitempty"` + MaxItemsPerBatch jsontext.Value `json:"MaxItemsPerBatch,omitempty"` + MaxInputBytesPerBatch jsontext.Value `json:"MaxInputBytesPerBatch,omitempty"` + BatchInput jsontext.Value `json:"BatchInput,omitempty"` } // decodeBatchLimit reads an integer limit, or a JSONata string into expr. -func decodeBatchLimit(raw json.RawMessage, n *int, expr *string) error { +func decodeBatchLimit(raw jsontext.Value, n *int, expr *string) error { if len(raw) == 0 { return nil } if raw[0] == '"' { - return json.Unmarshal(raw, expr) + return json.Unmarshal(raw, expr, jsonx.V1()) } - return json.Unmarshal(raw, n) + return json.Unmarshal(raw, n, jsonx.V1()) } // UnmarshalJSON accepts a JSONata string for either batch limit. func (b *ItemBatcher) UnmarshalJSON(data []byte) error { var w itemBatcherWire - if err := json.Unmarshal(data, &w); err != nil { + if err := json.Unmarshal(data, &w, jsonx.V1()); err != nil { return err } @@ -134,15 +137,15 @@ func (b ItemBatcher) MarshalJSON() ([]byte, error) { return nil, err } - return json.Marshal(w) + return json.Marshal(w, jsonx.V1()) } -func encodeBatchLimit(n int, expr string) (json.RawMessage, error) { +func encodeBatchLimit(n int, expr string) (jsontext.Value, error) { switch { case expr != "": - return json.Marshal(expr) + return json.Marshal(expr, jsonx.V1()) case n != 0: - return json.Marshal(n) + return json.Marshal(n, jsonx.V1()) } return nil, nil @@ -150,10 +153,10 @@ func encodeBatchLimit(n int, expr string) (json.RawMessage, error) { // ItemReader configures reading items from S3 for a Map state's Distributed Map. type ItemReader struct { - Parameters map[string]any `json:"Parameters,omitempty"` - ReaderConfig *ReaderConfig `json:"ReaderConfig,omitempty"` - Resource string `json:"Resource,omitempty"` - Arguments json.RawMessage `json:"Arguments,omitempty"` + Parameters map[string]any `json:"Parameters,omitempty"` + ReaderConfig *ReaderConfig `json:"ReaderConfig,omitempty"` + Resource string `json:"Resource,omitempty"` + Arguments jsontext.Value `json:"Arguments,omitempty"` } // ReaderConfig describes how the ItemReader should interpret S3 object data. @@ -196,7 +199,7 @@ type ResultWriter struct { Parameters map[string]any `json:"Parameters,omitempty"` WriterConfig *ResultWriterConfig `json:"WriterConfig,omitempty"` Resource string `json:"Resource,omitempty"` - Arguments json.RawMessage `json:"Arguments,omitempty"` + Arguments jsontext.Value `json:"Arguments,omitempty"` } // ResultWriterConfig is ResultWriter.WriterConfig: Transformation @@ -215,22 +218,22 @@ type State struct { jx *jxState assignVals map[string]any // numExprs holds JSONata strings for fields that are integers in JSONPath. - Assign json.RawMessage `json:"Assign,omitempty"` - Arguments json.RawMessage `json:"Arguments,omitempty"` - Output json.RawMessage `json:"Output,omitempty"` - Items json.RawMessage `json:"Items,omitempty"` + Assign jsontext.Value `json:"Assign,omitempty"` + Arguments jsontext.Value `json:"Arguments,omitempty"` + Output jsontext.Value `json:"Output,omitempty"` + Items jsontext.Value `json:"Items,omitempty"` numExprs map[string]string QueryLanguage string `json:"QueryLanguage,omitempty"` lang string - Iterator *StateMachine `json:"Iterator,omitempty"` - ItemProcessor *StateMachine `json:"ItemProcessor,omitempty"` - ItemBatcher *ItemBatcher `json:"ItemBatcher,omitempty"` - ItemReader *ItemReader `json:"ItemReader,omitempty"` - ResultWriter *ResultWriter `json:"ResultWriter,omitempty"` - ItemSelector json.RawMessage `json:"ItemSelector,omitempty"` - SecondsPath string `json:"SecondsPath,omitempty"` - TimestampPath string `json:"TimestampPath,omitempty"` - ItemsPath string `json:"ItemsPath,omitempty"` + Iterator *StateMachine `json:"Iterator,omitempty"` + ItemProcessor *StateMachine `json:"ItemProcessor,omitempty"` + ItemBatcher *ItemBatcher `json:"ItemBatcher,omitempty"` + ItemReader *ItemReader `json:"ItemReader,omitempty"` + ResultWriter *ResultWriter `json:"ResultWriter,omitempty"` + ItemSelector jsontext.Value `json:"ItemSelector,omitempty"` + SecondsPath string `json:"SecondsPath,omitempty"` + TimestampPath string `json:"TimestampPath,omitempty"` + ItemsPath string `json:"ItemsPath,omitempty"` // ToleratedFailureCount/Percentage (and their *Path variants) bound how many // Map iterations may fail before the Map state itself fails with // States.ExceedToleratedFailureThreshold. AWS supports these only for @@ -261,20 +264,20 @@ type State struct { // reference-path siblings, mutually exclusive with them and resolved against // the Task state's pre-Parameters input (AWS docs: // amazon-states-language-task-state.html, GlueJobTask example). - TimeoutSecondsPath string `json:"TimeoutSecondsPath,omitempty"` - HeartbeatSecondsPath string `json:"HeartbeatSecondsPath,omitempty"` - Retry []Retrier `json:"Retry,omitempty"` - Catch []Catcher `json:"Catch,omitempty"` - Choices []ChoiceRule `json:"Choices,omitempty"` - Result json.RawMessage `json:"Result,omitempty"` - Branches []Branch `json:"Branches,omitempty"` - Parameters json.RawMessage `json:"Parameters,omitempty"` - ResultSelector json.RawMessage `json:"ResultSelector,omitempty"` - TimeoutSeconds int `json:"TimeoutSeconds,omitempty"` - HeartbeatSeconds int `json:"HeartbeatSeconds,omitempty"` - Seconds int `json:"Seconds,omitempty"` - MaxConcurrency int `json:"MaxConcurrency,omitempty"` - End bool `json:"End,omitempty"` + TimeoutSecondsPath string `json:"TimeoutSecondsPath,omitempty"` + HeartbeatSecondsPath string `json:"HeartbeatSecondsPath,omitempty"` + Retry []Retrier `json:"Retry,omitempty"` + Catch []Catcher `json:"Catch,omitempty"` + Choices []ChoiceRule `json:"Choices,omitempty"` + Result jsontext.Value `json:"Result,omitempty"` + Branches []Branch `json:"Branches,omitempty"` + Parameters jsontext.Value `json:"Parameters,omitempty"` + ResultSelector jsontext.Value `json:"ResultSelector,omitempty"` + TimeoutSeconds int `json:"TimeoutSeconds,omitempty"` + HeartbeatSeconds int `json:"HeartbeatSeconds,omitempty"` + Seconds int `json:"Seconds,omitempty"` + MaxConcurrency int `json:"MaxConcurrency,omitempty"` + End bool `json:"End,omitempty"` } // Retrier defines retry behavior for a Task state on error. @@ -294,8 +297,8 @@ type Retrier struct { // Catcher defines catch behavior for a Task state on error. type Catcher struct { - Assign json.RawMessage `json:"Assign,omitempty"` - Output json.RawMessage `json:"Output,omitempty"` + Assign jsontext.Value `json:"Assign,omitempty"` + Output jsontext.Value `json:"Output,omitempty"` assignVals map[string]any outputVal any Next string `json:"Next"` @@ -314,8 +317,8 @@ type Branch struct { // ChoiceRule represents a single condition/transition in a Choice state. type ChoiceRule struct { // Condition and Assign are the JSONata-mode rule fields. - Condition string `json:"Condition,omitempty"` - Assign json.RawMessage `json:"Assign,omitempty"` + Condition string `json:"Condition,omitempty"` + Assign jsontext.Value `json:"Assign,omitempty"` assignVals map[string]any // Numeric comparisons NumericEquals *float64 `json:"NumericEquals,omitempty"` @@ -386,7 +389,7 @@ func ParseIsolatedState(definition string) (*StateMachine, error) { func parse(definition string, checkTransitions bool) (*StateMachine, error) { var sm StateMachine - if err := json.Unmarshal([]byte(definition), &sm); err != nil { + if err := json.Unmarshal([]byte(definition), &sm, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", ErrParseError, err) } @@ -610,7 +613,7 @@ func (s *State) UnmarshalJSON(b []byte) error { } } - if err := json.Unmarshal(b, (*stateAlias)(s)); err != nil { + if err := json.Unmarshal(b, (*stateAlias)(s), jsonx.V1()); err != nil { return err } @@ -622,8 +625,8 @@ func (s *State) UnmarshalJSON(b []byte) error { // liftNumExprs removes string-valued integer fields from the state object and // returns them separately; the object is returned untouched if there are none. func liftNumExprs(b []byte) ([]byte, map[string]string, error) { - var raw map[string]json.RawMessage - if err := json.Unmarshal(b, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(b, &raw, jsonx.V1()); err != nil { return nil, nil, err } @@ -636,7 +639,7 @@ func liftNumExprs(b []byte) ([]byte, map[string]string, error) { } var str string - if err := json.Unmarshal(v, &str); err != nil { + if err := json.Unmarshal(v, &str, jsonx.V1()); err != nil { return nil, nil, err } @@ -652,7 +655,7 @@ func liftNumExprs(b []byte) ([]byte, map[string]string, error) { return b, nil, nil } - out, err := json.Marshal(raw) + out, err := json.Marshal(raw, jsonx.V1()) return out, exprs, err } diff --git a/services/stepfunctions/asl/result_writer.go b/services/stepfunctions/asl/result_writer.go index f2f101f8d6..06b51ab3d3 100644 --- a/services/stepfunctions/asl/result_writer.go +++ b/services/stepfunctions/asl/result_writer.go @@ -3,11 +3,12 @@ package asl import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -172,7 +173,7 @@ func (e *Executor) exportMapResults( DestinationBucket: bucket, MapRunArn: mapRunARN, ResultFiles: files, - }) + }, jsonx.V1()) if err != nil { return nil, 0, fmt.Errorf("ResultWriter: marshal manifest: %w", err) } @@ -267,7 +268,7 @@ func buildMapItemRecord( } func stringifyJSON(v any) string { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return aslNullLiteral } @@ -358,7 +359,7 @@ func encodeJSONLines(entries []any) ([]byte, error) { buf.WriteByte('\n') } - b, err := json.Marshal(e) + b, err := json.Marshal(e, jsonx.V1()) if err != nil { return nil, fmt.Errorf("marshal JSONL entry: %w", err) } @@ -501,7 +502,7 @@ func (e *Executor) writeMapResultFile( if outputType == outputTypeJSONL { data, err = encodeJSONLines(entries) } else { - data, err = json.Marshal(entries) + data, err = json.Marshal(entries, jsonx.V1()) } if err != nil { diff --git a/services/stepfunctions/asl/sdk_integration.go b/services/stepfunctions/asl/sdk_integration.go index 0f912a5203..8d2aeee2d9 100644 --- a/services/stepfunctions/asl/sdk_integration.go +++ b/services/stepfunctions/asl/sdk_integration.go @@ -3,9 +3,12 @@ package asl import ( "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -150,7 +153,7 @@ func (e *Executor) invokeLambdaOptimized(ctx context.Context, input any) (any, e var payload []byte if raw, ok := params["Payload"]; ok { - b, err := json.Marshal(raw) + b, err := json.Marshal(raw, jsonx.V1()) if err != nil { return nil, &FailError{ErrCode: errCodeStatesRuntime, Cause: err.Error()} } @@ -176,7 +179,7 @@ func (e *Executor) invokeLambdaOptimized(ctx context.Context, input any) (any, e if len(bytes.TrimSpace(resp)) > 0 { var parsed any - if json.Unmarshal(resp, &parsed) != nil { + if json.Unmarshal(resp, &parsed, jsonx.V1()) != nil { parsed = string(resp) } @@ -222,11 +225,11 @@ func lambdaFunctionError(resp []byte) error { } var probe struct { - ErrorMessage *json.RawMessage `json:"errorMessage"` - ErrorType *string `json:"errorType"` + ErrorMessage *jsontext.Value `json:"errorMessage"` + ErrorType *string `json:"errorType"` } - if json.Unmarshal(trimmed, &probe) == nil && (probe.ErrorMessage != nil || probe.ErrorType != nil) { + if json.Unmarshal(trimmed, &probe, jsonx.V1()) == nil && (probe.ErrorMessage != nil || probe.ErrorType != nil) { code := lambdaErrUnknown if probe.ErrorType != nil && *probe.ErrorType != "" { code = *probe.ErrorType diff --git a/services/stepfunctions/asl/variables.go b/services/stepfunctions/asl/variables.go index 28a52f7c4c..e8769890a9 100644 --- a/services/stepfunctions/asl/variables.go +++ b/services/stepfunctions/asl/variables.go @@ -1,12 +1,14 @@ package asl import ( - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" "strings" "unicode" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // maxVariableNameLen is the AWS limit ("Variable name syntax"). @@ -75,7 +77,7 @@ func (e *Executor) setVars(vals map[string]any) error { assignTotal := 0 for name, v := range vals { - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return dataLimitError("variable %q cannot be serialized: %v", name, err) } diff --git a/services/stepfunctions/distributed_map.go b/services/stepfunctions/distributed_map.go index 59ef3a566a..4480a4a310 100644 --- a/services/stepfunctions/distributed_map.go +++ b/services/stepfunctions/distributed_map.go @@ -2,10 +2,11 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -89,7 +90,7 @@ func marshalDistributedMapInput(item any) string { return "{}" } - b, err := json.Marshal(item) + b, err := json.Marshal(item, jsonx.V1()) if err != nil { return "{}" } diff --git a/services/stepfunctions/eks_integration.go b/services/stepfunctions/eks_integration.go index c860f18033..47f846a676 100644 --- a/services/stepfunctions/eks_integration.go +++ b/services/stepfunctions/eks_integration.go @@ -6,7 +6,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -18,6 +18,7 @@ import ( v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/smithy-go" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -105,7 +106,7 @@ func invokeModelOutput(out any) any { } var parsed any - if json.Unmarshal(raw, &parsed) != nil { + if json.Unmarshal(raw, &parsed, jsonx.V1()) != nil { parsed = string(raw) } @@ -183,7 +184,7 @@ func (s eksCallSpec) request(ctx context.Context, token string) (*http.Request, var body io.Reader if s.body != nil { - b, err := json.Marshal(s.body) + b, err := json.Marshal(s.body, jsonx.V1()) if err != nil { return nil, runtimeFailure("invalid RequestBody: %v", err) } @@ -279,7 +280,7 @@ func doEKSCall(client *http.Client, req *http.Request) (any, error) { } var parsed any - if json.Unmarshal(data, &parsed) != nil { + if json.Unmarshal(data, &parsed, jsonx.V1()) != nil { parsed = string(data) } @@ -287,7 +288,7 @@ func doEKSCall(client *http.Client, req *http.Request) (any, error) { return map[string]any{"ResponseBody": parsed}, nil } - cause, _ := json.Marshal(parsed) + cause, _ := json.Marshal(parsed, jsonx.V1()) return nil, &asl.FailError{ErrCode: errCodeTaskFailed, Cause: string(cause)} } diff --git a/services/stepfunctions/error_path_sweep_test.go b/services/stepfunctions/error_path_sweep_test.go index d1b1f3e5b2..0d888256c3 100644 --- a/services/stepfunctions/error_path_sweep_test.go +++ b/services/stepfunctions/error_path_sweep_test.go @@ -1,7 +1,7 @@ package stepfunctions_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -267,13 +268,13 @@ func Test_TagResource_TooManyTags_WireType(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": tagList, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(t.Context(), t, h, e, "TagResource", string(body)) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TooManyTags", resp["__type"]) } @@ -313,7 +314,7 @@ func Test_CreateStateMachineAlias_ErrorCodes(t *testing.T) { ) var pubResp map[string]any - require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &pubResp)) + require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &pubResp, jsonx.V1())) versionARN, _ := pubResp["stateMachineVersionArn"].(string) require.NotEmpty(t, versionARN) @@ -338,7 +339,7 @@ func Test_CreateStateMachineAlias_ErrorCodes(t *testing.T) { rec := sfnPost(t.Context(), t, h, e, "CreateStateMachineAlias", tc.body(h, e)) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tc.wantType, resp["__type"]) }) } diff --git a/services/stepfunctions/execution_history.go b/services/stepfunctions/execution_history.go index 99959dc8a8..88d576d4e9 100644 --- a/services/stepfunctions/execution_history.go +++ b/services/stepfunctions/execution_history.go @@ -1,11 +1,12 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/v2" "fmt" "sort" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -307,7 +308,7 @@ func historyValueToJSON(v any) string { return "" } - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) if err != nil { return "" } diff --git a/services/stepfunctions/execution_history_test.go b/services/stepfunctions/execution_history_test.go index c910f7c59e..3d493da6e6 100644 --- a/services/stepfunctions/execution_history_test.go +++ b/services/stepfunctions/execution_history_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -252,7 +253,7 @@ func TestHandler_GetExecutionHistory(t *testing.T) { if tt.wantEvents > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["events"].([]any), tt.wantEvents) } }) diff --git a/services/stepfunctions/executions.go b/services/stepfunctions/executions.go index 941d98ee38..4f6fdb4878 100644 --- a/services/stepfunctions/executions.go +++ b/services/stepfunctions/executions.go @@ -2,7 +2,8 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "slices" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/apptrace" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -272,7 +274,7 @@ func finalizeSyncExecutionResult( return syncResult } - outputBytes, _ := json.Marshal(result.Output) + outputBytes, _ := json.Marshal(result.Output, jsonx.V1()) syncResult.Status = statusSucceeded syncResult.Output = string(outputBytes) @@ -674,7 +676,7 @@ func (b *InMemoryBackend) finalizeExecutionRecordLocked( return } - outputBytes, _ := json.Marshal(result.Output) + outputBytes, _ := json.Marshal(result.Output, jsonx.V1()) exec.Status = statusSucceeded exec.Output = string(outputBytes) exec.OutputDetails = &CloudWatchEventsExecutionDataDetails{Included: true} @@ -1142,7 +1144,7 @@ func validateExecutionInput(input string) error { return fmt.Errorf("%w: input exceeds %d bytes", ErrInvalidExecutionInput, maxExecutionInputBytes) } - if input != "" && !json.Valid([]byte(input)) { + if input != "" && !jsontext.Value([]byte(input)).IsValid(jsonx.V1()) { return fmt.Errorf("%w: input is not valid JSON", ErrInvalidExecutionInput) } diff --git a/services/stepfunctions/handler.go b/services/stepfunctions/handler.go index 46a6e6b03b..22a28165d8 100644 --- a/services/stepfunctions/handler.go +++ b/services/stepfunctions/handler.go @@ -2,7 +2,7 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -194,7 +195,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var data map[string]any - if uerr := json.Unmarshal(body, &data); uerr != nil { + if uerr := json.Unmarshal(body, &data, jsonx.V1()); uerr != nil { return "" } @@ -249,14 +250,14 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) case "CreateStateMachine": resp, err := h.createStateMachineAction(ctx, body) if err != nil { return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) case "ListStateMachines": return h.listStateMachinesAction(ctx, body) case "CreateActivity": @@ -265,14 +266,14 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) case "ListActivities": resp, err := h.handleListActivities(ctx, body) if err != nil { return nil, err } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } fn, ok := h.dispatchTable()[action] @@ -285,7 +286,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(response) + return json.Marshal(response, jsonx.V1()) } // handleError writes a standardized JSON error response. @@ -311,7 +312,7 @@ func (h *Handler) handleError( Message: errorMessage(reqErr), } - payload, _ := json.Marshal(errResp) + payload, _ := json.Marshal(errResp, jsonx.V1()) return c.JSONBlob(statusCode, payload) } @@ -458,7 +459,7 @@ const actionStartExecution = "StartExecution" func (h *Handler) listStateMachinesAction(ctx context.Context, body []byte) ([]byte, error) { var input listStateMachinesInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } @@ -472,5 +473,5 @@ func (h *Handler) listStateMachinesAction(ctx context.Context, body []byte) ([]b items[i] = newStateMachineListItem(&sms[i]) } - return json.Marshal(&listStateMachinesOutput{StateMachines: items, NextToken: next}) + return json.Marshal(&listStateMachinesOutput{StateMachines: items, NextToken: next}, jsonx.V1()) } diff --git a/services/stepfunctions/handler_activities.go b/services/stepfunctions/handler_activities.go index cf92f3419b..427f10cfa1 100644 --- a/services/stepfunctions/handler_activities.go +++ b/services/stepfunctions/handler_activities.go @@ -2,7 +2,9 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createActivityInput struct { @@ -100,7 +102,7 @@ func (h *Handler) activityActions() map[string]actionFn { func (h *Handler) handleCreateActivity(ctx context.Context, b []byte) (any, error) { var input createActivityInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -131,7 +133,7 @@ func (h *Handler) handleCreateActivity(ctx context.Context, b []byte) (any, erro func (h *Handler) handleDeleteActivity(b []byte) (any, error) { var input deleteActivityInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -154,7 +156,7 @@ func (h *Handler) handleDeleteActivity(b []byte) (any, error) { func (h *Handler) handleDescribeActivity(b []byte) (any, error) { var input describeActivityInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -163,7 +165,7 @@ func (h *Handler) handleDescribeActivity(b []byte) (any, error) { func (h *Handler) handleListActivities(ctx context.Context, b []byte) (any, error) { var input listActivitiesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -182,7 +184,7 @@ func (h *Handler) handleListActivities(ctx context.Context, b []byte) (any, erro func (h *Handler) handleSendTaskSuccess(b []byte) (any, error) { var input sendTaskSuccessInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -195,7 +197,7 @@ func (h *Handler) handleSendTaskSuccess(b []byte) (any, error) { func (h *Handler) handleSendTaskFailure(b []byte) (any, error) { var input sendTaskFailureInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -208,7 +210,7 @@ func (h *Handler) handleSendTaskFailure(b []byte) (any, error) { func (h *Handler) handleSendTaskHeartbeat(b []byte) (any, error) { var input sendTaskHeartbeatInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -222,7 +224,7 @@ func (h *Handler) handleSendTaskHeartbeat(b []byte) (any, error) { // handleGetActivityTask handles GetActivityTask with context support for long-polling. func (h *Handler) handleGetActivityTask(ctx context.Context, body []byte) ([]byte, error) { var input getActivityTaskInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } @@ -232,11 +234,11 @@ func (h *Handler) handleGetActivityTask(ctx context.Context, body []byte) ([]byt } if task == nil { - return json.Marshal(&getActivityTaskOutput{}) + return json.Marshal(&getActivityTaskOutput{}, jsonx.V1()) } return json.Marshal(&getActivityTaskOutput{ TaskToken: task.TaskToken, Input: task.Input, - }) + }, jsonx.V1()) } diff --git a/services/stepfunctions/handler_activities_test.go b/services/stepfunctions/handler_activities_test.go index 167ce463b6..ea681a9e5e 100644 --- a/services/stepfunctions/handler_activities_test.go +++ b/services/stepfunctions/handler_activities_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -104,7 +105,7 @@ func TestHandler_ActivityOperations(t *testing.T) { rec := sfnPost(ctx, t, h, e, "CreateActivity", `{"name":"setup-act-`+tt.name+`"}`) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) actARN = resp["activityArn"].(string) } case "CreateActivity": @@ -162,7 +163,7 @@ func TestHandler_CreateAndListActivities(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) activities, ok := resp["activities"].([]any) require.True(t, ok) @@ -249,7 +250,7 @@ func TestHandler_SendTaskSuccess_WithRealToken(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var actResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &actResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &actResp, jsonx.V1())) actARN := actResp["activityArn"].(string) // Enqueue a task by calling InvokeActivity from the backend. @@ -276,7 +277,7 @@ func TestHandler_SendTaskSuccess_WithRealToken(t *testing.T) { body, _ := json.Marshal(map[string]string{ "taskToken": task.TaskToken, "output": tt.output, - }) + }, jsonx.V1()) rec = sfnPost(ctx, t, h, e, "SendTaskSuccess", string(body)) assert.Equal(t, http.StatusOK, rec.Code) @@ -315,19 +316,19 @@ func TestHandler_GetActivityTask_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var actResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &actResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &actResp, jsonx.V1())) actARN := actResp["activityArn"].(string) // GetActivityTask with a short timeout — should return empty. pollCtx, cancel := context.WithTimeout(ctx, tt.timeout) defer cancel() - body, _ := json.Marshal(map[string]string{"activityArn": actARN, "workerName": "w1"}) + body, _ := json.Marshal(map[string]string{"activityArn": actARN, "workerName": "w1"}, jsonx.V1()) rec = sfnPost(pollCtx, t, h, e, "GetActivityTask", string(body)) assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // With no task available, taskToken should be absent or empty. token, _ := resp["taskToken"].(string) assert.Empty(t, token) @@ -402,20 +403,20 @@ func TestHandler_StartSyncExecution_HTTP(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var smResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp, jsonx.V1())) smARN := smResp["stateMachineArn"].(string) body, _ := json.Marshal(map[string]string{ "stateMachineArn": smARN, "name": "sync-exec-" + tt.name, "input": `{}`, - }) + }, jsonx.V1()) rec = sfnPost(ctx, t, h, e, "StartSyncExecution", string(body)) assert.Equal(t, tt.wantCode, rec.Code) if tt.wantStatus != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantStatus, resp["status"]) } }) @@ -466,7 +467,7 @@ func TestHandler_Reset(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["tags"]) }) } @@ -718,7 +719,7 @@ func TestActivityName_Validation(t *testing.T) { ctx := t.Context() h, e := newSFNHandler(t) - body, err := json.Marshal(map[string]string{"name": tt.actName}) + body, err := json.Marshal(map[string]string{"name": tt.actName}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateActivity", string(body)) @@ -1429,23 +1430,23 @@ func TestCreateActivity_EncryptionConfiguration(t *testing.T) { "kmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/test-key", "kmsDataKeyReusePeriodSeconds": 300, }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateActivity", string(body)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) actARN, _ := createResp["activityArn"].(string) require.NotEmpty(t, actARN) - descBody, _ := json.Marshal(map[string]string{"activityArn": actARN}) + descBody, _ := json.Marshal(map[string]string{"activityArn": actARN}, jsonx.V1()) descRec := sfnPost(ctx, t, h, e, "DescribeActivity", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) encCfg, ok := descResp["encryptionConfiguration"].(map[string]any) require.True(t, ok, "expected encryptionConfiguration echoed back on DescribeActivity") assert.Equal(t, "CUSTOMER_MANAGED_KMS_KEY", encCfg["type"]) @@ -1465,23 +1466,23 @@ func TestCreateActivity_InlineTags(t *testing.T) { "tags": []map[string]string{ {"key": "env", "value": "prod"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateActivity", string(body)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) actARN, _ := createResp["activityArn"].(string) require.NotEmpty(t, actARN) - tagsBody, _ := json.Marshal(map[string]string{"resourceArn": actARN}) + tagsBody, _ := json.Marshal(map[string]string{"resourceArn": actARN}, jsonx.V1()) tagsRec := sfnPost(ctx, t, h, e, "ListTagsForResource", string(tagsBody)) require.Equal(t, http.StatusOK, tagsRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tagList, _ := tagsResp["tags"].([]any) require.Len(t, tagList, 1) @@ -1499,32 +1500,32 @@ func TestDeleteActivity_ClearsTags(t *testing.T) { ctx := t.Context() h, e := newSFNHandler(t) - createBody, _ := json.Marshal(map[string]any{"name": "del-tagged-activity"}) + createBody, _ := json.Marshal(map[string]any{"name": "del-tagged-activity"}, jsonx.V1()) rec := sfnPost(ctx, t, h, e, "CreateActivity", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) actARN, _ := createResp["activityArn"].(string) require.NotEmpty(t, actARN) tagBody, _ := json.Marshal(map[string]any{ "resourceArn": actARN, "tags": []map[string]string{{"key": "k", "value": "v"}}, - }) + }, jsonx.V1()) tagRec := sfnPost(ctx, t, h, e, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, tagRec.Code) - delBody, _ := json.Marshal(map[string]string{"activityArn": actARN}) + delBody, _ := json.Marshal(map[string]string{"activityArn": actARN}, jsonx.V1()) delRec := sfnPost(ctx, t, h, e, "DeleteActivity", string(delBody)) require.Equal(t, http.StatusOK, delRec.Code) - tagsBody, _ := json.Marshal(map[string]string{"resourceArn": actARN}) + tagsBody, _ := json.Marshal(map[string]string{"resourceArn": actARN}, jsonx.V1()) tagsRec := sfnPost(ctx, t, h, e, "ListTagsForResource", string(tagsBody)) require.Equal(t, http.StatusOK, tagsRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(tagsRec.Body.Bytes(), &tagsResp, jsonx.V1())) tagList, _ := tagsResp["tags"].([]any) assert.Empty(t, tagList, "tags must be cleared after DeleteActivity") } diff --git a/services/stepfunctions/handler_aliases.go b/services/stepfunctions/handler_aliases.go index 084fee5320..85cbeb3dce 100644 --- a/services/stepfunctions/handler_aliases.go +++ b/services/stepfunctions/handler_aliases.go @@ -1,7 +1,9 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // createStateMachineAliasInput has no StateMachineArn member: the real @@ -95,7 +97,7 @@ func (h *Handler) aliasActions() map[string]actionFn { func (h *Handler) handleCreateStateMachineAlias(b []byte) (any, error) { var input createStateMachineAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -111,7 +113,7 @@ func (h *Handler) handleCreateStateMachineAlias(b []byte) (any, error) { func (h *Handler) handleUpdateStateMachineAlias(b []byte) (any, error) { var input updateStateMachineAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -127,7 +129,7 @@ func (h *Handler) handleUpdateStateMachineAlias(b []byte) (any, error) { func (h *Handler) handleDeleteStateMachineAlias(b []byte) (any, error) { var input deleteStateMachineAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -140,7 +142,7 @@ func (h *Handler) handleDeleteStateMachineAlias(b []byte) (any, error) { func (h *Handler) handleDescribeStateMachineAlias(b []byte) (any, error) { var input describeStateMachineAliasInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -154,7 +156,7 @@ func (h *Handler) handleDescribeStateMachineAlias(b []byte) (any, error) { func (h *Handler) handleListStateMachineAliases(b []byte) (any, error) { var input listStateMachineAliasesInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/stepfunctions/handler_executions.go b/services/stepfunctions/handler_executions.go index 3b94fbd13f..f764031652 100644 --- a/services/stepfunctions/handler_executions.go +++ b/services/stepfunctions/handler_executions.go @@ -2,8 +2,10 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type startExecutionInput struct { @@ -150,7 +152,7 @@ func (h *Handler) executionActions() map[string]actionFn { func (h *Handler) handleRedriveExecution(b []byte) (any, error) { var input redriveExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -164,7 +166,7 @@ func (h *Handler) handleRedriveExecution(b []byte) (any, error) { func (h *Handler) handleDescribeStateMachineForExecution(b []byte) (any, error) { var input describeStateMachineForExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -189,7 +191,7 @@ func (h *Handler) handleStartExecution(b []byte) (any, error) { func (h *Handler) handleStartExecutionCtx(ctx context.Context, b []byte) (any, error) { var input startExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -209,7 +211,7 @@ func (h *Handler) handleStartExecutionCtx(ctx context.Context, b []byte) (any, e func (h *Handler) handleStartSyncExecution(b []byte) (any, error) { var input startSyncExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -218,7 +220,7 @@ func (h *Handler) handleStartSyncExecution(b []byte) (any, error) { func (h *Handler) handleStopExecution(b []byte) (any, error) { var input stopExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -236,7 +238,7 @@ func (h *Handler) handleStopExecution(b []byte) (any, error) { func (h *Handler) handleDescribeExecution(b []byte) (any, error) { var input describeExecutionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -264,7 +266,7 @@ func validateRedriveFilter(filter string, hasMapRun bool) error { func (h *Handler) handleListExecutions(b []byte) (any, error) { var input listExecutionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -313,7 +315,7 @@ func (h *Handler) handleListExecutions(b []byte) (any, error) { func (h *Handler) handleGetExecutionHistory(b []byte) (any, error) { var input getExecutionHistoryInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/stepfunctions/handler_executions_test.go b/services/stepfunctions/handler_executions_test.go index c5b46a5248..2a204579d3 100644 --- a/services/stepfunctions/handler_executions_test.go +++ b/services/stepfunctions/handler_executions_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -42,7 +43,7 @@ func TestHandler_StartExecution(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["executionArn"].(string), "exec1") }, }, @@ -239,7 +240,7 @@ func TestHandler_ListExecutions(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["executions"].([]any), tt.wantCount) }) } @@ -292,7 +293,7 @@ func TestExecutionName_Validation(t *testing.T) { "stateMachineArn": smARN, "name": tt.execName, "input": "{}", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "StartExecution", string(body)) @@ -312,14 +313,14 @@ func TestStartExecution_ResponseContainsARNAndStartDate(t *testing.T) { "stateMachineArn": smArn, "name": "start-resp-exec", "input": "{}", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "StartExecution", string(body)) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["executionArn"]) assert.Greater(t, out["startDate"].(float64), float64(0)) @@ -339,7 +340,7 @@ func TestListExecutions_OrderedByStartDateDesc_ViaHandler(t *testing.T) { "stateMachineArn": smARN, "name": name, "input": "{}", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "StartExecution", string(body)) @@ -347,14 +348,14 @@ func TestListExecutions_OrderedByStartDateDesc_ViaHandler(t *testing.T) { time.Sleep(5 * time.Millisecond) } - listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}) + listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "ListExecutions", string(listBody)) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rawExecs, _ := resp["executions"].([]any) require.Len(t, rawExecs, 3) @@ -381,7 +382,7 @@ func TestSFN_DescribeStateMachineForExecution(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) execARN, _ := resp["executionArn"].(string) require.NotEmpty(t, execARN) diff --git a/services/stepfunctions/handler_map_runs.go b/services/stepfunctions/handler_map_runs.go index 9c023f4061..1e3934901d 100644 --- a/services/stepfunctions/handler_map_runs.go +++ b/services/stepfunctions/handler_map_runs.go @@ -1,7 +1,9 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type describeMapRunInput struct { @@ -53,7 +55,7 @@ func (h *Handler) mapRunActions() map[string]actionFn { return map[string]actionFn{ "DescribeMapRun": func(b []byte) (any, error) { var input describeMapRunInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -61,7 +63,7 @@ func (h *Handler) mapRunActions() map[string]actionFn { }, "ListMapRuns": func(b []byte) (any, error) { var input listMapRunsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -86,7 +88,7 @@ func (h *Handler) mapRunActions() map[string]actionFn { }, "UpdateMapRun": func(b []byte) (any, error) { var input updateMapRunInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/stepfunctions/handler_state_machine_versions.go b/services/stepfunctions/handler_state_machine_versions.go index 0a7e613ed2..e3b7a5c48a 100644 --- a/services/stepfunctions/handler_state_machine_versions.go +++ b/services/stepfunctions/handler_state_machine_versions.go @@ -1,7 +1,9 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/v2" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type publishStateMachineVersionInput struct { @@ -47,7 +49,7 @@ func (h *Handler) versionActions() map[string]actionFn { return map[string]actionFn{ "PublishStateMachineVersion": func(b []byte) (any, error) { var input publishStateMachineVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -59,7 +61,7 @@ func (h *Handler) versionActions() map[string]actionFn { }, "DeleteStateMachineVersion": func(b []byte) (any, error) { var input deleteStateMachineVersionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteStateMachineVersion(input.StateMachineVersionArn); err != nil { @@ -70,7 +72,7 @@ func (h *Handler) versionActions() map[string]actionFn { }, "ListStateMachineVersions": func(b []byte) (any, error) { var input listStateMachineVersionsInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/stepfunctions/handler_state_machines.go b/services/stepfunctions/handler_state_machines.go index 2de5167950..0846429d8f 100644 --- a/services/stepfunctions/handler_state_machines.go +++ b/services/stepfunctions/handler_state_machines.go @@ -2,9 +2,11 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "maps" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type createStateMachineInput struct { @@ -89,7 +91,7 @@ type updateStateMachineOutput struct { // configuration and inline tags when supplied in the request body. func (h *Handler) createStateMachineAction(ctx context.Context, b []byte) (any, error) { var input createStateMachineInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -153,7 +155,7 @@ func (h *Handler) createStateMachineAction(ctx context.Context, b []byte) (any, // configuration when supplied in the request body. func (h *Handler) updateStateMachineAction(b []byte) (any, error) { var input updateStateMachineInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -211,7 +213,7 @@ func (h *Handler) stateMachineActions() map[string]actionFn { // CreateStateMachine and ListStateMachines are handled in dispatch (ctx-aware). "DeleteStateMachine": func(b []byte) (any, error) { var input deleteStateMachineInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } if err := h.Backend.DeleteStateMachine(input.StateMachineArn); err != nil { @@ -230,7 +232,7 @@ func (h *Handler) stateMachineActions() map[string]actionFn { }, "DescribeStateMachine": func(b []byte) (any, error) { var input describeStateMachineInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } diff --git a/services/stepfunctions/handler_state_machines_test.go b/services/stepfunctions/handler_state_machines_test.go index 59b132e987..961c742a0c 100644 --- a/services/stepfunctions/handler_state_machines_test.go +++ b/services/stepfunctions/handler_state_machines_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -33,7 +34,7 @@ func TestHandler_CreateStateMachine(t *testing.T) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["stateMachineArn"].(string), "test-sm") }, }, @@ -149,7 +150,7 @@ func TestHandler_StartExecution_StateMachineDeleting(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) smArn, ok := createResp["stateMachineArn"].(string) require.True(t, ok) @@ -165,7 +166,7 @@ func TestHandler_StartExecution_StateMachineDeleting(t *testing.T) { require.Equal(t, http.StatusOK, runningRec.Code) var runningDesc map[string]any - require.NoError(t, json.Unmarshal(runningRec.Body.Bytes(), &runningDesc)) + require.NoError(t, json.Unmarshal(runningRec.Body.Bytes(), &runningDesc, jsonx.V1())) require.Equal(t, "RUNNING", runningDesc["status"]) delRec := sfnPost(ctx, t, h, e, "DeleteStateMachine", `{"stateMachineArn":"`+smArn+`"}`) @@ -175,7 +176,7 @@ func TestHandler_StartExecution_StateMachineDeleting(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code, "DELETING state machine must still be describable") var desc map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1())) assert.Equal(t, "DELETING", desc["status"]) startRec := sfnPost(ctx, t, h, e, "StartExecution", @@ -183,7 +184,7 @@ func TestHandler_StartExecution_StateMachineDeleting(t *testing.T) { assert.Equal(t, http.StatusConflict, startRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "StateMachineDeleting", errResp["__type"]) } @@ -219,7 +220,7 @@ func TestHandler_ListStateMachines(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Len(t, resp["stateMachines"].([]any), tt.wantCount) }) } @@ -245,7 +246,7 @@ func TestHandler_DescribeStateMachine(t *testing.T) { makeSMBody("desc-sm", validPassDef, "EXPRESS")) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["stateMachineArn"].(string) }, @@ -255,7 +256,7 @@ func TestHandler_DescribeStateMachine(t *testing.T) { t.Helper() var sm map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sm)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &sm, jsonx.V1())) assert.Equal(t, "EXPRESS", sm["type"]) }, }, @@ -344,7 +345,7 @@ func TestStateMachineName_Validation(t *testing.T) { "name": tt.smName, "definition": sfnPassDefinition, "roleArn": "arn:aws:iam::123456789012:role/role", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) @@ -352,7 +353,7 @@ func TestStateMachineName_Validation(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidName", resp["__type"]) } }) @@ -405,24 +406,24 @@ func TestCreateStateMachine_InlineTags(t *testing.T) { reqBody["tags"] = tt.tags } - body, err := json.Marshal(reqBody) + body, err := json.Marshal(reqBody, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) smARN, _ := createResp["stateMachineArn"].(string) require.NotEmpty(t, smARN) // Verify tags were applied. - listBody, _ := json.Marshal(map[string]string{"resourceArn": smARN}) + listBody, _ := json.Marshal(map[string]string{"resourceArn": smARN}, jsonx.V1()) listRec := sfnPost(ctx, t, h, e, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var tagsResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsResp, jsonx.V1())) rawTags, _ := tagsResp["tags"].([]any) got := make(map[string]string, len(rawTags)) @@ -485,24 +486,24 @@ func TestCreateStateMachine_EncryptionConfiguration(t *testing.T) { reqBody["encryptionConfiguration"] = tt.encCfg } - body, err := json.Marshal(reqBody) + body, err := json.Marshal(reqBody, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) smARN, _ := createResp["stateMachineArn"].(string) require.NotEmpty(t, smARN) // Describe to verify encryption config is stored. - descBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}) + descBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) descRec := sfnPost(ctx, t, h, e, "DescribeStateMachine", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) if tt.wantType == "" { // No encryption config present in response or nil. @@ -531,19 +532,19 @@ func TestUpdateStateMachine_EncryptionConfiguration(t *testing.T) { "type": "CUSTOMER_MANAGED_KMS_KEY", "kmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/my-key", }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(body)) assert.Equal(t, http.StatusOK, rec.Code) // Verify via describe. - descBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}) + descBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) descRec := sfnPost(ctx, t, h, e, "DescribeStateMachine", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) enc, ok := descResp["encryptionConfiguration"].(map[string]any) require.True(t, ok) assert.Equal(t, "CUSTOMER_MANAGED_KMS_KEY", enc["type"]) @@ -583,14 +584,14 @@ func TestCreateStateMachine_WithPublish(t *testing.T) { "definition": sfnPassDefinition, "roleArn": "arn:aws:iam::123456789012:role/role", "publish": tt.publish, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) smARN, _ := createResp["stateMachineArn"].(string) require.NotEmpty(t, smARN) @@ -606,12 +607,12 @@ func TestCreateStateMachine_WithPublish(t *testing.T) { } // Check versions. - versBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}) + versBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) versRec := sfnPost(ctx, t, h, e, "ListStateMachineVersions", string(versBody)) require.Equal(t, http.StatusOK, versRec.Code) var versResp map[string]any - require.NoError(t, json.Unmarshal(versRec.Body.Bytes(), &versResp)) + require.NoError(t, json.Unmarshal(versRec.Body.Bytes(), &versResp, jsonx.V1())) versions, _ := versResp["stateMachineVersions"].([]any) if tt.wantVersion { @@ -636,23 +637,23 @@ func TestUpdateStateMachine_WithPublish(t *testing.T) { "stateMachineArn": smARN, "definition": newDef, "publish": true, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["revisionId"], "expected a non-empty revisionId after update") assert.NotEmpty(t, updateResp["stateMachineVersionArn"], "expected stateMachineVersionArn when publish=true") - versBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}) + versBody, _ := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) versRec := sfnPost(ctx, t, h, e, "ListStateMachineVersions", string(versBody)) require.Equal(t, http.StatusOK, versRec.Code) var versResp map[string]any - require.NoError(t, json.Unmarshal(versRec.Body.Bytes(), &versResp)) + require.NoError(t, json.Unmarshal(versRec.Body.Bytes(), &versResp, jsonx.V1())) versions, _ := versResp["stateMachineVersions"].([]any) assert.Len(t, versions, 1, "expected one version after update with publish=true") } @@ -671,14 +672,14 @@ func TestUpdateStateMachine_NoPublish_NoVersionArn(t *testing.T) { body, err := json.Marshal(map[string]any{ "stateMachineArn": smARN, "definition": newDef, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["revisionId"]) _, hasVersionArn := updateResp["stateMachineVersionArn"] assert.False(t, hasVersionArn, "expected no stateMachineVersionArn when publish=false") @@ -699,7 +700,7 @@ func TestUpdateStateMachine_VersionDescriptionRequiresPublish(t *testing.T) { "definition": `{"StartAt":"S","States":{"S":{"Type":"Succeed"}}}`, "versionDescription": "should be rejected", "publish": false, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(body)) @@ -747,7 +748,7 @@ func TestCreateStateMachine_ResponseContainsARNAndDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.NotEmpty(t, out["stateMachineArn"]) assert.Greater(t, out["creationDate"].(float64), float64(0)) @@ -765,18 +766,18 @@ func TestCreateStateMachine_Idempotent_ViaHandler(t *testing.T) { "name": "idem-handler-sm", "definition": sfnPassDefinition, "roleArn": "arn:aws:iam::123456789012:role/role", - }) + }, jsonx.V1()) require.NoError(t, err) rec1 := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) rec2 := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, resp1["stateMachineArn"], resp2["stateMachineArn"]) } @@ -831,7 +832,7 @@ func TestCreateStateMachineRequiresRoleArn(t *testing.T) { h, e := newSFNHandler(t) ctx := context.Background() - body, err := json.Marshal(tt.body) + body, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) @@ -840,7 +841,7 @@ func TestCreateStateMachineRequiresRoleArn(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"], "error type for case %q", tt.name) } @@ -880,7 +881,7 @@ func TestCreateStateMachine_NameValidation(t *testing.T) { "name": tt.smName, "definition": validPassDef, "roleArn": "arn:aws:iam::123456789012:role/role", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) @@ -888,7 +889,7 @@ func TestCreateStateMachine_NameValidation(t *testing.T) { if tt.wantType != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) @@ -930,14 +931,14 @@ func TestUpdateStateMachine_ArnValidation(t *testing.T) { body, err := json.Marshal(map[string]any{ "stateMachineArn": tt.arn, "definition": validPassDef, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(body)) assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) }) } @@ -1025,14 +1026,14 @@ func TestHandler_UpdateStateMachine(t *testing.T) { body, err = json.Marshal(map[string]any{ "stateMachineArn": smARN, "roleArn": "arn:aws:iam::123456789012:role/new-role", - }) + }, jsonx.V1()) require.NoError(t, err) } else { var err error body, err = json.Marshal(map[string]any{ "stateMachineArn": smARN, "definition": sfnPassDefinition, - }) + }, jsonx.V1()) require.NoError(t, err) } @@ -1040,7 +1041,7 @@ func TestHandler_UpdateStateMachine(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "updateDate") }) } diff --git a/services/stepfunctions/handler_tags.go b/services/stepfunctions/handler_tags.go index 0efef17690..0b9d36c2e9 100644 --- a/services/stepfunctions/handler_tags.go +++ b/services/stepfunctions/handler_tags.go @@ -1,8 +1,10 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type sfnListTagsForResourceInput struct { @@ -82,7 +84,7 @@ func (h *Handler) stateMachineTagActions() map[string]actionFn { return map[string]actionFn{ "ListTagsForResource": func(b []byte) (any, error) { var input sfnListTagsForResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -96,7 +98,7 @@ func (h *Handler) stateMachineTagActions() map[string]actionFn { }, "TagResource": func(b []byte) (any, error) { var input sfnTagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -116,7 +118,7 @@ func (h *Handler) stateMachineTagActions() map[string]actionFn { }, "UntagResource": func(b []byte) (any, error) { var input sfnUntagResourceInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } h.removeTags(input.ResourceArn, input.TagKeys) diff --git a/services/stepfunctions/handler_test.go b/services/stepfunctions/handler_test.go index 07817e1896..e8ca9fa534 100644 --- a/services/stepfunctions/handler_test.go +++ b/services/stepfunctions/handler_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -67,7 +68,7 @@ func makeSMBody(name, def, smType string) string { input["type"] = smType } - b, err := json.Marshal(input) + b, err := json.Marshal(input, jsonx.V1()) if err != nil { panic(err) } @@ -83,7 +84,7 @@ func createSM(ctx context.Context, t *testing.T, h *stepfunctions.Handler, e *ec require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["stateMachineArn"].(string) } @@ -102,7 +103,7 @@ func startExec( require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["executionArn"].(string) } @@ -148,7 +149,7 @@ func TestHandler_Routing(t *testing.T) { t.Helper() var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.Contains(t, ops, "CreateStateMachine") }, }, @@ -252,14 +253,14 @@ func TestHandler_Shutdown_CancelsRunningExecutions(t *testing.T) { var smResp struct { StateMachineArn string `json:"stateMachineArn"` } - require.NoError(t, json.Unmarshal(smRec.Body.Bytes(), &smResp)) + require.NoError(t, json.Unmarshal(smRec.Body.Bytes(), &smResp, jsonx.V1())) // Start an execution. execBody, err := json.Marshal(map[string]string{ "stateMachineArn": smResp.StateMachineArn, "name": "exec-1", "input": "{}", - }) + }, jsonx.V1()) require.NoError(t, err) execRec := sfnPost(ctx, t, h, e, "StartExecution", string(execBody)) @@ -268,7 +269,7 @@ func TestHandler_Shutdown_CancelsRunningExecutions(t *testing.T) { var execResp struct { ExecutionArn string `json:"executionArn"` } - require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp)) + require.NoError(t, json.Unmarshal(execRec.Body.Bytes(), &execResp, jsonx.V1())) // Shutdown should cancel the long-running Wait execution and return promptly. h.Shutdown(t.Context()) @@ -276,7 +277,10 @@ func TestHandler_Shutdown_CancelsRunningExecutions(t *testing.T) { // After Shutdown, the cancelled execution goroutine should eventually // transition the execution out of RUNNING (to FAILED due to cancellation). require.Eventuallyf(t, func() bool { - descBody, marshalErr := json.Marshal(map[string]string{"executionArn": execResp.ExecutionArn}) + descBody, marshalErr := json.Marshal( + map[string]string{"executionArn": execResp.ExecutionArn}, + jsonx.V1(), + ) if marshalErr != nil { return false } @@ -290,7 +294,8 @@ func TestHandler_Shutdown_CancelsRunningExecutions(t *testing.T) { Status string `json:"status"` } - return json.Unmarshal(descRec.Body.Bytes(), &descResp) == nil && descResp.Status != "RUNNING" + return json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1()) == nil && + descResp.Status != "RUNNING" }, 5*time.Second, 50*time.Millisecond, "[%s] execution should leave RUNNING state after Shutdown", tt.name) }) @@ -331,7 +336,7 @@ func TestClassifyError_InvalidExecutionInput(t *testing.T) { body, err := json.Marshal(map[string]string{ "stateMachineArn": smARN, "input": tt.input, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "StartExecution", string(body)) @@ -339,7 +344,7 @@ func TestClassifyError_InvalidExecutionInput(t *testing.T) { if tt.wantErr { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidExecutionInput", resp["__type"]) } else { assert.Equal(t, http.StatusOK, rec.Code) @@ -384,7 +389,7 @@ func TestClassifyError_InvalidArn(t *testing.T) { "name": "arn-check-sm-" + tt.name, "definition": sfnPassDefinition, "roleArn": tt.roleArn, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(body)) @@ -392,7 +397,7 @@ func TestClassifyError_InvalidArn(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidArn", resp["__type"]) } }) @@ -438,7 +443,7 @@ func TestHTTP_StateMachineAlreadyExists_Returns409(t *testing.T) { assert.Equal(t, http.StatusConflict, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "StateMachineAlreadyExists", out["__type"]) } @@ -453,7 +458,7 @@ func TestHTTP_InvalidDefinition_Returns400(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "InvalidDefinition", out["__type"]) } diff --git a/services/stepfunctions/handler_tracing_logging_test.go b/services/stepfunctions/handler_tracing_logging_test.go index d95559eacc..b4e4328c26 100644 --- a/services/stepfunctions/handler_tracing_logging_test.go +++ b/services/stepfunctions/handler_tracing_logging_test.go @@ -1,12 +1,14 @@ package stepfunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateStateMachine_PropagatesTracingAndLogging(t *testing.T) { @@ -30,7 +32,7 @@ func TestHandler_CreateStateMachine_PropagatesTracingAndLogging(t *testing.T) { }, } - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) ctx := t.Context() @@ -40,19 +42,19 @@ func TestHandler_CreateStateMachine_PropagatesTracingAndLogging(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) arnStr, _ := createOut["stateMachineArn"].(string) require.NotEmpty(t, arnStr) - descBody, err := json.Marshal(map[string]any{"stateMachineArn": arnStr}) + descBody, err := json.Marshal(map[string]any{"stateMachineArn": arnStr}, jsonx.V1()) require.NoError(t, err) descRec := sfnPost(ctx, t, h, e, "DescribeStateMachine", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) tracing, _ := descOut["tracingConfiguration"].(map[string]any) require.NotNil(t, tracing) @@ -74,19 +76,19 @@ func TestHandler_UpdateStateMachine_PropagatesTracing(t *testing.T) { updBody, err := json.Marshal(map[string]any{ "stateMachineArn": arn, "tracingConfiguration": map[string]any{"enabled": true}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(updBody)) require.Equal(t, http.StatusOK, rec.Code) - descBody, _ := json.Marshal(map[string]any{"stateMachineArn": arn}) + descBody, _ := json.Marshal(map[string]any{"stateMachineArn": arn}, jsonx.V1()) descRec := sfnPost(ctx, t, h, e, "DescribeStateMachine", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) tracing, _ := descOut["tracingConfiguration"].(map[string]any) require.NotNil(t, tracing) diff --git a/services/stepfunctions/handler_util.go b/services/stepfunctions/handler_util.go index 54705da4f1..143eb89ff3 100644 --- a/services/stepfunctions/handler_util.go +++ b/services/stepfunctions/handler_util.go @@ -1,10 +1,12 @@ package stepfunctions import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/ptrconv" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -39,7 +41,7 @@ func (h *Handler) utilActions() map[string]actionFn { return map[string]actionFn{ "ValidateStateMachineDefinition": func(b []byte) (any, error) { var input validateStateMachineDefinitionInput - if err := json.Unmarshal(b, &input); err != nil { + if err := json.Unmarshal(b, &input, jsonx.V1()); err != nil { return nil, err } @@ -132,11 +134,11 @@ func testStateMockRun(m *testStateMock, stateName string) (*asl.MockRun, error) var step map[string]any if m.Result != nil { - if !json.Valid([]byte(*m.Result)) { + if !jsontext.Value([]byte(*m.Result)).IsValid(jsonx.V1()) { return nil, fmt.Errorf("%w: mock result is not valid JSON", ErrValidation) } - step = map[string]any{"Return": json.RawMessage(*m.Result)} + step = map[string]any{"Return": jsontext.Value(*m.Result)} } else { if m.ErrorOutput.Error == nil || *m.ErrorOutput.Error == "" { return nil, fmt.Errorf("%w: mock errorOutput.error is required", ErrValidation) @@ -152,7 +154,7 @@ func testStateMockRun(m *testStateMock, stateName string) (*asl.MockRun, error) "StateMachines": map[string]any{ "s": map[string]any{"TestCases": map[string]any{"t": map[string]string{stateName: "m"}}}, }, - }) + }, jsonx.V1()) if err != nil { return nil, err } @@ -194,7 +196,7 @@ func inspectionDataFor(level string, executor *asl.Executor, trace *httpTrace) m } for key, value := range executor.Inspection() { - if raw, err := json.Marshal(value); err == nil { + if raw, err := json.Marshal(value, jsonx.V1()); err == nil { out[key] = string(raw) } } @@ -208,23 +210,23 @@ func validInspectionLevel(level string) bool { // detachNext swaps Next for End:true so TestState can run a non-terminal // state without a synthetic next state, returning the new definition and Next. -func detachNext(definition, stateName string, raw json.RawMessage) (string, string) { +func detachNext(definition, stateName string, raw jsontext.Value) (string, string) { var ( next string - rawState map[string]json.RawMessage + rawState map[string]jsontext.Value ) - if json.Unmarshal(raw, &rawState) != nil { + if json.Unmarshal(raw, &rawState, jsonx.V1()) != nil { return definition, next } if nextRaw, hasNext := rawState["Next"]; hasNext { - _ = json.Unmarshal(nextRaw, &next) + _ = json.Unmarshal(nextRaw, &next, jsonx.V1()) delete(rawState, "Next") - rawState["End"] = json.RawMessage(`true`) + rawState["End"] = jsontext.Value(`true`) } - if modified, err := json.Marshal(map[string]any{stateName: rawState}); err == nil { + if modified, err := json.Marshal(map[string]any{stateName: rawState}, jsonx.V1()); err == nil { definition = string(modified) } @@ -234,7 +236,7 @@ func detachNext(definition, stateName string, raw json.RawMessage) (string, stri // handleTestState executes a single state definition in isolation and returns its output. func (h *Handler) handleTestState(body []byte) (any, error) { var input testStateInput - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, err } @@ -243,13 +245,13 @@ func (h *Handler) handleTestState(body []byte) (any, error) { } // Wrap the state definition in a minimal state machine. - var states map[string]json.RawMessage - if err := json.Unmarshal([]byte(input.Definition), &states); err != nil { + var states map[string]jsontext.Value + if err := json.Unmarshal([]byte(input.Definition), &states, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid state definition JSON: %w", ErrInvalidDefinition, err) } if _, bare := states["Type"]; bare { - states = map[string]json.RawMessage{bareStateName: json.RawMessage(input.Definition)} + states = map[string]jsontext.Value{bareStateName: jsontext.Value(input.Definition)} input.Definition = fmt.Sprintf(`{%q:%s}`, bareStateName, input.Definition) } @@ -326,7 +328,7 @@ func testStateResult( } } - outputBytes, _ := json.Marshal(result.Output) + outputBytes, _ := json.Marshal(result.Output, jsonx.V1()) out := &testStateOutput{ Status: "SUCCEEDED", Output: string(outputBytes), NextState: nextState, InspectionData: inspection, @@ -342,7 +344,7 @@ func testStateResult( // configureTestStateExecutor applies the request's mock, context and // stateConfiguration to executor, rejecting combinations AWS rejects. func configureTestStateExecutor( - executor *asl.Executor, input *testStateInput, stateName string, rawState json.RawMessage, + executor *asl.Executor, input *testStateInput, stateName string, rawState jsontext.Value, ) error { if input.Context != nil && input.Mock == nil { return fmt.Errorf("%w: context may only be specified together with a mock", ErrValidation) @@ -350,7 +352,7 @@ func configureTestStateExecutor( if input.Context != nil { var ctxObj map[string]any - if err := json.Unmarshal([]byte(*input.Context), &ctxObj); err != nil { + if err := json.Unmarshal([]byte(*input.Context), &ctxObj, jsonx.V1()); err != nil { return fmt.Errorf("%w: context must be a JSON object", ErrValidation) } @@ -369,7 +371,7 @@ func configureTestStateExecutor( Type string `json:"Type"` } - _ = json.Unmarshal(rawState, &typed) + _ = json.Unmarshal(rawState, &typed, jsonx.V1()) if typed.Type != stateTypeTask && typed.Type != stateTypeMap && typed.Type != stateTypeParallel { return fmt.Errorf("%w: mock is supported for Task, Map and Parallel states only", ErrValidation) @@ -386,20 +388,20 @@ func configureTestStateExecutor( } // isHTTPTaskState reports whether raw is a Task state calling http:invoke. -func isHTTPTaskState(raw json.RawMessage) bool { +func isHTTPTaskState(raw jsontext.Value) bool { var st struct { Type string `json:"Type"` Resource string `json:"Resource"` } - _ = json.Unmarshal(raw, &st) + _ = json.Unmarshal(raw, &st, jsonx.V1()) return st.Type == stateTypeTask && strings.HasSuffix(st.Resource, ":::http:invoke") } // validateTestStateTrace rejects the TRACE and revealSecrets combinations AWS // rejects (test-state-isolation.html, "TRACE inspectionLevel"). -func validateTestStateTrace(input *testStateInput, raw json.RawMessage) error { +func validateTestStateTrace(input *testStateInput, raw jsontext.Value) error { if input.InspectionLevel == inspectionTrace && !isHTTPTaskState(raw) { return fmt.Errorf("%w: inspectionLevel TRACE is only applicable to an HTTP Task state", ErrValidation) } diff --git a/services/stepfunctions/handler_util_test.go b/services/stepfunctions/handler_util_test.go index 2b918337dc..464c6726f5 100644 --- a/services/stepfunctions/handler_util_test.go +++ b/services/stepfunctions/handler_util_test.go @@ -2,12 +2,14 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ValidateStateMachineDefinition(t *testing.T) { @@ -55,14 +57,14 @@ func TestHandler_ValidateStateMachineDefinition(t *testing.T) { ctx := t.Context() h, e := newSFNHandler(t) - reqBody, err := json.Marshal(map[string]string{"definition": tt.definition}) + reqBody, err := json.Marshal(map[string]string{"definition": tt.definition}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "ValidateStateMachineDefinition", string(reqBody)) assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantResult, resp["result"]) diag, ok := resp["diagnostics"].([]any) @@ -83,7 +85,7 @@ func TestValidateStateMachineDefinition_Valid(t *testing.T) { ctx := t.Context() h, e := newSFNHandler(t) - body, err := json.Marshal(map[string]any{"definition": validPassDef}) + body, err := json.Marshal(map[string]any{"definition": validPassDef}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "ValidateStateMachineDefinition", string(body)) @@ -96,7 +98,7 @@ func TestValidateStateMachineDefinition_Invalid(t *testing.T) { ctx := t.Context() h, e := newSFNHandler(t) - body, err := json.Marshal(map[string]any{"definition": `{"not":"valid-asl"}`}) + body, err := json.Marshal(map[string]any{"definition": `{"not":"valid-asl"}`}, jsonx.V1()) require.NoError(t, err) // AWS returns 200 with Result:"FAIL" and diagnostics — not a 4xx. @@ -104,7 +106,7 @@ func TestValidateStateMachineDefinition_Invalid(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "FAIL", out["result"]) } @@ -168,7 +170,7 @@ func TestTestState_NextState(t *testing.T) { body, err := json.Marshal(map[string]any{ "definition": tt.definition, "input": tt.input, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TestState", string(body)) @@ -179,7 +181,7 @@ func TestTestState_NextState(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantStatus, resp["status"]) @@ -223,14 +225,14 @@ func TestValidateStateMachineDefinition(t *testing.T) { t.Parallel() h, e := newSFNHandler(t) - body, err := json.Marshal(map[string]string{"definition": tt.def}) + body, err := json.Marshal(map[string]string{"definition": tt.def}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(t.Context(), t, h, e, "ValidateStateMachineDefinition", string(body)) assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantResult, resp["result"]) }) } diff --git a/services/stepfunctions/http_task.go b/services/stepfunctions/http_task.go index f0c6f6e920..4124487f94 100644 --- a/services/stepfunctions/http_task.go +++ b/services/stepfunctions/http_task.go @@ -3,7 +3,7 @@ package stepfunctions import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -19,6 +19,7 @@ import ( "unicode/utf8" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -374,7 +375,7 @@ func mergeHTTPBody(spec httpSpec, connBody []NameValue) ([]byte, error) { } } - out, err := json.Marshal(body) + out, err := json.Marshal(body, jsonx.V1()) if err != nil { return nil, runtimeFailure("RequestBody is not serializable") } @@ -455,7 +456,7 @@ func fetchOAuthToken(ctx context.Context, client *http.Client, o *OAuthCredentia AccessToken string `json:"access_token"` } - if json.Unmarshal(data, &tok) != nil || tok.AccessToken == "" { + if json.Unmarshal(data, &tok, jsonx.V1()) != nil || tok.AccessToken == "" { return "", errOAuthToken } @@ -510,7 +511,7 @@ func doHTTP(client *http.Client, req *http.Request, trace *httpTrace) (any, erro return out, nil } - cause, _ := json.Marshal(out) + cause, _ := json.Marshal(out, jsonx.V1()) return nil, &asl.FailError{ErrCode: httpStatusPrefix + strconv.Itoa(resp.StatusCode), Cause: string(cause)} } @@ -559,7 +560,7 @@ func httpOutput(resp *http.Response, data []byte) map[string]any { media, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type")) if media == "application/json" || strings.HasSuffix(media, "+json") { var parsed any - if json.Unmarshal(data, &parsed) == nil { + if json.Unmarshal(data, &parsed, jsonx.V1()) == nil { body = parsed } } diff --git a/services/stepfunctions/http_trace.go b/services/stepfunctions/http_trace.go index 93c05ee1de..1255f3d32f 100644 --- a/services/stepfunctions/http_trace.go +++ b/services/stepfunctions/http_trace.go @@ -3,11 +3,13 @@ package stepfunctions import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "strconv" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const traceMask = "***" @@ -79,7 +81,7 @@ func (t *httpTrace) headers(h http.Header, dropAuth string) string { flat[k] = t.scrub(strings.Join(vs, ",")) } - raw, _ := json.Marshal(flat) + raw, _ := json.Marshal(flat, jsonx.V1()) return string(raw) } diff --git a/services/stepfunctions/integrations.go b/services/stepfunctions/integrations.go index 4f03132ff2..a8f5ce9534 100644 --- a/services/stepfunctions/integrations.go +++ b/services/stepfunctions/integrations.go @@ -3,7 +3,7 @@ package stepfunctions import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" @@ -12,6 +12,7 @@ import ( awss3 "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" dynamodbpkg "github.com/blackbirdworks/gopherstack/services/dynamodb" ecsbackend "github.com/blackbirdworks/gopherstack/services/ecs" gluebackend "github.com/blackbirdworks/gopherstack/services/glue" @@ -182,12 +183,12 @@ func (a *s3ResultWriterAdapter) PutObjectBytes(ctx context.Context, bucket, key // convertViaJSON converts a value to a target type by marshaling to JSON and back. func convertViaJSON(input, target any) error { - b, err := json.Marshal(input) + b, err := json.Marshal(input, jsonx.V1()) if err != nil { return err } - return json.Unmarshal(b, target) + return json.Unmarshal(b, target, jsonx.V1()) } // outputToAny converts a typed SDK output struct to an untyped map via JSON round-trip. diff --git a/services/stepfunctions/item_reader_parquet_test.go b/services/stepfunctions/item_reader_parquet_test.go index 5ff112abad..cae59ca1e0 100644 --- a/services/stepfunctions/item_reader_parquet_test.go +++ b/services/stepfunctions/item_reader_parquet_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" @@ -10,6 +10,7 @@ import ( sfntypes "github.com/aws/aws-sdk-go-v2/service/sfn/types" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/parquetio" ) @@ -159,7 +160,7 @@ func TestItemReader_ParquetFlattenAndAthena(t *testing.T) { require.Equal(t, sfntypes.ExecutionStatusSucceeded, status, "error=%s cause=%s", errCode, cause) var items []map[string]any - require.NoError(t, json.Unmarshal([]byte(output), &items)) + require.NoError(t, json.Unmarshal([]byte(output), &items, jsonx.V1())) assert.Len(t, items, 6) }) } diff --git a/services/stepfunctions/item_reader_s3_resource_test.go b/services/stepfunctions/item_reader_s3_resource_test.go index 4051b5a7ce..1740e7a729 100644 --- a/services/stepfunctions/item_reader_s3_resource_test.go +++ b/services/stepfunctions/item_reader_s3_resource_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "context" - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" s3pkg "github.com/blackbirdworks/gopherstack/services/s3" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -126,7 +127,7 @@ func TestItemReader_S3ListObjectsV2(t *testing.T) { require.Equal(t, sfntypes.ExecutionStatusSucceeded, status, "error=%s cause=%s", errCode, cause) var items []map[string]any - require.NoError(t, json.Unmarshal([]byte(output), &items)) + require.NoError(t, json.Unmarshal([]byte(output), &items, jsonx.V1())) require.Len(t, items, 2) assert.Equal(t, "data/a.txt", items[0]["Key"]) @@ -217,7 +218,7 @@ func TestItemReader_S3Manifest(t *testing.T) { "files": []map[string]any{{"key": dataKey, "size": len(inventoryCSV)}}, } - b, err := json.Marshal(manifest) + b, err := json.Marshal(manifest, jsonx.V1()) require.NoError(t, err) return string(b) @@ -242,7 +243,7 @@ func TestItemReader_S3Manifest(t *testing.T) { require.Equal(t, sfntypes.ExecutionStatusSucceeded, status, "error=%s cause=%s", errCode, cause) var items []map[string]any - require.NoError(t, json.Unmarshal([]byte(output), &items)) + require.NoError(t, json.Unmarshal([]byte(output), &items, jsonx.V1())) require.Len(t, items, 2) assert.Equal(t, map[string]any{ "Bucket": "src-bucket", "Key": "csvDataset/titles.csv", @@ -269,7 +270,7 @@ func TestItemReader_S3Manifest(t *testing.T) { require.Equal(t, sfntypes.ExecutionStatusSucceeded, status, "error=%s cause=%s", errCode, cause) var items []map[string]any - require.NoError(t, json.Unmarshal([]byte(output), &items)) + require.NoError(t, json.Unmarshal([]byte(output), &items, jsonx.V1())) require.Len(t, items, 2) assert.Equal(t, "imageDataset/pic.jpg", items[1]["Key"]) }) @@ -295,7 +296,7 @@ func TestItemReader_S3Manifest(t *testing.T) { require.Equal(t, sfntypes.ExecutionStatusSucceeded, status, "error=%s cause=%s", errCode, cause) var items []map[string]any - require.NoError(t, json.Unmarshal([]byte(output), &items)) + require.NoError(t, json.Unmarshal([]byte(output), &items, jsonx.V1())) require.Len(t, items, 1) assert.Equal(t, "csvDataset/titles.csv", items[0]["Key"]) }) diff --git a/services/stepfunctions/jsonata_distributed_map_test.go b/services/stepfunctions/jsonata_distributed_map_test.go index d403b25215..1c2c159b07 100644 --- a/services/stepfunctions/jsonata_distributed_map_test.go +++ b/services/stepfunctions/jsonata_distributed_map_test.go @@ -2,13 +2,14 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -260,7 +261,7 @@ func runS3ArgumentsCase(t *testing.T, reader, writer, input, wantOutput string, } var out mapExportOutput - require.NoError(t, json.Unmarshal([]byte(d.Output), &out)) + require.NoError(t, json.Unmarshal([]byte(d.Output), &out, jsonx.V1())) assert.Equal(t, "data-bucket", out.ResultWriterDetails.Bucket) assert.NotEmpty(t, getS3ObjectBytes(t, s3Bk, "data-bucket", out.ResultWriterDetails.Key)) } diff --git a/services/stepfunctions/list_executions_golden_test.go b/services/stepfunctions/list_executions_golden_test.go index 95c63e645a..697ce63e67 100644 --- a/services/stepfunctions/list_executions_golden_test.go +++ b/services/stepfunctions/list_executions_golden_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "os" @@ -15,6 +15,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -99,7 +100,7 @@ func TestListExecutions_PageGolden(t *testing.T) { var resp struct { NextToken string `json:"nextToken"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if resp.NextToken == "" { break diff --git a/services/stepfunctions/map_runs_test.go b/services/stepfunctions/map_runs_test.go index 2612f72f0c..a18a4c5b8a 100644 --- a/services/stepfunctions/map_runs_test.go +++ b/services/stepfunctions/map_runs_test.go @@ -2,13 +2,14 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -43,14 +44,14 @@ func TestListMapRuns_ReturnsEmptyList(t *testing.T) { smARN := createSM(ctx, t, h, e, "no-maprun-sm") execARN := startExec(ctx, t, h, e, smARN, "no-maprun-exec") - listBody, err := json.Marshal(map[string]any{"executionArn": execARN}) + listBody, err := json.Marshal(map[string]any{"executionArn": execARN}, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "ListMapRuns", string(listBody)) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) mapRuns, _ := out["mapRuns"].([]any) assert.Empty(t, mapRuns) @@ -118,24 +119,24 @@ func TestMapRunStorage(t *testing.T) { "definition": mapIterStateDef, "roleArn": "arn:aws:iam::123456789012:role/test", "type": "EXPRESS", - }) + }, jsonx.V1()) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var smResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp, jsonx.V1())) smARN := smResp["stateMachineArn"].(string) syncBody, _ := json.Marshal(map[string]any{ "stateMachineArn": smARN, "name": "sync-exec-1", "input": `[1,2,3]`, - }) + }, jsonx.V1()) syncRec := sfnPost(ctx, t, h, e, "StartSyncExecution", string(syncBody)) require.Equal(t, http.StatusOK, syncRec.Code) var syncResp map[string]any - require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp)) + require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp, jsonx.V1())) execARN := syncResp["executionArn"].(string) assert.GreaterOrEqual(t, bk.MapRunCountForTest(execARN), 1, @@ -156,35 +157,35 @@ func TestMapRunStorage(t *testing.T) { "definition": mapIterStateDef, "roleArn": "arn:aws:iam::123456789012:role/test", "type": "EXPRESS", - }) + }, jsonx.V1()) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var smResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp, jsonx.V1())) smARN := smResp["stateMachineArn"].(string) syncBody, _ := json.Marshal(map[string]any{ "stateMachineArn": smARN, "name": "sync-exec-2", "input": `[1,2]`, - }) + }, jsonx.V1()) syncRec := sfnPost(ctx, t, h, e, "StartSyncExecution", string(syncBody)) require.Equal(t, http.StatusOK, syncRec.Code) var syncResp map[string]any - require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp)) + require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp, jsonx.V1())) execARN := syncResp["executionArn"].(string) require.GreaterOrEqual(t, bk.MapRunCountForTest(execARN), 1) // ListMapRuns via handler. - listBody, _ := json.Marshal(map[string]any{"executionArn": execARN}) + listBody, _ := json.Marshal(map[string]any{"executionArn": execARN}, jsonx.V1()) listRec := sfnPost(ctx, t, h, e, "ListMapRuns", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) mapRuns, _ := listResp["mapRuns"].([]any) require.NotEmpty(t, mapRuns, "expected non-empty mapRuns list") @@ -192,12 +193,12 @@ func TestMapRunStorage(t *testing.T) { mapRunARN, _ := firstRun["mapRunArn"].(string) require.NotEmpty(t, mapRunARN) - descBody, _ := json.Marshal(map[string]any{"mapRunArn": mapRunARN}) + descBody, _ := json.Marshal(map[string]any{"mapRunArn": mapRunARN}, jsonx.V1()) descRec := sfnPost(ctx, t, h, e, "DescribeMapRun", string(descBody)) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) assert.Equal(t, mapRunARN, descResp["mapRunArn"]) assert.Equal(t, execARN, descResp["executionArn"]) assert.Equal(t, "SUCCEEDED", descResp["status"]) @@ -217,34 +218,34 @@ func TestMapRunStorage(t *testing.T) { "definition": mapIterStateDef, "roleArn": "arn:aws:iam::123456789012:role/test", "type": "EXPRESS", - }) + }, jsonx.V1()) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var smResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &smResp, jsonx.V1())) smARN := smResp["stateMachineArn"].(string) syncBody, _ := json.Marshal(map[string]any{ "stateMachineArn": smARN, "name": "sync-exec-3b", "input": `[1]`, - }) + }, jsonx.V1()) syncRec := sfnPost(ctx, t, h, e, "StartSyncExecution", string(syncBody)) require.Equal(t, http.StatusOK, syncRec.Code) var syncResp map[string]any - require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp)) + require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &syncResp, jsonx.V1())) execARN := syncResp["executionArn"].(string) require.GreaterOrEqual(t, bk.MapRunCountForTest(execARN), 1) - listBody, _ := json.Marshal(map[string]any{"executionArn": execARN}) + listBody, _ := json.Marshal(map[string]any{"executionArn": execARN}, jsonx.V1()) listRec := sfnPost(ctx, t, h, e, "ListMapRuns", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) mapRuns, _ := listResp["mapRuns"].([]any) require.NotEmpty(t, mapRuns) @@ -254,12 +255,12 @@ func TestMapRunStorage(t *testing.T) { updateBody, _ := json.Marshal(map[string]any{ "mapRunArn": mapRunARN, "maxConcurrency": 10, - }) + }, jsonx.V1()) updateRec := sfnPost(ctx, t, h, e, "UpdateMapRun", string(updateBody)) require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) maxConc, _ := updateResp["maxConcurrency"].(float64) assert.InEpsilon(t, float64(10), maxConc, 1e-9) }, diff --git a/services/stepfunctions/overwide_list_test.go b/services/stepfunctions/overwide_list_test.go index 24bb88c00c..1f17da1d5e 100644 --- a/services/stepfunctions/overwide_list_test.go +++ b/services/stepfunctions/overwide_list_test.go @@ -2,13 +2,16 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestOverWideListResponses asserts on the raw response body that every @@ -55,14 +58,14 @@ func TestOverWideListResponses(t *testing.T) { "tracingConfiguration": map[string]any{"enabled": true}, "loggingConfiguration": map[string]any{"level": "ALL"}, "encryptionConfiguration": map[string]any{"type": "AWS_OWNED_KEY"}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) smARN, _ := created["stateMachineArn"].(string) require.NotEmpty(t, smARN) @@ -71,7 +74,7 @@ func TestOverWideListResponses(t *testing.T) { "stateMachineArn": smARN, "definition": validPassDef, "roleArn": "arn:aws:iam::123456789012:role/test", - }) + }, jsonx.V1()) require.NoError(t, err) updRec := sfnPost(ctx, t, h, e, "UpdateStateMachine", string(updateBody)) @@ -100,7 +103,7 @@ func TestOverWideListResponses(t *testing.T) { "type": "CUSTOMER_MANAGED_KMS_KEY", "kmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/test-key", }, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateActivity", string(createBody)) @@ -128,18 +131,18 @@ func TestOverWideListResponses(t *testing.T) { "stateMachineArn": smARN, "name": "wide-exec", "input": `{"secret":"do-not-leak"}`, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "StartExecution", string(execBody)) require.Equal(t, http.StatusOK, rec.Code) var started map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &started, jsonx.V1())) execARN, _ := started["executionArn"].(string) require.NotEmpty(t, execARN) - descBody, err := json.Marshal(map[string]string{"executionArn": execARN}) + descBody, err := json.Marshal(map[string]string{"executionArn": execARN}, jsonx.V1()) require.NoError(t, err) require.Eventuallyf(t, func() bool { @@ -149,14 +152,14 @@ func TestOverWideListResponses(t *testing.T) { } var desc map[string]any - if unmarshalErr := json.Unmarshal(descRec.Body.Bytes(), &desc); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(descRec.Body.Bytes(), &desc, jsonx.V1()); unmarshalErr != nil { return false } return desc["status"] != "RUNNING" }, 5*time.Second, 20*time.Millisecond, "execution should finish") - listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}) + listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListExecutions", string(listBody)) @@ -187,14 +190,14 @@ func TestOverWideListResponses(t *testing.T) { "definition": mapIterStateDef, "roleArn": "arn:aws:iam::123456789012:role/test", "type": "EXPRESS", - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, rec.Code) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) smARN, _ := created["stateMachineArn"].(string) require.NotEmpty(t, smARN) @@ -202,25 +205,25 @@ func TestOverWideListResponses(t *testing.T) { "stateMachineArn": smARN, "name": "wide-maprun-exec", "input": `[1,2,3]`, - }) + }, jsonx.V1()) require.NoError(t, err) syncRec := sfnPost(ctx, t, h, e, "StartSyncExecution", string(syncBody)) require.Equal(t, http.StatusOK, syncRec.Code) var synced map[string]any - require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &synced)) + require.NoError(t, json.Unmarshal(syncRec.Body.Bytes(), &synced, jsonx.V1())) execARN, _ := synced["executionArn"].(string) require.NotEmpty(t, execARN) - listBody, err := json.Marshal(map[string]any{"executionArn": execARN}) + listBody, err := json.Marshal(map[string]any{"executionArn": execARN}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListMapRuns", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var listed map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listed)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listed, jsonx.V1())) runs, _ := listed["mapRuns"].([]any) require.NotEmpty(t, runs, "expected at least one MapRun") first, _ := runs[0].(map[string]any) @@ -234,7 +237,7 @@ func TestOverWideListResponses(t *testing.T) { "maxConcurrency": 5, "toleratedFailureCount": 1, "toleratedFailurePercentage": 10.0, - }) + }, jsonx.V1()) require.NoError(t, err) updRec := sfnPost(ctx, t, h, e, "UpdateMapRun", string(updateBody)) @@ -261,14 +264,14 @@ func TestOverWideListResponses(t *testing.T) { h, e := newSFNHandler(t) smARN := createSM(ctx, t, h, e, "wide-alias-sm") - pubBody, err := json.Marshal(map[string]any{"stateMachineArn": smARN}) + pubBody, err := json.Marshal(map[string]any{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) pubRec := sfnPost(ctx, t, h, e, "PublishStateMachineVersion", string(pubBody)) require.Equal(t, http.StatusOK, pubRec.Code) var published map[string]any - require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &published)) + require.NoError(t, json.Unmarshal(pubRec.Body.Bytes(), &published, jsonx.V1())) versionARN, _ := published["stateMachineVersionArn"].(string) require.NotEmpty(t, versionARN) @@ -279,14 +282,14 @@ func TestOverWideListResponses(t *testing.T) { "routingConfiguration": []map[string]any{ {"stateMachineVersionArn": versionARN, "weight": 100}, }, - }) + }, jsonx.V1()) require.NoError(t, err) aliasRec := sfnPost(ctx, t, h, e, "CreateStateMachineAlias", string(createBody)) require.Equal(t, http.StatusOK, aliasRec.Code) var alias map[string]any - require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &alias)) + require.NoError(t, json.Unmarshal(aliasRec.Body.Bytes(), &alias, jsonx.V1())) aliasARN, _ := alias["stateMachineAliasArn"].(string) require.NotEmpty(t, aliasARN) @@ -294,13 +297,13 @@ func TestOverWideListResponses(t *testing.T) { updateBody, err := json.Marshal(map[string]any{ "stateMachineAliasArn": aliasARN, "description": "updated", - }) + }, jsonx.V1()) require.NoError(t, err) updRec := sfnPost(ctx, t, h, e, "UpdateStateMachineAlias", string(updateBody)) require.Equal(t, http.StatusOK, updRec.Code) - listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}) + listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListStateMachineAliases", string(listBody)) @@ -331,13 +334,13 @@ func TestOverWideListResponses(t *testing.T) { "stateMachineArn": smARN, "description": "leaks if present", "revisionId": "leaks-if-present", - }) + }, jsonx.V1()) require.NoError(t, err) pubRec := sfnPost(ctx, t, h, e, "PublishStateMachineVersion", string(pubBody)) require.Equal(t, http.StatusOK, pubRec.Code) - listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}) + listBody, err := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListStateMachineVersions", string(listBody)) @@ -354,14 +357,14 @@ func TestOverWideListResponses(t *testing.T) { body := tt.raw(t) - var resp map[string]json.RawMessage - require.NoError(t, json.Unmarshal(body, &resp)) + var resp map[string]jsontext.Value + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) itemsRaw, ok := resp[tt.itemsKey] require.True(t, ok, "response missing %q key", tt.itemsKey) - var items []map[string]json.RawMessage - require.NoError(t, json.Unmarshal(itemsRaw, &items)) + var items []map[string]jsontext.Value + require.NoError(t, json.Unmarshal(itemsRaw, &items, jsonx.V1())) require.NotEmpty(t, items, "expected at least one item in %q", tt.itemsKey) for _, item := range items { diff --git a/services/stepfunctions/persistence.go b/services/stepfunctions/persistence.go index b678eed6a4..8522628345 100644 --- a/services/stepfunctions/persistence.go +++ b/services/stepfunctions/persistence.go @@ -2,9 +2,11 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" "github.com/blackbirdworks/gopherstack/pkgs/store" @@ -93,17 +95,17 @@ func (b *InMemoryBackend) newPersistedDTORegistry() ( // guards against decoding a snapshot from an incompatible (older or newer) // build of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // handlerSnapshot wraps the backend snapshot together with handler-level state // (tags) so both are persisted and restored together. type handlerSnapshot struct { Tags map[string]map[string]string `json:"tags,omitempty"` - Backend json.RawMessage `json:"backend"` + Backend jsontext.Value `json:"backend"` } // Snapshot serialises the backend state to JSON. @@ -329,7 +331,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { Snapshot(ctx context.Context) []byte } - var backendBytes json.RawMessage + var backendBytes jsontext.Value if s, ok := h.Backend.(snapshotter); ok { backendBytes = s.Snapshot(ctx) } @@ -346,7 +348,7 @@ func (h *Handler) Snapshot(ctx context.Context) []byte { Tags: tagsData, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { return backendBytes } diff --git a/services/stepfunctions/result_writer_test.go b/services/stepfunctions/result_writer_test.go index 900a5d0f21..2a0cb654f5 100644 --- a/services/stepfunctions/result_writer_test.go +++ b/services/stepfunctions/result_writer_test.go @@ -2,7 +2,8 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "log/slog" "strings" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" s3pkg "github.com/blackbirdworks/gopherstack/services/s3" "github.com/blackbirdworks/gopherstack/services/stepfunctions" @@ -198,7 +200,7 @@ func TestDistributedMapResultWriter(t *testing.T) { require.Equal(t, "SUCCEEDED", d.Status, "cause=%s error=%s", d.Cause, d.Error) var out mapExportOutput - require.NoError(t, json.Unmarshal([]byte(d.Output), &out)) + require.NoError(t, json.Unmarshal([]byte(d.Output), &out, jsonx.V1())) assert.Equal(t, bucket, out.ResultWriterDetails.Bucket) assert.True(t, strings.HasPrefix(out.ResultWriterDetails.Key, "jobs/")) assert.True(t, strings.HasSuffix(out.ResultWriterDetails.Key, "manifest.json")) @@ -207,7 +209,7 @@ func TestDistributedMapResultWriter(t *testing.T) { manifestBytes := getS3ObjectBytes(t, s3Bk, bucket, out.ResultWriterDetails.Key) var manifest resultManifest - require.NoError(t, json.Unmarshal(manifestBytes, &manifest)) + require.NoError(t, json.Unmarshal(manifestBytes, &manifest, jsonx.V1())) assert.Equal(t, bucket, manifest.DestinationBucket) assert.Equal(t, out.MapRunArn, manifest.MapRunArn) require.Len(t, manifest.ResultFiles.Succeeded, 1) @@ -219,7 +221,7 @@ func TestDistributedMapResultWriter(t *testing.T) { succeededBytes := getS3ObjectBytes(t, s3Bk, bucket, manifest.ResultFiles.Succeeded[0].Key) var records []map[string]any - require.NoError(t, json.Unmarshal(succeededBytes, &records)) + require.NoError(t, json.Unmarshal(succeededBytes, &records, jsonx.V1())) require.Len(t, records, 3) assert.Equal(t, "SUCCEEDED", records[0]["Status"]) // Default Transformation (NONE, since ResultWriter exports without a @@ -255,7 +257,7 @@ func TestDistributedMapResultWriter(t *testing.T) { require.Equal(t, "SUCCEEDED", d.Status, "cause=%s error=%s", d.Cause, d.Error) var arr []float64 - require.NoError(t, json.Unmarshal([]byte(d.Output), &arr)) + require.NoError(t, json.Unmarshal([]byte(d.Output), &arr, jsonx.V1())) assert.Equal(t, []float64{1, 2, 3}, arr) runs, _, err := b.ListMapRuns(exec.ExecutionArn, "", 0) @@ -292,7 +294,7 @@ func TestDistributedMapResultWriter(t *testing.T) { // NONE, same as the writes-to-S3 case -- the missing S3 writer only // changes whether the formatted result is exported, not its shape. var records []map[string]any - require.NoError(t, json.Unmarshal([]byte(d.Output), &records)) + require.NoError(t, json.Unmarshal([]byte(d.Output), &records, jsonx.V1())) require.Len(t, records, 3) assert.Equal(t, "SUCCEEDED", records[0]["Status"]) assert.Equal(t, "1", records[0]["Input"]) @@ -401,7 +403,7 @@ func startWriterConfigExecution( // assertTransformationEntries checks succeeded-file/preview entries against // what each Transformation must produce for three items whose child output // is always [10, 20] (AWS docs: input-output-resultwriter.html). -func assertTransformationEntries(t *testing.T, transformation string, raw []json.RawMessage) { +func assertTransformationEntries(t *testing.T, transformation string, raw []jsontext.Value) { t.Helper() switch transformation { @@ -411,7 +413,7 @@ func assertTransformationEntries(t *testing.T, transformation string, raw []json want := []float64{10, 20, 10, 20, 10, 20} for i, r := range raw { var v float64 - require.NoError(t, json.Unmarshal(r, &v)) + require.NoError(t, json.Unmarshal(r, &v, jsonx.V1())) assert.InDelta(t, want[i], v, 0) } case "COMPACT": @@ -419,7 +421,7 @@ func assertTransformationEntries(t *testing.T, transformation string, raw []json for _, r := range raw { var v []float64 - require.NoError(t, json.Unmarshal(r, &v)) + require.NoError(t, json.Unmarshal(r, &v, jsonx.V1())) assert.Equal(t, []float64{10, 20}, v) } default: // NONE @@ -427,7 +429,7 @@ func assertTransformationEntries(t *testing.T, transformation string, raw []json for _, r := range raw { var rec map[string]any - require.NoError(t, json.Unmarshal(r, &rec)) + require.NoError(t, json.Unmarshal(r, &rec, jsonx.V1())) assert.Equal(t, "SUCCEEDED", rec["Status"]) assert.Equal(t, "[10,20]", rec["Output"], "NONE stringifies Output like a real DescribeExecution") assert.Equal(t, true, rec["InputDetails"].(map[string]any)["Included"]) @@ -438,21 +440,21 @@ func assertTransformationEntries(t *testing.T, transformation string, raw []json // decodeResultEntries parses a SUCCEEDED_0.json/FAILED_0.json file's bytes // into individual JSON values, per OutputType: JSON is one array, JSONL is // one value per newline. -func decodeResultEntries(t *testing.T, data []byte, outputType string) []json.RawMessage { +func decodeResultEntries(t *testing.T, data []byte, outputType string) []jsontext.Value { t.Helper() if outputType != "JSONL" { - var arr []json.RawMessage - require.NoError(t, json.Unmarshal(data, &arr)) + var arr []jsontext.Value + require.NoError(t, json.Unmarshal(data, &arr, jsonx.V1())) return arr } lines := strings.Split(strings.TrimSpace(string(data)), "\n") - raw := make([]json.RawMessage, len(lines)) + raw := make([]jsontext.Value, len(lines)) for i, l := range lines { - raw[i] = json.RawMessage(l) + raw[i] = jsontext.Value(l) } return raw @@ -488,7 +490,7 @@ func TestDistributedMapResultWriter_TransformationOutputType(t *testing.T) { "cause=%s error=%s", aws.ToString(desc.Cause), aws.ToString(desc.Error)) var out mapExportOutput - require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out, jsonx.V1())) require.Equal(t, bucket, out.ResultWriterDetails.Bucket) assert.True(t, strings.HasPrefix(out.ResultWriterDetails.Key, "jobs/")) assert.True(t, strings.HasSuffix(out.ResultWriterDetails.Key, "manifest.json")) @@ -496,7 +498,7 @@ func TestDistributedMapResultWriter_TransformationOutputType(t *testing.T) { manifestBytes := getS3ObjectBytes(t, s3Bk, bucket, out.ResultWriterDetails.Key) var manifest resultManifest - require.NoError(t, json.Unmarshal(manifestBytes, &manifest)) + require.NoError(t, json.Unmarshal(manifestBytes, &manifest, jsonx.V1())) require.Len(t, manifest.ResultFiles.Succeeded, 1) assert.Empty(t, manifest.ResultFiles.Failed) assert.True(t, strings.HasSuffix(manifest.ResultFiles.Succeeded[0].Key, "SUCCEEDED_0.json")) @@ -566,26 +568,26 @@ func TestDistributedMapResultWriter_FailedItemsKeepFullRecord(t *testing.T) { ) var out mapExportOutput - require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out, jsonx.V1())) manifestBytes := getS3ObjectBytes(t, s3Bk, bucket, out.ResultWriterDetails.Key) var manifest resultManifest - require.NoError(t, json.Unmarshal(manifestBytes, &manifest)) + require.NoError(t, json.Unmarshal(manifestBytes, &manifest, jsonx.V1())) require.Len(t, manifest.ResultFiles.Succeeded, 1) require.Len(t, manifest.ResultFiles.Failed, 1) succeededBytes := getS3ObjectBytes(t, s3Bk, bucket, manifest.ResultFiles.Succeeded[0].Key) var succeeded [][]float64 - require.NoError(t, json.Unmarshal(succeededBytes, &succeeded)) + require.NoError(t, json.Unmarshal(succeededBytes, &succeeded, jsonx.V1())) require.Len(t, succeeded, 2, "2 of 3 items succeed") assert.Equal(t, []float64{10, 20}, succeeded[0]) failedBytes := getS3ObjectBytes(t, s3Bk, bucket, manifest.ResultFiles.Failed[0].Key) var failed []map[string]any - require.NoError(t, json.Unmarshal(failedBytes, &failed)) + require.NoError(t, json.Unmarshal(failedBytes, &failed, jsonx.V1())) require.Len(t, failed, 1) assert.Equal(t, "FAILED", failed[0]["Status"]) assert.Equal(t, "2", failed[0]["Input"]) @@ -636,18 +638,18 @@ func TestDistributedMapResultWriter_DistributedChildIdentity(t *testing.T) { "cause=%s error=%s", aws.ToString(desc.Cause), aws.ToString(desc.Error)) var out mapExportOutput - require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(desc.Output)), &out, jsonx.V1())) manifestBytes := getS3ObjectBytes(t, s3Bk, bucket, out.ResultWriterDetails.Key) var manifest resultManifest - require.NoError(t, json.Unmarshal(manifestBytes, &manifest)) + require.NoError(t, json.Unmarshal(manifestBytes, &manifest, jsonx.V1())) require.Len(t, manifest.ResultFiles.Succeeded, 1) succeededBytes := getS3ObjectBytes(t, s3Bk, bucket, manifest.ResultFiles.Succeeded[0].Key) var records []map[string]any - require.NoError(t, json.Unmarshal(succeededBytes, &records)) + require.NoError(t, json.Unmarshal(succeededBytes, &records, jsonx.V1())) require.Len(t, records, 3) seen := map[string]bool{} @@ -694,20 +696,20 @@ func TestDistributedMapResultWriter_PreviewWithoutExport(t *testing.T) { if tt.outputType == "JSONL" { var jsonl string - require.NoError(t, json.Unmarshal([]byte(output), &jsonl)) + require.NoError(t, json.Unmarshal([]byte(output), &jsonl, jsonx.V1())) lines := strings.Split(jsonl, "\n") require.Len(t, lines, 6) var v float64 - require.NoError(t, json.Unmarshal([]byte(lines[0]), &v)) + require.NoError(t, json.Unmarshal([]byte(lines[0]), &v, jsonx.V1())) assert.InDelta(t, 10, v, 0) return } var arr []float64 - require.NoError(t, json.Unmarshal([]byte(output), &arr)) + require.NoError(t, json.Unmarshal([]byte(output), &arr, jsonx.V1())) assert.Equal(t, []float64{10, 20, 10, 20, 10, 20}, arr) }) } diff --git a/services/stepfunctions/s3_item_reader_test.go b/services/stepfunctions/s3_item_reader_test.go index cb29db16d2..f4bc6d167b 100644 --- a/services/stepfunctions/s3_item_reader_test.go +++ b/services/stepfunctions/s3_item_reader_test.go @@ -2,13 +2,14 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -73,7 +74,7 @@ func TestStartExecution_MapItemReader_S3(t *testing.T) { require.Equal(t, "SUCCEEDED", described.Status, "cause=%s error=%s", described.Cause, described.Error) var output []map[string]any - require.NoError(t, json.Unmarshal([]byte(described.Output), &output)) + require.NoError(t, json.Unmarshal([]byte(described.Output), &output, jsonx.V1())) assert.Len(t, output, 3, "expected one output entry per S3-sourced item") }) } diff --git a/services/stepfunctions/sdk_convert.go b/services/stepfunctions/sdk_convert.go index 2e614db78e..7cc20736f0 100644 --- a/services/stepfunctions/sdk_convert.go +++ b/services/stepfunctions/sdk_convert.go @@ -2,7 +2,7 @@ package stepfunctions import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -10,6 +10,8 @@ import ( "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -63,7 +65,7 @@ func streamString(src any) string { return s } - b, _ := json.Marshal(src) + b, _ := json.Marshal(src, jsonx.V1()) return string(b) } diff --git a/services/stepfunctions/sdk_integration.go b/services/stepfunctions/sdk_integration.go index 377ecd46e8..f3c735160f 100644 --- a/services/stepfunctions/sdk_integration.go +++ b/services/stepfunctions/sdk_integration.go @@ -3,7 +3,7 @@ package stepfunctions import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -20,6 +20,7 @@ import ( "github.com/aws/smithy-go" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/safemap" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire" @@ -418,7 +419,7 @@ func withJSONString(m map[string]any, key string, blob bool) map[string]any { raw, isStr := val.(string) if !isStr { - b, _ := json.Marshal(val) + b, _ := json.Marshal(val, jsonx.V1()) raw = string(b) } diff --git a/services/stepfunctions/sdk_sync.go b/services/stepfunctions/sdk_sync.go index 557373c4a0..4086c1954d 100644 --- a/services/stepfunctions/sdk_sync.go +++ b/services/stepfunctions/sdk_sync.go @@ -2,10 +2,11 @@ package stepfunctions import ( "context" - "encoding/json" + "encoding/json/v2" "slices" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/asl" ) @@ -172,7 +173,7 @@ func runTaskFailures(call asl.SDKCall, out any) error { return nil } - cause, _ := json.Marshal(failures) + cause, _ := json.Marshal(failures, jsonx.V1()) return &asl.FailError{ErrCode: "AmazonECS.Unknown", Cause: string(cause)} } @@ -186,7 +187,7 @@ func executionSyncResult(p map[string]any, pattern string) any { if s, ok := p["Output"].(string); ok { var parsed any - if json.Unmarshal([]byte(s), &parsed) == nil { + if json.Unmarshal([]byte(s), &parsed, jsonx.V1()) == nil { p["Output"] = parsed } } @@ -257,7 +258,7 @@ func finishSync(req syncRequest, poll map[string]any, state string) (any, error) return result, nil } - cause, _ := json.Marshal(result) + cause, _ := json.Marshal(result, jsonx.V1()) return nil, &asl.FailError{ErrCode: errCodeTaskFailed, Cause: string(cause)} } diff --git a/services/stepfunctions/sdkwire/call_test.go b/services/stepfunctions/sdkwire/call_test.go index cb1f7326a1..fb0fa2dcbd 100644 --- a/services/stepfunctions/sdkwire/call_test.go +++ b/services/stepfunctions/sdkwire/call_test.go @@ -2,7 +2,7 @@ package sdkwire_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire" ) @@ -85,7 +86,7 @@ func TestCall_Request(t *testing.T) { require.NoError(t, err) var got map[string]any - require.NoError(t, json.Unmarshal(seen, &got)) + require.NoError(t, json.Unmarshal(seen, &got, jsonx.V1())) for k, v := range tt.wantJSON { assert.Equal(t, v, got[k], k) @@ -107,7 +108,7 @@ func TestCall_IdempotencyToken(t *testing.T) { require.NoError(t, err) var got map[string]any - require.NoError(t, json.Unmarshal(seen, &got)) + require.NoError(t, json.Unmarshal(seen, &got, jsonx.V1())) assert.NotEmpty(t, got["clientToken"]) } diff --git a/services/stepfunctions/sdkwire/legacy.go b/services/stepfunctions/sdkwire/legacy.go index caa13817fe..16457a0e69 100644 --- a/services/stepfunctions/sdkwire/legacy.go +++ b/services/stepfunctions/sdkwire/legacy.go @@ -3,7 +3,8 @@ package sdkwire import ( "compress/gzip" "embed" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" @@ -11,6 +12,7 @@ import ( "github.com/aws/smithy-go/traits" smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions/sdkwire/ir" ) @@ -36,7 +38,7 @@ func legacyService(key, signing, userAgentAPI string, protocol protocolFor) *Ser } var m ir.Model - if derr := json.NewDecoder(zr).Decode(&m); derr != nil { + if derr := json.UnmarshalDecode(jsontext.NewDecoder(zr), &m, jsonx.V1()); derr != nil { panic(fmt.Sprintf("sdkwire: model %s: %v", key, derr)) } diff --git a/services/stepfunctions/sdkwire/parity_whitebox_test.go b/services/stepfunctions/sdkwire/parity_whitebox_test.go index c437ea0dfd..e2583852d2 100644 --- a/services/stepfunctions/sdkwire/parity_whitebox_test.go +++ b/services/stepfunctions/sdkwire/parity_whitebox_test.go @@ -3,7 +3,7 @@ package sdkwire import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -25,6 +25,8 @@ import ( "github.com/aws/smithy-go/transport/http/protocol/restxml" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const testEndpoint = "http://sfn-sdk-integration.local" @@ -166,7 +168,7 @@ func decodeJSONBody(raw []byte) (any, bool) { var v any - return v, json.Unmarshal(raw, &v) == nil + return v, json.Unmarshal(raw, &v, jsonx.V1()) == nil } func bodyDiff(contentType string, want, got []byte) string { diff --git a/services/stepfunctions/sdkwire/schemair/encode.go b/services/stepfunctions/sdkwire/schemair/encode.go index 780df9a83f..7e80d25ea7 100644 --- a/services/stepfunctions/sdkwire/schemair/encode.go +++ b/services/stepfunctions/sdkwire/schemair/encode.go @@ -3,12 +3,14 @@ package schemair import ( "bytes" "compress/gzip" - "encoding/json" + "encoding/json/v2" "fmt" "reflect" "sort" "github.com/aws/smithy-go" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // OpRef is an operation's schemas as the SDK package declares them. @@ -99,7 +101,7 @@ func (e *encoder) addOp(m *Model, ref OpRef) (Op, error) { // Write gzips the model as JSON. func (m *Model) Write() ([]byte, error) { - raw, err := json.Marshal(m) + raw, err := json.Marshal(m, jsonx.V1()) if err != nil { return nil, err } @@ -198,7 +200,7 @@ func (e *encoder) traits(s *smithy.Schema, direct bool) ([]Trait, error) { continue } - raw, err := json.Marshal(t) + raw, err := json.Marshal(t, jsonx.V1()) if err != nil { return nil, err } diff --git a/services/stepfunctions/sdkwire/schemair/schemair.go b/services/stepfunctions/sdkwire/schemair/schemair.go index ba59e7b8e4..f7ee9feb89 100644 --- a/services/stepfunctions/sdkwire/schemair/schemair.go +++ b/services/stepfunctions/sdkwire/schemair/schemair.go @@ -5,7 +5,8 @@ package schemair import ( "compress/gzip" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +15,8 @@ import ( "github.com/aws/smithy-go" "github.com/aws/smithy-go/prelude" "github.com/aws/smithy-go/traits" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ErrModel marks an invalid or mismatched schema model. @@ -58,8 +61,8 @@ type Op struct { // Trait is a smithy-go trait by codec name and JSON-encoded fields. type Trait struct { - Name string `json:"n"` - Value json.RawMessage `json:"v,omitempty"` + Name string `json:"n"` + Value jsontext.Value `json:"v,omitempty"` } // Operation is a decoded operation. @@ -161,7 +164,7 @@ func Read(r io.Reader) (*Model, error) { defer zr.Close() var m Model - if derr := json.NewDecoder(zr).Decode(&m); derr != nil { + if derr := json.UnmarshalDecode(jsontext.NewDecoder(zr), &m, jsonx.V1()); derr != nil { return nil, fmt.Errorf("schemair: %w", derr) } @@ -245,7 +248,7 @@ func decodeTraits(cs map[string]codec, in []Trait) ([]smithy.Trait, error) { v := reflect.New(c.typ) if len(t.Value) > 0 { - if err := json.Unmarshal(t.Value, v.Interface()); err != nil { + if err := json.Unmarshal(t.Value, v.Interface(), jsonx.V1()); err != nil { return nil, fmt.Errorf("schemair: trait %s: %w", t.Name, err) } } diff --git a/services/stepfunctions/state_machine_versions_test.go b/services/stepfunctions/state_machine_versions_test.go index 1f2a6fbf63..bbe3da7dfe 100644 --- a/services/stepfunctions/state_machine_versions_test.go +++ b/services/stepfunctions/state_machine_versions_test.go @@ -2,7 +2,7 @@ package stepfunctions_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/stepfunctions" ) @@ -172,7 +173,7 @@ func TestHandler_ListStateMachineVersions(t *testing.T) { body := tt.body if body == "" { - b, err := json.Marshal(map[string]string{"stateMachineArn": smARN}) + b, err := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, err) body = string(b) } @@ -181,7 +182,7 @@ func TestHandler_ListStateMachineVersions(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "stateMachineVersions") }) } @@ -271,24 +272,24 @@ func TestListStateMachineVersions(t *testing.T) { "definition": validPassDef, "roleArn": "arn:aws:iam::000:role/r", "type": "STANDARD", - }) + }, jsonx.V1()) require.NoError(t, err) createRec := sfnPost(t.Context(), t, h, e, "CreateStateMachine", string(createBody)) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) smARN := createResp["stateMachineArn"].(string) - listBody, merr := json.Marshal(map[string]string{"stateMachineArn": smARN}) + listBody, merr := json.Marshal(map[string]string{"stateMachineArn": smARN}, jsonx.V1()) require.NoError(t, merr) rec := sfnPost(t.Context(), t, h, e, "ListStateMachineVersions", string(listBody)) assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["stateMachineVersions"].([]any) require.True(t, ok, "stateMachineVersions should be an array") assert.Empty(t, versions) diff --git a/services/stepfunctions/tags_test.go b/services/stepfunctions/tags_test.go index 53e082481f..a02ef80d48 100644 --- a/services/stepfunctions/tags_test.go +++ b/services/stepfunctions/tags_test.go @@ -1,13 +1,15 @@ package stepfunctions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagResource(t *testing.T) { @@ -67,7 +69,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].([]any) assert.NotEmpty(t, tags) }) @@ -112,7 +114,7 @@ func TestHandler_UntagResource(t *testing.T) { listRec := sfnPost(ctx, t, h, e, "ListTagsForResource", `{"resourceArn":"`+arn+`"}`) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].([]any) assert.Len(t, tags, tt.wantTagCount) @@ -140,24 +142,24 @@ func TestTags_CreateWithInlineTags(t *testing.T) { }, } - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "CreateStateMachine", string(raw)) require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) arnStr := out["stateMachineArn"].(string) - listBody, err := json.Marshal(map[string]any{"resourceArn": arnStr}) + listBody, err := json.Marshal(map[string]any{"resourceArn": arnStr}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var tags map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tags)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tags, jsonx.V1())) tagList, _ := tags["tags"].([]any) assert.Len(t, tagList, 2) @@ -173,21 +175,21 @@ func TestTags_TagAndUntag(t *testing.T) { tagBody, err := json.Marshal(map[string]any{ "resourceArn": arnStr, "tags": []map[string]string{{"key": "k1", "value": "v1"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(tagBody)) require.Equal(t, http.StatusOK, rec.Code) // Verify - listBody, err := json.Marshal(map[string]any{"resourceArn": arnStr}) + listBody, err := json.Marshal(map[string]any{"resourceArn": arnStr}, jsonx.V1()) require.NoError(t, err) listRec := sfnPost(ctx, t, h, e, "ListTagsForResource", string(listBody)) require.Equal(t, http.StatusOK, listRec.Code) var tagOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagOut, jsonx.V1())) tagList, _ := tagOut["tags"].([]any) assert.Len(t, tagList, 1) @@ -196,7 +198,7 @@ func TestTags_TagAndUntag(t *testing.T) { untagBody, err := json.Marshal(map[string]any{ "resourceArn": arnStr, "tagKeys": []string{"k1"}, - }) + }, jsonx.V1()) require.NoError(t, err) untagRec := sfnPost(ctx, t, h, e, "UntagResource", string(untagBody)) @@ -206,7 +208,7 @@ func TestTags_TagAndUntag(t *testing.T) { require.Equal(t, http.StatusOK, listRec2.Code) var after map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &after, jsonx.V1())) tagList2, _ := after["tags"].([]any) assert.Empty(t, tagList2) @@ -225,14 +227,14 @@ func TestTagResource_KeyTooLong_Error(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": []map[string]string{{"key": longKey, "value": "val"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TagPolicyViolation", resp["__type"]) } @@ -246,14 +248,14 @@ func TestTagResource_EmptyKey_Error(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": []map[string]string{{"key": "", "value": "val"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TagPolicyViolation", resp["__type"]) } @@ -268,14 +270,14 @@ func TestTagResource_ValueTooLong_Error(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": []map[string]string{{"key": "mykey", "value": longVal}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TagPolicyViolation", resp["__type"]) } @@ -297,7 +299,7 @@ func TestTagResource_MaxTagsExceeded_Error(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": batch, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) require.Equal(t, http.StatusOK, rec.Code) @@ -307,14 +309,14 @@ func TestTagResource_MaxTagsExceeded_Error(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": []map[string]string{{"key": "overflow-key", "value": "val"}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // AWS: TagResource's own error switch models TooManyTags for exceeding // the per-resource tag limit -- "TagPolicyViolation" names no type // anywhere in this SDK. @@ -345,7 +347,7 @@ func TestTagResource_ValidTagsAccepted(t *testing.T) { body, err := json.Marshal(map[string]any{ "resourceArn": smARN, "tags": []map[string]string{{"key": tt.key, "value": tt.value}}, - }) + }, jsonx.V1()) require.NoError(t, err) rec := sfnPost(ctx, t, h, e, "TagResource", string(body)) @@ -395,7 +397,7 @@ func TestHandler_GetTags_EmptyAndNonEmpty(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := resp["tags"].([]any) assert.Len(t, tags, tt.wantTagsLen) diff --git a/services/sts/persistence.go b/services/sts/persistence.go index 7a6d9befe3..5051e465e3 100644 --- a/services/sts/persistence.go +++ b/services/sts/persistence.go @@ -2,9 +2,10 @@ package sts import ( "context" - "encoding/json" + "encoding/json/v2" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -45,7 +46,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { OpsGetFedToken: b.cntGetFederationToken.Load(), } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "sts: failed to snapshot backend state", "error", err) diff --git a/services/sts/token_validation.go b/services/sts/token_validation.go index 8525f58b5a..f7063bd935 100644 --- a/services/sts/token_validation.go +++ b/services/sts/token_validation.go @@ -2,7 +2,7 @@ package sts import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/xml" "errors" "fmt" @@ -10,6 +10,8 @@ import ( "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // clockSkewLeeway is the tolerance applied to JWT/SAML temporal claims so that @@ -87,7 +89,7 @@ func parseJWTPayloadClaims(token string) map[string]any { } var claims map[string]any - if err = json.Unmarshal(decoded, &claims); err != nil { + if err = json.Unmarshal(decoded, &claims, jsonx.V1()); err != nil { return nil } @@ -215,7 +217,7 @@ func jwtTimeClaim(claims map[string]any, key string) (time.Time, bool, error) { switch n := v.(type) { case float64: return time.Unix(int64(n), 0).UTC(), true, nil - case json.Number: + case jsonx.Number: secs, err := n.Int64() if err != nil { return time.Time{}, false, fmt.Errorf( diff --git a/services/sts/token_validation_test.go b/services/sts/token_validation_test.go index 38c4b41cde..a30711461f 100644 --- a/services/sts/token_validation_test.go +++ b/services/sts/token_validation_test.go @@ -2,7 +2,7 @@ package sts_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "testing" "time" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sts" ) @@ -19,7 +20,7 @@ func makeUnitJWT(t *testing.T, claims map[string]any) string { header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"none","typ":"JWT"}`)) - payload, err := json.Marshal(claims) + payload, err := json.Marshal(claims, jsonx.V1()) if err != nil { t.Fatalf("marshal claims: %v", err) } @@ -232,7 +233,7 @@ func TestJWTTimeClaim(t *testing.T) { }, { name: "json_number", - claims: map[string]any{"exp": json.Number("2000")}, + claims: map[string]any{"exp": jsonx.Number("2000")}, key: "exp", wantOK: true, wantEpoch: 2000, diff --git a/services/sts/trust_policy.go b/services/sts/trust_policy.go index f7ddf906eb..dd08ba8275 100644 --- a/services/sts/trust_policy.go +++ b/services/sts/trust_policy.go @@ -2,7 +2,8 @@ package sts import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" @@ -10,6 +11,7 @@ import ( "time" "github.com/blackbirdworks/gopherstack/pkgs/condeval" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -126,10 +128,10 @@ func (e trustEval) conditionValue(key string) (string, bool) { // trustStatementDoc is a single parsed trust-policy statement. type trustStatementDoc struct { - Condition map[string]map[string]json.RawMessage `json:"Condition"` - Effect string `json:"Effect"` - Principal json.RawMessage `json:"Principal"` - Action json.RawMessage `json:"Action"` + Condition map[string]map[string]jsontext.Value `json:"Condition"` + Effect string `json:"Effect"` + Principal jsontext.Value `json:"Principal"` + Action jsontext.Value `json:"Action"` } // principalSet is the parsed Principal element of a statement. @@ -147,7 +149,7 @@ type trustPolicy struct { // trustStatement is a single statement in a trust policy. type trustStatement struct { - Condition map[string]map[string]json.RawMessage `json:"Condition"` + Condition map[string]map[string]jsontext.Value `json:"Condition"` } // evaluateAssumeRoleTrust evaluates a role's trust policy against the caller @@ -213,10 +215,10 @@ func parseTrustStatements(policyJSON string) ([]trustStatementDoc, bool) { } var doc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if err := json.Unmarshal([]byte(policyJSON), &doc); err != nil { + if err := json.Unmarshal([]byte(policyJSON), &doc, jsonx.V1()); err != nil { return nil, false } @@ -227,7 +229,7 @@ func parseTrustStatements(policyJSON string) ([]trustStatementDoc, bool) { if raw[0] == '[' { var arr []trustStatementDoc - if err := json.Unmarshal(raw, &arr); err != nil { + if err := json.Unmarshal(raw, &arr, jsonx.V1()); err != nil { return nil, false } @@ -235,7 +237,7 @@ func parseTrustStatements(policyJSON string) ([]trustStatementDoc, bool) { } var single trustStatementDoc - if err := json.Unmarshal(raw, &single); err != nil { + if err := json.Unmarshal(raw, &single, jsonx.V1()); err != nil { return nil, false } @@ -244,7 +246,7 @@ func parseTrustStatements(policyJSON string) ([]trustStatementDoc, bool) { // trimLeadingSpace drops leading ASCII whitespace from a raw JSON message so the // first significant byte can be inspected without importing bytes helpers. -func trimLeadingSpace(raw json.RawMessage) json.RawMessage { +func trimLeadingSpace(raw jsontext.Value) jsontext.Value { i := 0 for i < len(raw) { switch raw[i] { @@ -260,7 +262,7 @@ func trimLeadingSpace(raw json.RawMessage) json.RawMessage { // actionMatches reports whether the requested action is granted by the // statement Action element (a string or array; wildcards supported). -func actionMatches(raw json.RawMessage, requested string) bool { +func actionMatches(raw jsontext.Value, requested string) bool { if len(raw) == 0 { // A statement without an explicit Action is treated as matching so that // condition-only test policies (which omit Action) keep working. @@ -282,7 +284,7 @@ func actionMatches(raw json.RawMessage, requested string) bool { } // principalMatches reports whether the caller satisfies the statement Principal. -func principalMatches(raw json.RawMessage, ev trustEval) bool { +func principalMatches(raw jsontext.Value, ev trustEval) bool { if len(raw) == 0 { // No Principal specified. Real trust policies always name a principal, // but ExternalId-only test fixtures omit it; treat as matching so those @@ -320,11 +322,11 @@ func principalMatches(raw json.RawMessage, ev trustEval) bool { // parsePrincipal parses the Principal element, which may be the string "*" or an // object keyed by AWS / Federated / Service / CanonicalUser. -func parsePrincipal(raw json.RawMessage) principalSet { +func parsePrincipal(raw jsontext.Value) principalSet { var out principalSet var asString string - if err := json.Unmarshal(raw, &asString); err == nil { + if err := json.Unmarshal(raw, &asString, jsonx.V1()); err == nil { if asString == "*" { out.wildcard = true } else { @@ -334,8 +336,8 @@ func parsePrincipal(raw json.RawMessage) principalSet { return out } - var obj map[string]json.RawMessage - if err := json.Unmarshal(raw, &obj); err != nil { + var obj map[string]jsontext.Value + if err := json.Unmarshal(raw, &obj, jsonx.V1()); err != nil { return out } @@ -476,7 +478,7 @@ func assumedRoleArnMatches(callerArn, account, roleName string) bool { // conditionsSatisfied reports whether every condition in a statement holds for // the caller context. Unmodelled keys and operators are treated as satisfied. -func conditionsSatisfied(cond map[string]map[string]json.RawMessage, ev trustEval) bool { +func conditionsSatisfied(cond map[string]map[string]jsontext.Value, ev trustEval) bool { for op, kv := range cond { for key, raw := range kv { if !conditionOperatorHolds(op, key, raw, ev) { @@ -497,7 +499,7 @@ func conditionsSatisfied(cond map[string]map[string]json.RawMessage, ev trustEva // cannot evaluate does not silently break existing callers. Both fallback // paths log loudly at WARN so the gap is discoverable at runtime instead of // silent -- that is the fix for gopherstack-yg95, not a change of default. -func conditionOperatorHolds(op, key string, raw json.RawMessage, ev trustEval) bool { +func conditionOperatorHolds(op, key string, raw jsontext.Value, ev trustEval) bool { // AWS docs: IfExists may suffix any operator except Null (which already // tests presence), so "NullIfExists" is left as an unrecognized operator. //nolint:lll // AWS doc URL, cannot be split @@ -615,7 +617,7 @@ func dateOperatorHolds(normOp string, want []string, actual string) bool { // be present. Unlike every other operator, Null tests key existence, not the // key's value, so it is driven by conditionValue's known result rather than a // string/bool comparison against actual. -func nullConditionHolds(raw json.RawMessage, known bool) bool { +func nullConditionHolds(raw jsontext.Value, known bool) bool { for _, v := range extractStringValues(raw) { wantAbsent, err := strconv.ParseBool(v) if err == nil && wantAbsent == !known { @@ -728,7 +730,7 @@ func validateExternalID(trustPolicyJSON, externalID string) error { // policy leaves tp with a zero value (empty Statements), so no ExternalId // condition will be found and the call proceeds without validation — the // permissive behaviour is intentional for a mock implementation. - _ = json.Unmarshal([]byte(trustPolicyJSON), &tp) + _ = json.Unmarshal([]byte(trustPolicyJSON), &tp, jsonx.V1()) var hasExternalIDCondition bool @@ -757,7 +759,7 @@ func validateExternalID(trustPolicyJSON, externalID string) error { // requiredExternalIDs extracts all sts:ExternalId values from a trust-statement Condition map. // Returns nil when no ExternalId condition is present. -func requiredExternalIDs(condition map[string]map[string]json.RawMessage) []string { +func requiredExternalIDs(condition map[string]map[string]jsontext.Value) []string { for condOp, condMap := range condition { if !strings.EqualFold(condOp, "StringEquals") && !strings.EqualFold(condOp, "StringLike") { continue @@ -791,7 +793,7 @@ func validateMFACondition(trustPolicyJSON string, mfaPresent bool) error { // Unmarshal errors leave tp with a zero value (empty Statements): a malformed // trust policy is treated permissively, same as validateExternalID. - _ = json.Unmarshal([]byte(trustPolicyJSON), &tp) + _ = json.Unmarshal([]byte(trustPolicyJSON), &tp, jsonx.V1()) var hasMFACondition bool @@ -821,7 +823,7 @@ func validateMFACondition(trustPolicyJSON string, mfaPresent bool) error { // requiredMFAPresent extracts the required aws:MultiFactorAuthPresent Bool value // from a trust-statement Condition map. The second result reports whether the // condition is present at all. -func requiredMFAPresent(condition map[string]map[string]json.RawMessage) (bool, bool) { +func requiredMFAPresent(condition map[string]map[string]jsontext.Value) (bool, bool) { for condOp, condMap := range condition { if normalizeConditionOp(condOp) != condOperatorBool { continue @@ -845,14 +847,14 @@ func requiredMFAPresent(condition map[string]map[string]json.RawMessage) (bool, // extractStringValues unmarshals a JSON RawMessage that may be either a string // or an array of strings and returns the values as a Go string slice. -func extractStringValues(raw json.RawMessage) []string { +func extractStringValues(raw jsontext.Value) []string { var single string - if err := json.Unmarshal(raw, &single); err == nil { + if err := json.Unmarshal(raw, &single, jsonx.V1()); err == nil { return []string{single} } var many []string - if err := json.Unmarshal(raw, &many); err == nil { + if err := json.Unmarshal(raw, &many, jsonx.V1()); err == nil { return many } diff --git a/services/sts/validation.go b/services/sts/validation.go index 6578a4cd91..fc2679cbfa 100644 --- a/services/sts/validation.go +++ b/services/sts/validation.go @@ -1,11 +1,13 @@ package sts import ( - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // roleSessionNameRe is the AWS-allowed character set for RoleSessionName/FederationToken Name. @@ -198,7 +200,7 @@ func validateInlinePolicy(policy string) error { } var doc map[string]any - if err := json.Unmarshal([]byte(policy), &doc); err != nil { + if err := json.Unmarshal([]byte(policy), &doc, jsonx.V1()); err != nil { return fmt.Errorf("%w: %w", ErrMalformedPolicyDocument, err) } @@ -306,7 +308,7 @@ func validateJWTNotExpired(token string) error { switch v := exp.(type) { case float64: expTime = time.Unix(int64(v), 0).UTC() - case json.Number: + case jsonx.Number: n, err := v.Int64() if err != nil { return err diff --git a/services/sts/web_identity.go b/services/sts/web_identity.go index e2d93964eb..1e037ec9c0 100644 --- a/services/sts/web_identity.go +++ b/services/sts/web_identity.go @@ -2,13 +2,15 @@ package sts import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // webIdentitySubjectPlaceholder is returned when the sub claim cannot be extracted from the token. @@ -479,7 +481,7 @@ func (b *InMemoryBackend) GetWebIdentityToken( claims[jwtClaimTags] = tagMap } - payload, err := json.Marshal(claims) + payload, err := json.Marshal(claims, jsonx.V1()) if err != nil { return nil, fmt.Errorf("build token payload: %w", err) } diff --git a/services/sts/web_identity_irsa_test.go b/services/sts/web_identity_irsa_test.go index e74d29212a..4fd339ec4d 100644 --- a/services/sts/web_identity_irsa_test.go +++ b/services/sts/web_identity_irsa_test.go @@ -6,7 +6,7 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "strings" "testing" "time" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sts" ) @@ -53,10 +54,10 @@ func (l irsaOIDCLookup) OIDCProviderClientIDs(issuer string) ([]string, bool) { func signIRSAToken(t *testing.T, key *rsa.PrivateKey, claims map[string]any) string { t.Helper() - hdr, err := json.Marshal(map[string]string{"alg": "RS256", "kid": "k"}) + hdr, err := json.Marshal(map[string]string{"alg": "RS256", "kid": "k"}, jsonx.V1()) require.NoError(t, err) - body, err := json.Marshal(claims) + body, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) signing := base64.RawURLEncoding.EncodeToString(hdr) + "." + base64.RawURLEncoding.EncodeToString(body) @@ -77,7 +78,7 @@ func irsaTrustPolicy(cond string) string { func forgeIRSAPayload(t *testing.T, token string, claims map[string]any) string { t.Helper() - forged, err := json.Marshal(claims) + forged, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) parts := strings.Split(token, ".") @@ -89,7 +90,7 @@ func forgeIRSAPayload(t *testing.T, token string, claims map[string]any) string func unsignedIRSAToken(t *testing.T, claims map[string]any) string { t.Helper() - body, err := json.Marshal(claims) + body, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) return base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"none"}`)) + "." + diff --git a/services/sts/web_identity_test.go b/services/sts/web_identity_test.go index b9457e16c8..697294bbd1 100644 --- a/services/sts/web_identity_test.go +++ b/services/sts/web_identity_test.go @@ -2,7 +2,7 @@ package sts_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "encoding/xml" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/sts" ) @@ -41,7 +42,7 @@ func buildJWT(t *testing.T, claims map[string]any) string { t.Helper() header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"mock","typ":"JWT"}`)) - payload, err := json.Marshal(claims) + payload, err := json.Marshal(claims, jsonx.V1()) require.NoError(t, err) return header + "." + base64.RawURLEncoding.EncodeToString(payload) + ".fakesig" @@ -52,7 +53,7 @@ func buildParityJWT(t *testing.T, expUnix int64) string { t.Helper() header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"none","typ":"JWT"}`)) - payload, err := json.Marshal(map[string]any{"sub": "test", "exp": expUnix}) + payload, err := json.Marshal(map[string]any{"sub": "test", "exp": expUnix}, jsonx.V1()) require.NoError(t, err) return header + "." + base64.RawURLEncoding.EncodeToString(payload) + "." @@ -69,7 +70,7 @@ func parseJWTClaims(t *testing.T, tokenStr string) map[string]any { require.NoError(t, err) var claims map[string]any - require.NoError(t, json.Unmarshal(payloadBytes, &claims)) + require.NoError(t, json.Unmarshal(payloadBytes, &claims, jsonx.V1())) return claims } diff --git a/services/sts/web_identity_verify.go b/services/sts/web_identity_verify.go index 5f3e137886..c06b2e5ffa 100644 --- a/services/sts/web_identity_verify.go +++ b/services/sts/web_identity_verify.go @@ -5,10 +5,12 @@ import ( "crypto/rsa" "crypto/sha256" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const jwtAlgRS256 = "RS256" @@ -37,7 +39,7 @@ func verifyRS256(token string, keys []*rsa.PublicKey) error { Alg string `json:"alg"` } - if err = json.Unmarshal(rawHdr, &hdr); err != nil || hdr.Alg != jwtAlgRS256 { + if err = json.Unmarshal(rawHdr, &hdr, jsonx.V1()); err != nil || hdr.Alg != jwtAlgRS256 { return fmt.Errorf("%w: unsupported JWT signing algorithm", ErrInvalidIdentityToken) } diff --git a/services/support/cases.go b/services/support/cases.go index 6da4dd5c0a..3ea1463308 100644 --- a/services/support/cases.go +++ b/services/support/cases.go @@ -2,7 +2,7 @@ package support import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "slices" "sort" @@ -10,6 +10,8 @@ import ( "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -382,7 +384,7 @@ func pageOffset(token string) (int, error) { } var t pageTokenJSON - if unmarshalErr := json.Unmarshal(decoded, &t); unmarshalErr != nil || t.Offset < 0 { + if unmarshalErr := json.Unmarshal(decoded, &t, jsonx.V1()); unmarshalErr != nil || t.Offset < 0 { return 0, fmt.Errorf("%w: invalid nextToken", ErrValidation) } @@ -390,7 +392,7 @@ func pageOffset(token string) (int, error) { } func encodePageToken(offset int) string { - data, _ := json.Marshal(pageTokenJSON{Offset: offset}) + data, _ := json.Marshal(pageTokenJSON{Offset: offset}, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(data) } diff --git a/services/support/cases_test.go b/services/support/cases_test.go index 7b9d67dcf0..125bb77968 100644 --- a/services/support/cases_test.go +++ b/services/support/cases_test.go @@ -2,7 +2,7 @@ package support_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/support" ) @@ -25,7 +26,7 @@ func opaqueToken(t *testing.T, token string) int { O int `json:"o"` } - require.NoError(t, json.Unmarshal(raw, &obj), "token must be JSON with 'o' key") + require.NoError(t, json.Unmarshal(raw, &obj, jsonx.V1()), "token must be JSON with 'o' key") return obj.O } diff --git a/services/support/handler.go b/services/support/handler.go index af7d7163ac..cdcbe1ffdd 100644 --- a/services/support/handler.go +++ b/services/support/handler.go @@ -2,7 +2,7 @@ package support import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -152,7 +153,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req extractSupportResourceInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.CaseID != "" { return req.CaseID @@ -231,7 +232,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // handleError writes an AWS JSON-1.1 error envelope: the "__type" field is @@ -256,7 +257,7 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin payload, marshalErr := json.Marshal(service.JSONErrorResponse{ Type: errType, Message: errorMessage(errType, err), - }) + }, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } @@ -269,9 +270,6 @@ func (h *Handler) handleError(ctx context.Context, c *echo.Context, action strin // resolveErrorType maps a backend error to the wire "__type" exception name // and HTTP status a real AWS Support (awsjson1.1) response would carry. func resolveErrorType(err error) (string, int) { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, ErrNotFound): return "CaseIdNotFound", http.StatusBadRequest @@ -294,7 +292,7 @@ func resolveErrorType(err error) (string, int) { case errors.Is(err, ErrDescribeAttachmentLimitExceeded): return "DescribeAttachmentLimitExceeded", http.StatusBadRequest case errors.Is(err, ErrValidation), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return "ValidationException", http.StatusBadRequest default: return "InternalServerError", http.StatusInternalServerError diff --git a/services/support/handler_test.go b/services/support/handler_test.go index 1ffe2462be..62bf8de29c 100644 --- a/services/support/handler_test.go +++ b/services/support/handler_test.go @@ -2,7 +2,7 @@ package support_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "maps" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/support" ) @@ -24,7 +25,7 @@ func newTestSupportHandler(t *testing.T) *support.Handler { func doSupportRequest(t *testing.T, h *support.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -47,7 +48,7 @@ func decodeSupportResponse(t *testing.T, rec *httptest.ResponseRecorder) map[str t.Helper() var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) return result } diff --git a/services/support/persistence.go b/services/support/persistence.go index f9b9e00574..634948bd81 100644 --- a/services/support/persistence.go +++ b/services/support/persistence.go @@ -2,10 +2,12 @@ package support import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" @@ -55,7 +57,7 @@ func newAttachmentSetDTORegistry() (*store.Registry, *store.Table[attachmentSetS // is order-sensitive and left a plain map -- see store_setup.go -- so it is // persisted here directly instead of through a store.Table. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Communications map[string][]Communication `json:"communications"` NextDisplayID uint64 `json:"nextDisplayId"` Version int `json:"version"` @@ -96,7 +98,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { NextDisplayID: b.nextDisplayID, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "support: snapshot marshal failed", "error", err) @@ -161,7 +163,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreAttachmentSetsLocked rebuilds the "dirty" attachmentSets table from // tables via the ephemeral DTO registry, converting each DTO back to its live // type. The caller MUST hold b.mu for writing. -func (b *InMemoryBackend) restoreAttachmentSetsLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreAttachmentSetsLocked(tables map[string]jsontext.Value) error { dtoReg, asDTOs := newAttachmentSetDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("support: restore snapshot DTO tables: %w", err) diff --git a/services/support/whitebox_test.go b/services/support/whitebox_test.go index 0964201d54..4654c03405 100644 --- a/services/support/whitebox_test.go +++ b/services/support/whitebox_test.go @@ -2,7 +2,7 @@ package support import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -12,12 +12,14 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doWhiteboxSupportRequest(t *testing.T, h *Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -184,6 +186,6 @@ func TestSupport_CreateCase_CaseCreationLimitExceeded_WireType(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "CaseCreationLimitExceeded", result["__type"]) } diff --git a/services/swf/decision_lifecycle_test.go b/services/swf/decision_lifecycle_test.go index aad14c2a07..288c3407ed 100644 --- a/services/swf/decision_lifecycle_test.go +++ b/services/swf/decision_lifecycle_test.go @@ -1,13 +1,14 @@ package swf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -597,7 +598,7 @@ func TestRespondDecisionTask_ViaHandler(t *testing.T) { if tt.wantExecStatus != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Verify via describe - pick the right domain/workflowID var domainName, wfID string if tt.wantExecStatus == "COMPLETED" { diff --git a/services/swf/decision_orchestration_test.go b/services/swf/decision_orchestration_test.go index 06068e2dcc..43b41e6462 100644 --- a/services/swf/decision_orchestration_test.go +++ b/services/swf/decision_orchestration_test.go @@ -7,13 +7,14 @@ package swf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -80,7 +81,7 @@ func TestStartChildWorkflowExecutionDecision_Success(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) openCounts, ok := body["openCounts"].(map[string]any) require.True(t, ok) assert.InDelta(t, 1, openCounts["openChildWorkflowExecutions"], 0) diff --git a/services/swf/handler.go b/services/swf/handler.go index 78e04381e0..912871bfa7 100644 --- a/services/swf/handler.go +++ b/services/swf/handler.go @@ -2,7 +2,7 @@ package swf import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -136,7 +137,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { return "" } var req extractSWFResourceInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.Name != "" { return req.Name } @@ -211,13 +212,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - code := http.StatusInternalServerError var errType string @@ -253,7 +251,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err code = http.StatusBadRequest errType = "OperationNotPermittedFault" case errors.Is(err, errInvalidRequest), errors.Is(err, ErrUnknownOperation), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): code = http.StatusBadRequest } diff --git a/services/swf/handler_activity_types_test.go b/services/swf/handler_activity_types_test.go index 66802b5b61..29a189feea 100644 --- a/services/swf/handler_activity_types_test.go +++ b/services/swf/handler_activity_types_test.go @@ -1,13 +1,14 @@ package swf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -119,7 +120,7 @@ func TestHandler_DeprecateActivityType(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) diff --git a/services/swf/handler_test.go b/services/swf/handler_test.go index 5553f9c97c..8a9b0555a4 100644 --- a/services/swf/handler_test.go +++ b/services/swf/handler_test.go @@ -2,7 +2,7 @@ package swf_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http" "net/http/httptest" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -29,7 +30,7 @@ func doSWFRequest(t *testing.T, h *swf.Handler, action string, body any) *httpte var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } else { bodyBytes = []byte("{}") @@ -54,7 +55,7 @@ func parseSWFResp(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -252,7 +253,7 @@ func TestSWFHandler_Actions(t *testing.T) { if tt.wantNotEmptyField != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantNotEmptyField]) } }) @@ -578,7 +579,7 @@ func TestSWFHandler_ErrorTypes(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) }) } diff --git a/services/swf/handler_workflow_types_test.go b/services/swf/handler_workflow_types_test.go index 73dbbc9e5b..7d8cd30ad6 100644 --- a/services/swf/handler_workflow_types_test.go +++ b/services/swf/handler_workflow_types_test.go @@ -1,12 +1,14 @@ package swf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListWorkflowTypes_Pagination(t *testing.T) { @@ -251,7 +253,7 @@ func TestHandler_DeprecateWorkflowType(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) diff --git a/services/swf/lambda_tasks.go b/services/swf/lambda_tasks.go index 7656935f08..1455d89539 100644 --- a/services/swf/lambda_tasks.go +++ b/services/swf/lambda_tasks.go @@ -2,11 +2,13 @@ package swf import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "slices" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -189,7 +191,7 @@ func lambdaFailureDetails(functionError string, payload []byte) (string, string) ErrorType string `json:"errorType"` } - if json.Unmarshal(payload, &body) == nil && body.ErrorType != "" { + if json.Unmarshal(payload, &body, jsonx.V1()) == nil && body.ErrorType != "" { return body.ErrorType, string(payload) } diff --git a/services/swf/models.go b/services/swf/models.go index e5b2ec11b3..03f3de479b 100644 --- a/services/swf/models.go +++ b/services/swf/models.go @@ -1,9 +1,12 @@ package swf import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "maps" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -118,24 +121,24 @@ func (e HistoryEvent) MarshalJSON() ([]byte, error) { } maps.Copy(m, e.Attributes) - return json.Marshal(m) + return json.Marshal(m, jsonx.V1()) } // UnmarshalJSON restores a HistoryEvent from its JSON representation, // capturing any unknown keys (the attributes block) into Attributes. func (e *HistoryEvent) UnmarshalJSON(data []byte) error { - var raw map[string]json.RawMessage - if err := json.Unmarshal(data, &raw); err != nil { + var raw map[string]jsontext.Value + if err := json.Unmarshal(data, &raw, jsonx.V1()); err != nil { return err } if v, ok := raw["eventType"]; ok { - _ = json.Unmarshal(v, &e.EventType) + _ = json.Unmarshal(v, &e.EventType, jsonx.V1()) } if v, ok := raw["eventId"]; ok { - _ = json.Unmarshal(v, &e.EventID) + _ = json.Unmarshal(v, &e.EventID, jsonx.V1()) } if v, ok := raw["eventTimestamp"]; ok { - _ = json.Unmarshal(v, &e.Timestamp) + _ = json.Unmarshal(v, &e.Timestamp, jsonx.V1()) } known := map[string]bool{ "eventType": true, "eventId": true, "eventTimestamp": true, @@ -144,7 +147,7 @@ func (e *HistoryEvent) UnmarshalJSON(data []byte) error { for k, v := range raw { if !known[k] { var x any - _ = json.Unmarshal(v, &x) + _ = json.Unmarshal(v, &x, jsonx.V1()) e.Attributes[k] = x } } diff --git a/services/swf/multi_region_test.go b/services/swf/multi_region_test.go index 4a137d5c0d..f79de1272a 100644 --- a/services/swf/multi_region_test.go +++ b/services/swf/multi_region_test.go @@ -2,7 +2,8 @@ package swf_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -180,8 +182,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/swf/persistence.go b/services/swf/persistence.go index 2b082cb974..b67b04e7ae 100644 --- a/services/swf/persistence.go +++ b/services/swf/persistence.go @@ -2,7 +2,7 @@ package swf import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -78,7 +78,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // activeDecisionTasks. History, ActivityQueues, and DecisionQueues stay plain // maps by design (order-sensitive) and are written as-is. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` History map[string][]HistoryEvent `json:"history,omitempty"` Tags map[string]map[string]string `json:"tags,omitempty"` // ActivityQueues/DecisionQueues are the pending FIFO task lists, persisted in order. @@ -284,7 +284,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // activeDecisionTasks; see store_setup.go's registerAllTables doc) from // tables via the ephemeral DTO registry, factored out of Restore to keep // Restore's own cognitive complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreDirtyTablesLocked(tables map[string]jsontext.Value) error { dtos := buildPersistenceDTORegistry() if err := dtos.registry.RestoreAll(tables); err != nil { return fmt.Errorf("swf: restore snapshot DTO tables: %w", err) diff --git a/services/swf/persistence_test.go b/services/swf/persistence_test.go index dc6db5daf0..bf5453f4da 100644 --- a/services/swf/persistence_test.go +++ b/services/swf/persistence_test.go @@ -1,13 +1,14 @@ package swf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/swf" ) @@ -375,7 +376,7 @@ func TestSnapshotRestore_ChildLinkAndOpenTimers(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var body map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) openCounts, ok := body["openCounts"].(map[string]any) require.True(t, ok) assert.InDelta( diff --git a/services/textract/handler.go b/services/textract/handler.go index d957c29a66..733abeac74 100644 --- a/services/textract/handler.go +++ b/services/textract/handler.go @@ -2,7 +2,7 @@ package textract import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -203,7 +204,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req documentLocationInput - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) bucket := req.DocumentLocation.S3Object.Bucket key := req.DocumentLocation.S3Object.Name @@ -280,7 +281,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // Operation name constants for the ops referenced by @@ -330,9 +331,6 @@ var opsWithoutValidationException = map[string]bool{ //nolint:gochecknoglobals / } func (h *Handler) handleError(_ context.Context, c *echo.Context, action string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - var code string var status int @@ -345,7 +343,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, action string, code, status = "InvalidS3ObjectException", http.StatusBadRequest case errors.Is(err, ErrValidation), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): if opsWithoutValidationException[action] { code, status = "InvalidParameterException", http.StatusBadRequest } else { @@ -355,7 +353,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, action string, code, status = "InternalServerError", http.StatusInternalServerError } - payload, marshalErr := json.Marshal(service.JSONErrorResponse{Type: code, Message: errMessage(err)}) + payload, marshalErr := json.Marshal(service.JSONErrorResponse{Type: code, Message: errMessage(err)}, jsonx.V1()) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") } diff --git a/services/textract/handler_adapter_versions_test.go b/services/textract/handler_adapter_versions_test.go index ac9c2983a1..7937dc6588 100644 --- a/services/textract/handler_adapter_versions_test.go +++ b/services/textract/handler_adapter_versions_test.go @@ -1,7 +1,7 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -38,7 +39,7 @@ func TestHandler_AdapterVersionLifecycle(t *testing.T) { require.Equal(t, tt.wantStatus, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] // CreateAdapterVersion @@ -59,7 +60,7 @@ func TestHandler_AdapterVersionLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] assert.NotEmpty(t, adapterVersion) assert.Equal(t, adapterID, createVersionResp["AdapterId"]) @@ -73,7 +74,7 @@ func TestHandler_AdapterVersionLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, getVersionRec.Code) var getVersionResp map[string]any - require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp)) + require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp, jsonx.V1())) assert.Equal(t, adapterID, getVersionResp["AdapterId"]) assert.Equal(t, adapterVersion, getVersionResp["AdapterVersion"]) assert.Equal(t, "ACTIVE", getVersionResp["Status"]) @@ -152,7 +153,7 @@ func TestHandler_CreateAdapterVersion_RequiresDatasetAndOutputConfig(t *testing. require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) body := map[string]any{"AdapterId": createAdapterResp["AdapterId"]} if tt.datasetConfig != nil { @@ -229,7 +230,7 @@ func TestHandler_CreateAdapterVersion_DatasetConfig(t *testing.T) { require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] createVersionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -248,7 +249,7 @@ func TestHandler_CreateAdapterVersion_DatasetConfig(t *testing.T) { require.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] getVersionRec := doTextractRequest(t, h, "GetAdapterVersion", map[string]any{ @@ -258,7 +259,7 @@ func TestHandler_CreateAdapterVersion_DatasetConfig(t *testing.T) { require.Equal(t, http.StatusOK, getVersionRec.Code) var getVersionResp map[string]any - require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp)) + require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp, jsonx.V1())) datasetConfig, ok := getVersionResp["DatasetConfig"].(map[string]any) require.True(t, ok, "GetAdapterVersion should include DatasetConfig") @@ -287,7 +288,7 @@ func TestHandler_AdapterVersion_InProgressThenActive(t *testing.T) { require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] createVersionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -305,7 +306,7 @@ func TestHandler_AdapterVersion_InProgressThenActive(t *testing.T) { require.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] // Immediately check: should be CREATION_IN_PROGRESS. @@ -316,7 +317,7 @@ func TestHandler_AdapterVersion_InProgressThenActive(t *testing.T) { require.Equal(t, http.StatusOK, getRec1.Code) var getResp1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1, jsonx.V1())) assert.Equal(t, "CREATION_IN_PROGRESS", getResp1["Status"]) // After delay, should be ACTIVE. @@ -330,7 +331,7 @@ func TestHandler_AdapterVersion_InProgressThenActive(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var getResp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2, jsonx.V1())) assert.Equal(t, "ACTIVE", getResp2["Status"]) }) } @@ -352,7 +353,7 @@ func TestHandler_AdapterVersion_EvaluationMetrics(t *testing.T) { require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] createVersionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -370,7 +371,7 @@ func TestHandler_AdapterVersion_EvaluationMetrics(t *testing.T) { require.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] getVersionRec := doTextractRequest(t, h, "GetAdapterVersion", map[string]any{ @@ -380,7 +381,7 @@ func TestHandler_AdapterVersion_EvaluationMetrics(t *testing.T) { require.Equal(t, http.StatusOK, getVersionRec.Code) var getVersionResp map[string]any - require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp)) + require.NoError(t, json.Unmarshal(getVersionRec.Body.Bytes(), &getVersionResp, jsonx.V1())) evalMetricsList, ok := getVersionResp["EvaluationMetrics"].([]any) require.True(t, ok, "GetAdapterVersion should include EvaluationMetrics as a list") @@ -417,7 +418,7 @@ func TestHandler_DeleteAdapterVersion_GetReturnsErrorAfterDelete(t *testing.T) { }) require.Equal(t, http.StatusOK, createAdapterRec.Code) var adapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &adapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &adapterResp, jsonx.V1())) adapterID := adapterResp["AdapterId"] createVerRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -434,7 +435,7 @@ func TestHandler_DeleteAdapterVersion_GetReturnsErrorAfterDelete(t *testing.T) { }) require.Equal(t, http.StatusOK, createVerRec.Code) var verResp map[string]string - require.NoError(t, json.Unmarshal(createVerRec.Body.Bytes(), &verResp)) + require.NoError(t, json.Unmarshal(createVerRec.Body.Bytes(), &verResp, jsonx.V1())) version := verResp["AdapterVersion"] require.NotEmpty(t, version) @@ -456,7 +457,7 @@ func TestHandler_DeleteAdapterVersion_GetReturnsErrorAfterDelete(t *testing.T) { }) assert.Equal(t, http.StatusBadRequest, getAfterRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(getAfterRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(getAfterRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"], "deleted version must return ResourceNotFoundException") } @@ -472,7 +473,7 @@ func TestHandler_ListAdapterVersions_HappyPath(t *testing.T) { "FeatureTypes": []string{"FORMS"}, }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] for range 3 { @@ -496,7 +497,7 @@ func TestHandler_ListAdapterVersions_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["AdapterVersions"].([]any) assert.True(t, ok) assert.Len(t, versions, 3) @@ -541,7 +542,7 @@ func TestHandler_ListAdapterVersions_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] verRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -565,7 +566,7 @@ func TestHandler_ListAdapterVersions_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) versions, ok := resp["AdapterVersions"].([]any) require.True(t, ok) @@ -604,7 +605,7 @@ func TestHandler_AdapterVersion_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] createVersionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -622,7 +623,7 @@ func TestHandler_AdapterVersion_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] getRec := doTextractRequest(t, h, "GetAdapterVersion", map[string]any{ @@ -632,7 +633,7 @@ func TestHandler_AdapterVersion_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ct, ok := getResp["CreationTime"].(float64) assert.True(t, ok, "GetAdapterVersion CreationTime must be a JSON number") assert.Positive(t, ct) @@ -641,7 +642,7 @@ func TestHandler_AdapterVersion_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) versions, ok := listResp["AdapterVersions"].([]any) require.True(t, ok) require.NotEmpty(t, versions) @@ -670,7 +671,7 @@ func TestHandler_ListAdapterVersions_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] for range 3 { @@ -699,7 +700,7 @@ func TestHandler_ListAdapterVersions_Pagination(t *testing.T) { NextToken string `json:"NextToken"` AdapterVersions []map[string]any `json:"AdapterVersions"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) assert.Len(t, resp1.AdapterVersions, 2) require.NotEmpty(t, resp1.NextToken, "first page must return a NextToken") @@ -713,7 +714,7 @@ func TestHandler_ListAdapterVersions_Pagination(t *testing.T) { NextToken string `json:"NextToken"` AdapterVersions []map[string]any `json:"AdapterVersions"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2.AdapterVersions, 1, "remaining 1 version on the second page") assert.Empty(t, resp2.NextToken, "no more pages") } diff --git a/services/textract/handler_adapters_test.go b/services/textract/handler_adapters_test.go index 3aca1cc31e..d1bdd937ec 100644 --- a/services/textract/handler_adapters_test.go +++ b/services/textract/handler_adapters_test.go @@ -1,7 +1,7 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -55,7 +56,7 @@ func TestHandler_AdapterLifecycle(t *testing.T) { } var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] assert.NotEmpty(t, adapterID) @@ -65,7 +66,7 @@ func TestHandler_AdapterLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, tt.adapterName, getResp["AdapterName"]) assert.Equal(t, tt.description, getResp["Description"]) @@ -114,7 +115,7 @@ func TestHandler_GetAdapter_IncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) getRec := doTextractRequest(t, h, "GetAdapter", map[string]any{ "AdapterId": createResp["AdapterId"], @@ -122,7 +123,7 @@ func TestHandler_GetAdapter_IncludesTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) tags, hasTags := getResp["Tags"].(map[string]any) assert.True(t, hasTags, "GetAdapter must include Tags") @@ -151,7 +152,7 @@ func TestHandler_DeleteAdapter_CascadesVersions(t *testing.T) { require.Equal(t, http.StatusOK, createResp.Code) var cr map[string]string - require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &cr)) + require.NoError(t, json.Unmarshal(createResp.Body.Bytes(), &cr, jsonx.V1())) adapterID := cr["AdapterId"] // Create a version @@ -170,7 +171,7 @@ func TestHandler_DeleteAdapter_CascadesVersions(t *testing.T) { require.Equal(t, http.StatusOK, versionResp.Code) var vr map[string]string - require.NoError(t, json.Unmarshal(versionResp.Body.Bytes(), &vr)) + require.NoError(t, json.Unmarshal(versionResp.Body.Bytes(), &vr, jsonx.V1())) adapterVersion := vr["AdapterVersion"] // Delete adapter should cascade to versions @@ -217,13 +218,13 @@ func TestHandler_CreateAdapter_ClientRequestTokenDedup(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) rec2 := doTextractRequest(t, h, "CreateAdapter", body) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, resp1["AdapterId"], resp2["AdapterId"], "same token should return same AdapterId") } @@ -246,7 +247,7 @@ func TestHandler_UpdateAdapter_PreservesNameAndFeatureTypes(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] require.NotEmpty(t, adapterID) @@ -258,7 +259,7 @@ func TestHandler_UpdateAdapter_PreservesNameAndFeatureTypes(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "immutable-name", updateResp["AdapterName"], "AdapterName must be unchanged after UpdateAdapter") @@ -375,7 +376,7 @@ func TestHandler_UpdateAdapter_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] updateRec := doTextractRequest(t, h, "UpdateAdapter", map[string]any{ @@ -386,7 +387,7 @@ func TestHandler_UpdateAdapter_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, "updated description", updateResp["Description"]) assert.Equal(t, "ENABLED", updateResp["AutoUpdate"]) @@ -406,7 +407,7 @@ func TestHandler_UpdateAdapter_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -468,7 +469,7 @@ func TestHandler_UpdateAdapter_PartialUpdateSemantics(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] body := map[string]any{"AdapterId": adapterID} @@ -482,7 +483,7 @@ func TestHandler_UpdateAdapter_PartialUpdateSemantics(t *testing.T) { } var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.Equal(t, tt.wantName, updateResp["AdapterName"]) assert.Equal(t, tt.wantDesc, updateResp["Description"]) }) @@ -507,7 +508,7 @@ func TestHandler_ListAdapters_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) adapters, ok := resp["Adapters"].([]any) assert.True(t, ok) assert.Len(t, adapters, 3) @@ -533,7 +534,7 @@ func TestHandler_ListAdapters_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) adapters, ok := resp["Adapters"].([]any) require.True(t, ok) @@ -569,14 +570,14 @@ func TestHandler_Adapter_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] getRec := doTextractRequest(t, h, "GetAdapter", map[string]any{"AdapterId": adapterID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ct, ok := getResp["CreationTime"].(float64) assert.True(t, ok, "GetAdapter CreationTime must be a JSON number") assert.Positive(t, ct) @@ -588,7 +589,7 @@ func TestHandler_Adapter_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) uct, ok := updateResp["CreationTime"].(float64) assert.True(t, ok, "UpdateAdapter CreationTime must be a JSON number") assert.Positive(t, uct) @@ -597,7 +598,7 @@ func TestHandler_Adapter_CreationTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) adapters, ok := listResp["Adapters"].([]any) require.True(t, ok) require.NotEmpty(t, adapters) @@ -633,7 +634,7 @@ func TestHandler_ListAdapters_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Adapters []map[string]any `json:"Adapters"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) assert.Len(t, resp1.Adapters, 2) require.NotEmpty(t, resp1.NextToken, "first page must return a NextToken") @@ -644,7 +645,7 @@ func TestHandler_ListAdapters_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Adapters []map[string]any `json:"Adapters"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2.Adapters, 1, "remaining 1 adapter on the second page") assert.Empty(t, resp2.NextToken, "no more pages") } diff --git a/services/textract/handler_analyze_document_config_test.go b/services/textract/handler_analyze_document_config_test.go index 27a015b638..2b8c757eef 100644 --- a/services/textract/handler_analyze_document_config_test.go +++ b/services/textract/handler_analyze_document_config_test.go @@ -1,7 +1,7 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -103,7 +104,7 @@ func TestAnalyzeDocument_AdaptersConfig(t *testing.T) { } var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, tt.wantType, errResp["__type"]) }) } @@ -159,7 +160,7 @@ func TestAnalyzeDocument_HumanLoopConfig(t *testing.T) { var out struct { HumanLoopActivationOutput *struct{} `json:"HumanLoopActivationOutput"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Nil( t, out.HumanLoopActivationOutput, @@ -189,7 +190,7 @@ func newTestHandlerT(t *testing.T) *testHandlerT { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) versionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ "AdapterId": createResp["AdapterId"], @@ -206,7 +207,7 @@ func newTestHandlerT(t *testing.T) *testHandlerT { require.Equal(t, http.StatusOK, versionRec.Code) var versionResp map[string]string - require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &versionResp)) + require.NoError(t, json.Unmarshal(versionRec.Body.Bytes(), &versionResp, jsonx.V1())) return &testHandlerT{ h: h, diff --git a/services/textract/handler_document_analysis_test.go b/services/textract/handler_document_analysis_test.go index b4be85e43d..b185d2c0b5 100644 --- a/services/textract/handler_document_analysis_test.go +++ b/services/textract/handler_document_analysis_test.go @@ -2,7 +2,7 @@ package textract_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -27,7 +28,7 @@ func startDocumentAnalysisJob(t *testing.T, h *textract.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobID := resp["JobId"] require.NotEmpty(t, jobID) @@ -46,7 +47,7 @@ func startTextDetectionJob(t *testing.T, h *textract.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) jobID := resp["JobId"] require.NotEmpty(t, jobID) @@ -58,7 +59,7 @@ func blocksOfType(t *testing.T, body []byte, blockType string) []map[string]any t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) raw, ok := resp["Blocks"].([]any) require.True(t, ok, "response should have Blocks array") @@ -121,7 +122,7 @@ func TestHandler_AnalyzeDocument(t *testing.T) { if tt.wantBlocks { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) blocks, ok := resp["Blocks"].([]any) assert.True(t, ok) assert.NotEmpty(t, blocks) @@ -164,7 +165,7 @@ func TestHandler_StartAndGetDocumentAnalysis(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] assert.NotEmpty(t, jobID) @@ -174,7 +175,7 @@ func TestHandler_StartAndGetDocumentAnalysis(t *testing.T) { assert.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) blocks, ok := getResp["Blocks"].([]any) assert.True(t, ok) @@ -235,7 +236,7 @@ func TestHandler_GetDocumentAnalysis_RejectsTextDetectionJobID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidJobIdException", resp["__type"], "cross-type access must return InvalidJobIdException, not a different error") } @@ -475,7 +476,7 @@ func TestHandler_AnalyzeDocument_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "1.0", resp["AnalyzeDocumentModelVersion"]) } @@ -494,7 +495,7 @@ func TestHandler_AnalyzeDocument_DocumentMetadataPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) meta, ok := m["DocumentMetadata"].(map[string]any) require.True(t, ok, "AnalyzeDocument response must have DocumentMetadata") pages, ok2 := meta["Pages"].(float64) @@ -518,7 +519,7 @@ func TestHandler_AnalyzeDocument_BytesInput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, ok := m["Blocks"].([]any) assert.True(t, ok && len(blocks) > 0, "AnalyzeDocument with Bytes must return Blocks") } @@ -539,7 +540,7 @@ func TestHandler_GetDocumentAnalysis_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetDocumentAnalysis", map[string]any{ @@ -549,7 +550,7 @@ func TestHandler_GetDocumentAnalysis_PaginationNextToken(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) blocks, _ := getResp["Blocks"].([]any) assert.Len(t, blocks, 2) @@ -574,14 +575,14 @@ func TestHandler_GetDocumentAnalysis_BlocksHaveGeometry(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetDocumentAnalysis", map[string]any{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) blocks, _ := getResp["Blocks"].([]any) require.NotEmpty(t, blocks) @@ -619,14 +620,14 @@ func TestHandler_GetDocumentAnalysis_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetDocumentAnalysis", map[string]string{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m, jsonx.V1())) ver, ok := m["AnalyzeDocumentModelVersion"].(string) assert.True(t, ok, "GetDocumentAnalysis must have AnalyzeDocumentModelVersion") assert.Equal(t, "1.0", ver) @@ -647,14 +648,14 @@ func TestHandler_GetDocumentAnalysis_JobStatusSucceeded(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetDocumentAnalysis", map[string]string{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m, jsonx.V1())) assert.Equal(t, "SUCCEEDED", m["JobStatus"], "synchronous backend job must SUCCEED immediately") } @@ -679,7 +680,7 @@ func TestHandler_StartDocumentAnalysis_AsyncInProgressThenSucceeded(t *testing.T require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] // Immediately after start, job should be IN_PROGRESS. @@ -687,7 +688,7 @@ func TestHandler_StartDocumentAnalysis_AsyncInProgressThenSucceeded(t *testing.T require.Equal(t, http.StatusOK, getRec1.Code) var getResp1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", getResp1["JobStatus"]) // After delay, job should be SUCCEEDED. @@ -698,7 +699,7 @@ func TestHandler_StartDocumentAnalysis_AsyncInProgressThenSucceeded(t *testing.T require.Equal(t, http.StatusOK, getRec2.Code) var getResp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp2["JobStatus"]) }) } @@ -725,7 +726,7 @@ func TestHandler_StartDocumentAnalysis_AsyncInitialStatusInProgress(t *testing.T require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] require.NotEmpty(t, jobID) @@ -734,7 +735,7 @@ func TestHandler_StartDocumentAnalysis_AsyncInitialStatusInProgress(t *testing.T require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "IN_PROGRESS", getResp["JobStatus"], "job must be IN_PROGRESS immediately after Start when async delay is non-zero") } @@ -758,14 +759,14 @@ func TestHandler_StartDocumentAnalysis_ClientRequestTokenIdempotency(t *testing. require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) jobID1 := resp1["JobId"] rec2 := doTextractRequest(t, h, "StartDocumentAnalysis", startBody) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) jobID2 := resp2["JobId"] assert.Equal(t, jobID1, jobID2, "same ClientRequestToken should return the same JobId") @@ -786,7 +787,7 @@ func TestHandler_StartDocumentAnalysis_JobIdNonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) jobID, ok := m["JobId"].(string) assert.True(t, ok, "StartDocumentAnalysis response must have string JobId") assert.NotEmpty(t, jobID, "JobId must not be empty") @@ -879,7 +880,7 @@ func TestHandler_AnalyzeDocumentAndStart_ValidationErrorsUseInvalidParameterExce require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidParameterException", errResp["__type"]) }) } diff --git a/services/textract/handler_document_detection_test.go b/services/textract/handler_document_detection_test.go index c754be8aec..eff4ae4bd1 100644 --- a/services/textract/handler_document_detection_test.go +++ b/services/textract/handler_document_detection_test.go @@ -1,13 +1,15 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DetectDocumentText(t *testing.T) { @@ -76,7 +78,7 @@ func TestHandler_StartAndGetDocumentTextDetection(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] assert.NotEmpty(t, jobID) @@ -85,7 +87,7 @@ func TestHandler_StartAndGetDocumentTextDetection(t *testing.T) { assert.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) }) } @@ -143,7 +145,7 @@ func TestHandler_GetDocumentTextDetection_RejectsAnalysisJobID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidJobIdException", resp["__type"], "cross-type access must return InvalidJobIdException") } @@ -192,7 +194,7 @@ func TestHandler_DetectDocumentText_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "1.0", resp["DetectDocumentTextModelVersion"]) } @@ -212,7 +214,7 @@ func TestHandler_GetDocumentTextDetection_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] // Get first page with MaxResults=3. @@ -223,7 +225,7 @@ func TestHandler_GetDocumentTextDetection_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, getRec1.Code) var getResp1 map[string]any - require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1)) + require.NoError(t, json.Unmarshal(getRec1.Body.Bytes(), &getResp1, jsonx.V1())) blocks1, _ := getResp1["Blocks"].([]any) assert.Len(t, blocks1, 3, "first page should have 3 blocks") @@ -240,7 +242,7 @@ func TestHandler_GetDocumentTextDetection_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, getRec2.Code) var getResp2 map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &getResp2, jsonx.V1())) blocks2, _ := getResp2["Blocks"].([]any) assert.NotEmpty(t, blocks2, "second page should have remaining blocks") @@ -260,7 +262,7 @@ func TestHandler_DetectDocumentText_BlockIDsAreUUIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, ok := m["Blocks"].([]any) require.True(t, ok) require.NotEmpty(t, blocks) @@ -291,7 +293,7 @@ func TestHandler_DetectDocumentText_ConfidenceInRange(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, _ := m["Blocks"].([]any) require.NotEmpty(t, blocks) @@ -325,7 +327,7 @@ func TestHandler_DetectDocumentText_WordHasTextType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, _ := m["Blocks"].([]any) require.NotEmpty(t, blocks) @@ -361,7 +363,7 @@ func TestHandler_DetectDocumentText_PageIsSet(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, _ := m["Blocks"].([]any) require.NotEmpty(t, blocks) @@ -392,7 +394,7 @@ func TestHandler_DetectDocumentText_GeometryBoundingBoxValid(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, _ := m["Blocks"].([]any) require.NotEmpty(t, blocks) @@ -439,7 +441,7 @@ func TestHandler_DetectDocumentText_DocumentMetadataPages(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) meta, ok := m["DocumentMetadata"].(map[string]any) require.True(t, ok, "response must have DocumentMetadata") pages, ok2 := meta["Pages"].(float64) @@ -462,7 +464,7 @@ func TestHandler_DetectDocumentText_BytesInput(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) blocks, ok := m["Blocks"].([]any) assert.True(t, ok && len(blocks) > 0, "DetectDocumentText with Bytes must return Blocks") } @@ -481,14 +483,14 @@ func TestHandler_GetDocumentTextDetection_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetDocumentTextDetection", map[string]string{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m, jsonx.V1())) ver, ok := m["DetectDocumentTextModelVersion"].(string) assert.True(t, ok, "GetDocumentTextDetection must have DetectDocumentTextModelVersion") assert.Equal(t, "1.0", ver) @@ -511,7 +513,7 @@ func TestHandler_StartDocumentTextDetection_ClientRequestTokenIdempotency(t *tes require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) jobID1 := resp1["JobId"] require.NotEmpty(t, jobID1) @@ -519,7 +521,7 @@ func TestHandler_StartDocumentTextDetection_ClientRequestTokenIdempotency(t *tes require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, jobID1, resp2["JobId"], "same ClientRequestToken must return same JobId") } diff --git a/services/textract/handler_expense_analysis_test.go b/services/textract/handler_expense_analysis_test.go index fa360a6412..38cd0e58b4 100644 --- a/services/textract/handler_expense_analysis_test.go +++ b/services/textract/handler_expense_analysis_test.go @@ -1,13 +1,14 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -57,7 +58,7 @@ func TestHandler_AnalyzeExpense(t *testing.T) { if tt.wantDocs { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["ExpenseDocuments"].([]any) assert.True(t, ok) assert.NotEmpty(t, docs) @@ -110,7 +111,7 @@ func TestHandler_StartExpenseAnalysis_ClientRequestTokenIdempotency(t *testing.T require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) jobID1 := resp1["JobId"] require.NotEmpty(t, jobID1) @@ -118,7 +119,7 @@ func TestHandler_StartExpenseAnalysis_ClientRequestTokenIdempotency(t *testing.T require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, jobID1, resp2["JobId"], "same ClientRequestToken must return same JobId") assert.Equal(t, 1, textract.ExpenseJobCount(h.Backend.(*textract.InMemoryBackend))) @@ -140,7 +141,7 @@ func TestHandler_StartExpenseAnalysis_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] require.NotEmpty(t, jobID) @@ -148,7 +149,7 @@ func TestHandler_StartExpenseAnalysis_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) assert.Equal(t, "1.0", getResp["AnalyzeExpenseModelVersion"]) docs, ok := getResp["ExpenseDocuments"].([]any) @@ -185,7 +186,7 @@ func TestHandler_AnalyzeExpense_SummaryFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["ExpenseDocuments"].([]any) require.True(t, ok) @@ -232,7 +233,7 @@ func TestHandler_AnalyzeExpense_LineItemGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, _ := resp["ExpenseDocuments"].([]any) require.NotEmpty(t, docs) @@ -264,7 +265,7 @@ func TestHandler_AnalyzeExpense_ExpenseIndex(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) docs, ok := m["ExpenseDocuments"].([]any) require.True(t, ok) require.NotEmpty(t, docs) @@ -290,7 +291,7 @@ func TestHandler_GetExpenseAnalysis_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] require.NotEmpty(t, jobID) @@ -298,7 +299,7 @@ func TestHandler_GetExpenseAnalysis_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m, jsonx.V1())) ver, ok := m["AnalyzeExpenseModelVersion"].(string) assert.True(t, ok, "GetExpenseAnalysis must have AnalyzeExpenseModelVersion") assert.Equal(t, "1.0", ver) @@ -344,14 +345,14 @@ func TestHandler_GetExpenseAnalysis_RejectsDocumentJobID(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetExpenseAnalysis", map[string]any{"JobId": jobID}) assert.Equal(t, http.StatusBadRequest, getRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidJobIdException", errResp["__type"], "expense analysis must not accept a document job ID") }) @@ -376,7 +377,7 @@ func TestHandler_AnalyzeExpense_CurrencyAndTypeWireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["ExpenseDocuments"].([]any) require.True(t, ok) @@ -453,7 +454,7 @@ func TestHandler_GetExpenseAnalysis_Pagination(t *testing.T) { NextToken string `json:"NextToken"` ExpenseDocuments []map[string]any `json:"ExpenseDocuments"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) assert.Len(t, resp1.ExpenseDocuments, 2) require.NotEmpty(t, resp1.NextToken, "first page must return a NextToken") @@ -467,7 +468,7 @@ func TestHandler_GetExpenseAnalysis_Pagination(t *testing.T) { NextToken string `json:"NextToken"` ExpenseDocuments []map[string]any `json:"ExpenseDocuments"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2.ExpenseDocuments, 3, "remaining 3 documents on the second page") assert.Empty(t, resp2.NextToken, "no more pages") } diff --git a/services/textract/handler_id_analysis_test.go b/services/textract/handler_id_analysis_test.go index f939855920..717705bbd5 100644 --- a/services/textract/handler_id_analysis_test.go +++ b/services/textract/handler_id_analysis_test.go @@ -1,12 +1,14 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_AnalyzeID(t *testing.T) { @@ -57,7 +59,7 @@ func TestHandler_AnalyzeID(t *testing.T) { if !tt.wantErr { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["IdentityDocuments"].([]any) assert.True(t, ok) assert.Len(t, docs, 2) @@ -83,7 +85,7 @@ func TestHandler_AnalyzeID_IdentityDocumentFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["IdentityDocuments"].([]any) require.True(t, ok) @@ -133,7 +135,7 @@ func TestHandler_AnalyzeID_NormalizedValueDate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, _ := resp["IdentityDocuments"].([]any) doc, _ := docs[0].(map[string]any) @@ -180,7 +182,7 @@ func TestHandler_AnalyzeID_DocumentIndex(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) docs, ok := m["IdentityDocuments"].([]any) require.True(t, ok) require.NotEmpty(t, docs) @@ -206,7 +208,7 @@ func TestHandler_AnalyzeID_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) ver, ok := m["AnalyzeIDModelVersion"].(string) assert.True(t, ok, "AnalyzeID response must have AnalyzeIDModelVersion") assert.Equal(t, "1.0", ver) @@ -227,7 +229,7 @@ func TestHandler_AnalyzeID_MultiPageDocumentIndex(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) docs, ok := m["IdentityDocuments"].([]any) require.True(t, ok) require.Len(t, docs, 2, "two DocumentPages should yield two IdentityDocuments") @@ -277,7 +279,7 @@ func TestHandler_AnalyzeID_DocumentMetadataPagesMatchesInputCount(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) meta, _ := resp["DocumentMetadata"].(map[string]any) gotPages, _ := meta["Pages"].(float64) assert.InDelta(t, float64(tc.pageCount), gotPages, 0, @@ -310,7 +312,7 @@ func TestHandler_AnalyzeID_NoFabricatedGeometry(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) docs, ok := resp["IdentityDocuments"].([]any) require.True(t, ok) diff --git a/services/textract/handler_lending_analysis_test.go b/services/textract/handler_lending_analysis_test.go index 32260ae93e..703b712df7 100644 --- a/services/textract/handler_lending_analysis_test.go +++ b/services/textract/handler_lending_analysis_test.go @@ -1,13 +1,14 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -55,7 +56,7 @@ func TestHandler_StartLendingAnalysis_ClientRequestTokenIdempotency(t *testing.T require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]string - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) jobID1 := resp1["JobId"] require.NotEmpty(t, jobID1) @@ -63,7 +64,7 @@ func TestHandler_StartLendingAnalysis_ClientRequestTokenIdempotency(t *testing.T require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, jobID1, resp2["JobId"], "same ClientRequestToken must return same JobId") assert.Equal(t, 1, textract.LendingJobCount(h.Backend.(*textract.InMemoryBackend))) @@ -83,7 +84,7 @@ func TestHandler_GetLendingAnalysisSummary_IncludesWarnings(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] textract.AddLendingJobInternal(b, &textract.LendingJob{ @@ -103,7 +104,7 @@ func TestHandler_GetLendingAnalysisSummary_IncludesWarnings(t *testing.T) { Pages []int `json:"Pages"` } `json:"Warnings"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Warnings, 1) assert.Equal(t, "InvalidPageException", resp.Warnings[0].ErrorCode) } @@ -123,14 +124,14 @@ func TestHandler_GetLendingAnalysis_ExpandedLendingResult(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetLendingAnalysis", map[string]any{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) results, ok := getResp["Results"].([]any) @@ -163,14 +164,14 @@ func TestHandler_GetLendingAnalysisSummary_PopulatedSummary(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetLendingAnalysisSummary", map[string]any{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) summary, ok := getResp["Summary"].(map[string]any) @@ -195,14 +196,14 @@ func TestHandler_GetLendingAnalysis_ModelVersion(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetLendingAnalysis", map[string]string{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var m map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &m, jsonx.V1())) ver, ok := m["AnalyzeLendingModelVersion"].(string) assert.True(t, ok, "GetLendingAnalysis must have AnalyzeLendingModelVersion") assert.Equal(t, "1.0", ver) @@ -224,7 +225,7 @@ func TestHandler_StartLendingAnalysis_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] require.NotEmpty(t, jobID) @@ -232,7 +233,7 @@ func TestHandler_StartLendingAnalysis_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", getResp["JobStatus"]) } @@ -264,14 +265,14 @@ func TestHandler_GetLendingAnalysisSummary_HappyPath(t *testing.T) { }) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] rec := doTextractRequest(t, h, "GetLendingAnalysisSummary", map[string]string{"JobId": jobID}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "SUCCEEDED", resp["JobStatus"]) assert.Equal(t, "1.0", resp["AnalyzeLendingModelVersion"]) } @@ -285,7 +286,7 @@ func TestHandler_GetLendingAnalysisSummary_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidJobIdException", errResp["__type"]) } @@ -308,14 +309,14 @@ func TestHandler_GetLendingAnalysis_LendingFieldWireShape(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetLendingAnalysis", map[string]any{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) results, ok := getResp["Results"].([]any) require.True(t, ok) @@ -372,14 +373,14 @@ func TestHandler_GetLendingAnalysis_PageClassificationUsesPrediction(t *testing. require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]string - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) jobID := startResp["JobId"] getRec := doTextractRequest(t, h, "GetLendingAnalysis", map[string]any{"JobId": jobID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) results, ok := getResp["Results"].([]any) require.True(t, ok) @@ -441,7 +442,7 @@ func TestHandler_GetLendingAnalysis_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Results []map[string]any `json:"Results"` } - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) assert.Len(t, resp1.Results, 2) require.NotEmpty(t, resp1.NextToken, "first page must return a NextToken") @@ -455,7 +456,7 @@ func TestHandler_GetLendingAnalysis_Pagination(t *testing.T) { NextToken string `json:"NextToken"` Results []map[string]any `json:"Results"` } - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Len(t, resp2.Results, 3, "remaining 3 results on the second page") assert.Empty(t, resp2.NextToken, "no more pages") } diff --git a/services/textract/handler_tags_test.go b/services/textract/handler_tags_test.go index ef98543190..c345450b8c 100644 --- a/services/textract/handler_tags_test.go +++ b/services/textract/handler_tags_test.go @@ -1,13 +1,14 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -22,7 +23,7 @@ func TestHandler_TagResource_HappyPath(t *testing.T) { "FeatureTypes": []string{"FORMS"}, }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] tagRec := doTextractRequest(t, h, "TagResource", map[string]any{ @@ -37,7 +38,7 @@ func TestHandler_TagResource_HappyPath(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) assert.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -56,7 +57,7 @@ func TestHandler_UntagResource_HappyPath(t *testing.T) { "Tags": map[string]string{"env": "dev", "team": "ml"}, }) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] untagRec := doTextractRequest(t, h, "UntagResource", map[string]any{ @@ -69,7 +70,7 @@ func TestHandler_UntagResource_HappyPath(t *testing.T) { "ResourceARN": adapterID, }) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["Tags"].(map[string]any) _, hasEnv := tags["env"] assert.False(t, hasEnv) @@ -93,7 +94,7 @@ func TestHandler_TagResource_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -129,7 +130,7 @@ func TestHandler_UntagResourceAndListTagsForResource_NotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) }) } @@ -150,7 +151,7 @@ func TestHandler_TagResource_ByARNRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]string - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) adapterID := createResp["AdapterId"] // Build an ARN using the backend helper. @@ -172,7 +173,7 @@ func TestHandler_TagResource_ByARNRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "prod", tags["env"]) @@ -194,7 +195,7 @@ func TestHandler_TagResource_AdapterVersionARN(t *testing.T) { require.Equal(t, http.StatusOK, createAdapterRec.Code) var createAdapterResp map[string]string - require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp)) + require.NoError(t, json.Unmarshal(createAdapterRec.Body.Bytes(), &createAdapterResp, jsonx.V1())) adapterID := createAdapterResp["AdapterId"] createVersionRec := doTextractRequest(t, h, "CreateAdapterVersion", map[string]any{ @@ -212,7 +213,7 @@ func TestHandler_TagResource_AdapterVersionARN(t *testing.T) { require.Equal(t, http.StatusOK, createVersionRec.Code) var createVersionResp map[string]string - require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp)) + require.NoError(t, json.Unmarshal(createVersionRec.Body.Bytes(), &createVersionResp, jsonx.V1())) adapterVersion := createVersionResp["AdapterVersion"] versionARN := b.BuildAdapterVersionARN(adapterID, adapterVersion) @@ -230,7 +231,7 @@ func TestHandler_TagResource_AdapterVersionARN(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].(map[string]any) require.True(t, ok) assert.Equal(t, "v1", tags["version-tag"]) diff --git a/services/textract/handler_test.go b/services/textract/handler_test.go index 196f205ebe..00f8f59d45 100644 --- a/services/textract/handler_test.go +++ b/services/textract/handler_test.go @@ -2,7 +2,7 @@ package textract_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -34,7 +35,7 @@ func doTextractRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -122,7 +123,7 @@ func TestHandler_UnknownAction_ErrorEnvelope(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ValidationException", errResp["__type"]) } @@ -214,7 +215,7 @@ func TestHandler_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) @@ -380,7 +381,7 @@ func TestHandler_HandleError_AdapterNotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -397,7 +398,7 @@ func TestHandler_HandleError_JobNotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidJobIdException", errResp["__type"]) } @@ -520,7 +521,7 @@ func TestHandler_ErrorEnvelope_TypeAndMessage(t *testing.T) { assert.GreaterOrEqual(t, rec.Code, http.StatusBadRequest) var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) assert.Equal(t, tt.wantType, m["__type"], "__type must match expected error code") assert.NotEmpty(t, m["message"], "message must be present in error envelope") }) diff --git a/services/textract/job_output_test.go b/services/textract/job_output_test.go index d2c45a3029..8cafc9579d 100644 --- a/services/textract/job_output_test.go +++ b/services/textract/job_output_test.go @@ -2,7 +2,7 @@ package textract_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "sync" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -109,7 +110,7 @@ func TestAsyncJobWritesOutputConfig(t *testing.T) { assert.Contains(t, w.objects, "out/pre/"+id+"/.s3_access_check") var page map[string]any - require.NoError(t, json.Unmarshal(w.objects["out/pre/"+id+"/1"], &page)) + require.NoError(t, json.Unmarshal(w.objects["out/pre/"+id+"/1"], &page, jsonx.V1())) assert.Contains(t, page, tt.wantKey) assert.Contains(t, page, "DocumentMetadata") diff --git a/services/textract/persistence.go b/services/textract/persistence.go index e00de2a504..390bb84291 100644 --- a/services/textract/persistence.go +++ b/services/textract/persistence.go @@ -2,7 +2,7 @@ package textract import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "time" @@ -117,7 +117,7 @@ func newDTORegistry() *dtoRegistry { // values are strings, not *T, so they do not fit store.Table's // keyed-by-identity-value shape and are unaffected by this conversion. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ClientTokenToJobID map[string]map[string]string `json:"clientTokenToJobId,omitempty"` AdapterClientTokenToID map[string]map[string]string `json:"adapterClientTokenToId,omitempty"` ExpenseClientTokenToJobID map[string]map[string]string `json:"expenseClientTokenToJobId,omitempty"` diff --git a/services/textract/persistence_test.go b/services/textract/persistence_test.go index b849634a86..929095bd94 100644 --- a/services/textract/persistence_test.go +++ b/services/textract/persistence_test.go @@ -2,11 +2,14 @@ package textract //nolint:testpackage // needs access to the unexported region c import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Test_PersistenceRoundTrip proves that every store.Table-backed resource @@ -201,11 +204,11 @@ func Test_PersistenceVersionMismatch(t *testing.T) { rewrite: func(t *testing.T, snap []byte) []byte { t.Helper() - var m map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &m)) + var m map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &m, jsonx.V1())) delete(m, "version") - out, err := json.Marshal(m) + out, err := json.Marshal(m, jsonx.V1()) require.NoError(t, err) return out @@ -264,16 +267,16 @@ func Test_PersistenceVersionMismatch(t *testing.T) { func rewriteSnapshotVersion(t *testing.T, snap []byte, version int) []byte { t.Helper() - var m map[string]json.RawMessage + var m map[string]jsontext.Value - require.NoError(t, json.Unmarshal(snap, &m)) + require.NoError(t, json.Unmarshal(snap, &m, jsonx.V1())) - versionJSON, err := json.Marshal(version) + versionJSON, err := json.Marshal(version, jsonx.V1()) require.NoError(t, err) m["version"] = versionJSON - out, err := json.Marshal(m) + out, err := json.Marshal(m, jsonx.V1()) require.NoError(t, err) return out diff --git a/services/textract/realism_test.go b/services/textract/realism_test.go index 2afde33da9..745a624b08 100644 --- a/services/textract/realism_test.go +++ b/services/textract/realism_test.go @@ -1,13 +1,15 @@ package textract_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestRealism_RequestValidation(t *testing.T) { @@ -92,7 +94,7 @@ func TestRealism_RequestValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) assert.Contains(t, resp["message"], tt.wantMsg) assert.NotContains(t, resp["message"], "Exception: ") diff --git a/services/textract/s3_object_test.go b/services/textract/s3_object_test.go index a96e632326..1082f40a0a 100644 --- a/services/textract/s3_object_test.go +++ b/services/textract/s3_object_test.go @@ -2,7 +2,7 @@ package textract_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "net/http" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/textract" ) @@ -100,7 +101,7 @@ func TestSyncDocumentOps_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doTextractRequest(t, h, tt.action, tt.body("good-bucket", "file.pdf")) @@ -125,7 +126,7 @@ func TestAnalyzeID_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doTextractRequest(t, h, "AnalyzeID", map[string]any{ @@ -174,7 +175,7 @@ func TestStartOps_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doTextractRequest(t, h, tt.action, body("good-bucket")) @@ -230,7 +231,7 @@ func createAdapterForS3Test(t *testing.T, h *textract.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["AdapterId"] } @@ -263,7 +264,7 @@ func TestCreateAdapterVersion_S3ObjectValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidS3ObjectException", resp["__type"]) rec = doTextractRequest(t, h, "CreateAdapterVersion", diff --git a/services/textract/s3_output.go b/services/textract/s3_output.go index c7beeb3244..32196112b7 100644 --- a/services/textract/s3_output.go +++ b/services/textract/s3_output.go @@ -3,13 +3,14 @@ package textract import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "path" "strings" "github.com/aws/aws-sdk-go-v2/aws" awss3 "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" s3backend "github.com/blackbirdworks/gopherstack/services/s3" ) @@ -87,7 +88,7 @@ func (b *InMemoryBackend) writeJobOutputLocked(cfg *OutputConfig, jobID string, return true } - body, err := json.Marshal(page) + body, err := json.Marshal(page, jsonx.V1()) if err != nil { return false } diff --git a/services/timestreaminfluxdb/docker_engine_ops_test.go b/services/timestreaminfluxdb/docker_engine_ops_test.go index 24bd69df7f..aacb8c7e38 100644 --- a/services/timestreaminfluxdb/docker_engine_ops_test.go +++ b/services/timestreaminfluxdb/docker_engine_ops_test.go @@ -1,7 +1,7 @@ package timestreaminfluxdb_test import ( - "encoding/json" + "encoding/json/jsontext" "os" "path/filepath" "testing" @@ -192,7 +192,7 @@ func TestParameterEnv(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - assert.Equal(t, tt.want, timestreaminfluxdb.ParameterEnv(json.RawMessage(tt.in))) + assert.Equal(t, tt.want, timestreaminfluxdb.ParameterEnv(jsontext.Value(tt.in))) }) } } diff --git a/services/timestreaminfluxdb/engine_ops_test.go b/services/timestreaminfluxdb/engine_ops_test.go index 8a83202322..448cf4187f 100644 --- a/services/timestreaminfluxdb/engine_ops_test.go +++ b/services/timestreaminfluxdb/engine_ops_test.go @@ -2,7 +2,7 @@ package timestreaminfluxdb_test import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "maps" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreaminfluxdb" ) @@ -273,7 +274,7 @@ func TestAuthParametersSecret(t *testing.T) { assert.Equal(t, arn, aws.ToString(got.InfluxAuthParametersSecretArn)) var secret map[string]string - require.NoError(t, json.Unmarshal([]byte(e.secrets.all()[arn]), &secret)) + require.NoError(t, json.Unmarshal([]byte(e.secrets.all()[arn]), &secret, jsonx.V1())) specs, _, _, _ := e.eng.snapshot() assert.Equal(t, map[string]string{ diff --git a/services/timestreaminfluxdb/engine_params.go b/services/timestreaminfluxdb/engine_params.go index 0ad52b6d50..d800823b49 100644 --- a/services/timestreaminfluxdb/engine_params.go +++ b/services/timestreaminfluxdb/engine_params.go @@ -1,13 +1,16 @@ package timestreaminfluxdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "slices" "strconv" "strings" "time" "unicode" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const hoursPerDay = 24 @@ -15,14 +18,14 @@ const hoursPerDay = 24 // ParameterEnv translates an InfluxDBv2 parameter group document into influxd environment settings. // Every InfluxDBv2 parameter has an influxd flag of the same name in kebab case (INFLUXD_); // groups for other engines are stored but not applied. -func ParameterEnv(raw json.RawMessage) []string { - var union map[string]json.RawMessage - if json.Unmarshal(raw, &union) != nil { +func ParameterEnv(raw jsontext.Value) []string { + var union map[string]jsontext.Value + if json.Unmarshal(raw, &union, jsonx.V1()) != nil { return nil } - var fields map[string]json.RawMessage - if json.Unmarshal(union["InfluxDBv2"], &fields) != nil { + var fields map[string]jsontext.Value + if json.Unmarshal(union["InfluxDBv2"], &fields, jsonx.V1()) != nil { return nil } @@ -54,13 +57,13 @@ func envName(param string) string { return sb.String() } -func paramValue(name string, raw json.RawMessage) (string, bool) { +func paramValue(name string, raw jsontext.Value) (string, bool) { if isDurationParam(name) { return durationValue(raw) } var v any - if json.Unmarshal(raw, &v) != nil { + if json.Unmarshal(raw, &v, jsonx.V1()) != nil { return "", false } @@ -76,12 +79,12 @@ func paramValue(name string, raw json.RawMessage) (string, bool) { return "", false } -func durationValue(raw json.RawMessage) (string, bool) { +func durationValue(raw jsontext.Value) (string, bool) { var d struct { DurationType string `json:"durationType"` Value int64 `json:"value"` } - if json.Unmarshal(raw, &d) != nil { + if json.Unmarshal(raw, &d, jsonx.V1()) != nil { return "", false } diff --git a/services/timestreaminfluxdb/handler.go b/services/timestreaminfluxdb/handler.go index 708974587a..277ee19cb6 100644 --- a/services/timestreaminfluxdb/handler.go +++ b/services/timestreaminfluxdb/handler.go @@ -2,7 +2,7 @@ package timestreaminfluxdb import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "slices" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -39,7 +40,7 @@ func bind[I, O any](fn func(*Handler, context.Context, *I) (*O, error)) opFunc { var in I if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, invalid("malformed request body: %v", err) } } diff --git a/services/timestreaminfluxdb/handler_other.go b/services/timestreaminfluxdb/handler_other.go index 334cbd731a..f5d6abce67 100644 --- a/services/timestreaminfluxdb/handler_other.go +++ b/services/timestreaminfluxdb/handler_other.go @@ -2,7 +2,7 @@ package timestreaminfluxdb import ( "context" - "encoding/json" + "encoding/json/jsontext" ) func registerGroupOps(ops map[string]opFunc) { @@ -15,7 +15,7 @@ type createGroupReq struct { Tags map[string]string `json:"tags"` Name string `json:"name"` Description string `json:"description"` - Parameters json.RawMessage `json:"parameters"` + Parameters jsontext.Value `json:"parameters"` } func (h *Handler) createGroup(ctx context.Context, in *createGroupReq) (*wParameterGroup, error) { diff --git a/services/timestreaminfluxdb/models.go b/services/timestreaminfluxdb/models.go index 8fcb08506b..7c70c494fa 100644 --- a/services/timestreaminfluxdb/models.go +++ b/services/timestreaminfluxdb/models.go @@ -1,7 +1,7 @@ package timestreaminfluxdb import ( - "encoding/json" + "encoding/json/jsontext" "time" ) @@ -149,7 +149,7 @@ type DBParameterGroup struct { Description string `json:"description,omitempty"` AccountID string `json:"accountId"` Region string `json:"region"` - Parameters json.RawMessage `json:"parameters,omitempty"` + Parameters jsontext.Value `json:"parameters,omitempty"` } // DBBackup is a backup of an instance or cluster. diff --git a/services/timestreaminfluxdb/parametergroups.go b/services/timestreaminfluxdb/parametergroups.go index 2929af5acc..c6a709cefc 100644 --- a/services/timestreaminfluxdb/parametergroups.go +++ b/services/timestreaminfluxdb/parametergroups.go @@ -3,7 +3,7 @@ package timestreaminfluxdb import ( "cmp" "context" - "encoding/json" + "encoding/json/jsontext" "slices" "github.com/blackbirdworks/gopherstack/pkgs/page" @@ -16,7 +16,7 @@ type GroupInput struct { Tags map[string]string Name string Description string - Parameters json.RawMessage + Parameters jsontext.Value } // CreateDBParameterGroup creates a parameter group. diff --git a/services/timestreaminfluxdb/persistence.go b/services/timestreaminfluxdb/persistence.go index 4b69fffcc7..3d8bb9960e 100644 --- a/services/timestreaminfluxdb/persistence.go +++ b/services/timestreaminfluxdb/persistence.go @@ -2,7 +2,7 @@ package timestreaminfluxdb import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -12,10 +12,10 @@ import ( const snapshotVersion = 1 type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serialises the backend state. diff --git a/services/timestreaminfluxdb/secrets.go b/services/timestreaminfluxdb/secrets.go index 36253ea804..ca0620948f 100644 --- a/services/timestreaminfluxdb/secrets.go +++ b/services/timestreaminfluxdb/secrets.go @@ -1,9 +1,10 @@ package timestreaminfluxdb import ( - "encoding/json" + "encoding/json/v2" "github.com/blackbirdworks/gopherstack/pkgs/awsid" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -39,7 +40,7 @@ func (b *InMemoryBackend) authSecretLocked(sc scope, id string, a authSecret) (s return "", nil } - body, err := json.Marshal(a) //nolint:gosec // the secret holds the credentials by design + body, err := json.Marshal(a, jsonx.V1()) //nolint:gosec // the secret holds the credentials by design if err != nil { return "", fail(ErrInternalServer, "encode auth secret") } diff --git a/services/timestreaminfluxdb/validate.go b/services/timestreaminfluxdb/validate.go index f05afcded1..1f70ff5abf 100644 --- a/services/timestreaminfluxdb/validate.go +++ b/services/timestreaminfluxdb/validate.go @@ -1,11 +1,14 @@ package timestreaminfluxdb import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "regexp" "slices" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -220,13 +223,13 @@ func validateListArgs(maxResults int32) error { } // validateParameters checks the union shape: one engine key holding a parameter object. -func validateParameters(raw json.RawMessage) error { +func validateParameters(raw jsontext.Value) error { if len(raw) == 0 { return nil } - var union map[string]json.RawMessage - if err := json.Unmarshal(raw, &union); err != nil || len(union) != 1 { + var union map[string]jsontext.Value + if err := json.Unmarshal(raw, &union, jsonx.V1()); err != nil || len(union) != 1 { return invalid("parameters must set exactly one of %s", strings.Join(paramGroups(), ", ")) } @@ -235,8 +238,8 @@ func validateParameters(raw json.RawMessage) error { return invalid("parameters must set exactly one of %s", strings.Join(paramGroups(), ", ")) } - var fields map[string]json.RawMessage - if err := json.Unmarshal(body, &fields); err != nil { + var fields map[string]jsontext.Value + if err := json.Unmarshal(body, &fields, jsonx.V1()); err != nil { return invalid("%s parameters must be an object", engine) } @@ -248,7 +251,7 @@ func validateParameters(raw json.RawMessage) error { return nil } -func validateParameterFields(engine string, fields map[string]json.RawMessage) error { +func validateParameterFields(engine string, fields map[string]jsontext.Value) error { for name, val := range fields { if !paramKeys[name] { return invalid("%s has no parameter named %q", engine, name) @@ -275,21 +278,21 @@ func validateParameterFields(engine string, fields map[string]json.RawMessage) e return nil } -func checkEnum(name string, raw json.RawMessage, allowed []string) error { +func checkEnum(name string, raw jsontext.Value, allowed []string) error { var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return invalid("%s must be a string", name) } return oneOf(name, s, allowed) } -func checkDuration(name string, raw json.RawMessage) error { +func checkDuration(name string, raw jsontext.Value) error { var d struct { Value *int64 `json:"value"` DurationType string `json:"durationType"` } - if err := json.Unmarshal(raw, &d); err != nil || d.Value == nil { + if err := json.Unmarshal(raw, &d, jsonx.V1()); err != nil || d.Value == nil { return invalid("%s must be a duration with durationType and value", name) } diff --git a/services/timestreaminfluxdb/wire.go b/services/timestreaminfluxdb/wire.go index 916d0d7a38..62e86e4d46 100644 --- a/services/timestreaminfluxdb/wire.go +++ b/services/timestreaminfluxdb/wire.go @@ -1,7 +1,7 @@ package timestreaminfluxdb import ( - "encoding/json" + "encoding/json/jsontext" "maps" "slices" "strings" @@ -129,11 +129,11 @@ type wClusterSummary struct { } type wParameterGroup struct { - Arn string `json:"arn"` - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description,omitempty"` - Parameters json.RawMessage `json:"parameters,omitempty"` + Arn string `json:"arn"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Parameters jsontext.Value `json:"parameters,omitempty"` } type wParameterGroupSummary struct { diff --git a/services/timestreamquery/column_info_marshal_test.go b/services/timestreamquery/column_info_marshal_test.go index 7f405f8d68..81ee388a6a 100644 --- a/services/timestreamquery/column_info_marshal_test.go +++ b/services/timestreamquery/column_info_marshal_test.go @@ -1,11 +1,13 @@ package timestreamquery //nolint:testpackage // needs unexported marshalColumnInfos for the wire-shape check. import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestMarshalColumnInfos_PreservesNestedUnion verifies that marshalColumnInfos @@ -95,12 +97,12 @@ func TestMarshalColumnInfos_PreservesNestedUnion(t *testing.T) { require.Len(t, marshalled, 1) // Round-trip through JSON, exactly as the handler's response does. - raw, err := json.Marshal(marshalled) + raw, err := json.Marshal(marshalled, jsonx.V1()) require.NoError(t, err) var decoded []map[string]any - require.NoError(t, json.Unmarshal(raw, &decoded)) + require.NoError(t, json.Unmarshal(raw, &decoded, jsonx.V1())) require.Len(t, decoded, 1) typ, ok := decoded[0]["Type"].(map[string]any) diff --git a/services/timestreamquery/handler.go b/services/timestreamquery/handler.go index 2b64e96643..b7290cc2ba 100644 --- a/services/timestreamquery/handler.go +++ b/services/timestreamquery/handler.go @@ -2,7 +2,7 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -161,7 +162,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { Name string `json:"Name"` } - if unmarshalErr := json.Unmarshal(body, &req); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &req, jsonx.V1()); unmarshalErr != nil { return "" } @@ -272,7 +273,7 @@ func (h *Handler) handleDescribeEndpoints(host string) ([]byte, error) { "CachePeriodInMinutes": endpointCachePeriod, }, }, - }) + }, jsonx.V1()) } func (h *Handler) handleError(c *echo.Context, err error) error { @@ -296,7 +297,7 @@ func errorPayload(errType, msg string) []byte { b, _ := json.Marshal(map[string]string{ "__type": errType, "message": msg, - }) + }, jsonx.V1()) return b } diff --git a/services/timestreamquery/handler_account_settings.go b/services/timestreamquery/handler_account_settings.go index 4af40c7836..85f9270add 100644 --- a/services/timestreamquery/handler_account_settings.go +++ b/services/timestreamquery/handler_account_settings.go @@ -2,14 +2,16 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleDescribeAccountSettings(ctx context.Context) ([]byte, error) { settings := h.Backend.DescribeAccountSettings(ctx) - return json.Marshal(buildAccountSettingsResponse(settings)) + return json.Marshal(buildAccountSettingsResponse(settings), jsonx.V1()) } func buildAccountSettingsResponse(settings AccountSettings) map[string]any { @@ -32,7 +34,7 @@ func (h *Handler) handlePrepareQuery(ctx context.Context, body []byte) ([]byte, ValidateOnly bool `json:"ValidateOnly"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -49,7 +51,7 @@ func (h *Handler) handlePrepareQuery(ctx context.Context, body []byte) ([]byte, "QueryString": result.QueryString, "Columns": marshalSelectColumns(result.Selected), "Parameters": marshalColumnInfos(result.Parameters), - }) + }, jsonx.V1()) } // updateAccountSettingsRequest is the parsed request body for @@ -119,7 +121,7 @@ func (nc *accountSettingsNotificationConfigWire) toModel() *AccountSettingsNotif func (h *Handler) handleUpdateAccountSettings(ctx context.Context, body []byte) ([]byte, error) { var req updateAccountSettingsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -130,7 +132,7 @@ func (h *Handler) handleUpdateAccountSettings(ctx context.Context, body []byte) return nil, err } - return json.Marshal(buildAccountSettingsResponse(settings)) + return json.Marshal(buildAccountSettingsResponse(settings), jsonx.V1()) } func marshalSelectColumns(cols []SelectColumn) []map[string]any { diff --git a/services/timestreamquery/handler_query_execution.go b/services/timestreamquery/handler_query_execution.go index a146ae5e6a..ff8cfe58cc 100644 --- a/services/timestreamquery/handler_query_execution.go +++ b/services/timestreamquery/handler_query_execution.go @@ -2,8 +2,10 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleQuery(ctx context.Context, body []byte) ([]byte, error) { @@ -17,7 +19,7 @@ func (h *Handler) handleQuery(ctx context.Context, body []byte) ([]byte, error) MaxRows int32 `json:"MaxRows"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -58,7 +60,7 @@ func (h *Handler) handleQuery(ctx context.Context, body []byte) ([]byte, error) resp["QueryInsightsResponse"] = page.Insights } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // marshalRows converts []Row to JSON-serialisable form. @@ -99,7 +101,7 @@ func (h *Handler) handleCancelQuery(ctx context.Context, body []byte) ([]byte, e QueryID string `json:"QueryId"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -113,5 +115,5 @@ func (h *Handler) handleCancelQuery(ctx context.Context, body []byte) ([]byte, e return json.Marshal(map[string]any{ "CancellationMessage": "Query has been successfully cancelled.", - }) + }, jsonx.V1()) } diff --git a/services/timestreamquery/handler_scheduled_queries.go b/services/timestreamquery/handler_scheduled_queries.go index 123cb33990..569f31cf75 100644 --- a/services/timestreamquery/handler_scheduled_queries.go +++ b/services/timestreamquery/handler_scheduled_queries.go @@ -2,9 +2,11 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // multiMeasureAttributeMappingInput mirrors types.MultiMeasureAttributeMapping. @@ -137,7 +139,7 @@ func convertMultiMeasureAttributeMappings( func (h *Handler) handleCreateScheduledQuery(ctx context.Context, body []byte) ([]byte, error) { var req createScheduledQueryInput - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -211,7 +213,7 @@ func (h *Handler) handleCreateScheduledQuery(ctx context.Context, body []byte) ( return json.Marshal(map[string]any{ keyArn: sq.Arn, - }) + }, jsonx.V1()) } func (h *Handler) handleDeleteScheduledQuery(ctx context.Context, body []byte) ([]byte, error) { @@ -219,7 +221,7 @@ func (h *Handler) handleDeleteScheduledQuery(ctx context.Context, body []byte) ( ScheduledQueryArn string `json:"ScheduledQueryArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -239,7 +241,7 @@ func (h *Handler) handleDescribeScheduledQuery(ctx context.Context, body []byte) ScheduledQueryArn string `json:"ScheduledQueryArn"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -254,7 +256,7 @@ func (h *Handler) handleDescribeScheduledQuery(ctx context.Context, body []byte) return json.Marshal(map[string]any{ "ScheduledQuery": scheduledQueryToView(sq), - }) + }, jsonx.V1()) } func (h *Handler) handleExecuteScheduledQuery(ctx context.Context, body []byte) ([]byte, error) { @@ -263,7 +265,7 @@ func (h *Handler) handleExecuteScheduledQuery(ctx context.Context, body []byte) InvocationTime float64 `json:"InvocationTime"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -290,7 +292,7 @@ func (h *Handler) handleListScheduledQueries(ctx context.Context, body []byte) ( MaxResults int32 `json:"MaxResults"` } if len(body) > 0 { - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) } if err := validateScheduledQueryPaging(req.NextToken, req.MaxResults); err != nil { @@ -306,7 +308,7 @@ func (h *Handler) handleListScheduledQueries(ctx context.Context, body []byte) ( resp["NextToken"] = result.NextToken } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } func (h *Handler) handleUpdateScheduledQuery(ctx context.Context, body []byte) ([]byte, error) { @@ -315,7 +317,7 @@ func (h *Handler) handleUpdateScheduledQuery(ctx context.Context, body []byte) ( State string `json:"State"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } diff --git a/services/timestreamquery/handler_tags.go b/services/timestreamquery/handler_tags.go index 02ba40296b..78efcec040 100644 --- a/services/timestreamquery/handler_tags.go +++ b/services/timestreamquery/handler_tags.go @@ -2,8 +2,10 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleTagResource(ctx context.Context, body []byte) ([]byte, error) { @@ -15,7 +17,7 @@ func (h *Handler) handleTagResource(ctx context.Context, body []byte) ([]byte, e } `json:"Tags"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -33,7 +35,7 @@ func (h *Handler) handleTagResource(ctx context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, error) { @@ -42,7 +44,7 @@ func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, TagKeys []string `json:"TagKeys"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -54,7 +56,7 @@ func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([]byte, error) { @@ -62,7 +64,7 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([ ResourceARN string `json:"ResourceARN"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("invalid request: %w", err) } @@ -77,5 +79,5 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([ return json.Marshal(map[string]any{ "Tags": tags, - }) + }, jsonx.V1()) } diff --git a/services/timestreamquery/handler_test.go b/services/timestreamquery/handler_test.go index 3e20f852ef..89b4d276bf 100644 --- a/services/timestreamquery/handler_test.go +++ b/services/timestreamquery/handler_test.go @@ -2,7 +2,7 @@ package timestreamquery_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/config" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamquery" ) @@ -38,7 +39,7 @@ func doRequest( var bodyBytes []byte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -80,7 +81,7 @@ func parseResponse(t *testing.T, rec *httptest.ResponseRecorder) map[string]any t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -238,7 +239,7 @@ func TestTimestreamQueryHandler_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() h := newTestHandler() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/", bytes.NewReader(bodyBytes)) e := echo.New() diff --git a/services/timestreamquery/persistence.go b/services/timestreamquery/persistence.go index c5a70c57a9..b1e84282d2 100644 --- a/services/timestreamquery/persistence.go +++ b/services/timestreamquery/persistence.go @@ -2,9 +2,11 @@ package timestreamquery import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -30,7 +32,7 @@ const timestreamquerySnapshotVersion = 1 // guards against decoding a snapshot from an incompatible (older or newer) // build of this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` AccountSettings map[string]accountSettingsSnapshot `json:"account_settings"` Version int `json:"version"` } @@ -84,7 +86,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { Version: timestreamquerySnapshotVersion, Tables: tables, AccountSettings: settingsSnap, - }) + }, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "timestreamquery: failed to marshal snapshot", "error", err) diff --git a/services/timestreamquery/query_execution_test.go b/services/timestreamquery/query_execution_test.go index 4f4756eab0..8c84fd42b9 100644 --- a/services/timestreamquery/query_execution_test.go +++ b/services/timestreamquery/query_execution_test.go @@ -1,13 +1,14 @@ package timestreamquery_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamquery" ) @@ -295,7 +296,7 @@ func TestCancelQuery_UnknownIDReturnsValidationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } diff --git a/services/timestreamquery/scheduled_queries_test.go b/services/timestreamquery/scheduled_queries_test.go index 2fe517f4aa..ae3c84ae6d 100644 --- a/services/timestreamquery/scheduled_queries_test.go +++ b/services/timestreamquery/scheduled_queries_test.go @@ -1,7 +1,7 @@ package timestreamquery_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamquery" ) @@ -565,7 +566,7 @@ func TestCreateScheduledQuery_ConflictReturns409(t *testing.T) { assert.Equal(t, http.StatusConflict, rec2.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ConflictException", errBody["__type"]) } @@ -629,7 +630,7 @@ func TestCreateScheduledQuery_RequiresNotificationAndErrorReport(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"], "error response must include __type") } }) diff --git a/services/timestreamquery/ts_meta.go b/services/timestreamquery/ts_meta.go index 132699a2e4..6a4859b14d 100644 --- a/services/timestreamquery/ts_meta.go +++ b/services/timestreamquery/ts_meta.go @@ -1,10 +1,12 @@ package timestreamquery import ( - "encoding/json" + "encoding/json/v2" "regexp" "sort" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func varcharResult(names []string, rows [][]string) *resultSet { @@ -188,7 +190,7 @@ func (b *InMemoryBackend) showMeasures(region, q string, src RecordSource) (*res dims = append(dims, map[string]string{"dimension_name": d, "data_type": types[d]}) } - enc, _ := json.Marshal(dims) + enc, _ := json.Marshal(dims, jsonx.V1()) rows = append(rows, []string{m.name, m.typ, string(enc)}) } diff --git a/services/timestreamwrite/handler.go b/services/timestreamwrite/handler.go index 24e93b8b2a..71c56bd86e 100644 --- a/services/timestreamwrite/handler.go +++ b/services/timestreamwrite/handler.go @@ -2,7 +2,7 @@ package timestreamwrite import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/ctxval" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -284,12 +285,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError var rejectedErr *RejectedRecordsError switch { @@ -316,8 +315,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, awserr.ErrInvalidParameter) || errors.Is(err, errInvalidRequest) || errors.Is(err, errUnknownAction) || - errors.As(err, &syntaxErr) || - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err) || + jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyTypeField: "ValidationException", keyMessageField: awserr.StripCode("ValidationException", err.Error()), diff --git a/services/timestreamwrite/handler_batch_load_tasks_test.go b/services/timestreamwrite/handler_batch_load_tasks_test.go index f06f40e985..3d29547254 100644 --- a/services/timestreamwrite/handler_batch_load_tasks_test.go +++ b/services/timestreamwrite/handler_batch_load_tasks_test.go @@ -1,7 +1,7 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamwrite" ) @@ -72,7 +73,7 @@ func TestHandler_CreateBatchLoadTask(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["TaskId"]) } }) @@ -102,7 +103,7 @@ func TestHandler_DescribeBatchLoadTask(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskID, _ := createResp["TaskId"].(string) require.NotEmpty(t, taskID) @@ -137,7 +138,7 @@ func TestHandler_DescribeBatchLoadTask(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp, jsonx.V1())) desc, ok := resp["BatchLoadTaskDescription"].(map[string]any) assert.True(t, ok) assert.Equal(t, taskID, desc["TaskId"]) @@ -207,7 +208,7 @@ func TestHandler_ListBatchLoadTasks(t *testing.T) { assert.Equal(t, tt.wantStatus, result.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(result.Body.Bytes(), &resp, jsonx.V1())) tasks, ok := resp["BatchLoadTasks"].([]any) assert.True(t, ok) assert.Len(t, tasks, tt.wantLen) @@ -238,7 +239,7 @@ func TestHandler_ResumeBatchLoadTask(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) taskID, _ := createResp["TaskId"].(string) require.NotEmpty(t, taskID) @@ -349,7 +350,7 @@ func TestHandler_CreateBatchLoadTask_DataSourceConfigRequired(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var errBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ValidationException", errBody["__type"]) } }) @@ -380,7 +381,7 @@ func TestHandler_CreateBatchLoadTask_WithDataSourceConfig(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) require.NotEmpty(t, taskID) @@ -388,7 +389,7 @@ func TestHandler_CreateBatchLoadTask_WithDataSourceConfig(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) desc := descOut["BatchLoadTaskDescription"].(map[string]any) dsc := desc["DataSourceConfiguration"].(map[string]any) @@ -424,14 +425,14 @@ func TestHandler_CreateBatchLoadTask_WithReportConfig(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) descRec := doRequest(t, h, "DescribeBatchLoadTask", map[string]string{"TaskId": taskID}) require.Equal(t, http.StatusOK, descRec.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) desc := descOut["BatchLoadTaskDescription"].(map[string]any) rpt := desc["ReportConfiguration"].(map[string]any) @@ -504,7 +505,7 @@ func TestHandler_ListBatchLoadTasks_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) tasks1 := out1["BatchLoadTasks"].([]any) assert.Len(t, tasks1, 2) @@ -516,7 +517,7 @@ func TestHandler_ListBatchLoadTasks_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) tasks2 := out2["BatchLoadTasks"].([]any) assert.Len(t, tasks2, 2) @@ -555,7 +556,7 @@ func TestHandler_ListBatchLoadTasks_StatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tasks := out["BatchLoadTasks"].([]any) assert.Len(t, tasks, 1) @@ -594,7 +595,7 @@ func TestHandler_ListBatchLoadTasks_SummaryResumableUntil(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tasks := out["BatchLoadTasks"].([]any) require.Len(t, tasks, 1) @@ -633,7 +634,7 @@ func TestHandler_DescribeBatchLoadTask_ErrorMessage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) desc := out["BatchLoadTaskDescription"].(map[string]any) assert.Equal(t, "S3 object not found", desc["ErrorMessage"]) @@ -660,14 +661,14 @@ func TestHandler_BatchLoadTaskDescriptionView_MissingResumableUntilOmitted(t *te require.Equal(t, http.StatusOK, cr.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) dr := doRequest(t, h, "DescribeBatchLoadTask", map[string]string{"TaskId": taskID}) require.Equal(t, http.StatusOK, dr.Code) var descOut map[string]any - require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &descOut, jsonx.V1())) desc := descOut["BatchLoadTaskDescription"].(map[string]any) _, hasResumable := desc["ResumableUntil"] @@ -698,7 +699,7 @@ func TestHandler_DescribeBatchLoadTask_RecordVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) desc := out["BatchLoadTaskDescription"].(map[string]any) assert.InDelta(t, float64(42), desc["RecordVersion"], 0, @@ -726,14 +727,14 @@ func TestHandler_DescribeBatchLoadTask_RecordVersionZeroOmitted(t *testing.T) { require.Equal(t, http.StatusOK, cr.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) dr := doRequest(t, h, "DescribeBatchLoadTask", map[string]string{"TaskId": taskID}) require.Equal(t, http.StatusOK, dr.Code) var out map[string]any - require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &out, jsonx.V1())) desc := out["BatchLoadTaskDescription"].(map[string]any) _, hasRV := desc["RecordVersion"] @@ -771,7 +772,7 @@ func TestHandler_DescribeBatchLoadTask_ProgressReport(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) desc := out["BatchLoadTaskDescription"].(map[string]any) report := desc["ProgressReport"].(map[string]any) @@ -803,14 +804,14 @@ func TestHandler_DescribeBatchLoadTask_NoProgressReport(t *testing.T) { require.Equal(t, http.StatusOK, cr.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(cr.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) dr := doRequest(t, h, "DescribeBatchLoadTask", map[string]string{"TaskId": taskID}) require.Equal(t, http.StatusOK, dr.Code) var out map[string]any - require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(dr.Body.Bytes(), &out, jsonx.V1())) desc := out["BatchLoadTaskDescription"].(map[string]any) _, hasPR := desc["ProgressReport"] @@ -840,14 +841,14 @@ func TestHandler_DescribeBatchLoadTask_TimestampsAreFloats(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) taskID := createOut["TaskId"].(string) rec2 := doRequest(t, h, "DescribeBatchLoadTask", map[string]any{"TaskId": taskID}) require.Equal(t, http.StatusOK, rec2.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &raw, jsonx.V1())) desc := raw["BatchLoadTaskDescription"].(map[string]any) ct, ok := desc["CreationTime"].(float64) diff --git a/services/timestreamwrite/handler_databases_test.go b/services/timestreamwrite/handler_databases_test.go index 881d7aa0f6..05fa63c23c 100644 --- a/services/timestreamwrite/handler_databases_test.go +++ b/services/timestreamwrite/handler_databases_test.go @@ -1,7 +1,7 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateDatabase(t *testing.T) { @@ -41,7 +43,7 @@ func TestHandler_CreateDatabase(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) db, ok := resp["Database"].(map[string]any) assert.True(t, ok) assert.Equal(t, "my-db", db["DatabaseName"]) @@ -65,7 +67,7 @@ func TestHandler_CreateDatabase_Conflict(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ConflictException", errBody["__type"]) } @@ -122,7 +124,7 @@ func TestHandler_ListDatabases(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dbs, ok := resp["Databases"].([]any) assert.True(t, ok) assert.Len(t, dbs, 2) @@ -141,7 +143,7 @@ func TestHandler_ListDatabases_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) dbs := out["Databases"].([]any) require.Len(t, dbs, 3) @@ -165,7 +167,7 @@ func TestHandler_ListDatabases_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) dbs1 := out1["Databases"].([]any) assert.Len(t, dbs1, 2) @@ -178,7 +180,7 @@ func TestHandler_ListDatabases_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) dbs2 := out2["Databases"].([]any) assert.Len(t, dbs2, 2) @@ -189,7 +191,7 @@ func TestHandler_ListDatabases_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var out3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &out3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &out3, jsonx.V1())) dbs3 := out3["Databases"].([]any) assert.Len(t, dbs3, 1) @@ -209,7 +211,7 @@ func TestHandler_ListDatabases_NoNextTokenWhenFits(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Empty(t, out["NextToken"]) } @@ -302,7 +304,7 @@ func TestHandler_DeleteDatabase_RequiresEmpty(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -417,7 +419,7 @@ func TestHandler_CreateDatabase_MinimumNameLength(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -489,7 +491,7 @@ func TestHandler_CreateDatabase_NameFormatValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -510,7 +512,7 @@ func TestHandler_CreateDatabase_NameValidationErrorBody(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) assert.NotEmpty(t, body["message"]) } @@ -577,7 +579,7 @@ func TestHandler_CreateDatabase_TagKeyValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -599,7 +601,7 @@ func TestHandler_CreateDatabase_WithKmsKeyID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createOut map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createOut, jsonx.V1())) db := createOut["Database"].(map[string]any) assert.Equal(t, kmsKey, db["KmsKeyId"]) @@ -622,7 +624,7 @@ func TestHandler_CreateDatabase_KmsKeyRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) db := out["Database"].(map[string]any) assert.Equal(t, kmsKey, db["KmsKeyId"], "KmsKeyId should survive DescribeDatabase") @@ -645,7 +647,7 @@ func TestHandler_ListDatabases_IncludesKmsKeyID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) dbs := out["Databases"].([]any) require.Len(t, dbs, 1) @@ -684,7 +686,7 @@ func TestHandler_CreateDatabase_ConflictException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ConflictException", body["__type"]) assert.NotEmpty(t, body["message"]) } @@ -703,7 +705,7 @@ func TestHandler_DescribeDatabase_TableCountTracking(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) db := out["Database"].(map[string]any) @@ -735,7 +737,7 @@ func TestHandler_CreateDatabase_ARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) db := out["Database"].(map[string]any) arn := db["Arn"].(string) @@ -759,7 +761,7 @@ func TestHandler_CreateDatabase_TimestampsAreFloats(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) db := raw["Database"].(map[string]any) ct, ok := db["CreationTime"].(float64) @@ -786,7 +788,7 @@ func TestHandler_CreateDatabase_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Fetch the ARN then list tags db := out["Database"].(map[string]any) @@ -798,7 +800,7 @@ func TestHandler_CreateDatabase_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].([]any) assert.Len(t, tags, 2) diff --git a/services/timestreamwrite/handler_endpoints_test.go b/services/timestreamwrite/handler_endpoints_test.go index 6f6345aca0..d73383e251 100644 --- a/services/timestreamwrite/handler_endpoints_test.go +++ b/services/timestreamwrite/handler_endpoints_test.go @@ -2,7 +2,7 @@ package timestreamwrite_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DescribeEndpoints(t *testing.T) { @@ -20,7 +22,7 @@ func TestHandler_DescribeEndpoints(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints, ok := resp["Endpoints"].([]any) assert.True(t, ok) assert.NotEmpty(t, endpoints) @@ -40,7 +42,7 @@ func TestHandler_DescribeEndpoints_CachePeriodIs1440(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) endpoints := out["Endpoints"].([]any) require.NotEmpty(t, endpoints) @@ -60,7 +62,7 @@ func TestHandler_DescribeEndpoints_CachePeriodPositive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) endpoints, ok := out["Endpoints"].([]any) require.True(t, ok) @@ -95,7 +97,7 @@ func TestHandler_DescribeEndpoints_EchoesRequestHost(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) endpoints := resp["Endpoints"].([]any) require.NotEmpty(t, endpoints) diff --git a/services/timestreamwrite/handler_internal_error_test.go b/services/timestreamwrite/handler_internal_error_test.go index 67659813f0..5548926aab 100644 --- a/services/timestreamwrite/handler_internal_error_test.go +++ b/services/timestreamwrite/handler_internal_error_test.go @@ -1,7 +1,7 @@ package timestreamwrite //nolint:testpackage // needs access to the unexported handleError method. import ( - "encoding/json" + "encoding/json/v2" "errors" "net/http" "net/http/httptest" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errUnmatchedForTest = errors.New("boom: matches none of handleError's sentinel checks") @@ -46,6 +48,6 @@ func TestHandleError_DefaultBranchEmitsInternalServerException(t *testing.T) { assert.Equal(t, http.StatusInternalServerError, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InternalServerException", body[keyTypeField]) } diff --git a/services/timestreamwrite/handler_records_test.go b/services/timestreamwrite/handler_records_test.go index f555fc289f..6402f0cca6 100644 --- a/services/timestreamwrite/handler_records_test.go +++ b/services/timestreamwrite/handler_records_test.go @@ -1,7 +1,7 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamwrite" ) @@ -149,7 +150,7 @@ func TestHandler_WriteRecords_RequiresMeasureName(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.NotEmpty(t, errResp["__type"], "error response must include __type") } @@ -369,7 +370,7 @@ func TestHandler_WriteRecords_InvalidMeasureValueType(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -450,7 +451,7 @@ func TestHandler_WriteRecords_InvalidTimeUnit(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -527,7 +528,7 @@ func TestHandler_WriteRecords_DimensionCountLimit(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -562,7 +563,7 @@ func TestHandler_WriteRecords_InvalidMeasureValueTypeViaCommonAttributes(t *test assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } @@ -594,7 +595,7 @@ func TestHandler_WriteRecords_InvalidTimeUnitViaCommonAttributes(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } @@ -683,7 +684,7 @@ func TestHandler_WriteRecords_MultiMeasure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 1, int(ingested["Total"].(float64))) @@ -722,7 +723,7 @@ func TestHandler_WriteRecords_CommonAttributes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 1, int(ingested["Total"].(float64))) @@ -770,7 +771,7 @@ func TestHandler_WriteRecords_CommonAttributesMerge(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 2, int(ingested["Total"].(float64))) @@ -814,7 +815,7 @@ func TestHandler_WriteRecords_CommonAttributesDimensionOverlapRejected(t *testin require.Equal(t, http.StatusBadRequest, rec.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "ValidationException", errBody["__type"]) } @@ -891,7 +892,7 @@ func TestHandler_WriteRecords_RejectedRecordsException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var errBody map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errBody, jsonx.V1())) assert.Equal(t, "RejectedRecordsException", errBody["__type"]) rejected, ok := errBody["RejectedRecords"].([]any) @@ -963,7 +964,7 @@ func TestHandler_WriteRecords_MaxRecordsLimit(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -988,7 +989,7 @@ func TestHandler_WriteRecords_EmptyBatch(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 0, int(ingested["Total"].(float64))) @@ -1035,7 +1036,7 @@ func TestHandler_WriteRecords_MagneticStoreInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 1, int(ingested["Total"].(float64))) @@ -1069,7 +1070,7 @@ func TestHandler_WriteRecords_ReturnsIngestedTotal(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, 2, int(ingested["Total"].(float64))) @@ -1097,7 +1098,7 @@ func TestHandler_WriteRecords_ReturnsMemoryStoreCount(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) ingested := out["RecordsIngested"].(map[string]any) assert.Equal(t, int(3), int(ingested["Total"].(float64))) diff --git a/services/timestreamwrite/handler_tables_test.go b/services/timestreamwrite/handler_tables_test.go index 769c5d3ac4..411b444d9c 100644 --- a/services/timestreamwrite/handler_tables_test.go +++ b/services/timestreamwrite/handler_tables_test.go @@ -1,7 +1,7 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamwrite" ) @@ -119,7 +120,7 @@ func TestHandler_ListTables(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tbls, ok := resp["Tables"].([]any) assert.True(t, ok) assert.Len(t, tbls, 2) @@ -150,7 +151,7 @@ func TestHandler_ListTables_DatabaseNameOptional(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tbls, ok := resp["Tables"].([]any) require.True(t, ok) assert.Len(t, tbls, 2) @@ -255,7 +256,7 @@ func TestHandler_ListTables_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbls := out["Tables"].([]any) require.Len(t, tbls, 2) @@ -278,7 +279,7 @@ func TestHandler_ListTables_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) tbls1 := out1["Tables"].([]any) assert.Len(t, tbls1, 2) @@ -294,7 +295,7 @@ func TestHandler_ListTables_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) tbls2 := out2["Tables"].([]any) assert.Len(t, tbls2, 1) @@ -323,7 +324,7 @@ func TestHandler_CreateTable_WithSchema(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) schema, ok := tbl["Schema"].(map[string]any) @@ -361,7 +362,7 @@ func TestHandler_DescribeTable_ReturnsSchema(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) schema, ok := tbl["Schema"].(map[string]any) @@ -394,7 +395,7 @@ func TestHandler_UpdateTable_WithSchema(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) schema := tbl["Schema"].(map[string]any) @@ -423,7 +424,7 @@ func TestHandler_ListTables_IncludesSchema(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tables := out["Tables"].([]any) require.Len(t, tables, 1) @@ -458,7 +459,7 @@ func TestHandler_CreateTable_MagneticStoreRejectedDataLocation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) mswp := tbl["MagneticStoreWriteProperties"].(map[string]any) @@ -501,7 +502,7 @@ func TestHandler_DescribeTable_MagneticStoreRejectedDataLocationRoundTrip(t *tes require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) mswp := tbl["MagneticStoreWriteProperties"].(map[string]any) @@ -578,7 +579,7 @@ func TestHandler_CreateTable_NameFormatValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -690,7 +691,7 @@ func TestHandler_CreateTable_RetentionPropertiesRangeValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -817,7 +818,7 @@ func TestHandler_CreateTable_PartitionKeyTypeValidation(t *testing.T) { if tt.wantStatus == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } }) @@ -846,7 +847,7 @@ func TestHandler_UpdateTable_PartitionKeyValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) // Valid DIMENSION with Name should succeed. @@ -879,7 +880,7 @@ func TestHandler_CreateTable_TagValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ValidationException", body["__type"]) } @@ -897,7 +898,7 @@ func TestHandler_CreateTable_ConflictException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ConflictException", body["__type"]) } @@ -916,7 +917,7 @@ func TestHandler_CreateTable_StatusActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) assert.Equal(t, "ACTIVE", tbl["TableStatus"]) @@ -941,7 +942,7 @@ func TestHandler_DescribeTable_StatusActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) assert.Equal(t, "ACTIVE", tbl["TableStatus"]) @@ -966,7 +967,7 @@ func TestHandler_ListTables_StatusActive(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tables := out["Tables"].([]any) require.Len(t, tables, 3) @@ -994,7 +995,7 @@ func TestHandler_CreateTable_ARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) arn := tbl["Arn"].(string) @@ -1018,7 +1019,7 @@ func TestHandler_CreateTable_TimestampsAreFloats(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) tbl := raw["Table"].(map[string]any) ct, ok := tbl["CreationTime"].(float64) @@ -1043,7 +1044,7 @@ func TestHandler_CreateTable_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) arn := tbl["Arn"].(string) @@ -1052,7 +1053,7 @@ func TestHandler_CreateTable_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].([]any) assert.Len(t, tags, 1) @@ -1081,7 +1082,7 @@ func TestHandler_CreateTable_RetentionProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) rp := tbl["RetentionProperties"].(map[string]any) @@ -1108,7 +1109,7 @@ func TestHandler_CreateTable_MagneticStoreWriteProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) mswp := tbl["MagneticStoreWriteProperties"].(map[string]any) @@ -1136,7 +1137,7 @@ func TestHandler_UpdateTable_RetentionProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) rp := tbl["RetentionProperties"].(map[string]any) @@ -1170,7 +1171,7 @@ func TestHandler_UpdateTable_MagneticStoreWriteProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) mswp := tbl["MagneticStoreWriteProperties"].(map[string]any) assert.Equal(t, true, mswp["EnableMagneticStoreWrites"]) @@ -1224,7 +1225,7 @@ func TestHandler_CreateTable_DefaultRetentionProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) rp := tbl["RetentionProperties"].(map[string]any) @@ -1250,7 +1251,7 @@ func TestHandler_CreateTable_NoPropertiesReturnsDefaults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) rp, hasRP := tbl["RetentionProperties"] @@ -1290,7 +1291,7 @@ func TestHandler_DescribeTable_RetentionAfterUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tbl := out["Table"].(map[string]any) rp := tbl["RetentionProperties"].(map[string]any) @@ -1318,7 +1319,7 @@ func TestHandler_ListTables_IncludesRetentionProperties(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) tables := out["Tables"].([]any) require.Len(t, tables, 1) diff --git a/services/timestreamwrite/handler_tags_test.go b/services/timestreamwrite/handler_tags_test.go index 3938c6e4f6..7bcf0b8c4c 100644 --- a/services/timestreamwrite/handler_tags_test.go +++ b/services/timestreamwrite/handler_tags_test.go @@ -1,13 +1,15 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_TagResource_UntagResource_ListTagsForResource(t *testing.T) { @@ -34,7 +36,7 @@ func TestHandler_TagResource_UntagResource_ListTagsForResource(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok := listResp["Tags"].([]any) assert.True(t, ok) assert.Len(t, tags, 2) @@ -48,7 +50,7 @@ func TestHandler_TagResource_UntagResource_ListTagsForResource(t *testing.T) { rec = doRequest(t, h, "ListTagsForResource", map[string]string{"ResourceARN": arn}) assert.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tags, ok = listResp["Tags"].([]any) assert.True(t, ok) assert.Len(t, tags, 1) @@ -96,7 +98,7 @@ func TestHandler_ListTagsForResource_Sorted(t *testing.T) { descRec := doRequest(t, h, "DescribeDatabase", map[string]any{"DatabaseName": "sort-db"}) var descOut map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) arn := descOut["Database"].(map[string]any)["Arn"].(string) doRequest(t, h, "TagResource", map[string]any{ @@ -112,7 +114,7 @@ func TestHandler_ListTagsForResource_Sorted(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var tagsOut map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &tagsOut, jsonx.V1())) tags := tagsOut["Tags"].([]any) require.Len(t, tags, 3) @@ -185,7 +187,7 @@ func TestHandler_TagResource_HTTP400OnUnknownARN(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -207,7 +209,7 @@ func TestHandler_TagResource_ScheduledQueryARN(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) require.Len(t, tags, 1) @@ -249,7 +251,7 @@ func TestHandler_ListTagsForResource_EmptyWhenNoTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Tags field should be present and empty (not absent). tags, ok := out["Tags"] @@ -287,7 +289,7 @@ func TestHandler_UntagResource_FromKnownARN(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) require.Len(t, tags, 1) @@ -327,7 +329,7 @@ func TestHandler_TagResource_CumulativeUpdates(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &out, jsonx.V1())) tags := out["Tags"].([]any) require.Len(t, tags, 2, "should have two distinct tags") diff --git a/services/timestreamwrite/handler_test.go b/services/timestreamwrite/handler_test.go index e732428fdd..7e47171be2 100644 --- a/services/timestreamwrite/handler_test.go +++ b/services/timestreamwrite/handler_test.go @@ -2,7 +2,7 @@ package timestreamwrite_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/timestreamwrite" ) @@ -78,7 +79,7 @@ func doRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/timestreamwrite/multi_region_test.go b/services/timestreamwrite/multi_region_test.go index 1c37796172..cb5a3a8398 100644 --- a/services/timestreamwrite/multi_region_test.go +++ b/services/timestreamwrite/multi_region_test.go @@ -2,7 +2,8 @@ package timestreamwrite_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/timestreamwrite" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/timestreamwrite/partition_key_enforcement_test.go b/services/timestreamwrite/partition_key_enforcement_test.go index cf091d750b..c0230b541b 100644 --- a/services/timestreamwrite/partition_key_enforcement_test.go +++ b/services/timestreamwrite/partition_key_enforcement_test.go @@ -1,12 +1,14 @@ package timestreamwrite_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_WriteRecords_RequiredPartitionKey(t *testing.T) { @@ -63,7 +65,7 @@ func TestHandler_WriteRecords_RequiredPartitionKey(t *testing.T) { if tt.wantRejected { var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Contains(t, out["RejectedRecords"].([]any)[0].(map[string]any)["Reason"], "region") } }) diff --git a/services/timestreamwrite/persistence.go b/services/timestreamwrite/persistence.go index 50cedf4c66..907fb25d82 100644 --- a/services/timestreamwrite/persistence.go +++ b/services/timestreamwrite/persistence.go @@ -2,10 +2,12 @@ package timestreamwrite import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" @@ -52,7 +54,7 @@ const timestreamwriteSnapshotVersion = 1 // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Records map[string]map[string][]Record `json:"records"` Tags map[string]map[string]string `json:"tags"` NextTaskID int `json:"next_task_id"` @@ -107,7 +109,7 @@ func (b *InMemoryBackend) Snapshot() ([]byte, error) { // Marshal failure is returned to the caller (the Persistable wrapper logs it // via the context-aware logger); do not log through slog.Default() here. - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { return nil, fmt.Errorf("timestreamwrite: marshal snapshot: %w", err) } diff --git a/services/transcribe/call_analytics_test.go b/services/transcribe/call_analytics_test.go index 98eb1e52dc..5f55131c5c 100644 --- a/services/transcribe/call_analytics_test.go +++ b/services/transcribe/call_analytics_test.go @@ -1,7 +1,8 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -515,7 +517,7 @@ func TestCallAnalyticsJobIncludesTranscriptURI(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) job, ok := resp["CallAnalyticsJob"].(map[string]any) require.True(t, ok, "CallAnalyticsJob must be present") @@ -557,7 +559,7 @@ func TestChannelId_JSONKey(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) job, _ := raw["CallAnalyticsJob"].(map[string]any) require.NotNil(t, job, "CallAnalyticsJob must be present") @@ -651,16 +653,21 @@ func TestCallAnalyticsCategory_CreateTimeAndLastUpdateTimeEchoed(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createRaw struct { - CategoryProperties map[string]json.RawMessage `json:"CategoryProperties"` + CategoryProperties map[string]jsontext.Value `json:"CategoryProperties"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw, jsonx.V1())) for _, field := range []string{"CreateTime", "LastUpdateTime"} { val, ok := createRaw.CategoryProperties[field] require.True(t, ok, "expected field %s in CreateCallAnalyticsCategory response", field) - var num json.Number - require.NoError(t, json.Unmarshal(val, &num), "field %s must be a JSON number (epoch seconds)", field) + var num jsonx.Number + require.NoError( + t, + json.Unmarshal(val, &num, jsonx.V1()), + "field %s must be a JSON number (epoch seconds)", + field, + ) } updateRec := doTranscribeRequest(t, h, "UpdateCallAnalyticsCategory", map[string]any{ @@ -673,9 +680,9 @@ func TestCallAnalyticsCategory_CreateTimeAndLastUpdateTimeEchoed(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateRaw struct { - CategoryProperties map[string]json.RawMessage `json:"CategoryProperties"` + CategoryProperties map[string]jsontext.Value `json:"CategoryProperties"` } - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw, jsonx.V1())) assert.Contains(t, updateRaw.CategoryProperties, "LastUpdateTime") } @@ -706,9 +713,9 @@ func TestListCallAnalyticsJobs_JobNameContainsAndStartTime(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var raw struct { - CallAnalyticsJobSummaries []map[string]json.RawMessage `json:"CallAnalyticsJobSummaries"` + CallAnalyticsJobSummaries []map[string]jsontext.Value `json:"CallAnalyticsJobSummaries"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.CallAnalyticsJobSummaries, 1) assert.Contains(t, raw.CallAnalyticsJobSummaries[0], "StartTime") } diff --git a/services/transcribe/handler.go b/services/transcribe/handler.go index b93734b9e0..92b599043c 100644 --- a/services/transcribe/handler.go +++ b/services/transcribe/handler.go @@ -2,7 +2,7 @@ package transcribe import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -106,7 +107,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var req extractResourceRequest - if jsonErr := json.Unmarshal(body, &req); jsonErr != nil { + if jsonErr := json.Unmarshal(body, &req, jsonx.V1()); jsonErr != nil { return "" } @@ -215,20 +216,17 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrNotFound): return c.JSON(http.StatusNotFound, errorBody("NotFoundException", errMessage(err))) case errors.Is(err, awserr.ErrAlreadyExists): return c.JSON(http.StatusConflict, errorBody("ConflictException", errMessage(err))) case errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, errorBody("BadRequestException", errMessage(err))) case errors.Is(err, errUnknownAction): return c.JSON(http.StatusBadRequest, errorBody("UnknownOperationException", errMessage(err))) diff --git a/services/transcribe/handler_test.go b/services/transcribe/handler_test.go index 020306fe75..1da37a246e 100644 --- a/services/transcribe/handler_test.go +++ b/services/transcribe/handler_test.go @@ -2,7 +2,8 @@ package transcribe_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -35,7 +37,7 @@ func newHandlerWithBackend(t *testing.T) (*transcribe.Handler, *transcribe.InMem func doTranscribeRequest(t *testing.T, h *transcribe.Handler, action string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -502,7 +504,7 @@ func TestTranscribe_BadParams_NotInternalFailure(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"], "expected %s, not InternalFailureException", tt.wantType) }) @@ -671,13 +673,13 @@ func TestTranscribe_TimestampFields_AreJSONNumbers(t *testing.T) { rec := doTranscribeRequest(t, h, tt.action, tt.body) require.Equal(t, http.StatusOK, rec.Code) - var raw map[string]json.RawMessage - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + var raw map[string]jsontext.Value + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) // The response wraps the resource under a single top-level key; find it. - var inner map[string]json.RawMessage + var inner map[string]jsontext.Value for _, v := range raw { - _ = json.Unmarshal(v, &inner) + _ = json.Unmarshal(v, &inner, jsonx.V1()) if inner != nil { break @@ -689,8 +691,8 @@ func TestTranscribe_TimestampFields_AreJSONNumbers(t *testing.T) { val, ok := inner[field] require.True(t, ok, "expected field %s in response %s", field, rec.Body.String()) - var num json.Number - err := json.Unmarshal(val, &num) + var num jsonx.Number + err := json.Unmarshal(val, &num, jsonx.V1()) assert.NoError(t, err, "field %s must decode as a JSON number (epoch seconds), got %s", field, val) } }) diff --git a/services/transcribe/language_models_test.go b/services/transcribe/language_models_test.go index 8014cb228d..d4ec69f7b3 100644 --- a/services/transcribe/language_models_test.go +++ b/services/transcribe/language_models_test.go @@ -1,13 +1,15 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -289,7 +291,7 @@ func TestDescribeLanguageModel_TimeFields(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) lm, _ := raw["LanguageModel"].(map[string]any) require.NotNil(t, lm, "LanguageModel must be present") @@ -320,7 +322,7 @@ func TestDescribeLanguageModel_UpgradeAvailability(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) lm, _ := raw["LanguageModel"].(map[string]any) require.NotNil(t, lm) @@ -354,16 +356,16 @@ func TestDescribeLanguageModel_TimestampFieldsAreJSONNumbers(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var out struct { - LanguageModel map[string]json.RawMessage `json:"LanguageModel"` + LanguageModel map[string]jsontext.Value `json:"LanguageModel"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) for _, field := range []string{"CreateTime", "LastModifiedTime"} { val, ok := out.LanguageModel[field] require.True(t, ok, "expected field %s in response %s", field, rec.Body.String()) - var num json.Number - err := json.Unmarshal(val, &num) + var num jsonx.Number + err := json.Unmarshal(val, &num, jsonx.V1()) assert.NoError(t, err, "field %s must decode as a JSON number (epoch seconds), got %s", field, val) } } @@ -436,7 +438,7 @@ func TestCreateLanguageModel_EchoesInputDataConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) cfg, ok := raw["InputDataConfig"].(map[string]any) require.True(t, ok, "CreateLanguageModelOutput must echo InputDataConfig") assert.Equal(t, "s3://my-bucket/training/", cfg["S3Uri"]) diff --git a/services/transcribe/medical_scribe_test.go b/services/transcribe/medical_scribe_test.go index aa97e6bb99..02660a619d 100644 --- a/services/transcribe/medical_scribe_test.go +++ b/services/transcribe/medical_scribe_test.go @@ -1,13 +1,15 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -292,9 +294,9 @@ func TestListMedicalScribeJobs_JobNameContainsAndSummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var raw struct { - MedicalScribeJobSummaries []map[string]json.RawMessage `json:"MedicalScribeJobSummaries"` + MedicalScribeJobSummaries []map[string]jsontext.Value `json:"MedicalScribeJobSummaries"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.MedicalScribeJobSummaries, 1) summary := raw.MedicalScribeJobSummaries[0] @@ -334,7 +336,7 @@ func TestMedicalScribeJob_OutputURIsPresentWhenCompleted(t *testing.T) { } `json:"MedicalScribeOutput"` } `json:"MedicalScribeJob"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw, jsonx.V1())) assert.Contains(t, raw.MedicalScribeJob.MedicalScribeOutput.ClinicalDocumentURI, "scribe-output-bucket") assert.Contains(t, raw.MedicalScribeJob.MedicalScribeOutput.TranscriptFileURI, "scribe-output-bucket") } diff --git a/services/transcribe/medical_transcription_jobs_test.go b/services/transcribe/medical_transcription_jobs_test.go index ff4777b6d3..e552ccbf4d 100644 --- a/services/transcribe/medical_transcription_jobs_test.go +++ b/services/transcribe/medical_transcription_jobs_test.go @@ -1,7 +1,8 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -121,7 +123,7 @@ func TestHTTP_StartMedicalTranscriptionJob_ContentIdentificationType(t *testing. require.Equal(t, http.StatusOK, rec.Code) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) job := out["MedicalTranscriptionJob"].(map[string]any) assert.Equal(t, "PHI", job["ContentIdentificationType"]) } @@ -272,7 +274,7 @@ func TestMedicalTranscriptionJobTranscriptURI(t *testing.T) { } `json:"Transcript"` } `json:"MedicalTranscriptionJob"` } - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &out, jsonx.V1())) uri := out.MedicalTranscriptionJob.Transcript.TranscriptFileURI assert.NotEmpty(t, uri, "Transcript.TranscriptFileURI must not be empty") @@ -312,7 +314,7 @@ func TestStartMedicalTranscriptionJob_TranscriptURIInStartResponse(t *testing.T) } `json:"Transcript"` } `json:"MedicalTranscriptionJob"` } - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &out, jsonx.V1())) uri := out.MedicalTranscriptionJob.Transcript.TranscriptFileURI assert.NotEmpty(t, uri, "StartMedicalTranscriptionJob response must include TranscriptFileUri") @@ -369,9 +371,9 @@ func TestListMedicalTranscriptionJobs_JobNameContainsAndSummaryShape(t *testing. require.Equal(t, http.StatusOK, listRec.Code) var raw struct { - MedicalTranscriptionJobSummaries []map[string]json.RawMessage `json:"MedicalTranscriptionJobSummaries"` + MedicalTranscriptionJobSummaries []map[string]jsontext.Value `json:"MedicalTranscriptionJobSummaries"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &raw, jsonx.V1())) require.Len(t, raw.MedicalTranscriptionJobSummaries, 1) summary := raw.MedicalTranscriptionJobSummaries[0] @@ -380,6 +382,6 @@ func TestListMedicalTranscriptionJobs_JobNameContainsAndSummaryShape(t *testing. assert.NotContains(t, summary, "Tags", "MedicalTranscriptionJobSummary must not include Tags") var outputLocationType string - require.NoError(t, json.Unmarshal(summary["OutputLocationType"], &outputLocationType)) + require.NoError(t, json.Unmarshal(summary["OutputLocationType"], &outputLocationType, jsonx.V1())) assert.Equal(t, "CUSTOMER_BUCKET", outputLocationType) } diff --git a/services/transcribe/medical_vocabularies_test.go b/services/transcribe/medical_vocabularies_test.go index eb61bc2c16..645d396562 100644 --- a/services/transcribe/medical_vocabularies_test.go +++ b/services/transcribe/medical_vocabularies_test.go @@ -1,13 +1,14 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -160,7 +161,7 @@ func TestGetMedicalVocabulary_NotFound(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "BadRequestException", body["__type"]) }) } @@ -201,7 +202,7 @@ func TestMedicalVocabulary_LastModifiedTimeAndFailureReason(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createRaw map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw, jsonx.V1())) assert.Contains(t, createRaw, "LastModifiedTime") getRec := doTranscribeRequest(t, h, "GetMedicalVocabulary", map[string]any{ @@ -210,7 +211,7 @@ func TestMedicalVocabulary_LastModifiedTimeAndFailureReason(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getRaw map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw, jsonx.V1())) _, hasFailureReason := getRaw["FailureReason"] assert.False(t, hasFailureReason, "FailureReason must be omitted (empty) on success") @@ -221,6 +222,6 @@ func TestMedicalVocabulary_LastModifiedTimeAndFailureReason(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code) var updateRaw map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw, jsonx.V1())) assert.Contains(t, updateRaw, "LastModifiedTime") } diff --git a/services/transcribe/multi_region_test.go b/services/transcribe/multi_region_test.go index 45aa198007..c3410b63f6 100644 --- a/services/transcribe/multi_region_test.go +++ b/services/transcribe/multi_region_test.go @@ -2,7 +2,8 @@ package transcribe_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -182,8 +184,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/transcribe/persistence.go b/services/transcribe/persistence.go index 0ba1cd05cb..d647308592 100644 --- a/services/transcribe/persistence.go +++ b/services/transcribe/persistence.go @@ -2,9 +2,11 @@ package transcribe import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -34,7 +36,7 @@ const transcribeSnapshotVersion = 2 // decoding a snapshot from an incompatible (older or newer) build of this // backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourceTags map[string]map[string]string `json:"resourceTags"` Version int `json:"version"` } @@ -57,7 +59,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { b.mu.RLock("Snapshot") defer b.mu.RUnlock() - var tables map[string]json.RawMessage + var tables map[string]jsontext.Value tables, tblErr = b.registry.SnapshotAll() @@ -74,7 +76,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { return nil } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "transcribe: failed to marshal snapshot", "error", err) diff --git a/services/transcribe/realism_test.go b/services/transcribe/realism_test.go index d3cf01ac9c..6d14402b79 100644 --- a/services/transcribe/realism_test.go +++ b/services/transcribe/realism_test.go @@ -1,7 +1,7 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "testing" "testing/synctest" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -115,7 +116,7 @@ func TestRealism_RequestValidation(t *testing.T) { rec := doTranscribeRequest(t, newTestTranscribeHandler(t), tt.action, tt.body) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) assert.Contains(t, resp["message"], tt.wantMsg) assert.NotContains(t, resp["message"], "Exception: ") diff --git a/services/transcribe/s3_output_test.go b/services/transcribe/s3_output_test.go index f7cbea84f4..82dc9c203f 100644 --- a/services/transcribe/s3_output_test.go +++ b/services/transcribe/s3_output_test.go @@ -2,7 +2,8 @@ package transcribe_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "sync" "testing" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -84,10 +86,10 @@ func TestTranscriptionJobWritesOutput(t *testing.T) { Transcripts []struct { Transcript string `json:"transcript"` } `json:"transcripts"` - Items []json.RawMessage `json:"items"` + Items []jsontext.Value `json:"items"` } `json:"results"` } - require.NoError(t, json.Unmarshal(w.objects[tt.wantKey], &doc)) + require.NoError(t, json.Unmarshal(w.objects[tt.wantKey], &doc, jsonx.V1())) assert.Equal(t, "j", doc.JobName) assert.Equal(t, "COMPLETED", doc.Status) assert.NotEmpty(t, doc.Results.Transcripts) @@ -146,7 +148,7 @@ func TestCallAnalyticsJobWritesOutput(t *testing.T) { } var doc map[string]any - require.NoError(t, json.Unmarshal(w.objects[tt.wantKey], &doc)) + require.NoError(t, json.Unmarshal(w.objects[tt.wantKey], &doc, jsonx.V1())) assert.Equal(t, "COMPLETED", doc["JobStatus"]) assert.NotEmpty(t, doc["Transcript"]) assert.NotEmpty(t, doc["Participants"]) diff --git a/services/transcribe/tags_test.go b/services/transcribe/tags_test.go index f8f96d0225..b1f583a9b2 100644 --- a/services/transcribe/tags_test.go +++ b/services/transcribe/tags_test.go @@ -1,13 +1,14 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -307,7 +308,7 @@ func TestHTTP_ListTagsForResource_ReturnsStoredTags(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagMap := make(map[string]string, len(resp.Tags)) for _, tag := range resp.Tags { tagMap[tag.Key] = tag.Value @@ -344,7 +345,7 @@ func TestHTTP_UntagResource(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagMap := make(map[string]string, len(resp.Tags)) for _, tag := range resp.Tags { tagMap[tag.Key] = tag.Value diff --git a/services/transcribe/transcript_synthesis.go b/services/transcribe/transcript_synthesis.go index fc8a8bc5e6..9c91ea9f3d 100644 --- a/services/transcribe/transcript_synthesis.go +++ b/services/transcribe/transcript_synthesis.go @@ -1,9 +1,11 @@ package transcribe import ( - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // syntheticWordBaseDuration is the base duration in seconds for synthetic word timing. @@ -17,7 +19,7 @@ const syntheticWordGap = 0.05 // marshalJSON marshals v to JSON bytes, returning nil on error (only used for synthetic output). func marshalJSON(v any) ([]byte, error) { - return json.Marshal(v) + return json.Marshal(v, jsonx.V1()) } // deriveTranscriptText produces a transcript string from the job name and media URI. diff --git a/services/transcribe/transcription_jobs_test.go b/services/transcribe/transcription_jobs_test.go index de1ac43899..487737e88c 100644 --- a/services/transcribe/transcription_jobs_test.go +++ b/services/transcribe/transcription_jobs_test.go @@ -1,7 +1,7 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -898,7 +899,7 @@ func TestListTranscriptionJobsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, summariesOK := resp["TranscriptionJobSummaries"].([]any) require.True(t, summariesOK) @@ -919,7 +920,7 @@ func TestListTranscriptionJobsPagination(t *testing.T) { assert.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) summaries2, summaries2OK := resp2["TranscriptionJobSummaries"].([]any) require.True(t, summaries2OK) @@ -1069,7 +1070,7 @@ func TestMediaFileUri_JSONKey(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) job, _ := raw["TranscriptionJob"].(map[string]any) require.NotNil(t, job, "TranscriptionJob must be present") @@ -1102,7 +1103,7 @@ func TestTranscriptionJob_MediaInResponse(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &raw, jsonx.V1())) job, _ := raw["TranscriptionJob"].(map[string]any) require.NotNil(t, job) @@ -1131,7 +1132,7 @@ func TestTranscriptionJob_OutputBucketNotInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) job, _ := raw["TranscriptionJob"].(map[string]any) require.NotNil(t, job) @@ -1194,7 +1195,7 @@ func TestTranscriptionJob_LanguageIdSettings_Echoed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) job, _ := raw["TranscriptionJob"].(map[string]any) require.NotNil(t, job) diff --git a/services/transcribe/vocabularies_test.go b/services/transcribe/vocabularies_test.go index 2dcb0f5ece..26f810a331 100644 --- a/services/transcribe/vocabularies_test.go +++ b/services/transcribe/vocabularies_test.go @@ -1,7 +1,7 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -278,7 +279,7 @@ func TestGetVocabulary_DownloadUri(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw, jsonx.V1())) assert.NotEmpty(t, raw["DownloadUri"], "DownloadUri must be present in GetVocabulary response") } @@ -301,7 +302,7 @@ func TestGetVocabulary_LastModifiedTime(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var raw map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &raw, jsonx.V1())) assert.NotNil(t, raw["LastModifiedTime"], "LastModifiedTime must be present in GetVocabulary response") } @@ -464,7 +465,7 @@ func TestCreateVocabulary_LastModifiedTimeAndFailureReasonEchoed(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) _, hasLastModified := raw["LastModifiedTime"] assert.True(t, hasLastModified, "CreateVocabularyOutput must include LastModifiedTime") @@ -488,6 +489,6 @@ func TestListVocabularies_EchoesStatusFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var raw map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &raw, jsonx.V1())) assert.Equal(t, "READY", raw["Status"]) } diff --git a/services/transcribe/vocabulary_filters_test.go b/services/transcribe/vocabulary_filters_test.go index eb4b4ac4fb..dd099ab53b 100644 --- a/services/transcribe/vocabulary_filters_test.go +++ b/services/transcribe/vocabulary_filters_test.go @@ -1,13 +1,14 @@ package transcribe_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transcribe" ) @@ -340,7 +341,7 @@ func TestVocabularyFilter_LastModifiedTimeAndDownloadUri(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createRaw map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createRaw, jsonx.V1())) assert.Contains(t, createRaw, "LastModifiedTime", "CreateVocabularyFilterOutput must include LastModifiedTime") getRec := doTranscribeRequest(t, h, "GetVocabularyFilter", map[string]any{ @@ -349,7 +350,7 @@ func TestVocabularyFilter_LastModifiedTimeAndDownloadUri(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, getRec.Body.String()) var getRaw map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRaw, jsonx.V1())) assert.Contains(t, getRaw, "LastModifiedTime", "GetVocabularyFilterOutput must include LastModifiedTime") assert.Equal(t, "s3://bucket/filter.txt", getRaw["DownloadUri"]) @@ -360,6 +361,6 @@ func TestVocabularyFilter_LastModifiedTimeAndDownloadUri(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code, updateRec.Body.String()) var updateRaw map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateRaw, jsonx.V1())) assert.Contains(t, updateRaw, "LastModifiedTime", "UpdateVocabularyFilterOutput must include LastModifiedTime") } diff --git a/services/transfer/handler.go b/services/transfer/handler.go index 29e3f9c55c..e99c7501a9 100644 --- a/services/transfer/handler.go +++ b/services/transfer/handler.go @@ -2,7 +2,7 @@ package transfer import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/collections" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" @@ -221,7 +222,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { ServerID string `json:"ServerId"` UserName string `json:"UserName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.ServerID != "" && req.UserName != "" { return req.ServerID + "/" + req.UserName @@ -340,13 +341,10 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, errInvalidNextToken): return c.JSON(http.StatusBadRequest, map[string]string{ @@ -366,8 +364,8 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err case errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownAction), - errors.As(err, &syntaxErr), - errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), + jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyTypeField: "InvalidRequestException", keyMessageField: publicMessage(err), diff --git a/services/transfer/handler_access_test.go b/services/transfer/handler_access_test.go index 14f7df68f3..464d323a65 100644 --- a/services/transfer/handler_access_test.go +++ b/services/transfer/handler_access_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -26,7 +27,7 @@ func TestHandler_UpdateAccessFullFieldsRoundtrip(t *testing.T) { var srvOut struct { ServerID string `json:"ServerId"` } - require.NoError(t, json.Unmarshal(createSrvRec.Body.Bytes(), &srvOut)) + require.NoError(t, json.Unmarshal(createSrvRec.Body.Bytes(), &srvOut, jsonx.V1())) createAccessRec := doTransferRequest(t, h, "CreateAccess", map[string]any{ "ServerId": srvOut.ServerID, @@ -65,7 +66,7 @@ func TestHandler_UpdateAccessFullFieldsRoundtrip(t *testing.T) { Policy string `json:"Policy"` } `json:"Access"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "LOGICAL", descOut.Access.HomeDirectoryType) assert.JSONEq(t, `{"Version":"2012-10-17","Statement":[]}`, descOut.Access.Policy) @@ -118,7 +119,7 @@ func TestHandler_ListAccessesIncludesHomeDirectoryType(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) accesses := listResp["Accesses"].([]any) require.Len(t, accesses, 1) @@ -167,7 +168,7 @@ func TestHandler_CreateAccess(t *testing.T) { if tt.wantKey != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantKey]) } }) @@ -302,7 +303,7 @@ func TestHandler_DescribeAccess(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Access"]) } @@ -381,7 +382,7 @@ func TestHandler_CreateAccessPosixProfile(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) access := descResp["Access"].(map[string]any) posix := access["PosixProfile"].(map[string]any) diff --git a/services/transfer/handler_agreements_test.go b/services/transfer/handler_agreements_test.go index 8f7b8ea524..2a59af863e 100644 --- a/services/transfer/handler_agreements_test.go +++ b/services/transfer/handler_agreements_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -23,7 +24,7 @@ func TestHandler_DescribeAgreementIncludesArnAndTags(t *testing.T) { }) require.Equal(t, http.StatusOK, localRec.Code) var localResp map[string]any - require.NoError(t, json.Unmarshal(localRec.Body.Bytes(), &localResp)) + require.NoError(t, json.Unmarshal(localRec.Body.Bytes(), &localResp, jsonx.V1())) localProfileID := localResp["ProfileId"].(string) partnerRec := doTransferRequest(t, h, "CreateProfile", map[string]any{ @@ -31,13 +32,13 @@ func TestHandler_DescribeAgreementIncludesArnAndTags(t *testing.T) { }) require.Equal(t, http.StatusOK, partnerRec.Code) var partnerResp map[string]any - require.NoError(t, json.Unmarshal(partnerRec.Body.Bytes(), &partnerResp)) + require.NoError(t, json.Unmarshal(partnerRec.Body.Bytes(), &partnerResp, jsonx.V1())) partnerProfileID := partnerResp["ProfileId"].(string) serverRec := doTransferRequest(t, h, "CreateServer", map[string]any{}) require.Equal(t, http.StatusOK, serverRec.Code) var serverResp map[string]any - require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp)) + require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp, jsonx.V1())) serverID := serverResp["ServerId"].(string) agRec := doTransferRequest(t, h, "CreateAgreement", map[string]any{ @@ -50,7 +51,7 @@ func TestHandler_DescribeAgreementIncludesArnAndTags(t *testing.T) { }) require.Equal(t, http.StatusOK, agRec.Code) var agResp map[string]any - require.NoError(t, json.Unmarshal(agRec.Body.Bytes(), &agResp)) + require.NoError(t, json.Unmarshal(agRec.Body.Bytes(), &agResp, jsonx.V1())) agreementID := agResp["AgreementId"].(string) rec := doTransferRequest(t, h, "DescribeAgreement", map[string]any{ @@ -60,7 +61,7 @@ func TestHandler_DescribeAgreementIncludesArnAndTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ag := resp["Agreement"].(map[string]any) arn, hasArn := ag["Arn"].(string) @@ -116,7 +117,7 @@ func TestHandler_CreateAgreement(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["AgreementId"]) } }) @@ -248,7 +249,7 @@ func TestHandler_DescribeAgreement(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) agreementID := createResp["AgreementId"].(string) rec := doTransferRequest(t, h, "DescribeAgreement", map[string]any{ @@ -291,7 +292,7 @@ func TestHandler_UpdateAgreement(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) agreementID := createResp["AgreementId"].(string) rec := doTransferRequest(t, h, "UpdateAgreement", map[string]any{ @@ -328,7 +329,7 @@ func TestHandler_ListAgreementsEnrichedFields(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) agreements := listResp["Agreements"].([]any) require.Len(t, agreements, 1) @@ -376,7 +377,7 @@ func TestHandler_CreateAgreementInactiveStatus(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) agID := createResp["AgreementId"].(string) descRec := doTransferRequest(t, h, "DescribeAgreement", map[string]any{ @@ -386,7 +387,7 @@ func TestHandler_CreateAgreementInactiveStatus(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) ag := descResp["Agreement"].(map[string]any) assert.Equal(t, "INACTIVE", ag["Status"]) } diff --git a/services/transfer/handler_certificates_test.go b/services/transfer/handler_certificates_test.go index d6ad6485a9..c3f42d3086 100644 --- a/services/transfer/handler_certificates_test.go +++ b/services/transfer/handler_certificates_test.go @@ -1,13 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -79,7 +80,7 @@ func TestHandler_DescribeCertificateBodyReturnedWhenPresent(t *testing.T) { var importOut struct { CertificateID string `json:"CertificateId"` } - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importOut, jsonx.V1())) descRec := doTransferRequest(t, h, "DescribeCertificate", map[string]any{ "CertificateId": importOut.CertificateID, @@ -91,7 +92,7 @@ func TestHandler_DescribeCertificateBodyReturnedWhenPresent(t *testing.T) { Certificate string `json:"Certificate"` } `json:"Certificate"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, testCertPEM, descOut.Certificate.Certificate, "DescribeCertificate must return the certificate body when present") @@ -108,7 +109,7 @@ func TestHandler_DescribeCertificateIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["CertificateId"].(string) rec := doTransferRequest(t, h, "DescribeCertificate", map[string]any{ @@ -117,7 +118,7 @@ func TestHandler_DescribeCertificateIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cert := resp["Certificate"].(map[string]any) arn, hasArn := cert["Arn"].(string) @@ -139,7 +140,7 @@ func TestHandler_ListCertificatesIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) certs := resp["Certificates"].([]any) require.NotEmpty(t, certs) @@ -189,7 +190,7 @@ func TestHandler_CertificateARNContainsAccountAndRegion(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["CertificateId"].(string) rec := doTransferRequest(t, h, "DescribeCertificate", map[string]any{ @@ -198,7 +199,7 @@ func TestHandler_CertificateARNContainsAccountAndRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cert := resp["Certificate"].(map[string]any) // newTestHandler uses testAccountID = "123456789012" and testRegion = "us-east-1" @@ -284,7 +285,7 @@ func TestHandler_DescribeCertificate(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["CertificateId"].(string) rec := doTransferRequest(t, h, "DescribeCertificate", map[string]any{ @@ -314,7 +315,7 @@ func TestHandler_UpdateCertificate(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["CertificateId"].(string) rec := doTransferRequest(t, h, "UpdateCertificate", map[string]any{ @@ -357,7 +358,7 @@ func TestHandler_ImportCertificateMalformedPEM(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", resp["__type"]) } @@ -373,7 +374,7 @@ func TestHandler_ImportCertificateValidPEMExtractsDates(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) certID := createResp["CertificateId"].(string) descRec := doTransferRequest(t, h, "DescribeCertificate", map[string]any{ @@ -382,7 +383,7 @@ func TestHandler_ImportCertificateValidPEMExtractsDates(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) cert := descResp["Certificate"].(map[string]any) assert.NotEmpty(t, cert["NotBeforeDate"], "NotBeforeDate must be set from PEM") diff --git a/services/transfer/handler_connectors_test.go b/services/transfer/handler_connectors_test.go index a16bdfd297..68934b9352 100644 --- a/services/transfer/handler_connectors_test.go +++ b/services/transfer/handler_connectors_test.go @@ -1,13 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -34,7 +35,7 @@ func TestHandler_UpdateConnectorLoggingRoleAndSecurityPolicyName(t *testing.T) { var createOut struct { ConnectorID string `json:"ConnectorId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) updateRec := doTransferRequest(t, h, "UpdateConnector", map[string]any{ "ConnectorId": createOut.ConnectorID, @@ -54,7 +55,7 @@ func TestHandler_UpdateConnectorLoggingRoleAndSecurityPolicyName(t *testing.T) { SecurityPolicyName string `json:"SecurityPolicyName"` } `json:"Connector"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, "arn:aws:iam::123456789012:role/TransferLogging", descOut.Connector.LoggingRole) assert.Equal(t, "TransferSecurityPolicy-2024-01", descOut.Connector.SecurityPolicyName) @@ -107,7 +108,7 @@ func TestHandler_CreateConnector(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ConnectorId"]) } }) @@ -174,7 +175,7 @@ func TestHandler_DescribeConnector(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "DescribeConnector", map[string]any{ @@ -203,7 +204,7 @@ func TestHandler_UpdateConnector(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "UpdateConnector", map[string]any{ @@ -225,7 +226,7 @@ func TestHandler_TestConnection(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "TestConnection", map[string]any{ @@ -246,7 +247,7 @@ func TestHandler_StartFileTransfer(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "StartFileTransfer", map[string]any{ @@ -268,7 +269,7 @@ func TestHandler_StartDirectoryListing(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "StartDirectoryListing", map[string]any{ @@ -279,7 +280,7 @@ func TestHandler_StartDirectoryListing(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ListingId"], "ListingId is a required field on StartDirectoryListingOutput") assert.Equal(t, connectorID+"-"+resp["ListingId"].(string)+".json", resp["OutputFileName"]) } @@ -296,7 +297,7 @@ func TestHandler_ListFileTransferResults(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "ListFileTransferResults", map[string]any{ @@ -318,7 +319,7 @@ func TestHandler_StartRemoteDelete(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "StartRemoteDelete", map[string]any{ @@ -340,7 +341,7 @@ func TestHandler_StartRemoteMove(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) rec := doTransferRequest(t, h, "StartRemoteMove", map[string]any{ @@ -368,7 +369,7 @@ func TestHandler_StartFileTransferPersistsRecord(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) transferID := startResp["TransferId"].(string) assert.NotEmpty(t, transferID) @@ -379,7 +380,7 @@ func TestHandler_StartFileTransferPersistsRecord(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) results := listResp["FileTransferResults"].([]any) require.Len(t, results, 1) @@ -407,7 +408,7 @@ func TestHandler_DescribeConnectorLoggingRole(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) descRec := doTransferRequest(t, h, "DescribeConnector", map[string]any{ @@ -416,7 +417,7 @@ func TestHandler_DescribeConnectorLoggingRole(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) connector := descResp["Connector"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/logging", connector["LoggingRole"]) @@ -450,8 +451,8 @@ func TestHandler_StartDirectoryListingUniqueId(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var r1, r2 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1)) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &r1, jsonx.V1())) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &r2, jsonx.V1())) id1 := r1["ListingId"].(string) id2 := r2["ListingId"].(string) @@ -513,7 +514,7 @@ func TestHandler_StartRemoteDelete_ReturnsDeleteId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["DeleteId"]) assert.NotContains(t, resp, "TransferId", "StartRemoteDeleteOutput has no TransferId field in real AWS") @@ -540,7 +541,7 @@ func TestHandler_StartRemoteMove_ReturnsMoveId(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["MoveId"]) assert.NotContains(t, resp, "TransferId", "StartRemoteMoveOutput has no TransferId field in real AWS") @@ -577,7 +578,7 @@ func TestHandler_ConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) descRec := doTransferRequest(t, h, "DescribeConnector", map[string]any{ @@ -586,7 +587,7 @@ func TestHandler_ConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) connector := descResp["Connector"].(map[string]any) assert.Equal(t, tt.ipAddressType, connector["IpAddressType"]) assert.Contains(t, descRec.Body.String(), `"IpAddressType":"`+tt.ipAddressType+`"`) @@ -603,7 +604,7 @@ func TestHandler_ConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) descRec := doTransferRequest(t, h, "DescribeConnector", map[string]any{ @@ -612,7 +613,7 @@ func TestHandler_ConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) connector := descResp["Connector"].(map[string]any) _, hasIPAddressType := connector["IpAddressType"] assert.False(t, hasIPAddressType, "IpAddressType must be absent, not an empty string, when unset") @@ -634,7 +635,7 @@ func TestHandler_UpdateConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) connectorID := createResp["ConnectorId"].(string) updateRec := doTransferRequest(t, h, "UpdateConnector", map[string]any{ @@ -649,7 +650,7 @@ func TestHandler_UpdateConnectorIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) connector := descResp["Connector"].(map[string]any) assert.Equal(t, "DUALSTACK", connector["IpAddressType"]) } diff --git a/services/transfer/handler_host_keys_test.go b/services/transfer/handler_host_keys_test.go index 9eaeba8036..1ed9d2fcff 100644 --- a/services/transfer/handler_host_keys_test.go +++ b/services/transfer/handler_host_keys_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // testSSHHostKeyBody is a syntactically valid (but not cryptographically @@ -25,7 +27,7 @@ func TestHandler_DescribeHostKeyIncludesFingerprint(t *testing.T) { serverRec := doTransferRequest(t, h, "CreateServer", map[string]any{}) require.Equal(t, http.StatusOK, serverRec.Code) var serverResp map[string]any - require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp)) + require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp, jsonx.V1())) serverID := serverResp["ServerId"].(string) importRec := doTransferRequest(t, h, "ImportHostKey", map[string]any{ @@ -36,7 +38,7 @@ func TestHandler_DescribeHostKeyIncludesFingerprint(t *testing.T) { }) require.Equal(t, http.StatusOK, importRec.Code) var importResp map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp, jsonx.V1())) hostKeyID := importResp["HostKeyId"].(string) rec := doTransferRequest(t, h, "DescribeHostKey", map[string]any{ @@ -46,7 +48,7 @@ func TestHandler_DescribeHostKeyIncludesFingerprint(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hk := resp["HostKey"].(map[string]any) fp, hasFp := hk["HostKeyFingerprint"].(string) @@ -75,7 +77,7 @@ func TestHandler_ListHostKeysIncludesFingerprintAndArn(t *testing.T) { serverRec := doTransferRequest(t, h, "CreateServer", map[string]any{}) require.Equal(t, http.StatusOK, serverRec.Code) var serverResp map[string]any - require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp)) + require.NoError(t, json.Unmarshal(serverRec.Body.Bytes(), &serverResp, jsonx.V1())) serverID := serverResp["ServerId"].(string) doTransferRequest(t, h, "ImportHostKey", map[string]any{ @@ -90,7 +92,7 @@ func TestHandler_ListHostKeysIncludesFingerprintAndArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) hostKeys := resp["HostKeys"].([]any) require.NotEmpty(t, hostKeys) @@ -150,7 +152,7 @@ func TestHandler_DescribeHostKey(t *testing.T) { require.Equal(t, http.StatusOK, importRec.Code) var importResp map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp, jsonx.V1())) hostKeyID := importResp["HostKeyId"].(string) rec := doTransferRequest(t, h, "DescribeHostKey", map[string]any{ @@ -174,7 +176,7 @@ func TestHandler_DeleteHostKey(t *testing.T) { require.Equal(t, http.StatusOK, importRec.Code) var importResp map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp, jsonx.V1())) hostKeyID := importResp["HostKeyId"].(string) rec := doTransferRequest(t, h, "DeleteHostKey", map[string]any{ @@ -198,7 +200,7 @@ func TestHandler_UpdateHostKey(t *testing.T) { require.Equal(t, http.StatusOK, importRec.Code) var importResp map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp, jsonx.V1())) hostKeyID := importResp["HostKeyId"].(string) rec := doTransferRequest(t, h, "UpdateHostKey", map[string]any{ diff --git a/services/transfer/handler_profiles_test.go b/services/transfer/handler_profiles_test.go index 6c88bec2de..d1e943b2af 100644 --- a/services/transfer/handler_profiles_test.go +++ b/services/transfer/handler_profiles_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ProfileCertificateIDsRoundtrip verifies that CertificateIds set via UpdateProfile @@ -25,7 +27,7 @@ func TestHandler_ProfileCertificateIDsRoundtrip(t *testing.T) { var createOut struct { ProfileID string `json:"ProfileId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) certIDs := []string{"cert-aaa111", "cert-bbb222"} updateRec := doTransferRequest(t, h, "UpdateProfile", map[string]any{ @@ -44,7 +46,7 @@ func TestHandler_ProfileCertificateIDsRoundtrip(t *testing.T) { CertificateIDs []string `json:"CertificateIds"` } `json:"Profile"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descOut, jsonx.V1())) assert.Equal(t, certIDs, descOut.Profile.CertificateIDs) } @@ -62,7 +64,7 @@ func TestHandler_DescribeProfileIncludesArnAndTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) profileID := createResp["ProfileId"].(string) rec := doTransferRequest(t, h, "DescribeProfile", map[string]any{ @@ -71,7 +73,7 @@ func TestHandler_DescribeProfileIncludesArnAndTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) profile := resp["Profile"].(map[string]any) arn, hasArn := profile["Arn"].(string) @@ -98,7 +100,7 @@ func TestHandler_ListProfilesIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) profiles := resp["Profiles"].([]any) require.NotEmpty(t, profiles) @@ -119,7 +121,7 @@ func TestHandler_ProfileARNContainsAccountAndRegion(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) profileID := createResp["ProfileId"].(string) rec := doTransferRequest(t, h, "DescribeProfile", map[string]any{ @@ -128,7 +130,7 @@ func TestHandler_ProfileARNContainsAccountAndRegion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) profile := resp["Profile"].(map[string]any) // newTestHandler uses testAccountID = "123456789012" and testRegion = "us-east-1" @@ -192,7 +194,7 @@ func TestHandler_CreateProfileReturnsProfileID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ProfileId"]) } @@ -237,7 +239,7 @@ func TestHandler_CreateProfile(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["ProfileId"]) } }) @@ -256,7 +258,7 @@ func TestHandler_DescribeProfile(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) profileID := createResp["ProfileId"].(string) rec := doTransferRequest(t, h, "DescribeProfile", map[string]any{ @@ -285,7 +287,7 @@ func TestHandler_DeleteProfile(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) profileID := createResp["ProfileId"].(string) rec := doTransferRequest(t, h, "DeleteProfile", map[string]any{ @@ -306,7 +308,7 @@ func TestHandler_UpdateProfile(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) profileID := createResp["ProfileId"].(string) rec := doTransferRequest(t, h, "UpdateProfile", map[string]any{ diff --git a/services/transfer/handler_security_policies_test.go b/services/transfer/handler_security_policies_test.go index 3408cb257c..af63279761 100644 --- a/services/transfer/handler_security_policies_test.go +++ b/services/transfer/handler_security_policies_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ListSecurityPolicies(t *testing.T) { @@ -42,7 +44,7 @@ func TestHandler_ListSecurityPoliciesIncludesCurrentNames(t *testing.T) { var resp struct { SecurityPolicyNames []string `json:"SecurityPolicyNames"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) names := make(map[string]bool, len(resp.SecurityPolicyNames)) for _, n := range resp.SecurityPolicyNames { @@ -85,7 +87,7 @@ func TestHandler_DescribeSecurityPolicy_ServerShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pol := resp["SecurityPolicy"].(map[string]any) assert.Equal(t, "SERVER", pol["Type"]) @@ -109,7 +111,7 @@ func TestHandler_DescribeSecurityPolicy_ConnectorShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pol := resp["SecurityPolicy"].(map[string]any) assert.Equal(t, "CONNECTOR", pol["Type"]) @@ -129,6 +131,6 @@ func TestHandler_DescribeSecurityPolicy_UnknownName(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } diff --git a/services/transfer/handler_servers_fields_test.go b/services/transfer/handler_servers_fields_test.go index e43501f48e..2d2e6a3074 100644 --- a/services/transfer/handler_servers_fields_test.go +++ b/services/transfer/handler_servers_fields_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Test 1: CreateServer with IdentityProviderType=API_GATEWAY is echoed by DescribeServer. @@ -26,7 +28,7 @@ func TestHandler_CreateServerIdentityProviderTypeAPIGateway(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{ @@ -35,7 +37,7 @@ func TestHandler_CreateServerIdentityProviderTypeAPIGateway(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.Equal(t, "API_GATEWAY", server["IdentityProviderType"]) @@ -65,7 +67,7 @@ func TestHandler_CreateServerDomainEFS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{ @@ -74,7 +76,7 @@ func TestHandler_CreateServerDomainEFS(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.Equal(t, "EFS", server["Domain"]) @@ -89,7 +91,7 @@ func TestHandler_UpdateServerLoggingRoleAndBanners(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) updateRec := doTransferRequest(t, h, "UpdateServer", map[string]any{ @@ -106,7 +108,7 @@ func TestHandler_UpdateServerLoggingRoleAndBanners(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.Equal(t, "arn:aws:iam::000000000000:role/logging", server["LoggingRole"]) @@ -124,7 +126,7 @@ func TestHandler_StartServerStartingState(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // Stop the server first so we can start it. @@ -134,7 +136,7 @@ func TestHandler_StartServerStartingState(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var resp map[string]any - _ = json.Unmarshal(descRec.Body.Bytes(), &resp) + _ = json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1()) require.Equal(t, "OFFLINE", resp["Server"].(map[string]any)["State"].(string)) // Start the server: immediate state should be STARTING. @@ -144,14 +146,14 @@ func TestHandler_StartServerStartingState(t *testing.T) { // Check immediately — should be STARTING (async transition hasn't fired yet). descRec = doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) immediateState := descResp["Server"].(map[string]any)["State"].(string) assert.Equal(t, "STARTING", immediateState) // Wait past the async transition to ONLINE. time.Sleep(serverTransitionWait) descRec = doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) - _ = json.Unmarshal(descRec.Body.Bytes(), &descResp) + _ = json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1()) assert.Equal(t, "ONLINE", descResp["Server"].(map[string]any)["State"].(string)) }) } @@ -173,7 +175,7 @@ func TestHandler_TestIdentityProviderKnownUser(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.EqualValues(t, 200, resp["StatusCode"]) } @@ -192,7 +194,7 @@ func TestHandler_TestIdentityProviderUnknownUser(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.EqualValues(t, 401, resp["StatusCode"]) } @@ -205,7 +207,7 @@ func TestHandler_UpdateServerProtocolDetails(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) updateRec := doTransferRequest(t, h, "UpdateServer", map[string]any{ @@ -224,7 +226,7 @@ func TestHandler_UpdateServerProtocolDetails(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) pd := server["ProtocolDetails"].(map[string]any) @@ -249,14 +251,14 @@ func TestHandler_CreateServerEndpointTypeVPC(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.Equal(t, "VPC", server["EndpointType"]) @@ -279,14 +281,14 @@ func TestHandler_CreateServerWorkflowDetails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) wd := server["WorkflowDetails"].(map[string]any) onUpload := wd["OnUpload"].([]any) @@ -308,14 +310,14 @@ func TestHandler_CreateServerS3StorageOptions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) s3 := server["S3StorageOptions"].(map[string]any) assert.Equal(t, "ENABLED", s3["DirectoryListingOptimization"]) @@ -332,14 +334,14 @@ func TestHandler_CreateServerStructuredLogDestinations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) dests := server["StructuredLogDestinations"].([]any) require.Len(t, dests, 1) @@ -357,14 +359,14 @@ func TestHandler_CreateServerIpAddressType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.Equal(t, "DUALSTACK", server["IpAddressType"]) } diff --git a/services/transfer/handler_servers_test.go b/services/transfer/handler_servers_test.go index 7c6c32d6cc..b679da8f8e 100644 --- a/services/transfer/handler_servers_test.go +++ b/services/transfer/handler_servers_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "testing/synctest" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -23,7 +24,7 @@ func mustCreateServer(t *testing.T, h *transfer.Handler) string { var out struct { ServerID string `json:"ServerId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out.ServerID } @@ -40,7 +41,7 @@ func TestHandler_DeleteServerCascade(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // Create access and agreement on the server @@ -66,7 +67,7 @@ func TestHandler_DeleteServerCascade(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var resp map[string]any - _ = json.Unmarshal(descRec.Body.Bytes(), &resp) + _ = json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1()) require.Equal(t, "OFFLINE", resp["Server"].(map[string]any)["State"].(string)) deleteRec := doTransferRequest(t, h, "DeleteServer", map[string]any{"ServerId": serverID}) @@ -93,7 +94,7 @@ func TestHandler_DeleteServerOnlineSucceeds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // A real server self-starts after CreateServer; see TestHandler_CreateServer. @@ -101,7 +102,7 @@ func TestHandler_DeleteServerOnlineSucceeds(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var resp map[string]any - _ = json.Unmarshal(descRec.Body.Bytes(), &resp) + _ = json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1()) require.Equal(t, "ONLINE", resp["Server"].(map[string]any)["State"].(string)) delRec := doTransferRequest(t, h, "DeleteServer", map[string]any{"ServerId": serverID}) @@ -125,7 +126,7 @@ func TestHandler_ListServersIncludesIdentityProviderType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // Add a user to check UserCount. @@ -136,7 +137,7 @@ func TestHandler_ListServersIncludesIdentityProviderType(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) servers := listResp["Servers"].([]any) require.Len(t, servers, 1) @@ -161,7 +162,7 @@ func TestHandler_DescribeServerUserCount(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": s.ServerID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server := descResp["Server"].(map[string]any) assert.EqualValues(t, 0, server["UserCount"]) @@ -173,7 +174,7 @@ func TestHandler_DescribeServerUserCount(t *testing.T) { descRec = doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": s.ServerID}) require.Equal(t, http.StatusOK, descRec.Code) - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) server = descResp["Server"].(map[string]any) assert.EqualValues(t, 2, server["UserCount"]) } @@ -226,7 +227,7 @@ func TestHandler_CreateServer(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp[tt.wantKey]) }) } @@ -242,7 +243,7 @@ func TestHandler_DescribeServer(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) tests := []struct { @@ -286,7 +287,7 @@ func TestHandler_ListServers(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.IsType(t, []any{}, resp["Servers"]) } @@ -355,7 +356,7 @@ func TestHandler_DeleteServer(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // AWS requires server to be OFFLINE before deletion; stop it first. @@ -365,7 +366,7 @@ func TestHandler_DeleteServer(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var resp map[string]any - _ = json.Unmarshal(descRec.Body.Bytes(), &resp) + _ = json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1()) require.Equal(t, "OFFLINE", resp["Server"].(map[string]any)["State"].(string)) rec := doTransferRequest(t, h, "DeleteServer", map[string]any{"ServerId": serverID}) @@ -386,7 +387,7 @@ func TestHandler_UpdateServer(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) rec := doTransferRequest(t, h, "UpdateServer", map[string]any{ @@ -437,7 +438,7 @@ func TestHandler_ListServers_Pagination(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) servers := resp["Servers"].([]any) assert.GreaterOrEqual(t, len(servers), tt.wantMinCount) @@ -497,7 +498,7 @@ func TestHandler_StartStopDeleteServer(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) body := tt.body @@ -513,7 +514,7 @@ func TestHandler_StartStopDeleteServer(t *testing.T) { descRec := doTransferRequest(t, h, "DescribeServer", map[string]any{"ServerId": serverID}) var resp map[string]any - _ = json.Unmarshal(descRec.Body.Bytes(), &resp) + _ = json.Unmarshal(descRec.Body.Bytes(), &resp, jsonx.V1()) require.Equal(t, "OFFLINE", resp["Server"].(map[string]any)["State"].(string)) } diff --git a/services/transfer/handler_ssh_keys_test.go b/services/transfer/handler_ssh_keys_test.go index 167e1f2105..1ca9733cea 100644 --- a/services/transfer/handler_ssh_keys_test.go +++ b/services/transfer/handler_ssh_keys_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_ImportSSHPublicKey(t *testing.T) { @@ -53,7 +55,7 @@ func TestHandler_DeleteSSHPublicKey(t *testing.T) { require.Equal(t, http.StatusOK, importRec.Code) var importResp map[string]any - require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp)) + require.NoError(t, json.Unmarshal(importRec.Body.Bytes(), &importResp, jsonx.V1())) sshKeyID := importResp["SshPublicKeyId"].(string) rec := doTransferRequest(t, h, "DeleteSshPublicKey", map[string]any{ @@ -92,7 +94,7 @@ func TestHandler_ImportSshPublicKeyDuplicateBody(t *testing.T) { assert.Equal(t, http.StatusBadRequest, secondRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceExistsException", errResp["__type"]) } @@ -114,6 +116,6 @@ func TestHandler_ImportSshPublicKeyUnknownUserReturnsResourceNotFound(t *testing assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } diff --git a/services/transfer/handler_tags_test.go b/services/transfer/handler_tags_test.go index 746540b920..1a34c0f5a4 100644 --- a/services/transfer/handler_tags_test.go +++ b/services/transfer/handler_tags_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -31,7 +32,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisible(t *testing.T) { var createOut struct { ServerID string `json:"ServerId"` } - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createOut, jsonx.V1())) serverARN := "arn:aws:transfer:us-east-1:123456789012:server/" + createOut.ServerID listRec := doTransferRequest(t, h, "ListTagsForResource", map[string]any{ @@ -45,7 +46,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisible(t *testing.T) { Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tagMap := make(map[string]string, len(listOut.Tags)) @@ -88,7 +89,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin var out struct { AgreementID string `json:"AgreementId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return "arn:aws:transfer:us-east-1:123456789012:server/" + serverID + "/agreement/" + out.AgreementID }, @@ -107,7 +108,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin var out struct { ProfileID string `json:"ProfileId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return "arn:aws:transfer:us-east-1:123456789012:profile/" + out.ProfileID }, @@ -150,7 +151,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin var out struct { WebAppID string `json:"WebAppId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return "arn:aws:transfer:us-east-1:123456789012:webapp/" + out.WebAppID }, @@ -169,7 +170,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin var out struct { CertificateID string `json:"CertificateId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return "arn:aws:transfer:us-east-1:123456789012:certificate/" + out.CertificateID }, @@ -191,7 +192,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin var out struct { HostKeyID string `json:"HostKeyId"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return "arn:aws:transfer:us-east-1:123456789012:host-key/" + serverID + "/" + out.HostKeyID }, @@ -214,7 +215,7 @@ func TestHandler_ListTagsForResourceCreationTagsVisibleAcrossResources(t *testin Value string `json:"Value"` } `json:"Tags"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) tagMap := make(map[string]string, len(listOut.Tags)) for _, tag := range listOut.Tags { @@ -254,7 +255,7 @@ func TestHandler_TagResourceListTagsRoundTripServerARN(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) tagMap := make(map[string]string) @@ -293,7 +294,7 @@ func TestHandler_UntagResourceRoundTrip(t *testing.T) { listRec := doTransferRequest(t, h, "ListTagsForResource", map[string]any{"Arn": arnStr}) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags := listResp["Tags"].([]any) tagMap := make(map[string]string) @@ -342,7 +343,7 @@ func TestHandler_ListTagsForResource(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotNil(t, resp["Tags"]) } diff --git a/services/transfer/handler_test.go b/services/transfer/handler_test.go index 5790c69a53..7dd0ff3111 100644 --- a/services/transfer/handler_test.go +++ b/services/transfer/handler_test.go @@ -2,7 +2,7 @@ package transfer_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -147,7 +148,7 @@ func doTransferRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/services/transfer/handler_users_test.go b/services/transfer/handler_users_test.go index 59518d6f6b..2602eb7f1d 100644 --- a/services/transfer/handler_users_test.go +++ b/services/transfer/handler_users_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_ListUsersSshPublicKeyCountAndHomeDirectoryType verifies that ListUsers returns @@ -25,7 +27,7 @@ func TestHandler_ListUsersSshPublicKeyCountAndHomeDirectoryType(t *testing.T) { var srvOut struct { ServerID string `json:"ServerId"` } - require.NoError(t, json.Unmarshal(createSrvRec.Body.Bytes(), &srvOut)) + require.NoError(t, json.Unmarshal(createSrvRec.Body.Bytes(), &srvOut, jsonx.V1())) createUserRec := doTransferRequest(t, h, "CreateUser", map[string]any{ "ServerId": srvOut.ServerID, @@ -57,7 +59,7 @@ func TestHandler_ListUsersSshPublicKeyCountAndHomeDirectoryType(t *testing.T) { SSHPublicKeyCount int `json:"SshPublicKeyCount"` } `json:"Users"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listOut, jsonx.V1())) require.Len(t, listOut.Users, 1) assert.Equal(t, "LOGICAL", listOut.Users[0].HomeDirectoryType) @@ -95,7 +97,7 @@ func TestHandler_UserARNFormat(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) user := descResp["User"].(map[string]any) // newTestHandler uses testAccountID = "123456789012" and testRegion = "us-east-1" @@ -130,7 +132,7 @@ func TestHandler_CreateUserPosixProfile(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) user := descResp["User"].(map[string]any) posix := user["PosixProfile"].(map[string]any) @@ -164,7 +166,7 @@ func TestHandler_CreateUserHomeDirectoryLogical(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) user := descResp["User"].(map[string]any) assert.Equal(t, "LOGICAL", user["HomeDirectoryType"]) @@ -207,7 +209,7 @@ func TestHandler_DescribeUserIncludesSshPublicKeys(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) user := descResp["User"].(map[string]any) keys, ok := user["SshPublicKeys"].([]any) require.True(t, ok, "SshPublicKeys must be present") @@ -235,7 +237,7 @@ func TestHandler_ListUsersPagination(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) users := listResp["Users"].([]any) assert.Len(t, users, 2) @@ -269,7 +271,7 @@ func TestHandler_UpdateUserPosixProfile(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) user := descResp["User"].(map[string]any) posix := user["PosixProfile"].(map[string]any) assert.EqualValues(t, 9999, posix["Uid"]) @@ -285,7 +287,7 @@ func TestHandler_UserCRUD(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) // Create user @@ -298,7 +300,7 @@ func TestHandler_UserCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, createUserRec.Code) var userResp map[string]any - require.NoError(t, json.Unmarshal(createUserRec.Body.Bytes(), &userResp)) + require.NoError(t, json.Unmarshal(createUserRec.Body.Bytes(), &userResp, jsonx.V1())) assert.Equal(t, "alice", userResp["UserName"]) // Describe user @@ -315,7 +317,7 @@ func TestHandler_UserCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, listUsersRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listUsersRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listUsersRec.Body.Bytes(), &listResp, jsonx.V1())) users := listResp["Users"].([]any) assert.Len(t, users, 1) @@ -341,7 +343,7 @@ func TestHandler_UserCRUD(t *testing.T) { assert.Equal(t, http.StatusOK, listUsersRec2.Code) var listResp2 map[string]any - require.NoError(t, json.Unmarshal(listUsersRec2.Body.Bytes(), &listResp2)) + require.NoError(t, json.Unmarshal(listUsersRec2.Body.Bytes(), &listResp2, jsonx.V1())) assert.Empty(t, listResp2["Users"]) } @@ -354,7 +356,7 @@ func TestHandler_CreateUser_MissingFields(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) tests := []struct { @@ -395,7 +397,7 @@ func TestHandler_ListUsers_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) serverID := createResp["ServerId"].(string) for _, username := range []string{"alice", "bob", "charlie"} { @@ -434,7 +436,7 @@ func TestHandler_ListUsers_Pagination(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) users := resp["Users"].([]any) assert.GreaterOrEqual(t, len(users), tt.wantMinCount) @@ -503,7 +505,7 @@ func TestHandler_DescribeDeleteUpdateUser(t *testing.T) { require.Equal(t, http.StatusOK, createServerRec.Code) var serverResp map[string]any - require.NoError(t, json.Unmarshal(createServerRec.Body.Bytes(), &serverResp)) + require.NoError(t, json.Unmarshal(createServerRec.Body.Bytes(), &serverResp, jsonx.V1())) serverID := serverResp["ServerId"].(string) doTransferRequest(t, h, "CreateUser", map[string]any{ diff --git a/services/transfer/handler_web_apps_test.go b/services/transfer/handler_web_apps_test.go index 6e520b0602..a83bd5783c 100644 --- a/services/transfer/handler_web_apps_test.go +++ b/services/transfer/handler_web_apps_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // webAppCreateBody returns a minimal CreateWebApp request body satisfying the @@ -60,7 +62,7 @@ func TestHandler_WebAppCustomizationValidatesWebAppID(t *testing.T) { "%s on non-existent WebAppId must return 400 (ResourceNotFoundException)", tt.operation) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) errType, _ := errResp["__type"].(string) assert.Contains(t, errType, "ResourceNotFoundException", @@ -81,7 +83,7 @@ func TestHandler_WebAppCustomizationRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID, _ := createResp["WebAppId"].(string) require.NotEmpty(t, webAppID) @@ -99,7 +101,7 @@ func TestHandler_WebAppCustomizationRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code, "DescribeWebAppCustomization must succeed") var descResp map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &descResp, jsonx.V1())) customization, ok := descResp["WebAppCustomization"].(map[string]any) require.True(t, ok, "WebAppCustomization must be present in response") @@ -123,7 +125,7 @@ func TestHandler_CreateWebAppReturnsWebAppID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WebAppId"]) } @@ -138,7 +140,7 @@ func TestHandler_CreateWebApp_MissingIdentityProviderDetails(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "InvalidRequestException", errResp["__type"]) } @@ -158,7 +160,7 @@ func TestHandler_DescribeWebAppIncludesArnTagsAndIdentityProvider(t *testing.T) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) updateRec := doTransferRequest(t, h, "UpdateWebApp", map[string]any{ @@ -175,7 +177,7 @@ func TestHandler_DescribeWebAppIncludesArnTagsAndIdentityProvider(t *testing.T) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) webApp := descResp["WebApp"].(map[string]any) assert.Equal(t, @@ -212,14 +214,14 @@ func TestHandler_ListWebAppsIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) listRec := doTransferRequest(t, h, "ListWebApps", map[string]any{}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) webApps := listResp["WebApps"].([]any) require.Len(t, webApps, 1) @@ -261,7 +263,7 @@ func TestHandler_CreateWebApp(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WebAppId"]) }) } @@ -294,14 +296,14 @@ func TestHandler_CreateWebAppVpcEndpoint(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) descRec := doTransferRequest(t, h, "DescribeWebApp", map[string]any{"WebAppId": webAppID}) require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) webApp := descResp["WebApp"].(map[string]any) assert.Equal(t, "VPC", webApp["EndpointType"]) @@ -327,7 +329,7 @@ func TestHandler_DescribeWebApp(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) rec := doTransferRequest(t, h, "DescribeWebApp", map[string]any{ @@ -353,7 +355,7 @@ func TestHandler_DeleteWebApp(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) rec := doTransferRequest(t, h, "DeleteWebApp", map[string]any{ @@ -371,7 +373,7 @@ func TestHandler_UpdateWebApp(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) rec := doTransferRequest(t, h, "UpdateWebApp", map[string]any{ @@ -393,7 +395,7 @@ func TestHandler_UpdateWebAppVpcIPAddressType(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) updateRec := doTransferRequest(t, h, "UpdateWebApp", map[string]any{ @@ -423,7 +425,7 @@ func TestHandler_UpdateWebApp_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", errResp["__type"]) } @@ -436,7 +438,7 @@ func TestHandler_WebAppCustomization(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webAppID := createResp["WebAppId"].(string) // DescribeWebAppCustomization diff --git a/services/transfer/handler_workflows_test.go b/services/transfer/handler_workflows_test.go index c95e649dfb..faf2a3707c 100644 --- a/services/transfer/handler_workflows_test.go +++ b/services/transfer/handler_workflows_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestHandler_CreateWorkflowInvalidStepTypeRejected verifies that CreateWorkflow returns 400 @@ -61,7 +63,7 @@ func TestHandler_DescribeWorkflowIncludesArnAndTags(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) rec := doTransferRequest(t, h, "DescribeWorkflow", map[string]any{ @@ -70,7 +72,7 @@ func TestHandler_DescribeWorkflowIncludesArnAndTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wf := resp["Workflow"].(map[string]any) arn, hasArn := wf["Arn"].(string) @@ -96,7 +98,7 @@ func TestHandler_ListWorkflowsIncludesArn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) workflows := resp["Workflows"].([]any) require.NotEmpty(t, workflows) @@ -117,7 +119,7 @@ func TestHandler_CreateWorkflowReturnsWorkflowID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WorkflowId"]) } @@ -205,7 +207,7 @@ func TestHandler_CreateWorkflow(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["WorkflowId"]) }) } @@ -222,7 +224,7 @@ func TestHandler_DescribeWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) rec := doTransferRequest(t, h, "DescribeWorkflow", map[string]any{ @@ -250,7 +252,7 @@ func TestHandler_DeleteWorkflow(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) rec := doTransferRequest(t, h, "DeleteWorkflow", map[string]any{ @@ -270,7 +272,7 @@ func TestHandler_ListExecutions(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) rec := doTransferRequest(t, h, "ListExecutions", map[string]any{ @@ -321,7 +323,7 @@ func TestHandler_DescribeWorkflowTypedCopyStepDetails(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) descRec := doTransferRequest(t, h, "DescribeWorkflow", map[string]any{ @@ -330,7 +332,7 @@ func TestHandler_DescribeWorkflowTypedCopyStepDetails(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) wf := descResp["Workflow"].(map[string]any) steps := wf["Steps"].([]any) require.Len(t, steps, 1) diff --git a/services/transfer/multi_region_test.go b/services/transfer/multi_region_test.go index 21aeadc5fb..346fabcfa9 100644 --- a/services/transfer/multi_region_test.go +++ b/services/transfer/multi_region_test.go @@ -2,7 +2,7 @@ package transfer_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/transfer/paging.go b/services/transfer/paging.go index ffec79288c..b15d4f6ecc 100644 --- a/services/transfer/paging.go +++ b/services/transfer/paging.go @@ -1,9 +1,10 @@ package transfer import ( - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -36,7 +37,7 @@ func validateListPaging(body []byte) error { func decodeListPaging(body []byte) (listPagingInput, bool) { var in listPagingInput - err := json.Unmarshal(body, &in) + err := json.Unmarshal(body, &in, jsonx.V1()) return in, err == nil } diff --git a/services/transfer/persistence.go b/services/transfer/persistence.go index 3208b9db17..e847ac65d7 100644 --- a/services/transfer/persistence.go +++ b/services/transfer/persistence.go @@ -2,7 +2,7 @@ package transfer import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -31,7 +31,7 @@ const transferSnapshotVersion = 1 // (and TagsStore is handled separately below) -- see store_setup.go and the // field comments on InMemoryBackend for why. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` TagsStore map[string]map[string]string `json:"tags_store"` Version int `json:"version"` } diff --git a/services/transfer/realism_test.go b/services/transfer/realism_test.go index 9a00ae6c4d..ef604813aa 100644 --- a/services/transfer/realism_test.go +++ b/services/transfer/realism_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const realismRole = "arn:aws:iam::123456789012:role/TransferUserRole" @@ -18,7 +20,7 @@ func transferErr(t *testing.T, body []byte) (string, string) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out.Type, out.Message } diff --git a/services/transfer/resource_id_shape_test.go b/services/transfer/resource_id_shape_test.go index 4b514f4574..4886999b1f 100644 --- a/services/transfer/resource_id_shape_test.go +++ b/services/transfer/resource_id_shape_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // Patterns are the SDK-documented ID shapes; terraform-provider-aws validates workflow and server IDs against them. @@ -87,11 +89,11 @@ func TestResourceIDShapes(t *testing.T) { require.Equal(t, http.StatusOK, srv.Code) var srvOut, profOut map[string]any - require.NoError(t, json.Unmarshal(srv.Body.Bytes(), &srvOut)) + require.NoError(t, json.Unmarshal(srv.Body.Bytes(), &srvOut, jsonx.V1())) prof := doTransferRequest(t, h, "CreateProfile", map[string]any{"As2Id": "AS2", "ProfileType": "LOCAL"}) require.Equal(t, http.StatusOK, prof.Code) - require.NoError(t, json.Unmarshal(prof.Body.Bytes(), &profOut)) + require.NoError(t, json.Unmarshal(prof.Body.Bytes(), &profOut, jsonx.V1())) rec := doTransferRequest( t, @@ -102,7 +104,7 @@ func TestResourceIDShapes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Regexp(t, tt.pattern, out[tt.idField]) }) } @@ -116,7 +118,7 @@ func TestSSHKeyAndExecutionIDShapes(t *testing.T) { srv := doTransferRequest(t, h, "CreateServer", map[string]any{}) var srvOut map[string]any - require.NoError(t, json.Unmarshal(srv.Body.Bytes(), &srvOut)) + require.NoError(t, json.Unmarshal(srv.Body.Bytes(), &srvOut, jsonx.V1())) doTransferRequest(t, h, "CreateUser", map[string]any{ "ServerId": srvOut["ServerId"], "UserName": "alice", "Role": "arn:aws:iam::000000000000:role/r", @@ -128,6 +130,6 @@ func TestSSHKeyAndExecutionIDShapes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var out map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Regexp(t, `^key-[0-9a-f]{17}$`, out["SshPublicKeyId"]) } diff --git a/services/transfer/sftp_apigw.go b/services/transfer/sftp_apigw.go index 65e7b031ce..166a8178eb 100644 --- a/services/transfer/sftp_apigw.go +++ b/services/transfer/sftp_apigw.go @@ -2,7 +2,7 @@ package transfer import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "net/http" @@ -15,6 +15,7 @@ import ( "golang.org/x/crypto/ssh" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -205,7 +206,7 @@ func (s *sftpServer) apiGatewayLogin( } var resp idpAuthResponse - if jerr := json.Unmarshal(body, &resp); jerr != nil { + if jerr := json.Unmarshal(body, &resp, jsonx.V1()); jerr != nil { return nil, errSFTPDenied } diff --git a/services/transfer/sftp_server.go b/services/transfer/sftp_server.go index 317aa0bc9e..0c2602f86d 100644 --- a/services/transfer/sftp_server.go +++ b/services/transfer/sftp_server.go @@ -3,7 +3,7 @@ package transfer import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "errors" "io" "net" @@ -14,6 +14,7 @@ import ( "github.com/pkg/sftp" "golang.org/x/crypto/ssh" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -106,7 +107,7 @@ func (s *sftpServer) serve(conn net.Conn) { var sess sftpSession if raw := sc.Permissions.Extensions[sftpSessionExtension]; raw != "" { - if jerr := json.Unmarshal([]byte(raw), &sess); jerr != nil { + if jerr := json.Unmarshal([]byte(raw), &sess, jsonx.V1()); jerr != nil { return } } @@ -176,7 +177,7 @@ func (s *sftpServer) authenticate(c ssh.ConnMetadata, key ssh.PublicKey, passwor sess.User = c.User() - raw, err := json.Marshal(sess) + raw, err := json.Marshal(sess, jsonx.V1()) if err != nil { return nil, errSFTPDenied } @@ -288,7 +289,7 @@ func (s *sftpServer) lambdaLogin( event["password"] = password } - payload, err := json.Marshal(event) + payload, err := json.Marshal(event, jsonx.V1()) if err != nil { return nil, err } @@ -299,7 +300,7 @@ func (s *sftpServer) lambdaLogin( } var resp idpAuthResponse - if jerr := json.Unmarshal(out, &resp); jerr != nil { + if jerr := json.Unmarshal(out, &resp, jsonx.V1()); jerr != nil { return nil, errSFTPDenied } @@ -340,7 +341,7 @@ func parseLambdaMappings(details string) ([]HomeDirectoryMapEntry, error) { Entry string `json:"Entry"` Target string `json:"Target"` } - if err := json.Unmarshal([]byte(details), &raw); err != nil { + if err := json.Unmarshal([]byte(details), &raw, jsonx.V1()); err != nil { return nil, errSFTPDenied } diff --git a/services/transfer/undeclared_members_test.go b/services/transfer/undeclared_members_test.go index 0dac04035a..129d86df9c 100644 --- a/services/transfer/undeclared_members_test.go +++ b/services/transfer/undeclared_members_test.go @@ -1,12 +1,14 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_DescribeUser_SshKeyOmitsKeyType(t *testing.T) { @@ -45,7 +47,7 @@ func TestHandler_DescribeUser_SshKeyOmitsKeyType(t *testing.T) { SSHPublicKeys []map[string]any `json:"SshPublicKeys"` } `json:"User"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.User.SSHPublicKeys, 1) assert.NotContains(t, out.User.SSHPublicKeys[0], "KeyType") assert.Equal(t, tc.body, out.User.SSHPublicKeys[0]["SshPublicKeyBody"]) diff --git a/services/transfer/wire_field_fixes_test.go b/services/transfer/wire_field_fixes_test.go index fcf2838991..ae67e2faed 100644 --- a/services/transfer/wire_field_fixes_test.go +++ b/services/transfer/wire_field_fixes_test.go @@ -1,7 +1,7 @@ package transfer_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/transfer" ) @@ -78,7 +79,7 @@ func TestDescribeWorkflow_CustomStepTimeoutSecondsKey_RealClient(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) workflowID := createResp["WorkflowId"].(string) rec := doTransferRequest(t, h, "DescribeWorkflow", map[string]any{ @@ -230,7 +231,7 @@ func TestListExecutionsAndDescribeExecution_NoFabricatedWorkflowId(t *testing.T) var listResp struct { Executions []map[string]any `json:"Executions"` } - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) require.Len(t, listResp.Executions, 1, "must exercise a non-empty collection") require.Contains(t, listResp.Executions[0], "ExecutionId") @@ -247,7 +248,7 @@ func TestListExecutionsAndDescribeExecution_NoFabricatedWorkflowId(t *testing.T) var descResp struct { Execution map[string]any `json:"Execution"` } - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) require.Contains(t, descResp.Execution, "ExecutionId") _, descHasWorkflowID := descResp.Execution["WorkflowId"] diff --git a/services/translate/handler.go b/services/translate/handler.go index 1f5118d4d1..2deec69537 100644 --- a/services/translate/handler.go +++ b/services/translate/handler.go @@ -2,7 +2,7 @@ package translate import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -12,6 +12,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -106,7 +107,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { } var values map[string]any - if unmarshalErr := json.Unmarshal(body, &values); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(body, &values, jsonx.V1()); unmarshalErr != nil { return "" } @@ -147,7 +148,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt var input map[string]any if len(body) > 0 { - if err := json.Unmarshal(body, &input); err != nil { + if err := json.Unmarshal(body, &input, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid JSON: %w", ErrValidation, err) } } @@ -161,7 +162,7 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt return nil, err } - return json.Marshal(output) + return json.Marshal(output, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { diff --git a/services/translate/handler_languages_test.go b/services/translate/handler_languages_test.go index cc6355c5ab..95e0dde86e 100644 --- a/services/translate/handler_languages_test.go +++ b/services/translate/handler_languages_test.go @@ -1,12 +1,14 @@ package translate_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListLanguages(t *testing.T) { @@ -154,7 +156,7 @@ func TestListLanguages_UnsupportedDisplayLanguageCodeRejected(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "UnsupportedDisplayLanguageCodeException", body["__type"]) } }) diff --git a/services/translate/handler_parallel_data_test.go b/services/translate/handler_parallel_data_test.go index 822fd0cf01..82f9ccffce 100644 --- a/services/translate/handler_parallel_data_test.go +++ b/services/translate/handler_parallel_data_test.go @@ -1,13 +1,14 @@ package translate_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/translate" ) @@ -255,7 +256,7 @@ func TestUpdateParallelData_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -283,7 +284,7 @@ func TestCreateParallelData_DuplicateNameReturnsConflictException(t *testing.T) assert.Equal(t, http.StatusBadRequest, rec.Code) var respBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody, jsonx.V1())) assert.Equal(t, "ConflictException", respBody["__type"]) } @@ -435,7 +436,7 @@ func TestUpdateParallelData_ConcurrentModification(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ConcurrentModificationException", body["__type"]) }) } @@ -494,7 +495,7 @@ func TestCreateParallelData_TooManyTagsRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "TooManyTagsException", body["__type"]) } diff --git a/services/translate/handler_tags_test.go b/services/translate/handler_tags_test.go index 0003fdf509..744a6b2dd9 100644 --- a/services/translate/handler_tags_test.go +++ b/services/translate/handler_tags_test.go @@ -1,12 +1,14 @@ package translate_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestTagResource(t *testing.T) { @@ -85,7 +87,7 @@ func TestTagResource_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -103,7 +105,7 @@ func TestUntagResource_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -120,7 +122,7 @@ func TestListTagsForResource_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -180,7 +182,7 @@ func TestTagResource_TooManyTagsRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "TooManyTagsException", body["__type"]) } diff --git a/services/translate/handler_test.go b/services/translate/handler_test.go index df32822a18..ee41a8524a 100644 --- a/services/translate/handler_test.go +++ b/services/translate/handler_test.go @@ -3,7 +3,7 @@ package translate_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/translate" ) @@ -38,7 +39,7 @@ func doRequest(t *testing.T, h *translate.Handler, operation string, body any) * if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -63,7 +64,7 @@ func unmarshalJSON(t *testing.T, data []byte) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(data, &m)) + require.NoError(t, json.Unmarshal(data, &m, jsonx.V1())) return m } diff --git a/services/translate/handler_text_translation_jobs_test.go b/services/translate/handler_text_translation_jobs_test.go index ae9278a072..56fa152d58 100644 --- a/services/translate/handler_text_translation_jobs_test.go +++ b/services/translate/handler_text_translation_jobs_test.go @@ -1,7 +1,7 @@ package translate_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/translate" ) @@ -199,7 +200,7 @@ func TestStopTextTranslationJob_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -213,7 +214,7 @@ func TestDescribeTextTranslationJob_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", body["__type"]) } @@ -306,7 +307,7 @@ func TestStartTextTranslationJob_UnknownTerminologyRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var respBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", respBody["__type"]) }) } @@ -354,7 +355,7 @@ func TestStartTextTranslationJob_RequiredFieldsValidated(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var respBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody, jsonx.V1())) assert.Equal(t, "InvalidRequestException", respBody["__type"]) }) } @@ -409,7 +410,7 @@ func TestStartTextTranslationJob_UnsupportedLanguagePairRejected(t *testing.T) { if tt.wantCode == http.StatusBadRequest { var respBody map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &respBody, jsonx.V1())) assert.Equal(t, "UnsupportedLanguagePairException", respBody["__type"]) } }) @@ -544,7 +545,7 @@ func TestListTextTranslationJobs_InvalidFilterRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var body map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) assert.Equal(t, "InvalidFilterException", body["__type"]) } diff --git a/services/translate/multi_region_test.go b/services/translate/multi_region_test.go index 4dc043b372..83f9c4e69a 100644 --- a/services/translate/multi_region_test.go +++ b/services/translate/multi_region_test.go @@ -2,7 +2,8 @@ package translate_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/translate" ) @@ -183,8 +185,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/translate/persistence.go b/services/translate/persistence.go index 37de19b1ef..d103f65279 100644 --- a/services/translate/persistence.go +++ b/services/translate/persistence.go @@ -2,7 +2,7 @@ package translate import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" @@ -38,7 +38,7 @@ const translateSnapshotVersion = 1 // (see backend.go's InMemoryBackend field doc comment). It is persisted // directly here. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` AccountID string `json:"accountId"` Region string `json:"region"` diff --git a/services/verifiedpermissions/cedar_attributes.go b/services/verifiedpermissions/cedar_attributes.go index cdd9e948bc..0612b68c1c 100644 --- a/services/verifiedpermissions/cedar_attributes.go +++ b/services/verifiedpermissions/cedar_attributes.go @@ -1,11 +1,14 @@ package verifiedpermissions import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" cedar "github.com/cedar-policy/cedar-go" cedartypes "github.com/cedar-policy/cedar-go/types" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // entityIdentifierJSON already exists in handler_authorization.go (entityType/entityId). @@ -18,9 +21,9 @@ import ( // the same as cedar-go's own implicit JSON value format (types.UnmarshalJSON: // bare JSON literals plus __entity/__extn tags), so this needs its own converter // rather than reusing cedar-go's decoder. -func attributeValueToCedar(raw json.RawMessage) (cedar.Value, error) { - var m map[string]json.RawMessage - if err := json.Unmarshal(raw, &m); err != nil { +func attributeValueToCedar(raw jsontext.Value) (cedar.Value, error) { + var m map[string]jsontext.Value + if err := json.Unmarshal(raw, &m, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid attribute value: %w", errInvalidRequest, err) } @@ -38,25 +41,25 @@ func attributeValueToCedar(raw json.RawMessage) (cedar.Value, error) { // per-member would scatter the union's shape across more functions than it clarifies. // //nolint:cyclop // one discriminated-union switch over AWS's 9 AttributeValue member types; decomposing -func attributeValueMemberToCedar(key string, v json.RawMessage) (cedar.Value, error) { +func attributeValueMemberToCedar(key string, v jsontext.Value) (cedar.Value, error) { switch key { case "boolean": var b bool - if err := json.Unmarshal(v, &b); err != nil { + if err := json.Unmarshal(v, &b, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid boolean attribute: %w", errInvalidRequest, err) } return cedar.Boolean(b), nil case "string": var s string - if err := json.Unmarshal(v, &s); err != nil { + if err := json.Unmarshal(v, &s, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid string attribute: %w", errInvalidRequest, err) } return cedar.String(s), nil case "long": var n int64 - if err := json.Unmarshal(v, &n); err != nil { + if err := json.Unmarshal(v, &n, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid long attribute: %w", errInvalidRequest, err) } @@ -71,7 +74,7 @@ func attributeValueMemberToCedar(key string, v json.RawMessage) (cedar.Value, er return parseCedarStringAttr(v, cedartypes.ParseIPAddr) case "entityIdentifier": var eid entityIdentifierJSON - if err := json.Unmarshal(v, &eid); err != nil { + if err := json.Unmarshal(v, &eid, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid entityIdentifier attribute: %w", errInvalidRequest, err) } @@ -85,9 +88,9 @@ func attributeValueMemberToCedar(key string, v json.RawMessage) (cedar.Value, er } } -func parseCedarStringAttr[T cedar.Value](raw json.RawMessage, parse func(string) (T, error)) (cedar.Value, error) { +func parseCedarStringAttr[T cedar.Value](raw jsontext.Value, parse func(string) (T, error)) (cedar.Value, error) { var s string - if err := json.Unmarshal(raw, &s); err != nil { + if err := json.Unmarshal(raw, &s, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid string-encoded attribute: %w", errInvalidRequest, err) } @@ -99,9 +102,9 @@ func parseCedarStringAttr[T cedar.Value](raw json.RawMessage, parse func(string) return val, nil } -func recordAttributeToCedar(raw json.RawMessage) (cedar.Value, error) { - var fields map[string]json.RawMessage - if err := json.Unmarshal(raw, &fields); err != nil { +func recordAttributeToCedar(raw jsontext.Value) (cedar.Value, error) { + var fields map[string]jsontext.Value + if err := json.Unmarshal(raw, &fields, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid record attribute: %w", errInvalidRequest, err) } @@ -119,9 +122,9 @@ func recordAttributeToCedar(raw json.RawMessage) (cedar.Value, error) { return cedar.NewRecord(rec), nil } -func setAttributeToCedar(raw json.RawMessage) (cedar.Value, error) { - var items []json.RawMessage - if err := json.Unmarshal(raw, &items); err != nil { +func setAttributeToCedar(raw jsontext.Value) (cedar.Value, error) { + var items []jsontext.Value + if err := json.Unmarshal(raw, &items, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid set attribute: %w", errInvalidRequest, err) } @@ -141,7 +144,7 @@ func setAttributeToCedar(raw json.RawMessage) (cedar.Value, error) { // attributeMapToCedarRecord converts an AWS "attributes"/"contextMap" object // (map of name -> AttributeValue) into a cedar-go Record. -func attributeMapToCedarRecord(m map[string]json.RawMessage) (cedar.Record, error) { +func attributeMapToCedarRecord(m map[string]jsontext.Value) (cedar.Record, error) { rec := make(cedar.RecordMap, len(m)) for k, v := range m { @@ -161,10 +164,10 @@ func attributeMapToCedarRecord(m map[string]json.RawMessage) (cedar.Record, erro // awsAwsjson10_serializeDocumentEntityItem). CedarTagValue has the same members // as AttributeValue (serializers.go:2334), so tags reuse the attribute converter. type entityItemJSON struct { - Identifier *entityIdentifierJSON `json:"identifier,omitempty"` - Attributes map[string]json.RawMessage `json:"attributes,omitempty"` - Tags map[string]json.RawMessage `json:"tags,omitempty"` - Parents []entityIdentifierJSON `json:"parents,omitempty"` + Identifier *entityIdentifierJSON `json:"identifier,omitempty"` + Attributes map[string]jsontext.Value `json:"attributes,omitempty"` + Tags map[string]jsontext.Value `json:"tags,omitempty"` + Parents []entityIdentifierJSON `json:"parents,omitempty"` } // entitiesDefinitionJSON mirrors the real SDK's types.EntitiesDefinition union @@ -183,8 +186,8 @@ type entitiesDefinitionJSON struct { // (contextMap: typed AttributeValue objects: cedarJson: a literal Cedar JSON // object using cedar-go's own native record JSON shape). type contextDefinitionJSON struct { - ContextMap map[string]json.RawMessage `json:"contextMap,omitempty"` - CedarJSON string `json:"cedarJson,omitempty"` + ContextMap map[string]jsontext.Value `json:"contextMap,omitempty"` + CedarJSON string `json:"cedarJson,omitempty"` } // entitiesToCedar converts a parsed entitiesDefinitionJSON into a cedar-go @@ -198,7 +201,7 @@ func entitiesToCedar(def *entitiesDefinitionJSON) (cedar.EntityMap, error) { if def.CedarJSON != "" { var em cedar.EntityMap - if err := json.Unmarshal([]byte(def.CedarJSON), &em); err != nil { + if err := json.Unmarshal([]byte(def.CedarJSON), &em, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid entities cedarJson: %w", errInvalidRequest, err) } @@ -245,7 +248,7 @@ func contextToCedar(def *contextDefinitionJSON) (cedar.Record, error) { if def.CedarJSON != "" { var rec cedar.Record - if err := json.Unmarshal([]byte(def.CedarJSON), &rec); err != nil { + if err := json.Unmarshal([]byte(def.CedarJSON), &rec, jsonx.V1()); err != nil { return cedar.Record{}, fmt.Errorf("%w: invalid context cedarJson: %w", errInvalidRequest, err) } diff --git a/services/verifiedpermissions/handler.go b/services/verifiedpermissions/handler.go index 9644569b76..4687845e51 100644 --- a/services/verifiedpermissions/handler.go +++ b/services/verifiedpermissions/handler.go @@ -2,7 +2,7 @@ package verifiedpermissions import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -13,6 +13,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -147,7 +148,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { PolicyID string `json:"policyId"` PolicyTemplateID string `json:"policyTemplateId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.PolicyStoreID != "" && req.PolicyID != "" { return req.PolicyStoreID + "/" + req.PolicyID @@ -223,14 +224,11 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { message := stripCodePrefix(err.Error()) - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrNotFound): return c.JSON(http.StatusBadRequest, map[string]string{ @@ -258,7 +256,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err keyMessageField: message, }) case errors.Is(err, awserr.ErrInvalidParameter), errors.Is(err, errInvalidRequest), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyTypeField: "ValidationException", keyMessageField: message, diff --git a/services/verifiedpermissions/handler_authorization.go b/services/verifiedpermissions/handler_authorization.go index 55f6ab88d4..934dafa251 100644 --- a/services/verifiedpermissions/handler_authorization.go +++ b/services/verifiedpermissions/handler_authorization.go @@ -3,7 +3,7 @@ package verifiedpermissions import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "maps" @@ -11,6 +11,8 @@ import ( "strings" cedar "github.com/cedar-policy/cedar-go" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type entityIdentifierJSON struct { @@ -414,7 +416,7 @@ func parseJWTClaims(token string) (map[string]any, error) { } var claims map[string]any - if unmarshalErr := json.Unmarshal(payload, &claims); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(payload, &claims, jsonx.V1()); unmarshalErr != nil { return nil, fmt.Errorf("%w: bad payload JSON: %w", errMalformedJWT, unmarshalErr) } diff --git a/services/verifiedpermissions/handler_authorization_test.go b/services/verifiedpermissions/handler_authorization_test.go index 93a9dd7f2a..819aa227fb 100644 --- a/services/verifiedpermissions/handler_authorization_test.go +++ b/services/verifiedpermissions/handler_authorization_test.go @@ -2,7 +2,8 @@ package verifiedpermissions_test import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,13 +11,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) // makeTestJWT builds a minimal unsigned JWT whose payload contains the given claims. func makeTestJWT(claims map[string]any) string { b64 := func(v any) string { - raw, _ := json.Marshal(v) + raw, _ := json.Marshal(v, jsonx.V1()) return base64.RawURLEncoding.EncodeToString(raw) } @@ -92,7 +94,7 @@ func TestVPHandler_BatchIsAuthorized(t *testing.T) { if tt.wantLen > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["results"].([]any) assert.Len(t, results, tt.wantLen) @@ -200,7 +202,7 @@ func TestVPHandler_IsAuthorized_DeterminingPolicies_ObjectShape(t *testing.T) { require.Equal(t, http.StatusOK, policyRec.Code) var policyResp map[string]any - require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp, jsonx.V1())) policyID := policyResp["policyId"].(string) rec := doVPRequest(t, h, "IsAuthorized", map[string]any{ @@ -212,7 +214,7 @@ func TestVPHandler_IsAuthorized_DeterminingPolicies_ObjectShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ALLOW", resp["decision"]) determining := resp["determiningPolicies"].([]any) @@ -248,7 +250,7 @@ func TestVPHandler_BatchIsAuthorized_RequestEcho_Shape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) results := resp["results"].([]any) require.Len(t, results, 1) @@ -283,7 +285,7 @@ func TestVPHandler_IsAuthorizedWithToken_PrincipalFromJWT(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) // Create a permissive policy so we can verify ALLOW. @@ -357,7 +359,7 @@ func TestVPHandler_IsAuthorizedWithToken_PrincipalFromJWT(t *testing.T) { if tt.wantDec != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantDec, resp["decision"]) } }) @@ -374,7 +376,7 @@ func TestVPHandler_IsAuthorizedWithToken_MissingToken(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) rec := doVPRequest(t, h, "IsAuthorizedWithToken", map[string]any{ @@ -393,7 +395,7 @@ func TestVPHandler_IsAuthorized_PolicySetCacheDirtyOnMutation(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) authReq := map[string]any{ @@ -416,7 +418,7 @@ func TestVPHandler_IsAuthorized_PolicySetCacheDirtyOnMutation(t *testing.T) { rec := doVPRequest(t, h, "IsAuthorized", authReq) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DENY", resp["decision"], "no policies → DENY") // Add a permissive policy. @@ -430,14 +432,14 @@ func TestVPHandler_IsAuthorized_PolicySetCacheDirtyOnMutation(t *testing.T) { }) require.Equal(t, http.StatusOK, policyRec.Code) var policyResp map[string]any - require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp, jsonx.V1())) policyID := policyResp["policyId"].(string) // After adding policy: cache must invalidate, now ALLOW. rec2 := doVPRequest(t, h, "IsAuthorized", authReq) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, "ALLOW", resp2["decision"], "after CreatePolicy → ALLOW (cache invalidated)") // Delete the policy: cache must invalidate again, back to DENY. @@ -450,7 +452,7 @@ func TestVPHandler_IsAuthorized_PolicySetCacheDirtyOnMutation(t *testing.T) { rec3 := doVPRequest(t, h, "IsAuthorized", authReq) require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) assert.Equal(t, "DENY", resp3["decision"], "after DeletePolicy → DENY (cache invalidated)") } @@ -503,7 +505,7 @@ func TestVPHandler_IsAuthorized_RequestValidation(t *testing.T) { require.Equal(t, http.StatusOK, ps.Code) var psResp map[string]any - _ = json.NewDecoder(ps.Body).Decode(&psResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(ps.Body), &psResp, jsonx.V1()) if v, ok := tt.body["policyStoreId"]; ok && v == "__REPLACE__" { tt.body["policyStoreId"] = psResp["policyStoreId"] @@ -514,7 +516,7 @@ func TestVPHandler_IsAuthorized_RequestValidation(t *testing.T) { if tt.wantField != "" { var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantField) } }) @@ -567,7 +569,7 @@ func TestVPHandler_IsAuthorizedWithToken_RequestValidation(t *testing.T) { require.Equal(t, http.StatusOK, ps.Code) var psResp map[string]any - _ = json.NewDecoder(ps.Body).Decode(&psResp) + _ = json.UnmarshalDecode(jsontext.NewDecoder(ps.Body), &psResp, jsonx.V1()) if v, ok := tt.body["policyStoreId"]; ok && v == "__REPLACE__" { tt.body["policyStoreId"] = psResp["policyStoreId"] @@ -645,7 +647,7 @@ func TestVPHandler_IsAuthorizedWithToken_MultipleIdentitySources_MatchByIssuer(t require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ALLOW", resp["decision"], "token from issuer B must resolve to the Customer identity source, not the first-created Employee one") } @@ -778,7 +780,7 @@ func TestVPHandler_IsAuthorizedWithToken_ClientIDValidation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantDec, resp["decision"]) }) } @@ -821,7 +823,7 @@ func TestVPHandler_IsAuthorizedWithToken_ResponseIncludesPrincipal(t *testing.T) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) principal, ok := resp["principal"].(map[string]any) require.True(t, ok, "response must echo the resolved principal, got: %v", resp) assert.Equal(t, "User", principal["entityType"]) @@ -849,7 +851,7 @@ func TestVPHandler_IsAuthorizedWithToken_ResponseIncludesPrincipal(t *testing.T) ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "DENY", resp["decision"]) assert.NotContains(t, resp, "principal") }) @@ -895,7 +897,7 @@ func TestVPHandler_BatchIsAuthorizedWithToken_RequestEcho_Shape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) principal, ok := resp["principal"].(map[string]any) require.True(t, ok, "top-level principal must be echoed, got: %v", resp) diff --git a/services/verifiedpermissions/handler_identity_sources_test.go b/services/verifiedpermissions/handler_identity_sources_test.go index 04de19e264..9d35bc2d34 100644 --- a/services/verifiedpermissions/handler_identity_sources_test.go +++ b/services/verifiedpermissions/handler_identity_sources_test.go @@ -1,13 +1,15 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -105,7 +107,7 @@ func TestVPHandler_IdentitySource(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -138,7 +140,7 @@ func TestVPHandler_GetIdentitySource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var isResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp, jsonx.V1())) return storeID, isResp["identitySourceId"].(string) }, @@ -206,7 +208,7 @@ func TestVPHandler_DeleteIdentitySource(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var isResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp, jsonx.V1())) return storeID, isResp["identitySourceId"].(string) }, @@ -285,7 +287,7 @@ func TestVPHandler_ListIdentitySources(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sources := resp["identitySources"].([]any) assert.Len(t, sources, tt.wantCount) }) @@ -348,7 +350,7 @@ func TestVPHandler_CreateIdentitySource_OIDCIdentityTokenClientIDs(t *testing.T) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotContains(t, createResp, "configuration", "CreateIdentitySourceOutput has no configuration field in the real SDK") @@ -361,7 +363,7 @@ func TestVPHandler_CreateIdentitySource_OIDCIdentityTokenClientIDs(t *testing.T) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) oidc := resp["configuration"].(map[string]any)["openIdConnectConfiguration"].(map[string]any) tokenSelection := oidc["tokenSelection"].(map[string]any) @@ -396,7 +398,7 @@ func TestVPHandler_CreateIdentitySource_CognitoIssuer(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotContains(t, createResp, "configuration", "CreateIdentitySourceOutput has no configuration field in the real SDK") @@ -409,7 +411,7 @@ func TestVPHandler_CreateIdentitySource_CognitoIssuer(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cognito := resp["configuration"].(map[string]any)["cognitoUserPoolConfiguration"].(map[string]any) assert.Equal(t, "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_test", cognito["issuer"]) @@ -446,7 +448,7 @@ func TestVPHandler_ListIdentitySources_FilterByPrincipalEntityType(t *testing.T) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sources := resp["identitySources"].([]any) require.Len(t, sources, 1) assert.Equal(t, "MyCorp::User", sources[0].(map[string]any)["principalEntityType"]) @@ -535,7 +537,7 @@ func TestVPHandler_UpdateIdentitySource(t *testing.T) { require.Equal(t, http.StatusOK, psRec.Code) var psResp map[string]any - require.NoError(t, json.NewDecoder(psRec.Body).Decode(&psResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(psRec.Body), &psResp, jsonx.V1())) psID := psResp["policyStoreId"].(string) @@ -551,7 +553,7 @@ func TestVPHandler_UpdateIdentitySource(t *testing.T) { require.Equal(t, http.StatusOK, isRec.Code) var isResp map[string]any - require.NoError(t, json.NewDecoder(isRec.Body).Decode(&isResp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(isRec.Body), &isResp, jsonx.V1())) isID := isResp["identitySourceId"].(string) @@ -588,7 +590,7 @@ func TestVPHandler_CreateUpdateIdentitySource_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code, "body: %s", createRec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) assert.NotContains(t, createResp, "principalEntityType") assert.NotContains(t, createResp, "configuration") assert.NotEmpty(t, createResp["identitySourceId"]) @@ -608,7 +610,7 @@ func TestVPHandler_CreateUpdateIdentitySource_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, updateRec.Code, "body: %s", updateRec.Body.String()) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotContains(t, updateResp, "principalEntityType") assert.NotContains(t, updateResp, "configuration") assert.Equal(t, createResp["identitySourceId"], updateResp["identitySourceId"]) diff --git a/services/verifiedpermissions/handler_policies_test.go b/services/verifiedpermissions/handler_policies_test.go index 39cdf2be70..6467d4e566 100644 --- a/services/verifiedpermissions/handler_policies_test.go +++ b/services/verifiedpermissions/handler_policies_test.go @@ -2,7 +2,7 @@ package verifiedpermissions_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -42,7 +43,7 @@ func TestVPHandler_PolicyCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) // Create policy @@ -57,7 +58,7 @@ func TestVPHandler_PolicyCRUD(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var policyResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp, jsonx.V1())) policyID := policyResp["policyId"].(string) assert.NotEmpty(t, policyID) @@ -253,7 +254,7 @@ func TestVPHandler_GetPolicy_NotFound(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) rec = doVPRequest(t, h, "GetPolicy", map[string]any{ @@ -280,7 +281,7 @@ func TestVPHandler_DeletePolicy_IdempotentOnMissingPolicy(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) rec = doVPRequest(t, h, "DeletePolicy", map[string]any{ @@ -318,7 +319,7 @@ func TestVPHandler_CreatePolicy_TemplateLinked(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) // Create a policy template first. @@ -329,7 +330,7 @@ func TestVPHandler_CreatePolicy_TemplateLinked(t *testing.T) { }) require.Equal(t, http.StatusOK, tmplRec.Code) var tmplResp map[string]any - require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp)) + require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp, jsonx.V1())) templateID := tmplResp["policyTemplateId"].(string) // Create template-linked policy @@ -346,7 +347,7 @@ func TestVPHandler_CreatePolicy_TemplateLinked(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var policyResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &policyResp, jsonx.V1())) assert.Equal(t, "TEMPLATE_LINKED", policyResp["policyType"]) } @@ -370,7 +371,7 @@ func TestVPHandler_UpdatePolicy_TemplateLinkedRejected(t *testing.T) { }) require.Equal(t, http.StatusOK, tmplRec.Code) var tmplResp map[string]any - require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp)) + require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp, jsonx.V1())) templateID := tmplResp["policyTemplateId"].(string) createRec := doVPRequest(t, h, "CreatePolicy", map[string]any{ @@ -385,7 +386,7 @@ func TestVPHandler_UpdatePolicy_TemplateLinkedRejected(t *testing.T) { }) require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["policyId"].(string) t.Run("templateLinked definition rejected outright", func(t *testing.T) { @@ -429,7 +430,7 @@ func TestVPHandler_UpdatePolicy_TemplateLinkedRejected(t *testing.T) { }) require.Equal(t, http.StatusOK, staticRec.Code) var staticResp map[string]any - require.NoError(t, json.Unmarshal(staticRec.Body.Bytes(), &staticResp)) + require.NoError(t, json.Unmarshal(staticRec.Body.Bytes(), &staticResp, jsonx.V1())) staticPolicyID := staticResp["policyId"].(string) rec := doVPRequest(t, h, "UpdatePolicy", map[string]any{ @@ -449,7 +450,7 @@ func TestVPHandler_UpdatePolicy_TemplateLinkedRejected(t *testing.T) { getRec := doVPRequest(t, h, "GetPolicy", map[string]any{"policyStoreId": storeID, "policyId": policyID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) def := getResp["definition"].(map[string]any)["templateLinked"].(map[string]any) assert.Equal(t, "alice", def["principal"].(map[string]any)["entityId"]) } @@ -479,7 +480,7 @@ func TestVPHandler_BatchGetPolicy(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var pResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &pResp, jsonx.V1())) policyID := pResp["policyId"].(string) return map[string]any{ @@ -544,7 +545,7 @@ func TestVPHandler_BatchGetPolicy(t *testing.T) { if tt.check != nil { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tt.check(t, resp) } }) @@ -562,7 +563,7 @@ func TestVPHandler_BatchGetPolicy_EmptyRequests(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp["results"]) assert.Empty(t, resp["errors"]) } @@ -580,7 +581,7 @@ func TestVPHandler_ListPolicies_FilterByPrincipalIdentifier(t *testing.T) { require.Equal(t, http.StatusOK, ptRec.Code) var ptResp map[string]any - require.NoError(t, json.Unmarshal(ptRec.Body.Bytes(), &ptResp)) + require.NoError(t, json.Unmarshal(ptRec.Body.Bytes(), &ptResp, jsonx.V1())) templateID := ptResp["policyTemplateId"].(string) linkedRec := doVPRequest(t, h, "CreatePolicy", map[string]any{ @@ -614,7 +615,7 @@ func TestVPHandler_ListPolicies_FilterByPrincipalIdentifier(t *testing.T) { require.Equal(t, http.StatusOK, filteredRec.Code, "body: %s", filteredRec.Body.String()) var filteredResp map[string]any - require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp)) + require.NoError(t, json.Unmarshal(filteredRec.Body.Bytes(), &filteredResp, jsonx.V1())) policies := filteredResp["policies"].([]any) require.Len(t, policies, 1) @@ -628,7 +629,7 @@ func TestVPHandler_ListPolicies_FilterByPrincipalIdentifier(t *testing.T) { require.Equal(t, http.StatusOK, unspecifiedRec.Code, "body: %s", unspecifiedRec.Body.String()) var unspecifiedResp map[string]any - require.NoError(t, json.Unmarshal(unspecifiedRec.Body.Bytes(), &unspecifiedResp)) + require.NoError(t, json.Unmarshal(unspecifiedRec.Body.Bytes(), &unspecifiedResp, jsonx.V1())) unspecifiedPolicies := unspecifiedResp["policies"].([]any) require.Len(t, unspecifiedPolicies, 1) } @@ -649,7 +650,7 @@ func TestVPHandler_BatchGetPolicy_IncludesDefinition(t *testing.T) { require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID, _ := storeResp["policyStoreId"].(string) require.NotEmpty(t, policyStoreID) @@ -667,7 +668,7 @@ func TestVPHandler_BatchGetPolicy_IncludesDefinition(t *testing.T) { require.Equal(t, http.StatusOK, staticRec.Code) var staticResp map[string]any - require.NoError(t, json.Unmarshal(staticRec.Body.Bytes(), &staticResp)) + require.NoError(t, json.Unmarshal(staticRec.Body.Bytes(), &staticResp, jsonx.V1())) staticPolicyID, _ := staticResp["policyId"].(string) require.NotEmpty(t, staticPolicyID) @@ -681,7 +682,7 @@ func TestVPHandler_BatchGetPolicy_IncludesDefinition(t *testing.T) { require.Equal(t, http.StatusOK, tmplRec.Code) var tmplResp map[string]any - require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp)) + require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp, jsonx.V1())) templateID, _ := tmplResp["policyTemplateId"].(string) require.NotEmpty(t, templateID) @@ -705,7 +706,7 @@ func TestVPHandler_BatchGetPolicy_IncludesDefinition(t *testing.T) { require.Equal(t, http.StatusOK, tlRec.Code) var tlResp map[string]any - require.NoError(t, json.Unmarshal(tlRec.Body.Bytes(), &tlResp)) + require.NoError(t, json.Unmarshal(tlRec.Body.Bytes(), &tlResp, jsonx.V1())) tlPolicyID, _ := tlResp["policyId"].(string) require.NotEmpty(t, tlPolicyID) @@ -748,7 +749,7 @@ func TestVPHandler_BatchGetPolicy_IncludesDefinition(t *testing.T) { require.Equal(t, http.StatusOK, batchRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &resp, jsonx.V1())) results, ok := resp["results"].([]any) require.True(t, ok, "results must be an array") @@ -779,7 +780,7 @@ func TestVPHandler_ListPolicies_PaginationOpaqueTokens(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) // Create 3 policies. @@ -803,7 +804,7 @@ func TestVPHandler_ListPolicies_PaginationOpaqueTokens(t *testing.T) { }) require.Equal(t, http.StatusOK, page1Rec.Code) var page1 map[string]any - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1, jsonx.V1())) nextToken, _ := page1["nextToken"].(string) require.NotEmpty(t, nextToken, "nextToken must be present when more results exist") @@ -821,7 +822,7 @@ func TestVPHandler_ListPolicies_PaginationOpaqueTokens(t *testing.T) { }) require.Equal(t, http.StatusOK, page2Rec.Code, "page2 body: %s", page2Rec.Body.String()) var page2 map[string]any - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2, jsonx.V1())) page2Items, _ := page2["policies"].([]any) assert.Len(t, page2Items, 1, "page2 should have the remaining 1 policy") @@ -851,7 +852,7 @@ func TestVPHandler_CreatePolicy_StaticScopeEcho(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Forbid", resp["effect"]) @@ -894,7 +895,7 @@ func TestVPHandler_CreatePolicy_UnconstrainedScopeOmitsEchoFields(t *testing.T) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Permit", resp["effect"]) assert.NotContains(t, resp, "principal") @@ -919,7 +920,7 @@ func TestVPHandler_GetPolicy_TemplateLinkedScopeEcho(t *testing.T) { }) require.Equal(t, http.StatusOK, tmplRec.Code) var tmplResp map[string]any - require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp)) + require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp, jsonx.V1())) templateID := tmplResp["policyTemplateId"].(string) rec := doVPRequest(t, h, "CreatePolicy", map[string]any{ @@ -934,7 +935,7 @@ func TestVPHandler_GetPolicy_TemplateLinkedScopeEcho(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) policyID := createResp["policyId"].(string) assert.Equal(t, "Forbid", createResp["effect"]) @@ -949,7 +950,7 @@ func TestVPHandler_GetPolicy_TemplateLinkedScopeEcho(t *testing.T) { }) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) principal, _ := getResp["principal"].(map[string]any) require.NotNil(t, principal) @@ -982,7 +983,7 @@ func TestVPHandler_ListPolicies_StaticItemOmitsStatement(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp["policies"].([]any) require.Len(t, items, 1) @@ -999,7 +1000,7 @@ func TestVPHandler_ListPolicies_StaticItemOmitsStatement(t *testing.T) { getRec := doVPRequest(t, h, "GetPolicy", map[string]any{"policyStoreId": storeID, "policyId": policyID}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) getStatic, _ := getResp["definition"].(map[string]any)["static"].(map[string]any) assert.Equal(t, `permit(principal, action, resource);`, getStatic["statement"]) } diff --git a/services/verifiedpermissions/handler_policy_stores_test.go b/services/verifiedpermissions/handler_policy_stores_test.go index ba5a183785..d275f8cf84 100644 --- a/services/verifiedpermissions/handler_policy_stores_test.go +++ b/services/verifiedpermissions/handler_policy_stores_test.go @@ -1,7 +1,7 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "maps" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -55,7 +56,7 @@ func TestVPHandler_CreatePolicyStore(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantKey) }) } @@ -81,7 +82,7 @@ func TestVPHandler_GetPolicyStore(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["policyStoreId"].(string) }, @@ -148,7 +149,7 @@ func TestVPHandler_ListPolicyStores(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores := resp["policyStores"].([]any) assert.Len(t, stores, tt.numStores) }) @@ -175,7 +176,7 @@ func TestVPHandler_DeletePolicyStore(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["policyStoreId"].(string) }, @@ -225,7 +226,7 @@ func TestVPHandler_UpdatePolicyStore(t *testing.T) { map[string]any{"description": "original", "validationSettings": map[string]any{"mode": "OFF"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["policyStoreId"].(string) }, @@ -302,7 +303,7 @@ func TestVPHandler_CreatePolicyStore_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotEmpty(t, resp["policyStoreId"]) assert.NotEmpty(t, resp["arn"]) } @@ -353,14 +354,14 @@ func TestVPHandler_DeletePolicyStore_DeletionProtection_InvalidStateException(t require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) storeID := createResp["policyStoreId"].(string) rec := doVPRequest(t, h, "DeletePolicyStore", map[string]any{"policyStoreId": storeID}) require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidStateException", resp["__type"]) } @@ -409,7 +410,7 @@ func TestVPHandler_CreatePolicyStore_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "validationSettings") assert.NotEmpty(t, resp["policyStoreId"]) @@ -432,7 +433,7 @@ func TestVPHandler_GetPolicyStore_CedarVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "CEDAR_4", resp["cedarVersion"]) } @@ -451,7 +452,7 @@ func TestVPHandler_ListPolicyStores_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["policyStores"].([]any) require.NotEmpty(t, items) @@ -479,7 +480,7 @@ func TestVPHandler_UpdatePolicyStore_WireShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "validationSettings") assert.NotEmpty(t, resp["createdDate"], "createdDate is a required UpdatePolicyStoreOutput field") @@ -554,7 +555,7 @@ func TestVPHandler_CreatePolicyStoreAlias(t *testing.T) { assert.Equal(t, tt.wantCode, rec.Code, "body: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantType != "" { assert.Equal(t, tt.wantType, resp["__type"]) @@ -591,13 +592,13 @@ func TestVPHandler_CreatePolicyStoreAlias_IdempotentAndConflict(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) rec2 := doVPRequest(t, h, "CreatePolicyStoreAlias", body) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, resp1["createdAt"], resp2["createdAt"], "same (aliasName, policyStoreId) replays, no duplicate") rec3 := doVPRequest(t, h, "CreatePolicyStoreAlias", map[string]any{ @@ -606,7 +607,7 @@ func TestVPHandler_CreatePolicyStoreAlias_IdempotentAndConflict(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec3.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) } @@ -657,7 +658,7 @@ func TestVPHandler_GetPolicyStoreAlias(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "Active", resp["state"]) assert.Equal(t, aliasName, resp["aliasName"]) }) @@ -700,7 +701,7 @@ func TestVPHandler_ListPolicyStoreAliases(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["policyStoreAliases"].([]any) assert.Len(t, items, tt.wantCount) }) @@ -756,7 +757,7 @@ func TestVPHandler_DeletePolicyStoreAlias(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantState, resp["state"]) }) } @@ -802,7 +803,7 @@ func TestVPHandler_DeletePolicyStore_CascadesAliases(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["policyStoreAliases"].([]any) assert.Empty(t, items, "dangling alias row survived policy store delete") @@ -872,7 +873,7 @@ func TestVPHandler_ResolvePolicyStoreID_AcceptsAlias(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, storeID, resp["policyStoreId"], "response echoes the real ID, not the alias") }) } @@ -923,13 +924,13 @@ func TestVPHandler_CreatePolicyStore_ClientTokenIdempotency(t *testing.T) { rec1 := doVPRequest(t, h, "CreatePolicyStore", body("first")) require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) // Same token, same parameters: replays the original policy store. rec2 := doVPRequest(t, h, "CreatePolicyStore", body("first")) require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, resp1["policyStoreId"], resp2["policyStoreId"]) assert.Equal(t, resp1["createdDate"], resp2["createdDate"]) @@ -938,7 +939,7 @@ func TestVPHandler_CreatePolicyStore_ClientTokenIdempotency(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec3.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) // A different token creates a genuinely new policy store. @@ -949,6 +950,6 @@ func TestVPHandler_CreatePolicyStore_ClientTokenIdempotency(t *testing.T) { }) require.Equal(t, http.StatusOK, rec4.Code) var resp4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4, jsonx.V1())) assert.NotEqual(t, resp1["policyStoreId"], resp4["policyStoreId"]) } diff --git a/services/verifiedpermissions/handler_policy_templates_test.go b/services/verifiedpermissions/handler_policy_templates_test.go index 946e024005..b5b412c861 100644 --- a/services/verifiedpermissions/handler_policy_templates_test.go +++ b/services/verifiedpermissions/handler_policy_templates_test.go @@ -1,12 +1,14 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestVPHandler_PolicyTemplateCRUD(t *testing.T) { @@ -38,7 +40,7 @@ func TestVPHandler_PolicyTemplateCRUD(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) // Create template @@ -50,7 +52,7 @@ func TestVPHandler_PolicyTemplateCRUD(t *testing.T) { require.Equal(t, tt.wantCode, rec.Code) var tplResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tplResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &tplResp, jsonx.V1())) templateID := tplResp["policyTemplateId"].(string) assert.NotEmpty(t, templateID) @@ -195,7 +197,7 @@ func TestVPHandler_UpdatePolicyTemplate_NotFound(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) rec = doVPRequest(t, h, "UpdatePolicyTemplate", map[string]any{ @@ -219,7 +221,7 @@ func TestVPHandler_DeletePolicyTemplate_NotFound(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var storeResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &storeResp, jsonx.V1())) storeID := storeResp["policyStoreId"].(string) rec = doVPRequest(t, h, "DeletePolicyTemplate", map[string]any{ diff --git a/services/verifiedpermissions/handler_schema_test.go b/services/verifiedpermissions/handler_schema_test.go index 562b11631a..783fbabd34 100644 --- a/services/verifiedpermissions/handler_schema_test.go +++ b/services/verifiedpermissions/handler_schema_test.go @@ -1,13 +1,14 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -77,7 +78,7 @@ func TestVPHandler_PutSchema(t *testing.T) { if tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, storeID, resp["policyStoreId"]) assert.NotEmpty(t, resp["createdDate"]) assert.NotEmpty(t, resp["lastUpdatedDate"]) @@ -147,7 +148,7 @@ func TestVPHandler_GetSchema(t *testing.T) { if hasPut && tt.wantCode == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, storeID, resp["policyStoreId"]) assert.JSONEq(t, `{"namespace": "MyCorp"}`, resp["schema"].(string)) } @@ -180,6 +181,6 @@ func TestVPHandler_PutSchema_UpdateSchema(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, `{"v": 2}`, resp["schema"]) } diff --git a/services/verifiedpermissions/handler_tags_test.go b/services/verifiedpermissions/handler_tags_test.go index 55e5f0fd5f..80d4394d06 100644 --- a/services/verifiedpermissions/handler_tags_test.go +++ b/services/verifiedpermissions/handler_tags_test.go @@ -1,7 +1,7 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strconv" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -34,7 +35,7 @@ func TestVPHandler_TagResource(t *testing.T) { map[string]any{"description": "test", "validationSettings": map[string]any{"mode": "OFF"}}, ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["arn"].(string) }, @@ -95,7 +96,7 @@ func TestVPHandler_UntagResource(t *testing.T) { "validationSettings": map[string]any{"mode": "OFF"}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["arn"].(string) }, @@ -156,7 +157,7 @@ func TestVPHandler_ListTagsForResource(t *testing.T) { "validationSettings": map[string]any{"mode": "OFF"}, }) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["arn"].(string) }, @@ -193,7 +194,7 @@ func TestVPHandler_ListTagsForResource(t *testing.T) { if tt.wantTags { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "tags") } }) @@ -210,7 +211,7 @@ func TestVPHandler_TagResource_TooManyTags(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) resourceARN := getResp["arn"].(string) tags := make(map[string]any, 51) @@ -225,7 +226,7 @@ func TestVPHandler_TagResource_TooManyTags(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TooManyTagsException", resp["__type"]) } @@ -245,7 +246,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) // Get policy store ARN. @@ -254,7 +255,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { }) require.Equal(t, http.StatusOK, getStoreRec.Code) var getStoreResp map[string]any - require.NoError(t, json.Unmarshal(getStoreRec.Body.Bytes(), &getStoreResp)) + require.NoError(t, json.Unmarshal(getStoreRec.Body.Bytes(), &getStoreResp, jsonx.V1())) storeARN := getStoreResp["arn"].(string) _ = storeARN @@ -270,7 +271,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { }) require.Equal(t, http.StatusOK, policyRec.Code) var policyResp map[string]any - require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp)) + require.NoError(t, json.Unmarshal(policyRec.Body.Bytes(), &policyResp, jsonx.V1())) policyID := policyResp["policyId"].(string) // Build the policy ARN (format: arn:aws:verifiedpermissions:::policy//) @@ -289,7 +290,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { listRec1 := doVPRequest(t, h, "ListTagsForResource", map[string]any{"resourceArn": policyARN}) require.Equal(t, http.StatusOK, listRec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(listRec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(listRec1.Body.Bytes(), &resp1, jsonx.V1())) tags1, _ := resp1["tags"].(map[string]any) assert.Equal(t, "test", tags1["Env"]) @@ -303,7 +304,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { listRec2 := doVPRequest(t, h, "ListTagsForResource", map[string]any{"resourceArn": policyARN}) require.Equal(t, http.StatusOK, listRec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(listRec2.Body.Bytes(), &resp2, jsonx.V1())) tags2, _ := resp2["tags"].(map[string]any) assert.Equal(t, "prod", tags2["Env"]) @@ -319,7 +320,7 @@ func TestVPHandler_TagResource_PolicyResource(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) _, envPresent := tags["Env"] assert.False(t, envPresent, "Env tag should be removed after UntagResource") @@ -335,7 +336,7 @@ func TestVPHandler_TagResource_PolicyTemplateResource(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) tmplRec := doVPRequest(t, h, "CreatePolicyTemplate", map[string]any{ @@ -345,7 +346,7 @@ func TestVPHandler_TagResource_PolicyTemplateResource(t *testing.T) { }) require.Equal(t, http.StatusOK, tmplRec.Code) var tmplResp map[string]any - require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp)) + require.NoError(t, json.Unmarshal(tmplRec.Body.Bytes(), &tmplResp, jsonx.V1())) templateID := tmplResp["policyTemplateId"].(string) templateARN := fmt.Sprintf( @@ -364,7 +365,7 @@ func TestVPHandler_TagResource_PolicyTemplateResource(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) assert.Equal(t, "parity-test", tags["Purpose"]) } @@ -379,7 +380,7 @@ func TestVPHandler_TagResource_IdentitySourceResource(t *testing.T) { }) require.Equal(t, http.StatusOK, storeRec.Code) var storeResp map[string]any - require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp)) + require.NoError(t, json.Unmarshal(storeRec.Body.Bytes(), &storeResp, jsonx.V1())) policyStoreID := storeResp["policyStoreId"].(string) isRec := doVPRequest(t, h, "CreateIdentitySource", map[string]any{ @@ -394,7 +395,7 @@ func TestVPHandler_TagResource_IdentitySourceResource(t *testing.T) { }) require.Equal(t, http.StatusOK, isRec.Code, "CreateIdentitySource body: %s", isRec.Body.String()) var isResp map[string]any - require.NoError(t, json.Unmarshal(isRec.Body.Bytes(), &isResp)) + require.NoError(t, json.Unmarshal(isRec.Body.Bytes(), &isResp, jsonx.V1())) identitySourceID := isResp["identitySourceId"].(string) identitySourceARN := fmt.Sprintf( @@ -413,7 +414,7 @@ func TestVPHandler_TagResource_IdentitySourceResource(t *testing.T) { }) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) tags, _ := listResp["tags"].(map[string]any) assert.Equal(t, "parity", tags["Owner"]) } diff --git a/services/verifiedpermissions/handler_test.go b/services/verifiedpermissions/handler_test.go index 9a4bfee5b1..0eb2a67d03 100644 --- a/services/verifiedpermissions/handler_test.go +++ b/services/verifiedpermissions/handler_test.go @@ -2,7 +2,8 @@ package verifiedpermissions_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -33,7 +35,7 @@ func doVPRequest( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -75,7 +77,7 @@ func createTestPolicyStore(t *testing.T, h *verifiedpermissions.Handler) string require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp["policyStoreId"].(string) } @@ -235,7 +237,7 @@ func TestVPHandler_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -315,7 +317,7 @@ func TestVPHandler_Snapshot_Restore(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores := resp["policyStores"].([]any) assert.Len(t, stores, tt.numStores) }) @@ -384,7 +386,7 @@ func TestVPHandler_Snapshot_Restore_WithNewResources(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var isResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &isResp, jsonx.V1())) isID := isResp["identitySourceId"].(string) // Put schema @@ -414,7 +416,7 @@ func TestVPHandler_Snapshot_Restore_WithNewResources(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var schemaResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schemaResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &schemaResp, jsonx.V1())) assert.JSONEq(t, `{"ns": "test"}`, schemaResp["schema"].(string)) } @@ -475,7 +477,7 @@ func TestVPHandler_HandleError_ValidationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.NewDecoder(rec.Body).Decode(&resp)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(rec.Body), &resp, jsonx.V1())) assert.Equal(t, "ValidationException", resp["__type"]) } @@ -515,7 +517,7 @@ func TestVPHandler_UnknownOp_ReturnsUnknownOperationException(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "UnknownOperationException", resp["__type"], "body: %s", rec.Body.String()) }) } diff --git a/services/verifiedpermissions/idempotency_test.go b/services/verifiedpermissions/idempotency_test.go index ea1b1ddff8..9d6ed32bbf 100644 --- a/services/verifiedpermissions/idempotency_test.go +++ b/services/verifiedpermissions/idempotency_test.go @@ -1,12 +1,14 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestVPHandler_CreateOps_ClientTokenIdempotency table-drives the shared @@ -93,19 +95,19 @@ func TestVPHandler_CreateOps_ClientTokenIdempotency(t *testing.T) { rec1 := doVPRequest(t, h, tt.action, tt.body(storeID, "fixed-token", "v1")) require.Equal(t, http.StatusOK, rec1.Code, "body: %s", rec1.Body.String()) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) // Same token, same parameters: replays the original resource. rec2 := doVPRequest(t, h, tt.action, tt.body(storeID, "fixed-token", "v1")) require.Equal(t, http.StatusOK, rec2.Code, "body: %s", rec2.Body.String()) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) assert.Equal(t, resp1[tt.idField], resp2[tt.idField]) listRec := doVPRequest(t, h, tt.listAction, map[string]any{"policyStoreId": storeID}) require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) items, _ := listResp[tt.listField].([]any) assert.Len(t, items, 1, "a replayed ClientToken call must not create a duplicate resource") @@ -113,7 +115,7 @@ func TestVPHandler_CreateOps_ClientTokenIdempotency(t *testing.T) { rec3 := doVPRequest(t, h, tt.action, tt.body(storeID, "fixed-token", "v2-different")) assert.Equal(t, http.StatusBadRequest, rec3.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "ConflictException", errResp["__type"]) }) } diff --git a/services/verifiedpermissions/multi_region_test.go b/services/verifiedpermissions/multi_region_test.go index f790a3625f..81efc36fa2 100644 --- a/services/verifiedpermissions/multi_region_test.go +++ b/services/verifiedpermissions/multi_region_test.go @@ -2,7 +2,8 @@ package verifiedpermissions_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -19,6 +20,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/verifiedpermissions" ) @@ -180,8 +182,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/verifiedpermissions/oidc_jwks.go b/services/verifiedpermissions/oidc_jwks.go index e09957cda8..b584091b30 100644 --- a/services/verifiedpermissions/oidc_jwks.go +++ b/services/verifiedpermissions/oidc_jwks.go @@ -6,7 +6,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/base64" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "io" @@ -20,6 +20,7 @@ import ( awsarn "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -103,7 +104,7 @@ func (v *TokenVerifier) getJSON(rawURL string, out any) error { return fmt.Errorf("read %s: %w", rawURL, err) } - if err = json.Unmarshal(body, out); err != nil { + if err = json.Unmarshal(body, out, jsonx.V1()); err != nil { return fmt.Errorf("decode %s: %w", rawURL, err) } diff --git a/services/verifiedpermissions/omission_defaults_test.go b/services/verifiedpermissions/omission_defaults_test.go index a61e124fc7..c1e5a8194b 100644 --- a/services/verifiedpermissions/omission_defaults_test.go +++ b/services/verifiedpermissions/omission_defaults_test.go @@ -1,13 +1,15 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // These tests lock in the documented per-page default the real SDK states @@ -28,7 +30,7 @@ func TestVPHandler_ListPolicyStores_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stores, _ := resp["policyStores"].([]any) assert.Len(t, stores, 10, "ListPolicyStores omits maxResults => real SDK defaults to 10 per response") @@ -58,7 +60,7 @@ func TestVPHandler_ListPolicies_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, _ := resp["policies"].([]any) assert.Len(t, policies, 10, "ListPolicies omits maxResults => real SDK defaults to 10 per response") @@ -83,7 +85,7 @@ func TestVPHandler_ListPolicyTemplates_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) templates, _ := resp["policyTemplates"].([]any) assert.Len(t, templates, 10, "ListPolicyTemplates omits maxResults => real SDK defaults to 10 per response") @@ -114,7 +116,7 @@ func TestVPHandler_ListIdentitySources_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sources, _ := resp["identitySources"].([]any) assert.Len(t, sources, 10, "ListIdentitySources omits maxResults => real SDK defaults to 10 per response") @@ -139,7 +141,7 @@ func TestVPHandler_ListPolicyStoreAliases_DefaultPageSize(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) aliases, _ := resp["policyStoreAliases"].([]any) assert.Len(t, aliases, 5, "ListPolicyStoreAliases omits maxResults => real SDK defaults to 5 per response") @@ -169,7 +171,7 @@ func TestVPHandler_CreateIdentitySource_CognitoGroupEntityTypeDefault(t *testing require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String()) var created map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &created, jsonx.V1())) rec = doVPRequest(t, h, "GetIdentitySource", map[string]any{ "policyStoreId": storeID, @@ -178,7 +180,7 @@ func TestVPHandler_CreateIdentitySource_CognitoGroupEntityTypeDefault(t *testing require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) cfg, _ := resp["configuration"].(map[string]any) cognito, _ := cfg["cognitoUserPoolConfiguration"].(map[string]any) diff --git a/services/verifiedpermissions/persistence.go b/services/verifiedpermissions/persistence.go index 53cb195968..2ad772f1fa 100644 --- a/services/verifiedpermissions/persistence.go +++ b/services/verifiedpermissions/persistence.go @@ -2,7 +2,7 @@ package verifiedpermissions import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -57,7 +57,7 @@ func buildSchemaDTORegistry() (*store.Registry, *store.Table[policyStoreSchemaDT // InMemoryBackend's doc comment in backend.go) and is persisted here // directly, as before. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ResourceTags map[string]map[string]string `json:"resourceTags,omitempty"` AccountID string `json:"accountID"` Region string `json:"region"` @@ -163,7 +163,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // registerAllTables doc) from tables via the ephemeral DTO registry, factored // out of Restore to keep Restore's own cognitive complexity low. Callers must // hold b.mu.Lock. -func (b *InMemoryBackend) restoreSchemas(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreSchemas(tables map[string]jsontext.Value) error { dtoReg, dtoTable := buildSchemaDTORegistry() if err := dtoReg.RestoreAll(tables); err != nil { return fmt.Errorf("verifiedpermissions: restore snapshot schema DTO table: %w", err) diff --git a/services/verifiedpermissions/policy_scope.go b/services/verifiedpermissions/policy_scope.go index 9d6ccc13aa..56f067d4b7 100644 --- a/services/verifiedpermissions/policy_scope.go +++ b/services/verifiedpermissions/policy_scope.go @@ -1,10 +1,12 @@ package verifiedpermissions import ( - "encoding/json" + "encoding/json/v2" "regexp" cedar "github.com/cedar-policy/cedar-go" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // cedarScopeEntity mirrors the "entity" object nested inside a Cedar JSON @@ -80,7 +82,7 @@ func instantiateTemplate(templateStatement string, p *Policy) string { // cedarEntityLiteral renders entityType::"entityId" as a Cedar entity UID literal. func cedarEntityLiteral(entityType, entityID string) string { - b, _ := json.Marshal(entityID) // Cedar string-literal escaping matches JSON's for plain ASCII IDs. + b, _ := json.Marshal(entityID, jsonx.V1()) // Cedar string-literal escaping matches JSON's for plain ASCII IDs. return entityType + "::" + string(b) } @@ -105,7 +107,7 @@ func parseCedarScope(statement string) *PolicyScopeResult { } var pj cedarPolicyJSON - if unmarshalErr := json.Unmarshal(raw, &pj); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(raw, &pj, jsonx.V1()); unmarshalErr != nil { return nil } diff --git a/services/verifiedpermissions/policy_template_item_shape_test.go b/services/verifiedpermissions/policy_template_item_shape_test.go index dfeafdbb97..d4461e57d7 100644 --- a/services/verifiedpermissions/policy_template_item_shape_test.go +++ b/services/verifiedpermissions/policy_template_item_shape_test.go @@ -1,11 +1,13 @@ package verifiedpermissions_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListPolicyTemplates_ItemHasNoStatement proves ListPolicyTemplates' @@ -35,7 +37,7 @@ func TestListPolicyTemplates_ItemHasNoStatement(t *testing.T) { var body struct { PolicyTemplates []map[string]any `json:"policyTemplates"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &body, jsonx.V1())) require.Len(t, body.PolicyTemplates, 1) item := body.PolicyTemplates[0] diff --git a/services/verifiedpermissions/policy_validation.go b/services/verifiedpermissions/policy_validation.go index 0b686b94bf..c5a3db341d 100644 --- a/services/verifiedpermissions/policy_validation.go +++ b/services/verifiedpermissions/policy_validation.go @@ -2,19 +2,22 @@ package verifiedpermissions import ( "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "strings" cedar "github.com/cedar-policy/cedar-go" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var errSchemaMismatch = errors.New("policy validation failed") type cedarSchemaNamespace struct { - EntityTypes map[string]json.RawMessage `json:"entityTypes"` - Actions map[string]json.RawMessage `json:"actions"` + EntityTypes map[string]jsontext.Value `json:"entityTypes"` + Actions map[string]jsontext.Value `json:"actions"` } // splitQualified splits "NS::Sub::Name" into its namespace and local name. @@ -34,7 +37,7 @@ func (b *InMemoryBackend) loadSchemaNamespacesLocked(policyStoreID string) (map[ } var ns map[string]cedarSchemaNamespace - if err := json.Unmarshal([]byte(s.Schema), &ns); err != nil { + if err := json.Unmarshal([]byte(s.Schema), &ns, jsonx.V1()); err != nil { return nil, true } @@ -73,7 +76,7 @@ func (b *InMemoryBackend) validateStaticPolicyLocked(policyStoreID, statement st } var pj cedarPolicyJSON - if json.Unmarshal(raw, &pj) != nil { + if json.Unmarshal(raw, &pj, jsonx.V1()) != nil { continue } diff --git a/services/verifiedpermissions/schema.go b/services/verifiedpermissions/schema.go index ce86f7c45b..5fb8f2d4b2 100644 --- a/services/verifiedpermissions/schema.go +++ b/services/verifiedpermissions/schema.go @@ -1,18 +1,20 @@ package verifiedpermissions import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "time" "github.com/blackbirdworks/gopherstack/pkgs/collections" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // extractSchemaNamespaces parses a Cedar JSON schema and returns its top-level namespace keys. func extractSchemaNamespaces(schemaJSON string) []string { - var top map[string]json.RawMessage + var top map[string]jsontext.Value - if err := json.Unmarshal([]byte(schemaJSON), &top); err != nil { + if err := json.Unmarshal([]byte(schemaJSON), &top, jsonx.V1()); err != nil { return []string{} } @@ -31,7 +33,7 @@ func (b *InMemoryBackend) PutSchema(policyStoreID, schema string) ([]string, err } // Validate JSON format. - if !json.Valid([]byte(schema)) { + if !jsontext.Value([]byte(schema)).IsValid(jsonx.V1()) { return nil, fmt.Errorf("%w: schema is not valid JSON", ErrValidation) } diff --git a/services/vpclattice/handler.go b/services/vpclattice/handler.go index e1fc76a20a..8fff26fd74 100644 --- a/services/vpclattice/handler.go +++ b/services/vpclattice/handler.go @@ -1,7 +1,8 @@ package vpclattice import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "net/http" "strconv" @@ -13,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -593,7 +595,7 @@ func (h *Handler) handleREST(c *echo.Context) error { var body map[string]any if c.Request().ContentLength != 0 { - if err := json.NewDecoder(c.Request().Body).Decode(&body); err != nil && + if err := json.UnmarshalDecode(jsontext.NewDecoder(c.Request().Body), &body, jsonx.V1()); err != nil && err.Error() != "EOF" { return validationError(c, "invalid JSON body") } diff --git a/services/vpclattice/handler_test.go b/services/vpclattice/handler_test.go index d2224d5337..b7b8d1ac26 100644 --- a/services/vpclattice/handler_test.go +++ b/services/vpclattice/handler_test.go @@ -3,7 +3,7 @@ package vpclattice_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/vpclattice" ) @@ -33,7 +34,7 @@ func doRequestWithRegion( var buf *bytes.Reader if body != nil { - data, err := json.Marshal(body) + data, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) buf = bytes.NewReader(data) } else { @@ -71,7 +72,7 @@ func doRequest( var buf *bytes.Reader if body != nil { - data, err := json.Marshal(body) + data, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) buf = bytes.NewReader(data) } else { @@ -95,7 +96,7 @@ func doRequest( func parseBody(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/vpclattice/multi_region_test.go b/services/vpclattice/multi_region_test.go index b71532f154..5af29fae29 100644 --- a/services/vpclattice/multi_region_test.go +++ b/services/vpclattice/multi_region_test.go @@ -2,7 +2,7 @@ package vpclattice_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/vpclattice" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/vpclattice/persistence.go b/services/vpclattice/persistence.go index 602637d495..5932ddc433 100644 --- a/services/vpclattice/persistence.go +++ b/services/vpclattice/persistence.go @@ -2,7 +2,7 @@ package vpclattice import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -34,7 +34,7 @@ const vpclatticeSnapshotVersion = 1 // incompatible (older or newer) build of this backend as though it were the // current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Targets map[string][]*storedTarget `json:"targets"` AuthPolicies map[string]string `json:"authPolicies"` ResourcePolicies map[string]string `json:"resourcePolicies"` diff --git a/services/vpclattice/whitebox_test.go b/services/vpclattice/whitebox_test.go index 89799da154..da03922fbf 100644 --- a/services/vpclattice/whitebox_test.go +++ b/services/vpclattice/whitebox_test.go @@ -2,7 +2,7 @@ package vpclattice import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -10,6 +10,8 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func ruleCount(b *InMemoryBackend) int { @@ -24,7 +26,7 @@ func doWhiteboxRequest(t *testing.T, h *Handler, method, path string, body any) var buf *bytes.Reader if body != nil { - data, err := json.Marshal(body) + data, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) buf = bytes.NewReader(data) } else { @@ -49,7 +51,7 @@ func parseWhiteboxBody(t *testing.T, rec *httptest.ResponseRecorder) map[string] t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } diff --git a/services/waf/byte_match_sets_test.go b/services/waf/byte_match_sets_test.go index 04e8ba472d..060ec8b14a 100644 --- a/services/waf/byte_match_sets_test.go +++ b/services/waf/byte_match_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -23,7 +24,7 @@ func TestWAF_ByteMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) bmsMap := createResp["ByteMatchSet"].(map[string]any) id := bmsMap["ByteMatchSetId"].(string) require.NotEmpty(t, id) @@ -33,7 +34,7 @@ func TestWAF_ByteMatchSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "GetByteMatchSet", map[string]any{"ByteMatchSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bms := resp["ByteMatchSet"].(map[string]any) assert.Equal(t, "my-bms", bms["Name"]) @@ -57,7 +58,7 @@ func TestWAF_ByteMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetByteMatchSet", map[string]any{"ByteMatchSetId": id}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bms = resp["ByteMatchSet"].(map[string]any) tuples := bms["ByteMatchTuples"].([]any) require.Len(t, tuples, 1) @@ -69,7 +70,7 @@ func TestWAF_ByteMatchSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "ListByteMatchSets", map[string]any{"Limit": 100}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["ByteMatchSets"].([]any) assert.Len(t, sets, 1) @@ -118,7 +119,7 @@ func wafCreateByteMatchSet(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["ByteMatchSet"].(map[string]any) id := m["ByteMatchSetId"].(string) require.NotEmpty(t, id) diff --git a/services/waf/change_token_test.go b/services/waf/change_token_test.go index 96885f93a1..1a60e19932 100644 --- a/services/waf/change_token_test.go +++ b/services/waf/change_token_test.go @@ -13,13 +13,14 @@ package waf_test // itself consume any other token. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -73,7 +74,7 @@ func TestWAF_GetChangeTokenStatus_Fresh(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PROVISIONED", resp["ChangeTokenStatus"]) } @@ -97,7 +98,7 @@ func TestWAF_GetChangeTokenStatus_AfterMutation_INSYNC(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "INSYNC", resp["ChangeTokenStatus"]) } @@ -202,7 +203,7 @@ func TestChangeTokenStatus_Lifecycle(t *testing.T) { rec := wafDo(t, h, "GetChangeTokenStatus", map[string]any{"ChangeToken": token}) require.Equal(t, http.StatusOK, rec.Code) var before map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &before, jsonx.V1())) assert.Equal(t, tt.wantBefore, before["ChangeTokenStatus"], "status before mutation") if tt.mutate != nil { @@ -213,7 +214,7 @@ func TestChangeTokenStatus_Lifecycle(t *testing.T) { rec = wafDo(t, h, "GetChangeTokenStatus", map[string]any{"ChangeToken": token}) require.Equal(t, http.StatusOK, rec.Code) var after map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &after, jsonx.V1())) assert.Equal(t, tt.wantAfter, after["ChangeTokenStatus"], "status after mutation") }) } @@ -229,7 +230,7 @@ func TestChangeTokenStatus_UnknownReturnsINSYNC(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "INSYNC", resp["ChangeTokenStatus"], "unknown token should return INSYNC per AWS behavior") } @@ -299,7 +300,7 @@ func TestChangeToken_AlreadyConsumedTokenRejected(t *testing.T) { require.Equal(t, http.StatusOK, statusRec.Code) var statusResp map[string]any - require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp)) + require.NoError(t, json.Unmarshal(statusRec.Body.Bytes(), &statusResp, jsonx.V1())) require.Equal(t, "INSYNC", statusResp["ChangeTokenStatus"], "token must be consumed before reuse attempt") // Reusing the same, now-INSYNC token for a second mutation must fail. @@ -315,7 +316,7 @@ func TestChangeToken_AlreadyConsumedTokenRejected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.Len(t, listResp["Rules"], 1, "the rejected second CreateRule must not have mutated state") } diff --git a/services/waf/geo_match_sets_test.go b/services/waf/geo_match_sets_test.go index afce69e173..0b45020079 100644 --- a/services/waf/geo_match_sets_test.go +++ b/services/waf/geo_match_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -23,7 +24,7 @@ func TestWAF_GeoMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) gmsMap := createResp["GeoMatchSet"].(map[string]any) id := gmsMap["GeoMatchSetId"].(string) require.NotEmpty(t, id) @@ -48,7 +49,7 @@ func TestWAF_GeoMatchSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "GetGeoMatchSet", map[string]any{"GeoMatchSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) gms := resp["GeoMatchSet"].(map[string]any) constraints := gms["GeoMatchConstraints"].([]any) require.Len(t, constraints, 1) @@ -81,7 +82,7 @@ func TestWAF_GeoMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetGeoMatchSet", map[string]any{"GeoMatchSetId": id}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) gms = resp["GeoMatchSet"].(map[string]any) constraints = gms["GeoMatchConstraints"].([]any) require.Len(t, constraints, 1) @@ -90,7 +91,7 @@ func TestWAF_GeoMatchSet_CreateGetUpdateDeleteList(t *testing.T) { // List rec = wafDo(t, h, "ListGeoMatchSets", map[string]any{"Limit": 100}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["GeoMatchSets"].([]any) assert.Len(t, sets, 1) @@ -137,7 +138,7 @@ func wafCreateGeoMatchSet(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["GeoMatchSet"].(map[string]any) id := m["GeoMatchSetId"].(string) require.NotEmpty(t, id) diff --git a/services/waf/handler.go b/services/waf/handler.go index d850c0875f..32706bf544 100644 --- a/services/waf/handler.go +++ b/services/waf/handler.go @@ -2,7 +2,7 @@ package waf import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -10,6 +10,7 @@ import ( "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -112,12 +113,12 @@ func (h *Handler) dispatch(_ context.Context, action string, body []byte) ([]byt var tokenHolder struct { ChangeToken string `json:"ChangeToken"` } - if jerr := json.Unmarshal(body, &tokenHolder); jerr == nil && tokenHolder.ChangeToken != "" { + if jerr := json.Unmarshal(body, &tokenHolder, jsonx.V1()); jerr == nil && tokenHolder.ChangeToken != "" { h.Backend.MarkChangeTokenUsed(tokenHolder.ChangeToken) } } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } // paginate returns a window of items starting after nextMarker, limited to limit items, @@ -282,7 +283,7 @@ func unmarshal(body []byte, v any) error { return nil } - return json.Unmarshal(body, v) + return json.Unmarshal(body, v, jsonx.V1()) } func tagsToMap(tags []Tag) map[string]string { diff --git a/services/waf/handler_test.go b/services/waf/handler_test.go index e8302ad73d..9ceab9987b 100644 --- a/services/waf/handler_test.go +++ b/services/waf/handler_test.go @@ -7,7 +7,7 @@ package waf_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -33,7 +34,7 @@ func wafDo(t *testing.T, h *waf.Handler, action string, body any) *httptest.Resp var b []byte if body != nil { var err error - b, err = json.Marshal(body) + b, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -56,7 +57,7 @@ func wafGetToken(t *testing.T, h *waf.Handler) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) token, ok := resp["ChangeToken"].(string) require.True(t, ok) require.NotEmpty(t, token) @@ -68,7 +69,7 @@ func errType(t *testing.T, body []byte) string { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(body, &resp)) + require.NoError(t, json.Unmarshal(body, &resp, jsonx.V1())) typ, _ := resp["__type"].(string) diff --git a/services/waf/ip_sets_test.go b/services/waf/ip_sets_test.go index 283d23a7fc..85af15ad3a 100644 --- a/services/waf/ip_sets_test.go +++ b/services/waf/ip_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -22,7 +23,7 @@ func wafCreateIPSet(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["IPSet"].(map[string]any) id := m["IPSetId"].(string) require.NotEmpty(t, id) @@ -41,7 +42,7 @@ func TestWAF_IPSet_CreateGetUpdateDeleteList(t *testing.T) { rec := wafDo(t, h, "GetIPSet", map[string]any{"IPSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ipSet := resp["IPSet"].(map[string]any) assert.Equal(t, "my-ips", ipSet["Name"]) descs := ipSet["IPSetDescriptors"].([]any) @@ -66,7 +67,7 @@ func TestWAF_IPSet_CreateGetUpdateDeleteList(t *testing.T) { // Verify rec = wafDo(t, h, "GetIPSet", map[string]any{"IPSetId": id}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ipSet = resp["IPSet"].(map[string]any) descs = ipSet["IPSetDescriptors"].([]any) require.Len(t, descs, 1) @@ -92,7 +93,7 @@ func TestWAF_IPSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetIPSet", map[string]any{"IPSetId": id}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ipSet = resp["IPSet"].(map[string]any) descs = ipSet["IPSetDescriptors"].([]any) assert.Empty(t, descs) @@ -101,7 +102,7 @@ func TestWAF_IPSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "ListIPSets", map[string]any{"Limit": 100}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["IPSets"].([]any) assert.Len(t, sets, 1) @@ -139,7 +140,7 @@ func TestWAF_IPSet_IPv6Descriptor(t *testing.T) { rec = wafDo(t, h, "GetIPSet", map[string]any{"IPSetId": id}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ipSet := resp["IPSet"].(map[string]any) descs := ipSet["IPSetDescriptors"].([]any) require.Len(t, descs, 1) @@ -155,7 +156,7 @@ func TestWAF_MultipleIPSets_List(t *testing.T) { rec := wafDo(t, h, "ListIPSets", map[string]any{"Limit": 100}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sets := resp["IPSets"].([]any) assert.Len(t, sets, 2) } diff --git a/services/waf/logging_configuration_test.go b/services/waf/logging_configuration_test.go index 6c69cf2221..1f4b4a4f8d 100644 --- a/services/waf/logging_configuration_test.go +++ b/services/waf/logging_configuration_test.go @@ -1,12 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestLoggingConfigurationLifecycle(t *testing.T) { @@ -40,14 +42,14 @@ func TestLoggingConfigurationLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &putResp, jsonx.V1())) assert.NotNil(t, putResp["LoggingConfiguration"]) // Get rec = wafDo(t, h, "GetLoggingConfiguration", map[string]any{"ResourceArn": aclARN}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) cfgMap := getResp["LoggingConfiguration"].(map[string]any) assert.Equal(t, aclARN, cfgMap["ResourceArn"]) @@ -55,7 +57,7 @@ func TestLoggingConfigurationLifecycle(t *testing.T) { rec = wafDo(t, h, "ListLoggingConfigurations", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) cfgs := listResp["LoggingConfigurations"].([]any) assert.Len(t, cfgs, 1) @@ -70,7 +72,7 @@ func TestLoggingConfigurationLifecycle(t *testing.T) { // List after delete → empty rec = wafDo(t, h, "ListLoggingConfigurations", nil) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) cfgs = listResp["LoggingConfigurations"].([]any) assert.Empty(t, cfgs) }) diff --git a/services/waf/non_empty_entity_test.go b/services/waf/non_empty_entity_test.go index b763303508..b23cfa87fc 100644 --- a/services/waf/non_empty_entity_test.go +++ b/services/waf/non_empty_entity_test.go @@ -10,13 +10,14 @@ package waf_test // delete succeeds. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -505,7 +506,7 @@ func wafCreateNamedSet( require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m, ok := resp[respKey].(map[string]any) require.True(t, ok) id, ok := m[idKey].(string) diff --git a/services/waf/pagination_test.go b/services/waf/pagination_test.go index 2ea15bc145..196b925a97 100644 --- a/services/waf/pagination_test.go +++ b/services/waf/pagination_test.go @@ -4,13 +4,14 @@ package waf_test // every List* operation. import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -21,7 +22,7 @@ func wafListPage(t *testing.T, h *waf.Handler, op string, body map[string]any) m rec := wafDo(t, h, op, body) require.Equal(t, http.StatusOK, rec.Code, op+": "+rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) return resp } diff --git a/services/waf/permission_policy_test.go b/services/waf/permission_policy_test.go index 5f3886b52d..d4c6c5030e 100644 --- a/services/waf/permission_policy_test.go +++ b/services/waf/permission_policy_test.go @@ -1,12 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPermissionPolicyLifecycle(t *testing.T) { @@ -40,7 +42,7 @@ func TestPermissionPolicyLifecycle(t *testing.T) { rec = wafDo(t, h, "GetPermissionPolicy", map[string]any{"ResourceArn": rgARN}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) assert.Equal(t, policy, getResp["Policy"]) // Delete diff --git a/services/waf/persistence.go b/services/waf/persistence.go index f0cf3fb6b2..e164d896d8 100644 --- a/services/waf/persistence.go +++ b/services/waf/persistence.go @@ -2,7 +2,7 @@ package waf import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -33,7 +33,7 @@ const wafSnapshotVersion = 1 // plain maps -- see store_setup.go's file doc comment for why they do not fit // store.Table's keyed-by-identity-value shape. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` ChangeTokens map[string]string `json:"changeTokens"` RuleGroupRules map[string][]ActivatedRule `json:"ruleGroupRules"` PermissionPolicies map[string]string `json:"permissionPolicies"` diff --git a/services/waf/rate_based_rules_test.go b/services/waf/rate_based_rules_test.go index 9e690eefdb..98835f1be5 100644 --- a/services/waf/rate_based_rules_test.go +++ b/services/waf/rate_based_rules_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -26,7 +27,7 @@ func wafCreateRateBasedRule(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ruleMap, ok := resp["Rule"].(map[string]any) require.True(t, ok) id, ok := ruleMap["RuleId"].(string) @@ -60,7 +61,7 @@ func TestRateBasedRuleLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) ruleMap := getResp["Rule"].(map[string]any) assert.Equal(t, "BlockBots", ruleMap["Name"]) assert.Equal(t, "IP", ruleMap["RateKey"]) @@ -88,7 +89,7 @@ func TestRateBasedRuleLifecycle(t *testing.T) { // Get to verify updates rec = wafDo(t, h, "GetRateBasedRule", map[string]any{"RuleId": ruleID}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) ruleMap = getResp["Rule"].(map[string]any) assert.InEpsilon(t, float64(3000), ruleMap["RateLimit"], 0.001) preds := ruleMap["MatchPredicates"].([]any) @@ -117,7 +118,7 @@ func TestRateBasedRuleLifecycle(t *testing.T) { rec = wafDo(t, h, "ListRateBasedRules", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) rules := listResp["Rules"].([]any) assert.Len(t, rules, 1) @@ -125,7 +126,7 @@ func TestRateBasedRuleLifecycle(t *testing.T) { rec = wafDo(t, h, "GetRateBasedRuleManagedKeys", map[string]any{"RuleId": ruleID}) require.Equal(t, http.StatusOK, rec.Code) var mkResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mkResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &mkResp, jsonx.V1())) assert.NotNil(t, mkResp["ManagedKeys"]) // Delete diff --git a/services/waf/realclient_match_sets_and_rules_test.go b/services/waf/realclient_match_sets_and_rules_test.go index 7c5ff5c48a..100f1a94ee 100644 --- a/services/waf/realclient_match_sets_and_rules_test.go +++ b/services/waf/realclient_match_sets_and_rules_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -942,7 +943,7 @@ func testPermissionPolicyRealClient(t *testing.T) { }, } - policyBytes, err := json.Marshal(policyStatement) + policyBytes, err := json.Marshal(policyStatement, jsonx.V1()) require.NoError(t, err) policy := string(policyBytes) diff --git a/services/waf/regex_match_sets_test.go b/services/waf/regex_match_sets_test.go index c90aef1887..3f57ac03ba 100644 --- a/services/waf/regex_match_sets_test.go +++ b/services/waf/regex_match_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -22,7 +23,7 @@ func wafCreateRegexMatchSet(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) setMap, ok := resp["RegexMatchSet"].(map[string]any) require.True(t, ok) id, ok := setMap["RegexMatchSetId"].(string) @@ -57,7 +58,7 @@ func TestRegexMatchSetLifecycle(t *testing.T) { rec := wafDo(t, h, "GetRegexMatchSet", map[string]any{"RegexMatchSetId": setID}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) setMap := getResp["RegexMatchSet"].(map[string]any) assert.Equal(t, "SqlMatchSet", setMap["Name"]) @@ -80,7 +81,7 @@ func TestRegexMatchSetLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetRegexMatchSet", map[string]any{"RegexMatchSetId": setID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) setMap = getResp["RegexMatchSet"].(map[string]any) tuples := setMap["RegexMatchTuples"].([]any) assert.Len(t, tuples, 1) @@ -107,7 +108,7 @@ func TestRegexMatchSetLifecycle(t *testing.T) { rec = wafDo(t, h, "ListRegexMatchSets", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["RegexMatchSets"].([]any) assert.Len(t, sets, 1) diff --git a/services/waf/regex_pattern_sets_test.go b/services/waf/regex_pattern_sets_test.go index e9a4133096..330dec962d 100644 --- a/services/waf/regex_pattern_sets_test.go +++ b/services/waf/regex_pattern_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -22,7 +23,7 @@ func wafCreateRegexPatternSet(t *testing.T, h *waf.Handler, name string) string require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) setMap, ok := resp["RegexPatternSet"].(map[string]any) require.True(t, ok) id, ok := setMap["RegexPatternSetId"].(string) @@ -55,7 +56,7 @@ func TestRegexPatternSetLifecycle(t *testing.T) { rec := wafDo(t, h, "GetRegexPatternSet", map[string]any{"RegexPatternSetId": setID}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) setMap := getResp["RegexPatternSet"].(map[string]any) assert.Equal(t, "SqlPatterns", setMap["Name"]) assert.Empty(t, setMap["RegexPatternStrings"]) @@ -73,7 +74,7 @@ func TestRegexPatternSetLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetRegexPatternSet", map[string]any{"RegexPatternSetId": setID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) setMap = getResp["RegexPatternSet"].(map[string]any) assert.Len(t, setMap["RegexPatternStrings"], 2) @@ -89,7 +90,7 @@ func TestRegexPatternSetLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetRegexPatternSet", map[string]any{"RegexPatternSetId": setID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) setMap = getResp["RegexPatternSet"].(map[string]any) assert.Len(t, setMap["RegexPatternStrings"], 1) @@ -97,7 +98,7 @@ func TestRegexPatternSetLifecycle(t *testing.T) { rec = wafDo(t, h, "ListRegexPatternSets", nil) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["RegexPatternSets"].([]any) assert.Len(t, sets, 1) diff --git a/services/waf/request_validation_test.go b/services/waf/request_validation_test.go index edb9b1b6a8..64b0684734 100644 --- a/services/waf/request_validation_test.go +++ b/services/waf/request_validation_test.go @@ -1,13 +1,15 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_RequestValidation(t *testing.T) { @@ -128,7 +130,7 @@ func TestHandler_RequestValidation(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, tt.wantCode, out.Type) assert.Contains(t, out.Message, tt.wantMsg) assert.False(t, strings.HasPrefix(out.Message, tt.wantCode), "message repeats code: %q", out.Message) @@ -152,7 +154,7 @@ func TestHandler_StaleTokenMessage(t *testing.T) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(second.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(second.Body.Bytes(), &out, jsonx.V1())) assert.Equal(t, "WAFStaleDataException", out.Type) assert.Equal(t, "The input token is no longer current.", out.Message) } diff --git a/services/waf/rule_groups_test.go b/services/waf/rule_groups_test.go index ed96f059b1..d95b117381 100644 --- a/services/waf/rule_groups_test.go +++ b/services/waf/rule_groups_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -24,7 +25,7 @@ func wafCreateRuleGroup(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rgMap, ok := resp["RuleGroup"].(map[string]any) require.True(t, ok) id, ok := rgMap["RuleGroupId"].(string) @@ -60,7 +61,7 @@ func TestRuleGroupLifecycle(t *testing.T) { rec := wafDo(t, h, "GetRuleGroup", map[string]any{"RuleGroupId": rgID}) require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) rgMap := getResp["RuleGroup"].(map[string]any) assert.Equal(t, "MyGroup", rgMap["Name"]) @@ -89,7 +90,7 @@ func TestRuleGroupLifecycle(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) var listARResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listARResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listARResp, jsonx.V1())) activated := listARResp["ActivatedRules"].([]any) assert.Len(t, activated, 1) @@ -116,7 +117,7 @@ func TestRuleGroupLifecycle(t *testing.T) { rec = wafDo(t, h, "ListRuleGroups", nil) require.Equal(t, http.StatusOK, rec.Code) var listRGResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listRGResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listRGResp, jsonx.V1())) groups := listRGResp["RuleGroups"].([]any) assert.Len(t, groups, 1) @@ -216,7 +217,7 @@ func TestUpdateRuleGroup_RejectsDuplicateRuleId(t *testing.T) { rec = wafDo(t, h, "ListActivatedRulesInRuleGroup", map[string]any{"RuleGroupId": rgID}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) activated, _ := listResp["ActivatedRules"].([]any) assert.Len(t, activated, 1, "group must still contain only the one successfully-inserted rule") } @@ -291,7 +292,7 @@ func TestListSubscribedRuleGroups(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups := resp["RuleGroups"].([]any) assert.Empty(t, groups) }) diff --git a/services/waf/rules_test.go b/services/waf/rules_test.go index 24019ba617..e379b25e95 100644 --- a/services/waf/rules_test.go +++ b/services/waf/rules_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -24,7 +25,7 @@ func wafCreateRule(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ruleMap := resp["Rule"].(map[string]any) id := ruleMap["RuleId"].(string) require.NotEmpty(t, id) @@ -45,7 +46,7 @@ func TestWAF_Rule_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["Rule"].(map[string]any) assert.Equal(t, "my-rule", rule["Name"]) assert.Equal(t, id, rule["RuleId"]) @@ -55,7 +56,7 @@ func TestWAF_Rule_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) rules := listResp["Rules"].([]any) assert.Len(t, rules, 1) @@ -97,7 +98,7 @@ func TestWAF_Rule_UpdatePredicates_InsertDelete(t *testing.T) { // Verify predicate rec = wafDo(t, h, "GetRule", map[string]any{"RuleId": id}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule := resp["Rule"].(map[string]any) predicates := rule["Predicates"].([]any) require.Len(t, predicates, 1) @@ -124,7 +125,7 @@ func TestWAF_Rule_UpdatePredicates_InsertDelete(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetRule", map[string]any{"RuleId": id}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule = resp["Rule"].(map[string]any) predicates = rule["Predicates"].([]any) assert.Empty(t, predicates) diff --git a/services/waf/sampled_requests_test.go b/services/waf/sampled_requests_test.go index 6909be80ea..970159aea7 100644 --- a/services/waf/sampled_requests_test.go +++ b/services/waf/sampled_requests_test.go @@ -1,12 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestWAF_GetSampledRequests_EmptyStub(t *testing.T) { @@ -31,7 +33,7 @@ func TestWAF_GetSampledRequests_EmptyStub(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) samples := resp["SampledRequests"].([]any) assert.Empty(t, samples) assert.EqualValues(t, 0, resp["PopulationSize"]) @@ -105,7 +107,7 @@ func TestGetSampledRequests_ReturnsTimeWindow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tw, ok := resp["TimeWindow"].(map[string]any) require.True(t, ok, "TimeWindow must be present in response") diff --git a/services/waf/size_constraint_sets_test.go b/services/waf/size_constraint_sets_test.go index cee0604e52..acc2c4dd60 100644 --- a/services/waf/size_constraint_sets_test.go +++ b/services/waf/size_constraint_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -23,7 +24,7 @@ func TestWAF_SizeConstraintSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) scsMap := createResp["SizeConstraintSet"].(map[string]any) id := scsMap["SizeConstraintSetId"].(string) require.NotEmpty(t, id) @@ -50,7 +51,7 @@ func TestWAF_SizeConstraintSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "GetSizeConstraintSet", map[string]any{"SizeConstraintSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) scs := resp["SizeConstraintSet"].(map[string]any) constraints := scs["SizeConstraints"].([]any) require.Len(t, constraints, 1) @@ -61,7 +62,7 @@ func TestWAF_SizeConstraintSet_CreateGetUpdateDeleteList(t *testing.T) { // List rec = wafDo(t, h, "ListSizeConstraintSets", map[string]any{"Limit": 100}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["SizeConstraintSets"].([]any) assert.Len(t, sets, 1) @@ -110,7 +111,7 @@ func wafCreateSizeConstraintSet(t *testing.T, h *waf.Handler, name string) strin require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["SizeConstraintSet"].(map[string]any) id := m["SizeConstraintSetId"].(string) require.NotEmpty(t, id) diff --git a/services/waf/sql_injection_match_sets_test.go b/services/waf/sql_injection_match_sets_test.go index 8a0c876b3d..d4e7eaf1ba 100644 --- a/services/waf/sql_injection_match_sets_test.go +++ b/services/waf/sql_injection_match_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -23,7 +24,7 @@ func TestWAF_SqlInjectionMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) simsMap := createResp["SqlInjectionMatchSet"].(map[string]any) id := simsMap["SqlInjectionMatchSetId"].(string) require.NotEmpty(t, id) @@ -48,7 +49,7 @@ func TestWAF_SqlInjectionMatchSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "GetSqlInjectionMatchSet", map[string]any{"SqlInjectionMatchSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) sims := resp["SqlInjectionMatchSet"].(map[string]any) tuples := sims["SqlInjectionMatchTuples"].([]any) require.Len(t, tuples, 1) @@ -60,7 +61,7 @@ func TestWAF_SqlInjectionMatchSet_CreateGetUpdateDeleteList(t *testing.T) { // List rec = wafDo(t, h, "ListSqlInjectionMatchSets", map[string]any{"Limit": 100}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["SqlInjectionMatchSets"].([]any) assert.Len(t, sets, 1) @@ -107,7 +108,7 @@ func wafCreateSQLInjectionMatchSet(t *testing.T, h *waf.Handler, name string) st require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["SqlInjectionMatchSet"].(map[string]any) id := m["SqlInjectionMatchSetId"].(string) require.NotEmpty(t, id) diff --git a/services/waf/tag_leak_test.go b/services/waf/tag_leak_test.go index 4c19d76ccb..0de085f93e 100644 --- a/services/waf/tag_leak_test.go +++ b/services/waf/tag_leak_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -223,7 +224,7 @@ func TestWAF_Delete_ClearsTags(t *testing.T) { rec := wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resourceARN, ok := resp["WebACL"].(map[string]any)["WebACLArn"].(string) require.True(t, ok) @@ -257,7 +258,7 @@ func TestWAF_Delete_ClearsTags(t *testing.T) { rec := wafDo(t, h, "ListTagsForResource", map[string]any{"ResourceARN": resourceARN}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) require.NotEmpty(t, listResp["TagInfoForResource"].(map[string]any)["TagList"]) token := wafGetToken(t, h) @@ -277,7 +278,7 @@ func TestWAF_Delete_ClearsTags(t *testing.T) { // Deleting one resource must not disturb another's tags. rec = wafDo(t, h, "ListTagsForResource", map[string]any{"ResourceARN": otherARN}) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) assert.NotEmpty(t, listResp["TagInfoForResource"].(map[string]any)["TagList"]) }) } diff --git a/services/waf/tags_test.go b/services/waf/tags_test.go index a2179ba1c6..ecd07e29be 100644 --- a/services/waf/tags_test.go +++ b/services/waf/tags_test.go @@ -1,12 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestWAF_Tags_TagAndList(t *testing.T) { @@ -19,7 +21,7 @@ func TestWAF_Tags_TagAndList(t *testing.T) { rec := wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": aclID}) require.Equal(t, http.StatusOK, rec.Code) var aclResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp, jsonx.V1())) arn := aclResp["WebACL"].(map[string]any)["WebACLArn"].(string) require.NotEmpty(t, arn) @@ -37,7 +39,7 @@ func TestWAF_Tags_TagAndList(t *testing.T) { rec = wafDo(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) info := listResp["TagInfoForResource"].(map[string]any) assert.Equal(t, arn, info["ResourceARN"]) tagList := info["TagList"].([]any) @@ -62,7 +64,7 @@ func TestWAF_Tags_UntagResource(t *testing.T) { rec := wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": aclID}) var aclResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &aclResp, jsonx.V1())) arn := aclResp["WebACL"].(map[string]any)["WebACLArn"].(string) // Tag @@ -85,7 +87,7 @@ func TestWAF_Tags_UntagResource(t *testing.T) { // Verify only k2 remains rec = wafDo(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tagList := listResp["TagInfoForResource"].(map[string]any)["TagList"].([]any) require.Len(t, tagList, 1) assert.Equal(t, "k2", tagList[0].(map[string]any)["Key"]) @@ -108,12 +110,12 @@ func TestWAF_Tags_CreateWebACLWithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) arn := resp["WebACL"].(map[string]any)["WebACLArn"].(string) rec = wafDo(t, h, "ListTagsForResource", map[string]any{"ResourceARN": arn}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) tagList := listResp["TagInfoForResource"].(map[string]any)["TagList"].([]any) require.Len(t, tagList, 1) assert.Equal(t, "cost-center", tagList[0].(map[string]any)["Key"]) diff --git a/services/waf/web_acls_test.go b/services/waf/web_acls_test.go index 3e269f8dfc..b60f5ee818 100644 --- a/services/waf/web_acls_test.go +++ b/services/waf/web_acls_test.go @@ -1,7 +1,7 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strings" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -25,7 +26,7 @@ func wafCreateWebACL(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) aclMap, ok := resp["WebACL"].(map[string]any) require.True(t, ok) id, ok := aclMap["WebACLId"].(string) @@ -49,7 +50,7 @@ func TestWAF_WebACL_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) acl := getResp["WebACL"].(map[string]any) assert.Equal(t, "my-acl", acl["Name"]) assert.Equal(t, id, acl["WebACLId"]) @@ -64,7 +65,7 @@ func TestWAF_WebACL_CreateGetDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) acls := listResp["WebACLs"].([]any) assert.Len(t, acls, 1) @@ -92,7 +93,7 @@ func TestWAF_WebACL_DefaultAction_BLOCK(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) acl := resp["WebACL"].(map[string]any) da := acl["DefaultAction"].(map[string]any) assert.Equal(t, "BLOCK", da["Type"]) @@ -114,7 +115,7 @@ func TestWAF_WebACL_UpdateDefaultAction(t *testing.T) { rec = wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": id}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) acl := resp["WebACL"].(map[string]any) da := acl["DefaultAction"].(map[string]any) assert.Equal(t, "BLOCK", da["Type"]) @@ -148,7 +149,7 @@ func TestWAF_WebACL_UpdateRules_InsertAndDelete(t *testing.T) { // Verify rule present rec = wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": aclID}) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) acl := getResp["WebACL"].(map[string]any) rules := acl["Rules"].([]any) require.Len(t, rules, 1) @@ -175,7 +176,7 @@ func TestWAF_WebACL_UpdateRules_InsertAndDelete(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) rec = wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": aclID}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) acl = getResp["WebACL"].(map[string]any) rules = acl["Rules"].([]any) assert.Empty(t, rules) @@ -263,7 +264,7 @@ func TestWAF_WebACL_RulesPrioritySorted(t *testing.T) { rec = wafDo(t, h, "GetWebACL", map[string]any{"WebACLId": aclID}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules := resp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 2) assert.EqualValues(t, 1, rules[0].(map[string]any)["Priority"]) @@ -284,7 +285,7 @@ func TestWAF_WebACL_ChangeTokenRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, token, resp["ChangeToken"]) } @@ -299,7 +300,7 @@ func TestWAF_MultipleWebACLs_List(t *testing.T) { rec := wafDo(t, h, "ListWebACLs", map[string]any{"Limit": 100}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) acls := resp["WebACLs"].([]any) assert.Len(t, acls, 3) } @@ -369,7 +370,7 @@ func TestCreateWebACLMigrationStack(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) s3URL, ok := resp["S3ObjectUrl"].(string) require.True(t, ok) assert.Contains(t, s3URL, "my-migration-bucket") diff --git a/services/waf/xss_match_sets_test.go b/services/waf/xss_match_sets_test.go index 77e9177725..e5feca34f1 100644 --- a/services/waf/xss_match_sets_test.go +++ b/services/waf/xss_match_sets_test.go @@ -1,13 +1,14 @@ package waf_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/waf" ) @@ -23,7 +24,7 @@ func TestWAF_XssMatchSet_CreateGetUpdateDeleteList(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) xmsMap := createResp["XssMatchSet"].(map[string]any) id := xmsMap["XssMatchSetId"].(string) require.NotEmpty(t, id) @@ -48,7 +49,7 @@ func TestWAF_XssMatchSet_CreateGetUpdateDeleteList(t *testing.T) { rec = wafDo(t, h, "GetXssMatchSet", map[string]any{"XssMatchSetId": id}) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) xms := resp["XssMatchSet"].(map[string]any) tuples := xms["XssMatchTuples"].([]any) require.Len(t, tuples, 1) @@ -57,7 +58,7 @@ func TestWAF_XssMatchSet_CreateGetUpdateDeleteList(t *testing.T) { // List rec = wafDo(t, h, "ListXssMatchSets", map[string]any{"Limit": 100}) var listResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &listResp, jsonx.V1())) sets := listResp["XssMatchSets"].([]any) assert.Len(t, sets, 1) @@ -104,7 +105,7 @@ func wafCreateXSSMatchSet(t *testing.T, h *waf.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) m := resp["XssMatchSet"].(map[string]any) id := m["XssMatchSetId"].(string) require.NotEmpty(t, id) diff --git a/services/wafv2/capacity_test.go b/services/wafv2/capacity_test.go index cf932b4901..19896f15d0 100644 --- a/services/wafv2/capacity_test.go +++ b/services/wafv2/capacity_test.go @@ -1,13 +1,14 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -29,7 +30,7 @@ func checkCapacityFor(t *testing.T, h *wafv2.Handler, stmt map[string]any) int { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) consumed, ok := result["Capacity"].(float64) require.True(t, ok) @@ -358,7 +359,7 @@ func TestCheckCapacity_MultipleRulesSum(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) consumed, ok := result["Capacity"].(float64) require.True(t, ok) assert.InDelta(t, float64(1+40), consumed, 0) diff --git a/services/wafv2/export_test.go b/services/wafv2/export_test.go index 03a9a6478a..b857580317 100644 --- a/services/wafv2/export_test.go +++ b/services/wafv2/export_test.go @@ -2,7 +2,7 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" ) // CreateWebACLSimple is a test helper that creates a WebACL with minimal parameters, @@ -13,11 +13,11 @@ func CreateWebACLSimple( name, scope, description, defaultAction string, tags map[string]string, ) (*WebACL, error) { - var da json.RawMessage + var da jsontext.Value if defaultAction == "BLOCK" { - da = json.RawMessage(`{"Block":{}}`) + da = jsontext.Value(`{"Block":{}}`) } else { - da = json.RawMessage(`{"Allow":{}}`) + da = jsontext.Value(`{"Allow":{}}`) } return b.CreateWebACL( diff --git a/services/wafv2/handler.go b/services/wafv2/handler.go index 05cebab83f..91951b8eff 100644 --- a/services/wafv2/handler.go +++ b/services/wafv2/handler.go @@ -3,7 +3,8 @@ package wafv2 import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "maps" @@ -14,6 +15,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awserr" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -279,9 +281,6 @@ func (h *Handler) dispatch(ctx context.Context, op string, body []byte) ([]byte, return fn(ctx, body) } func (h *Handler) handleError(c *echo.Context, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - var errType string var statusCode int @@ -310,7 +309,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { case errors.Is(err, ErrConfigurationWarning): errType = "WAFConfigurationWarningException" statusCode = http.StatusBadRequest - case errors.Is(err, errInvalidRequest), errors.As(err, &syntaxErr), errors.As(err, &typeErr): + case errors.Is(err, errInvalidRequest), jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): errType = "WAFInvalidParameterException" statusCode = http.StatusBadRequest case errors.Is(err, errUnknownAction): @@ -324,7 +323,7 @@ func (h *Handler) handleError(c *echo.Context, err error) error { payload, _ := json.Marshal(map[string]string{ keyTypeField: errType, keyMessageField: publicMessage(err), - }) + }, jsonx.V1()) c.Response().Header().Set("X-Amzn-Errortype", errType) @@ -332,10 +331,10 @@ func (h *Handler) handleError(c *echo.Context, err error) error { } // parseVisibilityConfig parses a stored VisibilityConfig JSON string or returns a default. -func parseVisibilityConfig(stored json.RawMessage, metricName string) map[string]any { +func parseVisibilityConfig(stored jsontext.Value, metricName string) map[string]any { if len(stored) > 0 { var m map[string]any - if err := json.Unmarshal(stored, &m); err == nil { + if err := json.Unmarshal(stored, &m, jsonx.V1()); err == nil { return m } } @@ -514,7 +513,7 @@ func handleListResourceFamily[T any]( buildSummary func(T) map[string]string, ) ([]byte, error) { var req listFamilyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -531,5 +530,5 @@ func handleListResourceFamily[T any]( resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } diff --git a/services/wafv2/handler_api_keys.go b/services/wafv2/handler_api_keys.go index 7c474db3c5..55a506e7e7 100644 --- a/services/wafv2/handler_api_keys.go +++ b/services/wafv2/handler_api_keys.go @@ -3,9 +3,10 @@ package wafv2 import ( "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -17,7 +18,7 @@ type createAPIKeyRequest struct { func (h *Handler) handleCreateAPIKey(ctx context.Context, body []byte) ([]byte, error) { var req createAPIKeyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -46,7 +47,7 @@ func (h *Handler) handleCreateAPIKey(ctx context.Context, body []byte) ([]byte, return json.Marshal(map[string]any{ "APIKey": encodedKey, - }) + }, jsonx.V1()) } // deleteAPIKeyRequest is the request body for DeleteAPIKey. @@ -57,7 +58,7 @@ type deleteAPIKeyRequest struct { func (h *Handler) handleDeleteAPIKey(ctx context.Context, body []byte) ([]byte, error) { var req deleteAPIKeyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -94,7 +95,7 @@ type listAPIKeysRequest struct { func (h *Handler) handleListAPIKeys(ctx context.Context, body []byte) ([]byte, error) { var req listAPIKeysRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -137,7 +138,7 @@ func (h *Handler) handleListAPIKeys(ctx context.Context, body []byte) ([]byte, e resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // getDecryptedAPIKeyRequest is the request body for GetDecryptedAPIKey. @@ -148,7 +149,7 @@ type getDecryptedAPIKeyRequest struct { func (h *Handler) handleGetDecryptedAPIKey(ctx context.Context, body []byte) ([]byte, error) { var req getDecryptedAPIKeyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -176,7 +177,7 @@ func (h *Handler) handleGetDecryptedAPIKey(ctx context.Context, body []byte) ([] return json.Marshal(map[string]any{ "TokenDomains": a.TokenDomains, "CreationTimestamp": a.CreatedAt, - }) + }, jsonx.V1()) } // apiKeyDispatchOps returns the API-key-family operation dispatch entries. Each entry is a diff --git a/services/wafv2/handler_api_keys_test.go b/services/wafv2/handler_api_keys_test.go index aefcf246f9..e516f90cc7 100644 --- a/services/wafv2/handler_api_keys_test.go +++ b/services/wafv2/handler_api_keys_test.go @@ -2,7 +2,7 @@ package wafv2_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/wafv2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_CreateAndDeleteAPIKey(t *testing.T) { @@ -79,7 +81,7 @@ func TestHandler_CreateAndDeleteAPIKey(t *testing.T) { } var createResult map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResult)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResult, jsonx.V1())) apiKey, _ := createResult["APIKey"].(string) deleteRec := doWafv2Request(t, h, "DeleteAPIKey", tt.deleteBody(apiKey)) @@ -100,7 +102,7 @@ func TestAPIKeyBase64Encoding(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apiKey, ok := resp["APIKey"].(string) require.True(t, ok) @@ -249,7 +251,7 @@ func TestHandler_GetDecryptedAPIKey(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) apiKey, _ = resp["APIKey"].(string) require.NotEmpty(t, apiKey) } @@ -267,7 +269,7 @@ func TestHandler_GetDecryptedAPIKey(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "Scope", "GetDecryptedAPIKeyOutput has no Scope member") assert.Contains(t, resp, "TokenDomains") } diff --git a/services/wafv2/handler_ip_sets.go b/services/wafv2/handler_ip_sets.go index aad5ce9f51..555628eacc 100644 --- a/services/wafv2/handler_ip_sets.go +++ b/services/wafv2/handler_ip_sets.go @@ -2,9 +2,10 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -21,7 +22,7 @@ type createIPSetRequest struct { func (h *Handler) handleCreateIPSet(ctx context.Context, body []byte) ([]byte, error) { var req createIPSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -88,7 +89,7 @@ func (h *Handler) handleCreateIPSet(ctx context.Context, body []byte) ([]byte, e keyLockToken: s.LockToken, keyDescription: s.Description, }, - }) + }, jsonx.V1()) } // getIPSetRequest is the request body for GetIPSet. @@ -100,7 +101,7 @@ type getIPSetRequest struct { func (h *Handler) handleGetIPSet(ctx context.Context, body []byte) ([]byte, error) { var req getIPSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -134,7 +135,7 @@ func (h *Handler) handleGetIPSet(ctx context.Context, body []byte) ([]byte, erro keyAddresses: s.Addresses, }, keyLockToken: s.LockToken, - }) + }, jsonx.V1()) } // updateIPSetRequest is the request body for UpdateIPSet. @@ -149,7 +150,7 @@ type updateIPSetRequest struct { func (h *Handler) handleUpdateIPSet(ctx context.Context, body []byte) ([]byte, error) { var req updateIPSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -191,7 +192,7 @@ func (h *Handler) handleUpdateIPSet(ctx context.Context, body []byte) ([]byte, e return json.Marshal(map[string]string{ keyNextLockToken: s.LockToken, - }) + }, jsonx.V1()) } // deleteIPSetRequest is the request body for DeleteIPSet. @@ -204,7 +205,7 @@ type deleteIPSetRequest struct { func (h *Handler) handleDeleteIPSet(ctx context.Context, body []byte) ([]byte, error) { var req deleteIPSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/wafv2/handler_ip_sets_test.go b/services/wafv2/handler_ip_sets_test.go index f2c4caee6f..a271d4aa62 100644 --- a/services/wafv2/handler_ip_sets_test.go +++ b/services/wafv2/handler_ip_sets_test.go @@ -2,7 +2,7 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -54,7 +55,7 @@ func TestHandler_CreateIPSet(t *testing.T) { if tt.wantID { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) summary, ok := result["Summary"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, summary["Id"]) @@ -164,7 +165,7 @@ func TestHandler_UpdateIPSet(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.NotEmpty(t, result["NextLockToken"]) } }) @@ -250,7 +251,7 @@ func TestHandler_ListIPSets(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) list, ok := result["IPSets"].([]any) require.True(t, ok) @@ -281,7 +282,7 @@ func TestHandler_CreateIPSet_Duplicate(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "WAFDuplicateItemException", result["__type"]) } @@ -364,7 +365,7 @@ func TestHandler_ListIPSets_Scope_Filter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) list, ok := result["IPSets"].([]any) require.True(t, ok) assert.Len(t, list, tt.wantCount) @@ -427,7 +428,7 @@ func createIPSetHelper2( require.Equal(t, http.StatusOK, rec.Code, "createIPSetHelper2: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary := resp["Summary"].(map[string]any) return summary["Id"].(string), summary["LockToken"].(string) @@ -500,7 +501,7 @@ func TestIPSetListPagination(t *testing.T) { require.Equal(t, http.StatusOK, page1Rec.Code) var page1Resp map[string]any - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp, jsonx.V1())) sets, _ := page1Resp["IPSets"].([]any) assert.Len(t, sets, 2) @@ -580,7 +581,7 @@ func TestIPSet_MaxEntriesRejected(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "10001 IPs should exceed limit") var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFLimitsExceededException", errResp["__type"]) } @@ -661,7 +662,7 @@ func TestUpdateIPSet_ClearAddresses(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "UpdateIPSet with empty addresses: %s", rec.Body.String()) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) newLockToken := updateResp["NextLockToken"].(string) // Verify addresses were cleared. @@ -669,7 +670,7 @@ func TestUpdateIPSet_ClearAddresses(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &getResp, jsonx.V1())) ipSet := getResp["IPSet"].(map[string]any) addresses, _ := ipSet["Addresses"].([]any) assert.Empty(t, addresses, "addresses should be empty after clearing") diff --git a/services/wafv2/handler_logging_config.go b/services/wafv2/handler_logging_config.go index 1e41925095..dd0a7103fd 100644 --- a/services/wafv2/handler_logging_config.go +++ b/services/wafv2/handler_logging_config.go @@ -2,11 +2,13 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "strings" arnpkg "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -63,7 +65,7 @@ type deleteLoggingConfigurationRequest struct { func (h *Handler) handleDeleteLoggingConfiguration(ctx context.Context, body []byte) ([]byte, error) { var req deleteLoggingConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -91,24 +93,24 @@ func (h *Handler) handleDeleteLoggingConfiguration(ctx context.Context, body []b // putLoggingConfigurationRequest is the request body for PutLoggingConfiguration. type putLoggingConfigurationRequest struct { - LoggingConfiguration json.RawMessage `json:"LoggingConfiguration"` + LoggingConfiguration jsontext.Value `json:"LoggingConfiguration"` } func (h *Handler) handlePutLoggingConfiguration(ctx context.Context, body []byte) ([]byte, error) { var req putLoggingConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } // Extract ResourceArn for validation. - var cfg map[string]json.RawMessage - if err := json.Unmarshal(req.LoggingConfiguration, &cfg); err != nil { + var cfg map[string]jsontext.Value + if err := json.Unmarshal(req.LoggingConfiguration, &cfg, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: invalid LoggingConfiguration JSON: %w", errInvalidRequest, err) } var resourceARN string if raw, ok := cfg["ResourceArn"]; ok { - if err := json.Unmarshal(raw, &resourceARN); err != nil || resourceARN == "" { + if err := json.Unmarshal(raw, &resourceARN, jsonx.V1()); err != nil || resourceARN == "" { return nil, fmt.Errorf("%w: LoggingConfiguration.ResourceArn is required", errInvalidRequest) } } else { @@ -118,7 +120,7 @@ func (h *Handler) handlePutLoggingConfiguration(ctx context.Context, body []byte // Validate destination ARN prefixes. if destRaw, ok := cfg["LogDestinationConfigs"]; ok { var destinations []string - if unmarshalErr := json.Unmarshal(destRaw, &destinations); unmarshalErr == nil { + if unmarshalErr := json.Unmarshal(destRaw, &destinations, jsonx.V1()); unmarshalErr == nil { for _, dest := range destinations { if destErr := validateLoggingDestination(dest); destErr != nil { return nil, destErr @@ -135,13 +137,13 @@ func (h *Handler) handlePutLoggingConfiguration(ctx context.Context, body []byte log.InfoContext(ctx, "wafv2: put logging configuration", "resourceArn", resourceARN) var respCfg any - if err := json.Unmarshal(req.LoggingConfiguration, &respCfg); err != nil { + if err := json.Unmarshal(req.LoggingConfiguration, &respCfg, jsonx.V1()); err != nil { respCfg = map[string]any{"ResourceArn": resourceARN} } return json.Marshal(map[string]any{ "LoggingConfiguration": respCfg, - }) + }, jsonx.V1()) } // validateLoggingDestination checks that a destination ARN has an accepted prefix. @@ -168,7 +170,7 @@ type getLoggingConfigurationRequest struct { func (h *Handler) handleGetLoggingConfiguration(ctx context.Context, body []byte) ([]byte, error) { var req getLoggingConfigurationRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -190,13 +192,13 @@ func (h *Handler) handleGetLoggingConfiguration(ctx context.Context, body []byte } var cfg any - if unmarshalErr := json.Unmarshal(cfgJSON, &cfg); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(cfgJSON, &cfg, jsonx.V1()); unmarshalErr != nil { cfg = map[string]any{"ResourceArn": req.ResourceArn} } return json.Marshal(map[string]any{ "LoggingConfiguration": cfg, - }) + }, jsonx.V1()) } // listLoggingConfigurationsRequest mirrors ListLoggingConfigurationsInput @@ -261,7 +263,7 @@ func skipToLoggingConfigMarker(entries []loggingConfigEntry, nextMarker string) // and LogScope, paginated by Limit/NextMarker. func (h *Handler) handleListLoggingConfigurations(ctx context.Context, body []byte) ([]byte, error) { var req listLoggingConfigurationsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -271,7 +273,7 @@ func (h *Handler) handleListLoggingConfigurations(ctx context.Context, body []by for _, cfg := range configs { var v map[string]any - if err := json.Unmarshal(cfg, &v); err != nil { + if err := json.Unmarshal(cfg, &v, jsonx.V1()); err != nil { continue } @@ -298,7 +300,7 @@ func (h *Handler) handleListLoggingConfigurations(ctx context.Context, body []by resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // loggingConfigDispatchOps returns the logging-configuration-family operation dispatch diff --git a/services/wafv2/handler_logging_config_test.go b/services/wafv2/handler_logging_config_test.go index 2e18078365..9390a75ed3 100644 --- a/services/wafv2/handler_logging_config_test.go +++ b/services/wafv2/handler_logging_config_test.go @@ -2,13 +2,15 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -29,7 +31,7 @@ func TestHandler_DeleteLoggingConfiguration(t *testing.T) { require.NoError(t, h.Backend.PutLoggingConfiguration( context.Background(), arnStr, - json.RawMessage(`{"ResourceArn":"`+arnStr+`"}`), + jsontext.Value(`{"ResourceArn":"`+arnStr+`"}`), )) return arnStr @@ -88,7 +90,7 @@ func TestLoggingConfigurationFullRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) webACLARN := createResp["Summary"].(map[string]any)["ARN"].(string) // Put a full logging configuration. @@ -111,7 +113,7 @@ func TestLoggingConfigurationFullRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) cfg, ok := getResp["LoggingConfiguration"].(map[string]any) require.True(t, ok) @@ -126,7 +128,7 @@ func TestLoggingConfigurationFullRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) configs, ok := listResp["LoggingConfigurations"].([]any) require.True(t, ok) assert.Len(t, configs, 1) @@ -155,7 +157,7 @@ func TestLoggingConfig_FirehoseDestination(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["LoggingConfiguration"].(map[string]any) dests := cfg["LogDestinationConfigs"].([]any) require.Len(t, dests, 1) @@ -182,7 +184,7 @@ func TestLoggingConfig_S3Destination(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["LoggingConfiguration"].(map[string]any) dests := cfg["LogDestinationConfigs"].([]any) require.Len(t, dests, 1) @@ -209,7 +211,7 @@ func TestLoggingConfig_CloudWatchDestination(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["LoggingConfiguration"].(map[string]any) dests := cfg["LogDestinationConfigs"].([]any) require.Len(t, dests, 1) @@ -275,7 +277,7 @@ func TestLoggingConfig_DeleteAndGetNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, getRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -290,7 +292,7 @@ func TestLoggingConfig_DeleteNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -335,7 +337,7 @@ func TestLoggingConfig_FullFieldRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) cfg := resp["LoggingConfiguration"].(map[string]any) // RedactedFields should round-trip. @@ -443,7 +445,7 @@ func TestListLoggingConfigurations_ReturnsStoredConfigs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) configs, _ := resp["LoggingConfigurations"].([]any) assert.Len(t, configs, 2, "ListLoggingConfigurations should return 2 stored configs") } diff --git a/services/wafv2/handler_managed_rule_catalog.go b/services/wafv2/handler_managed_rule_catalog.go index 7d77b7dff5..eaffe087c2 100644 --- a/services/wafv2/handler_managed_rule_catalog.go +++ b/services/wafv2/handler_managed_rule_catalog.go @@ -2,9 +2,11 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // defaultManagedRuleGroupVersion is this catalog's single hardcoded version @@ -17,7 +19,7 @@ func (h *Handler) handleDescribeAllManagedProducts(body []byte) ([]byte, error) var req struct { Scope string `json:"Scope"` } - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -36,7 +38,7 @@ func (h *Handler) handleDescribeAllManagedProducts(body []byte) ([]byte, error) }) } - return json.Marshal(map[string]any{"ManagedProducts": products}) + return json.Marshal(map[string]any{"ManagedProducts": products}, jsonx.V1()) } // describeManagedProductsByVendorRequest is the request body for DescribeManagedProductsByVendor. @@ -48,7 +50,7 @@ type describeManagedProductsByVendorRequest struct { // handleDescribeManagedProductsByVendor returns catalog entries filtered by vendor. func (h *Handler) handleDescribeManagedProductsByVendor(body []byte) ([]byte, error) { var req describeManagedProductsByVendorRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -75,7 +77,7 @@ func (h *Handler) handleDescribeManagedProductsByVendor(body []byte) ([]byte, er }) } - return json.Marshal(map[string]any{"ManagedProducts": products}) + return json.Marshal(map[string]any{"ManagedProducts": products}, jsonx.V1()) } // describeManagedRuleGroupRequest is the request body for DescribeManagedRuleGroup. @@ -89,7 +91,7 @@ type describeManagedRuleGroupRequest struct { // handleDescribeManagedRuleGroup returns catalog data for the requested managed rule group. func (h *Handler) handleDescribeManagedRuleGroup(body []byte) ([]byte, error) { var req describeManagedRuleGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -133,7 +135,7 @@ func (h *Handler) handleDescribeManagedRuleGroup(body []byte) ([]byte, error) { resp["VersionName"] = defaultManagedRuleGroupVersion } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } } @@ -205,7 +207,7 @@ type generateMobileSdkReleaseURLRequest struct { // handleGenerateMobileSdkReleaseURL returns a presigned-style URL for the requested mobile SDK release. func (h *Handler) handleGenerateMobileSdkReleaseURL(body []byte) ([]byte, error) { var req generateMobileSdkReleaseURLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -231,7 +233,7 @@ func (h *Handler) handleGenerateMobileSdkReleaseURL(body []byte) ([]byte, error) return json.Marshal(map[string]any{ "Url": url, - }) + }, jsonx.V1()) } // getMobileSdkReleaseRequest is the request body for GetMobileSdkRelease. @@ -243,7 +245,7 @@ type getMobileSdkReleaseRequest struct { // handleGetMobileSdkRelease returns the mobile SDK release from the catalog. func (h *Handler) handleGetMobileSdkRelease(body []byte) ([]byte, error) { var req getMobileSdkReleaseRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -272,7 +274,7 @@ func (h *Handler) handleGetMobileSdkRelease(body []byte) ([]byte, error) { "ReleaseNotes": release.ReleaseNotes, "Tags": []any{}, }, - }) + }, jsonx.V1()) } // listAvailableManagedRuleGroupVersionsRequest is the request body for ListAvailableManagedRuleGroupVersions. @@ -287,7 +289,7 @@ type listAvailableManagedRuleGroupVersionsRequest struct { // handleListAvailableManagedRuleGroupVersions returns versions for managed rule groups that support versioning. func (h *Handler) handleListAvailableManagedRuleGroupVersions(body []byte) ([]byte, error) { var req listAvailableManagedRuleGroupVersionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -299,11 +301,11 @@ func (h *Handler) handleListAvailableManagedRuleGroupVersions(body []byte) ([]by {"Name": defaultManagedRuleGroupVersion, "LastUpdateTimestamp": nil}, }, "CurrentDefaultVersion": defaultManagedRuleGroupVersion, - }) + }, jsonx.V1()) } } - return json.Marshal(map[string]any{"Versions": []any{}, "CurrentDefaultVersion": ""}) + return json.Marshal(map[string]any{"Versions": []any{}, "CurrentDefaultVersion": ""}, jsonx.V1()) } // listAvailableManagedRuleGroupsRequest is the request body for ListAvailableManagedRuleGroups. @@ -316,7 +318,7 @@ type listAvailableManagedRuleGroupsRequest struct { // handleListAvailableManagedRuleGroups returns the catalog of managed rule groups. func (h *Handler) handleListAvailableManagedRuleGroups(body []byte) ([]byte, error) { var req listAvailableManagedRuleGroupsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -350,7 +352,7 @@ func (h *Handler) handleListAvailableManagedRuleGroups(body []byte) ([]byte, err resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // listMobileSdkReleasesRequest is the request body for ListMobileSdkReleases. @@ -366,7 +368,7 @@ type listMobileSdkReleasesRequest struct { // handleListMobileSdkReleases lists mobile SDK releases from the catalog. func (h *Handler) handleListMobileSdkReleases(body []byte) ([]byte, error) { var req listMobileSdkReleasesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -398,7 +400,7 @@ func (h *Handler) handleListMobileSdkReleases(body []byte) ([]byte, error) { resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // managedRuleCatalogDispatchOps returns the managed-rule-group and mobile-SDK catalog diff --git a/services/wafv2/handler_managed_rule_catalog_test.go b/services/wafv2/handler_managed_rule_catalog_test.go index 59772f49c1..efd4365edb 100644 --- a/services/wafv2/handler_managed_rule_catalog_test.go +++ b/services/wafv2/handler_managed_rule_catalog_test.go @@ -1,12 +1,14 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestListAvailableManagedRuleGroups_ReturnsCatalog(t *testing.T) { @@ -19,7 +21,7 @@ func TestListAvailableManagedRuleGroups_ReturnsCatalog(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["ManagedRuleGroups"].([]any) require.True(t, ok) @@ -53,7 +55,7 @@ func TestDescribeManagedRuleGroup_ReturnsCatalogData(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) capacity, _ := resp["Capacity"].(float64) assert.InDelta(t, float64(700), capacity, 0, "AWSManagedRulesCommonRuleSet should have capacity 700") @@ -73,7 +75,7 @@ func TestGetMobileSdkRelease_KnownVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "GetMobileSdkRelease Android/3.1.0: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) release := resp["MobileSdkRelease"].(map[string]any) assert.Equal(t, "3.1.0", release["ReleaseVersion"]) @@ -95,7 +97,7 @@ func TestGetMobileSdkRelease_IOSVersion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) release := resp["MobileSdkRelease"].(map[string]any) assert.Equal(t, "3.0.0", release["ReleaseVersion"]) } @@ -112,7 +114,7 @@ func TestGetMobileSdkRelease_UnknownVersion(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -139,7 +141,7 @@ func TestGetMobileSdkRelease_MissingPlatform(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", errResp["__type"]) } @@ -155,7 +157,7 @@ func TestListMobileSdkReleases_Android(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) releases, ok := resp["ReleaseSummaries"].([]any) require.True(t, ok) @@ -180,7 +182,7 @@ func TestListMobileSdkReleases_iOS(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) releases, _ := resp["ReleaseSummaries"].([]any) assert.NotEmpty(t, releases, "should return at least one iOS release") @@ -198,7 +200,7 @@ func TestListMobileSdkReleases_UnknownPlatform(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) releases, _ := resp["ReleaseSummaries"].([]any) assert.Empty(t, releases, "unknown platform should return empty list") } @@ -215,7 +217,7 @@ func TestGenerateMobileSdkReleaseUrl_Shape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) url, ok := resp["Url"].(string) require.True(t, ok, "Url field should be present") @@ -259,14 +261,14 @@ func TestWebACL_ManagedRuleGroupStatement_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "ManagedRuleGroupStatement: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 1) @@ -333,7 +335,7 @@ func TestDescribeManagedRuleGroup(t *testing.T) { require.Equal(t, tc.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantType != "" { assert.Equal(t, tc.wantType, resp["__type"]) @@ -414,7 +416,7 @@ func TestGenerateMobileSdkReleaseUrl(t *testing.T) { require.Equal(t, tc.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tc.wantType != "" { assert.Equal(t, tc.wantType, resp["__type"]) @@ -510,7 +512,7 @@ func TestDescribeManagedRuleGroupRules(t *testing.T) { } `json:"AvailableLabels"` Capacity float64 `json:"Capacity"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) // Rules and AvailableLabels must never be null (always an array). assert.NotNil(t, out.Rules, "Rules must not be null") diff --git a/services/wafv2/handler_managed_rule_sets.go b/services/wafv2/handler_managed_rule_sets.go index ef1c37c45a..7584e60c57 100644 --- a/services/wafv2/handler_managed_rule_sets.go +++ b/services/wafv2/handler_managed_rule_sets.go @@ -2,9 +2,10 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -33,7 +34,7 @@ type getManagedRuleSetRequest struct { // handleGetManagedRuleSet returns the stored managed rule set. func (h *Handler) handleGetManagedRuleSet(ctx context.Context, body []byte) ([]byte, error) { var req getManagedRuleSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -64,7 +65,7 @@ func (h *Handler) handleGetManagedRuleSet(ctx context.Context, body []byte) ([]b "RecommendedVersion": ms.RecommendedVersion, }, keyLockToken: ms.LockToken, - }) + }, jsonx.V1()) } // listManagedRuleSetsRequest is the request body for ListManagedRuleSets. @@ -77,7 +78,7 @@ type listManagedRuleSetsRequest struct { // handleListManagedRuleSets lists all stored managed rule sets, filtered by scope. func (h *Handler) handleListManagedRuleSets(ctx context.Context, body []byte) ([]byte, error) { var req listManagedRuleSetsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -115,7 +116,7 @@ func (h *Handler) handleListManagedRuleSets(ctx context.Context, body []byte) ([ resp["NextMarker"] = nextMarker } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // putManagedRuleSetVersionsRequest is the request body for PutManagedRuleSetVersions. @@ -130,7 +131,7 @@ type putManagedRuleSetVersionsRequest struct { func (h *Handler) handlePutManagedRuleSetVersions(ctx context.Context, body []byte) ([]byte, error) { var req putManagedRuleSetVersionsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -165,7 +166,7 @@ func (h *Handler) handlePutManagedRuleSetVersions(ctx context.Context, body []by log := logger.Load(ctx) log.InfoContext(ctx, "wafv2: put managed rule set versions", "id", req.ID) - return json.Marshal(map[string]string{keyNextLockToken: ms.LockToken}) + return json.Marshal(map[string]string{keyNextLockToken: ms.LockToken}, jsonx.V1()) } // updateManagedRuleSetVersionExpiryDateRequest is the request body for @@ -187,7 +188,7 @@ type updateManagedRuleSetVersionExpiryDateRequest struct { func (h *Handler) handleUpdateManagedRuleSetVersionExpiryDate(ctx context.Context, body []byte) ([]byte, error) { var req updateManagedRuleSetVersionExpiryDateRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -235,7 +236,7 @@ func (h *Handler) handleUpdateManagedRuleSetVersionExpiryDate(ctx context.Contex keyNextLockToken: ms.LockToken, "ExpiringVersion": req.VersionToExpire, "ExpiryTimestamp": req.ExpiryTimestamp, - }) + }, jsonx.V1()) } // managedRuleSetDispatchOps returns the ManagedRuleSet-family operation dispatch entries. diff --git a/services/wafv2/handler_managed_rule_sets_test.go b/services/wafv2/handler_managed_rule_sets_test.go index 387f961a6d..bda216f6fc 100644 --- a/services/wafv2/handler_managed_rule_sets_test.go +++ b/services/wafv2/handler_managed_rule_sets_test.go @@ -1,12 +1,14 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestManagedRuleSet_PutAndGet(t *testing.T) { @@ -33,7 +35,7 @@ func TestManagedRuleSet_PutAndGet(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code, "PutManagedRuleSetVersions: %s", putRec.Body.String()) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) lockToken1, _ := putResp["NextLockToken"].(string) assert.NotEmpty(t, lockToken1, "PutManagedRuleSetVersions should return NextLockToken") @@ -46,7 +48,7 @@ func TestManagedRuleSet_PutAndGet(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "GetManagedRuleSet: %s", getRec.Body.String()) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ms := getResp["ManagedRuleSet"].(map[string]any) assert.Equal(t, msID, ms["Id"]) @@ -78,7 +80,7 @@ func TestManagedRuleSet_GetNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -93,7 +95,7 @@ func TestManagedRuleSet_GetMissingID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", errResp["__type"]) } @@ -119,7 +121,7 @@ func TestManagedRuleSet_UpdateExpiryDate(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) lockToken := putResp["NextLockToken"].(string) expiry := int64(9999999999) @@ -142,7 +144,7 @@ func TestManagedRuleSet_UpdateExpiryDate(t *testing.T) { ) var updateResp map[string]any - require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(updateRec.Body.Bytes(), &updateResp, jsonx.V1())) assert.NotEmpty(t, updateResp["NextLockToken"]) assert.Equal(t, "Version_1.0", updateResp["ExpiringVersion"]) assert.InDelta(t, float64(expiry), updateResp["ExpiryTimestamp"], 0) @@ -156,7 +158,7 @@ func TestManagedRuleSet_UpdateExpiryDate(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) ms := getResp["ManagedRuleSet"].(map[string]any) versions := ms["PublishedVersions"].(map[string]any) v10 := versions["Version_1.0"].(map[string]any) @@ -180,7 +182,7 @@ func TestManagedRuleSet_UpdateExpiryNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -199,7 +201,7 @@ func TestManagedRuleSet_UpdateExpiryVersionNotFound(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) lockToken := putResp["NextLockToken"].(string) // Attempt to expire a version that was never published. @@ -214,7 +216,7 @@ func TestManagedRuleSet_UpdateExpiryVersionNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -242,7 +244,7 @@ func TestManagedRuleSet_PutLockTokenEnforcement(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFOptimisticLockException", errResp["__type"]) } @@ -275,7 +277,7 @@ func TestListManagedRuleSets_ScopeFilter(t *testing.T) { require.Equal(t, http.StatusOK, filtRec.Code) var filtResp map[string]any - require.NoError(t, json.Unmarshal(filtRec.Body.Bytes(), &filtResp)) + require.NoError(t, json.Unmarshal(filtRec.Body.Bytes(), &filtResp, jsonx.V1())) filt, _ := filtResp["ManagedRuleSets"].([]any) assert.Len(t, filt, 1) assert.Equal(t, "regional-ms", filt[0].(map[string]any)["Name"]) @@ -284,7 +286,7 @@ func TestListManagedRuleSets_ScopeFilter(t *testing.T) { require.Equal(t, http.StatusOK, cfRec.Code) var cfResp map[string]any - require.NoError(t, json.Unmarshal(cfRec.Body.Bytes(), &cfResp)) + require.NoError(t, json.Unmarshal(cfRec.Body.Bytes(), &cfResp, jsonx.V1())) cf, _ := cfResp["ManagedRuleSets"].([]any) assert.Len(t, cf, 1) assert.Equal(t, "cloudfront-ms", cf[0].(map[string]any)["Name"]) @@ -388,7 +390,7 @@ func TestManagedRuleSet_RequiredFieldValidation(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code, rec.Body.String()) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", errResp["__type"]) }) } @@ -439,7 +441,7 @@ func TestListManagedRuleSets_DuplicateNamePagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["ManagedRuleSets"].([]any) for _, item := range items { diff --git a/services/wafv2/handler_permission_policies.go b/services/wafv2/handler_permission_policies.go index b97e1839e8..74d9945c56 100644 --- a/services/wafv2/handler_permission_policies.go +++ b/services/wafv2/handler_permission_policies.go @@ -2,9 +2,10 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" ) @@ -15,7 +16,7 @@ type deletePermissionPolicyRequest struct { func (h *Handler) handleDeletePermissionPolicy(ctx context.Context, body []byte) ([]byte, error) { var req deletePermissionPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -41,7 +42,7 @@ type putPermissionPolicyRequest struct { func (h *Handler) handlePutPermissionPolicy(ctx context.Context, body []byte) ([]byte, error) { var req putPermissionPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -66,7 +67,7 @@ type getPermissionPolicyRequest struct { func (h *Handler) handleGetPermissionPolicy(ctx context.Context, body []byte) ([]byte, error) { var req getPermissionPolicyRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -79,7 +80,7 @@ func (h *Handler) handleGetPermissionPolicy(ctx context.Context, body []byte) ([ return nil, err } - return json.Marshal(map[string]string{"Policy": policy}) + return json.Marshal(map[string]string{"Policy": policy}, jsonx.V1()) } // permissionPolicyDispatchOps returns the permission-policy-family operation dispatch diff --git a/services/wafv2/handler_permission_policies_test.go b/services/wafv2/handler_permission_policies_test.go index 49803740fb..3b6c2fcd9f 100644 --- a/services/wafv2/handler_permission_policies_test.go +++ b/services/wafv2/handler_permission_policies_test.go @@ -2,13 +2,14 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -107,7 +108,7 @@ func TestPermissionPolicy_PutGetDelete(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code, "GetPermissionPolicy: %s", getRec.Body.String()) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) storedPolicy, ok := getResp["Policy"].(string) require.True(t, ok, "Policy field should be present") assert.Equal(t, policy, storedPolicy) @@ -125,7 +126,7 @@ func TestPermissionPolicy_PutGetDelete(t *testing.T) { assert.Equal(t, http.StatusBadRequest, getRec2.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(getRec2.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -140,7 +141,7 @@ func TestPermissionPolicy_DeleteNotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } @@ -184,7 +185,7 @@ func TestPermissionPolicy_UpdateReplace(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, policy2, resp["Policy"]) } @@ -259,7 +260,7 @@ func TestHandler_PutAndGetPermissionPolicy(t *testing.T) { if tt.wantGetStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Policy") } } diff --git a/services/wafv2/handler_rate_based_rules.go b/services/wafv2/handler_rate_based_rules.go index 2d32d18d0f..8c3a3679ef 100644 --- a/services/wafv2/handler_rate_based_rules.go +++ b/services/wafv2/handler_rate_based_rules.go @@ -2,9 +2,11 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // getRateBasedStatementManagedKeysRequest is the request body for GetRateBasedStatementManagedKeys. @@ -19,7 +21,7 @@ type getRateBasedStatementManagedKeysRequest struct { // handleGetRateBasedStatementManagedKeys returns empty rate-based managed keys. func (h *Handler) handleGetRateBasedStatementManagedKeys(ctx context.Context, body []byte) ([]byte, error) { var req getRateBasedStatementManagedKeysRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -46,7 +48,7 @@ func (h *Handler) handleGetRateBasedStatementManagedKeys(ctx context.Context, bo return json.Marshal(map[string]any{ "ManagedKeysIPV4": map[string]any{keyIPAddressVersion: "IPV4", keyAddresses: []any{}}, "ManagedKeysIPV6": map[string]any{keyIPAddressVersion: "IPV6", keyAddresses: []any{}}, - }) + }, jsonx.V1()) } // getSampledRequestsRequest is the request body for GetSampledRequests. @@ -61,7 +63,7 @@ type getSampledRequestsRequest struct { // handleGetSampledRequests returns an empty sampled requests response. func (h *Handler) handleGetSampledRequests(ctx context.Context, body []byte) ([]byte, error) { var req getSampledRequestsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -97,7 +99,7 @@ func (h *Handler) handleGetSampledRequests(ctx context.Context, body []byte) ([] "SampledRequests": []any{}, "PopulationSize": int64(0), "TimeWindow": req.TimeWindow, - }) + }, jsonx.V1()) } // getTopPathStatisticsByTrafficRequest is the request body for @@ -128,7 +130,7 @@ type getTopPathStatisticsByTrafficRequest struct { // this same structural gap. func (h *Handler) handleGetTopPathStatisticsByTraffic(ctx context.Context, body []byte) ([]byte, error) { var req getTopPathStatisticsByTrafficRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -166,7 +168,7 @@ func (h *Handler) handleGetTopPathStatisticsByTraffic(ctx context.Context, body return json.Marshal(map[string]any{ "PathStatistics": []any{}, "TotalRequestCount": int64(0), - }) + }, jsonx.V1()) } // rateBasedRuleDispatchOps returns the rate-based-rule and traffic-monitoring operation diff --git a/services/wafv2/handler_rate_based_rules_test.go b/services/wafv2/handler_rate_based_rules_test.go index 56570b789d..a1cea6a6a4 100644 --- a/services/wafv2/handler_rate_based_rules_test.go +++ b/services/wafv2/handler_rate_based_rules_test.go @@ -1,7 +1,7 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -105,7 +106,7 @@ func TestRateBasedStatement_WithScopeDown(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "RateBasedStatement with ScopeDown: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) // Retrieve and verify the rule is stored with ScopeDownStatement. @@ -113,7 +114,7 @@ func TestRateBasedStatement_WithScopeDown(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 1) @@ -275,7 +276,7 @@ func TestGetRateBasedStatementManagedKeys_Valid(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "GetRateBasedStatementManagedKeys: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) ipv4, ok := resp["ManagedKeysIPV4"].(map[string]any) require.True(t, ok, "ManagedKeysIPV4 should be present") @@ -349,7 +350,7 @@ func TestValidation_RuleNameUniqueness(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "duplicate rule names should be rejected") var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", errResp["__type"]) } @@ -541,7 +542,7 @@ func TestGetTopPathStatisticsByTraffic(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "PathStatistics", "PathStatistics is a required response member") assert.Empty(t, resp["PathStatistics"], "no real traffic in emulator") assert.Contains(t, resp, "TotalRequestCount", "TotalRequestCount is a required response member") @@ -675,7 +676,7 @@ func TestGetRateBasedStatementManagedKeys(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "ManagedKeysIPV4") assert.Contains(t, resp, "ManagedKeysIPV6") } @@ -809,7 +810,7 @@ func TestGetSampledRequests(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "SampledRequests") assert.Empty(t, resp["SampledRequests"], "no real traffic in emulator") assert.Contains(t, resp, "TimeWindow") @@ -1053,7 +1054,7 @@ func TestGetRevenueStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // No-fabrication assertion: whichever statistic list is populated for this // StatisticType must be empty -- this emulator has no real AI-bot traffic to @@ -1135,7 +1136,7 @@ func TestGetRevenueStatisticsSummary(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) breakdown, ok := resp["RevenueBreakdown"].(map[string]any) require.True(t, ok, "RevenueBreakdown must be present") @@ -1269,7 +1270,7 @@ func TestGetRevenueStatisticsTimeSeries(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "DataPoints") assert.Empty(t, resp["DataPoints"], "no revenue events exist in this emulator to bucket into a time series") }) @@ -1364,7 +1365,7 @@ func TestListSettlementRecords(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Settlements") // No-fabrication assertion: no real payment/settlement pipeline exists in // this emulator, so there must never be an invented PayerAddress, diff --git a/services/wafv2/handler_regex_pattern_sets.go b/services/wafv2/handler_regex_pattern_sets.go index 2ea94bc74c..11bc8e5b9d 100644 --- a/services/wafv2/handler_regex_pattern_sets.go +++ b/services/wafv2/handler_regex_pattern_sets.go @@ -2,9 +2,11 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -12,16 +14,16 @@ import ( // createRegexPatternSetRequest is the request body for CreateRegexPatternSet. // RegularExpressionList accepts both []string and []{RegexString:...} shapes. type createRegexPatternSetRequest struct { - Name string `json:"Name"` - Scope string `json:"Scope"` - Description string `json:"Description"` - RegularExpressionList json.RawMessage `json:"RegularExpressionList"` - Tags []tags.KV `json:"Tags"` + Name string `json:"Name"` + Scope string `json:"Scope"` + Description string `json:"Description"` + RegularExpressionList jsontext.Value `json:"RegularExpressionList"` + Tags []tags.KV `json:"Tags"` } func (h *Handler) handleCreateRegexPatternSet(ctx context.Context, body []byte) ([]byte, error) { var req createRegexPatternSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -84,24 +86,24 @@ func (h *Handler) handleCreateRegexPatternSet(ctx context.Context, body []byte) keyLockToken: rps.LockToken, keyDescription: rps.Description, }, - }) + }, jsonx.V1()) } // parseRegexEntries accepts either []RegexEntry or []string and normalises to []RegexEntry. -func parseRegexEntries(raw json.RawMessage) ([]RegexEntry, error) { +func parseRegexEntries(raw jsontext.Value) ([]RegexEntry, error) { if len(raw) == 0 { return []RegexEntry{}, nil } // Try object form first: [{"RegexString": "..."}] var entries []RegexEntry - if err := json.Unmarshal(raw, &entries); err == nil { + if err := json.Unmarshal(raw, &entries, jsonx.V1()); err == nil { return entries, nil } // Fall back to plain string form: ["...", "..."] var strs []string - if err := json.Unmarshal(raw, &strs); err != nil { + if err := json.Unmarshal(raw, &strs, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: RegularExpressionList must be an array of objects or strings", errInvalidRequest) } @@ -123,7 +125,7 @@ type deleteRegexPatternSetRequest struct { func (h *Handler) handleDeleteRegexPatternSet(ctx context.Context, body []byte) ([]byte, error) { var req deleteRegexPatternSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -150,7 +152,7 @@ type getRegexPatternSetRequest struct { func (h *Handler) handleGetRegexPatternSet(ctx context.Context, body []byte) ([]byte, error) { var req getRegexPatternSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -188,7 +190,7 @@ func (h *Handler) handleGetRegexPatternSet(ctx context.Context, body []byte) ([] "RegularExpressionList": r.RegularExpressionList, }, keyLockToken: r.LockToken, - }) + }, jsonx.V1()) } func (h *Handler) handleListRegexPatternSets(ctx context.Context, body []byte) ([]byte, error) { @@ -212,17 +214,17 @@ func (h *Handler) handleListRegexPatternSets(ctx context.Context, body []byte) ( // updateRegexPatternSetRequest is the request body for UpdateRegexPatternSet. type updateRegexPatternSetRequest struct { - ID string `json:"Id"` - Name string `json:"Name"` - Scope string `json:"Scope"` - LockToken string `json:"LockToken"` - Description string `json:"Description"` - RegularExpressionList json.RawMessage `json:"RegularExpressionList"` + ID string `json:"Id"` + Name string `json:"Name"` + Scope string `json:"Scope"` + LockToken string `json:"LockToken"` + Description string `json:"Description"` + RegularExpressionList jsontext.Value `json:"RegularExpressionList"` } func (h *Handler) handleUpdateRegexPatternSet(ctx context.Context, body []byte) ([]byte, error) { var req updateRegexPatternSetRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -259,7 +261,7 @@ func (h *Handler) handleUpdateRegexPatternSet(ctx context.Context, body []byte) log := logger.Load(ctx) log.InfoContext(ctx, "wafv2: updated regex pattern set", "id", req.ID) - return json.Marshal(map[string]string{keyNextLockToken: r.LockToken}) + return json.Marshal(map[string]string{keyNextLockToken: r.LockToken}, jsonx.V1()) } // regexPatternSetDispatchOps returns the RegexPatternSet-family operation dispatch diff --git a/services/wafv2/handler_regex_pattern_sets_test.go b/services/wafv2/handler_regex_pattern_sets_test.go index 28aad8b1bb..ac3cb40ac2 100644 --- a/services/wafv2/handler_regex_pattern_sets_test.go +++ b/services/wafv2/handler_regex_pattern_sets_test.go @@ -2,13 +2,14 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -74,7 +75,7 @@ func TestHandler_CreateRegexPatternSet(t *testing.T) { if tt.wantID { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) summary, ok := result["Summary"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, summary["Id"]) @@ -180,7 +181,7 @@ func TestRegexPatternSetObjectShape(t *testing.T) { require.Equal(t, http.StatusOK, recObj.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recObj.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recObj.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) // Get and verify the entries are returned as objects. @@ -190,7 +191,7 @@ func TestRegexPatternSetObjectShape(t *testing.T) { require.Equal(t, http.StatusOK, recGet.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp, jsonx.V1())) rps := getResp["RegexPatternSet"].(map[string]any) entries, ok := rps["RegularExpressionList"].([]any) @@ -232,7 +233,7 @@ func TestRegexPatternSet_MaxEntries(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "11 regex entries should exceed limit") var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFLimitsExceededException", errResp["__type"]) } @@ -268,7 +269,7 @@ func createRegexPatternSetHelper(t *testing.T, h *wafv2.Handler, name string) st require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary, ok := resp["Summary"].(map[string]any) require.True(t, ok) @@ -331,7 +332,7 @@ func TestHandler_GetRegexPatternSet(t *testing.T) { if tt.wantField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantField) } }) @@ -389,7 +390,7 @@ func TestHandler_ListRegexPatternSets(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["RegexPatternSets"].([]any) require.True(t, ok) @@ -459,7 +460,7 @@ func TestHandler_UpdateRegexPatternSet(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "NextLockToken") } }) diff --git a/services/wafv2/handler_resource_associations.go b/services/wafv2/handler_resource_associations.go index fe1092bab6..d2afbc12de 100644 --- a/services/wafv2/handler_resource_associations.go +++ b/services/wafv2/handler_resource_associations.go @@ -2,9 +2,11 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // associateWebACLRequest is the request body for AssociateWebACL. @@ -15,7 +17,7 @@ type associateWebACLRequest struct { func (h *Handler) handleAssociateWebACL(ctx context.Context, body []byte) ([]byte, error) { var req associateWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -84,7 +86,7 @@ type disassociateWebACLRequest struct { func (h *Handler) handleDisassociateWebACL(ctx context.Context, body []byte) ([]byte, error) { var req disassociateWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -106,7 +108,7 @@ type getWebACLForResourceRequest struct { func (h *Handler) handleGetWebACLForResource(ctx context.Context, body []byte) ([]byte, error) { var req getWebACLForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -130,7 +132,7 @@ type listResourcesForWebACLRequest struct { func (h *Handler) handleListResourcesForWebACL(ctx context.Context, body []byte) ([]byte, error) { var req listResourcesForWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -156,7 +158,7 @@ func (h *Handler) handleListResourcesForWebACL(ctx context.Context, body []byte) } } - return json.Marshal(map[string]any{"ResourceArns": filtered}) + return json.Marshal(map[string]any{"ResourceArns": filtered}, jsonx.V1()) } const ( diff --git a/services/wafv2/handler_resource_associations_test.go b/services/wafv2/handler_resource_associations_test.go index 71c7d95b79..2d9d0da0bf 100644 --- a/services/wafv2/handler_resource_associations_test.go +++ b/services/wafv2/handler_resource_associations_test.go @@ -2,7 +2,7 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -270,7 +271,7 @@ func TestHandler_GetWebACLForResource(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) webACL, ok := result["WebACL"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, webACL["Id"]) @@ -297,7 +298,7 @@ func TestHandler_GetWebACLForResource_WithVisibilityConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) webACL, ok := result["WebACL"].(map[string]any) require.True(t, ok) assert.Equal(t, "my-acl", webACL["Name"]) @@ -317,7 +318,7 @@ func TestGetWebACLForResourceReturnsRules(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getRespW map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRespW)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getRespW, jsonx.V1())) webACLARN := getRespW["WebACL"].(map[string]any)["ARN"].(string) // Associate with a resource. @@ -335,7 +336,7 @@ func TestGetWebACLForResourceReturnsRules(t *testing.T) { require.Equal(t, http.StatusOK, forResourceRec.Code) var forResourceResp map[string]any - require.NoError(t, json.Unmarshal(forResourceRec.Body.Bytes(), &forResourceResp)) + require.NoError(t, json.Unmarshal(forResourceRec.Body.Bytes(), &forResourceResp, jsonx.V1())) webACL := forResourceResp["WebACL"].(map[string]any) rules, ok := webACL["Rules"].([]any) @@ -371,7 +372,7 @@ func TestListResourcesForWebACL_MultipleResources(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) arns, _ := resp["ResourceArns"].([]any) assert.Len(t, arns, 3, "should list 3 associated resources") @@ -451,7 +452,7 @@ func TestHandler_ListResourcesForWebACL(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) resources, ok := resp["ResourceArns"].([]any) require.True(t, ok) assert.Len(t, resources, tt.wantResources) @@ -539,7 +540,7 @@ func TestAssociateWebACL_ReplaceExisting(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) webACL := resp["WebACL"].(map[string]any) assert.Equal(t, "acl-two", webACL["Name"]) } @@ -557,7 +558,7 @@ func TestGetWebACLForResource_NotFound(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) } diff --git a/services/wafv2/handler_revenue_statistics.go b/services/wafv2/handler_revenue_statistics.go index 531b69d117..afba8c4e8f 100644 --- a/services/wafv2/handler_revenue_statistics.go +++ b/services/wafv2/handler_revenue_statistics.go @@ -2,8 +2,10 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // This file implements the AI-bot pay-per-crawl monetization reporting family added to @@ -333,7 +335,7 @@ func validateGetRevenueStatisticsRequest(req getRevenueStatisticsRequest) error // dollar amount. func (h *Handler) handleGetRevenueStatistics(body []byte) ([]byte, error) { var req getRevenueStatisticsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -366,7 +368,7 @@ func (h *Handler) handleGetRevenueStatistics(body []byte) ([]byte, error) { resp["RevenuePathStatistics"] = []any{} } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // ---- GetRevenueStatisticsSummary --------------------------------------------------- @@ -385,7 +387,7 @@ type getRevenueStatisticsSummaryRequest struct { // ("zero monetized traffic observed") rather than a fabricated dollar figure. func (h *Handler) handleGetRevenueStatisticsSummary(body []byte) ([]byte, error) { var req getRevenueStatisticsSummaryRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -414,7 +416,7 @@ func (h *Handler) handleGetRevenueStatisticsSummary(body []byte) ([]byte, error) "UnverifiedAmount": "0", "VerifiedAmount": "0", }, - }) + }, jsonx.V1()) } // ---- GetRevenueStatisticsTimeSeries ------------------------------------------------- @@ -487,7 +489,7 @@ func validateGetRevenueStatisticsTimeSeriesRequest(req getRevenueStatisticsTimeS // time-series intervals, so there is nothing genuine to aggregate. func (h *Handler) handleGetRevenueStatisticsTimeSeries(body []byte) ([]byte, error) { var req getRevenueStatisticsTimeSeriesRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -511,7 +513,7 @@ func (h *Handler) handleGetRevenueStatisticsTimeSeries(body []byte) ([]byte, err return nil, err } - return json.Marshal(map[string]any{"DataPoints": []any{}}) + return json.Marshal(map[string]any{"DataPoints": []any{}}, jsonx.V1()) } // ---- ListSettlementRecords ---------------------------------------------------------- @@ -565,7 +567,7 @@ func validateListSettlementRecordsRequest(req listSettlementRecordsRequest) erro // TransactionId, or Amount. func (h *Handler) handleListSettlementRecords(body []byte) ([]byte, error) { var req listSettlementRecordsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -589,7 +591,7 @@ func (h *Handler) handleListSettlementRecords(body []byte) ([]byte, error) { return nil, err } - return json.Marshal(map[string]any{"Settlements": []any{}}) + return json.Marshal(map[string]any{"Settlements": []any{}}, jsonx.V1()) } // revenueStatisticsDispatchOps returns the AI-bot monetization reporting operation diff --git a/services/wafv2/handler_rule_groups.go b/services/wafv2/handler_rule_groups.go index f8da2e8bea..1f00f19c80 100644 --- a/services/wafv2/handler_rule_groups.go +++ b/services/wafv2/handler_rule_groups.go @@ -2,9 +2,11 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -17,7 +19,7 @@ type checkCapacityRequest struct { func (h *Handler) handleCheckCapacity(ctx context.Context, body []byte) ([]byte, error) { var req checkCapacityRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -32,7 +34,7 @@ func (h *Handler) handleCheckCapacity(ctx context.Context, body []byte) ([]byte, return json.Marshal(map[string]any{ "Capacity": capacity, - }) + }, jsonx.V1()) } // createRuleGroupRequest is the request body for CreateRuleGroup. @@ -40,9 +42,9 @@ type createRuleGroupRequest struct { Name string `json:"Name"` Scope string `json:"Scope"` Description string `json:"Description"` - VisibilityConfig json.RawMessage `json:"VisibilityConfig"` - CustomResponseBodies json.RawMessage `json:"CustomResponseBodies"` - MonetizationConfig json.RawMessage `json:"MonetizationConfig"` + VisibilityConfig jsontext.Value `json:"VisibilityConfig"` + CustomResponseBodies jsontext.Value `json:"CustomResponseBodies"` + MonetizationConfig jsontext.Value `json:"MonetizationConfig"` Rules []map[string]any `json:"Rules"` Tags []tags.KV `json:"Tags"` Capacity int64 `json:"Capacity"` @@ -50,7 +52,7 @@ type createRuleGroupRequest struct { func (h *Handler) handleCreateRuleGroup(ctx context.Context, body []byte) ([]byte, error) { var req createRuleGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -121,7 +123,7 @@ func (h *Handler) handleCreateRuleGroup(ctx context.Context, body []byte) ([]byt keyLockToken: rg.LockToken, keyDescription: rg.Description, }, - }) + }, jsonx.V1()) } // getRuleGroupRequest is the request body for GetRuleGroup. @@ -134,7 +136,7 @@ type getRuleGroupRequest struct { func (h *Handler) handleGetRuleGroup(ctx context.Context, body []byte) ([]byte, error) { var req getRuleGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -171,7 +173,7 @@ func (h *Handler) handleGetRuleGroup(ctx context.Context, body []byte) ([]byte, } arnStr := rg.ARN - visConfig := parseVisibilityConfig(json.RawMessage(rg.VisibilityConfig), rg.Name) + visConfig := parseVisibilityConfig(jsontext.Value(rg.VisibilityConfig), rg.Name) // LabelNamespace grammar ("awswaf::rulegroup::") confirmed via @@ -194,14 +196,14 @@ func (h *Handler) handleGetRuleGroup(ctx context.Context, body []byte) ([]byte, if len(rg.CustomResponseBodies) > 0 { var crb any - if json.Unmarshal(rg.CustomResponseBodies, &crb) == nil { + if json.Unmarshal(rg.CustomResponseBodies, &crb, jsonx.V1()) == nil { ruleGroupMap["CustomResponseBodies"] = crb } } if len(rg.MonetizationConfig) > 0 { var mc any - if json.Unmarshal(rg.MonetizationConfig, &mc) == nil { + if json.Unmarshal(rg.MonetizationConfig, &mc, jsonx.V1()) == nil { ruleGroupMap["MonetizationConfig"] = mc } } @@ -209,7 +211,7 @@ func (h *Handler) handleGetRuleGroup(ctx context.Context, body []byte) ([]byte, return json.Marshal(map[string]any{ "RuleGroup": ruleGroupMap, keyLockToken: rg.LockToken, - }) + }, jsonx.V1()) } func (h *Handler) handleListRuleGroups(ctx context.Context, body []byte) ([]byte, error) { @@ -238,15 +240,15 @@ type updateRuleGroupRequest struct { Scope string `json:"Scope"` LockToken string `json:"LockToken"` Description string `json:"Description"` - VisibilityConfig json.RawMessage `json:"VisibilityConfig"` - CustomResponseBodies json.RawMessage `json:"CustomResponseBodies"` - MonetizationConfig json.RawMessage `json:"MonetizationConfig"` + VisibilityConfig jsontext.Value `json:"VisibilityConfig"` + CustomResponseBodies jsontext.Value `json:"CustomResponseBodies"` + MonetizationConfig jsontext.Value `json:"MonetizationConfig"` Rules []map[string]any `json:"Rules"` } func (h *Handler) handleUpdateRuleGroup(ctx context.Context, body []byte) ([]byte, error) { var req updateRuleGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -287,7 +289,7 @@ func (h *Handler) handleUpdateRuleGroup(ctx context.Context, body []byte) ([]byt log := logger.Load(ctx) log.InfoContext(ctx, "wafv2: updated rule group", "id", req.ID) - return json.Marshal(map[string]string{keyNextLockToken: rg.LockToken}) + return json.Marshal(map[string]string{keyNextLockToken: rg.LockToken}, jsonx.V1()) } // deleteRuleGroupRequest is the request body for DeleteRuleGroup. @@ -300,7 +302,7 @@ type deleteRuleGroupRequest struct { func (h *Handler) handleDeleteRuleGroup(ctx context.Context, body []byte) ([]byte, error) { var req deleteRuleGroupRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/wafv2/handler_rule_groups_test.go b/services/wafv2/handler_rule_groups_test.go index 5fb68a5aa3..7caf3fc0ae 100644 --- a/services/wafv2/handler_rule_groups_test.go +++ b/services/wafv2/handler_rule_groups_test.go @@ -2,13 +2,14 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -56,7 +57,7 @@ func TestHandler_CheckCapacity(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) consumed, ok := result["Capacity"].(float64) require.True(t, ok) assert.GreaterOrEqual(t, int(consumed), tt.wantMinCap) @@ -106,7 +107,7 @@ func TestHandler_CreateRuleGroup(t *testing.T) { if tt.wantID { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) summary, ok := result["Summary"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, summary["Id"]) @@ -136,7 +137,7 @@ func TestHandler_CreateRuleGroup_Duplicate(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "WAFDuplicateItemException", result["__type"]) } @@ -190,7 +191,7 @@ func TestHandler_DeleteFirewallManagerRuleGroups(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.NotEmpty(t, result["NextWebACLLockToken"]) } }) @@ -266,7 +267,7 @@ func TestDeleteRuleGroupReferencedByWebACL(t *testing.T) { require.Equal(t, http.StatusOK, rgRec.Code) var rgResp map[string]any - require.NoError(t, json.Unmarshal(rgRec.Body.Bytes(), &rgResp)) + require.NoError(t, json.Unmarshal(rgRec.Body.Bytes(), &rgResp, jsonx.V1())) summary := rgResp["Summary"].(map[string]any) rgID := summary["Id"].(string) rgARN := summary["ARN"].(string) @@ -304,7 +305,7 @@ func TestDeleteRuleGroupReferencedByWebACL(t *testing.T) { assert.Equal(t, http.StatusBadRequest, delRec.Code) var delResp map[string]any - require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp)) + require.NoError(t, json.Unmarshal(delRec.Body.Bytes(), &delResp, jsonx.V1())) assert.Equal(t, "WAFAssociatedItemException", delResp["__type"]) } @@ -323,7 +324,7 @@ func TestRuleGroupScopeValidationOnGet(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) // Get with wrong scope should fail. @@ -369,7 +370,7 @@ func TestRuleGroup_UpdateRules(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) rgID := createResp["Summary"].(map[string]any)["Id"].(string) rgLock := createResp["Summary"].(map[string]any)["LockToken"].(string) @@ -411,7 +412,7 @@ func TestRuleGroup_UpdateRules(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["RuleGroup"].(map[string]any)["Rules"].([]any) assert.Len(t, rules, 2) } @@ -437,7 +438,7 @@ func TestListRuleGroups_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, page1Rec.Code) var page1Resp map[string]any - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp, jsonx.V1())) groups1, _ := page1Resp["RuleGroups"].([]any) assert.Len(t, groups1, 3) @@ -453,7 +454,7 @@ func TestListRuleGroups_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, page2Rec.Code) var page2Resp map[string]any - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2Resp)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2Resp, jsonx.V1())) groups2, _ := page2Resp["RuleGroups"].([]any) assert.Len(t, groups2, 2) @@ -476,7 +477,7 @@ func createRuleGroupHelper(t *testing.T, h *wafv2.Handler, name string) (string, require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary, ok := resp["Summary"].(map[string]any) require.True(t, ok) @@ -541,7 +542,7 @@ func TestHandler_GetRuleGroup(t *testing.T) { if tt.wantField != "" { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, tt.wantField) } }) @@ -599,7 +600,7 @@ func TestHandler_ListRuleGroups(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, ok := resp["RuleGroups"].([]any) require.True(t, ok) @@ -666,7 +667,7 @@ func TestHandler_UpdateRuleGroup(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "NextLockToken") } }) @@ -764,7 +765,7 @@ func TestCheckCapacity_EdgeCases(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) consumed, ok := result["Capacity"].(float64) require.True(t, ok) @@ -787,7 +788,7 @@ func TestCheckCapacity_NilRules(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) capacity, _ := resp["Capacity"].(float64) assert.InDelta(t, float64(0), capacity, 0, "nil rules capacity should be 0") @@ -798,7 +799,7 @@ func TestCheckCapacity_NilRules(t *testing.T) { }) require.Equal(t, http.StatusOK, rec.Code) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) capacity, _ = resp["Capacity"].(float64) assert.InDelta(t, float64(0), capacity, 0, "empty rules capacity should be 0") } diff --git a/services/wafv2/handler_tags.go b/services/wafv2/handler_tags.go index 1a49b25505..efd9a72ece 100644 --- a/services/wafv2/handler_tags.go +++ b/services/wafv2/handler_tags.go @@ -2,9 +2,10 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) @@ -22,7 +23,7 @@ type tagResourceRequest struct { func (h *Handler) handleTagResource(ctx context.Context, body []byte) ([]byte, error) { var req tagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -51,7 +52,7 @@ type listTagsForResourceRequest struct { func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([]byte, error) { var req listTagsForResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -78,7 +79,7 @@ func (h *Handler) handleListTagsForResource(ctx context.Context, body []byte) ([ resp["NextMarker"] = pg.Next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // untagResourceRequest is the request body for UntagResource. @@ -89,7 +90,7 @@ type untagResourceRequest struct { func (h *Handler) handleUntagResource(ctx context.Context, body []byte) ([]byte, error) { var req untagResourceRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } diff --git a/services/wafv2/handler_tags_test.go b/services/wafv2/handler_tags_test.go index 135ada616d..88eb7bfa67 100644 --- a/services/wafv2/handler_tags_test.go +++ b/services/wafv2/handler_tags_test.go @@ -2,7 +2,7 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -55,7 +56,7 @@ func TestHandler_TagResource_and_ListTags(t *testing.T) { assert.Equal(t, http.StatusOK, listRec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &result, jsonx.V1())) info, ok := result["TagInfoForResource"].(map[string]any) require.True(t, ok) @@ -188,7 +189,7 @@ func TestHandler_TagResource_Errors(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, tt.wantType, result["__type"]) }) } @@ -228,7 +229,7 @@ func TestHandler_ListTagsForResource_Errors(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, tt.wantType, result["__type"]) }) } @@ -264,7 +265,7 @@ func TestTagValidation(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) arnStr := createResp["Summary"].(map[string]any)["ARN"].(string) // More than 50 tags should fail. @@ -280,7 +281,7 @@ func TestTagValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, tooManyRec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(tooManyRec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(tooManyRec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFTagOperationException", errResp["__type"]) // Reserved prefix "aws:" should fail. @@ -291,7 +292,7 @@ func TestTagValidation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, reservedRec.Code) var reservedErr map[string]any - require.NoError(t, json.Unmarshal(reservedRec.Body.Bytes(), &reservedErr)) + require.NoError(t, json.Unmarshal(reservedRec.Body.Bytes(), &reservedErr, jsonx.V1())) assert.Equal(t, "WAFTagOperationException", reservedErr["__type"]) } @@ -324,7 +325,7 @@ func TestHandler_TagResource_RegexPatternSet(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagInfo, ok := resp["TagInfoForResource"].(map[string]any) require.True(t, ok) tagList, ok := tagInfo["TagList"].([]any) @@ -390,7 +391,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, firstRec.Code, firstRec.Body.String()) var first map[string]any - require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &first)) + require.NoError(t, json.Unmarshal(firstRec.Body.Bytes(), &first, jsonx.V1())) firstInfo, ok := first["TagInfoForResource"].(map[string]any) require.True(t, ok) @@ -411,7 +412,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, secondRec.Code, secondRec.Body.String()) var second map[string]any - require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &second)) + require.NoError(t, json.Unmarshal(secondRec.Body.Bytes(), &second, jsonx.V1())) secondInfo, ok := second["TagInfoForResource"].(map[string]any) require.True(t, ok) @@ -428,7 +429,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, allRec.Code) var all map[string]any - require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &all)) + require.NoError(t, json.Unmarshal(allRec.Body.Bytes(), &all, jsonx.V1())) allInfo, ok := all["TagInfoForResource"].(map[string]any) require.True(t, ok) allList, ok := allInfo["TagList"].([]any) diff --git a/services/wafv2/handler_test.go b/services/wafv2/handler_test.go index d8c576b6d8..d4132c7673 100644 --- a/services/wafv2/handler_test.go +++ b/services/wafv2/handler_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -37,7 +38,7 @@ func doWafv2Request( if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -133,7 +134,7 @@ func TestHandler_UnknownOperation(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "WAFInvalidOperationException", result["__type"]) } @@ -261,7 +262,7 @@ func TestLockTokenEnforcement(t *testing.T) { assert.Equal(t, http.StatusBadRequest, recBad.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(recBad.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(recBad.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFOptimisticLockException", errResp["__type"]) // Update with correct lock token should succeed. @@ -388,7 +389,7 @@ func TestLockTokenRequired_MissingTokenRejected(t *testing.T) { ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", resp["__type"]) }) } @@ -413,7 +414,7 @@ func TestVisibilityConfigMissingMetricName(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", resp["__type"]) } @@ -445,7 +446,7 @@ func TestListPagination(t *testing.T) { require.Equal(t, http.StatusOK, page1Rec.Code) var page1Resp map[string]any - require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp)) + require.NoError(t, json.Unmarshal(page1Rec.Body.Bytes(), &page1Resp, jsonx.V1())) acls1, ok := page1Resp["WebACLs"].([]any) require.True(t, ok) @@ -469,7 +470,7 @@ func TestListPagination(t *testing.T) { require.Equal(t, http.StatusOK, page2Rec.Code) var page2Resp map[string]any - require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2Resp)) + require.NoError(t, json.Unmarshal(page2Rec.Body.Bytes(), &page2Resp, jsonx.V1())) acls2, ok := page2Resp["WebACLs"].([]any) require.True(t, ok) @@ -496,7 +497,7 @@ func TestScopeValidationOnGet(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) // Get with wrong scope should fail. @@ -571,7 +572,7 @@ func TestHandler_Reset(t *testing.T) { // Verify it exists. rec := doWafv2Request(t, h, "ListWebACLs", map[string]any{"Scope": "REGIONAL"}) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ := resp["WebACLs"].([]any) assert.Len(t, items, 1) @@ -580,7 +581,7 @@ func TestHandler_Reset(t *testing.T) { // Verify it's gone. rec = doWafv2Request(t, h, "ListWebACLs", map[string]any{"Scope": "REGIONAL"}) - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) items, _ = resp["WebACLs"].([]any) assert.Empty(t, items) } @@ -727,7 +728,7 @@ func TestValidation_ScopeMismatch(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code, "scope mismatch should return 400") var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFNonexistentItemException", errResp["__type"]) }) diff --git a/services/wafv2/handler_web_acls.go b/services/wafv2/handler_web_acls.go index b181635a55..4b98d6d4e0 100644 --- a/services/wafv2/handler_web_acls.go +++ b/services/wafv2/handler_web_acls.go @@ -2,25 +2,27 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/tags" ) // createWebACLRequest is the request body for CreateWebACL. type createWebACLRequest struct { - DefaultAction json.RawMessage `json:"DefaultAction"` - VisibilityConfig json.RawMessage `json:"VisibilityConfig"` - CustomResponseBodies json.RawMessage `json:"CustomResponseBodies"` - AssociationConfig json.RawMessage `json:"AssociationConfig"` - CaptchaConfig json.RawMessage `json:"CaptchaConfig"` - ChallengeConfig json.RawMessage `json:"ChallengeConfig"` - MonetizationConfig json.RawMessage `json:"MonetizationConfig"` - DataProtectionConfig json.RawMessage `json:"DataProtectionConfig"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig"` - OnSourceDDoSProtectionConfig json.RawMessage `json:"OnSourceDDoSProtectionConfig"` + DefaultAction jsontext.Value `json:"DefaultAction"` + VisibilityConfig jsontext.Value `json:"VisibilityConfig"` + CustomResponseBodies jsontext.Value `json:"CustomResponseBodies"` + AssociationConfig jsontext.Value `json:"AssociationConfig"` + CaptchaConfig jsontext.Value `json:"CaptchaConfig"` + ChallengeConfig jsontext.Value `json:"ChallengeConfig"` + MonetizationConfig jsontext.Value `json:"MonetizationConfig"` + DataProtectionConfig jsontext.Value `json:"DataProtectionConfig"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig"` + OnSourceDDoSProtectionConfig jsontext.Value `json:"OnSourceDDoSProtectionConfig"` Name string `json:"Name"` Scope string `json:"Scope"` Description string `json:"Description"` @@ -31,7 +33,7 @@ type createWebACLRequest struct { func (h *Handler) handleCreateWebACL(ctx context.Context, body []byte) ([]byte, error) { var req createWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -108,17 +110,17 @@ func (h *Handler) handleCreateWebACL(ctx context.Context, body []byte) ([]byte, keyLockToken: w.LockToken, keyDescription: w.Description, }, - }) + }, jsonx.V1()) } // validateDefaultAction validates that exactly one of Allow/Block is set in DefaultAction. -func validateDefaultAction(raw json.RawMessage) error { +func validateDefaultAction(raw jsontext.Value) error { if len(raw) == 0 { return nil } - var m map[string]json.RawMessage - if err := json.Unmarshal(raw, &m); err != nil { + var m map[string]jsontext.Value + if err := json.Unmarshal(raw, &m, jsonx.V1()); err != nil { return fmt.Errorf("%w: invalid DefaultAction JSON: %w", errInvalidRequest, err) } @@ -142,7 +144,7 @@ type getWebACLRequest struct { func (h *Handler) handleGetWebACL(ctx context.Context, body []byte) ([]byte, error) { var req getWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -196,11 +198,11 @@ func (h *Handler) marshalWebACL(ctx context.Context, w *WebACL) ([]byte, error) defaultActionJSON := w.DefaultAction if len(defaultActionJSON) == 0 { - defaultActionJSON = json.RawMessage(`{"Allow":{}}`) + defaultActionJSON = jsontext.Value(`{"Allow":{}}`) } var defaultActionMap any - if err := json.Unmarshal(defaultActionJSON, &defaultActionMap); err != nil { + if err := json.Unmarshal(defaultActionJSON, &defaultActionMap, jsonx.V1()); err != nil { defaultActionMap = map[string]any{"Allow": map[string]any{}} } @@ -231,7 +233,7 @@ func (h *Handler) marshalWebACL(ctx context.Context, w *WebACL) ([]byte, error) return json.Marshal(map[string]any{ "WebACL": webACLMap, keyLockToken: w.LockToken, - }) + }, jsonx.V1()) } // addOptionalWebACLConfigs unmarshals each opaque config field on w that is @@ -240,7 +242,7 @@ func (h *Handler) marshalWebACL(ctx context.Context, w *WebACL) ([]byte, error) func addOptionalWebACLConfigs(webACLMap map[string]any, w *WebACL) { configs := []struct { key string - raw json.RawMessage + raw jsontext.Value }{ {"CustomResponseBodies", w.CustomResponseBodies}, {"AssociationConfig", w.AssociationConfig}, @@ -258,7 +260,7 @@ func addOptionalWebACLConfigs(webACLMap map[string]any, w *WebACL) { } var v any - if json.Unmarshal(c.raw, &v) == nil { + if json.Unmarshal(c.raw, &v, jsonx.V1()) == nil { webACLMap[c.key] = v } } @@ -266,16 +268,16 @@ func addOptionalWebACLConfigs(webACLMap map[string]any, w *WebACL) { // updateWebACLRequest is the request body for UpdateWebACL. type updateWebACLRequest struct { - DefaultAction json.RawMessage `json:"DefaultAction"` - VisibilityConfig json.RawMessage `json:"VisibilityConfig"` - CustomResponseBodies json.RawMessage `json:"CustomResponseBodies"` - AssociationConfig json.RawMessage `json:"AssociationConfig"` - CaptchaConfig json.RawMessage `json:"CaptchaConfig"` - ChallengeConfig json.RawMessage `json:"ChallengeConfig"` - MonetizationConfig json.RawMessage `json:"MonetizationConfig"` - DataProtectionConfig json.RawMessage `json:"DataProtectionConfig"` - ApplicationConfig json.RawMessage `json:"ApplicationConfig"` - OnSourceDDoSProtectionConfig json.RawMessage `json:"OnSourceDDoSProtectionConfig"` + DefaultAction jsontext.Value `json:"DefaultAction"` + VisibilityConfig jsontext.Value `json:"VisibilityConfig"` + CustomResponseBodies jsontext.Value `json:"CustomResponseBodies"` + AssociationConfig jsontext.Value `json:"AssociationConfig"` + CaptchaConfig jsontext.Value `json:"CaptchaConfig"` + ChallengeConfig jsontext.Value `json:"ChallengeConfig"` + MonetizationConfig jsontext.Value `json:"MonetizationConfig"` + DataProtectionConfig jsontext.Value `json:"DataProtectionConfig"` + ApplicationConfig jsontext.Value `json:"ApplicationConfig"` + OnSourceDDoSProtectionConfig jsontext.Value `json:"OnSourceDDoSProtectionConfig"` ID string `json:"Id"` Name string `json:"Name"` Scope string `json:"Scope"` @@ -287,7 +289,7 @@ type updateWebACLRequest struct { func (h *Handler) handleUpdateWebACL(ctx context.Context, body []byte) ([]byte, error) { var req updateWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -346,7 +348,7 @@ func (h *Handler) handleUpdateWebACL(ctx context.Context, body []byte) ([]byte, return json.Marshal(map[string]string{ keyNextLockToken: w.LockToken, - }) + }, jsonx.V1()) } // deleteWebACLRequest is the request body for DeleteWebACL. @@ -359,7 +361,7 @@ type deleteWebACLRequest struct { func (h *Handler) handleDeleteWebACL(ctx context.Context, body []byte) ([]byte, error) { var req deleteWebACLRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -405,7 +407,7 @@ type deleteFirewallManagerRuleGroupsRequest struct { func (h *Handler) handleDeleteFirewallManagerRuleGroups(ctx context.Context, body []byte) ([]byte, error) { var req deleteFirewallManagerRuleGroupsRequest - if err := json.Unmarshal(body, &req); err != nil { + if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: %w", errInvalidRequest, err) } @@ -427,7 +429,7 @@ func (h *Handler) handleDeleteFirewallManagerRuleGroups(ctx context.Context, bod return json.Marshal(map[string]string{ "NextWebACLLockToken": w.LockToken, - }) + }, jsonx.V1()) } // webACLDispatchOps returns the WebACL-family operation dispatch entries. Each entry is a diff --git a/services/wafv2/handler_web_acls_test.go b/services/wafv2/handler_web_acls_test.go index b4492609ea..50828f0b09 100644 --- a/services/wafv2/handler_web_acls_test.go +++ b/services/wafv2/handler_web_acls_test.go @@ -2,13 +2,14 @@ package wafv2_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -57,7 +58,7 @@ func TestHandler_CreateWebACL(t *testing.T) { if tt.wantID { var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) summary, ok := result["Summary"].(map[string]any) require.True(t, ok) assert.NotEmpty(t, summary["Id"]) @@ -162,7 +163,7 @@ func TestHandler_UpdateWebACL(t *testing.T) { if tt.wantStatus == http.StatusOK { var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.NotEmpty(t, result["NextLockToken"]) } }) @@ -248,7 +249,7 @@ func TestHandler_ListWebACLs(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) list, ok := result["WebACLs"].([]any) require.True(t, ok) @@ -275,7 +276,7 @@ func TestHandler_CreateWebACL_Duplicate(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec2.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "WAFDuplicateItemException", result["__type"]) } @@ -287,7 +288,7 @@ func TestHandler_GetWebACL_MissingID(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var result map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) assert.Equal(t, "WAFInvalidParameterException", result["__type"]) } @@ -362,7 +363,7 @@ func TestHandler_ListWebACLs_Scope_Filter(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) list, ok := result["WebACLs"].([]any) require.True(t, ok) assert.Len(t, list, tt.wantCount) @@ -408,7 +409,7 @@ func TestHandler_GetWebACL_BlockDefaultAction(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) webACL, ok := result["WebACL"].(map[string]any) require.True(t, ok) defaultAction, ok := webACL["DefaultAction"].(map[string]any) @@ -443,7 +444,7 @@ func TestHandler_GetWebACL_WithVisibilityConfig(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResult map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResult)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResult, jsonx.V1())) summary := createResult["Summary"].(map[string]any) id := summary["Id"].(string) @@ -455,7 +456,7 @@ func TestHandler_GetWebACL_WithVisibilityConfig(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var result map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result, jsonx.V1())) webACL, ok := result["WebACL"].(map[string]any) require.True(t, ok) vis, ok := webACL["VisibilityConfig"].(map[string]any) @@ -497,7 +498,7 @@ func createWebACLWithRules(t *testing.T, h *wafv2.Handler, name, scope string) ( require.Equal(t, http.StatusOK, rec.Code, "createWebACLWithRules: %s", rec.Body.String()) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary := resp["Summary"].(map[string]any) return summary["Id"].(string), summary["LockToken"].(string) @@ -517,7 +518,7 @@ func TestWebACLRulesRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) webACL := resp["WebACL"].(map[string]any) rules, ok := webACL["Rules"].([]any) @@ -548,14 +549,14 @@ func TestDefaultActionRawJSONRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recAllow.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(recAllow.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(recAllow.Body.Bytes(), &createResp, jsonx.V1())) idAllow := createResp["Summary"].(map[string]any)["Id"].(string) recGet := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": idAllow}) require.Equal(t, http.StatusOK, recGet.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(recGet.Body.Bytes(), &getResp, jsonx.V1())) da := getResp["WebACL"].(map[string]any)["DefaultAction"].(map[string]any) _, hasAllow := da["Allow"] assert.True(t, hasAllow, "DefaultAction should contain Allow key") @@ -572,14 +573,14 @@ func TestDefaultActionRawJSONRoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, recBlock.Code) var createRespBlock map[string]any - require.NoError(t, json.Unmarshal(recBlock.Body.Bytes(), &createRespBlock)) + require.NoError(t, json.Unmarshal(recBlock.Body.Bytes(), &createRespBlock, jsonx.V1())) idBlock := createRespBlock["Summary"].(map[string]any)["Id"].(string) recGetBlock := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": idBlock}) require.Equal(t, http.StatusOK, recGetBlock.Code) var getRespBlock map[string]any - require.NoError(t, json.Unmarshal(recGetBlock.Body.Bytes(), &getRespBlock)) + require.NoError(t, json.Unmarshal(recGetBlock.Body.Bytes(), &getRespBlock, jsonx.V1())) daBlock := getRespBlock["WebACL"].(map[string]any)["DefaultAction"].(map[string]any) _, hasBlock := daBlock["Block"] assert.True(t, hasBlock, "DefaultAction should contain Block key") @@ -616,14 +617,14 @@ func TestWebACLExtendedFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) webACL := getResp["WebACL"].(map[string]any) // TokenDomains should be round-tripped. @@ -676,7 +677,7 @@ func TestCaptchaAction_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "Captcha action: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) // Verify round-trip. @@ -684,7 +685,7 @@ func TestCaptchaAction_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 1) @@ -724,14 +725,14 @@ func TestChallengeAction_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "Challenge action: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 1) @@ -761,14 +762,14 @@ func TestChallengeConfig_WebACLLevel(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) webACL := getResp["WebACL"].(map[string]any) challengeCfg, ok := webACL["ChallengeConfig"].(map[string]any) @@ -809,14 +810,14 @@ func TestLabelMatchStatement_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "LabelMatchStatement: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) require.Len(t, rules, 1) @@ -887,14 +888,14 @@ func TestAssociationConfig_RequestBodyDecryption(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "AssociationConfig: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) webACL := getResp["WebACL"].(map[string]any) assocCfg, ok := webACL["AssociationConfig"].(map[string]any) @@ -1020,14 +1021,14 @@ func TestWebACL_CustomResponseBodies_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "CustomResponseBodies: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) webACL := getResp["WebACL"].(map[string]any) crb, ok := webACL["CustomResponseBodies"].(map[string]any) @@ -1120,14 +1121,14 @@ func TestWebACL_AllActionTypes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "all action types: %s", rec.Body.String()) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) id := createResp["Summary"].(map[string]any)["Id"].(string) getRec := doWafv2Request(t, h, "GetWebACL", map[string]any{"Id": id}) require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules := getResp["WebACL"].(map[string]any)["Rules"].([]any) assert.Len(t, rules, 6, "all 6 rules should round-trip") } @@ -1155,7 +1156,7 @@ func TestWebACL_Update_ClearsOldRules(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) rules := resp["WebACL"].(map[string]any)["Rules"].([]any) assert.Empty(t, rules, "rules should be empty after clearing") } @@ -1171,7 +1172,7 @@ func createWebACLHelper(t *testing.T, h *wafv2.Handler, name, scope string) (str require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summary, ok := resp["Summary"].(map[string]any) require.True(t, ok) @@ -1230,7 +1231,7 @@ func TestHandler_DeleteWebACL_CascadeLogging(t *testing.T) { // Delete the WebACL. var createResp map[string]any rec2 := doWafv2Request(t, h, "ListWebACLs", map[string]any{"Scope": "REGIONAL"}) - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &createResp, jsonx.V1())) webACLs, _ := createResp["WebACLs"].([]any) require.Len(t, webACLs, 1) webACL := webACLs[0].(map[string]any) @@ -1274,7 +1275,7 @@ func TestDeleteWebACL_FailsWhenAssociated(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFAssociatedItemException", errResp["__type"]) // After disassociation, delete should succeed. @@ -1325,7 +1326,7 @@ func TestCreateWebACL_DuplicateNameScope(t *testing.T) { assert.Equal(t, http.StatusBadRequest, rec.Code) var errResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &errResp, jsonx.V1())) assert.Equal(t, "WAFDuplicateItemException", errResp["__type"]) } @@ -1348,7 +1349,7 @@ func TestLockToken_RotatesOnUpdate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "update with correct token: %s", rec.Body.String()) var updateResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &updateResp, jsonx.V1())) token2 := updateResp["NextLockToken"].(string) assert.NotEmpty(t, token2) diff --git a/services/wafv2/interfaces.go b/services/wafv2/interfaces.go index ad6001944e..c68778a745 100644 --- a/services/wafv2/interfaces.go +++ b/services/wafv2/interfaces.go @@ -2,7 +2,7 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" ) // StorageBackend is the interface for WAFv2 storage operations. @@ -16,11 +16,11 @@ type StorageBackend interface { CreateWebACL( ctx context.Context, name, scope, description string, - defaultAction, visibilityConfig json.RawMessage, + defaultAction, visibilityConfig jsontext.Value, rules []map[string]any, tokenDomains []string, - customResponseBodies, associationConfig, captchaConfig, challengeConfig json.RawMessage, - monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig json.RawMessage, + customResponseBodies, associationConfig, captchaConfig, challengeConfig jsontext.Value, + monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig jsontext.Value, tags map[string]string, ) (*WebACL, error) GetWebACL(ctx context.Context, id string) (*WebACL, error) @@ -28,11 +28,11 @@ type StorageBackend interface { UpdateWebACL( ctx context.Context, id, description, lockToken string, - defaultAction, visibilityConfig json.RawMessage, + defaultAction, visibilityConfig jsontext.Value, rules []map[string]any, tokenDomains []string, - customResponseBodies, associationConfig, captchaConfig, challengeConfig json.RawMessage, - monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig json.RawMessage, + customResponseBodies, associationConfig, captchaConfig, challengeConfig jsontext.Value, + monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig jsontext.Value, ) (*WebACL, error) DeleteWebACL(ctx context.Context, id, lockToken string) error ListWebACLs(ctx context.Context) []*WebACL @@ -73,7 +73,7 @@ type StorageBackend interface { name, scope, description, visibilityConfig string, capacity int64, rules []map[string]any, - customResponseBodies, monetizationConfig json.RawMessage, + customResponseBodies, monetizationConfig jsontext.Value, tags map[string]string, ) (*RuleGroup, error) GetRuleGroup(ctx context.Context, id string) (*RuleGroup, error) @@ -83,15 +83,15 @@ type StorageBackend interface { ctx context.Context, id, description, visibilityConfig, lockToken string, rules []map[string]any, - customResponseBodies, monetizationConfig json.RawMessage, + customResponseBodies, monetizationConfig jsontext.Value, ) (*RuleGroup, error) DeleteRuleGroup(ctx context.Context, id, lockToken string) error DeleteAPIKey(ctx context.Context, scope, apiKey string) error DeleteFirewallManagerRuleGroups(ctx context.Context, webACLARN, lockToken string) (*WebACL, error) - PutLoggingConfiguration(ctx context.Context, resourceARN string, configJSON json.RawMessage) error + PutLoggingConfiguration(ctx context.Context, resourceARN string, configJSON jsontext.Value) error DeleteLoggingConfiguration(ctx context.Context, resourceARN, logScope string) error - GetLoggingConfiguration(ctx context.Context, resourceARN, logScope string) (json.RawMessage, error) - ListLoggingConfigurations(ctx context.Context, scope string) []json.RawMessage + GetLoggingConfiguration(ctx context.Context, resourceARN, logScope string) (jsontext.Value, error) + ListLoggingConfigurations(ctx context.Context, scope string) []jsontext.Value DeletePermissionPolicy(ctx context.Context, resourceARN string) error DeleteRegexPatternSet(ctx context.Context, id, lockToken string) error ListAPIKeys(ctx context.Context, scope string) []*APIKey diff --git a/services/wafv2/list_summary_shapes_test.go b/services/wafv2/list_summary_shapes_test.go index 04619e9336..e14f30cdc0 100644 --- a/services/wafv2/list_summary_shapes_test.go +++ b/services/wafv2/list_summary_shapes_test.go @@ -1,7 +1,7 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -9,6 +9,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/wafv2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestListAPIKeys_SummaryShape locks that ListAPIKeys' APIKeySummary items @@ -32,7 +34,7 @@ func TestListAPIKeys_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["APIKeySummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 1) @@ -58,7 +60,7 @@ func TestGetDecryptedAPIKey_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) apiKey, ok := createResp["APIKey"].(string) require.True(t, ok) @@ -69,7 +71,7 @@ func TestGetDecryptedAPIKey_SummaryShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp, "Scope", "GetDecryptedAPIKeyOutput has no Scope member") assert.Contains(t, resp, "TokenDomains") assert.Contains(t, resp, "CreationTimestamp") diff --git a/services/wafv2/logging_config.go b/services/wafv2/logging_config.go index a90af8a895..9d7494247d 100644 --- a/services/wafv2/logging_config.go +++ b/services/wafv2/logging_config.go @@ -2,22 +2,25 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutLoggingConfiguration stores a full logging configuration JSON for the given resource ARN. func (b *InMemoryBackend) PutLoggingConfiguration( ctx context.Context, resourceARN string, - configJSON json.RawMessage, + configJSON jsontext.Value, ) error { b.mu.Lock("PutLoggingConfiguration") defer b.mu.Unlock() region := getRegion(ctx, b.region) - stored := make(json.RawMessage, len(configJSON)) + stored := make(jsontext.Value, len(configJSON)) copy(stored, configJSON) b.loggingConfigsStore(region)[resourceARN] = stored @@ -50,7 +53,7 @@ func (b *InMemoryBackend) DeleteLoggingConfiguration(ctx context.Context, resour func (b *InMemoryBackend) GetLoggingConfiguration( ctx context.Context, resourceARN, logScope string, -) (json.RawMessage, error) { +) (jsontext.Value, error) { b.mu.RLock("GetLoggingConfiguration") defer b.mu.RUnlock() @@ -65,7 +68,7 @@ func (b *InMemoryBackend) GetLoggingConfiguration( ) } - out := make(json.RawMessage, len(cfg)) + out := make(jsontext.Value, len(cfg)) copy(out, cfg) return out, nil @@ -73,7 +76,7 @@ func (b *InMemoryBackend) GetLoggingConfiguration( // loggingConfigInScope reports whether cfg's LogScope (default CUSTOMER when the // document omits it) matches wantScope ("" matches the default, CUSTOMER). -func loggingConfigInScope(cfg json.RawMessage, wantScope string) bool { +func loggingConfigInScope(cfg jsontext.Value, wantScope string) bool { if wantScope == "" { wantScope = defaultLogScope } @@ -82,7 +85,7 @@ func loggingConfigInScope(cfg json.RawMessage, wantScope string) bool { LogScope string `json:"LogScope"` } - if err := json.Unmarshal(cfg, &doc); err != nil { + if err := json.Unmarshal(cfg, &doc, jsonx.V1()); err != nil { return false } @@ -97,7 +100,7 @@ func loggingConfigInScope(cfg json.RawMessage, wantScope string) bool { // ListLoggingConfigurations returns all stored logging configuration JSONs for the // given scope (REGIONAL configs live under the request's actual region; CLOUDFRONT // configs are global and stored under the "" region key -- see arnRegionForScope). -func (b *InMemoryBackend) ListLoggingConfigurations(ctx context.Context, scope string) []json.RawMessage { +func (b *InMemoryBackend) ListLoggingConfigurations(ctx context.Context, scope string) []jsontext.Value { b.mu.RLock("ListLoggingConfigurations") defer b.mu.RUnlock() @@ -111,11 +114,11 @@ func (b *InMemoryBackend) ListLoggingConfigurations(ctx context.Context, scope s sort.Strings(arns) - result := make([]json.RawMessage, 0, len(arns)) + result := make([]jsontext.Value, 0, len(arns)) for _, arn := range arns { cfg := regionMap[arn] - out := make(json.RawMessage, len(cfg)) + out := make(jsontext.Value, len(cfg)) copy(out, cfg) result = append(result, out) } diff --git a/services/wafv2/models.go b/services/wafv2/models.go index 6566ae452a..3f6ef3f80d 100644 --- a/services/wafv2/models.go +++ b/services/wafv2/models.go @@ -1,6 +1,8 @@ package wafv2 -import "encoding/json" +import ( + "encoding/json/jsontext" +) const ( // ScopeRegional is the REGIONAL WAFv2 scope. @@ -53,16 +55,16 @@ type VisibilityConfig struct { type WebACL struct { Tags map[string]string `json:"tags,omitempty"` ARN string `json:"arn,omitempty"` - DefaultAction json.RawMessage `json:"defaultAction,omitempty"` - VisibilityConfig json.RawMessage `json:"visibilityConfig,omitempty"` - CustomResponseBodies json.RawMessage `json:"customResponseBodies,omitempty"` - AssociationConfig json.RawMessage `json:"associationConfig,omitempty"` - CaptchaConfig json.RawMessage `json:"captchaConfig,omitempty"` - ChallengeConfig json.RawMessage `json:"challengeConfig,omitempty"` - MonetizationConfig json.RawMessage `json:"monetizationConfig,omitempty"` - DataProtectionConfig json.RawMessage `json:"dataProtectionConfig,omitempty"` - ApplicationConfig json.RawMessage `json:"applicationConfig,omitempty"` - OnSourceDDoSProtectionConfig json.RawMessage `json:"onSourceDDoSProtectionConfig,omitempty"` + DefaultAction jsontext.Value `json:"defaultAction,omitempty"` + VisibilityConfig jsontext.Value `json:"visibilityConfig,omitempty"` + CustomResponseBodies jsontext.Value `json:"customResponseBodies,omitempty"` + AssociationConfig jsontext.Value `json:"associationConfig,omitempty"` + CaptchaConfig jsontext.Value `json:"captchaConfig,omitempty"` + ChallengeConfig jsontext.Value `json:"challengeConfig,omitempty"` + MonetizationConfig jsontext.Value `json:"monetizationConfig,omitempty"` + DataProtectionConfig jsontext.Value `json:"dataProtectionConfig,omitempty"` + ApplicationConfig jsontext.Value `json:"applicationConfig,omitempty"` + OnSourceDDoSProtectionConfig jsontext.Value `json:"onSourceDDoSProtectionConfig,omitempty"` ID string `json:"id"` Name string `json:"name"` Scope string `json:"scope"` @@ -106,8 +108,8 @@ type RuleGroup struct { Scope string `json:"scope"` Description string `json:"description"` VisibilityConfig string `json:"visibilityConfig"` - CustomResponseBodies json.RawMessage `json:"customResponseBodies,omitempty"` - MonetizationConfig json.RawMessage `json:"monetizationConfig,omitempty"` + CustomResponseBodies jsontext.Value `json:"customResponseBodies,omitempty"` + MonetizationConfig jsontext.Value `json:"monetizationConfig,omitempty"` LockToken string `json:"lockToken"` Rules []map[string]any `json:"rules,omitempty"` Capacity int64 `json:"capacity"` diff --git a/services/wafv2/multi_region_test.go b/services/wafv2/multi_region_test.go index 689da195d5..e7675c80de 100644 --- a/services/wafv2/multi_region_test.go +++ b/services/wafv2/multi_region_test.go @@ -1,7 +1,7 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/wafv2" ) @@ -30,7 +31,7 @@ func regionCall(t *testing.T, h *wafv2.Handler, region, target, body string) map require.Equal(t, http.StatusOK, rec.Code, rec.Body.String()) out := map[string]any{} - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) return out } diff --git a/services/wafv2/persistence.go b/services/wafv2/persistence.go index a2b1199870..37f067a9de 100644 --- a/services/wafv2/persistence.go +++ b/services/wafv2/persistence.go @@ -2,7 +2,7 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -74,13 +74,13 @@ func newDirtyDTORegistry() ( // they do not fit store.Table's keyed-by-identity-value shape and are // unaffected by this conversion. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` - LoggingConfigs map[string]map[string]json.RawMessage `json:"loggingConfigs,omitempty"` - PermissionPolicies map[string]map[string]string `json:"permissionPolicies,omitempty"` - Associations map[string]map[string]string `json:"associations,omitempty"` - AccountID string `json:"accountID"` - Region string `json:"region"` - Version int `json:"version"` + Tables map[string]jsontext.Value `json:"tables"` + LoggingConfigs map[string]map[string]jsontext.Value `json:"loggingConfigs,omitempty"` + PermissionPolicies map[string]map[string]string `json:"permissionPolicies,omitempty"` + Associations map[string]map[string]string `json:"associations,omitempty"` + AccountID string `json:"accountID"` + Region string `json:"region"` + Version int `json:"version"` } // Snapshot serializes the backend state to JSON. @@ -150,7 +150,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { "gotVersion", snap.Version, "wantVersion", wafv2SnapshotVersion) b.resetTablesLocked() - b.loggingConfigs = make(map[string]map[string]json.RawMessage) + b.loggingConfigs = make(map[string]map[string]jsontext.Value) b.permissionPolicies = make(map[string]map[string]string) b.associations = make(map[string]map[string]string) @@ -189,7 +189,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { if snap.LoggingConfigs != nil { b.loggingConfigs = snap.LoggingConfigs } else { - b.loggingConfigs = make(map[string]map[string]json.RawMessage) + b.loggingConfigs = make(map[string]map[string]jsontext.Value) } if snap.PermissionPolicies != nil { diff --git a/services/wafv2/realism_test.go b/services/wafv2/realism_test.go index 9b66992da9..166a9548ac 100644 --- a/services/wafv2/realism_test.go +++ b/services/wafv2/realism_test.go @@ -1,7 +1,7 @@ package wafv2_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func decodeError(t *testing.T, body []byte) (string, string) { @@ -18,7 +20,7 @@ func decodeError(t *testing.T, body []byte) (string, string) { Type string `json:"__type"` Message string `json:"message"` } - require.NoError(t, json.Unmarshal(body, &out)) + require.NoError(t, json.Unmarshal(body, &out, jsonx.V1())) return out.Type, out.Message } @@ -115,7 +117,7 @@ func TestLoggingDestinationNaming(t *testing.T) { ARN string `json:"ARN"` } `json:"Summary"` } - require.NoError(t, json.Unmarshal(acl.Body.Bytes(), &created)) + require.NoError(t, json.Unmarshal(acl.Body.Bytes(), &created, jsonx.V1())) rec := doWafv2Request(t, h, "PutLoggingConfiguration", map[string]any{ "LoggingConfiguration": map[string]any{ diff --git a/services/wafv2/rule_groups.go b/services/wafv2/rule_groups.go index 9b160a6869..f1d9cc766c 100644 --- a/services/wafv2/rule_groups.go +++ b/services/wafv2/rule_groups.go @@ -2,7 +2,8 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "sort" @@ -10,6 +11,7 @@ import ( "github.com/google/uuid" "github.com/blackbirdworks/gopherstack/pkgs/arn" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (b *InMemoryBackend) buildRuleGroupARN(name, id, scope, region string) string { @@ -46,7 +48,7 @@ func (b *InMemoryBackend) CreateRuleGroup( name, scope, description, visibilityConfig string, capacity int64, rules []map[string]any, - customResponseBodies, monetizationConfig json.RawMessage, + customResponseBodies, monetizationConfig jsontext.Value, tags map[string]string, ) (*RuleGroup, error) { b.mu.Lock("CreateRuleGroup") @@ -197,7 +199,7 @@ func (b *InMemoryBackend) UpdateRuleGroup( ctx context.Context, id, description, visibilityConfig, lockToken string, rules []map[string]any, - customResponseBodies, monetizationConfig json.RawMessage, + customResponseBodies, monetizationConfig jsontext.Value, ) (*RuleGroup, error) { b.mu.Lock("UpdateRuleGroup") defer b.mu.Unlock() @@ -242,13 +244,13 @@ func cloneRuleGroup(rg *RuleGroup) *RuleGroup { cp.Rules = cloneRules(rg.Rules) if rg.CustomResponseBodies != nil { - crb := make(json.RawMessage, len(rg.CustomResponseBodies)) + crb := make(jsontext.Value, len(rg.CustomResponseBodies)) copy(crb, rg.CustomResponseBodies) cp.CustomResponseBodies = crb } if rg.MonetizationConfig != nil { - mc := make(json.RawMessage, len(rg.MonetizationConfig)) + mc := make(jsontext.Value, len(rg.MonetizationConfig)) copy(mc, rg.MonetizationConfig) cp.MonetizationConfig = mc } @@ -278,13 +280,13 @@ func cloneRules(rules []map[string]any) []map[string]any { return []map[string]any{} } - data, marshalErr := json.Marshal(rules) + data, marshalErr := json.Marshal(rules, jsonx.V1()) if marshalErr != nil { return shallowCopyRules(rules) } var out []map[string]any - if unmarshalErr := json.Unmarshal(data, &out); unmarshalErr != nil { + if unmarshalErr := json.Unmarshal(data, &out, jsonx.V1()); unmarshalErr != nil { return shallowCopyRules(rules) } diff --git a/services/wafv2/store.go b/services/wafv2/store.go index 2610c92402..514a861a0f 100644 --- a/services/wafv2/store.go +++ b/services/wafv2/store.go @@ -2,13 +2,15 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "maps" "regexp" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/store" ) @@ -128,7 +130,7 @@ type InMemoryBackend struct { managedRuleSetsByRegion *store.Index[ManagedRuleSet] apiKeys *store.Table[APIKey] apiKeysByRegion *store.Index[APIKey] - loggingConfigs map[string]map[string]json.RawMessage + loggingConfigs map[string]map[string]jsontext.Value permissionPolicies map[string]map[string]string associations map[string]map[string]string mu *lockmetrics.RWMutex @@ -161,7 +163,7 @@ func initRegion[V any](m map[string]map[string]V, region string) map[string]V { func NewInMemoryBackend(accountID, region string) *InMemoryBackend { b := &InMemoryBackend{ registry: store.NewRegistry(), - loggingConfigs: make(map[string]map[string]json.RawMessage), + loggingConfigs: make(map[string]map[string]jsontext.Value), permissionPolicies: make(map[string]map[string]string), associations: make(map[string]map[string]string), accountID: accountID, @@ -173,7 +175,7 @@ func NewInMemoryBackend(accountID, region string) *InMemoryBackend { return b } -func (b *InMemoryBackend) loggingConfigsStore(region string) map[string]json.RawMessage { +func (b *InMemoryBackend) loggingConfigsStore(region string) map[string]jsontext.Value { return initRegion(b.loggingConfigs, region) } func (b *InMemoryBackend) permissionPoliciesStore(region string) map[string]string { @@ -219,13 +221,13 @@ func nameScope(name, scope string) string { } // validateVisibilityConfig parses and validates a VisibilityConfig JSON blob. -func validateVisibilityConfig(raw json.RawMessage) error { +func validateVisibilityConfig(raw jsontext.Value) error { if len(raw) == 0 { return nil } var vc VisibilityConfig - if err := json.Unmarshal(raw, &vc); err != nil { + if err := json.Unmarshal(raw, &vc, jsonx.V1()); err != nil { return fmt.Errorf("%w: invalid VisibilityConfig: %w", errInvalidRequest, err) } @@ -243,7 +245,7 @@ func toInt64(v any) (int64, bool) { return int64(n), true case float64: return int64(n), true - case json.Number: + case jsonx.Number: i, err := n.Int64() return i, err == nil @@ -275,7 +277,7 @@ func (b *InMemoryBackend) Reset() { defer b.mu.Unlock() b.resetTablesLocked() - b.loggingConfigs = make(map[string]map[string]json.RawMessage) + b.loggingConfigs = make(map[string]map[string]jsontext.Value) b.permissionPolicies = make(map[string]map[string]string) b.associations = make(map[string]map[string]string) } diff --git a/services/wafv2/web_acls.go b/services/wafv2/web_acls.go index c95468ebfa..1250d0f7fc 100644 --- a/services/wafv2/web_acls.go +++ b/services/wafv2/web_acls.go @@ -2,7 +2,7 @@ package wafv2 import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" "sort" @@ -29,11 +29,11 @@ func (b *InMemoryBackend) WebACLARN(name, id, scope string) string { func (b *InMemoryBackend) CreateWebACL( ctx context.Context, name, scope, description string, - defaultAction, visibilityConfig json.RawMessage, + defaultAction, visibilityConfig jsontext.Value, rules []map[string]any, tokenDomains []string, - customResponseBodies, associationConfig, captchaConfig, challengeConfig json.RawMessage, - monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig json.RawMessage, + customResponseBodies, associationConfig, captchaConfig, challengeConfig jsontext.Value, + monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig jsontext.Value, tags map[string]string, ) (*WebACL, error) { b.mu.Lock("CreateWebACL") @@ -134,11 +134,11 @@ func (b *InMemoryBackend) GetWebACLByARN(ctx context.Context, webACLARN string) func (b *InMemoryBackend) UpdateWebACL( ctx context.Context, id, description, lockToken string, - defaultAction, visibilityConfig json.RawMessage, + defaultAction, visibilityConfig jsontext.Value, rules []map[string]any, tokenDomains []string, - customResponseBodies, associationConfig, captchaConfig, challengeConfig json.RawMessage, - monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig json.RawMessage, + customResponseBodies, associationConfig, captchaConfig, challengeConfig jsontext.Value, + monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig jsontext.Value, ) (*WebACL, error) { b.mu.Lock("UpdateWebACL") defer b.mu.Unlock() @@ -195,8 +195,8 @@ func (b *InMemoryBackend) UpdateWebACL( // Extracted from UpdateWebACL to keep its cyclomatic complexity down. func applyOptionalWebACLConfigs( w *WebACL, - customResponseBodies, associationConfig, captchaConfig, challengeConfig json.RawMessage, - monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig json.RawMessage, + customResponseBodies, associationConfig, captchaConfig, challengeConfig jsontext.Value, + monetizationConfig, dataProtectionConfig, applicationConfig, onSourceDDoSProtectionConfig jsontext.Value, ) { if len(customResponseBodies) > 0 { w.CustomResponseBodies = customResponseBodies @@ -302,61 +302,61 @@ func cloneWebACL(w *WebACL) *WebACL { // Clone RawMessage fields (byte slices). if w.DefaultAction != nil { - da := make(json.RawMessage, len(w.DefaultAction)) + da := make(jsontext.Value, len(w.DefaultAction)) copy(da, w.DefaultAction) cp.DefaultAction = da } if w.VisibilityConfig != nil { - vc := make(json.RawMessage, len(w.VisibilityConfig)) + vc := make(jsontext.Value, len(w.VisibilityConfig)) copy(vc, w.VisibilityConfig) cp.VisibilityConfig = vc } if w.CustomResponseBodies != nil { - crb := make(json.RawMessage, len(w.CustomResponseBodies)) + crb := make(jsontext.Value, len(w.CustomResponseBodies)) copy(crb, w.CustomResponseBodies) cp.CustomResponseBodies = crb } if w.AssociationConfig != nil { - ac := make(json.RawMessage, len(w.AssociationConfig)) + ac := make(jsontext.Value, len(w.AssociationConfig)) copy(ac, w.AssociationConfig) cp.AssociationConfig = ac } if w.CaptchaConfig != nil { - cc := make(json.RawMessage, len(w.CaptchaConfig)) + cc := make(jsontext.Value, len(w.CaptchaConfig)) copy(cc, w.CaptchaConfig) cp.CaptchaConfig = cc } if w.ChallengeConfig != nil { - chc := make(json.RawMessage, len(w.ChallengeConfig)) + chc := make(jsontext.Value, len(w.ChallengeConfig)) copy(chc, w.ChallengeConfig) cp.ChallengeConfig = chc } if w.MonetizationConfig != nil { - mc := make(json.RawMessage, len(w.MonetizationConfig)) + mc := make(jsontext.Value, len(w.MonetizationConfig)) copy(mc, w.MonetizationConfig) cp.MonetizationConfig = mc } if w.DataProtectionConfig != nil { - dpc := make(json.RawMessage, len(w.DataProtectionConfig)) + dpc := make(jsontext.Value, len(w.DataProtectionConfig)) copy(dpc, w.DataProtectionConfig) cp.DataProtectionConfig = dpc } if w.ApplicationConfig != nil { - ac := make(json.RawMessage, len(w.ApplicationConfig)) + ac := make(jsontext.Value, len(w.ApplicationConfig)) copy(ac, w.ApplicationConfig) cp.ApplicationConfig = ac } if w.OnSourceDDoSProtectionConfig != nil { - osdc := make(json.RawMessage, len(w.OnSourceDDoSProtectionConfig)) + osdc := make(jsontext.Value, len(w.OnSourceDDoSProtectionConfig)) copy(osdc, w.OnSourceDDoSProtectionConfig) cp.OnSourceDDoSProtectionConfig = osdc } diff --git a/services/workmail/handler.go b/services/workmail/handler.go index 50bea99fc4..fb9a5d10b9 100644 --- a/services/workmail/handler.go +++ b/services/workmail/handler.go @@ -2,7 +2,7 @@ package workmail import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/idempotency" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" ) @@ -116,7 +117,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) precheck(action string, body []byte) error { @@ -178,7 +179,7 @@ func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err } payload, marshalErr := json.Marshal( - service.JSONErrorResponse{Type: code, Message: strings.TrimPrefix(err.Error(), code+": ")}, + service.JSONErrorResponse{Type: code, Message: strings.TrimPrefix(err.Error(), code+": ")}, jsonx.V1(), ) if marshalErr != nil { return c.String(http.StatusInternalServerError, "internal server error") diff --git a/services/workmail/handler_access_control_test.go b/services/workmail/handler_access_control_test.go index d92d35a184..4736eea1a9 100644 --- a/services/workmail/handler_access_control_test.go +++ b/services/workmail/handler_access_control_test.go @@ -1,7 +1,7 @@ package workmail_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workmail" ) @@ -124,7 +125,7 @@ func TestGetAccessControlEffect_RuleEvaluation(t *testing.T) { body["Name"] = name body["Effect"] = effect - jsonBody, err := json.Marshal(body) + jsonBody, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) rec := doOp(t, h, "PutAccessControlRule", string(jsonBody)) diff --git a/services/workmail/handler_availability_config.go b/services/workmail/handler_availability_config.go index acec865643..050445a5af 100644 --- a/services/workmail/handler_availability_config.go +++ b/services/workmail/handler_availability_config.go @@ -2,8 +2,11 @@ package workmail import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Availability Configurations ---- @@ -117,12 +120,12 @@ type listAvailabilityConfigsReq struct { } type availabilityConfigJSON struct { - EwsProvider *json.RawMessage `json:"EwsProvider,omitempty"` - LambdaProvider *json.RawMessage `json:"LambdaProvider,omitempty"` - DomainName string `json:"DomainName"` - ProviderType string `json:"ProviderType"` - DateCreated int64 `json:"DateCreated"` - DateModified int64 `json:"DateModified"` + EwsProvider *jsontext.Value `json:"EwsProvider,omitempty"` + LambdaProvider *jsontext.Value `json:"LambdaProvider,omitempty"` + DomainName string `json:"DomainName"` + ProviderType string `json:"ProviderType"` + DateCreated int64 `json:"DateCreated"` + DateModified int64 `json:"DateModified"` } type listAvailabilityConfigsResp struct { @@ -153,12 +156,12 @@ func (h *Handler) handleListAvailabilityConfigurations( raw, _ := json.Marshal(map[string]string{ "EwsEndpoint": c.EwsEndpoint, "EwsUsername": c.EwsUsername, - }) - rm := json.RawMessage(raw) + }, jsonx.V1()) + rm := jsontext.Value(raw) item.EwsProvider = &rm } else { - raw, _ := json.Marshal(map[string]string{"LambdaArn": c.LambdaARN}) - rm := json.RawMessage(raw) + raw, _ := json.Marshal(map[string]string{"LambdaArn": c.LambdaARN}, jsonx.V1()) + rm := jsontext.Value(raw) item.LambdaProvider = &rm } result = append(result, item) diff --git a/services/workmail/handler_impersonation_test.go b/services/workmail/handler_impersonation_test.go index 7e98058a5c..362d852300 100644 --- a/services/workmail/handler_impersonation_test.go +++ b/services/workmail/handler_impersonation_test.go @@ -1,7 +1,7 @@ package workmail_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workmail" ) @@ -167,7 +168,7 @@ func TestGetImpersonationRoleEffect(t *testing.T) { h := newTestHandler(t) orgID := createTestOrg(t, h, "imp-effect-org") - targetJSON, _ := json.Marshal(tc.targetUsers) + targetJSON, _ := json.Marshal(tc.targetUsers, jsonx.V1()) roleBody := fmt.Sprintf( `{"OrganizationId":%q,"Name":"test-role","Type":"FULL_ACCESS","Rules":[{"ImpersonationRuleId":"rule-1","Name":"rule-one","Effect":%q,"TargetUsers":%s}]}`, //nolint:lll // existing issue. orgID, diff --git a/services/workmail/handler_mobile_device_access_test.go b/services/workmail/handler_mobile_device_access_test.go index 4b5805cdf3..b149f4ba37 100644 --- a/services/workmail/handler_mobile_device_access_test.go +++ b/services/workmail/handler_mobile_device_access_test.go @@ -1,13 +1,15 @@ package workmail_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ---- Mobile Device Access Rules ---- @@ -35,11 +37,11 @@ func TestMobileDeviceAccessRuleLifecycle(t *testing.T) { body := fmt.Sprintf(`{"OrganizationId":%q,"Name":%q,"Effect":%q,"Description":%q`, orgID, tc.name, tc.effect, tc.description) if len(tc.deviceModels) > 0 { - modelsJSON, _ := json.Marshal(tc.deviceModels) + modelsJSON, _ := json.Marshal(tc.deviceModels, jsonx.V1()) body += fmt.Sprintf(`,"DeviceModels":%s`, string(modelsJSON)) } if len(tc.deviceTypes) > 0 { - typesJSON, _ := json.Marshal(tc.deviceTypes) + typesJSON, _ := json.Marshal(tc.deviceTypes, jsonx.V1()) body += fmt.Sprintf(`,"DeviceTypes":%s`, string(typesJSON)) } body += "}" @@ -163,7 +165,7 @@ func TestGetMobileDeviceAccessEffect(t *testing.T) { h := newTestHandler(t) orgID := createTestOrg(t, h, "effect-org-"+tc.name) - modelsJSON, _ := json.Marshal(tc.deviceModels) + modelsJSON, _ := json.Marshal(tc.deviceModels, jsonx.V1()) doOp(t, h, "CreateMobileDeviceAccessRule", fmt.Sprintf( `{"OrganizationId":%q,"Name":"test-rule","Effect":%q,"DeviceModels":%s}`, orgID, tc.ruleEffect, string(modelsJSON), diff --git a/services/workmail/handler_test.go b/services/workmail/handler_test.go index ee212344e8..c549f819c9 100644 --- a/services/workmail/handler_test.go +++ b/services/workmail/handler_test.go @@ -1,7 +1,7 @@ package workmail_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workmail" ) @@ -41,7 +42,7 @@ func decodeJSON(t *testing.T, rec *httptest.ResponseRecorder) map[string]any { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &m, jsonx.V1())) return m } @@ -190,7 +191,7 @@ func TestWorkMail_Protocol_GetRoot_Returns_OpList(t *testing.T) { require.NoError(t, h.Handler()(c)) assert.Equal(t, http.StatusOK, rec.Code) var ops []string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &ops, jsonx.V1())) assert.NotEmpty(t, ops) } diff --git a/services/workmail/lifecycle.go b/services/workmail/lifecycle.go index 8b8b71a48f..15865fb44f 100644 --- a/services/workmail/lifecycle.go +++ b/services/workmail/lifecycle.go @@ -2,12 +2,14 @@ package workmail import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "regexp" "strconv" "strings" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -95,7 +97,7 @@ func validatePageParams(body []byte) error { NextToken *string `json:"NextToken"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.MaxResults != nil && (*req.MaxResults < minPageSize || *req.MaxResults > defaultPageSize) { return fmt.Errorf("%w: MaxResults must be between %d and %d", ErrValidation, minPageSize, defaultPageSize) @@ -188,7 +190,7 @@ func organizationIDOf(body []byte) string { OrganizationID string `json:"OrganizationId"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) return req.OrganizationID } diff --git a/services/workmail/persistence.go b/services/workmail/persistence.go index 4b595a9b45..84b1247c79 100644 --- a/services/workmail/persistence.go +++ b/services/workmail/persistence.go @@ -2,7 +2,7 @@ package workmail import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "maps" @@ -149,7 +149,7 @@ func buildPersistenceDTORegistry() persistenceDTOTables { // snapshot from an incompatible (older or newer) build of this backend as // though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` OrgsByAlias map[string]string `json:"orgsByAlias"` UsersByEmail map[string]map[string]string `json:"usersByEmail"` GroupsByEmail map[string]map[string]string `json:"groupsByEmail"` @@ -321,7 +321,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { // restoreResourceTables rebuilds every store.Table on b from snap's // per-table JSON, factored out of Restore to keep Restore's own cognitive // complexity low. Callers must hold b.mu.Lock. -func (b *InMemoryBackend) restoreResourceTables(tables map[string]json.RawMessage) error { +func (b *InMemoryBackend) restoreResourceTables(tables map[string]jsontext.Value) error { if err := b.registry.RestoreAll(tables); err != nil { return fmt.Errorf("workmail: restore clean tables: %w", err) } diff --git a/services/workspaces/bundles_test.go b/services/workspaces/bundles_test.go index 5a2dbcaeee..6e72f19a38 100644 --- a/services/workspaces/bundles_test.go +++ b/services/workspaces/bundles_test.go @@ -1,7 +1,7 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -27,7 +28,7 @@ func TestDescribeWorkspaceBundles_PaginatesResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bundles, _ := resp["Bundles"].([]any) assert.NotEmpty(t, bundles, "DescribeWorkspaceBundles must return at least one bundle") @@ -79,7 +80,7 @@ func TestDescribeWorkspaceBundles_FiltersByBundleID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bundles, _ := resp["Bundles"].([]any) assert.Len(t, bundles, tc.wantCount) @@ -95,7 +96,7 @@ func TestDescribeWorkspaceBundles_ComputeTypeAndStorage(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bundles := resp["Bundles"].([]any) require.NotEmpty(t, bundles) @@ -169,7 +170,7 @@ func TestDescribeWorkspaceBundles_ByOwnerAmazon(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) bundles := resp["Bundles"].([]any) for _, b := range bundles { @@ -199,7 +200,7 @@ func TestCreateWorkspaceBundle_StoresStorageCapacity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bun := resp["WorkspaceBundle"].(map[string]any) assert.Equal(t, "50", bun["UserStorage"].(map[string]any)["Capacity"]) @@ -222,7 +223,7 @@ func TestDescribeWorkspaceBundles_IncludesCustomBundle(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) customBundleID := createResp["WorkspaceBundle"].(map[string]any)["BundleId"].(string) // Without owner: only the account's own (custom) bundles. @@ -230,7 +231,7 @@ func TestDescribeWorkspaceBundles_IncludesCustomBundle(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) bundles := resp["Bundles"].([]any) found := false @@ -253,7 +254,7 @@ func TestDescribeWorkspaceBundles_FilterByID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) bundles := resp["Bundles"].([]any) require.Len(t, bundles, 1) assert.Equal(t, "wsb-bh8rsxt14", bundles[0].(map[string]any)["BundleId"]) @@ -475,7 +476,7 @@ func TestCreateWorkspaceBundle_UnknownImage_ConsumesNoState(t *testing.T) { require.Equal(t, http.StatusOK, describeRec.Code) var before map[string]any - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before, jsonx.V1())) countBefore := len(before["Bundles"].([]any)) rejectedRec := doTargetRequest( @@ -487,7 +488,7 @@ func TestCreateWorkspaceBundle_UnknownImage_ConsumesNoState(t *testing.T) { require.Equal(t, http.StatusOK, describeRec2.Code) var after map[string]any - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after, jsonx.V1())) countAfter := len(after["Bundles"].([]any)) assert.Equal(t, countBefore, countAfter, "rejected create must not add a bundle") diff --git a/services/workspaces/directories_test.go b/services/workspaces/directories_test.go index f23186bd39..81ec2ebf42 100644 --- a/services/workspaces/directories_test.go +++ b/services/workspaces/directories_test.go @@ -2,13 +2,14 @@ package workspaces_test import ( "encoding/base64" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -29,7 +30,7 @@ func TestDescribeWorkspaceDirectories_PaginatesResults(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs, _ := resp["Directories"].([]any) assert.Len(t, dirs, 2, "both registered directories must be returned") @@ -42,7 +43,7 @@ func TestDescribeWorkspaceDirectories_PaginatesResults(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) dirs2, _ := resp2["Directories"].([]any) require.Len(t, dirs2, 1, "cursor should skip d-aaa and return only d-bbb") @@ -61,7 +62,7 @@ func TestDescribeWorkspaceDirectories_AfterRegister(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs := resp["Directories"].([]any) assert.Empty(t, dirs, "DescribeWorkspaceDirectories must be empty before registration") @@ -77,7 +78,7 @@ func TestDescribeWorkspaceDirectories_AfterRegister(t *testing.T) { require.Equal(t, http.StatusOK, rec3.Code) var resp3 map[string]any - require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3)) + require.NoError(t, json.Unmarshal(rec3.Body.Bytes(), &resp3, jsonx.V1())) dirs3 := resp3["Directories"].([]any) require.Len(t, dirs3, 1) @@ -108,7 +109,7 @@ func TestDescribeWorkspaceDirectories_FilterByID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs := resp["Directories"].([]any) require.Len(t, dirs, 1) assert.Equal(t, "d-aaaa", dirs[0].(map[string]any)["DirectoryId"]) @@ -131,7 +132,7 @@ func TestDescribeWorkspaceDirectories_AfterDeregister(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) dirs := resp["Directories"].([]any) assert.Empty(t, dirs, "deregistered directory must not appear") } @@ -156,7 +157,7 @@ func TestRegisterWorkspaceDirectory_DuplicateRejected(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec2.Code, "body: %s", rec2.Body) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "ResourceAlreadyExistsException", errOut["__type"]) } @@ -195,7 +196,7 @@ func TestDeregisterWorkspaceDirectory_BlockedByWorkspaces(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec2.Code, "body: %s", rec2.Body) var errOut map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidResourceStateException", errOut["__type"]) // The directory must still be registered -- deregistration was rejected, diff --git a/services/workspaces/directory_registration.go b/services/workspaces/directory_registration.go index 1afea6788f..8df52b9e15 100644 --- a/services/workspaces/directory_registration.go +++ b/services/workspaces/directory_registration.go @@ -1,12 +1,13 @@ package workspaces import ( - "encoding/json" + "encoding/json/v2" "fmt" "slices" "strings" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -239,7 +240,7 @@ func streamingPropertiesFromDS(ds *storedDirSettings) *StreamingProperties { } var sp StreamingProperties - if err := json.Unmarshal([]byte(raw), &sp); err != nil { + if err := json.Unmarshal([]byte(raw), &sp, jsonx.V1()); err != nil { return nil } diff --git a/services/workspaces/handler.go b/services/workspaces/handler.go index df8a713bdb..ed5f74d649 100644 --- a/services/workspaces/handler.go +++ b/services/workspaces/handler.go @@ -2,7 +2,7 @@ package workspaces import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/labstack/echo/v5" "github.com/blackbirdworks/gopherstack/pkgs/awserr" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -94,7 +95,7 @@ func (h *Handler) dispatch(ctx context.Context, action string, body []byte) ([]b return nil, err } - return json.Marshal(result) + return json.Marshal(result, jsonx.V1()) } func (h *Handler) handleError(_ context.Context, c *echo.Context, _ string, err error) error { diff --git a/services/workspaces/handler_test.go b/services/workspaces/handler_test.go index f0ef791f73..28b054a9f4 100644 --- a/services/workspaces/handler_test.go +++ b/services/workspaces/handler_test.go @@ -3,7 +3,7 @@ package workspaces_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strconv" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -59,7 +60,7 @@ func doTargetRequest( if body != nil { var marshalErr error - bodyBytes, marshalErr = json.Marshal(body) + bodyBytes, marshalErr = json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) } @@ -79,7 +80,7 @@ func doTargetRequest( func decodeJSON(t *testing.T, body []byte, dst any) { t.Helper() - if err := json.Unmarshal(body, dst); err != nil { + if err := json.Unmarshal(body, dst, jsonx.V1()); err != nil { t.Fatalf("unmarshal response: %v (body=%s)", err, body) } } @@ -122,7 +123,7 @@ func createWorkspace(t *testing.T, h *workspaces.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pending, ok := resp["PendingRequests"].([]any) require.True(t, ok, "PendingRequests missing from response") @@ -173,7 +174,7 @@ func createWorkspaceWithRunningMode(t *testing.T, h *workspaces.Handler, running require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pending, ok := resp["PendingRequests"].([]any) require.True(t, ok, "PendingRequests missing from response") @@ -204,7 +205,7 @@ func createImage(t *testing.T, h *workspaces.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) id, ok := resp["ImageId"].(string) require.True(t, ok) @@ -267,7 +268,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) pending, ok := resp["PendingRequests"].([]any) require.True(t, ok) assert.Len(t, pending, 1) @@ -291,7 +292,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) wsList, ok := resp["Workspaces"].([]any) require.True(t, ok) assert.Len(t, wsList, 1) @@ -308,7 +309,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) wsList, ok := resp["Workspaces"].([]any) require.True(t, ok) assert.Len(t, wsList, 1) @@ -329,7 +330,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) statuses, ok := resp["WorkspacesConnectionStatus"].([]any) require.True(t, ok) assert.Len(t, statuses, 1) @@ -418,7 +419,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Empty(t, failures) @@ -438,7 +439,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Len(t, failures, 1) @@ -461,7 +462,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Empty(t, failures) @@ -478,7 +479,7 @@ func TestWorkSpaces_Operations(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) stopFailures, _ := stopResp["FailedRequests"].([]any) require.Empty(t, stopFailures, "setup: StopWorkspaces must succeed to reach STOPPED") @@ -495,7 +496,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Empty(t, failures) @@ -518,7 +519,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Empty(t, failures) @@ -541,7 +542,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Empty(t, failures) @@ -561,7 +562,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) failures, ok := resp["FailedRequests"].([]any) require.True(t, ok) assert.Len(t, failures, 1) @@ -624,7 +625,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) tagList, ok := resp["TagList"].([]any) require.True(t, ok) assert.Len(t, tagList, 1) @@ -641,7 +642,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) bundles, ok := resp["Bundles"].([]any) require.True(t, ok) assert.NotEmpty(t, bundles) @@ -655,7 +656,7 @@ func TestWorkSpaces_Operations(t *testing.T) { check: func(t *testing.T, respBody []byte) { t.Helper() var resp map[string]any - require.NoError(t, json.Unmarshal(respBody, &resp)) + require.NoError(t, json.Unmarshal(respBody, &resp, jsonx.V1())) dirs, ok := resp["Directories"].([]any) require.True(t, ok) assert.Empty(t, dirs) diff --git a/services/workspaces/images_test.go b/services/workspaces/images_test.go index 2d9b279b1c..988a093e85 100644 --- a/services/workspaces/images_test.go +++ b/services/workspaces/images_test.go @@ -1,7 +1,7 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -309,7 +310,7 @@ func TestCreateWorkspaceImage_UnknownWorkspace_ConsumesNoState(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code, rec1.Body.String()) var out1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &out1, jsonx.V1())) firstID, _ := out1["ImageId"].(string) require.NotEmpty(t, firstID) @@ -319,7 +320,7 @@ func TestCreateWorkspaceImage_UnknownWorkspace_ConsumesNoState(t *testing.T) { var before struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before, jsonx.V1())) rejectedRec := doTargetRequest( t, h, "CreateWorkspaceImage", createWorkspaceImageReq("ws-doesnotexist"), @@ -332,7 +333,7 @@ func TestCreateWorkspaceImage_UnknownWorkspace_ConsumesNoState(t *testing.T) { var after struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after, jsonx.V1())) assert.Len(t, after.Images, len(before.Images), "rejected create must not add an image") @@ -340,7 +341,7 @@ func TestCreateWorkspaceImage_UnknownWorkspace_ConsumesNoState(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code, rec2.Body.String()) var out2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &out2, jsonx.V1())) secondID, _ := out2["ImageId"].(string) require.NotEmpty(t, secondID) @@ -462,7 +463,7 @@ func TestCopyWorkspaceImage_UnknownSourceImage_ConsumesNoState(t *testing.T) { var before struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before, jsonx.V1())) rejectedRec := doTargetRequest( t, h, "CopyWorkspaceImage", createCopyImageReq("wsi-doesnotexist", "us-east-1"), @@ -475,7 +476,7 @@ func TestCopyWorkspaceImage_UnknownSourceImage_ConsumesNoState(t *testing.T) { var after struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after, jsonx.V1())) assert.Len(t, after.Images, len(before.Images), "rejected copy must not add an image") @@ -577,7 +578,7 @@ func TestCreateUpdatedWorkspaceImage_UnknownSourceImage_ConsumesNoState(t *testi var before struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before)) + require.NoError(t, json.Unmarshal(describeRec.Body.Bytes(), &before, jsonx.V1())) rejectedRec := doTargetRequest( t, h, "CreateUpdatedWorkspaceImage", createUpdatedImageReq("wsi-doesnotexist"), @@ -590,7 +591,7 @@ func TestCreateUpdatedWorkspaceImage_UnknownSourceImage_ConsumesNoState(t *testi var after struct { Images []map[string]any `json:"Images"` } - require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after)) + require.NoError(t, json.Unmarshal(describeRec2.Body.Bytes(), &after, jsonx.V1())) assert.Len(t, after.Images, len(before.Images), "rejected create must not add an image") diff --git a/services/workspaces/multi_region_test.go b/services/workspaces/multi_region_test.go index ee611ec970..db10b976b3 100644 --- a/services/workspaces/multi_region_test.go +++ b/services/workspaces/multi_region_test.go @@ -2,7 +2,8 @@ package workspaces_test import ( "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net" "net/http" "net/http/httptest" @@ -18,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/service" svc "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -173,8 +175,8 @@ func TestHandler_MultiRegionPersistence(t *testing.T) { snap := src.Snapshot(context.Background()) require.NotNil(t, snap) - var doc map[string]json.RawMessage - require.NoError(t, json.Unmarshal(snap, &doc)) + var doc map[string]jsontext.Value + require.NoError(t, json.Unmarshal(snap, &doc, jsonx.V1())) if _, ok := doc["regions"]; ok != tc.remote { t.Fatalf("regions key present = %v, want %v", ok, tc.remote) diff --git a/services/workspaces/persistence.go b/services/workspaces/persistence.go index 5d797d95a8..939b48eb49 100644 --- a/services/workspaces/persistence.go +++ b/services/workspaces/persistence.go @@ -2,7 +2,7 @@ package workspaces import ( "context" - "encoding/json" + "encoding/json/jsontext" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -43,7 +43,7 @@ const workspacesSnapshotVersion = 1 // against decoding a snapshot from an incompatible (older or newer) build of // this backend as though it were the current shape; see Restore. type backendSnapshot struct { - Tables map[string]json.RawMessage `json:"tables"` + Tables map[string]jsontext.Value `json:"tables"` Tags map[string]map[string]string `json:"tags"` ClientProperties map[string]storedClientProps `json:"clientProperties,omitempty"` ImagePermissions map[string]map[string]bool `json:"imagePermissions,omitempty"` diff --git a/services/workspaces/pools_test.go b/services/workspaces/pools_test.go index 23a429f902..1d8f95558d 100644 --- a/services/workspaces/pools_test.go +++ b/services/workspaces/pools_test.go @@ -1,7 +1,7 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" @@ -10,6 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/workspaces/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestWorkspacesPool_CapacityStatusAndRunningMode verifies fields that were @@ -196,7 +198,7 @@ func TestWorkspacesPool_UpdateRunningModeRequiresStopped(t *testing.T) { if tc.wantStatus == http.StatusBadRequest { var errOut map[string]string - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &errOut, jsonx.V1())) assert.Equal(t, "InvalidResourceStateException", errOut["__type"]) } diff --git a/services/workspaces/tags_test.go b/services/workspaces/tags_test.go index 9c5d5b2537..5eb99df325 100644 --- a/services/workspaces/tags_test.go +++ b/services/workspaces/tags_test.go @@ -1,13 +1,16 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -126,7 +129,7 @@ func TestCreateTags_VisibleInDescribeTags(t *testing.T) { Value string `json:"Value"` } `json:"TagList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := make(map[string]string, len(resp.TagList)) for _, tag := range resp.TagList { @@ -172,7 +175,7 @@ func TestDeleteTags_RemovedFromDescribeTags(t *testing.T) { Value string `json:"Value"` } `json:"TagList"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags := make(map[string]string, len(resp.TagList)) for _, tag := range resp.TagList { @@ -206,9 +209,9 @@ func TestDescribeWorkspaces_NoTagsField(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp struct { - Workspaces []map[string]json.RawMessage `json:"Workspaces"` + Workspaces []map[string]jsontext.Value `json:"Workspaces"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.Workspaces, 1) assert.NotContains(t, resp.Workspaces[0], "Tags") } @@ -238,7 +241,7 @@ func TestCreateWorkspaces_Tags_VisibleInDescribeTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending, _ := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) wsID := pending[0].(map[string]any)["WorkspaceId"].(string) @@ -249,7 +252,7 @@ func TestCreateWorkspaces_Tags_VisibleInDescribeTags(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var tagResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &tagResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &tagResp, jsonx.V1())) tagList, _ := tagResp["TagList"].([]any) found := false diff --git a/services/workspaces/workspace_properties.go b/services/workspaces/workspace_properties.go index 61db4c1579..76c58c118f 100644 --- a/services/workspaces/workspace_properties.go +++ b/services/workspaces/workspace_properties.go @@ -1,8 +1,10 @@ package workspaces import ( - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // ModifyEndpointEncryptionMode stores the endpoint encryption mode for a @@ -151,7 +153,7 @@ func (b *InMemoryBackend) ModifyStreamingProperties(directoryID string, props St merged.GlobalAccelerator = props.GlobalAccelerator } - raw, err := json.Marshal(merged) + raw, err := json.Marshal(merged, jsonx.V1()) if err != nil { return fmt.Errorf("encode streaming properties: %w", err) } diff --git a/services/workspaces/workspace_properties_test.go b/services/workspaces/workspace_properties_test.go index 6f32d30f09..7fac31bfef 100644 --- a/services/workspaces/workspace_properties_test.go +++ b/services/workspaces/workspace_properties_test.go @@ -1,12 +1,14 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestDirectoryModifyOps exercises the directory-scoped property-modify @@ -193,7 +195,7 @@ func TestDirectoryModifyOps_RejectsLegacyDirectoryIdKey(t *testing.T) { "DirectoryId": tc.body["DirectoryId"], }) - rawBody, marshalErr := json.Marshal(tc.body) + rawBody, marshalErr := json.Marshal(tc.body, jsonx.V1()) require.NoError(t, marshalErr) require.NotContains( t, string(rawBody), `"ResourceId"`, diff --git a/services/workspaces/workspaces_lifecycle_test.go b/services/workspaces/workspaces_lifecycle_test.go index ced7d83a60..183482bf49 100644 --- a/services/workspaces/workspaces_lifecycle_test.go +++ b/services/workspaces/workspaces_lifecycle_test.go @@ -1,7 +1,7 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "net" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -29,7 +30,7 @@ func TestConnectionStatus_Available_IsDisconnected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) statuses := resp["WorkspacesConnectionStatus"].([]any) require.Len(t, statuses, 1) assert.Equal(t, "DISCONNECTED", statuses[0].(map[string]any)["ConnectionState"], @@ -48,7 +49,7 @@ func TestConnectionStatus_Stopped_IsNotConnected(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) stopFailures, _ := stopResp["FailedRequests"].([]any) require.Empty(t, stopFailures, "StopWorkspaces must succeed to reach STOPPED") @@ -58,7 +59,7 @@ func TestConnectionStatus_Stopped_IsNotConnected(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) statuses := resp["WorkspacesConnectionStatus"].([]any) require.Len(t, statuses, 1) assert.Equal(t, "NOT_CONNECTED", statuses[0].(map[string]any)["ConnectionState"], @@ -80,7 +81,7 @@ func TestConnectionStatus_AllWorkspaces_NoFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) statuses := resp["WorkspacesConnectionStatus"].([]any) assert.Len(t, statuses, 2, "empty WorkspaceIds must return status for all workspaces") @@ -103,7 +104,7 @@ func TestConnectionStatus_UnknownID_Excluded(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) statuses := resp["WorkspacesConnectionStatus"].([]any) assert.Empty(t, statuses, "unknown workspace ID must be silently excluded from status results") } @@ -205,7 +206,7 @@ func TestRebootRebuildWorkspaces_StatePrecondition(t *testing.T) { ErrorMessage string `json:"ErrorMessage"` } `json:"FailedRequests"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if !tc.wantFailed { assert.Empty(t, out.FailedRequests) @@ -247,7 +248,7 @@ func TestRebootWorkspaces_AllowsAvailableAndStopped(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) stopFailures, _ := stopResp["FailedRequests"].([]any) require.Empty(t, stopFailures, "StopWorkspaces must succeed to reach STOPPED") } @@ -262,7 +263,7 @@ func TestRebootWorkspaces_AllowsAvailableAndStopped(t *testing.T) { ErrorCode string `json:"ErrorCode"` } `json:"FailedRequests"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) if tc.stop { require.Len(t, out.FailedRequests, 1) @@ -292,7 +293,7 @@ func TestMigrateWorkspace_SourceRemovedTargetCreated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Original workspace must no longer exist. assert.Empty(t, workspaces.WorkspaceState(backend, srcID), @@ -375,7 +376,7 @@ func TestDescribeWorkspaces_EmptyList_WhenNoWorkspaces(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList := resp["Workspaces"].([]any) assert.Empty(t, wsList) @@ -396,7 +397,7 @@ func TestDescribeWorkspaces_MultipleIDs_AllReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList := resp["Workspaces"].([]any) assert.Len(t, wsList, 2) } @@ -416,7 +417,7 @@ func TestDescribeWorkspaces_FilterByUserName(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList := resp["Workspaces"].([]any) assert.Len(t, wsList, 2, "UserName filter must return only Alice's workspaces") @@ -446,7 +447,7 @@ func TestCreateWorkspaces_VolumeEncryption_Propagated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) @@ -460,7 +461,7 @@ func TestCreateWorkspaces_VolumeEncryption_Propagated(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) wsList := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) descWs := wsList[0].(map[string]any) @@ -512,7 +513,7 @@ func TestErrorMessages_AreNotGarbledByExtraFormatArgs(t *testing.T) { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.NotContains(t, resp["message"], "%!(EXTRA", "error message must not contain a garbled fmt.Sprintf EXTRA marker") assert.NotEmpty(t, resp["message"]) @@ -565,7 +566,7 @@ func TestCreateWorkspaces_PartialFailure_DoesNotAbortWholeBatch(t *testing.T) { } `json:"PendingRequests"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) require.Len(t, resp.PendingRequests, 1, "the valid spec must succeed") assert.Equal(t, "gooduser", resp.PendingRequests[0].UserName) diff --git a/services/workspaces/workspaces_test.go b/services/workspaces/workspaces_test.go index e88575ff7b..e6c74bd471 100644 --- a/services/workspaces/workspaces_test.go +++ b/services/workspaces/workspaces_test.go @@ -2,7 +2,7 @@ package workspaces_test import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "sort" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/workspaces" ) @@ -39,7 +40,7 @@ func createWorkspaceWithSpec(t *testing.T, h *workspaces.Handler, userID, dirID require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pending, _ := resp["PendingRequests"].([]any) require.Len(t, pending, 1) @@ -64,7 +65,7 @@ func describeWorkspacesPage( require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, _ := resp["Workspaces"].([]any) ids := make([]string, 0, len(wsList)) @@ -236,7 +237,7 @@ func TestStopWorkspaces_TransitionsToStopped(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) assert.Empty(t, failures) @@ -258,7 +259,7 @@ func TestStopWorkspaces_StateVisibleInDescribe(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) stopFailures, _ := stopResp["FailedRequests"].([]any) require.Empty(t, stopFailures, "StopWorkspaces must succeed to reach STOPPED") @@ -268,7 +269,7 @@ func TestStopWorkspaces_StateVisibleInDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, _ := resp["Workspaces"].([]any) require.Len(t, wsList, 1) ws := wsList[0].(map[string]any) @@ -299,7 +300,7 @@ func TestStartWorkspaces_ResumesFromStopped(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) assert.Empty(t, failures) @@ -328,7 +329,7 @@ func TestStopWorkspaces_AlreadyStopped_Fails(t *testing.T) { require.Equal(t, http.StatusOK, firstStopRec.Code) var firstStopResp map[string]any - require.NoError(t, json.Unmarshal(firstStopRec.Body.Bytes(), &firstStopResp)) + require.NoError(t, json.Unmarshal(firstStopRec.Body.Bytes(), &firstStopResp, jsonx.V1())) firstStopFailures, _ := firstStopResp["FailedRequests"].([]any) require.Empty(t, firstStopFailures, "first StopWorkspaces call must succeed to reach STOPPED") @@ -338,7 +339,7 @@ func TestStopWorkspaces_AlreadyStopped_Fails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) require.Len(t, failures, 1, "stopping an already-STOPPED workspace must fail") failed := failures[0].(map[string]any) @@ -362,7 +363,7 @@ func TestStartWorkspaces_AlreadyAvailable_Fails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) require.Len(t, failures, 1, "starting an already-AVAILABLE workspace must fail") failed := failures[0].(map[string]any) @@ -393,7 +394,7 @@ func TestStopWorkspaces_AlwaysOnRunningMode_Fails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) require.Len(t, failures, 1, "stopping an ALWAYS_ON workspace must fail even though its state is AVAILABLE") @@ -430,7 +431,7 @@ func TestStartWorkspaces_AlwaysOnRunningMode_Fails(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) require.Len(t, failures, 1, "starting an ALWAYS_ON workspace must fail even though its state is STOPPED") @@ -458,7 +459,7 @@ func TestStopStartWorkspaces_AutoStopRunningMode_Succeeds(t *testing.T) { require.Equal(t, http.StatusOK, stopRec.Code) var stopResp map[string]any - require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp)) + require.NoError(t, json.Unmarshal(stopRec.Body.Bytes(), &stopResp, jsonx.V1())) stopFailures, _ := stopResp["FailedRequests"].([]any) assert.Empty(t, stopFailures, "AUTO_STOP workspace must be stoppable") require.Equal(t, "STOPPED", workspaces.WorkspaceState(backend, wsID)) @@ -469,7 +470,7 @@ func TestStopStartWorkspaces_AutoStopRunningMode_Succeeds(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) startFailures, _ := startResp["FailedRequests"].([]any) assert.Empty(t, startFailures, "AUTO_STOP workspace must be startable") assert.Equal(t, "AVAILABLE", workspaces.WorkspaceState(backend, wsID)) @@ -492,7 +493,7 @@ func TestStopWorkspaces_UnknownID_ReturnsFailure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) assert.Len(t, failures, 1, "unknown workspace must produce one FailedRequest") @@ -514,7 +515,7 @@ func TestStartWorkspaces_UnknownID_ReturnsFailure(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) failures, _ := resp["FailedRequests"].([]any) assert.Len(t, failures, 1, "unknown workspace must produce one FailedRequest") } @@ -576,7 +577,7 @@ func TestModifyWorkspaceProperties_VisibleInDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, _ := resp["Workspaces"].([]any) require.Len(t, wsList, 1) @@ -606,7 +607,7 @@ func TestWorkspaceProperties_DefaultRunningModeBeforeModify(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, _ := resp["Workspaces"].([]any) require.Len(t, wsList, 1) @@ -639,7 +640,7 @@ func TestTerminateWorkspaces_RemovedFromDescribe(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, _ := resp["Workspaces"].([]any) assert.Empty(t, wsList, "terminated workspace must not appear in DescribeWorkspaces") } @@ -771,7 +772,7 @@ func TestPagination_FilteredByDirectoryID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList := resp["Workspaces"].([]any) assert.Len(t, wsList, 2, "filter by DirectoryId must return only matching workspaces") } @@ -809,7 +810,7 @@ func TestWorkspace_RealMembersPopulated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) wsList, ok := resp["Workspaces"].([]any) require.True(t, ok) require.Len(t, wsList, 1) @@ -853,7 +854,7 @@ func TestWorkspace_WorkspaceNameThreadedThrough(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending, _ := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) pendingItem := pending[0].(map[string]any) @@ -867,7 +868,7 @@ func TestWorkspace_WorkspaceNameThreadedThrough(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) wsList, _ := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) ws := wsList[0].(map[string]any) @@ -901,7 +902,7 @@ func describeOneWorkspace(t *testing.T, h *workspaces.Handler, workspaceID strin var out struct { Workspaces []describedWorkspace `json:"Workspaces"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Len(t, out.Workspaces, 1) return out.Workspaces[0] @@ -956,7 +957,7 @@ func TestCreateStandbyWorkspaces_DataReplicationAndRelated(t *testing.T) { WorkspaceID string `json:"WorkspaceId"` } `json:"PendingStandbyRequests"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Empty(t, out.FailedStandbyRequests) require.Len(t, out.PendingStandbyRequests, 1) @@ -1001,7 +1002,7 @@ func TestCreateStandbyWorkspaces_UnknownPrimaryFails(t *testing.T) { } `json:"FailedStandbyRequests"` PendingStandbyRequests []any `json:"PendingStandbyRequests"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) require.Empty(t, out.PendingStandbyRequests) require.Len(t, out.FailedStandbyRequests, 1) diff --git a/services/workspaces/workspaces_validation_test.go b/services/workspaces/workspaces_validation_test.go index 3408a7f01c..ec2e473e70 100644 --- a/services/workspaces/workspaces_validation_test.go +++ b/services/workspaces/workspaces_validation_test.go @@ -1,7 +1,7 @@ package workspaces_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,8 @@ import ( sdktypes "github.com/aws/aws-sdk-go-v2/service/workspaces/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // --------------------------------------------------------------------------- @@ -113,7 +115,7 @@ func TestCreateWorkspaces_MaxAllowed_Returns200(t *testing.T) { ) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pending := resp["PendingRequests"].([]any) assert.Len(t, pending, 25) } @@ -145,7 +147,7 @@ func TestCreateWorkspaces_WithProperties_Stored(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) @@ -172,7 +174,7 @@ func TestCreateWorkspaces_WithProperties_Stored(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) wsList := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) @@ -210,7 +212,7 @@ func TestCreateWorkspaces_DefaultsRunningModeToAlwaysOn(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) ws := pending[0].(map[string]any) @@ -226,7 +228,7 @@ func TestCreateWorkspaces_DefaultsRunningModeToAlwaysOn(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) wsList := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) @@ -259,7 +261,7 @@ func TestCreateWorkspaces_ExplicitRunningMode_NotOverwritten(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) ws := pending[0].(map[string]any) @@ -273,7 +275,7 @@ func TestCreateWorkspaces_ExplicitRunningMode_NotOverwritten(t *testing.T) { require.Equal(t, http.StatusOK, descRec.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(descRec.Body.Bytes(), &descResp, jsonx.V1())) wsList := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) assert.Equal(t, "AUTO_STOP", wsList[0].(map[string]any)["WorkspaceProperties"].(map[string]any)["RunningMode"], @@ -320,7 +322,7 @@ func TestCreateWorkspaces_InvalidRunningMode_FailsPerItem(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "batch op must return 200 even with a failed item") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) pending, _ := resp["PendingRequests"].([]any) assert.Empty(t, pending, "the invalid item must not be created") @@ -358,7 +360,7 @@ func TestCreateWorkspaces_SubnetId_Propagated(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &createResp, jsonx.V1())) pending := createResp["PendingRequests"].([]any) require.Len(t, pending, 1) @@ -372,7 +374,7 @@ func TestCreateWorkspaces_SubnetId_Propagated(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var descResp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &descResp, jsonx.V1())) wsList := descResp["Workspaces"].([]any) require.Len(t, wsList, 1) assert.Equal(t, "subnet-12345678", wsList[0].(map[string]any)["SubnetId"]) @@ -528,7 +530,7 @@ func TestModifyWorkspaceProperties_InvalidComputeType_MessageIsDescriptive(t *te var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp["message"], "NOT_A_REAL_TYPE", "message should describe the actual invalid value, not just the error code") assert.NotContains(t, resp["message"], "%!(EXTRA") diff --git a/services/xray/handler.go b/services/xray/handler.go index 9889c101b8..6cb3a16e84 100644 --- a/services/xray/handler.go +++ b/services/xray/handler.go @@ -2,7 +2,7 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "errors" "fmt" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" "github.com/blackbirdworks/gopherstack/pkgs/config" "github.com/blackbirdworks/gopherstack/pkgs/httputils" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/regionpeers" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -336,7 +337,7 @@ func (h *Handler) ExtractResource(c *echo.Context) string { RuleName string `json:"RuleName"` } - _ = json.Unmarshal(body, &req) + _ = json.Unmarshal(body, &req, jsonx.V1()) if req.GroupName != "" { return req.GroupName @@ -498,9 +499,6 @@ func invalidParameterExceptionName(err error) string { } func (h *Handler) handleError(c *echo.Context, _ string, err error) error { - var syntaxErr *json.SyntaxError - var typeErr *json.UnmarshalTypeError - switch { case errors.Is(err, awserr.ErrNotFound): return c.JSON(http.StatusBadRequest, map[string]string{ @@ -518,7 +516,7 @@ func (h *Handler) handleError(c *echo.Context, _ string, err error) error { keyMessageField: err.Error(), }) case errors.Is(err, errInvalidRequest), errors.Is(err, errUnknownPath), - errors.As(err, &syntaxErr), errors.As(err, &typeErr): + jsonx.IsSyntaxError(err), jsonx.IsTypeError(err): return c.JSON(http.StatusBadRequest, map[string]string{ keyTypeField: errInvalidRequestException, keyMessageField: err.Error(), diff --git a/services/xray/handler_encryption_config.go b/services/xray/handler_encryption_config.go index 64fb6f079d..cb92649375 100644 --- a/services/xray/handler_encryption_config.go +++ b/services/xray/handler_encryption_config.go @@ -2,11 +2,13 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "github.com/labstack/echo/v5" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putEncryptionConfigInput struct { @@ -30,13 +32,13 @@ func (h *Handler) handleGetEncryptionConfigBody(_ context.Context, _ []byte) ([] return json.Marshal(map[string]any{ keyEncryptionConfig: cfg, - }) + }, jsonx.V1()) } func (h *Handler) handlePutEncryptionConfig(_ context.Context, body []byte) ([]byte, error) { var in putEncryptionConfigInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -65,5 +67,5 @@ func (h *Handler) handlePutEncryptionConfig(_ context.Context, body []byte) ([]b return json.Marshal(map[string]any{ keyEncryptionConfig: cfg, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_encryption_config_test.go b/services/xray/handler_encryption_config_test.go index 8f17a085d2..a925b599d1 100644 --- a/services/xray/handler_encryption_config_test.go +++ b/services/xray/handler_encryption_config_test.go @@ -1,12 +1,14 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetEncryptionConfig(t *testing.T) { @@ -143,7 +145,7 @@ func TestEncryption_UpdatingStatusAfterPut(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) enc, ok := putResp["EncryptionConfig"].(map[string]any) require.True(t, ok) @@ -154,7 +156,7 @@ func TestEncryption_UpdatingStatusAfterPut(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) enc2, ok := getResp["EncryptionConfig"].(map[string]any) require.True(t, ok) @@ -200,7 +202,7 @@ func TestGetEncryptionConfig_DefaultIsNONE(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) enc, ok := resp["EncryptionConfig"].(map[string]any) require.True(t, ok, "EncryptionConfig must be present in response") @@ -294,7 +296,7 @@ func TestHandler_EncryptionConfig_KMSRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp, jsonx.V1())) cfg, ok := resp["EncryptionConfig"].(map[string]any) require.True(t, ok) @@ -309,7 +311,7 @@ func TestHandler_EncryptionConfig_KMSRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec4.Code) var resp4 map[string]any - require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4)) + require.NoError(t, json.Unmarshal(rec4.Body.Bytes(), &resp4, jsonx.V1())) cfg4, _ := resp4["EncryptionConfig"].(map[string]any) assert.Equal(t, "NONE", cfg4["Type"]) } @@ -358,7 +360,7 @@ func TestEncryptionConfig_UpdatingThenActiveStatus(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) enc, ok := putResp["EncryptionConfig"].(map[string]any) require.True(t, ok) @@ -368,7 +370,7 @@ func TestEncryptionConfig_UpdatingThenActiveStatus(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) enc2, ok := getResp["EncryptionConfig"].(map[string]any) require.True(t, ok) @@ -384,7 +386,7 @@ func TestEncryptionConfig_NoneTypeAccepted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) enc, ok := resp["EncryptionConfig"].(map[string]any) require.True(t, ok) diff --git a/services/xray/handler_groups.go b/services/xray/handler_groups.go index 24619dcf00..fd6da66310 100644 --- a/services/xray/handler_groups.go +++ b/services/xray/handler_groups.go @@ -2,9 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -42,7 +43,7 @@ type createGroupInput struct { func (h *Handler) handleCreateGroup(_ context.Context, body []byte) ([]byte, error) { var in createGroupInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -76,7 +77,7 @@ func (h *Handler) handleCreateGroup(_ context.Context, body []byte) ([]byte, err return json.Marshal(map[string]any{ keyGroup: toGroupView(g), - }) + }, jsonx.V1()) } type getGroupInput struct { @@ -87,7 +88,7 @@ type getGroupInput struct { func (h *Handler) handleGetGroup(_ context.Context, body []byte) ([]byte, error) { var in getGroupInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -113,7 +114,7 @@ func (h *Handler) handleGetGroup(_ context.Context, body []byte) ([]byte, error) return json.Marshal(map[string]any{ keyGroup: toGroupView(g), - }) + }, jsonx.V1()) } // GetGroupsInput (xray@v1.39.4 api_op_GetGroups.go) has no page-size member, @@ -125,7 +126,7 @@ type getGroupsInput struct { func (h *Handler) handleGetGroups(_ context.Context, body []byte) ([]byte, error) { var in getGroupsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -147,7 +148,7 @@ func (h *Handler) handleGetGroups(_ context.Context, body []byte) ([]byte, error keyNextToken: pg.Next, } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } // updateGroupInput uses pointer fields for FilterExpression and InsightsConfiguration @@ -165,7 +166,7 @@ type updateGroupInput struct { func (h *Handler) handleUpdateGroup(_ context.Context, body []byte) ([]byte, error) { var in updateGroupInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -194,7 +195,7 @@ func (h *Handler) handleUpdateGroup(_ context.Context, body []byte) ([]byte, err return json.Marshal(map[string]any{ keyGroup: toGroupView(g), - }) + }, jsonx.V1()) } type deleteGroupInput struct { @@ -205,7 +206,7 @@ type deleteGroupInput struct { func (h *Handler) handleDeleteGroup(_ context.Context, body []byte) ([]byte, error) { var in deleteGroupInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -218,5 +219,5 @@ func (h *Handler) handleDeleteGroup(_ context.Context, body []byte) ([]byte, err return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/xray/handler_groups_test.go b/services/xray/handler_groups_test.go index 5d99d35ea7..f1ccd8d43a 100644 --- a/services/xray/handler_groups_test.go +++ b/services/xray/handler_groups_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -94,7 +95,7 @@ func TestHandler_GetGroups(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["Groups"].([]any) require.True(t, ok) @@ -259,7 +260,7 @@ func TestHandler_UpdateGroup_AppliesInsightsConfiguration(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) group, ok := resp["Group"].(map[string]any) require.True(t, ok) @@ -299,7 +300,7 @@ func TestHandler_UpdateGroup_OmittedFieldsAreNotWiped(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &resp, jsonx.V1())) group, ok := resp["Group"].(map[string]any) require.True(t, ok) assert.Equal(t, `service("original")`, group["FilterExpression"], @@ -313,7 +314,7 @@ func TestHandler_UpdateGroup_OmittedFieldsAreNotWiped(t *testing.T) { require.Equal(t, http.StatusOK, updRec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(updRec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(updRec2.Body.Bytes(), &resp2, jsonx.V1())) group2, ok := resp2["Group"].(map[string]any) require.True(t, ok) ic, ok := group2["InsightsConfiguration"].(map[string]any) @@ -353,7 +354,7 @@ func TestGroup_ARNBasedLookup(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) group, ok := createResp["Group"].(map[string]any) require.True(t, ok) @@ -369,7 +370,7 @@ func TestGroup_ARNBasedLookup(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) g2, ok := getResp["Group"].(map[string]any) require.True(t, ok) @@ -428,7 +429,7 @@ func TestHandler_GetGroups_Pagination(t *testing.T) { require.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["Groups"].([]any) require.True(t, ok, "Groups field must be present and array") @@ -462,7 +463,7 @@ func TestHandler_GetGroups_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) groups1 := resp1["Groups"].([]any) assert.Len(t, groups1, defaultPageSize) @@ -474,7 +475,7 @@ func TestHandler_GetGroups_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) groups2 := resp2["Groups"].([]any) assert.Len(t, groups2, total-defaultPageSize) @@ -490,7 +491,7 @@ func TestHandler_GetGroups_EmptyBodyAccepted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "Groups") assert.Contains(t, resp, "NextToken") } @@ -504,7 +505,7 @@ func TestGroups_ARNBasedLookup(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) group, ok := createResp["Group"].(map[string]any) require.True(t, ok) @@ -517,7 +518,7 @@ func TestGroups_ARNBasedLookup(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) g2, ok := getResp["Group"].(map[string]any) require.True(t, ok) @@ -533,7 +534,7 @@ func TestGroups_UpdateByARN(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) group, _ := createResp["Group"].(map[string]any) groupARN, _ := group["GroupARN"].(string) @@ -545,7 +546,7 @@ func TestGroups_UpdateByARN(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updResp map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) g2, ok := updResp["Group"].(map[string]any) require.True(t, ok) @@ -561,7 +562,7 @@ func TestGroups_DeleteByARN(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) group, _ := createResp["Group"].(map[string]any) groupARN, _ := group["GroupARN"].(string) @@ -603,7 +604,7 @@ func TestGroups_FilterExpressionStoredAndReturned(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) g, ok := resp["Group"].(map[string]any) require.True(t, ok) @@ -621,7 +622,7 @@ func TestGroups_ARNPresentInCreateResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) group, ok := resp["Group"].(map[string]any) require.True(t, ok) @@ -647,7 +648,7 @@ func TestGroups_ListGroups(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) groups, ok := resp["Groups"].([]any) require.True(t, ok) diff --git a/services/xray/handler_indexing_rules.go b/services/xray/handler_indexing_rules.go index d42eae5934..68a614344c 100644 --- a/services/xray/handler_indexing_rules.go +++ b/services/xray/handler_indexing_rules.go @@ -2,9 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -32,7 +33,7 @@ type updateIndexingRuleInput struct { func (h *Handler) handleUpdateIndexingRule(_ context.Context, body []byte) ([]byte, error) { var in updateIndexingRuleInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -54,7 +55,7 @@ func (h *Handler) handleUpdateIndexingRule(_ context.Context, body []byte) ([]by return json.Marshal(map[string]any{ "IndexingRule": toIndexingRuleView(rule), - }) + }, jsonx.V1()) } type indexingRuleView struct { @@ -90,7 +91,7 @@ type getIndexingRulesInput struct { func (h *Handler) handleGetIndexingRules(_ context.Context, body []byte) ([]byte, error) { var in getIndexingRulesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -111,5 +112,5 @@ func (h *Handler) handleGetIndexingRules(_ context.Context, body []byte) ([]byte return json.Marshal(map[string]any{ "IndexingRules": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_indexing_rules_test.go b/services/xray/handler_indexing_rules_test.go index 71fee3c341..8c41189302 100644 --- a/services/xray/handler_indexing_rules_test.go +++ b/services/xray/handler_indexing_rules_test.go @@ -1,12 +1,14 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_GetIndexingRules(t *testing.T) { @@ -33,7 +35,7 @@ func TestHandler_GetIndexingRules(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, ok := resp["IndexingRules"].([]any) require.True(t, ok) @@ -80,7 +82,7 @@ func TestHandler_GetIndexingRules_Pagination(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, _ := resp["IndexingRules"].([]any) assert.GreaterOrEqual(t, len(rules), tt.wantMin) @@ -98,7 +100,7 @@ func TestIndexingRules_GetDefault(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rules, ok := resp["IndexingRules"].([]any) require.True(t, ok) @@ -114,7 +116,7 @@ func TestIndexingRules_UpdateModifiesTimestamp(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule, ok := resp["IndexingRule"].(map[string]any) require.True(t, ok) @@ -147,7 +149,7 @@ func TestIndexingRules_UpdateAppliesProbabilisticRule(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) rule, ok := resp["IndexingRule"].(map[string]any) require.True(t, ok) @@ -165,7 +167,7 @@ func TestIndexingRules_UpdateAppliesProbabilisticRule(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) rules, ok := getResp["IndexingRules"].([]any) require.True(t, ok) @@ -197,7 +199,7 @@ func TestHandler_UpdateIndexingRule_NotFoundReturnsResourceNotFoundException(t * require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // UpdateIndexingRule's modeled error set uses ResourceNotFoundException, unlike // most other X-Ray not-found cases (which use InvalidRequestException). assert.Equal(t, "ResourceNotFoundException", resp["__type"]) diff --git a/services/xray/handler_insights.go b/services/xray/handler_insights.go index e25ab7968e..7ddbdcbd42 100644 --- a/services/xray/handler_insights.go +++ b/services/xray/handler_insights.go @@ -2,10 +2,11 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -64,7 +65,7 @@ func toInsightView(i *Insight) insightView { func (h *Handler) handleGetInsight(_ context.Context, body []byte) ([]byte, error) { var in getInsightInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -80,7 +81,7 @@ func (h *Handler) handleGetInsight(_ context.Context, body []byte) ([]byte, erro return json.Marshal(map[string]any{ "Insight": toInsightView(i), - }) + }, jsonx.V1()) } type getInsightEventsInput struct { @@ -97,7 +98,7 @@ type insightEventView struct { func (h *Handler) handleGetInsightEvents(_ context.Context, body []byte) ([]byte, error) { var in getInsightEventsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -128,7 +129,7 @@ func (h *Handler) handleGetInsightEvents(_ context.Context, body []byte) ([]byte return json.Marshal(map[string]any{ "InsightEvents": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } type getInsightImpactGraphInput struct { @@ -141,7 +142,7 @@ type getInsightImpactGraphInput struct { func (h *Handler) handleGetInsightImpactGraph(_ context.Context, body []byte) ([]byte, error) { var in getInsightImpactGraphInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -163,7 +164,7 @@ func (h *Handler) handleGetInsightImpactGraph(_ context.Context, body []byte) ([ "ServiceGraphStartTime": in.StartTime, "ServiceGraphEndTime": in.EndTime, keyNextToken: "", - }) + }, jsonx.V1()) } type getInsightSummariesInput struct { @@ -215,7 +216,7 @@ func toInsightSummaryView(i *Insight) insightSummaryView { func (h *Handler) handleGetInsightSummaries(_ context.Context, body []byte) ([]byte, error) { var in getInsightSummariesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -266,5 +267,5 @@ func (h *Handler) handleGetInsightSummaries(_ context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "InsightSummaries": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_insights_test.go b/services/xray/handler_insights_test.go index 5ec29b498c..e0193feae5 100644 --- a/services/xray/handler_insights_test.go +++ b/services/xray/handler_insights_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "maps" "net/http" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -45,7 +46,7 @@ func TestGetInsightSummaries_ALLState(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) @@ -117,7 +118,7 @@ func TestGetInsightSummariesStateFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) @@ -145,7 +146,7 @@ func TestGroupInsightsConfigurationRoundtrip(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) group, ok := resp["Group"].(map[string]any) require.True(t, ok) @@ -237,7 +238,7 @@ func TestHandler_GetInsight_ResponseFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insight, ok := resp["Insight"].(map[string]any) require.True(t, ok) @@ -296,7 +297,7 @@ func TestHandler_GetInsightEvents(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, ok := resp["InsightEvents"].([]any) require.True(t, ok) @@ -362,7 +363,7 @@ func TestHandler_GetInsightImpactGraph(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "insight-xyz", resp["InsightId"]) @@ -426,7 +427,7 @@ func TestHandler_GetInsightSummaries(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) @@ -491,7 +492,7 @@ func TestHandler_GetInsightEvents_Pagination(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) nextToken, _ := resp["NextToken"].(string) if tt.wantHasNext { @@ -524,7 +525,7 @@ func TestHandler_GetInsightEvents_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) events1, _ := resp1["InsightEvents"].([]any) assert.Len(t, events1, 4) @@ -540,7 +541,7 @@ func TestHandler_GetInsightEvents_NextTokenContinuation(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) events2, _ := resp2["InsightEvents"].([]any) assert.Len(t, events2, 2) @@ -604,7 +605,7 @@ func TestHandler_GetInsightSummaries_Pagination(t *testing.T) { } var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["InsightSummaries"].([]any) assert.Len(t, summaries, tt.wantCount) @@ -630,7 +631,7 @@ func TestHandler_GetInsight_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insightData, ok := resp["Insight"].(map[string]any) require.True(t, ok) @@ -657,7 +658,7 @@ func TestHandler_GetInsightSummaries_ResponseShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) @@ -699,7 +700,7 @@ func TestGetInsightSummaries_LastUpdateTimeReflectsActivity(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) require.Len(t, summaries, 1) @@ -717,7 +718,7 @@ func TestGetInsightSummaries_LastUpdateTimeReflectsActivity(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) insight, ok := getResp["Insight"].(map[string]any) require.True(t, ok) assert.NotContains(t, insight, "LastUpdateTime") @@ -770,7 +771,7 @@ func TestGetInsight_FieldsReturned(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) insight, ok := resp["Insight"].(map[string]any) require.True(t, ok) @@ -813,7 +814,7 @@ func TestGetInsightEvents_ReturnsEventsForInsight(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) events, ok := resp["InsightEvents"].([]any) require.True(t, ok) @@ -868,7 +869,7 @@ func TestGetInsightImpactGraph_ReturnsInsightId(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "i-impact-001", resp["InsightId"]) } }) @@ -919,7 +920,7 @@ func TestGetInsightSummaries_StatesValidation(t *testing.T) { if tt.wantStatus == http.StatusOK && tt.wantCount > 0 { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["InsightSummaries"].([]any) require.True(t, ok) diff --git a/services/xray/handler_resource_policies.go b/services/xray/handler_resource_policies.go index a62dde5c9d..0e6a6c7aaf 100644 --- a/services/xray/handler_resource_policies.go +++ b/services/xray/handler_resource_policies.go @@ -2,10 +2,11 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -17,7 +18,7 @@ type deleteResourcePolicyInput struct { func (h *Handler) handleDeleteResourcePolicy(_ context.Context, body []byte) ([]byte, error) { var in deleteResourcePolicyInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -30,7 +31,7 @@ func (h *Handler) handleDeleteResourcePolicy(_ context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type resourcePolicyView struct { @@ -55,7 +56,7 @@ func (h *Handler) handleListResourcePolicies(_ context.Context, body []byte) ([] MaxResults int `json:"MaxResults"` } if len(body) > 0 { - _ = json.Unmarshal(body, &in) + _ = json.Unmarshal(body, &in, jsonx.V1()) } policies := h.Backend.ListResourcePolicies() @@ -71,7 +72,7 @@ func (h *Handler) handleListResourcePolicies(_ context.Context, body []byte) ([] pg := page.New(views, in.NextToken, in.MaxResults, defaultResourcePoliciesPageSize) resp := map[string]any{"ResourcePolicies": pg.Data, keyNextToken: pg.Next} - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type putResourcePolicyInput struct { @@ -84,7 +85,7 @@ type putResourcePolicyInput struct { func (h *Handler) handlePutResourcePolicy(ctx context.Context, body []byte) ([]byte, error) { var in putResourcePolicyInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -107,5 +108,5 @@ func (h *Handler) handlePutResourcePolicy(ctx context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "ResourcePolicy": toResourcePolicyView(p), - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_resource_policies_test.go b/services/xray/handler_resource_policies_test.go index 843e19caea..ac469ff0fb 100644 --- a/services/xray/handler_resource_policies_test.go +++ b/services/xray/handler_resource_policies_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -67,7 +68,7 @@ func TestPutAndListResourcePolicies(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ResourcePolicies"].([]any) require.True(t, ok) @@ -82,7 +83,7 @@ func TestPutAndListResourcePolicies(t *testing.T) { require.Equal(t, http.StatusOK, putRec.Code) var putResp map[string]any - require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp)) + require.NoError(t, json.Unmarshal(putRec.Body.Bytes(), &putResp, jsonx.V1())) policyObj, ok := putResp["ResourcePolicy"].(map[string]any) require.True(t, ok) @@ -94,7 +95,7 @@ func TestPutAndListResourcePolicies(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) policies, ok = listResp["ResourcePolicies"].([]any) require.True(t, ok) @@ -148,7 +149,7 @@ func TestListResourcePolicies_NextTokenInResponse(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["NextToken"] assert.True(t, ok, "NextToken must be present in ListResourcePolicies response") @@ -314,7 +315,7 @@ func TestResourcePolicy_ListAfterPut(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) policies, ok := resp["ResourcePolicies"].([]any) require.True(t, ok) @@ -339,7 +340,7 @@ func TestResourcePolicy_DeleteExistingPolicy(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) policies, _ := resp["ResourcePolicies"].([]any) assert.Empty(t, policies, "policy must be removed after delete") @@ -372,7 +373,7 @@ func TestResourcePolicy_MaxCountUsesCorrectErrorCode(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PolicyCountLimitExceededException", resp["__type"]) } @@ -393,7 +394,7 @@ func TestResourcePolicy_SizeLimitExceeded(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "PolicySizeLimitExceededException", resp["__type"]) } @@ -413,7 +414,7 @@ func TestResourcePolicy_LastUpdatedTimeIsEpochSeconds(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) policy, ok := resp["ResourcePolicy"].(map[string]any) require.True(t, ok) @@ -447,7 +448,7 @@ func TestHandler_DeleteResourcePolicy_RevisionIDEnforced(t *testing.T) { require.Equal(t, http.StatusBadRequest, wrongRec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(wrongRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(wrongRec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "InvalidPolicyRevisionIdException", resp["__type"]) // The policy must still exist after the rejected delete. @@ -455,7 +456,7 @@ func TestHandler_DeleteResourcePolicy_RevisionIDEnforced(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) policies, _ := listResp["ResourcePolicies"].([]any) assert.Len(t, policies, 1, "policy must survive a delete with the wrong PolicyRevisionId") } diff --git a/services/xray/handler_sampling_rules.go b/services/xray/handler_sampling_rules.go index 15ea6b120a..1f6fa8b716 100644 --- a/services/xray/handler_sampling_rules.go +++ b/services/xray/handler_sampling_rules.go @@ -2,9 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -94,7 +95,7 @@ type createSamplingRuleInput struct { func (h *Handler) handleCreateSamplingRule(_ context.Context, body []byte) ([]byte, error) { var in createSamplingRuleInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -143,7 +144,7 @@ func (h *Handler) handleCreateSamplingRule(_ context.Context, body []byte) ([]by return json.Marshal(map[string]any{ keySamplingRuleRecord: toSamplingRuleRecord(r), - }) + }, jsonx.V1()) } type getSamplingRulesInput struct { @@ -153,7 +154,7 @@ type getSamplingRulesInput struct { func (h *Handler) handleGetSamplingRules(_ context.Context, body []byte) ([]byte, error) { var in getSamplingRulesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -174,7 +175,7 @@ func (h *Handler) handleGetSamplingRules(_ context.Context, body []byte) ([]byte return json.Marshal(map[string]any{ "SamplingRuleRecords": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } // samplingRuleUpdateInput uses json.RawMessage so we can detect which fields @@ -204,7 +205,7 @@ type updateSamplingRuleInput struct { func (h *Handler) handleUpdateSamplingRule(_ context.Context, body []byte) ([]byte, error) { var in updateSamplingRuleInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -246,7 +247,7 @@ func (h *Handler) handleUpdateSamplingRule(_ context.Context, body []byte) ([]by return json.Marshal(map[string]any{ keySamplingRuleRecord: toSamplingRuleRecord(r), - }) + }, jsonx.V1()) } type deleteSamplingRuleInput struct { @@ -257,7 +258,7 @@ type deleteSamplingRuleInput struct { func (h *Handler) handleDeleteSamplingRule(_ context.Context, body []byte) ([]byte, error) { var in deleteSamplingRuleInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -273,5 +274,5 @@ func (h *Handler) handleDeleteSamplingRule(_ context.Context, body []byte) ([]by return json.Marshal(map[string]any{ keySamplingRuleRecord: toSamplingRuleRecord(r), - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_sampling_rules_test.go b/services/xray/handler_sampling_rules_test.go index 6eed4ea626..8b2b885149 100644 --- a/services/xray/handler_sampling_rules_test.go +++ b/services/xray/handler_sampling_rules_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -84,7 +85,7 @@ func TestHandler_GetSamplingRules(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["SamplingRuleRecords"].([]any) require.True(t, ok) @@ -172,7 +173,7 @@ func TestHandler_UpdateSamplingRule_Attributes(t *testing.T) { } `json:"SamplingRule"` } `json:"SamplingRuleRecord"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, map[string]string{"env": "prod"}, resp.SamplingRuleRecord.SamplingRule.Attributes) } @@ -238,7 +239,7 @@ func TestUpdateSamplingRule_ZeroFixedRate(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) record, ok := resp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) @@ -277,7 +278,7 @@ func TestSamplingRuleAttributes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) record, ok := resp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) @@ -310,7 +311,7 @@ func TestSamplingRuleModifiedAtInRecord(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["SamplingRuleRecords"].([]any) require.True(t, ok) @@ -425,7 +426,7 @@ func TestHandler_GetSamplingRules_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["SamplingRuleRecords"].([]any) require.True(t, ok) @@ -545,7 +546,7 @@ func TestSamplingRule_DefaultRulePresentAtStart(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) records, ok := resp["SamplingRuleRecords"].([]any) require.True(t, ok) @@ -630,7 +631,7 @@ func TestUpdateSamplingRule_ZeroValues(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) record, ok := resp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) @@ -762,7 +763,7 @@ func TestSamplingRule_SamplingRateBoostRoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) record, ok := createResp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) rule, ok := record["SamplingRule"].(map[string]any) @@ -785,7 +786,7 @@ func TestSamplingRule_SamplingRateBoostRoundTrips(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updResp map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) updRecord, ok := updResp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) updRule, ok := updRecord["SamplingRule"].(map[string]any) @@ -811,7 +812,7 @@ func TestSamplingRule_UpdateAndDeleteByARN(t *testing.T) { require.Equal(t, http.StatusOK, createRec.Code) var createResp map[string]any - require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp)) + require.NoError(t, json.Unmarshal(createRec.Body.Bytes(), &createResp, jsonx.V1())) record, ok := createResp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) rule, ok := record["SamplingRule"].(map[string]any) @@ -826,7 +827,7 @@ func TestSamplingRule_UpdateAndDeleteByARN(t *testing.T) { require.Equal(t, http.StatusOK, updRec.Code) var updResp map[string]any - require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp)) + require.NoError(t, json.Unmarshal(updRec.Body.Bytes(), &updResp, jsonx.V1())) updRecord, ok := updResp["SamplingRuleRecord"].(map[string]any) require.True(t, ok) updRule, ok := updRecord["SamplingRule"].(map[string]any) @@ -840,7 +841,7 @@ func TestSamplingRule_UpdateAndDeleteByARN(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var getResp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &getResp, jsonx.V1())) records, ok := getResp["SamplingRuleRecords"].([]any) require.True(t, ok) for _, r := range records { diff --git a/services/xray/handler_sampling_statistics.go b/services/xray/handler_sampling_statistics.go index cd8e7ec60e..099ad14c43 100644 --- a/services/xray/handler_sampling_statistics.go +++ b/services/xray/handler_sampling_statistics.go @@ -2,9 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -23,7 +24,7 @@ type getSamplingStatisticSummariesInput struct { func (h *Handler) handleGetSamplingStatisticSummaries(_ context.Context, body []byte) ([]byte, error) { var in getSamplingStatisticSummariesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -50,7 +51,7 @@ func (h *Handler) handleGetSamplingStatisticSummaries(_ context.Context, body [] return json.Marshal(map[string]any{ "SamplingStatisticSummaries": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } type samplingStatisticsDocumentInput struct { @@ -104,7 +105,7 @@ type unprocessedStatisticsView struct { func (h *Handler) handleGetSamplingTargets(_ context.Context, body []byte) ([]byte, error) { var in getSamplingTargetsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -156,5 +157,5 @@ func (h *Handler) handleGetSamplingTargets(_ context.Context, body []byte) ([]by "UnprocessedStatistics": unprocessedViews, "UnprocessedBoostStatistics": unprocessedBoostViews, "LastRuleModification": lastModTS, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_sampling_statistics_test.go b/services/xray/handler_sampling_statistics_test.go index 589434ba70..34e6e40af8 100644 --- a/services/xray/handler_sampling_statistics_test.go +++ b/services/xray/handler_sampling_statistics_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -26,7 +27,7 @@ func TestGetSamplingTargets_LastRuleModAndTTL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // LastRuleModification should be a timestamp. lastMod, ok := resp["LastRuleModification"].(float64) @@ -65,7 +66,7 @@ func TestGetSamplingStatisticSummaries_AfterPut(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["SamplingStatisticSummaries"].([]any) require.True(t, ok) @@ -92,7 +93,7 @@ func TestGetSamplingTargets_UnprocessedWithErrorCode(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedStatistics"].([]any) require.True(t, ok) @@ -126,7 +127,7 @@ func TestGetSamplingTargets_EmptyClientID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedStatistics"].([]any) require.True(t, ok) @@ -159,7 +160,7 @@ func TestHandler_GetSamplingStatisticSummaries(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["SamplingStatisticSummaries"].([]any) require.True(t, ok) @@ -233,7 +234,7 @@ func TestHandler_GetSamplingTargets(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["SamplingTargetDocuments"].([]any) require.True(t, ok) @@ -260,7 +261,7 @@ func TestHandler_GetSamplingTargets_TargetFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["SamplingTargetDocuments"].([]any) require.True(t, ok) @@ -305,7 +306,7 @@ func TestHandler_GetSamplingStatisticSummaries_Pagination(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "SamplingStatisticSummaries") assert.Contains(t, resp, "NextToken") }) @@ -326,7 +327,7 @@ func TestGetSamplingTargets_LastRuleModification(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) lastMod, ok := resp["LastRuleModification"].(float64) require.True(t, ok, "LastRuleModification must be present") @@ -347,7 +348,7 @@ func TestGetSamplingTargets_ReservoirQuotaTTL(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, ok := resp["SamplingTargetDocuments"].([]any) require.True(t, ok) @@ -417,7 +418,7 @@ func TestGetSamplingTargets_UnprocessedForUnknownRules(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) targets, _ := resp["SamplingTargetDocuments"].([]any) assert.Len(t, targets, tt.wantTargets) @@ -490,7 +491,7 @@ func TestGetSamplingTargets_BoostStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessedBoost, _ := resp["UnprocessedBoostStatistics"].([]any) assert.Len(t, unprocessedBoost, tt.wantUnprocessed) @@ -524,7 +525,7 @@ func TestGetSamplingStatisticSummaries_AccumulationFromTargets(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["SamplingStatisticSummaries"].([]any) require.True(t, ok) @@ -547,7 +548,7 @@ func TestGetSamplingStatisticSummaries_EmptyWithoutStats(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["SamplingStatisticSummaries"].([]any) require.True(t, ok) @@ -573,7 +574,7 @@ func TestGetSamplingStatisticSummaries_AccumulatesAcrossCalls(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["SamplingStatisticSummaries"].([]any) require.Len(t, summaries, 1) diff --git a/services/xray/handler_service_graph.go b/services/xray/handler_service_graph.go index a3f4713d32..ce134da179 100644 --- a/services/xray/handler_service_graph.go +++ b/services/xray/handler_service_graph.go @@ -2,10 +2,11 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -20,7 +21,7 @@ type getServiceGraphInput struct { func (h *Handler) handleGetServiceGraph(_ context.Context, body []byte) ([]byte, error) { var in getServiceGraphInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -49,7 +50,7 @@ func (h *Handler) handleGetServiceGraph(_ context.Context, body []byte) ([]byte, "ContainsOldGroupVersions": false, keyStartTime: in.StartTime, keyEndTime: in.EndTime, - }) + }, jsonx.V1()) } type getTimeSeriesServiceStatisticsInput struct { @@ -66,7 +67,7 @@ type getTimeSeriesServiceStatisticsInput struct { func (h *Handler) handleGetTimeSeriesServiceStatistics(_ context.Context, body []byte) ([]byte, error) { var in getTimeSeriesServiceStatisticsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -104,7 +105,7 @@ func (h *Handler) handleGetTimeSeriesServiceStatistics(_ context.Context, body [ "TimeSeriesServiceStatistics": pg.Data, "ContainsOldGroupVersions": false, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } type getTraceGraphInput struct { @@ -115,7 +116,7 @@ type getTraceGraphInput struct { func (h *Handler) handleGetTraceGraph(_ context.Context, body []byte) ([]byte, error) { var in getTraceGraphInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -135,7 +136,7 @@ func (h *Handler) handleGetTraceGraph(_ context.Context, body []byte) ([]byte, e return json.Marshal(map[string]any{ keyServices: pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } // resolveGroupFilterExpression resolves an optional GroupName/GroupARN (both diff --git a/services/xray/handler_service_graph_test.go b/services/xray/handler_service_graph_test.go index c573e3909a..83827b2486 100644 --- a/services/xray/handler_service_graph_test.go +++ b/services/xray/handler_service_graph_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -9,6 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGetServiceGraph_NonEmpty(t *testing.T) { @@ -33,7 +35,7 @@ func TestGetServiceGraph_NonEmpty(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -63,7 +65,7 @@ func TestGetTimeSeriesServiceStatistics_BucketedData(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stats, ok := resp["TimeSeriesServiceStatistics"].([]any) require.True(t, ok) @@ -99,7 +101,7 @@ func TestGetTraceGraph_ReturnsNodes(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -117,7 +119,7 @@ func TestGetTraceGraph_EmptyForUnknownTraces(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -177,7 +179,7 @@ func TestGetServiceGraph_ContainsOldGroupVersions(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["ContainsOldGroupVersions"] assert.True(t, ok, "ContainsOldGroupVersions must be present in GetServiceGraph response") @@ -231,7 +233,7 @@ func TestHandler_GetServiceGraph_Pagination(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "NextToken") assert.Contains(t, resp, "Services") assert.Contains(t, resp, "StartTime") @@ -279,7 +281,7 @@ func TestHandler_GetTraceGraph_Pagination(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "NextToken") assert.Contains(t, resp, "Services") } @@ -339,7 +341,7 @@ func TestHandler_GetTimeSeriesServiceStatistics_Pagination(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Contains(t, resp, "NextToken") assert.Contains(t, resp, "TimeSeriesServiceStatistics") } @@ -369,7 +371,7 @@ func TestGetServiceGraph_NodesAfterSegments(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -394,7 +396,7 @@ func TestGetServiceGraph_NodeFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["Services"].([]any) require.NotEmpty(t, services) @@ -459,7 +461,7 @@ func TestGetServiceGraph_EmptyOutsideTimeWindow(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["Services"].([]any) assert.Empty(t, services, "service graph must be empty when no segments fall in the time window") @@ -510,7 +512,7 @@ func TestGetTimeSeriesServiceStatistics_ReturnsContainsOldGroupVersions(t *testi require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, ok := resp["ContainsOldGroupVersions"] assert.True(t, ok, "ContainsOldGroupVersions must be present in response") @@ -542,7 +544,7 @@ func TestGetTimeSeriesServiceStatistics_BucketedStatsAfterSegments(t *testing.T) require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) stats, ok := resp["TimeSeriesServiceStatistics"].([]any) require.True(t, ok) @@ -575,7 +577,7 @@ func TestGetTraceGraph_ReturnsNodesForTraceIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -601,7 +603,7 @@ func TestGetTraceGraph_EmptyForUnknownTrace(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, _ := resp["Services"].([]any) assert.Empty(t, services) @@ -634,7 +636,7 @@ func TestGetServiceGraph_EdgeStatisticsAndDirection(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) diff --git a/services/xray/handler_tags.go b/services/xray/handler_tags.go index 03d73f34c6..ab79f19809 100644 --- a/services/xray/handler_tags.go +++ b/services/xray/handler_tags.go @@ -2,11 +2,12 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "strings" "unicode/utf8" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -18,7 +19,7 @@ type listTagsForResourceInput struct { func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]byte, error) { var in listTagsForResourceInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -41,7 +42,7 @@ func (h *Handler) handleListTagsForResource(_ context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "Tags": pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } // tagWire mirrors types.Tag (xray@v1.39.4): a {Key, Value} object, one per @@ -61,7 +62,7 @@ type tagResourceInput struct { func (h *Handler) handleTagResource(_ context.Context, body []byte) ([]byte, error) { var in tagResourceInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -78,7 +79,7 @@ func (h *Handler) handleTagResource(_ context.Context, body []byte) ([]byte, err return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type untagResourceInput struct { @@ -89,7 +90,7 @@ type untagResourceInput struct { func (h *Handler) handleUntagResource(_ context.Context, body []byte) ([]byte, error) { var in untagResourceInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -102,7 +103,7 @@ func (h *Handler) handleUntagResource(_ context.Context, body []byte) ([]byte, e return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } const ( diff --git a/services/xray/handler_tags_test.go b/services/xray/handler_tags_test.go index 03e7ed2e15..23b0a1b12e 100644 --- a/services/xray/handler_tags_test.go +++ b/services/xray/handler_tags_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "strconv" "testing" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -23,7 +24,7 @@ func createTaggableGroup(t *testing.T, h *xray.Handler, name string) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) group, ok := resp["Group"].(map[string]any) require.True(t, ok) @@ -83,7 +84,7 @@ func TestHandler_ListTagsForResource_Pagination(t *testing.T) { if tt.wantStatus == http.StatusOK { var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["Tags"].([]any) assert.Len(t, tags, tt.wantTags) assert.Contains(t, resp, "NextToken") @@ -111,7 +112,7 @@ func TestHandler_ListTagsForResource_WithTags(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) tagsList, _ := resp["Tags"].([]any) assert.Len(t, tagsList, len(tags)) @@ -173,7 +174,7 @@ func TestTags_RoundTrip(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags, ok := resp["Tags"].([]any) require.True(t, ok) @@ -204,7 +205,7 @@ func TestTags_UntagResource(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &resp, jsonx.V1())) tags, _ := resp["Tags"].([]any) assert.Len(t, tags, 1, "only key2 should remain after untagging key1") @@ -222,7 +223,7 @@ func TestTags_TagResource_UnknownResourceReturns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -238,7 +239,7 @@ func TestTags_UntagResource_UnknownResourceReturns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) } @@ -260,6 +261,6 @@ func TestTags_TagResource_ExceedsMaxTagsReturns400(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "TooManyTagsException", resp["__type"]) } diff --git a/services/xray/handler_telemetry.go b/services/xray/handler_telemetry.go index 2f95403c4c..82469192f4 100644 --- a/services/xray/handler_telemetry.go +++ b/services/xray/handler_telemetry.go @@ -2,8 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type telemetryRecordInput struct { @@ -21,7 +23,7 @@ type putTelemetryRecordsInput struct { func (h *Handler) handlePutTelemetryRecords(_ context.Context, body []byte) ([]byte, error) { var in putTelemetryRecordsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -47,5 +49,5 @@ func (h *Handler) handlePutTelemetryRecords(_ context.Context, body []byte) ([]b h.Backend.PutTelemetryRecords(records) } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } diff --git a/services/xray/handler_telemetry_test.go b/services/xray/handler_telemetry_test.go index 6e069697bb..d3380b9ab2 100644 --- a/services/xray/handler_telemetry_test.go +++ b/services/xray/handler_telemetry_test.go @@ -1,13 +1,15 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutTelemetryRecords(t *testing.T) { @@ -37,7 +39,7 @@ func TestPutTelemetryRecords_Accepted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Response should be an empty JSON object. assert.Empty(t, resp) } @@ -93,7 +95,7 @@ func TestPutTelemetryRecords_AllFieldsAccepted(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Empty(t, resp, "response must be an empty JSON object") }) } diff --git a/services/xray/handler_test.go b/services/xray/handler_test.go index 8f56b43bec..d6616a08cc 100644 --- a/services/xray/handler_test.go +++ b/services/xray/handler_test.go @@ -2,7 +2,7 @@ package xray_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -218,7 +219,7 @@ func TestHandler_ExtractResource(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyBytes, err := json.Marshal(tt.body) + bodyBytes, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/CreateGroup", bytes.NewReader(bodyBytes)) @@ -275,7 +276,7 @@ func TestXRay_Handler_Reset(t *testing.T) { var out struct { Groups []any `json:"Groups"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &out, jsonx.V1())) assert.Len(t, out.Groups, tt.wantAfter) }) } diff --git a/services/xray/handler_trace_retrieval.go b/services/xray/handler_trace_retrieval.go index 513b1f6cdc..f622287d6a 100644 --- a/services/xray/handler_trace_retrieval.go +++ b/services/xray/handler_trace_retrieval.go @@ -2,10 +2,11 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -35,7 +36,7 @@ func buildTraceView(t *Trace) map[string]any { for _, rawSeg := range t.Segments { var doc segmentDoc - if err := json.Unmarshal([]byte(rawSeg), &doc); err == nil { + if err := json.Unmarshal([]byte(rawSeg), &doc, jsonx.V1()); err == nil { spans = append(spans, map[string]any{ "Document": rawSeg, "Id": doc.ID, @@ -66,7 +67,7 @@ func buildTraceView(t *Trace) map[string]any { func (h *Handler) handleListRetrievedTraces(_ context.Context, body []byte) ([]byte, error) { var in listRetrievedTracesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -101,7 +102,7 @@ func (h *Handler) handleListRetrievedTraces(_ context.Context, body []byte) ([]b resp[keyNextToken] = pg.Next } - return json.Marshal(resp) + return json.Marshal(resp, jsonx.V1()) } type startTraceRetrievalInput struct { @@ -113,7 +114,7 @@ type startTraceRetrievalInput struct { func (h *Handler) handleStartTraceRetrieval(_ context.Context, body []byte) ([]byte, error) { var in startTraceRetrievalInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -134,7 +135,7 @@ func (h *Handler) handleStartTraceRetrieval(_ context.Context, body []byte) ([]b return json.Marshal(map[string]any{ "RetrievalToken": token, - }) + }, jsonx.V1()) } const ( @@ -148,7 +149,7 @@ type cancelTraceRetrievalInput struct { func (h *Handler) handleCancelTraceRetrieval(_ context.Context, body []byte) ([]byte, error) { var in cancelTraceRetrievalInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -161,7 +162,7 @@ func (h *Handler) handleCancelTraceRetrieval(_ context.Context, body []byte) ([] return nil, err } - return json.Marshal(map[string]any{}) + return json.Marshal(map[string]any{}, jsonx.V1()) } type getRetrievedTracesGraphInput struct { @@ -172,7 +173,7 @@ type getRetrievedTracesGraphInput struct { func (h *Handler) handleGetRetrievedTracesGraph(_ context.Context, body []byte) ([]byte, error) { var in getRetrievedTracesGraphInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -196,5 +197,5 @@ func (h *Handler) handleGetRetrievedTracesGraph(_ context.Context, body []byte) "RetrievalStatus": status, keyServices: pg.Data, keyNextToken: pg.Next, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_trace_retrieval_test.go b/services/xray/handler_trace_retrieval_test.go index b3e2101538..7d2ccc364a 100644 --- a/services/xray/handler_trace_retrieval_test.go +++ b/services/xray/handler_trace_retrieval_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -31,7 +32,7 @@ func TestListRetrievedTraces_IncludesSegments(t *testing.T) { "start_time": 1700000000.0, "end_time": 1700000001.5, } - segJSON, err := json.Marshal(seg) + segJSON, err := json.Marshal(seg, jsonx.V1()) require.NoError(t, err) unprocessed := b.PutTraceSegments([]string{string(segJSON)}) @@ -46,7 +47,7 @@ func TestListRetrievedTraces_IncludesSegments(t *testing.T) { require.Equal(t, 200, startResp.Code) var startResult map[string]any - require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startResult)) + require.NoError(t, json.Unmarshal(startResp.Body.Bytes(), &startResult, jsonx.V1())) token, ok := startResult["RetrievalToken"].(string) require.True(t, ok, "expected RetrievalToken in response") @@ -55,7 +56,7 @@ func TestListRetrievedTraces_IncludesSegments(t *testing.T) { require.Equal(t, 200, listResp.Code) var listResult map[string]any - require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listResult)) + require.NoError(t, json.Unmarshal(listResp.Body.Bytes(), &listResult, jsonx.V1())) traces, ok := listResult["Traces"].([]any) require.True(t, ok, "expected Traces array in response") @@ -90,7 +91,7 @@ func startTestRetrieval(t *testing.T, h *xray.Handler) string { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) token, ok := resp["RetrievalToken"].(string) require.True(t, ok) @@ -130,7 +131,7 @@ func TestHandler_CancelTraceRetrieval(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }) } @@ -148,7 +149,7 @@ func TestHandler_GetRetrievedTracesGraph(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "COMPLETE", resp["RetrievalStatus"]) @@ -173,7 +174,7 @@ func TestHandler_GetRetrievedTracesGraph(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "ResourceNotFoundException", resp["__type"]) }) } @@ -204,7 +205,7 @@ func TestHandler_GetRetrievedTracesGraph_ReflectsRetrievedTraces(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) token, _ := startResp["RetrievalToken"].(string) require.NotEmpty(t, token) @@ -212,7 +213,7 @@ func TestHandler_GetRetrievedTracesGraph_ReflectsRetrievedTraces(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) services, ok := resp["Services"].([]any) require.True(t, ok) @@ -241,7 +242,7 @@ func TestTraceRetrieval_StartAndList(t *testing.T) { require.Equal(t, http.StatusOK, startRec.Code) var startResp map[string]any - require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp)) + require.NoError(t, json.Unmarshal(startRec.Body.Bytes(), &startResp, jsonx.V1())) token, ok := startResp["RetrievalToken"].(string) require.True(t, ok) @@ -253,7 +254,7 @@ func TestTraceRetrieval_StartAndList(t *testing.T) { require.Equal(t, http.StatusOK, listRec.Code) var listResp map[string]any - require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp)) + require.NoError(t, json.Unmarshal(listRec.Body.Bytes(), &listResp, jsonx.V1())) assert.NotEmpty(t, listResp["RetrievalStatus"]) } diff --git a/services/xray/handler_trace_segment_destination.go b/services/xray/handler_trace_segment_destination.go index c54a3456cd..41d4befae4 100644 --- a/services/xray/handler_trace_segment_destination.go +++ b/services/xray/handler_trace_segment_destination.go @@ -2,8 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func (h *Handler) handleGetTraceSegmentDestination(_ context.Context, _ []byte) ([]byte, error) { @@ -12,7 +14,7 @@ func (h *Handler) handleGetTraceSegmentDestination(_ context.Context, _ []byte) return json.Marshal(map[string]any{ "Destination": dest, "Status": statusActive, - }) + }, jsonx.V1()) } type updateTraceSegmentDestinationInput struct { @@ -22,7 +24,7 @@ type updateTraceSegmentDestinationInput struct { func (h *Handler) handleUpdateTraceSegmentDestination(_ context.Context, body []byte) ([]byte, error) { var in updateTraceSegmentDestinationInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -44,5 +46,5 @@ func (h *Handler) handleUpdateTraceSegmentDestination(_ context.Context, body [] return json.Marshal(map[string]any{ "Destination": dest, "Status": statusActive, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_trace_segments.go b/services/xray/handler_trace_segments.go index 946c9500ad..16188b9310 100644 --- a/services/xray/handler_trace_segments.go +++ b/services/xray/handler_trace_segments.go @@ -2,8 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type putTraceSegmentsInput struct { @@ -13,7 +15,7 @@ type putTraceSegmentsInput struct { func (h *Handler) handlePutTraceSegments(_ context.Context, body []byte) ([]byte, error) { var in putTraceSegmentsInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -45,5 +47,5 @@ func (h *Handler) handlePutTraceSegments(_ context.Context, body []byte) ([]byte return json.Marshal(map[string]any{ "UnprocessedTraceSegments": out, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_trace_segments_test.go b/services/xray/handler_trace_segments_test.go index 5ded66f0be..ef153ad517 100644 --- a/services/xray/handler_trace_segments_test.go +++ b/services/xray/handler_trace_segments_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "strings" @@ -10,6 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestHandler_PutTraceSegments(t *testing.T) { @@ -55,7 +57,7 @@ func TestHandler_PutTraceSegments_Unprocessed(t *testing.T) { assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedTraceSegments"].([]any) require.True(t, ok) @@ -82,7 +84,7 @@ func TestPutAndGetTraceSummaries_Populated(t *testing.T) { require.Equal(t, http.StatusOK, getRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(getRec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -124,7 +126,7 @@ func TestPutTraceSegments_MalformedJSON(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code, "malformed segments should not crash the handler") var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedTraceSegments"].([]any) require.True(t, ok) @@ -145,7 +147,7 @@ func TestPutTraceSegments_MissingTraceID(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedTraceSegments"].([]any) require.True(t, ok) @@ -292,7 +294,7 @@ func TestHandler_PutTraceSegments_ExactLimitRespondsWithUnprocessedField(t *test assert.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) _, hasField := resp["UnprocessedTraceSegments"] assert.True(t, hasField) } @@ -361,7 +363,7 @@ func TestPutTraceSegments_ParsesSegmentFields(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, _ := resp["UnprocessedTraceSegments"].([]any) if tt.wantParsed { @@ -400,7 +402,7 @@ func TestPutTraceSegments_IndexesSegmentsForDownstreamAPIs(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var sumResp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &sumResp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &sumResp, jsonx.V1())) summaries, ok := sumResp["TraceSummaries"].([]any) require.True(t, ok) @@ -411,7 +413,7 @@ func TestPutTraceSegments_IndexesSegmentsForDownstreamAPIs(t *testing.T) { require.Equal(t, http.StatusOK, batchRec.Code) var batchResp map[string]any - require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp)) + require.NoError(t, json.Unmarshal(batchRec.Body.Bytes(), &batchResp, jsonx.V1())) traces, ok := batchResp["Traces"].([]any) require.True(t, ok) @@ -437,7 +439,7 @@ func TestPutTraceSegments_MultipleTracesIndexedSeparately(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var sumResp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &sumResp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &sumResp, jsonx.V1())) summaries, _ := sumResp["TraceSummaries"].([]any) assert.Len(t, summaries, 3, "three separate traces must be indexed separately") diff --git a/services/xray/handler_traces.go b/services/xray/handler_traces.go index 5306a88cf0..e1dde65996 100644 --- a/services/xray/handler_traces.go +++ b/services/xray/handler_traces.go @@ -2,10 +2,11 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "fmt" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/page" ) @@ -222,7 +223,7 @@ func validateSamplingStrategy(ss *samplingStrategyInput) error { func (h *Handler) handleGetTraceSummaries(_ context.Context, body []byte) ([]byte, error) { var in getTraceSummariesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -280,7 +281,7 @@ func (h *Handler) handleGetTraceSummaries(_ context.Context, body []byte) ([]byt // per-TraceSummary field. "ApproximateTime": float64(time.Now().Unix()), keyNextToken: pg.Next, - }) + }, jsonx.V1()) } type batchGetTracesInput struct { @@ -302,7 +303,7 @@ type traceOutput struct { func (h *Handler) handleBatchGetTraces(_ context.Context, body []byte) ([]byte, error) { var in batchGetTracesInput if len(body) > 0 { - if err := json.Unmarshal(body, &in); err != nil { + if err := json.Unmarshal(body, &in, jsonx.V1()); err != nil { return nil, err } } @@ -341,7 +342,7 @@ func (h *Handler) handleBatchGetTraces(_ context.Context, body []byte) ([]byte, ID string `json:"id"` } - if err := json.Unmarshal([]byte(rawDoc), &hdr); err == nil { + if err := json.Unmarshal([]byte(rawDoc), &hdr, jsonx.V1()); err == nil { segViews = append(segViews, batchSegmentOutput{ ID: hdr.ID, Document: rawDoc, @@ -360,5 +361,5 @@ func (h *Handler) handleBatchGetTraces(_ context.Context, body []byte) ([]byte, return json.Marshal(map[string]any{ "Traces": traces, "UnprocessedTraceIds": unprocessed, - }) + }, jsonx.V1()) } diff --git a/services/xray/handler_traces_test.go b/services/xray/handler_traces_test.go index f4524ad238..ad4f66d9a0 100644 --- a/services/xray/handler_traces_test.go +++ b/services/xray/handler_traces_test.go @@ -1,7 +1,7 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -73,7 +74,7 @@ func TestHandler_BatchGetTraces(t *testing.T) { assert.Equal(t, tt.wantStatus, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) if tt.wantTraces > 0 { traces, ok := resp["Traces"].([]any) @@ -110,7 +111,7 @@ func TestBatchGetTraces_SegmentShape(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) traces, ok := resp["Traces"].([]any) require.True(t, ok) @@ -163,7 +164,7 @@ func TestGetTraceSummaries_FaultFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -197,7 +198,7 @@ func TestGetTraceSummaries_TimeRangeType(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) // Should still return the trace — TimeRangeType is accepted without error. summaries, ok := resp["TraceSummaries"].([]any) @@ -225,7 +226,7 @@ func TestTraceSummary_FaultAndErrorPropagation(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -270,7 +271,7 @@ func TestGetTraceSummaries_ThrottleFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -337,7 +338,7 @@ func TestGetTraceSummariesTimeFilter(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -366,7 +367,7 @@ func TestGetTraceSummaries_TimeWindowExclusion(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -393,7 +394,7 @@ func TestTraceSummary_UsersFromAnnotations(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -429,7 +430,7 @@ func TestTraceSummary_OmitsForecastStatistics(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) summaries, ok := resp["TraceSummaries"].([]any) require.True(t, ok) @@ -453,7 +454,7 @@ func TestBatchGetTraces_UnprocessedForMissingIDs(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) unprocessed, ok := resp["UnprocessedTraceIds"].([]any) require.True(t, ok) @@ -545,7 +546,7 @@ func TestHandler_GetTraceSummaries_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec1.Code) var resp1 map[string]any - require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1)) + require.NoError(t, json.Unmarshal(rec1.Body.Bytes(), &resp1, jsonx.V1())) summaries1, _ := resp1["TraceSummaries"].([]any) assert.Len(t, summaries1, defaultPageSize) @@ -556,7 +557,7 @@ func TestHandler_GetTraceSummaries_Pagination(t *testing.T) { require.Equal(t, http.StatusOK, rec2.Code) var resp2 map[string]any - require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2)) + require.NoError(t, json.Unmarshal(rec2.Body.Bytes(), &resp2, jsonx.V1())) summaries2, _ := resp2["TraceSummaries"].([]any) assert.Len(t, summaries2, total-defaultPageSize) @@ -581,7 +582,7 @@ func TestGetTraceSummaries_DurationFromSegmentTimes(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -644,7 +645,7 @@ func TestGetTraceSummaries_BooleanFlagFields(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -710,7 +711,7 @@ func TestGetTraceSummaries_HTTPFieldsPopulated(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -749,7 +750,7 @@ func TestGetTraceSummaries_ServiceIDsFromSegments(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -781,7 +782,7 @@ func TestGetTraceSummaries_EntryPointFromRootSegment(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -812,7 +813,7 @@ func TestGetTraceSummaries_IsPartialWithoutRootSegment(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -839,7 +840,7 @@ func TestGetTraceSummaries_TracesProcessedCount(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) count, ok := resp["TracesProcessedCount"].(float64) require.True(t, ok) @@ -928,7 +929,7 @@ func TestGetTraceSummaries_FilterExpressions(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) assert.Len(t, summaries, tt.wantCount, "filter=%q wantCount=%d", tt.filter, tt.wantCount) @@ -961,7 +962,7 @@ func TestGetTraceSummaries_OmitsForecastStatistics(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -996,7 +997,7 @@ func TestGetTraceSummaries_AnnotationFilter(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -1026,7 +1027,7 @@ func TestGetTraceSummaries_ResponseTimeFilter(t *testing.T) { require.Equal(t, http.StatusOK, sumRec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(sumRec.Body.Bytes(), &resp, jsonx.V1())) summaries, _ := resp["TraceSummaries"].([]any) require.Len(t, summaries, 1) @@ -1076,7 +1077,7 @@ func TestBatchGetTraces_UnprocessedForMissingTraces(t *testing.T) { require.Equal(t, http.StatusOK, rec.Code) var resp map[string]any - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) traces, _ := resp["Traces"].([]any) assert.Empty(t, traces, "missing traces produce no Traces entries") diff --git a/services/xray/helpers_test.go b/services/xray/helpers_test.go index 7305063dfa..632e5faf76 100644 --- a/services/xray/helpers_test.go +++ b/services/xray/helpers_test.go @@ -2,7 +2,7 @@ package xray_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -12,6 +12,7 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -34,7 +35,7 @@ func buildFaultSegmentJSON(t *testing.T, traceID, name string, fault bool) strin "fault": fault, } - data, err := json.Marshal(seg) + data, err := json.Marshal(seg, jsonx.V1()) require.NoError(t, err) return string(data) @@ -61,7 +62,7 @@ func doXrayRequest(t *testing.T, h *xray.Handler, path string, body any) *httpte if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -126,7 +127,7 @@ func segJSONWithHTTP(traceID, segID, name string, startTime, endTime float64, st // segFmt formats a float64 timestamp as a JSON value string (no quotes). func segFmt(ts float64) string { - out, _ := json.Marshal(ts) + out, _ := json.Marshal(ts, jsonx.V1()) return string(out) } diff --git a/services/xray/multi_region_test.go b/services/xray/multi_region_test.go index 60643394d9..46b552876b 100644 --- a/services/xray/multi_region_test.go +++ b/services/xray/multi_region_test.go @@ -2,7 +2,7 @@ package xray_test import ( "context" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "strings" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/services/xray" ) @@ -41,7 +42,7 @@ func decode(t *testing.T, body string) map[string]any { out := map[string]any{} if body != "" { - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) } return out diff --git a/services/xray/persistence.go b/services/xray/persistence.go index efc499678c..72053117d9 100644 --- a/services/xray/persistence.go +++ b/services/xray/persistence.go @@ -2,9 +2,10 @@ package xray import ( "context" - "encoding/json" + "encoding/json/v2" "time" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/persistence" ) @@ -85,7 +86,7 @@ func (b *InMemoryBackend) Snapshot(ctx context.Context) []byte { ResourceTags: b.resourceTags, } - data, err := json.Marshal(snap) + data, err := json.Marshal(snap, jsonx.V1()) if err != nil { logger.Load(ctx).WarnContext(ctx, "xray: failed to marshal snapshot", "error", err) @@ -182,7 +183,7 @@ func (b *InMemoryBackend) Restore(ctx context.Context, data []byte) error { for _, t := range b.traces.All() { for _, rawSeg := range t.Segments { var seg Segment - if err := json.Unmarshal([]byte(rawSeg), &seg); err == nil { + if err := json.Unmarshal([]byte(rawSeg), &seg, jsonx.V1()); err == nil { seg.Document = rawSeg b.parsedSegments.Put(&seg) } diff --git a/services/xray/policy_lockout.go b/services/xray/policy_lockout.go index 8df55a7ffc..1b0bb9f231 100644 --- a/services/xray/policy_lockout.go +++ b/services/xray/policy_lockout.go @@ -1,18 +1,21 @@ package xray import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "path" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) type lockoutStatement struct { - Effect string `json:"Effect"` - Principal json.RawMessage `json:"Principal"` - Action json.RawMessage `json:"Action"` - Condition json.RawMessage `json:"Condition"` - NotPrincipal json.RawMessage `json:"NotPrincipal"` - NotAction json.RawMessage `json:"NotAction"` + Effect string `json:"Effect"` + Principal jsontext.Value `json:"Principal"` + Action jsontext.Value `json:"Action"` + Condition jsontext.Value `json:"Condition"` + NotPrincipal jsontext.Value `json:"NotPrincipal"` + NotAction jsontext.Value `json:"NotAction"` } // policyLocksOutCaller reports whether policyDocument has an unconditional Deny of xray:PutResourcePolicy that @@ -23,16 +26,16 @@ func policyLocksOutCaller(policyDocument, callerARN string) bool { } var doc struct { - Statement json.RawMessage `json:"Statement"` + Statement jsontext.Value `json:"Statement"` } - if json.Unmarshal([]byte(policyDocument), &doc) != nil { + if json.Unmarshal([]byte(policyDocument), &doc, jsonx.V1()) != nil { return false } var stmts []lockoutStatement - if json.Unmarshal(doc.Statement, &stmts) != nil { + if json.Unmarshal(doc.Statement, &stmts, jsonx.V1()) != nil { var one lockoutStatement - if json.Unmarshal(doc.Statement, &one) != nil { + if json.Unmarshal(doc.Statement, &one, jsonx.V1()) != nil { return false } @@ -53,19 +56,19 @@ func policyLocksOutCaller(policyDocument, callerARN string) bool { return false } -func stringList(raw json.RawMessage) []string { +func stringList(raw jsontext.Value) []string { var one string - if json.Unmarshal(raw, &one) == nil { + if json.Unmarshal(raw, &one, jsonx.V1()) == nil { return []string{one} } var many []string - _ = json.Unmarshal(raw, &many) + _ = json.Unmarshal(raw, &many, jsonx.V1()) return many } -func matchesAny(raw json.RawMessage, target string, fold bool) bool { +func matchesAny(raw jsontext.Value, target string, fold bool) bool { for _, p := range stringList(raw) { if fold { p = strings.ToLower(p) @@ -79,12 +82,12 @@ func matchesAny(raw json.RawMessage, target string, fold bool) bool { return false } -func principalMatches(raw json.RawMessage, callerARN string) bool { +func principalMatches(raw jsontext.Value, callerARN string) bool { var wrapper struct { - AWS json.RawMessage `json:"AWS"` + AWS jsontext.Value `json:"AWS"` } - if json.Unmarshal(raw, &wrapper) == nil && len(wrapper.AWS) > 0 { + if json.Unmarshal(raw, &wrapper, jsonx.V1()) == nil && len(wrapper.AWS) > 0 { raw = wrapper.AWS } diff --git a/services/xray/policy_lockout_test.go b/services/xray/policy_lockout_test.go index 96e9847274..fb5c7e4552 100644 --- a/services/xray/policy_lockout_test.go +++ b/services/xray/policy_lockout_test.go @@ -2,7 +2,7 @@ package xray_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "net/http/httptest" "testing" @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/awsmeta" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestPutResourcePolicy_LockoutPrevention(t *testing.T) { @@ -70,7 +71,7 @@ func TestPutResourcePolicy_LockoutPrevention(t *testing.T) { h := newTestHandler(t) payload, err := json.Marshal(map[string]any{ "PolicyName": "p", "PolicyDocument": tt.doc, "BypassPolicyLockoutCheck": tt.bypass, - }) + }, jsonx.V1()) require.NoError(t, err) req := httptest.NewRequest(http.MethodPost, "/PutResourcePolicy", bytes.NewReader(payload)) @@ -89,7 +90,7 @@ func TestPutResourcePolicy_LockoutPrevention(t *testing.T) { if tt.wantType != "" { var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, tt.wantType, resp["__type"]) } }) diff --git a/services/xray/resource_policies.go b/services/xray/resource_policies.go index 232aa42e6d..7d48b795a4 100644 --- a/services/xray/resource_policies.go +++ b/services/xray/resource_policies.go @@ -1,11 +1,14 @@ package xray import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "sort" "strconv" "time" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func cloneResourcePolicy(p *ResourcePolicy) *ResourcePolicy { @@ -21,8 +24,8 @@ func cloneResourcePolicy(p *ResourcePolicy) *ResourcePolicy { // Returns ErrMalformedPolicyDocument if policyDocument is not valid JSON. func (b *InMemoryBackend) PutResourcePolicy(policyName, policyDocument, revisionID string) (*ResourcePolicy, error) { // Validate JSON. - var js json.RawMessage - if err := json.Unmarshal([]byte(policyDocument), &js); err != nil { + var js jsontext.Value + if err := json.Unmarshal([]byte(policyDocument), &js, jsonx.V1()); err != nil { return nil, fmt.Errorf("%w: policy document is not valid JSON: %w", ErrMalformedPolicyDocument, err) } diff --git a/services/xray/service_graph_histogram_test.go b/services/xray/service_graph_histogram_test.go index ae416b14f4..90c231b82e 100644 --- a/services/xray/service_graph_histogram_test.go +++ b/services/xray/service_graph_histogram_test.go @@ -1,13 +1,15 @@ package xray_test import ( - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestGetServiceGraph_Histograms(t *testing.T) { @@ -39,7 +41,7 @@ func TestGetServiceGraph_Histograms(t *testing.T) { } `json:"Edges"` } `json:"Services"` } - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) byName := map[string]int{} for i, s := range resp.Services { diff --git a/services/xray/trace_segments.go b/services/xray/trace_segments.go index cd8f4f229a..9fa5ffa087 100644 --- a/services/xray/trace_segments.go +++ b/services/xray/trace_segments.go @@ -1,11 +1,13 @@ package xray import ( - "encoding/json" + "encoding/json/v2" "math" "time" "github.com/google/uuid" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // PutTraceSegments stores raw segment JSON strings, parses them into typed Segment structs, @@ -19,7 +21,7 @@ func (b *InMemoryBackend) PutTraceSegments(segments []string) []string { for _, seg := range segments { var hdr segmentHeader - if err := json.Unmarshal([]byte(seg), &hdr); err != nil || hdr.TraceID == "" { + if err := json.Unmarshal([]byte(seg), &hdr, jsonx.V1()); err != nil || hdr.TraceID == "" { unprocessed = append(unprocessed, uuid.NewString()) continue @@ -46,7 +48,7 @@ func (b *InMemoryBackend) PutTraceSegments(segments []string) []string { // Parse into typed Segment struct and index it. var parsed Segment - if err := json.Unmarshal([]byte(seg), &parsed); err == nil { + if err := json.Unmarshal([]byte(seg), &parsed, jsonx.V1()); err == nil { parsed.Document = seg b.parsedSegments.Put(&parsed) diff --git a/services/xray/whitebox_test.go b/services/xray/whitebox_test.go index 468ab4c42c..7c2b89f564 100644 --- a/services/xray/whitebox_test.go +++ b/services/xray/whitebox_test.go @@ -2,7 +2,7 @@ package xray import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "net/http" "net/http/httptest" @@ -11,12 +11,14 @@ import ( "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func doWhiteboxRequest(t *testing.T, h *Handler, path string, body any) *httptest.ResponseRecorder { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) e := echo.New() @@ -53,6 +55,6 @@ func TestCreateSamplingRule_RuleLimitExceeded(t *testing.T) { require.Equal(t, http.StatusBadRequest, rec.Code) var resp map[string]string - require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp)) + require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &resp, jsonx.V1())) assert.Equal(t, "RuleLimitExceededException", resp["__type"]) } diff --git a/test/guards/hardcoded_arn_partition_guard_test.go b/test/guards/hardcoded_arn_partition_guard_test.go index acde1927e4..f3e23c5995 100644 --- a/test/guards/hardcoded_arn_partition_guard_test.go +++ b/test/guards/hardcoded_arn_partition_guard_test.go @@ -1,7 +1,7 @@ package guards_test import ( - "encoding/json" + "encoding/json/v2" "os" "path/filepath" "sort" @@ -9,6 +9,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const hardcodedARNAllowlistPath = "test/guards/testdata/hardcoded_arn_allowlist.json" @@ -23,7 +25,7 @@ func TestNoNewHardcodedAWSPartitionARNs(t *testing.T) { require.NoError(t, err) var allow map[string]int - require.NoError(t, json.Unmarshal(raw, &allow)) + require.NoError(t, json.Unmarshal(raw, &allow, jsonx.V1())) got := countHardcodedARNs(t) diff --git a/test/guards/jsonv1_import_guard_test.go b/test/guards/jsonv1_import_guard_test.go new file mode 100644 index 0000000000..59b01b3ddb --- /dev/null +++ b/test/guards/jsonv1_import_guard_test.go @@ -0,0 +1,110 @@ +package guards_test + +import ( + "go/parser" + "go/token" + "io/fs" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const jsonV1Path = "encoding/json" + +// importsJSONV1 reports whether src imports encoding/json (v1); string +// literals containing the path do not count. +func importsJSONV1(name string, src any) (bool, error) { + f, err := parser.ParseFile(token.NewFileSet(), name, src, parser.ImportsOnly) + if err != nil { + return false, err + } + + for _, imp := range f.Imports { + if p, uerr := strconv.Unquote(imp.Path.Value); uerr == nil && p == jsonV1Path { + return true, nil + } + } + + return false, nil +} + +func TestImportsJSONV1(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + src string + want bool + }{ + {name: "single", src: "package p\nimport \"encoding/json\"\n", want: true}, + {name: "grouped", src: "package p\nimport (\n\t\"fmt\"\n\t\"encoding/json\"\n)\n", want: true}, + {name: "aliased", src: "package p\nimport j \"encoding/json\"\n", want: true}, + {name: "blank", src: "package p\nimport _ \"encoding/json\"\n", want: true}, + {name: "v2", src: "package p\nimport \"encoding/json/v2\"\n", want: false}, + {name: "jsontext", src: "package p\nimport \"encoding/json/jsontext\"\n", want: false}, + {name: "raw string", src: "package p\nconst s = `import \"encoding/json\"`\n", want: false}, + {name: "comment", src: "package p\n// import \"encoding/json\"\n", want: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := importsJSONV1("x.go", tt.src) + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} + +// TestNoEncodingJSONV1Import forbids encoding/json outside pkgs/jsonx, which +// owns the v1 option set; everything else uses encoding/json/v2 and jsontext. +func TestNoEncodingJSONV1Import(t *testing.T) { + t.Parallel() + + var offenders []string + + err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + switch { + case path == filepath.Join("pkgs", "jsonx"), + d.Name() == "testdata", d.Name() == "node_modules", + path != "." && strings.HasPrefix(d.Name(), "."): + return filepath.SkipDir + } + + return nil + } + + if !strings.HasSuffix(path, ".go") { + return nil + } + + src, readErr := os.ReadFile(path) + if readErr != nil { + return readErr + } + + bad, parseErr := importsJSONV1(path, src) + if parseErr != nil { + return nil //nolint:nilerr // unparsable files are the compiler's concern + } + + if bad { + offenders = append(offenders, path) + } + + return nil + }) + require.NoError(t, err) + assert.Empty(t, offenders, "import encoding/json/v2 (+ jsontext) and pass jsonx.V1() instead of encoding/json") +} diff --git a/test/guards/sdk_source_test.go b/test/guards/sdk_source_test.go index e7303d86e3..5b73b1b763 100644 --- a/test/guards/sdk_source_test.go +++ b/test/guards/sdk_source_test.go @@ -2,7 +2,8 @@ package guards_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "os" @@ -15,6 +16,8 @@ import ( "testing" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -80,16 +83,16 @@ func downloadSDKDirs(mods []sdkModule) (map[string]string, error) { out, runErr := cmd.Output() dirs := map[string]string{} - dec := json.NewDecoder(bytes.NewReader(out)) + dec := jsontext.NewDecoder(bytes.NewReader(out)) - for dec.More() { + for dec.PeekKind() != 0 { var r struct { Path string `json:"Path"` Version string `json:"Version"` Dir string `json:"Dir"` Error string `json:"Error"` } - if err := dec.Decode(&r); err != nil { + if err := json.UnmarshalDecode(dec, &r, jsonx.V1()); err != nil { return nil, err } diff --git a/test/integration/acm_test.go b/test/integration/acm_test.go index b66b887248..8236b85b7b 100644 --- a/test/integration/acm_test.go +++ b/test/integration/acm_test.go @@ -8,7 +8,8 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/base64" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "encoding/pem" "io" "math/big" @@ -20,13 +21,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func acmPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, @@ -57,7 +59,7 @@ func acmReadJSON(t *testing.T, resp *http.Response) map[string]any { defer resp.Body.Close() var m map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &m, jsonx.V1())) return m } @@ -218,7 +220,7 @@ func TestIntegration_ACM_ImportCertificate(t *testing.T) { importedARN := struct { CertificateArn string `json:"CertificateArn"` }{} - require.NoError(t, json.Unmarshal([]byte(importBody), &importedARN)) + require.NoError(t, json.Unmarshal([]byte(importBody), &importedARN, jsonx.V1())) // Describe the imported cert descImportedResp := acmPost(t, "DescribeCertificate", map[string]any{"CertificateArn": importedARN.CertificateArn}) diff --git a/test/integration/apigateway_test.go b/test/integration/apigateway_test.go index e3874a005a..f79703523c 100644 --- a/test/integration/apigateway_test.go +++ b/test/integration/apigateway_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +11,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func apigwPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) @@ -46,7 +48,7 @@ func apigwReadJSON(t *testing.T, resp *http.Response) map[string]any { defer resp.Body.Close() var m map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&m)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &m, jsonx.V1())) return m } diff --git a/test/integration/appsync_test.go b/test/integration/appsync_test.go index 108c515adb..f3592ec079 100644 --- a/test/integration/appsync_test.go +++ b/test/integration/appsync_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -255,7 +256,7 @@ func executeGraphQL( body["variables"] = variables } - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, gqlEndpoint, bytes.NewReader(bodyBytes)) @@ -284,7 +285,7 @@ func executeGraphQL( ) var result map[string]any - require.NoError(t, json.Unmarshal(respBytes, &result)) + require.NoError(t, json.Unmarshal(respBytes, &result, jsonx.V1())) return result } diff --git a/test/integration/awsconfig_test.go b/test/integration/awsconfig_test.go index 91ca4d57dc..ee579dbd68 100644 --- a/test/integration/awsconfig_test.go +++ b/test/integration/awsconfig_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func awsconfigPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) diff --git a/test/integration/azurearm_test.go b/test/integration/azurearm_test.go index 1289bb97b6..6be7a08b56 100644 --- a/test/integration/azurearm_test.go +++ b/test/integration/azurearm_test.go @@ -20,7 +20,8 @@ package integration_test import ( "crypto/tls" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "strings" "testing" @@ -29,6 +30,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -79,7 +81,7 @@ func armDecodeJSON(t *testing.T, resp *http.Response) map[string]any { t.Helper() var body map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&body)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &body, jsonx.V1())) return body } @@ -96,7 +98,7 @@ func TestIntegration_AzureARM_MetadataAndToken(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) var doc map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&doc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &doc, jsonx.V1())) assert.Equal(t, "gopherstack", doc["name"]) assert.NotEmpty(t, doc["resourceManagerEndpoint"]) diff --git a/test/integration/azureservicebus_test.go b/test/integration/azureservicebus_test.go index b31dbb5727..5b36dcac16 100644 --- a/test/integration/azureservicebus_test.go +++ b/test/integration/azureservicebus_test.go @@ -16,7 +16,7 @@ package integration_test // namespace's Brokered Messaging API. import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -27,6 +27,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -97,7 +98,7 @@ func TestIntegration_AzureServiceBus_QueueSendPeekLockComplete(t *testing.T) { var bp sbBrokerProperties - require.NoError(t, json.Unmarshal([]byte(resp.Header.Get("Brokerproperties")), &bp)) + require.NoError(t, json.Unmarshal([]byte(resp.Header.Get("Brokerproperties")), &bp, jsonx.V1())) require.NotEmpty(t, bp.MessageID) require.NotEmpty(t, bp.LockToken) diff --git a/test/integration/chaos_test.go b/test/integration/chaos_test.go index ccb8436914..916a88eb66 100644 --- a/test/integration/chaos_test.go +++ b/test/integration/chaos_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -19,6 +19,7 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -103,7 +104,7 @@ func newDynamoDBClientAt(t *testing.T, ep string) *dynamodb.Client { func postChaosRules(t *testing.T, ep string, rules any) { t.Helper() - body, err := json.Marshal(rules) + body, err := json.Marshal(rules, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext( @@ -128,7 +129,7 @@ func postChaosRules(t *testing.T, ep string, rules any) { func postChaosEffects(t *testing.T, ep string, effects chaosNetworkEffects) { t.Helper() - body, err := json.Marshal(effects) + body, err := json.Marshal(effects, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext( diff --git a/test/integration/cloudwatchlogs_test.go b/test/integration/cloudwatchlogs_test.go index a955255ca4..98aba361ba 100644 --- a/test/integration/cloudwatchlogs_test.go +++ b/test/integration/cloudwatchlogs_test.go @@ -4,7 +4,7 @@ import ( "bytes" "compress/gzip" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "testing" "time" @@ -16,6 +16,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // decompressGzip decompresses gzip-compressed bytes. @@ -349,7 +351,7 @@ func TestIntegration_CloudWatchLogs_SubscriptionFilter_KinesisDelivery(t *testin // Verify the payload matches the CloudWatch Logs subscription format. var payload map[string]any - require.NoError(t, json.Unmarshal(decompressed, &payload)) + require.NoError(t, json.Unmarshal(decompressed, &payload, jsonx.V1())) assert.Equal(t, "DATA_MESSAGE", payload["messageType"]) assert.Equal(t, groupName, payload["logGroup"]) assert.Equal(t, logStreamName, payload["logStream"]) diff --git a/test/integration/cognito_test.go b/test/integration/cognito_test.go index 8c032dbfc1..12a06d052f 100644 --- a/test/integration/cognito_test.go +++ b/test/integration/cognito_test.go @@ -3,7 +3,7 @@ package integration_test import ( "crypto/rsa" "encoding/base64" - "encoding/json" + "encoding/json/v2" "fmt" "io" "math/big" @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -122,7 +123,7 @@ func TestIntegration_CognitoIDP_FullFlow(t *testing.T) { Alg string `json:"alg"` } `json:"keys"` } - require.NoError(t, json.Unmarshal(jwksBody, &jwks), "JWKS should be valid JSON") + require.NoError(t, json.Unmarshal(jwksBody, &jwks, jsonx.V1()), "JWKS should be valid JSON") require.Len(t, jwks.Keys, 1, "JWKS should have exactly one key") assert.Equal(t, "RSA", jwks.Keys[0].Kty) assert.Equal(t, "sig", jwks.Keys[0].Use) diff --git a/test/integration/cosmosdb_test.go b/test/integration/cosmosdb_test.go index 6e092acb70..31efe7000a 100644 --- a/test/integration/cosmosdb_test.go +++ b/test/integration/cosmosdb_test.go @@ -1,13 +1,15 @@ package integration_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // cosmosDBDevMasterKey is the real Cosmos DB Local Emulator's published @@ -81,7 +83,7 @@ func TestIntegration_CosmosDB_DatabaseContainerDocumentLifecycle(t *testing.T) { } doc := testDoc{ID: "doc1", PK: "partA", Value: 42} - body, err := json.Marshal(doc) + body, err := json.Marshal(doc, jsonx.V1()) require.NoError(t, err) pk := azcosmos.NewPartitionKeyString("partA") @@ -95,7 +97,7 @@ func TestIntegration_CosmosDB_DatabaseContainerDocumentLifecycle(t *testing.T) { require.NoError(t, err) var gotDoc testDoc - require.NoError(t, json.Unmarshal(readResp.Value, &gotDoc)) + require.NoError(t, json.Unmarshal(readResp.Value, &gotDoc, jsonx.V1())) assert.Equal(t, doc, gotDoc) // Query via SQL. @@ -113,7 +115,7 @@ func TestIntegration_CosmosDB_DatabaseContainerDocumentLifecycle(t *testing.T) { for _, item := range page.Items { var qd testDoc - require.NoError(t, json.Unmarshal(item, &qd)) + require.NoError(t, json.Unmarshal(item, &qd, jsonx.V1())) if qd.ID == "doc1" { found = true @@ -125,7 +127,7 @@ func TestIntegration_CosmosDB_DatabaseContainerDocumentLifecycle(t *testing.T) { // UpsertItem (replaces existing doc1). upserted := testDoc{ID: "doc1", PK: "partA", Value: 100} - upsertBody, err := json.Marshal(upserted) + upsertBody, err := json.Marshal(upserted, jsonx.V1()) require.NoError(t, err) _, err = containerClient.UpsertItem(ctx, pk, upsertBody, nil) @@ -135,7 +137,7 @@ func TestIntegration_CosmosDB_DatabaseContainerDocumentLifecycle(t *testing.T) { require.NoError(t, err) var afterUpsert testDoc - require.NoError(t, json.Unmarshal(readResp.Value, &afterUpsert)) + require.NoError(t, json.Unmarshal(readResp.Value, &afterUpsert, jsonx.V1())) assert.Equal(t, 100, afterUpsert.Value) // DeleteItem. diff --git a/test/integration/ecrpublic_test.go b/test/integration/ecrpublic_test.go index 06fb878e0f..411e38fd53 100644 --- a/test/integration/ecrpublic_test.go +++ b/test/integration/ecrpublic_test.go @@ -3,7 +3,7 @@ package integration_test import ( "crypto/sha256" "encoding/hex" - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -13,6 +13,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -102,7 +104,7 @@ func TestIntegration_ECRPublic_RepositoryImageLifecycle(t *testing.T) { "mediaType": ecrPublicManifestMediaType, "config": map[string]any{"mediaType": ecrPublicConfigMediaType, "digest": configDigest}, "layers": []map[string]any{{"digest": layerDigest}}, - }) + }, jsonx.V1()) require.NoError(t, err) put, err := client.PutImage(ctx, &ecrpublicsdk.PutImageInput{ @@ -117,7 +119,7 @@ func TestIntegration_ECRPublic_RepositoryImageLifecycle(t *testing.T) { "schemaVersion": 2, "mediaType": ecrPublicIndexMediaType, "manifests": []map[string]any{{"digest": childDigest}}, - }) + }, jsonx.V1()) require.NoError(t, err) _, err = client.PutImage(ctx, &ecrpublicsdk.PutImageInput{ diff --git a/test/integration/eks_irsa_test.go b/test/integration/eks_irsa_test.go index b980cad68e..38744c8512 100644 --- a/test/integration/eks_irsa_test.go +++ b/test/integration/eks_irsa_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "io" "net/http" "os" @@ -22,6 +23,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -33,7 +35,7 @@ type irsaToken struct { func mintIRSAToken(t *testing.T, cluster string, body map[string]any) irsaToken { t.Helper() - raw, err := json.Marshal(body) + raw, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) resp, err := testclient.New(t).Post(endpoint+"/_gopherstack/eks/"+cluster+"/serviceaccount-token", @@ -47,7 +49,7 @@ func mintIRSAToken(t *testing.T, cluster string, body map[string]any) irsaToken require.Equal(t, http.StatusOK, resp.StatusCode, string(out)) var tok irsaToken - require.NoError(t, json.Unmarshal(out, &tok)) + require.NoError(t, json.Unmarshal(out, &tok, jsonx.V1())) return tok } @@ -100,7 +102,7 @@ func TestIntegration_EKS_IRSA(t *testing.T) { defer disc.Body.Close() var discDoc map[string]any - require.NoError(t, json.NewDecoder(disc.Body).Decode(&discDoc)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(disc.Body), &discDoc, jsonx.V1())) assert.Equal(t, issuer, discDoc["issuer"]) provider, err := iamClient.CreateOpenIDConnectProvider(ctx, &iamsdk.CreateOpenIDConnectProviderInput{ diff --git a/test/integration/elasticsearch_test.go b/test/integration/elasticsearch_test.go index 3218788db5..769dfe4d3b 100644 --- a/test/integration/elasticsearch_test.go +++ b/test/integration/elasticsearch_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -79,7 +81,7 @@ func doElasticsearchRequest(t *testing.T, method, path string, body any) (int, m var reqBody io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) @@ -99,7 +101,7 @@ func doElasticsearchRequest(t *testing.T, method, path string, body any) (int, m var result map[string]any - if err = json.NewDecoder(resp.Body).Decode(&result); err != nil { + if err = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &result, jsonx.V1()); err != nil { result = nil } diff --git a/test/integration/firehose_delivery_test.go b/test/integration/firehose_delivery_test.go index a270dc2cdf..4e7b019c07 100644 --- a/test/integration/firehose_delivery_test.go +++ b/test/integration/firehose_delivery_test.go @@ -4,7 +4,7 @@ import ( "bytes" "context" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "log/slog" "net/http" @@ -18,6 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" pkglogger "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" "github.com/blackbirdworks/gopherstack/pkgs/testclient" @@ -73,7 +74,7 @@ func (keepOrDropLambdaInvoker) InvokeFunction( payload []byte, ) ([]byte, int, error) { var event transformEvent - if err := json.Unmarshal(payload, &event); err != nil { + if err := json.Unmarshal(payload, &event, jsonx.V1()); err != nil { return nil, 500, err } @@ -87,7 +88,7 @@ func (keepOrDropLambdaInvoker) InvokeFunction( out[i] = transformRecord{RecordID: rec.RecordID, Result: result, Data: rec.Data} } - resp, err := json.Marshal(map[string]any{"records": out}) + resp, err := json.Marshal(map[string]any{"records": out}, jsonx.V1()) if err != nil { return nil, 500, err } @@ -440,7 +441,7 @@ func TestIntegration_Firehose_HTTP_UpdateDestination(t *testing.T) { doPost := func(action string, body any) (int, string) { t.Helper() - bodyBytes, marshalErr := json.Marshal(body) + bodyBytes, marshalErr := json.Marshal(body, jsonx.V1()) require.NoError(t, marshalErr) req, reqCreateErr := http.NewRequestWithContext( t.Context(), http.MethodPost, srv.URL, diff --git a/test/integration/firehose_test.go b/test/integration/firehose_test.go index 79c5815720..155a48777a 100644 --- a/test/integration/firehose_test.go +++ b/test/integration/firehose_test.go @@ -3,7 +3,7 @@ package integration_test import ( "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -11,13 +11,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func firehosePost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) diff --git a/test/integration/fis_test.go b/test/integration/fis_test.go index 09879c9e05..0f8bf49784 100644 --- a/test/integration/fis_test.go +++ b/test/integration/fis_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "net/http" "testing" "time" @@ -14,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -32,7 +34,7 @@ func fisRequest( var bodyReader *bytes.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) } else { @@ -55,7 +57,7 @@ func fisBody(t *testing.T, resp *http.Response, out any) { defer func() { _ = resp.Body.Close() }() - require.NoError(t, json.NewDecoder(resp.Body).Decode(out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), out, jsonx.V1())) } // ---------------------------------------- @@ -309,7 +311,7 @@ func TestIntegration_FIS_ExperimentLifecycle(t *testing.T) { defer func() { _ = getResp.Body.Close() }() - if err := json.NewDecoder(getResp.Body).Decode(&getResult); err != nil { + if err := json.UnmarshalDecode(jsontext.NewDecoder(getResp.Body), &getResult, jsonx.V1()); err != nil { return false } @@ -591,7 +593,11 @@ func TestIntegration_FIS_KinesisThroughputException(t *testing.T) { return false } - if decodeErr := json.NewDecoder(getResp.Body).Decode(&getResult); decodeErr != nil { + if decodeErr := json.UnmarshalDecode( + jsontext.NewDecoder(getResp.Body), + &getResult, + jsonx.V1(), + ); decodeErr != nil { return false } @@ -642,7 +648,11 @@ func TestIntegration_FIS_KinesisThroughputException(t *testing.T) { return false } - if decodeErr := json.NewDecoder(getResp.Body).Decode(&getResult); decodeErr != nil { + if decodeErr := json.UnmarshalDecode( + jsontext.NewDecoder(getResp.Body), + &getResult, + jsonx.V1(), + ); decodeErr != nil { return false } diff --git a/test/integration/gcp_iam_test.go b/test/integration/gcp_iam_test.go index 1c21758a5f..3248783535 100644 --- a/test/integration/gcp_iam_test.go +++ b/test/integration/gcp_iam_test.go @@ -1,7 +1,7 @@ package integration_test import ( - "encoding/json" + "encoding/json/v2" "testing" iam "cloud.google.com/go/iam/admin/apiv1" @@ -11,6 +11,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/fieldmaskpb" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func newIAMAdminClient(t *testing.T) *iam.IamClient { @@ -57,7 +59,7 @@ func TestIntegration_GCP_IAM_ServiceAccountAndKey(t *testing.T) { ClientEmail string `json:"client_email"` } - require.NoError(t, json.Unmarshal(key.GetPrivateKeyData(), &kf)) + require.NoError(t, json.Unmarshal(key.GetPrivateKeyData(), &kf, jsonx.V1())) assert.Equal(t, "service_account", kf.Type) assert.Equal(t, sa.GetEmail(), kf.ClientEmail) diff --git a/test/integration/glacier_test.go b/test/integration/glacier_test.go index abd34e56a0..2d4761795f 100644 --- a/test/integration/glacier_test.go +++ b/test/integration/glacier_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "net/http" "testing" "time" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -212,7 +213,7 @@ func glacierAddTags(t *testing.T, vaultName string, tags map[string]string) erro Tags map[string]string `json:"Tags"` } - payload, err := json.Marshal(addTagsReq{Tags: tags}) + payload, err := json.Marshal(addTagsReq{Tags: tags}, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, diff --git a/test/integration/iot_test.go b/test/integration/iot_test.go index 52d96d6ad5..1809c7f436 100644 --- a/test/integration/iot_test.go +++ b/test/integration/iot_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -16,6 +17,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/sqs" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -26,7 +28,7 @@ func iotRequest(t *testing.T, method, path string, body any) *http.Response { var reqBody io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) @@ -93,7 +95,7 @@ func TestIntegration_IoT_ThingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]string - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, thingName, out["thingName"]) assert.NotEmpty(t, out["thingArn"]) assert.NotEmpty(t, out["thingId"]) @@ -110,7 +112,7 @@ func TestIntegration_IoT_ThingLifecycle(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.Equal(t, thingName, out["thingName"]) }, }, @@ -197,7 +199,7 @@ func TestIntegration_IoT_PolicyAndRule(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) // AWS GetTopicRule wraps fields under a "rule" object with "ruleArn" at top level. rule, ok := out["rule"].(map[string]any) require.True(t, ok, "response should contain a 'rule' object") @@ -246,7 +248,7 @@ func TestIntegration_IoT_DescribeEndpoint(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode) var out map[string]string - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &out, jsonx.V1())) assert.NotEmpty(t, out["endpointAddress"]) }) } diff --git a/test/integration/lambda_esm_test.go b/test/integration/lambda_esm_test.go index 8ed06edc41..89bba917e8 100644 --- a/test/integration/lambda_esm_test.go +++ b/test/integration/lambda_esm_test.go @@ -2,7 +2,7 @@ package integration_test import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http/httptest" "strconv" @@ -23,6 +23,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/container" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc/portalloctest" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -207,7 +208,7 @@ func TestIntegration_Lambda_SQS_ESM(t *testing.T) { "Code": map[string]string{"ImageUri": lambdaEchoImage}, "Role": "arn:aws:iam::000000000000:role/lambda-test", "Timeout": int(esmInvokeTimeout.Seconds()), - }) + }, jsonx.V1()) require.NoError(t, err) createFnResp, err := doLambdaRequest(ctx, "POST", diff --git a/test/integration/lambda_new_ops_test.go b/test/integration/lambda_new_ops_test.go index 1fb7cf5574..8bb2f65475 100644 --- a/test/integration/lambda_new_ops_test.go +++ b/test/integration/lambda_new_ops_test.go @@ -3,7 +3,7 @@ package integration_test import ( "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "log/slog" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc/portalloctest" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -58,7 +59,7 @@ func createLambdaFunction(ctx context.Context, t *testing.T, serverURL, fnName s "PackageType": "Image", "Code": map[string]string{"ImageUri": "test:latest"}, "Role": "arn:aws:iam::000000000000:role/test", - }) + }, jsonx.V1()) require.NoError(t, err) resp, err := doLambdaRequest(ctx, http.MethodPost, @@ -133,7 +134,7 @@ func TestLambda_AddPermission(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - body, err := json.Marshal(tt.body) + body, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) targetFn := fnName @@ -153,7 +154,7 @@ func TestLambda_AddPermission(t *testing.T) { require.NoError(t, readErr) var out map[string]any - require.NoError(t, json.Unmarshal(rawBody, &out)) + require.NoError(t, json.Unmarshal(rawBody, &out, jsonx.V1())) assert.NotEmpty(t, out["Statement"]) } }) @@ -174,7 +175,7 @@ func TestLambda_AddPermission_DuplicateStatementId(t *testing.T) { "StatementId": "AllowS3", "Action": "lambda:InvokeFunction", "Principal": "s3.amazonaws.com", - }) + }, jsonx.V1()) require.NoError(t, err) url := fmt.Sprintf("%s/2015-03-31/functions/%s/policy", server.URL, fnName) @@ -210,7 +211,7 @@ func TestLambda_GetAccountSettings(t *testing.T) { require.NoError(t, err) var out lambdapkg.AccountSettingsOutput - require.NoError(t, json.Unmarshal(respBody, &out)) + require.NoError(t, json.Unmarshal(respBody, &out, jsonx.V1())) require.NotNil(t, out.AccountLimit) assert.Positive(t, out.AccountLimit.ConcurrentExecutions) @@ -238,7 +239,7 @@ func TestLambda_CodeSigningConfig(t *testing.T) { }, }, "Description": "test config", - }) + }, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -251,7 +252,7 @@ func TestLambda_CodeSigningConfig(t *testing.T) { require.NoError(t, err) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRespBody, &createOut)) + require.NoError(t, json.Unmarshal(createRespBody, &createOut, jsonx.V1())) cscData, ok := createOut["CodeSigningConfig"].(map[string]any) require.True(t, ok, "expected CodeSigningConfig in response") @@ -279,13 +280,13 @@ func TestLambda_CodeSigningConfig(t *testing.T) { require.NoError(t, err) var listOut map[string]any - require.NoError(t, json.Unmarshal(listBody, &listOut)) + require.NoError(t, json.Unmarshal(listBody, &listOut, jsonx.V1())) configs, ok := listOut["CodeSigningConfigs"].([]any) require.True(t, ok) assert.Len(t, configs, 1) // Put function code signing config - putBody, err := json.Marshal(map[string]any{"CodeSigningConfigArn": cscARN}) + putBody, err := json.Marshal(map[string]any{"CodeSigningConfigArn": cscARN}, jsonx.V1()) require.NoError(t, err) putResp, err := doLambdaRequest(ctx, http.MethodPut, @@ -307,7 +308,7 @@ func TestLambda_CodeSigningConfig(t *testing.T) { require.NoError(t, err) var getFnCSCOut map[string]any - require.NoError(t, json.Unmarshal(getFnCSCBody, &getFnCSCOut)) + require.NoError(t, json.Unmarshal(getFnCSCBody, &getFnCSCOut, jsonx.V1())) assert.Equal(t, cscARN, getFnCSCOut["CodeSigningConfigArn"]) // List functions by code signing config @@ -364,7 +365,7 @@ func TestLambda_CapacityProvider(t *testing.T) { "SubnetIds": []string{"subnet-1"}, "SecurityGroupIds": []string{"sg-1"}, }, - }) + }, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -377,7 +378,7 @@ func TestLambda_CapacityProvider(t *testing.T) { require.NoError(t, err) var createOut map[string]any - require.NoError(t, json.Unmarshal(createRespBody, &createOut)) + require.NoError(t, json.Unmarshal(createRespBody, &createOut, jsonx.V1())) cpData, ok := createOut["CapacityProvider"].(map[string]any) require.True(t, ok, "expected CapacityProvider in response") @@ -410,7 +411,7 @@ func TestLambda_CapacityProvider(t *testing.T) { require.NoError(t, err) var listOut map[string]any - require.NoError(t, json.Unmarshal(listBody, &listOut)) + require.NoError(t, json.Unmarshal(listBody, &listOut, jsonx.V1())) providers, ok := listOut["CapacityProviders"].([]any) require.True(t, ok) assert.Len(t, providers, 1) @@ -418,7 +419,7 @@ func TestLambda_CapacityProvider(t *testing.T) { // Update capacity provider updateBody, err := json.Marshal(map[string]any{ "CapacityProviderScalingConfig": map[string]any{"MaxVCpuCount": 200}, - }) + }, jsonx.V1()) require.NoError(t, err) updateResp, err := doLambdaRequest(ctx, http.MethodPut, @@ -432,7 +433,7 @@ func TestLambda_CapacityProvider(t *testing.T) { require.NoError(t, err) var updateOut map[string]any - require.NoError(t, json.Unmarshal(updateRespBody, &updateOut)) + require.NoError(t, json.Unmarshal(updateRespBody, &updateOut, jsonx.V1())) cpUpdated, ok := updateOut["CapacityProvider"].(map[string]any) require.True(t, ok) scalingConfig, ok := cpUpdated["CapacityProviderScalingConfig"].(map[string]any) @@ -453,7 +454,7 @@ func TestLambda_CapacityProvider(t *testing.T) { require.NoError(t, err) var delOut map[string]any - require.NoError(t, json.Unmarshal(delRespBody, &delOut)) + require.NoError(t, json.Unmarshal(delRespBody, &delOut, jsonx.V1())) cpDeleted, ok := delOut["CapacityProvider"].(map[string]any) require.True(t, ok, "expected CapacityProvider in response") assert.Contains(t, cpDeleted["CapacityProviderArn"], "test-provider") @@ -497,7 +498,7 @@ func TestLambda_FunctionUrlConfig_2021(t *testing.T) { createLambdaFunction(ctx, t, server.URL, fnName) // Create function URL config via 2021 path - createBody, err := json.Marshal(map[string]any{"AuthType": "NONE"}) + createBody, err := json.Marshal(map[string]any{"AuthType": "NONE"}, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -518,7 +519,7 @@ func TestLambda_FunctionUrlConfig_2021(t *testing.T) { require.NoError(t, err) var cfg lambdapkg.FunctionURLConfig - require.NoError(t, json.Unmarshal(getBody, &cfg)) + require.NoError(t, json.Unmarshal(getBody, &cfg, jsonx.V1())) assert.Equal(t, "NONE", cfg.AuthType) // List function URL configs via 2021 path @@ -532,13 +533,13 @@ func TestLambda_FunctionUrlConfig_2021(t *testing.T) { require.NoError(t, err) var listOut map[string]any - require.NoError(t, json.Unmarshal(listBody, &listOut)) + require.NoError(t, json.Unmarshal(listBody, &listOut, jsonx.V1())) urlConfigs, ok := listOut["FunctionUrlConfigs"].([]any) require.True(t, ok) assert.Len(t, urlConfigs, 1) // Update function URL config via 2021 path - updateBody, err := json.Marshal(map[string]any{"AuthType": "AWS_IAM"}) + updateBody, err := json.Marshal(map[string]any{"AuthType": "AWS_IAM"}, jsonx.V1()) require.NoError(t, err) updateResp, err := doLambdaRequest(ctx, http.MethodPut, diff --git a/test/integration/lambda_test.go b/test/integration/lambda_test.go index 61c5494e7e..be2efb94dd 100644 --- a/test/integration/lambda_test.go +++ b/test/integration/lambda_test.go @@ -4,7 +4,7 @@ import ( "archive/tar" "bytes" "context" - "encoding/json" + "encoding/json/v2" "fmt" "io" "log/slog" @@ -23,6 +23,7 @@ import ( dockerapifilters "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/filters" dockerapiimage "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/image" dockerclient "github.com/blackbirdworks/gopherstack/internal/dockercompat/client" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -163,7 +164,7 @@ func TestLambdaIntegration_Invoke_DockerEchoContainer(t *testing.T) { "Code": map[string]string{"ImageUri": lambdaEchoImage}, "Role": "arn:aws:iam::000000000000:role/lambda-test", "Timeout": 15, // 15s gives enough time for container cold start in CI - }) + }, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, server.URL+"/2015-03-31/functions", @@ -277,7 +278,7 @@ func buildEchoLambdaImage(ctx context.Context, t *testing.T) { Error string `json:"error"` } - if jsonErr := json.Unmarshal([]byte(line), &msg); jsonErr == nil && msg.Error != "" { + if jsonErr := json.Unmarshal([]byte(line), &msg, jsonx.V1()); jsonErr == nil && msg.Error != "" { t.Skipf("Docker image build failed (infrastructure error — skipping test): %s", msg.Error) } } diff --git a/test/integration/lambda_url_test.go b/test/integration/lambda_url_test.go index 5b2d90431a..ed78d18226 100644 --- a/test/integration/lambda_url_test.go +++ b/test/integration/lambda_url_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "fmt" "io" "log/slog" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/portalloc/portalloctest" "github.com/blackbirdworks/gopherstack/pkgs/service" @@ -57,7 +58,7 @@ func TestLambdaFunctionURL_CreateGetDelete(t *testing.T) { "PackageType": "Image", "Code": map[string]string{"ImageUri": "test:latest"}, "Role": "arn:aws:iam::000000000000:role/test", - }) + }, jsonx.V1()) require.NoError(t, err) resp, err := doLambdaRequest(ctx, http.MethodPost, server.URL+"/2015-03-31/functions", @@ -67,7 +68,7 @@ func TestLambdaFunctionURL_CreateGetDelete(t *testing.T) { require.Equal(t, http.StatusCreated, resp.StatusCode) // Create function URL config - urlBody, err := json.Marshal(map[string]any{"AuthType": "NONE"}) + urlBody, err := json.Marshal(map[string]any{"AuthType": "NONE"}, jsonx.V1()) require.NoError(t, err) urlResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -80,7 +81,7 @@ func TestLambdaFunctionURL_CreateGetDelete(t *testing.T) { var cfg lambdapkg.FunctionURLConfig respBody, err := io.ReadAll(urlResp.Body) require.NoError(t, err) - require.NoError(t, json.Unmarshal(respBody, &cfg)) + require.NoError(t, json.Unmarshal(respBody, &cfg, jsonx.V1())) assert.NotEmpty(t, cfg.FunctionURL, "FunctionURL should not be empty") assert.Equal(t, "NONE", cfg.AuthType) @@ -100,7 +101,7 @@ func TestLambdaFunctionURL_CreateGetDelete(t *testing.T) { var getCfg lambdapkg.FunctionURLConfig getBody, err := io.ReadAll(getResp.Body) require.NoError(t, err) - require.NoError(t, json.Unmarshal(getBody, &getCfg)) + require.NoError(t, json.Unmarshal(getBody, &getCfg, jsonx.V1())) assert.Equal(t, cfg.FunctionURL, getCfg.FunctionURL) // Delete function URL config diff --git a/test/integration/lambda_zip_test.go b/test/integration/lambda_zip_test.go index 0178191953..4a195a7864 100644 --- a/test/integration/lambda_zip_test.go +++ b/test/integration/lambda_zip_test.go @@ -4,7 +4,7 @@ import ( "archive/zip" "bytes" "encoding/base64" - "encoding/json" + "encoding/json/v2" "io" "log/slog" "net/http" @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" pkglogger "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" lambdapkg "github.com/blackbirdworks/gopherstack/services/lambda" @@ -75,7 +76,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { "Handler": "index.handler", "Code": map[string]string{"ZipFile": zipB64}, "Role": "arn:aws:iam::000000000000:role/test", - }) + }, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -87,7 +88,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { var created lambdapkg.FunctionConfiguration body, err := io.ReadAll(createResp.Body) require.NoError(t, err) - require.NoError(t, json.Unmarshal(body, &created)) + require.NoError(t, json.Unmarshal(body, &created, jsonx.V1())) assert.Equal(t, "zip-crud-fn", created.FunctionName) assert.Equal(t, lambdapkg.PackageTypeZip, created.PackageType) assert.Equal(t, "python3.12", created.Runtime) @@ -103,7 +104,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { getBody, err := io.ReadAll(getResp.Body) require.NoError(t, err) var getOut lambdapkg.GetFunctionOutput - require.NoError(t, json.Unmarshal(getBody, &getOut)) + require.NoError(t, json.Unmarshal(getBody, &getOut, jsonx.V1())) assert.Equal(t, lambdapkg.PackageTypeZip, getOut.Configuration.PackageType) require.NotNil(t, getOut.Code) assert.Equal(t, "S3", getOut.Code.RepositoryType) // Zip locations use S3 repository type @@ -120,7 +121,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { } listBody, err := io.ReadAll(listResp.Body) require.NoError(t, err) - require.NoError(t, json.Unmarshal(listBody, &listOut)) + require.NoError(t, json.Unmarshal(listBody, &listOut, jsonx.V1())) require.Len(t, listOut.Functions, 1) assert.Equal(t, "zip-crud-fn", listOut.Functions[0].FunctionName) @@ -128,7 +129,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { newZipB64 := makeZipPayload(t, "index.py", `def handler(event, context): return "v2"`) updateCodeBody, err := json.Marshal(map[string]any{ "ZipFile": newZipB64, - }) + }, jsonx.V1()) require.NoError(t, err) updateCodeResp, err := doLambdaRequest(ctx, http.MethodPut, server.URL+"/2015-03-31/functions/zip-crud-fn/code", "application/json", @@ -142,7 +143,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { "Runtime": "python3.13", "Handler": "main.handler", "Description": "updated", - }) + }, jsonx.V1()) require.NoError(t, err) updateCfgResp, err := doLambdaRequest(ctx, http.MethodPut, server.URL+"/2015-03-31/functions/zip-crud-fn/configuration", "application/json", @@ -154,7 +155,7 @@ func TestIntegration_Lambda_Zip_CRUD(t *testing.T) { var updatedCfg lambdapkg.FunctionConfiguration cfgBody, err := io.ReadAll(updateCfgResp.Body) require.NoError(t, err) - require.NoError(t, json.Unmarshal(cfgBody, &updatedCfg)) + require.NoError(t, json.Unmarshal(cfgBody, &updatedCfg, jsonx.V1())) assert.Equal(t, "python3.13", updatedCfg.Runtime) assert.Equal(t, "main.handler", updatedCfg.Handler) @@ -235,7 +236,7 @@ func TestIntegration_Lambda_Zip_ValidationErrors(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - bodyJSON, err := json.Marshal(tt.body) + bodyJSON, err := json.Marshal(tt.body, jsonx.V1()) require.NoError(t, err) resp, err := doLambdaRequest(ctx, http.MethodPost, @@ -278,7 +279,7 @@ func TestIntegration_Lambda_Zip_S3Code(t *testing.T) { "S3Key": "functions/my-fn.zip", }, "Role": "arn:aws:iam::000000000000:role/test", - }) + }, jsonx.V1()) require.NoError(t, err) createResp, err := doLambdaRequest(ctx, http.MethodPost, @@ -297,7 +298,7 @@ func TestIntegration_Lambda_Zip_S3Code(t *testing.T) { getBody, err := io.ReadAll(getResp.Body) require.NoError(t, err) var getOut lambdapkg.GetFunctionOutput - require.NoError(t, json.Unmarshal(getBody, &getOut)) + require.NoError(t, json.Unmarshal(getBody, &getOut, jsonx.V1())) assert.Equal(t, "nodejs20.x", getOut.Configuration.Runtime) require.NotNil(t, getOut.Code) assert.Equal(t, "S3", getOut.Code.RepositoryType) diff --git a/test/integration/opensearch_test.go b/test/integration/opensearch_test.go index 0031681007..dbd84d42ab 100644 --- a/test/integration/opensearch_test.go +++ b/test/integration/opensearch_test.go @@ -2,7 +2,8 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "fmt" "io" "net/http" @@ -11,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -23,7 +25,7 @@ func doOpenSearchRequest(t *testing.T, method, path string, body any) (int, map[ var reqBody io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) reqBody = bytes.NewReader(b) @@ -43,7 +45,7 @@ func doOpenSearchRequest(t *testing.T, method, path string, body any) (int, map[ var result map[string]any - if err = json.NewDecoder(resp.Body).Decode(&result); err != nil { + if err = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &result, jsonx.V1()); err != nil { result = nil } diff --git a/test/integration/pipes_sqs_lambda_test.go b/test/integration/pipes_sqs_lambda_test.go index 2c409e1c84..0c0319095d 100644 --- a/test/integration/pipes_sqs_lambda_test.go +++ b/test/integration/pipes_sqs_lambda_test.go @@ -2,7 +2,7 @@ package integration_test import ( "context" - "encoding/json" + "encoding/json/v2" "log/slog" "net/http/httptest" "strings" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/logger" "github.com/blackbirdworks/gopherstack/pkgs/service" pipespkg "github.com/blackbirdworks/gopherstack/services/pipes" @@ -219,7 +220,7 @@ func TestIntegration_Pipes_SQS_To_Lambda(t *testing.T) { EventSource string `json:"eventSource"` } `json:"Records"` } - require.NoError(t, json.Unmarshal(payload, &event)) + require.NoError(t, json.Unmarshal(payload, &event, jsonx.V1())) assert.NotEmpty(t, event.Records, "payload should have at least one record") assert.Equal(t, "aws:sqs", event.Records[0].EventSource) diff --git a/test/integration/pipes_test.go b/test/integration/pipes_test.go index badca5b3eb..e4cfe31c4a 100644 --- a/test/integration/pipes_test.go +++ b/test/integration/pipes_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func pipesRequest(t *testing.T, method, path string, body any) *http.Response { if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } diff --git a/test/integration/ram_test.go b/test/integration/ram_test.go index 2c311260e9..18a47025d1 100644 --- a/test/integration/ram_test.go +++ b/test/integration/ram_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func ramRequest(t *testing.T, method, path string, body any) *http.Response { if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -91,7 +92,7 @@ func TestIntegration_RAM_UpdateResourceShare(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "create body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) shareARN := createResult["resourceShare"].(map[string]any)["resourceShareArn"].(string) @@ -116,7 +117,7 @@ func TestIntegration_RAM_DeleteResourceShare(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "create body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) shareARN := createResult["resourceShare"].(map[string]any)["resourceShareArn"].(string) @@ -139,7 +140,7 @@ func TestIntegration_RAM_AssociateResourceShare(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) shareARN := createResult["resourceShare"].(map[string]any)["resourceShareArn"].(string) @@ -164,7 +165,7 @@ func TestIntegration_RAM_TagResource(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) shareARN := createResult["resourceShare"].(map[string]any)["resourceShareArn"].(string) diff --git a/test/integration/rdsdata_test.go b/test/integration/rdsdata_test.go index 6e064344df..da5dc8d7e2 100644 --- a/test/integration/rdsdata_test.go +++ b/test/integration/rdsdata_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func rdsdataRequest(t *testing.T, path string, body any) *http.Response { if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -96,7 +97,7 @@ func TestIntegration_RDSData_TransactionLifecycle(t *testing.T) { // Parse the transaction ID. var beginResult map[string]any - require.NoError(t, json.Unmarshal([]byte(beginBody), &beginResult)) + require.NoError(t, json.Unmarshal([]byte(beginBody), &beginResult, jsonx.V1())) txID, ok := beginResult["transactionId"].(string) require.True(t, ok, "transactionId should be a string") require.NotEmpty(t, txID) @@ -135,7 +136,7 @@ func TestIntegration_RDSData_RollbackTransaction(t *testing.T) { require.Equal(t, http.StatusOK, beginResp.StatusCode, "body: %s", beginBody) var beginResult map[string]any - require.NoError(t, json.Unmarshal([]byte(beginBody), &beginResult)) + require.NoError(t, json.Unmarshal([]byte(beginBody), &beginResult, jsonx.V1())) txID, ok := beginResult["transactionId"].(string) require.True(t, ok) require.NotEmpty(t, txID) diff --git a/test/integration/redshiftdata_test.go b/test/integration/redshiftdata_test.go index 8bac0ad4ab..cd0a36967d 100644 --- a/test/integration/redshiftdata_test.go +++ b/test/integration/redshiftdata_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func redshiftDataRequest(t *testing.T, target string, body any) *http.Response { if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -62,7 +63,7 @@ func TestIntegration_RedshiftData_ExecuteStatement(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var respObj map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &respObj)) + require.NoError(t, json.Unmarshal([]byte(body), &respObj, jsonx.V1())) assert.NotEmpty(t, respObj["Id"], "expected statement ID in response") } @@ -79,7 +80,7 @@ func TestIntegration_RedshiftData_DescribeStatement(t *testing.T) { require.Equal(t, http.StatusOK, execResp.StatusCode, "body: %s", execBody) var execObj map[string]any - require.NoError(t, json.Unmarshal([]byte(execBody), &execObj)) + require.NoError(t, json.Unmarshal([]byte(execBody), &execObj, jsonx.V1())) id := execObj["Id"].(string) @@ -89,7 +90,7 @@ func TestIntegration_RedshiftData_DescribeStatement(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var descObj map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &descObj)) + require.NoError(t, json.Unmarshal([]byte(body), &descObj, jsonx.V1())) assert.Equal(t, id, descObj["Id"]) assert.Equal(t, "FINISHED", descObj["Status"]) } @@ -107,7 +108,7 @@ func TestIntegration_RedshiftData_GetStatementResult(t *testing.T) { require.Equal(t, http.StatusOK, execResp.StatusCode, "body: %s", execBody) var execObj map[string]any - require.NoError(t, json.Unmarshal([]byte(execBody), &execObj)) + require.NoError(t, json.Unmarshal([]byte(execBody), &execObj, jsonx.V1())) id := execObj["Id"].(string) @@ -149,7 +150,7 @@ func TestIntegration_RedshiftData_BatchExecuteStatement(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var respObj map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &respObj)) + require.NoError(t, json.Unmarshal([]byte(body), &respObj, jsonx.V1())) assert.NotEmpty(t, respObj["Id"]) } diff --git a/test/integration/resourcegroups_test.go b/test/integration/resourcegroups_test.go index 6dea026c60..a5d485cf53 100644 --- a/test/integration/resourcegroups_test.go +++ b/test/integration/resourcegroups_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func resourceGroupsPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) diff --git a/test/integration/resourcegroupstaggingapi_test.go b/test/integration/resourcegroupstaggingapi_test.go index ef2941bd90..f3d41d1862 100644 --- a/test/integration/resourcegroupstaggingapi_test.go +++ b/test/integration/resourcegroupstaggingapi_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -21,7 +22,7 @@ import ( func taggingAPIPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) @@ -115,7 +116,7 @@ func TestIntegration_TaggingAPI_TagResources(t *testing.T) { // Decode the response and assert no failures. var tagOut map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &tagOut)) + require.NoError(t, json.Unmarshal([]byte(body), &tagOut, jsonx.V1())) assert.Empty(t, tagOut["FailedResourcesMap"], "expected no tag failures") // Verify via GetResources that the tagged queue appears when filtering by tag. diff --git a/test/integration/route53resolver_test.go b/test/integration/route53resolver_test.go index 182c4bb681..48b50ebc55 100644 --- a/test/integration/route53resolver_test.go +++ b/test/integration/route53resolver_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func route53resolverPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) @@ -91,7 +92,7 @@ func TestIntegration_Route53Resolver_GetEndpoint(t *testing.T) { var createBody map[string]any createData, _ := io.ReadAll(createResp.Body) createResp.Body.Close() - require.NoError(t, json.Unmarshal(createData, &createBody)) + require.NoError(t, json.Unmarshal(createData, &createBody, jsonx.V1())) ep, _ := createBody["ResolverEndpoint"].(map[string]any) id, _ := ep["Id"].(string) @@ -120,7 +121,7 @@ func TestIntegration_Route53Resolver_DeleteEndpoint(t *testing.T) { var createBody map[string]any createData, _ := io.ReadAll(createResp.Body) createResp.Body.Close() - require.NoError(t, json.Unmarshal(createData, &createBody)) + require.NoError(t, json.Unmarshal(createData, &createBody, jsonx.V1())) ep, _ := createBody["ResolverEndpoint"].(map[string]any) id, _ := ep["Id"].(string) @@ -179,7 +180,7 @@ func TestIntegration_Route53Resolver_DeleteRule(t *testing.T) { var createBody map[string]any createData, _ := io.ReadAll(createResp.Body) createResp.Body.Close() - require.NoError(t, json.Unmarshal(createData, &createBody)) + require.NoError(t, json.Unmarshal(createData, &createBody, jsonx.V1())) rule, _ := createBody["ResolverRule"].(map[string]any) id, _ := rule["Id"].(string) @@ -206,7 +207,7 @@ func TestIntegration_Route53Resolver_GetRule(t *testing.T) { var createBody map[string]any createData, _ := io.ReadAll(createResp.Body) createResp.Body.Close() - require.NoError(t, json.Unmarshal(createData, &createBody)) + require.NoError(t, json.Unmarshal(createData, &createBody, jsonx.V1())) rule, _ := createBody["ResolverRule"].(map[string]any) id, _ := rule["Id"].(string) diff --git a/test/integration/s3_eventbridge_test.go b/test/integration/s3_eventbridge_test.go index 0e2cbd2738..4349ab6718 100644 --- a/test/integration/s3_eventbridge_test.go +++ b/test/integration/s3_eventbridge_test.go @@ -1,7 +1,8 @@ package integration_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "testing" "time" @@ -16,6 +17,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestIntegration_S3_NotificationToEventBridge verifies that when EventBridgeConfiguration @@ -144,37 +147,37 @@ func TestIntegration_S3_NotificationToEventBridge(t *testing.T) { }, 10*time.Second, 500*time.Millisecond, "should receive EventBridge event in SQS within 10s") // Validate the EventBridge event envelope. - var event map[string]json.RawMessage - require.NoError(t, json.Unmarshal([]byte(receivedMsg), &event), "event must be valid JSON") + var event map[string]jsontext.Value + require.NoError(t, json.Unmarshal([]byte(receivedMsg), &event, jsonx.V1()), "event must be valid JSON") var source string - require.NoError(t, json.Unmarshal(event["source"], &source)) + require.NoError(t, json.Unmarshal(event["source"], &source, jsonx.V1())) assert.Equal(t, "aws.s3", source) var detailType string - require.NoError(t, json.Unmarshal(event["detail-type"], &detailType)) + require.NoError(t, json.Unmarshal(event["detail-type"], &detailType, jsonx.V1())) assert.Equal(t, "Object Created", detailType) // Validate the event detail. - var detail map[string]json.RawMessage - require.NoError(t, json.Unmarshal(event["detail"], &detail)) + var detail map[string]jsontext.Value + require.NoError(t, json.Unmarshal(event["detail"], &detail, jsonx.V1())) - var bucketDetail map[string]json.RawMessage - require.NoError(t, json.Unmarshal(detail["bucket"], &bucketDetail)) + var bucketDetail map[string]jsontext.Value + require.NoError(t, json.Unmarshal(detail["bucket"], &bucketDetail, jsonx.V1())) var bucketName string - require.NoError(t, json.Unmarshal(bucketDetail["name"], &bucketName)) + require.NoError(t, json.Unmarshal(bucketDetail["name"], &bucketName, jsonx.V1())) assert.Equal(t, bucket, bucketName) - var objectDetail map[string]json.RawMessage - require.NoError(t, json.Unmarshal(detail["object"], &objectDetail)) + var objectDetail map[string]jsontext.Value + require.NoError(t, json.Unmarshal(detail["object"], &objectDetail, jsonx.V1())) var key string - require.NoError(t, json.Unmarshal(objectDetail["key"], &key)) + require.NoError(t, json.Unmarshal(objectDetail["key"], &key, jsonx.V1())) assert.Equal(t, objectKey, key) var reason string - require.NoError(t, json.Unmarshal(detail["reason"], &reason)) + require.NoError(t, json.Unmarshal(detail["reason"], &reason, jsonx.V1())) assert.Equal(t, "PutObject", reason) t.Logf("S3→EventBridge event delivered: source=%s detail-type=%s bucket=%s key=%s reason=%s", diff --git a/test/integration/s3_notification_test.go b/test/integration/s3_notification_test.go index 3ce2a51233..887d6cf38a 100644 --- a/test/integration/s3_notification_test.go +++ b/test/integration/s3_notification_test.go @@ -1,7 +1,8 @@ package integration_test import ( - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "strings" "testing" "time" @@ -14,6 +15,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // TestIntegration_S3_NotificationToSQS verifies that S3 bucket notifications @@ -117,41 +120,45 @@ func TestIntegration_S3_NotificationToSQS(t *testing.T) { }, 10*time.Second, 500*time.Millisecond, "should receive SQS notification within 10s") // Validate the notification payload format. - var payload map[string]json.RawMessage - require.NoError(t, json.Unmarshal([]byte(receivedMsg), &payload), "notification body must be valid JSON") + var payload map[string]jsontext.Value + require.NoError( + t, + json.Unmarshal([]byte(receivedMsg), &payload, jsonx.V1()), + "notification body must be valid JSON", + ) records, ok := payload["Records"] require.True(t, ok, "notification must contain a Records array") - var recordList []map[string]json.RawMessage - require.NoError(t, json.Unmarshal(records, &recordList)) + var recordList []map[string]jsontext.Value + require.NoError(t, json.Unmarshal(records, &recordList, jsonx.V1())) require.NotEmpty(t, recordList) record := recordList[0] var eventSource string - require.NoError(t, json.Unmarshal(record["eventSource"], &eventSource)) + require.NoError(t, json.Unmarshal(record["eventSource"], &eventSource, jsonx.V1())) assert.Equal(t, "aws:s3", eventSource) var eventName string - require.NoError(t, json.Unmarshal(record["eventName"], &eventName)) + require.NoError(t, json.Unmarshal(record["eventName"], &eventName, jsonx.V1())) assert.True(t, strings.HasPrefix(eventName, "s3:ObjectCreated:"), "eventName should be ObjectCreated") - var s3Block map[string]json.RawMessage - require.NoError(t, json.Unmarshal(record["s3"], &s3Block)) + var s3Block map[string]jsontext.Value + require.NoError(t, json.Unmarshal(record["s3"], &s3Block, jsonx.V1())) - var bucketBlock map[string]json.RawMessage - require.NoError(t, json.Unmarshal(s3Block["bucket"], &bucketBlock)) + var bucketBlock map[string]jsontext.Value + require.NoError(t, json.Unmarshal(s3Block["bucket"], &bucketBlock, jsonx.V1())) var bucketName string - require.NoError(t, json.Unmarshal(bucketBlock["name"], &bucketName)) + require.NoError(t, json.Unmarshal(bucketBlock["name"], &bucketName, jsonx.V1())) assert.Equal(t, bucket, bucketName) - var objectBlock map[string]json.RawMessage - require.NoError(t, json.Unmarshal(s3Block["object"], &objectBlock)) + var objectBlock map[string]jsontext.Value + require.NoError(t, json.Unmarshal(s3Block["object"], &objectBlock, jsonx.V1())) var key string - require.NoError(t, json.Unmarshal(objectBlock["key"], &key)) + require.NoError(t, json.Unmarshal(objectBlock["key"], &key, jsonx.V1())) assert.Equal(t, objectKey, key) t.Logf("S3 notification delivered: eventName=%s bucket=%s key=%s", eventName, bucketName, key) diff --git a/test/integration/scheduler_test.go b/test/integration/scheduler_test.go index 1a1c5a58d0..b4ac70736e 100644 --- a/test/integration/scheduler_test.go +++ b/test/integration/scheduler_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func schedulerPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) diff --git a/test/integration/secretsmanager_rotation_test.go b/test/integration/secretsmanager_rotation_test.go index 2c694c4496..b2d016e017 100644 --- a/test/integration/secretsmanager_rotation_test.go +++ b/test/integration/secretsmanager_rotation_test.go @@ -2,7 +2,7 @@ package integration_test import ( "context" - "encoding/json" + "encoding/json/v2" "io" "net" "net/http/httptest" @@ -23,6 +23,7 @@ import ( dockerapibuild "github.com/blackbirdworks/gopherstack/internal/dockercompat/api/types/build" dockerclient "github.com/blackbirdworks/gopherstack/internal/dockercompat/client" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/container" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -384,7 +385,7 @@ func buildRotationLambdaImage(ctx context.Context, t *testing.T) { Error string `json:"error"` } - if jsonErr := json.Unmarshal([]byte(line), &event); jsonErr == nil && event.Error != "" { + if jsonErr := json.Unmarshal([]byte(line), &event, jsonx.V1()); jsonErr == nil && event.Error != "" { buildErrorMsg = event.Error break diff --git a/test/integration/servicediscovery_test.go b/test/integration/servicediscovery_test.go index 129815659c..51fcb962fd 100644 --- a/test/integration/servicediscovery_test.go +++ b/test/integration/servicediscovery_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func servicediscoveryRequest(t *testing.T, op string, body any) *http.Response { if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -71,7 +72,7 @@ func TestIntegration_ServiceDiscovery_NamespaceLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) opID, ok := createResult["OperationId"].(string) require.True(t, ok) require.NotEmpty(t, opID) @@ -82,7 +83,7 @@ func TestIntegration_ServiceDiscovery_NamespaceLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, opResp.StatusCode, "body: %s", opBody) var opResult map[string]any - require.NoError(t, json.Unmarshal([]byte(opBody), &opResult)) + require.NoError(t, json.Unmarshal([]byte(opBody), &opResult, jsonx.V1())) operation := opResult["Operation"].(map[string]any) targets := operation["Targets"].(map[string]any) nsID, ok := targets["NAMESPACE"].(string) @@ -114,7 +115,7 @@ func TestIntegration_ServiceDiscovery_ServiceLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) svcData := createResult["Service"].(map[string]any) svcID, ok := svcData["Id"].(string) require.True(t, ok) @@ -162,14 +163,14 @@ func TestIntegration_ServiceDiscovery_UpdateHttpNamespace(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) opID := createResult["OperationId"].(string) // Get the operation to find the namespace ID. opResp := servicediscoveryRequest(t, "GetOperation", map[string]any{"OperationId": opID}) opBody := servicediscoveryReadBody(t, opResp) var opResult map[string]any - require.NoError(t, json.Unmarshal([]byte(opBody), &opResult)) + require.NoError(t, json.Unmarshal([]byte(opBody), &opResult, jsonx.V1())) nsID := opResult["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) // Update the namespace. @@ -193,13 +194,13 @@ func TestIntegration_ServiceDiscovery_UpdatePrivateDnsNamespace(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) opID := createResult["OperationId"].(string) opResp := servicediscoveryRequest(t, "GetOperation", map[string]any{"OperationId": opID}) opBody := servicediscoveryReadBody(t, opResp) var opResult map[string]any - require.NoError(t, json.Unmarshal([]byte(opBody), &opResult)) + require.NoError(t, json.Unmarshal([]byte(opBody), &opResult, jsonx.V1())) nsID := opResult["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) updateResp := servicediscoveryRequest(t, "UpdatePrivateDnsNamespace", map[string]any{ @@ -222,13 +223,13 @@ func TestIntegration_ServiceDiscovery_UpdatePublicDnsNamespace(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) opID := createResult["OperationId"].(string) opResp := servicediscoveryRequest(t, "GetOperation", map[string]any{"OperationId": opID}) opBody := servicediscoveryReadBody(t, opResp) var opResult map[string]any - require.NoError(t, json.Unmarshal([]byte(opBody), &opResult)) + require.NoError(t, json.Unmarshal([]byte(opBody), &opResult, jsonx.V1())) nsID := opResult["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) updateResp := servicediscoveryRequest(t, "UpdatePublicDnsNamespace", map[string]any{ @@ -251,7 +252,7 @@ func TestIntegration_ServiceDiscovery_UpdateService(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) svcID := createResult["Service"].(map[string]any)["Id"].(string) updateResp := servicediscoveryRequest(t, "UpdateService", map[string]any{ @@ -281,7 +282,7 @@ func TestIntegration_ServiceDiscovery_ServiceAttributesLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) svcID := createResult["Service"].(map[string]any)["Id"].(string) // UpdateServiceAttributes. @@ -332,7 +333,7 @@ func TestIntegration_ServiceDiscovery_UpdateInstanceCustomHealthStatus(t *testin require.Equal(t, http.StatusOK, createResp.StatusCode, "body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) svcID := createResult["Service"].(map[string]any)["Id"].(string) regResp := servicediscoveryRequest(t, "RegisterInstance", map[string]any{ @@ -374,13 +375,13 @@ func TestIntegration_ServiceDiscovery_DiscoverInstancesRevision(t *testing.T) { require.Equal(t, http.StatusOK, createNsResp.StatusCode, "body: %s", createNsBody) var createNsResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createNsBody), &createNsResult)) + require.NoError(t, json.Unmarshal([]byte(createNsBody), &createNsResult, jsonx.V1())) opID := createNsResult["OperationId"].(string) opResp := servicediscoveryRequest(t, "GetOperation", map[string]any{"OperationId": opID}) opBody := servicediscoveryReadBody(t, opResp) var opResult map[string]any - require.NoError(t, json.Unmarshal([]byte(opBody), &opResult)) + require.NoError(t, json.Unmarshal([]byte(opBody), &opResult, jsonx.V1())) nsID := opResult["Operation"].(map[string]any)["Targets"].(map[string]any)["NAMESPACE"].(string) createSvcResp := servicediscoveryRequest(t, "CreateService", map[string]any{ diff --git a/test/integration/sesv2_test.go b/test/integration/sesv2_test.go index 8cb337a866..56df2741dd 100644 --- a/test/integration/sesv2_test.go +++ b/test/integration/sesv2_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "net/url" @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -21,7 +22,7 @@ func sesv2Do(t *testing.T, method, path string, body any) *http.Response { var bodyReader io.Reader if body != nil { - b, err := json.Marshal(body) + b, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) bodyReader = bytes.NewReader(b) @@ -62,7 +63,7 @@ func TestIntegration_SESv2_CreateEmailIdentity(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, "EMAIL_ADDRESS", out["IdentityType"]) assert.Equal(t, true, out["VerifiedForSendingStatus"]) } @@ -83,7 +84,7 @@ func TestIntegration_SESv2_GetEmailIdentity(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, "EMAIL_ADDRESS", out["IdentityType"]) } @@ -105,7 +106,7 @@ func TestIntegration_SESv2_ListEmailIdentities(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) identities, ok := out["EmailIdentities"].([]any) require.True(t, ok) @@ -165,7 +166,7 @@ func TestIntegration_SESv2_SendEmail(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.NotEmpty(t, out["MessageId"]) } @@ -197,7 +198,7 @@ func TestIntegration_SESv2_GetConfigurationSet(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, name, out["ConfigurationSetName"]) } @@ -218,7 +219,7 @@ func TestIntegration_SESv2_ListConfigurationSets(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) sets, ok := out["ConfigurationSets"].([]any) require.True(t, ok) @@ -267,7 +268,7 @@ func TestIntegration_SESv2_URLEncodedIdentity(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "GET with percent-encoded identity should succeed; body: %s", body) var out map[string]any - require.NoError(t, json.Unmarshal([]byte(body), &out)) + require.NoError(t, json.Unmarshal([]byte(body), &out, jsonx.V1())) assert.Equal(t, "EMAIL_ADDRESS", out["IdentityType"]) // DELETE with percent-encoded path. diff --git a/test/integration/sns_roundtrip_test.go b/test/integration/sns_roundtrip_test.go index 0a13441dcf..de8a8d75ee 100644 --- a/test/integration/sns_roundtrip_test.go +++ b/test/integration/sns_roundtrip_test.go @@ -1,7 +1,7 @@ package integration_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -12,6 +12,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // snsEnvelope is the JSON body SNS delivers to a subscribed SQS queue @@ -64,7 +66,7 @@ func TestIntegration_SNS_AddRemovePermissionRoundTrip(t *testing.T) { require.NoError(t, err) var policy snsPolicyDocument - require.NoError(t, json.Unmarshal([]byte(attrsOut.Attributes["Policy"]), &policy)) + require.NoError(t, json.Unmarshal([]byte(attrsOut.Attributes["Policy"]), &policy, jsonx.V1())) var granted *snsPolicyStatement @@ -90,7 +92,7 @@ func TestIntegration_SNS_AddRemovePermissionRoundTrip(t *testing.T) { require.NoError(t, err) var policyAfter snsPolicyDocument - require.NoError(t, json.Unmarshal([]byte(attrsOut2.Attributes["Policy"]), &policyAfter)) + require.NoError(t, json.Unmarshal([]byte(attrsOut2.Attributes["Policy"]), &policyAfter, jsonx.V1())) for _, stmt := range policyAfter.Statement { assert.NotEqual(t, label, stmt.Sid, "RemovePermission should drop the statement from Policy") @@ -244,7 +246,7 @@ func TestIntegration_SNS_PublishBatchRoundTrip(t *testing.T) { for _, msg := range recvOut.Messages { var env snsEnvelope - require.NoError(t, json.Unmarshal([]byte(aws.ToString(msg.Body)), &env)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(msg.Body)), &env, jsonx.V1())) assert.Equal(t, topicARN, env.TopicArn) priority := "" diff --git a/test/integration/sns_sqs_cross_test.go b/test/integration/sns_sqs_cross_test.go index 9a42496ac2..ba08b9eb91 100644 --- a/test/integration/sns_sqs_cross_test.go +++ b/test/integration/sns_sqs_cross_test.go @@ -1,7 +1,7 @@ package integration_test import ( - "encoding/json" + "encoding/json/v2" "testing" "github.com/aws/aws-sdk-go-v2/aws" @@ -12,6 +12,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) func TestIntegration_SNS_SQS_CrossService(t *testing.T) { @@ -71,7 +73,7 @@ func TestIntegration_SNS_SQS_CrossService(t *testing.T) { // Message body should be SNS envelope JSON var envelope map[string]any - require.NoError(t, json.Unmarshal([]byte(*recvOut.Messages[0].Body), &envelope)) + require.NoError(t, json.Unmarshal([]byte(*recvOut.Messages[0].Body), &envelope, jsonx.V1())) assert.Equal(t, "Notification", envelope["Type"]) // Cleanup @@ -286,7 +288,7 @@ func TestIntegration_SNS_SQS_RedrivePolicy(t *testing.T) { // DLQ receives the same body that was attempted to the failed queue. // Without RawMessageDelivery=true, that body is the SNS envelope JSON. var dlqEnvelope map[string]any - require.NoError(t, json.Unmarshal([]byte(*recvOut.Messages[0].Body), &dlqEnvelope)) + require.NoError(t, json.Unmarshal([]byte(*recvOut.Messages[0].Body), &dlqEnvelope, jsonx.V1())) assert.Equal(t, "Notification", dlqEnvelope["Type"]) assert.Equal(t, msgBody, dlqEnvelope["Message"]) diff --git a/test/integration/stepfunctions_asl_test.go b/test/integration/stepfunctions_asl_test.go index a511cc442b..b33b479ff1 100644 --- a/test/integration/stepfunctions_asl_test.go +++ b/test/integration/stepfunctions_asl_test.go @@ -1,7 +1,7 @@ package integration_test import ( - "encoding/json" + "encoding/json/v2" "fmt" "testing" "time" @@ -12,6 +12,8 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) // passThroughDefinition is a minimal ASL state machine that passes input through. @@ -335,7 +337,7 @@ func TestIntegration_StepFunctions_FullExecution(t *testing.T) { assert.Equal(t, "SUCCEEDED", string(descOut.Status)) var output map[string]any - require.NoError(t, json.Unmarshal([]byte(aws.ToString(descOut.Output)), &output)) + require.NoError(t, json.Unmarshal([]byte(aws.ToString(descOut.Output)), &output, jsonx.V1())) require.Contains(t, output, "original", "output should contain the original input field") assert.Equal(t, "data", output["original"]) meta, ok := output["meta"].(map[string]any) diff --git a/test/integration/swf_test.go b/test/integration/swf_test.go index 9301f160ea..f5679ccf73 100644 --- a/test/integration/swf_test.go +++ b/test/integration/swf_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,13 +10,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) func swfPost(t *testing.T, action string, body any) *http.Response { t.Helper() - bodyBytes, err := json.Marshal(body) + bodyBytes, err := json.Marshal(body, jsonx.V1()) require.NoError(t, err) req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, endpoint, bytes.NewReader(bodyBytes)) diff --git a/test/integration/verifiedpermissions_test.go b/test/integration/verifiedpermissions_test.go index 26f7cabf2d..31bbc1f750 100644 --- a/test/integration/verifiedpermissions_test.go +++ b/test/integration/verifiedpermissions_test.go @@ -2,7 +2,7 @@ package integration_test import ( "bytes" - "encoding/json" + "encoding/json/v2" "io" "net/http" "testing" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -20,7 +21,7 @@ func verifiedPermissionsPost(t *testing.T, action string, body any) *http.Respon if body != nil { var err error - bodyBytes, err = json.Marshal(body) + bodyBytes, err = json.Marshal(body, jsonx.V1()) require.NoError(t, err) } @@ -72,7 +73,7 @@ func TestIntegration_VerifiedPermissions_PolicyStoreLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createResp.StatusCode, "create body: %s", createBody) var createResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createBody), &createResult)) + require.NoError(t, json.Unmarshal([]byte(createBody), &createResult, jsonx.V1())) storeID, ok := createResult["policyStoreId"].(string) require.True(t, ok, "policyStoreId should be a string") require.NotEmpty(t, storeID) @@ -127,7 +128,7 @@ func TestIntegration_VerifiedPermissions_PolicyLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createStoreResp.StatusCode, "create store body: %s", createStoreBody) var storeResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createStoreBody), &storeResult)) + require.NoError(t, json.Unmarshal([]byte(createStoreBody), &storeResult, jsonx.V1())) storeID := storeResult["policyStoreId"].(string) // Create a policy. @@ -143,7 +144,7 @@ func TestIntegration_VerifiedPermissions_PolicyLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createPolicyResp.StatusCode, "create policy body: %s", createPolicyBody) var policyResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createPolicyBody), &policyResult)) + require.NoError(t, json.Unmarshal([]byte(createPolicyBody), &policyResult, jsonx.V1())) policyID := policyResult["policyId"].(string) require.NotEmpty(t, policyID) @@ -198,7 +199,7 @@ func TestIntegration_VerifiedPermissions_PolicyTemplateLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createStoreResp.StatusCode, "create store body: %s", createStoreBody) var storeResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createStoreBody), &storeResult)) + require.NoError(t, json.Unmarshal([]byte(createStoreBody), &storeResult, jsonx.V1())) storeID := storeResult["policyStoreId"].(string) // Create a policy template. @@ -211,7 +212,7 @@ func TestIntegration_VerifiedPermissions_PolicyTemplateLifecycle(t *testing.T) { require.Equal(t, http.StatusOK, createTplResp.StatusCode, "create template body: %s", createTplBody) var tplResult map[string]any - require.NoError(t, json.Unmarshal([]byte(createTplBody), &tplResult)) + require.NoError(t, json.Unmarshal([]byte(createTplBody), &tplResult, jsonx.V1())) templateID := tplResult["policyTemplateId"].(string) require.NotEmpty(t, templateID) diff --git a/test/internal/tofu/download.go b/test/internal/tofu/download.go index b08d0492f8..74096f6076 100644 --- a/test/internal/tofu/download.go +++ b/test/internal/tofu/download.go @@ -8,7 +8,8 @@ import ( "archive/zip" "bytes" "context" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "io" @@ -16,6 +17,8 @@ import ( "os" "runtime" "strings" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) var ( @@ -48,7 +51,7 @@ func DownloadBinary(ctx context.Context, logf func(format string, args ...any)) } `json:"versions"` } - if err = json.NewDecoder(resp.Body).Decode(&api); err != nil { + if err = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &api, jsonx.V1()); err != nil { return "", fmt.Errorf("decoding OpenTofu version list: %w", err) } diff --git a/test/terraform/azure/cosmosdb_test.go b/test/terraform/azure/cosmosdb_test.go index de81ca4702..af77bb373d 100644 --- a/test/terraform/azure/cosmosdb_test.go +++ b/test/terraform/azure/cosmosdb_test.go @@ -1,7 +1,7 @@ package azure_test import ( - "encoding/json" + "encoding/json/v2" "os" "os/exec" "strings" @@ -10,6 +10,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const azureCosmosFixture = ` @@ -150,7 +152,7 @@ func TestTerraform_Azure_CosmosDB(t *testing.T) { require.NoError(t, err) pk := azcosmos.NewPartitionKeyString("p1") - item, err := json.Marshal(map[string]any{"id": "item1", "pk": "p1", "email": "a@example.com"}) + item, err := json.Marshal(map[string]any{"id": "item1", "pk": "p1", "email": "a@example.com"}, jsonx.V1()) require.NoError(t, err) ctx := t.Context() @@ -182,7 +184,7 @@ func TestTerraform_Azure_CosmosDB(t *testing.T) { func mustJSON(t *testing.T, v any) []byte { t.Helper() - b, err := json.Marshal(v) + b, err := json.Marshal(v, jsonx.V1()) require.NoError(t, err) return b @@ -192,7 +194,7 @@ func stripSystemFields(t *testing.T, raw []byte) string { t.Helper() var m map[string]any - require.NoError(t, json.Unmarshal(raw, &m)) + require.NoError(t, json.Unmarshal(raw, &m, jsonx.V1())) for k := range m { if strings.HasPrefix(k, "_") { diff --git a/test/terraform/azure/eventgrid_test.go b/test/terraform/azure/eventgrid_test.go index 45cf2d2606..76ea1c018a 100644 --- a/test/terraform/azure/eventgrid_test.go +++ b/test/terraform/azure/eventgrid_test.go @@ -5,7 +5,7 @@ import ( "context" "crypto/tls" "crypto/x509" - "encoding/json" + "encoding/json/v2" "io" "net/http" "os" @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/azureauth" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( @@ -146,7 +147,7 @@ func armCallAPI(ctx context.Context, t *testing.T, c *http.Client, method, path, var out map[string]any - require.NoError(t, json.Unmarshal(raw, &out)) + require.NoError(t, json.Unmarshal(raw, &out, jsonx.V1())) return out } @@ -209,7 +210,7 @@ func verifyEventGridRoundTrip(t *testing.T) { var got map[string]any - require.NoError(t, json.Unmarshal([]byte(text), &got)) + require.NoError(t, json.Unmarshal([]byte(text), &got, jsonx.V1())) assert.Equal(t, "from-terraform", got["id"]) assert.Equal(t, "App.Thing", got["eventType"]) assert.Contains(t, got["topic"], "Microsoft.EventGrid/topics/"+azureEventGridTopicName) diff --git a/test/terraform/azure/servicebus_test.go b/test/terraform/azure/servicebus_test.go index 7d24f16945..5fe5016a7c 100644 --- a/test/terraform/azure/servicebus_test.go +++ b/test/terraform/azure/servicebus_test.go @@ -11,7 +11,7 @@ package azure_test import ( - "encoding/json" + "encoding/json/v2" "io" "net/http" "strings" @@ -20,6 +20,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -162,7 +163,7 @@ func verifyServiceBusQueueRoundTrip(t *testing.T) { assert.Equal(t, messageBody, string(gotBody)) var bp sbBrokerProperties - require.NoError(t, json.Unmarshal([]byte(resp.Header.Get("Brokerproperties")), &bp)) + require.NoError(t, json.Unmarshal([]byte(resp.Header.Get("Brokerproperties")), &bp, jsonx.V1())) require.NotEmpty(t, bp.LockToken) location := resp.Header.Get("Location") diff --git a/test/terraform/terraform_test.go b/test/terraform/terraform_test.go index 066923c93d..3656410958 100644 --- a/test/terraform/terraform_test.go +++ b/test/terraform/terraform_test.go @@ -5,7 +5,8 @@ import ( "bytes" "context" "embed" - "encoding/json" + "encoding/json/jsontext" + "encoding/json/v2" "errors" "fmt" "hash/fnv" @@ -152,6 +153,7 @@ import ( "github.com/stretchr/testify/require" "github.com/blackbirdworks/gopherstack/pkgs/httpclient" + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/testclient" ) @@ -689,7 +691,7 @@ func downloadTofuBinary(logger *slog.Logger) (string, error) { ID string `json:"id"` } `json:"versions"` } - err = json.NewDecoder(resp.Body).Decode(&api) + err = json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &api, jsonx.V1()) if err != nil { return "", fmt.Errorf("decoding OpenTofu version list: %w", err) } @@ -3558,7 +3560,7 @@ func TestTerraform_SESv2(t *testing.T) { "email identity %q should exist after terraform apply", email) var identityOut map[string]any - require.NoError(t, json.NewDecoder(resp.Body).Decode(&identityOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp.Body), &identityOut, jsonx.V1())) assert.Equal(t, "EMAIL_ADDRESS", identityOut["IdentityType"]) // Verify configuration set was created. @@ -3574,7 +3576,7 @@ func TestTerraform_SESv2(t *testing.T) { "configuration set %q should exist after terraform apply", cfgName) var cfgOut map[string]any - require.NoError(t, json.NewDecoder(resp2.Body).Decode(&cfgOut)) + require.NoError(t, json.UnmarshalDecode(jsontext.NewDecoder(resp2.Body), &cfgOut, jsonx.V1())) assert.Equal(t, cfgName, cfgOut["ConfigurationSetName"]) }, }, @@ -4706,7 +4708,7 @@ func TestTerraform_CloudControl(t *testing.T) { for _, rd := range out.ResourceDescriptions { var props map[string]any propsJSON := []byte(aws.ToString(rd.Properties)) - if unmarshalErr := json.Unmarshal(propsJSON, &props); unmarshalErr == nil { + if unmarshalErr := json.Unmarshal(propsJSON, &props, jsonx.V1()); unmarshalErr == nil { if props["LogGroupName"] == expectedName { foundIdentifier = aws.ToString(rd.Identifier) @@ -6612,7 +6614,7 @@ func TestTerraform_ServerlessRepo(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "expected 200 OK, body: %s", string(body)) var result map[string]any - require.NoError(t, json.Unmarshal(body, &result)) + require.NoError(t, json.Unmarshal(body, &result, jsonx.V1())) assert.Equal(t, appName, result["name"]) }, }, @@ -6668,7 +6670,7 @@ func TestTerraform_Shield(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "expected 200 OK, body: %s", string(respBody)) var result map[string]string - require.NoError(t, json.Unmarshal(respBody, &result)) + require.NoError(t, json.Unmarshal(respBody, &result, jsonx.V1())) assert.Equal(t, "ACTIVE", result["SubscriptionState"]) }, }, @@ -6786,7 +6788,7 @@ func TestTerraform_Textract(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "expected 200 OK, body: %s", string(respBody)) var result map[string]any - require.NoError(t, json.Unmarshal(respBody, &result)) + require.NoError(t, json.Unmarshal(respBody, &result, jsonx.V1())) blocks, ok := result["Blocks"].([]any) assert.True(t, ok, "expected Blocks in response") assert.NotEmpty(t, blocks, "expected non-empty Blocks") @@ -6848,7 +6850,7 @@ func TestTerraform_TimestreamWrite(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "expected 200 OK, body: %s", string(respBody)) var result map[string]any - require.NoError(t, json.Unmarshal(respBody, &result)) + require.NoError(t, json.Unmarshal(respBody, &result, jsonx.V1())) db, ok := result["Database"].(map[string]any) assert.True(t, ok, "expected Database in response") assert.Equal(t, databaseName, db["DatabaseName"]) @@ -7105,7 +7107,7 @@ func TestTerraform_Wafv2(t *testing.T) { assert.Equal(t, http.StatusOK, resp.StatusCode, "expected 200 OK, body: %s", string(respBody)) var result map[string]any - require.NoError(t, json.Unmarshal(respBody, &result)) + require.NoError(t, json.Unmarshal(respBody, &result, jsonx.V1())) webACLs, ok := result["WebACLs"].([]any) require.True(t, ok) From 4ae46fb0a14b6bedf1e0cb4ab40917e72e7052a8 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 13:52:07 -0600 Subject: [PATCH 08/11] refactor(json): lint fixes for services m-z (dupl scope, import comment, unused nolint) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- services/memorydb/handler_parameter_groups.go | 7 ++++++- services/memorydb/handler_subnet_groups.go | 7 ++++++- services/rds/engine_dumpstore.go | 5 +---- services/redshiftdata/engine_pgx.go | 4 ++-- services/sagemaker/handler_endpoint_configs.go | 6 +++++- services/sagemaker/handler_models.go | 6 +++++- services/sesv2/handler_email_identities.go | 12 ++++++++++-- services/timestreaminfluxdb/secrets.go | 2 +- 8 files changed, 36 insertions(+), 13 deletions(-) diff --git a/services/memorydb/handler_parameter_groups.go b/services/memorydb/handler_parameter_groups.go index 868477dad3..f5982753b2 100644 --- a/services/memorydb/handler_parameter_groups.go +++ b/services/memorydb/handler_parameter_groups.go @@ -34,7 +34,12 @@ func (h *Handler) handleCreateParameterGroup(ctx context.Context, c *echo.Contex return c.JSON(http.StatusOK, createParameterGroupResponse{ParameterGroup: toParameterGroupObject(pg)}) } -func (h *Handler) handleDescribeParameterGroups(ctx context.Context, c *echo.Context, body []byte) error { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleDescribeParameterGroups( + ctx context.Context, + c *echo.Context, + body []byte, +) error { var req describeParameterGroupRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { diff --git a/services/memorydb/handler_subnet_groups.go b/services/memorydb/handler_subnet_groups.go index e19cc1f89e..2bd198102e 100644 --- a/services/memorydb/handler_subnet_groups.go +++ b/services/memorydb/handler_subnet_groups.go @@ -35,7 +35,12 @@ func (h *Handler) handleCreateSubnetGroup(ctx context.Context, c *echo.Context, return c.JSON(http.StatusOK, createSubnetGroupResponse{SubnetGroup: toSubnetGroupObject(sg)}) } -func (h *Handler) handleDescribeSubnetGroups(ctx context.Context, c *echo.Context, body []byte) error { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleDescribeSubnetGroups( + ctx context.Context, + c *echo.Context, + body []byte, +) error { var req describeSubnetGroupRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { diff --git a/services/rds/engine_dumpstore.go b/services/rds/engine_dumpstore.go index d1e72ee5f7..e810e4cb6a 100644 --- a/services/rds/engine_dumpstore.go +++ b/services/rds/engine_dumpstore.go @@ -49,10 +49,7 @@ func (s *dumpStore) save(key string, at time.Time, d engineData) error { rec := dumpRecord{At: at, Key: key, Dump: d.dump, Password: d.password, DBName: d.dbName} - raw, err := json.Marshal( - rec, - jsonx.V1(), - ) //nolint:gosec // the master password must come back with the restored data + raw, err := json.Marshal(rec, jsonx.V1()) if err != nil { return fmt.Errorf("marshal dump: %w", err) } diff --git a/services/redshiftdata/engine_pgx.go b/services/redshiftdata/engine_pgx.go index 607fd12a5a..7db0d3069c 100644 --- a/services/redshiftdata/engine_pgx.go +++ b/services/redshiftdata/engine_pgx.go @@ -16,9 +16,9 @@ import ( "time" "github.com/jackc/pgx/v5/pgconn" - _ "github.com/jackc/pgx/v5/stdlib" + _ "github.com/jackc/pgx/v5/stdlib" // registers the "pgx" database/sql driver - "github.com/blackbirdworks/gopherstack/pkgs/jsonx" // registers the "pgx" database/sql driver + "github.com/blackbirdworks/gopherstack/pkgs/jsonx" ) const ( diff --git a/services/sagemaker/handler_endpoint_configs.go b/services/sagemaker/handler_endpoint_configs.go index f026a0a3e8..5229554264 100644 --- a/services/sagemaker/handler_endpoint_configs.go +++ b/services/sagemaker/handler_endpoint_configs.go @@ -144,7 +144,11 @@ func (h *Handler) handleDescribeEndpointConfig(ctx context.Context, body []byte) return json.Marshal(resp, jsonx.V1()) } -func (h *Handler) handleListEndpointConfigs(ctx context.Context, body []byte) ([]byte, error) { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleListEndpointConfigs( + ctx context.Context, + body []byte, +) ([]byte, error) { var req nameTimeListRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { diff --git a/services/sagemaker/handler_models.go b/services/sagemaker/handler_models.go index 5380f27c90..9ad05cc9be 100644 --- a/services/sagemaker/handler_models.go +++ b/services/sagemaker/handler_models.go @@ -140,7 +140,11 @@ func (h *Handler) handleDescribeModel(ctx context.Context, body []byte) ([]byte, return json.Marshal(resp, jsonx.V1()) } -func (h *Handler) handleListModels(ctx context.Context, body []byte) ([]byte, error) { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleListModels( + ctx context.Context, + body []byte, +) ([]byte, error) { var req nameTimeListRequest if err := json.Unmarshal(body, &req, jsonx.V1()); err != nil { diff --git a/services/sesv2/handler_email_identities.go b/services/sesv2/handler_email_identities.go index 18707a512f..4d07ec0275 100644 --- a/services/sesv2/handler_email_identities.go +++ b/services/sesv2/handler_email_identities.go @@ -167,7 +167,11 @@ func (h *Handler) handleDeleteEmailIdentity(identity string) (any, error) { return &emptyDeleteOutput{}, nil } -func (h *Handler) handleCreateEmailIdentityPolicy(c *echo.Context, identity string) (any, error) { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleCreateEmailIdentityPolicy( + c *echo.Context, + identity string, +) (any, error) { // Extract policyName from the URL: .../identities/{identity}/policies/{policyName} segments := strings.Split(strings.TrimPrefix(c.Request().URL.Path, sesv2PathPrefix), "/") if len(segments) < policyPathMinSegments { @@ -222,7 +226,11 @@ func (h *Handler) handleDeleteEmailIdentityPolicy(c *echo.Context, identity stri return &emptyDeleteOutput{}, nil } -func (h *Handler) handleUpdateEmailIdentityPolicy(c *echo.Context, identity string) (any, error) { +//nolint:dupl // structurally similar handlers +func (h *Handler) handleUpdateEmailIdentityPolicy( + c *echo.Context, + identity string, +) (any, error) { segments := strings.Split(strings.TrimPrefix(c.Request().URL.Path, sesv2PathPrefix), "/") if len(segments) < policyPathMinSegments { return nil, fmt.Errorf("%w: invalid policy path", ErrInvalidInput) diff --git a/services/timestreaminfluxdb/secrets.go b/services/timestreaminfluxdb/secrets.go index ca0620948f..dfcb154398 100644 --- a/services/timestreaminfluxdb/secrets.go +++ b/services/timestreaminfluxdb/secrets.go @@ -40,7 +40,7 @@ func (b *InMemoryBackend) authSecretLocked(sc scope, id string, a authSecret) (s return "", nil } - body, err := json.Marshal(a, jsonx.V1()) //nolint:gosec // the secret holds the credentials by design + body, err := json.Marshal(a, jsonx.V1()) if err != nil { return "", fail(ErrInternalServer, "encode auth secret") } From 7904d3dd75c1ee9d72a53020a5d595828c4fd8d7 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 16:04:53 -0600 Subject: [PATCH 09/11] fix(security): make JSON responses and int narrowing recognisable to CodeQL under json/v2 CodeQL sanitises v1 json.Marshal output for reflected-xss (JsonMarshalSanitizer) and does not model v2, so OCI/ssoadmin JSON writers were flagged. Write JSON via httputils.WriteJSONBytes (literal JSON Content-Type on a local writer plus nosniff). Add jsonx.Number.Int and constant int32 bounds checks where ParseInt(64) results were narrowed to int. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/httputils/httputils.go | 8 ++++++ pkgs/httputils/httputils_test.go | 28 +++++++++++++++++++ pkgs/jsonx/jsonx.go | 3 +++ pkgs/jsonx/jsonx_test.go | 33 +++++++++++++++++++++++ services/appsync/ddb_ops.go | 4 +-- services/appsync/vtl_bounds_test.go | 33 +++++++++++++++++++++++ services/appsync/vtl_eval.go | 8 ++++++ services/appsync/vtl_methods.go | 4 +-- services/cosmosdb/sql_funcs_more.go | 10 +++---- services/gcpbigquery/jobs_query.go | 4 +-- services/ociapigateway/handler.go | 5 ++-- services/ociartifacts/handler.go | 5 ++-- services/ocicontainerengine/handler.go | 5 ++-- services/ocicontainerinstances/handler.go | 5 ++-- services/ocicore/handler.go | 5 ++-- services/ocievents/handler.go | 5 ++-- services/ocifunctions/handler.go | 5 ++-- services/ociidentity/handler.go | 5 ++-- services/ociloadbalancer/handler.go | 5 ++-- services/ocilogging/handler.go | 5 ++-- services/ocimonitoring/handler.go | 5 ++-- services/ocimysql/handler.go | 5 ++-- services/ocinosql/handler.go | 5 ++-- services/ocinotifications/handler.go | 5 ++-- services/ociobjectstorage/handler.go | 10 +++---- services/ociqueue/handler.go | 5 ++-- services/ocistreaming/handler.go | 5 ++-- services/ocivault/handler.go | 5 ++-- services/sqs/dead_letter.go | 4 +-- services/ssoadmin/handler.go | 9 ++++--- 30 files changed, 171 insertions(+), 72 deletions(-) create mode 100644 services/appsync/vtl_bounds_test.go diff --git a/pkgs/httputils/httputils.go b/pkgs/httputils/httputils.go index c9144fcc5a..0559ad7fa7 100644 --- a/pkgs/httputils/httputils.go +++ b/pkgs/httputils/httputils.go @@ -645,3 +645,11 @@ func ReadBodyLimit(r *http.Request, limit int64) ([]byte, error) { return body, nil } + +// WriteJSONBytes writes an already-encoded JSON body with a JSON content type. +func WriteJSONBytes(w http.ResponseWriter, code int, body []byte) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(code) + _, _ = w.Write(body) +} diff --git a/pkgs/httputils/httputils_test.go b/pkgs/httputils/httputils_test.go index 468845aaa2..14f4082fe4 100644 --- a/pkgs/httputils/httputils_test.go +++ b/pkgs/httputils/httputils_test.go @@ -458,3 +458,31 @@ func TestWriteS3ErrorResponse(t *testing.T) { assert.Equal(t, "application/xml", w.Header().Get("Content-Type")) assert.Contains(t, w.Body.String(), "NoSuchKey") } + +func TestWriteJSONBytes(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + body []byte + wantBody string + code int + }{ + {name: "with_body", body: []byte(`{"a":1}`), wantBody: `{"a":1}`, code: http.StatusCreated}, + {name: "no_body", body: nil, wantBody: "", code: http.StatusOK}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + rec := httptest.NewRecorder() + httputils.WriteJSONBytes(rec, tt.code, tt.body) + + assert.Equal(t, tt.code, rec.Code) + assert.Equal(t, "application/json", rec.Header().Get("Content-Type")) + assert.Equal(t, "nosniff", rec.Header().Get("X-Content-Type-Options")) + assert.Equal(t, tt.wantBody, rec.Body.String()) + }) + } +} diff --git a/pkgs/jsonx/jsonx.go b/pkgs/jsonx/jsonx.go index c98f0ed4a5..b8fbc13ca0 100644 --- a/pkgs/jsonx/jsonx.go +++ b/pkgs/jsonx/jsonx.go @@ -131,6 +131,9 @@ func (n Number) Float64() (float64, error) { return strconv.ParseFloat(string(n) // Int64 returns the number as an int64. func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } +// Int returns the number as an int, failing when it is out of int range. +func (n Number) Int() (int, error) { return strconv.Atoi(string(n)) } + // MarshalJSON emits the number literal; an empty Number is 0 like v1. func (n Number) MarshalJSON() ([]byte, error) { if n == "" { diff --git a/pkgs/jsonx/jsonx_test.go b/pkgs/jsonx/jsonx_test.go index 89f976a3cb..8393123ace 100644 --- a/pkgs/jsonx/jsonx_test.go +++ b/pkgs/jsonx/jsonx_test.go @@ -157,3 +157,36 @@ func TestErrorClassifiers(t *testing.T) { _, ok := jsonx.SyntaxError(json.Unmarshal([]byte(`{"a":1}x`), new(doc), jsonx.V1())) assert.True(t, ok) } + +func TestNumberInt(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + in jsonx.Number + want int + wantErr bool + }{ + {name: "positive", in: "42", want: 42}, + {name: "negative", in: "-7", want: -7}, + {name: "fraction", in: "1.5", wantErr: true}, + {name: "overflow", in: "99999999999999999999", wantErr: true}, + {name: "empty", in: "", wantErr: true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := tt.in.Int() + if tt.wantErr { + require.Error(t, err) + + return + } + + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/services/appsync/ddb_ops.go b/services/appsync/ddb_ops.go index 6c11e62198..1d8c65fccd 100644 --- a/services/appsync/ddb_ops.go +++ b/services/appsync/ddb_ops.go @@ -237,9 +237,9 @@ func intOf(v any) int { case int: return n case jsonx.Number: - i, _ := n.Int64() + i, _ := n.Int() - return int(i) + return i default: return 0 } diff --git a/services/appsync/vtl_bounds_test.go b/services/appsync/vtl_bounds_test.go new file mode 100644 index 0000000000..32c981e885 --- /dev/null +++ b/services/appsync/vtl_bounds_test.go @@ -0,0 +1,33 @@ +package appsync_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/blackbirdworks/gopherstack/services/appsync" +) + +func TestRenderVTL_ListIndexBounds(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + tmpl string + want string + }{ + {name: "in_range", tmpl: `#set($l=["a","b"])$l.remove(1)|$l.size()`, want: "b|1"}, + {name: "beyond_int32", tmpl: `#set($l=["a","b"])$l.remove(5000000000)|$l.size()`, want: "$l.remove(5000000000)|2"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := appsync.RenderVTL(tt.tmpl, nil, nil) + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/services/appsync/vtl_eval.go b/services/appsync/vtl_eval.go index 28ef040e88..18ddf38015 100644 --- a/services/appsync/vtl_eval.go +++ b/services/appsync/vtl_eval.go @@ -790,6 +790,14 @@ func toInt(v any) (int, bool) { return 0, false } + return smallInt(f) +} + +func smallInt(f float64) (int, bool) { + if f < math.MinInt32 || f > math.MaxInt32 { + return 0, false + } + return int(f), true } diff --git a/services/appsync/vtl_methods.go b/services/appsync/vtl_methods.go index 6f099213f2..ff4af63f11 100644 --- a/services/appsync/vtl_methods.go +++ b/services/appsync/vtl_methods.go @@ -263,8 +263,8 @@ func listIndexOf(l *vlist, v any) int { func listRemove(l *vlist, v any) any { if f, isInt, ok := toNum(v); ok && isInt { - i := int(f) - if i < 0 || i >= len(l.items) { + i, small := smallInt(f) + if !small || i < 0 || i >= len(l.items) { return unknownMethod() } diff --git a/services/cosmosdb/sql_funcs_more.go b/services/cosmosdb/sql_funcs_more.go index 9bad347f3b..864d9b83f5 100644 --- a/services/cosmosdb/sql_funcs_more.go +++ b/services/cosmosdb/sql_funcs_more.go @@ -407,8 +407,8 @@ func moreCollection(name string, args []any) any { return args[arityPair] case biChoose: - i, ok := int64Arg(args[0]) - if !ok || i < 1 || int(i) >= len(args) { + i, ok := intArg(args[0]) + if !ok || i < 1 || i >= len(args) { return undef{} } @@ -606,12 +606,12 @@ func (ec *evalCtx) regexOp(name string, args []any) any { group := 0 if len(args) > regexGroupArg { - g, gok := int64Arg(args[regexGroupArg]) - if !gok || g < 0 || int(g) > re.NumSubexp() { + g, gok := intArg(args[regexGroupArg]) + if !gok || g < 0 || g > re.NumSubexp() { return undef{} } - group = int(g) + group = g } return extractRegex(re, subject, group, name == biRegexextractall) diff --git a/services/gcpbigquery/jobs_query.go b/services/gcpbigquery/jobs_query.go index f0eb0a30d3..89cb8d3a03 100644 --- a/services/gcpbigquery/jobs_query.go +++ b/services/gcpbigquery/jobs_query.go @@ -40,9 +40,9 @@ type datasetRef struct { func intOf(v any) (int, bool) { switch t := v.(type) { case jsonx.Number: - n, err := t.Int64() + n, err := t.Int() - return int(n), err == nil + return n, err == nil case float64: return int(t), true case string: diff --git a/services/ociapigateway/handler.go b/services/ociapigateway/handler.go index 69cec4f7f0..e98844c165 100644 --- a/services/ociapigateway/handler.go +++ b/services/ociapigateway/handler.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -127,9 +128,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ociartifacts/handler.go b/services/ociartifacts/handler.go index 2520893c7a..efcd5df436 100644 --- a/services/ociartifacts/handler.go +++ b/services/ociartifacts/handler.go @@ -21,6 +21,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -129,9 +130,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocicontainerengine/handler.go b/services/ocicontainerengine/handler.go index dfa6cc9b02..0dbcf22207 100644 --- a/services/ocicontainerengine/handler.go +++ b/services/ocicontainerengine/handler.go @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -125,9 +126,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocicontainerinstances/handler.go b/services/ocicontainerinstances/handler.go index b7d3610826..2954bf5269 100644 --- a/services/ocicontainerinstances/handler.go +++ b/services/ocicontainerinstances/handler.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -127,9 +128,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocicore/handler.go b/services/ocicore/handler.go index 86bde9aa17..9dbc45d914 100644 --- a/services/ocicore/handler.go +++ b/services/ocicore/handler.go @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -124,9 +125,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocievents/handler.go b/services/ocievents/handler.go index 1dc775fb16..93bbce8cbb 100644 --- a/services/ocievents/handler.go +++ b/services/ocievents/handler.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -126,9 +127,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocifunctions/handler.go b/services/ocifunctions/handler.go index ec40a337c5..989087c535 100644 --- a/services/ocifunctions/handler.go +++ b/services/ocifunctions/handler.go @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -126,9 +127,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ociidentity/handler.go b/services/ociidentity/handler.go index 1d6274e9aa..3c00c18ed6 100644 --- a/services/ociidentity/handler.go +++ b/services/ociidentity/handler.go @@ -14,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -123,9 +124,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ociloadbalancer/handler.go b/services/ociloadbalancer/handler.go index d6efc9b90b..942fbce6c3 100644 --- a/services/ociloadbalancer/handler.go +++ b/services/ociloadbalancer/handler.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -127,9 +128,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocilogging/handler.go b/services/ocilogging/handler.go index 9564c52e0d..4777977912 100644 --- a/services/ocilogging/handler.go +++ b/services/ocilogging/handler.go @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -125,9 +126,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocimonitoring/handler.go b/services/ocimonitoring/handler.go index 6e2a129c60..a760cd4499 100644 --- a/services/ocimonitoring/handler.go +++ b/services/ocimonitoring/handler.go @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -125,9 +126,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocimysql/handler.go b/services/ocimysql/handler.go index 75346061cc..8e1d93291c 100644 --- a/services/ocimysql/handler.go +++ b/services/ocimysql/handler.go @@ -15,6 +15,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -125,9 +126,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocinosql/handler.go b/services/ocinosql/handler.go index dfb281ccec..ee846e70e9 100644 --- a/services/ocinosql/handler.go +++ b/services/ocinosql/handler.go @@ -17,6 +17,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -127,9 +128,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocinotifications/handler.go b/services/ocinotifications/handler.go index 0250d6844e..713514fdd5 100644 --- a/services/ocinotifications/handler.go +++ b/services/ocinotifications/handler.go @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -127,9 +128,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ociobjectstorage/handler.go b/services/ociobjectstorage/handler.go index b20647f401..0861f616f8 100644 --- a/services/ociobjectstorage/handler.go +++ b/services/ociobjectstorage/handler.go @@ -13,6 +13,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -118,13 +119,12 @@ func (q *req) json(status int, v any) error { return fmt.Errorf("ociobjectstorage: encode response: %w", err) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - - if q.r.Method != http.MethodHead { - _, _ = q.w.Write(out) + if q.r.Method == http.MethodHead { + out = nil } + httputils.WriteJSONBytes(q.w, status, out) + return nil } diff --git a/services/ociqueue/handler.go b/services/ociqueue/handler.go index 74493562ac..a97c4c777f 100644 --- a/services/ociqueue/handler.go +++ b/services/ociqueue/handler.go @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -126,9 +127,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocistreaming/handler.go b/services/ocistreaming/handler.go index 4220d6d96f..16e9a24e15 100644 --- a/services/ocistreaming/handler.go +++ b/services/ocistreaming/handler.go @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -126,9 +127,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/ocivault/handler.go b/services/ocivault/handler.go index 0ec2c2d340..0689cff9a4 100644 --- a/services/ocivault/handler.go +++ b/services/ocivault/handler.go @@ -16,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/labstack/echo/v5" + "github.com/blackbirdworks/gopherstack/pkgs/httputils" "github.com/blackbirdworks/gopherstack/pkgs/jsonx" "github.com/blackbirdworks/gopherstack/pkgs/lockmetrics" "github.com/blackbirdworks/gopherstack/pkgs/logger" @@ -125,9 +126,7 @@ func (q *req) json(status int, v any, etag string) error { q.header("etag", etag) } - q.header("Content-Type", "application/json") - q.w.WriteHeader(status) - _, _ = q.w.Write(out) + httputils.WriteJSONBytes(q.w, status, out) return nil } diff --git a/services/sqs/dead_letter.go b/services/sqs/dead_letter.go index 4273e2322e..13ae714e34 100644 --- a/services/sqs/dead_letter.go +++ b/services/sqs/dead_letter.go @@ -37,7 +37,7 @@ func applyRedrivePolicy(q *Queue, attrs map[string]string, backend *InMemoryBack return &InvalidParameterError{Message: "Invalid value for the parameter RedrivePolicy."} } - count, err := pol.MaxReceiveCount.Int64() + count, err := pol.MaxReceiveCount.Int() if err != nil || count <= 0 { return &InvalidParameterError{Message: "Invalid value for the parameter RedrivePolicy."} } @@ -183,7 +183,7 @@ func (b *InMemoryBackend) ListDeadLetterSourceQueues( continue } - count, err := pol.MaxReceiveCount.Int64() + count, err := pol.MaxReceiveCount.Int() if err != nil || count <= 0 { continue } diff --git a/services/ssoadmin/handler.go b/services/ssoadmin/handler.go index 235d5ab5a8..02f1a76edf 100644 --- a/services/ssoadmin/handler.go +++ b/services/ssoadmin/handler.go @@ -741,9 +741,12 @@ func writeJSON(c *echo.Context, status int, v any) error { if err != nil { return err } - c.Response().Header().Set("Content-Type", "application/x-amz-json-1.1") - c.Response().WriteHeader(status) - _, _ = c.Response().Write(data) + var w http.ResponseWriter = c.Response() + + w.Header().Set("Content-Type", "application/x-amz-json-1.1") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(status) + _, _ = w.Write(data) return nil } From 6631de8e15aab5d556eec7aa58ed74590a8fed05 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 16:09:26 -0600 Subject: [PATCH 10/11] fix(security): lint fixes for CodeQL json/v2 changes Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/httputils/httputils_test.go | 4 ++-- services/appsync/vtl_bounds_test.go | 6 +++++- services/sqs/dead_letter.go | 2 +- services/ssoadmin/handler.go | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkgs/httputils/httputils_test.go b/pkgs/httputils/httputils_test.go index 14f4082fe4..7130d0ac68 100644 --- a/pkgs/httputils/httputils_test.go +++ b/pkgs/httputils/httputils_test.go @@ -464,12 +464,12 @@ func TestWriteJSONBytes(t *testing.T) { tests := []struct { name string - body []byte wantBody string + body []byte code int }{ {name: "with_body", body: []byte(`{"a":1}`), wantBody: `{"a":1}`, code: http.StatusCreated}, - {name: "no_body", body: nil, wantBody: "", code: http.StatusOK}, + {name: "no_body", wantBody: "", code: http.StatusOK}, } for _, tt := range tests { diff --git a/services/appsync/vtl_bounds_test.go b/services/appsync/vtl_bounds_test.go index 32c981e885..acddcc4f71 100644 --- a/services/appsync/vtl_bounds_test.go +++ b/services/appsync/vtl_bounds_test.go @@ -18,7 +18,11 @@ func TestRenderVTL_ListIndexBounds(t *testing.T) { want string }{ {name: "in_range", tmpl: `#set($l=["a","b"])$l.remove(1)|$l.size()`, want: "b|1"}, - {name: "beyond_int32", tmpl: `#set($l=["a","b"])$l.remove(5000000000)|$l.size()`, want: "$l.remove(5000000000)|2"}, + { + name: "beyond_int32", + tmpl: `#set($l=["a","b"])$l.remove(5000000000)|$l.size()`, + want: "$l.remove(5000000000)|2", + }, } for _, tt := range tests { diff --git a/services/sqs/dead_letter.go b/services/sqs/dead_letter.go index 13ae714e34..02b8e48cf9 100644 --- a/services/sqs/dead_letter.go +++ b/services/sqs/dead_letter.go @@ -73,7 +73,7 @@ func applyRedrivePolicy(q *Queue, attrs map[string]string, backend *InMemoryBack } } - q.MaxReceiveCount = int(count) + q.MaxReceiveCount = count q.dlq = dlq now := backend.now() diff --git a/services/ssoadmin/handler.go b/services/ssoadmin/handler.go index 02f1a76edf..d625890ad2 100644 --- a/services/ssoadmin/handler.go +++ b/services/ssoadmin/handler.go @@ -741,7 +741,7 @@ func writeJSON(c *echo.Context, status int, v any) error { if err != nil { return err } - var w http.ResponseWriter = c.Response() + w := http.ResponseWriter(c.Response()) w.Header().Set("Content-Type", "application/x-amz-json-1.1") w.Header().Set("X-Content-Type-Options", "nosniff") From f78e9c5c7eeb6d794bc9cb6078bbefeeaa58fd40 Mon Sep 17 00:00:00 2001 From: Witness Patrol Date: Sun, 1 Nov 2026 16:14:17 -0600 Subject: [PATCH 11/11] fix(security): route ssoadmin JSON writes through httputils Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01FGWXecoauvZN2AYe1vkvgM --- pkgs/httputils/httputils.go | 8 ++++++++ pkgs/httputils/httputils_test.go | 12 ++++++++++++ services/ssoadmin/handler.go | 7 +------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/pkgs/httputils/httputils.go b/pkgs/httputils/httputils.go index 0559ad7fa7..dd328e7244 100644 --- a/pkgs/httputils/httputils.go +++ b/pkgs/httputils/httputils.go @@ -653,3 +653,11 @@ func WriteJSONBytes(w http.ResponseWriter, code int, body []byte) { w.WriteHeader(code) _, _ = w.Write(body) } + +// WriteAmzJSON11Bytes writes an already-encoded body as application/x-amz-json-1.1. +func WriteAmzJSON11Bytes(w http.ResponseWriter, code int, body []byte) { + w.Header().Set("Content-Type", "application/x-amz-json-1.1") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.WriteHeader(code) + _, _ = w.Write(body) +} diff --git a/pkgs/httputils/httputils_test.go b/pkgs/httputils/httputils_test.go index 7130d0ac68..1cebcab8f8 100644 --- a/pkgs/httputils/httputils_test.go +++ b/pkgs/httputils/httputils_test.go @@ -486,3 +486,15 @@ func TestWriteJSONBytes(t *testing.T) { }) } } + +func TestWriteAmzJSON11Bytes(t *testing.T) { + t.Parallel() + + rec := httptest.NewRecorder() + httputils.WriteAmzJSON11Bytes(rec, http.StatusAccepted, []byte(`{}`)) + + assert.Equal(t, http.StatusAccepted, rec.Code) + assert.Equal(t, "application/x-amz-json-1.1", rec.Header().Get("Content-Type")) + assert.Equal(t, "nosniff", rec.Header().Get("X-Content-Type-Options")) + assert.JSONEq(t, `{}`, rec.Body.String()) +} diff --git a/services/ssoadmin/handler.go b/services/ssoadmin/handler.go index d625890ad2..b729c874da 100644 --- a/services/ssoadmin/handler.go +++ b/services/ssoadmin/handler.go @@ -741,12 +741,7 @@ func writeJSON(c *echo.Context, status int, v any) error { if err != nil { return err } - w := http.ResponseWriter(c.Response()) - - w.Header().Set("Content-Type", "application/x-amz-json-1.1") - w.Header().Set("X-Content-Type-Options", "nosniff") - w.WriteHeader(status) - _, _ = w.Write(data) + httputils.WriteAmzJSON11Bytes(c.Response(), status, data) return nil }

      CcHa^*q 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

    3. ?HZC4WH~cIvdf6{OR}4dQ1DKYkgzs&#R1W$e)yCVD_9T5Bq14fBFwi@TSeD zJSu!7b2lN$fim_t$pCOTL&v7Ifpu(p^n|YT8*vBH-=$~3?zx^~w zm%06uNZ)^kzIar@jwOEAu)kpWOLg>}siCjQUzWZSa4MtrpDPKS}88PZ5j0c1*6mwjH`>65HYZ;Mfj-1)j(usqYc&iTb_)uKH5D z$G%#A?VAABK1q3&@gw9fgJ0#f=Vt)o*%ju<+I4c@JjQ{-yXgwtwvGS+i$tGHd3n{!M3g_jgav?+|+Z z`xR2f>)*xTYWw+L<=H9p($Nxq2>fmE*9w;ZbO(Pmd{z10?_2=3Z%IBMvMspoZ|rg; z-vb1%o7s)}-h=OAey89o^$`rs?ZmrIpV8NKE{CFL@NEb8=*~!peS3U%68Lp8p-aH7 zQIF0r{Z8@>@SY|84e+lazGdNS*Y)6P*B$VEKVpCQ+QBfIY2x0ePJI2T$z9s89%rKs z$AO~_4LYk0>f~0_(6!=!_73c$=(kQM=bW2P{K{2%&JNytuv7ZcG`}2#z+-qK1kRKAn_}LF7MSkrq+A8VyWUw zz}CTmDHGag;a9xEA?yvquYG4P@ZI2#a;QoB>i){N;T;9OokQw9lzjujdlKTiJmB@Q z?V^I^-vzGxL%=Iwhx5I3HTb9SYd=;0d1M&%dtG1UC%w6+IUBhRk~Cu>>8BB|wleiK zYs}2dyGd(5`(1{~);|-ky5xVR@b!=7T%z9GC4SIhS@(~LOP1wX!YVI5qm)fq^KNF@ zlKEZ{cI{0VeQKGionuXuY9&RQ$KKMDzV)+7hRH8C2fyg2N${$l^n>lS`oZrq$ltHX zUkRQ;{N#ddGlvpyIV`J9fi7w=gqyD1Zag;+`Hv9J5kTtuAz{>KJ+vIs?uYlJZ(ZD# zVWWM=60i0xgnu9Si-G^mz&E}3)l9D+DLMzMI3i+}$BEjmxn1q@ZCXO~9>LxqCa+;) zNPHk+#oBZ|IND?#M4QGS8*OsXs(fvl9Pp;-zmojC2QJz64kNTqC4KxG!d3u@cOq>| z+%o9hQAJj4n`!!bM^~@w<9#_*eY`jLv)~1$gXBL>C|}uBc|BSBTSw;m)Ms#B@?Ps| zgmr%N-o5Q(8JUpnWhcV@63X~j1*_*Tjxwk@SeiP<8_EaC*D z@A?U&FYWg)hRrYeVr=de%Gz&g+AHaYw)N#Wr0*BJN`}ozN9X5`)(2~kb72SVzDJ~5 z2_@0QS^*hPOnx0wkW1IF@LGv;+m-YBcV*)Lk$?Y@^p?%`{gwmYa$x>zXe>1yqpAFL zY><^s)<17a-fP}s;o+r9tJRXz3?i`4ZXaKII7lgzyNG4MHm6O0&!@ch3ogYH*_Qu8 ztj#dBZKk*pcrP4R`CmnTG1z-f($nC(!2{XUX4J7gY3+MZW~cih)2N5y?MC@QaFzF2 znNNXVQPOMAD0H<2%YQRC@;@E;?kClI^{~L~~SbgLBM(W$GBfo14UvJreY2bYn zDUte4Bo_634%{Yg{{Dq)z{tNm_-{A-@g1;jOj6$lD39sAAJ8T)_ti*$2Y8MD0C(y$ z{gRX?rmxucG9~NjdTOBOse$gN1_l$xphDW?y{Bl;r;9zfIkitl3O^l}sD}%`Ma1sP zu-P2^2jc4%l_!B6TW=}+>k9sO!OnNv5`PVcqk>}22FwQ@>D)4$gO+M~M>oCcQ#ZX2 z->ETA-8uT-?;QQ`ovD&|7M8LSk(H@@zj_D&d{rMf~PonN(`iQ-E(nq5`I8{H-!ZKMb0WNL0xtaQU z54?2>U+kJR;-3|4+p=1{&z^|5=P-xCsBg-+m6lqiu08&Up4*Z08d?(H*@5rwz~Ah^ z&cRiF?g>5Ve)IuJThqJ&d>8R23qGpw*DBcjI_1xY7v+!Wke6TOmpzete&9N9n!oFv zDsO(`nqGSx!>T>XKOE%m0&hwB)j20A?|P@o+fS^M+E3Ky`wvy0_}e|h_)0p>Pe^~G z%AmO?^`z%H_RX-7|5M_X|7Q3XgX{X}BJi>3zs?GUz6f4Ke9H`zyo;?W{|orPkZ)YPN@3cMEWO|Xwr3`B3>g}U;E(`=?eHC zBfPoTr#zS1L-N}HEpW8|32?N3M`X>9?pW4nId~A==Cu=tWZs7n*1Wq;&UL?M;$~ZV z(Oqq^Y~JUNWqS}@%cgC9t2Ej+zr(ke7u(FjvhG2ser+YdP!vM)UR(06O^&-tL%@x||=PD#H-s->p+ z8+b=5&as=OkoJF1J(UQw+$lZH2M9MSX~nkvh<(PS;$OnQjP&(7PpoYbUm5UIr*S`s z^tW?JqfhTj-$%VQ!{%YeN!#111v@UzAYRACF^mK9XBGalr{(Ld$ptTadQTd&>wNmq zoUZg+-Afj}_%iIN*lRuWD(j64YkHw;Gc^8Ztx`WlO32(vX0?M z>Gi{>;OhrT`RBn={zz<#@{_gZ5Z1KXvO};% z-&_Z-zERh*h^niPLoH((-eF`@M~s2 zAox!37YdetC#^%;cIefUp$q%x2wxF*AU-%XNe_-a4MA_ zyN0~SaVlZ7-*K(lzvWr^8KFB&47~&V?}W!C#JdOJgUD;3V9T>2xGmW7t_8L{+Gvwo zbImn5vOkj*T}w2h%D$oY*bbsSuLf6p)c;Lz%OR=%TZGYHKEv6{gyi1>mhU)j{;RVv z=%V|xJQzC1Zi$z!Yxa}@?zZ>j=lpj-R?@D|5=Of|2CjDLC-)VqpS1Ig4nHg`eo&u& ze4a4+@d5Y)oU`7{mc7(;i1l4Fc=_NJmt0^h*)xYQ+T%K{+B5ZR#xwLi!8zN+c#gUe zA}-@u)+-PCCNfeTW5te-5zp?xJ9gj`I`D@(@RvLAj{|<5{GKV;@+X@yRI73|PY5 zp4Yi3-xpnsZPMGo&R1_Eg|g;5w^(gH_WhdAUr9R&{1Xmo*2O%ZOSnKm=uKelXbZjo zyfyd=nUHO2e?r@o^kVwf;C$5QdM)aEJviz+5nT0ImYHD7A}xOj<0s|3q2O)6`xC#u zVAC&8x)Eg$yj2QMUC$x=A;OOqzGZnkxaKW(j;UDP8-S}V%KsVJDz9zd23Om}Zz8?e zs<9r-s>bIMm&~Untohi^9rryaneUN?3Pb8Wlz7cYpEHyU)uDAPS;wO|a{YT|xczWp zqZx@zug`0nu_w(kpXv%HX_O`g> z{tUXl2zK94vaF97A}_5*2XegmNWrG}d5xNWSNQvYZ!h}v&Bes4Z9=fV!?R6VEk5G`F&E^)*YkDa9ZNIEPaXpt2Xegi{oFG2{O5Tro%pew+nJ-? zr=&%^xrlr&Cp;LtB=LiU72gfs58gS6OWj|=9wGR~VyEek0@w7fhHo1_siZ&QEj`V< zz^4>!pL~?Uv;`mZR`lW6#|!p8>3r~h1$z(Hx#;AAC(Y)45wO?alK4PuiTENM8?o=F zi1oLA?B(wd|uKm>^im7pVtnXbfkBm z(EJ=PJXTzB$&}i7YId_B;*#?JQGW8j%>x8CBJEnp{FD6p(_|%C%NA{&4vu9tpUBrY zm9OqQ!0OhA>gUQgEv}8zOLcW~{0H;?jAMgzK6naYU7v|x8?bfjybAwr#cf9u)mlJ5u72s%(_iLg(uIDON{+k{0>r=8Q|NW5O z^7uQDRsJ z2I_L%6zgy;J*;VuXae8bPd?`-G}l;VZy(_sEU_az;y>s*&`=!#190lyjL7G zz4$W)n??3#m)8d=PLM2lhIF>idb8T=jo*N4xh=;Tq-;4Sz4B`A7o)6ADC3zO_z5am zzU|5U#*gPeI>g#R&iP>)qNk$I_PQR2bPM=Q!n(ikEATJD103q=hU<8zef&k^lCm`0Vs| zlk|5^`n!4hyG1joySs<}4yO3x^tZq1;e7r(u^F4vr1WiXjyKAd3QMv4$2wjIht@j3 z;TqP+;Mpb3ZD8BPUIqUgygb-v7o53^omk~uB2(=%hQ0e`gMUEy!QIOw&F^mgzd_-$ou z`~>)h@!Y${X8xz6>EkIyXxz2A4zCRT$7`$oR>wGO_1to#p?|B2ues2|DnopW_ezw>oH>AuM^CB1kmauuu3HD=W(f5X7{x18jU zE_HF~NAkYITZ%7xKbr4TTtgat>9|ibb0|-?nO7{U<8UpDdxXb=TMo&+%Hs&Vj+Ep( zR<{C3{#AsPZ(V#I9DVJ(k=9imBl1>f##A}f)x2_CDGW&eZAKVvv|mOWe+q6nByDg! z&<4wzn~95nZq@{K*2sG8KT)r9RMdM6xaE-4t1oKVK96625B54p`X#vS=Gr~OG)^4^ zj^k9^_jR0-*Ov5_v$HPLUF|vOdfqDmzmZB@k z{^59kh!39~8RO#yLxh({(u4T_I!<}NRr(<7l+O~@`t7}e{T4ibK;rUL7}#%pyr-l; zy6~?l2CDDxjImYUmGC#E!M>}cSAHi(yee<{<-jrhK8&d~z4HIB;0f3;)IN;TKA7Lq z^Oo-U6k422>CM6D9E`aqpL9!v0b}Qsv?S?m0~+kT(4Xkb3afD&5X-j(h8pGI7Uvmw#9e9tzw=cX6Y+sNzy^%4J_(5rKWBJDXu^V{# z%ueIf@4#)r>VE=U`|?r9`z+Tk*eKlyJ{WvZhRx&P%h3J7GNx+Jq4>JmGv#C4Yo=~K zT=?QuSuRHGyT=vJgZ~Y1iw&A=wq;KtVb{>m3Qg~(=^4LC=`YXw<@0Gwd;{_5PuE1% zpI)!8h|+q!?pn`l;@VandweFTE&6=!eF6TQQ}FHBhl`twN_lL1m%y{_VRmX;jN9pF zLlyB{s_VY7EA%ZjE>F~)v)+#&jCSg?YNz#nKdq?coMgRt4O8pI_1b$mU)L?_yA&Iu zzRSQ>-%cOzY4*bIBa^l~KTXE4wqW)5f~$VhyT4G=tN(6r)c-Yb)vvwd=+jZ(cyQI{ zx@7>oPN^v8;`e~-T?4)5u1?m4x+ zr>DKAyKS51!S41O-R-^no!8#OMtsvOPX7^rEZ1p-v0R6OYq{3`ME)+qe%LBm&L;?4 z0i@raB&_9B-}QYX_1yrj`rd-RFJQ3GFG{9=dq=(bn+`R-`MICerqnsV2f;DFW6>4u z->RctK7jM0{JX$a{sQdzEb?FP&Ka2BO7!2Der0e?ue}F@V}2)stG(*mheoeH%uMyd z-~LtlyZg;S`2z`~{5!x^{!hq%693d|_i3NZ-<>#LVMzX~&@EpVYIbS@$cQI%NE1f$ zzl*o;%C4$Z~OWz6x!EmcB${yzreJY_Xa}u>MWamn>AVYE^MP3 zvux^$W%J%o)vs^=M#`3RQW|T))wlNPGtpi9v};7a)fd-@XMkNJnm^Ud#s2U6t_piY%hh*NrAvAAwrT%r;tQ6L{p^po&B{`NboUpKK0!NcB%Gk?boWC5oI?h}6 zFN0(LUjf(rkGqNQgMn{M8RdS&*7yi}-V3h2P~TU4d!6-(Up&(a)@F|Q!C^ANaKUwNP1cDFkj zn_ngCZw(a3`s4AP5!YkKcaP*>54L`#@i%ilgUyKsJAM*+xt7S7dP+el}__ny*Q3SaxJA=|8) zyBJ(`yq+lU)P} zQ$0=dflIDD=X4{v&EG-T3ZRGZf!{!zo?)639z~xvO5U&d5xDxq^x9L?JFYzfZc}R7 zGWb{EI4-V%qoTge!ByW2=sOR*7kNnH?t-;F`*aQZ)LQtlf5}UuKFzZ86EP@Hp-9Zzy&l6{-%YWD4(Y} zLWAVn5`LBUB_8I!@<4L|=gyJ^dGBj$!g%j%KKLgxA;($wV&XXK+OxI^eX)Co?QO9A zOZd+FMcb$hvMgWe9qEg^z||M}&N+U1PM*@QOdYia>$_>-nEp>8{m;qodGsyhoMaom z798zmDKWy=yMv>z_aS|oq;p-p9$fQtT;B=ZwNL4v)tE4%f3^eH{N(#gXyku0@b%wr zbf#GMTY#fImw}@_mxHT4%Kx!L{!c-E@@M#t2IGwDHc9_q0&Ww^<$Eu<>eK&Qfu|R~ z`hN|M_I(W;?c18p6ZOppSACZM{b0*avD48^T6*Hdpnp^1QU5;Rs{a`5cdh2$DAknZ zmvObxq<*+MVU*n!TxB0Y_Cc_}E5!eXYICov>~!UGD{@Yn#*{yeZ~e|9S3a;x4*G@kHyLOWF-AUSkoTrvNv7(M zyaqoVUc3hX7Py6{KdA~Xu;Oe2=X}(6I5_J2Bsl7O2UvaDm&c%$cxrK6Z+@~k+qf~js59DVy?GsDy-BBj zHb0AVP=?LN!SBF_R~CFfcr((^C%yh4nx2o6EvETl%$PH4{?^gioT_!?_54NXJCbuw z*Sf}i3W;bsH{J*y>YX@hV(*mEQ%3X5K{~}BeRKg~ERWY<)kpTZ2f!_d&U;A3CZ6FET67CR36JE&bEwQY3xefD~;wKrasj>-nTqof?vz)T4xH_wT|V<)x2Ey=93$Ip?c>`HTT0^0&QIe`t3z zZJK}6zTYIm+CIH^yDYfgyLEqO2Dt9;sC#vAESqJmdAs)e5V+-#OyAiD-^lrxzL&DK zoU^WM^UZ++{!OwiVa#i9aFtc}tPcLXe}M0OrT3Hmn9}at-?nZYuk1Ye^qAC-fNB4G zMMC+K`JX@-?K=@%?XxZIQp#p}>)HF_wVu6?^&8H+p6VvFQ+|wN(b@gYq6_ism+%mK%Kdb-rMs;&yL(E*|BG*QrO+`l}Pw#XMgFGq(){%^|nUpe(( z?k6*FzsP!Uzi6nAmdQ14|8PAN`^S#pTHpHTGvJm(vTff+SljkX`ET&RT)vpUI$lcV zBn(h_z`ej7yf6q zxaaQ}B5WkfDFPH!DAOAUR z=pVKDA5H&KKCli`e=qO!h#A`XL&GU#ow~M)bvg$e>vSh@%OTnS-$q#b|A)@W?>4NT zxcPk<+kk5wY0VF0eofz7@EMui_^i3t1@&3;abV@wNLNGodSxx}PfGe1<1Zcf3y_!U zTF7591{x~ng=18!7_eQ0w3UegUR&Q6};?CS>JVZR$Z1y^}i0hF!0QP zNe=i$en$QfJ3ln%mnA=nX?w`&`?xM!D))EJ{fsou;0JI>V(p8VCFBrxJ^6O{Er&Lw zwQJ8TV)^>=BEq^JGp({M=Un&L9(@SFop7->@pnwmiYunryj{D~+T{TgLRYQYo!&J* zB*W%{TWKT2-xaX$aEe_a*fylWrf;z69&ASWzpHDoX%>4rk-s}&d)yN_=|lYRh zvy%T!;B~=|acF{hOyw}2B{{b3U63^SN4&X$$42; z^{IOe9B(|?pO;n54y2pLIqx~B+H`C3gU-fNx_s%{oJu-vtLszqx8`I1i^1k^{m$eV zB0t!XXpf|~*?A9^D9P#Mn#pfVu1vJQVBf)ZFEhS_y(+lAgKhf5z%l)CsEp|k2gmep zpl~rg*WM%2|DC>7(;xjEerFf{UZt`p-PYCg>tPJ`>lw3HCf#7|Nfc4q%(OW@}B`AA8aEX zw&fb_wGim-Pno4FUWd!+8ItaCY}$*^_tYiFhw}+r0kp(#xhFvQL_!%aMcRtJK3lt+ zvQSQGWzzqW_<9*OXZ{;~8@|^_(ucuUg5Cd+)PFGLsruFfKMVeN;cr#&>N$C{H+Vw| z6X(usiuY*V2BX zzkUL46F2k!*1_MH_Eq`%>i}@|m+kX%WMljM7})mgHEe1lLpxQRD7!TB#tW(5F77M# zxn(tG+?dnH^uA)Np7}lVmu&q(p5Fe_sLc1ZB(C{>2S1w6L8V;3Vw2x%Slg%McQm#m zUbhAe6_au04e~37jDBn}5^_B*p)=|hm6a6zK!(%Bydu(5C@5#sc z=Y;gQe?k|5-v?gP%7<)o>xDLTEBtGz7^)U1uaf1pebw?jgZ>M_H<$bzBj$oz z4&^mFKZ!JqQ)x>2&iPop12T1f_B+srg16+5oWs6F80WAfz*eQ?7~=Y( zrV+kd0QsKLs)Uy$l(GAM6}#rU4qVrK%0CW{^3R3z>f02fs=VLYcTE0E>4VDO0*>;x zhV;tYzpA`-?(+<>&es6fI#=J3w2!E75M1Te_xXUeXEki8_V}CMAEa~mZ9mE1{Epv# z@i)J3ga1foH~!}LkHEKr>AJZN>O(n{!*k1(w4>86l&seDk7m`Iwh0zCgQFX!fz%yS zD$CbTY()9MwS4~8!N1%O7ou}_2|D)l5tSc)}|LKgu zQT_~YmAAgQKRBYkb_73E^0&Tx?mE`jabW99x&i&l@0DTl=hwjf1)KkO8N*}#-vd|v zlF#w3C1d`NOM3N*qrUfpYkKt^L8FNJK0zmq{PQ~aKCcq_TQDa?`4$}cH!?>={%COI zpEqG7|H~cxYdiSYfusDu#F6s*fh*tNv+%c))@kziV>8P4cJuvR$0OVeo!)!F<)455 z755~N#v$MHiv9L&;Mi|J5wQLC3n;Js)_(83#wb4r9Od5@u=3Y+$bYs&{&OL{Cx;Vn-nxjytdb>i;_l7A=C z*e3pYpqcXYK(jZ;1y6BaK8JLH2M(MJZ$l2r>*uvlTz%;E^TyzM{k-5W%%Rlh8&hib z4#BS@pNiiIzJ><5K759*+)k6tMWCE#*o3*@u&rauI{Y~as8d*u6!gM8ZwQ&Y3iMjLsomuTu#q}N+dUiIl9 z@zXgBKg@B92Rd%;YP+sYN7G!}HL*DZ$urAw8eu(r4(nX_=MqY`skai^rX=s(ifg_5 zUGpEp`%dEKYyT6;uPyi)e8RLi^!pXIlb?et-}g!VJ&O1~=|R+SeTI9=U)hHvz3-ez zv%xDh;Kjnzqf6= z=h=f!Z`Q+C;kAV?egJ(HyT{Sum%7Js$~E2T zS^9&sQO)~y>rQi=IwjwYXPbBE`pWNNe2aS9FSFC{Upxr*no2tKP~OKum;FOpi62w_ zIqjgf<7e=@W6lMX18kXg=y68C@q`x9F~o4-HdGl`OY@CwRO`=EVleQ@nl;`sdu z<-Z9(%CArPqx|@OpXQe`NSK%?ya&mIdMMY1Jl77bryyhr#nbJ=e>B=O$}#g120Q*-NwruO&q-vgM==k<&8()#IJ8Cx}5b#Fx{dC$w#eAFw9PUv%~hGp zcyab^Z+CC`ezJMIgYzwir2pL4ivDo_xcbBNb>GYM*0s+*)w-5{Qn69KnA^WeKhs-7 z(sa17BeonE*5BPf+gMuX{)NyvT~a>!!1W22Q$y>Mjh^Qn5|qAK#gO>X4m^weE8lt9 zXU(JjZv=bY$Ne0QuKtTjzT9vs@U`@Atm7?>nl1#A7j`;tRPOwAMF_)7xyU^*!gc2-MefZ_;$nYPx4KG&kK#G~H))`*&8;GuHpfMD6)H ziEDYkLw?-qX#PE^XqtZ;;CrZKLe(a+j!(dzSjSI*+mc>=-kYrY{)oQo!L>eI!(Iih zYuIrIa{r3T?L)uy35##d@Jt|~b>7UIH_u@9-}Al1qp-zxZMk`M%q`4>9WQ9ny=P25 zW84`ELxae0J2>616<-7X9s5p0^haEAZaft>BYNaZ^f>CZUWc*q}{rZ>N% z!O@;$z}23E;a>$_rQ~-Kcy*kb>n@K^x1v9`t;gWEq}TU|rcQ61WS&TYYskHT2YC(> zyWXr=yYyMK%QcmD>GS06uCAr)_+t8lIUmy>0jSMa-T&+^});%XbSO>>smY1{y_b%*6Jc#5=6e-5=KBaZ z=KB+H%=eezn(wl=X8F_23>y3{-+seiU&)y^+O-I*U6Skmr@-rG*tnl2wqB%1xVgOs z;aUkX8+G@l{hKWdUIjdd_$QH(wgKxW_lhLb>!+GtzP3mH-GOf#SQQ-Gh`y<9z~=xj z0Jj{H&*@!A_yrECBptPqe?VUSoZEmlDCz6R39GN&_dEf7mrTfK%=Ke@#{9S7TVz5$ zV=lIjcnz*vZpZW2FyEmEb2^_h&Gf|OPxm05as~f%pXDE7OQdt%r)Svqttj{Pi}*9i z*w|CjAD)RBdkPPYojpkGJpY`1s(&t!A)IF7Zk&Qr(_O^5Ze>wFF^~A)a3WY?v=o5i%zxOeky@Hr*Db!Qu{b!UD*0ayFPezT%t?fV$G<|qH@4*o1A z&&Yo_ILhA^`1;F*+Ch|Aa=&<4uAkg5mQw!XhULZ2bl`W5ALd&hr!j`q`Y`=X;F`bq znhC>L|9=`B{W*aVr6up)axBG4);Mmdi^=9^AI;Cm*FMns8=Ydu&uE8h1MN_c`j#Ba zy04Js-rn=2+^)qR0@ta%JdRz`aW6kOi5Y_AV<{#5|W-CcmgC z&ev$&-SfJqaie5Xw_=VN`w+%4<89zNX4voFKpwTso8g!H!F3F>ZF~exEi&e3QN}ot zL*kT4>euO1%I^b2V}6cFH9yCwxrnzpc^aeUfgPi&J|1@~+-(1MtTyU!DkWw%_l?DD;Kjr%s1keQXzyd4abU{9CXEd`QPZW5@KSZ!7-1 z;KZjClq`j*V z*7UBKHwRb$$X~sKzeVAjmwjRTCG&Nm^@C*^hrjSo`ru*)4Ys`gEyF+YZG|ZO8QT*X`iz^x78n&D-I(983kt zkLxBXcl677>oXGtrx;`NUtQ7Xw?%gE8_V#sd*4#&eEvIj>1O9{Q~LKqc&=}S^tU_z zO)00Pzm9a-HO`Ue0uJ&FwAm89=|1zKP(#n!3UNVU%7``m(jru$^W+B2Z3Q~UdysZ&Xs&gXtM ziuL4LTz9R-Go@3g6~NmJxPU_)$9EminFG6A z85ocMl&WWQ%AES(u7gSMF}g_VIkostO=7(lwV6+)k>|5kdB-#44L_SwQxo>323$|P z6dE@oWkBtysHLJ@jTPk@u1NpWdx~5hl?xiIsDFel{bPqNo)zt@TV#T!Z_rLyX>7Dp zE!l^%*Q;pJY9M*jJ)Ka~*9I;9Gds1U_G@b7x_BtPQvZ}8G-nF7^am~2IRXuRL_%SB zrKu;x{g+`{Vx(L|tvdUMl6K@^%F1Nz7*MvQ@)DXjgcigcXu>x5N}yq&++gLTGPEO5 zGu#&YdV?6(NF$JC?=O=0^Mc^dzNP~?DrM^LYi{}vQ2z+t0BE?52DExO2T>l5l2%cr z7T)aPBA9X*g_gR8!Glm0o<`dfmM{B0Rj zD_?!%SVUBP@?Q_GeC3y9Em-Bn%P|B+{9M2vhQA8~&-JCUU8j$tZsR(A8*p8x``pf_ zxo~@9Hm|uI`3b8dU&{AW@aHBE@0aP%KZC13y-qqB=eTB(o+kaHD{v2^+6A64%e6Xx*5aR zX9E5)ZsqPW-^T1VJ{SF3EzjI#YtA9^$%ORtn-Ax+W^iIiPs#;G>X%r{? z;@s|j0?S{Kc(vNTS9zy%+h!HoZQ$wrT6h=U8GrZ4Ive zu}#HyD6FT);n#Xn{8cALzd6+IhOCe;95T0k^I<>{tRxDbhc+@#`uaY-zwm0&u7VRHe>px zoRh?lj~~X~%libzt(e*AS=flZXY@Me0QI z=FdBF&z(3YZA(6XM()s}SHHiXc=Y?3;A+>Aq-S_c&p;`EA=vl0ep2kT91heqz1Z<3 z;`s$rT|>{0Hmh)nz*?Lo6sy_v+cOhkH!Dr(ZRVrj?}9rvFik^TaP!!OjwGu*_Ak!Q zH+6&4wJCo_Qs&n=l4Sk;{2`c{gZ>;$OTn~^2wE^H#r=!;(==0uf)>QdeuEG5huaD{ zIIusVKMs_@nXP#=qu=Hr@dmrOa*)WOX$CbOvhN*A82jFi;M(`>Yo7+U9FlGO7Q))L zmHz`c%Ks4@7;%@qS#ro@CHUDao@B1xBcs*uGzK_pxYUq9Z*Dl?geEH5|ug^t&8~$%O7!n&? zYn$%UU1Ixov)%UFEm&YAx0lxu#`@j?9P9g9aLXatUaljo^=Pl6Ob}<38TzL;HuL${8D>v%1`OAY55MDI@dg%`-`h}rg?RcdllP&_+xtN--mHd^ zE2Y$Y63=y#G?4yI7(I#4rSlZw==~7dk8}OR`@1KMUgXg?A^ny~Kj)`=FlhIeb_{HM zr+<*}6anP(Oa171EW#;F&o`Zq&1tZQZ{NQX9Q*!v!OOxMxOti? z{?qU7=nLDczR*7eIHR9G`TGd&oce6IywsPvT3PAa3C|H$UXtr3F?7jKc+a2ks)R=B z@s#)LS0-Gy@V%ez&|c>o@3+qYZ&~#lDA@b?yAjuJ$@Kcn^wxErUMKMEO#Y6! zwx?=XVq7zD>-3Z+mvd@182&Omo9z1PSP~D+UNxmrt{Kf{XCdoL8)|*oFO_Kv-?73q zcpWQV4u9~TRg>12(qUPXjXlHP)N?G*S8*(HKR%8nXMkG{Nt+iE{xfWTc=zc^=S$ga zg8%D$eYg>JMj!3~jz0YF*1L@<^`i-+w<6lS@$v4oe)+YP2|1QoKaORKj-JksyiQMR zHv2R*zFBFU*LM>qH!Ce?WTlnTqDPOo%sKH zdwVJS`Y)fJ%G5KpH;paFCzS6YZcM!8u#%W+(zkmFnp;S#Ke&WSwEopyX%6w6ZO=iE z`7ZIqc|Lh+ps#s;;7uo*&>&x%96?jjO1-?O*EFcE?TV(bKvp?}p5Mr*-|m)4J|+D=U%dKSs>- z!(~V&C0xs(wpa?~4k~3(k-rtN8sS?wY)jR4qC>Rosyq)y##@xkj{$#&w&uK|jPi*} z`!nwOvc?`d>p5+mH!t&7BrbWr(#|t_)AwdJD|v}~iAU^nt77Hy+*YM2?P@&B_Wv>W zF7TdD)&Kwdb1ric%`paJkaI9*5GI#$i_d6=A!-zbZU>E9lImM7Nyj~zC=nF>YGGYm2{8l|9tNEUgxayY1H@s?e}~9|7+%b-tX65Yp=cb+Iz3P-`5X3 zH%a^~>N^ROG4LaJ^ySFiP^6jOPUX3Ij;~`=zw03=o7n8nc`lb^n*(ep=+nPx-<3PB zg^k}?o6B+j&KjX<{5xwa`VO0G`pv7S{0^JzfkRj357hfzwo#tXv7ddp*749kw3uZ^ zp-;kB)!h~Ucg5cTTM_e0onih!-y%PkfSZl*leA;i_pO@$l$xK%D+{dxU;RFBV;0+V zkHYc!{MI+y)w-<3+QfcvV8x#qY{%mBD<0XZ#m86OKC2|@U*qm7f@Y8|phsKUm5&&? zes_%{EdxJ~{pAI<_!iUzJ{7*${$|~^SwFM`x1ZPE+H}_iL9KaXrJi-QR9Gc_xTcU# zY&T%vW#_(lF@6_uV9Zp~OU8B`EGFwXeHr^+K*Ciu#rnL6+Pi@-P5{I>VDG<3w5o#3Ah9_+LN`tvXX zWcKGPnH;jd_cHLazORBq--^n+Waec4@94le|DVC;x8FHlBEZ{LzXwLyZ@|_cgJW$k z|F$0fCwutI6W_W!mcmx+ZhW@xcEPr60Hp5!W^dW@%DCV;8IQHInOeGXv&%CEn(N7O zaZN9&t%_z0p0Vp~%0n4j7Ttntjh&|3EMn_|S{p0_n$BnW3Yo8q;;hI1lJV9R(>2@k zvi{Zj=r-f|jRzsG&7Y$Z+AN9vyY0KoI2K= z&i`{7?lg~0=^GpCj1Bak#Q#$%qkoLoWtzURJgBYD8&Z9)-gcmTm&x~aB>9&zCd1yl z;QQ>U->;DV0RAm_4TIncu=zJ;j6{CrU%bkMy!Cw-eLC0wbo69=4*nEdL@BnkJODEP zGudZ(?*V4~$%M7%!dhR~ zxh{y%eab=NJ=tfxWx{^5W=HVmY^p3xQi2se*r{FXpG3NJ6!?|w-%?P^|0BnluN}cx zx7R4uE#erC5+6;+6NlX-GnS5<;qHV` zGdgiR$E{GeNsd95PQ$kUctRX&jXOl%0t^9Bo@GJR7_l__ivw zBEEe#__nF}qfM3nB{=JQB+0LczXoMzedf>lycd`Cd7mca)z{0vDe<*We%9wLAC>s(lOOuTzv{uWQylFUgB9N_bQ9-wZw-pGaej$w$EToU~ED z{H*^nI(ybHKkQY0EN!Z^ABgup7}?BGyhg5_sqWyocSBi zn#|t>ocU+3KAC?GIP)LpVoKKkS8(RPipxKle>6Drzqi(8{`bMbe<}Vn-e6Lpv%oLu zOuXmW?GBXr=2p@q@!QyoaYJJ=Tf06h(?TmKk7j_J1-zsWpOX+uk|MJZCvgR||;+l&pK3nsk z6Dxjm#UHQu{EA<;uw6Usjx58wY)|rmJ?L6^u5nK)i1#nSt`S~ev3z4z@Wp!&69Oy$ zTyT~@he9&{ba3YXfH9r<*P}o952Ei(d~*}!vnws|E>40v6;l+8qdwkcwJ;(c2yaap;$Ja-mhZV&4v(Uq^E#G9&XSVF!19uP1Y;bHP)5*fZs6SlS9F88( zqu-=+A$`Ydw&T7#8UA75U0QZidY^aJpf>|an&i*HWY zb@3Sa9Rr$REP!@zI@9|)(@QsOW-j8{Dr7#<@(Lcs@Qj~Eqh)+9l@nXPwiTOZtme0k z*G|J;{ALx3T`Sw6u+lL(dZ;SM_ zu8`xx^NrAT&@t_AXT8Y$&^o)e*KJN}Ve=Z+N0)MZT*a=Jx*W&+uPq+O`J3N&Gcx?X z>YM$J_L9~RX_Duy^5ff@=HCk(`5g~$0>^kczv{n)G-=-r`$~S-n3CT$Sc84ccgnv6 z9P;YB2pswr;mftb(Uvoo3^dEY_DxCt>g34_#@o?GqCmK&BZ-nwM|5;nu?& z&5fJw_Nfa;DSvp43u5K30*5~3KLO72A0k+0{XYd~ z`A5N7el9^V%O3>J@<)QR{B#xoS$+vP%Rdhs^6$p49XevPyZGLj6ZltP-&a~#`^j3n zb6=L@b*wBTcK*uvz#jaQ9z3%r|H2;r5k1&GllA|s2hUFW9>gBo^O>Yc;z!tL>~+Y% zPv3(W1mACQO4f&E@OXLhp9RkRU3>V>znTB4#P|NxHsBlBB=1j||GI+O^5$}!>*w5< zvEv}{)vU7}m+Mq}jrl&?WXyMHwDa>6`g)y&Nb{LJuM^u&(l?&n&bfXYKzanc75h$K zf#us#M{yXj!)M~PzuU5#k>|A6Z{An&R^YQa*3Kzxs^QLd(H_{y7y8GLzYLj(`^JLb zf+H5p*|NXHRc(-NMBZm#!w2GDCHx53??Y@`?U(O23$nb=!319Kx%d$GoZhN0`o9Ry z{F{6D*WldXtN%_amhlgIu)kXze9JqA7?8`m8XWvr!T%`uDb*h9^DS_$&t^^ak?cc!%jXs5@*bDnJa#=bb# zTz=Z%tg+^#!CA|@ra>Qlcc;07eLUOw8SH#B?c#WsZ0A36oZIvQG05*y|pW{0pBv!52Ty0Lk)8iFH~2H{jsw*SndK!>{JQ zonRDv@z)c!e$S>{>!+V+!e;l~mn>P*?G{W`T?7pD>0n5IZNfhM_4K`XmkE5kOsIEU zOxt^){9f{%ExS?var%77i%*_1fe%OiUHIbdRsQQ>$N3f&%fFE0;EO+(M?-_HA_NY7T+YSDQz|o%a#laVUvj@K=)lYxC9w$csQT{vN z$iE2}@3$sD(_5jf!1{NCiWgP9amB0O#WyB6zKM2crO@)3XZ-AB?|PKyZ_jT|9!c!;g@LWlrld!Gyau@te4E0MarX1<-&YXd%mLe8##zby z*RzlO;;$$CQf|^e8~gTB7_$Fd503sL-{+}NCGp--vxS zJn*$(9`PK(b~nH=&{bcGhd z-vtHlXkoKH>&&-t{0Wsp+kqVe|5>r?fA$5%Uz2LJb>&RAJ z`CjnFV1|96)wr>*zgDjLk7nKMIcBVWa7ICzBWj%^F2oid4F%_5%6EC{eBPG>$*`t z{o(m~_J`***&mx$f3Pd#?kQ{-H@>TKI1CARN4UmlE+ z9!HFur6VBY1uph)T)J%hR`*$?99YtM-s-1)#YYVJLh|)l@K=3dyKbCQ%V@i)rM2{F z`0I1HcFn)reiP4LC~+EiJ@(To|5os8z#}rD$G{(9|LNAyW@LZfB}R6&B+n9MTz+r( zyzWt+TQ&ciz|ME~SNTtZPXPb8V)ZWqhyI7)UkmSbotj^LGkf%TPLcI((4+6UN#Ebl_ge6sRiFO*40wc1I{iiMbMuaM zNqj8(z&{5&PHwCDaQ4@i!Qp@HalQz*HqdhKv@j%n1eGk+)=pOK;;HxQ9n*I{% z!;s#);_bn+!S`1D3h+{JeBj_x@Uh_ERsLDTne7>9-)Yq~cfj{|h8&a9U%}^rznS!T zUKIM~y>y^_-_6)0?E`)agSvdJ2CO}QV11hH*$RH-*Pd;_Vb7W5pUy(lHIk&hE5TXc zap0`)bKtDcdupNYI`W^%`fg#XuITfgTGsbx_*tLNxn+Gjf)|?C+z%*5Nu@u5Bfs`-%=uc_ zXMJ`7hraKSe=jgEJQdQP;_&AUJ{IkG!voPAb;?uxOR_8pr+GBZJ zgQGm{-x-|kzYHAq>#vVT9$`s$tF?5od#v#-7Z4%_vWaVq;toP8zEz7l6&ZB1XuzH%L%edW1al&7z}77)I& z?{siV?mPblKlhz$z)>H4e}9iYpQ#Cb#>NHc%dv3?obz+3Z<0MngCoDOaF3o?=yPV@ zq|TD%FG#V_zJ4P(+j|K(mv?uPxBmXdTa;&P*@Re`W6MfCv2z!2_TORP$nV(Sj#%2Q z_Br-vg7et-w_@|y_d6@0ugq=4!WhfWZ8v~N+UhpWZC4Nr&#(GjTigM*4@kzA{{)AA z`{x|62Z9;3!}DGr%FQ{*Az)-?{Qc@PTZSbLB_b z$6V=L^%ywjD(9NBv3*m8A?J$K8RrXI*yz7!(4WG8mao1jKifkyv}2izpkyi6L~$K7 ztuw8&Qs+q>?|M--@n%EzF$RtIZvf|be=#`5obg^9@!sorJ5bm$7iy zM_P7SkG>6q!e--}zsne7R{3|)=d=7g`eexK(<8tKR(;xU{;=QpDUO(+z9sajtZypw zap;rpcO5eSCp~<><&*ih^z_MnuqE^F0B8NXb|&+`3eJ2^e<$UCHU0{|=L^ytWTd@b z-agCl_ZF5uG0buF3D=iPz_C6Rzqkh@JzoQV zx?=6)vgo*dC9c2=A6TB}2vOeQTsRm7|A*znpg; z0LQ%LJo+Fw=0W@8V)TW)<-Zyn{xko1;K;8(KMKzMLmd7zW{M+bx+eS@VIr?{rcs}~ z&iO6;(64=e184iz?y1jZM$b9dgYY9h8lP9`Ip^B2=bY<2a6ad{3>@}(&h>fl@@oI##Qzs@ z4rWZj%}qOF^{v$3X^$MQ*OQ*dtC!UBc-ZjC9C-~PpImGSm*yzzh1coT=e9dF`1-o9bHsP*?8Y?$)%czY5!xBnX8Xn*_5 z5%ith-yZFe_ug&D>))4CU;Rt5?YgcRe|)mJ^l;9rNRKsvYnp?>BW#lK^ECE3etKOu zx5rPwxjnuMj`mQW*ZM=B@zi@ZxqWgxb=_=R~(dKH}UyoAu z`+a9F+rJw)^6QV?!C}Ag?o#mPwLI;AeNX;R_vHUx%5OaSEb-AfTXMZ}9yrIN&w!)9 zS)Z?g!yfCiG4V6%<9L`w{Bt}=E4n7U4e7Z*&jW{k`>*TM+8i))FI78d=e7_YDM zVL#>P`S2;=82`?P;+PLT2VEz{2mLi;Ht&@oBN@+qe=g#M?frI~82;6sPZ5v89{smB zxNi%Tr^1f!Rr+Ezh>J^jM_pV1bAzQ@DjgK5? zzE3@mYsDMypRY+h^8NFjk#FzK@g6nuegZSge;i}7{QgN^zubZT@XKpBdHxytkFVt& zc1WlBD3~r)>VT*%>8?<;F%L!Z2-F~&TRNVA>73-V2$FXF5uELs*<+XI$x#pUd)^rN zpTrI5Wwh`2(1kgr4^3g-3G%$q^Yl0`oOMZGc^~qDD)6yaw)eu$toW-(wfNT+{~o*t z$NFBH`zp>G*ng;E{k|8HUicMlk+nl@MxdZ1`zUvs{`k&b(`||~HK z%&Ydhhr!YBocFe*J!0N_6nl0BKePJ7^ZN6^abE9vy!U3~JYN5cA3&$=rJ3zjJPshA zJyZ9^Y?AZb*6d@R(cWi+!(QuWeWHHKmdH=K-B&`V7A3 zEFJjj_8G~C6ohU8U%>vi70Y+d3I5+I{(0hmB=MF1cEUbuW%u2HP1+y48vFGNYM*_Q zw|T;@69Ri3;#lyDYI$CV@Vq2nhtOZntNPwLpI>{Q_w9{8ao=9wTv2^Pa=FIg9Gi9D z1+3mc#7It+YU#s2Q6>;JD; z>{wrudc|0`ye;8Hd9EoOcVVC9JqXU_4W{z!tBb)8RQ)B^fQ>bhzP=os{V@j4{?NWC zuh$>iW7`G)w7IlB@?Dif&Rz0H3Tn@R_T*T3+m7j&m~NzPv9Y)rJ#f^W&%W5tJV)ZR zx$W0pN3Vp6lFpRe(s0uZZ`f?OQNy1N{XR=)!@2z<8}^TM`bV06EJFaY&SUJO&Wq?H z;(M@LT2X&{Dd|zikNyYqE%+%_{?UW!BOH5=Nb*|o)4+2o|6#E4W&4Viw~e#>Y;eeX z?R+sfuASQ_#L*|r|KpzgKS}xJ{{UOE{vU!vzxBNz9QFM+_3^wb`snLl$2x~5d2O{< zyc!J?*!pa;@nd0YH zY(A!CcYG7qJ4lay;4{asg#UqRv$2Tf`FJe)I`Ur6SdV&0 zv&Y(JoEBAV{v|2@!N_Z$-|3LlHS;QLI<=EW(WY|I6^t8sICDk;>W<9BZ!wm>V_&?^pS*HD3>owWim=P6Ee0f%l>BeDIUl^p$2k zt^V@OAK@(o$M~F&EhmDvXOr~(M(nlKHB9)r;kgg-N^FJ7msy6H|JoI{KHmgJ_PJ}6 z?DH3av(FC&htK_O-8a!L@!Puk{0#Wn=cj|S&*f*I>#yu{<68LKdOjDN>-ks@e;9uS z-!>Tm=Qf!Ojy6%>o=JZ9(^@>QMn~tnN8soA&hx8?bH^bszYeFyXBqz!9M>WL&hg>Y z=hJM`Om4b~KrE?7M7;wf&^&I3x?MLuK?pu(b7S+IKHbYhh!bwm(Flc0Ilvynf~TE`m7X zj_*#~2X@URxt=$MZ%_~sr{aw(R{yU!4*g3h|9IN_?8Fxb-~Q*hPxL?i|7CFYzc~DF ze?J(R+}{Vmxxa4*zPXlXjM)Vo{oNRG8aVo^_!|jp|BH=NmWd8n#@ccvK-_jSoS)JTdU^XrM(`isbyQ~kAy^<6PTo=zjvoHFU388#m5x#Y+sn6&!7$eQ#ip zg?*Q3d3GA9dntKMkD<%K zc?|hpQS>4EoaZ6oGy5o0!X*A(iSHN^=P~pba2`Ycu16k2&P90)je_$S`YSk(p{HVB zj3Mp06`yJEgpX!%E-+ z`&Q(WC(ijylX4!h>$Mr|^LmXiJicDriJ0wt;Jr%qVWJo6{ndzZGTl57(T3-Snv@oJGiiVDof!X(%6}u+?XQI*J&$1 z*}f8fZ>9{^R^gjTZ)v{+^quOzJHfv}_S+T9e+K2r_qu>>@sl6^@P{KKBh5)C(be4` zvHV!ib2vWV4Yku&Gql{E&hLUe;{MWRsP69yT)5_I<%R~@{mj5t7HY=_FAY}yf;M^l z2R9>MtffLu4zJ_cpJJ_#dWG-&y;O=g9Yi zqdfJWMT3Wa&qKZM6{`f#r?#ZCM0q)=82Nq9Eb<%6AEq-!EO))Tkh<+>Lq zEBCftrreJcAJ-ON?kk=R&iA+WA%FBG>vuUg>=VD7AQM=B{05x;F=OQkzUQMK1jqTP z`ESnrYTv2VzGK1HW6uNCKG%r6#yW0~Ys81S@9Y|J4P+2)Ze45l*}Ko~=6}<=4oI#r zENr^`YstNNYHauI+6B`VbQX*(Sh`^8j{EGmlz(HU_A#)^oKOcCd9?d0?4#bspA+Z< z5r6Dwu0x`qDgS+N$lp)B#5+=V$#aJV)FH2X_5UJdqsl!l3{S4SO**n=JvG)`+UWtlj{HcVW{Py-4`B!Nm zv*CwTuI59@nSRG2r{zA6v1%5w{DnYs!T5#m(SuLHyP&eAkJY z?{^x4uTA#XY?Jo^9;o@X@zNgbI$FLyt$I7l-_-EG>9+Hb*0)F6KL85*e-3tzk8AE? z&wm43zb@^Z>-YPKa!UPviBG$vNu~ZcFW2ujaJO(f^JD(sQ@yFZ}%~{tQ0Y3I2CmcJp80oxxEjee`m0_(-4nzFPLF z^LzH`9ZB9c{4+SW5lgeCTg#LGEpX=hZcgy^>DI`GJ>nx1_B{lqo8}-k$@PZox!Vik z8VvK1YlUqp_8eWjU&WSh{#^cBz+E<7sGC+F9KgaBQx%5s!~->B=L|G2C+T+DMB1IW z`&RaOzI+Wh?05ZQd9i-cUUAs#`ogx2^@aLhD8K6Wn!%yqe9eFkRjwImWU;r(TGsmN zVv{UOY+2)VTYaK#rILO9)5{(i^Y6$$=g+ok%R%t7Er)^U)bhQy_?5oN*B0Lm9zjO3 zZWpkRx+(9v>FF{m$jv zpWwx8lJ}3i?&19->7V(Jsky|+x4ea?U|D~OW8Ge!Ai<_n+UZJFg}h$r^`K`|Z2f0r zZ`9wpaZmVRkL7;`9QMk;KJmYg{UcN|pIGOhZ=>!VwPt)pc7y#Sos z&-Dw9#%e+U*za5afP4gY2S^N`Q^zth8?3(oxO>8LsX6maIh9mi$<-97xnn3yvE6UayY zo3Quu@L$%nr2W2Y8+`ruzLh8PUkzTHv15Fbl=u5@!v%5el4tw;j=;*DHooF)?m;@e(iZ3INS4j@Nm^$?ve^7`+E>rD3F=fG5{kmbqG z`48YiL*%!-L!Z)?M;K@bHBhJSY0L9@_LG#;N;=;Q25-!9*e7eXQFT3lsA|UAAGiWncOi{F7(TCI9H8{KUnS zU;aPSU-&csS^2|XSTspLc8%-50{bTM$Kd`meqm4KKe^=JXF~siN%^b){=t5QhW#^E z{42lBXj-LV_g(mX)ZgP3QMcwF{z8ujs<3?WSM-m&;6G6T^0lHfp7qNYjvsO$pOdDs z34Z3beE$9`{_=m3f3nhw#-{dL{+~H@{b&5+{uO_Png8dB(=T8dgZCHLEZc)mU~b;K zV$WmNWG;@_;kAOF!|ztU`Q=A`@vU4J415syQ_Q7vL;jsy$78M|ycC)a-f?IG8!O(m z>cpD&>I?ZsDzQG~J=ZXn++OpGjWc4`VDgsrHOsD;)T4m^H~u%5anbjGr1_tSwRYc% z-Tynn`75CA6ZOgQH{Di{iKKxs{;ZIubyt{7;tDv!Rd(q=t)p7And zR!;R!Xd35mrHDLNi6>~dJ$z!$@Y2vbo~h=6(@T{zf9YjUz!`o5PG2*;yf@2uxx<OOm|4ne#=e^UcPk!jL{2iV=S^iFNmY1L97qbS+`mY3MdHEr)y=P-w z_UG%s+1^*NX3F|*1805mL!b8U-6Q{Vt_Ng!`B{D$3#+XEW^k65AM(D-co}Q9i);V3 zymzcVIsg8gkLUdIBfs*VkLU8P1Y~*nS^oQsjV%A&*^}kvXZc&!nk+w;^Xsf%ewM#t zy~*--3{RGqAM(pC;+rXqS8jb4`slHp=1TCA7B;r$Z^5}er))U6Jx>Pb`pld=xjgw% zp8i_2(Pa5Qg1fam$ESSd83v7Jd1bV{NZO{+y`f>5v|6|Ehfrh4evs>9Tf;p>5y)?J zZ^IrJ7xJ6jFXhOXB^j^$ZN40@d=4Vw)!+^7?};AJikJIw*KnNcdp+{q#9z`kneYAU z%*WtK`CkAIzV>ZJt-?P2^@b^v<$n$idHKKX(RXu-ciQj$im?Cdw72*$Hp%aLe~|qp z1-0+K`u@+wY|_BHc;1%dEnC=J_@%z`o&VP+d^N{`w@2Q^o#!`FFJ6tCbk;5G5q~dX z<$q*8Hfj0k{pJ2*^dGTLngv#V23UFAF#fFt^Og(XocVM1TIf04OCYqB-vJo={=Aa* zrkb`_D^lKT(?4gjEk~yN?)gP8E^kIC$3E%tyb-We({MQt*v)RXUwh74v*~Qksjb|| zND%~^MyQgm{$l4NU+nz+i=Dov^Ol93^E#cAJDr*IV=irt=ObrZMk%QNK}J$8&NHX= zH9K(++@I5UI@=l>vlSs!Z9LShv8mgtZ0j~_Zn_rx*~qYM<_2%Gq2+6A?6!cd@wl_b zrspEZ&pd6s6kP;wx-i=?e}~Jni%~ahtcJDEG|s67PwTtCe>xja%(-<&nxl*1Bh9fK zpV*nleqM)d(EV|wjTZhO`PJQQwPv|*ZMoHF%@`64)p7qcO&Ry)eqXcBy6equ*7Z{Q zIDf>j0gkk0%dPsS_JK%@a^{VUAkkvenzhy|vBI{hbwo=`rWKhvYZGzT8Z_PhRODJW zbUK}p(kDz0yLnr;+%&njOl zz<0Ar%HP8N_JaNqD?b%OL*8#(al3f@n`7ob9VbVApNSObXCluAzo6>(-mLd?wy#c6 zz8}YA`PIN7uYUQV-}{@hiEmzWm3-I2Zx)TTu)J$A6@J{`^x3ja!1i}(WNC}NM=Blq z=}z+z_?uL0dDCd5D9`wKC^*OK*)&+UM4d5uR#Aotn z{j+G$tbcvV3jO8&C-@n)eA{OU$I(98|HdTWin7V(b>QjDg+9%4hKH^-T z4Z%?#?4Axt`)E$9ldP9QCxES0?`8 zrTo4C_zs;6`JT-$*q?^&lJD6Vpzg2O_iX-1`j0F2S!U(qS!SONyaHadv+v;?0RCl_ z_qzkiJ6B7-m*e+HepmVB+jZdcTXv)VZ8^^RiFV`q)h9pn{r|Ba{D`_md+2}PYYA*W z*uAG8+)Nw`{{P?FyF=Wv{o+~mf7RYTW2F28Y?AHmw^eg{ADr4-{kCV;pW9n~^3~@& z>gb=xoJm|L^J}EB(%fpRE&HZ0MHc$s^oz5}8RN$Ia3SrOLKX5|%4dN$uJ~{8c^o*N+i1k!OW1z&+|*CR?@ri$wLZ>?_~P$Y z?La@{mCHi%eeNvy=3lqYcjNK4^=pZ@t5myIo!yzu>lPKY@n{E7jz_zLb3779f9{RD zzU%Nc`0=iT{ps`Ih#$VA`T%%+HpzEX#hVwz`~dzd$6=rEsQwnbLFM;;hsAkzAAGQ8 z<$G`EN^rMg{or$!Veg5Y_iWLJ-^zr;`3CWEIXLDi<$nSWdE@Cyv_p=kCxLT3{V+Jk zQ{R(}cxt?S931h|@!~T@dAxX?D&nL5+Y;Ne|JDcVztz}ce6X4f>d>r(w-Nja>UL%~ z+jd#B&Oh3f>(chmI=Y5GNBaehqnGpNPhaxSqyD+gKVRX``Kt%KN-K_iV?XclY`6+vzXy{J3i; zE)Pvw3-Nf_xW1EliClh{O|t&t@P}*VF&c7vY?OTW@`uXmYe;$R33=_Y{CNJ}^8F3+ zycT;iIO=14%7grL2|GG5X&;A=9}y z9rL7iOIV!rblOWBe;B1E(fZI=r#O!J)#px)oqw);W04vNEy&+?v$z9`S{9&ATocC9U0 zzBuH4CvF+_i~BxrB(@&HdgQ6qf9BU8=BL|~t(n?a-fyDYm2-m;hygi*8_G3ncF@W* z`Uhro`ncybqnSCQxqC)4T#BKjQ%HpD>yEYP>(>2q;HY~qR^DsMA#Yqh7JLtzeH@(UwJ(5UUUMG13%s~Br@ZUGoJO$zcKOmCBh5&M z_7Jyi`iJ}b#=gb&mCJ4$`_h?2edcy&p*R)^A%=SoqC)?uiXi z58LTPaI};B4<>#uR(>A(L*71rBz}!PZ=YRCdC_OZelsAj`g|ue$~VS|bBuckBaeeQ;1~z4_xN<;_4dzc|U4xB|}p`VBbzW&iMASoB}9{^{*6bQ%AbKE#w!Xxf5lJNm9MFFW=1 zFPOTZe?fz$*5*yvXPfr|XPXc0!LLu)>(gg|zr!Y3r;o7D`Zl1X(B~Kx#~3w6Yz>as z=sfN@VxGrc2L<2!@*}@}=1<`0Gv*iP{JxtR`EBEE!S^5|ng7G!$gh4UtI)4~Urza* zCuhQsdGfV9+<5^V;o5e{m370fQlIo4>ox3ywUb-|z65+}TYUNc-q*l4SM2wiz74*! zV(lA2f7oXq@^?PNpX&cMIP3Q}8M1zVQ{(2Oe;6G4eFyuK;CKhy`jvMbncF4tGU^uf z)qi8esC#geeXBP{+3!q`K8rJ_G^b2$PUb%=;wjDPQ=3zZuf9|+NT1hfJmoKB-}%4U z7j4^F6qeieN0c0WL*KgQ4By(9t^()2WPA#F^~ulr9!-3&Q5{ZSh-*}0uOVmb*FG{{ zoUr4YrNQ`kw=I4IjTg z*WN7uG5SK5|1dbqTi+~y4E-w0zZRV3^;eefa{VC7` z5Fc0N%R5Wpl_^8=ov!`Cu~zo`7;lk}PRVx;&7a>n{0{hmmfifbXBcSi@iC})U~aHK zLmx@@1IJbL1F!qN5WKxi$aRl%d|Ty@ zaUys>c!WAge!pZ#csI1LV9#{}tN-2Ltl#sdtlxED=(j$X;k&4h^Zr-CdEUPVY@PH$ ziczWGa6hkqu;CX%;D5DPwjw_r11J2TpN<8GpNyUF14r!qHuc^MJ9l7{PU9N(i#hHV z)V4#u_xKp{v$1mlGKR!rr&BjUG%%fdaA0LQ?Y-24*@r#e`*6LM?|s|^9$}Nb_wf+> zSdS_H9?Ht{uLFm?^`8z7znb4~9YlWb)q5V4@12NaTv-1%QJ-A@{H+G{{}q1d-|PL< zpFYx#TJCYuj&s4e9k&GAjuZWQ?e&JiQg3^Ce)3Av=@ z`knpuUU2kN@%q#^u=%ZP&c7=-@;ffRNB-!yV((Q4)_#8*EBx_S>hJYx>njy zC-q}^VnSh|0pj13{;v{WP!6rgFRtmbU&P@T+if+n=5}-4-$h1J-`l}qr~URmu>Drj z&fio!#m2W~v|GeC^B)C{{I>I%sh!RL6|nV;em}2_gBG{-JOs@L@qO%r$K&XV>iI#W zay`XSPut(~li*wLkAic(KM(GbM^eA{{=#ni>tb;9SKI4(;M`vRCPmDz|0nFby2n1I z;HF!w`}gdN@l^bbJ~5Z4AipkhL307+NX`YG!$izk(HiXx_~9eRoG~zbt`B~h_(xpX z;=`)`74glV`Qp%T40|0u&N0k38leoyn6(U?W7a#tIcA9?W?8=9zzO|ge{(J4BUtl@ zv(GF`yov|S#`ugcDb_mK&kiOv`q_$n=KL9D=o4|Sb1#37~o)39~|d=4^f}}!9QV>EdPL1{^}oS z@nbD}h5TEP55Dyk=lY7HzV?YrFf#XvSAj>8{@3=j@zdZ(e&^|P;diUNeaLSZ{G)$+`Nrqq>pyY! zpE&Aoe-TH2v40$mKk_{MMsUPA%exyK`Nik<_|xxscd3(O#JQ^Z+uwiXPV$>cuVo+K zOcLv?z!y=!8_0h^k#4_l{X6gm75nVK5tO$vIIf4e-?H-At=}}m&GLS7xSKglQn$Uv z+->?iKkce*0lbY6xvJfPt^oBf?=LgXl6Hb61Ge!nSD(tp`q_=~kDUj*v^)PczDsi% z`*@ee?_K)ssEf>RI`5zUiM{bu^8V*X;H}xhvR?FBW4B`8UzNYOV)c1_GW7YqvhUHk z;`?UmU%(K}`Y)V1S^p8>tY3cUH~(T9E9d_iNgp<0AHW|A={u zE*|F?*Yi8gR2Z67TE8Cmu|#bTn_267fWQ4)j>{pxC5M`^HuFFk^verlTL1WC+Rg90 z9Xy`#}oEEIHegHtYRFOVI=f8=)u0e(edLrU|$k#%X!$8+mh}% zscoF&yEUVIO@6ec`F(F8^4s@50gk?BTl-C|+}1vekoCzAeU6PaF+Puto57*a@}5jz zjPlg)cTThZkM#6i`JvzZr{T+-e@(6}|8{)^7aL@t}FuUa!o-9CBbrN;yTnJtmiW6@ZvtP(rVYEYjnfM1r_O)X zZnn)Baxu?}AHv3HtAFt0c!B?TV0p1l?d87bCeAZR^qgN3@4`Ogcc36}_h#;I!vCVe zkoSIEr$($;jrzU=e6vjGMgQ3;zazH@e=-#n|4gl?fnt)SfoZk;Thae&60&~dcGiCx zIO~5UdDSl+^Ob)u|MXk_z5Jj2H}k*jtN&j4kNunZFTC~ND}UN;|L^mkRol;@5^=ON z<_i7{{nz9eb_aMFK|98UYk~=4z^s5QCyj@H5R$)B$|vrn(>R%Z4~Y?n#5pdBb6hfB zuZSMIi)%I1KVpygLB?CgJ78hpe-(Q+882kA)gtFM=Sj(Txb$`C6+1TucFp44nb$1x zV;sttGT-qW{C~BkkgvWcT61_mYBTuxe$;T%FW>x6#P@dsr8%vc&Eq3RLC&$j`eOBh znyar~sS1F5f4lFq2lba{(}v-xt)4}-8CrGa+k^|?<@;E!Yh0^FyyLU61LhZV4h6N} zW@~@NrX(~&%i6emRtuZ$?`z+UdRfIU2hZWyZ-+~M1N4pT7Z=pt&)XEs;(ngjm$^hU zetp?@DAp!#yhGs{_ch?W#`X8PyXbSJWA*sOo=&;wP}7P>r%i)7rJU}Q+`RP#t=(4& zpkBK_U+v~myh7d&((bq);t=ZQ-^lY zD&u5Y!QE#)f3^NohJ)d~>DK`Az2g(XmsSDi?)PzgbH(1<{xHXPR_u2aH=}N&76|zr z#pU2-EiB(bc@NmWZ$DS8{Kk6ao7S#phKNI}v8};*+EZwqX8fvzzpM5bcEs{as2L@Hs6jR+2%XI*=C<5(PqhSVf+%DzlE^@ zj?UxcG;kML+gjt@Br#d3P5<<1?NNE&e+QCcjqJNie6Dl+nw-BY{!943E*W{2el4YGyhr~T(hg#iGFFx@+{~FRr)l*2^Vo;q^`mhu z{HUMB`kCsNa#opcd}#58q!r?%8|s$h@juJQk33JezIWFY@f*+)*z2S$uP0qMJu+eC z*TI&M7r(U!4^p|{tM5j98`oi#e+(?&G2(XaIp>^X5Ae8+&r|q4(v1c_Ffe7{bpDZC z?#H{{chh&R|MVbh&L0dk`>>zSrm(52^C&aB!aJC~Jkv|Q!J@KYec5cXNtw1SpQ<3! zk%~QS;hm|?fTNn<2fDw#?(y7$aP$w`cVsO?@;dz}`!1U#zJ`5Q0KMr)?e8vJ*uug; zn&WQ5_L+>2N!S>20yxKzXMl4Ic?tMtHpv)rIQxhp<~Ke@exEB*Up!ahvtO?OXMNiu zpY<&SKaoE3dygpRe^*a_E=835wujpqY?8-q%S`L^m6Z1S^V>OIvts@E9ge#RUyr_w z_pX>rUv->JUj?EQO)D|qblaLPH~q{mS5Jp8>yC+`MZ93(eHrHsX+N;~lOj5*+dDPnY$TXCq%wKr->+Ka^S*n5x0VU{eDqBA-YbyIe*^o-Kl4}Z z^EkH^F6&INefRW=ccJ4scb-x48^QL^cPIYAJ$$c=1%InYSZ{(OX1pBy2W-8*=Dz~` zH1I(c-v^!vj`E-Xn}PCup4}?n`~xY!{vU=H{uj?p*l!g%!(PHB$zQ}i%b(waA5B<$ zPEGdw;8E6BU}Ku3zpdXB`Fp3|a()VbbMi>9ulS7>tAFht{Rbuew+9(f`Z7rp&<>V1K+9 z9Qo~khms!s%l=_~qJQl9$AQN9^ENX>*3bBx>$el(H`mW+F>?Lh0gn2eg1&c8X`11p zjc=Zz@1&`d^M4$i^M4N<`9Dtnr7KUIe`(JKEb7A^?Z1h@752;jJBzB!A6{jGuf9WA zBOF-mQT`Ti$jk4}nBZ$KU35}?oo}+AXJfi=JO z?+Xt5wa4Gp$@Y8=9Qo}pKL@|9=C^-&ULXC-{9g0V`8|=0{MzgI&Gs(pvDfRZA+LR| zf5N{1jelKxWP2_GhyDxx+^$#Y5{1_JOS@hftN3KF=X=krcs7fB=e~Ir?*ZNl`^GA^ ze%pa_{hVuZdz=K0@@?O5gQI;N)6Iq|@hpcau_6~hNK;M_ZM^UD<=HooK3_i1k&71$m@1|1z;pmWD-<-v9 zUccBMV}0{6&7FE$-{TAcS$R1MV{TAaZIG$ax>tB+ZSpTa3 z+u+b|`OYs<{u-UZ@}7%pENNG;bN{Pb*m%9*GBCrwP%l0b`4gy1~V)9+UDDTU)eDU_^53GG> z_1Nb-(xFfLMw$Nt&!qp^7xuyj(smWUFz~=&Sxd%v^8959a{2saF*w@uU!70Mzp5wy zl_~$dlxKhUI=Hl8aIl;!Kdpt$bHR6U{PT*92VV2b@xXfoLzVCNm7mA&Zr~WdGdMXi zem;ym(>T3}wfm~$RIVSHUf0u$_zG$1%=q9qer>WDenWYNZKRxWu3E|+8dpxfAMk#{ zf3shiO}ZBQx23%6*rcy>zUnj9%PN+C8aVi?E$KA=KIguzc#+?b_RaD>haK|f-)&$5 zccu)Mclmt(PV&0Cb=Aj`*9%UA*DZ+qFAMt1*uOBz8_To&U%(-6e(#S3exTDnZy)nP zhsy`9eV@f9?FRk<`z;INWD)#pj^$I$_E}sSk1Dm#yi`T5`|YQB-Mcbo1(5AMioc@$9-The%%S41tNz|*{eco+)j%kOut?p2g79i8iu{HK@k5z-**e7Q;HnTNP}1h?VP9{CN^nS0VL1o1?66PjJ?E8o0|Qsqb|5VZZrr2Iu@=0q6YQ zuj-N}ng6L^^Hc5d^;+tqJ*uE8dSZ>9b(R)b0hbwypfd74Kg0!iv97j9ZE0?JAy2EU^3o*(}HQYB~db z?v~9MEdE$U0DTTTihnoa*fQ5OQ5s`&5?R37_GmWto3WK2TW0s%S8$z}z0WI2x9!lb zS(mo3{084e@W@)o-+=o)c(`JJGt2jFGXGI<<}d5v`+R)x{Y|aanXGJk>(|DgtEXID zYRUD8RR_yAIbQ`&n)TAQUwo^D%`We4V~FuoAGQ8iZ)Hp@bT|23cN_C4rcrHwe_zoq z*5Aw)eM5b-*a|53XpFJ>9?e1ExJTo2eUE~DPH;kp_YuZOZRy~dg9Z6ck0kbdRct*= zTbdb?=RA^St#9CK;2R^RluTR$1n&dBlui4ME1PXrB1*?=8m6`Jg>w%6?cH8w?kufW zn_X+z=C-5cwbi}Z4;9p2OTLQZoho*1dnL!NjWk(5$2vSPDb;&zefB^``<2b|&a;kyzt;eQrDnAHN6L4}(95pml2dMW?^NpPp!D$Ti1N>?1~5mu;v(mo)3*`U)=& z4;?l%y3XjVqi2n-Iy!Xpg3+NRL*0|B4#&&ykjmrb_uyeR$@`+)VsG3RRo-i4S^hTg zaFM3n<)eG6ij_Z}ie`D=j|h4BC-?BZ?~(aOQ-03>YH;xFtNzAC_|5SvcKk{!dLGpF z)<4qDv-ED$_`9dlnLT)Ig26E9yRq2^T(6#a-X>?Bx6+FK!>a!gdqPr=hr5)+w~~gs2qet6TOEz zzZg8Xrac5c7@xkV;*HlBY`#KZbY5^=+m#4m?8={#*7nzPIHwpc0#D}dLI*j?drv2` zzp$Y8-j{e@#oqgRE64gtvY#&|bMEKofxCs<>iZ!$^exA}UxUvo1FYqL8S8@YIN1cA z`HfXYj5}9kDYW*QgXKK=6BYjl_!5q_M_IQi=##9A<5u1JLLKArqoxrb3VHplnK5I^ z*)yi>I%CQQW=uJK#*}xK#CHA4R5!lCyZgauFafZmR0MtT^znyj;&sMdkLE)pC%sX z7hLNa{6lHP$nU*Pv2$$jeP=84#hHI3LnipzCl31t<_tEc)7Iaw`dqu-%J_L5HnA(Q ze6#+I`Bw$lnI17|7*A|bqqh>)?_l=1e$JP}XZ@)y0Lk8oWZ(ZOYKlz)-^tUyiv?JlH=r(BBL^d(Z_E|0$NgsXmS&V|I+8 zSMWpBH-oQkH8x-3{9C^FRHR$r`(E|-Eo@d>XRthD6l-ChweWiL{L1&a6;3_J*F@eA zy_m`@seJFJitD*t(btddS)bR-L!bHiSk$EaV)Hv}^~H5p52XKXLGs#p_P7OaSn$RL zZ7OX>4B8s|&Y}#*7ezO#tTISSi)&2K{cX@F2i$*WZL^eP*EU9I^>4Ao7W1YOUd45M z7d=DZpg6X#yWWq!A-)UgjE#L_W3){+bt?Z0wP_JE`kEb!`=+rUM$WQV9pgBERwfd0@*hkL_?y!p?n}U==y#tw%2n zPkb_4R^Lbu-a2EJ%#$$k;KRwMdZ};0KjMu^&wO!E--64gPr}EpHvS23W%{neXc@CXBVG?l-AfDz?+oyzYMf2i^;{~`Ffd~uX-JYI%; z2`J>z{#(GIPy9wEu8a?6u@YGQiDFJ6_(1-ASTf-RqFmYBTy;9z|s zuT3L6#8WoIeZzfQ^KW>f-+CT&C)_v>+G~Ts@^P-GmptwBI9^{~0#-j=$LFI8DPo$N zQE_3X%V?QNTeR`ZRO{DeAN4Z^i6aKdKOpg4|B2_ZNv@e6XCH&!=Ybf9)V%im{~$X9wC{#}Wlg`N>O12QzO6<2EH>x4d~P}I%=7Ah7?Aw!%2EB(t^3h- zKYXw=Qqv5-HgLPoe}6H5u-tE4zb3k_9L1JcS8l}z9^VAsukzR0WU!2%RV$vob9+zg zHn4q};oDp{rT(KUU+3zO{X}0MZbpb8!^kbDdk!0)ReUG=uM42(ZqZ-vTkl7_ls>a- zr|}x`cU#!}7uajW4^;dC@bkdeRczmW44nJk)2T-nzU@1+$n`D0hW|~^fBCT{Y*%T` z(EAUgmk(X(-&tjZ4t=j(-x9L;4eoXxiPS|IZ#M-8>o;+pB6c$!fn7T^Z&g_G_^t zeYNgu^7ykvyG8>0PhrEAIOd&{YZIgT{iXVvCZz@?B2~T-fWKlm{@#6X8gKSjS|Deih;(zv+Lgl9A96K zKU@CR)>(^>sh&)Jzi}lU0Uo077^C#7Hb1macUBi*otYY&Wpjp$wBxYw_nf=u-0obi z+srL}r#))Nsj+38(0kHUPW6U4fXFg~Ao7b~nToBJ%fIq|W{E9u7 zdoEe8uGn+84}!O^*mJXwfL~b0vvbwwv2~tmdIdP< zr2`gBZWre%<5A30?}q+&E-<+`ej8&n}^2AY|F+*$&kj(!#bY*?d zqyq%rbxYn~z7oa6Tr@B?g;K2SbT%(*ysN8j^sn-#aaGxaF%}#K8*5|7iW3D;gjY4CS{fvXZiEMA;0b~`pWh0{fo84 z2ZFx!ImQNncG$YTH};wqHWxpe-zwqw`HT8P2*T{KjxmT>^prGPwZih^F21aNnQVFW2IsD!7Ko*y;3&B>p!EU zeL@E0`IpD%71UnS6|Y&b>qXa1-HMGdKL3Ap#l{%hG{=~$z!779jE_%5_8V1xk8L)d@^($6D?S^87Y`n8`VXo&=8syvNxRZEq-5WJ7#zOWS9gN5uNLFyE@{$r z)ZJ&Hu4rM2e?FrT`qY1L-(;NQkNnMh_^;~eE9%Sk`0P`*XAj!GOZjy9x*o2^)SYF# zjN@z*VQL)zfbp>%I+rH-vy)BsM{(F-osHpFB>6p)e&xl=yEF4LaL zHksxlEtN>~>l?5wl;Zrq6C(vAcJiXLs6!i6t*xr?mTO(9D@LhYFEq`ZBf^(@^si z`f#Olv@s}RV8IK<#js`j47O~+5yh$nS;2zP#>9a}8UUKYjk;Xl&nl1cF?P>eW~y z{BHa9ywUcR#FwE{Y!xkQ>shnPaXBjiLuDx1u8zUZWz(O39sj32e;fZlul{eI$E2#v zrfe;t7`5f^U|-Xv89Cu9!_jazHv-p~o%4wiyf~7xf zSESoNXtY_G9$ORH+kwQA?k&F9zQ-5qlb(ICB;j}O*sfP!?7)Lu=WoM4*7@SiD%Q@K zY)!X+@xJ`;TfA?x7{g6p*K`P5hG@T`z5%v6727_JglL~XJ(IZ>yk(oE5wC%;czpbK zxxQ3wa#!2Qq6&FFp)0v(0h!e9OpiI()JkYC)YlB>eYdX@xFq94@mLj)eakC<`?@Xg zS@8zpR+5Eh8F1~W^E~=^xJR|3<=WHVs6>u;r(t}z@}ImjYXS7VEy;fooaHY9D<9)z zv$oO&Kc(htmUB*Y4wP5CARCvpVDa4^14kK315yK@Vs4C-l^SB+jX;z zM@Y`gsAjOsbz2f&Y6eLBD0}hRY;7I%#^P(X|KI&5?>~~dulvX3|9Q%+Yulz9OIc{X zS=Y9`@(GfYuw(HFm7tp_lKao_gmhNIaVW{jZAU68V=4WdD}3js&{*BO8#B3kZ8@Br zOsDyWWF%%?OCLbfSd!*&b&_@JIg^u>UP1Ee)q~5EbXO(+=vb1YmOavuJl0I2NY2tl zV8J9Y!EjB9EEUG?|46dRCc3@rDW8+i< z%lOkh*xv-pe4q8scuV{zei9q1z1Fo#c>t-V!Df{(ds=teChMX&?!mkU#)|fDB>Y0RjmG4MW19U>L$Y1eAG7lqm?v zsDOZ=1Q|pbWKt%DFsV3!42nbq6$Am1$)vl#|F5dn>2-<-*Z1E0-21)HTgmRd|Fu@F zTD5A`xQCO`Rn>Jm@(-8Yz5K(3z5L6Cz5FYLz5K-)U9MfHQ~nXs#h0HpY2~B*M+y7# zpW*1}_jO^f-%Y|^zb@fY2Z8c;>x_QX5l8>@#67yKEbMhzM)9 zg0iru@5|CE?90NKSccRw{Y+uXqNWhq;0TSTTr+R?fjyn46;Y;0)(P0%&y}Y;Ous!_ z*!peo^%;J_VfHvaFKqq#os*lxJKrZN4p&E~^ofdqM+%29QwEqRj+x6@Ou@aFrxZ;+ z6WE8{Kp0tse{LUbo8-9BvcW%`qXXWKGhll#r43s zinsLubNN+8yFziaUCkqkHJai-U4}rsx&d{FqbrrsAu9Cs_>J%DPmmnzOX=%ZSH1bZ z{xo6V*Rv;jZxk2$dfrR%eLeiv*V8wzr&4Vqesl?4i+*IoM)CiSzId|ov%ZhMc3)xN z*Rsa4zLxrYUFG-nIaQeYr2UCi_NyvJ56?`E`?GT65O{atKv8Iyl#63nB66*vJp{3o z+HaVxW3Lny=I5Ugu=dM*eV`b@uNNMu zv&2Lv(%Ay>^(~5~qEEXPN_?gG7g|ZKqg9=5O9fWGN4u`B%7BXS9@qDE?c4or!kZ>K z->ZE>*J~wApU%3sOqhOTV`2IM!kOFYnPK4>5f<>z&-l-B{6C)--^Uw~_*dM%xwugN zHPfZ1&n^=tzb;|&qeR$o+by;zbqd((glb|!pn96Yp)3m}3jzCU8pm^d(FtO7u*GOy zds}QMY__0}#1}k$vqWdyMJ}u45Ohr(?Uvdat=_3qPgC|$?}*;1YD1pq3VWH8ge_0( z*DYM?AW(jM!R(Dr*Qszm{q@2=J^o*kSb_9^6Snlo|D6m|25O`~FKl$=)84%Nt%be( z%Y=RUuM1mxzSpvw3X8o754N-vV9vog-hCi-pS|P4l@Onu|#?ilt}YT+5ZP znT9XnYYNpkAjD@9<|$&B4*U&0bsH&^)!I#=J57E1hY_UsK=K(kX!``}ZH&%VZ|nDTp(=in)JN<eSBqnF<$#> zm6~1wvf-e}?`2V@K~AUetiAB4C_6lB|4rcm3B$jR6f+yZ5BB`bS3Uni)w$;fd;ZU; z@;(2Z!k!=O`S+5~cz)Jp#?LwqY-2n6fqnXmkaI|sW{;8ry9I~0?4V5izj>j`McM4ON z1jhOOWxF#X4D&YHzK!z;nXh)-SLf9CyJxuL^V}K`LTY$E5w6l7m02XIq9oyOTl_2A zC`>t0`Ig~t;@9acO+a?jnKnguT=+?yUy)8SNocQ^Rxg#D`20QX7ko(=scR~9{ttTO zJ%L33B9#1qxeNbsd{7u8J^ytYIXy`@(HZ@F zLy{lt)EnD-73rOUe$UQ&20|p;sOMdQ%T)2>6Z>G5XQ43P%Orr`QDqyZ&L+!AsWa** zS~B@YiVKBrk6i+5wjC9}r49n?=Y4hFGa!9aLh_gB`X>nw)mq~wU5}7;Xb-)97}}D` z5dXsteJU6AP&Z2`-rU`1yg93amb&_T{VK(UL}rHiWD$KCKfJ!H2%Ek?mVTixNVSK) znsEy*mq80W^7Flu&b|iKUZ(>ym&#=>-j0Q%A#sk};Y(x+m3-5NS$OZpn-#<$;axw^I6Z>WX;ZMWZ0|4(-p1H7B3>kpmOFNQ}ZQcK(^_;xI2?PUA7(7W0^I|9Jef3~Ra8NYC&> zmCw?%R{x8zU#l+?R&|Czd8exU@DmlH2M-xCIFdvELw~Vl!t}Sx>Du}q_Uld-KGM<8 zOLXd=+Gj1+6jUE%;R6ZTZLP!F=8BBY z^W~n-oV5(8WBT7Gx{BSPA2^x?{bB<2+eepPzhi{Gejf;zItb|ZPn~`KU(E9VQpz7& zkl%0xokBYd4W(ru+k{~}M2+X4kJqtJRaRw8*8~rYDKHi=uk&?P%Vb6R_XRt+(D;>Q7*#Vc+}<=)0<0YS7?MUelC8Si+L*HVc~~$eQ&~id+0#5H;o*j zPbQy3rWMoDqc0(DBncHt9aFhTf%44fx5Qgy=+fi_DyUD`dcC>*~2Lan%tF!qD zYtdn<{NMit{}b9=U8 z{oJ1W=%Fx5LBGKLD*6R%6nw9oJVXD6#eXq=RncOQ^0Ewn=cd2Niq}Pj`kR~TfOW(Y zmlx}ZtCZIn;vumAJ5cz<2!k$jq`mcN@b^<6t#53)w@^ux z0ygEjL~qm0B%ln`NIzS8divwS(D4OqJ8am{p=oLw;v`N=@Xe%Z%vx~uy_<{Ul8hs~a$W=P~mzF!>=PIDt;B`^0aJtw)>!&sNUXSyPb^ zc)w$wuAYrByx;LfUB8$x5F~9 zscdTDDI zbnM@sAKHj!3w2h}`)Kh=r?B@sRYdlF3G59oqqFS|gS$lsTRB%>eWfT+e8ic|x=_Wj zr%b(nl-$#rqFmY>M^SFM#oi?s@*}+i#QxRk5f*dz)c2%>t(?rAekXi)qT^>fOA-8x z0DT9Yp;NS=V=5!wGIffjygMmE&s>hJ6Sy{*G-2=$J8VM)Qp7485zib9i73R%qk6 zs0SsASw>sdb!4?-}daL;squDfpD7+RZDy*oUN@CM?ACdEs8DT zPfzsG@X=gUt_tz79Lww4mji6=m~zf?blNJ|x79BQ`?h+N@QXSKwAD*>wzkUt+$`Z$ zbP(8|dr4<&7v%SvYVk07))4;uo*t;ZMKiFx7ohJ-e&WK&1R&3IZMyIAD>=L zz9Ibz!lY;2F15m;QwYROO4s33FEywPQT9h-Vn9eeq!CnN?K$NZyV$}m#@D&AC4IKH z&ipF2jf&0ppm)*RB`70JcVgf~$A?U69~ z?;~vaGnWI~7(n^^%89M~L-caNn!>B5^nA}oKgZPYJ)09nKT0~__jUWI0>F$fgi^-? zI)1FQF;*wDStm#UNHAF%s#Zihg5#w1|Jl* zHb}p{r8?(QIudBZTM5&KX@|7E+4`bNm4B*v>Yn&9IxL*W#U=dd;Loo5D*v`pu^~`S z?*I65t}X1#xsLFQDHUx4Kk#-sLo}a$VV3^kEd6UPJ$ASxvje}i=k1`MwrH@!KZLOZ z{q6wtYM;7H!@s7f`WNZ&C{*XlOp~g8sw-9dS68SGiUt#b{29A_JFBsIa%ih|CrvGh49c!Isn?hx$PMjd@Me+2^&tu<4cN>@#MBdljV6 z{AcezVK1XIAl-x4JZyo)`FYq^gl!(iH<=C+?-U*6JuIf15KnP#koKcwj0Z4B-Ou=y zJp4^&wihV_9u8AcEc#LP4?oghU5aDp-txuy#*k2N2-H-%qGg#v?EI-uYa_Z$A=)Hl zW>Hb3a%fi!8AYBmBYkee>8gkxh^J5n^1)|FPT99iv~UW|#YgmB!@I1Gi&h(_|7w@I zCT_Hj5bD;85E^q+-4o-sSl}gYrAUq)xLv0+^I255JK=ke)-!9mzE=nK#_q-3=%3+w z-YdmZcOoa!L#FYPH@>L6@(Y<%|Z`&5Dg&mT{d*^o=1ZLcY8ZF|JzNWVFfi~jQO zQ$*j%;jv&X1B$KqEjSu&++pjtpq&&k6re(HD(dE9j2zDvT^z1{5t) zMq_o;&aoK5-|iF9+kzsNq)@=t-xc<@zCqaAdZIdkGH^#*Zzzndl}~8Vez8GZm~XbM zJhXXS+b5!beRvJdnwL3}_p$Yay^sA)*nA9ru;+g{LvdyW#yI@fk8v9b`}xAg!Y}F|(5LLB^X)olkE&ih%g56m zv2Dt1;cr^CV!Y;#gSO70)KxgK1#HAU{aay)3q=WjTx}+s0(-8nv)L1TQ^JTN*EI&jGA{dipYW}-&nP8!4Sr~5 z5GF46_5J4R->J*bUH*a99$52%-5(G^0lj!X*Xwmq(hE9kFW%3!c_sV{ggyVO!X?ZK z@blq1_>98PmR(l;@3PB+t!;FwTNDfdo=#c4nFmrh6!4MX z>%0h{aGc~W5NXc{gZ=(2>~%lb*@N^q2ro+f7b^W%rReU$_>)MXO+p68w!yDy3ZVuB z1>`)g^CEx(HluI#`SN~P8K`Pqm+LtxUDM|fJ~gKjI`uswEN++;@7ZjbFm}C6*X4hd zF8Q=0FQ2p~zu%Sd8@uK=JL!S8cSJv22LXDw&Yr%R%H!$V2zxs7Wlv`h!PEJ@B2VXD zkEf52eLQ`fu%|Ou_4LnY^xHD}JsF*M0xbRJD&J~y%Jo8NwI8MOpCx=&!q|H+U6%>p zB>pFK{dtGaboe>ZPZzfF;sHI9c!u!aj{m}p|NM;qf{g!)jQ{HyKjV{^|Lu%_LB@Y= z#(zu3|GkX==8T`YtCgSf-ktIPAmd+{@jsaHKjiq4cS=V8nWOjpMsx9|u+`uC!Y%Tj z!HOd+UKHP{IyS=453&DHCVcBv&Ba_@k52f!+l%5VU7wurOQQcq*CP}Dh88-{>3V-h zXP?*8U&`pOWc0sf^tUtm`x(6}qcigQ{9A>6{%skZd#RqjY(^iO(N}f!Uv)MWUr_!R z>mZ!5UnTrTu8ncD2jrK5s^_(3fA(;^{Wljj`$MO1^z<^L|2d;$KcD_D8U0m9e_V^L zeS~eCcu#m+VQYU&qtA8pzkRbgj1k)@jPXy zPk1BIC#Uom3csuCK?!g2cAP)b<_OsHFlSFN&-|2u8tHFjc$KC`I=>-p{GAJ$!?!ob zru6vxp}HQOF#dj+uFc=i`-k!qo?>)i+N;Oxje=WsFvhRE@|ZE)JO+!TKYG)FvjX|k zANc&&6>)T+>azvPe?4K#AO0gG%k%S0t>^zh*!Zz0^KG-|*uTg9h0T(D?7Nz-&Awyg z4>N_e6(0ijJzV*hLK54%m#jDoH(lEt=4$lg1Z>1y#%yx9bfyh%6{xX|fPEWbf4NL_ z#+Xxeyx{0?#x|t?s<6pl@jCt1hHUfWWFIhNoMHNqOND(O!W_u@2>7qd_!;9o z|F<*#?`QnCX8gBh{10UO_htO|XZ-k!*Z=X1|0fy$GZ{Z)kk|j|jQ^#K|HX{|kB%Sv zouAPelf3+tjqGWw<&UE4Jc>DeFl>A5F3+UfV1jILV>4fKOD`bio6 zOBwy_jLsU$@?ZbGN_dYB{~<8`4iw$@Eqe)f#!8ILK9Yx;( z)&5QK-nNpazM9|mitDXnx%Q5cD=ZUusjs4`4{XIvl68m9Hr9dhOT*~)var_;+n0)C zY)}`VABA9*8F7%!W~T^@BXNvwD*Ck#)GNn*+TkOQ=XJI`!0LYM82|XG@MxG77*Djs zs@o6#mmELqt6wSOVUazouXv7qkA%5@#N2^$5qOS=@nzkBqCM&N%)ZPgP80U?jiZEZ zzJdM!9sX6n7r$q)cFK?W@6Jvh>xbFGdpr7!jJ{t+pPAA3&*-~k^aC87`R`2CkDov8 zB8&_Iblrk$pzo8>56b8VXY?a7`jL+QAF;;~(&MA-ab!l%?ZMi`r_b&21xKg6CujPe z;`D{iSm^Eb<&4hn{&+gyef9RdG^6uQw9&E0aOvaygKP6Q{KMDZ-Qu4wI(-7+AHu)Y z`MiMC4sMS4Ooy*fdohfEGw=CV{{4v3Um-euy3`Eqcoi-bJ}&J;x5TvQPNzU0u*$e` zp|5Dx^$_|7om&&Fn9$azvr|9;*%#^T_4<;q+2QtE^__HKD<^ok+PTNGGklx$_VjsD z%4240*Pefp8 z!s{kF`faW2GT}wHHy2W&-lz7tL+>VtHX_lPZ)_*};DlL|Kcs7$Z$QU>o{qhYK11^M z7N%Vi;NM4Q&%d9r@k8G?qtkwjPJPW59<75webHvDzM#YF>Bl)b<)0^9>L5`5)208g z2n)*px~_fs4-(z$`&ZFTAM`ykqraBu%{p@osXv8X6u*;v=0xi$o;E}KD9UomHj}x~ z{ggZ7_h8C^;+Qo={5EEN|E9PmwmyY13VRv7?Pjfsg!fV!!eMvC?|W|BHtF4E=0fLsydvM_c;J4!jpB&UnE;%J2u$#pvXX zpOiWXV81^>S!pMfRZSq=UwMp7Q~1IU^_>=7pPn%N%$FtK_cO-`TR+480=xfU>Z!ku z$Es875{V-pJup&_BaibH<@4Al%VYa2k3Tv*>Yix7Pa#)$^zrxtI_S<@3r_@1 zEhY)Yc!^-LR|#ibVoTPg^N3eK?yJIHuA1sn*FJ4(@>gJ7V<^+IXa^|hD~K|niQ02q>EgT$H~&k=dp=+ z$%8G=*$tI`#AvpyR}Ekwu5x_@>xT8`8g;9Ff0(R?ABba-)eUv~ zW7*o)lW6_tL42#e!|4;Ai6nEvhLre1#he70z2 zyIX%8`-=4wKbUdDFm3HL;d(m|opHdn9vunj1Ha{mJl2dRkMiv=T*9mXzQ*CpCGQ>KZ6dhVg2p-S#KML|E7%p`x%|RTa!oq z4wU~}{n9_2sQMVJgK&i8t*EoLXYdvd(|=qdZ2brH(TMEvjY9i(++<|A2C|fwSVw^ z8XV03!H;D47a4vw!!Ks|Ce^o>cY0eRK0Ct~WcZQ{UzuUb?&bd>!+*~3>luDK!yjaL z%?#g=;a{t6eE!d7_=OC=oZ-J__{q#(2ls1~|Ah=6pW(R~K0U+uqSx2=htxOYp{Fx` zdwh9@?{WCkKZ)N`vG#Pj@O`2mp@Z;%@FO}~`-A?nu&2M9(MLKu{M=vj{5uPKdGv=y zhu`;yTQ{TKAo^>1LlKW*vZ-!J38(9z*%KhE>>ofEImlNo)0`U_9z2LOF~zKi1NJ7@HB zGWtas{WeF(pWYWXf1*FVM*c8Z2Vufbo5MX$>;J$r6mOXRcA>EK&(Jq;bmTGDHhJ)$ zCNn!=? zVu$}GdFW&94~+kM%sWdS-=E=y8U9Izf0<#%2QTmW3{$tBj_o}5{R#T|{sip%6R_`3 z!1reIexG6HOFlpDpBWzbi^lodWZ|pDZ~l3T@D0M|pV0k$4E)E8pZq-kCzPMbga4Bb zBY!7h&p+4E;XlJ+_^-|Qf9>e-Kj$#~?`Hffx&8tE)f|R@Yhka?XEXX48U5Uh&V0_N zUzpL~$ms88^kJ?)LBG{qe}aDeHlLUO*^JKp1yAQ)GqXSG?{swPzdiLAI>o)JYICbD z!&+_)ovrP%mfKd?)^e=%zMs+YMd%1nv3TS=>#XZP6Xzn-_+UqI`I7&em=uITj=@q=x-g9|BAw<5BcLOmOpD(48;7Az}l7P zj;*hnEB&?=J|>cbezS#re%u=}On%o1`~1EmZ25)0O}I?*z+0-44ENQI?}4J(zC7Pq zrQaTs_*qMI>e}j_x&F$+<{JZk)f~P_@VUefW^HGf@*W~=<%P~I52GW0qOi$Fzpn|G zI_mY`M+Qt7|I%h!Q%!Y1K%Xz@Z2Eu~IE;OJgw4L-%aqnI{ODroq0e{x=)=BhsW|iP z*5;TwY1s#{wBS85Oj(Rh*?%c)Wd|e5FzF`=nEYk`OmrZ;MX07zgfO(@}Q3t zHvN$A*QwBHJ4Of7b_^qr`>rMre38TO-{APc3p31b@tQp7|8N+2%+pLh`mHQ%_5$+_ zC6DtPKJAZ^e&iO0l{dDG^_`k_R{%H=w&wCcLl?MU3 zZbQ}ik^iu;=?8w+VfbHj{NQHikMMU2TYB>2o|WYX-rix-`}P4o*2x2ZIl~JaMjq=F zlTZGvQ!Rhezv}p*(_TD%W#^yJH*$33PZ##`X)iwgX)Zna@&1C@AOHEbu=l6OGW?Rm zjBSh^HnxE$XLydojP36V+t|if$G(nX#@5dY+gQig4!#>A7KkaLz z{Li;9zK`nL*IpSu!C}(>N;g3*J^nsI*ve1-YdTE+n+tn=PjYnl&vqDozOQZk^iMCj z{K2n^?)9zdMyBD9nhUGiw{riyluQC+_gXsJSWbHOU@SdlCojJapsxKoV4h3QSaOE2jTOjW zkkRkR=&w3D{BJpoydl!p%kyh~==5EleweV82l_b~{Q*ZOzegN~|4$kJa_UP=9{h~; zhT-2$*ylehqo0z|Z*_F!-R&^)*kknacqhT<*CD6#^tFXOoo6VGjy%2tY8d}wkJ0-h z-{m%cWbB_WJX>`@ApP>{ODsKOGuXyz===`3r-O}-KRqFA{zQ588f;zP0Z(aNE_)mO zu!JYY?29XfuN0l}nea2=ZwTKVVR&BaYT>~Nb3gwo;bR@0xt^zgFQc^ZLDzrT@K4&+`a>%jmCX^sbD~^HG*R>D%NVUjP2WM*l$ivB&hC zWRDz&b+zbaqGSK3RsWL`rhMzD{(SkUUthlUgnj<&3S0i@Hz}i+8J#_9pMF|KXD#IE zyE;1MIbGPwhyL%$zf6D1_X*w8vGRcr%<#1ipZXh(MJhY{vV@z2f2lJ*LLhyQ&Luzr z{;9H;=bs{M{5L+WJ%8~%nbO0*udwk$f7H>*kGY(sho5~1IR2cO^r1Z+p?F`PpBMJ_K2q4%Cv#j+KRKg+IisJI(Z8C}FHUq- zW1L%SXHS>G*39cmfC9RornA@mbYZXinZjN-#v-r#MH&6VjDA%{|3*f?F{9t$=-7T^ zX>PWsZrOwKb ziO!ymFMIma8J+!nPyb^^XKXe)`mv6BKnDT+-qYFZ_lB^~|9xRgkA7Vly;^Cc_Z9Z( z*$43Hhh_8;iC*`emTK@JH3^;htDlSiH|v2mbG6cyBvzo@yqEJpK(XAr3Hx%>CPyba z<=od{>gix%UyeB${g{k?Vn(0m=qEiF-wXXhEM5WTzL8BRI+v1smjd zIgGp&ntS!7e^^`C`UCJD8UCWfv^V-bYj5Bg89v=%^rbyodCC8EVY3(X=FA^?cE{7X zr)23V?@_|DC4+!G{NMP&H#r>YGvj9+Wc=jMJtdP5=AM#awlo5BcFHs zynNo(^YYnqwDjb6pTqdi&xO4|EzU4|jz(v^Vmz?%3OqT(a~x*8URU*H;}zrAOwkQ9 zULGiH;}_#K{C>Q?OLWU0eP76MtN4x19y@cK;o>2X|BjloSbpTclj05M`7e$Cxs3l! zVbgbM{Ph1`KKn|Z|5iswpT`_VpBFOz)#N`W4}RVsF%17M!e0J29UXr9bIT&z`pD=l5bf|7eHd-$2;&f6>vA&u@}hdicMW@&D7& z;UC=G$iIrPmw%+A!$03)l|D2=4|CYn> zx5|G_KJCNrk<%Wob9>I<$20slhe>~KzuxwR|K6ZIYO^o-|HxtTe_Gh`hkuOHd;Sd_ zhJTu{@uSbaN^k8Ge4FSV|JLD;o1cfoq z@!IEikfX!Tw|6}MIT^o(fI1!i2OUQK3mJc#`YV$MKhNSChM#9XygoZ*^m8&g&wTjw zKg;M(W^|tE@bZTWTY8>N#TU)rc{X)hVS6?e`ku0{r!(FdeVaw{Cr5{W*GwM!TE_o} z#Bcu3vv&`QZvG0Uy?DHlOg?CbIU4wL_4VXtqGu;tIQw)zTueLlmpw%Z8X`fczZ znu`O3ZT^8irwRM~9(9=fs;>XWel=mskM_E!aH%p8z}Gtbas3g`K6Wad)fdk$t}JZz zd8PE-P}t^Q-~$|{ygWNQTL%HUUoRtnN5z|b^jj!g>L8HcmvpxLz|ak2zfDy?WA~8js$0jA#?SiJ=*V9rZ1PF}o}+_#R@V5Dx2mw|2i8xS)iL}t96$Kr z4AZ_$9`q|6MjpSpZt~HOX9`R|@Lx0B(%ef&-Y8*{5C6K3j{NO~XUm5O(D!q6@QDs1 z?=oSNNB?lMulmiJ(f3(<10&1h%N!>Er-ZG%b@Jl4NvFEH=w8ixOCj-UK^_s{YJ zKkhK;Uv}xi-5DO9`RfFSk;i>7lTZG$g-!pUpW}zlcXx?#qzlZ0*jV!Vdm zkJmpI-RsA_5|1|&zhTzPj|kg(nfzaM>t*uCRzCmJT>eYre>3Cf-iztGH2xz*_wvur z_(c$lL82%NT8~JAmd-?MmhX3k}|3ybfKA*w1 z^zg4F?Dg5#(cwSMVfYth{C{$E_*w6I`Kt(f`3E>U{PP_~{`HQZ_AyTW=-Wr>)}yrF zqci+nhe>~M|K9ZY@1a_+nttTZdfG7ge^=P+`-Y>#-!6Hce+^;dN1ye?Z|xI&jp!aP za`@xsr|7%AYmem5b6GzBbA>H`_@8xj`2XoJNi!#7Zh>d<9J4P#ZT{buRs*Z-7<`KmAf*}_(S z%CoifvGR}}Z2Y8W{cjk1oGWbU(RXcEKJY0@@9lA?!^r2mS0)enhdPXW=7%Pq{f`Ho z{_JP$?J)ZpM+w{h3;P*sD?cj_>A{vC>AB}@nDms-(z9PN(v=51)9DXB-eKhbB9qU% zVqQM)RG5687!yVa311_0h0|`wh|irMg}_ zVd&Vy)7k%qF0uAKD@lxD$u0VJlnB^}z<1ZS5FQ#~SkH2Qz7$qB9-cKHG@!Yjp7zIn z0dxX*L5Bb6@IJ4^_o-M@60Q^0a8v)S59qfDd-^6B{WlqXmZKk{^041EBFP6|oZ;&n zUPJV|h524M0sMEJ4U>M1XeJN(dcsEkiZ*w7rUD)U^wTr?JsF+naD4h^+1IBZC+z9m zfAw^}t>Nj{XY_>`o&6G@p8YAGev+`K?~>6^%jnCioR*&Yo-ADIAmD%OPk8^^U)cNS z;TiqtjDAW+KRu&Uzg|A|>*ZgW(HA)Sl)uJzr&m=R0Ze+sH(b-F)h^ePK%veXopubVk2Aqu-Iy|B%t&&FJ*^ z4fzW<PtEAty7b87evk1po^7r4qmq2|-9mKJ z7y6Qn&hrkQ-YIP9pH})Ug~uj&;3*CxZ+*w#{|(K5h1X5|;O#T~sSNWDqvvOSV;K2+ z3!6S*p7$|~{k(lBFZQwWfU%EZ__vU5zJAchF!n?rvnTvJWOVH7={sd~?nfCNdBJ~^ zJNHp6Buc|yle-&ofajv+n(}mxyU@msJ zI<|V>R%T+ZcJIbL!aWhLaEvg0<}nc#PYB}=yc5;K>GW1E&&QpDg79oZTO&=)bqlUO((>`X46#?+V*|?lR%0ghwQOu@}#$mWm_bJJh|`kF30YpBA?I zqrT4;_P#S$*n9{58LzGU*#C41H2vO}K353a{Cm`5@k_S@$W#G(yRgy8kF|i$Z?v%G zceB#Z7d}-70bic0v(a;X$dCJjmfv&24~zfHDSz~RLfGqDIDOzB=lGHT1z{^M`aCM^ z^|@cz^dbMDS$SC>T6x!862~iih5%;l1Jm|6^xGEv4Zg;%mgS9a&Jp&$d7v=9*{XxI zgZlREThZ5a!L;LI#3=oVnZ2pJj;R&Jxlw!p9^){!eNhRmEa3IU+khq1;}MCUyb;@~ z&-8F@?RjpcK2-?$Nx6Fd*p{{RHsU8>TlT6>jWE=Ip>@LnV3V~kiuALk#Z z3Ik6{>B6a}C!zX9x5aex00N=A_dSIe5&xpsEM1yj;9D}x(B$dNX*}kc8IRw|Fnf%i z&OJAeU(4{ODz~RohaSI>Vcr?=^m!TnmBZM5h>Yp&&K|$noi_UG*2Xq^o3PQT7t&KN z1n@=jE5q3D3SrX+KYm}>`|&Hn*2mHZ{O5n%EA}-So#^tjWE-E)X_*Kz~;C?dcB* z8y)-HDD3^X=xnc5aVmvdj_y;?PSy-4;x%Mjk9o($rJ`Fs zeP-FF@NC9@iX+Sv{Rr_=4+Q8uYi;zKL4g|{!Y{l|7pQEOCpvUFjE;Skr`Pc`VdFxE-qaF)r-Vq;YPDO1{Mf;Amm%14#d>uup%ZGO+a6dA4vFQpb4~-_G&!E*19jekpA7 zkk51Z9-kmP7)JggVUr*7Q!&B#9(~NfmMW(ZF6q+}=CS7_{GjlBU0;|mWA8APhdyI~ z4rHu2eE9GdesmklDG+adr5v;*Z!fk8|F>)}`sjb)l8|tlj9GE)%g)!?^rl=VWOnP6 zc(WUQ=S!k{J2i{$?X-@tm)FnPiF)LHHIs*3UK71U83p85MECN?2%CKPcT0Aq%_*tw z7c0b9eM39MHbr}-I<%>uG>L(>GD(-dt0XyF(Y<9vfV6zK$m@nRW5^4$xVC)`0w<+@c*BTyR312 zU-Bc#@qN#GvbXO`-V`=|`jTG=`@ZC_N>5*c-*dF4IRSOMt#GM>kk@r*zyDX)V`P_e zf^~}GqsCcS{x{V%`g~mdGT;2Dw)}DFd)hua{r~F=dgo#P+x??=e$=dyHV%fwsVmaF zU7?R=>Rc<_t&R6(bY|~O!)oYLik7N+ofz&J)VMDCyYTs;Ewmf|1Nr)4g&Pobq$^T(UC<2dG|KIUGcjY#Rq?@nRMpZl2H7d%XH z1nyfNBK&%U;lBK>!mlR$w#q+1nO>1F_E=6Bdk~O6QrP6vj{YEA25M}VyvGY>{=reK z*q^^4ke;=gr3a7A@a73qUXEh(72_mbm++6!*{5GM!&_yTxeNTriu$P1QusJ|*mq;` zdi#3$*lU{TW-sKiHX%ReUNQ~!hnEE$Dz4gO)AUfD9TLAz0pFhCMHx1Kq7cZlS-;^z z^B4>GEBn&eh`CSX59$OQI6GHdf%ZT^|Ce?4_I)G6i!;o=I{dxzn<;LX7o)m`c@fz(~M5}eg2ze^sO^GeW%Z#vitO9 zMxWy7*yCDZcnI$dYYFSVS0W7dc~;k6KK3*D@Z%fCf7!Av;T;{bKX|$-+T-0ad{Bm0 zmORh@-3)&}!}n!){|xWe)F|(B89p$>V>7&Wrr*ICKGETidnSGFj+XEaJ9R*~M0gqb z>%kEQJW|(&9~Yf(S^gx^Y5Q*r`@Z0b4FApHkJ88bwn2ji_3!J)s^)6iP0+ebeG~p^ zebc<x;_WaOG@k+&py!c(=eH4eU5RmmXoxQBHg}p53rH;Njur+qsUNgU~ z^sfw*NF%Qhv{#|*L!e*f{&X2(u z;fFFj(%FZ0&V5B|=fCP~Dt@N?FHZSm5B7|`J$QE1@`KI_&eL~u`R%`AOL4sLr;@y% z3NNSY2?=)#E4%u;sq1vce#yqkS;Fgxu61n)mkZN(jES)LuaHOmnY^K+~L zrR&cnJX!QxbiGr;==-FuO<(Y@9X>?-tOvGt{G)`8pZvBJ_W2zv?DOLpE}tLIkyv{2 zJI-P9`=PMU@5hc#emtjO`B9z^giSu>#s4gSk9mgA?{Hz$kNo&Ho#lu8 z?+KfH^8bpk<&XSZTzc@$4wK)T!al!u9i9A^k+1mtc)rEwx2&+wk8jzTzT~%o!{m32 zu+NWg*%?3iT`KJJ`=PMU?+Rg`-@Pt9`SFcylSh7xLq5MIwNImy-}=IqANJcw*yLkh zzIA8$BfoU%!F(&gA1puQ|4rEBlRw`Eu>6t#rb`cg!(sAUO9Qyi zZ#`kthy1=I?DJb7?DIQA*ys0cm!ABtb(sAAB<%CkGO(T>^r>o_p3XfL)8`)14;9`& zwO`7Ap{`9I^1I0KBkyHlFYm98jy%?JUfx<+dz+B8uN{TGJmy_qzoUh{yvv2XemtvZ z{J|c=Ufyetj(*%>_3|bNdwFZS_J+KjguOh!E-drP zJ7F)6b%WQhS^nzf(SE$V3C^EsKdkF~`=LE~{!qepoN_ z?;(6_iaYNgmEuNSPjPsm!yRK<3T;D$-*1M6GE5QnWtb}L%do95HbRg2B+A2oq!1}h ztMp?XWNS0@{g$xT_XiHcPknj*uRHp$Ri0agZH`EJm=pT)F#q@Exm4Kdob=2oeEKC> z`mQW}w@d$Vb0Xw#p2=T6lRqMp&)U%Rqt6@ZF!?h+@FP}M$$w%IU!Y1!GN)LZ6<@a&+AiXai>9L2UXAZi% zu%CnOBRob2fibYJ&Ne2|rr8^`HckG_uf6`PhfROz12Xz&9Uc7!30wKV?HL~IF#5Bu zGyUObZ^6<-Z*z3^4t_5@TnFLf>_vTIA77u;mC2_*v8S)k?S!p9vFB03-kv82|0{cv zALX(9a{EH3JVsxdy+0xPN7;K%M_-z~y?vn%5x*}l_2J9AK-kI)KkFmUPkng)7aTwJ zLHnUTaN&Qae>-nnOTj+lJIVJwCTgCJJgBKGHPBD|Q54?~JtFM;u}6i?u9WjJVJj!; zSCw#|erI8yp6C61`kBH${nc6epJwS=DD5v6ZhZRxvKF;^9T!!S=`(5W7dJfevCWW;dAt0 z)*ITNTnRY}jA0wq8f~|qu(#d*!d7>;ru4_h<*QHJLMz$@vf2l2_sn7+bgfJ7;v*Sd=EdW{wK`Lbu`@%J4*a=hj{GTgW*uDC|{ z5@E(f0_FOyuuuOJhw;7lGvC{w)>xnW2>bfnSJ?X=>AmmmB&V|R7~k7Z*!a=sT4B?N z{I}PD?0tWXoW%Rnr-Xg}pB6TGq`yYkr$0plh);i`uuuOTVM|Zj>8k<4>;I~-*S|~H z_#c#gPt$<(DQZ*U1K|@j;CwN{FhALGSnvFV@*gN{>Ct!ovW@!groqSSdz!G<_jF-P zPyW|*^yZH}dz81?6U_6+hHqIl?%}acBQPJ>MQ1-B_>Axvhzjt3S7*=vxUlDE{s})K zn@B26U#XG{r zPd{*h8m;dK770&D<)_}y*Tl#Cj=kW$Wq0N}u3w#E33gje_q;?~xsg8AIv?m?NpzhG z<}PdLY;zg*#`h8~br3dNy`^|WXSrSo@S~gO-$=L&)VP=aMuw-TK0WdF;AcM8P#OmT-8&4xT%_hhPb(qotYMNKhLp2RCu z;zQ25x=7FGy>5pJn{MRI-jwBy zzpN*0{(_CyUVCl*Es6`I*D<2uE9d}i<&}9HJYt=gIP~e0EcZjnS|a|viB~|^y~Sj@ zVwWwP9mxB76_C6Y9qRJ3aMu{eay?C*W^b(EN}0)J_yW6`}&~oSdOE z>m35`8k64MHAa_(iubx)AiC*-9nqsCu>!cS@-73CKC0vMWl&$XT}1ct=810d;OG93 z@gt9Sa!ek0r05>+?l5&RMtNJ^P=1=Cl^^_e!mQaOT2JMu06aFPlLcra6DW12A7Mhr z`B=@Zk5wmiVpWIEC+pZV9!)>j`3W7L5}%HyX*zGE!vgy4B;fViPuTQ>&Y0rqM+qAp z{ePKZew)hE`PR8%-gy`<2l4MbFxRrV1O5Wt`^!&+Ej|9SY;&W(tSW5&g8W<57`^=M zg-t&CzSi0+Z`xWd#b2Z^>u&<>j^Cc3-4UqYBV2t#AE@$r`b6PUykZOO^ojwoKcG)o zrBgv?u2l>%wD#eeu-=5Y@A2~p!}~JxC2Ko}@okSEO;|+^GFRc|a|+ZI{$O>*`!|0T zw)EupoUrAWKSS}(!lv-s@FymD+-v=UY;$qKl%3yY@?{^J+2+j5c6VmNi-JU_3?n*4wFzQ+U7hwn79P6^@CO7TU9p`YV$A^LY5raezm!cs>~2Y%U_#x-zN zhi0372eg5T;_7#!KWga~Li=M)#Y|0PkwLg)y_VuBb)NGgEU@Q%Dc6}W_WYi(mG_Ca z^sI`oy5kU@m%JM#Z^wj@zlN?&{cO)p!mcnHu7wm(wZZv(- ze?8H_l#M=2+cH5Kx{$Bwf~*lqmWHFiKWI>VR2@v(@F%1eeFOQv%0mB5z!pp`=S3K7 z@w9BynJ~6^PuOe$|F=~Ep8rgl-ShLCKA!(k<>&eLY-{8{S=jU6BJBA;P+`6N<+V2Z zDE``@M*h`>jeld6f4J6i*qd;K@a4h>CX7AzR(z?$?8mzt+_wX-tRn>NOC;+OO_phM zkBbXm--4CUkd$vMJP5pgz#)# zpDG!I>xGebWWv-P`OS;uP}gT^0??T-b*-VkZmUH~|Ge=0M5o^xuhNcl{H3tj*0)nw z@^;9)U^lfJn-?st9iAs&>2&h%5H|VvJ_}Ow{rhyoobOeillYOphOSNis*l8W$T!^x z*t0{|W>56pMYs&qBDBM=2%CL|NhyEm zcQ`u!+A9B;m*|WePpgCOOgQwF!sf5EpEa`fbBy{@-+sQ5`c|y5MUuk_>;tyFNfBj= z{MsgQ@88M>K1{k9hW~zH;|GtCP{a8=^gpwPK&5|Y&7dNOaY~=5iG!LjYlLs=Y-@zY z`f%`g>3^=`2+Z-pHs_~2)^=s$Ft=ExvWk2xdKr1B>(D%EL%km|G2D|TPA1TrINlK8 z^0`vqu8>^%4Z`Z`VAl|4UzT|WX;xV&?qPw`Z3bOMogUEH>+}hwEfrT!o17l|T&ws^ zbP&M5(%It|5@yVgx=++q)FI;0T8l{e6h|H^Oe^Iluuhw)v#ry>uVr{2CHD0B4x`iE z;`ciJHN(tY;`wE|E16fKg(rx}R68RbwgIYh4{yp!Rg3xRB5ItawXJ5elaiQGvRspvm~k zs=X1(YN_nCU_;BPYkXxwZ6cb_d0)C!0+Vs5OqKDq3ANtrt0O9*m`$y#G&1!Bd&xrM zE8PezYh6=n(`!X-Nsp#Wr5^UK^Gm{bGVGjCk5WFPLry^xJ;mWDuy&}5T76t^`7onc zVx34%udb?)kk8t&s;hE^=quH+RIx#KsiIjXL86tZ8zW2%wckcP8}2S^6tZhqY`UbY zM`|vqn1p&o$|=;1G%aHhz4kFyCDf27$EX)0DU!UqC+HeoqpN4b4r#zfT~nn`rCMpO zv{YIvwTklZ)XWl38(QtCj=Hbqy5p((aYB|^=RB-VojOJ)5+UN`b+ zL}rU5aOJ?Qg2rUQa*;$`;YyX|L@O$TLsBI4nr%FkwHjh5|4J!kts6-bf{|*2l2Jl; zpzAIv($&?i8lc9zf@(w&(bcn@3LZ4Y?MbOJQ!DED#2L)g^Oj!!!A#N3Lz|}WvV6=D z)vz`DNU`=4R=Ejmyybv8Pbv=q%9mS{xHOT0O>g&=4xu(jd zazY2AyOir#xk3i@3Q1lcn%vSOyF+h-8tqZJuE-qYyF&|A$<#j76R9D#>{{#DHTE!F z?bWDaF*KB2I2s`k%pS6|)TI0v9y7=KkG0qp%*f59k)hF$O>8f!FH(xX2n|6M(q18o z!HWD+1b$R+VPP<{4n`^GG*DFKNm1F>6tNmH)$!TH*41A55Y^aX?IdxrTj(~=lGaX# zMWKUB-rW^^SEa`6GOAZ7)MjPv%0%i|-S~OQ66!fZ7a${M?2J?5oG$;>MVpor0|&{@ zP7l=W@`GlmqAteks`06}i+1Mop*6jRZ@PwFCpOTaLeM?5JGB=Rigwg4jXFA?x~4FT zU?#y;BGRjNR_V8*1N=Yuzsee#`B5>cc66fVy1R4`tusSjAcwBedbZdv36VaXLj6Vp zekNZD)5VlTf>U2+5phrrJYlF2Hm|9V#>n)*DI3Jl8_*_Ef$ZozB2O$=eE_SwAuS`e zlvu<#VyGpgKK0mG@YpTU6Bi?VOm`ZDdOOgwD;u^?s*Mh%R}p$!(fC^E?z`$yA#Dy5 z&peGnN&lqCi9aGLb&r~lrOPOU{&T`fjd4*@2_?LDwP_k0LN5|}CVJHsZODjLOXFg_ z!*f&&87vjMA?CDMM78IaVblzYix^9g*|iaBmXb=Wk2`zAV%HC`PQd<5X9GW3hhl9cH{8OW$@)Lxn*}WSXUS~ zl9Z2R^8<`cfRnzy9BJ;7G^c2(X1u0qP675d6OBHrQ7!K;HiFt#Wn^U(k?qIIgo8fq zB!rd~Wu%;f6&X*GnI*c>id0-(c9<_$gWkmNrkVM~Ix(zWqSr;6N^EGEQ)*r6wZz*~ zSY_9<)mK%bere>A>-5~xBwl?E&^L$FBcv!syP{8foji&awHiATXQl65=646sH;Gu-HD5>AyiXrh0&?3DVLHd-TUapiMwhK)Ozj` zD77E-e&vALoLbKT#r!r~40-pn?n;x*CHS^P$7<%%wCj#7ZYkcIC10WuD?~{fNt|BW zHLM4E^^wRh_jqv9ifhqif}dqs;_U$Ur|k_eh^Slf+R^N>5&`cS(bX zA7cqRs=bBpn<4{qnz+S^OLqIDETpw->u}9FW8;giEia~#uqo=}iK}P>t*VKtb|vnT zW0eRC+9H*TkABPwvv2orLo$&(zlrAI?!*7SoTNP)x7OtMv*~Ubjpr_UI@+e|=M} zqj>81t1ImtMVyRC*^WA^7;7@ao+q0W=Q}v{-1FX-je3e#B&MDyFS|5pt}mfYfHj{+ zzxJ*C!&!caR~_Mpxinhmk(QYne@~jmbgJz{cQUi6IG^uzutZcHsHt0(guX}akZ`QL zZl+MGp&rY{dW2c*im(ZUmram))3#fEYbfT%0J;=`QfL2=LT$WaeTgDB+PHxm*P)l~ zRk61`1M34>jn<&Mm)1d70+S>c>!ZYnDn;CzOQP#RRm7A_eW|EoQ|gd)Z)8J6U6-88 zY{97czQ&&2r)i3DKvnm@D#nbhYB!dQ>>byw>7h-v_44@Jh(1(uGA=1FADq*5Jx$gf+i1v}PGMAg_HnZ}I>R9#e?yKP3t7F#dq z>9xByBr1y+_bgUak9kkGZsS*~O>yh6FPn!`ipA)&lzqi8q5vuR9I*Vxedrq@EJ-*rH(drs}x zTG!mBp6Rlt<%2qldmgLQzSyUBDT@qiZ(&I`abpb#E9lVzmqnN@tJ*tOtb2rfGj!5j zVT|aichly9v=ydaQ)*qNPR~TX39^Y75jU)NjRS;gLj61=Tu`WCr!6!OA01{Ht85V4 zjCPBHr-mk46c3t&7#-_Z?ITuiSObQ3*5y@6r9q$+QMLa(X=UkR&(~8o=^Wd$Yf2e> zSf)%i>SRrZu9uI{LQ;`fjn!M48Wb(6X`@Da$99JWnR7))dcSugFL%SlQ=f)eHCP=K zn&5J;sCVz6Uh6#_bUo$+*`-%oYL1%FJJv5{Zm@w$6;n75tCgVKyuptbh%BG`tr>R_H#qHn(=B zEE{XVvj(0%SzXlcAq6vs&M+vTVbwb7=swZRN7VIIuW5|I?TTU#E0pPmXBY1#KJ}Tw zvDaweV)@-2ddjZYu)BlZO#NhwB|YWIy*+lleWnH)YlfM6$H~PhvSJt%qE81W(KumS z(`o@d?UBnIaJotwrh@eaiv-A46HdmXv>_B8PuFD6dD4Vp;Dq9+U}DwnQa!e}>rE}# zy47Il9!oQ!DXQo+qz?>jHI_bDGj4y-DR+M8o>($moCIf{F-6*iRgEM{ZbwnPS5Z$C z{&ZIaClp8YR%EnUs5aG-Rj>JhEU_dimUhfMP~9dMSCv}R3=A@m?q5Y$)uuky^$*cc+5gi6>OoH6J$bR^-Or&(s#l0h~5nJ$Hu{ zpW7fQbT1|NrORCR>{H{W+lVfh%3JAT8LV+II)eg(vNg}m3ZVirmat;cZ zp1S1zjxmPPNMqGrXuXb4-We^{8O#!94XL|Af1}27_spv4KgLftRT*UHvP18vEMvK_ zW-o{aRaBT-qZagDpjmmaQ{PIzif#djO8%A6l`)mE)$vt&uGkhu*z9Co>V9=zFdCt% zpeUX#ep_^Grc%g-vZ=h56ygbY9W8kevg^i(d3GyP&1z#A($fXO5-wY1x7-Tzo0PbT z+s-?*udVspUTCS#ELOXleL2Hc)U}*bt=*n(P|J$u{yl%F)DG;3>e)g^+4LPWwOwx2 zYb{e<`ZYvzZ#8zKOgl1KWk6+MWl*I(mdmGWqcR#J+N-7$HmLXD_;Ukix63jog&v{v z!?KpJ zEG0Td(gcI)Vi^Q9CdX?iy}&#pn6!#pR=dJnqT0>tZ$> zq^SMEN*j`qsmH)AWw6dy>$zLq zc(jyv*UgV~*=SyBhLh7uV~>UzD}-7Y>l!NpTbFz3UR#Ii zq8^!^tlIn(JtU|{rrf%exsxJCtL=}z#qVY>$H=0Y(b#c8vK1w^OWY-_>65CdUORbO zQP*(@@0wDfQa_a0>DNkw=#9xkV%w-c@o3E;dPX#5eG}1&ZROQsM~lYj-d*ZCO(Xm) z7&*22*v$rd%9|R93$E1n%U@!P(zurv4xz2ZE+TXaakY#~pWMr;RFTDUwDLsN8AgM{ z;qxgD%s}3e-+&#qM!ptt*UK(!2I%V-MRI`;yp-d-q@T z_>esc5p1Kb0wL9&vUsOeHR}CV4LeqLusAh&W*StaWo&s};*lwa%#hM_1)sE-Gs zccBpSSiHv8=)HGkB#Na5eydH&#?d2KBj(i^HU`HR%ZY7nMSIY(L#u>xFlcCzdxB*v zr*1D=4@kR*-L@R6uZLu@111)~?4wmucUa|JRg;xlTIbZl#!8n;YIWK$15jn9+lNcF zlqz$IzKYN*^txL2%{A_OvW#4DskSkHR@z5v-M`RkG&w;w0Ary?ZG~&)bQQ!Xi4BsQ znE%vw6yn07DE?SE@1v?&YMAiUlFaGUSSHBHLM76su-jF2Wm6?3mqFR{ivGRhi>m9_Tjab7?AIaR5WR#G1oXN`87vKDVNZmL$fM2;G&Bno8n zUTU12BGoO>3#I--Z+yO$jE}KXgP9V0an(!lhgr!?u1-Q)wJViQ-e&ggEuERL=enZN z$e|D_LRCcwHVkR;I$w5m51M__%6%!}hMPULp0ZIyaXXWZ zy3EjuLvIA1UKP_!AW8n$7nn}UM81y!p|0`{ST@tf*iqV`T1#&gS(CvdLbXm;VGu92 z4!wWCHeqjWjaCR%9BR|WccW7(l==<)Z>a?~nk%q4LH^{g>y)^J@g#p;XR}CT_7+oy zJ|;Pev}|aiYTt3TC`UIBlbX>YDoC%GrBaLH1$JCmnlpKhkI#4NH321!ceWO%b8^^N z4x=_iP6&pxTdL8dp%cNj~?T68mxP_4DK4H~q}uwlc7cdT$JF=P=^D-Wgr261>y zMG%Fg^Yt-GI+KAq7=>E{U-$!a2z>t{lr2b%<>UJi#8C>$prm~l64z9Xr6;0azkWX_ z&O(LKRGXgyM-%jsF8$gD4j%Gqh{IO3zWv(<4r*U!$k6VXu0o>LzA~ReUpC+n z_Z1YPfw7Bp;+qdCP6}1!iT(OrP8>>LgiyBTmT&%l<} zh?rY2fC!ADf}qgkBruYb(jp29$QVJ;rFB&>0R|LBurVMi$^ZrsLo2A52T;Vcy#KGN z(|!AHwYdAazVCgn<~vjOo?9o@sdz)X%b6=H6i(@@N}`g}AJgTul(bCvwL<=S#ZQ%E zMbhTn%^C+f2&Hj|j%|h(TGO2>@qt6BH;JMsaa1;)HI%2)H-;8hV#$R=yy+Uj>-8qV zuZ&3~%#T!}V`wq$;M-lUr0T>+9G#*HQRST60^(9k3nVl6ucoFo)kp&~GU~_qftTjd zSm9LtYA?g;=87McVDn(}%`Z4r;pjgK)`oP_{B$j;O3KLSqRUYp!vdZ!DCGC)p&$e* zV-W}0IfHdM)l0B8Sn?``qX2qd1x)sIMN4{>R0Yl?PE%%PXXjExMgFD*lDe*<8uW{W zR%2Bh-A$Y}Le(z=VTHnpLsgT`c|y@Dzi3CnzIDP+iK4L7)aOh&94h{-xQO8=9)xuj zwh_k$#goQ^bIlX(^R?ItFrBKw32`T6|44YaLvdL##aLffj8h4)cZDG5l_ zQ8k5AKJfWiad~+a_&p=GBle|AC?b`=IZhl^W({Yfe>p?pBr4Dbk;8Ey}GT@mzTJzIE%X$aL$;62e1`Kqct#Cv`4*bO4=_ZXMH#8*#E)3?kOW`XO z;wBWb!a_^7I;GraaNwo_653=xLY&r4F=SghMx$a z@jEoF(ndu-YHts5l%bP~*S#7CO>~U2OZ}EOnn6oc)6dBKLGgpNs%24dh5R(WXw6_k z0=4RnD-h>N3ddsPheQ_^DOwRi7iMMg_lA^@wPcpeXr#+=lu|KNP*_-zziXleQ)~8r znVI}86XF=A29;%PHfiFSVJi`6&s?GDOEB;y7@VIXe>I?$)%%gD@I}{~4oIPN2imS85z>FexK* zwcsF<{Ll|oc%C?l(Vm7X**UKhN8?oyGzN^*A1hjRysS-CZ8=|S93q3%%JrECiBoQ& zODQEg=XX_3)gwL4YRls9P9PaOK#!zes!t_*QlX(DP^++9iZ7GH4qR6Ws#N1|RB#T$ zt~58luu|p9RjZ$;aI`!#3%H`H)oRq_Z&jcx_GPliFsFBZ) z6#$i2pNVC8M?R{L zgxb~p4c=EcD5DcAD&rI4d^u37W*vXyCdW5#)&7+FcreDv$fk>{U>;Vle#3?h&n6C1 zQq$o6T+|5C#l&&QQ;9W@o!wvIR8(YO)Gn%8t4_UZ6s-=I)a-2ZLWLD?Ax?)B>zhrr zXoaRtRaL1ZRIIp8;bLKrVDtH&*EmKlgAXksJNGr>*rvrgRKhl)#jv7AcvSj6g@b;G zNHZiC{%CL-g`h!|WMQF1|D|U!h7f;Q3PWh9%m2|2RJ#fvD4g zaU4Y`&+_~1-Za94V-$}fPV0saU$=-7S2>CF391~OX@U|_d@XT4&X(8*RYp8lt-4sz zqJGiyseS@8w)+(=9m1MpQ?F6~4dT)=athF2)T~*H4YS_YhL$4|T>$#r!-kf2>6D)F zn<}RVbmIhH3O@!SPRBez4Wz_z@MgQtEvQ%o1sf_H@v#U=Y2?D`EBH;oKfp0~(Tdpt zRy>jAV49MFHq6ocY(uNV2*S~)cGKld?ZAhq<_o2q3I#X{{X&1@)cP$e7vr%?qZKWU zljQS_Gqf-d{IRgY*fU+>P%IrCCmL#{qAJyHQ?wF9th4T_DXDriLXf|w zXq5=5Uf&*7PAS5vfl8mMaxg9 zs+e+cKlshZp6Rj8zJ#`C7{sHSjAKj_1ma(1?#I8RE7V~v@_2yQI2N(_ud z#5E^QDptE7vz?Tq9Mv29d>vIe6$OZKFoim25vSvsO&99r8UKibS1 zfH6TuONXchCd0nMSXE9l)a=k!RXO^KT?wkBpi~kw%mQ;5QaZpcMKJzCv zzj%iLwVzQqZJ3gda?dFo6{cp4%bc8-bvdaeHLh%p)9R5Pfwaez(=MgI(=$F%I0+V| zk?%91)df``ePPNOl*;x?IjU%q!YNHu^P`#>-?__C6h?x>hM)G9?qq%ZELzNW+!8D* zs!kl;ENvC`HZV9D0DvlY~CSS6D+ zE$d17n0}aU_|a1;PT~G*OgUvSYaP@#7=9p8?4VxGEwOTRf=;&^oNDOGvdk=g7hESL zm?r0}F#NQ=ddF`Kab(5iB%=yxqbWz{Gg1CasvOSax@5f}T;bSSfmL;xm32hpjLka!`At|P@v^e! zH&c$jM^dhc{TPqN={n)tjV7@e4bO<AA!yD|B7(e}24Nj6;D3N7btkXJk?r z(pHa`;}xY}EnSYs)I;?Vja50_J+pGTm)2VNF;LYgott|qaf-95M>;S)plBglc|=uc z=6MDeQyAB}DI80&PSg;b-&f&MGb?aIp?b|)Sf>XJfq0BGnovqG;8QYHl8GjTKd^ zR{eeAxa*3|R7?^J3M*HwTCU1*mlQ2GUv0Hi&A@j`IVV&avmIf4DN%v{doaW{?-T++%RsX4U0o zKA>nBL};XBmz!7cl;#JFt|CmPvNvd2wLgg+CNBL7w(4@^9TUA>m!n@}DUO34v;^sG zcRB6S)OU>xbIJ*P=7$PLvAX6EG1;HT%F!||zthsb(&cET_6+Lx5OIbXE~xaQ#!1yG zb&hCS<0Vx|8UIqamw>X?Aj3}ZNLtg3)BSWYV4~xlU1@4VhtW>qekHoPG*^t=OQNw(+0v^?l(M>%kn;#H{RK<#`HKZc_ zQDN;VUO=jDJ~XWSr{gBAmcl_1?$BV(4bfHFDjeA|U*JSE3zGw28^)89p_&Gz{Q$8jP!b*RFTRwc%ZZgxS}d*s>UgsrR+?>DKoU_tK&G)CFL4}b7|w79WNJig2Iu? zs7Re}U^#}oOTU|9w7M{BxHN_%JB`0J0jI?%T%wG$J4`vEnJ9iSar#svpv+QTPSjIc z-ffX_Y#iHpTH108tqW(okeYh0rJUeIMdtTe%EfT5g8$Uz*axe`xZ>{~YI|d7-)e&s z?{h?ZM&THY?ETS&p)qVy{5a!R+vDtt^WIcA?Q{NT)7hbL;!e&7GBbB8ehOzAduC=- z(?VlP=ADV$yl+%F>ZSq#tJb`Ne-W3KnTw{&J3#8$ql)Tx4rq!l%Wk5k{_O+Ckm^y{ z(KIFw+>{~goFSvFD#rmX*7atdOq^!M2B_M8XTiY@?3cLP*Hh7=ER!mqo_>kOK@&zO zyo_|YtDF*qh29W@Q|7A4a!&3z;>ZW89&*n~9>D_GunQa8*hJwY6mP}=eCM{eE=x}5U83Ba_MR5>tVGX8&EaHd^yy}Cou zvSUZpDo^F)e5i4(N96#hox5MrQm*z1qo`b!6NRZ4*72&G7Ry+Ln(2oXPU)f%VEdb* zrL&ZyIUC5$!e_AEi5GKRIK-o}Bwyj&=BB1qbeB`p&Ww!e3dfj=r&`2;RIPCI7DeF+ zE?SXqaK?e!o|cAIBWaw^*Vf3OYP{RVS!=+QqvUjKee+K2B{3OnRrE@F<`t?O_|VPt zJ<@Q6Q&ol{D)h6)X`!l)BMadle4?@^sh8OvL`Fj z=KP@e(JQJ5n?lxa8mE>inpi)}Muo#9te{d=+-lr-}1rp%k7ozzv%E4UcQKSK%_U^9nFI$L;t=O;2c1 zsS0J_h7uoo&>IN;w!~@8=t89Qj8hekkKmbbfmb^dr%GyHv*dXi$Es5afson5;8bb- zFQupAr|MU4{Nv$?{;Hf%DstZ-RW9aEbuifQQzu}-c66mFr)z=^%g&ih9N9pBJR(77 zRk|^epYrYk!!M>ER48@hjCpqwr>ldesOSV~Xd8pEjuqdLlW zVmQMValK39$PgZ+i0tf7q#R{4Fp)kNoK{F_^+gOv!8-jJ99e#&XxWyfN658~0#Tziei;W?xHN>ysq z_BUwUq}ijyVdo#4VU?=YuGgSp!-kE@;`|g-8nvA`#XbIShm=!NpdvzM7je{<70J#S z4%-(i2TgE==_|n*3CsjXpEE|8zV(#jweJm%!x79^G58~KI#3vtO7!o#oKcwJnvt1a zO_jq5Y6x>M+;`3|BFKQxh3i9;`m`Ko>w08{b{VzgRkvh7YBv;b>1 zEIz4PG(^!V_sT!t2oEhe#Bh4tSAHI=%PHjyv2TK*m1?6MQ;DMjNSG(7Ha$mVz!a7t z`es#5)X@1YQjSV!C#2pM!)aqkeV3v&1?V26WvU#d>bT&%{Xtz$`IB;)9**&gshRQ! zahi?(53j8@{0u@V_=Jm=Dl!=y1?z;_$hufLq8O`L*)I|Ym6cCa$mCUc+mvG^p>?3i zcyg)P3v(oV%wkjyqfi+hJ zg(DsbJQ#l!V>lh7Y`;~BQ!@BZ$w{jrT#XDcMos3@y~7#iwc~H;%*%2ivh`Ufd< z3@y&dUZuIj#Y-v8ZzL{m0^3OXB16lv>Js?frf>#f3|?%?xmczwk#a8NU9oZ?R36C8 zx{o-FjjBO%)W=}4#+1VqmB`|84~{xL5yQoWJgIR&P-7%m{7ekTavJ@t(8ftqo>MqM zkksefNSq>ywWN&ALK{~v<<&UOFi1^(Edi&s*{b;KGlI!}E!FkggIRY^+wT zT8&=}t!Bo7B{MTc|FE5|3tg4znF@zee1u+2ezLL)H4fUd3F3wlHj^5da(uc>&nPpq znrVKp51kW6Ic^xAu5sYUnJD*%a&o%FaR>`&f_8Etak{esLahjME*E~Q9rFP z>wTc2RXP*NrjRjQ(b8H~WlF_yT88O?l;Y`=gqB5-7)a9-4A^eY3N- z5EpN1xRjZ-JE$3a`!oS&av)9^FyqnteAv=Aj0|9lmtoT?&ac6wFfR7*j{ znp9KK3cXgewxU%-lZn&J%!X1VEolb z;S^8J6+A9CxR@A-?;pdNVu+Zb#F3Zr3B52<_~}ckPaPvTRaO;GD^WO7LZJ43#uO>1 znJTW+h|@0D#v;~c5y#y%WtD0(IX4=9N*A;a#{R9UoaoCC&&pcn#_4MFEhjF%wWNBi z2NgeUgyE3(u)@J4>Z{sTPVQPMhoa((XNXg7p-A>&MMbYG9G*4fO)RWED&eWt&xzAr zBp>Hc`{O?lhsKRZS^26*ExZEUpc=j~3m>3zxvJu=u!4%m6NjXAQ*KUgMV$7rax43Q z_6CQ=A4&7Mg@2C5;Y}75DimDdqByP8Qc5r4$dGl!JCRs54OHb&AwV%<>o9MODW|kh zSfB4Ig(H1D{RKD%i%O_~+?gU5%CN?nu5-&p1hGLZFgUfT%0lQ??;?&>iNp#g^}Pni zy=Gk@IXRCIM;GWy=PN%2>jlSVNlLW0SBO)!L54uUT{}%V705=?Zc~nd&)$kRuJ@{P z>h%L%BcT3Pm!qGJr+vNy3P(96L9c^u9JPcsM+{C?B&!K3{jT{LUf6(ujLd|W&cPD| zSqV5jLCZBb#ZUiBEpX#t3OtxqErC|+_(wPwzm)10T8%>~%o282jA*o~Fxj_|Tmsbh%dHlro}s+8mAJ@=irPLOgd7ah&m}_D3tS zvzG|1wpGRSy#|LWRAJA)_~95%g)Q1;PR>)pPoZ?%+NjED8;pZeUQp#kKjx{an^ZaF zD29rv%~v$7DX436D{-m>EMa9r?z_62YQe(ceS@Q9B>-OikT{%3KSWRL(>RGz)!x1m zoYF#@T&{42yDF8Q@sq|Wr?4YJsAe5CwA7Ye5$8yGb+laSA+}Z2I3<^DoT;k9v4V9~ z(l|eHBv)vqP(~AlQ*L1`DcTd_I7X`SP%DE|G8rv+eC|}@=y2_0wusD5s+>T-(MgobZG949E> zV1;8H!GET2ztWU5G8KBF(28xSx2uVZ$)p{=^y_rF1pFMqsSb*6PD`7saCAFodWZs~ zo8#qDbhxBv+#bWleSHUUluK$PcE)!boVG*ve-A2J#*c2loJ~9~bZl2qoxlb57jF1&udO<#$+@a|V`_Pg-zS0>6` z_}C-rV0FZWPk40r>9}2dL{w6i3-5mHuh4}zk69^_>Mp!~v_f<8yYTMY?@e8Ja|=`v zw07ZnJ55qY7v6oVBH+Tix6He^@UjI+Ud1kad@I0l`nd4!Wn0jN=hRfv2p8Tx1u1di z*^Nn>>cXoqG#5fHd|fGwe4Yzm&xJ2_;r%ZB5*NO{3mUS_M_l+OF8mf3{x}!D%!P02!tZk7k9XnYhy0EA6#T%s`!C&``H-jLkGc0xmr27_ zmf_Vja}?)|?gKxo&hLsyOh0wYooKeH&N&A6ggQ@iip}}>8Y9s?_?&*`e4;u}cZQqu zNi}&r!y8zi#?#>O z<0ecPJn+gZ+d2aV4<9$6WZ>A5gZ1IWaV6u1O_(@v@M!1Ck%I=eoG`9s2WP;5q2tGo z9XH_0af1g=964^RGkoa8fkTFjA31i|IA_@Sp+nWb7-smukpm`791ogtJi8E%>SZ1IaI(D)%X{HS45iM2*L9J=XUI@^cigmCQDgJifn&!_ zxN_)F=s$A!u#s0@NhO64s4)X4#9gY`qrebI9y|g92)K_&bx}A4-B>p9Ei) z1iv>4{--4Pd{m^(Z&i}uYbL?hPl9in1m7kJp5HOE>BDcC+3*)8!C#RCKROBi>LmD^ zlHl)2f`2jzeoGSkdr9!0B*F7rV>UnV+hR6+bqsJeeA^^=go#QVrde54 zyOipAZTQ4#>iX*$dUjs@vHKIs3*GL0cTKR-opb_6O7MThPItpa^K0Aa8mo^DInJ)n z?R0~>jKya>|6R|DL$#ifFYR=zue;vWf4Q+H? z)dz|kr~E=Y-B^3{y++97I*yuL>sAp|QqISBVulaE{x-WnBsTj`M zYp2`%%fp9kbiut^&m-U1>Ast=r@4*puA4Pom&10tSB~s$ZKG>`uciy8K4`6n&G+2A z-bPn8QPTw)+3BtbP5I77*WR?FKyy3Yvx^2?Vx#-v)O4la)RXOWwJuA!-9|Ue_@#Q? z6;}Js4R>8)qic4mwy)4{r+a6}&@>y}s-V_$OA|ZYq^b2Q+31#@uH}`tvD4M~rq*jV zx?3*PbY-LMbm86Or`qV&T&?ME$LfNU>~vQ>-}??5-Km#odBJP!biIFGXzeE!Z`5>KX4&b|pFZzA&;>O*|!2b0i+>%6kgMz>*rmKU05mpA8* zzE*h~jh-b7>~xpERqF?vytO^Gymd+FF1o7WVH@2^jWykoo9*(RU$x#k-o9bC%BVx~?X! z*DSWv9T_^xs%NCCvF|QB-I(3mtmAF>3{6+~w4Lt4LHnPx={d5F?gs~vSI-dW#9 zx3^H!1vlF1CZDyqnT>9)`dFpolx(uoeKYHub8K`EKdkNB|F)g3-r236x6zGG(R90Z z+38MtYf;AWmib^*eRvZ4mUA9cx!k`jbJw#pRzx zOA@ck`a$wTktWvu;wJSmPRA*m_po(dQP^mFV_V$(dZmt=;+yPrt>2nA&qnvE`A}+U z61uBLe!JEdZ*LiS;h!Ik#an&H|F^~4C9EHpzyIp^TZa$py5sq~eJ^RuQrjf+4Wb) z|AG7OS!j!^u!;XZdvzSMALEX_^kXNNr8!3?#%((T=WaWteMuf%zWEHBob~l|ds+8Z zTn_IWh@2?=nbj3*G;VkUgrDTwo@iNW-Bgn zaU=Qq6Ygwei=XW#F6VWM$4@ry{7C!^d@nKHZ-X4Mjd@vl;yAh!{g&H**R@OZ=iX+C z=cl7zW!wi5^Mpkx@8-XFyS^?su}AXIq1&#q`D2!87sWT)$EPvt=00GfyUu*rx-iN3 zbkFe4H_{=e1^kJYY{jW2$T4FqXt0UQ&&?M&KL5Z4HQwq1o# zmhe}%s{=c~J7BBVou*#POuO=q52wGM<}5ie-bTJb{~@u;T;f#nO^Xf}*yNO(`ShCq z&*MjYC-Eca$>K+@|JnGF@_%*w+}v%@>Tmwn^Wp!t{|RFZAxQj0a7;)RKT%vG{Mq<%(DxAj>iC(w z^R$y}-yyBw+TiE2xYOmwGY{DZd z-j{bs$Fo3bvHommHNBq_s?)|H{DgU?e+bq~_1Y-ta#Wv(ag8v0Oyd5F$d~;6TMuou z>G9+SqsOR6V|t`n^a!?Z;}90&eh2jk;h1pfqco>_f9TSojRKJ;dB+OfXW8V2joiR7 ze!memIm3;8`^)rvoO0ab;9l%Ea2*ip4L<^epX9?gjOhADe7hLF!x2X| zzTvG^9fI(a{G}(W4Yu)}Z{o3!D<1KPKr9}Q6<)fzu zgH7Lq%QW8+&2&9>E=k^++yTUx@;NbM;#Hwt}u=X!e8=z zy>1+2le6h0^BlsAxc_YJ#MzIhv;e|S@<&&Wy4l9JkI}#SadE!xaWAI-NazoU>5tze*HIn#}t(6Que|Di|zet;TL)5+x&3wBdwp4 z_s9K5_?L_yd{_ORI*7(mZHgc}g@$*uJ#Qv~|`2tE^N`M0CHAw)yP^718*(sY}4c6!P?&7Agu@O z<)7>~wDQ~+vFSC>bw61A5xouTB*3xsIxD!N?;q(Earr0H$^19Hg0P)%0rr#K_8&{n zA#Wv?7rlkYvGjiFxW|66>HVznXW+Nw{tQly%eLvc#pBOiQ{v^Rmz!SVOmhE}2X6Z# zz4q^j$D7xmZoc%V`}|mX(x2|~^yhz~_nVjIUTy0y_U_l?MAK^a{$hHydfRPu8#ZgY za6>y?+gF-)w9!5JJ>QOToGy**bb*4at@E>*6Schk6*b+TY0naC%>UE)yXB!De71Vd zo38aJt@QWkaaM;@ez57$QU5rm)5rh!=n-7h%=)}>m9818K8qXJ>+{Ez&0E;w;5zlA zoeu6v*y+ZV-x09ceV>Wfd6oYjyDz`UvEKjtMakDpJ_c>|4sf_b#%9NoiwGT)+6vY^;f;iro3nK z$NZjJkFweE`IdYB;T?BQd*$EfMSs+fK2SNayo{5QclzPEx;DLfHq&}_x$ggtUjO)K ztKl}i?#b19bu9XO+SAVQx4duDdZ{2+K6Py0? z*J}NPb^jhe4xhAmxlNDsh}I*k-ru9ggrhIMV$Rb20Meoqy_`E*{Z#ySjM;%M=n|?{` zx48au+x@oZd7Wf-3C$OD`D*C0{YP=c_h7{)OkVnF@!*G;M-Mr@q>3UTRvZmxKumg79r!XeCsKX^Y_bi22Eq8`gm(dUu1EgV9nl=N6x z(lmNGvHZE%uO!}i9sB`b1`Ykopa&e0^9arXpZCz^1Djhogo%$Q@=IBmcs>mFlE0+6 zp7KFsU-*R<4q>XNd?mxrzp;fwC^6-Q-%XzKQty&~GV$nITl-sHP0!a#>goPi%1d7O z-5n3w>aRm5P1o^7-QHP$?)xq)K8V*1brgP*4;i}pV;kQF<~{3q|0UnOtsc46X6L&D z(w#Nvzx}V+?JRh2%VC>7N1JLpk3{}EJI}po#%3GeE%M&`Yg!-ruRgxuA@jU5n=DEHX{3I5bufh8w?)K5q6YuvOOyobaDDix?nI}3qE%C9PmQJaOH-C+m4k7G` zzh$2ODHHEMyY&fq%CE!w=I-k&O?wsGQcwHnZR`zKglxc%t+l=3W;h45_q4Zd zoDKT`-uU&#r}W>>wTL&s0Mj3{PM9Pf^%>S-o_O-ci?=?Oewr8$Yd!HH_Da6&!PR9p zyDOif?JoaKkJD_oHva}IwRQ;NU;jeXD?s>5{_AfQt@j;1zgo+Q)Uo$hzd7e#Wz(&x6%EYr{(QWA}@OP_4{pfvyGmme!IMGHy^f+ zo8MyG+z&nd_3dBzNCZfkbJ@e_+p7Sc*6Z^4- zp7XZopQMju-o{)H3~l8QL_f(-x_r{5Hh+C|v5vPs=f(AO&+lX$31J)|2tUcYUAE5p z98xWeYfPon?d!zHH$57##nU#kUtK!QPItw^NFSRW9lB_FA=BRUJT?BDro>ZZCdO%i z=r8#xPmQpC4`@I7O_iS2{*m&Mulw}%g*H1znfi|=>ED`9ITW$kvD37R{r_b3Q0jSvGlJnR;@Pj3?7? z@3q-RSMJwwT9%|;wD@`bwYInzV8(@#$L#G?#&3T?Ylk55DfzTf~74xsC48aoUb8N!D45Dvr3%MmOXdO}DP6-QOo=U1;4$UXOJEQ=oy?Q@8JUzkWUX zKdyr!(_1MJyCr|J`)StivUD)tGYcfq=cUyjTJIw*F!RH8W?d(8BoCar`x=}5Q%s!h zO46S+ysPd>w)%hC)c@3%UEZT{JJyRPTr-u8C9>Bha*eWnTbXu2*V;`0e&WW1faQ0wQv zzm-FnXV!`Sf8ZSO2I41r1J-4$aSnLXtaBp|A)Wvqn01B!FHA&V3FO=1M*+w_{JZ)cDWqZGO!?ZmmHo8$0HC?p1j%(3R@~gYtHQnaV zC$JC3l;xTax!14qo=x~p_zO_D5Bo@+(wxxZmI{Qw;527sK9IT7n*8?ce{iMKZ#5G{q0xi#3g?0iMWaI@` zqRjxLJ|(}t)9=>z75ba;y|vkw@Q$}K-h`e*ya0rs`^`F~dXIP< zR&|ZXH8HPZJw?7oy#d;pbJjJ}(AJEnlw=*$+;PvP)=nnxGKp$1U9OVJ;8hrxaA&vlk6W77-5jTLRxu0|n`iE~( z9*~8&BE6)pp18jY@~D6KN5nbcVbczreTYlIM$;}s-+&)rooNT*ohT33g#9V<4!#5V zfHe~m^_QUlyITv55?J9H4hcnTxWV{?}<`t2K;0w6T zjEAB6*yjLT95($#omTj8ekc=1t9z+|LDOU)^W0*na3CRwf8Ht=HJrRR?lsX zALp&N)Ad{VWltO3E>q8?m)Ys&)@*Zzjqb!!U2k2kw)Z#V*0uc9Mi)l^z*J`Dk>U@@ zOLnw-*XHjfn1?g@e~SCteZM)`dy@{_)9*e;Vahf zD=ou1im5Eg{?v8deb(>&-fHwKOwylh?Kl1jTfHANbi0PycDSSFU)?cs1_|EY)QVQJxYtY})z5tF1 zqL<{q&U(48EnZ$U@ls~yNm5?&)vH^4W25`X%&Ws)?dy}k6H70$)oX_)+O92c>i*?& ze2>N*FVgP({hK-j(L?gPj^A^?jqf1y9n(Nh-G7j8j_Z45!!Ok1SF~SKhcL;U`!9wZ zKq=l2W~_wzHgyQsnd=fiPvZMya?G6XdGh-W(F?&35SW&D{RL0?f-@4Y&nwsRqL+dm zAofZA%;Wn;+w8opq4rML>x!cX#LuY9q@#&`Pty1kVi(EcOeT-WoZ zG5`IF_oo5kzsR9V4nh3qKZ^H60pdUZzic0cv2N3`H52HN5>%V!Xexwe({_HVS z``0;w_eB9>ujCu^SFN_$-MdiR?M&DGUU!_I=bRpEXEi#3lAmk zi}X2&K4*9wcL@E?{sCyWLkbn#19@T-^Hn?JWqH2jK;ri@dz$Ajc#Y{1JP*b1G59+a zDtOY+N7{iupt?t&b>@1gb)iG>d#*S2oHsD#wX~y0Z)o6i)(wj5_}k(5G0SZE0{e>N zU|&DT2W&9({*xdJFu96;u0Z%*i*r7AAm>9q#P@O0ugUovPU8A?1^ne+&%Wr!x;-(n&33wawL^kuS9{!Je>TA2_`n#TUc|JCB z3H$-bEP*}~phJB~|o-W%~L$IRuvL%0v> z2hhm0ujmPd4x#?8#PTB^OXPn9@x|w&gOE*-`KEs)`~}#LeLp_8;vbH4z*ioBJ-j24 z|K}e2?>6=X&jNpd6G@a`_AXY^iprEUBzfu3q!IbV+hQeN`#l;;1k(e=V}JxptI?DOmi6PsAyR~m>oU|N}} ze}{(sWP8{Ch16@HE#8L*%qmOtbAL}gl%ro1pD>^AxqbxK-Eq_n-$!znFZGlk2)o?Z zvpv^Gn>dy-lRW3+JoIOK;_f(49FN z@YvJNbNvNRoSp2s{)Xqe#Hr{w%j1t5J?Ce7`1!Ua>RWqzqJ3lP>ir_&f8@)=^2L*lhDB#!u+Sb`IeMPdk?V4*zfM z9D>Y;LjLv+q0E#IwrKAVp76w7Cca-q{*p>fe=p}np6hcw{la{69)fH_7REoJWiIm> zCj)*2$b7}AiE}`*@jY_5okQ4S`l;xVb`Igp!-@Pq@%ZBc&-f?fcOa*|qrlT{_Ek>o z2fX7#7f<X&{97Qp|24~;#c3aB5zTu(pLGMdQm6;C_9 z%Zvk&L+}s4+wZWS;rzn+wVi_RO?wI=jtSm=qQKMcCB7vOJ~O4cEzV~y)p73sNVl)v zxKHEW|M)pOF|OvGm^d%4csb&JVcgb}x+I?O_#}Rf{yUJD$nR`V`Kcf4@=nD({IFf# zzs*yc-4fVfn{Py~*LFl3+xH1ROu5_oyH)j|Ka<~QpQlXC-(~%7(w?!JZi}I#-`x8q z4{?49zeF45DX3Ln`^DcR&ml;?NdD61OzZue5oKCV$uw;j<=FNyB9KE6ev-dcZvP(F zg@{k4(mD2d-30@7Z?wfrgKWJo5YE*45p_+;IXPfpDIj62exEAZ4(8;*}bXHvj zPnq)J&Nv4wYLQ6a0rSx{)8lPO#6<9_fX9L2hy=WJ_CgML69UXA^_ z^Xe)Htw`j5E$rhs9s)1I@}Kqnc1?ZssJ9fugP4`n5~ zov|Kr@hA20UL{=*kqh7_z%REYe*e*1PqpxV5A6(egC2m>Q?cJM1Lqgv96-N`4a~)F zev~B~K!3@4j6xP+9rp{+UL!pqAMicS-SnT}{l3E4@KaCt2_W`Lep+FzmNvUzGIp1L zruTigzNqc`?!MR^+L-GQymm|6hd1Opgr~9IamVY=p8aC^URV&k2s=INdWmPTEf&wO zOQ2Z+6rcl)}^9NW13 zl(D-wWFKcvJ33&Tt=-)Bq3*Yv?$C6#F~4(4(-<)%}oDAHQG?I1_%$8jAkCK@9~fGW2ynt`X)VUP^F1fMdce zjQcDfKCXs>jpw32#(A_&4F%WZx+>oYu!AyX8Hy*zMpBQdu!{(*6%kub2Qz`Ms~Ws zX_s4nZ?**W#Z)%mK3^Qs;l^B>eWz{HbcIRgr%M|bTgQ)6zR`5WH)(l8;3xNea{2Cf zU<2kw0Qv5A5XS`h?sj-n1&1K@Ao-;8s(oqGx7g@AHHp6djh9;Qa}*nW3ypu0=^K0o z`T<1W5RM6=Z}2%>2Z)}Mk8hcFy-nYT&ocFLoxPvw-txy)Ho6yDXu8rQbdUb?_MtYq z#Z`1a(#O1)EBZu7W(wH`M$R=YD{U-vJyGUd23$ z-)jitm~aI92;mXn_hXKNDmNvL@8TcHr*+&=!DesmsMfnrq21n#zb;#6>)&VpZtT4` zZm+vv6ng`8p+7+E4dIv|_C|0_5PPFM28g|W_=+HQNZ$43;}+ZWx_^__YgaS94oOxI zA@C%KUXh=39D?W-{x!!Th+h6Q=mCi7g|dEt)I$i@2vQH>-#`x#eI@_rrUusE=^eRB z>+Nr8uZKN-$KGJGck;QqeUw(y^Bvmj?zd$84%9(C09IAh`wBrE6D~t}&dWkLCWxMr zH@knI^?S67jK1X$$K|@;Kb86qgC`;8XB)B0S+52n33 zkHq89sz-h30T4a>4N#u|(Ibpwg6I)w2!8=YzT~|Zw6AGvNB0?jM3S_lrl<6?et&wV zpf??Ba#Qd0Yv{uBb)<7|0s?XpkLs7Fj15xh&@hY_!SU~*L>7BK;l*AuVSa< zEf3zm)E0N28o!UYFYb3+`xm~Vx15XKaxU#m&P8uI7kwn}w=Hb_KJldzmrwq&UV$d4 zUx4W490&gZM6U>r38Gi12>t?yUXjYU4iJ4L55D%gbw6ivJ>5=sh5uNuAYzUndWCRI z5WT`UCWu}U91}z@KjMHO`bfU8#=2K+ar?N;vu@UUNqNb?ocuxYAJJv)v(qiOvEdLK z-LqyNu<$ecxIAOvy+t;<&EM+&aYPcj^*7vhzm0D1MokwvOJa-qLiT3_INq zV>-WNlXvIyn$Dku?gn3{uWWR!uhVp;r`hFI?lNhNjqYxvXCTS?^UlNf)uzOGjDnu->zVx$uipZF z+}CS>p6g!0jVVf`Ux0OxTYkAm{>2`ByB6s3ky1Rb23YLZ@&XI->>1z&!#{c}o<{@R zXReF<<>tEoHawpOc+6aP7U6j_z&ek9>pb)?dCq%5AMy^(ujCMBd;D{Sxi0d#-{^i$ zstWw){vDns@E5<=Cgq2NzHn^({3%a;dhf#x_V{Z&&fWF58|!)U_TLWs0k5O}c^-r> z2s_)G=TDcwp8$zl$?s}#@*-OtE;RcDOU&;uO#mNTyKp|jkLLk|pX6(9D|*nzx6te( zM9sbh`PzOLEc#AWhakTT=6|oMLy+GEbKZqq!1;IS_zCZ*>JUV}fxSm%RWJPH~0cXkLVug1rR+VxJD3plJ9t>iS@qC$++*ybY!aT7ha#r`}6Vl zpFi_qe89Yqb;#7!vmgDKC;mj9KVPYwj0?{zr0uyJCO2O>Q?cZu_(2_PU?v z_u4Dto3{Snze83f((GcJ9G}_WTQf=boAhfFe4$JBDOaOil4s!FB8QM(-?W=>k>dw+ z!+lzj$-Kj(iRUG_U+TWz+fzQ|xxT^36B@^}pZJF7dZE!r${)8hQQmUX4+Q=J{Q;{y z{lZ|6KI1&+htUrSZ{}%T63?G8aTUC?$RQMZuGjIL@Al|l3j5vn(W;|9+~;A>_2!=I zUEptb`5DmPeZB$qy3fCWe4YoE!5@IC=013E5%dQ%^XS{rD21;Qkxq(!n)?JaA4B> zIHsV>AMW-mdivoDg7`OOWc0p(5(^Q zA2`PIWY<4h$@+VX!J&xxhj@-{%@cCWmf_UG+cH>_6HpP2jeY(Z3OTQs{dE3zp z=()yKzBTBxPLI<|zasRdQ+-Y!SDasm_xMJ*^x^w0`)9`Ky>YOx`5bFpS2g``Y3I1z z*{=5!#qQ86*be~wRd)L~W4#U#yCXOzh@GKVArByS2De~65AfPmebt6cTR$Rp6}#fb z)}M-hy?kdzJ6iYI+CHY^v1FQkJU_2j-%2)p)`WC>EBRdSvoVg{^O864yviTVOCH{_ z|0Y|zDxItKDNQmzJA7VIJDWaTmKnM`bbHkL#Mj}RpK%{6+^xL=uYW%7Im^0VIwGL$ z?9#+OZ>g}Se=VCn-TIq;?7#HS)1USE(Z=`fJ=)F@`MSOW*k5(uSM#<@Z@Zg|=N;Yq zS;uN;2o=)x+!W6(6tcXXCrt%y&ya*Y((AY`Rmy`S;&n zabCuA_W&91CGNd)!{#~n$PPTm4q$s^S^uH-cqg;HYL7z8-1{D%yr&m^4(~Ytj>mmk zcli@L>iyEd5j>X)Jbn3mWS3!5452C^!0qBZxzQ*DvLhZfo@UJ=mXFL?l$F}4?z#8a+RhJ?1oZ-R9)pZq(aseef_HqD@i%g2MTa2cQ1Fb34nfAD$Y5Lt$T$=ji1!EqS(t~i zzWnD@bO^i9zIpC+!tXW%iqXD#9=#0m0WY-E=OOSWc&d+m01PL0~^_J6MJcCPzly8~09Hz1ka5nLmP-G10a5W9m@P~QNtJAz}v z|Jv>sZu;nDo83WUcj+<&#r90J7dD2@sLYrET5*=ZgB z!^Up^oIkGb&_w7BNM^SK8wg@|5XS_uJ3Ik#4G_B>@FM)L?e6zR+1s}MuT!Ru^Q?yU z`O={W?mb|m+gM4{b!=d#Th_Jk3LD+)jWu0330+#zp<8Tp<8w4!;A{K1kU!<=uC{o7 z%QonPrh!9rYqQ-_+F_zpXU73+#!6~J8_>;zS9)IHGz>vOL}1{1|84eC0cYk?iIU!OQpi zHCMb~tCy({X}+!fcK`1DX}tBltCznr`kbQalIau5Y3>lb`fUI81natf+;f_5>D4;^ z$k+Y*g!SHzubDY!9l^R@#xCakT_<&)<%biT06?CD4<9(eAq1|)ew6F}_C?qyaMOR> zM&GCLA36c^=M$Xh?}^uEQ$H8|t9Wn7P4Bg{Y~PK3TYUC4aUES9x6{4P7mJgBL1%z` zk0c6T66AXo(R7>xymEhf=iF;-^?m=(+P_PZ)c3@rL#@x`te{z)&Zd}PjCpLM;ONh z(IbLmg6I+Y3grQu_jBDWb?DXW!yWBUven<)rae~g9Iby_Ub;tSj5uu5uc;X~x*Vgw@FSK8UcTku_lwy0w#GV$X~{LZ-Pak( z^=te)xXIRO{@2^!eX};P{rKpXHV&cGj3>@#Z5#sMOXvG<;n#2<2_WyGOZ}vI+JDq@ zpW3^Qll86t4af(qH1dR>ymv0=v2`1C4FSALs$AnW?T zmu(z^_$At~twRvM_)(VdSNSFKHRJ>StY7>nOYr*Twc$^s+5B>;@yopb)Gy82IuU^Q z#W}vMLlD0NmbJxw^tfLflqLLCeubke{cxvgx?h|3rG0)j zXT+1eY;>axT{H<@(Z-Wbv(epZ=sG4@?~iD-z&al+GxtNI=6Tx>ZcKNo;SFn9&*oOt zwg)16v64d$8e`+Bt+b zcE`sW+9>^v178rL@VD5`e2uX`@ErUJ@W$7wUO#oT)pyNzbU$5uwLQMBU)-#{jqb_g z4BZuaT=UB7d*LOQ+1h!hL7J|7wBFwtfcF!dIgMg*vfne$8fxBO6kET=dzf;}{AWB@ z<~~2<`JPBxdgArvrzW0X2z}i2-tWu306X2+M|<><_ba8$dZT|N8^2Ql;P>U^8uJPs zeRg@iuM+i~Pk}u5d)}kL&wYM6#yR(Mb^AT^T=ow3U6mv|)Y+>+c{%CuzFY#df-@YxLM`Ygg%}9haKlC1SgB&$~~CAKkyV%zEbU zj7eR{eQP=Q+Sy~_YrAZ6o4%s;E&CtIeX-#I>-YZ$-D~8|)cw|9ZSPOBj=X5Ix6IT} zq3JLGtlZ$y<__1SsPpbRJvHx1?$=A$}fJ@`aR{B%=$jG zPmka9Pab+2ndiy6I#j`r?_v34>*_$R-y!gO6ie_tL!brD0WB)%{@ULFb^~szW5%Pp zekTan+F74Vzx3qqy3dL>@jHaG%zj*`2=V|YU|)vc$#IVND>w=KxzFREEa48}pAG(i z-Qdsb{(Q&>c0Ld&k%A7?<4h53e3u?>c?2O^>E#f8)r`c--O395FpEfj>ni^8p_JUX1-q z_w}>RPCUN@cDn0hlgEGO;QKJ{=Qy_Fy8FBv%@f~e`qaa3$(xDghk5+h!Nb3Y$DiJM?KNhj z^*PQiW}mTidb}OEpP!L-5%T#Rf|qaEmWx){;$?v0yXE^w8NLqV*8O{3lX0E?h#sxy z5FRo1M}Dp65T5q<;|fpv8|^t~{VRSc=$8OqJxAX>2dg7gg@uaG{NEy&1<>CZQWX z}55x&nu=#;orG*P}e(6qM)h7K;2+4gU~yB}n_0>mR{h>K~eb>wxC)E9LvA zKwrRe=&RnVm<{=WQp6>H|5)fB!TOKK{_!Xe_&2|=T5o-?H^aoux>0(3@zOP(FtCHI zzBV7m+yZIpg_@4_Rnv9fp%whY@2~q8LmxnW*i+sSG&m-t!aqEZ-UM;KKzD;VW|hW*jMXc@kdm{2(zTmhv z4&h9!oA_P5(8M+hoxvllJFeMNxRe|@uSrP}oRx{mhymKwUB zr(W*ojYThKA?{BCM6d87$OVXAeq1AnUI82vym~arE4R)Mp6{UbDBSJ#Py9Z&=;6N& zasZ-7x?j7s=wzeY zf%n6h);y#4TfB5##ypd6qifts)6IL(PS>sLuRCpYpQdTLz-l|)4L={~Z=)-@R@+y0 zi=A%dybli8=r%r}>EY{N66F&bh6uzppjou$I^HT|3>ymv6Lw zzoy_xEiYWb-mhP?>MiSc^9C$4^^io~tn-GSYqPKUa!t1@3Eg*F{jb^R78!X>-?Q6y zR;SA@x6z$#?3-y~Ju9~i} z+-_gm_I0yu_O-oA(>eL}`WruL-+CL}?tvz*7un@)YVovnJs7%^t7*q+U1T56TO7%^ z_7k%wX+8bN+x6UeLdjyAo}J9^(?#>_bRD)#nQ5adT(0daPGVn|Ya3bP`iIxGo}syR z``&Nb&-$Ew`C#pr@*C`Qw|v^ZicQbs+i1Ezv+ed(8MMIq-qO3RHC^;tJ6-4Uro(OW zx_paWir`+Dc#J*(^5=swNYJ+!}u9)G<3b=UUYt^R!H9_`N&N%UOx>19^BpO=tH}iXKyssQ;iuoyEXsYHHI1b)mJ@eD@3B<@><+P1g62%Z&YnqwIeBzVXh0t$xd=>;52U))QWN_ZCmE_CJL;Xu5fI z?Cm9UXusYzd5>eCkZH>{yPmW9&R%Zw+dmE6)V^BY@3_yC;hG1_eU|VfzeDJEw%+%U z`jqDx!&l)tfcIT^Ej$S4fLUh0*cs_}2=mQ(WEk#i0la?6c=Ro+Ury|+?JF5>Z!aD1 z=~>U_m!kHXt~}pPH}8&0*6;nC^NXgd{+5oXg3A))N!DF~`>HwwuO0i|S#5nUWf6X_ zifPSx+TZ5~(&6v;dq?u!q(C0#%>X`69K^m&qyY13fV!`R_7=i5f_&f3!7*XlcKtmN ze>Udj0Ezo>F4hMCubzEJWNx#?#o5Q1e$9M8f_hr_A*zEfK-QTN922~9_6^Lu*j7Iy zUeNvsC;6Us**lx+*z_wl?Ie7T_T!Ne=}slrd&d&Dk*BcF4tVCo#JIf`-?wr1Lrc#| z{0>_X{3XVjFGqRip~vevgio^*%a@iVmKVQ=)}lOMj^}s9-og5l`~ol3a|owiuFsuU z>N$j;$0ptXd9$km~3V;nbCqHLB=mCAc)z`z%)N=^Z?!qtO z9N?{=-pik~#zAxNQK?Y3ANtwduSz=zzYV?sFW;A2Ot7wVTbufuS~p&Q?tZ7ohl&0a ze@7pLy?{~h2kn*gNON62^bhzO(BITo^Z}Fyj5g;|-mB->-@p0T7H2b2uS`eG?-kL0 z_x{T!)T29&*d9d&a~c2q@1WiQUb*>APCv^gx0m_O*}Uz#|4HWe5O@;2d@~m3S-%rJ z7=C3cyIqeH+Mf8nKfj+hZ#?1(F;2MWQ++=&fHp)}?rBF}x!*ohXdP$1D$@N)p-V1j zTr!V%1Ae4j@!eEYU*We9SAf&%oBG`edjZ_f=e$G8^M0`VzG~^$`dVNI^agnKT=wiz z>-+F08~+6N+1DwrKbP^dtslD(`Z5*YW*>ixpMC8U8(k;UzWn3u-zZ#=C6t)|>G#daHf@xU=emciZSD`?Y?qTotxz_Ldy=v;CxKzgt<#MJW?PATFm>=W0hseG7y$--FklQhc z_K9P{nfU%C<34m>4F#7#51xl{PVmNk>%Cd$+3c^5@rEh#eq0at{c*7`x)yQ)UcSMd z&so3Mb`xtzq1)nVF37D9Cvws7iTKy z!?;G6Yy6?9j~;yxal~WiWzYk>dVk;L%~dvktTg+Kg=6gTAkUHeU&HUR08ZVBdO92T zM{rDd2mR*C4yY#_6TEUi`|U^TzV!cL?@hp~D4w!8I;GTtPuSE@<4N2u4&qh%Aa=L^cKGdn?_Q=_&gV z^>^?6-|zo?!}D^c)6?D6)m7Ei%k;cv%1wRAFV`gx(cP#o!155oJ%QyRj(Y;jgW3bS z07=J#J@3BXRsV`c9#TsC@=)F(mufZg1$LobvM+(JihIKECLCG={s6gi(Qb&3A&$_) z^qXPa6XtBxavZ`vLDE_7{qaLwbY5@tJv`+u267KD zf5M0($a3Ep(8PKEU(E2wE9JL~OYY;Zp&WqaKKwe$0a)&1Z$Qogmiq|q2`u*^JWF7? zSGXrgI?vfZ%DG?e;pW<(%3fg8>Cemj-F6JYCJ+*}V;FISlG<_FgNvNst(@3T%Uk|n zP3IG(XdkCP-p$w&+-E}X4QCC2J-@wi5okX-+j9E71%96$o-e`&k-r`P;V9Uh3_s00 z#AnfWA+Bj$gcs1iQh9NdN4Pv!r;k0@SP>SQ{JklSu}`G2+Fd=Ezih89N2)sgi<%D_ zeQ%}h6!C$+io*Rof0r-19Q6ix{HmU4tO)$wgBb1!zhIt>`uRAXB@EuL{o(iugn^L= z7mXKj9|A4|-9`0$3h_V-w2RHBZ7X#JRS_lE8K(h<&>V4-(Ee|_)`SQ?6)he!cVKq&+s?w+ zxoW(kQcag!6<(#~YSAiRt}0-p$@(Papqc1LWxGf|CZnDG|ti_E>=)x{_zO=Wz-zetox#PknCF>B99^7Nw{DtC{7m+z5Xn z9sWY-3-BLcedG3({!BKW=Q#RJgCAgri~HrxO;sG|SE%DdFCc#)1NETiLwnGV0|T)y zi^7qDCW`P7^3S;f@_88Y1H?f;#e0>SD#D}<7>6Q0v={jShmHJ2PiU$Lw|3Rf$0|0( zd!$X(rSKalee?)q4>$z=+wI!P_zjVL@C$%L==bRP&;if~9RHRne}7}_lWeR`IwLqw zTljNOA71_}IL}?TmOjTaz5;atN*^`(Z9x5ik=1oL{w(5wkSQ;=sR`yTny6lezIa*i z6Xx9X*;4`#|~{c?^64zCw9L->ZHAd;vyLdiYbZDC!NAhdy&!`fU$8 zl?Q*6|0e78=ts2%xaxJ}Q(dq0GJd`6aWL1*%Z5AyT(9VS$S;tB{%p~ep!+WHACTo% zzw5$!u5vene!7y9^gN67Q@Na2lVidI_`X#-sm{!EgPp%-*Ts=Mv@#==79zLWQH-X~qz3GDy-&yUS>@vArNB3=1){d&<~ zxWD7?1VxuZjsUrSptkw4OftO%{XEMy{mOc$e=yj&&tr-i7i7gW9Wvd-N~byBE4ubG zP5<&CUD1B15AZbX6vaorggyg#&=dRl6xew?Ea|G-deKN1 zUr+wi@YQ^0QtA!+(INQI1etHul{K8-Eo%=uN>^S2`Ka*S+mE{F$%Fl-E9Go0SBdCR zyCJ`Tq^DczxlxzAzGCWmD1qD!AM??07d`3l|LBUF@8%Lcwmz}`sFY?Px|!nds)un; zko48KH}4x4eI3wG(v@1ntxxwYOMl))-&ZR%eTNd*C#Ek7n@5oJ96x;T`>uTNGVKsC z?@`Hm-w1i7{v~<>@&%HiUlfkvo*>J~SibFYS2^#Vr0eZf@b%iBUts#fO~Fq<=KJwQ zy?43z88Z9b^XI$u^zCLZ-{+#oGxg3`W$UTGZp8L8c0c?pfa&v=pg#jLp@*cmvAYou zbjP@|s2^U8{tTF5;zNs?DuS%fp6%!SP`TCPKu|77puV0jExN52KIo`!Kx7=w9;^y|@HxF<+@AN=;xajtUD4QaVh z3w*xYa>4s&Vl5!I0PmxUr7$Kq34VDkoYM zehtt9ejR=PF**og;699JNsmGUVIKjqpGEOmhzFWt{6_XPem=%#z-buo7RAp)Jg|(? zW4o|%DWup0jmt3 zBNLG~K;ucOUw8(d2fR0R*!!>vz6XTy|7VyFgWU^FNBw|dw*~ngMS3bPIvM!`>ySUy zCpr~jK(@=CK3C_vzM*Z-bDn4T+#g!L!>_vOWBrZ2hw&-EaumTmL6&p5*L}8&56>9?BJ~kpkL>ra zxSVKn*hyd&#>pgq)P{6%xzVe@e}MTEhAtB%9q&aC{_Nt@A&jT#N-L}NM5Y_rW190^ znV~7#-ee~j*Rs6{p9FdUneV9O$c!1gVQdxE6z;I<2#`}a2%YWgw~%oFZ-Vykn1M3Q+g ztgxOhk9L1L6a72MgBp(c7(mkVey^U+_kTOSrRk|t(VZ{9ryYmR5oErXp1x?EORmp^ zU7;)2_;uu;+j7lv5t;@&1LR{}G~>!L%ELWjMKxn5aUTKrJ<~Am36hT0TUy-XqT|3> zT0SEd-|T*v>F_WXB5=7;+!MIm814zO+`PRzA9t0TZuBYnNx$Ez0DiE4S{rtq+RK{@ zc>*G^Q)E}YD-i|;rj;wQtKo@F6k!9-GbcM6yBhWeXu|1l#`C}@;1}f=zYekq+-&;G z*i<|ZNV+TcJE@$D?i?eZs<}_M?N{fZU5o5JeB3DTI{GULhZ?{x0}YWr9rFNT+!K<} z|K**D{towq+t8m-ylU922+trr&Etg;Cj1D!r*IVagbF6V814zO9tZAkA9mH_CF8d) zD!~tmHbXf8`#~YtSb{8P$E@}byUOWl>{M)@&#$JA^)qT4x)QCQ>DZ%3|KIvq(BF{j zK7V)pjQM%L@qaj6(t28p4X{Hu`Tgs^U0>t!Cc%#(e=Phw^cdjvHjYoU-p27#4sZTt zZMsVicU_?E+@XHH9NOPSV?QE}KA5lx_9Cl~U(aGcA_RQ^+QPn2e7F(x5?Ba(GX7TR zZDZ&y@BsQt3NxK^VZSIGLmZ(2>;%WrFZ(4P=6DFQUP(PSIln{p!3nxvG4nkEIp4Fqx_^p}^Z7-8Vf%b&D{R_%WmNQFlOlA+IDqQm?Ss7qem3?u zvLCh^Xt%$Nw$H!9-U5=2hdy8A{O;4m@VDtoHREflpWRO^H1n)fHeGjvuSNd;?~o_p zRE#&s{>Bf%?gMgO`3?B%I;H;qJ;I^ zmvp*p zP9sHNzK4c3QUvCEe0w8BV7|xjEP?pWG}ABhJ<_+4B9z4U-|jA};?OtFjp=c4maR{e0|E)DP&?v|L~vwS76gZX6!gND)e(9{e6+Y^LT%_#VUq`3M)4hrB(? z-^523H&TQ`6OIo;9MIFyqs~VCfXS#2^M-!wgFo~e>j(OP{h-&DTXmfdd;L)!Ap5m( z?`wKO3Uf2SX+lqUULo`V+8?<1p!VCSOuBd;L0tg)fIe+do;5B#2l){_3cM%$jPq^m zewF-F+E=3%As$$EzOIiq8}tH&Xdfy^?M6Hx<^1UPWwyEOQtjWheaTJmy`0-VY4d|i zKc3m4(}kbWc8T=E9$(3Q7m}VqeO5caHxdHh=sGl5=PT2Fo^ftvS3OEys?#Mu;!d|e zy5D)u(ko?ke>pu*&yUJ_6!(|i(e8kxr%COTce?n~r@qcNIaAM5P`>tlp7ifwC*ilp zdttvPFb48S@27AJL;4u=s(c&l|#{w3Xq zKG=DJi|+D}Bf9d<`_z)|(RjbbevhWO9?ek?U|3kwt*P?guTv?Y8%Rhu;=({lbnm?Q z>1-F>A=m@DLVx(}SlXJmWd4Plq8#9Mq7&mPrc?6g=TVP1_d{?wkHOEz-6VU#26};=$$JVdAKJ{s*vLyY>Kis{+r6(0kzNu;M^^@}lc66SL*zY|} zPfBNB->K&8|FIlIn>EJx5V8P&koc=06NE(Vu3ii&LP_nOTJc<`AHVN0O;=U|J{8je zniL@Ubob?bocmjojXg>I!LM&)>pK?Dll)lrduv@|kKcm60#}1y)Gm?NLW!tgVYMCn z1%5N>qhBB%I34xlyy*9KLC?9SKjCLGOn)2s1@!^?iS!qmaCklF0U}6G{E2Qrd4Ol? z6OJPu7+~mEZ-YLdtmv=1Rn+OdRY(i;M!3iySdB2S(B#MTWr5%6u%{gEhH-)&zTD6k zI|5z-zY6)%Mfa&Uhy`Rs`-h)psF9;C?fLdqSfADAWr5IgqGc z5yTNns@LX=A93#Iy#)R>UHO?l|EpN%A0(<*9K0lOz2cn^2Dn~cXVe>*X7roouN3@W zd!Kfe(9cAC2zNpI0XHE((%1NJ@HK!$e2L*%!fd0zTz*M>YSh2VDp&j0Fn-b@Gk;3{ zhCP4E`w~K@p}hbeXGL&N;C%@(+!KoTC7ceq1$Z15#yx@eB}8#g7)kRGRBzl9>OR;700GCoCbaY^c}IHaYq)3%FD zSF9!Y3CMP8`&~=t`u3%*v|c8?=jZG4W4u$LXFzd%yP>{7!uldE4wO{iVXszoekX5{ zu@~7N_;fkP3%yYe!1f__0R0)j_91i-;|GB0R(;TJKq9)sh$ECl_lPmk9g*9CH-fQGPd7@9h{atX+_+z2Z(B8n~u=ln- zVSD4XgB%0W-c&(t8m+8*r$&^ciA_t2*(4@lTQxA!(;{ufyKq~=$6GtvV$K`xReqJR7t-z)-B;IC5J z@TZ6e=$sb{hme-Q^JXDDOPH}H$p3P~O!`eo53Dfd#nxf|7m)K_vb`z{AKcs3Ud*?g z@ASGn`4QDEKk_;w-_a1}4*|)?A2AO^_27%&3-Y>RehrX*0rS;MK|GLa^wH~xFu;8C zx*!ZN-{PgAAHZqgqphzs&AKp`-$l$Hz6gJd)`2;m`5fMZ`BH$#Lke{x`~rJG&xTJ$ zJn(^#gOd2%x!WVo^V&W$^JU2^G@oVrG~4r-Q?F0@()1IPe0%2dkK$*5KfrxxFME8# z_DJ=Do&$;OPZ)88lI+j!3ZFM}$3O0f5!g@0w6ulGUZ9ulm!qdt-&ylWZ=35t4_U&y2%ig|dmTY` z=o2sjK9016 znoQ4J&;v-myt=CS)h@m?M>@K4jee3HwEbr8x1yNKCdhmz-94?2E8nF?{)TPw?JKxb zEPwpI4%eqY{MkCweS1aygx&ARa`SG;YUP@*eAf8Iu@l|%mFs8Ux6eiIhwuaFiU<6B zfBxgpC;B{_=p)b1-FA=AcB{^N?)hSF_jnK3EI{VFrA8a4A3fLj zBasD~|0GYgAI*GIeH$x6@%u8k4+FBCYwAx9x%kr2v{&I6zZ{z{O+^1C^L^sFk(sW1 zyF<_ETK&FnH*I^)^9kM|=qX$}}!0&&A4m861w2g}2|A_B{-U5=Y z;TH{dp6lMx^oP-~yB~e6W{UIuphg{aJFhOGog-n4Hvmb`vUTT2Tzm>)J(jNVCFC1N zo&=e%S1_}*OMknYe4`208+MGI^tCJ9+VeC$F|*Dh%Nx|Q^>?m%q#65{vDLOyzTUGQ zgsP$a0N%eC!99WZFNSeXkmc6AXUY#QdecmQ6y2irPo}$L{-keQ^v<|c%V)BY1JbW! z*;V$p$wtsMw7|Eq6qe;Kee5mgxm*Rtp2rjDHS0z6Z1fWV>qQLr1X<4fXPP^|>o(fV z??tkGy|(QKw}-;q9pT1W!F>U;oGMMHIOpGXbkOoLy_9cP|BfF+Jfn;K7#%u#^zZsH z{5<__&j{b1K3tk18&cz_dxEUjb$g$g;^OnlX1ZRHeeV9Y zSJeZ~_hELJ?*M1qsQE0*TfcX>bDv@k_FvI;=uW>Mvh5z**ErVn2&^9=*j9opC->lp zY*%}|)K{02JX_PJ=c#= z!9GV+@`1-s-Vn@t0!z;{k%WskMuqo@U-E z{IRxcP2vBPhWzsU$)CULzAoMY=V}Azh;?U4Uzw>(o!`@|&hulN-F7DTw=c`O>h(ia zqsOD&{nC3Yo^igXd$K7n<1*cTlFqTEj_c$qZ@KZ8vJ#Z{!@`f+xYFeeHS%J<;~~qt z;DsSix%mI6@ypYjYdS|@Tww2;;{H>$!uj~XLGmxG`A%8RbB~(gB6@_y3kGH!IIJN?~854h6h zn{@dJ(zR-JoAY~91zcVNI9$}$FI{yC-1U2T!!yo# ztJDmwU(?5GJJksOY9;(*JH`7U;)`LYfZrDe=cQ_3e%4;st1tHB^LxUPB_}BYe-DQH zTmD{26mbOhBSZJ&`v}156L607e5@DYp71lmoR)t1{YSMFdJIUt&3x|?=l9jN8UHL) z#%=$8Z@0@iKh=Jh=5y)@ZEuIeU$y-#wky#U%@u*)TZ`kKAnCiK^NG%LO*)!+$kmnn zcCpt3i~YB3@CjIj{be+siOt9NO@Ndgdc7yQ0DJ{xx#usb=UmsSZ^~6>UX0|yt{?l6 z;rmWf1a7bBJtzl|^u5|CF z=yW^lxzqhHV3>1X$PLe#@>=Nj9`-S{f^Xl8+hKeq6#``aZ$9x0=XV!8Q;*bkZh9`y zz4dHYJ*KbI^dt{-r&}>_Z*^C?TvJ|Qdw06ASt}#1bjvsB@)n)vPIuEsL!9R=MooFi z3CjEK-an?g%3EXFDZQ?{yn^vBI@4vF@^TZTo7k^WO;>sOCf(`;@-*YDU$(l^tzD-1 zQYV2tjmXY+j=#@0a_=SJOEhy$Rabc{4PW93zAyhq-8*W#(!Di6)9EFkGqd5JWnKQp z;L~)vxFz@Yd)dWyeR?Go0oV@2a8F>n9LGID>ct5^?sJY~n~c@vMvY!1(l>8rB}I_= zj-S(Pk*hwv4BtaWjwxUJTtU|3$W^Ehz~{TDt1BtO1lR%UZ#>)+WVvcj%g(NHYnuAx zW&8HSWlz-%lmjpwQQQ+`IUl|>@;X;JS-)z&<$UCqW49OE?HKYTa5<4{QD1=T>*1at z%U$=uj<8F<8eOOThw%ygjz&+9c8*()J4vU@`P}WVtlQMhDbJnH(&>^Cq}#h>-Ch@+ zYcbDF*RTZXo-MV$yDMG8T+P??4Q@KCMK(=$wa4e3ba@$9XgfA^Lh#&k_7fs2S}B6$ z_o7W1ja~F~xI@#Ec7oeJ_Ise;4K8{b?9%Cyf7S9q^w@I9^r%-_DFXW~;We%B4&`6z zD|L1y=ls?BXLUKz1oYiKrmA!Q*}C&K5I2qlWnHWBVD!?ehuf2V}m_ezJR=E8oRtJ~645raw`;N1g_s0H!|- znIy<^T5YZA{65om)9y*No-WceneP6Aj0auvJlxo=%mnFPxnaF?{qX13TEFs2(68{z zs0SeFIeKQBzAk?KV)QnJv7KU&YE0G(_5#v-akTebcGsFJkDxl*5OIE z>DrC3yEz}>`;h{}*{@&77icnGLdvy^WjQJWan|>cf zes=g}5uVdG$e)kq2g9w>g5h811;crGzs%0R0QIrMzlrwvR>ZFXKk}^ig>ukdNoVp^JycxhnCXw0CAK>ScLN{sQtZ%Ko3y%R><3UKTXQWvMP0wA5H`R?fp9s zp}cgA`}_Dtcm!in8V&+YZZGod%6v+;}Jj{}n5doG&j ze9uUkdA7(}za8!MyPAlne7$p9;{21A>S^c)>1V88%Oc2fW^US4!By{W&uM;5uj5_^ zxq4}))88&{(&g87r)&0T>hUiB_RCeey!<78y=;Cd_BJ9}+Z>y^n=ARfJ$Vj94V3}q9=Wq zPB;Bu((~-(4tKfo{ob@&mXU{lTF=7Eo^YO{JK6BP;9urDX4C=azKPq{Xg*{%arf7~ zlWP{Z>UqG_bJzhb2UJgc9XE_$1;)%6Tb()D}={lC3_`pud8yv)$Wpcl9W{X|lqGAdHFMG;z5(fvrIHo`!c zlXN)Ts0GgTYoU6Ya6Aq50p$AWFvQdQ5^$2~4^Z?g`(|?6} z(|u?f;(;9;&PEuJ^?IdoSLgdl$+LBPdS+di+SA_8!Q-TO{}e^|v4s6&LzmWd?jNgW z_?P^=mUAkny!HNIT5nw+uHP>ef?+uyFqY)N+P^Zr5aThlGp8SqFyGU!fA;ewLPVXnuszI-*q8_3-5ZCpx)iopE`KcA@o;CQyrQP^ez^OfV-UVE_B1h&_quAmp_Z|rw8g!BO0>oDv!A@Z@N zUm=c=hA`Ea^Z&%yvG9p_9%x*{oU>RT?F6(#{ljRt@L7llmK#0sMuQ$8)9}OVk1()# zg5ggFo(FcDaA+Xt1&)|-{9NP@tl|99kskOHazM02`ha#|B((?lA4PvgC`ry*E<$~+ zc}f%Hb(-&AZs~=-+^nN7XasW<2NXLtRz5xZG`M50a1YGPECXCHn`r zpuGUrmniy30?U7FDfj{K{;U}KV8TDuhZ)q*p#369OBewCB6$db2ZUCgVTaHUMXp9X z!2NO*eKLXjWiK1;3rKm-cuLDx`~lPl_!aVR%S%G}flUqpEI(n;Mv(1N=?WviZ-PF+ zWBqs%_dq=pAASVs0hXuerJx@usa+r2Q~zw2JUs-xp(|$gjV0naUvu>*6=5HWuC4BQl)2rfc6ZU&*T`M2<&W6os2YcSn?&s`>3L(vZ>PKRRn0X$ z8K!@udLL)?Q(siq^5gvs{sWC5U-mp_Ysdr5!^aRu=m+~~$2SyyQk`wVb*I^%1?R!X zV*jX}z7XZx^XSyxcD$_ThTQaPUG=PQ>ZuO;{)^oohaqPQ{zCj$$TcA8p1wo#H@pvW z2V83GF7cYKsR-NlMAma?Tg?~s8|)EKQa$c@v;QZqdTccBcjSDh<%inKeovsT81FNG zW2h5B^0y>9>X!a~p^J{J?pkg#pY!=?`{C?&#?WUFo<+a4dWu!4fvym`)zjfH?g`012G=1&kW1UX?#Fn>mj5&0=h@-sV8`s|2gC2S!@DX6 z&Oe_5^`!X1o<%BZcTjna~zIM8t)Ir)#P&qZN@xv1$-!hN`yWFcb2E$V^Ut`CA zgndbNnAg?4yXz{#?h}LYkANQg`IRC(TjYNk+TDKsD_Ne%zdrbCKR;||kbdq*_?ZQw zyeTNpmh+Oj+w~*^XzfssP`<(Ke--7W?@w~0)J59gJd9)Jw<%s;A75U{N-kw)!FVe3T>0c4) zJ5&g^*NmDvtZFw@gw3_f2K=;;vpyp=UC~!GT{2ybmzvFTrOWwLr%N~Wk?Drtu-!R-eXxs8cj#qzc{AHR zc)F{+x6Jxy@`#)weURl9EFAcXE8V^~ba|^sy3;-OoLAb_UO$I)y6IQzd7u{$msNFD zh2r+&^&Dywx_I6!-c{keOr>_hU#7oDIxDmXj@---%3n`&&J#UDSHaO>{C)5T?R_6T zItAt7jy^`-)4&ekeiPQY9X*yBz!ZF+vn!Tpet2UqySZKB`L1@<;7zuhTxhIoJ*|-&afTaL#Yv zi2Bo&Q{R`D+Nyj)c`25U!QeL_a-y*@yw#OxWv%=YcW!?o&~Dy-^-8*Mwtz@jM{gZMOH= zBQAL;FyqT%cl+|-+`qjL^#&FU4)*i1ocgtE-sdW(zmbppJ9U4&t7BP=*DDsw$87`f z-Oo`zzb{7rMg6U}wN??xzC_Z1?`jp{z!*J`uD-3M2(->a{zq(cts?OIe-Wf7%z(Y2 zah%$L=YjSM^gO%Tf-u1EnMCm{p;cAgKH;6U6hYQA>*lV`_gwdz^_R#Ox}J51msR#U zW8I0tb+i-_=JkO1=hYQKmb+*E(poP5erL+96Vdwja_`{!ChzklnW0PWYpo1^>lppN zEO*Qm^JcipO?g`D{jf^9zKP29Ms!jHS?&i|N3{JQS?+I1J)GY=;c^SF(te2KGuJo# zS#?Elm3yrE4y!z9nX5mYw^`RW`F6KI+GgeV&hNT3kLh$NJKgCn-uu<5uJXE?bcaUj zc9s13-#<-RAFFLq$5%!>6kHw!2D+?PRtK2%% zbi1@eKV^UaliNitt&8_+>-y#5J_^Wk|G;`~I_8Dd19%>g^}l0dHRn3$E;IhjE`g57 zeRUOq>#r7}93T-L5yTNB9aC=@T-U`9rX#)4vD+awy0aoM9gzi{6+zM=%k6ymxochJ z9>9D#T`AZ2?O@w=ZincD;5)Df?H}n3K0k!|1G1cy#^2m?ta1)j*7{F!MwW;DdM?Ln z-B}U1obc(LagKdwmHBN@&dz}yCp#U-vxN80*6~q1OOSM3dCJ?Ly6F1Ew12e9vFQq3 z(i!W2K3$<{2m^`e^6)Hy>GJR_LDDtks+5#t(p5scs3m9zfcX`{JwcW;dEa@?_s~!K zS=*bO>)qotHGR(nm%Z80P|Hnff^;|i+|KzP^zVC&U7Y0}*9>3r=p(N3)|m3V8{FxR zmYvnXmF_Ia4PD9e-S)KOC4V^IBU@zbX+Z)zT))He{jPSKbwHOF>ZJ8J|JvaG+a4Qy z--Ya^Y^QO@jdRY6|FBT!8$MmvU*?;OalJhsC-c4K%d_UW_|vbB&Ns8OyZzJNzT^v6 zJ>xTUI@L|nvkZQd?Z5E6UAX57iooX%#&J*Ja|dI%CrEma`)I~47rk=~z4_0$Tnf=LAJydcE`$uB8^Jw+*T+0OOOW)x_R6b!U34@J zYdW%*`E*o9YPN%yK|WG$@nvL4S99K2tD5+JOHGxt%a0@Zx&QZI_)!slEGcL=XAOj$ zSnJuN$(T%=MG>+_x{il`G$+FKT+yxBR<&3$I!H zsw>|U!B4uT&-dHEM$wF8(VsEC)BaVsBgPZJy6(aDk^bqIcLm#HMU&unE<0}z#&^sM zh6jLuwmf`>^6cz~{f^!qg0%MR}x zZN^*Q*HjAlp=Kd%^G3d);a&LRG=vgx_(-vr&M~QK$nyis^m?_2PT_eH86)hxxnD zF{CB%cc0_9Cwve2p#4CcMt%o67yX7E&)ePUpwwHg)wA{b0}N z%Dz~aBhx)z`MEb-^nG!jPUpSj)932{!>7Yv0l5EH;S(@1=lB1y?(kOt?*Bu0mLTaE zHND$T7yTz1KQ3a<$&~3{fAj0rF8Yr*>9R}kx1wjje*u{O5PT~F`&$b41X*s@o>QIu z)dckKbmd>_^R0z-K37$o`((G{M%XJmTwlZw7XCrqLBZ!oiTKMzc&o_2g~{JL8GabB zUFiQWB24Ga)A_Bj)@Vmyipf88A><#(5OO&W^|$NuCj0_B+(FbYAM#1@u{p5&Ko1dr zjtCcu`urin$H8B;%gcI9ha(l>hXV3_si7kO+9Lf}5q~}EpALS++rlpgTA)3O!VM7y zZV~*yQ-mj({JeJHKX63wy8`@0oBsQe-nPe&L9Qu2ej;oS&Bc>{p}jd7FGYm}Jd2ye{lI+rjuk)SIx?_yc!?#{l>Lp$DN)0Qdjiy{I>ksQ>ry zETN?S|K(r*=;hM;tI!|Om2r{ZZ`4z@{?h-eQ_+6{6TyFb9Js1UFkF&`EGTb>Jt<7amg#|7X2Q2G{~PmqWpjA4xfjk2&|54l%SpLvFmxA;uc?PVe}5D62`v8}(h^wyqqryhTltS6 zEumQc!Sgu4@*hVWVXUA}%6oYspC!rnKb2o8uTnmb)IVvatDT=V-%X2~c~cti*yAjo zPgJMFt^n+hM{rMIf84`8L6+O8<9k25#t-A5Z**nMa?fXns?58Op$GO451dn^%3|N;k!vw;ei7>#t1r#>N+%^ZX4={qhsgS^mU| zM_uI|fgLQWUjn`intAv=S36#7#y5-1yrXVMf4|vlV%%Cr_|IPne^=J?l8?JNzi08e zp*M1eZzpI60MF~N{CHg<9{|fw4EF?&@=lk`x=Lxvp@if#6$j5%Z41AYGp^gMu&gS15 zIM4GNgLa`SV%g!!*0{BJ-YgCM2k>|OkZ>o=4*+a8V_ngo0BkqoxF`HuyBY3=`~kL; zstfurK-xX&cS^oodh5PNUHqS8?7+@z{P}15`{T?P?ynQgA96hNfy2xP4$JvJp6}y$ zt|y0OJ(gr$<~-LlZ04I*zv0&dQc|ox4@0i)apW0E+V6?Y#JC*zL-aec+*4lpD$m8g z?ikO~HU1mlFQLD%-tza-!o$&yz`Mr(@o-Q0!q5@F5OM-^F!QzHi|{-k>1g-%na=&~ zV=&J^*Uo>r?(yiVfx}&TJ=55O%&**bd&%r0JzRX*Zs^H3_E*pU`F!bxeVx=EUM-B{ zfs)QUdAnQb6I|t7Xy!MQJNWJ1NcsB*S$@@W%x?n4{t@mY0Ly1&CBi@=`HUfs!15Vc zf#-o7v7h@rF^}-p3BmF9w<*E!?EQM4HwmCEBsZ~J^C$;{?HCff9gb`H?2gtt(Z?= z5B}KWd1<%g{CYJ}en^C+zt&Zh-$#U{KK1N%T&hd14&SBqDb~gBm+W;!p7)5tS0l)L z2fg*;CRe`sXdk*V66DMC4UwMk3jvvLr}rYxb>vLbkLFqPLN>kJk9udq?f^31iPIi? z!=?Z0!9Tj{eC^i%r+(_{^rKe3sMDqO_2-H0{le2>A8fgj^o(nh>^xUGWbAzAa^K$C z`G(;y+IC*%`%TX8&iR%_hJP8C`1IQA0aLLKo`ZELuM7MyfWQA1f=@!=@4v-xPoVF` zXU)L6RYTZuK+^H-V~Zxa{W%0Gnb8=Ujej%1XE*|tQpXidO_plyK zSMFT5Jk9%Js`EUYk4Nit`8T=KHD4EV?hpCiloz?#oo@g2Z{O&mbD$Y_gcFpvZsga_ zamRY@j}nYK))qYEeD8A=>@HmyW<6TA!`{{Xoag;y8hywf@5^m%NE^#bqWvS>{yG0c z`$xDu-ao?OTvLAdH>@uLDQ0~j+!68$^crOPvraWt6u5=w|4)P804y}&a4)0>UNZen zD2o0Pc-@4k{?q*}2eO8BaOrsiGagQh`+iGZ zg>}RtDNu_2mT-5>3jzP>yilTf{21~ku-~qFU|a>TU*zGQkZ9hX`Sw3GZ?D3j58!#E z814z|m&MLN7~p<1j6Reg?Hu_%G;h!JOFx9??KxiRz<+hSHqCvo zfvZ1AHFmbp?AMU;@I&KF=eV>=fwt?ZR)6lA7mUIuBNWf;;64Tv&+Fhm4#;wMUNOV@ zp5YebM+`er`w=o-iz6+-3_o~8|*H8rB_ZPji2F|&up%$3; zs<_O$c<;_0$9@?Kw)bUtf5dM8??wD4Xm7i{GBJ*~!_{BIz6b2@9 zJ&osq6r5o$YE^qh;PZA_Cg{5bbnh)| zuLv!1PGM4ajH9Cn1N7bw#YaIK;d0PNVZL^n{5{Y{h~A>(BcO#K`5hVPJ>!z&-G*;T z$N7A#?%-SO8`KkEzD2)BnLr}G#dhF%fcX}WgC_vxM2XlLO0&O!Uu1^H9n-X4?(#5n)G$RCh=ZuilI zKU{p?WcVDZ==0enpRtoWC<61@Yt}Ce~j(m@fJ&(Tzbfnq-Q?w}M<%;z+O0p@e4 zQwK#z#AnqI&jZBgEbuwn0Qm#V*Enb+B;u=TiSz)=XY@?m1CnoN-Szuy7vJtMd`m7t zuf37r6Tp0n4Fey6M0^X4K)nIxTj*kh0p?qDCg=p1Z{9@Y4=~>%mv>NvM0|^6ARZvT zc<%0C{8yl#)6(z5&jiCaGzx}SqQADEkBIv5c>w&( zi(=fcLzG8;Zl?7f$3Rh@JU{0T;m39o{8}LDJ5S^%+x6FdXSQ_73%6_Lhq_(wg zcJ<}%e|x)D9Da#&zPAbbZMt&K^7S>zTJJ1cm$2UFljn)GMS7NP`lWH5J?@&(dDKJalYTm%U;>s;_-{sP=y`A6wBrdrJ@hyZKtL z)`c5ge9eZu(Y1P;_Q$Cou-8jpH2q6-VrxZ^?X~}vea>@vIN$tlb-v^`IP?9op^5@B z--1)RwRO?^GVBXoxs&z$2jy$eH#A0nYwN>1!XB+RVK3Sc!s)D6`| zsBeb#eqe^_|JB1d{|@*8`ec7+Z#}owXGA@Gt{}YBK%j^v+8d%oclhbM*dQNaQo4B-u9bw-zTSA{k=O~ zi;t4tarx~9#vXgeyXRHD?^?n6J$gAfAe-%c|##zbmb>FPh#%}Z}vP^x{TZ0 z^?T(|zk6MBGadGpF7Ix?zroI?;`z8=jei=sv!Nm!HDT{A=mT)3=ugf>e?$5dzqcXY ze`%=x#Cj?9=V~$Z0f-rYSs{+l-}D!;n-K@}#yPUK|9`j8589t(>uV+9e>{ZeZU5l~ zv>!bmz8(4s#Em}3vv3a#GW2qu53qhO!1KV(2h6y9$kodpthh#>hIl~ zI=yhLcF4HT@2_0#5Nq065x5=V&01p~p>@J`2%p><-)(N~w?muOI0q1Un0AP?gnk3u z4xxI`XW+l99ik_}z5v_~;Rc`&NYoC|#&{m!c2EsLKai*$R13rdCAGtw7hU2!FZdm! z?**S~J)-`CG=%4;pAzyY_iwkP_oS?T`Y|D|QXWoTyus?t9czrrFys{$vVB(pc4d({?S00b3QI!>e z*RSJaK_8H4|7Lg`=mWZfJP=$F@@V;3Sl&<*>s z?D#EdIQx7y>}Le@0lW_(auN6ee9;2-ZjPVkS;24GFKoBZe4JNE`FnSOUqHIx|Cy$I zH3#JZTMfU$b5UPlwa7nBw8t{kKX0^85AO#J-H!GE`g8v2$RBtD&(nA?HU;$u)^{tb z#@~wlWtXEo;F~*in0a#bG98X1j_`}2FNVAcLrnhOXw(lliuoj)9^T*S%|kpO_3`-; z6Z*OI;0ExGuH=!+i+)KDT<;Yyo&5ejhh;fK7X0b_p8d_JA6?OAzP`EE_r1ZOAK>-y z&=Bw!;Bpo239{U!*PrA3KGieeJ6-u!{cQi6_njxIPlK|nXSw*+!`P3VZFIjze3SW- ze5%Qy7m)N`duM_3JCE<8-RVkx&2JC;`(pP%PRR}{v@xM2BuylH=K4 za+vKUhZEULj+b&jr*jwQ_Y+H()^eXx>c3X*BM(D=fkbj2M;w9WKJo~j2TGEA_8a1O zmhgA=Ap9uw3Sd2m;hvC454^`9hrr*}1MhJ>4E?CUNXy>w*>79NPSA_(%QM6yVUp}842=bI~RqGBglMP zoUzQgUKcn0eolr@ukCNh_XBwUfBbsr2_X0X%W`)QpWN3qU$NViJH3v3US-wc>&|!a zw{WWFZ}up^-?zW-{4)A=^2ga;u^$k-26_o_KOeQ{Ts2>F&XK{&a<})Bc`JH?&jp<*syx&AH0CGu`RNwpr1` zm9E)RO=m`BH=UneF~6IO?^C+ybV<)@KkoD8w2RY!pSZ!dTED{2W1lU+e2u(cOA!WU z2K8?i^5Zt5Us>-1f80CHMaNAsO^0XBO(i-4>+>}Jw%&J>`EIzWx%2xJ50BODkh;u0 zf41wr2lu)7x#>quPn{DqUu1cgjI8fGuPwc^Y4@^P{##xVJfEHS#j4VfOMv&mhH+0Q z_WN-k0%W=Cdfo0kSKxvwrX441da2ygRcf(6y83%xcc@)>ydJ9p{Q-`C7L3m+42~~z z5vFu}trp>|?{s{m4*F%_@jrD~g-}mm0pjiP>fDopa&j@~<-F;a*CV~ku&2PiCVze= zCd%*D0q+Y=_Gw&+^6C90RS)F@6Tu(*eJ1uJysF3_=!5h$o{ZH8KLE1lTo(OaE$Evg z!mCYvIZdkzg6X@8FwakT4N*QYsyEhwV4paBvEOkV=m8S>9id8)6CgG_Sl(KEzl`&u z-;34;!&iSC4BzurFnpJ(Uo-{w6!=)=cOm#=zn{4P?P=4`^B!_a{KXFlTK07Y>`PqeLGf~!bN{oMf|ecU-CoJ_g&A4&Upk6a#wVX(*0dR zd)X892H0MPa8F=+8OA+9mOE-p-``#RO`56Sp+kPTWVyM1Meh9-!OJ6oCJOWGay$i)AT!5=+Ou8yXfzcipUSRO2j`T^dwidn`4 zhlBR#$bn#ZO@45{MK`odmi1mhim*o=5l{0_oPR3fBbYCZH%Kl*WwD>^fir^i^bqf5 zaDT@6-GcanX~+}#5!ML$bAR&7rZk7}UW5HTtTaKd@Kz~G6(te*G_IQ!`;WbZI1m=fo28#(4 z^P>g$0myRKO?c`SSGgm<)a533)$KP0@?-n`oNxGD*egKh+jd)b=XWqT-&7+P)V}t( zhU=q3pdaA+gm6#bawE7W$o7?V^w_lb99RABJ4@FuRcSl(2*#84`U3AG4Iik3bF1s9 zdBe-9&^WyJfO~>0=e$3+eCaCZomX`^X=Z(s%CY&#Ax-%ti0!Z93ohIeL8cPxIY9^j7CQ&E4tLv4aZ@p)g0f}Ncxu?eAoG1sVfY>3tx1PXW#p3`vh0LGiR83pRVV7sos~V0gC;k zMzC|X-P?_@?Qih=2cd3NaV}<6^{aUPff~Vn?cn}k`bo`$?KKnOLeDC*Ofde?_F(!Q z{e$sJyuYW=kK6RV1b*B5Ch0qrwmqeBvmG94_U}beH$p|>7gQJF!Jk{SgK_e^3@;;p zo1b&~2Kn>R{9w2h){*V!f5mrD?Qq`KV15PSd(OX!_V`xBlV4-|DLH5_d%Y}kbg;bb zv@UJ=oAQ0qB*TAoT2-9eUsYWQex#?vPr*H*_&de8_kfD#y)dp*Q^C&~B0gW#_fEmT zdXQhvi++ce((gCLQ5IoQH60G0UKQuLS5;+ig}jaT)1-_nt5PTV;WY5S4*WLG^C6U% zKHm?w0loG}yQXVnzoAaXIN+MpqU(;FegWjXF_a!ES-*$etK!5CT3&FoS zc%J+gerBO~en0eyrWxKI1bFZ{Gb z!(61d?aiGCGi~(C-woxzwL^N+7Y;ut(jOARrgmZg3Nd1zBSJCz&?Le=eua2?I-y23V(n< zHveS4NA8%j)J1Qe@oRF{`F;(h<$gHXoR1UViS-Sj5OPZVj_*PkSc7(?FkgpH*5U9z z_|<@<>$o~PKC}n(EWp!3E*Ha};JoNp)}!+!-;H&R*WNVz$ve*Nhdg-YygOa#j@z#J znvvjq*E6TQSK#8?TH{}No$Yq^`IaQkHInss;oGmqx#$`DqNXQ#oNf=9E;TtV$wkkt z#t+LF>uyJ>-~ZM6EcI9Fr>w`~k#pVSZo}8)E}E}0-MpMsD&Gl-H)=D(Cq;+l`!NUZ}^VWFP8U`y-!&eX#9za;=~~ zv=)9webFz3e+b&KWY}Rlzgrdr^BW64(~fT@@|!5^@HGhAe%Pq7!Thd7*pB}d=Ox&7 zmHe{2FzjD<_-O$9Wg*-XW{L8O{U*ePf$L5Sme&^a+U3zcEb33*pzcVWe;D@!8Xr)97H*3$K;wZr*PuMy6Qmr__`ti!?_+5^ zkUQHC(|8~U>tM_)8V_Vy``so%uBd*Ij%Wv9^+&izdHnny$VHy@{7gJ=*RM!!K(E&d z{yM<^e7Fth2Uu=YJIE10{(1gXKY#MiBNn~npQl^p@w&cu3i1coU-ys~Atv;Y z2?Z$6)|)?2AG>~|!Ed{M|Ea%UjoKT2LkwjTSk67j3W5Dqg?mDpu>-0r{0v~x0xj3E zQ>)-R7gbc2(6hntpGZ$td!z?;n0}ty>rU}}HK8}sPG5KG#m@bzhm3vSY1zLz*8WDR zC;xx7f6P~wV-6>>e;ogJ?H@n?pW3_U=Kpbx%id+1{`Qb%?@m+=656}}>UJ!$XO`WT z{Tkah)dTVm{HONqf2v>f&}R`?E~2<6B$A65;s}3NF5-BWAp6CC+7B)ct)A?Xi=*xJ zK9#8P-^joD-zXQXAOE+=1=GuN!Qn)5!SR1rF8KNXR4#^3y}&t7oNfH0>0i42^NBmI z*yi%j-+xZ~=XvSw@z8?v2b6co;r_~64s%b|<*nZ8Ubl$UtEdRF|H{8S$9c|Kbe*PW z^)GsyN%^)^P5-vtBfl^0M&D2Qr~W+qdGVGN6+!yXamL2;2JL3VHJ{}Kv$dADC9mPFC$~XIMsujuy*l!Eto{-3Iiz1HT^4o0s+0TmO zS;F7dpKxoG4@muCzbt|{LP`BG`)yG?OJKi^X_S83KlRH_9Fy{ZOJ53a)^Z)n*K)lG z@2U1uDaCTl=UYbSHdll{#6E(Ud9Rh}+%O_Ijw%Cx+I~-W4pvS1S^C{7o?kmD7$3)Z zb@uZ^js(L!PAM0NFMEG5{_EYraOK9q@CoAib880k8`QaMV7;ulcz&Ot?^2Qe7g4{8 zuLsNjK-Bkk@W-CdQiNT@cF%hzn$WK*;EeeLHMfXiZDjdJ4uB3{LRqK&2e62b5#-YW7FG2wBH0# zpDv<(l0FU6yI9ocsA!+IqW%lT`bpR1V1B0vdLn|KJw<-MR}9M6b)xsu#>|I@&j+{S-duGP ze3RuaoYt$r9UgD>2@@n<$NFGL)ZtpcFxfALu6kA z`vM^^H2)E~5&Q$XqdjskUlN&(Fi;xpn>+;bA&4Uk$NJSUgyXm;-18;ES0n5p3`jnd zzrN~CF8&`d=Q-3Vul=h;bj9X?-vHAULLWe2y5fiH>U7iKJQlFZ0FPN4OMEkre`VH>q z;!i;zfT-|`BwhFJ|Hk>DGo#RS3c%qh%>_6P~t8~NgQ(SWO<|3Ug;}V^2EB3?N z`xd{#zTqs`(b$ISMfe%~FXfSG1aUyU>tLuHw!QlSLRwb4LaYnVOl;Vzb+X(-YIYW?$hb= zXJ~no^zixo;hge#f4KZ#_*3`x&pW#6SvX$jJ8Ycp=P6%%zw{{hd$gYCttwxH-zo;> zisu93FO^q>pGExT#&2cWEL9)&!P*}$>py<{2xq&N3$MTMN*5n)H1y@H^~<4>ng8!% zUpetst;S!0aVV!K{1U>zBvWo=732U|Z2TAxGC`1Z9DhcYb}l}pe`M-=o|Xfd?wjFN zocc8W1D!5;rLU*9-&LVJ&cnIGx9iv8d6pIWowHHv8~?3srC|J^A;IvYmj%O;PBs08 z4X*kX9Mp7X?{wGi`CUVt?{)QRruA_AUY%~#OTqpi3H!pP_s6>SscniN=^6d?peJ4J zUiiMIC$pEYceWo~XSdHY;*HFA&ykZVx$<4rTGJbupzQ|HYrp@%b|VySqX<6?4cZMp zpC^hqf-JZC&GD;T{2hI%F1NsxE7SeZcm8!QdjI^v@L{hnKTbRFW0HykCE0;*dz^Ex zi@x5QbU7K{1^Y#|13$dHbV@~s9hh-Qr;DHCw-fz^^)nUvX6yZpM}qCv65|9reyEsV zU_LP&^`<>AG|557a~(B*^QUM&aXS8e@xtVpu6kebp{C#a$u0LIY7KF&w+vc5pUSpTsJovIsmwTsg zH*NboDplKw_{_43Q17>6+l`4w``_a#rpwKTx_|cl7A{Bqgc<-Pm9r%@ zdx5K*YfsmDkUh<>pKYg0YTv8Q9e2Jf-}BH{(>1-SFTZxb`G%QyWVu=kJ7e>)B>$tQ zutQN{r?_4Dx7$xq=eYU!CpDcZH8q|5JpaCsbIJQIIeh5}oi28UTMqNGb`5l;yCX-Z zi(cxM`;?8toqp`rHagw-F4~VHd9d}gneZzr!tb^1ay=6ceNkEwxPJWmNaOQYxY{xE zdR?xUuIowV(q9tw53}JxW3 z8%$TEMELLd-e<3>=;$~5qh0BW^zqxr?k9GL{L9mv7n6e_~(O{QT-mu6&<2^-jCdw=b2!2bRku(=SEef$s`bGvWB# zn9~Q?uZg^iH37hboZEcia}r`P%zXh#d+@#u`cfOrk8@|5h3FW?5JJXPWWi_++=8?DX>9XI=E%e1(zg-oAX={b#SMf_$%m{T9q4`n^%C zQ!<_WyY`XtZ@TC$Z~WTqtK5Fq;;Zg+^6vrDZzWm$v+e8wG5;a?d2I>&?Vo#&^Sr*O z;cw)r=Y?GD`jctbkg$_n@3c2l8@TA1)j-p;^K#vPBpT<2d&A!cI6waV z;_Us-?*-m!rc2e z>=MB9C9G2q82ySPj=*&C?~#e`U*_Wb4AY(&W}L{+^Y7bF_I94B@-=^xnks8q3? z=JlQMt|Ud^{P?%W{OxHjdX6OP_6+~&?vH+M`P)Pn|Bje>px7^(?|S~gr>A(n<9y5y z05_*;z4OMkQG|;jN5so;1abl}o&5XG1?{eP(YxM^TQbgfxA(SZ3qEtv`vv=b{d~XA z_P-S7pY8G2ZQwVBBUQ>3;SKaVwjX%d^eb`f=OZxP{Cm%5vzoc+c*4kCdUao)ZU5^n zi!=AqvUAxvl|=2;&>|4I49MwKlB)5pK_t8V$x z#piEP4qb&GyY2odm)-9iZ*4Swd3b9G0CehKG0-FnZKzFGY4DZzf?Vb}w^{na+Ve+^;n>?`3XGoAeV%!gg4xa46> zIjw(bm-zm;-Cyy37^btNezCz-InHs`S~Gu^Rzu4j)5X8bCr>Wtl7k#GFQodr^=(C! zyPWgA9gUo4-{te)u9w`8AnVC=@$bCzyE)HmxRB?&taTdVDEqH6U&+6BF`lvYJ{$gn z9X_W7|Dfk<4PJJ&>l*XDdv&H?|NjZPSTCBs-=U35FHXBx>vjAN-~JGfnO`@q4$6HG z<6o2f#V#wY?iTU0tnqT}cdWrc?^ssp*F$;C&*;R`>X0>G9l5l$ItTd|$4~g{czQ(t zZ4sATt}yeo$phVTS@F~zrJKv;-R$lsXJ6RgxsRm` z<`d}(DPO;B|Bd{_*ihe=Fdh7R%d1nI`weRTsPoO=?aP;)@7w6V>~`S%iip8~d!Ags z-6bDcUmAK-{C?8*+Xq?xa|G*}7g^!(i{=0FeioO@zx7XAx6Z}i=S;afcLdv$>79Dl zWwTuLhA`fvYxN#qo?9Ty^4v+tYcu$5w!dEn@@MbEc;1@-2z^#oorV6)=HuNMud=+x zpDd%^#PfFiXiFc|(9(D}-H-PW-U<1)`;kwPp65$wFR{I!DE4z1H5&aemlqmRT0IK= z;xLu_f2ey8=qQe+U3kbMi!Ab*D1t$N0g;zr5Xp!v@|q~J$RaOU3zR@@A>aP=M<%3=6SlhI`?$Qv+zjg0hf|6>76n@I*q>px(b%JXjB5}MEq#GaW+sFTQ zJY4*UX$@Dd95^1fVLL>2xe5*ZQ_XAAYOY-QVY?rx>zC;37g{Grz9L@I*}M)n=j@pT z=_M{7T(3aylOC}&>wV5&han%jF8uBw`jvWriF`)+P}sB9GtaD3jYi`hLxSJAeG& z&KK8q4rKRLy@hfqE~l=)FaC$pjn;8m&9L49M1y%q;dfI_7&n2?JSL@u_}wt^w-cTT zA-|9=)OR<#KC&y8>noe2f9QSEgVHr)f1mGSoV4F&(9bTM=A4}?PdRWtCU6KpPP@2o z!(0w`59&#A+3S0@xAAtKdCu;mEQ9@-pf>LG*XJ|(oiNKH7(0Wg-v@}F^tPO(o^knk z4wiRsv`>_Gef>l0iOeV9TxJmBBfY4dZzYa*5cV^iiF^-qz&A%BM&AQn&Vzrlp3F2W zH8cKv@~2GCpu28A>GR`OSkFRvP3YNBKE3L?|F3Ipce`h{Cf5eQJ-u&-dx|INou!*j z;?nsB_(oiT2J>pg_U&con+rg@C$6~vL+#UEv(F1IJz}58a6%H9Pqg=kc_a{uFX;j~ ze422)6Y9wP9f#lJ#r%~1JWN`b;D9ve~J3u zK2FMEWnSn!&c9m$D`W?@Q;zX49sy|#>rn*W1b+*mc#^I&_3&!W?r@B6U=_FB`f{tz zixVH|nopLTw~yE{P-)jMX!H2+%GskU_QmykLIBl{5V`aoM*J#`S4Qx@!c#g z{w=T_vg3TJ+E0m6`v3Wr{s8%b^rE)^u;a=g?4SAI{G13UEtFSk@0P*1M&Hk;_TLG8 zbs;SK)o=r9mAfq$Jc=R38aV<9cU(;0I}k{3iHY$nV(CvA`Z+ zAsfIxJ)Yw0s&wF=4aXx|r)KI^C)P_ot=;)cKR)$_cAe}tHU2hUIdDG)g{_9$t#$S( zUQD=OaGip;!Mdul%Of{)`N)j@Z$E?e4SQxS4&ZRtU|b=tSo|JMc9PCCl0hnH@BlfFGmi|eR}SItiW%J;nGm_O)!3ZJxn z!nw1YUy9JWb%S}B6F-KBak$Ia9>*D+)BWX5nz9_uis=`$U;2~mBYiK2ja|2s4eM{) zDt9{Q`^gz#94zAQJPhl@K}Nv(TvvU2ETv`wnS}R_qbW5Z+h84q>wS3U1W~_Zl0Bq* zjLpTK6J4Q!%vZKZ{k)O;yA7>}GD;V}18~PzEfJ}LHiCuej}Zyb(e{pJ;ShnZ&v212={Lt%Xtnr zAM5KtgLNMRzMNwFN9pi8Tj&dSdZmYYf$I4)PS1Kc8;nP({u62VTN-yiQrusJ`EH@< zvO#-9e+#`5-q*Jqw6B%k5#K%a&-=qTNq@d+IPiJg-}kiVo)UgL7`N*A$d9D=4k{GI zrEesb%YY;9{FWgBztDJ>;$h?`=S3)AAmk^+hD;5a(hxGL-nX+-3SylhH6;c_f?J&0D)nfzDy z;iN*GA8KR&$7ay~NtXUIJKtkLT(kjh+vGLuI?U0C^ETKgn8DhWZMRL>Zdt0y`hns_ zdUG$wK`y;+Pe+|*#4M2*5kR`kRE#1?X$O&F&KVT^VZ}+=ImL ziv}(e$Z(kN66ZWQK4o`F+1bf8TNl8;gZDw`_xmjHu8C&4;im~9KUkXiX+kL87I;?( z#oN@}PZL7%cEaC6;^W;4_(3S%jzG8vp?I4hEFlzctqp_^Lh&O#ztF38Ts&`gkn!{{ zAnW^8<`nSzV&BG->LrS&HPlZNBH~HUgr;~ptY9Yy#nS=r3ZZz~;cp=nPtzEP2S|K8 z$HDs`6i;mg#0w-Ptd|z`foV9r50WQ|XZ;|4|49FPj5Qj_-)FRp0>6WJ!8k~NZrIa` zGJo13Y$59Jk3R?h2tEshErk3@dPTA(>^$EV;1!p7lw3a&Sznx|khothlQL;SDF2wJ zXVQd_U$rUFTL&S(I>%*#{dk$;{py&INfSbT)vWM72>I1A75G8Ouck4X!0(yj=bA@dm60Lh&QLXUy;Hy1?e2 zWqNtf;^)WrP4j1eU&|3Daent?eK@ocUmsc?fPEn3ALk2*9|+}V$8#vxAe8PJyeowK zVZRIU1tEVp04s$2VR{AS9)$d1e+ut|#QWnV@PSZ$Xny0T2_e6bo*8?rE!S=i#d$U> zuKS|*NuRSUJ;32!o0C&_aFEvK?*LVWPKanvp@TDX-8->eq1EFujzT4UI9%HK7+z=I&x_7v>CgEqdc4F1 zpO)q2^?Lr?SNj+ECJ#dKCcSt-tGXO-h8>dE%PG^Lz$dXT=G*E+Ts6P|b5E>3)>a<^aV?~l>%bD90qX+r4S zRjpz=O$e256Z|cN#)I|>=`kprUL z@fIgxQM`BkBY)pds|R*~2>*veI5O0)U+dt!ptTnG8ze<`&-9@1N$+YHz^*^{K|TPXd|+t~{s19<(%sCj*x%bZ^+u+1tW%Z?H5`hswIjp_M2#=; zlb)D58+(4&%`!4RS~0g@_3@!_ESg!BWU zaGdbB5bdE%OM7F;Hy{)*(%JgXUc}Web1>gTm*eYI|Jm;=aQ4R5lJMCj<^2&F%eHuuUXbWegGjmNe>y3luiFtm=2BuvRxGUS#K|`f3!o{6+(QZM_kWc zkMrLEn3ES*P;i7x)BB`1EG*BiLn_ivrf)3b1Xv$WI{(?UqJ$=d_(=C|J&WzXyt7E& z(4G-4dsJRJ*Vqo6LWqxa_VAzga`7xOPR28|zvQL&NgwVJ9mwHEb(1)A2#@=-;-9`8 z?)Y7?DhT=u19;p|lbkg<+9h;cxuEX7AFsTsS$f-Zu|%hojFgjVt54(ee_S6~s#z z0vGAWOHQ%%Z&YPzf0P05#-E|QHHY>UIE4@&Y191zb2)oUPL;gTLnEXi@UQ;dNVOlm ztfc!pjHok+pLEYl8QFd3%L>Z+D{z<$hu$aMapWG>pGAvFocGVNK3E3dm-YM3>tXxs ztO4iJg9JjqMf9I6@VAg7Fpnbc?bYGjcn}JY^v>b=*>ihrTclrn3d#AT+QPq@yZ^K{ z+TCXmeo%k6_P!nZGY#GEsQcq%9=M+gyt-fhX9!RHKV63)-_YMepMdY)5g~34b$@+M z=x^!YH#+y4-cjcp{z>N9@2Riwk^e~d?Y{jmm%pCdq#u0?{?GjwJ=`4^&X3~UKZ?iy z#E-rM-1z^m{n)AU#FSjU_q>TL2j(C6{)z8K+h)%H&7gdU%U(*h)1v(7=YzO>`~Q-^ zDSwf^yFXPHE}m1XqJK)b)`YP#=TTg6|-ryxMC)I)EI5{+)=QxenL?QV*WH;`<}S7bKdV*M;XGWDn_= zdsngTX{0w4&ai2(k5w^IlVz~0|>({$*FP@v=T_I{Zj!g;m zeN8u>@{=VHxIrQze+n*(2n&SlCw;zsZ}yys8#s;+KkH6MG1EoKD$xpRj*pk8{^A`tcdn*A{5Ig;4!!g};T6A4z96mrKTlQ+<|< zpM8={e^GDf*KPc_>Grni7xueAhto0~pUHea8xyx+8kcV09hA6OE00TdvUGMXUg!Hu zTqxrHcjMKy*Y~qI`?9Z)qCD9gzR!O0DpjxT^c+Sl9*jPG8~KI(swte zlQ)hR$iJkEZdme?!)1VTio|98Uiz8dCtdXB+f5v<-eT#8z?uAaoyzx4W#jyJB1Gcs zV`X^O{s!N(Iu+LJAY=#Wb+OIUaJ*+7k~a!}_eJHU?>*K6MKmGANBT;uPHa1W745Yd z#Pis)49hrs{=#)Fws2YAggs&>A?4ry^mkY+PYT01wuR%rSDBs_)`U3WI}qhB&)((EPT4+0*6`(7>`uQFDo^6M^ zMo7~u$u$3A$utN2Ekw+R#twyfh=NdVKqx#HDg4tX;?4svX5Fe~k_^`?)U!WExGKwE zZRT(*GfJGr%M(Z8W*U93Dp&5h_m;Tm?|9sl@Y^_;`aFD!AEHazaAy>$}~murvo zr*?tw=hir}BOQmEwoc;Aefjj8P_*R=4%ZRwj2_E}SM2u`?C+WlN1X3@9yeh1KkV;L zuc#ya5?o!@)8v2Bzqjr&l(REK1&Q-Eu(L}3yX^Y>Q@9_})S6F+3B6OM=fbE|# zmdDke-17p5`wMZ=2KnV`RP;a&_jb1oFW8{`jh-}_ogcW1`ww=#k#@>_?;dAtPX%Xb zR)O;NE0iY?@-ykmO;WJ^tdGcRv&!@};|^{|`l`Sx4sJeYF{+pC4cI0c0GNdNsHU1qLc(LTy_iNyS4WUmu^AcXixZ=0Dn zKbPJQFrRoIO&f5R3JSutz^%arvrT?W$7-BiM{>!0=YLGbN7$urAE=$uM&;9l5FhEIi=Iv4cw@H9`0lzT z%b(!&)~$Q)lvDOw$mXfdJ?}pOo}LLkFnJ2s{to)T1@OMu??Lyg6@2Q{p7hI=R!crjNH2(=SkGq<&gT;U-10o)9hw@sS>RZ2oeNH*l!r^}_E&dEvW!T3!0& zg6}>7_1*q`eAE56i098uJomHqSMKBBd!BfYt}0bM-;Y)JlHmLjy-(vN^UE}vkme~o z)60@bza?a7nWbF3Eg0|EQnG##@#gjuYQxjO{8k$6QD@l?BfIGQSZin+*rx*TJe2Wt zj7*~m`EE9*^O!WS{~?Vw7S>e?tYZN@2cdK!UE@{<_B-+V&4((&V6`hG?6O{1hs7F>@>&((bxzd=5rXF}6@ zEbSTi3dEtTW6h=TWl_RQqSVv*MZSb`MPbl*obIC_U+C+}2e2;I3-YlY!WJ?V*7J&e zUiAJrxYySUsUSQ(e;&o2UC>V_tkBC$5c_)~wsK)JsS;oyRq(>Gd zy-LAzef)DO`DX!^M~dGSB|kdhUYw`y2!y-}vR28@6E1qDUpUZuroKfmIy z!f+p^^Is|Ouiihg3ce!5PuNHHuK@q*zw?^mxgJmT0qH+JRAA@%0-$~tm!pVmXGFcA z?>~w4?~|^0w)++i_jQ(xXP`ya z-}FA|kA+sS=bHXHN8)xJmj0!HAKT>w(+Py~jo#;wx+3rbR_jsrW zq-Qj&Q=oiBe5CK}n0Jih%~4kRJsQ^o3SND_IRf(*#3}SMEI;;6x!^lMu5aw0V}GBI z3nzDb8IJh}nGR|=)E-)U=7N4uuK0Z|TCZH15Q+!s-pkvR=fX*HN%}w7!2eWVYMG%w z3_^UQkEgr9&If(GCwU{*yZ!&4_=$W+{G{(Bi7d$FyQ28rC(>YD+M1KYW^?g2BTj2B z=SkFjH^k;y?~xs(4^`X2uE#n-^-2cW-w?dnbmN}RN!{l&i@4H$M{6@kN08)Q!EeFt zJd_3Q?kA-{nX0KB-TtBi8*9F|-Q3Uc$uwez$u zJLC_-3T;Nbvtus!eU4n(Bq&Gv=b7JnzQ1{^yf?Q6`#_o?-qInLCd7Qy^ZgCrFFl{A zFZJ!OPc`K03|J6K57MuO23F$IyF+%FA07GJ=~7e67~c=1^DwPnARRzF>I3DF1ZHtnPK(Zz8Uzz{kMo;2S~Rtv-|&OT;u!* zeg!FANaD?dAf6!eU_V1J37a%qWU&P09 z4bl^&Q*lqeX5?=h|%n*;nIt|;s`s_hfC%Z^OYF9IPx(w&Dj`jO*pmJH{=TJ!B5^(!n;ri2h5>A;k& zBe`~XR2AgC!1o*5-a5C5v!@O2w+l@qo@VHK2q8O2XGz!Z7H5wY+BI>-c*%63_etLk zobiam-8dp~(YVf(-Y303pgg-zWCYX);Fdqg&e57Ag+B%A}Cnw}{ zae0rC{bPEc^o%^iUvPdc2JNovI>+bB4cC)-%mWY~>AwecX4k#mzbAQp66r5mAx{b+ zKGLP~T)E1{b3L}tk+`3a-Y31{@YDTVJexy3B`(JY_xM5I&m_NVV2cncH)i--2=SAi zd+Sg3{N)g+FI-mz{=3??TOD?D@ygN^{nduYHLy2o#l`D0)bHX7YUwVg`gMY~cQXB~ z`}1f*E@XlCVV*}jn8zg)AJVydZv4cBa}dj)-zEJx!#z%l59cok2ZX}09LWRqdY*6m zS0MQH2riuW(B6s5*4bS?xcFEu0xt-KW4fA06GHJI{V8-9TOV(1BEvELm2f!b?RhjI z@!{-*a6pKk^zFE~id=jqVY!S>Bz-KWAU+@zj`<9P3qt&)zn?WSgbSw^h7)!%;q-Cd z%me30y2EkY&Z7w-e$q2bCS&*aWLPEho24ILUoNit54(=ALqX~9@c!<4CJm%BttT?i zmHh})zucM-Kj?RecGzNt_61}P_M^?+pkD~m6yMkSLO%^8&oS9fTPDK$Am2fG67yw_ z>A79<3j0NlS#S@Me7oc~+kg+GG`&9uo`Xz=a_ljG>B^Pv{g3S@4`J8sw#4!n`_Uaw z{dx48aK1=u4doAn%8jKGq(4Y$sHa5##FPy38HgGBGopWKhi5`|b(P}*XDdiY5Xvu> z%76zs2G0eaE=o_*mFHh%zZ2Rq{{*y3xE?W|1)D%9Tg8!?lKdEiT`_d_8jJ+@aze zE)c_u8O!5(WUrf%^Ve!9|Kf^FtUsF->JJc#H|g`4%kARqd4&BZ6Q)1CPkP7NrEI^w zAI=ZPCDQ&lS3o%jq4MTf1?dSw{G?m<+}n_g_jt@F=1=;5k2{}G{bSw$(i#;(L#EDAb1_ z&c~kn-VWk?8~HRA#zEn*&W`RgLwMqE>kz<$P<%}bFo}mX7c{r`P+H++=`=^&tq}kn&LbJl^n52Oa{d-duD{h_+h9|T#OQa;yyg#I4Lbof3I0?#e*w-Bm7&G5GnvWIll zP0plTIe3rraW;ecZ|>`UpEz6qme-Ine7Vb5bJuzf7XtORxZ-y6{h?&TBMa4qv;oCQMRkv`h0|3NN(d$8Vd zBr>kj{)TWtC>#g;Erj?(DQzJbe4I{B>h?f6!YP zw}{KDt-BwkUnlqf`gt8AvA<-k2K5dI`ImI6Q8zMi>A8#A<3#EmQvlR&AXM*|8o)gW z)jMW*CWPu8JNzw#>K!ZmErjeL9TR6B&)Fq@16W*v{bhNs_M@l`-TUuSSai(1h%{;rZQ>!Y6$#@=x}6?XKdwdwXBE9s2Ja12W2Rw1^7OIj-TEjCw1>0dbYatwvUzO(+57M`X9%k2>t^q%Y%b^Qb@7D?q zJ;S~5OomJS=o4T!{VjAW<$VgDbd93J*xys~J}vEVwvh3s_enqh@*}$rC1N+?(o5XP zT`4@)OLor(zv~+2?)MWP>DilN$8qUViT3|Ami-OEtM|*C^e~>7$3IZxd6cX zw0A!b1Ur0ZxbG=^(sL)@o5|H*doX^1W27DQKI#73Hr3~FzaY+L@OvF&SI!y3;Zi=8 z{tRi!r^C$&xwmn+q}L@b+915Qxtv8gKQCV(aiM2mPuR(tSV8ejCPw zy^Z}`F#D7_oc#@)qPGnFg9&n+MgAon=hI~vhdcF2;%wu1oMYUOzd76`#CebBaiOOk z@8EE^DLez5^K}DuKa}Gc#?QdcQz?3eaN%uDEz>8^z%Ml#FDb_1+OL(kxO;p)N_xFl zbq?1LarXN>?*4%z>^`yjS7mqs4|v>>=-wH){HOJj^{y$i#F-v=uD3pR-JO?2{YLqL zbhB#_?01BdW#zewv4!|@d)=~eCTCCaP-#zOeu)$I=+Dhn&s9^;qZ{$w(_ZzwIkKDd zT}wbYE*&1i{!?+8#_;{7YOhXq;&9=mWV{2H@$nA*eBrla&tnn(*N;7&Dr1S7g;W%C-U`nqb&EYaJco@ zK8And<6Zojnf=}F9oQb5@mxFdFX^rYe`ojqpTzY5SMYoGUoalf_g`o|fVlzu&JGC8 zV>lYZ@8W>O&tt&fCJ>s(Fu}V*D16eHT8?7Bch6WQ{S|aX`b*fM?=O=b&fnnoeL#qh zbc2Pyxw-tB?w#a~NQBqC5aI_ye55Po%-Mkx>Z@r zeEs^1_-+g910DUrk02GQ%X_Ua{9X}AJ>VD5>3uWwSM=Xuo5FK?CN%96ar_E=AOms# zlznz~O~^smPp{{z2Ydo&otIq`(oPAlcOeH`yRvL1T)4%+esOt~b*FbK-S5q)`!m(_R`+X$!}%q8JJkJ~ zbKyHtAoxf4TwLmYPO_Ku^u-UFady`zEA7^BfAq6$p5q?!kM^}B{7zQMZ_?p%x)kiZ z<3RjQ5wcUJ!*Q5b)R))9`a^|FoMgY#`T5CuKYGXij5i|5#d%!4`WV|gdzj=UzmaY^ zEjfFhPgm-1?E0VC^FH&2Ib6C#PQdyjOtw?oV7+cy*l9@hN1?AW?Jc!(XhJ@J^vu_q znCIvM^~aAnT%zVTb>CYuoNti1>Fd|}bv^mEE9=rz!MrfND|8_o&zmdffZxT)p-qKx zte97(cgT;V*9>pUp6io)AI7_^TvsmQonBXtYQl5k6gnFGq`%J!@fP={5k8ubA55Ol z)p+~9k~TU`KAI3(=dIQ7f#1dO(ORJ&v{G;n@=v(ue2*`Lr>}QY!u*i_{(DR(b8a6^ zNZ+=e_K-hF?>G?3ekc8k=Q~6Oy7Pm+JW=~+dFG=DAwJUA-k+|_<+JQC&mt~oHQ7HG z{^oe?FMKp1#7Fvht&TZ3-cp#3&XjIm{W`*u=iPZjq!-mQ&L@x#AjD7lN!NF5eeebQ zL$TXr`7^TL0X`8ze5CzpXn*s144F?Zak(+363`lln-&m7M1Omh^PMdbku$d?Z-7g zg8U4kmZzpl{-%D1B?j^(2<=BTJq9~L$ZieNTnP0O99F2eKxqG_eMAm8?0s)~*Y_cLR$S%$wKK2G7ZHi1g9YLugzO+ar=V>J z$GZf11FO5si)b;az9&D~fm6s!I9ECh_6du!Bd!l{udjC~JkpyV-eBi#4|&P>IOe&_ zkG`Bzy<&atqY0t@y9Rk)2=SA?SLZRi{`OiBhNFugSI;wS#^H2=S3#^}5YGj`uOP1GWTs ztz)4-)D-F!5aJ_!cGKGNoZlT-@A`k?>xs&Tp0fS7X)|SdMNV{=XZ<{g?Ww!$ihNXC zsW-_k(hV!GXY22{kun_r|3l#n+f$Q0_aX=MYs6*Su1~jb>n9Vmu|mjh(xJusbmjb; z^^@d{#(plnPx?-5x^W!tA@p~}6=_g^kFC;&El16;-nUKV%R_~Iwb}J>aX5bxXwc7~ z`q=_)uMo1I^z%|fa&htK1nDj=ulsy|Ao#e({(fHD0utvpjL(-RYI*&_h1Ude_MtrP z;LCv9#l5^T2iRo)+g^US%RXB-oh2trM zcGz-C9@~qsT9{)smQuO|}4af5d z&)*M6o{&U%!o8=g;CKeygmb{)ibkG@M0jSm?$M3o3HVE3&!tq+!`SLT4$2?i`*pbIS5uQv-uP5Vp9NQ(&6)$N=NFqEjN1l}AcxwG3 zc^s)FPedX-^+%?B$niX|W4zKx9%mvvhqrfV#qqQsFL^@KN*nMw;2hY$zKc(d6!zGQc=AM!hIOI9L*Mhg zuX^&Bi4W@gMdjq{>4R1jrkC`9?OuJpQ%HKXJuN z;aT!ia?Q%*L*j8(lSHKV`SzKV3;bg)EA0tyxJL}jwBl(n-5<&Pq)DDUlSygcD`L5b#{Q2t_7gH8KC{BJ;Ci7eB3`jd zza@u3{X_V0h3E3ge=>@AnM-(<(-g4&S7f1RD(~B6dSyX;5rrqFS<8;yMrNH%BWxWCw-+IcI9u{08}l{9F|0{i3JKa_SrDX%F#`K0fMT0nR@=@cV7p zZHW(8c&L1kuCnM;8xgNyET>m+ey_s?nO=S-IbR+5yQe*bC%trpDV*b(`9bnT<(E9c zn4ihd6d&@BfBr?GqFku{N&8W*Ggiw5@sJ&)``!NKkgz92iP!$c(jK2H($BlFyb}-E zLwfX;lO+l;`KJzkx3M;haG4&tD`EcxMsIt=`KM`fX-^2AdlQBAGuh*djxnJ=wz~Fq z!GpJ&qXN#yj*vXgN^+dykNqf>hxn@fytb8|CkWf+R*hu2h#V<-g7@mVO+>L9M`*5orsC(anPrG- zKa=p3Z-~b-;Gt_?LajGe;k>BYPf&S?ud!*yXowZ{`QM)W zBm5kI{oY`ISx(PX#(3d6&{&0s?4Wp6t+HY?S06?_kUX@W#`l_M{!!b(Rav}yv-tL5`jG|M|BTpMMDN#DpWguIb7TdjEJ;!}%8ceHQC8Ss#Y)mwwKQcEqIe zH0X!qHQI{wvMBw-%DtpLYCimo@HmC1ZruI%g2$=!$6iwT!hJJwSWdr^8RTcwZ5m~G zF6KAL&tW*fv0#64%>sV*o3Pr2^jRk31xrlig&8O|hrI1Dct+#Qz=KaUf8;5P^|RXl ziRZzJFb)Tr;f|(t^gK4?X}b~qGf$3p!nP^)P`uE9bFt}N^Yauhs((&rlRRoaA>JN^ zXNh0nA>n70=XDBM&wJrKi5cffjCl5RjC6gMQF%t-e4X}H_BUcw9>qVeua#LM{Npt@ z!WB~!`llPrYlTC4sqJaJJu=#qJesvf)rF#dR_A-iLHQDww^BdH^HBODQ^AQ@54!4S zr9JIm6?xQoW5k=%AOWiI0m)7Zo=7D>kM6+p5Z+6%XT;V6X9SN$88>M--cjof!jDq? zbGo)~7uUE+;mL@GzrI5r*tPC) zy$R5(M3sdY8 z^>gHGSuSF5oN@^FlX;tQoPzU6WDnsDbzGr(Q?NR%^#G|HrhiaEIaOJBYAUoDc`O3 zb%JxW!5-B=8sW(v)CZn5aD6woVfz(ZRi=A7Y?u9im-S&duDdXi8N`G4rJf&~E9!aT zq5j6g=Q6!wF3bGvhvQ`Ju5vezQr)p&gj;PW%_kVYD9eTzPQMY^l)#Ri-QP}3_OulPCX`KT+LJzt^! zBQ7;R6HhwVQ};guGMDKf>O=KAaC&hlMyl z?}vIU6w14r?!*(nARZ0M`l0*;VUPN~dwY}QS|nF*V1^`(@cBKapN){nNXUbYN^fS-zqi zvV0MbVvaUox$sj)ykJ=8F3op^wRo<0;?^^PYGTtE`lM*kV@cm0gywrNE zB7CSKN zB`(!Ju0sP{4_uGq|H&|>LSx|{wY>K*m~SB-yHZZ;f6j4O@I)%>0fxbPfFQ=tKad4Z z`a|kQce;fM|2UL!uJd0RFJJr)Yr=Vce}tRiI6ZNZF1~MJXEARRh&*59@0cNdX#r3;h$KA zCqouK9}-@*XSw&)Bb+@CAV1rf{G;*^-?>$`X?mVO^mCrSr9JBWGx5aHhh~h})_&vn z2p)^Fp5zJk!_|IECoG?_88xY~zZI$>{H(SY zD}8xC6W$p=u_>7jPHuJHRc|Qs3G=bMtMvxqYmyV?EgX7qxM_s$H^XCG}(jm zB-Gz^AfEKOr%8*8`p1IxPb8L$+6MIx@u>D3nY^zqXU}UWr%_BfB_53?+|aI)qZ$Oe z%7s#|&cJ?@TF*n*!FADkG`!XBq(7TZ^ncWKaZ3&QKg6S%h(YQm@6z2A>7}m!sW0Yx zQ#0);;jtZzL%N?s7cLflb}ou={m(A^zHFH&(>;2Y%!gjM9spb>FBAPCb;kLX+6e!s z_6#-f5AirWX|zub21khWaw_HG%n!0$1P+n*n6O+BkJ>-H6tZKC@UuG4HfXMl7yS-Y z6n+;b9y69N(w6sC1_}R=nLfBKx9V2OL%)aQkL&%2$3y_smKDj%2>+=4%+@sDtF(i} zV^(;6{BFE!-Jn{pZpD7D+71#AX`-9@s7phUf7E`sBRl-g0+WB@@yft^V597={;EwW z7k^;CB^=NFioyJ2Ap>Xtg*tD`IjvmZt&k@I`#+12CmQ=dVc7p69@0cxcU9ML5ih4Q z{z_)BewFY)69MYd(-$uiJXR%MYYqBQ@pz?OE-u~!ZH8p&1mz3AI%*oNbGQxTcX4?gS>@6y?!(JQeK}mM(z2fL`^@8V zKCSUDhs#_>;%I-M8eY1saSu7%;KS0+pj4|_J3DOe|A@n7!~T>bEsqN;*}f8oyS7w@ zNBa*|JBvpAU5mq&>nw3$ZTax}-n}Z;FMN{@&o)ZG&^|>qytJ3o`Ej_sZzPWPC91e7 zZ7*HnaJ^?q9PL9?aW_7%ddlIl+>kkp_8qFY+yMvXa=1FUpOf|(s<buwPG!Ogx6^GkA4byKHpAH-D7pceLo?*I&&f#&tRaWcxbp#rJM>86EL(Zpgw{E}a=0JvNnCgwkNacJ^d%gwF@ArGD6obt ze;@nq66>wM$=5Zy$?$wj@VM+<7g);-<#6{M5=Z+9RNV8T!>@C=f_UyO?JHJs7i(ON z=5Q-;-!APVR&lM)*jjM7=@X@2Xy34kOW8W87l-RLP~vExu!{3PR9Sq#`=;C;#Qlc; z&EE&JN~dT>(2u?UZeHaDz5m&NU?wJoBT4Rp!5r^-&Ap@ea|{L zTwoW8^PVKn8F(&E1T7z5n?r)}(9c&U73cs3Jn=a1zwu;Y%V zXlGnQ-p(pRB2IDPO+uVAA0J-lz4(6l*zbk+8@#`MbsUa6$J;X)*#QSqhOsXIbx9TTpXUI|B&RhEqi*=9R)DyKV z66bA~>%`P_Km0yzBMvvXmc#{Y<8kMf)nn%iBJRliVtUW#v(-;(u;ZN4IG;uP8C5%r zjr^0fGj$zvpo{C(aXjKj8iOPm&H-Ib4Yp(oS1GKA$c8;c9vgw;1OmX&aBeizyDV6{qIY$e{#onOXY8_wavu{_YeX%#nNMp$Fs7te`Saov9#w28y@g!zI9 z$S;vwdB3dLcVr-kJC{nvFEWyk-@IZ6*nVrSV2PuB`l_8X>;IXJ3-367XZD`Kx6{k} zwO`NSmSVd}>p#@+D%`G^io+Ggb6UJ-^5LCX9m%$1?QY9-p!MTwc=OA4Ov;7VuZG0Y zxdSThNO0O29Bwi0PYIpL=TA$=8NM8@dUqKfoll^KH^i$p``ys{xWv)xMr(gBP`wMZnFl--UxAXb>+q34tLKxg(mi<*<$$c!Y18`c=TNG+nDKivbACDaUWOO*h>u^sl<(O2kT>|Ed zEOib9a=5za&%j!|oxOLIW9LIs;ru+Uk5$7PG$$E5PCbtMm}#GiimT9IEZZI}xhnl> zHt=Vs(LQWF5r*-L-NMIj`>P~uy*mZIcle}n@B3Hn%rkRy0nVS7X2^7K-sk(R<-Ppb zdUq^-|8u_OaZ|GteanS+?{68NWeJaq89s?k_i7HrE#`5}r`%-6D|1n~%68JZ?$R&o?<-!`B$UKX^Mk**>%L zrf)YRE|$mjO}(9+M>&V{ik4kGZhGU`HJqIXmSK1|c-)uuKlR~oF&hx~JC6%!e|;f` z^Ff?*K96hPWhz_V>n)ezIp6cROV&1SLVs^QNt{TA}LLt!cZ;==3s1aXUa z+=mN4i1WL?>GzCZi@2pcu45xV)}I~bBJL)SE0C`RTMx!fLEJ4Kcl!EPwtww>h`8H4 zZt&%_Be?kG$9mV|V;Xj@ZxaYjPoBJw|em63>uG4Yu z;c@%kWn=rvxydhEc%0Y#32eW7Fy*tqd0h7Mzp?Ys`;o+p?9% z-MG`PIp>#rQJC)Ac-+dBMYeOewuIZx<6d097{KAYCSZ6D9_M}X7F)k;U5B`9JnpZz zXZmvCyr6OfGT>YaG=X}oN))wE-&g(B+iMYKy?r`>*8M*KtP`mPx$K7gF zmYp9AUW)NM!s7}~IL3~1g0Mf~yvO4rD_3L3sm*bHf#nsCtFqH~Hy6L{)E=$iapB>e z*mVhER8L&yaW{80VR0tJIrs6nQJ>$0aCUyb5B<5E$5}hSXTMuK-;cQ0Jnr$js%-rd z)f;h9Jg!xiQr?`MU$Ne`oZ)ewt6yi!?e5_iUO0~{khJ{}F1%cbbAIJ<>8`H7&*3b% zPR{a%$At&vX4}mSUD3`3Jg#ldh$~!pY4E&n%Q7B!qQjtW9L~N1!&}AUDhzA9h{Jv9 zh`5zJ?&Y#K6FA(Bz7psB%;VB*yurq==5!1%lE*z6JU)yIZvg%-jb$f~i**!9$KiJW zis7B(akaibxr@UcU4^(yJT72iCU#z9Dzy*idEAgYk-=Peji~;N;c@K;99_xb9`{2# zf8%ja>)m9(!_LBWv6dY?uBGMC04}_=n9rO^`Eg_1##I+M+%8-<>U_tC7Z6d`#^C}& zWc-{5d7RC+0{h+mF2(OCk4sZzM9*Lhrq%>RmWjlUT` zM1*1d9`m?yJ07s*b_bQee|cPF>ieI$@QzWvw3^42Ka_C+hx5gJ=1j(?yE(<&KRMh0 z8V5Y#!z-1iNCysg55NCePVqSZ+;79Cp4IT?*3HGP z3%V2_)6f3`@0XopZyw>o^Iajsqy5opc%>@87{lSpCY9mQdD|-Pr+<>N-+|h$l;PRR z@^)q#dB%?mZ|o(BGnM0Uud8SJk;6sUBrg6uZ`Z0F_x=Z;GY6h?xE4nxj?V8^;}`j6 z(k2c!AN}bxNQXqEBYaTMjkyNEbCUqlUW=i*4VKj@_J4Azx&JMf9kXT6ia?`MnhZeZv0t$E@&JGavM zGXuX=J5gd3hqL2%r?`83KKo_g-H#k@8{+KudE6IM(fJ(iCe|->evInRA3qFd$2m=K zKbJS2SFYm9PdjJg!mD~2%R@@Oo?qUvO+gNK8uzczdE{z%hxggpeS_owk>Szrx2rhK zH)mEZypHgD@!~T2J?GoMzHU{V`Tg5Pg)m>^xp6|^ zXV2ew%i*Vek@zr&%m+sJQhP&sbNE9qCEmNGY!{92!A~;Y$zP^lqyZzhd~7 z$qD1Pto)%hhp+rj`rn*L_)XsR?Ze@V6_xhW?@t@0Uytg!E^zoF(`5Mc`_o4F^HU-Q zaCq<85>LNBZG_+K%rlk4r-pNE_2r+AaiV&IbpP_tV>x`|ik|T|!uMM+undQW(eo_m%7J zay-*(%lH!y{oaicPtVk=zvp;He(%Xc``}2E9i$JJSUry8NrCe_nkM~1c+y681tcFh zn&Zoh`+_KbiSgX3RI3`tvjXQ0i6^9*Y>$oX$&tJGJdS6hzo(z9HDtLr;_>Nud=Pd5c`{XvDK@hF1W`bGDWzPxS1Bd0yZ8xR~R~SHqJhq({Q>DjOACp5rmM@#L}0 zP1w(QEXmpY7>nzFDZQwDvSB}i@*(N$ll!s$8G28a?{9c;{|Mnp&r1CZ8?Tjk4i4pO zTIU^amjU0RqBXwb{4^5R^^sk)9@{AW=M~HMh2#0PuBX5K$|UUX`Bj<}X zrp9U(U-PxI35Q>!;7w*8pRvF;Uk?9B!3P=OOANfShr|2gx(D)~%>duW(Re$DFBRY3 z$@n`1c>AxMm{pm>cdg^;Ki?ia{!``FDLH%++~-gB2Y=!5+xksA!r?dgdWLVwCeQhx zbSJ$dG-DSI-?WG)p3co79O+V-%CqGmT|rO0Ukg6`T_b}xbKw_N@O1tTg-d#V&AFi* zzLtWgb9e|x`gPcm=NvwKIo0Qw|3i8EYZb7x;P4Amd&b}Pl*bpi{?`o--{Xd7_`6>4 zc>kL%+5A7k%QJj?ERX-&w7xJG{^)F;_<*i*e;WCX^paY||K{)&vA<9GH&i*llJM!Y zPHaD6?@Z75Q-6$bq`ynKj4i)TCH;1tmh~{@U7y!WNO{<4Di#{HM%H`2`(Y-j7QflEC7Px}T5N4i_` zv_C39&bt$ibdvln+5T^HI)@SKfBGFr!jV2)zB23ot2p0J_Ist`>yOKWUcBSt-x|+F zB|MF9DO}PGvaX!N;h*AsKjCAq^5IVjiW$SM!H?&fvPhq&N>t=MEcbiXZ99tq1Jjc(d2{v{U6XvhzgCq-?$aHdgW_{}1g{ z!y|i1-+z!K4`+9ZLo%FX2H{YDKQaD=W2`@O{P&KLU*x>Ez3OUL`bSoin)r?8dA>CC zzxto>dLf@z_5X}_X@|<}eDApx(%vNK53i<@FM6KTMt0WAl9?U9)^8{IDF4#A)1;01 zBSZ7fVe{|Ul4PIk7F#<@yC|JWudf^B!};x8&r~j8GAvJ5hDp57kMj4-X@0{foxxr zox$-9!}@^gN8+P)H|BTgebd8+{UxDiYs9lMhFYTiA zB)#EvTDD#KkW1P_csi$>aHOM-=e@-FNyU?22uIqHwCF|-zpR93_}VGn{^6g8u=BDh zmr6XPJDnF!+NfS>I&R}V&Ym3sWRLWS&sS-WQ95^9^EwU3b1;(}uT%X(JpXC^QlsS% zwjcYeVxPAr=h2MptLt+&lCv*Vv5$EEQ~SRBaPAL|cYJ5h^q}+9NgL(wop-mza(s)G z@Agm~yY6C?Znx%X3Zj?ann>XiRfJ|p|GW?aqAb426s{v@G( zo;l(4t@vpO+g~h-<6Yv3>xw)E-w_AQ%fya5RUT{ign8atda(7(0Q{XMvL~o-!trui z@=f6UT@c3+#1m~#*q+IK@3G^_OAS5qDe+Kxk*4~K^pPAhTX1$Q#r^$Mk6zg!?IIlM zbcb59^E+p7Jr1qIh}kXi(FW<&^J;dsemFP8GhU`Wo;*hR`*VXpcHSyYO36p@in_qZ z>*(-7?Kr9RrQeeb<@o$?9}D%5h|lUPd5!G*>v`J_9A6(C_o#dt{;re}U;7abcK&bj!j!K5 z8;zsLE-&<7Pz7mcY;CE7>m+RV>F(!qa&|}6PdFU!ipY!O_r%6M%}>o|$KzcV$Z%3% zJxTFV<3a0-5{u8cpyP2|e0;{raFXG=9yJ`|r+CE2&*1w+yJNlC@8e~a@nK*M=_leP zZItc-OWW_{?9X10^0_R*)V~hIelgWcq$|B@&5oBAHToz z=f)e=OI?~ZXY*MjT$ci|vWkrDxGeoe@gQC8`+@8@Ef?-zq4;>=_eB3?{Jdc69A{E- z@i8~^^e>(FZWNyx{WkRCcy>^Qc56W%^b7b8BK&zwn||7ryDe9k!uukR}LsMuwW zFOxF=L3Sm!p0Y>gDM>iKMbmlv=)1g8eCI7n){NsjVvxRxtwVg?w?11wt_|buqwl6h z_8n`JeHLfm{P=#mXL+N3wh`armggFAeEV>}Y7%9=E%DL!DI?z7Ny=~HcsmuPc*~lF z(m81KYFGb>>J`!-+ID2^JC}s#AwI&Bp3z`^FlWzoTn|d^CE=;wBs}SVb8P*Q;~B5E zQ&(iW;8%nHj`;NIJa&9>7{7ykV~;^QwWoanc0F3{_<1K!KO3zJ7*}q@VJ=>mGDtsD zJ5K%~O@1Nmzb^$lFLw*q)6+Pf@T4hU5fABrF5bmCyG*UgF3KKK z=b|JZ_1}pnF>RFpYh7AVkqc*A1ck%fZ4@5)gY=LaU7m9Md8SBynio^~C|}ceE#f1c z^Ib8v{)@o=vyp#j-u9dD4DxL*)1(oc{b^rF`%~a|k#G3$Tx$A%`c4^tZxCLeb??`4 z;q}CRu9`0?KN2tbhji*v)qdgll2_sVPkgE-KGKC!?PTZQ?_+&T^W|h0)x*SVlpp(* zntzD1*Zx4-tMbNwKQ1HdF(ckadCS%2cuQ56yi|`-zB5`^QKj~%MI28%T-QwfTH+yl zNR$6azyIRT+SLo!f0JF&xUZCW2~YZU-3DQtU9<7b(kaK9&K*`(}u%aJ(lBYTJ^ zdLv(dO`Uy%op0IDgSRKTF~1I?c%Q@UI;<{lBu{c2_me#|9;NRz>US0L7wMeAbJ_GP za7yyicVLyD>Jjr)IsP$9-#VGb58%?pud3vy_KNt8(l^uBG|xGn8KphvS>k!H{_*o$ zCH+dyo1?-QmJ9m8ba+X|WoPe*;Lt}>b4Bt!% z=VSliG&Q+!p5pwWny!?dq!ZgmR_kgCHeU`u%;y{8B~9hVC>`2pWmx-P#pioI9f+Ui zrxFXN<4fXlD!LzQE!4;5ul+ z8~HJO=5@CH-j4fNs6HdSQTc0md0sC?F+^ zHo_<>N((N9iZl#MyCH6nqcR|l&-}3h@w?;uNY8zl z@#d30Ts@xk{@5$Gj(_CI+3&ZH{XypYbC2Ho{^e(8zyFg@{IU0BjsN4n7Two0SS^Z3e{Y%^X znb@I@cKT7Z8?*ZP{1YOcw$AJ0|B_ArzrOF(C$jo^bf~A_4o}oK+v)bxpZoUAeLZgq zb>-Xp*{Qz!=bu{2jDLGO`OU5KTK&W9^`yT(wf4NMdA&7!SHiiH-_;8EjmPctdc@Oj zEoSxeL!sV1>Wlb(JnqCtAN;GgWcoYL3i;se{ayZ=(`_fceEv|HX~$o5TjX!ohZ8&S z(If8uT4vqZw{7#|;`=+zt8#YmKWE|Tf%io?oNlq7c-)TffBm`gld}4GD6EskJVku} z!7#6Qz7w9l`;|9juD_im|NFrEHtIfi%8Nbvzy9Sscq;waq5qK8 z&qubc1IB*haXX&=&v*S*WZOX_%EFu`M#|AocqD3A6)~)_aAN@ z@k`(TsLXYUo%(yYb;SSl#P@tl7JTpM)TKDaBYd%5;jv*IekVTvhkcSZhpyvBOeo%F)mPn~>G7JP5n7AMBvVT{KJ-*<P48#^ zEUUjuKfaaT@%I_yai{)X``RYzxiuW7qWMiG{PIS5VmeG5&=KaBK_1f|G`QmY>dH?UqlRlf( z-|s1p|N9&EapJ4lam**DelL^XKK<0K{1*Mto#ypNkAKb&X2J2XQ(OCqe&|m9d~Wp@ z-sls z`>9O-<$0kVDb_JY{cwG(i`=2U^}!eadS;&G+pmv!c7BZgMZVcd-y|QK{f?~p9j#>d z_i%jhw?B9I!&&`xg*bitd>@V(FuQeB-=#qUVv-n_rj(-wU_rEyH@j zPW}8|{sXsU_47A>82udQj1D|I#Fbw=^+Qj|>Sym~v-^p8xb1v)>j!=%GcWwer$;(& zg=gZHY<=*BzWQ%v!E<+ro1)xw<`wX?9iA_(eDfQ!`g!8A!{b!jkekT&+xz*)FFdc7 z)lcca#D2EU>#=)1zZmuU_Wqvt-} z-rmnnb(l}Mv5@I+@47C|&;8{HPvgDW`O~|Tn8P|7WKha-``XQe0q$eKw z^!L0jYrdDmI()2Ki2cWYw;#9T@x{M-_LEutzAfy_-p(hn|Ly&(eemUfl-1AQgx}qW z@n?KL9v^N!=*0_P%FNS!SJ1aH?vMR-jyve@*FE#*eOYi;pAzZ4m7imO5s%yF{hCi5 zd`wn?R**gi~ib9`u(k+TYF;`oPX4jr))Ys-1=Yj!0n4!{q907h9Nz2)uH0t|Wji0e?%gLd=lj36)m_Bz8|vie#7)K)yjesZDS<>B<$<;ui=&+7NZA#Wb_P3(6k z_+Ip(v7gK8=kuZNF3vOlj=)ZQ_T{fs?#}Ax!<~GK^I81P|4#k9;rCj1Wc9Pw*(d0B zqc0QQyLZUle6GC6!sZz@8|rFWapDU{HRY} z&g$pChVLZDey$5~b)^6HdHugG72Ey37@zN;zi++w$(i+*FWZ(cy)NwI*@=H% zvhZIr_3U-a(eHD5#eCiN`P_8F>ofWIaLB(zKRdqPIfnUd@9(F6WBk=wcpeSkr-^uu z{p>{d@BM*K{BTx3cWujWJ{a&D`-{izaQ$gxF|&@e`U6o9xO~L^;&CVVZW(`9=KkEi z&N{VgfQfgye;nmxr~cmj>Bp}#-$yyMlFoOae>|*|O39@qv){GEUZM?8Opja_XxW*_s2XJz5z+rz$u?fU@N!|zvLZ8-k6^)lI$ zEBN$n;rpKR|79y(*6(+@ee5e;k3A6hGV)>67u%1KZ^PpqzK-ub_2wDvYr6uD-w*M@ zLqF+oJn#uWu7}^(zS{Ws&V|pZ-sK87UVXylcF$K_f5qQ_S^p)+$4i4=|M%h}zYTv8 zAJ1rfsgec9S3+KO&ybHBf3M;EkNf%R|05hR{)*$r<8S`O`@b&>j)(qJz(?N4jrQ{V zSN;6H|L^PbN92ddCvm);_~X^Tc<)3O9FI8Sa9rFDNBEubs}0AUpM70d797jBIULvh z@K!(jeE413OIH~m&)xkItxsIRr#)d^`tnNfW1=1lzdw5Ewf7l{Pj0g>*9XLJKkfzW!4#FAu%^J{$R^ArOslOayq2gkwBE z9L{&5%X=@rUv*wr;N#98+X~0N_d0#n!|%^`;0OvK!qM0UM?8NxIFA1D4T`_6fa7B! z?;7zD?f&{tZ^cJ$8$Kc)wjUo3j+NIuL*LQ90*;9%J3jXO%T~Ev|0{=M{>QJb9=qe# z?|NMp93KpM-;ck48yuf-IIgz-_`-dU`b-uaFMOHf;P{U>Ivm$OuniyU4#(Bj>lc5aqB^fD_~Rb~e{|{~L;QL^ z{LXyjkE?}`>keIbSr!~W_A1X0L^GBI-nFYu4NvBJUC*yJb*By>M z!7tn?eu;W@&o+M9$^ZE0INlWEhV{DZ^A0}3?;an1-F=3Mo#+zj5swi+ zJK2|!6KAx3bA`OTG3@i+zD|GsHyj^V+dtiZ`!h4+{X@ZDk8ngjS^veYaO{MSIRA)` zhvSc*Xw)L#?|#c~Eoaf?5utA7;_ch` zBmVC9RgUNOJ>^~6Pk04?eDWt9A5l*B{2$Mct^bPS1)vsNFkB^1?e1zkn{}%A^ z=hp^~d**M`I?okwbOpN~;kf^!0gjJf8#rD&{^6M{IKF&gD}U_!Gl%2+=dKMLZ#}h; znaBO*qg&yK-|;;Eo7V=8PoH_xKo&k;9pc+am+QaidBgMnd~M(;AN=m$&Vu9aQ2!I* zh~H~lf8Vu%W9jLCkf}fZB-s53$3v$)FLnNJuMHfJ$o<8;vheZOVVy6+5%Y%YU${1K zy!h?U%Z&G59^&i>NBo}J`Wv^xv6G#P_V#+y!u;-ZIPRp^pMGrU`Ye3hzKt&XE`@yI zpI#d{${+mPuVle-eOSkh_?QoHod2zB1IK4?c=UJ{9Op_~^~a@%kDs|VaD3B$JNK_y zaC|w`M@4*GcVD2(KVBO+-qL;3?OAYqBK+=7groEQwg;{a9Dh6h`Nw6!am&H2bb0K1 z0zN)^ZQ%H>SN-PwS#Y#NeP6^!XFcjQ*9MM{J@S=5p9ROSe8S_~2uEDcKcBe28vVkn zr9b-L_v{<8;P~_0R=S-3^FWs`UK@OzddGhv}axOE^|C8_DijT$(9yhJO z;o88_J8}14X3^#O!&~8q^``4@-U`RRH?G_XAOGPI>-)3dc;w5r%1g`(t-on29RFVa z*a?nb{;SKGd6=`my$y~~|8o9o*9ML^zu@loXW`?ckKRg`PQ3q)t#Di|x~#tM8NmaSFS6kHK-d=_;kf_q0LRC!4IJD721_32LX^5^weYG2zGbh+c!t$cdjq{DIk@3z8mwfOWCum5A!on8UQm#BYxXcM1C zysZD^wSnWyuf6UiS#W&%AGhj{n73U2wXJYmEk6CJZTzus8-K*}hvSb6Jzsis794;1(XIH1^_J(qa&7SO-rMJ&lm*8`sB4V)ctu=C z{+(+BN7o~t_tY#nroZg?xcpDs)`5QC;kerCV#Cv~)_%4t_+!tT16^W$XUyY%z~PAN zQP&54i2B3dN|L^CJ)XyU<8b+kb+L#3^zW)!aJ(wSx7P)F#NUTm{|krXYOhCq`uT6X zGYgLY^^LB_A{?FivCnRWV<$Zppf8(;YM`hMmWbb0W%9HSAAxK4NeU$(+= za@#nOJ_FmXNBZmp#|`&CUiJ1@!12Ve&ppaX$4`EX!x7i#Ub=0(h==XR2;WX{{KJ8_ z&1J#yZK19?!qLG;m+P^s4aeljr!Hi{G5DR%9}fmO>A>;#*9IRy_|sqcsVq2tps)>& zD7PQJHgG)k#bcT4gooY~y^?Qt#v!M*g^d8~=E($rbwJ{Ih>A zvwrOEusA8!A0N)+VP9y(IC%JrH_Y$KT$ z|LHCEu~hS@WpA zw#PUz@>OH;>(ArT-o+&qtSLC!zAf9pIB*S`Kd;`cH`x5?F( z^Qadh+%Yc^kKgwfzx_Wp&*P=fa((r|8@J9QsXxp-{^vF3t0%Y~j`N6mDjuKt>d(An z^E~bg^mxkm^(5EbzAK4*^}xf-8+`)qge&?b7kqviC7ae6#Pza)Mqq3X| z_}veDUepP<)JEGqg{PWt~-O2Tnag-!^XovCDoxY86L=FCX>5n>`@jGjNHAx2F?$@~GSA zN4?5D?Z`iu0vwT|@%T^o`nWN^jPzOw*AFkcJmlf2#c3hyU52jJLPt(aHEhgz~lD3kxnWQU8I+LWeB%M#vN|G)n zX*)?9NxGD#BWXIGrl*qhLXxf~>0FW)l5{PnXG&>0m8R#?^f_rdnx+$JdNfHF()3uG z-kzo>lJo^hdT*Kzr|BI@T1|J2jV8NFb&j=USG|?&T3kwZo!iI1{pqgZ7T38p%e|Rq zva7wq`9!j7{y?&;IM20}WLKj|dokHnt#YK@d?g&$QJ~ zBiU6c@$4ek5AklDJ}X>rr@PKH(p|^7H_N}deaWsC&$d^2o@bi$d4hju=%WHm3kB}& z=O6GCI2Jh87m{5o+@IxN5%^E>{7L$5s!#f=a(#y5vi>dcF7unCy~wzCG4H#W_g%n! z7jWMN+;`o?zeD`HnSY1*cT2kKHlDkU=WgS<+j#Cap1Y0bZsWPzZUzR%r~*%w`x7IK zJqJwuYqmM+AFwPiW*fL_Gt8Z5=fTZYU3($c+ zD$BeNZWR|On0B1JeBM&!V= zw&pY>-LF*CL31wMeTO=2tpVwj{+y|DW4sKwjaga~@c8a_wUyhwc!qfl&+y1-0bETj z%`lJY5y8wD_1Rels_EeZolY1M1=_H#l@}HnyufoUO|`DO?M2{g7FK}XplX8bsU@B( zF0AI65qHaizFMchlZMFx&^Lvln(#cXKhyOalij5yW`275EUmh3sFzm7<_5_c8m+km zCRb1lyC?S_;?KbY;1r(TJp*Iyo)Jol1zL?Fe`odgFlJIG{HU=#2w<jL3R68XGKwS% z=F@d1b9xCO885>OXPK~0?(bPl|_`rq-(JN z8+Va0`u&GN$1n9@xo#`?Lxh9x6%ehT>#ih zyN*>Ewd=MDlG}xj;mTCyUYdkh(YouNS@`*xwKIvMiRC#8;-f9D<{XJf9 z(sK=HxohJV>m}Mn-U2EqjV`d?vMaoc;#%NI>mQBR)Rj4)owXTFmCImYstxYC&NNV4 zUClZq=5Ccf(P%v1mY(aHH)z|1N|iZQ(5YP|{sL#E1_ti6{!cL$aPp+)(xRW1bW2yI zb;lvvYv_fpnnBoTmY3fX7>$D5y3+;|C)wn)pkc@K)TydQ_8gDEDIo!oxI0Q`6 zgU!7eXTcnsMunj`jitTi$Wcw4~v?5Zp_z~Nm;AF|fQ(L*z11-r(LZ;ztAk@S-K8Aha$GW$EiU;456&Vql* zR2waNYu&5>*h{H$3lR?9WB zCJpJ9w(Muutm$@;4Q6V1t9fQ2$n}@!R~y1rvkvE1>`DV2m~_3Mjyc6@G}grPlB|1h zG3m1@oYdtv0WM(E&?9Rv~a~U;KAA##%kak2Lg&r z0wLFzX7=$USQ7uBdAiXm`1;)!mdZ;yLl@qYc27&srroljoE^Kc1b(`YqH|hl_i$A> z?mk{A7_O`{6*+U0!Uo*OG4e0tXpLeJ0(rdXo1FZNkiM zbf91X_VQ}d4enQY0WH!j08+DnG4F=6^(2SWOG!6g|LLW)8z5HKa@|-(Je6*=4Cqv6 zXs7P!I{al=!uM03utYb^&|K40q_DeDsB?5(^t0pDI`+AHOh9mGjbnqmr>d1=IUkW# zUYvo+y6>!%@EW?S6$xW^vA%@;>n^m9ojJ}34hxpvqJTO8*OivWo5eYpO}dx#BnQBq6}Y1nQEa~C z2Y5|q^_3a`&T}Rd$W91LZDw?O2`47$mY)C+a$f+cv?kGp4p>3xhlPWCCYhh!Yg9FQ zr8PP=twXEL#Y$_bU4+4A<;sa)@Js~D)O6a7n<5@OU9Yv_iOI5}w{FxgE>HK&l02?% z*+hmd&X=)-0zxlL@*=$)bMnKMN1@oM@-iW0_tX-sD0Va8tGXy~6~uJc%b`#Ue2@c99`y9lL{z z%f!H3MACqIzFb8sb+-hPgc9aM0S=X`8s|*bmxIhNhgJiFr+d=q%unuOcT)#YF6M&(oY3b~5$y=F90iM#X7EDT zM=yF_eO8)ix$bryI2ovZ1O8EWVHuu+{NM_30Z;@Oag~7T#gXkUm8*CqFnbM?+TAuk zxLcM$!-}QoWd;MoG;90!?GuS-$><=k(49w|d*npllXS~!ALg)Rc-cE61UEG%+XnbSb4lSUk|FnyM#aK&x~ zjfW#u=aEVcqr?lYuZsn`k-&mAF0PatAPb`6P<5A@#8EnvLx()rnc|N9C|nK)xQ7K3 zEZ~|E=8ofB>z;f7sl161l!te{RIAkK3{5^)&bdnGy=qx-&X(j-FwFu{8VAJ7=x3Zo zR6y4&O@a#UmFz$OV<15|F4h$Dz}`)S8noiiaIt{@z{QgV5;Ev43og19wtxa1xF>yf z&<+PN45LgPm7rL#m9rTE#IWnn*)kRZ6+2&+jYIF@7kA?aEf#=ttwk8#UG%f#LItoW z;E{}(b}KK-9Re~%4&6j7OO1Rtk^V9xjMU3GbJ!ze_J$-c*F6KJkSZJru?8su9g6d) zCtmRP&ej%narw{^eg;a;NGz^l?)ckMYo#(S2k60F2f%yG*GGqtc@oa#`FGbe9#k=J zf)|Jogt}vArqPiygAx)m1?UNBqDt$)fg6ErwJ|LBhT}9$k=mK0E^XNyh3}4bCM5jtZUC`-I5ADAa593*h8{r30~+~3~&NJa4?U0 zeWAj2=1C4A=~=27DSH$`+x)Fx-G};&Gh8gfcljQ3XM`Wb5&hUxuT|Gh?oWD{hKx&3 zg&>B!Xpad8^FZg2rPO%~FGojns_i-SIrH~%;r=Eius?r!dB)Dyzu@nk|3^Pw3eR19 z^_1ODd(8I(pJS~%%Y_B-RxjNld@MCeavyun+A--db=HDT(n}mGtrN19(60i#(1GlV z@If#$iGkGfHjgTJhuM3SAV4kJ5udCFMkU}}f4uX}o^SKx`WMd`T<813yq*xQKcQ;Z zk9?~i&p$c5H{j3h`OffMJU+$Gli!~8{+{aR7q9o@<-LA9@^nA$d8QxF@Am#K=R&_f z;>Y!Hy!fMje(C3(4wu7wM}|Vb;b?M$8VmBnaja$G6a3j$a#=^a&k;9)bGeQOh2K_t zy57aw#!aj}!cWCE`WbnwPb&?k`;xaF65w`JctQvTUU5YCi7pyP=Wud+&$||E{_Ej* z`F=k?|NMEoE`D?VFBrckJvg6JGpqD3fAbFY)5fA8|2EG0(*KkZ;9{WMNDE;3U|$a{U4QYL;(Zz86;&UP% zCgm)a*6+F}$Tv$=h}QbCQ!W?B{U|vrDw+1y_#AqzjNc5O<6{H=QcW7l_0)0WH%t2U z%+-fi3gDwSza&2tK9z^Ce!%VCo`Zfo5{?(cF}cyNC;dS#p6BPzAL0w?Ef%zT_IhaE zV^POp&bhuH`>dng=P3QQ_qorfW$+ee!Sh_byej{K6pz{UM$yvtJ+ru&;&-Ho>>+aB zZsHyDd=Wca01qB@Ko>ustLqKPC7wCYEBP$>l06{ggpXbThe6lMZ2K(s6{p4I9`j*z zt+YlIseqT`N+az8;R}1AnfEBYaRt6WTmWW$~TG39XBF zpEr5R2me^~fIRI>Z+?zlKk^no<~#Zuwq}iZ{W0!GU4G-DJ$Ly{eoWr%N0W!8Vtf66 zy1$To&X3ZU(nI(o3YO%T7hL~nIb%%rQtoYQ&!6~w&WEG;=-xGw-KJmU|25mnADpK| zMgN&Uad1C+eoV2S$$6XeOE+)$8w5e^i;tbN=hq+S$BWG7KDrBZza2|w~l?_csM`*rDA9>>t%T5X!N4fJ_VxrH3saa8ct=2(XA88&3QZNU=w=Ri>x^(z?VRyzB^JjOzX`vBd!oK_fPUp*AveQz zAAf4Gp~N0`cKNjUjblajhqzWt>WU8_5l5qg=4DC!9@g(qlrLN!b$&{|*N@`=xjFFn zZnvvP9^>@B6plyUJ>ct0@ zvg8>OWmUMZm-?2KdUGM|oh0>!eoT9zD|u6mZVoDq6JVTme;_19Rc_XjUR!VQXKZx6 zj!}f&fbfEqF7#4#q=$725h9Q7##VVi~Dz{41N zn}sqHGI_m9F`Sw_oA$~_QwbD3vj{;hj)vtcl3v1YPz20{B1t9)3550xgK}Lg+Kc}w zr14B?Sy>TX!7E1Ed*O+e(ty47hQdv-Fe;q3PPBiVD-mdSGmHT5nZ89YP0$#$)2BLgN_abIw}R zJWRF|&jyTv-gc7=Im}ir)JVNRFJk)^=mlfMrVI4LGJtUcvRNhqgMXx5gcgokZD*#k zlXyf>8R%JC>!o|k*7o`x1dX&N|3Azu=pVmOLLD0xFEgkI%rxMKQKgiO6VNqj@7UCt zJ5}q_tG^{G;d)gXK}j57l-n!?A=Ko@Ruy2wT8GTjHYCU;?)4N14HB+eTR?=1mPSc? z;YJbHSZi8&linJq3dDNlu2{o8cYtp=*QwD^5MhmJrG0y$(z4uX$(Q13u2gDjARt1e zcy%(Q^uPuSQ&JALDuh!Bge>z2hmKulAqpy=(hCMN*IVqep%XGZ};!S4vAq}Bie zZ`ds$l?9RVEMYg`=Q|56t6-7g5U8*pRI?yH1$%=q*c;M* zNRw`YaPd5mlQ&4g^|IjR^djc9I=x=maOlFkfLP0N;Afe_JP3zcRzlz9R4XaHFu-wz z!oBLBE|T7R>x(mHwzPI(^g^N4Ok+bGi~o=m3_S@NBqcOdVuYb`3u{awo>B4&mME+4 z08MK;Z!rMR!d zRe2_8#@HSYg77&PBKo0Z$owD83UlrP;vP|JxY?AMaM+n(0}Eoe)UXbr>GCl$xNdIb z|A>nh%lMF|LzowCRSZf(rtJ;VypX0Y2g_f8tIW1?X zQ|diNF2ovR7zgtBsFbLvYf2oqkS4r&XMVYAu9m6%p-S5iIo2tHi(S+E`-rUN$2ew|`al`rFXjFIAD2#c-c2$kwqGo-QFu3&+sp%qpnmk}g8 z?zA)3vI<~iJ&(hNNM+i4Dn3)H+ZrnRr`|kCeTUh~lc$Fn6y0tM@V&Tzb1K=@Sa;T? z7{`D|v7}rz)n7UD+cSic?jE$}$;VMJ1=rzY$;xkLbvX^sG|JS8s4QAnVexs>EuE`yabsD-;u)qV~&j#i?+KG&)h8m)PxK1cSfDW^nZ5U|Lp%qG=fIE-nUJ5isq`7K-vG!k#1KNJY&tU3>+Bw0XqNVS># z+R$lkZ@o3-lA@NJBqX$6vyd#!O$V5rPbDADVHVuy7BOYbHl-9f{DJz4&4ZdS_m6V3 zcsf?io>SGHa1FKK;&Bu+^CkBn7l>K%9NbB(TA9&fbGclJ+Aiv`PY2nOaYgnktEvS~ za=ySNT>@UfA61;R%FB*>85!I3|#b9$N->0&W7gPfjT3S_q#?`Xy*!%7F?+n>n$UO@;n|Sk@h#U2l8o zV-B_CrJFe-1qG_6G4UMmYJ)7OA~3g?uxkkIgWg4-x&~48v_)ZXc8R2%bl3~RHLx2r zjrb~Rn&ZuasbyrLuyVT!37IeQVfiL$Op%EB%11LRmTSQSc+&7GT7UvCjBrlp=7;B6 z9ldLA0$!4FHldd^4R|q1^RA_6NlxS@Ivk;1ES$>~$Fl2&^eHM|vcA$ocpbHcFJ1>Y<2dzt2~28_$uxY-a|$I1zvQKrOR{QQgXFL!xI$|+h%IOlhMI*1L#mfQ z;cu+Ak843TM^J{|qX=Bqe#(4Y;lSfm`YY5dh6U!eQL8V7cP)WP&lsEwt{v41^Ia;{ z=X^$rF%?G}UL4Ovuv*Unr{X`qwroqc`0>s;1|RZ5JVc;v?^^w)ID0`8pzt%QjLDfs54wcdT#5y1 z5l>P`pu1>ggo>2{UWpl*~H?fUOsXBCg6b%g7prK-o!iwq1)FT_k@40e)HbewG6J%en zianj{r1h|fOO9uJWywAYjh1$BP_1isJpwlFbl;XF^Spa_fLTFz&>!h5yC!U~CtzY~ z3Y>b@6&zrhs!P`2Uh1fZMy4m3$6Rr7=){P;D$SgPfT+q=B5M)fGIKKPvc$nxrgavl zf;f*>@HX+JZI-}n3%}(i5`bS;!`Y^#eGNz`c&W7KZRep$chjVHFN{A_tISI?kS8>c z3^#!lOY+lTccN8B){y`>$JTp{?~ma@r1)1TKSk^EBLaMEhEcH~I?-?4^effL&JSIE{frE$E`f_1iu^5xFl>NRFFDV#KpXtJYH?1|Q%>`k z?dke7Iw;MPK=1|FTpm6l7A7H(=BIJL>P=ISZaV~dp=xMgglIbYbT7h-%`nk)jSxR zn}CdZtCi#%L4`4)Nfk&;H`%V3hf&L=6ZfiVGH*Mt@(Ocgh=A9MDg0TRkj47yY;{fW z(u1}r$tz?CG?NGZK27;jU`KmkOoin4%G=xn_au1;SR)p|1|2R#pW%?mV8n>arN^#yDf=9i^6>jl`Y+Nk~tojub|o+^`QU zx{)Mdshu7$@{~>(=*TpDJEI|3h$ZyqEXjx1oTaKfLA>{1vp}Vj8K-G8SKOUNqCb?s4D#STmDUub*dlTtP!)2#Ny1U$&3qC4S_CU&84K;_%x5XsuhQ@Ycxp<4vi?qmOoZ#R^4~Xhh>53v=81+{2N7t*k^nXhN!5 zHh!1^M|i&?YzvniMjiuE%G;~riGEqqcF5p$D+VL_PxB|CDdIwDCa)BLU`M>+w7}#S%k~Y8y!QL}rX@p)QV-&ERS+Tbw$>v&1eKuXZA4weRTbOjS#b{a*Lfu?yc8S7 zgoA8O61GqYiK)puWERz&J~u7?4Oe5+u9nybVKSfQM`IHuhOs$4p*3gpnJkYrZN^eJ z%#Em~+$u^VV&q{R`4o9l3xZx6QR@ptL=v(wGTBtgvA_@AZt2hs+d?i#{HvfWG|SDV z*VZR_bPYWnB}xVKIYR}8743<0%`QBIO#W*Nlt^u(`dcg@Ir^-#fIdYqp*dk9BI39Y z4%4>jAK8(GM1i?cBNAGg^VdcR;!7&7P~AEs1k-&w$ipkHCUg+&EO+egaoOolMCs3OSFv~Q%K z@a`@9HrTup9=?9yICIxhiD)wV>^{$%4Yr^-kKoyB)r|H$#-9>c+E_ z?p479&2UvOhi5(9#+VBw<&v=m(N|pMLMtP&rr3jmc8zG%+z{#Tz+S4mhLn`SgsSOY zn>Cfw!L?K^xcg`LH1e`b<@{zRXJm5PU~F}Dqh*_G@B9yxTIct!-n8$QA${x&2~fp> zHI=o}ItkJ;(o{xngmn*SF{ibpdC+HzHJh9qA9zZMP(HjMAm|8CEyA8k=;smxNbK&S{c2 zyMjB&gog1ved#u@_|jL$u!ZH?sd}r0H#oLPA%MhR3|^yd!Q74tEZ`YkSZ)>kB9kGq z#3=(Makk*p?^i ztD{^;SK4#)NnfdMPsv>ME!iglEPX^ji|p$+AHPpVaH(aMr4RGauAeTv0IGyGsXN-J zI_Om)(4y_G9G@yn`wVn9FMTWcB`p4`eg(WymgBx?pC@i+v`W^8b|=}rR2~5~xj$NG zB#7-Z&B*h*4wq2?Z$_lg*DcIN>6@_-$*e@5R!`9OT0sOJuS&t_^vU5i5NJb-P*Iuo z!Hr=9g05rX%7@>#Pl0LrkAkGn^K^LI#HG@93 zb!)~7Is42TBs+=E4s5QF)OMp`wdLV_gEaR8(ai~5w z1!ZQpC)cn;UWIWIO1C$vM!LE3k=)?y2% zXxi1|+jp(Lqz|P@*yTJa9uA>vU#(ul>n`Xs4}BNxa}=hS0uEL4uRbLuQkrR>)t`u| znY&qiU-j-IX(i;d*p{eGjtGU&v^Hr9rEcKEN(m)Orhu`igpWB1a9b~hJQ#e7ex9)H zo9ZXv!TJevgopVQ6FBFUq|eerObG@ zQp$k`Nww-wL~GIq%n`Ls|5jDYa*z0dELgKZ4Q0|Nmk8wO^EiE~sx@(gHwYnO5h?Sn zg^;7u56b{)pKsH*d{^JzHrzRMFWd#p);13tJjergx$qF&>7qIniWJeyX`j+$N0l)) znK~45l=M@n51H;je%02@B+F_?o#r$ZCy0(wPa?~vN-Y#I-B@nQ+Y-HQ335$8mb|i+ z`99yWZ*EMuE}IdbG0&{ew-Mezo=bYqG9JdaXGW$bm?DfW9isG*&k-!ke~{PFHx80b zZ_@TWmnGx-i1_Xxt;|DdAKSb_8`;F@m!&EUC;MZ*M|vry;rl{CvT_8_akV|-+y47H zStZ^jV@{p-9IhKWp#xjc6=ji|XIcv^zJOYur<(w?=~yL^Ra4UE*)q*b`VIX+@{@09 zL2I&pN;HF8lP+kAz3&4Ftd)!^zV0g;T&fQMKPdD=Tx@3u_Hnvy?I^t@z1(hseYLIsFkfp+C5SgPZVTTN-a{#&8*Tl!FKoxC z;fG4Yx5;MQ6~F49rkMkU19ai_(jmm*Y?e42pJsY zs8%}RpFA-6ioS&Sf1|z8Cp?BYGYYnqP?Ysn*E0eb9%c5>S0U^WmKolFgM+G6BLBYx!ppEWHK)kDy*$my)O=`|oZ4L=m|x<`~n{f^!9}3tqInpMI1S zDxvMsZ>op%4-@t&S%7eo_+eZtwm+foyMkwJJat-h=0*P=Cml7pLxI)3;#B?1E3`yN zpNcF=pQ@&#&z}*q1fChTyi}ibX4o2wzOAjrxvOoD@UH0x&&hZ{zLpJc@ex|KvO}`&jQH$6&iikT#<2?v;4S@o=ZsY5FXgX(1l%`T9~7Nuov^ zy+m~0;JZVNML!+i%ya^eh{v#@apkwq@^|KB1pVM4Jn_YX#Ygh}c>d;4>*_Ixhk){_ zmX*ELGtN68=mI{uU9;>6IA=&t*}*3TZHThx)$Yi?K2khnb(MX}+J(;?S$n!JK2Q6U z0-FjklzjfMRk@GVLV23lZrKz(wUS~tj{&DxEtkK9UolA-qI%Z8>E@bDc%r%4h0@Vw_C!_eR%wnSjS{OfU*MAfAt+BQy_kjKkrplmIUv^nX<10u*A|w zrPNxek?Esy1FRr2;Ae`&1`d)k#L-7>w(z@Jo$Kx!U_G=qO?)d$qUsm&39M!eo#YR` z0g>i0%oCN2=;W2)o6)B#pj3t^9kNCid(nMn=C~nT$CN2QuzUKI^P#i zgiO6sAL?@0H(tTp=j2}L^G@*X)J9t=Vt>f^AGy@d9h>96m}kK7BC4)8>}!~oH;6v4 zl3viL(qy&JzHN)|N8)h^?-%|@HIPehn~clKxNeDYqGDd!<^y|Mi&ya(#x)7C*vk4; zNRGd{=^3%f4aH_rG7kTcWmG@Pchx$2EEFDq4)i&HWB>Re`h0<1N4{*jPE$5l51rIj zFVXtuhzDY{PFrhp*bmk5_u;p6WI+ZIU2i@=QE=zFjBj}quSUKQ1rpAcYE$)T`5f7% zQN&JaP(C>k*bUU7z>utu$%9vFLsr9+^eg7Q!7XpvzmcuHhsV6G zOx082&QbdwTH1exXbx|a9T@GTzXYd6ce#HCV?&yd{#!}EbYZxY_M1XRg~*%iH*b5( ziQB=ne~Qh6yr$*Xv>&DBi}-jM{mRl&q-bl-{Z>?LD!oP52&a@W?pxB&x5f^fZOrje zWjgRdja>95qPeY0`YktrJ5NxW_RE-toojRu{1i+gII#M$vh7;y$62*~X@p&&11-x4 zHq1Q9E!}LU{Yo}=z?nY)212n}|NOyCC(zp$wfN#vzrr5gsUf@!`rLgn38@no5PAHZ zc;FvSJn|1GZl=P?O`Qw@?>NtgJFcNQ$@OcobyT@SwqgqcTyA{{2aJx*nip}5>ei$m z^~XFt|JRS)BY?i?jcHpZP}z{QKUi^0E2 zs3J}$z76hdvzqp^Xeh^2=A8~)VJM@R^y{PP<&vwy{!>&QooTus=co#sa>Pg^FU_KN z#ZMvF=Ct@p39Fpz7q|q%mXxuRn2qb-`vQWLA!Qqc_>CM^XQoOb=Hs->O?EjUGJJ{z zS6<8gfys^el787(kYY(f?kHWSZ#y6*AsV*@JUUQ%&lnq2g}rGgC%R^{8Jqb)KI8Dk zcG&YwlO7Nmk1)hO+}V&He+R?uchrI05#wtXImiORg4o-B)%aH0Us9gbNk2Mb;- z)ab{n^l~@y-u)Z-ItaXh905u;jw*bmM3R0g0f`TrvUc3D0yS5<{Q=Km+Fmw>2eRsF zqs%(9;32u`mw1q=ILA{Hozxj)4(N5Ju+CW|i|_LqzEu>)ud_Sof5KL9Epq$Bk_ zHd$7=y_AEe*``z!gcgHgJL9k>z6nr$JjA>qm;!$5S|lY0W6ID(CagWV9-S!Q$dG{OH%A`?s7kBf28rtS z7_^0Zm7X(xBWn`0a@^L2?3vVWzC+>xb*uG+e%xP?J&=*&>ALUC2fg-TR}Z=Ram_aF z7aM|pIm<=n84isQr?wsR+R;4;TTWYJ1ID2WiU1h=~8L`_^keLbb0 z5*6ScOat{HT=XsP%5rcF`F&R0FmB^SMR1|F(18IelO{fxShDSEnjDhl$hCZo>;i+RMgx6-qeoTRF;d8- ze7_~tLYUi6FfQDiPup*mWp*1J1gFY&d-qeeL=pwL!kz9X7$LiE>+UY~uv~wBOc94-9DoH$uDN1u!4mJrUHcR=xduEf8zY@_C+ElzI0F$W)u> zFgB}n22#(a44eu51s&&37)0)Cx6x39u zwC01|W+#yLcfrLP)FTjc%v##H8OaEBajnZZu~l?pvl;zuy%Uz91t%G*>C43)oQ}@%C*d8rWQb0JNt~N}62hjbMYdaWT{xz`bZo&Yi2u8+X99Wu@#h zuuRTMAA-|JybfHm_3`5)QVvommdldOlE{R|IyzB$v}M(DmSl;X=&ORVfTl)H$x!ZX zS}oWRKOe_CriAQEA>t6jfsB1Padp8ItZSQgJPG3z$cHV>81~GSLRYfDEUB0Dk=i0j zBr-O%lQ9I}8?tba$6_|~Z4gooOpq)#4eVc;n_-Q<;mB=7z1Ild4X*chVIq>^md@{z?_yIp~4f^^aL`5QHL1A7biQZ!N?(l6XHy02b(t=j-znF)jWQv<%rOm+%4P;e3- z)@#1%Ge919OwNIAiP8KvHpmPp+X|STpBm6gEjeSaR332SPB6e$M&NYi;#r)5cKucu z*@Zh9z}MBfYJd#Bu{^&*TcZ(APRut+U?l@EizhO%JLv%4U%eU4^1$?#K4(?C5-aQm z$bx}peX@mw64bPG+cDecJ3rkJ zuAHv{O#2Vo49sdFAxL9at`)vMV`;O_7icVRCaM(qs2|KL$UIkuw+_y7-b+ZTiMHC7 zhjB!X#AmLuxXXy<_2;X56 zlfr{Y2iCJjm*QlI#Q(VlvQY+R*7`ZRm;96gsml3&EqZO+2so$!p{S zpHX(D{oUaVvBEwuy76E{g=)3*bJL5&SZp-rVI6LiYReHd>KC5NVPFrRc*!hxQ8JQIXUhj z2BelOI}a@G6Z01fP4{0F<$Ow}r z53WF=yK4r6lesIm)@aU}V==HP2`8%P9{wr%0BTCp9=E^>|Ce4UJ@1??qBY9wg%!UD z6RKZ|S_8|j>>tzQXBPrBy>cy{;fymvI^b8MMuF$|9f<4AXbn%Ai7IfUL=6tTfp7ty zuvD1k2gY;YWudIuu+$7Jma;h`9ZVIrpOL3RWydqNFX}A8c2w9YWU-56g@COr?WUm3 z=B{Eh5>+>DIXe{I)BXp$XTA8@A(ubPhAE#mU^G^u%+3rlMwjhC9uyX;q=+lRAowbW zU7g60l31pspr*aY9P}PEV%VXO*G>mcl6YWigw+Ozd$pD_f3x9CQl_N$0GTyHa=I{W zgKNk#mIsK8j(#e7@j2sp3eD4|l4-#b&!oxXlV~ESKEc{MRq4I5U$zWSO{)Gpi>YAPAPQ**%j#BdFD@4TQ;9o-a_kn%tU=^MW;Ee92~QK{qY6 zH$Zqm#h%)-aoB0I^zK!fTTfR+;K+(E2czQvJFR4gT z+n5L3Aow-mMYZlVuct>7De)#hUcPXX&o-Gi4|MWB(L`j)ts0Lf{d-?lcQ=53p3={v zsvZH&uC0{Fqh;-6(S7$Pt7pkTX9Fl2m$RaeHEknM-hYYnj7Xc8xG%KV_s`b~iEi+;+7 zv=0>>iij3FwORRrVJp*eo!r&=Qj{`h(MO4Wy2m1&D$DF)xc?|9oQ#acyqfq^I?PQ_ z&Sq2!2Fd)^I($b4iG7=jS14lO1KIkxbUZU)as!0F;M{wWCDHFunY~0$xVP!^(u_97 z!$+~LTp>y5y#VnI^NL0N8&*CC*TT^nZaKr^8AAkXxaAB>NjRxU(H=pcvABviZdC+~ zpv0e?T>uDY3LZ9{A)6a#rwa|;4o{*L{EV4du1FPQ;T~ZCn@E_uEsXQAMwO;=&+`XX z-9;4ANf}UcFc4A;q_U_Ki)V{fJCjw5i9dRg+R=Usi%In1cC^a`qQ(fv^xMgC*XV%n zC534E_1gij6k|h!zL{i}va?z_aPG_`zLM)_Y;2%FA$O?8*STl0!B7H& zeB9=+?{Hj0(2Q>C?ETr`C2Gy0bWGQ8)XzEbJZ-rW}Hmr8Cyb4pLzNX1|+P92W^XJlw16DzTZ-n_#@Lgi&?j1z-rP$ z4$d^Y6lPn?RODZzQKSpl(<+T38>!5(WTk=8CdE^h{|c7OzDuiEBrHMU6K53!16=#h z>0sg%@o|~3WQpB9e78h4;HC|qVYbp}p{e*XnXGS6T>rE^Wd#_?AfMjZlyB?YMgNjq4W}(*l&4wG#2B$Wb}O7} zVS}Eli%wQJB|=c-Lsyo`3*RwM20<=`NX0fgaH!xN4ABJnUKKzND#fFgVJ#U{Mg%q4 zQmNPeWKgUIlG=6K$u($YUeA7JoRPVD!~hLj+aAPrqp>?s;Sv*P(YJD55h{SG@jFmJ zrA=q@G%dOuWQCCOq?kM#l<^ym-%9}-n|n?NmF}@G3xR*;TU=`4$7&S)K8U8kcar44 zD4H2m_TuJ_!WlHNo-DgIp=U{XJWU2Eg|!9rQ{`pi6i&;tWCDzbTIv}Jgz76!1*E-i z4%c8cJm?t?yX!wZt&n_>4x1D46KLt6uMLC*Rx;>m@^A`KHiMB429)Bd>U)5Le1Vbm zH)ZgYLK|!?%?NX0m+>HSyZQ9!F;>fwQc}mKf!V4V!`Ih1g+{~&aR=)l97K8stcv$Q zEEDeJOa%tjAcfkR>dX9HSR+)=g6GZYNS!MB4AFHmXkLb*a^+J%9pyckLyFK@%1H-R zp0?=}3*%Whg;Xgrs6DO0Q|a3H9FsC^xj_Qe5lb_hk{b-GP!d-%J%cD1TnW`VQ+J*p zR9Y=OffgFv8-I*o2>3KmaO3nCcZ2+L50{oxiq`n2!d0fPj7zobnfMkWsk^RCt!FBZ ztVT^w>#pk6)J8?7gBH4+R0pU|BX^B*PSalWZ2Ds3uF`g=2y5&miF0F3c{$5!0u^^V zUxDM4aicrm;Ni~J)U)JQ2jy2;@a*^Zt!Q z9H*qL`Mi%U9te}1mZ?B+_0Gcz*y3*e!M(26T0?9{kb-*d^Ea*K4tB_Gj@sZDAK@ZE zX^&Ykn;y0t9O$8ZlCJdSw8=ZI{({qxk#nWrIi*V?#m%SEv4&V2eAc%#L9b8~+Yrcz z`l>e!$#HQzKRZm}s~eC(5>Q%Uowog@P|$zM#81)fo9{Bv*1LQc1Ah;fPHA@uY(rZu zTfRCvXsI;zi}LdY(qNmf;||^WISp3?A-6B_MFZB52fZ+l(X|}ODJoYZ z`44P%_25r#JXW-#06iMexD}GlG3+*W6&PGTT zD0JrQsk<$whma%X17n!8_4E)^5Ey(&JqRq*_t`sCEo4m#g|_m5geudf;7zm$@5<5C z2i%#j-Xx#XRD6oM4!cUN<_v))!!v^$=6jI_k8eJe?QY*djZzzDiQn`v?Ts4Yvzpqh zWHZvKE%c_yAZ3TOpo0K|G?>=oYzmxu<_k=za5SD;nhGFg2d(Y)=>IbIF5huo_q}J; zrIOH&1%TjF5-r2D6AQ9j6iG>zoqJcC;zL456d8hwvs#PG4FW|FA&7!efJElD*UF^V z>fs&sFw-9N|8R#r>|qZ*yu&-_L1x{b@9(kqKBo$xyb=+$&p!L?$M5~x7%TuV8n#h1 zhi{rnmkcd_qUyVi%b&9MVnH!0NNU*8@zIf%<<^51~aq5dO5sSbvM zqE*4FcE+Rx!;Sbi7eP#dve33?pf^+n9sfBeO-)Az0YoQpfrp^jNS}wk9dhxi_|g6p zg+#tj$nR9uf?@3ncus>FL`tFy1erVr3yu~Zaf19rGcgMr(n#m2RN&^RgkIvd z#(bMN>o@oFk<>aNj)?dF6xX+LMxBwddjWW4<5>zSM|S<=ntkBHC-|-{c{O+w6Qn9! z$+G7%Lt4<}XnT|JVP?$fvp4NN?_nPoFnsdy#~-E-_Uk~GNJ&Sh%Q+oO$5q#iVSFx z9SQS7OXR#qGG!X3H2IR^lCC?-&c?_QMQ_DWwK<~9sDYL+sC{m+42gd~5sSSl#yQtS z+^&{x*Ejv=mokS+6QTTnsdU1|g7Pw$g-tGha)fZ9^3)|eo&HnvHoAGO{0!~M&`46Q zinDV@`e*cXD`ge?Nl>K3x8a+*3RauEHobHIuF)&;Dx$U!UYuNu;Ti+#{)ELqG26~Y z1Ck#Fjg6mhE71V!A*#bZOZF0GySOC?gipJwB1UlNW-)QArn6*M{WOok=xbK`sZKx4 zNM?k6Q(<%v1a&_2OHdFENv0?qdKcJi7j@10$`L&WDk6j)Wb&bK{3$~ zVr}-*KgEYE67Jdat*5$hEq($&VzY%WAW-pt<>%VeBI4d;KlR6FJGcrt-}tGGlxPZj z(o^lAR>V(PP6(2uvym?;?{E-X0;qvl7CD&cunJ+9%wXx0Z(7Q8{V7pjQ6yfl4Pe0S zE(Yz)I&D{k6G+TsC!5eT;h@=$j1mstOcRusN0dm6;zeOK>7v6o?<&PIyM#7Tf70~{ z;s!z^JX|yfN=0T46VZA#5Q6rT9aWxZ8V4Ri=8Wsrf-%7Q zcZA6=q;Bo=8?^uX*Z<>p_VY|M=I=|r-yimV|7-8}?|Q#i;`d-7(yq{i<-r^-fGidy z_Gt12iPFP`G_OT2Ui{9>0tXAS#;r|7Ql&f&77Th1(iSjS08jDE?QMr@6^jjRcvbx+ zM?)tqq0%-Bc^j?wj)8D|PbJ^rfP2FQnYJ2vRPUFNw0lSX+`YOYL|RX}ij1f&hyl3d zm%kP6CibcE2MgfMgPO6ze9VC8=DhJi?mySm+5htQ4|=}`|Jr^2PyOfrq5J&3-t$j; zzXwa*{fEL!qJ`upX;#h?@tE{=33j|f+Lva zZox(Wd||j?~NCIP468nxF~!JtyaBGogzZZfGB*|bwc~ify8e=&qow~p_D(8n*WvnO%-3p z^xyi+OhT;B75#^6w{0N?Zyp=xrpX1j%@qwb;Wv;o&-X{M-}(E`!)PeTd*sY(!5yVL zQ%N)syZD_R(ZRwVry?;U;$}r0%(d!)a5?^4z3=_c@ms_K+gjXXh$aBMBE7JKPMLrQ zJxAptXaF*v0Ch`#wJn1DNljyzQB`n!l0G%+{3e|8>02^9T=hV_W?#Eqn5!{x%^GdY1hW zYgEX@eoIa2JjV~@d~Ud4;|hsfXI)T1zI9yo+**(Dkn5V+Pe1+EH3vuP-i+h=^OKwQ*X8(~&;Qrn?`OT=@AiH##BaX8r?3MuGfWuC@$U5S;HUmcq~Ij5s<6|oEbE|x)a11>ZPscbR(v<``tw z8!qsN#h97R5BRggdAR-vc)+kVT=fW|4!(z`7Fj`{r)|~ELkj02mY~M zzv2z~t}8FO6dvLp=YhC|u!^HRbuP{9XEnmEQPEJ^8%PFTUvY|MUOX9q)hZ(f@z#{r<1seUS5A?*0D1 zd%ypCC2`+x7v=YQ$# z&*|QJKkKdMKgDy+H*#;Tiqnc;DNM$~jpS)uxKEIPiMGMd4>7U5keN7sgB`N4IJ$|R z6t}!&a`;JFhT$-K$T#Kp8fxrjuIK;ht>?e=e!q<0ylAN*(x3kv;TD8M{g_=K^6R-|ld=6eI>` zBm7@MD2nll{a`<3kq%px=p!5p<;K5}^ZR+(e@Gu)D!+2Ov#iaM)Q$g!wOCq!_V4h3 zZ+shOAmnc>!u3)!|80&zGZ8P~S$lR*MZPT9FTel8@_kvAHb;tglv$ba-IzNvYo_F5 zx9yI%s4I5uH-ZoB#^X$-&hh?x@4Wu})IXr}!c<&r&Ae}-6pH}L@W3s2042h%*Kvv8 z66vkrUi{9>Iby#xIWtxp{KjBfZ_ekl3NK-dhF{7Nx9~n0xg-8R<@Gi!^X6f`|L?Is z<#!K%{zKrK@cYxofX#0+Gr!m+dXk)L=4X0=0M7L-v;7$Z_22t{l#M%W@v?7()mn^9 z{N2VgU%l+s@MGj2$%Y==uz(nArfHB3Mu`64zbTq8`$*1zB^7A&p{eTm2MY(jOs+@& zLr)U_k~~Z_wu#TzKh5|5t-uRbL3}GDZJT{U@W|z@=u>{(6yM*Kwo)>&?RQPn=6f<} zmk#lpcf6RO@WpN6$-nvSe}Z2-@Kg9I@*dFu7VOIRBY@NOW1R`#JV+!_PLMdm*jn5v0Db7MIcbK5Ks= z2P4sh_`aukWBU;P<$MR1y7cT{KkWYgpqvNmwGxF9CRsu%klpFpSt_;yHFtW`ETNT`FrrI zZvTz`^E8-AKG(-3u`;oIf2Aj14gTC6Zx8}h_W$>u{1xnJAbw)}D2p*duT@ZypbFz3 zz!%}@m0k+Jo^9Y-j{W4f<*%j_SLbtp1(;aA4N4^zeE;2hz4`Ti|7$4xIp5#);B8R& zr}%?{Z(+L}sOD3HaVf?qd}~_j^Mt?bkG2XUE(qfC3B=Tzs%7brV{gpB*l0 zd|{4S;C91BSwK1s>9mN?4i=^B6D7iTw;}V>;i4QNcB%}bXr)ESuEs4n{EN2ZE_)gO zT*PPA_F!TrK$~=C6x$}o4&hZZD#+qqZ0vu-S+fJG=A6s-E&m?@%EkBn5FV!0g>zBO zo07jjSmZs=RCQ*hKq!_;Z{I63h%`tR#@{LJes&Wz+RE-Sny<9m~+-Qb#u-l-15QSV=>r{^zB7? zEEGAOE{a8WY3SUL$sD8z;pd*2J+33t4FnpaJjOL)4W`0R4%RH7c+uQClx)XVD+Qdz z!5|N||!xdQBkqhTU3n&l`|@vTmOm00(n$)KKF^#P`i-P2PU=5WxY1v3dhAhwOK8 z3(!Da2!V(KU!9=HwOykl^@@F_cv`@@)>8sDSi|RGdDXeNuS1`W9fMg3$t(TX{*cWj z^@XbRXl)#W&+A_ZTQc0G!6=>0*1^(`!2$pjKP;e&Na~0lUX)A1h)N+S8M@}AkD1aS z^(43^4US&ZQNEH6hKRW~vSsA4G!&BafvWMYGE>t`RKQikG2~d3BdOi#7=!>)<_4%m;MZx~1BE7X4C@~9OQ?au zP1*(%qB{)=*Q5a?JOb}4$=R%42Z%4A9d5o1A!Kpx2Z4R8OR|M~bU)iP_-6-;?iDH1 zV{v%aqWYD>f<$t_XFGWF`3wRHzeu0RU=eD9E1Aw7Lj?CADA;MR7vltxb;F08BuxXh zQ?UE~!L3{CLUqgmI%scYreNGntlz4stB6e+|u`WR!R9`9r)10nbc~QoN z?!XCPNeHg($!U|zV>31Spqq!!ROb|{g|VdRA)a^v`Z`xuFQzg}jS5a@a{xU>H&^bZ zivd`4kUU~%cM_yZD=F|E>IjJD|^CWH%a z@rBpm%<@E{K~(M1ohLal_?#wMQukTDe*JzUbNMAp$-aLpya9tnWUXx^JoW&7D3Jwt zGl|V?tG3BgY<*A04f*LH%^Si@-7f$dPOq^^X zt&izIz0dJ}GpNTVHx0W_t*Bi46)PN28zxWw*|^xZ91Ls|5bI5Zt9RPC zA7jz{7#L@`IY_Z-!$occAd^m^7?y8m60FBqhbwE*?wbKH<=<4SRsD(~0E;8yPhq*m zdc7#42pWBD2=yNCi9KKpw}uOF74Sg=E3r6Z12ZW_z=`l&Uxr=NBTdK;B~a^?(qM%W zng(shA9zKW-9f_0V5Kyx7pZU&&g{T~B~EUy7=lf>V$fnK4r%L%R0cw(#}SX!qwA!Z z8Lu>w;pG_^L)KZ)P|4kLf1@U};TLS7%P`0RC`&THF22ttbH<%KCV~dDpsue+wW(~V zVX=}OIsv(&mg_gaDm+PSe%fttvn!BEx|l93UBn7`>oY*YSftLy8#qZBfQ86;lq4x4 zrA$vRZg0MLfRp1XJk)8j+bXLu6H2EWOrE`Z!X+=VhA!^^kpYoW5ICH|xcRfJWw=;4 zZRD}DAF4*#4r&d=YaE(DHduT@xk({D(Wru(Akr9Gh^vQg8WKXW9@T42v_VolG!6Op zU=|r=o0R`+zd#N+4S<11`Ljfi(%_+joC}Okz&suqDAN#@$nd5hvB~GFg{QQ&>5;X{ zgVNQX1z&tQ=>lqgz+HcD-w zHhCOv)?%~E&{b&Pv>0vgudYjOq-&oS%3kAqNZp`|;5=JiDcb8vs}3!IPl@6yN2N;)$K z1X>!ih>Skj2N^=87?G}qO8_>Pc#jVXfnUOu1`l;T<}+0&UP^nM#6U@O!zC8(f)pd| z3PhK7beEUae_#J@2Y4PXVd>FCjI#(shD-K}b}FQx;nLT8;~+<7Sh$`ue8P7_R9GTR z0&?z{DuOy#V#A67Nm3(w=q9$bH0=$Rj0dQ)yQBetX1Ij?(snH8IaorlIuaijUt#lk zD|fZ_VGGSLWAYsGaL!QqH)Wsg>rYd>VSftEt7mF`o~52v#$hc&80Z!wV=D{-gV0C@ zfVJ3*8I8JBy|M4hZ15?4ihp+MnuVXco>C{<&pkz@tKlo*Ew=~eeYC5CC8a2NOzUS< z3?Cn!dPB(Y*W#JKy`q4aE5oJF-8_*tvFTvxC@%HRrr{DxR*fYN_LU{>17kBID?lzr zCez^Al~ZphqcmE`N!y}D>@`}XdC&q4$reb;_{w0ZB;QA2NN1{DJ`4epBD z8)#9)vYEDA4IV7PJy3nY3q>kJVSyhsUaQ((c3v&aTXlm?BKJQ3pc`9Di!jSREwdXg zfZ-DOa{s`Y11uGlbqO)P*CKuZg}G@iYNg<_hus!dx`!kN9ADLWP=@P`PN6-Sxj0ij zBUBTpj#aox%7h{pd6rb|Qi@Nerxr+%W!OMQEfJBcYnl~v#%^@+ojt@bxb7FNxWZqk zg!{X>LUzebRS?fqPnTp?a;{`&0;UwZ(q}5bjZ{*`k)UOH#!vuKS;i`Fg_9V5OCPfn zMPab7$bpU)vhgU?V;ZM$ryHrdq-%tm(9)@9s7O_j^tgFtsW_s&8ZCVu%)A9X4P*1QKxq{|JRuj&HzB_MeEf>~wzi(Zl6lxMqboYa zlEZw4Pa}|*3_8|cH(lg`9kUa3m%LeTXc5;F_2be3b9F3P4P9VdK-C~K4R;7C4Kf5{Wn|OHB)>V%$Yb*}}L80ib!!KP{q*ab@9APiF( zke|T^rz%yyOYU0RTgT)t>mYAYiKJ$<>RYgIGC$X)acIMY z?>SD~ztXf2cqdF4EIrM1arRLT41J3#DhD?qv)of52iTITT~U1Rl}yy8xGpu8AJ>q; zIFjvm-Na(%qWbmk$P#}-^lELROY`O-+myHTbpm^JItCJ0ckU{mZi^Gl9Sc($Z=p_x zbt&LEu0*l8aG#Gs-QAs+83@QYup)EtU>f9<;c?Y!6W6t|s~A1FoE?MI)+3TqkjL`R zf85zn{1P?U za)dfB)k$h%$KZ@;@yw?b)&im|b9$<(dou7y{vmQ)B7EjvFV+6JQctkXZqiD8WL5!L zSNMCjg!7gq(GqqborMsiwjjGe6s0ND=&k$~n~FitJlsad3Tzb7)~Fw@Jum9#5(uY7 zy7%6;a+a{PfP*luP77Z*qYEs^5W{43YvFS0XyIGdq6=wEjuZW{7L*}zD{z@{;5*hh zmLR2Z!i^`$yQ;fp=>sQ1lNrGeDT~AHTT5o2Y0NK!GZ8p+!1Zef+Vd$*1{{bc+)iPE zF4?rYVmM=>)S37HCvutEysZ9`TyCt=0GEYahm*PTRb(0p)bD`hPyyJ`P(BA!nY|6N%k{EsF4jxn0 zdM|Ge&tL=c#YsREVHlnXB3-9CJOjrd-o+zpJPDggxFe^Tmx(X=4Y?72aONv6?;{?? zwRo+O&5=+$0$?&8NL$Fwv>m&OcC`qZFl|)aIHA=Qo$N>kD(%GctbKlKvcF@;5s*`Q z4bS-3@9aXR!trtjbAoh4>3t#BodM5FwL`>9 z3w|{D5@GAq8%m4*ky!F?ulxaD>h_g^7R2_pY0Jzj%@rYc4$lNFs^*>n%QjmHOVk$> zzNEd^;D&4l(j1x^MhHlRMk2Xz#ZEMp$QAq-XUY$i6Ewd-^l~(_h#-cyu^hx*=iq2% z&+uOMMV+>q+(wp7=>H9l2%xoO%MQb zQwc+^O|eTXDD^-&-Hc7y=Jfopyr`HMNir6;YfxxS%}vOs&y=W|HB-yD*XE3=#-VTr zFl8V^N#7lwDbXgO;zM98EX2U89Bt9-WSO!uk!K`65w%t|@&c>H!~tOTEeJFrhREF2 zSTKC5kT^G#N!9lzOcBC(42qQMGav^u^dq7w&d9KU)&aLk%Yro_Rq1r1Y@apBP%M2w zHl$rm6;E<&ks0`D!xo8yNvt)SL?@iz=aoi@FUYcpsWSVU1U*_MraF7D1_BMujHZ{9 z1GD7Zq_hQ1#;sOY5Fwsffoqx?o4rMx35Uw%1oiVe4P=r+->1ay4%9d4LZjxoTr>>3%VGdX-x;fDuF6&^f=1pjU3ZNVBEZ_MA|Jy zkI)NDgE4(OqGD9ACgyNe%;IV?Hx^{fWAv2xFAtg=p1G+sr!`dBZH2LHQ0n-M*$YDM z)-6j{q;7%;U0}|lcJ!oZY79$HLM~S?HGdMHcNTBpDrHJZ_wS=oD z)SlVcg7kNCWY2)W{igOs&lEm`dbx+Lus4mcN~TH^)^SqF?BZ2bo2vVz?&}ZkIm^u5 zkARWdD>mnW#Fdwz&gOHOJUo}RZVu=t=SDj`62IluHecN0z9}~Po@lgfrkJ+sdG53? zvXhpu3}DJf4tnZJ7Tk=i5eH|;6yHEZ{{pG-KIgI10+X{& zV{^G^>Dp!%J>$h*Zaw%K!-d(^bwbyB<_xFg78Z2d?|Kd5ZYJo+Y=m?O(^%-sS8~0Y z9NjcQRA{1CF?$r`gS!-OQc5t|O@uA0ttYRA=vOoWn6fpA;b+r2N4o|iH2`R1W4Hr0 zBpA$MWN9Q_O*_Imdk_4Xh~eIs(I3=C3^XrhudjAtq0eyC)+X({OlD#yGjzi7QO6Z_ z$kS(-sRzxbJTW-4H~vmmv`U#`s%EE&SQd_>2zNV^Ajkw1ngCi%H5v;R#0JQDMa9hc>`f1DeF<59a&KdsD;LnMEUmJdTWAWCOtEILImYmbMX>90 z&{5y$)f4+4xX>3FKv!6_W{}cULLAr}1tmx<2Vp$*@{Gp-br`-kAr!DiPsluDV&tud zUsij-8DJcWjseAF0X9L)Casc}#Oo6Z-On;I%#vx7UW7mOd+9|YkJx4pG>Wl0!AQ^v zuFGwQhg)rJdEm_h8D6nGvR@V%^wKg_JvPYX3DOyb1b(Bs2%jkq9^LM;2?iI4&90@O ztpjEd7%a8V6@mjJS$mAp~xlGWXEP5XPfOCbY0W zozQe_I*73xEvPnSKCw%DVpQDgXa8j^PXMGo%tzO42^t@%3vqFZL^%9?)dy$5`2m z8&vweXzKT(h;F|ZP1dU!9+fs;#Pz@a$AiNg0N_Vf{0{)|rjKb-RIWHo;LzUTVFaO< zCXN6p5G#RLldc`M5T6W30`8T**HB+xv?fK?RMKIx_QP5>(1s^PcvQc5`V96hp@3U1 zRR!ZTGG?!dHKNTaAS3GVsl$A)-*&BOlPu+MZd9| z!0aE|#DYg;%v-#J0a>&?LnI#`tjpnWK)(h&{p-W!2g0rhWsmzamYaB@uRH>N7~>VA z6c(}kZmYXwo2mT4>1i{1ZIg64cy+McSYJv%^UPq9fF8T8aBH|6hAt`0p|mn*NgI%C z1qFm)y^Pmc;wFy{C&WK1njybIWt3uVUs{Lh3P}8wCl8jf0};!j zAodd16no%1XDW^MKxVP@y?$#(FxouNp(^#mW%nb+Qa$!~`KkGqx@|S8208`EuWb#M zEka$|6$-VP!=}s+>dx__z|}SpYeiyFU?r?yoLh;~L9?-nkf;7aaYNIvO(}3_dgat# zmu9c*cqCDf^T6_@qf{L`124gl;fLP(G;h{fPUC@DwY)~yvWORK19u;8+?~BUzPOZ#t{6v?M<%4L=2m8mOzmee2Ij~yIPKX>^={ugy1X{U zTJ&552k) zz049_TYW?ziK2eNRmCE}DrLOqWhsMdGe23wlLv;sUfaW`BYJP{Cw;ErzZRJT%hSyK zyJa1|wp<6v&D|&(JEKk;u`LGUjp6N(m>6I@TK4(rF`TsxoT0!{;7l6hWT5#ym(n-y z$|7X*ZrWbR;$U%+b-Zn;)ZTO1=xUp6PA*E;Ho>LE18J|64)r;w1}nOw6qmtrF`5|z zHLKaO41zUj%8YBv;$p$Xs59sIYtj|~wXZIIeIT&=661Z^*DQXg&V`~Fk@c?qE87*R zX|#RJ=Ies0lD}5p1&6(+4e}MsoU$cIkoth^Znd8tA`##etZfl`b9e9ba{TEPy}%3O z$$4%HqW&&uQ?|X3>!G*zhLf_%oL(mLY#Y~CL=2g;XgN)0ih1R7UuiVUH6EzM|J3lGu(u_RXzXbgkYMu@p2MgxyY1{-?hD^2Qqv@_&u-cjUjwMN z=OII-*($(6tx~2prIPJD!3(N$gCUQ0jXFf!`SueThWN%eT!!0$HRcjlAn{ysGYDX+ZB0}QYxC+`)m((kTI%FvEiPo5 z>6G|#XS2CpmmMVtOeMiQxN{FVNAWL((VK5n`hpB@(7q`zJR4jGd zhI$)qvf(_@{@uwsQphjdlKK=Nz>1(OL#{qtzUj58?qfTOs2-ii?)2J?k=?GCvJW~5 z0>GhRxT-{o{`K3ax-cV)QoMe-HPSpYeB&F9;l}hpossHLb!%0Xwx(W{@lZnyPwH}c zV+sK6BAckL8eT8)nG6{)Dq*yp?|N{MgST0B3^oXJC`@ph3@*{8UgVJA;2A-L8=o3z z7W(Wa9jnb`vLpHyFvmK4K(p9*n>Q4b&2mlXs%@ZEy%gcgBhtv3OR-)|!+eo#CUp1O zEa$q{MhpOPTyC2iF1J^CnmA=L$hE$~;w*Xvw{toUW_re17g|FpajA89wpa^XdA_UQ zr?c;mB~}rQu77;(G>Udm8+_{(DNhFPyTh{xa*f_^0VKn-9EqQjp|Y#3XN$oUh&&qSCsC4RsNa2;7HaLrrjpFi5vsshQ_$|=@XHl6_9nSX$ zXWMua2)PnWIF6!tmooNkBLegvt%S|+Y#0F26Fqs39MZfV^B}qIEJ`)(b`SAU5!;&a z^weM2sk|w5mPiwu|CPbnP|5E{sTwKj?dxn(6t&4^c530!$mEDMl7y%YP{>JX43Bxt z({xvGpu|6~GI{&XNJ*Z1UQOZgYXJgXpoZru1yHtN02 zY-CDdG%&agtHD_$26ii;#;V9q2WMSnw$KylI-K(!sGXNHHU=rCgfi@!y^?%Q+7fd0 zBUuJ#ccw)#*C|x_)9iVI_!o*5Ir~fpgJ{uQXE``4vx4uCIgx}SkPB6u?1k0FJnL@M4`HwZ z!0-s!`47*QXsJ|oka0D6i|%ce{Ie*!9uv}N`L(gC`Fh=xWLi7P*`m`sDC;=hSnOrR z|DXRrdCl6>HGTC2LeeB)Kpc~IeRJ}nQIdyeZHKzrG-FElE!EvCa;do!b>h_fddJwz z*Ins!R)IW)z%)GTzf8cV#j+fX%fM57V)PO=#FP;1>^dip1{t1>-*h0rA64lE8s*t1 z%B7ZIW_6i72_e7kaOZtNge2rPn^@7#wBEM{FBTsW%2=gr+m|54Wkq4lu`$>sU*7i2hV{ zAc9mxyy%cmGP8(6RNztVDW=R`!y1}K+}pa>30xeU1uvzxNpFM>nV3Y+`t=fj(v0aj z8~DYWG3%YYP2+c}k^aQQ!20?WQ~d4mKGH_h6GsyC&e9ZXPm?Zl=W{!}r=xbNS*TcU zW5f>TXXJVj@~10CNI{u&QLgvp;Pe4$JYuPmB+09HE@Q5E$&nVKI6SM+3d|sYqB%-T ziDKsw2voLiTpjXfF?BYsc4MDRiBi`+7def_AI1jr{$9$ zWAWxTF)u@b!0K7+Q)cNysV!N? zlogut2h)eXc`c2HQ~-!0b`1_KY#U=UzEWSisdcf%-Z(sqgl82x8^<)DXcyQ;pm*6i z6E6_#a5r@)-*sXS&+^5rL1)^8!e^1FWeEI|b71b_qV6{O!SVI+mhxn#7Q^9IxxqO{ zt|I6{OeP1X{_^GvvA$3UHtffh?7O;>a)QZwF+y!M5`3;`k{dEqNRb3g&K>O?Fj0|S zfj8QZO4yxq&CBF7n2#}0`ufa#TUV7SA?Q2TJ;2hM8iW@(bb0-pl*Z{7=&9E}EJ+T- zbI1`9CD8^G4a7j6 zQ+JaxuGy;f+S=1~t_a^Xd4X2s1!RytvdIr+lw@tgb0(FiV(L_-%*>||vc>A)oF993 zE<1@xJY$2?DvBamJi_Nt{1m_K$qRb`*0ags@Epo%Xt2-)R&6(?pPM3Q0bAMK)WyL$ z(^=v9n>;f;_wzgVPW`2`!GImH>Z2*JgNOEDER*JzMWAt=B{wjg%Z=*jt>=)5gpcHL zh<`j(0xbLB7Q(eXujra94$amq^ol|v{|tz#N-kUPS}G&heE=^wb$6u4Dtt$#)=`J| z*(;>Pa~_Bn`;EFT4Yoo_tE;{-Qx!qV=4nm{W#T~j^NNrL2`I?R2tZWdZOqyZ4!*_! zy6%CvSCT$6GB67d)5lA@RCWMc%%sB>H`N`^eWy_RqS^Xj?4+xuTdILosw#NvGkJmos-!V`D;37*T9X#M zRpA*sFX88;WGP9(Tc41OeDDf41=5frPneksfSN#qn&U`4JlC(QU^k#;YezoQ$zPjQ zM$Z*>5E@wwBj@@RK+Kz5`-YD=ctF6{h!c4>*>c;+xyA!*qOdA#0y|O@3zY^L6$R|A z&nDBj7wo=*N?38!O>jyhdg8Et?V}n0t1v(#cfGf8Cl1(ZD9AUdy(13dTxLV8J+P~T z<7+lEG72~CZlWW*eGK@;4XulPlY&WV&}RY7(!l?I0?=z$GICU8|V2clSpyJ*SKdDv7IvCY^m93jzRj^3LDjc(r1a^Q>eo zg%4rZ;aK{76DlV+tf(i1)h*ME>ul6PGfmDwNhq&Iv;ZsSXLHE*>T9)`WwR7iOKLbr z1tDjakjV8TqNuqbv@?QqW%t4coh;u3&nM8y@_XB;rO_yjaP0;mqxnHkFF1#~RNbL` zQMy#;Yt?Vd2n3Cm0m2Kaaj9)ynmzlV-x^;lz4qIg$pxyUgif*oBPc&QryH3Fw3epg zB?YQC0Sv>D4RqOq=fTPHI7{VI{8k8Se-Bp^l0K-CB!wP^iGIR{Qilwz` z9@t0Dx#myp-RqxTzjluR#3z%N*@|M!iE`5J=RAk6oPase1_&)Qjz1&?b-bS*oZe~W zgQZo0?aUIR@$Eb7&erKmh0IZ}N+zvV2%#Ixm94PjJNHVsRkr%^>()N;*pybtylE?$ z3!=mZy3y{99OZP4o7ku9Sx4h{-a@O>Z}a5?ED6=#x{u3W7NEcu^K&}CFn0ubs_gn6 zh-zg38V!GVP64ZVFAf!43QdI?_57ZV+z0pL|IGi%K17JSGC=mWKQ$Y}@Lc*nJM{~Y z*DbHMI7NjmjG*0dMZX50cUnuZd8ajl%i)k_Z7*qpS7rJfoQq)cN7y8&+e*CN9??XM z@af|j#h%t*&uO*jA)K;8(L)?ADtyTZJ9r>Q`j6#^n&W164tlPyeZ;t3O`KM53K10X z1My9LZ_MjUbi%PCY_&n?P(;PSKx(g7FM;p@j|-N z;QXxKt&s2YEdl-@l<8IVmK-EvNy>DVqRifrfuHv=56&Y2I8-JbHPid~{N>NYUgUW_ z@5->qyOKmpGYTe}Wk2@%JdrEXNhp~qZt@6pNBJC_C!|SwC%F!UDf6DywPb=eWe@w) z$Ojgr7R@GmH1bR|0|OqJ#*`#nMl(u4?W<4v*s`Hc<GP0#Pw_3rh-`A}jJMs}g|9w|K?o?n~Sd&qv9vfb@H zIPb!i5f)=xrrr+E`(>o!rd;xidTTMO?F85G*(BR)=8Z*LB->m=O|!>}x|LshQVa{# z8GYXS+_CzG0Hrg^|L~*n{&Nyd9ZCuZ_T~hv(mXi-)JjnxaiP(~it$vRULWs1{gPn0 zEQ>%Dyr)+N=bxDd7t4_GfU3yj;dzBd>DW{Lu{x52^HK)^e7`3i!Oo)!)C`9@wCXe< zbQm7&i1Tn^Z0JI|b)-Fcuim9J55Wn=>Ovx@aZogWJiqyq*=A11q=(`-#DIpsim^>{ zQo%>LfioWAyj;7*DdFa`M-zIxyfqE$Z`jrP%_8&$_Sst|^->vuvsCrOUggEX`HiE) z$*iV+zL+o??HjP)H06RX*+t-MQ`4M8PfUpw0fS<=A)el$K0hmHDIqADIkmWQ9I#M8 zLW~`AG2j+0KEK&DLxj2LJTjrevhUpb!bdmj#o)Z$zF*|f#X)V&56Ay(Ha&}?GN%!k z<{BEH)ffZL<4r4uk`m1w^JY3oaeiHfxt{?Dl0N$O7JAD-E&G9#`*MqeH(PJ~7I0Iq zCMyKAMn|!G;cz*Rs5?6oNWsQ*M>jfg(k7iDZgA}%WM+B(ISZJ;~cyoDo;0_BVoAa!0qj7PHyGoDF8P$c@NmhqUC9gY$@-Kos3t z#t0Kotcf~Q4mlC1wxM(^E2#bZ1X>`4EycxfKpH8OTWEtT*-kn1zQOHDkXJ z6+nm(@zmlQgSR+r9OGW0fGA>16tT46;0SrAIdt7HOo>zy zTFh2;Zihe=kZ0(;6Y2e~4m&)LF-R2Cr0+sfYj2qkKIgKeXBMVyr!zzC`6O7(A=cpI zJGX9sF+7iGZ)RVVeJsEnG1@37<=U-Z`A`+v^P!mfJ=$ zmVnyx+ml@+wh>pc!PG!wxjtAMt?yH*Y ziRUGoBuLobZtk}=n;X|a#}b=0!O;FX4qlomiaethf>Mfc5XIjfN4YR;+ZSB$Q;f>) z_$4OA2o$_fw7nq{NA!=5jEhW(lnjtnGOAZy-n(j2s?{2zG=B<*_;=2$cr%Y*=F7tHO z$4I`%7o?hOXvo!c@`=x-)a;ksmV z?E@sE$s{%faoCJ+4Zs_6!?@eNxqC$1nLws(&)mj-d#I%|cTv9AHjcNZ^qd2M#~GX|Al@;=z%M?^f$dwtXAp| zp}S@=d}B_Ar`FLYE%JZ!eMt>FcW?2=`)Q{Ikq)F`vQ z+Y3?;cU5?+GvMF?ma7LFuPAk7!V(DS;xce+>Yy08g@iga7+jD(C|R!Pgn{q&-MDk9 z@$FvNRG@@kT#&aNk+MFxK$atyNH@dS-MQ>fdWaPsQ2f5JE|gPOIssY3>*0m3b+fg} z+l`hcx@zO>ZQXxb)Khtt`*b7g?_Wr)x{y9zRpBMr<9$G za}i(Yw0nr7#_@{wA?&OlB6&jRZJrk9vxh2H_c_`tJvUR~@IpF6QP33Rs@ztv2fEj) zi8XBR0)z-``3GD8(Uv9_)UmX)L6d|CE6ugsRqxcr+*GEe5d$@ z(izrf{!aEkzY8PVe2%%1tUm$*!Qa;JSR#9q&*od0qG6}vv)^3*u&9{DC&~V2&j)rv z@J`53wVm%0oO2(+qKbL{_5A8i9VM%?8zOp zRPm|O>f=Pv>4h4=%uFn5Ss2>(w*}7muD9nnb$oo;VB|erjw3p=->vO#?l7$@v_px@ zA78sZx=pqgx&!BH)w)=#72)-e6ZJP%MBdMi%A7+^Jcc>iacN@%e>j;Oh8Md-55vSp zUG^LYVRMIQ`7+MnLf?PoY8~@Q{jLO4OTnx2_k!+O0)qZN(329?9P}TmtBUP@CyRo} zEgo%nf%dN@;d|VLLxbo*yFXxT-5>Y`8KH%(c~+>&dvPaC>-QYOm$}mUb+lYxFQG@r1Dn#;?sx@l&Ga7DFE z5lS?@b{&drHQuX3w=F443WzeEN4@LGh-X?%<+{$FHQXQWmocuWZ(o+8o%fNhZV^0-e>I3^2(v@4QG}Pm{?vDD#GlYLlh)Ba-MCkee z4Hjn%+3+!4+bdb4;OL0os_>M=^7^O0e(X+*HcAh;vWUL$ZxDy(Jc@7hjr@L-CMQ_D z7VMQ(oHId)H_8JrzdqoNl*qptACg@6JZ$?KN-(?wxQ?)?i%smvaH0p2HlUj(d*5?k zG)BOS;rtfC_8W`hR^p`XdeGin#H@;Vyw_%-3#h3E!iMg=a3|Q>{aDBTL6K3{EMQKe zkqDUxz#P-b@M4I7Gcu7LNCv$2NmmH8H}v58N5?$4alQM1k2f0q9-x~QwZK73SOZ4D zRTIKJ6|E(G0TKongIUJnnP_~&&YWJJM}OnGr|b+bN;!36&=D&A0oc`-Hp@Yw|9%NG z!V>Sj1{Y@was+ptrPMiH6^DQ+D?`%+10QO55jNDhdnc-svJR09@jMj_MLq#AEdZpy zC0YLS)M>97IX+l)?!S4Y5|S#CcXK3xX~dJMyZfYL9B;lO_bBPXhp<;&N!~nhp;qQPev1@V22`t0Y^i`m&j$xddm5r+atW& z(E?2E3^Yrb*IlT5V{TH48Ne?YWgZ>nF~ z({y+V-Pt0h+jJ=OA3>rX7FglYHw90pkFQru0$Y+pcM8!BO-_mXaS;cs0ZSICj2#bB>3C}b6(jT zBeWMH8eaN(&(?ZJx7Rt;hZ$7oQ;5-|HISAWL_|wbGg*(BJc}M#0uu8{=~|xXOv7on zZ|N^3eua0GZo$o|X4BBx#(sMeD>ZaC_Y-H(#6!-J97Gej%Jxz#XWrz0;sSEB^29+p z;(?4^1%!a2wV>KPGO2Z~JIRoPOKqk;a3xbzU^u3TPGAH7!sDYB|md`rO= z5xh}iINmDa-FF^08&V!&AMut0Wu{rVfcKUGu?6{?@@1*!9yK42*}v7wMIB4y;4ShbbeUK!SFRYeuPBy3cx%J&F*M8I{XJ(sIbfACx-!_Q zA2s&BtZ#k@{lL5bR(+|l1&X*Z`9^X}8OVjL=B*MUA9SjD)C-ws!1}Qq&)?!vk&v9f zmfCQgM=}~>e?X;@>9l(~h2 zGKu41TUjeAf(_m(qSzOB@sRMIk25{g-!i-uCbnXNKWYS(f3&D{NgXqfWTiNoHjnz^ zNPPq|#QN8K$R3%ThKS@_&^#Tym5*ixnLs_zJe(X4$~76Yk4oOt?4xpbN36>xU$)9D zFvGXR4QE2IEy4ROyD<5ak0@Z#W3j`x)~3d|6k}or+LC6m|DsFVM zJ?$u`yd@<_w!$JmihP+#k9ak&qsxY!$b zvYG?TP+nik52s{ zi16C&C7tPSujKEoD}%TFRMH0Jf=yVV-kvuRKcsxme`V237E10$_gOto3od;-MHLed z6rU0Y77t63Td_{XvcB@CJO@K_DFdo`nqDUM%%k0#|&pt5#q{21s1I2RsuirHqImHzC^eP-8*tcl%7NKy5@`pm-kZb4LkPf~?$zU7&LQP>m|my{J8S5N)G$b}?` zfL)_I`YqVa`9FcS+@=D*;zE-CrBScQv%B#xujEI~XBigcZW8Am!?)$|!I-4& z=?4+Ys{O*YJ})h8QAs^gH%`%RWxcoVF7s@-5LW?%n^GC4GjK>L` z7yBe;IIGC^&dzjBv`h%n@4%}e`p>$|EFackohF!m975+iP!b_vlPYe5;0&A&n+c`T zTyC^yos95?VpxYo z8#RVzFoyMZE}y^}v~KX4t_u)JDRY+p7E$kt!kQjZghF6qNK$ zuFUUEq%gWwL?lo-&OB_SmFQ?`RdDL^<}(%^VFOYTorU?EK6Ieo+U=C(+1m)Ou?j9l zJ`vtAY(AX5u%~%A#kFf?RFpO>sv#PmZ?=iUVYC2wKRs6Psc#xDA?89<$uaLEVZr;fdj+tE6V#eP@=NfxDBZ{ zmZ2ww^M;3`N+$%Sz2i=f@atvfjS?s*Q}vF&QNwkg?(9#mee~f~Zq(t;#-Z^~_qkuV z@o5;T(ZxA)tOL9`UrdtCvOMg|N#aF@nPVk@-p-A~_CjIr zz~1mj`}OL@K<`?@@tZ)PJm0kN>j>iS9ySlVOs9xcOq+GOl_BqWGBDfoaQneKgo|xW z4z6~RApnl6$o|83B7o-hgs69A^i#`-x)c^GJhon1Y)v;H2s^Isqqv>7`JbT?iEgW*(Eru1(B&fF5!VWgUb=*p%Hbli_3=h z_e^;kTrM}Ora;D3rHN1ZZa)&*kZn4=jPC}CasE?A?l>@FD}C(!g*kIZSZlP z+AcSuS2AsZtjE1xKF(nAXoAV2eb*^?n*kYc)rw|~5EW13lNK?p&xQhYIh-O?ZAF~w zUNk!O@1~H@7pd51i8;pzOW;w4am^ih&b=#TDty=Q-j@o#_#f$*y!^fiHeCs%h$nOQ zN@7rC6UN9r46P&EcdL}rBnqzPtm@Myy|6sZsph}Ns`b>R41}LdGj|lW+;^MvH?V$j z;7=c$6374{KwsWaVP)Npp%O7 zzoW)~3@*>3q3oqsJ-A%>yXlN3+*FC9KAkGs`1q&9^>V@Sc#rTrd1%pPPyJB;91)Sa zH4Yq{mIh(Bquq!i1F~Q##>EK^c7mCwlG+e>On8HeI$X)byK08PPSDlmCQO$Y+7hPg zvc+XMF~&?8BN0*^wmAz7qulVo$f8n4_4g;nRM)Yk?7WP3LzZE6sc1;*FlU6Y%%IK$ zkf~=za>b#inF(@2>X0X($x3kntp1G zUO6yBuI&Y~(BK+fuOJ&-!!CxG*FC2p&7Ga6gJb7B-rRb|oQs8`xP7i>C=pL3>o+07 zCS9ksFR&tK;T_#6fA0WUv_aby-R<@n26+H3-O20Zf7&G%87Y6y2W)(K1=CRgl;RIC%74%|yBDGTf7kRbR# zTn?C8e)&K#gL2lk8UrU56{;GYv{>c`KR%9t8@*w0+cgt-)*gH{1`>R4SLJsGkc}cY z*=E6MoQ7-NCn!nBej6Yn09S7xuMpC;#DH-!xsB6Sp1YS7;ZSG13xIBaWbC*a@j`u2Oz3-#Tca0?rzaZ`~qeBH+{ zeelSjs;zB3K04SPF`vP^Si|P%oYO}W3l$l>drT%S@|Fyk!*}uL&dby-&u@?IQetkq zM&$Z#1Mhu1KhD3*P2&|7QRiQt6N;_EHOyaAgXZ3YIr;k9E$JFka{r4=7_=fS0W;6B z)rgkV=U$`c7~N|4?z{)Ag2WfQSv<#ova^lf4w}L3#r9W(OvH1y_qjvqc~b)>;d36< zvG54sA48E*BGlvAh^^V@Ei)5-mET6*5)u60gn$2)mqVc7u|l%GG3wg>2YgmrR{4wP z3JgEqlKO5T*$OpPf}|P#aGoXpG#n_Y`wOM*ZOWnm{B(7YTO0d_NF`~OnR)KvpBDK$ z1&5iR^RUCB4PyEu1!%_%w_~0c$nj9?qAj2r5!%!|muQ7x!KgL-f$uw8DCHskafixv z)%^Odi-XkqAXLfPI}-ZvU6ocJ-L9@F7yP4%!Y!m^K(SL!4aBAN)k+ve~9`rA>}74g1GWj^`w{?%_|4 zXC=|0PO|4x_BqsY;OSgeIq=rG{1fD;ve0=7MY9iXi3vWGHN*!$iO{N>6d@!!?||ZM zn<^ol1ShxJI1<`vKTJ|v-B2{nVMgzW<1QBV8q{GBqY;c$+keD36gFj=K`^Z$tC$}< z898klqswlopL16E~rl3qrvh0x+ znY^i+0qy=>M}wJ-azb6z=jadwytZQ;ae5aWLXU`kn@!}Ccj)LcaGlmr(K)Pn_woW! zpH%KPN8$NNVQ|j1?h;-E?tXzidO}>q3+B*0NGsCGks6Wx^8*FToj1C01 zazfnT-ut;tnuMd#UD}E3fnpL_fMqAHKTFy zi4}(^t2#1Q>&hN;v?|wb9%qjR$^T?}Zgo+{SLh*5#6L4^$--+J?3xYIZF_`_(&bFd zgLbpNuOJu4RV9D7qO?GL6ZYBkxVsYM@b6as>BH!&9$f>LBr0m&6=N6Gzh`>bU6@Ue z;Y#H_tv#t$6Fv1;;XJ=2g8thpq>{)h)^MM83{b0=@N59O(ggL+WpV8o-T^B%HwkQ7 zO25R))^B#+r=lvQ%{)&1h@%sW}j&1(`5r?v)lk1VN}Hz)cT= z3?+fz#y-UC_lg8|EQ}eBeQHo>V~AnuP1jSk8|7Y(f|Y_%iZB;4rFS+E>;@|*`RQa> z>aV3P#F5A5fpif#7Z}xu8@#|6IxzGdLVuhYT6KM$7SgeZ{mL;qVe-{gdZa35ko(cIUjJXRi(A3egvzX97JY8z=v_8XcBzn`+^%LhkqRD+Ux|nr{Q3*aspc- zxtOrv*!8s3z1J$z=6uQ?bNP9cOY7+{*3}DI3uTXd*^Lapk^va1n)(;O@3tQobPvz|ANBh`@cNN8;oB+G`{HG^S z+%P}?)If-o7`ETz@4n&+9l(BV5Ajid40@vo=0Eu;u&#{4<~V8Z67IkZp!ugq^3ia*2BC?;29y|$3z8rS&KLf~dY7vrwi1O|U7s37*Q_aJQI1)c(@i?h-hVw!nmN-svSV{z9eR!}3kxKcKs$@%>@%uu!HO$$XpWJw8aUs= z#tej+AZp)|xYx4+bbs1DcVHD_8>H6hs*NLH0v6;_C@zB5oh+EIbn>`}sb+r~mz_5s{Bg9CPKBP8)FW=zo*ZpIBQ(|tY};vum?w?Y#CuyXhg|)v z5n^9hRrL>6OrrH4E(*-qr&%j?j70o2(KJR=KUisgMXQ#`pnvf` zHzFjRn(3@4h>=?Zo~lBa+aWRa3&xwpqzVmXZOyxM;?k>%!_EX}JM|7Ythc&{J1ODt zXYcFAhqP`VLz;h<Otj3;E44m8X7bcu3qkOdqufrz8hk*D ztOaSrpwfFYmhvF1Ag3@fO{R|~&$*Pd>2-`@;_tE8wX<)q_D@~4D&Pyqa%ddYyrfBq zMP{rX5$ym@%9-=eu}^E~pU}gV_`cH5?Su>$nRsJ@&CL14{mvSFO7r4TeqM;=_5?1< zZjOmI)fJy+#ra~gt3bhk`!p{SXmCWzC-Eez6p|!i-WSUoB?5(BHhZ5^O0SicqHyA8 zrPqvwuxj8R2&~s0Jf;`X7_TLj?P)i1WiRrh?UnmA8~-tL+Cs+}>2ju52PW(dJ4c$2 z@zqqD-pp7X0#L>}j$n?rzT*n5>Gh94zV@5J-}v4mY`{1>(ShqW6N@o?Ot(q`pk2oF z=0s}zO{FI@yl@tt8en$a5S1Pu${{AV7@JHHzWl2@0No-7^mZz|=P8=&E0 zz^NaZ@4QQUz9ZGLM|+yl!jy>^Ih#?>++^u6HHd>L?D2#4M|XRD`9dQTD;*#_p8EKe zav8dS0Aa^gdJ_F{V6kpaG%{+YVxAacp&A@kPb&5q2ER#i7JyX6OB+LIsfhDtH2Y|= zZDj}OR`;V7-qdA&1O#VV6ze%8r1@wat!}SL7jch_&=&Xz)AtH*Q@C5M>&PA0`Gvi z@}GrSuY)(Ur?;b>;NG9R1QDEW*x4*t`dI{60!*gW&vxrT@A2InO?spKZKZErid4J{ zSg1j*zdadedH)9~SXSxhtm@@y<(M$-3ha6&6}dwqD`84a+S< z&uH51{ATz=&iqd{KO>v2e%M+wBES8i^*RY_DXW4S3Y`r#B>Hu&cpqe}!)pG)c!i!c zqpX+_8*QyQx14QnpIh;`Io}j|w)ti!yr|6YL>gO2cC5qaf!=QRO%KO%$B_|>Ro0;= z$nc$tpvo}3f3UNyGW`|~16*~q!5|bSXEkXU9k|lDX>h9u66i5+U)0YA^5P)TGqjUf z2cTZ|yETj!!aX0JLyIwni_5j{GiUa}ib%!2l^?&icJGd7Q)Vo>!D;AWc_wo_>w~|Y zM@FH5eqWgw2VZ#ks)gq+zO{CMI={*syZ6*J>+P^Ho%^*<*rmcQogVPrAl}Gelf8Rb z1~j=D5?%XI8Ok!Yj_s#1WUprk(6!R-B-_BT`-iZ7wF=zK@3nAmtV7=|7&k*XVt0I> zF$0YDxwrftQtGy@1EC@r*A(uV1eN+Y@Mrxf9Q(ccQAPH|e!qCl{0f5nV!o>L9!F<> zr-X#zFOH@7c?0XW8@os2$EQwbl<>Rmx$n{Qe0pW@i<9abD3LPw&p?YQH2fst_7^SH zuhRAYOpT{sRJNqUYl&o+F7!J3wndlf!RMe)>ZrZ+40-ElrVO>6?22hdY*4u>8()Kq z=Fp$tQR;>ZlvcM_L@Ca?sMA7i4sC`7(9sCx9u5TLP!A5pw9xF-A^fVBgCrdOt-x3!~=Iv6K_ZndDiedfY)4eeR zu@w#%BfkFJjqG%HDSw%FO(0gRMC@PM%xph(&I$@2QGmJBX&@oc3p8YHkpp(VqOWbx zv7X)cobk+H+bmwbS7qQb;gAe=sF8?6AakhSiy)IHSaP4=+_e&R59Y?2^!Brx+;nuDuC#cD5r2FxMU>KbE4*c0HD) z%#-E&YHl<>(^ET|;Fp9o&<&7N2QWSz9H zwIGU3fI$-LPu3j*4PDkqDmKp3XZ>)9>hL$+2D+5>fw=$ z+e5PBDZ*^u4(@c2cmAFM4sfZCmBjYU04(@d6B8+mf)V*bB#$`@#$5>j|DM?1&5^8P$4(TuVEs%kqW)(@%sYntmX=h7&V-y~}azB-^58JpI0P5?Fwg;^N;5ZvqBL3tR7(LgWP zVIw=Qu+}g-2%$R!JS}$3$PK(}&h~nju>P{Yah-{@g4FB+J6%O*&Btj%Wu0>spZ%C6 zwM6~)#{bVWj-i)xh)T0S?Q>@upl^DHn0$B6-QCF7S{6Dx4W|)v>B=v~Z}Y}(-4Aa8 z9!;Bwk)RU3)51n~8g?k$L}MoDTd-A|b03;hNC+ru1)teDpFmrht?N!BFnxVIe(uF; zY#Nmq`ZCgMH^DKdKQH$VL+moyON#iE*@q-U$&@izib6<+R+l6XnJ^w%cZ+tr6o+E!XH(Y>8H`=Peif4og^TKDfdvi>=m* zHBx`lbGt;S6`#C0eWU;yYP}r2IQ1rJsdf06_lvfznF(Xh;7t8kQ)$-n9!@Pk=r>Jc z-m?#`41p7YtHdyB#f!8%gp}aQ7QPb<4Z}qZdliBrV(gD|AqL$61Gw)9CAjFw%Wxac3*qOmGB57|X z-nV35)op{e6?*lV^w?wJ0CPA(Gn3u%o(}NuR=C<_<(q5QKdm?C zyrBH3n2q41vn%v3R<^G2Ij?uON6f~C@Kp+8UA1~Gg>B|-f>{#cI%q?EG;hSt;tVZI zNEN(mc$-<}arD^4zF!sAF14~7c4|V@cN=>awE7Qr=fV|3LWH*bYV5xZ@MpGM?J(h}W$ zR4G8RlewH0Ij45IX;o?_(_pm3?o|DKxsnoXGCj2G%wAHYHz=Ccy8GKJ|Jm$|NXxc_ zK#dv8Imgr^7$?%M+3qJ2f!XdSQi1t9^Kd1@3A{#4iL{A*fBNEZ%8h8FzYjY#nI65C zgqhCHR987?#SKWYL%x}_8`*TX6sg(n{f&GL;pj}pznWvZp2=BxN)wYAoj_-j4mA22 z{rj^ynbOSm@60GaQAo|`1cb6LwZ=Z1e_3u1=B>A>3DouW+Db@_3*-qO5}+3%+)rFa zgAp~2tu*EP<8#K}lS!e{y>a-C59E7m6D(h|-Wl>l{~6wwAWyQbw-uHnq(-Wj!xG8 z!|77Zqf-R`d-U&=)IVuIo5}bjeg56^>P&xDf}7bNP5ye#iLXcOQknX@kZs||ua#J4 z#_x+|4f_)OT&?)kg@VbD77R{BSw1xtH!s_OQxpGwR9GdQtLDVP3y%)N$G?P*^ z50*Nwgpt1$zCNtPSSyfFp~Te8(Ww(EhKvsz<4)S!tZvV-zS9r;`_!3~V7GIp0?YU? zXc=KFNWbGPBGBy%30#K(Yw^}%#U0`>3X{> zV%*EDses}_MDs?E$?N=FYH~Hwn53_xi%p%i&l7~2ZwPif{X?qn`4oC@1o5tJhggN7 z^~^f-4bkOd7mC-z9+74$&b+5}zK)*vX4P4Tf+^C|`GKY#@>r*%*QYXr&ywU@c&PV1^#cP$ub#bbAs7=-}J4hVj%*0+R z3lC;qX+SO2!L|wDdd*tqQLSrE;Tt2Ai9C&Ay!cGx55B?Tg z=FECtFXfzC>fR|ip8nMJ+EVynR%$u5giG^atV`Y=j1M;XC*HxU*=cShol{HIJLn0~ z@lJI;dUNy6V0I5$x)Q+IHi4engQ~(6?6zLVX~r}A)&ZUQQq{~m-$Uk^d8hv!N82iH z#Cpmqgrwg?CgD3h80~y$F7=q1+xL)UX5Q(3X0BxNnz_v-AlJX2d%m3U?qu8Gpu2DL zLRSNZf*D?~3}i-LoGTDfBI$ZRpDH|Srh@_#v*BHjd1uB&{aSrkd+o37WZ3NYdZ)7o z-$UY>J)hT;-r0A$fbhL&@Ar_qZp^^-_aN9edTjA~`6_QzNa%_ZT_2K(1y0OC)f?Xr zOqEDyp(MH!YB0N|*As2MG}o(JFkqhj?}m$6hj`YuZbk{jZ^nBbNN?8#*ndpDx1f3M zO5sbUQGTzNh#o=_v6oJyKl2G{v*o5pbpmx$0`D|x%V!|sdywH9l|Q7IXC)15xDI2_*>$NN9Q>U{Fdxl%NPF z0tOX0X$DX@E0H2mP=lfdu>@3zh!92Poqcxao_+S&CwIy3|DGS&yUXo-cgoK0v$H!( z-L{&%@JZW$=WlMFAKu?w$q%>O)<3_;^~5z#+A=%RdLT19 zes;9PvsrC@dUM{Xv`c7t(lo$A#hDXO!tYgwut32=EnyJAqZeuL$dU&4^Fiw3nUFv~ zEp2XcY8*sw?}I76F;iGQoKZ{Pi&I^ZFD4CtBDrl9-Z{<6r+eLVscLygg0?1C>rWpp zoo&!%KUh{n+hBsg^g;Te8aTlM&ra0Sv&Sj^nBA65i1@J@trN3FFZ#>=(NIO$WXo@5 zqFUB|2{Q?R(+)`E>1h6BukZ%rp_b&(SX+5#S2_ZtMVTg;V22u#bht{Z1?T3Cw?_G% zWI_wY696q}UV`C};yE_8#DoLw^qwNvylN}IHuupa4^0%Rd7n|l9*A-glNV~$gtZUB z6X>c|o}UuXq(*w@PHfFpyHb!nS88Zu$NN8<@fvmbv$X37npFi4zpU4$pXr!WR@rw8}7-)kkKm-7?1g2`6 z;v(p&mrnKI5Hl>ZLDB<=0Ku{T#M#Ye$4>3krWwy5)TvcHXk>}AP^;e7UY4YxXIqaJ z?S+x4G(n?kJQWhSGTd4)DE_hd8JKp1B}$V2S}*8cJue*HMc&9e$jF)C;g7;d6I5-; z+$8z{FgYO+l14-i)ZzyH<8b$Qvih&}2*^cRR4}gQam5+G1f{pvJ&MWa@rfZ^r|s(Zh&c${WF?6G7l*IP7eOeNz0HMQE+j*I~EU7Em;Yh2PMC zp4M8~z53fPBTH)t^ftIe*z86vp@gxuq|w}xPq~tJ@3a;|g$4FVdED~q0EQDb-{nt3 z#{G`tNk`p=jI!1DX3_^vINl9zR#PBT3JABOFnLFvMSBl*Loyg|@LBipT%#RLy~Qx> z$^42_9**j@81EZKp=4Bz0rT;5{tYI-g1+XZ${XCNWTlqa+5E1n=x&`X)x%ab@R}Z# z@poeS@v>t1M#-<&aExZ5-x5md$ zucOp%Q}iYm0pQNU(*?7J@tVTXGT5;j2rjGgjdb>5k|nCx|H=v-LuJD*POq?pNz5WE zuL=S)>=`X(W$(|u>K;hE2ks#X}k1Zj8CRb@00rZjjSWzQ>`rLgbtteaNb zyIjkbb-gX|hwCna>k-adaYHfe!BZ?B@Y-HOvK(=hX;B5fsfn@)ns*loH&VJ}!~Y_j z-KTu}H?B}?gY|mvJOeJ{N{x>LnJb=aypr?k(8AYum7Q4Wx>r{wbd%U{JE$;K(PpzO z`>S^px2lf4(_8ZWF2iEy!dwXYs^)@8SKZv`)%JP}g&sZ~9zD2MXB(X4nE_WJC(lfr z+~N@}3dWx>K<*sfyUEKtPQc;~y#q8^yC^Bd$k_N}-{FQJH(RZ#})|vA?DUljtjiyc!U! zeGcPwre&lb^{(I#1_ksH4pzr!`{Jysn)W1uve`+=KA3y4E8M=VluStHBUJfQ% z3jXEx56!$95A{v`KW|Pj3G;*hqKdY+RP}3s{t7@PzV!F}tJMcX{R%SwMIgU~v4LdE z=OybuVcxT!tMD&?{_~avlJ1R5_Fv=9AA49;zk0n860_WQ{cp3@yr8Oo_fNrO)Q=S!=j6h2rMZQI{$O2Zw}7_M7@Fw10H~dHK_l>(4kl@_DF#w_LyGcCeo{=K29T zwDvA*UbTyr0s=xaCI5f6X)uY{uUHywne>Dn0f6W8P)w_-3k1W664rJZ0;(vca zFo}AMkb&PC^(XtEoYqejtNhOgw}VJwe_dKwPsVTiK!dkc_`M2(NO61p*H-oCJ+^Y1 zN`9VSgNW;8Grs-}Q{=hg3-5ydf@S^XLj7n3zFhy=FE=$*>HjqFU+mI0Rrx_A+z<^D?XKY9N{;7^&0T84(!!0{93&l8^m`RxcKg-n&Rk#S|J@Hhn5*(XF9UvbM{|AT8znQXX5(OJzp4Mc4fv6reb*m&^>k|$ z|4Y9D`Pt0%WjS_xX;T-K|8CeWgru}K*VjE7yELM8tg zsGqHtK|0<)XxbDBohxB$4?nQ{KbbJQq_O%a4^Z- z5=a*0lw7|_!$Va6rul2&*B~kIUvhm}e+LJ8=Bo79rZxDFsR6{Z+lVjAf5ODED^>Ep z>j=z$Qv%8Le~tY|#?QESigNs~H5&N;EPyng!4R>Y+<$78+oK%6pZ*1&Un&r?YiP;! zA8*tsM%Dl3wt@az!(3nH-;ufOIPh9t#B|6MPD{ka3l{;nnKzwz$EXI1!rL;d_Ugq%n>+P}>I@uTezs_Ks%2kS?N14y|v zV|}z^05;f>P?D*X-r z7y4hHK(ftYtWUb>>&M1$g|wcng)8to%-{e^xIXLSZw&-s1)E0mjrB2XU^->Pg9qB` zImSwc(!79LeN!k~`<l#R%9yI55u;A{!c;wlh%&|y2&ACJvQN8+7?%>jX6Ze z%lf-C@xiSs{hf~m|98@i5AxSydEOwV;w&*NylWvoV@^FD!R7T8)%ZqQv6dnN(5*@Q zj2VfrqY^HZrCa7pxdjf|UzYmby)b30uWyOzCI^3bcnZ@^`wCojD_h_SH^|8SzvJCI z%o%3|>UA1n1=7Wu(lbbL!7^k2os75`%}-F5%rtN%hcSL>QWzCGx`5&;$>;!@W) zTTsuVN=OHrJi3?M16dfggf3_%;0-rHW7sYcW2crki*z@|$V+KN-B~AwJ$G>3SXyig ze|wQvi)AH%d(l7(nj0x?3-o?iMgn?Abf`LFsfGfFZi-X*G5OB6WVnL?as@z+Tz(rv z?2N=X?Ept-TZ$o78tfLY*(Zr!sXZ7ruP3I=h}W_z4oaR3$rE9N^+RlzbbJXvsTWj5 z*jb&LJQ;4lg$-Ml+pE35fY|Kp_?aoQ=hY)r4$?LeqxEU0gG;bypy0Jz-*L|0bLR*1CkJ8wK+O+@)X&15P zf54X*5)PL%z38Ez_e25N^v%wRX^*z&wxoYKKRGELzJ{N(EI%ej*k4NF;(}_^+wjuh z1Wvs2TD*G9!06q1cx7HP9Bh~;Y~3fc6_Qzbwdm!{XlSyV>mf}wymJo5kg#=tT7~kC zSlWvJalq+ewX?_nF{@{(>_Tl@JuM7FvoJamqL!&)XkWsKi8=9Uupx~71-e;Jy`$0^ zxM74_hIeO`b=EMAhHT>qtmUHgYXt3C@(AkPs-iQ!3GCk*6zHWhw%AAq`N8t_L%TdJLqn^|ak${EjF0HK*&1K+eipesDcL;} zRqg554EAHS(Ay)&nNHvEZ>Fi}Y@HlJGEWB(_kuSx zzRm$%`oi@gkM@a>9A4fPI^%p`Xy|?XBgCfJKEGTyTVE?!|GM@k=LfH9CCZib)!mmk zOV9>u&6&#mOSLN-oT)&^=+^lds(B3E88V;D{D}UoZIOpF;O1rV=7Lv6zS22gs}mVt zF&h|PnV%T>a`1%=J1;jqmD@<9lfmh%Tg2&PF*=2(jdTdFU(DMx?unttL^?T~&I!H_ zAG49sDb6#}aq@*(2w7>b6|FuwD$>dA#`JaWDsRsVj85oB5*^k}ND416eZRiFNT-m~ zdHYvR=S4=xA=BafIC;6L#+J`TIw>7kd%AzX>1<+jqTiF+Bhjh9CH}CAj_U_b=Osob zT%tp`Tnf3oZ~pMcYLSkUw`b7noX%!OCtc#p!`tI62V74R=@f8%wXRZ5`(?})MkiOY zAFPl4tL4VmzYytQ|GJjN+v8$%@;)@mN4CRuhqts6>7X4x=HYZ+W^_U&JCy0zGTJRx z(W$eM)7i@C#GEp=2l>MO^+@rcbde7BuSId3&MS;g=#)6eP?loNGFTy>%gm= z&NfDeNOaH-VcDjceTK@<|F@a@KR)ir>)x_oy&N|DKb2o?&=SU-TtcGPu<=W#?!#o9XGeb{bN`r(1vNl`GOIie!G{wLf@! z_A)vN?;H8Tc3`=1@Y!UM4z|a2jnmo3=y)XgV0|pNF0A8H(IF=|o&AhXu@5@o=axLI zqSF=W9AI?pC)9jl|2mY>b+$+c``6ctd3z3WI-eTppqz31`Y3R{LGS1{D!stzyv67g zSm>Sb*XJMZ{zhyM+OspB)5&3U@+Ey?KgaT|*Y>Xz>7YI5yus-lVsuEZkuTH}`qe+@ zRa+?1LBHBzGow>*n9+&!LFeGQ=M3W)(#cxR=^Wwmv7m$P`mo%2<#@3;o6~ul(TO@~ z3qcK zgned|b0IOlR(#m=MqogIcixNkJOSw(XLKCrjC5puz0}cRXbU2)$V@4-R;tSh@es#+1mPa~nLIGUpm%If(JtPeuNWPd)E*~q2bOC#yn9=0PZ6IVUc&Z#&FDBKzk&6!y!qFx z)+#!yxAXQ~V06Nyd7X!_7xvSfkU>9*bg-X>Z{T#kVRYOU&tFLA$%xkt;}_ByvXayJ zmeDDc=pa8>h8{jyD7FXXQ~xrj^BtpO^Witz1axdE(!ur=q5TvvI-@M;c$k=o=e;SH zL^`PV@cpbk1(z6|B552%ez2U?^6?i%I_RH&UdQSD!02SZYxIY*JwN_=d&BdWqbu`2 zpMS{d{K)8dBzwkoVEK6Nt_Q{Tpq%@0y%+q%=ww>R2lYPWkK77A%!Ox6N zhBSU5Us#@wm~5Co3u1dvK0&Lvd@eIOITrmZov_z) zE%v-7(kbTs^f8pr6-FmZ8c#jEK9;|;OzM4JIbPg+o74H7 z(TR}!yv$d(_jVinGxBx%eNN{(qvMd~8#0}To+IQ*eW|r@%*l-{Yfwchd>>}!q5B_#aW-GsiZ<_Y+mTWi1$gTB&vzqro#Hy7Mw?QvN=U!dQp{>Jh# zB46mA5AWdexy9(@_!z%-{qs?Riq5Y{rQ8q zaXJ6PMMxR ziIK)H(vQb+yov01PFa4jH(cM78lRR%cdKb>Xdoy|e+j8g(`Y6?*vW-qVG|*qWwz9W zqU7*Bi&XL8a%o~$QF;taie0f7ejHq2Oz*EW?nhu@armyacW+fdRLN0h@6HvU;|2ll z{Mx_bn^J#M9KOtg0#YnhlcroP4_;Zdryx~Ui|TKwKDwJ`ZhY)?ntP~M?BoQN9!*S# zC5HDQifKtoGbhuI2rX}n$|``=K#N@z-gqictn1eeN&_ufgpCI+CibFtT1*7W(9b5) zu1GW7Y3)K)3r0!?TM;WUC#h!WstwbYxz zhO5>yHarkQY_LCqyGif_~Lyh6dH zAQIX?h}_{X{2uAP7g>kyD=_8Rxf2mWGP<)oFCx8HFX*%=Nts^nn*VlE(JO-ZRaoEB z(~JN8`yDEJ^+*UwC0wQUA&BX87-{D*o&udc}ey3NN@q>z9`<@}h)vfgW-m1Ro zs)}B{M?y%kAM{YKXfLb&m@y6P#dHq(5y&Ishz=lhKMl1()MFIvi$Pma>9LcN zAg_yUejup@d3i+nUHY2YpXb`$#Ix~k@BSfd-$z%s4^-Ln=;|TF!Sl3;^w6Fim1`4M z(^?pQM{?xa`Wi2(&W%-zhW$uOS>6^EJ$9|3-ysWrU*0vTQwbNAh4W_q?6r=C*LI}UkxvKO#CHmdev zA4WZ(y+o#te^tfrB*=^7T3<3foAZ8?J_3Gt>2Z~QKdb?H)@B8ggHzP@LKfC0w%N5! z_S~*uZWon3-=KMe!dTuN6~CkbocM6t%=DU{eNjd4fe~OYmCW?kL0%=49WCW^sb8$j zx~%dCU3P#yKWL_h_7W3Ok9h8_OW1A@)CM7!uRj@~I%j-1820s5Fw?{SX6sgu6zs5> z^zr=AF3VKE=B2klzg1b@ z4spB;l*UV$-b43wNm9{s1HH%wrKcD7*7XZ2dXAHDF8}`0(+lr@cLf!_dO1L^Y3b<= zx$8nP&@+u6>4zY1TXm$Tk001S9KVDT&u;-HeY8FHSh|W{tD2C<5c1%qIMx2eGuTEv zL1udylr!@imAyQA1@dyeWlhiau#MP)&Gu4x?x6wDKGXclvlDvy&;T-fR0#Mao!=nX zhnzBB_c1u{Lc6(DuaR;-{sYhp8y-Nu8Cp7eEl*avpyD_6E|@?2K@Z!79_!+ilMyO? zRD--K5yO19Po~%4!C~J5JyV{RD9BTiQwDld<~`p*)xP!(Lx^VrA>*>t_F|h5L7b09 zn8uHa1ClrNY-`Q--vgfH%M52adv3v{T}INOwKQ- zYTu_G$h#BA@}{WzhqGQoVvA{DlHYIn)qYdSFM0*&H{P0_1L%=LGrg7NzH6tVcO3HC zyI#}+^emYx4@9n!Gk6j7$Vl3z#8FAU8qIY*4m_K*7ZeLy#);{vE)gmfg zkk^)8^@Dh0$9tDOh4t7bV};}8$S0QPe!2fcRr_kYA@5iT{Cb-EY@d%CDcCx%@kg+n zT_V5j+cJ)|94?FiT^fgXZEV^-m9R?Pw>NxjOEVm_Z);nGd}7&g#I{2!eiL9l!VUY? z&|WYOjrJn1?;^dfCmR2uqBjxt_1R8X(+m5S#lMgamWTT-%~8>72K$Cal|(Prxc-dv z{@s%Knu^{UXkTUt^r91YDf>snpoXhd^m^|LA-N^c%dlu)uYjyuDtcq!d77NGmLHxk z#Q8Xu9hcoKg1F=TDLfBxKF>pc5%T!jJD_$6NyvYVdj?~Ha>H`&jqquz_SIboc^OOS zzm9U*jPS$sMrgPjpoMm{R_vcF!%FE6bdD!Oke+l+1`EpA7L+ne!}x$9O=#q*1-}|$ z?El`vXe*Cpyn9aT$?SY@@|>i&5vhrA6I?3m)Z(#U@CnhrLR>UBHKJE^4~R%XKv?)h z52^Eyy&(IA_wtF-w2@~I(N7O*ZDbMKKB=j_;Qn?vSUpq{W8&GMaH`Whv`O%IdXUc6aN$CbcQ=`=>4u*Mc{lG(EmT~jX)DGYe|YrOodB#{tr5& zmnNj7OHLXLSJC|MoqV`1Pf11I^c_=YBu|Q+(I+V`B^hjUaBNcS)c90(v9P8cDas83 z9j+aE=K_$-+pBr#&Mo18Ka&iM2cn!HEBcmWg5GQlicuzw)q4Sd5i$TXu8sCrGGPoTq zI}zoC3u^Sufaj+BGHpAxZ?L_m|A2MN!FoP{{CwVCKGl))9pHQx=Ql^|?Y#l*HRW;G zbO7isgmqAU4wl|up?VI*=RD*e%by-Pyi+BI$b5LtYiunC`JM)BC(@1jEbbYIzubrU z8Bh*QpNI8onpa^7o7W|9Ibb|U&a)uPH}v|3vG81Pl5Zc#AD(x2Ac=mG(G5G#&=<~^Q9ej`MfZSl)XwC4AY8D%n*r;SXb)&-SYOUhEz4osgAKc@2aQ#KHV4-W>FWDL4)clUUrcn;}d<%Np z1$lJ1-dx*B6$1_m$sH{h7TPqnpn6@h&(9>z=y(ZKm6Gnp?VX-e(LD}yBcQ!mk1)DUA9Uq@u`y?VJ5|4E z29~xqy5^EATQUhsPq}7OC-9}fNqY0ZaH30 zrW+;E{eAW$_fonsO^p3*9ndXO&@FF4*Cx?Dxnt-Jl^p&&1nXiiST8vZVO( zohe{vrt=eHTR^?d*5il^ti{Ds*u8}0OUzEh`zh+|%m*DoX8q2CP;Qqg_S!Q_W@9lxsS z<^kR4Bs1L)&ZO2<(G4GLq?=_yH|&QX66G+{C9i+5UPbq!)ZU^J=!W(*)9o~W)eRNh zF^i4ujrvV3hs9OdIEQk@GPp*ya24ImWk$L#3%YaQe!s{>h_O7XKf!sQHrX>_X>t;K zms(g=c!U$^N(&D3{6`D6JkU2WenwmxdqQTtu7>5^+|y1Va#Jm?VT#CBpCf2IP> z&t&RvgL@h2jVKGugVjFZ@S2P`_z&hc5rOLA%r zxTKi)slkG-ol#(UgZXVzBL#4E(%G=~%<@J-lz zkgAo<8mttAVO3LW9bIFF?BCkjleQ=}N4snqLn_T|#?Os${n)a_-sM@1nzrJmI@RL+ z13lUz#CWY`tO{j7o>+~L)_i(|3sal7u^9t45abwHs)&T*$e5QiFg)mHVVqs#D_!r@=y|WlrzW zR&CbLeYJwD*C@``oD#GeR%vMqCMTvOK+t0jq`-$S+v0Cwu(KrXm7m5G8yr=pq5nm; z4NKD8HsDkjm96&}BLCXh_ZWGN6I2GYdW@Ao^zU&>P@1`bjb`Szrp-DRy#qczwZ(8q z|ISv(#ZK8Ic2Z&szINV5>Wx5qoZdd8OA@CFz%29>f0x}geS(bxb@l7!+-0+1{#|{P zbYJf3iSQgUO0Q$P#r(hi4SOfwr;g(aj)y;Yx@QSIH<->%WxWsUD`VI>r$88Ov7Wrn zhR>;_lASoFwUpt>{%@D8RJH$6$UhY}R{wc{pY7Lcuy^lg^vYAw-&GgRDU8>D?I`w7 zK6(xIu4%p7%~kYoH-_g+Sf|IA%YwdXy&fy@^1aEM=zYp2{oWn|=l&+*EC+u4m%9CO zeqo6`2|d0oT1DS67uHid>%We%pdTE`R+3QvdJXpO&EjG7J~mVPe_I3lWIE};_V`I( zmnf@y;frd2K>JPiRS$0h>r+p$b5Npv;=V=#=d_$PY7n$f2R*k1=c44-Q{!TaRq`1E z_klZ~)8+5{TP=V2zHyoUtS#GHs_4ISFYG(psM9YfBmFn8jLuilZ}B7SGkjL3@3>vI z_75EN%{dkQC6NCsJyWOe@{>N=5&ECv_usrv<$u;6hkZB~*tsfEza8ORM#@rs{k7m{ zm@C3OR9h#5b6fIjOzZcQ@?QaQtHQ0iwZ;6SmXCZNyG*~&wZ-*S^2vthl+d<1eUAnG z`X86vzaGt5TT4ZME9`r6et(Ue+?xzxQ~9#BkZ|| z>X*K-9cVubYHd*7=bCmN{7(~W`kpJHq(DJmmkfJ1YxMj#RPz5P49*?Exfgu7{!`0e zj{E5r!D>#ax#(S>Z}M*=;M`AGOKiU$f5`pKxR1F`&0s^^3+00Cn!3MYSMblKb59@8 zIA}vN{pt6BJ_qRi>s9!iA$&%{gAJ?lV!F|7;k-EGP z7t8qW6@OK=|1pT`hWFFkUtrPxsi)X;Gul1U#j?@1$498>Ux#yd(E@!(fLcDj=x<5N zIiaHeJhVSUpzkUp{SK#w(0%Bp`9m0-OYsQwNnqL9zj@CaJyi7fmV@zKu%8$U`tp6& zvj1$>Gks&-^ctX_jf4^eM_8EBJkJYT6FA9a{ z3tKt==wm;?azXRadtiQI+6VqTtjC5egZ^SJ_gj&3E6Zb+Sw zR!_&;RQm0C8}^~3=)ZH_rI!EQNj(2`wA_)06+{rK0~U$fp4A z%f?rX1${?9*6&cS_(WKt_R|IdMJC*GR%;Woh3cqCWG`&Uahc^yPqyE`6{=Qldo{#Dg z;$A_=UwwUVMStUX`_hZX&)9C1Q{&xFz777zloy~k+!N-hPYAtlN~E84C5VJi2qL!W zm5Jx}eWdsd#Krpr5f^-R!e`V2;w%hba18vXX?^mp?_mFJLu>kugv!KmL#Iy?D-#=h zmgO_?)K{@8`J}==8s|eL(4PYI{?O?=;WL5H*lsLyLWVtOrQd8pzqp?!f(zE;H0qaJ zVERS*U^%+qs?DnLr6B(i??KNngeN$ZXloaRA3e+%mnLy`vZ<8xO&ZI7NbND})H(l3pMpahJP3Fg$3ghu~Ge7&1R#Z~q6w%*b({Vh0;w+vB=RXv3 z>(QzqJttwZx7K%H{vz-bQN=%g0#}0lz`Ct$2j^~o|B?!)4eSTA|Dp4f=_k(6K``&YAV3pP?oP(QT-u9=CQ|u?sHmFDUmC5}4)NL=#YiN?&C!c|R-qdko?)Oh_p&g-K zZ!^yES2p%h;T$W1d2X?elj|o=CfGp)?1Pc{Nj~yVH5JZd{b0NtO30UE*}8!J0X07u z55|7lsS4OZS2NBRBi^NPVUyh2tOkG3BY;d9xKo=~WLe-~+!JvIcY^hX_GX-(H~OAa z;hcRF=63=PsjB8j#(4wQNy3JkaiX95d8rELC%|#{()mg76X*7L@FSDWI1ApsmZriP z1Lv;_1)MxTasGn#r3^FUM1AZ0P=#Zg1LMyiou9~R{>d#A;%KUUgKe65TB&ecfD?L@ zklqW}xZtwD!TWg84srn}J=x69mrr!0=budWb_DFrA>f3DtND>}@HtrSKN~u>nWMs~ zKMCwWz)A5F$7($Nqo`F270z#+!C#*YAkEU5-104O-iCe1^o4T6{g*O7#}90rslwS4 z0sWwB0LkSzj_PW;jrzoh^E;fQ%8fPaXK#ZKA5`HS0i5E_I!?BqIC~(^iVElG`sK=b zRpw)`9@<6639I2BKV1W%-z_ln;~tx}LB-G8FGE~Xz)ANL=OXNr2wP&td2e1|2Nlly zu)iZp&`*J%IFsOcDr%7#XV0P-nt##Me~yEGqC4qwi+a#Mxm}_8eHG*Ot&ak==S_Lu z>jC|Q3pj2+adI92Kf21y&&%~2DD5B*a1sRlgxB&37%a8KW8z%iYl&FKdEaT?Fhit8m)p`YN|ow#1> zX;+naF6(()(Jy@5{owB^e(dwX@4$YC`xY{OqHC$;hWj0`{Z{+Q&sCfitHQZB4E(5o zljA3jm4EBJA~{!u^CraK)9VM22?y9b#Kxb`@%ai%JSU9&Sj~F}ZTo4r3MU@+ACNBt z$fY|>ZW$IhY4mr3zb=MxE(+r2s242Tk$=vpaB_ZyeJ$I#u|QE|frGz5esI48(#LXi zR*3R>;Y)~{XSWU{AzK+gqw1*b0ORI}V>QmDHcGgx;wN(h#5dl8`vLL%lm!mW^GRQb z)Bf8alC{t*xAT{p|ER)w<2202TL+N8>#})ogiX!Q({ouI0&!@*HQNd^&WBN<%5gg# z@^ps65x2~>3@6h9$M&-kCltol^ucDFKX&cxD+_z^ETSa?_cfx z0oFI~i;?z^c5e;y%Gb^3p3#1O-ETZ+j`}Beni1E(%}jQ^dUenBDt>Mp2LF~6NG4@7 zd&{k>*3Wg=M6gR!$+E!tvZB$hI{=RA`R79SyT_?;PC)!UTfiX?sriv{3gP)j^<46N zl_!D~~`t0P@lf{)hSNJPRC}2UoNM%&Uub ziDky_dFxbi3x#vmDI;{8$oguz$vD$szlrMkry#LUBNfi3PhdW=Opo8XEO0PBjDF|q zd%<5R&S(8z?tYrT*ff75OJN-;ose_YnA}1esQHPTX|%T$V_^SMoLN5|9t`_Ih12B> z^i#N^5ph!d#EIAl^H{}maBPhqe^cQ^0}h$5=f0$no|} zZjOd(xs8N%Fwx#{{)Tpj<;&&9hN*B8;GAaY3lJy2#&EJNaOin|5eM@Kpk0J&eK*5!z>mdwDi*|vik~qf zSvxmnO3DV=pZIC063<()Q*GEkvF!KEvZ1PY<)7c-$$!?-98DNMLA>8#iRW^=jsibD zCx`_1ffCk7NrJ8)bF2x^IsGruCPo9|O#;&Y=`ka7#xF}GO?99LZzv3oC}B=SEnKIa zrlUu?Sf)EYQ5^hmycV}Jo-`DY%+hPZkG}mc(qlA0dWpK8jM7tP24jq}2G35M8Q)?A z{6kM@!qGdPRIw*Z9NX3=pK`Q@@`_D3ebSKjQtLjE|` zqf(OLjN80^sj(>u4@1&KjYr`}kYr8^+)6(K3C^^{q6!}tpO!r1F-=Co@mTMvOK3R# zRa{aUoDQ6lI8_rRb`LnaC>c&kaB3-z9nYwhBuDW#k|fbjU>VmvXp_qSCGLjjy~p+V zsouW}=b`u#>}g3b&%bVcJm@JEUVWH{Wc;AViHa=nFfNIB zFT;AEV{8zq(*Wv2iG1OF;-R#GbeuQspV6z zJl6qU-1g_yzO)h}R9y7iB#ekL_RLk`5m*P!|5(SfwPO6q1Y|s14|l!* zSYs=i@Hw4#_alKz|-|wS3{-omXp~>*P4C~|G zS8FwY6i<{V;y4%FLmad2G4a>`_i8jxj%mK*0{%Qg93zF}AzxU^{2`vzbHlmbl|EJB zjaUQv6V|Z{{KP|fTH)<`AUj`$=LY_w1^%MjsQZHze{CRdOLn@s{~Z`p`)?IqJn&c0 zQI9)#{KR`R0M7NmddyjfTd3j>1?7IKtioHn7yQG+f#f7#*R;1)^M`pZZQQVO{$%F~ zY5XQj5m)JYrNzH0yx)evbH$^9q!RZpE(<(7pNn{lL5^CU5Adt1d>_r1ETs9uO!nCb z&Wk!1>G6oLc541G9)WoDyrgGw5a|hdIdhhp^>=e*xkwdW(hcBmosQ@96E73|HC^XA z2m1;LtP9{cgk`|Wga0*BEUu&>$)jHdA9b5NO;SCB0Jjlz2@s~UcJdD5CINx;t zBt2h=>#xWc%CpryBc=hKX?%Yj?&-6wX7~Py-7M^_)ZLbcEV?j!#Lq{ z41AVf6H}VDQTgko|bbsycz~m{{m-EBo_!rX?@cNta-pm~Ep9=5xI`9)4bUa(6 ze|R|lxqv@c)B~pRp>pF(%KmrP2-qhB=eaQ6l*#dMT)-0JO*YPW)DNIP*xx)A=1t1} z{?2<7Rrb;i&hJIS`7XpG9o6D@2Q<5R91O$q%U+kxee(^f7}>2Ev4L9(|I@c5Xqlw#tZuWweM7T zb~x`BwM>sE6j|V5JOS~@?|=vPIRx@R7b@bWlRSHr^ZD<8fq2=II$lgywLE3K*I{1> z^)FZZK->(*L9`PrH`m(bQSo;Q@UjHFJU{Vn0}hQd{W}`uqwr_8>qnI5f2t0II1rqF z!Opb>wz!Kw7XrJ-bKyT0=R)L&V@u+*Nj#J_#9D{k*S#a4`Sbrxx9)UPm4&Zq* z5zp8Btl@-B@2U7}3+I%g>l3oC2E$9Sz@za4`a(QB&xGfgv_A^}v^~&`-eYDuAKU6X z7^gG!9~N*t{Tu!c?o$-UhbI7^`c1SSlB}Oc5pt#3dd^6mJbifL{P>8*^opy_Hdwcd zpB(|KX5yE_=gh>l_QrSwrL%2hDr6edzmE_We__2Y#cFvFBMtsvJ|QRFY-?*`O46wz z`Ws51+0xSDQ(<|sg!lrFDzM)fv$!?3X;B4h9-E}WRTVShr_4y4nlQUXztrS8DX_vx z6Ml)`PmY~I?;2~(mwdG~P+U?Ml(Yz!)PcuYR#MfDzR=4r;#;u8F_2-6r!K=>bv(fx zTZ5$;?`FrR(~N^OeVn+a%~xMF7E6L;(x#fAgj)1wm+myPX}W>DZ?NW{7CUK1ycSXd zY0~eLQ)Z{N7_QyA!G);FMYM^MAjRKl6-$>vO$u!Qg?5-c(NeG`$p0I*OU0!G*@qqx zi-)VJN+)Rzl9AF97HSLc+{&%87YhBu+-c}-So*idE`l}-7VBN0hZTA6C1owBfzZpv zTJ+cM+3Kvlr(gD%J)8X@F@?Tme@IK6EZjua1AgZHUiv+7Ia}`}-Y8O&DKp@HsTK)v zj1DsRatW3uZJ;-Wu#ys>&e2hg5hcnbWo%Gl8cXmgeZgZPY4g&0C&td;VI^+>Bo4j< zrwsQ*fw?N8OU(b{xQx&H6IZ8Rf$^()G~dtV;`i3w4e<&`qW-*L@5kl?_zjj7AwEH0 z_*~HWGdAAgx(Y+ppGOe)EwXsE3ioH&FE9!oDbiQ7d2+S|ZYVqli@5vevful{{h@!~ zcU8D2AAskNkO1$wG+UIKUyPR^zt7B9hRrpOob% z?h72(v!CbV=Y(bbj*4BgRK;)a_h7z#M~@GM_5a`am2qqJsc=e#n@i7C3Fpf){KOsm zgj&urZs^$u@2GIUg}mw+6Hxk44p8%p=b2Ey6%+XWOeZUm0^(v>IBVf_iYwp$xS;~g zo1~wkO7|1@+8M@g#xT}SE8LoMrdCwp7WaUAHpl6>MSkKo;_J`h{P&1!<8RQe7fu`D zq_`xLwKJRhjlGaZbkr~%H({WEa`wE#=tS3M=hP7w{S1EIW$&b|-(^bsPuoX@kf{Fn zE7&LOC+_QGxxbR~(V$*KImwTI9ZB~cnfzoY0?$o-blg#c{NuOn0RQ~tnql|R{WK=r zVSwxDt>fnXALF(daOVpZ?rpGVyTEVM;Qx(Zv?r8vr%rKOG`r%gp`U#0EX0=w==^&8 z#GR4E?{%Tmo+7!~XFb^#jB8>@xai8F$|D<#hj-33t-N zA;dWlTMO}DKXG4+V1BAt!j-{%kh=2TM@pEDF_{*Mdbv|Yd znY%xq-J^Yp_o%gx2Yv_ZzjOJC>v@#%o5%MtA_cT3EZ4Ms&C?R(jQ6*pUBx{P zd5;HSEjTw2?H|84IBwCcZF*&RhjPZU`{cXmJ?p0UTfrRIFE8vT$mFyEVjgCc^L9Re4wvqy4&}PW^5~lBIV!tyKs-4|h$qJkSKAfFVG;L*SF$yP&{jtM zVmr~)E{$LO4_)_?$Nh8rK+cd?8PC<_`-yv3=aR>Lw5xmOef)z;zaPB<{dc{N8$E*Y zE9+P0ciTs>{yZj#+^P!k-USdthtH9)&Mx<(p|^jg=k847!WF>HSgYgaa$J-bmNM?w z=a`%^u8ne)ao1&xeL#i#XLVSQ7Ub-B#6SIpulEl(&ly9{;h6aS_X~I)%+UGG@e_B> zZHAk-(`Z*RzcqL78?M4#2Kl;+SLnF*NB!e>_?!Omn_IL@Ip1&ru4|=^o9!p=&wlFn znhQtpCcm z*l$C*fnT>hzJub*^PKJb;atKRo!_ug{_#6*1=FuQ&p}))HwIRv=Rd2<=b9^j3331D zb=(X;adDl&7Q@mDd2Nl)Wr&C6jYHom z^ZisA3UL~t|E6Z0C8R3M_Ej!TulmLOxF6xc@B62Z!yB=5HLlOi9@Gk%*hi zaWlc5Gq2*PL&&JHYJO$hiJ!B6RP?uz-$;&!Wze9GG*5(=-^|WT&OdE~e)O}Bo98EP z;x>kBizyj*;|EzZZ;=VN_&DJHs^dnD^N-&*-($FL2{)AUi{;g)JD*m~uO`8MFV9+i zzn8}X7x#NbaJo7Cxh#}!<`7R|+99ZBUx9RV7w!S9o7Z1a}Zae5~^$e%~JTwe@Ft zp0leBtX~PZg?{2L#5hiE)=ubLmaQ@u^{i? z(Y{i$#?bv&-f@t$XX9^M;3KA?zMnLDvYKDqPl~v=-_O?CkvEOyS=BzkKPX=;r@XN+ z18`0Ax8LUSff7NF9!QBasR9%&Od&K zRc6mAdAE(vp~yFupJfFr@0BP@fPIR=dVZB03tY^vf^tsSz~mgw=XZ#M@$ur| z;9Ys!QtTJAp8~sTpyP&3^^f1J+@3$n+y;=c0?(^ug?Mt)`7f36M)QQ6h%Y}mIOrsI+X z|M>0A=g)W_h84f}R)0G}g}V&)rQ6|Nq>!zw{po(<;<}2Ai}+a9e)RY;&7P%x)QR3l z6Qbi5`H74Ajh<@sSF)TpKIw@Be(#g@n+*HZ3tI(}OrA&HmCxv4f1v(?J{_YUy2oyu zU%Y(LI3F2>jPkO3YjOfT-W#^+ybAC?_= z&lyGKERXw7_J(`Sn+1|HF)R)>YML4s@BNA3d^F(moFaZs57~6^H(1V}*jkJK;@=~? zu<^Hu?#~x+^ZdlE<6``VKVak+^^0ZI(I@|E1pFc{jtfuJgm_sso!_YG{_%Stm*F}l zvJ&Z{e6j4g{TD5+AMtrzMc~~ z!#{poE@gbm_uL?#Sf2WIoHicG{GMwE@qLHhO1A~>NXSz~UlE*Z?_RP$R_+y`d#KMJ^}dEL{H4=ruPdGvL};9jmdGcT)0_0`ui|$Qc_LKB{R0f=n!t)@R7PxpG1aa+rJaRNOj)TZ2mPLc-S69h7Z!tWF3g=Kl zlNrCVoMl}3915P(!YjS7oIkncGAd`}KeQ9`SM}lkqio2d)#MH4x1AgpEe%V&KMVQA zd5-f<s%BIl8fNz7g>{=yz5CSrN>> zk4{zdTYZetKcC_Jj=INaSI8%p5W8rj>c44_mn|h-KR1)haby647Pwp5hiIH2zX9Rw_ZfGLep1GLebvsRD%>Xk zH>{S9YoD#=SH|tOit#&&x6>Xjgb{uru607uq|Bd=BR%vlZtDyFSvl2OSsW z`PDGE4=!xEE}XE()cp2JHS%k=hrfgvSF@dj>VE4xo z@9B%+gz>pszBiCrfsWp5`8DnSZh8OYrQ6^qpVog@V1aug-DuC%a6Y+4-G7l{x$EzD zrG5j~3GunRV{OP&DBzBor?x8@x8kyFjkII78W-(({*eM2*D%HD67pdFoUG^L%(KA7 ze4HrfG>iBGu6HBu$WAZPJW$^GB+lzj0j}qE0117GwLfaUn%}JJ%!48Baf^L2=pPX` zxN1|Hchbb~#cyDp{~sOKQ%YQUzlzLn&A;DQ?nheiB3R%wxcBWa<2Q1Fn%}`;Mt^mf z&vPQ&M*YgTpG+A;^VFK;{5;$nNTw6A<0k7zZVTM@gN*hZ$j=QGe`&-;Ib-?fccHy0 zt~@Th3;rsi0a`sgS1(lai|2MxzgExPMLH?%U7be`Y4Ma|Za>(M_H+Qh(JK({6l8LC zS>U>Yk=GO{0da-eS zT1+MK! zqu*%yAd^qnc_XgP$S!%{_sQv%z@FuKogL1X(J9@kD)0}yiY;(!B^u>?k@w$>%d8&4 z+3^i8lj>YNLve{TpX>#=bW1zpraYmRvlVWEgc~K{{<1RrVTv0g>Gx5}g zMqV-UYm;z)Dzv|+l5+ysRpur_j)t@PF-|qV4<{MrjP{%<;d?}KlY9$Y`M&Q#d>vR`pOkU0K78U!6>i;kAq!quoeuQPsS%)u){TJ7fzOa`guG7T3e&txA=2yl={mSb| zxL$_ks;hwkA}+3*HEvaoBnY@UrNouj%|f|7VcBl?Jmr4=XNJJKcPo88$Nr?6U#s;T zSDbNNKs+o*cHZ%0OX$Dy^U;tdAtYD8&Hf*8$zv>UbYuM@Pa$K%|G%^r^0-hqV7In! z1lh`i0rrpR$&!eA3sswlnkIc}TP?#C;l`<8u${ zxM9mmhnw#*jz_ZJI6J*sKUM!d0qYE&?fN*FVSy`;gI4`l#@%<{g|Ae&-ByE~1%E}B ztNAUfzsejv`U@5A_)j1{DB!05ALD-aa_?3u+^81iNQNNiA`9HI$~k-3cWYI+%bhTP zJ_Gm7@Oe(cQ))TOe$q<6WUf`V1aGzoEmH+c;*2S;F{y->`oqs3(!|c~g%sKIt$>Yr zyIFP-Ee8s`1tRp~VaRGdYfikD#i5OsuL6>&(5xzukVgA6LFy(sw+`^VK(}*9 zACf#Lb#i?F-aONgtsX__G_Kyn)Wo=P_3CxD^-i8VXJ&lT>@-O4JggHJN?|e*|z-oVI4gbyZ-zGR24UHqrBPdj53JGt95BQISBNSN6jE>G+&7 zCjjD(kpCC+s8@h|j5H7Mahi8-9GZp?i$eZDT`;zhH@e?2O1G^q*Kw>u4 zCt>h>N%MVq;Ior{<^-{<_wBT=RPw(E&K;)<_nA6YspXINrlR~?LcYu5*+Hc4{jh!& z344FOfqkY>TAinz|NfxnD*Sc(;W<_~Z|SkX$8(Q}{{@_DbHaJc-=T~e9YiWY9$Pn* zjiC&O@8wtPuIb}c@?Q$)0!G343w$|NtMyO!SBv_`{o4hRRpB1c2S^^|YmZI>+>UVH zB7DaAFw$-B*pm#;mw`Ah#`U3dfFF~|^6v)24sO&J(su$q*Y8!l`FB0=xd1-ne(?hM zOs-cUvCkUwy&)Yen>`w_S0(?yhC@8;146ny&E~0&HER8zg8k(5h4McH`p@VPM4kh^ z)4YUTVV?%gKimt-DCmdsYps3fMy33BK>of4y8JyHU#?I0{fhGU_P+u3h~rvaz5l`I z82Bu|x^FxDs|r8=V_3gwtm8W})%ut5@f^9Ue?39~58LB`&o%}Az5~nORN==y2>E-P z==dH#@zFj=7vQ&HU9z|;%twWMf2en~!}5!ozXSR=<$u0468bOPpH27u(EqUBKR1p0 z_2NL!;&}nQKbw5tl*H_5>diYH1D_r68F5h$4bSd44EA3^wtweh$a^q7kkI`2a#9HvCq$Z33=k-GvZ=d{X&uQ{_+&qZxANLNj(<$ z7$-%18YiXs#W7A=u^L_P4I&r54^rN@7d(FRCo2ArKs-F*ydI}@Jgeqk#&?6i3x#`2 z*8;zhF_1?Z_8rjtosZa<9FT7;$1U5wMTOs{AFL;?g*+%cPVBM3cfjxH3;F*M;>Hd* zXMYs-O%%iV(KDdOtckE+4BBHGZ1z8ap(EZ<^}pVYAfFQC55<>by}JL?{Gp=%LHl%t zw<69;tw`7pAP?|+9{B8{pE*G+JAXZ4H{3Vnjfdp(bCz4v*t#L&yE#7YOvEyquiMJ| zcwXn!*_8y_U9P?h>Io0sckKc^103TCE|Gm#LMLj zd3bsCM1#d5ei%P*@*-b1MSQmfegMYz`2J%~mULU5t-VcunXS(v|JV*J@0p!&UBpNE z@7ZLOzx{bN|5oyE%j2w(4UO_gTr9WFU%E<#{~@ejh%a{;@jZ=7#*e&vu}y^^^RyA) zzM*XVr!+C*qy3>i8b{q6DB|OKRqkkp@72ErKH8rg??n5<^=_0m+FuSAZu>hKi>nZ@n0bEAIdf5cU#~i|9P()_ZOo5 zd$zE3+enTFsTs6aIxp{kweBntKc^eRKY7rIZ-23D{71ZEwEq;|ju>8^Kh<`hh#$lG zkNLrf@3z4A#lQVs7MJky&!+(CynKD??srA}e9r&BZX>>ZQ`z`Wk@!bD#B%hQXC4so zJ$(G1bl8aRw!laJM{V2ACCUoazdelYYeIjU!GDG2C(RR%i1-Oy{uP!P@$D~_jsF}U z{9oKrdxeOP{4f95i0`(*NB+~-s`($~G1?#Ujpdz?o}pVBg0`wIJ8F8=|R0S&glA>!wA z|Np*Ze|A^d_|LT9AKMeME#(&jKG**$KL0}byDjjM|7>pOGXE%-P>F93|9s?^lZO6} z^Y6+djPkd?TsHpmCH^BgF6zJD_lv&~`A7W+yk*39Ti_%A$R{W7)xV3!Em7X`{AbGM zU%HFB|f$xid^nb{IE;o=IUjDfHsc%L8asD6tyEOmb zRyO|K68|=ii)E835c*=V#sw*|g0{v+;V?MD7_{)^@M(~DC?{7mluw@UMG z`}VT&Uo7#D?cib{(|iB-yNHkL-}jD@__x6K@-IFAqyNX}KeV?D1m@+h;ZHrG!k=_U z(*KUK@t?QD*#D7#EK}p`dqsR)f2ap}wZ)g)0^e%=0oQ-Ro3Qym@{hP!4*984h6;bs zG$X$KRW<*<@N?@M=bwm+W&Ws*hW>~Azs={LCk#s8vyTRu|p-+_-mh;Pp> z8~?VQ+cgqa_?wD{Kdr(KgMEJD%UwqNtk1TUi2w5gG3QkHg_8X3JIltu=j)RB5A>|~ zO@)8|GZO!$#K-kFU;00EtoaNT{uA8)q7Lk@m5zVJ&wH(8{_mYXtfC6P%|PP@XLlL# zWBw_*|NWZ~sKoCe*`NLOvhg2L-{^mAT%g$hzg%@S&Ox#w)j{>zA;^%GnFKzx)tmcP9C(jXQ8sj~my zRW|;kzBcL~=YLpU_+`#y5g+qSO_TLsM*O@tjQk@m^8el3YZpX(9DmaJ{L`!d-DTq+ zpG#2w5t9CwpXf7Ah5z;XYi6VX!&ujWCpa1cn6Z@XB@t;tc z<^4zg5f{rvXL?T;@eBF$?|rcEo4&lyzZUp7|C94y;QSBso1?yQ-iu|OjGAXfd^hJm zi`zfq+udsZeXak8ziOQSA>UYrR&Ux|#K-x+TYCO{Oxa+jsF;lf9!u)Zf#I`xQLI>zrn8<@!b~q$iM9tlQZL9=Ra~d^FOHnT>b+r zTR1OX6Y+8V=cugzy=CJ+TjC%4zm2ye>t^=_B0lPW+%<`R3w-1s`IPw&t7+{2QGDGG z&p%B2B-<(C7jpZLf5(V#-&Z#NizNP0?^s5~KHNvdNBzgj@ed1p!YzMOuHd?=Ktwk=e%nk9=b}?b<@a_=EiK`@krFw*|g0{vCnaHIuO7|F;H} zm#Fw(n`y+iA1E9DP9OZoS4#R^#7F*rlliy6_r-riaLN2TmppD4@lpR(o|E`LST_E1 zE%?Xr@N&x)qeOgM|N5TK|8V?qTj2ZR-)jFw4tErT5ARGD@p1jDWh;sQx5~zU*iNJU zqyIzucYa^-hKP^)PvXyiUj8lceeoahEc1V8|LFfP{=Ky6g&HEhldr!$_Nc^vPTBY$ zCGn4Zqn}YzLM#4`iGW@$va1kH>$JAGZa*)%qK*KV%gf*MHFd5I^$kO3L-0xoaiT2VntxyR z7wyCTrU#^NG~n~`zix_A{%#9=EBizFlYQ#(5B2fZiANfV_&EQ*e~MB5_V?8M`;tHA zMV95C!}~+Ilxdwse4KyZ1NW~P^lyRhOa57s{B0Z;+tYtcl?oz0_Wv1t{N+C<_V?BN z`;veD0pt3wjK6<=3&Z{+#9t%fyUU0l#_y3tearX{^?zTv{=Zkkw|`JJ{-b>0H?^%c z#Q%~13w-{M@^_aJ-{}K?eTO=8Rr)VlZtQ>d56i}X4$otQ@<+diRQTC^{^jMrjQGCxKXrS*C`5%H^_0Z_sj~4OdDX~2 z+MkUx_T|S7M~nF3eE(hhCye&zw!laGPe0G}jPjE0AMvpNWBjLX67jMBotEw20^e8v3;ode{DX4Ga=;r?l;{7Rd0w*rGiv^Q z;ggNV{YPm3IR1@(s>tB~aQq8cC+Xh;AN6lF{)Hbg&i~NrZ~t7)zZE{t|Losv*GPnNLWqmywgnG$Q{nG_QsTdq_{e|g{F3n_zn^P3 z|AhW$5w|}t|6i1je=q*`#_<>XJ(dsl40}c7AN&8Y7a9NPf87@NzU)6|LdpGqNk*DS z#K-lIYEzB)_Ak}^`x^i9_89$d1Q#gs|IgudhW&@gf3fWUE%1HuZ}$;@8FKx&A^wfy z|Nmp|OyHub-v56<(9twe%P>=KrZw)9OJQYBsfC(3wo;ajDTcW~f{Cd$l@*yKEhgC_ zE!MP{sF|cK(~jmsWl83OrA4+;SyGw(pF8LIaPK+ZD+Brcz5dfHj&o+_p7;5j=j_`R zdih^gxA-R)sqsg=;l9(lld}F5@$aFxe_X<^DgMQqr2Qkmq1=btwDdcr|BLirr?-E; zs9XGlTKo;I9Jr*cv9kUL?f=e;Rr@P)2_Nwfu8{FWentOBU;pjla=(hdI6JLv{a8I{q%$QMZe68=Jj z-DTgz^|Qwx?f+K-YX0->s9XF?YKZ^U$1hddzli@FZTz9gC49uc?8Can|DrV;mGTeq zuh7STcGfNaNy`s!{{wFxKFY2?;@@e#s(+D7_=ta=OZ-#M3rABL>7U2x4!8Kce5L;l z`~T*7HGE%r-Qu67#b3Aovp#66>_0{P@6qdjm+%pPZ%N(K|NOI8DEqIG{z+GB@!wUq z_!nyNN4|%9=F}HkIHiAwJQ+SGmnd=x->v_F_BYxENPmP2_n}sul=dg|e~tA=_`a{4 z<6l$wdi{fN;ojc&Ott;R{lDkuYVogS_~?Jt6#xE1K1g-a|5?5N^L6dwUmgCM#Y+A| zyy1Gn-fXAvU*Yl(`WMwPe7*id{)2mG^KzyAiS}1SYk&B5JI5dS5A_Uq(f+KwKplT9 z;V-})c5dtEl=$=b%SNsJQREVSP5rNm8uH)iL$6$I4g-RsSNF@N0^HM2kQ2J>tLk%5RJ9=@0vF^@19{ zuj26W4~=l1f2(Qz^S4btQ}j>e^uLzJ|Ekm9CH$J=?|H@9{*e!^eK0{;{}|!&=fpxS z{@)!w{%+-8(nad{E9@U`%RN^s=g(pP;U`-Ev&bdKK0MFnKN}^hdnmR!l5<(H=h9 zf3x0H^Plf0=lIvu{_}mYI2vQ5cL~QI?y%t(erOLL<8N29{?+BbOZYX}zjvit{(}SV zps&tKQo?8Zzx@N%{(L_>$KTEVk^Y{oGXBut%khW)i~n4Bj6Hnlf8t72|00+0p?~0& z!`HtChnvddznK4j?RC!*d-xdt?-^3V_f09iCOgFLDVV z@ef`r^EpSedjEeuuZux=dHjVCyHor_AGOCHt;TO4tUsL>(!fO9hxBq! zm+)(fe{k#JkI5 z*Z&hgz3DW2{GtDb2etVB?i_#UkA6OzcXj!L{kI-1-y#1Ed8&tU{s`(n?7jyW{`n9XFho8*t z&vtFq@QYl+uPOdjF7XG?{%O0L+rvlt*DFxN_f;J}{zgOjIY+D7{-KL*{}KLT=+B&e z_V6+O{u8(VtJ{Ar;nx&@f3a%+NPonCSi@Gz`Adj@Pd)yB9zOn|I>!I|Aq|xJ5Akn4 zM%BN_CH$J=pI1ZtKbiYmhFyQe|M@4?@O^(BKK@DfNS$k&{@XLR1?=G?{?|`Z!!L3P zzoz(?y2KxL@LS@_f%foG{%_Ue|M%hJ4?EZ6@BK}Vi^ATJ|KVOG8Vcm+)(ff6D5^=l`Z} zwHt5OAMuaZ?%(kV89(eJgNydBTl(YtPo%$|{|8<&VU|67#Q&yKH2Zf6zoz(ywD^Mq z_P=ez<{Rzd!~VDG;~#N{kH68(dHkW2*JUBRJhuA~yO%5*p^U#_{9*qfE&eXy*A)Mf z8sh&|PC!|Ii}?4RqlWK`uUq^BHN-#ZsohW6^+){2U#x~-TB z;Na+sM~B_3)c>e|_G;n#5^9LQ%lbo<|GNDn{Ns1MsO*14_$`ms(%&Wgn&Mxm#b4ZF zUH^QZF_rFV&dQlW7i;^BF`0BFb#6{~y1LwS$&YUx*FLcBT$gvS(@oj->#l7VWcTD- zrRh<ulJBmTP@^Z0NuPM$)X8HyMa6ReO_Zcs#_FFr-G{v+c=soCA7-lzzKE9QRT*h1%adjO4ZFjA%tptKqI}6o zhull~dh-KSP8?spO!tD)z0}}HYY-d9JvT}2{I)6w?#C@WiSDN!ds6lNu*ffOKbJYU z2kC+PVNpJR*e+3c_gNg}F>+kM_cG#KcIW|)&U=|oG!S>)ZdQm zqix4SI2xCfKJLWP`(3)X_g{-6w_$90xY_Bh6uJlZwtAxc*p8xbXZu6aCHLDK=QyQH zpG3L`{>?bimD5`^a^`rQ?yEKPke5>-@m8rv+9Y*7&)M7LJ+8Rx80i7`#qo{%JL$3L zH@ZiCc)a-NDf!$y7mkrtCP&Tr7J3AqZ7hP9G(IFpt+7;zkf_Y&U~FP45P zIg*Z&ddONv2)MXUJ%#nC=|1D1o|5^L{a{{5c&5@j<5@d@vX^W*~d+D zB}ajwmZzSL^+Yb+b8Ix~Dk9%^5qf|3gM`PFrQ(1Rv}sB6oBFap_K6S;Zj zTe!KM2)^8|I=_Hp!x?ctr*yd?llcFR6Q0Lq{3@6OWT1; z^+bGos%I~&C$6M&EREdxUyz$)-B*uv8SN?mlQ<5^xBCy!2w!_kkE~|SdJM=?+owBc zNNzpfR_igYxhP!RtXdCnJYLyhs}sjH5wcSoN7WJH5Z5&q;@M`0lpoh-e9_;@P6gc` zQ2bQ9$e$j(*{?^eNf& z0E4=R)t}xd{kmpO8lRIsDJy3>ebbl)`-J;KWtV+Ub{cxPzDQm##2YVidbf~zz&_y) zqyCHes%`lp?uzRi?YVWnF0*@f#^|i{?i9PJV{(icM*8G2nPaIZ*Td8y`X}1a&35}B z`u+4N7w3%5NjGM7HO!xNA3b*Ll=STE(brB)zijlxsp(yf&Zd86R!(;Ji=!cRGSa6^ z$((W|NyerVdEH6wj_W+~>LaDf|4%IcF@;E%YU5A`L8^@>s@mlAoE{lDIa$#^Ia5ZD zN$)=J!ixuHPEH>@d0eLK_1E?nJ&n#Idtc21FEj%1A6U-M%%Q=W$+ck7exbA6^PhB~ z{4yn{7BD2G@)MoLs!VMEx@Ab_A5H1Jz%*_*V!Z6e^Ad&sX6uWU$I0@=@{#{C>pSy5 zlvk){{B4dB<&}-Z%gtoH7^L^cFO9?%^nJ6Q4AFZ*@AcP$hNWI7o;^bnM6k;Gb|~4I z#~iP*^X#Q^-g7Rs-qvzdoHB+ z2EB(pN9etv_Xa-*>9sCz>A6vT@+CLY%hMxK6dgpULIhgJrq9$R@;Q3@?iS4->7?`g zbN+junmpy)j`CuE0Nu};I#P%&BW3@r+=b`5WwK@AXY@hbzS74bXYQ7qg)hnV;%+=Q zw>oWiQ{wTRAp4twd3IBKFL=4dlg0NgAz#7OdG2Z?pM!hSps=s4^e>$*+V@G9D zzy1WG^cz1tqrOvmjsBFzqij4yG4c%C@0`CzYW~p0tMSZU zJpS}35Bnp(Ur!@~WrNw19Dlpm^yxi>b>MT?@Pt7hN&mbhQaA7z`~~RqOx(lmob*|A zT%yQ08&9KiWB(&hXtLx~1dacuPa5l1deh-~x;+zF z>cn#!rB}uvi>LBG^4$N9nvT#%x1Xntwa+@)&ySQ|g*KkhiLvPu-%c%O5TolGN&oVf zRQmxJ+?U4qQca$qHh(rJNcGnUtNcl79~+O4>vw+_`F-$oEk=8cKQ@VWW9;!HYt?xEgmLa4o;#rOAmR?JA2W5-Sha zJGp;L9l+DAN^*qb7e~E3`~f)dy&3g;MC*%co`G^dcIP;1k6mr?1Ul4CAKiZTO_KRb zUms&I2;Av!zj=viKPBA$!TOBQRO+X^OH~-xkL4~rn@i=mpP!#Q*k!y;pPz*;Uj7}@ z@2oD3H#+6_7w)5ZP#aHHM`wLv5WJpQ}8V z@jRK%gKaXb*k8z5#K0425+^@+StG0jIL^xjBelzF- zt|u4u{@3KmeNcWM<>AfCX&n0uE4_+bc+zNo%Y6Bxe}%v~FR886d9X6(#QH0Q&p)en zN{)Rx&Z+-(Dd`jHXYu&GQlIJ{@;^)-d;h&(Jk4*;s3(HCG+r?NsOtHR2)&PF93?P+ zTTbuG>AkMcz)=+;Q=c;AckZ87o=ffd3$1zNQszOw0^ zLo9tlonzDIZH%kzQ`2i2&l_PqDR^K%c)xex@#g%0t71-f^uK;@k|=z?S@xX7?HSk& z+~ThjqA~GveEdAFf^vqv#YZ>GbS&N|+a1sY9Qa<+-r-Xk(E4($-@$m@-ITvPY4M^d zmxqNeJc~Y4?fEIr*M(IwT!e#mTIpytpMneS=97l!Ikh*QCZ5Phi^td1IlXkAKClxm z_rP-}rx(sefG!4q0X)|XJo-|*{h&Oow}Q&&Yb~Bgj68daWV+;ks_O6-uWQNOEb|?B zzybGmp>oPqxCeSEuKKP*!0-|dv2`e_fOfsyoI_yANs(pS{%C8)TfH= zxr%v?J~~n4jj?#jW8~@nwA2Ut5;-|U2|vG*b%q`x{sMTuj0`9>c`7xY)ud0r#*@`O zHhu2ATDAj2%nzOm*{(_!O5G5?kH6q$H*(&q(fMioE``rexQN#K7?)f62p%UvK8LH@ zvs?bcc&7KHml0Idm8FH{we8k*tuzoL;r%(fegOPx0^F*E;b8rX>h} zAB(5x2=VCp7_2Mo`;W{8FF2JyGsjYXf5=)d=0DY0AFLNcdbPY;rfc><-A^h zfycvKcXkex*m+QYr9MseTww8(#>mr@c@QoKBesTQzJorfM|HQsrz0OSc|x4uF+TPj z-OpEU(8~g>>&kY$5B-+yp_1Cvlf0fO{uY?HoicOyt+^*1hKIZxh z=?H!F^!j5>!EBSKl=(3}pS*{7?zQYEsdsEV1w8(v+w+C2Tkt_Oy}Yas+z(qlw9Bqf z8sG2J`YIaVm}%)#7$eWtCDLxoo>S{ny?+W_kWO$f8+_M=#B<2{u9JVK_Lxl{UmvMY zeU1-YJ-=gp*Ma-Z_Dap`ykI|YyJnwOX6jSM>4ovA;#X+B`=eHRMVJSQ!PR-n-+!Cl)^;<6G{+(}(7Z&6hv=SBQv9z3Emyg9GkS7hL#`Q~SA;cq+cJc(P7+)<@?V z&FNCO>KP`K&UNgMb0s|dX^>q%yN`FhR+(Qe;r8LbJrhN^(&7;*vGF|mnbfoDN@*t? zjQE6g%lllmR|EV3@)`I>-FwdlGrdZ=|Bm`=(-x{vzqa~c`7!d;)c;E5dvB0FhQ{?} z?_o`%_M?qQh0|$#;~tC0=Iv^` z`k&)rusdbK!NvCch4IxE{S!p#EK48%8L{aT;QAu>UbUTkH`ia#2X^Drc=DFMcd`>t zHpQnnWbu^#N1i7+9rI3*b`Bosg7*VfZ(8qUKjqV@JvQCq37#37KGpSh^}t!{ras3p{W+*~BSJcdawqW7Yj-9*@fIMeC8~ zS@s;_dx%hP!PV`#&%2zDZc*FM?>-~_16i_O!|!!_UN`dTzntvnb+YG*e2XWkUu@}h z${ZPP^|%~Ie0`E^hd>|L3-p0ozxjvF6&^01zcbSdn?UKAg)Tg$H^~;TpTj+!*Kb5F zlU(dAZb3bAiS+mI2jIZ_!daD<+3PQq&&|K3`aL^doZL*t%XhZ3KCg~bc~)_~kb8pK z-sq7hIrQ;E=mdA!O_QVhAW&bRe^E*CE-e+}8D5VOapCE`Nae}a@)7h2bA6PSEc+eM zMgAJ!5@Pc0D=uuBkkCl)UwnTt)fevxv3_SgnrTj~UOzW~yIda^{HC#pe9%}-Z6(WH z>`CZP`wvoSJsaMmoDR|V%in7(25gp}N6h#1dvL++JEHxQWIu=07u$&^m3Yo#`z-G- z(+l+kT$9&)`J;b@0BacjIZ?V%S?wJabl2{z|rZ z`~zas2j!k_Kdo{lG|B4!GW>qlRRDOfO!Gf=?Ux)J4g6%@x2k3pX)Js^!bzs<*&ky z7Efi2JpNN;dF4N-+7H&*f(PM4AGptaec>{@J`t|p%ZaDzEQ=>JC^mh%b9orp{w#uw zxn}jAP?PuVNYBr1N6qDdlm$V4~U|#Qdpl=YD`O z&{O5Je~q?(I>~TR9wvW8{gVEcK7}#zU_9KDtMZIseTkNy>cYbX8%n}^0IcodoBc8uVzDxSUUaS_n1oDn6o!NlatLJO$)rZkO z;gaSSPb5YjH+^$N#|D)!9n`K^gGUT3Sn0;#d-GltV8yiUzuzwvlD z@)yiT=efM&s{LkqVLdId@v|^+6Mo9?618Xcuj2dC z?x*xh>um944USEpHry{R{zA2%dap|R%zaS$qrI%_^IFovi=5Ky>(;dYu9L+hhQ!7* zpZmqBrE2-}G~07c>GkGAyN`9^d5ZK2+3M5$7EP4s_AL1RjpLYGDaS( zQ%#+%mOl$wAJ{X7-gJG6-)Jz+NuM8xr}#KapU{P|>GL$(3G5c}ev$K6>PNC3fj-st z%wPOBd*E#*PZ95TKz-4R?sLnx)u&0rW8?8pllGjqSAHKnSf7x3uWHX#4dgex?7nyB zJHOl4j|F-C*ymx|Z+?QMPhpHaKXN^uae>;-LA@X5{Dts+3~aDFZ)~`SJ-=hT_c*$5 zq{y&%e1X{XDJzh6TUe&r&sxrR`OBq0%4OYtR=wXg+TYRJ^Vio;6dqgo9Ep+VU9@w? zs_6xNa8D@g2Rv|pFYTRWw`cUf#&o6nw27rpU_@;C3|J-g(d~H{`x|Ry`QygZ^5k2; zu=AjQkxJ*4R5q}9%46gy=WzqfE3sLK-I~7}PjUB7Q|$HweO{*eG}mT7Sr^5o&$pbf zJ>%8({3mQbzIdr0c=Z0xU45o^a9R(LMfwEa5Td-Z%)jDdXP&H(e4?L)=o*&c>GSVL z@wqqfM>UH4<>lXhE?$qWpReHlMMht_etyBJ)LtDIC-QMliwlo&tID&I$2XE@s`crg zSYOBW1;R%@gZp^Dzn-wC7sgjFN~3YO#@0DA#wE`BnCHxxFMsr}pf%G{pOi&vd%h!c z`c9SU=;7}hnj7ErsZJ(O@%y)lE`77&qi>D|?o({9*bI@+*-~`sSVqc*fPvw=@ z+-LF>^ZX#n!=#NgK1S!?;N`#6Ss(NK8}sFl{uN>jrwir<*jr%S9_#K<-WdD^yf05^ z*4v(5$Y1rpr~cp~i>EY39;{Q%ze`Q8d$vj4B3oqn41HiXct6~`@FSB4xi4$@2fMe|>o@#0!8-;&Z|<8hns-pc(! zgX0DJMS4N6KhIv))^5*Ok2JS=qNtdFSkU}ej6B7>9$Rcy%R_yA6nOOdV&3kGjZXE& zy9;Q)%w&tlcSUUaWWY|eah2+M)f(21T^RS{ZFYT--yfoL(Ts@}Pb5a3bGV)=Wj$d( zuycL=7<9t-ruErcqO>=7{HNO*s^7CLp1_r{>C=nLXXI;yGmJUm5Bt@5&Utp`d?%jG zlwRew{8b(!PYUzob2$T^6WN~Ouk+x&zfsyAI}h?#KGoa#Hhaz*8Jj*Avkpl-4iBDc zyVClD&9@;l07*bU=|S#R|1ZntODUjw>P`J86) z_(#R2&)>{bs^zbQ=cOIOANdLTco}HN>_O4_9l_^I__%%_@;a?weHYZU|J{Wr=LOZC z(H_(5ca(?lhdx#a@?R(Xz2QZt{c#~Wm(cgA)!qnRBlXdL-)W+Hz75VN5$84$g>g-) z&nGeHeL20y`6PaNAEEcq1^kJ?Eb(`#Yzf4Xj=xjerMyNb1 zcsxA$L3RDu`#dg0|DfsiOTd;3+>+JX*P}+t0p><9e9(tdG|nr2SuIHhr>q{0$Zkx3>D|<7VK2+j7F} zydE|lUyy+ zkEVU#bl#f3eq#}eYb@eu{c*_vxqhrLzHxMYmU*6RkUlr)J=T+z)B8gDKFS}sf3@8@ zipu9h){iYKp!(toA!eP$?VoW{pZXjTxJ@3A7U^gI9_D!p7tlK5y>ve6(0XFVag70D}9yp-Sh6$~ou$PBuZ@fc1o;X+uwX>K9K5)P8rShD= zBOHA+$~}bh9M=~Al!9@tOlcFOPd5Gs`~*E!pd&VzmTk)sv^CF**3 zd=;DsA3Sg$=y=QxPU+R>N?Jc=JAb&8d5}(UasIHML&yGL1K-*5{ReYI=$8(%zDPQOBd^aXJ=_lh1=5x?AEiUb3fG z1nX(3J(lvS#Zwt0&lc`~rHoeF&)YSBq?eENG1&drH?Pp%{y}@b#Wu44<(B<~#>b}5 zRnw(Dm8YofpMpD8f25DD&-WW!DB}sx=Nl>yy~UP3N!Q25(~;K|;~rIxws?-yE3JV{ zFX&UHRjAjsxb0*!y$U(qk>3m7p!Qf>A)4-z@hWuTS#+9OzvDc{(rk6UU>o|aIWiq9 zm_z63Kkl&;oOo6cPeB`t$2Y-Qpa06Er`LlGTblb%4=JA~7*wBrAw=pgQr`&kAfLlE z&-pfA{^(yJmQp*#JG!3OL;hjP??rUJi)TnZ@h1CkqH-jcKELZ-#+)_<_=^+~NsLbk;}bDdO>#vb)vta5txy(Dr-k`ZVyJaI}*?HPlz*4lI@t_4bJ+k%T@Ci#!;aI z2PfRd51|j-H8~xkQGX#QgR!Tj>MKN3%w5E(6`KA|bj`k41am@j|yuMk+zuj_;L#_)$8Uj7|;=Ka2T zfjz&2=e1O_=T&jy#x{~CDchN+ezwZxf@2FX!2nH4($1fOzMBx?)8Yo$P?s#7RH@8 zSh1exFFY?k8}$MY(#ha2PU>3k7DXRE-*_JJ1a0~RrpBg^@wiMcqziaf-Yfl6-%#t* zAb%mi?z&5FJZR@h;q@fVX&+T3*$?hLDUXrI%RG_#s{PDgEqRb$sT{t+u7}+>h9=4V z)chXhbLz!3-%XFWak9)`SvNZCQ~y0Rf1x}?KH|rU4>-L7Ts|Xz8~g>l50*CD9o0uG ze}>b2F2UEV{+F2M%+va6wZ2%#>4I_wJO!NJ;Sc+T{doC{!}E{wn>?k=Q_TI-D~ZQz z7)^5A?( z=z!n~)@K-f&wTl#f9ZTD?$_jN z?ZZ|)UKeg4*WsYN0SDf1dU{xWr}m*aURM=w<@ZV#o@Y*1?FZv^RmUu5Lg~1T*BSgR zxCifR6=(9`Jp2IH7e#rrp5%W1GC83c&iafzUDapHu5k26;l^tD{3oXu#ubrXup_uL zj%qO9Za+A0=WmL)f4$Y-NSf))vzhG7eEFk)g}^$NfL9%FLHUDudGG}JcL8?yUe@Vm zJ5LqwFPKmFdwXm=g)#ChT_^R?c^Z_-axCpDsT+7amPtg3etfR`b7p!KYU{PK=w7a* zd?B*Flh5(Za@I%mSMBFzPM7?-YI+ShUOor?3u-zAx5OdjJ@mFKUYsJ^iAWZmMdj~h?m9<}`pp0r2Vp9i!I4QtR#Pel8tLTmr5 zBYUo*^BAjNA!nWtwQJ3nKl)dQ=eZwI@`-9cpQ7L4ay|*l>EDK}>}t0k)EE0Bq|bHn zqOuj|ix_$KaJZ$~yyRTopOW;d)Cb9>=dYb-`#acqkiX3SV4yfo)ZZ_8j9Z=cdH4b~ zzt^@u=)pKN>-*fz_w2Cq1kRrx{p5|oRQ?Q#7sq@rd5Tz2uM zDXviSdkW{@@>JOl@vv~hq{UNNOP;Da@k@dlKpMsO|ipJDhp+^N9BF_)p4el}8`1gB|Pc;9Fi< zZt`G0MR5D@qQ$g+-o{f{OCG&E)Olb(&;{@pXN6Q+gHKcp|mrDV=wC9_Zuad}gqF#nTP4?E0YpRXL`<@NE#)>qP^1 zIqRdBhv+Y(9Ohs|zBbPSJ-~zXYIw((c4m83Uk|x&U81O3kEhW-rxgY`BTkNU2AeUbZ8yy(mG z5#nxVp0#f0tEa2^9p@kF^9ZmT=yT4dA3G}c!}_f4RbP0YweG{sci}Pb!!=+2=wBhe ze=QvSS7?~Z^E>++H>>-t#C@)JSXy^}jx(aydv-FaFYmlIGjrmZM&{%(=|=YS$z!?? zr+=Mk+&FsT__2okEX%wMH+{;u(e#xWv(7Z=GT5mTbJQmo6?2$7uySsU-XZjfP3g74*v|Z)JvYnz2ufvbbi#7Y$t{i>9mFRF1$;*QOn@I8* zjxyB^s|MkEYvu`Ced$ z)QjMYO21)hdUkEDYIXXVeqHNBHmwfLV7AO-3^K1t_I5HX zYxpl2?{H5(^nU7hy3IBB?;f(=#5juT|9w__-*=xZFB@<<1Q++Crn0}ee$iYffqPpU zo9D*Sd2+wdJus&KrN7I2??;hq`j4mY=MATS^Y7uNUEIdo!=W6XZF2o>ag{I^MzY|V zT=Ddum!FGyptNVyaXs8mQ#iDPF#rFB*2R_3dKiQLZT^pP9B!Yri=*>*8QOhn7aDXw zV3oxcoG0}H4_uuq{;qJ8P``f@`vM}TbQD4QKWVqrtDOEFnsO-D_fsN+&3Z=XdUX`7 z%ZrN>$Gs%Osfv+HZ?Cb80$hb1I|~2Sld8Fllj%NH^F4nNZlgylo_69o`G0VTRn^S%a zpGD`?^svrVOnbmtFY}y7yIu!)URG>S^CNhJ>rNEr|JCa_!G;{fGK~B%Q~J&&wNn#jrDIT<4XBVJabC#zW5OXs+M2r(^Z`#ckF30F)D< zACpC-MRIjHA%030{$r94NyovL9D9RPI+mSGXRBsf>wJn`xXg7vb}pRvi2Xr`S2Y*i zof@M5=Uqzc9Qs(A;(Ktv$}7!r+V3@p=7|Gkabk6W9G?r!ch+kNjRVJvxN7^lg69E3 zepN5nd1P%9VU#oxn`pk#&SfwV+^mOtJQ#2G1Nl|K{faKD<@hB0%a}{{A_U#dCSPG5 z-`4k2^yYk-)ma^PN@0K0Qz);HZ{Ri_(|xF&%g^H*SYL2~7hJmgL9gMH>|9t+U$9^0Dy$=y$Z}4{ zz`fER>8NvMwCQ<+6W6I9saz=qbc7UOl@E3#MN_|%9Zg*-Sk5EI+v$h>WICANb*}ayu9FYDeQW_LuL` zy6NTlSGFs3E|e3{3w&_@xi#3_&V_Pf{|BmGC3WOVYp^&PJ)J9*9FF>f%U}`UP8)yL zB0CrKdbmX83O-ghz4Deg>s7f@&ToMWI>BvMbyd8b3wmXjqoph(QdLJT?*Vn)Aj5WxuDnT0@c3qAFrEU-hZ6SFI_M2z#Wv>VxFA~`LXa3mCO4?-MA3G zZeQR$Jt#TPp){QIoN9X*gmlHltN4RGUOlxQ7D&uo^9(`X;$KpD2;hYP^66F`t(O@23 zug9kBo^R(uI{y8H$`yF3ZhCqA&grPPb9Al`C(Ks#0@vHWs9Y6wiEARhk z)2Ps{7s~rl$Ef93=;^xYxD8mYoaha*lsq)hqd#x^We?bLK+% z1rDSm-uJzK;uB6>^?y~lit5Pa=k|=QSHvUxkKpjK{UaZ&UH(UfoeSyMey+-uy0~t7 zVSS9w1%K$IyHEadWt^Q0cE93#m8-mtTo|9zxzHbhUOHF3tD1In;_~cL+h4iQ)=jTa zjO9Jj5AJT?pNie1opZltUrEo^jjQNP=kbY(Ws9R0rR#+EbI#oSk&|A5ovL2pI&u}q zs26zP9ysCI-cDS>YYVE^Jfe#I)c3fmkd{J%63chGpg$6rrG z=zWmhW4^SU-iPS@hcq9MH=RaD+a4tf={=qUotOEx|7gx*h4}n0%ri_lDp3UYTk~s` z%!d(vxaNFh9R25KaIA+;S}W5N@!65e>vVaa2Exa@TOrM}1^2hd*Q?!jZ$6mqq~E|j z=KdZ~(D{EaIqPTMXPZDzL%ct4PxHT5(!5@awxayo6T~m{KJ^M~{J!b&bZ)ureJ6UK zOy3vBv=t%xKAr=2-{`k@I?cD;o=oHKbe|*U+k8tTAL0!c^KAi+G3Ku@--dDh9v$TT zo7=n_=AFI#9OT>kp6uJ!OkW5Z=5c=GCVJi@7GEjzK~cCSpE;Z9=Lb~rxw^=gc<$ZH z!_j}1^SVap<6o?vM+ASk!K;#wbJFjV1lrGGSo4BeFFWgp``@5n_#GMETT7+ewvyHj z&^>gXzBDg8u%5W*9{K(y`n-hJ6YM=G-3I(U=mtLT^)r7k_46!{@k2ZJWV-Jxe3CWK zo3vE&K{vQ2pFMwIJ-qRcx}LCz*Y81B*azmD3eRpYLQ9NjT0nEtJ?65>BPf4(^z+5G zeL?d}bYGM?KUtrCh4|onr^xpnn%}E026R``r-b6=ImgNm&CgZe57)jwr9%B2;eh{_ z=UPXal72W(6y;08M+u_vbZdS!P~@zi$#1v63;4duigH=MLW^`hA1Jq z=^}mMc0JvHrkTDtj~e;ov>{Xu^s@LW56fqjf1XFAogf{-ms}wI^Y|Vv=!EnIBmD8Z zW^ea;$F3jttN5O$d0;wED)A`}Z`tAWv-k=y52x*an8NFlF`tL@>$1g~w+`KAt%orf z@T+_7t7k7?u)a02f%fQO+u1LQNXkOj8 zo9-(f(_WNc)4qD16rbP!{G{o2KJ;($&Zc(Dwbps0r7nEt{JK5=x~;d#>MH9utjk3@ zB7Gyny~0ob!yo#dGv(vi#Frf4^+3oU&1n9%{4$y!rts_2fB0R>pajL9e`%n;H|P89 z`FBh^%AZvJnf6t<=M<4k=f$PcIu6)d2EE6>P1nciiu7$C+5doDKcw#vbH3kpzHHJf z&grY`SKIZ=EvhWOU?Z;p7t+_?Ys=~=pSEAA>U*kxZRb-Jx$v3m5$x%^R@;}&a)|s# zRr^DFpgawJpDcp3E&*Kl+_$DvbiZpEpH~v$`uE_Mls}44O9&BI>8zj5cmB7MLq9)j zIG^W^atHQRZGS(|I*LYz^8K{qoDx$%o$ol>FIce3I^U}@M!qL`KW@s!vR~$=ANZi3 zL42X>tCzdrXCg2AngXZx-wbC$xLCS2hOi5{IQjYJk?6v zPvu)mklN4mzMS6o=X0#e>AiTmmAKTP_5!sN#80h+LGQs0cYDe0si%;B`g(Dnuf8yB z>&1PmoYU7_FK)L#+$&QuR@KjKy|~%Fx94AQ!M*kIetn(zrrb#9L%(RPXD_WKU*3cx z!?(Eq-m{$e#%56cYtt{QxOVzQ#?_5aEOPB%>TBHX3uVupm^o&`#p7>Er)9Y0f2MI! zdUkq_mzJ2@JujX*$vZN-@HnND!T&hZxO~d^oOH|IOTWhob;m{2PsVkwUM)>aey5Jf zF=iO)lc_s9e)4rauFuY#+~dZc-6vBom{$a!dFZDT(x)HlIeP3^T7{oI`r3)E*Ef2gPaJF_3`<&22(aNX2f-!#jaG+yV3cGiB{uO7PIYDcH7mg$W3JaC&( zKi7Pv@pHHA3rGKj@{Ya5qPMu8sqHHrGKbe$asSicALyJFUCw{qiL=ot>Vw-j#hU+H z&J^ZF{k(dfZ=cDDcw=96_+u)sY@Fd3ISsT6wR4H)@i_{5yJr52s{YVXciYUIn{9Fi zIo*r7{`>fDIyZ29oS4PW54;|mp14m^Pxq=jR34P~kMi?V=gRR2q)IYe-=77(>S4L=Y(c& z+wBv2UP*lkabI!O zBDH<=!Xl{~@(XxAWxK`q4d#Nba6^mcn)i?#vJdD1+CSp8jU%VLBRL!LbKvUb(s&xD z3yrTQZX!24k@ghuxZWc?u4j(tAj8%2n8B+eWe-lKZ{XA3E#qsPVz*xfl7|uf@2JLrNCJ-Sbo2X=Vg%2&=I_?_ukgV z)U#0Qf4}oDjX#dEIDPNM#@T@N#QZQg-SW{#oZs`cbKSsK9iLrozB4()%!zXT)gGkh zg%)R7jGRsQey75Jq;BB6V5HP7!u2D<-?vWsS9~IMfSx}7p_kouFYk(;zpJ13_W3n* zK16?nLQRtQW7G5cAu`;&chquzP=@TqN^nMT<=hFS*Xh1iMJ;M3@(sOCQ z`$ZOKX^fm_pDx4AdRr|&zgQwU;Sc-!=nd5$I>H5a@Sooj?3@+cPWDZpeeeN}3^}Ii3*Nt?K6C4?;qwd)dpX&R+f;?!=t4@3V83GUvD;&DV^u^fXFhW*1ZRUrpPgdrsdJW`Nc%1+zoVSbS{s|5Zk%y1OWl%wjExh# zh)>g=tD@)Dpk0T4$J{e0zYnuGlh?(@iFDV`2|lAxa+dOVo`>~3mib}N;6m2$^Y=Ct zjg6iMS;_aRRq*+ygD<3h$FMjtZm6{XhzsW*g$dCorSbDHUX5~wy#>xCN**N77X;6p z++KyhkADCcx}Le^#!`DeLj8XHlhp39ab|qvtf$V2{c2c$3C?xgzrZ=H;Ox?v%K`3> zz%Idu?}aw57-8qc__c2;wUdWhdM2%pjZ-`+(--Tb!8!0v>5ui?NcW*1OMkRmz~$v1 z8tgu`{Ij2c`}?+2p;|ZWN^Vnd^YBu8$B;4i|>^} zJ7lDn?l-$BUfj#&MsS0(o^9wJ0rORpeH#3HJ-STS+rh*-UsP(FAJH> z?u4|~`Nt7wR22H-9l9nusq!ju8pGqoM?61T#GGiy!yQTUOXdrD2Dl%j=l4&(2}i$I z7?SlPbPAp*^HFvFVlFbd=qp7!BL9+!N89sJ@QmrvPdc_r6s5x~&a_R=>8^9)9`DFo zYP~r)A~})nsT}@h*1>a|?}3k<^;|^rL*@(inaS;+U|0El4o)1) z&na&q?ZMy=T5JB$4|?PGlUBdE#MCp`j_XI>FR+c$z5GgxvnobT+?!WerS>~;zhC~R zD!+ceAMCL)0NGu5%n9!_NJuz@vlp%NO1{G4EaY@VK8LI8iE%KU6a7$(a{>eV`_XQZ ztp(aTk1w#hzo^khQ%}qbV%^4TbUs8uXF9j|t8nz2sjLI|;3lM~?GSK^KUF>9AJqI8 zV}G``&O_%s>xb;<`K&r;a2j!*ZgE!rk2&)-PULrk_533FH|5+-tV5W2CiOe+u;$SV zHaq7da~+`hLOx2-&P(H9#F|fKx?sK|nLn7!^X_PeAb*1s?$TMm%`n&Nl=6DY3hr-4 zNYCKHc(Ih9@Bb_|PCs+{`5r28KK-=hgg^50OYDz+w81}si|-9MX~Q-4@)Pa(>uEh? zaE`@U5hLd0bJhU&abkG~}k(ih=>#Ouo7FKcZfkp6H-O+PJQat3&PB*v3J>P+iYZTGUK zY;op%_fMJg(>UHmF7t68bN>SE6Qrkpj)uX{@v@uD?!?{k(Q-bGIWdoLbvljDzYs5a zJtK7}kCAgHpFav74n};Z`GYf3q3Ue#4@%gLuzUM2GxF`}9^!j|S8t(u^V>MFnCGYR z%AED=qs_-*U9x_j$FuK9p2~W%UF6~Lvu~6B1sAFNg#G+^3cF)QUlX;@Le?|F{Y~Q= zN_QKl?~B+t`yPQLs<2KMw=iD%PXiK|&g7Y`xjND;ydcXX?@l`|OYMA9}*Q>hg74 z?0S}Se*g3$;w-S%spoEsP0v;wF6u$(q0b{A-B)wDmvWhm2kbG6e+c*TCtjay=d5JT zrKD$)?R;5ddu*JWxSdusRjrQ<``~ejonx_Q&j;7`HjQ6}6Ko z-LWsBBu36P+&@YludchseQ0Pec{u#Lz{%x;JvIU`2F~ z!VYIWJFHdPbqSpA`uWOw{fKmb?cH#c2=zO-;Np9K?JF;{b7Ee*VkM0)O^FvLH{*8B zPG`2qhF=*&%r1q=)Sjd zXFc2ht+toG&N*kR?fy&(9wULzISwq*)PUEF7!7aGxJ9WYadOq3n%u`r15i?a60Pu+ea`S z!sWTN79n2c?;{_1_&LxUZeho)_4a&(en6`QQ9Xs4d#V=$JeRRdkD+99IoPduJE(8-lna^>G?V~&T?*tB=J5b4o-Z#Lgts; zIJKQQJ4co$p{-Ryc|JUPYOpX9YTi(=$-({nJ-cf&rb`MKUix+9&{ zU9>`^f4}(=^PUr*A>#%6yoxxJp0e_L+HPk(3$^?%c%Mi<+aY)oG=Drfd4bd!--q4m z`RJqk*B3Q)7+;!9oT)ZWv8Q&NN!s`ZIN=W-aKazyoWc<_*zNS_osRbk4*r75Pa9`A zM$TbePNse#>mBHM5&MVOAND7Hkb0s&g7VVKKLq#7@tdOKOL!ja^W6;6Gg}DUdl~q~ zS#V1_pU!-x@dLl-auWN#*jt2I zPxvD}XF<=~WqFJI4n5&6^pA<2+pDkpT~79y+TP+!t%!|tT3I-Xrk6jhg)C3t51w<_ zKGXKe_Nu`V1D}WAKlG4Cx$heGS+<|% z+}^a_rn$vg5hLeR4%atC#tXr9;QGk3PR%cvM@VD;Y8?>~e!%?iIz-1AvUr{moHN6; zUh!;;GynV8^mI%2{a;8uBO3pHw&#>vWW4~+BnZo#r~P$m3scWfC$)Z$%%X9deimoS z53zA#KI@QlcPW=pFNE_YC-A@vw|>1_SJ}&X^y4P3r+wf@S)AoDat`M4x3oB^AJTmw zxA!Vm%Y1}ny`1&LxEVMF?E96aV#k@gwJ1#9e*`Dr6d~al9+NT`sV{w+n$ccLz5iSQKE=NC<$34K=Zm#4^ zeP3saI?qQ5Lc^YRI5KEnOF`Z_>;ybHQ5V0#9q!F+J}tr&FH{n2)EzE&T7RX%+ll z`N^CHuM_y=c`BDKwm6GpCKx?>&?>Bzx|d2FBXhn}BtzJtHPKR`V2`?d?N zY~s{jy4F0O|VbHehJB$HF`zo$_6 z;ZH5jv_GBo)H$oy(P`s~+gP_Gt)2X}=HHmXV4q0$r9)qb1x6XbOidOJD5pZnRJ-t)&B?0S|k=gm~k`)$S?`1`-< zc`Me#FhBH6;dLYa7i9T>^hVH#&ysuBFShH6_WTQUPK{w(zf|SInf;fV?jLiy>;0n) z))V;!;h&89o$VI+2cNT?V(re69#c6~9|_@v5-(_B|sewxLZ`p^HCGhgFGy2H)vJm4C8x??=#(n&P_ zNjDGSRq4X{buTsDA3(d}sKxkc)a`U{IO;~&A9`UP9R5gmFaH|uISsD((4LPxSXX&F zt+RU7I;W`MptGLlIZEa$ji3AI4#|W1k-f!p?4Q;^eh!^(%tqYCbA{RO*F%%{Zcp^R^%A;C(eeGDZkUXU(hozJ~lnUnevmG?zQFgMN>%#gWWe$j(Nn+ ziT>t(vb)lctW4*t=gc{Bq?+#NzoXsD!H8}zNc$-sC0*#&n(HH!V@PkW#@VI(vgo)? z{$uj@7!PUrBh445TIGD13+G>C$L0(6*>|RV4*F{xoNyaw$mMV`&SUToz>DAeAD-IB z)U&*`n%~=9MeVxDLVS3d^baLC>v{QHm2)NAr(O?E=Wz!3dl(=C>+X2`7CK|T1MVGD z?%ZwPcNXG(XJ3+i8krWSH!(KOLJqfNl4_ra?2~06%pZBi%5?Cszn9~I`1CBVx6*E( z$nUGRC(szAmF}f3oCUwC<2Hlukl_`-p>p1NxAaH8M!F_HuKF9y2N(LT+4f!Z9LE&? zKGp^OL7Zs^;)I9&bL%_nsdHlAR&i^!-h7?gA+SS)zfWtIfQ~UG2w`gAGr8sftA2PpZ zd7SlZd4bvv*~RPA$}Usu&ApmGc#h%v9p8tJ;DdXqclGH`oUagPUfAMHZdg0c@FmWi z@Ygxv@5Whju!pif1nv2)#OZy};*8XiGjgdjC;W9z_=7VD!({iauN&1f^(@!+8~#X~ zk>@SWj7GK7v*a6fd>-ize}ltEy2Ibk{$6$wpDk~!iLO&+Z-Mgj;;X6uK2C@?R)?b> zB^~9=IV?%7kN%h?zaMTO&kewHC-V4=UVe7sbK&4`@DB&yd{3^2BhZoSefT4P z>+W%>aVI+E_hTNT{(C;upnacBoH<9Hu5$j%eN? z*MA0k$>*Rx`h)tBfvIsKmF+X_XlFgkH2b`O>ucW}HQnE3o#79j))Qp7p_^sD+Ye4e zgx`1nZ1@tBGhgG}MC0BSHcrv>f5X{?+r3G*sGP71xUcNpw512-BaDNgT=L&d?d0+C zqOz5YZdYsh2h43$5#ou=s z|HSuhe0bwKr#PhhwC=P{z-R5(E^Owkr`x`A&vmMv82{Awn`2*jDff>!Sp@jte!c7C z*-o6t=g_%ZT`bPj=C$KYN0WSz)4kh^tB-Ty+)C#_R@gZG$J8#}jq8tWx-Xg6VV@J{ zQx((>>Tc;-QA^I^j3djLU3Jc*PMpRbS`TK+@A=2pPS3LON0xKZdqY<`aqj*(Q6%-S z^h{}4JI>T2%-Q&!HhY{nZ>RJ6OS)N{<+bF@I>PDx#H`3ePMlwpeFkjhXWntO(=+Wq zmY)U}_^3Z`m@;}#1FDZu4`4l5{pDnz!>x0-e96w7v7Tdg2Dj&NZW!9b+px}x>mzXK zoZAboRrVKy^GxEbxX|J(J3^c|$E+sK01M}5_kmr5e>e5i&#(LHXpczRD5}q|3$=3A za~MxhpuME8Pvc8bZOuUbmyfA+TO&E&Su zoNnz;zjlwze{Co4x<0k36X!iEsejbV;*8Xiv*-x7KQmuy;;3h0BvJTmdS6!5#^E>hn+~n?md7U`l_<-tnTfakes2yj;f9!XF4{py? z&t*=WD}HV$A~w!&EjfMvaok2PKc5xAHTUB-^&x`!I~9G262gF&HlcCfKLU)jMP!ekHIpOyAd?7}9f+C%+{ z@qJADb+U(CvIp>HbaK{L=dH6n5O2hR7y2SS; z-qvmp`nokdq1y&&C#7sBNZ*3J^+fV0y61O7a}li9Twq>GOlmIt^j_zEYh^p(#QW=` zG#`#HQ=ldPBi{8iZw7lc-F7q|oadK*!55lU^8)4GxBIS-x78CkZz!*GeWJ8p8C|5l zC^zATxnGQSGJesU=aKWu;u$!)1HyK zgV)RY!fkhYj-oI2g`Uwv<<0F@H+{jS^Lm@T7$wnpbMKeDx*gzstA(wuand*Ke3jSR zy>7f|5!sH=d8;0BwqNkN>3hl0hb!#7xW8zb##>fL-rzk_N1Ye(02lHbc%dik0PfPn z!O3=B*n_u=s&8J8y6Ky@MCNy$7yF2Hd%*YIcxU#yqlulj5a-PfPpq9lIgDV z1~?u%FX92+eL}wAetg}|6Yab>r@weZL;j|8D(c9awZf%*sFMB$hXQ-3Tq@H8=?_l0 zBR*VrsuS;@8&%$dQ|qR0*oD{lGd5mu!|hhydB5%c>_v87?A!cD;|=#Zvic%lC297Hc)+ex z_;a|!uO6Rd=Plv+qZY@g_K?=QZoK|M&iM`dBy?WvV?g>NpTRx%)W^@Z^Oo`b7|Ut= z#{Tm3`M=@K;``dc3!UL^UwP_nc3!k6zYQnaaYb<*dEMHRf#aR)V|*XwFF4_jU(oCv zJ8vrAlhPj`y6KDlgok5~_AlDYx;d0GCKOB98ZVw*qUS`+>?8MC;x_KiXIPpH9_22T&sH471o%08*ux&H=#oj0WheMdDM($C2rawe#}sr~B4 zo9Ci0{B_=%^nJy<;yowcxf501sygzPx$wfjw!EwA`7d?i6&i2&?7Hde-QsM&@UJaz z@xgBzIPv!SO4T>5f8BUI&V$o@4BvI%ba-szE$PTIHzvuYytnp# zuMVzo*4Ow)me=3|FWiD(cOJCsi}udA+f;qa>d1@!uAbjQ7lotB>H2yvmHyyOWqniF zEnPO}T{~~#S@I^jqt_<#H>8s{sBZd(Cd&P0Ixogcz=ifY{9(6ZSzPDroGDYsnP3&zw9oefmYCCtsI7VDy-bbo$b% z#+b~>IqA7M-3LgQ{Ce7dIKle*pvgH?rqk!W3<_`j34y=`9|FmZhP}vkgNVjs zHJSq%&Nl*V?DKOHc<>bD0k}R z+u0um;v>-?;=`k5A5)yA8dKc@-4h>dAE5i7Lv+2oe74pjVwgNd;XL=2cAVOvaL%(t z@WP>cNIaq42=83^R9xjvPZXvu-R$9uug zWD~J7*WYBK+?O39b^-sHqP22Aysg=!gV?L2lnc{=`#*P~EALvIE6V-Cv)hQDt{%p8T^+36O!nknvX?sKarGJXkV;d7I-=djr z2M90NxZ(nr?gadk7{6w*oWB)a;GJhyaY+7p>7EPd+6?PuBjWdQ-2layLdJhV+~g1* zR3RP*`6S(?p9SrPaPs@aq)D5&bk_lI9sFmnd{O*pdeDlENsP=-x9eBsmv`F@D%Y^( zM^lUQm-yXN>oO*@T=SD|@P(bA>{q zT1Pj}UCKi5D9(JoQ0WVG)b^2b<2ilx*gs3TezQvI!PvGYIYQ{}+q>CL_`GuH*8N?& z?ek4jriOZQ8N9v614a;xeZX8}W7xC5Ir1p^bE=c!35Z5Dd zlD2ma%J27q=CAx%<&yxs=vAq?6P0e~^M3BpZGm6+mu|h+J)g?#tlt;E01>y;8-&@BH^T55kVieJ1u3F+b}C+d*f&K)M$i z(#z*nKkw1SrMn(-V!vv`0pj(FO+wq$(l{jvhMFnR16RO|Z7U*uH8jWL`XN~ zO1hm(Bp`ZBu4>=7;Z*0;nN!9``a1(Aj6Y@i*n#`coOafP(F4X$J3BRF>L3|XOqe!h z?BqeGPD)K5JR~}3%B1NtCX64L*kzX?iK+7Rq~XrgDdQ(N)6bqVe&FHq*Kp^ov6CmA z;*6U*b@Fg0<>WA&I##lrGiSIXBZ8TeXZ+E!Wcct`kUn&`{~qZq>#rew*P{QP)SJut zYe*lu%i#Z-)SJuF@h0m5+n17ABXj+6R9nOIbN0Md;<)@`Ot1U2o~Dk`_J#dArgvk% zZwd&we=b(9?FjKUpWA8m8`;mY+sh{~4rM%4(i;UrwlnwjUBAfx9pyUs8Kc^ny45V* znCP*sqrU|068#W~VPt3hu2uXT98ZKe{urqJA=3E*#_8-=lHMYV{vp>KHqxcP4u0d+ z=%4S~TlTk&Wa-lXYJq-t{OSHE{~;VVTkYij&nW%jb5t*EC({vp{{eS$*kqsg8qLq| zEajfW^90h#r&s3AXTYr~!uj)S=1bg#!@coy)p7adZ_|G@=npRrepmOnSLsOuPC38% zp29N^XnxZ9$}I|yBYzwOQvS^M^@BSP_uEer^dB3SedIp+Q^l>Le|Q%yx7wnAHSDUm zSnCt%pPtqGdcYmfS+$Mg;rEO7W2YlZ&U(^Me+lT%td#!e37-6;$G49Dju>xnzLR<_ z!Mq07$wPQ>3%<*VpBLsJVZiNrO@19b=lwm`zP_JJKhMGAylq`n_Vpg`(cjog`u`*znYsWOMTxTDIG^#8Ow>cvlLCzSsaKWhFk=K09i-@q5;K=~(tFoyK)x%W== z%fAltKS9Pv)uX()8qpK;)6e)HDd5|vtI}CveZM|MoR93XV7s*P0i{1PFgTy|l@%8x z4*WL#9S$lAoKH*o|5hmb#Sbk&^eli}c zLMBP7PRcL;F>mWk0OikfFsOH8c;!-+GvQ%8VEn)OLHhl503WkBm_G`5%u3I1yZg~O z`u|Jr@g^%>g4?NKmJOP{+7;HpUi#&zRRTlObhOSK0A&z>F0C4|NM`~ z_H*fH`^ove`-V%L@@ERnPH3N_V_HXlOYJAmw`_ViSbx`^r*dQaL%P1U;HZi- z-p|Dy2}AyAoSW1*Q|6r|emUuHY$g3A=tt2`AWmb)p&^|^A^*m`gYzTXVV*d>kHRBB z#P^7|e%O-jUHR8r=ZbH*TISKuX=AQJ{D7)te)(^0+5ZHTo3Q%HFCxw*`@>uNN?mOrw^X&CUwK3g5e`;)g`frzW1>Ii?_;{X4 zrb)k70Gn0l&&P&nJte#zdQUyA_$lAfoJX0Xct~#?FEYLVfY7%&`T?(l{q)*J&Ic3u zFJ7tgiH^%pzq_8`{z(6bjqyFbC)m!vI!fWGw-ru%E+d`T2TMBNMto4NXH)J8&>2HI z{e&$7>wV$j+J62xpuLG)=F#8SO8U>gUFoDfpcpgxFokp7G=vA8KMV5Z06zPEg=ZlL z($DvZ_mE@WipW0Qu8hmV`M}F3NSyD_3d~S>fi>Kk{T zG22h}KgY|uPQ#}K<}QrmQm5p%AD2J(NBiOVvGM1F_Fs>7*gnT;jRmKi>QLY5A5MCm zTxp&>J9Qa;l579r?V(?cAGiBK)^|Sl=#Nfl9sN8vnB}54(}4ZyrhHKjL^~*J;T)=I zn5QlNMCD-9PrQ@QTtC*OKW6RwA0_Kr6&HBl-^Lc`ch}Y2ALU=y!n)cOn6Kq{ob(^} zP-X6Y!YTjX7#GUw|2w(drg@&W{~eEQaOtnY`Wn}%Dr%+u^sNh4ovQNZj4e}_e)nGt zc$dN6*lqx9y8Nbe5>7g~E}!0gGh^hME9g|J{*yoX9n0%{->WR-`|To`lBVSqyI6`X}6!}K>mc>#Nig}q=$AY|AV zdS8B~@=JYH<2lpmqc*Dc%RdCan$&Eu|64rz8(T?#1of!=j-bCs5!PqfFDeHe`&#e} z;5+QC?MYcr<)aF42PyfvaKQ9OT>4Wem;KKH?IfPiu9TAW|0m^_|Mo8gzrXhSJc=_V z>ECPydkH zgY@%!wsOSlCH<+siYNAl+CvBrM!v3emakMe>16-2^c)>WI~Lu{_fckYJHP#K{MjSNhrRFm>1W+sX=T4EW!I-9~l`+7Hi}WdDKskFSyTMdEYU@6g92<)R;m ziS#kCetpcdI|bL}Hbps11`oPpYd7voBjnHi!!)7a>E+o^XGz+E8pKjU)-9i$$w7%wtvOH&_77%my7gg zqC&r1HvP1F+Rr;L-Fs6$`?=xsb|$r@XFsVk{v7>`@7|LAqzCsgMy_W1cagv4-lpG{ z|F=)=SeH-!A8jFVRk=7U%8E|;bM)W4T=g49f54W%Gq8`T5qly1Ms$%Dm`%R}!(keF zeAU%{`E&m5OKBI=y*>Fif_`mnjCh>s&#k}iFQvDJ>o1wr!Tu-ZAAdPGFK5s9hJeSO zzop!5`}w_1^nO46Y=5?WSNujq{wF`8?OxT?KPP|E-;({*?<@8%SF`;0m-c7Bf0e&Y zf8xs>j>|{?h%Lo0z}J4JQh$#A+cr@-v`D|uo0O}W{sV>n1OAo%81%#Rh+oWFhVwr*{r0*Z<@-IxHT8u$-j4zipA+xQ zgYO>Tj=yTQR{5~~?9e3r=bmj$`#URhSsPoR|N0+;^mCjN-B-V-ENAJLiihJG+Vis( zobBTAj|B5OK*Z<7d;Que8@u#3TIa=mBle#h;?Z92&euo zMt;s0h48``cjKY{`3Ktnb(={0vxi52V=L+36>@I+Bq--Imn!|)x%yq8 zob7YcNPji>&06DM@?#cz3Vg^U*(B;v%a7$y=kbN>(arKf9mYk(cfj2mdklg(m!Zf5FWyV zVHTY7kM)FJuwF*`8}ME=(ii)m7+60oh9B*y8>Ro;&Z9p%yLI%3DwWRgyTSSY2;@w? zke(>ukta331G-L!9AcL!ya@0J7!M;oam%NB`_FMr;T+faPtt#QT=qc>P&qWVKz}N& zJ%JSPugAH#S*!kLF}^M=S9(yqIT-C^1?KrfcyK!O5(XXz@F>dR`(umFc-7y3X8U=f z_>C9-!=u0Ioc!{)>HiLP%YG(`GYQa1z9|3WEVzRg7SR4NFBAdXP80t)VwOvPBlJlB znXcl`T{EG;l<%nWPo0~ee&>Rq{MpZmhJ)YVE%99@obnqFIxCQ$_Rn=~`rDJ=W;+5u zn?JnC?JoTd_90qBfbr}= zj%hx3@ks5LQvN@}&Z{2OdOY}>m1aL#V>4EN39?0dQhI$LiNnE^**t`x62p z@<+T)nVt5@o$H8wDC|F<+_$}{oy<~X{wMwC=pW2|I2Qfa0v@|Y?T7RazgXqK`9{)D zyC?ls9cTRN_8+p=`1fboFH}FJjTwjf)!0hZc+rOIt9 zAc|P&zAyJa*I$1bSMPJ_|2GXRFc&_k?Pt{m`Q_ieW6=Kh!n{4_$w_}H=(po-rU8%b zsN*u)`K|aa)E%yRaDd28ubuPO3oiXt{JtaZ*V04W^AJ4xQx~?5{+9e_%0MUAk7y4S z&@cThY2SOHUK38fq81Y3V695 z=j<6AzmG=!t(>B8(zyimC)iH_p2q>t;yXgSA^qfM__Orij`Y4? zjV;js!4X0GsivH*@7G0bg8fO-e>mi0)4vYiJJuu89|wOiq?0c;Wq$jw#rk{wh0=fM zj7*YLU7TP3_a70I{}TBB6wV8-zdQ$jD)y@>$CKa}M>yM;lG&EdepO+jc^M~D;OYCEA>*%NdUgEOg{PP`X56b~(J9!c8DhqfBMV47`wo74{1os=> zyWt~Uzr%jCYV;pg9xwLayqi(l|4Uj&{}RyIaI?0DltA)km1pWqh0_lHf&9^16kdZD z1~h7Z`ah7~5USpUS0?Ki|SNvv^PFy+Tpxq>;3f8e`ez^CEmF2+_0)k^UI&-u%$p~ zTl5FmPLh6}!$vq;hWkKgW~|a5!V9GnwZ2!MtbCJS@)1G4d2OfW{GVA)G3L*!E)xHN z`@QqoQe~~9za0K2RmW(##Jd1`$-Wn)^NM>kU(rNO9lWsQL%k=z5x`?sdix{WsQ(_| zp}p0AY*X21*SO51KYCf~=wAtWHuej)Kg%J{BVDS)^4+ z&*=Z_n|}KVgZ?Amm+^14&;DCU|8{k%_t?2X`~NW;geOt{)orz%Vmn_0_@IeFcrD;@ zq~vGovmWp2r{4knd${&5s(7=PmRogse)*qrMzH>J-&4u7;P>}Y+7G_7VbJmZ*(!IA zm#LSxP>%?wUTpd&jyfRcKL&J$^e2S=qS+q(sVn|B>7U!_^lACzpE^k9AAItUUirU4 zzqnciegke^|BdrGxrg%KS8V64_{v%6h2JUCW&2@nPDEDv z+K8_Pb}J~@yx8i0-noOUf35a1H-df-qJPy1pB*GtPZ$ptOM4oT_#9kM`Ba`)7J2to zvR@-4>n+Y#n;Yl(&CQcm{?|kvrSg7Ep2y_*r5nUwS^S%b&p|olbINz~>;3Hy{U25g zkvKf>854*7RF&tKze~USqx`?L>;c7@MhhOogPt6hbyhp294bonp7SuIw+QbsePim0 z^ZoRv(EogTfy}?nlW_~}|JwZY$3_I{=Xt8hdBOH)@0XMweve3}xkcgiu&W5@dmZgk z)n0eyAW^`RNSQoQeBDNF`%`btUmYrRl};@%qd!vo(d+WlzfSbz{wV*4QBSL`)_Tfv z?D|Xk?fRR*3wHf22HdgI*}ESU=zntl@bsIc{i#HwEAKS6K>wLf2I(J-`IE*Sm2VVh zCcsa!D5UTZ9=!IO-X{iYO1>WWLhoa{YD)Xz^AO%2)nVx}zx{Cj|A@GZf9oW^Sr6?; zRn5yU|E7{)`%nLYG}Zmg8l=Y@K)4H7tG!|=l?*Y zmDvCFMGu*Od&i?cHNSQAZ#!4%Njx01pDpVZ&i0)0q+ z{bl|l!1*5eKW&@E_xkN82KmS3oUEz^;u83^;%RJw{--4liu+3ee=m$X>boi*0Gmzm zJuRN2?MVm^wm>^+w@Zg?q2*Fvl)r=bm`*%#-z#1EIe%D#_(Kl}{bi>av*-uKQ*}dr z`R_I=NdGsm+f+}b6UCWHnE&B-mh`W`O8E?5r1d3?7mC0y@lf8Rn|SYDJ>+he{;bu0 zPJUhdZ~Gau1ae5-n4f<4Ts8Mc`Coa3(vyWfu$=ob9wD6cmtozCaMHhIwc;Vaq(2IT zOgFBZ^|(ua{jHk63iEH(Uy1*ioMXpdv?4$KuS!1mNBSqjp6&jR-7g}YBc2G->Ey5( zQwMr@9z_IjrsSt?=8(Yno&ASrPZIi1@jBa$EzqBy8l<25PYYKD+s`v#4`Jv<-;(%I z&XaEZOjtHL#SGiU;g`#4bs04 z+L_XHu>UXu`>e}0RXn8g0`SFkQqoC3e8Q=hX1c-WVWHR;`RMQWoUC7*=+U3L=|7{t zu?70mo8_m!zN_+U(@!|*Pk`u+Rk{`#BT zCcpiMt98DP_RsU!xqd-s3b>(l|jDZ`>DD;zx-RWpYj&yZ)$=5Oj+yf$2{qa_h!Y3ZjK+_90zXV z)Pd7W#-=6=^hIuS4xBb^>a<9IgnxD1@zM6a%3KkRe-Ew)kdN3lLZ@8ZH=CBflX5lho0Y#aa*>aE`Mc(u&K@5U3){Gt z^*eX*Hs9pq`}?O((P=cmXA@5u-6$p`PL58kt0GkrO>w#coX_@}=|6y-8yzR<^ycJ;^Mr@zfNCv?OcnuPEAV|;MD zW%I%F6xrU8kLI|*D4l!|59uZ!OrMEg`=+0dEXMsatn-`e{vaQu%jTo3t~)SBW2lD$=!d9kCy63^=6g1a!4=jisNqwbdnFkX-Bp`_Nch%3O^qi z)bq!!bHt*Re~^zQ+CJI(V4QGUAC=a*T;zlGocvJ_ObfbPm-6#b4!?vt>%60;KgdVp zOZoW-zo2lN56Yc-A|GtuY(4OP$;Yd=@bkg?5j&_8G^gow{8s9^RmDHF+NJZU6d1qZC8=+6y92W#MY=hD1Y+F^vt%8 z2IA#$y!XBIOJe7H{gULp$_Hnln7aK$_q>aks?D?%uVf?m#g?v9dPqO}U76m}|C5XT z6{nB%tK^>jm5kiSC$|6lfZt`^?;Edw61`9P;k*}9 zw}0Zs^-clr>z7pK{-V7DY>F^XNjUl8c%5(uFT|MN@_%Rl%h|NAaSq$QxgSrxAFy=x zC+>Py66>K{PucPt@y9s8i-&3M zM-l@ak3bL6-xdO*$@gbyzl!s&EWf-;_6^9n z9_$aMo|Svw`sZDvWM13%ocv@qj+)q!gG?Ny#E`BHk2%QSe{4d%88b-68l#X&k}UY4 zUYNT4`1Lcpr;bxg9#Fd?hJS7zgwx(nx?bVzk3{jpLn9QPIavFZv@7!Cbc>qI%L5J9 z=~>SAyS-SOFJ47j;w9Aj;#FiG$gdxFzkWOE9mjyMrFa`1yQ_XGHz=O2$j^8cu_D_s?T!8qB`?W3ddS;9m0Fyi zA9w$wtE(6gUXOK(WSgM>*xB$?C7kxwv4gBrUG3T1xl%4|&rL6q_;~*Pk%PK;&mGyL zLw!b2{^i-T$GP?vx~Vb;387zkLU-AZDkj7IB(W;xhjzx)-B04Tx7%wK59>FIG55Zz zaMmBnb(`x^ujc7@ly+!95Aira#Pf;jJMUy_+U;aQEC6ZwG5cR9`srfFS37x~tPhVb zFzz`Jon(B)^1~8OtrqpweBIAD;)m?ohbv1*?jL&0yLVy7{I2%n{_XzOZ4`VSl5-vS zzWe++>-{>pcj5f?7r#}1{vu2;Fnz49Yq7sQ2w}eT&WQ`Vt9Dp|2ldcH@eev5Py_hQU#mVtI9Hcjr~Kz(xID(d57W!L zToUmAHsEKAkh^~1@l*BCpW|m3_-Weg|DB&&@G}DWOAl7QD1VzD2l;6~-Lsd@@av}r z>p8JGvLAGjHy@l{qWrL5z|@`3b4UC!;9d6*Ex#K5G=R-N0e8*|j_Z3!{4&~-n?AEg z(7t9%d*gpz_*w8iiUOD}TK!4BAk$Cgp9IE!P>tL>aL3;v0m8G<|DhiU%jqNMA^F>>{?*S?lbu zCBC?Sv!voKP@;*w-->+AzN~*KefxW5DB-SLXhr9^-&t zMn44Xdt!UR_ll73r&lk!+SOMr@T9?4gY@$=2P2atNyLq({W0Zv4dm;cHA+tw{T*Ux z#CaKEjDJFS@QY<{)XUCT_cvA??=`@m!T62!ihRd_civUc-Qn`p1im7O13yd7(P%u> z8#fg_nqOZwUt1WA8?1d~ds=YP|G`+zU-#L<97PW3x*g|GP+t+ims)V@htHXwGkWNW zZvUL|krLqRxx<97qdmUDkF}1k;!m_+M86b}W8VF-GWTcvTctmQ2e({_{@5|War_C; zZ~8mUPrI!}yu_w@t)~v~kRRrI`>oECU44b%H^Oy=U5=H0`tcrL4Xxzs7sxZYLFqxU z#y($wd>xMS2&fn8abi~G!0{sK&){4V!h53t>W%5l*P}1`+ruX4%RDFk*oS%k7&VXQ z*BAXU%7A~ulS)t0irfE96W|F=Dc22v7apx}(*M9n)ni4I>LmjFk6xwlrY{xF`jx`- z5c9qI?sAu}*ma7R^AcCI6F>i_j5z>)L={iu=j%=P96$M$0UzUu6;IM~0XCa2R{Yhc zX+M|cA7%NEk>6+0Zg3pt08tclnj6$^BY@W;rM@;geRO%Q-9Y{n`tK_alYZ2*Ui|sg zlll2#{QolGwd2eKZ0J9kfd3Wk?I+OB`19ne{Eo`pt0mp_d_@O{#?fDEh02F~B=9_r z^n^}_9_aE_g7{jMu*1LKA@eyi*;^O?^r!Ok#kln3s}OitUr>x;oC?Cp*HdpO{e(Ms zA^TJi9tC_1;%G5{3~=&8J`Z~?9oTQ4guWKaxwqNF+nASt$EnHB*XX989n#N%<)T{o@0xCp?~$8Vvf{{HIbO#3CwOuA zn_A$Darn!C@KLPab6-5mxuHh+3d0UVcyNaW=X_I#&ozI|Ank`x4ii@f;hZOPfRAZO zkGTuo?-%2%C(z&6>`rMn#(I2Z5&yqE-e+p_H5~h+Nk6h1o+ChbJ3N?+{vOxM$nPtF zXVE_)Un?y*^%MiX2+|n~mfYZP=ZnEtxBX?De1jLazw(*40l*4)_!DJc9cUmw0-<^9a(4t>07Xg?2UVY2=5!ML>UK&tU#2;Ky`RIOP*(exwf4+R>AyyLMQF zeaEa{TkS3J8z&Z+-|)SNK9`@bs}MiG4EXMW{n+hB7I+xXGlcwX4~u#ze%6=Q@LglO zL3)pWrZV?t6z$3Oz(f9+Z{f*9uJzY1`qkH7CvkPwc;^~~p3l!0&t)KAFN3e}6Txxu zthbb&%p(dX{TBhwc7u9Z2|QV}pR}*{EO-oj(GHo8pYu>|zeW`CxM~rv;2ntrk@cN- zP~QSyjJHp|=(Vd9 z%$7NNA79lg^6Sgy>u{_WP|hgE^aWpphwz{!|NNo9sea?Dwf%6Ae?Ih8fpa>jNAk^l zPrdo^tA0C-qn$srPV8_~FTQbkt@6crL#B+cUW{^ETJM?pkkVgl4!Q4O;*JtGsgSL)?0V5qB;yC5yrLv!Bdrx1n7xUX8<7t;cUyPf_ zb8rAQ%h11~9a66BcM(p$*#9S-`dGQ7GKVsO_JsClr}H{jclPtedF;KH$voQ*9$$qo zwT>^&v)OUNInNdytnCB&wddKwcwo=7Q4aPz8|6U0nQzn^zkKiKi*{HMmVVUc9$$^% zi}i|WYwK5hxym^VIkSIj*Dvx#JFGuY)=}l69hwmmm;0c9wL|hpzP1{-CO596{OD(~ z^(0yE?CPzn*1nuyUyKV~1_aw<|8M9;ZO4fBLD*qof$|r^g9!2$J{R;KIRoP_%7OHj zT5vnw7t1@n{gUqf`6#XzUoY`;GXp)oGOx6buL0xH&w*Z8&YSasaPsx=SwT4U^~Rk+ zIQiPk!tbB}2MC#d-R-qQww3lUg*ej1h{IX@vg{)sH!&H;nkSS;&X+Ip4rOyYP(49O^J$Am1$Sx>w>SyY;JVf###WJ~~#;N8Zxo zEAd+E_&TXT<($QSTbA<{=NH_ebaH+s zf*0(5NDS~Q)JLvEB>*o)T7vY8u?K(RZx1WL*NKnHdgb5(^K)<1f2_MNF4C)2+UdjZz{Yu*X==U)Q-jXjk=)`z_(sJ#_!s&EJNt(Ewd z{&l^Fgr3?--kS1eAGI~<)Ac^xbtgl7c-`z@p1IbIpJvDZUn21j%cpwr8>`;PZ-5Fmp zNGHo#!u{INBilocJIHSbyb#6sns~^U9UqnYB7aQxd2H5Tw|=EDKgoX7aydt)aVxJs zU-Xvp#d^imjlU0S_m)L<7Mi{w!@EqxNEsP-)qO+O+7Att5O-a{#Efe zw7?hRMwX%63vSc=cHG6p%?hWz(GH6(IPLK6i#0#>9s+)j7YL^vI(W`}Pd6-B;p!^` zJLLH5pTbu%RbVb_r|odfJNfN!^AlX}NYCG%`A1RnW#9^`XkG0`U^r4l-q&#xmf`qCdcR zi~yTAEjZ=+67<6Sw5Ky()N&g!uSI?tKd10M?f*wnK$sOC_ut$#a+RyETG#{ohmY?j z->(&3{I1ly`Rf^_n?~8m5!S|Z;nT#XG`9s>(ulN8wf_A2y^$v7%orUla z;1LwW^s*tBZ{=?{iZE}Jx>&|vA9-<^;_v0>i*cFAmmN=ud^IBO8SOBH2Zy#-JCAp% z%t5HHy$TiH)LG%w*SK%=zG}7hXB^;3Af+AdzQ^h#{d{r#t8j{}FR$|Wa#ppDuTF?} z!Tv3ZGYznZ*pMKd1<*_Vwc37?&R=1N#6x>)WIF>r#!*1bO6Q!r)uDdAqKKpT{=E{1 z>N+nDRZ|OmF%DH3@U|3(>hO=0AJR#^Fg{gi@4IpsBEZA=RAq=yMZQ?SGJ9%%>W9yn z_APq%cRycE@JD__;%mj{dwgZz&#y0=ua?@w$CfEy$-bJBFWOsSCxz4AXrI-9JK%RT z?6&AfwL{7wf#)%#pPs+#_I|!%(AUvfnU9LMF{dq3JFom8KVLup5*&Y(q1~%^UB9O& z#@POoCeekzRq-~dl6Wv5DIR_%n7VPg{NH7JoJ$NX`2*bXQjjmw`Lx7|^pC$L zTK>QME<0~+YhsJHHGGfh1KIg&{rckiSNSF4SGlafoVB%%E2H)K_0?gzexb|2z+l)< z=0)|d0N6xd4$>dOgEux;d!W8L0nYPVGo7`aq}^WdsN$(!qjXU}^fzaD-#s?(6qm2q zV8zexa<%9yGs_sKLgAs+`T43^AGAaI+caFJ_Rn&Tz&c&i)qukgpT~DRjCR`r+&#WXfbdp*J#1QvGp$eKC$!8M01A zxopRXq2sw~KZJ+y;O5l|rybJXw#0rme(z{+MXzXn!r4yNu^^<*ONV{u&i96Q3ff_f z@D)9%jrk1vD*q%uUuPk{SsCzAUzIKBD?CN@7(;$rUp0W+`lv1CNcrov&V6U^@J$_F4E@e!gz7?2zqz>gB(toljfwyV%Z0*9P193>iS0`n}&P z{&s`y{Nj&f-Qi|qo-EY&8(ZM(uqi=(ah%@pg}%q)*dEryo(cZ~?Ka`Gr%g-M-Uv_N zg_o`TrGQsh>AHh@=HhBb;on;Z|HBR!wl|3}URvK=lpwZzLve%-W2-y$~63EeA)5h z{wQB%E$|he7UU}ixkiyz_Wn8G&&F}e+GpCE((AoAoTY2?^Tjxv)ECEJC2U-4~I7w6+^wD8s7<14c6ui>ldzrzCX%WqLuBu&DZ;DPdmh~FWTX(T{@V$g`OQI zzs}EBOLl0->uZTG+F|@Zw8Qd$qpuFjFT6A#U)Aq*GRfCu-~ToGy(ntT&llrx+V$(d z&6jz<<@kg%r%XC?=7fRc$4;3#<=6m=@H-4jfWB-on#o`a_#+OS0VFUc-dCmsQ*&lw# zp$oM=h~Ytpg=!aBtkZH|expFj5F6V`Z){djv`AX}mQkq@@-6S>c!O#5e>fL^ZG)_)N) z=GKz9Jm>Osw)v71r zy$tJLRfyX`Iq&zecRq)+zMt7d&aLz7BP#JPcwZyW=k4O%$K>8@>)pHgiclcakKbzA z)gSjMf_0=36i zFUEJBaR%8R{+BfR;ZQ$+by%M$zknPl!sI{y7=Q6olrEb;#@nMkl0Wic^H=f4!W4Y;%pYZb+#=P7&Hw5{M{qV>5`>Wy%Chk}M$OrY;i2a(>8~I|o`=bTR z^YM3NI>?{%M!fAK^BCygz2pSpoeqPUJc(zM^UR-{g<&G5LwZeq%@{-}LGx ze*G1~KI7*F^;iEt%3u9nx<8ftCBat$X?o`AX+M84?04y7#WAe;>5u7;08S zY+vXH!}`PavuLQcQ!(VHeG(7#Mm||j+uWL(=jV^{CQEk=>M!&2ALB2&I{){frFfIv z*Ix)e$X_V7CYH}S^zsL8eA>@nA^7|F<{*E`U;h|?6-izHv-u<3vG@y( zQ2t0S`3r#$>V^FA`xgfu^2Kz{-|oo8#i+-;r-OOeP4|%Vt@p=Ek|cgp{&Y6ki+jxY zdu7P_&i9qMzbJ2FxamFZzcc1Uchzjm+Lp!rb#s}$DUO%+x_xyai`vu*&Z{)M3^&I-ykstC&e^2%Y z9MH82^V4=aY42}~BmXA@g6rWSz?q)&)zowPg+k3I8?(QC!w<4g{7f0YBVI}BX|?!)kSz1v&jET&|C+R2Zo{e+CJ-`IBR?hEqkbC>0n zIn-fm+_V?q93OF9*#J8VV_Zo53-1CRz}ZT4S{HZ@0wfx7!Fl>5swG<?Hf2?sm+-^WzPXf28+T|N77%87ESowA;^jm3>14Jbl&`s6J_TOkF-Z3ZD_+ z3-6%%kH4(nM}W;E6NBTqGdhXi=@Fi-Eu0^GzTC=RC-zk_)XTrpdTw3}zE3_`e*X;z z_i)!=$tTzI!j-bWcL#60UxWCVe14Ag5AKs;Ip<4#a_bF$N4yn`lexYw z_`K)p;QfHDf_x0?61<=OMlgR21v9N#SFw?Q+@D1JxnJenu%`81+^@>Es!!Gvri^En z0p9;~-(fl9(qTV6>(h>y*PuN+z<&V7!=cS9bC4+D!~UuFrC$d736ww66?Yw)izA5F zOcdkfrh4%+`px6FqFw9w4#Eo1UwvQDu8TRIe_!bgfsi$iEB$Q0*lzbioUPiA zG(Y9D9pD_7JHS(dlNaX#Xf z@q17Df4N=x3Oh=F1b8@qUv-PZsmI><&X$eV_u|NZJMi;+m;gM6l<)ugd@ASPU5NE+ zt`qK;k#pGg^!P39&^mrUxnJqv_ZY>Q^?)Zo)A2s}-RK<6pFx~v>g)G43g><-2Z&6uA8&^Bx$EQ*zHu}EZKiBy^V3>|8y~(o8!uEA#o!7 zaiQ0K5NsdD9xi@P2YRrn)_s!|w{!TO!TgODz5oIQ4vnTA6+lOtoQatQuJR|ES&Zk~{ zlt`ES{4zdD1_(ORZG;K`CaaVa?3%#J?~=k`%J-0-}>#DaYw3TKVMZ3ufH7HNcm-do+;xZ zq)={4aYx#2P&zp-;=Zn0jB_|%Aiviy*Zj0+>X-2nlDi70aDL z+{5Pi`Q`Vw(~q)Gy|>426ZmC6lBvtD`^)71H->&{JkJDRLw^DKJB0Ay432}2f;<5K z1ae3mu5j}EF6=hCr@|fN-xl($Jxt*dz>BQ(AK~*>`}wUuK+oHmC*zZNUyt90jq}^H z%`f|tc07;QFn+MdNpHjNlJjgK(AN?DPtGfm-%pu;$z8de4)WXeg8b56kj->DY+2kL z7x7#RwpT|ilkr(MZ(LN@P5EVu&D0$ixw?)4VG-gVq#j(vB68^fz+*2foP0f9@AVJd ze!}Atui1aDz}GTPWdFfUdu6YqJS^$VA}{IY#!{Y{-Ke$zcYerv<| z^~?Al8E{vF{y*DQGM%*GZBeg_3?YQd@B7zseSzIt-* z`&+W0G6$i44_hnykNbK2R&UZees6mW-^YW3`+-)ztN7V|Iw*f5#EoEkOFB=zTk{j% zANiNUPRK9Yq0gTOew?Rm*IUZ5)7dW{<*&bWh?9SJljzqMSEI6f>-aqh^v8Y;^4owo zRpEE_`w{~ERTZEU-zmyr{Ch!o1o^jFp>WE9{7$swHW>NiNSSZ+pd-|>D(K>!>pclpqL2-uPQ*&{U-(4}jV>}!3)gOHE`$c-^f-mZqdhF9v?TT`U zpD_RP=kvWJ7; z--+)B%SCZ!I^dy>iiiB3Z^6m$P0$zfv%T8R`Sr^<3K`%_&QZCs9|*A7^#g^o zeJ;d<@9~{t{747zd#g2n7IL87J_0=wKlyzG`Rh;8b}|7x5i9*+v$YXdzoj=Tey+>j zBXJ07#E+Q2c%kykeg@Mn5{ICJ{EH#uIP7mO-(U0d{a?|);=X(b58U+;Gs^2TM8t2b zc%*lKPA}=l`|hLiJhYehyu4KW-%j@KFOqek5+A-S%3(Tx)`(#)zg6J35dOvAihj!; zZezA@P&pKBo?pKY?-jJ?htJmhwVUgD8TnlVy%%n&aO&$03!cOaQS4(&ZK3(g0e=zp zOug3t&i(yOCu{w!1-y_89=JbyO_!X1ZVmWle`B4*1qrS2;ub`<$j>k17G!{r{UtkY z!Ox8<2YxU9UEG3>9|iNvrrF%D6WaN5jw=Btzl4VYr@co&U(JfiXS@1s0>9jsyg~M> z)%o`Q7jBuKU&b@Y0N*3fS9)@=zhTEY2qQoDb0p^l=RFMfH{-iQdLIRT&hrcao?k9j z`B3k)9|zCbUhMe%DHpi>mfWKG8PDc|5mGPCC@_7ozdW>6etsXp{_+g)UXOA~55VRm z>_;J-_5Xb85qxo6eFflQYyHo*=MV~rf&NrV_l_uiEa5Zf)B9OFWpy*JM5A zY6*q8ozBZNwZQL-vX8+1Wpe);W9t!M!}D-#eouQzz zlg|NP$R7bbj_)Yxn<`E+vjrd6-GM~L;hPkXup^60|5W+fM9<(4mjhO@_U^Coc(it zmy>{3Au75NLcL1L_SK(>I%b^~>fZR&z^t(fTBcQXUgUY!Cc+ye)fuy+P!K2;!8@2Ye z_t;(bV@)eC@kW(%wUeLUx&wpyZA8B!db!fW(zq{^a0d@Y%~rk$j{(m8)`TYk-|}>& zCw-o_OKHFd0v?^C?R+|-57OHp1Cnn#kGsm{H@&OkY5xB1Eb)+Lc>GrO{@>ttBb=)c zK0nCsR)ANMUwnWXgY23$-QLLNzQ42wjDJ5mN!qLZ+L%q(sT?Z$ldCE z)Gz0sY3H?|V;$_4@GRiPi2KFwQ61omu)m-A>j58x^_TF~+TJt(PIHF3&D?#%XZq_e z<0q{z7k`aoynS6|+vVq%`?@l~UyAk0L{#Muut@{XeY*Va@Z8$Eo?7q1c;T2#W$v#` zyI?>_~h@jT$7}{vcm;`llWW7MSht+@zuyT^6_0Md>0lJm|pi)=15P15Aw^@ z=9}vbP4n*}%el1j8Ig~iyIS*;tbfS$)MC9i^0#|!Bjvg4>5lyEUZG(!&vJm!{hQD& z*A;T!Vea|Q@?5U_xf4>K&j@b!Li63s|FNS!tM=Dx+IbI0{0JZP#>ELYIEMVF zXQuABI3ylfk=#>bZp65T{U3nM72@yEFvc6Nf476)$38DKHKo1GLa}?7PX3ON`33&% zraz36e*SKv-v;3z-OKDgT<@K=^8VSqy!Es%3Qg?7US=DipYNM%do|Bf#6ZwTXFb;5 z@7ElK|ITF}um`Uhi~1|y9q}I1f46Um>qE3J?ptcfFTM0ywG--xe$CnY^n2i-eEK!B zKCzuHgS}PWw=kEp2>D}3d4KHrzrF0|oBMrsUJ&FvI^d7-P5)k-@3OY~9VdVESLZ$_ z2XvBe?t7tKk#E9nzU^^G0{ED|UH$Wiemf6gzIx%)5;uB|cg}6mj>VdUq!VcC(v?=t{Y@3%KA@~53V1R|COEe`&ar? z&<<{hE1dcxy&oe#`)8EPWj`o>!YP+ouPK~(Xzyj9w-jlQQLF0wa;QhWKW&D@Pw@He z#dgjw2m0+%4wG=sW8-4w3&og{Im#E|g?O;llpvh+e~JEa!#>JK9Qn`sMDr7#0NmLI zc(CqO40tK&0XzjbpY#2Go$tEHl|u;rE2Z!U+DH7x8lLga^@|V8F9)9MM>(8@@n>k7 z=0~x{UZ*L-gFEj~K4XZ>M}GgYSmD$o>Fxhn5Pk&k4Cgs|m|qYT=6)5|1@j*Tc!`x> zea4wT`t6|-a!87wUuH%da~0Or5`*%~f#(2H4mQ6i&YTYaA?Gc%lQ14EN4s4Ncm(hW z^ul$H7~r3P-vs6_D4zqXlwZQB?^RDJJl0psO#)BcN-utKa8JJ+Lf9YjZ5#1to##9M zE1F*p^oOGyIKNg4zc&KnkK8CXz#13aMy`s+z`8Xv)sjfHtY*t zCw{t#i@d(3z3(OsIWhg_!kOz_dnmd=<(x&m7`>zTOd*k_KN#y^*f~No{KGN~jE^pVka)?6? zb&$iLQ)S=A*&GeX`uC95$>H~BKtK91DAqKu*IM(@_WZSj7wS3hjQq6cPR|DA6GQ%T zOK$rD{`FhI{QCi3j5LO{Wcsmzc>8heb2wl2mlc&3m{?zJXVOFS%ON{kXK-i_6X*vC z`caIj#{P{O?8gh^!8`CXW;ezp$|;Ay~V57cKV^hi8$*djrP+O&zYp} zT=A+Km!uweIKMgS1>rC3jhD-IQ#rK9i%jW%Sq6BR>wlJCIQ;|4R%km$OXE2ab%3+| zOd~Ey7~eQzjsPA*O1xW- zzT$qrJ<#v%I*~)u?w%Yn!&)Z?jwj0x2#&KTpCasICBKaOnjWwD9niOYk?JvtbEdWj z{1w3M`QK~4)co|fqn>-jw0$F-_EW=(2D~3!KI$#kztb6@`Pn{n8rt48ZRW|La*x)@ zp$6xCg%@dl6k`s7e_J`~dpYR1{XM0h@Cv}Qz(aTj@O!QNvK=w^yJUS3PZi+Hto+r0 zQy!%6{lpGCyK=~G9h5`GUb0u%cOG2T@Yczpp(02R%lU0-5FWyV8!h?JP8%&ewEvFF zf_NO@*~EfJ0AF=?FhA|2kqtfaUD$P1Zr^9vvWFu($T=E=J$tC$vvqP*T<551q#rQ3Sbk*hN9Tu>3IQXA`I|w1*!o zJ<=WuuTeZ<EY@~rd%*8DYUga9`vT7M&v9$6n11vP?*8?x71!*}1KOJ+ z-}za!d*_z}&(Ep`!j{ej>rxFlz#oPEgwrb(p0)f}5;q0&hk$ZvRfo$f{&hdj>dniG7kVULHovq7 zo8Rs&@Y|yWeyMMsr&ay6yhwDytEAFBQa_J;lH%iNT8OMXO<-T&V^ugZRDR*&QDzkDY<6aA}E|q?BC*xl3 zI#ijgLmBzoy|@llFL~XI>rgfFw|o7vz3exW{q-^V+r7B{mXUYes~FTV-8;MEWPksm z7JjH-2!GD;-g#d2`{uU?`k}I3yhA&O-YJZFz}XL^9_;>SAzrxUh05GtS>T}^ueIt5GL ze&%)48)ZJieeP^5_}mMGF|EDqv&~$4s7E{8gn9eT?v;6%8_9(+jqtnG(S)H}rJywJbKOn-^6sW3|6S+#?j|F7=)YSd_c6KX zznfkm@5?>?cayb}Utlp1MtfTQ%JO4eIizn^I%5awez4bmmUYV8$b~UY2js688%dlS z_g9Uq8!Wy6HjJlDIfU?_O=*7l)M8x5{FKkj7Tf`zv+q$ntVa>R?fDJXuMD1-BAwK8 z!_+|gfN@qr{N$ox1|!0I$b~JBzg2F+ZN=mqX<~Y7g7(ChfyR-nllR5&7l7 zb8RRGGh53|&)57Ywt2q|&)tZie4by^@Q&uM1f2fLJin$2@OtXCLk0`rQ5$B_T6mxKBx9~<8rgmZl-j`A&-9sBEMCDdwkN1NX^>Q3}`hBkeT5131_BIUgAToa_6E&llz(MS#<< zp#peffM?Jim!m%t2b|BDo)}tN;+IDm=I81+bi^B)I3xd(H6s{{^9yy8pcE8L4oaw{I zw9l>kRiU3n|A=+Rw>Q~#p5I&Xp(+o>+#s4`he?6k#L>7YB?njkRJ^W25pE{f$7`{^Rl;Oejr-Snfg`jJ|mkN)Zs`wnh z=iRUO6*c$gFz~#!82ly}Pbr4{^WkT~ehv9v-cIe2`zw>kuh?ZD3F!N2>W`cFE%#7(>OO_DUTu4T z!V}0JNB%31Re16q&7TDPVBm>9pzu<_>kifYmB3#Pcp1_((k-vNd8}VPjgZf_56QV( zhZUGpM=HP7iTv{U0TZ>fANm)tUw~pv9pY0F9>N3eKVo|k27D;i+v&F!0sK<kIqJN#J)j|0A2Y ztUDsVeBN~TQ_7F>VZXcfcGVAxZN^jdgw_k%$=y#XMYR7iyztuVLHK2WKV;><9PsTd z|D7uU-`Rp+33$V&il2HZ2fP|-71B3O>6_aRg{2}0pTIs>ZPT0=1pJJ@Xa{cXCi60rd#`9AsJUYL8=%+yW%zFrWx8fbe zxIPTHj;dwcy*8LX1p3;45rlUIeDvE2&jL>v@Rt`VylR-rhxR$iSP0{9_VXQtnADd5$>Pe0o<;4Fvf{zuQ=)-Rtl zEB;DF6qjrbb;dG`K9%;@Ry2u z>o%pw<(CiFx3j>{ctoL6r3YYhIo4qkBXvAYIL`}WJP^ulOMIs?r)Yl4jqBC+I`B&L zKMCI+1#q8W81jz*egWoz>atoNDbHd&XTA@+4nD_~PdViSznJiOvQML(C!dPq*2yQ0 z`7^eklmp{M#}_L-Aw0N$sp^H}O3LSawDW{J$p0Ytq8*a2=6E2G1NHwJ>KEyW0nZrt zO_U-oQyg%P+Yd-AD1zIF1cpnNQUnOiJ4<#Qj#%L(MC zeAeT8M>y@L!Gb$rB=nWanfW7t_XM2vl=3{>iYGG|`71DRDo6Uxg2tQu?N2G@^Zs_6 zob&m*F=qfz-3j^S^V@0qCCUPS9pqg5TJZZ$f0^_!t#`EJL2b1CVf#=5JoUiCdQl2E ze{V2@;RY$d-OuaKMBI{QX3b?UQ_ zzG|zy5-Wcr=&DD$L+Y@0e)~ycp7`UNB+kn3-hT6h&`!z#xA(J`18(n6S1a)JjBMuo zv%W0N`72rRLWk9ed}M!mf9y{$9+O`_|G@rq%BMZ-gm%tywzlAuPa)-r?+)cN2K^S| zDFmWZEVu*sRu-NJ;En~40=~TkXFaVy)$8-QS@&B1+Fh=E>UY-q$nV$35-+GO<;kZs z**f`f-!b>ygB)`e{8Ng%XuIv;0r!I!U90v`(^((XL!Pk;z`s!VRvJ4{Li@j^5OZDl+XX)=YK+w3)9up_B%eG z|4TF>=fv*r)y2B;Dj!0ay77Cv$Uo{aitl*MR%$0G&T#*6&4O)>d;L65=81?p58h zohiRc=B;nuHg|n3_r&d{t7RTLd|_LYk>~DJ3BsAKE&s3VB-nm`yFvVuPW0yQ zi%!iiH_qQvZoeNKtoJPE6Uc|(s}LTH8LjyV4+B2???HGW;J@D-ggbzraAgo40sO6{ z3a5OiudggP#~)km9?ZWB@T9Huqh-UV`0Xu?dFzQ+Nj>n%Ej6)qa-3{wfYB{!+jzkd`5R zZOq#P{BkRW+@{|u@gooS?5(oo&&lnhOF$3!rQEJQPxZ@n9@^X1Co0@NH{;GX~6lMX}{9tr~2hq54k<~ zrnJ-hdFv$glk&@r>m&`pe>Lg1&SBW7tI|_Zuj58!H&s~Q;Cu<;`(Pa)Vf9bbn7(%y`=i`m0X_T^y;UIpWA) z20V8Bw%5oPE#IR1q{mC)pF9SV< z?+5q`pojK+0N{K5qUDmFIN)~r+tzoC_sh+}Jl4jtj#qoRC%2j@t&<#WGfKNZM-)8DjQo_kXTcp>CWd#eVV<%Dtn;U>q- z_1jww{HIS1%lYd)*?P-(_)MjT?K4w%-LI3xIW7jicYjxUYM<2l2(T%-TH%R@RX!m+ zxO}<7SzjE$7s;neQ0wJ9kfdDW>U3OIKUCsX$+geXnm@gp+{;yLz0dPRV!QV- z8F~Irzu-B26Z`6YjXY1wWuG@v1iDDy;gt3t3V~-i=5@*dC%xZrAC9$t zb^8av1NctBv$9&@)C=wKdGJLz#|z<`gZVjLpj|L+S1{#7zr95;4>U*Se~Uhp^Q68} zJeleF>nY<9H-OHT+P7|~U+kxakiVrk#G|Zv_XzSE%&$}al*8})t9}WmeY86^2#*0z z7%)%@O1pAP-lF*!&-iOc{DV&S;u+V?$S*g>Gj0I> z=6J@?JHUqXj$FqJ;XwlBX07$HV#0xk^zQPl(#d^a4)E+_!FvPF^BkDJ58#z0Do@(m zc7S(!RPmQv_DuPa?z280U9I-uK_#5!hejpKK+mha&HiieLoJ!fz5kD$NjMKT{&cb(@i6Q8AWWB;6~>o4QR`%3{|Oa7i$ zqd&=gR$=6CbC=4KdM91>JP+-M{-K;JYso*9&*>k^d-{j+z9s)qKIgn0@6D5K227tZ zZRYqH&N4NIp2gS(aLNS9KVjNYGse!C;LO>{abFua_LNhmO_)A??6}DjjvYIB z=7gP`0WN%MYR2?|N98E$?@X9BZK_MmVCR2^lwF(wqX+MD5(MSU`L75tC)fWC0sd)H z{zZVfnp1-M!*tCfUkCgK3ehh<|6z%1CyVKeS86>ApQH7-Bi?7~j>FoSg64f;3Cxdj zoP_MgLHkEI>+wBLD}KTqyzsCEXFFGJ^;=`eZ^wx$27C?L(ek0%&LsgqTiPGa+o$_& zZ4Q_7GOEYvT)Y$6+N|2Vee=A!Ghl0Tg8zB{t()5|wqM2LznJ6yj)XAp^!PWjetr-N zm8AGwm1Adsm~wttM49`&xJKo|@i?-ZN$~q7oZpds05ASt*OMu)Fy`f&)-KGU;CG<{ z^U3K(g~w1p*EPZKNF4CXKu_Ignm+;fCEsfP)K?0p+*fy2c=|hqCy~Do>8aQLe+l5_ zNXw9}IHjnoE6*_IwTdCnq2=vOSdf=hmHg(qw zv5=`}$Mp&?$GC(1tw&ss1mJPxFZzGjdlT>~ zifwJU5Rd>GH-Zwtp#g`Dh(ra9Akt39t$+kkiGtY7K?S0y!~tpNAc}F01KKJ|6qInB z;(%`FIIJ;A1OFEJDY;q7r3iRF9+3Gvu;I0Tn)aTVUm0?exQ8+KckLI^jpNbIqQCCa zE!*>mk`|&7wkC85i(a>S2uE zWf(75E(<>u{p^SN+#`@5;tn$UCH7@7|4HCSydBSH58$k)#RyLtaP<+<@jZZFqGXQV z-!zF&r&Ph^Tehb^J#Nn`_(hA~e+VfE;k|6-*9uO}H_;9cNV(@A*4is1{{`m>?f_p2 zJn@9!N#L#FXREqGa2NP4&`-OifOoa1Pgbn!pRDPn)P=y>`+ICTG^E1E_Ao z#IX~c8Rt(M-+Syi)2B`uzu)0uOe9t^_Uwt%&T;lZaLTj^Q_h|^{+$28^rxO1roP|M zbM@k_F<0Y@r<|$RWz(Ed`}aFFn!Cd3dTBWE>@8$~S)6gyv~$irKQw@TPQ5bvWSf0P zo%+Al{SR4pm9}pF|C;wdRC(EtkyiYAptJWD?#vaTyDUlR5- zDGWf=mqh==@quBEBOI^HzNYO}&j0bfx%NG|_Px07`uILC;~%1L$j~$OzO88Z2z?&0 z~Czs;7u^Px|z@21c9b!$9lTLybu!k`;SvtR}|yi_rO;AeJw9N(Q!&}UYqtMHTOB2Kib*7S?tVq5Hj`u8owWBt-A)| z{b5=b# z(m{>PYYLluygIQd9IWin_}!MY&abzwgW6y37iE6kRUI1d-}U>&w5r{k)@kl_ zTkbcwPGf!E+Bv@2E2Z2Ev0h@iw!?af^HgSU)vJ)lJr^wBDVN1@)|B(LiG2rKBk(#+Buw`^x~ zAEEhUzp)wXTfT=5nfiZ^Eev-g{e@5b$1Lr;r-ls-7 z@~CHH_lQ^E9BAok?e}@Q>0Y-i?rCFxLCSmGXy=3IN0=l17_y@lUIIHz1CEJwa4m4y z#|Pd5&sF=b*yj@93n8CDxs(B4I#cvy){5V)9C$hORGlsRV5)!*L_Vpf7Wmw!MGxh( zz%!UPa{iWsre25r3YDAXxg6j=9-Q>6M@Gla<5a;PJ>IXUZrO5uray>w z=6*Q(eQ4)8_-)H9zt3&huj#ZyJ`o{x7wiUmCV}5fe;nqAY@cgUujnUoAz%J>To3!r zjgY6EJ;-0ic87F}ffph_?m*F30-Wc6Yk-#mXFVpp@5wP2Mf;6teNH^vbT3^M?wMmf zCgr_!v@`2-(f?3=u7>~auh!@44O_0yY5%`gpDF)W>vO$TpHMMhyNltWyVocOU^m}zpG}_l!<3f7*=x5 zlH}BPiuc3|4QcnHT&;1SM0#?hw;0v6rB0Y0ps{L;_@t)sTR(8SzanG z??6w z1iT7VP^A_Rnej_>{LH}rv}~x}zpX#&w_=pc$LjCevi-R)h4sG>_y5sNBun_v`U!)!E`v_@=js3*_+}BY8{r4kX z?k6k*{uuE5-je?c;7gHi8t3%_;J-qDIp#aGH!0({ed@H?q5a|ibFq)*+Y?(VKXUJ5 zN$}U~zXbb6_*}@2T8@0uZh2rFl#v{;KM9D1$;B@iFsua z@QaQW`!n5Q;G>|2?Y9(oxmB-x;BQ*{WXgf(TKjMU;N+Jfy!&?hI??*?q5kio_x~4N z(6mpr{+=z{pZB`4{=bfXn|4MrY6IrKESDTGj(xT={1?9)=K#O^xECl_}sou#PY7CHowTf!Cw|Pfd_@LkaLtu|KEoK*<-&C9{X<&vq2t zhy1%6C7hWp^`{KDXVHn5_lTW0Z|wgk8~+LhRUN0~zAf9I_r}rw|J(nIfw$KGv;MPO zS6_F^OVRpYhkNOEYS&Wb9oXbYtY5HY`_qp|`*Xfwe^0CGR;dpzzRQ(^dcb`+>?c#e zOD+=mLiC@7z#qr^2Y!!-{Yf?S6ZarL>tfMEycqaBcMHz;MSIx$!_R_zU))b-_e&o= zAbN=VkWV8&#LIw}W19zpYTTUBYmI*~e;;W_^q0S^?eBGLvVRG_%f)#oscrv0mcNbZ zJPH3O?U@5c7W#yT>SK9c$~(ZzEq`hf_>GV+M>*yLpA3H|@dDtbz^k!; z$pt>h@&|kHy98Fc#lWk8Q%?zSmILe4K4&~_-U~JQ9c%GDmF?z8 z4S6t*v%QS8xndvYhxQz5;k4%oz@4MSzu`j9C<`wHo(DUWt(N?Fz^}mkob!K{Lj(AApniGZ z*nQX)ct1AdAiYoIt)_Kf@lq)lzONzu;Ncef8*JM&zV9twB+tu!9?7UZF+LKfo$D`@ z`bM1gITi1(h^L@vvW0uV-^D(8%9jHF?bCRE%7H)go8TPpB&1X;`cW}&sfPShICo$C ztn^DYz}rKfcosPCDe&IdS^2N-td7?kPPktu{oKxKwzeCwX2h0mduvQ_(&wuU3|SDGB+R zKZ}0)RSJMVhx2OdQS_v7o-P1hhWn}NAuqYsehuhP;GA6*t$pUw=<$B!o1neC)54(+cbTFEtzwyRbZ1PVd6LEI$VkIxDd+5A?J1K?ePd&(AX`O#727Ws7Z@14`#gZ;@mh1c{rTkc*DxoJp zITd1DOao^*IqmaRdb{3@`vz&JORt_|?p^3mjQz*_Uiq1N-(JP4rtfMLJ|X4Q1A0mM zU5z4iiGSDoc+LHf=j#2=^?q|T4EI5%*Xi@}`a7E4{~>f=LsQMwNc|qm;GM>Z{E1q= zOyf^!J$dIfSK~F`=(|ko^G|KAdg^__Rr-F&O?sa~3HAj`;u!kej)U4(qW@_l*x~#4LWS}W_0|_xy{w}TED0DcGmey>3IBZ=SaP;+Q_Bx zTowAeOeS2b;~Dz9)??BetM!`nTIhYv^~KFqQa?}r^yaES=Qppkxw>2HPw9Iv+iCsg zd!Oc>%(7#3`_Xz#xL~6W577K=^}bq7S>B|17k4@-+MX(~4y`{+=X)axMU#dnrJQmB zk#ZgCp`6lNS%=!^Mp;kJ4z&cnHWWIMCx+b-no`Ewy~ zd)-YeiEw2FOwd-L0 z-gZ5NHK}~+ua%d5E{PfrvdV?!Rm1W{Kja{Sy+4}em7zS!m*tX!bq)KQ6!a`d`Lh4> zfY(9~>q80fEcGKlwDTbNPq^NcuXrkT4DiJH(hvI3lUOGfrhFOj7qRYRe#(K5fFAav z0q`u=t)vxo-Cv8AR}R*#B{TJV7X7gT-Xl=-%$CcG{sgu!2kYnptoMr<{1S&pXz&sgow z!#tDnNhFX4PWgP`+ntYk0zC!5Yq0*M9vArbIG@Y!Tc>~@hV?A<7XlykO1xgtuBX+; zab8v6VSUZ=It6<6{yHu{3V1Q72fF;24GHre!S62Ro~ zqZ|)`o=tdPNqY_i-h81v7uVf~0_VNH%)bl#DCj4i0zS;bS?;{|FEc^>$t?GB#3P;G z=gu9X{h@>R4y*NhpQ2t(U4yz5 zRNWNsXLg02soXzqwbKF6UkE%2`9*l|Q-tsHd!5}7h31Q zZUw$CD2dVpBDWj&nvXHm4e)vkrysKi>I3b} z^8FF-n~1Y~Cju`-`LY}vpr5#dba_sqd=IHFEEjt|mJfNJm$m0V4(3b6pUFHe1^LaW z=k)ioe0F|S((_=qBFLA6lC+&1j4|^TXJ6?D*d90B+CsUUTx;Qy*S1`aKm0D|U)df9 z&XRP?VIQV*xP|9{aosg>dD?k1=B2bh?R+%!5NCTCV&M+-&#DytY}afrCtn^eD#qsu7 z4*A;GL_QA@?p`7J=eXtoXM5*TIu$< zO$z=>w#Vgt^}U^s=<_r)TB=TJr$#?#(GN}Mh0S|~?n9g2FPQKm?bqYIdFt)m)L#0Y z8-w#N`OkQG(++w>9N(nVzf#|mf0=}{@9m~$jE>7+VudgNCeHsv=bLF6dhg#XOUW9hTYb5z?emu#&(tE!qQbN=c7xID-1``;_iN&EhPyF4fC`yVe)9}ScA>ikPX zzYN=J3BJ#Cc#D=QeL&ND)8HNHXE~mc?(w>AU;3{cq9g8?eu3u%sCP8*)NaCOy}IX1 z3Hy0MsrSt5rGMvn5B9&#o^jkk0{Orjx{978@KNa3a*%F5@QKJz&8{NP{&e~85-!|d zs0;Z=kWUx;l~cfv^5Xd^1m31l@N{3%!~S#^;Dz~udyrp^boso+z*C3D^_Kwu3i4%m zF803x_#Wu-ogO?gy3Q=Zd+~bR4|+c}eMi#IY`J{-9Z8n&uq!0r^xGmCbs}(nN0Q~Z z{2`IAcu3}XEXTjSB{;_+2Z~Dem**v(1U_?<$aCGuaxA}5aONik`O6_s|0eDKWLD%k zf1*8yBR?F^&Vimsuy2z2p`H2tO5#4`edM3xdKvK9*vC+ad)DRvzaIIdo^s%|up9MM z0IvhhfYu*3E%tuB8vE*cJgVOZUfJXa_uiB8ZHIWI^n+KT{jR_|B=exm&mgX9;Rk1a zSdR9+Iy_qcOO@D}@|@T9`T{uCW4sq~9ra^A;UM80_~luSN#L_Bf42+#A?(|$T`2ia z0l)cINtb#&;BR96!{=rBs%}yblduEJw1}Xoq^w>4D;jUjxF`Md!@42|6TOKmdm}wmwub& z?m!Q}uY+XN`P_el{3pOT6YCtVS6Lrwpocg&LjT-M?8*ATdh#~>bjisw&vuw_PuL%L z5_rPG^MS9i^b`QM{YozI=i#SgyQ5wI0smkE`_hUa{|w5v;!>$s9`IYgl^T$|Oz>i~ zqc@>Hz`5^-WLc>eK)&)^k=N6;@UL&B=qV@@JR!yNFYlG_`K?u6v_G#xxmP}*-=pl> zv@R%*-p;`uoQ^1oT_yd@f*X?;h#qn77A>qhjYqx$dC>$hmQ+~N<=`lEbTukWJalodWkueYN7YxO-Tk`wv= zG;6(C3p->$-*mcv7H$7ojQ5H4+QOGNjrWBgOFh7~$NCO3`Qvz>M#0+mJwr@wu=b&| zyno?14Syud`vhxTXL(<5jb|)ZuLSK7`xjW>fBqoeKG~1h`}!SZG;59b>=zts{7yms z^i`stL%yuBIHCfciJp+%tH1lW*!tV~yqP_&puxNX^$jeox2K|2DsCEqy6{Zz9Xa(9u@7ROjE-`wl5H zS>LP3e;c}9@4t-l?eFzeoge34K3~t*uGaerbzaQx)d6}v-oLr>j?($lKYq_A_?vzn z{qx_6k1MC@dlb!gy_tt**7Kb9v)=DGtBKEgL3;D0cMjfC{n+Kema6csrutEl{cH7O z#CuW?(*MQ!p$^qIn(5zvs(yG{xB0O?Wc9zzkM+SBr0a+N{ohg_0-YE0V|{R3oj?6! zeee#`&!d0i^uAP6zFGZm^ZW1Ck0j;;IiMT9tVu@a8F^S|e5vm#%z~$0-2*65fMz9dj`7*Dbt1@a4d{F5&v)L*RT~7xLF2pDDa|P65vW zUWj$MJiSt%Sb8|mD7W-fL(ff?o;;M-$?%J?TpZv@IF9l_w_DabZN8%cb*dQO(Rk@& zeNIg$LO(=yz0?!#A0VY4q8|Erf02K1e4P0O&&7LiVz zVhc|I?+p8AkRR5I8(|0H4&>R-Bv9VBop*W6f2pt!>ZXtM`GMP-)-%o*Qh#{=B`Mc4 z4kj)uao&f|g<@CjFO}!z`jYje*zzwrh%nlk_ZI-S{g;KnPah*QeXe(p2j2TPq>FWe zz5*%y8$2Ms&N%^i^7A;Zuj~o`s<6+N&s7Axc3xb*1i0;|ECp`+JIjEt8VWsFe+R%n z!a66LFa51NjZ&Xg$J4EW{I`~#H-PuY^D_S#$|L{8>wuq#@BXkpE7X?~tGqZ~O@Mq2 z{HE-$>YqyU?=>(hcsA z{^UsDgOP5@L6UwU@H_B+jOD`mcF!LoNBt#`e|o0i^dGanjfMZ1ddeW5nGvr)0q`gB zK8@vm5AbX79xS+6`XxzCDcfII1^HVp68-Fds)670sKliHH1NGyE@-DO0RIm5^q!G) zYk>QB-&nn?;2Gez^SxhhNv9V08+fiX@GS6=uzw~adg_4ZqrQ_~tmen=B`wGKlIi0er}xhuEZ;V4{R;zDh zvre9?dW=wx_W|^g=IxgF&a5vy%tMNfIzNn(S-yf24eZli7TU%f7 zd_nzN@%07I7ZA@u{>EdTmh+m(CxG9N{fC^N=K*&sdNg`3e3IJB$O){jLR*WPBVCd>PY)o(aGg&<^OICj!6r-ne}x z0q1=PESF;7=U*juBVGdh=dWQ;oGU2>{u=UA^oiKh2d>VObQ4QtK3@j>T|6)EPpAN% zW6`s(IVOKg{+Hkt{r+MTI)5D}?+2;>L`bXGwNO3O9x4gFyeEq30#-cVOFvO!=eXa> zock@fMEjlEv<`pfoG)b!?XqoL-o?3B%J4j}YTH_wUqYY1Gv{o{H|K+E^!Z&sr*-(d z>bkf-o)@P4o>qEO8=7<(ne%iw`u@b6BR2UDTDJ~=<~%WV8G73IczV-xI2zxaGdB5S z9CO~d#?|)NN83aHc^KX8$t^DxZv1+BCU;lXi*wy(lKb}LTex66pw$%FckLQxf zH|LZ2Z$o+h*xgp^)4z)ji9b(oZLjF_@SL)#Z=)M^j%46_fOuYp;&o*IU5-XMgB=v`y1}UCxiv z4q72TshQVwRZaI!oPlwP=YZJ`YOkye|H*U1Ibf^>p1)egH}?1Tc$f!yp1&+g$NP1A z|1bM>d;MJiJ@xurI&EU;Z&tWL?{kgvU$NR{+4?yD9*cjpKDQi=-*%gLc-tLYH0~oc zav6ONJ}Tc%^P~RxoEPK#U99-4^gNXNQjMOTI{ku~O?iAr=g*v*XBsDJe)h_y@OUe{ zw@E)D|C&CR&$x!#-!q%JN1VSw+cTQ~PxbRf+sOx7Uo?D{PCpv{!LmpG*}7ds`n8=b zdwyl+;rd<#=J7I}pJ+JH_s>Pc_V?2`Pa@4LKPM6Ozb4Tx_Fkg>{=YQM_X`@NUGSV7 zDd+n8`pum2l4e_SNv8|(j6%!_&6m-B@uAz!ketS>#(^A!AN z^xG8!9}PUci=@kOICY)0(?ZN^N+JI_+G)-z(eDF42kpHKcp30nz`1X|9Qc(MUIF|% z;9M65zyqAOCVmg_PCrRLiQfzSJKVp^{EL)Qy_d_sQn)9t3i4%GH!z>ozzbmq?#E99 z{}uX^dx#xsf!qC07Wl<;WuB6OJ?nrso9Y>?`2?e}%AfE%raqFH#JA`Ump-T%Y;CZ9gLGa}W5{c&{Prv+ZwV zeY5?JHPHWCuGpXX$pCKye`E>nMW_S*_hvHw5obNI{g*6X+keUOwf&a`s3&dU&*S>i z1y27Z>s1l(-Qa(voju^TzpxbeWcYXUR!BQ42Yxni>aPSo2=_G5K2^XwA)kfNQv>`e zlq2_hWP!g9zbW-J0RPtVgCeyP{-INj*5mSh z&D4x#Qm=~tkahtzinMuqv!2*pxzPK}@XE%Ja>2lU&{j`8t|9_osFIK*tN^cezi8nO8#}vclXyqwd{anctCm|A)DMigCE^OlzL`aX*Z@ zPs{6HeqEESiSvWCKHz>CU(1@`MvMR9adCSd_+fKZS*myYEztV)kNYP){crQL_q%X^ zi*x_>%KQ%2@yiZs%F`Vm#qGiU4p}X0ek1h$7Cx(?-2dP%++LaAfS;Rm8UCkwKA*T$ z-}|L`=C@*Reg5IHCYhy{eGgp~Pybro-i#jpr7U|NX{EQ$vQM?8zreEpJ^FdgekJNR z`*-+nLx)=W7ixK9Z_2!{_XnB%LJY5-7Z0CvPdxm+mA{iL{bv0U&5zkHMBRq6-H`4$ zcyig6+RsDVw^Vg6HMO6b7Jse%H0~Gr54WG}?Ychc-`3hsaL4w_{Mdf7`rqdFXYJ>& zwioYC-9Ge>?Io@MZGKy8FaCVp9`*09wiov<-5&IBYwabtTR)%vZLPgHfo`Ar$Nfak zJvyv^|J#1z?eo9demE~<`jCw@I!UDkJ8_d#=yaG z+dZJ23Z^8~Z2et!w$t?K2{lH~YZz9SB~*Rnd~y29gqj=S8@UF}kNRf^>+{EqZ)kZ$ zK6_R|jXkx=4r+NqwT|$;wFz~G&M)IT-zU_$k#M>$p{7UT8@VGNZj$$YPN=;jelCB# zmS5MDA2m0juDPR0KKoEYowKGX?A?)24bz*#*&w0Li^NZVsI9oENuNo-S0uf(-c)mQ z$kNv$GS5lt z%|pAq8&7}gZY>+_ZQ?gUg`H^$bz{Un?$Zf%Ql!3^ z_zNQQKJW5`8gA(?j-+qoxgH}uy3H|PNBsvL_J6!ttMBjb7TN!S``Npp9g=eYhhCb5 zf4o=1dsO^b5LdSUnEk*v*k{1+A+evZ{m>2+@xEieZ%YFIgZnd1ko8$U@Hcjp^&i)- z)xc}5`;VRi-hlkL@5y@ZS>SW7t_=T0zf=wI-?)DQek1w`Ucx>G%4Z>etfi+8c)5kw z1NU*yJM}aG-vIw*?Gvyw*3EBYUzhq!@}C1djpt3cg69E${wsMd`sWkSSeoKB7@Jlww zf3-ZbE-eO(9qB={*yc9ay^KU|1? zip8*-ohDyWe4F1-~rY-6oz>PRo0nGNjuU{?Rh{DFfhV zpdJ#h2F`Xsy79#kGq&VkoUGp;2j_01uEn|0njNK`qB$zkUG;i)f9*jjLOI?D`EtCM z0IUY#JRJMg95CKO|DV`B-hO*W<}cYXZB(0vrujsAd>hq1GQahQw^30)r8lvSx=s5n z%{;;U1uI)C`YqMhZB%-?{zcaD&hc$j=ZHS%WUW7vp3%{4MN|6Ok!{rO`W#hszP%ta zUrB3yHQEox_oiNLYqg<;_~inV{=2Q!B|C{9(C9XQt+f8AzFn;J?fnm3b$+9Mw;cH0 z)HiLEr|pr{{IZB2a8La{T~d<&(+}wy`QkQ;_tR%}*g3OJqhHefwvE1DO+SyeS2TaU zBla>H=j!?r<=032ChoayRK|+W^-osoSDDso4{cB8&-L2;%euFR=0~4rdu^|p$a~vs zv^}HYTdnX~?U#x2_q6QWK4O2jsEyiB^P|sW{G`lZc0wCKH&ZB$)EU-~3n25c~BH;V_ zTDXgT>PQRsfu}4y4Sa}&^94wuh4a1RxwvPV&+Efv7g%^2_-qSj2Y9)KbNw*K!hP6z zo`t7@-)P}_`4#?EShx#(zJ>e1@3rtW@P!txT8jR~7VZLHYT-WcCoDV-{22>Z+lv0Q zg}cCCv2Y*w8y21hzTCp~(dO{)0}FS7ue5L<_!Z=9N?oZJOSLZ z@I2rXEZhNJY~e}ZXIgkZ@Dd9z0A7W5K>B|2v+mLLu!DUjN6*#!5Wj5NXA*Rl{$XD+ zry}J(lYG>lQtT7pJ%|ujhv5Aq=TFFv8jABe$s;R6QO?Ux!~TjY;GBm%iuG8gldS6; zB=8OQcl8vU^Yy2&pTQX*`U@cc4@=$!J`(vUJ6`6UDc}nCr0}^okC}>m791t|J;2EG#SZ7Xnp zSsFO+d7*p_aNhGm`3!LTo|jtSn{lp!_n~Bg_r|>~EZ;id_Wds#fnNx_WibD%2i{?p zJTLJE;QPUD#5pe5_qODqe$TvJ^e~?Z;PWgz5BTptiXDqj7U}@scdF>&zQH8$`=KX` za>)mN3d*Yx&&7HFAS?ea#2K359(>DU)Uzf2+Umw}gKAD0LGebk4<>-UEiD*^rj z_Tki`zLf&cLcRfdxK42Kye!8G$RBQ%?`^NPO)ymnC_5beD|Ln*50Lt~hhyKUjp9V2y-$#}J<7TWIE89zc^MG#; zzf#TN(jFb)clc5t@_S4BO#&~0Ux59?zQEh_{2%;f1;nAB`~6eEyJDXS?SCwA`}?1T zz(-;o%lcCU+`b>p13m!jeCi(y+`CDhpZGZ7_Ibw%!0mg=CIKIh{P5nAV&L}uYbC(B zpNIQo%7EMVxCOv(!up)@)xhoh+A_fH{Zw_pxgUwo+W_3Yk42&0K7e$&ZqEUJFX|8V zIKaEW4qR6!f!~JpHsxL5KI#wsk160k^_Tia`6A%ukT04h^^<&9Y44_UOPTIl?ytC>Vt>W&)o0+JLN!!*m`5crj-Y#M{Ju>C z&K2b#!uhX?-6+rg?fTE-IM3bh{juPMXN#XG4|-moDR>d|=L4^(5Zrm=fek8=h0Q}SE^@B?Azs{2Gw z74Tz_u0K`q8sLLiF6W898ok}d{2dQ_)_frL&)_^g-y0RRllEH+yb|RS93%P3!v$a+ zVV^?SCkcFKe0RnDr^x36-xKo5$ub`<0G=4}V3@DO72>yafvfujr~VZ1Zji5eR`Op6 zyxA;y&VoxM|3$$6347LlCHX1bGfYmoNu-PXduW#?Y@LZHn1OL2($P=#tz7y&X`|}L&!7O*ATMPV7q)RE zbJD(i;G>Wqp8u-=u3%5%0q|B9E~zOs1M4ixS3y44lCK6nANizw8u(?kqLFwF@UHNW z6VCwO$kMHUPgBko#CS^i z1n_dSN8)+Fcd?#}^Qi6?o`ig{RgU?m5TNdJ=q{B`7qcpmTvslUI}ckW~7`D_>Gv)OM| zAz!4g-1XGm(SEEL`!>w?KMbevZRl+t;UCXEalH)jt$q*0KHrpw z2=;d{9N;ftUj^;92k;VW9{`3mb>j-L3-=8qA^#TjVEvd6{EBrVPydDs+&&+a0&brV zDg@qmFZmzRZx;dQzKWtxrF=c$_P&ZUf!p6jIS06XZ`QfM8_yqMf5UmeM_T(BW&)pR z;ibU$87|{2?dAjThkXpRe;M$aTf}b8bK;jM2R`>J!5iBh@aOLrykwkE`M**}Lw|kz|O>zkiQ!GSzh_TH+_iw zpq}gx{5j?mI6qY}8|{nbQULk%Ir03n|F1xPSbtKGx6i2+0#Bhoq@SkI#DTe&q*@APuUjlrswO;mtZvgK3aerE6ODWF^(0g}(;)3Y>`6QijO(9@|}Nybqc6rv~!Rz>k-1 zEB4O-Pv0adb&}8I$AYIIUjw^Qp8gXD<-&Ga3iddE%A8J3>GAKc#^mgnSaO1%4guNxU9-KJ*jM!91Y| z_EArZeH`Ei;dujmXF?x83IC3Vo%vjaz+bpTo|pQIfUkm`iI)I>nC&Z&bjyI>dz|R0 z1s(u@2t_(xWL>VVf<`QiKD<1BmTp?^ptpR6bOz;A<{J=QDWk0Jl8 z4<7LC%H#E+7K11m;&a0Y4b)sdC^Iz{fo=>C#^p03XVH zLSCfw{za^73YSQ^R6*YM+bjj1LAkKK{~h?E_VN1mDDV>83q|?IfZvAaCH^?@?~otj zPXPbT!k+{_`uKRd)xe)de$-hqK63x}LMz>;AwM4F#dMzm-fE>-Duee3+%NvR^}Nd< zKh@In9Prh!8`qo91FwaiLX=Ay_~XbY@fzT}!JkHdbq4qs&_n&Tz583c&sD(tV1CH@nFY@87;&Dw9{5byhvQlu@Jp=rqR`eK5;Q1EL`Sv|`OFiLt&RxhK4Ee-L z%r~e9{Z$72fCt?Et~lq<)0j`xlM=}9j^|~+Q3`zaI4Q5HqoiG51pIL1r}hcy4}IWy z$WIx*OJ4?@e%I7QX-6C%=!Z`OuYi0@_<>n(tAQ7z{?MLjri=1VfDSutJ14sDHr@C9 zkW-@Xlh3SbrtZH>?Cc&Y;|``XoDQnK`dsf6HLP*p?dpp~-o7X7>;A} zm-j@>S66+Wm-`&kcju~abeQ{0-5^()?{u2;`_6zJlz&gI+7yvD@#gFM1{mMapMPwM zZ^F~}ir<%Wp$^yU$)n+gf6e3khR@^izZe?lE9<{-T-93ZW7Z7aF%tHF%T?wcH1fTtb5(R7u)&{->KSd1=sws=U0ykVYtm6N zHlE(+<~%j-KXRVWRnhwmoOG_fqg43nkR6n(!{(l~lwNFjCj3@z<2`G>4tqM>TJM8q ze%+qAYLAFL4c5q zoU3k($gAGD>POw47~k1HS2+>=*-vuSs{T!U|G->zcO<@v_o%KvzP_i={M%cTs|H2# z@2t*MDII3}Qg7(~BvK!PwYe%8NzdruzVJYom-|_+8XnPS_@`LmBXoT$)Ah~p%wM~Y zbp4Cmr?5!pm*r*nvm^D}*^sN&{G#IzXo^4cP%V#ec3rL-yKU3+2MxNsJ8Hh}|BNnm zZ?0My*%xlG%XNJ28xN{;)%7}TaPyb_Dpw7R$Om8Ms{M7?v=@=sy!oz3{H$p|UpDcK z%n$lL0NT@p|FIz+cJw`sQGVrX@$lWlo5E?`pP#PNi^|{E5KnJyB)=xT(fa-bL-}{y z+NQ8tpzD{_9`4ci!%#N6B3C_mgYIu|E+MVU_Z40LX>TL9NXxT4eQkdS;}yrJj~0H@ z)vVVtyUV!Gar5kEEmh{oW@^%4!Ap;lag&}g(x3Fg`b<4;y3jk}Dj6TM14SONI`Cb= zId9AZBRW2s{6@#eF#o#0H}xZZM^EMI-~V67NB_>A%F(}nH$EDBM8`)H{&(Y};r~yL zk4E3W8y^inIzF24e`kC&@uTCT33GgO=J(Y1L-cGMAAKG6^pE$DI(PL{feuHZ16`kVdHpBHN0a_WJ^n}g=QVo1 z8VxtM?xUHf$5)PzCjS1B`G^UBr{i;cG~s+}{8#$^8-w$&T|~cMl~e;PeV^*}0%iTB zNp+OwN5|84T3E4g^D zw4#^Zr`3X)gSz^h0tTT6=@Y)2~v12wC9t zZ@9oaLJ#$)fS-o%l$D<)>)Ar!4&)m?mG?xYznik7X6`!!8k= z=~e^pY55`3z-Rp;@|-`^0AD^+aPITW03V3+y~JyQAB}X0XMuBnDg6(1!22OT^hebL z{|e7lh<$zk0DcDT2EShe@FS5Q>Y+bsu!Zye@?loG^i%zabZLhU@Q3t3xe(t8`01a= z?Y1-UA=Hn2b_9Mr@&kKK4XW(9^EZl7xS^A>C5!Bc)%iHNUeCKbQ;op{NfmmlW`QwwH97&mq9CLq1*X zhb#m>0($a_#otu~d;sjm_Xr+v`rGM`Ee75m`79hP{x|yTj)Wfi=Y7b}MEREDUVt*- zQ)wSOZy6@+r51h-@XLU!p^|Pn@H?z>34kwzol`r?dyq=t^Qa$wOTM4I9Qh2Ip}j(W zS3GY9^+&-mcQEXqLH=`q|MObZ2ei8c@PFCA4Sa9tr~UJQ(+^qDUh?k%zYY1Pzfrq3 z!oLL;UIKi7=x4cTS4a4_5O(u6OF!uYue(8>pZbZ{TX-4dAB7&)!*bv$tA5@D{BgEB zlw$?(0mx?>`El_6?h5qV_3ubOPkboqTV+=80?036`J!Bk@t*E3_A|gsfWL(NupCQ) zKMg(gXJWhn&hP1Q-@AixkoQCIzQ|Knx4YXII(^2_(B9l1QZwxSFdV#h;C1F7?xDwo z;gassE{p#V{!xhz;gFF2^01K4_~jj?{?9&k`cGl}UNSQCo|N))r2K+c-w9tmx!os* z@yRc)5d90@-g%f|1oJ1v_~o|>zt_h5!&gPl;_)G$&&PYdKe*t*8HSM^Jth`Ey}QJ} zX5i9EhT*gv665nbONS)7>=*J^#`9nH;{&1ml+t5E2f1@xJbw8DqJLzs;bDn*D`%Vn`)L(v^#Q);3o?-b0=fu-*K>TNS{AW1y1_#FD`>jO(3k#=*6~liz{(SDf zVxI@L|N9FjVRz_>VfuW2{}^cx`yKJhrH0{jkC#uwddc6$VMW73ereqPIXRO4H!IHm z)bPFPc>0+KCH~}r6|aQxuaf%1`{;T9eEr1dzcKvmw{d>?BGJDze|5+Y_KH7$(E`zb z%Le(tS^6}IPx}|ollVm=c1?!qj}ktgUtK5szOUck#_-bziGK1c!2jy(bZFlI<;VQz zmrMLMchucy;(N#+S_pTSYz21Kyd_|r8Q2M_LNAT1&5`X4h6$ukRxO1E#Dj)oc%?rYC-$S3BWd7m5 zJuM8Ap9B6ChyT7I`*yD%66(kJL4LtoGT!ev^QmK_e5T*fOzKBEu|v2N@;6L2 zVvY5q;cL;qymOyE26y{UF+>%8D|(AtN&FYyTC&;T!77PQeo+hI?>6rJdkxYjehm0sA2mo#=X7fo?pWbmc*a04Ej&H?vGat z-=7%gC-L3Q-MvHqF#Po9xc%$!y$Y}I?&16*d#v!8zhHl9$KMwn{CTKwW%fpYnef^FCEEyp(Uk258NT;~*oX0Reir*w4^Bz_8z+3$-}En14_AHEag&L! zy2|+H?jiZgpD6l2`A4@O4cpyW;*(#xNc6Y8_>}z&KfU32LzJ_N#4jAMFbubPZCUt< zmTccs!!Xl#dJBKt%ppe^hL;)@=e#2Jd*yGZ zg%gWxhY_*(Mc`lPPx#$1vJcAm#pkai|IXao4c~o8_{Cktenp)n{kJx37tYVJ4@m#d z_}P9Uw}0CcPB-z@(0KfYJc&Q+iYwO|wuAW8U)V|b{fD)jXZSw&tUs0gqf7`}f(SPYHjm%Uc(bHKpT(T1N*#p9RbyOjkmPg-I4?(y;X?jEB5 z^YQJnh98WK^Hne5KmX#Y>X1J?&aWII{Egj8`h|Qef8IRFUq5$AIB@#M#Pe4)RO0Ww zq?wElBjWniY0^G-`R#2{bbP#jD!_Mgo2{RJu}NQDBkeo8r-)ZwApPq$N9G=CmdPMA>JpH1tjsC!Tew7gZx6YVwej2Pl&4@MD&%F1={v!_G z_cMb#UB?>I$oI;noF0ArO4)ijB%Z&jH4^{i$4-(59T3-_+Dq(r!+mdr`BN6Z0sQla z^bF@;KKMzTyGk4^>31A`^MfW|?uvN*@_(0Pn|ItOTO$9NGGdMS&w_v9uD8xKc>32k zzv4}a-{<-BN<;pso*|9#>%bpUJ$1FgoiUyvs%Ce|m)BqD=Y`LN^K)m0*oXXdTe1I1 zZww3ThdVva&ny-GXLIK@H+r*Hd~b-@ud?s1Jq%x+8@GS`aIt@8{T#=z-P|(`X`Fwj zwiEr%<{4rAcRI)UIcueTU-|q4VMpxUH#HW&>LcMl>*jrH7{Tl~zxZY0f7j!ekP%FX z^Su{^U+`l7E+)QvqVU;1laC4i+kfuf*6^Lec>E0Pd%*miLqi8G;`uLqRN_DS)k(8W z{NPxL&-rs1=FdNO+k1-PbACpCE%?3P?6_)6{N&qGKR%uGW^zmXQtXV?N_^l z@JGMb?rDSjt-@}$kza%InRNaw;rh{;7LT8Y@n!q0AC8ai-{a$7NvY_cG^R^0qhIYf zG$hPl4$cQPU-SH3hT(J^67o}fEedJg=Td)q^}FyZ1MvCDF9HA1K1W^~0eNy0AyzY_5m{BW|A&sgCzfAx<^{_~&d@ukt5w&uU- z8->5y<*#39_`WrNPUBqJrw3jn?bCX`R7UbS`py^LG4X>{@$#zxf7Wi*QgGkK`E}qw z|HFpQ!t^JfWk{p_3f>j{OV`dQH+Z^L*v&Wci-$jKVAXt&UBc&gZn5UyH_7uIbHYxc zV*fZdly9`p!P0)a9eUoIhT+~CkKfQq_%FTMDl}}m&yZOBGUV@;Z_WtokG~;4{wCj( z{4ZS5;?Xc-|M>hVZ>{M6`+diR^+PQ`Gp4^NDbF{<+b%a`Sp1wG!r!)TN?*hGEq?Y! zsejw#oDdo!NQ!+qf3JsqJ}b+dW8$Y*4mG6Fz6sR-u{qga3?7^pum2Ux#Xqxt#2gtI z8-^RP#`wj#Qh)oedwVB?2h%4SqMZFCUnTp<^C$a{nrHBIpTUMGe>b6&E7(iqKB)L! zDp0=gvn}It>Agknn3wmy)#ypLhQ9Won9pSAE;4Mj|J&a^7ybi&M;Da$-aC1r+0?DA zGvWB-bd&tMpp>)y>}mMf>2Gh8v)&h|C&XXO_XZ_c&-s<|9KSvNe67i!f11bzpf2tQ zFWpA$``L4?+8eo`Q2Kv0Tqx76gP;AKH|I+MJ}SlKFBM8T`+bKW$h4jBJt&vFTk`kv zo==IL7m1wzkWk81zAg6aRCLgxCV%NUQV!nLLMc}RKk|;hf9D%H1-Ss!KS0W>4*skY zZtr}Q5px$xdkgLtO1pU1i2MUL4B6Mn1$#=lr9tbVZ)@*g(yfM=XsV>Q=t(FUhtgxZ zb}_hf;bcP^#}mrsZ5F#s8UJgTA#Zocohvj8eR*R>tQ`0 zpOkV9r-{A?Z+-W+f2Xg+6S<|!TVM6>GEAIUjOA&u)0p z$ay6V~m`dC~{d)%9X(XHPQWE z+R?Nv>#K#_<*j#WXViJq<8mb!$1}T1{ytn%-_6Jci)B1g4-2JS(QYC)@1u6%dqGtx zd=FGXU%ex8C!LiH`xo^PwDofSNSbe9Nq`ilKBeHNN*sb2FgEHO0u z&1geZ`a7YNYk*&_!|iLr2Alp&_`&+PoPxgJN@xCJ^ti8p|5{uw|3FE%%ap~x89D!b z;d>v(F+AL4Q~2Z-FUfjFZ4cOds}T&@^)S=-QXkkRL@7QVaIk~>oL zy?WC07mS=*CHyof%cBDJ>sI{31xC!<06iPy`pRIxlg{uu7`b#7{7>U@iGw8F{x^Mi zs*!WSS14zun}J<6PCH;$sP8$^6Qtw%Y6gnF8{d5U9wV2f-8RML>QEjhPI-2)k#nDc zK2WAxHVAg<>W6;MH073wJjcQMzEbbs&7Sm)(dWM*{;vR(a@hk!?$dRXzBY2%Wg@4Z z6H2*!_$w!T+2O}f?moyZh|9T2(f8AWpKdU6s-^H9P#^OM?>cFB*XKWYTPSymjHfOr z$G0rx1}%6x%wKS_$fZFk*KqyfP)&)uwwL*b_wm>;?0zVea>;k4A76OUn6RDuIY_sa z(EI|)SN0W=`}L<$;rzfqO!(Qu<8s0CBDZGZePO-I9x43v(Q&z=YLRPrvu-Dov1~u# zy9IGM-ZNA3?s?OUoOcA|pqKe8ds+029v2KUa_K=Lmv!U%GB1f-(Xt)VMlO3I^uZrU zeMN7I+&8U0=xXGgLm>yflq-Khff-KX@VWKq(hI zDRSLA?o($3oEB0~d{92GEtf_9UD%OwcDjCl$(J_(&w=+<{y0gu{)ENheA3@l^5=FD z%J#9f{UctX4BM>FIV+^Sb?cZHzCcW0FY^KgO1To8R~^0cN#~j8b#D;4tRLh?7g z=ZT*hx!{*G3{h!N=MZThd6!DMXZQ6&|GTq)VJPPu2nxA|%S5jChC^kX&Icbfe~{>F z=q~BrzGvZnMv?pW&`_TTO1Yex1tI?N4V&IF|L~4HD-8Rfl&joB^f}L+v?P>!P4xMo zl=GplVEdu7jhy3(J{Q!({L0=hq=pR%)AdLpXU~h(wvYo&xbnPJ@Uz^|ZSp5!{@@>R zN@bZrxte$7c@tl3cdU^M+6dnTrCc@Ev&~j~($mOgFBCa7E3VILE9v)mvaFnOO3vu-$X-HaEYw9T4BvkBq$Mh+MGCmgVa)KlozVlKYIj-wE;^Mb-tn9o~#q&)A^`zykB&-}U<$~ez(@p#eiESGlp{-wA6!{`ql z^$bzzDo}(gr@@|o(qDM!H|l$c{MPn)IPkanSVvNRYx_o=F~woNT&z!NAE%Gxzv{z_ zDvUs|QQRomuY{%%E;twVyjtX)j}8y*slJtUM)n(_F2a=e=7{{K7u*`ohusY#=YXm& zBusgAmB@dWdixQRA7`cT6=)W;be!ZTwZp?kOg;AH@)d?UKTb461^*E0BJ9Dh6Wk;6 zqh@Um$8C4N!J)hlng(@x3(k1yo|3Oo%Y!3K1h=2?)j>kjqMFo zUDP6pcUJSKC!2V|{-W18KxhE!BEMPqU&_xAd+s@7Y(EpvSr`uQN`C;#1XcC{p+3X& z7KM1_xzawL{OzI>4A7XrD~E>s05l8g;XQvE{nCW%Zv=er@9UM@xU`*q)ZI_|O+H_$tE6{eX2~xmp4wm9w|9V0 z2Voa9dxJb*{u5%)vKgmIKlQuFr$Muz>JPygulNc{Z{53B)tltfOTh>A|1RMGv_4nT zslqz>=(pau#>Df-oMMPdgSw#JX@V=zD(t%|_?wJttu9*C&ct(yM9w)ysEcp_>Vq`Q4U*PT8qoM*VLM;bNC&k^b%oNg;&4`Ify z>m>2JbnI|z7;h8C1H7m45LQ169w5y4MYF{2>pxtQHSyhDr2hJ#3e@R@`rSn+<7d8+ z^zUsx>@5@DyLq@FDto=q^o>GQxlm`GP{uF)TH@cd$M>U5Jin~O5WP=MXaMTWld!s4 zDC3uZCGlTfomw46oFIH>ywEIYdJ=H(89%6(_{**?2>+4&L*#-Vgr*U8nw=G@SDOVd zOGy2zc|hWCJ8Oq4!hGL2DU@?=5}HL=A?zT`_})T^f9af4e=!lA>kz+OsEcqwI!|!M z&qw-S>^3``S9;eA-@8Gmk8qY0di_CYKT{tF^LxSdwX4E^+=l)G)CJ8}2<{-vekYCn zh3R9Z9;x?Bvqq0wCgt2Hhp;n8aPKPcNuj5Du;_XI>NPJLJ>HdZJz0cZ#PhEZeioGZ zsTv}B`t0<67o*3&Jg!GU-UAIT6TX66;lW~`Kl5Ly_b}gtKg(el`;e*U&-`0njp*^y z(1$SXM?HV$|8gFIo(Dh?w)Om(f6U8~_*wYN(g;%z?Obz=*m=Z?<;NL2J6Ff;93ZUb z3htu(15oP8rbN%ZRc~)Lda@(pdeXxr>>USu2K1dJv}CfB*Vg*eti1mH(|*-EL-f>Q zK3tH!ZvS~=W6*zao7PM}HgoH<%An2jeost`+vr6#Fz_eeuGu?%j>P>^qXayBzs= zSEvW-09T;YqhO!A4!`LRqes;s9;ovs^damL2W7c$Z5;G|_-o@K^=xfCOz(bHn7uz6 z7pZ4!!u@hScLUmK^WXKUlMdxx~2KO3(z*GjqP>=`ci)OY^LuZITN zd!pC{)J;k_4XXA5pEPHDD4)T+yJ3jvd+fxP{S71A8}ZT3f_w?P`wLYE#QAB2eVi+! z-n@NeUibZZg$EnGer`CuXl%#XHWGF(llhqs%6gwg*!@ZP3G5S9dr5wmeLMI)qc`1J zo=1T?p#JuPJ8gt|z_WOM7h&et-iNKQ51aYnzHAq`XYqZ615oO%JW$5>54O3wD$K7H zFN?4mEbYVrWx6iH9w_xT;Qh+spS_(ndVMQiz%Xc*VfLTcC+>h!uf3n#1)urh{&F99 zVDZxkXF+RH(%)5oFXeXjHOJ(e{Cb^be}$4`Gupo<;h>XHuRr)5g}OTnbq*04bU=6~ zq0C?XEGXP{7Z z*q_KBDtzCP^AO)o|1XCT--lfk=`qKd;%aQSYVu)WSQQKPCkb_cd%)A=PZWL{a_NDo zFn)lr8ZZ3p?t?=-yH@V5_}PQsMl7gi}cbnCG3n6n%!2YzgTGc zRnX&s!oi`yA*}&`YI!+>238hYXSD1NEl?zcq9}D+m2q`f$Os z`=g&a0F>eO5>`8bb`a`<`k-l0)qJe9yIN1uuls-4dk^?3ioFeZcK7s}0_n-wLui4N zlhA8UAoLbNy1)q`bV%r+LXI?P(yT~32$H6P1#B1&D8+)H(!|066-6*a5EKGA-!r?j zkOa8*a_{@S_x-+~ll-6OKeMy5duC^5r?1TJ%QCypG52zry|-j`YUT4p!uYi8?)i;z zDPz6-yPPKZcR0ftua?sxRcpE?PYh7oliE%<+pQxJL!B+EBUy4D|2rl+nuZAaEQpx ze};uyOSY4bX6#|?V@w*$=ebz8BC|Uc zcgAkU9>!kAKE|X8yFOzlV-E}0#q4gyow1KGY0A!L>}2d>>}Kp?>{H@_*-10`d?#Z! zV=rUUoQ1D2d)_X_9>z|Vjy)`$xChAT*V%^UgH)MGJDFYSGJ8A9EOwFEXJ_`>GP~Wa*#f zOEHSY$9MAeT%XC|iAw(2AfM-D`PbW4KHnEDpGP8DK8|D8?IzpZEPj2lvb&2h*~jjy zr_8QgcAVXZn}zFE$}i^bJ0<(~uyDLK`8+YjCB=(7R%TbY%)WG)y^MYBnO!e4F*0WE zV#!ECjgztar3sSV!&vMo+r4c4nJ1IkH!=QxoaCSUB(w9J%x=csubBG@=Kks!+5a`! zE`B1H%kEEQ7Qd3&^#QZrlyWD@~yezYaF}Wn$U5veq z#WLC5&Dh7-$-?m{;k_yQBkSbfN7l>iO=8z!{afyLr%U(cxg^JW6z(m-Brep z|IUsxc3+n5&MPvLKV1DfX4$FUqayk=>7#A~sMP_$RIb83D?0!Cy*%i&wVX@54XjYyb&z9q< zt{jh^28>f#{5lz@$?VHv$4AKQ%9fdAF!wGpyF1D3Wp-~j+3wsTKOa{Ji=R-LJzhB- zi@Ri&Zt8FNI|lxafxlzm?-=+y2L6tLzhmI<82CE|{*HmaW8m)?_&WyvKNbUiu~UvX zeA<}tBgRY|*;2<>zkS`PoaDrmW{Hi8w2m3uOsl8r__Q;7wC9e8oy*OfI$EDSGjl@j z`0T{2oC!&pk4~GMoiHVP^7JuT*~6zzNyy5XG9hP5!i=2Bz(v%V7;Fy&&Ia@y+cibqkk$!Y? z%Sodq_J4Rx|0&6xnx#$3>NY5QRLAM#x~3-&pD>_nR%UwNM$_6mI&|+dYEYBDZ64r4 zBQmFEN>`)5k6y1yqJv&;#?lc}RqruTS|%Z-^hHGA^J%<=R}$&KVoJ)AvxY;yY^{TnyzIj~9l-2P+x^d2{< zd(OFK_OMYm~^vUB#&q$jxu}810Nuzp=7~f*TtY%YM^qMtjeDhvSlKOV)`*7EO19JM~ z)}*wjPml;HB)d)a%xuLGi7I!@`0UATMrARl_MLhS>(Dc;UH1;@ZIUawweQ$Hty3Q* zH0rB;M#kN40|wmX);+z7Q>R{Oz1w$glR05T)5a|PPQ7~dX)}Jz#A!2cJEZkUZ`!!c z^hV5Kde)RSNTGLZiIcOZkC`$iXJVVI7~jRsZngP0mKa!mG! zHd7~0%Qjq3X`j3>Oq@*SwhKrLIeEEKCYJK|$T7K7kiBz6KS@}4)%wlq7Y;@x3h}R$ z_V+KDe70oi+QLPD)$Uh!-N9!pzBji?XL}x&`@`Hv<$gI=?xT`>^Vu?=&3#MucXfxv z8PRV`{19Ww0#GqU+`L87G|cYaD%*|B9>!SBm~4@c8<;(hl}uV@Ke$0Yu48uPe0?>$ z!0etK^6#q2>w8ti1{K9vGh`QAk+ zJMLrm&#d<)*IV*^SNE`!J(vBAk25~U_!?u)G5Pt0Fs{qEDdUce`!OELcsk>SjGtq? zmGMr-`xzf+e2(!o#+u{o`i$!`ZpyeL<9>`sGM>(OA>-#5Z)Lob@qWg~8J}Z(jj@xZ z*F}uQj&cfAxZp##6t!;lU=%K}KOwp2zAMMP!eQUY?!Tl5NCy-q;%dq6IWMPJg%$Um z(Q-HncOE3CClcV44m`o0mttSZ?Bcuf^WVhsnU`^Imd{*_|LV?ew1>>^u5)DU8d zPVPLMhA7~VGV%HULI@}Qr#VtztS@pTPK*P3w*I*l?)ClkIpPfMLqAd#KP;ZZu8obM zAKBvH!V!1KI(*bBBPtJ{l5!TzD1e`Wc%WPRx)%D&4G}^Ip@YDYb;2$|Bs*YRiQ-HC z4SCX?V?IvV4Y^1=b5$y;Z`&`c8z2;-5(I%4I6*0gt#G48DW@xI#7%!aOr9K9vPDL+ zeR)}=bf%oo5aE(d371}r8l`+y-XkHh^FMWWGJoQIm^$ODj<@f-KJ%xriPI+VLhWggK@i_gIo}ziB+#K}x|rm3cpG}-y|LbUUU*;z zsfO6_O!CM^>B&qqbL3SEM^ZUL%CB(54}nTZI!8KoWO`(Gd|s?)WFGy<*l3P4A1k|i zBd@^aW~86GM?~V&WHAvo`hl_)z_Vc!j*VS0F^DG1fKTRHM6gz77kIC2?6 zb)w=(FNmZgTs=h65mqaRq^mhn4?=Yx!nnr5aUczLg-CufInn|`^)$zG4vwsMYy^_R zghGxa6(#|l6F4#pLj7#F;a(wBcjF${vHQ#jduAUk#Vh)!slZx~264-3FWsq3#*@9gix%1;4Kz z`;9If&trZFK4#Y$LjC9B_+rHm?kNub1KD*maGjUfwcL@r@#MTw z2j~arLTjQlv4z@z8Q~M~X}jF;sX%wp-Xe~CQ*;{0Sz00$IxT~NUOd|??D?)d%aPY0 z^tTYtvMn50xn)0);5wbywblslqTDI5mEif^PnYvWyAGYY^b~1nO7j{GGYPH5q-m2g zCyvOOK*+_w3xU4{@_Z->BjNOlgak*|OG)cBC@bgDy!lV9k=+>5^Tjsu{1NIz?d~lI zh8fA;u&Uj4vZ{YyEX}>Lq5i!Uy%nnzp7XCBRqU=bd425v5Ls`~e~ z>VDg=bo`5|cJbY+*K_moycK#9_3!;e9@kgw?pyMFh@{-fIax_lvd521%A7V+e%Dj~ zPPL1Al?=7JC%a?|klMu|!>icct*geDFH#<7r=F;P*VS=V{5#qFdgZt?a#WS$KDJ+n za@@7WS>?FLQ1$nER#bgHB(Q4yc(+%5K7@T=gX4I~D5P9Z+$PUsQ0#6tpGL8J->(|J z>+7oFdtV+{<$hh;s@k1%s`_{DkmFtn-^JFAD|V61tGR9Oc_;ly&*Q6V_E)N=A0L~) ztDNtAR(}49-Q6mUs*<7Mxre!A3y|8KY~3_Tn5(lN#EYOcJQ<>THkc|M17TuiQNce42}%5m?T zRiC$)?Vqh2cfDQpdHd>DyT4^s&v(|W`aFFl^86PiJo0f>yF03?f6_{x4@3P|j_)+s zX~~lbq4f!RjEcwvgn9x&JwXOvZVJ8y%q`ws%#pLgCA{(6@mEj-y&mrex(g5CU3H}JYvA{Vr-3A@8Qv(Z zqPhTkMD+stimu`P;Vu3RA(Rzg2a|4eSlc`!6j$bI7uU%7+p|jMjNV zQ4e57(LmrMMZhplU0zc|X1a-^4jb%SB@QwD& zzZrEm2tC&UZozaX>RNpv)V)7=7}H(&-ILjGp9#)mx)a=&=>x#SnC?bO-wUDP90F6J zx;ykcq;g;Ad0<)Sb*hK^QRgB-90`O_Kf&NMrf&!T%Jeeub*78>g)Jb|e=3*?)x8Fe zoP$vP0{9x!$uAuF2twTtfR8hspq`n|>c1J_flPPnII;mk{pW+XG2I zCxDZf?g4+u^n>7IOy7=r@K>xZd=gyFbT@cC(>>rqrW3?dB#SE>ms?kqWb@B&AA~}Wla+Eg>E3+r^3p@(^4j&~o%b3&P3eDC`XioToeuOEHH~GG>N8a3 zZnFLe=1z%T-`Skir`i1RN{6N69zlLzI@9jdQxrea`F(RGt9zi#$}!6HxQ~6WK^%Rj zUZMD*$3>l7fAogPj3SxPo;nkx^84KZdkaV!q;fr>vU^7y%Y=-CZ1>8~Ct$D4&NDKr zbb?B&Q|Z-ujb5$O=r|Rp<}`v@&@56dMqVk2_)fHGz88HW-v8o{z}&5q(W5ksq>4V9 zQ+!ygK^j#wu0U$8=mkvmr}{baJ_#3x+M>mlVl)vF)rmYYB$^Wi5}jyIR1uMQ@LqO@ z5YesYL<7Q15{HSna|bP@Nq7v(5iz_W&=KAW=nPK}SCJ0ky=eIo#v#S2!Zcw#(T0UX z7sF-(-C;#kj~I$Jrz_%dU|z&x;L3-ao%+*@ znSmwI%lMe=cUJ9vDKO;G_m>UTZqT1SSkP!4egW>E6M0b(Riawdh+0u6>hWvnZy^r% zZqIJ_#+AF>E2QA=0_AR$e4^9>l~i-T<4P^%e#e#bXdXVPZfX)Jxw5==kK-}y zctE(xDAZ6{ZGn1Cq=gHK3DX4;b#$mXn2#{jjFN^y=)Jq*<#g7kp!O62p?;#l4Vmr$cVs%j zd$|XDH}?ilV|pH#3O(0}x?eV{|BV4JVES_K3Z^?bjx2{z{~j>;66MViyidR#Ak^K5 z_xWX3Px=FVmFeYRKhp``;{ohl9t3X5^tRwZO#cyeCbEm+3C>D5mG46}AFG{j3J(GrbVJlj$BkN8W}|KfAz(nf@i%&vb(O=?bBK zdV!y0`U>zyraMs&8OrJ+F7OzpPXy;M-Gg#GA40<^0-s9F257N#lX#r^p93DuNZ%x+^G#W;*G z<38mCa+zCXdoFshZ3S}H3$~5G0^2s=F573e0CLlI6MAV#8S30F`&>J6zI_o;>##c_ zNG(U417j+VmcVmcFKxvyRLw`t=t)(Q8ugB-CCEVyqi06fZ?MQ-6-1Ba{5=fy8V=31cw_0E5iwz>en5z^>+A zz=zFQz>(%WAhC9`a-@rOJaCfrdEgrBE?|lEGvMdeqrk7Nr+|9Y7&#)61tgo$`iie6 zk!o9am$D7LNf?Q8cnd!(_)PB&_8Po3yz9t%yaAe!Ag_VYF{;)?>kag(3H77+|7U*b zGjOL8BBo)Zv37W~q+`R&jwIv5PNeqKF7D^Tx{13=y4N2!vFCNZW=54Khabv8?rEfB z7`(mT@w-l9e(&;+JS>^JPN2hFl0nfY84G(s2QUs|jOLYWkP39HEH!|eGQByt1Jg6W z|esdc?#Eo&~V(~%SVU)XdQHsZol9&a6OdUQc#skLz|hcR&Aas`*#^DXf%} z)ysF~x=J~w_*dNTcRz|hg{%8l?niM~{57bTAU12%Bq}Z?Hql-uzHyABesXl}hE1)i z@L)X`5ui4P>P*@|5+WEZni`SHG%7hVq&cx3XIe-z@#E|MFDoO18k!8 zQ>l*nfX{*qW%?lN&N>fy1Z#Q%Ifmgz_#Via-O7>w+E(|cLa7S?*;dd zxcwYY4sag>KjA(D{?1(ix@}M5EwIw|JkVpy2fk_h5O0SowkyybjXhR}S)+F??962g zDxOo5O;L^rjlRLc&I|uEbDXZ)(U%0C6RV%a|HHFzl%D0NewOeL&%#l9mQ#MTO8QXJ zi<0i1dS5=G99LM$7mEE~Jx@v#xa5PLr?jsg^gN~B@}TF@J`-vl^gN}Vc)#yx%6RHPluwsadMV5)xB4v1wbixn^{ogeGlNrW#S4J}}%Km)wFk1Vz+pkkV2x z21mv=Y}BfDeB;)%{WcXsuabtoPC6fj)`h$&D-4)tyYSw)?r<)oNQg;NEz54`5IKM&R`cH_*p- z<7=Q>i<&S5uH;GZcBa1pevj$oG~VA3>ZcC40n^<<99amV?u)=nAT+L)f}djUE5PfS zz7br=bTSTgCI~$@13ZxFgTa|h&jQb2`fTtDri=ff!6k1Snr7XuG|BE6E32;$dy7P`s31o?Sh`K~gYP7Rx!U9BtE>Nr~awIe{ z0{tf~6I5H9LW`{4y9BKsHjV_D$M>O@`PnB+NJX?3oSf((y|2l zGRtP*%a(k&6j(lh?zMab+;2Gumya!U z)t~~W*7AC-S|=E^s#no_(FeWFI7Ff}-)Z(>Tx6y032v3{tnMLV2{Vefv?kGtU)?}V z1iHi#z>#7O&|h)ge}mlcm-|thMa_kdtI;yW(HMCSLhs&#{Ii+mp($Trz7~YKqn$-W z2yI*2!Fdqs?!uTzHX9ci1s=`xvEb!QUkP5t^ryiuFx>+#Wcm~4d1l&s^c?U-^XtGj z&F=$0Fni4c*<;=h{S)(Hvzi<+ABBG0eA3L5ug#~SpEF+qUN-*$q(;U&?Q^AnQ)#~| z?>D794VKQjGaeGb>`FPU_^V#-qBxCehNGOX@V^^Q z_22iP;V9=T{jUG+{V3rm{Wbq-I7&KD;#&z{Nk59aQjb$uc~2|;6@LmV?hhJ{@_YW% zaFpx+r{O5+`#%jwiMRhWoa*tZ{Lbp`%Jmek{=5|Xe|kUF>xcjD{V3(szk5H*dDZzr z@5jN)xBsbdl=NJiyoB+P&E#d2)GO3R&Eup(nk#%+e+6Af<@({5ZqqXKZ7(;i1gir!2zbnN9Qdv2d!Wzs1Mr;b67YA^6(BL0fEH5#FvwIN*uc~R*xHm1>}aBM zle?OF0Q;Ky0SA}{0Ut390lG|Cz>%gL;0#k9P&NwRFaE3Nt7hy3r9Gvbr|`cUo)Z7c z`AUDdVpqbio`3Fle{HJ$J|!Htejc9V0{t@J3jIpp)A|Bnk$yYy4gF5N3gag4Lf@tT z2zWq$5csM7bKnX6w|X`CPJdd@6QBMExSZ2h0G}|-GayXEQ@|C5RluhW1;8T1cHkR^ zH-S40?*exj_5lwVJ_dejI0QUm@EHQg8N(0I&l!FPUN`uGB+ws-US~%V>hsCT%ah@f z5|e`Gm@l9{_&hKMefRe*$>Q|1Gd=8|HaK zXk1(cmoxnqxPs|qJ4eLVA@F1e*Md<0eZeCjblf2uJc_x~8jTS`{m|a&x=gPRZprl4 z;5JN81@~Zj26zb5-QXKcC#ZL6Slvqp)-&A*Zp!qQ;MNeDZrXrTneGI4g3$ZP01sq3 zXB3QRD;Z5dt1$o=Y^)D#U~~XejE#UzjC3YkYhyaFld&_fo3RJ5udzSy5#tcxFk=>Q zq;Uptu5li4fpH0Nxp5_MweeZt8sm$=b;b=wo@_L3Hmb-LV*#+xSOoXijPC+VjC+Cm zjR%3B7!LuD7*80r-F8yFnG6hk9m6GKyAb3+SYYeQQDPf`u-pm#EK26i*_ z06t_GXwZ>ChDV?eHH?Hl$}k-|fzT_^-=YR< zvgbHQzQD`)8*n*9#I5IXIO#cvER?3ltP(pqOANdRO(eM)e0(=re z@0n;+XfbItMxa>}A+?@jfTAW9n5O9p?5D{APSSh}{9fY+W@z)!X3y2FLXX7rx--BZ zbaXU2qrA;6v?XsH2A19O19K~;V(e;q#ZBNX4sRA7esS4Wm!e0!b`cm+62u;H)!8@4y+h8x# z_k#C9sGkGiPni2>;A2cb0Y1s}GvKpKS1A=7oJ)tM*C4hnMAV)pJExXfg=HB{u;-NKvH4FGZQNkfP|dQ!E=L9y$pQ2 z9}A`6>8-Sf9wwhB(eKE*2!8c*S>F!!U6A!M@Q_mG|1bE*QbFll#C+FaLDDn8vl`1f z4fY>(4A5irJs=D9UDe2UT-B|zO}=(zm;YQ>#>y>A*=(^`tpNdnfk8pRFg0Lm!i2zt!i2$u!$iPD zG84s2G&3>G*s2+^n)#y5n{vhA&~ic_R%MS2BKI#&#;2qKSE427=uxA8Y7L;P8OT87a<=XwyDzAMjXe$aPU z<+(E%=tolKG|{=cyCF1ux+ZcMgzA;&>XY*vu|uePecX$(*0b`Q>IZ!{R-V6;i~CXL zRe5nQr`i3ua4&i6ek!jQsD*oJ&+ca^QVDu4$u>Olx5zt0MfURh@NW8&KMnjzTEX%g ze+eU%WxO9Q(}ekgl`Iez=>+u$w%s9t9K5m{+D{C(C5WHkMw>r?iBE5TrH&f z+KKg%-rFViO$;Xe69+@rIRcRCYd9i+(T>zxwGM?=G^vOo%_`a>y?3e@h_pYrVhD7d zzm>lc8SEeCSCQfV;niYNxo;&NMzDzch5g`wda{FOq3qMyPX2}N=U$KxuyyR@lNVb_ z4nG7AvrJ>cb|zt97o$vwkp-X**64*YtI3T~F7B(3*ak@iK6xX%5=W1I$B_ z=5x(6feoyUtf(IaKaN_6yz1jrc&_-IW~w+#MC)H%49u_(vm@o%UA0f}nYGu}#=4K% ze&FzvXH_)y9)pgUzT@b#44Ku1B70^ByPggpju zf2iYtO-#3f1DGBRuFv!aUS#R1l)q@t-1mk7j?o>=Jw-d1yoX}kOO8W7Nv;9^BJUtS`}iM$B)Sf2K=IL!0Eb7@ z{`zszGk~+AOMoQCAA@?Ym?v7uN^zZtIJY-Me5TlY+M_VLi_YtE#plJNrJDaF^7hjF zZ-Kw(`+<()LB(jd6^{UpEFJ?S4t7*fio-G^I0Psb*9F!uP6RqIyBhbY8H1XBndUmstNmDu=dRB|DREAJ2{_V_gVyOe!zJKI zV~!EJ@e)w(b(4GYMw)ZXaF<4fGAsivxCd#3PPE3MByk3G2|x@4tO3ev$pWM`5gnzq z5=X+nM(f>OX&ppHFE{X6)d^;K0~GuZ6RojGe4ew63=*5HXW*Ib!z zZX)$aE7F#%;5G=4sh6ssRzIhHN&SZUJ@rEDt)ka8)%DX|(WwkI3}J>mOOfS+fF^-H zRIQ&3S{$@IXhV=HI4(FjxN&gH;3dH;f_Db*3Em(4Y4GvjM{3jv4-Ib`uE$#0f+%gY zA-Yv`+vt(eW1?3?uZ|A1<W82Mb{%w7au0Q(f(f5w-I{ML3&9R!t zqK~yamU^tiv4@U%PHBC$e06-M&;9)K#h)+z?EhI+Dwf8U)-P>T+Pt)7Y3I_erQJ(2 zO8b-!C>>P#Na@g0S7}!1xY8-5GfQWe=9Mlf-BMaq>Mc7`cHqX-<=go^C|~#UU)(Nh zFY=|RO-&UZ6*O2A>eT#9e$t#nTK+?O6>0f~HbN(o+PeBW75P{6P-{LHA?NMG?%X*V-^ZFDSI7rh(lpmGWQc>HXX$2kc}iC)Z3NOr`N6h{-( z#9BGlJBE`Dj+>65m_u6umztixw)~*FzU9^yyveraZJk2aZC#I)8=7xJ`JJ1;C_fBk z`5(~#%D)agTzIZ9l;jqDS2TfKDf**`mhQuf@dhr=^=lvA;NK{vWhAA$jA*YFTf0u3 zx^?T-t6#rYs>!2=J)^D$oswA4}-Cv z*=-Xm2#r-LReGgsR(mFQSy#@TJ9iO8q4~EB+!x`9=e|ZdWs H`Hc>w4840_at6 zokfd$a~Bb+&Y!=?i)+vK&Bd+U@A8Y-UES~Ew{MH4L3FgCkL7k38`dEkQFNIxTgr;| zSs)2QS6dBqwuNBzHQkSicDO}hrD+UiR*A$;YLQq{Tk3$TN9vO}(ttE1@g#vHVqJ-Y zB$E{ML^MXXTvO5vU2`ok{@04M#>ih=l1iK;lME+WWCY2^`sGn%G#Nw2l5u1_)_+eV zIq15ZL?)9dWGb0Prjr?DCYgn{<6!a#`tydOWOk7>(vGwz>7)bcNIH?uqzmbawqSRR zCiWz~&;|Gq>5bh)9!6JSKhmEJAOq0?eT+PgzQ8$^%U>zt@6L|@{TzDtJ^k;x)Vgyy zOs+sRh?zUi_t6I95iv88vAn98t*CztkKn&<%%QB`J1izD3jeaXtwd=I29sH%Ga3v! zqfVpIU>ORK8m-Q%F&WJ0c)yp?X?5mcvqfW7W7;D4=8u}(}VEY5IHeW%8Qt*j2yv}SIFxq3r>(f zk+-i28chJN)#%U`NEdsfujNtkaS@}c;xb^E-D$5+((LJWjCI*p+B=X{_Gh5KXkQET z*tgmR@|yi~yGRb(zl46&{s;7{c7H97h_UuqTrqYndLY-uz6t%?*fYSl>+GpxAb-{I z*Fj66uD9Mp+@5+L)x+F~dOrcn>iK~rZf+b#!s1Qb)mpe^1oy&*=S8+HfA zl@G6IA&jUPi4iiRKgu6SqWv*w1w7&(iXPpw{_}n<`PF|BF0YcM!c)RafV{!n>U@2n{&oHLdX*v0kZfpdXl7_*7-E=jSZ-KtC^Wooc+0Tg@Cgb^l`+nkY;0^C zYMgIeWn61qZ~WM3HU*mEOdU*JO#MxRO;4FtnF>vBnf94JHk~$=VQ?nU+`-(%>^9Fg zzhT~GK4v~)o@ZHLS!&s0*=pHmIbb<#>1=($`hoS3b$>vYp#DJv(awB5Xm`+_pc6rX z!S0X=p_4)_VYcvL5j`RY*aq1iu?@BDuKK`mSS!Cm#Ir4 z4|SXQ;?dOaP3sTY&mK=TgxVIr7x{InXKwR9FLe4QHQ?72U!PImr5@3II(osQr&G7K zJWkYme5sZr&&DM0K9l<8qp6*Qch07cvU_g4S^PulQYpM2QyZ^;q3+!IKc#-QsMB&X z_FU@2+MdU4-F{A;l3Q|2U;mfXLp%vNN6x3d6_9c3>tp9rkJfNs)#d-1dMc&wif5)? zNbT!6^U}Ju7gL|p)t!*4{w;O<)zsoO2Y*YQGIscz`xlj__SGC->g#X`Jr2|;{c5u9 z9w@>sptz`rc4O=M_3cZ$^Hq%-H4@;)KV7>EdK?HpIqCrS;+i#F*pR6l{BUmsx8l04 zuFVAn2GZ9I*JAk(v>9U$EUbF~@-6Z!Hpd2nYjX z#-n)Lr}PuyM~!tBM${g{P#0)`8bC|Dk^A9YorQP%SiIAxqu6(oMPwO90aue}u=;cp z#(G}Gc;I{JVgHDHMh=rN$WinPe?u;!NB9O}hUZkAhSPBd&cs={Ag%@%%0+N7Ty4(5 zwcuKDZ83h>jqAk?!6@QLZag=GdyJcn9mJmC=5Y(Kq<#grihG({%WdRd;bY%g6JH zyn|2SoAGUUC*O`w=R5LU_+ES;zCS;VAIXp5$MX~UN&GB+9>0WN&Ogh)z;EC^{AT`T zzJPy~-^Rbrzsc|5-{#-rckw0sr~D!QFn^3c!GF!4}NVD#TW~O`d5Q(Ot*t;F}*gp9)yl8 z#eq|pdt-1jrndmMg3uh(4%`Vs3ydz{9?ZQbxEF+8>mhJ&rauhs524`?1ZP5MIK#ms zm_72ttt2o2{6@M7k^6ug${o4}iy{xZ0b>BZppnNH_3 z(YZ|Yx&*C+tpY1U`vx%C|-?@5*QJ{rE?C7eAaIfm}YCpTJMyr}H!UNBPJ3 zJbnScn12d+eI37%e~I71=OdrLix~_bA%B0)ALWnpC;4yq?|2{o6aO=R9wXRv{F>(V zYrKF>n6!dfup*z=5bQ!jAwftI8VSvXbfJsTTNoe=5i*65!dUdqE)t#-wg_8=0-;EF zO?X|{DZC@RFYFf%3SS~Y{2k-}yD{Dk?bJSKn~pk&1 zcsnKIFOTbk)yVtsw;z8WAvGSv-^chnzs}@Cd-Rg?T#NS%{xnefNoW{=49q@}+;#X|PofQfV?A;KH z`$*TV-SD?4N{vxkO}V;U9&@{UWd0wI!pY_W(~;umMlgK%XN=g16qec zP}Y3XolG!`;GfPQkVggOJx}D>1poR7p+|*x0fd(MRrb|1V}A$;bsvdQ%Nz*REAO31 z_y0_VQ1>I?ubEzX-^&bayfF|W`2j2Y99G`DvhqHPmG^h2`$DyV&~ts5e{`PBL8?68 zx$>Tkbl(m-N=p4#o+IwTIF_>J&j(%EQ!&FvN9|?*j!aw&LeF)Ly|W*Z7rL@%W92oj zxfuUc_Pj6q472+o^xV%eFW3*EdgVPf%Ff=|r?Cv@QnHwmOzhGeoV=97DR@>X z0~!q^0~`4p!A}o=4_rl>QMO2$QRXOUfw?(}g@+3_-JV_6_SRPqrQQmt_<{shgrj%D zQPCUtu+&pAx?&u3e+7p=3f?cGccK+$pyAp1vw^w(4gN&3(eLx8ku%adqF?-_aKG-q z1*|-?2IW24V0)^}ta*>aEOxYX=*}2V<0(IfI*KySWx6!aL)SM3VOqcBvPs@r>@;hvt^F4^8FWrR6=8s_aY?-4OXnnb-3obQ1HRb7Xee zuxi4#*QO#LviUNf!R1J$Su;M{MYt%lX6PPJyj^Qo6N5b%X{M$<+^!-K_Gsv}?G5Za z-Z=@-lkAOwE$pq)bJfP43cZ893$Uksp1lc~Zzu7O8@Tw#Frqyt{zu@2_)_3yY1iz^ zJMK8QPQb{ud+SPHJUFx?EU!SoPt6w{l7TQI#9xGmG2;B=;U1b2nd-i>bH z4CX!_ynyK*@ViVu3jU4hI;{7wL+Jgq2KQxpE_gB13&38cp9SAwdKAj|#;lz02cF3E zmEZ!Ve*&iSbem$*IR{qe>*8{^jYVbVc&icX>@_B}9@FrwT9t)2bFdoqYC)&sEIPA> zH(E`4tzb|St4YVJ^qf|06f6d!Fqt|IwR*PU%^Cqp?BEZ4G;RK^eh477PjTL<#THeGN5WYrFOhzs4 zQ?RIcoeC3uv1G`s)2rZJ%UgJpiqjg58l76OV#G>sF~UWQ`^D-dL9f$b2Op!sjJ|rk zNv#ox#faUKI7ASxp*N`10xn|J^H>F97E~6*iUGe(Ytmz@0<(n}1)bhv#br$>5mmUX zQKJ%g9JLyZ7EY@nIxMSkPJwR$N1kD;dq$ zd)J`FfOn)Ez0fd$fCEyR4`#$htrvC~S zSe}akH)DEl@HnO~1aD;ed*H8_UJBN-JXZ_cis}8pIZR&yewpce!Kax1E%*%6Z-Q&E zd>I0cWO`F@Po`&p`!YQjyol*bz$=(u1m4T^kH8-@{ZlaAW2Ffu(sE!ugqABt@V)k3 zsXSj^%OUY2G3#oda&}1CAx1tof}F0RNhm+^1l0(_xh~7 zH)!QPylB)y>q2Na4}l+M`aZDojVrn*Y&L}Ysr>z=Lj6?UqsBcEwJ8X7_kM}A2cfzTe1++*ukc(T)Sd3fe;7jbNf%KYhfw`h@HVEu z4t|U2+;3Qe2cdqFz-^e04b6xNLfr*@D}8g)R`0}f=%Viq?5XbsoGYzsF45EHqpVr} z4EhPZV2CGe4fOfUGn5!wk=+I_^p6dnVm;?)2Hx0|2*$R?R>W!Sg!QMLjopj_>5dhz zMyyfYZRE(FDl1h#gUbmcXKFxr6AD$5Capc6YnlhW#N;*cWRJ9}{Qz6l{wdt$Rqa49o@;JM=3y6=?$|};3%Hz=_D{KNz5>0iH5Jb`&)P8H z6%rqi9H1u616lO$&SMJ3f1KO!jeLP>@M^cq7GZ+D8fA#H3s%5daNjs%r3f6G?A1RU4qNiq92M& z$&bb7ih1&L@p<5{#TS8F(MH554@P8oGFSDK+Q=D(3LUwHaAjCrO7q?dV?xdGv<0-j5-wWbxraMn=h5mpJ z9)>QrAU8X5?7J($vVufy9okUn1BwK%HF=tYHs9ojueZ zW7iU!Jr*u?&_?7*qP?ZvL|WOq+O4EJYbh?Vw<1gJ&)N;-Ir|#;TxZ`1++=?VxW)c5 zFyH*cX9s#eM@k8+)e> zx~}$lv_wgropmtFyp9*Rx6YqHQg>oq)b8t!!f5t0^>zd0Z$FZTNe$7?XxI_hqv4&F z>re5&#-nbU_z>E!cklF7mgG-Ds&fQ6EF>5$S~F=XwP@Q)E!vgItI%?Nu1YJGqy!R9 z+Bcv6?tP zzQ@tSI*(h-E$7y7n=!Wcp47*B7`^?cxu3ZU+-2?tXW&E7vtNf##<*P<{vq_{XQTiA z34S5Jf`4A>x8KYcVtnp(ekVrd_VGvfQ~dY*8T8iEzIr+?cNM)NJo@Ns3gJSeP+O>v ze)<&j(svemqL-fb&`%U*3iE`e=%0NVeXx6l&xNl9pYWq_UbrCqhF;Yx!k-v4)u;@r z2vu!WoGKo@s4dX1+D_G3)kD=!HCUCY8m-DvO;#3?ZB`YlUQ@lP zdRuis^||Ux)p6B#s?(~os-INnRhLyaRDSHXWmMNxN2}|ro2lEYyWrbC!_{NeQ`B?R z3)Ii3H>qF7Z1(rDi{_{5Q|hzo-_+OCH`OYQSre{_(Zp+#G|e@wG)_$yO;62W%}A^$ ze^fJDQ0*A)1Z}Q%iuN(BTf11hOuI_ER=ZKVMO&bKMY~P=hIXfR zpY{vwG3_bsY3+~NU$nnzuW8G%uZkLzZ31*5x+q<&&Y^3mbLzV2y6bxB`sn)OdykpA zQM&QE99^Dnq3$WHbAMj9LAO~~qZfr@GH|U+RwQPU*hG>h~XY=XDo!zhN2P z->L5JRQJE1>S!O0vbMJJTHng+Y#(&p?}M((t-MaS@*3UBYlbVY*QM)+mG!z#)NAut z-PQxX*SEe1+Gmy9e6+s@Z#1dThxYeS{Uz|f((m)Hv#5#GRQi3Yw-IUEkj5cxAO5p;A?+_}50U)ilv=OVKk-7+ zl6Hr(FU77(Z#F5ZRga5@%e^~xeY5z9m%rI@zWI*MR|fCx*CPCgdgt$fzYkp7D}39Q zxv8teo|tgz*wCorcD%6pg(B_AlAPQQ+~9dZ%ij30XUT%(+GpSLANz2&sc+8W$1YDD zQZo7V=R#Uly#BqrNzj2h`I>LnK2vwh;ihx;9uv5vU9mkd} z-M@a1HGADFGd|m7sy&TwI4~#ve8RjRw@xgYKeg-8^0W`WE!_Udjy{3&PA$4Vz4-LV z(%uiXeIX#_t%M2tlM7PqqD| zbtHFbx4n*%hc%lY8h;?H_od_EzpVZupfI~{ZOxkF4a7Te=zs^3*$4k)SR{djXyVEFKO6k@(-71PTIdNv+l2-x2^YycCXid;GKnE z#9Z(lIzIc*DeT zUc7ObfjEeZ0KVcL&DA8=y8PukrOGb#j=u!K2rr8L%bS8Q2XqIi5Vq z%>m|NF9@{OFn5b5i@0T+imc|Iy>=u=TP)uQ*qTq}1w!X_ zVGTQGb@3#Fe;B$y>5M5_bi@n{hV zCxBn$OPtu{05wP4tx%5nb`I4ryiqb$PpEjZRJ9wp7j;6O9L9(Y+M?=(YJ?zt2S6Tw zk-zKdj#`BFN=7swOwKR~~Tu@atK!6E_d4OZ#v1Zfy6;mH#iE5Q@VPs&FM!H5Y` zMgHT!JdB(0WLf^Id^LGG{~3&!JfB|(mmT>Z0uSbY0z8!e4e(lipW-2cJbEIp=axsu zl(pvH)AEr^L`q2EngUy(MZuG<+)Uss%pAl$aC4DD=5q_7KZ&*lPnKXFA@(Z5OhWAA z#ytakj(Y*Pj$04hh`mcV@)G72@+2Q^5X_^-3`3r5<6Z~8!M%y2JGi%@zr*c9s-yEk z&<4gl5bS4!86eoLg8K$XzvoJUbS4N^Ut)d|PyXcof_{TbLF#JBw?bNK!?y*d@$KP4 z=O3bnjqeG)gODpUB$I{dNLP8n-J^J`kd{`n)#}AaQHO<-f}WfbO5y$o+9m?IF5H0o zEg=bM%!L*ReznRA+@m@KJfccO8k0x;Dv$TcV|Z*EHk$}8aIweO>CIdEBY*VkL#vC%QUgZPFEdVi#K@V`hSdVfjZbE%6l zI~B(4QqcaNhfz87GR7yNwd{%?jx?4PKLYxw_zBP_#^*wx96t@|a8A4%`rP=laK8}$ z8}M?xb8F98?Y53b+H-Gx5m+lf5oswUeC+q_mU&$I{+Aw)dr!_UTb>!qK*D)Oen~Eg}Es)1;lmqEw{)GT2K4Yqxl5?zRzYwNf!U>conx zD6)yaV!L>S1{AELMBf&B%x9{c3?+k-pQR*I-DDn9$RJ zQ3Fl12Kyvo4hd$bY9;`WVv2b@;iNC6{;9pL#T!T0R)_rpF}Fm+W$SbGMsiC(-7t%k z8D^NCxtM3ERen`*)y^i z`X2{Hx`4AI^ME%a{lHdHsd%@}iOK_dqYePSiV6|i3!$PY>WN*fC*pUB&4I1Nw!k#8 zJ+PDb5U`KfSHx~o;!x<<<8Puws*t|7or}eDEAfKTB&vxvQHNeXW1zu7da(U~Y(5Dv6K=0n?1&4uu72E*cEJ!R&AxVY93LRvR^c8UV``_}{ znZGYOjUK?VqThiRiUTU@^bV{D!3>u03P(jK=}^%TdY6jszzjCar9bpx6`8=%6=N%S zg844~=P=hr@MCP>uLTCQm3%^=i$DtH>x_kj;G{Sf#Y z2;JA|JFxPN;^skkb`W|l{eHqxq-k^#OZy+vy$|torTq`P)xZ;l-W}WvLj4Z{SN>M> ze%QyreNRn{*+8hDv=H1Igz7Hvc&5{D6}LtXnFsea;In?_<`-oz(X-G~ zk!R@AKPR{&g!+FGypHJ`z%MbKAP4Co)DQiRavJiF3wk@S@;xp3UBgKb>gUfGq)Z6a z+oMeG1))0qUNZfr)+9{im;_e7t@V2n#_}N4PvvhDULA{Z^Rsg$f3 z7eSwQ5|FNdMLZEFkS>#iU(C#l!pfLUq&CXfVwAXYDNE<*sZi2BiMQ(@R?5;nO-oSL zV(**(LRs6=S{J+MwL!XHU_D~(M!xummSlOcKySf0lWU8 z{ENER0^*G%?FQ&@w82=6JeTnQof5b0tv>ghOGwMttcuYU zYBE-uQOL3K)qwKVbQ=S6GTe`6inpV?fAwVBO>R9)Xz*SG&l zef#rcPBPlmA~M?4`4>l<#u+9tsx+1PM6;T8iZQ2B%2~?DlkudHCs|2oQrjXnwz8hk zbkdm9A;z3cC&rv)w5f^lJo@gZ8gu%=KKG|%Mfs*>rkZN`X^a&eGi92as7AjyVidLB z{rM3ib;fJo z{+_SD@6g`|>hERxyNZ3+`_0!}5aZbX^zZ4e^QXm*Gq#=ne~vy6`T9Kf)%!`)=PzG> z-=n#^-d<^T$I92dLzh>fw=dA?nR@$Nz1<$o6`ITR`O4Ja2Wmc~S?TSSKJG)Bcj*7; z#;&){SD?RV>T+{p|JQs-A7_p(C+*qjb=;%RL-*M4)&FeGEX10G9(-ig%Q9@57?H)g1Y4bmU*YK5m(%ku{I%)M6V^}@Xo1H?ykgknFn>OU zWmGge%*ce#t+yJ!upY6->liTu?O)i3s4pYY90ohOIrpf)I}&MNvdMYE68j%ZX?t@r+~@=lw)dDkpZ5*qH7kV$yp=N>apFmk8@O5wUNU zQ=;_kbUwx3ZY)Y=ZD%AJpR1)S+jX@oOx(mBcwm(XiHaEPcM@q`xh2l_v+h0ai#^@( zPutfs&XbQn+KqUi-Q`L4ipN>;H!I#|Wlluq-jr{Szrg=3uCtN@sjQ023H&+GH*j|# zH}FP4)`yCBXoWA=wBQ55++b<2Ecg{Jw$2S@hFXPk`0Eh5BQ!8{PbfFEG*lLPGPEc3 z8c%qQlv*hdr3}X7Yktbilmf;lC9;IXl~6UlsBx@D^O~*j`g$=j>t(goRz@ZF)MTaI z8OfjbWWN){StdZ)gDt@R@TY7 zy1r-KeeQkde$n8&1`ha4_yP%NwCau{*UEq=WCIegMq6#toV#)nFB@k#q;Nwd1|5~F8y?=c&n9oM-uHwVjW3bQ;BLSYo=ty z)EP&2e}Cxv(D5|-!2>1I36YQ_4w6Jck{C!50jUD(M0s))<8(#=Evh`Y3}m3Mf>#3> z*0;ya`a8`W*}w$QjC>nb)MaDQ^pQ& zB7ZZuIgo90;I>-704@W!k-iFEt}*V<7u&1-I6E8+aM$Px=aYrA}WD*J8}_7Shw;+Isx*9Jm2vm`p>cbT|V@ znJwT<#xTD{7klqh#ZEe(^c)~-*xJF*g9+#_z%K$RXCM5Q*7w8bG2SWX{0jI=AbF<4 z{TTCn3jId-W+3OMA!D6wKq7hxyb55zsMf-xStI!h`WQGCt5o8XP61NpH25oeWqtVa zHEg1HBryY;z)gYVX#>mLtLSav`u$jA*H)=>;RZm`FJ+8#1Q1@a@L{dDW*j$LkLgN`VTrSR#ibPb3~Nn*lz#+1rgf&@ z)tcv`>6_s_TCac)YQ6hztet^u%fYL!Kt$&poTJY}J@^K#-wNNZ^&#+3t&fFEw7vrV zNbBkao+BV-UI42XWsNpd9dJ(&+1Fmy2md3gH-C+hWFYBx!1rkVK6r@Mhrz?O-tBFk zkxv+#ry|Jsl&ua)ObyD1&jnIWCOlc|1@H>3uY$L0{b6{w)}M#J(z^37V|YNyc@H*z z9@X7&E3N0i7izsbe5uy^!Z&JNeSy6Lka94BPighNw0;Oargcmt)IWgauYf<+ z`XN|-8;uvtbhfes$>WAQX}vpqmDc;hBeb3mFV}h*yhZCf;D@!YzT=)c5-qbYED^P( z{DJU8TF-??YkfStQ|r6nXMyqlULq*q-B zmc#S(Th@WKW&Z3`G19C0cld8#EB15#DgK!?WWU9qMb&j?zo&1D*m|{!;1BE7e#y5* zY#rNg^=(mg-J4==tv`_aEwdl*H6Z%w_`ImPX0EFLi>mAAzT`aN}(An!KuhG=8u3c~$*!{88^piA}hZ`g{T`@6C3ch+led{t@rWL;peV zN{P)VaT!y%A0#%T#AOs+VlzryM$siUqr_ztU1BpzTt?B=-hb^qTlo&{V9vk1Z_9xA z7m#~1+iSL5_ z-~f0JybnGAA5~VWW0jTJA4c`W@6kU-{{(yrJ_85AA#fOc4vv%O3;0X$75Ex_1HJ{{ zfg|83kobk)(oy*i9HB$;9mgXv2&I2>gtg{JNIxq7=lfCl4ohrAiJcXTiO4M)>6b`9 zSDuX;pe8s2)B+TVbr{=&V}q4S6PlYR2f+I$y#5b5{!0ewL~a2>cF+yHI_(yzQ3 zNMB9tQ*H&)kGvh+0i0@ zcovX0*V*74PzS^T@kxCzs0-?W`he5HsItOiA?ABP`e5QEH67d!9sqv@4}!meF+3a8TJ(zu_vcFU~n|-EoEQ9%;&2dQigV{cj^lXkLn`4nO z26G&84B6^1dPQZW>22^a`3_gcb6nZ#bJ9P6`E3TC3lqw}BsW*VUS=e_45!bCLYwTi@r z9%3G4HmHe~t;`>8w>*pm-y@dCkdHGvV^r=)jPEXSeHfG+823utO-j~WGmaRyANhXV z2gr}&K1C+QXU3^5gg~kl)Aq6GAGG5Ml(a25YCW=T4}Dte23Eyoxy< zi3vU*`IL?fZn83lWNnRX6Y&>vsr3r<>#Wx!!x7&h<<@OhquS0K5bIT#1!6sw^;zVr z)_1Vae%E^3S_5BE64U+XW5Ex!rK&q^_u9-VY#Tz(ay*VurtNX`Cu~n5pJtAT(Qaml z7|*a(A`Nzvoig!3LVS5EIfsxUGfft}n7oAk zigT}%$ih{8nKW`W!4+0h=AZbbu1k=sTx&^L=PF0v<$4YoObpRsXqtE)UNoYl-&dL#QXU&Tsd=BXN~RaK&(s~YAS_yvjhN4c%W-RQYB@{kK^EJwb_Y!+Vm zh@Z!Ztd5udL!|U?szgeU#z;Td;BW)>l3tPCPraR9na9TKIS5 zyu$g&LxqQt#^ShQv$7YTSsYYn71t?d6r4G!9w+>)JWfhQ@nK|T@i`@RRGpIa60T9i z^Ga^X5cD+>Zz~5%>Xmj-^-G(TVoP1xwbZJ8t~^xwcT&nqSK}*xP3c>Id_Q`XPs>`{(P2atD5r96KHH>KW#isjninfpX%WT-O6_BlW<=Jp0M| z*?-FUf-^zAsGs^quB%m((|*S9OdQ0socpuSc)I&$mEq3hnQiQDjy%uZ5_x{)slT$y zQy+WMhv6G(IL~{$n(MySyTjO9Kj}W6=*EF8wipu2F(qs_Tsp$p2xDPw}gCu*PB18`R9A4rz8$ zO;SP1J2ii(Prf~=KG~Os2d1AGFG=_l(NpHv@x=2m3ro((z4PfYV|4V zmQPC0Ri83B{5hjmYMO+Roj7SSlXFw2O{c^eGiS|KYR+6;_&j*ND$w5) z=2<`bEL3VyENSr)(F%)Hafwo;n70g7%U3A1vTW7rHEQj;^;n^7ycZANo5{5WloObK z`;LcYqsSPRdgRfFPB5Lw=kX~0n%wzBEXS^xqMkgVowoASPjf!~%(LpbpC+G9%5Jqs zMUU(G7j*s?;g`V6`ui)mF#pxh-e1k}&t*9KoH})h8Qeg|1W)Hfa4hh%6Q!YxC zkEe?MKcZIGzt#2c&%F|=>)$F5d3F6;gEQiV zZ5qvjFJCO7|c$n5>wyToff<9nJAo@V~ZeT)}(VoEo^DmVPi;b(~5j)q-T7LvqNgNyL z2G|HBPaU|4*2U&k>|G`OZa5dn8!Zfr4XmV#4eSoBKM6mhb+Lint#z@5Z4M-V8@Mfy z<9rMLNT(}CqGEQht@?qj#WwcO=wch&5y)}&hQ%KCGIX(reN?B5&FeaC-zv7QJG8zJenabG^O^&soTcyv zt)D@E{9GXEV#C@Jh%R=kr?OX-K6o1-dBkp2Y*xATRC`!#SI47^?dq#Q@!8<0F%u-LSU-U@D`^-l1mfKHaW48B^YkA`PzT|8)rt*dM+wyw>9=q+IJ zr6KwxxJc__1G`@9jj(TRrfpqY!mWY)mh<6kt>?fO04b*vEH<<4(W~0b=94y2=Mnqa z>018+n_01&m2H*Sl4^TWv7;3m+D0Uc9c@dUF1EDowB8HOX~L)_lkT11%Yl?rs~?`2 zf#`>B#jg_(J@Ynx3lP2A0L~kb-*Ooov%Q^wJ_$&k{jk{LN)uA-ap#s(M|8!{B8&?k zbseoo1Dp;b<-;AdE_S~Zc@EEO^!ppVZ?ggGTAls_fIA$PvEBJP; z-wO`~@+{1T=j-$Z@Jg+#3hGH9+a|z4t=E8SYyC|4EUljd*Vp<4IP-1Bh1s?d+zd!L zE3mWq1W0}LDSQw}`X~F*f#{zdKnJ3~`yST^NImcwd=NuovRX^YAM`(mQ;} zOaTyG8C>ch5d8tuUwISc;_sJpM*Lu-k_f`%4OdvMw2)#Mi_Ev|vb0c7T6Uvpe=$f4G8 zR;wCsooF?wNkk_Os8!ZAjJB?|uCr2qTelz|x9&tfX?+U0+xiM}ul050o7Vl-ICa2U zX~llSh67^azPfk|CD}YkiEx~tn%G)0=Guxl$41rO){*qiwu_LL*u;0rWwtAk*V_8< z-@djR(eJnAA|)cSO-W2-j)$noCbikNh4h`a=h(|`+w|QsO3? zmDBFBa}0J5Qlcnx4EC1xIMvF2f!(G$+B@TM{v!J&Iy)9o|RB^t9)71$S|FR>RPm)e&jH`})&AGJS@eA50L z`FGo&C+7?HS4i1wKY%=HuS7~DXS1s3Xz55&t%&GsQ=J``I4r80qX(nE65ZLXdOP}{ z-{80rInZ$*QX)Q^mBf6utIdurq)6;%vwF_)68fu-*O6~I_EXLQ;z8ThmySwOBrddB zNn~iV>hAnA?SLDcHzFlYv{_Ae&P11Z(KfZsxgGrp=aa~%ozEd9hO|*tI1iv7avny0 zMKBb`q+M;0*SK<#5@Q{z-jR5= z>Yq3;(V!#__1Ws##McvDYF}a{DLdV}+(z}J`x#ma&$)LaJ9{qia88I+ouIDr^hWPP z#OnHLyk`P$@l~Gnq--F5b%J`>vlIOZ;#j*?lGpFGsDSrsZwGaa_wU}?YLIs@Z_!!a z`N*%m-yn~BE0J^k^Lg`q=dVQi1G1WkL8b#`> z8b^8CwW!&Wci2TWyCTQboPgX?vmCjr=5FNCnw3a@YJhi0t<+Rx$J9>9OH#$d&6Py> z#`|3AV04M}?IsR|tbo{;dMMS$nuo9OyI7feW7pT#`tS$&ZAoO|!NypbAw+kiC;>2=eMs$P17bn2q?hR9pe`y=m6 zAB3EqJ|9^`Jn;n8J7aJLzdGZ~j9%)ij7s!Z8Xj!O+b?r^<`rs2rfPJHGBh$bqRuAj zcpvp%qtDP&8;@Ju|E}?iCoJafUA!CFpfI}-8~4IW-V zsJ`UMgc|`lo+fZJAZ;<}pGe;%9$oq;(l?R8+;`!seG~)rlx$nIkCH>0^f|=N@aOs* zTljyh&+#0(^eJS&(yx#{g_PNXK0`JTy&c>^>(a-N{)O0Su7Nk|^v&>gU?F`6{0NXT zrSGwtzQsYw56Ai+<>*^=pJO|Gs=i1Tb#F`E|2QAc22!T z$1MF8>9gE~o(lg7NS-s{vw`HP1IPL_4XK}-14%y*j`eS(AJZC0y7XtHzLwwk5?rBCS9*Cx-8`z|d=mvVlo@6uD}xeBh@kC~>^XTVkaG}lqf%Q?9oz5z)2H^G_I z>@q6e2(H@KIiK&6NBTU{-;uuKWH{FEDMc>>l4mu%M(gX~f2BVpeV@*hDgB?RKzOKoMy z)wVUrb@)DD?|44&stViN=-=6hTBzde4m*3q0|I-r*G1O1XCfQhvye^kioh?$6GAF0 zHT%#n>1*#t%ANKhc8?l{Uj#;M?D@z^_(z}yvd==!vCku?_)0J<@s>dU1CI%`N%5J$ zRkK?hO;w!3K|jOga3ejAy2$!?PGDb-D;+h|RgPZh*Wg2etKjH|%ykT-k22gb7Ja-U zA34cUj4XAmL9WBY0>2LL3aRQ1$D8OCj<=DA9iJo3PKT3yIo(K)vnBF;=OxZ0)x+5n zy^pgW@pb->$n;#j0| z*Qec)?e5Nm+@XQ&c^Iz}9C;v#H)m>~5i%!mDY9?ic4Ys+ zKxA%U4RT)~E!aWT4z}Z6+5tZkqz8v0M+A$J;&UQSt-|jFrG;wo?(B}w37$c`PLLD7 z6TF4+Ji&ic{JinfQhFdQHL`fKT~MPda!8E=jfV{KxKIDU?gG%x5Ub+%}Rp~nP^`)Ci z8Fwk&O3Ds=Wf;}#rTfq;Nv^XlrDfqdBCvJ=z}G;b=!> zr=zP#fAQ$~-*Yd0KLI)E`zMfxzCVf_c>ErEMfZs>4s}!IfJ%N>R|o;hf%;+uok z65csz3*(=IUKbuZI1((XnZ3Y>f^kVk-<~%9)s#zA*6?p0fg`l5s!0sk7~$Kifv9L^O?2|84b z|BpuF>}d|=NJ~tkwoJ=F_DvgrtRA2H-N)y?{k_KL7&SSq@wubCkD}vqZ6k3!`mq9( zc9dGj%=%`vgY~2j*lF#V>T#^;e0#{I}ojGy8Cb)e}U=8o<&-H&`Q5(Q}R zDPp!P;J=GZUm?FSh0U}liSt8yh6s=JM=X6U@x=TYiGFgw?591l195Kk9{sX}-_S4n zGX5*xjI0t)h*O40A1x)}tOT2?OFYJ)YWuVOwI>r!)nB`_y1(}SU4N}3eXf75zqS+4 zdw%uC@7!xEaC_7O_v7^7#FJl~j+AxG{qN|J-6 zXbh;nk=SCn+84CMecG1#2(w#{rap$gGZF(T<_r3DQYs>mpkltDkCAd`+F<6s^6_8D z=w$8q+7`S+d+B5TT&y1P7tOe`j@8o{{gT>4YByCwYpVti5ld=+17`1uS4K|?kI?*z zDjuPu{ni2Lx#>wN{7>~>8)jHCUopgGHp)C#HO_2GzqJ+pSw__&{n@#h^U)VX`m@LI zrbxg0SNgNjp6vILo~(l&Yt^1?PGNsi1{cmn7DW29fuhtR#^Z}dBFEsBkx_-;wQsw- zq@pBAy&dV{zV|CV+|%#dzEP!b`z5;gh5Y%xZRXNm{P&ure?bmBjef3pj$~X8-;sYz zpSN~20$63QO6mXpa-Wwm6xtEpfy4;O1xG;4r$Ee~fcO#+zj_54;zK~@4RdL0%mD>p z52yg*Pe9R{I1{7;@%hyqh+ShYcoggcF9V5PI~T-!fW_k1#$wkJm|N8Wnc#XLv3JVB z4)6sK=Zei}LF9nTL0@n)$OW5$qMcv?37`dNt&t7S14UpZr~qGqqo4-;ZHen6qrno} z=PDrMz#Bk0*bQC)Vvi}dm`y;qg5 zt^{|12f#!Siw#tQz7iiCu=o9V!D)g9`995F1d5L3A0o7l^H=*mLdy zAAm#PJ0SL*oj`YR9}xS^FM(ndQsy{wfy5Y+F-w`_jQK1RTTBN?1Tt3X1!9BQ30w%e zfQvzQ4e>iFxE6@tQJD)ByUT$@D}A$L2m2^OgNTE_ed$0soNidhSx} zCdF1#F%H@RbO%>~Sp1?~bctWI13U@#fOmmnOf&_=>?kwQI|9YKRN@*HfX{*0iNrDP zY1MGREr85JO1z_(ueAd7B2Wrs9#ZTl#conDPAc}0-GRhADg)nwSj?lC9psK0{AO?n zdyYuxx6Mk*FbC>`+_6w zN$ zQY`-T7W5Z^8bJL8x&g75l)1zCpaSd%Vk;@WoReirEE? z?(k*ca*Z3{o54VEbT#Fa6S)oy1P_5+FcRd0nLvDuN?fRzf0md}(U?C`@g*ugS;SUT zY&0{0*k{K4imE-F4}e2dbq=Tp#J{S{VTzAX@ee9~L1X?_D$u_G>cyy^mAw5kDmo%S!Aw#b#6DP1gcvgZe=1H^pXC z>@~$MGZWka#5Pl)-o~N_h@Iy7Am)Sb5_IuBn*R>71YigF4v3F5!Jhqm2YU{19|4J@ zCD`#E=K~xEm7wB%gL>=(>H;A4nG)-|3yAsa>y0ikw@&z2`IO@T>N9LgK^@QvwA1JW z_W)Ob8^FzAHdp|*0P)op^V252Sz^9XV}4P^C#v{9jrm-8?=UUS=M_&bgHI*s`` zjrlkg|E7DtW?lw}Khu~m)0iLAm=9C&UmEjaD!xnIpcCj0#Aj*DUuizN_$n;};-@s` zqjV4YUJ&zB+V@D*M`_GIX)fQzH>vm~jrk+phyE52AEYsVC*pfl{F{guu(ybds)%QD z#zvz`1IwQy1`eqBm^j7Y+Rym^xBUNzSO#Ff={4~_FsZ*b!Qw;P&!R9=5}lXEi-tN! z>viFlT5k=Xuk~zL+Cg#zv9^%tvG!0zH%8k!qQ}}hqDxyR6^JhFogA&VgF9ki zZ3~Gm?I9bGGiZmK0!eQUOFKz)X)8%PN$hBH;LCM-U-&+)=fcvClKd6$=UV>~miCmS zO8~!QAbJ`s?JCi8U};;49&2BTzKyi)I$hbgCk3P@!CoMFlHq{XL$I{LBwgBD^r)g` z!gI7P?XM@aF1}#)YdzKulWlYC(Y9Em9CT@qiJl8fn@sdrJ1n9*Y2yOXFM`D*i|F0p zTo)r~dSnJY0dra%G zHkxc}a%0~FM86ZhOY72R8v9-4Gya za)!dIb^62bV_JU=-Us9!lXhPckTSjSxmwSLbF?mP!r@wv&TB`v9YdPTaLcx0?K@ZN z^WkExOFQySty{d&Hl*Z_wId_@CA}^Xy*`|&^~P|P)|PROZ&2)PM0?2 zD6PlZmU4dbNn5AWH^9#W@n!fTEbYv6bOYQ3$T4(+FVcD+SlXeIE^X13T7L|FT{QyT(Fm-ec(Pg_fVxKyWagr$9YA?XHK+NqL12bMOf=+aI- z7lkZypbJuP`+ZE4Y^J$(p>9&1yJ z-nI$X8i*ciTSxNf_H{(>NB;#x^jo6sY|*8y-5ZEL5ZOB=fu`lYb6 zwIyBJ+tSvSwL>?;(&m=*Si3t?PI(UxbauT2~)L+rW}v+O;Mix&=`)g$Ur-1t1McH#wR zSM|5w^-Me&Iotmkq7g0KEY*Z{7R^+1)k5K#j2Q8)83Sn(i4)(JNcHVi2X%q!s5;R* zc#0Jq7pX2kI{2sc_h;Z|fAl~3da@HHmQ(!XvpbR^Eu51-&#MVSF=?S1e;B!wY7%^#_c(LPb15(!M! zC&fOJKl(YO4#(68e}2-pFHZXQuYUPbef5(fzWzyyQs0~+?e|am_V+LHHA?S9A3FSh@TaGWcqqh< z?P_8;TpNke@O$nO7tAM$bDq#}eWu$JCz4L7$jCwU=Rf@nRJXsY+uzmg@9LKNZ|$X2 zx4(Z{vsbsj<(yQvzfZn1s@vbO^HJUYj-83q<3GOrjrWKJ#lYnn}-!Yna)hYV2#BSxr#F=JH0xN+v@`T6eV6DJ;THhHotm^SUc z=F_L=G@mo4Zu7ZwFKa$;o+?B6vqT-BjX=zq?>9UOQat19ODlI&5 zVph1UEF-*XRaSWQnhefWR(Rd|jPQm{S>er_Gs0WSv%*`qW`wtG%L;GbZejd7E1a8~ z6%L0p@UWf{9y%-|JbXk(c;u+8@aWMJ&5rU{WrSC+&I+%gysZo#O4_uUS>f3n$C9F~ za0&ZnPBlCeU*snKH+_caS>ZYJBhl>&ii?}KDJf9}Wo6lIR;^M6Yu0pXvv#d%W_fu6 zBj}d!xN%t=cSd;9q^$7d$ywnkQ)+aa!M2RHhs(>=%x&8eI8M1X-P(*9EBV#T>C><7 zIA`u{9p}%_;t&k+zDvHlJI7vIK%23;+-cJnb(}M2X~(&9rA#^h_qUlcMUEj7!LMNWh{0_}kDkCbBTj5HeYzpY z{aG-4_;kvX@@t2uPCIe@1=|^DwW|4TxUMthnhqac)MmtpmE=9U%jnUK+K(9%{Y}wr zEL@|i``f_&o?w65tL(2{uXtsd$@Q5zVS*}{IdgZLS+ml+%$d`={oJ{)wwV_>cV~t- zZnALA<+q;|9yvyi=j{8wr0beB^|-fIbX~V@4d-0tZP>7-IE(wr!t;>DeKoJnWe&ccOj>J$}iuCr{}^g6OnxqpTak3>x@ zShD1;HarhASFA8`OqTGb$ZyDy>rOsZkQ;r*H!Wa*o9{D=IlscWdBR!Yxsl&*2~U}7 zk-CE4ZHe4la!r|=440IcNoz>CJP)|GH_AObo%1k5uDK;#P{1=&p271W$HViqmh-bY zi|Zoye>C0B@kXATyo~S=e%r8789Xmp;W2YE!gJ?lg$tHsgbNFKMoXK8moCMMK-J04 z&25-1^-*44^Xwt|oGe|M5ni?|E4+M-9GfMKBYuv@#I_cmUrCd5pzDxH2A++K@Km0? zS+g^EzSvKJA-s@!VEOW_$g{q2lbPR8-;x_v{3aE7Hk|y1{E3F}Bzd-`8^SYY@$6EU zELdO&FOg#`$_N)1^Bk8L*gwa!QtFTg+Z$DDV`1SH1P9=5zvKp~dxs2Z*J|icRWNd7=T@UeNxj;=)!4DBV9}y0S}k7E zyOq>=<>m1l?-Q*G794K1a8ZrcrOVCy=HZqSCSdlkz>sW zFOAfT7V0#~Z=(Jbwn*8WH#x^Y)X^I@Qjc-0axaF%mN3s$B(K!#aY`Lvo1Nj=>Hz0s z=iCkI0MFXaO_6h;cIHl22dJZVPF<-El$EKSt77S6)B(=-&T&QR0PoJ7C8YD)cjgXJ z2l)Lvhs{?93JTQD1zXes>e-!JW7|zv2Y42C&RnAo@cist7fYX@4sgD9PF$)E@OyVI zkEM@L2S$!mJ4Y>22No|@JC~5oIoz3hB0Y}z&My4HwLxf3QR8(l0Jpw(RHy z%a?cRuwvDX9agXXdxv%FM|Ie^acYN6Tb6eyFJIGP+qO8Kn@t^Z!;g0uGW69B!$%$M zFnaX;9mb65(_!q`q7LK6J>MaEeN=ey5~Z()3eTRa^5*I5&GB+h74Kb@x0<>@?g1iM zaC}^+!i;bc&yCzOX3|HEr3~%?X!L+Fx-Kc)(Y2KA zETrX)*wJb-fgLEi04#91n0$@D3T#Zq_VSFnjjIcHCps!L!>fT^g-> z<2VlL)|o{`OWLhiv9cX)u!2>qE#Wn~Zq3a#McNATEUa5+;@&m#dre_^hNUixz0YJn zBSvg$H)hPE?PBlS>C>~qh17p#YqPGk^8dWNXWMbD+i{%K7jL(dHd=oE$L%IgR5Q8f zXG(p|^ROu|&)0R>Fl*NlBT~C^@68-F$`T&WwU+ujFVDm?$#Xi--jlpDc_s>Y$IRTk zxw74sEnl@O-)e0y?{hg`$xFMBYoKPz@7lP@+kW%rGum(261@iUJLGwlywbLaw)HHL zI$hE>Z8AmPvD`nA{j6J8r~Sr_mhe`}mu;nNdFG?{K=gei-=$qB%zYU-M|pX?Be^z` zM!g;3Fz++QwKq{e&75B_r0aqO#sZUKeQ>WQ6l0Z7|y6 zqoVhxJkL@WpX$T)tL|S^_b;mZ7m>bIb^n68qPl-k-M^^rUr0N?x_?pKzo_nCRQE5c z`xpOo|Ke1Aj_S03=NX8u^!Qdh&eMFCDxB7 zLc$p9Xtw%){|j{aKlLMIB}nY^z=`!Btk)w^R)i>(`=d1>BS{+tMuY#GkE}*x z|Hi8cDql@xoylZUqH9cuI&k9PW^hNuR+|t(jC7_KPUAC|6)5sIPxJf;7qAv3_Ma%r z%9N-kYf}o9tTQPgh0rjpEUC@P5?NIu>q+Xe*VR0)(RCW@BWpC62ICW3qrm`TWQB&L z?GV97R%#GoL$B44lqW>6W`!Dlp*(*=`y-VftowhD zy+l_C{BlVz<0JFcU(WJ7{a4l}{9k>d_2ECN)Qgu#R!PVTiIYFk^%9q}UP3;XM^=ZP zoa2XY@2copiuZp=(%J{CsQBn7sXw3aG5>lQyi_HNtim|?^O^p7Q1hV^|BgOWhk24d z|Irf{d;Y$_nrklh`O)vu`rzvmdB5S8eyhI2uUT~U01=NOW&iLVIhA%?pU+B$p`&XH ze#jMFWgy?<4LG^@#Se}w{!c%@zJFQ4D0BAmVa7p!erN;5QclgDQzxHD{lEXe%@F;w z(BiY;@FVv9-^C|R#VM6vKR?N*+%A^*>)Xe2o|=Dc`%`aKo%-K(2CDl%r@CI%{h#Xo zPxQX1?*E+X`G}^)T3OZopPxTRr}Li|PAAi8=c(@h#7f-T#U8 zbE^A4Rqup_tFsujml696)#xPO9IY8|Z-+0A3mI9L zQS?idjGgyl_55{=ao@^#_C0v*$;Cg@gU$?<;sA>3hWUm9!$QMi zLm^@7N)5{lD-30ZRfaW&b%ynZjfTyJa>F*_d_H1$%&^n2%kY%p8N+jiJ%$$yFBx7j z>@~b**k^dtP+@q-u-|aN@V?4e2;(T@c;jT_ zbmMGefpLkk)VR{P%DCRR#kj-xi17*IF5|Pr&3W1Qnz6$8q4A*cTjLSqG2?M2eHsfXz*Q*YDtrdv#RnC>D1&qKtL%QFon{?2IASkrjZWYbL3LQ}D6m1&J>ooRz< zlWB`-t7*IGVbi0g$4yU|o;K|^y=Z#X^t$OS)4QhkO&^;Mn!Yeq;^HFCoM5(@9cGs~ z(d;z`%x9R-G}kq!n;V;(n_HXPnmd}in7f-VH}^94G2dYRi@Cq~Zu0}?znk;SBg|vX z6V21iv&{wOCFWA|O7mKCx%n~klji5lFPit7-!Q*pe&76w`LOwG^HFYCi^XP1wD>F` zOD)Tpmb#X7OJhrOOKVG8OGir=OLxoVmR^=VmK!X8vGljxZF#`*pyeUUAWN<#&ob09 zoR~qQEn_X?E%}y7mMNBLmN}M%mc^DrOR=TYvdpr=Qf66gS!-Eu*=X5pDYtC1?65p$ z*=2dgvd8k0Wv^wQrNXk`@}cE3%NLffEZo`liEB=i52JtQ8+s0oM|L6EV@%`f;j2{v| zHhyaS?Dz%oMe)ny*AtQNx%gM(-;Mt~{wPCv@d^HfKP5CuXqnJCp&PM>`VlGi?u3UD zMkY*5n4VCOP?E4ZVOzoz340R$k?=vnmkCD_tky(p4Qm~1Cb47NSue5nuwHBZi*uI~v*2~t%cBAcfBFElmd%*Uf?IGJBTdpn7Hqp+VcXZXqfC-o>^6I%-DeNkYuV2vzHGX^vAwyywY{yqqrHp0yZthI4|`AhmG)l5 znC)%vYroEZll@kEfBRkb`|Jl`;YZgSk>xYcpHqrYRI<1WWNj{6)BI39F7umQI)*z&JH|UEIi@*g zIp#SQItqzXyUbDMSnJs6D0l2|Jm%Qtc*e2E@seXN@oFm^`yC%RK5-m!eChbsaf~Tt zvonEswQi@+8Fbckra8}Y)^#>;W;&ZVTR2-gbDSNV7dpE-yE}V0uXJAH?CZS2d5iOQ z=RoH@&Igm1j)#Jz3mYUyg@YUk?c zy2y2j>oQkQS1(s@*LAL&T(`RVyY6z`=X%gJh-kROiGn-cHOV#2HOn>6wa``QDs`=J zt#++-|L|;=pGkZnac|gu^qdURva{JsV?lku~?gsA0?iTJg z?hfvYh_u_&eU1A%_btTMy~q8aJJ&tjJ=Q(RJ;OcEz1UsqE_1JUm%ATv?{Yuqe#!ls zyTbjR`xE!)?r+`4-R2})k~_(tR5R&MNp+JllA0v7Ov*{>nAA1tvZO1MdMDkGbZgSU zr2CQ{N*bCpHfc)IoTSA`%aYb6ZBBYU>7%62lfFp$GU=`Znpiq$5d3la3{Q zpL9H_5(jq%kI`fDm^~Jc)#LOed6GRL&l#RnPi@bcp0ho5JoP;1deS`&J&inBo~EAW zp7T7dJm-6|J#9VhJr{U7c{+Q#5D&PU=Tgs~J(qi~@Lc7QXuy3u{XExuZuZ>f8Q{6w zbC2g<&wZZzJr8*P>iL`J@1DV)uxE&8m}i7%lxGa_g7ZC-JX1W=JTpAAJ##(tJqtXG zJWD)9o)XVe&vMU7&nnMa&w9^B&t^|Kv4ka(@ME5xo?V`&J;Yr>p-f7+$-dWx`-g({v??UflZ=tu?Tk2irUEwYBuJ*3=uJ>;A zZuXXYw|O7-KI(nk`-JyN@6+CAy}P~7dtdav?A_~q&AZS0rnkcTj(5NJJ?{tJkG!9F zKl2{)e(wF!`;GUA_j{ZQntX9StIy#}^m%;AzM!v$ua>X2?<`*(UwvP?FVmOhYvw!8 z*V>ouYv=3i>*BlE*UfjSuZORv?@C`U-!;D8z8ieE`tI-z^xf^d&-Yi~L%zYjJl`reV_Rb`;O4Sa3m)u*GjIFoSA%Ha=YXUk}pi|l6*<>rO7># zuSo8dd~I^yMyd=3ed1>;B$zLRYo%~($vE<5Rqu=6B@Z0?^f0Ezl5BO93XZX|nXZp|a*Yh{IR2mOEd z=lX~Ehxc6$17iZ?0}}&N0@DMt0&@cefklDBKuKU(U}a!+U|nEi zU`t?I;NieyfhPh_1)dG;3A`A1CGZa-r@a+;CvYI}LEz)SXMw|kF9Y8Mjs(8PrKKqt z7qkW)!Ni~^m>diSYXoZrYX{E?)(O@RrUx^FS;1z(^Mb8|*~HSmAb4T0OYoB5rNJJ- zD}ud(*9Q9ruMgf7{7dlm;DF#=!F!3#_P5}mV3=6jBZ8xYwKZ2&IJ12&IM244o6I7ith{7-}498fp=06>1Y| z8|o116uKyMaj1Lf&!L{7t3ua=`h>0v-59zhbX%x@=uYB%-yeD~^!HG1Xh>*yXjEuy zXhLXGXliIiXm)5`XhCRks3=q#S{^D3tqH9UZ3>l#wuc@GJs#Q>dOGx6==sn~p;tq% zh298Ngx(Fk7y2;tN$6nc^UznJZ$n2z$3un`b4q-QEybDQPVo{!Jd{#1B{k(wDQBnD zO*uCuBc)MFla%HuEmO`<$w`rZUv+P+x;Iwc8>{Y(RrkiKdt=qTvFhGfb#JV?H&)#n ztL}|e_s0JHy|Mr9IDJg2MdBBWk#8(^vFNe*#S!CQ%c!z6F-}$WrDGSYjkcjv?;X;{)c#6Ehe{{tp$4OF2>w z=FSpNS@h}{g8H1;qp_Ujocz`pg0XncvTZD;bL2b|L$GRWL5b-s=>uSi>nys&82q`| zg4OW^IX}4EuZ}0kc_41!e^NX_iGBT6b!@>uEVkhPdOX1#VhOg_@dSS^wxGoIz8y$C znbV&*^+5Cjc%#;1F}@`|7Ux@Zi9a|Qv`3!;OT2GMmzdvgYyDmLbC5{-7qG-DbfTY5 zyh4cy{soXSzk-iy{d@Sh*8i_!8cJO69zc$*Cp<^%^I(bhE$Oj%-zM}z(j?}$=%w&7 zoo5BSN$XqStpHDaY8(8hPJbM>yc{hv9+tS_Qoh6v_i5b^*VK9~_&lw*g4<|42kxNt zSj=%edZ{j?b=T>a!4ijD%9mK=JGA}?{F>JH!AG=y4EDVm&F_bsXuTPHiPpQr{k1+2 z9;x-waIw});YYOo7%VZ+v%+IFhlLlFiX2-npcoZhXm)_eb;Z zIq=8Cmy~$vay$}e@}G_``6164ka8r>y2P7Y$HgUzN6~2Vknl*nltX(_Uux{NL!}|3r)rO5W^4-yX#*Dk#&zv>2{p{Jj z+s~O3#|{C8i8U+zBm(-xl_$4%nz^$B@^*f1+pUVaPyaHWp#n=)d=wJ9S< z&JB$k^>}^!+N=5VYg1QGR;yOkQ)@Q`sNZ{Awrpv|K9kheZFAY5kvh1x${iI@qeu6) zj2Y8PjUAh$#*H7M^7F^2i4*6mNt0Ho$&*tJQ>IK*Q>RW>(`GJEvt|{k*>j#u!EY`5 z{b&4>$K$)F>`&rL86VFPf6Bk^m;6D4i+k-C{gN*h-^b#ce0QB?%U`Lpa^;`viT~iA z_fsyufv!-w6ZpL)wRtzn{rp1xv14yC8dZ7CwQGB&tc&>aj`}h;68E;e{0^>{ zH!=pea%IflFn+1IhQw5N&7Ut^Kd@$vnYHG_`uYu@}A`$$UTLB^c9)-%w1t2ZiRK@<~Z`jnOCi{nOCoV zrpuZ&F7w*8FLYVA-ecad!EfHUF~z)T)0xL&PY`-a-M@k81MQ6I{GjIVSDYb#m?=FIJ8m^bgD!2J1z2I5U{ z1}u@d82|nL(7?e(@1_=V4L)4_Dyw@Y;-KKJf4N=4Ax5rui z5Ve^!6W*+HC%0EqmJd-YB6*5b?uhnkzvyFMPF0;&@-G#ck2X%EXeMdAY14Wbr%&%?oH1jNapuec##ys&H_o2@jbY9*hjIDx`o3R2@|>)^YeQcCr<2ToHS{Waq{E=#wk;7H%^`UjbU1$!&p>Q z-&nk&C-1v#qa3eO4KU`8yv#CcR2Spu(LIb~#`H3d9XrT4ZrlLl`0=+JCrtRpkYC{7 zcCvw*ACjabwCaJ*sb6;Kl5I)fEffe51y~n7r?uwkmC05|1KhNl5JZwukoI(;*|Ri|%*w*%SlmvE)l zn`0}St?h+-!hN)U3p`ls!{JrnT(;c;SL*aQY>VTyeX$j82GYrM9^6W&pAWaudQW&h z=uDmhxKO8;!Eb5(3;1gwzvUbFh)%DGYp_~Cj=v?`M(e%c!CK!4Z_)Z5_<60HZ5$_% zG814skaB!*5QzOzGq|}`T&eYD*c!J0vag=- z646f9AX9vF#NI7fZ?OOi={!Z(4u`_O{ZH-&P*;>B|zD4W9 z;c;5ehx@pqWe$c*fn47e@JgM&8h%*oyWrhg{|Ee?*6Sv+Um(ZU3m%~L(eO&GKLfv| z^>5%xtzY6cs7rxtdmlVV>s#SR0kc8sF?hF5{}4W?^&@bl)|)07)P=xH{?2eWAZ6YU z57v4G{1p)Y%wNNmI^BcaaXXMndV6>%+4_$R>n@ zPOzY2M}?5kiv$z}?AWnmZ`h8#1&|^lASwzf#0G*$lO_t-d-vFny_aL}jc={JC(7ZT zbKn2lZu=O1Po7yTYi7@$J+o$J0SV5vEZ|%K+B^k*LGz!1t7yKC3H*H_0RDo8h=Gj& zIQEQzTLCN}Zx8H1^=`nv0Q^+%j==s@9{}79fa9|}a8CfXClI(V0Nc*T3&47o0msvPG4NghwqZZ;0RYy22>3VvzL}I<1ik{md$|gH3xGCv zfvaeKkSRlg0r>1j051Zd%@N?!G=CNKX1u-_xP<0!09VnxuQ@zN0G15`9!m3*fEUqx z8E_@d9|Jy3^Y?(OXuh5W{7oVN>uCdQNAsP4t7zT>{=PYl{*Ch+;O{gquw)1ez_LPM zeVR7~wg6y1I03uTyc=*Q0RC;MA8>a7*M8tMn%@eXN%NP1uh9H`;3}H;s|#fTSauU| zF3o=euA+HiJ?Ikv+KdIRr1?9*FKGTVa23t#)d&9uum$^$z}*2@b`tPpnoj^;PV-xV zO91#cv!%dQR4-@%fBOl*dv^wQ1zk-M)k*mPgDJK;1@Li9=M9;J5GQ;2Vk8+z`+0( z^0R^GQ+)!k*CgI%F0fY!pI-}{M)Ny?%V_>r;3}H$JQ;iu0PBwij-z=s@J*V(5B!4W zKLA(J{KZ)4a{!iYxD5IhfcZDTFLL?(Ti~w%Y;zTGlYEB2BOpzI?Ez@70Parny?}eu zd|%)ZG(Q%2GR=Q2fHv&n%TCx0dH~k50C*A2F9D9H`4r%_G_MA(I?mgFI{|qBmMuI5 ze=7~Z{8`|eH2(^?iso%kgP#GQO()>)G=BiNiss*+fjj_hTAXD_O91Al1J9-Tr@&P- z-|-xbVF23v3Vf61-vU?Be82NB4gqL02e^vn`}_*~VSpd#)xaA7XtN1;GtFlJZ>9O| zz-0jRW4nP50Pwl!UVw25z_maGYzDwJt^u$cpaJB)fPDctk2(SS1MpfsfzvNCqz?!g zz$Y#-1f~`_2^@PB?hO{CWxy!_v{wV?0dURD2d=uo>l@yLaRES^*1%OXFSx}JO8|aC zXkB1y0JgaqaBBdzrwyi=`+WWj@OPRg@Hg3&0KC>s;P(LB8+-u%M)l+&JZk{jJOq9Q z!2W*$Tm``XIrxYnhX81E3Al>pyF7-m2S9xg@L-xB20Y~%uP*{7zw`Naz*RI~=Q%?f z0qR59Ccw=AxMye%+>+)Mz%Br6j~lQD)q4Va1Ms@-fjiQ?A8;1{*3$#H7Xa6SKEQne zXx|@r7yxZX0FR>i(ZCY`c&+Kc3ut~3a0~$b=Q?0D0PEQdoCUz=z8m-j)xQR=dcoVY zc?r)Nfc7ha(`Y^yIFIJ{0G|P1KfedAqWYXy47m@$vf8gH%Q=A;6PqegW_znqLaMjOGsm9|hoZ zJO+G%>aPRep!ui3&uRV>a23t3_yYfD0~iZszXDfP@z=eTu0^T<*aoXoEz%Hx`J7W) zBo~1B+fTK~3jpSaJO}#^)c!N%tN46p6K&W}YjZYp9kd~yAm;Kf;cpJBstmb&ZCrxy z^V+xs-w(BM3BDix{~VXVn8XPH`j%6`wQ-5sxI}GSf{@y{1n(36C&VRcV-ftb_`ej3 z*!Qr1)W#ob;}859wl@C2`_W1L zqmXd+-yv3^iC4gpgiBAV);v`Nd^k98Xi}MXz`Q+@+|c7D2ZxwEUDZBg(3d&^aiBBh5q9pN$+E_RR3_(<9y5 zf7b6)2eo}N^ibNM^<&#J0j}H1z4RRt#|=TawoAEB~}v zFfg)NXe*D^Hsfyx&i!yrv3Y#z(HQrT#w)|;ClBm-FjIAH+=t_DUcBC~Eoxl#-2Prs z`nz7Ok{x;-5kEd_cvEgV-qt_=?11Fpd*wanxXg6vl00Ta&e}f1e>D@&QlEQ#AgQwa zO{1&hBZIr=Rj$6)(fn#c?hAc9%c9IHKbKHcGvdq zDdQ8C9v#u){dl&=x33p1zhy^gZ%=bOdwa{T4|c87UR$C_)BEZeBwF0mdiIsmbuakt zcIjr(uG@{?X?7obiC^r95`H$gJ#KaTdC#usJu&Lh<;3CrsXZ^;H8~(j?xcTb;HlFK zZwb6AtSw7Q&z##b{P6rE4WC%~UcdP2!;K+5j_5qDPvS0xd?_3Iwu6)K#HBN>I@n&b z-)DN>b7exx$@+KB?u&2vZk*rfqImOe!zLfR{{C}*-nM%^y<6A>lYHOs0-2XneqCCJhb`@KNIVVEa4mxD1tVom{&RzOs$?QwXMK1+w`+qL=7v7M*l!PCh+Rei5dc>HG zs*)*%6~XyUhL@x_vJO9ZvT6B?yzta{Et-!sN@0^_24DJ|xuwJcD_f4o|*)o5_; zm!69|9W&mleJ`fR<}|tU#)Ss#>te0SI$p;Wzq`h?8<}+2a^%2Esh1MJWk2d)aHR3r z#`cdp&Z~0sd_2B&$=BG3Jf|^6RS(lVhU9G7SKoEj{gG-Hkr;Xo}sAFtdZhlhs z+r>7b{u6wcy=b*~yut3^K|@?0mu7bR#qV~`;z41iFQg84rn;5LtpfJ63_Q?c@^i_C zd*^Ps+ji^74!a%pcFe9OEv7epeFrb%ya_x{D_bF=qiWdoDc zQ--6Hbd#^1*n7!gfUk9<#H%H)KHd-d_G$5cc|uxYc}&ZZo)eabsVD0m-f$)`ZNtmh zFB3=Gj11pCBCo-k^|1j9i~A4Xcyq+feb1gcefKz3HL};1)=%#hpS74}kZN&m^0iLZ zP9+Aerq9_mwx?Y+vyQU79YrUZeDEverdRWW2-k7;&W z9qaR}9_P%y7g^{0T;H>&0vcM6k(Z8kY@;Js(`l!AVMdQ$T3gSrGyl48VO<}R(W+;j zTZ?|L+ow(a^5I^YUuEf|ewPQOnwU(+7C%hF6o%xF5bVf!0d?>p~1UfgfX zxh~UgjN3b7-0sE>p)*BqV?P{AGcyhdzV7j=oq=n;I%lR|(0#Ps{mRlO<6aLxIomUL zX}_cE$1ZZqlqwtpE6VHl$Y@K9^Vi09m^84^{`Kf%qep4qb1u2_xMynV>9K3;_m1i~ z<*0M3!JAs%Y+01oVcd*@?@QNpYqGDs_r6x~x?0P+&-wOt!F{uvV_zod=UicF7ZeuH zy*+VCz^kk&O1B%UjvnviIJEDh$5%?Vf*rE2HIP2>kMTa$tL4t!8NJ*lZ|K;}Bx_@E z%cGq~jNW^3s(QulQ{$@=dp?<%sgf(_HVqmb8t*O*8hLNeIaQa|*6D6#{kwXmMvS;` zcYI0s#+~=R8?P!AZ456L?HHc7{Ni!FwCpz@%Uq*N51jpdhxX0EdcTJqKd`d-`(fwT zM(xx-bf({EAJvDe{Uf%?Q-kYWTXf{MU8MO1mpPZnvjHuV`nuh{lF-@0?nphI$U*0h zJss@6?V97->t`m++!|$iEWEh+P@i7!XR4L0Jq9~m{5UP<@yK7iXLozj?z)!Utl5D+ zj~1;~1~+J(_-oylUs^rsw$x_bs$*I%y$m zEnbI8FL!dC^2@gp^_*L=zp3*ZHklQ2w8TeIY~Dik;F4aZ>&ffSj#&;I+rqSK$?~{! z6XEY{-3-KYzU*CYR9vsL{QQ`OMt9yXG5DHv-ukJ3-k0o!z8AWVdbf7Xk43CHIC{+}^!?pwo%jo~z^u;WO2% z7WZ-=?|OdElKAxK%hC0>t{oAYF=*DhWw~A}TCVTuWpLohfdw}YU$+0wT)ViyMO!sV zd$rJd?1#p>v4R%t+!I?b4j4A0<42o*Pi*#o`gYWbSziB6go)Aj>+KHTjM|jGap&)I zzPvy9+uXB#FC5;~a>6IQ79Yl+TITa|T-!e8`w~+s3U{p=T>tH{_c_kp*JNHgX=v2` z{ILcncHD0;-{Z=*A;B3&;dRi7HNrdRy4NkMqgw-eFA^UYt?u93e)z%}U33if>xV66br*j!I^E$w*9msRGD@79 zE&9}a!-Yr-#fodw!l#_fJbJZf)82xhhnMOsAJx)e!~M;<4@y5Cf7&#mNwYU9#e5TX zsLzm0snI66Rcn=Uxcczdd_&&ueW-JEq%~x6MLMU5wNFqv-NVnbjOboTP>fh{*c_FtKsjjXYSeV*1=-T zy;*k_I4+sE-lI52Fele>;I%rpCY)+<`PINHEww7wj@WU#*}U8KIn8!1Se5GYxJk3I z3q7_C6|YhZNUNOc^uz|fTg@F}TKx6Iz}Oxc*&{yH@mj3T+O*~T(?^>>_kM=c(daVbY@R>~(XRmZxTf(*p`LtO7 z!nDeSckI)TbEd4E#_EJME}1wkFMtRGv*G)|#Yg)FKh}Be@LXq1(=N@;FNDoVJnUi8amMC(w|Cqr%ock9f6m+2Nk<#M0-^U)#Zt|_YL1MGlBj<$11Z^*Gwk?R+`C{Gfg`U%& zY>t0u<+0g%&Wy7W;=7H%hu%8qX*_&%w=r`J_eTEqWoO-;UaO@`Y+@%J>+}3qQdDFX zIH?o4U^D5-ogHI)e2qBX~C{EPGK#-icN>jag}oAS8Z9*2Ua`;AYB z{&MlrP1763f~|W!b?%J{);ZZRsmYze-y;V8ev}+DT_tFm}jqU;d8*O&32=p3l*8mvIB3lsVHwH`r=}KCd6-J{~jCTuQz-=ug7U=zi7A=)Ft7}x==#X?Iu9I9IZD{=^b;iPBQ-@8Q@43q= z(QaI1JUgK*Y0kOtPoCJ67i1f5dvjx-sHF9^;=IMi^;;)al@Gjj;MYr5P1Wjz(1Bh# zr-v={eLtt(ax3Y|So=Zh3wITHQ`1!reKN|v3|Td2#-+SNXWk#3)uMfy(eL*)me}lG z8|k~dFmj*&xsW6Iqwjbg^wE11*C|P-Ud{vCrNhrpp7msKJ2wIAl{+=0!I@68#ox2O z9LNoAcv5+Ew&2jzil&W|#@D%7ysyFOiIP<-x~)7TP;RoSGv@G}Lo-J;I{K+zV9y~_ zFSVXKA=2AvPOQg_)pPHS3Ycw~eKqjuhw1b6jm`^7S{>N!)nY=ru=k9hBW-2oH}3Tn zPC2hUQZ?|*SM6R=7o(fq-J<(@#WuI`BR)1C6*I%7(St`<=T#ijW`lK6stVtf%bHvwQmlQl}WxXt#-QTX;Zy9}!=Eq7C zn;HgvtUp_8RHqL5d-Hb;9voLrdGp|i+oIZP_ z+n6IqEbng%OI{f9?$t7*eGaOLCd%TO(?8qYNZHusOvajp4`+4FGfkVcq0{e6>umSz zY%g!H;@Y?YBIATh{!_^y%tcw>k2Z9Sn!3TT%>}Skrf7$)T z>vOYGCf{bFmX(H#9vj)x;nc%veFPVm_s$Pn_Oy4!)4Ca>_RSKcwwrwYdME$LK63_* z_`WQ7?I*8aUE7VZwtg3TcoMsC#OQSk(?;KQe(v%pcXOv*mlDfM?p(XMEw$mznUClE3!2owsiA z3BRr0YwzV*O%;xu?Ru<%y7KGD#fK+U*=-Z98S=mQ#r@@w>1#LiTX?A19(y;T z+Eo+(s^$Ow9)M5Rg}?jKhW}g8fxo|7LSl%3EQPB;FW80X<}wlopPD0q zzpP6j@I|X+IeatvifZKqP>TOyImXiZq!DQhKTSx}f75NQg#RKjg-?D~J? zm1M&Ayl*4fWIM@$&m77l`JnmZPXXCM3P}-s7kmjRB|AwO*#+MUUrs7WCD}vv!uP}P zCkMzua)=y;Z;FQv2sutp!2g)FAT6O+TfvVF;3WL_P8;~|D_dd*|I2a;zMo!BPD3ls z0PyE5<#R;AeRDmp{oAkS;hX8VkPCo|Tn(3q6I{)iTqalG8|$x;-^g`xgWQDguD?z0 z5EtS~?vi`tK75nC8~i`tL-L4t5Ks88zQ^PV@gm9^_x{J8_}?dO`CoZIPsy_%?f#v3 z6Cd&%K6k4F@g*I}3-Xe@BCp9C@|L_K@5u-9k$fVb$rtjKd?Vj~l>2u)t19jTPyV@y z&HNupT8uVRhtXj=!GE|47(e)*$pF%sbRjI$75+E2JLy4s5Vm}o)MM&1g9*bl zV62#iOe3Z-W6d;SnljCp=1dD_2x-Z*Vur%|HcV@#4bzsfW$YLkSGzqUXB3PB|JuChPp-}P`@gOi_?o8v zgB8~7k053mGoAT`nZe9tX8obg*;Jatj3jg6zUDFWnFW7xe>H3TSI7&QMR4^@qWVLN z{`-Z{ANL=|g#XBAlEweBre%@{Ch}ia+uvUizhfCicQd>c#Y8hpm>8JbO9A*3%PeE! zn0O`u%MYPblD$8vHB%Y+z=SjZ{~YHZhw) zwS}tZkhx?YN&jJ#0e8BU$z3n_Z>V#_B&-!@sK3&i^qj`G3Eovj4I+@A{J~?f$Ew@DJ%15fup~ zVI-U^CJ`i(M8Tfp?@52%Yvq5^_P@6N_q|i`_uS6kZTq)&&-~dNPu)T|bqnC!E#ywT zn$xc4%w3)N6R?0g0}J33EPykx@PFt}C9{X?v%L)d?EAa>@1HI3&-RP;zqw!k*7&G> z|9^iE)W+Xx<8QU`w}0OX{?FE28-M#}SJ{7m`P%qfZT#(@o#+3td~N*gKlaH#qN$C) z{rf%OpI?EGAdUJ%oUAtfRvUl&M`rP#m8p%t{aLSQbhYs}O;7yeTpNG;XJb_VS^3)d z+ke(O!vFojrN6oZHT?0DntPMa{q-y1EdTg^^;-Y<&VQ8tR{836{g>xY*`Bwp>U7yw z>}TRf)D8T+?K;|7`vuvZv^!^a$<7Hrf^mc_Qnpm4^z-%W4H8is+gsSzw~zE&X^)M) zYJbx{!S9}Zn%`z9pX1k69w^`8H(Gu}epmiTei%ypqFAk1r#S0((eFN2zNJH32f2fV zf35?3%C5t8+sF2G{8ssWu@%TAcJ<_@c8%ngcFp8gb~f^sb`Em9Mhm}EzaDmj~TB9FCOBTus1C|_%rA>U$`FVC_o=4^kn`(1w9?zQ}Z-3Pgz%uMmr4r?I9 zMAlHzLgu1?PcoMIDBNXT6i%{EAn|F4Y_ejOELt&1wvg%q{I2;W$TlcaWZO7RsqCoY ztn7|rpX|J1lHYf~YqDpGC$cY!X@1)N+V++XZ)HNbA42B)8Tg0#8T&W3cXnuP@9iM7 z@95CYex$=x`zVKG`$C89_PgzWb2w!Gz~Q+4QwKT%v0y0ogE^WW+P<-WXU8bgWO)il z`_2xwuH|kmT#MZtT@SdyeHS36t>F4+fNZ?N++~Za$kEDC>S*Km%=V-GE8B1O&(a*XEZ$NNw-{CIWl&{>h}-&w1RGhBv`7sJ!s2q<(s=Qzgm#~4wA zp$2@JKg#$XCUuhIA;%g1?;X?pS*O!~qrA!~)`^h004zC{XUOh$+U#@+B{e{E9W_Ym zJf}ajhf-#XQ-9~HPD7k;IgR9OA2^NwPp+o9 zYIU~dMgTrrP0sE|?vJAbN6Ak+yHGhux}kzlHdHTE7^)vC3N;87hf3hbFw`j27)F5! z9SPO0r-r=RB2*e`8Co~AUTFQ$2BB8m%)rt7bA)NGRITKnW*h#;EBvWlb!GLd{2ci| zwKa2uXj+5sXj;ja%dw zw;WleVu$R2qFi=LG1l*s-+Pw`w~Mleid(W*idlZF|2LOdw>qvX-1J>j++N6t!zY=< z!N9(W18Z;P;BP$Ux(&9U?htH0+hL6T0*8tAVGi@`mpja~ zk9APluXTv9S3AVmZ*kaazu#f6{cVRc_AebS*uQhQBG++9aySQTiHuwC@Oeu8GX3t@ zKDWQ*Jlge)^HA6O&cC?caGvDaz$M%DjdPgmGv|4(j7x&+XXhoZO(I!_v4e|~dxwYq-W{<0RUQJ*^WLw#uX}&-e(0^^@m=Lj`t|G9BG zwRe&C2JcGmZQe({?>XLZeBtrL@dLCr%3tEy+p(LYkK^y{gB(d{KP~w8hfrNdXV0&W zUU2vM{{1|MIlgH>(eYFJ*^bZM-no5sGj$R>4fVY1i*2pzG}$x3F~)JBV^w?j6lHgz zyODcAG<5=dHbb?zGn> zc)jWM5MEz+eSp_0FM+aJtN&)!>qo71lItXMdv&#>W)12e)uA4&V&%0(1g& z2lN9B1&jeq2F${G)Qcb&1&BvUlhmt~X`stc=E7@GtiCL<7nR#=g(MDFr?M!Bx9Ww7|x=-jNx@eSS z{8?galxTX#tU?&0KTX_R5+o5DI~i{@3((tW{G5HlCK_2A_ch5f3pTYj2oVRGz7`D8 zj}zG#W*LU)IT;19(?sV455%bkLgRgUIl}jbLrk1Z3&gKYZ;0gv<|cs#>4weOjqC%q zoA|xab7LRVzGi*(ghFF|8&R3TOo^LOqS;LIW9E0v<$BKzQpFEU-|L?fJr^xB7%eG~ z1RF*g*%-$eUo;(U^4)Z?9USd?XzWHyTc#TT3d83ydm^?id*xrbvdE z+Oo|}%=L8jbVbb#o*Q-3|1N%FaL4qHNxGSpskJDK?aKv!vf%Zq0gkZOY+b_}hCW6^ zjDn438of7rU^L#CkQfvA?lV(-U(3wa44IGs^KRyW=EdgC&GwlEvNPEjwxeF4UZP${ zVX$z#FkM(6jMGojPZb>!of16|B^vBAxML6~HkZgH!IEOhMM;36jZsIVZbkt{fku6e zf{a3prWqv}Wf>iUCm=U=Gwx??_B9PMO*P$U`q@;=?4ns+bGdnv zsI&A2v<})XxWT5f9oa~>fc4QE0&S2BeS|}VS;8{mccDuV|(yT~r~; zfi~@fR%sao8H_dvF-S7FY9JJg#n$4D;sSUweI?zXl?$PrVxy}Pv0+`qAj6r4DTWn> z`=EF37``^tHPSMY8|6T2Zy1>y+ZcC**4mf^njA6_o7RQax|wz}Z3k@*G!1}ukA`;N zFcq71G#hPJ0Ih#-CN!^W-W={B(!9CF9gFK05~-HJMqn#gF0GI{SsGhdTi|{DtI~VH zbHR7PFBU#*AlsK6!j5Lg!xIZ(b9AFEV%Rt~kF^~{A@Lb1?TSXXE*Y%a7FItkt2$43|->?RBnE`*U1CLApc5$ft46DA6igek%} z;YMMquvoak;+*iJ@P_b-@U>8^pKh_uqOQJ`zO}x&zK#Aq-9x%^eK+{Yv*@cIq(4M| zw0@CAi2gMF0MT6iW4e(r?l$VD>Q`E1=^wBt)-TX6(?6zvO8=DZ4gClDPxPPbpVK{R zaZy(&5{ryQbwvr5a?yE<^A_ifeMCN@tGe$kjz|MVL82SFA)x zvc*PGv8W72P?_i$jG-H%i=wNdJ1~--h~A4ni;NBG8rT@LGk9p>W?*a3(V&|_u)#Bn z@diT-`WigZon|oCAk1K3U(j+-Qa;iy73SJ zjzwc}bFr0JDE+SMCbks^hy%r@(!OFJ@er|=AXq$FJYGCgY$;tR))mBvt)y{cp&&(^ z4x_hN+(cSt(NcO*+*W!={6u_J{9ddpF_#D>Vo6p0 zPKI>_bp_oF17UUyF&uAbB?vPdDNQvTC(SZEWl?4rBAqUsEwvUj7rZtMlP-`(Nn@p- z4Zp*Wu92-kXe1Xn36i8%M$KU+xe3-v`x>dGTck6M;*8n}l8jP}QjM~tx$skLlRzLOHEj`W=IMdRnDqXk+f-;H%m-1LMdViRMN zx+b5c<|bAqauX*LYZEtT*~(*jd>%Vic7re&swOcO26f#*lifKFvH`Fv~L1e4}}ed6pnYP+&gavOo}O8ELuH@}haM;EDNb z^Y`Z8&2=rr7OO1(RX*syr5?I3f@^E`NPoqDW>LM#e^pMS|6Ap&*Y#hXuZ{m>m)FMs zYvcd5@&DTR|DUCeZWn?+X&Ya!PvaTTe)zAfiJgbIoHpmD}QMArEATO+8w+Lj! zuiyE;LRNu{*v}W|I22?ArgJ=zFpwiS-Ou(#f{eg)iYF2Ua&!&5B_PL8yOY#zDaf%k z?BYO1VCv2ji3b^h=@?HW0b~TG<2=D9p%IeE>3+6v1;_|Yn(M9v8G-3EPh=Iyh~ZR5 zP68Q$={!$lHOL4|XL*9pLn9=a)BU_|3do2})CPGi$O!LrUWvR8WCSM7HP(ZSz;uBp zk_s{+jLOJqAR{no#x;C*0@=dpezqkYWCW(GJdq5Lx7M)B1Q~%zW0wu`_8N9MAS0^V z<$|17!!94>0%~`KH-}GKBc!;7T?xntOxJiKr6BLDVFzCmO3G{KDnUlL&~nHJKt^D~ z>5tii@PdG;QAOV(haiK1DZu#+eD5&G2uzx?M?gm4`}8ex6f%hFWsiZ3s9yFs$cXA? zPk@Z5UiKu&zX3Ep1Nl10hBohQf$ zOoM5C?LbCgYDvp_fvg00X=Gq;kbOA2pL3x-$OufHw7w1?BQW{$M0`O;VCuvZ=?HRn zPWQ9E9v~wc((5Ak1Q}7E>W~9LMp#iDaxah(wzM6{y+KCEsSdd>$ndwPL_u}P13*SN zQ62I?kP(hlhdc;mME5QHO&|{g8Bx8y;UFVAQ#<4lAS3K)eaIt0MvS3$$fH0;w4^%Z z(I6u_P#yAEkP&vYKICyABid3O@_3LD)yqx*8S$YNe;>#bK}LAfYamYs8Bx8ysURc1 z(XzX3c4dGw}Z z9(fArrUR;3>KakqCXlz)&}D;+xJvs4c{|9tfNNBToDcF|z%8mn-Ul+`Hq{~T z2l;pnyAvQI_E0&7(;y=-u{@D8AS3osJLIzYPBFKni zREK;CWW-0RL%t013qbW}`4VJA7PUiu1u`O!>X2W9j1bWFBEJC{5liim--3+5bb#vL zfs9a78TkXqA33|9{`3>b2uz=-?Prj`)Uf*oauv1HtTXV13`7FJ)PpBt2(lg3HKIBh z$lU?AX#L1NKpqOHe!s&&4h2;2s~C_gYv}fXjKCz}iR=aWR1Le+AR}JU>mr{4*-i%w z{pHD{5>Eq0XYUxz3&r1F5`6I zbKdgpE(f`?hHg#+IPU@K#PIbYF8~?wK+Nlq<3L8ZP&YS<}3_N`&(2XfaMc0EBxRKJg2AS0^l`hbk6uImRfqPlJX$cXBFFc4%! zb=_c)5!H1=K}J;94Fh=$p!zk&f;_o~-4u|g0s{Er98Uvz2B0t1AbN?*w4dw51H>T~t?0$Np}R5tu$uT?NR9Yj>-vP>;MH zWJL9A90B<_0F!1tI{`8Rlcv5iAfE+P@2kroU!iuI_FV<}8r7|%ZMg;VZ9w(1_d!Nf zUmG8R{1|{qQ{NMipHf`{t?wDg2uzwa?+wU^>i6~$OdEG{}g{REInU=OA(mkP+2&Z9zs<*C`>^HHnLR{cN)enyQLt<*3c~j8G-3?5MMR{NZ9Uvnxsp&qt5aj)w?&mW)05SrTW_}$68G)&s)^`YG1g0aj?+=4~ zjMM$B?>NW^Ov$wD36QVVu=@>U1g6RX{PTDR^7|Tgy|%&r05I$;Z-YDq;4ZF)Af2mgZ* z)QEe9X9)5lKy^Dc$feY-9<|#A@_E30+CGjSGo lQp%o2Dv@p2DRf^Ky+@alB8ty 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 jJ;f@dI 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¥nG_K&L4nj z=ZvLasA#||%3fVmT*K|rVD_VLCo$@0as0TxP8guBu#FuW@*ocqUc**j32oV5sx!B# z3okr1@>=lAN6y}*f~=wy_v84A@dF}3rhCa?5WxuqRj

      }xx<(El2W@~C3jDfqXKfG`#p|5;L9>ahTBE_7~ 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

      UW>Sn&1R_`6@ls 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%0AsLtkxG#jn?9QOY%ST4f?W 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
      wkKcHzh> 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�O!-8`#Xb_iO9g8VH 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

      QLjb?Eb3N9f%5aOjl%kr z^q!SEwEBl%5XIC%7KsUEy?FE*~%?=Nt}u~Gt&np3F5y*!l+_r z=-iLPn!%A{a5&x7rIuRuB-0_(ht*-~b8(}hb9U%ui+589fP^DHw7LZzMEDTC?;%DK z{t^0nU1)(WcY6eOsWiWVeexskNMDiS2zJ85)gh(&Lkl~Ea>`>S`xACIxJ@0jDOZ1M zQaf0fNU?{})2+LvGPeMh<47PT^a76Lojo|VP-{c2g&s$NG>!Mx$OX`9>H&)fTmhHv zugBA_qB~Bh@y$lkq0@r_L$DQrE3xNxr;eVyr9WN0nfy2Gzqy2uPh zzj&OZT9p_Xl|xz-)$8wT>MLgoLQwM=Ut8Gb0(ci0KseT5-G ziDwjyMB`X~b5_jRdcGdhe8gqj_eL@6|ZiDTP0=X-E$`ZEt&uX(e$Jx{G<&U_t zPU`K(Ybw5X?2bq?F}XwG263@w^&j*y`c7qXk)B4QKf*x-4@k5wnwY_`E^)M{oT8Ht zy30I_LK)T+Tp(_S7G$$mdE1aqi>yT*X)***15Wm=S*HgVC6}C>*c1iBf99xv6ag2$ zg&?bo3of2lPAIG-7-iLDHi>j4Lk)?eXkNu`UVMsL$T>p`=@P$Hwj%k3YlJZX*Ypcb z&QzL}LZR_G==9h5)P=HKm2Z){+W(p0uzTfF(Xi??Fr+B>&Z)Sf|27I51?;(gKo?bV z=4k4cV0oPTcRc(1wLOIzrDW)-OGhD#8;Wk3b|!2n3KEniHiCTHrGtY=njYqDA%vd; zP}hBh%|opR4FaoK#uC~{t~ZpeQdH*a!bxPo*ZC|QOnl6%<(2Mgh#(UT7p}fmkbApg z*1+3PvZcraBOSpq6xdFmb^{+0X{LQBm{WxPrN=q~-OM|b+S(M+u=ai-!-R_>Ka+fV zN2yYR3q<{ja`s+cz2t0J*gIT4EiCf&fQymEY`eEWP>nVmp_L|~LSeRW>KW@gSgc?- zB&!aXyL>UoR3=_kjKGY4FxciGWi9@bi9%QNNActass6g{qFJPRF<*QqLiA2`5Fr7U^dQ`B?R%lkQ<#Ay zh|JiD|$NuNA~Sq*|J=-9EwgxSrHcAOw1F7Ejmwz17fI1^iZq;+Hnwy3PS{ zb082as7D5n=7(QT1wfC~4vvrmIE8uCGxn)cvM5TLJkgG14@Mt$_AWj)W6(C63zJiu zm&A{(b8s}5Rn1-w4mgB4JpROMEVAR@>w9cdfl9hrG-)NbwmR|=E0Pp&H@s8ZVEkIE z$VEn@^0^>YBLb=i#ShL*m7-GT!r^?oF(-_PxR2z*k#K4Tor-%CEQluJpn@A?hDo9= z6&N)(*G`1TCvMnpM=vPc@2>>P+D@QN;~8PRZY7J0*M|q`6Qov9zI0k02JV9OZ=v4A zffwYW$iJB$$gtooepCx-O;2Lvn#{djRD(K>9-Bb6+jAv3HOZ#LU@1tLhv8bSSrG7+ zomEXI9u+tNY}>fgz!*=jA(?N3s-sCMU<8bNvg+GAzd&%Ro+~7guoM>MdBizguS*Uq z-i|XxIi>KolCfJ~c@i;~pImX_ZcdmtL?r0VYqsoINXu33`>(4tXA^vm!@gaW6=qaZ z(TX@Mc)(FFmEguY#iX04-ys_+c;+W%e_iZR!ijx{Ksk^WR*wv`8fozS9G+ky3$p3I z00S!Y`V_IPFH^tK^&3*Tz>hNCHvBt0`BA-KUru@s1&P_h+tN-wkS}P1EjxV3S-K82 zlYX2{$eoVYCbAB&A)8;WdnT`x(>vp?6)wId%!aA}#g1xy_6tu~24nd|szz9N!rEtEVT|pj;G9z4z{h4sZ_RNaNQu~ zZ<@v^)PX`3zrx}`m$3c>m+7emB6?zF#rwk0bB*lijSRw%?LHz&J2t3;CF35Zu)@i? zYzrD($lH+8!}m$7!So)NyWgncE*`+6d?j3AX~QQJIAwcR$xQ@1P(G|d#|fE=2u!pCJyO|!3r>c!&c5JnxfN<5bv zZ9j>`rCXHg*Uh8u7eoewNl{=c-)pTrvRM?vCih%H!?GhvHP$jUmV!FX=WoE4R`%%? zI{lhgFa}ZWU{e^Ttj#?yJ%zzNa6u=a@iQ7q*owV;uw288X>4D)=3!+S(JLX>PkUj0 z%}MbXEE%gGkWVR37BF!B%U|rKYb4^g{Nmya8X6+AhSU3bPTH+a1`XYBs_`DOR_n!C; z%8DXY)IR+$PSyhi$>!blki+qc;dpkYQWSGov!$@>NrP4-5ey-Q*_d*HJ{rDqfK{F{3xc{Ym3j-LZh zHg1G&BW%H-45i+DQZs*TxF!j82Z6*4=a>ZvHY#i+=_K${UUjC*ue6<{2m0WU7lUSf z&chYfu*;@U^G;jzf@wqG1cfwt?Bm$(1xd-C7YQ}X{Vcf@+2;AsW>O?oX)&$PP^yby ze+KUP9WJD45S&T0Wwmz0^< zRU+Lt|7Hqy29o!eb z46Q{~pl2zzes6J?FAm+2JHsvWe~UBTcIhwmuJ+t+KN&+D_Z;=(cfjbxMC27ls|j@b z0FN)SiQ<6fczy-Z<%p;(0_6kZ9s4^^Q0WVM_P-wAn zCp8`!D|u$}_6?W)hmD-O&e$&-s8fPHLw^j+!L4q3)dO4IAcQ2Ku#6Oh^m$Vuq=Be`BAO> z0m;=6?$Ca0A-!5;;eGg5)x&dbQ90q<(K=~*RJ}erdv>&fsq`RB!n3$39o(iZYk)#T z;c@s000Yx@lJu%Gv;Lt=zzfHoJ6N?KUul(izOWs&63~ee7=-*o7WM^l@(E-pF^JW4 zLDN8cd{zj}p!;N0`^%yYS?bAi4Q&$^cW-75qw+XNmY^)D3{DRuMWugBxW2)t0WZ$4Ztnm_cXtmXX&8dpm|w;#pt}a8?`_7}|uyK8>BUq_Qs4c6T`(m0`t*H2c9%N8!Sz@lCiQ{LarWx(gZ{h*H3)rfQ;0DO#m$t> zKHVfiEDJ#lQUwCcnafvgLT6lr;X0oe7U}=2uH?O7MI3-Ff zqRZ3(CZwK~xf~&hmOo$ zL3r?EYfTU$aaL2oD_MVct%&wU61?^XunMV~-1t$v@TcEEqwv7pm#tRzrNtuY-4zc7Od$n=D_;$$c6y{@ zE9hb{O(nbTRmnc!U!V~-n^K)_^sj#QJ)VyN6RTC2b}^Z8<733FN7~Fd6eaymiTm60 zA~E3@ODE3ud7Hl9s#wb9ouq|Pb4U?bcarArnJxd^m_E<#(OeVhVjt+^pi{6kBhqtw99vJ%UKML=dn$|FZFQA@Xx$0() z&*`!u0CFVjD-Tj(L--vER2*VmZTfK`cLNgt_Vo`@dpvIQzOt*E26}-7&4HH@FDrg4 zp|5`8!l-v%IDw-)(EWI=g{u|2R6DEGiX6|XRlZ1pyoyp-45nAJlW0o*wXgWg%x0R; zdC|SG32bF|eNXWK->E5;tUyaMI1m(qNZjeiMHfOdGGk0>1HyI1%rDY53^$3TLh?t? z?AlJQ7K|Rmc+XF;tB$SDn8lvD1?D}jDKJg0(=!Q&6KjXFIR&!p98sdzv*ltyIcwI65t@( z@MF*$%&ws22`TV89Ku)JoX$wkp4G?rHsgv!xH2d7g-<^tH*N(|sCe%oUAOW8sWII& z%{aP>;s02Mrn7QISJ}S|8Dw;UZtZs=Q*J=3UQ^y%m+%^bOvPZwBD!YaFAA{EvEzsp zdo%EN`L|U%my`~pa>zTN?hSW?*-B#D@1+xDGpou+LJfKX&>cC|t`hTI4Ouy?WfL{Y z0w_}|;-Yv(f-c>M=DsearpA~t$H7+mTlUQm^4@YM6X-~#wS#~`8KF)kwd?;+>fAqa zzfk)b>Z(-?w1p}P+`eC*@*>4TX0O*M^wGfK^2vQUm4E|6zx)it5z(bzQniw<= zAbmo>;uhvl;@$r6pD(teows z;MxuvoDlI@5>i;03iw4tAGcZuOQbg&79mQuo@pWOXZ}{-{Ufz5_qiY;I$WP~ZqiUQ zNEh>|=!C>&e*~fWKB0A0^D5(pKIIwSlcz9`w zb1{v#0L=pe>xL~Gk!dSYL~c&=Rt--&Wg@}_xG2g;KpvJ$Lvu>7_ya5%DsiiaXO>Jt z?oWn7Y#Gd4&JJ7JlfJ=O!7;%ipM9uRR^;51)wU}_K#5GLT9xeWk}vX_7c!j)Whnaa z4+37=9GfFLhDk<`Mez}m8*!y=HJje-lhl2bfvtdo2KnT3moWapdWL~Kk$A2Cmfh*K zx9)}%wO%rgu#=%-baaJ5HQZXN4TSaDpElb>3?0D*l69@wO0hbkua5&gnm*6b&c%$MNtcaOGaTw*I8Vxt-lgk?JTBSD@st+c) zlV1T8r5Wp(HJqN(>(^0^7cv=b#XnNW@z0tF-Nv5{wk4Y{tmq(2T-nsCFexH?P_h+H zuy-Eo+MF#Jh--Q}d6zL5OpZMBQZzy1+?B7q) zIt6*@#Wx*5`dAq-4yWFH<{u^RmI}~xzLe`L8o=0fOZ^NuL@Ev}^1X$!#~X+AB8EID zl>eVVghq^yGH$nU53Vtn;l*IQoO0}U(QWvmm-O>6HGv`L{vcVwk}-ef9>w7?3=a+v z-Si@J%{KFd=8w4y2OUsY6iO1Bz7N(vYrK-kVOONfCvW~(NI3O7cAmBOaRN(Tj#^u( z21Y%Sf}{nTUD_T-#Qx^cF?ZS^{}}6cQF|w1ZSW|VE&xc4ZBP!w*68eG`Jc^L3f^1} zsyj}%&6hj*I1*zE3|3G*d3nz@8^hsvAzn2UFVU4Zh(a&JxgkBj0yGaEYsqt-^G`y_ zzxQmG*3kA@q%F!$6}UT{*6}>F?J!gpn?k~M)6f-)N5<1@H{^YP1~Xn_Ss=?@FpM{v zSp+?upFrWV!B>DMy6l9pfW4yUtdh)N$HYwA5mU?lj%`L`&hQxSNpc7q>!1zu-uqVj z<41jQSk#b{Hshm>Z59SVKz8W^1gVLFHp8_y*70(KdC^Nc#nRQDXBMW1JJ0>tyu@Bk zX==6;c5SZZC;a1f{9trqNj%2kA5(xO+aH*T9#l|kD@^^NkrLd>Pv52&I%&WI@)rS4 zV8pV}xS0xL8DAtsEFs3KAl$B~QV&vAPVKSH8VYc>4_38-mYMx?{UhkQ;k0ZYU6I>#k51Nl#ol*$PU2q5WnF8!DrUQu?N_LGjYD(EJ3NE zD-?k~23|wlYYMOI6-=19+M|+SBrI7f!jm9cEkw%gI&jr7z0m8nhcadTDvvO_$Quo; zi@2Mz1 zB-UxeAZxQ~nl83T!(%PAyui&FK1ZXN8(@z=i}7&eM&r%LqSuOKsye;HZlA6oRcwC8 zG);wA>bczS`F+A|W`@>jBVRy;suu*m{?RG^3P+Qkfkv2~f1=`PmTEo(Wgg?A2+$-7 zXt$it&Zpbq$8<7KBLV{^Y)ed&jP7C1iIW-QmqR?xSBFRdCJ5mB+O!7WqQk0cTmRhv z2d_n-pB;=ObXf|E#veI-2tXD+rGL;tKBOkaTjO+!r&KYFFWTTFiFSLMKVc&)N|w6B z79F}ZjZ|7!&{X@;{u?d@0%W{4A({Uv-&TPXxt#O8NL5bHKZo@2SIz@J+9iirGL_1e zTrb#ubntu#M>HOW>Q!dn*Do9v2^{>$-EU%hp&txW+_mJ)@J~{E3T&r}jTO#J_`q27p-D53` zWL3k=9wuX6Lx7*j);B{grUGN2SV_uBYLSuC)k!g#SV>hp-jSaR0*yCtQPNGLIk-ny z^0zoag(WELeSSmt6kF<@&ygJ`9pmH*vUjun)HTZ|6J7;H9^Q0yK5!@-sb z-S<|?h`g5GCe*dVqSKyhPuWPEC-^SAqf}$^XBZ1xMs?LuQ6iQ9u$k}J07dzTo#FEc z!9Ej*kZPj9y%Hy%X~kWsBtp?mKaiGyd*mr3nWa5iy4(3LaTmAAkz;jB08*ZuA)U+} zp=suQz}C@(Yi>JN&t1r@HT2sRRFBA5R&-$pSj88bel{j=#gNLSchDksPT-ThRi!0uln^J$&Mn?(GTh}wK!dyO5Z6f+vZ zP1Rn&iRf*v(h(ZjEA32jd8xAYUTQFjY0qv+qR5PU)e#o=g8Sf60lK)tie}X&2Nn&m z5!V!0qAOzZ;y-^^_1$VUl$>iE9)l~rCOEeW20G4(41$w19I!EM3 z)UTseZQ+Q-*`z|QcKG%6MB#(+j{xS~q$ZGT*^C^mmFY>FSUym5E^>e-yuyUxyu1Z0 zENIlbnqMVW)P(TD&nv`d2OMOu>FS^@noNc*V?`Sv)-B^`GN_WGNqAzP$v%;Sh&L?y z{n+jPjBoBf^Omors6X80H)p^dI3Pi`Tdag*yue z6u{)BngUssuGmoRvQ1hnDNfftH;;r>Gn@-Jt3|A~jREYaQ_N`sX+$4nn1>pTVoQu( zM-xjZJ#-xQ8Qya^lS;o+H9x%N1}SEQmPIi&)i~Y_DEBnRs78;D86-W28~Lh!5u0BT z?$zwtjjm9>{{YUesStNgJvt^&r)%;d_wx^F`p)o2Pl`%rXjG)SOpe^a1NI}Erkgdz zdV3fF*0kE$$m_v3L&~O02eeXDSf-ydw=a-^PfHrA-X*1aUAxkHSF`5AdMM0002216 zj8fOQ02D0ow*88Y-J(X*E;vVsle35>{4;JCh$p$bqw(zF$v3;e}nYZGGk&oQcsygyJ1x`h{JoL zUW7fc)LsCJ@S(!tKAqDIYiH-v{b6MnU~v2YH4b8^`DF4>Le4h#fhO9YLBqsI7Py;s zG57$`ATecyw4T;tyvj`Ub$!vX{7JWhf1or}Rr|Y#_c|>2gW_V))NZh#6Oy5yh$2_C z$Mf7?2rCwP4>0T64cRsU=(X+qeb1dtB-M0ivRq`MI*v4X?kAzU9bZ>d%!)`J7UqD3 zegl=zP$nsZlI2$xf|C@Pedenl=ZSGI4QDdvk*-zBy#A`=UdzwDU_q=(U31+U7Y-y_aJMWN}Z+>>ht;<$Vvs!+!H~Dl^-l z>sj5sSyIMVGELi@aFHUAlQ_L4J9(P$RyX8J>4riy&cohBu$Xa+wGR zLmlc*pF)aMQKaY+W>wQ1*9x+b{ts>dJlT{D7}*^^vn@QEYlduM2RHmq42 zmDwTxg?XpW907&HB< zUF?s%@}`n(c-DmfgA=EOp#R$jj97;i=T~UT^@R=8bjP-{5p(FMAvH|MS0iT+{wZ5w zbpGYdSaDkrQM>|<`~{&%9-udjq?;&8b)9yAAsp4=Z;Zf)6TP=H-7>JI3JU_;CODNm z$7BY8eiH><`3z>n0%OLC^3JjmP5_xUHJ48)TTg=O1Y6UdDL%A`FrZEMh%Cn}U-2C4iSYYP_L5Z);kVEiScJ!8|EoQ^bFO^Ovp_v0TOT>5B_LsT89YY7unvx7c+tP#;V)4$+D2NB|^9{9TOTBHK+KEL3 zE1cQm(oeiW!kE&h$x9*qe1KNEm$u{E>SRR%cpUG=NrAM_&FI|(CQVwW@N1N>I2CMv zO%*51A6woqlFXHYPljgc8HLz)yoO@xsR5a=O?hcp{+%Qt&8EA(3pd1TUi=|3fsb)v zi^n3p?cbbnJ=EFkJ~2xo8@m}F14KbsF{1~ob4iybWi|%%-l}JoT~n?ZFxA(_>!RbQ z+xl`AohEgq6C>`P)>u9J z{pONv2dF1!`PUnLrlGQ0ZfGD zyK|}PvnmEnCz~m++G>S-4!S0|vRrnQk((2T)1SSY=OKG>3>+kyc8|1^T5^jvXyb$7 zmRlcHPo3|e5Sc2ZIdR5zUI|X3$l-DFxEUule=i{y68Zo?>vf;DZ9X(^juB2jnYJZa zRlS&n`Yy8+)eW?v<0N{3RWN?TS6FvYmCSvx!J8}+5n~1E+@%85g|2RLLF+WC$v@@y zI7tqljA2Kfaf94xebiXYWE%7%8cf$_pMte$;3!@8W&|NAb<^1RPNv2$74a&1YR(y4 zNYqu=;z;)O(hF@NwVn8}YAx`_?F?o78uUhS--;ZTbG)&+vAurFe-zSV0|>$Q4zJ3^ z30&Fp8VmV@Nc8s9zpr|2n~jQx;AETSYBjy+oc!+eTGB4SrkFj1*coGF^>Z;6Pi)F$ z?JXCa*LC~&Cl2ARBmt5`-;-#Ka0Y)BLviqL>BZa z1I!+A*>>y@jDAY4ZVR~um`{b21?@{R6$|~NT#MOA825?qvpMkmypf5YdUzib^xfNFPWvF=+Hti>{fhJ9LL#d$7^er zYKu6>pTEy9hN~O2#f*V=TNZD6xDR-6*&^ zmqxxOc8#F2)(Gc7jjwC-v#w2{A6Igi{Vnn@bFqbu5QhM#0jr04Ac$G0{;H}~2k>e5 zGRVvtosG(c5sygH-iO(J$MUTtVZ>nYIWS-JmEdu83)kfj=U`$`hSh=v(NOoNUe`Hf z!@6~`(DRHb6VM?|R;Tm)KFvQqq)M`yjtICkz$V@5Mm@dBP4A^|YD|h)o%y0{q#Z9+ z)2rRl&H5V7_``B|1=N!6P7K+UJ7UTow2RW=d_m{Zk|!kf=MI-~yh8sTq-R`h-1Hw< zDu^I^n{an5e<8jdb5u2VA-7x2sPZaV&>dN6=k8c{WV%bqFe$sh@^~|?g_`9DMelQuUdrSekjo&za86jh#!5{ zhzyyFSVrm-gEoYkWV&FkL)Bo;%l*|YCylS(^KEW!Aj^y|Csj*Jq_LM|o z3Llv3gum_ZIAl{Y+`36|bx#06rM^(^lpNm>ea5;myeGGzb3G*}ZfG#_9MH2nT52#k zzzd`sI(U}-K?+XP%~JxJ)99f%hB(J2zJO$c^MxWEUN-JFTnp@vjg1(BO%ESP8t*ik z(ubtsLysDz-2yp$6sV=Nb7}qt_tG_fMOVVl@4{LeVE~8JNI#RZz7k1@uVurO-!2yB zOMK#ZvJtkP*04boI?{YdUP@Hi!lelx~9ZaJBm-mDlq}BLv>)Ex{D6+fP=iOR2G7B6GhKuMis@pyn#Ax-=0^eCwgZz>eewxh> z`@rfe3Oh#|xc#QENc`vzZ%iWNiQ#uwMaZS0DJXA6;Jy&d)hl+|R$SSNs2$nq6e2Da zbUdRU-)0P{aCTk&Q~X~dt+=(duF~H6bN_9t&q+0H59Kq|US`euZ)r1cwEPjy zto>VQV3>TbQsNGQEW258;SWV+do_!7zP{i0a_XPfbbbXZMHh3DdU1u+@7H#-gm!I> zf!ftbtOCD1oD+!~S~#Wp&Zi(~h09G)CY>7QMIo5LuO(fqGHhJ)!m}q%XQDf*#d>U? zprdIn&xQ;09b9UVhwleX{AO>lVIl$4+QN0I9yYuW=17<3#{iivHZ`E4532Tj;XEoI zhdAS*Iz-ig-?T?tizM1=8ge|{2)myjoFcMDe)*x3`+mAHMy=&eqY$q1rCh3O1OjYy zKKy}w3kI4i@Q}=&r;KQOFBVwa-@#P%nJRbm^h?}ld``0MdxA=;L&xOHEBMd)^>UOV zn@TLtg1hf5@qad1xCU-Gb+65%cv&Pen6U?#ZPUFi=@Esu=aqCrC#T(aWo{NU&#J0E z!K0+MKw>PN!b#1XW1%agJ%8cCGa+q!T;J zJ1Y%MiYcEX@dvWo&tR8q>n{1!KOn!zn@*>G{qx?6;cjkNZ;Z@D-jd$ zzXVcZ2+6JQ&ah(puGlpK*SCC0;y~6Q1QFfW7^{XFiZ48h*V|+vB z7HBEx5lj|#(!i%U4umP3`IQhKKMA>4v$+x(7sxsI1l0-t-AmoQJNslGG(`m4TkS&c z$RX&omEB+!PExsWP_H@OXvop6>6K}D$xNCuD7cW9WUgXcx1#GFFTvy2_S1V|A!IY( z9C3cz&j*RuHwpZG)r%U0nR=6mxB6&G!cuMwSk-lE5&&T3B#J9Wj)j8$2triKkQ%~1O0T0))D(8Y zW1hidIp+o7m5c~70F6qN`6W<%NGgXg$TpN}4oo7HS+yMiLy)U@|xxCH9r!I(76H>KcTbJW5|0f!$CAxZa$1x#2zq9e)ZZ4#K~{Mqt26b{Tt_& zRuuReKTBQEk6?^yiYm(5cCsZ0_6P4%cv(Zo@FU>584lwhh{#g0uW$O}MHVESU_OF` z!IfQe7gLo3b9EU5l}S7BsRBz207fTpS@mlN2zB+UQ_RIO(#6Ns{o5D=Ei@|!r;U%Z zisOxY+`VZvLP*J>hge(kV68?egtFDLesIz0ttn512}Now+*whoH<%b#z?7ef=ZVfq z;5PLqwG4^OIfalIp(;Gss|krP(>u2sD-_f0gsb(lS-*v9#-zUTXbLhsA5^4mIK_>v zh7rWKuuk*p(n+jF*2%S|sd^KG3w*~yI9eiT`~c7-2kGH2$j@UBl^;aL8?ezLk3^2_ z8TUASy0L$FU-~nf-&g?|q5a&H${GquCX>fw0&7x1oZV#0Sdy2bktKJ#MtIpsa4A?n zr#m5h(Qs?l)Xt#jwd;?OnG^Zs+U)Tl7!qMu= zSFSS$koVW=l-+#rT&Bq+FL|4T%IGk~nR zH9If|{RwYUMeTnD3M43j4DqDsjr}YC#P2ebF{(Aapm$Co4y5`Nb8U$-hVkVA>}Pm( zK7pYZ@%XLDl^1kWc-m~sh2h!(0noI!yp(#I3r<5t3(MI1uQ@~Yp7f6Co>s)%nG&T5 ziZO|I*d?&C2GX>Fl2_>Z7^F(}_qx}tk0nq(XxN{j)9Z4;JKc@j97rx1~H5Z)XiciO~)a+c_R+BSHlaMBmH3s$$BF`Uitkp5NV_sjhO^E7jQyF9f&?Bsn; zq%IzK&`&rEt+U#SxU;&u@{s0WYk>rduJ}<%(&Unyt41KlYZLQ)p>&K3bjuE zyUH1T(JvhAYe&oEEJxMZtVqcO3oCS9D_%psMz(2<%fTf;RMJ;Sw960a%(Hb<_^x zEUTw@)!;#zeg@$U>LXAvUq44M#%O=}QnR<)SkD3rP&;=F*_IzXAxJLj6&T>|uvfGH zIe_xu%_PaW_f-3#7;ODL&FfSIpNf{-})TI|rJsf^dgUjnG`S71vD~fjk zYy1R(*CVND^G|8o-$eRb5`Sj*+nI4sc`9$@_K$7A9TWKJt=_c=e9pA1S(;G-KI|&A zyb$-q87IQP%G1Bt9u>;TxB;Km7ykdyCw_P8qy0Pc#GFwIE}Rr&4UDll`{P<1EOF4Fn4g52+}!e~JG^ zf-Ug6B4PRf=6S3tSM@fI7l?u+R>M9KF&$F5`0?)*9)?Js6&KXt64aq8xH0il17i4b z9>sHSJxD5T-NFs(5+uu{{};I)K|E$qo+;ky&vZIH0+M=451F$mJzTM;S*S_8SP~G#(Fxas{79Rs8 zCmsyT9fj+J1s>D}3hI-gCCz`~!ubk~Fme-*{E%6QqYKP1_1(k$N<4i!O zI8&z*UfZF#;Ylmft);&dQ6L}eHjjd~dF#5Zo?E>ESOR*T3`>L_4IZHF$=`m6bx~qV zA+~9j-JcK?n0xs4R?4D?y!H(jh_^2O`E#WI^akn-Gd<|UwSnzJi%9)md06w=4^8Wx z4`NCdlyhpV+k2A60}q~`_l?3uso~fB9%g7L@kpcp(CGAh;5dajgu>Ko8HSoDk)RkR zbFpz|U~YNuGRBaQloKbZ#1Bn7mtgktoh+^Zes{~{eF?@vF7IC2Z`|%_p=kG%q`F-!!~I9!n|mDf(g)CEsz(%gJk4Z z@SS_cR%3HxAiG+nQoK>cn81^(OXgp(`AI7{M~(kYts%mm*7SWt752(`31vmQWZV;9 z6bBy}*@?yE2@cdhtEjdosXj4xE`(L&iWhKf$Mvo1|Q3 zn7Qw>S=xLTx(-G-S?O=y7&ychHvpf zA_dgAzo!%4*mVVVfuVYz7Ebpz9PJ79&ptX9k)%L8AJ*z>s{H8R{FRIqZ=}r=ZX21S z(5^2u6(mS`a9L|+-dno!-L`77yyj9JJ>3X~=b?*shGhrpD%&tg`WoEl6jxW-7l_68 zeZR*aZ0YXV&8$ajH|&h%`*)%YD#QZk6XZV;QNDb{?qnC;IoCdW-h3Vez~Sj!S#--# z60#*J6NOea90(f##FhViRJ4eIy-e<7iVU8b_cDLm%SR+@7}R&On;~%1s)Fg`lcl1< zELGabK+k;zcna|v&9;%+U1Tg|UXad-V7i*fwr zp$7>4edp-8J#eR)L=Rqn^EQrQ4wG_ezI%WpxOaRjQ2!^(1thrTVvskz7X#4Q7=D{6?Ij;=K*Z7omMzG})k}Cma;(CcDU3J!^2#WT++WV0S z9OOPg=oh~`J~TdaWj&i`4VcH$1ry=YGGYZYZ+gJ-n2&tz^hK*{pPB7h8wVp8W1hui3C>1P7ID+Iig@si;pSj0E7G_{5BXhAH4 zy^_(O9Vhm^jGTy3B0mhFlUgu?=vyfJ! zbYD?DtmS#yPtQtIUm-AtIy<;%ZgqvwE{k+rvV7C!SaLD2#KO$Q8iX}xX;7U#Ysr0m zy;K+d5adUp)!muXlx`_yI{OT>&BWl>$h4ho!MF)+-`U6qLK?b2ZN^d@_m$Ld+GJ8E zpB4`LVuO9lGA_t9^J6tY zPo<~Yt2itIt%&fQ?qFg?!CGk?lQwuw-_ANtk4k3|SyKJl`67F4Ky8E}RUe5L{2V=a zbp%bW zYO69m0|3C!u{>(o;dj<55ildja^~Zww*y07e&}T^%LL!X8}~FAG^p)7EO+=aOSU&c z5>E(?2mS2hnZAx_*jv_JN<+{F22Lh*EP;#;8fo zp#uzz2U+sD;QvkFORM)vP$6a_OkAV&_WvQCn2{b@ghU+&5&Q{3T$K?B9%d2oB)XHH z1nUK{gw)RMc(o+-p_|;6X^=kXw`PyO7J}{9^i3^?&%P{6oR5$0Cnb?6s2#2eR zyI;uuTR9O$9YHA5-uTVrdB9LH(7ZHR#OF&QuE|(Kb#a%SP1`UcLA$Zr+%b*~y@ZYy z(q9oAG*26*kHUyp75a6@3tPIS?hQPenNrX~&K9BOLM^cA{&knGwp>)908+4W>a?RV zeQ!{_GMl}Ncrc0OmnyO3H($KSakg_x1`GgeieKIrT$0A~)sac_l}pQ}W(C!K@Rz@+ zo}iHn z@LPacnA?Cto#Lfu;~Z;uZ;?|^CidMkANEgi1JQ+`jw1#_?6^kgZr6_ogP$?IgI?HYZd=xMY(`b*DiH=^g9OLCcqQPYPJSdMhO$AdbWr zfs%4JaiI0aC>-0`o1VwyQDBN?>Yr-HbIX(yBYVEa)gJRF{`jU^Hjl{ko=K`oA9An{ zYbyKW)u*#)9fguQeF=!C6G?CBihm9U!TsBa;tcxn2;KP7fOI)L@Ri$6iwf}$R^>-B zb-Y+bq))&PU+-LYbvj@qD#YBZhhm8D)7c*;V4QG0US(;Hr;;#^d zbk{JvuQ`{Rh)VR>1Ku-cH``rMvzuzw6kdTw2YhB`yOTtS?f57nf=H_u8dl6B&Knw1 zSqFoeCbqm}9zrwmwcy?+$T+61Y%~zF3ux!o)6Ue@mq2ge3!@TsQWTa6nx%>5{b$(o zfWgpGPbG6MtaLmxqu67RdT;LHL?;vyKVTtc5S=(q6sN9ApW>=?1$5 zF#Cl(fAJE+97OFOQyTVytlw4^Uys?&Fna8Wyyq0tmBps*?U{H+OGf7|)72gdJVNgr z6L!pL>UMr17pcwXAI{7t7C(uKYXR62Yfs0Ygx=P?VNMkD;ul!@&R)fvwK<6k|8T0y zJF{f5k+&*84*_ehH_K9cx@WhTL1p;-fb$K#N&%r{RP&TkCH6H;F7m-b8}+;Q;`4Bt zOzt5FWI;6_k{QMewCaNupNDcC_R5fSvgc~|^Vy1-_g4|5P#G8=emdId=Hb_=U%4iP z>x4I!5GpQIZtdg_gZ&bgxHV0@=>SxJs@JYh9w9%BAcveku`YCS=N?j zv{GZ!-9tttX&tSd*>K~{`dx8iZ1Q@YdmeSH#Y~;Iy%9qFa%B0F#!ueJ($jK`Wbj1a z^~-5{;grAhq711$;*==y_$5;s3)UBTY=1)vUCYUqh6LxECVVsDcA1=%T$!B`-_*voe%?X4NXSn?=|Jw-!JnTTNufh zr+)RTh$OTU7j$~<`i64pr)a~kBlzKQb9lF zJ=Co*sbZ9JTJV6$L$T{(Xz2z!dU!gy%$&*GqEW2F9ekvk6SOqJ)!5&!ug#D0?J>9zj=fh6M*O_+%=>nd z=KjyM&MJaBTajJI{?d*zY)4tc6TwBH&3oaCQ-K=xk3DRv!)NFLFUS^UUEwrVu(?QS z(tAU}$J7~Y0Mh)@cImO=ZZc z26wMt*s(q~GR!ByO<=wJ$c2Wl$HtXkssWEL&d9;kDrs~jGQLa1XrQFjcr*aG+dRrH z<;IVEnbQR9Yq1^b&&4Z`F34N3(vwH@e^EVlJ2q9r-Hy%{ZViI?5BKs)2&G|m($s#- za#R`JPDIl|NtW6;w4(kO0HU<6R+ILdJ)E&>kzYHZreKrY6r54Oap6KP=^9tU`OHD> zW2-UCPld>}cE$5Ip^_uU8yV$hJ80Ex99mX!iRN!$g91xPrv2h)XI-N6q`+m0-XXe& z(S!!4oaA)gJq+kGVRq;`O~a)YsiK5gHH;~^%s!|Iz@$v7e1;jC|G0It5LO5R+?E6P zi!zq-W3F%BOx&HE(3rglxWQ3GK=O5E)ErA>aME>iGwTOwy@n$Cy}rm+Mk`~)tkM(5 zLIT#WdP3S4Ms-}tw`DLf-lG@4n3yB@ZaWAICOv4BO{Mk*>ryug-E<&zBiz17lO=*a z{33Q^J6+{#69oY3Z2(O&^b%g5a02{fsfLtN=9x2+3=O&ofN+;OM_4#EwrXk&xZ(Ir z9wveWY+Ra=21w53(3*Nts;6oN4Ahb*uwiWF+G>1E44$#1c(I)Eetd&nmeSb1f$*ZE=XjT>h!r^Ls3Y zLY}AM@(93qAOnL;KbE)i;{!5~pn5EX`+73x3d$m{wh4BYk}%;o@mO_rV*9vr!Km!_ zG3diQCl)jIbVL{AGy=rK%87ZWANn@+#WGm!q(p*}RX=axkl|auAtpNXD{Cvt!*bU5 zgIjunMPm45a)0Rn^$DTDyC-v`TzFZ+wqk03=?U@LAW>FV7~iXi@he~Qa=bLZKGh+| z^g1JI+saB}!sqYMsTkkM^Le^?=nD=0>h&*DR$5HQPEmbq@Oi^ZpP~-e1Qe2FaPnya zk>x%_;DMk-p%?w-YAFu4efyW!oN*sWFe^tZQjBl@m?~oqgu?K}7SYU!Vtkk_uZR%! z&*m*m+RQ5|`S5x6{+A!g@?TlTYD;&iyXsPaOpSvNDvxd zI92P-RbtJIB2ge(iyKdzmegXG-UTn!1Bg8#_H#_-dpBf!!23>G1pdEeL51};V=&Ut z@V(6?ZwA&>TW$DUV=Z53<@PS|!Rb+sf^9U*Ed;NoZ-H|Fc~F%%^!LRRr_-Fs?JhN} zPPLp3h)1(C?s_gpnvI!!L-87ehfm-U$pVP&Y1ud#3!tGK5Ry;Azk|AAsuN8b-eqXM|Zuj0E_qf+7E-$S5HGyoFt6*t8EFGMRgxbv%vU| zlyARtOcPE;J@BqHS-=Z9)mFGJ-x3o9U%l$Ud)79F-$n0!wSVg0ALt2bH+R}GQ;d#c zyj5Furr9L#b|uc{wZ%yWU|tZ;$SS{n>| z#aF-_bRz~K=5(?Id5p{Ar^>AFm6Ylv?89cn6@2e!^KMbY99&mLI{@!A4F1ANpy#vR zW1JNC9l(wRY?zwIxoJ2c?|>d`gFt-GM?@)()fWyS9AFX>E`3lddEysZ`qS;0#eS@} z^ik3H)u#>RTDi{FxDGnpu#&W)V<_FTX?qoQVm(2{PRGRJ$HZT}_n$Jp+MW7f>MB}; zhs#BDt@Ri29cdluHYW6&GqN=w|dT$o6^cRD! z=5*}N_v6$1{Y!`7tQNKXqw|5r8DNAxupkzET<#JJ0mWl0-Lz=B9>r*8GR*_5TgwYh z_jzI}sLfxGpA(M#{afz6#8~C?cb`Aw^tx=)DOXw%s(Zc2vmOVHB z>84rNJQ)@7EGE)pC2*TR$XqiTk%Tdf+<<87Z^JVGWWSttBL&wzyh=hF}1V z+7iVo{lN9SYJ{Y0*Ek`p*iq`QL)1((MRjD$h05*CW+WS*j8h335Vs2yT@evpQRs@S zp7jH7Xa8dj`${8yQB_`b!H*z*PTRs^T}z7c&RLkM4+F0>{M6RHbVpQEO36_tzCdykmxJzgPYI9UG9=Jvh?d!+lt_wEIarVqanhji5yRVz=p?Th`=0 z-W7OpZcCY3(J|qtpvRTjsw2QA@@=%p?ffcmO$q&shN#xg%|pj~b-v0U#17ZDkdv(4 zN1kjdkg5=qC6oqo>(FFW^?-iSrxT`Ur{U9yt$oSJU=n$E=gaWqAM!8k5WME;!b+I! z1*6M%=sm^b+)rYIviZ83?7)Q-%~6zI$R2jFZFLhLRergon2S8+D9n~X_~Wj!jT#S< zpkc#E3K=nsEoY0V)KwS&(dWT?Doa1V2m34}#EYUbKT7nQ`q5(zeG}zmpV+AaQoxU8 z31dT0bV!LvVcMA0_%N>Nk*|w^(Gb@zAPj1Y2A+Q6L~9xx``joV+*hpDWXn2;rFP*$ ztm1;1WGi^$M!HTi^-zQ1ud0ka%5>KC@+#Q#9t~ht?GFjU2i{Ow@8C#9>rYyCKLYTw zkZ18ZGY|u_v&f@i9e9$a4sC}rR5-i{1A77}`vuRwFX6GIeQ0cBSbQM|JpkhXqp|^B zH>o>eZs8q>1%!;Hi}d&uFvL^F`Ou)&muMWkReudT4(j08t$JIylB!#?^hi!;x6$k? z!kT(*jrZ5$(3PC|VnPS?=@Isc3P(~%?45>^8Ih{@;;L;rsY`D!)05kYAleSwa*zEXk4xJIst~X^Ej55c4ttcC<~6G(6llVPkU<9 zxP(WhmZoL`o}tfwOZ&r;{bV0r-x+OC5lNM8p*(tN;h&hFeW)iRjEzWs7o&XxD9%Hr z7*#y^b{z-mJ8cRgNc~?}0}j{coflPBa7CzcTnu)Ig_}$y2UQEO3cq?~9$maR0`_jdC@IH6q-_FA~;y`FG+O1JLy& z$BgaWB~Ivm3W&{Pu&=0*V6SvF#-~0%LVw-@gxvfLQlT2NFL}^nRTew$vPYVgTRn*E z-MN{^1UQqofSmw@;F*+(CAPo+OWQwHGd)% z@+0NoHxLhHI{|~0L#sGMUXZ}=`)EP~Yj*|=qDv@yGZAbX#7VgVPwz_^M~yptH3fbS z09)Z-v?j4AbY>>QL=lqULX)}pEItFZ@y1W_RL|PnU^n}HrF)IoF$!AJcS-kX%P;Ls z2S9e3Wk-nd$MoFtX|bJ$YWZ!^)pbpDweQTns`dRq$JZe?>Frj}!FIJ$&Z#oCCtz=y z=sG~tWLkLW4Fw8jE@gt2N7nNY0=~RY-(IqKT`~Ez-Vbrf`85I_ngECop|~JOCqV5l zKoJOrthaK$<6{wEawZnk>TwKpt)m|IIieK_SUX2B0jY!7qGb0aeR9ZNZFL*->)39Xd@ruGkDB~w)zpt*UZs5{q|uGsgR8% zi|ZER4bmd~M2`ifD3-=ol9ncs&IeeELrxoxewq;ElQ<}?+MU&}%gGGGlYosq#x`H} zvN8>(o<=d>$dQ3QOW%|3wccAb#TO8qD5@5Qg)w5%5ba2$WKZoli?{E@r~~VPQadt{ zTpQWHF8{u^Gb@Pgq1Pg3QAPXEtLUGU8$^+Brh&manM$N%bZZNhUn{2c&!Pe7MnqvE z-;75tCm=fdvrxvEnhYusaQ|~in3Dj-0d1lB28Qg1i%s30lqbOtVAN}G0D7tCS^vIX zFwva$D5AAuhS3RPCW}DSs(oF!0JE`<4-rUytEyxK(mZ%(VW5i-C5!eg>x!VVVZ`8< zI1OaI4sVZdrd>xt;UY7c4wywU=dD%N0CEO_SC;jr;cFAyz9anPdDs)L+-xMD4y23IPq8xvt zn3#wtlAjr)-%1_~Sh{n<@PfQ$uQ&}4JI$u}wTiOXj!lVmh2W;{6*9>Vn7KkmpER8* z3Kto-y0tdED;6xXqCC<|g>y9q6@m8Ol43#sncKBX<4~cuRXxF@C?I;d21P>U!3Ok( z&y~%&xxujdbFQfov#W(Rqp6muuRfOo9al6dubXfG=s=1Jn=qzbkLov( z7S8d(B&PEaAqhmvqMj;vwedz)8>>Ri z0zN;0Y3$nss0jmqU(mWc_k}yCe;JOgb8-pB!L4Ud4n&v0jENDmpnr5fWvmX(CMQY&S#_Lq+$0YY~Ous}Dyd5K}0Jbu**{FV(-|ei%7UbiAH@L~9l{ zEHX>|JVULLQLA~n7pQ7->lNF<*sN~(W4?9-kskN@7G-|P+M7<-p7b!nV3T)g6hBChkt6TAJJC1M{M{{WLOOKP4&}{MXMWk_#ZRM&XyM*T>C(?~ zIr1t#BU0cRY6g@YzIC1e6ZES%$1%!m2${s29o7rA9=zi9j7pnItb=cq_r+}MD69YL z{FB-zO!nAJWbBf}QG1;ykk_JER#L|w#UJeq7cfJQ?TTeS>si_bE|g&lA~)O(qhLL{ zhkq_~(Ht>+ZX2-n?*DUSQG6wK?-}Jh=XcZ?(->H9!0lss11m$HxVGRJ!419I&h8Z#WtT*N)8)Y2F;jx+4NW9f~) zyVpH)y?(@^y2HF--plVb8Lc6xT-{6pjApEnN&3yf+|^ChJfOHBPcnoQC%JSn+43ZLP~JNEzpS`I2L&@Y1Ne_dKBYH6-%axd zq?2ilKpM?(BEaQCmlaz0eWoSB!pUzr%fDn0zrMEv%WZ(El0`&(RLzG(OJM>VLd7a+ zPhbOs(~)~3;s1H?z4@vYV?Op7`$Y5cW#yjvnUNvZA7&kj9OR7D#yg0N1le>vj}c`M z8;h?G?uj^Ywj1IN_h5Up$~M^CPp+(FW6ng!ZR&M1Ta`z!UnXR?!@@zBOkIk`U{6KQ z*N^F74C-oi;`;%|c^tB;UWmvE&%M!+?^zSdh9z0^S0M;$9Fd6f7j)c+tQE!77IB&OgaOuY|kBV0kM* zIi|?G+{Y=;ZG4YM|DEyrBE2^=CYKov~aq2|c_S`&-b#z@+i|G#b4d3g!K z9aA9cxviE0@W`@C4RbT2GZ`g%D-xHlMKdG8oHWNaumJRPh~9@*ua$Lhqem!`!QS?N zSQy~9%aOq^&ORt^R@@*Qi|@jC+|n*ZUQ^~#?SF(RR93SN&^>1ghC;#p3*BOiCpH^$ zaaS5~J}FudCmD8s&Kv;WeN501uz|MsmKm(0lK0;hFs{T83la=i$G8rbm-aQl(*)k) zET38ND3Yzx_)sK?tHCL_n-WNU$*)j4;f2>E;BKj7C%Q!^du{tW0W@WmLMp8rX98kV zywK==Pd(}}+`~c-D)KTo^rD9v8U|s;Yga`}_Q`k&(qH>+Jglp?kQ?B)0BZ9mHl9N1 z%`^9C%jmz{fkrx&$G<=dA`C99ABdwv-^X~6OZbEUwJ^x0}pA> zj1VFf$x1gAF64s((Wmc{N&;;Q`E5RDCLdT=)D-yz5{%zxVo}KTVkB(fwDFe_!H}HY zvm7mMo>!20S}ph}m0=yqy| zKpCV&g6}g$m31vGJcX=cRIQI$x7ve9q}MWS(e?Mcf!H1WEl>NEfW=)@@~%1Jxj7z9 z3a1H1vb&BmKC{zdVN|^p!W{($+C7vs?49n)f@e#Mj_FX2A3ExhrH(Zul)>StC&>$SP29jc#ryC{(4d$$3+hL=9x06?{=*nj)+xb5wFI~|7R9X5xLL^hXy(?H zeQ6ME+b>1S8YM7pPzLi*Wohm)*+?~$2<5Y|Tko*+Pnwjtz4M4XCWDJ0iJ2YSFnkoN z1K-p{{S{^H#jq~tbuXb8iT>j#;Ja*k>%gkT3bI}igZ3?K zGc^8pXZ*&^$K7yfgWiV=hy`J>zTL#x%7isE;!AZs98VUrl*s16I_)tBOpt3&?0qsO zRX7~Ru6rgaJN>~}okIWXxRVQvz=qf&Q;FLxvH)Jnx7hx}7XdTR_5qxM`o@~nRJ{*8 zy{6i2&!S0yXfSkfA9PLLBhp`@X6pLBsSZ?N-Zs#BMb|`{2i6zz%%n@jc z7*`@jWq$m_&D$@?pDf?ETOfPgQcfK^6y%~uc$Ag4ND-;;lh@=0b(SvuM$~?^FC+8o z;?NF{-7YG{o)7r{+h4VHGqjqm5ezQmAb84iMjIvOpx~@+Et3sQTx-0EnxS0@cg;97 z`@KkwIjJNslDI)tQN&#xRGyvuLGFgJ4Pn34UNoPbpUSNEU8Z|JhLkp_dU)EMQ@XW| zx7zs$!y8D}Ga&m~1RAgru{Gcz!X4zQR}#5j~fB#s|iJQ$fj@Kw^C`WUhOrec4> zkc+Xok-=^`_cHhBtA^(bku6G6^`ONH@2xUjl=dZ;*3?s*iMkL4#&#+L9I;qeSzVi? zKu=}JlPHA?N0c{G^!7fs3~62vDSegHuvukfV?#)Nj*56mJSV91sZ`E1xNJb~o7!*q z4<;NQP)C&xba}m<#?tv@h~6OqE+d86LVH;*cNaxd#lyB$`?;J^N99wy4PYpQp8+)S z8hL@>b}>g<2n_o*VggxgCiG#lpdsa}zOD-*G&_=2()6Ph7>*yc0@5c}>P0yGA+BMjp-I*OjjiK$E;mpYZDsqH zoO6|oL~*jgnBpOviR$cSG*>k@k#gnGJ?mv5D}23x!12J`=N2B{GROxEt&ioGn?u7v zq)_g2APygnq(cTHqsHsbi+?;*wc%rNvqz>)`X&oOObulk`~B$MWICk{a}3ys--hQ5 z$_kGoCz8(@{YAEX{p@Q6ws=2O zZL^S|Q!?>0`7%U#mr1RH0`(zBJV}NV6xW{A@e{<{*tEiGC)U##_`F9`MS2wvM9GvU z67&;F-2itve7~#XIqyzvk&38toJR&m+xSVbv(v&tQ)Mz}f(_9h=~@Xx@C zU-b(ORO?W|f{0n!(38SZET^O*iWxj)_E&895LY=Mu#u~mz}s*cY;ob5_&w#!qAPk^ zOxA_`nVNaBDyY6%`tFoB)MEaVxe>;V2KF8(H?Q$&X`X{Q$VT;QBkXs{$9Pp@b_HC$ zOex-|z@*W953k+g)by24aQs7p5*X)D+N;Hsd}_M`HFT5$6u*yot5cx@PAD&W$R_Xj z+@ARbU6MS8-8Gv)=7DXOaFOZUnOZvU<{cAL?0~$gHM2m;WPCvx>6dP=^-e`moG=#c zteZS`1V~1KO&4wAmvk95hC*7P39;?1arzLXZugbix5^oEAJK@u=Oe>(JP_Nm){(p6 z3fET?ZsHRHoIYZX8XReQBV}(40^}vcfl&j6F41X`Gl}FDpDua>>4Zs2>CWs4w7< zAJNs%Q(V#X{7o@Pu1`R-?_bKaqr3372$0ba;`|v&+$zx5f0*6{*c$etaCvg=av^kS$4*1njx3)(v{Eb~_zp?Yds?>u>isWUp^KHjKC;L1 zs=91xIUuw{mNdQsl-^q(#HH^!Yn{G2f_?`_-hUt}C@F?z{B*-R!~_OZ9S+nr?Qcjr zI*MOJ%6|g|%G6R&=`eyXt8@1QTarW8PLCvlD7p$VOC?0IOUmhUs zGk9tSD@G6b8JF1^VP6XdV)QZe!dK9Hv_@~GWxwG^Y|4!^|M9#*K6p5q7zc6MsWV-A z_UZ~QhnaU;htVl5O)-bcGuMa4KHLua$BG%tNl1wtWkx0sJ*kAKcm^Pw?_{Yh<}{c9 zhZ{9KOSHt|pYO7-40$FqM{EyRN+tpeAq7ad;*_C6;`yeF4m_}4wrZP6-aou@RC$~6 z(ttW{oLg(CpMgSc2z58)qv$@nP&Q`4Uk5U={1oeT_B7af2Fc8*{V(a}bR=r(@s+^S zt2Eg;ac#HczG1QiglRtKaA__b5zAj*JF=gLkW|;-a%@l$!STFdh0vEe2XJ1$f*l}3 zr!sQrGNd( zqBl~qYPvx zGs<`Z9NlKvu~Vw$rgm>;&!Q7xdAHByHW*T)tr|KVoL~1){{&V%A}e)%^WBae7!jI0 z-E{B{du_PPa>4)5@{oN4+krOovjAI!j;MsWllP!yOwik_0uBAcmDGZDi6j1Qe0)OV+R!^jLnkY zcq}za>j3f~D74T^ET57?PF*87W+#E?m@;ljXT4$^$Xgdb3}$$PP2H~-iQxoIj0UKM z0T!q-g_^RG;pAA`JBkg*hFhlSJ3yeAPHzrho}Vn}<~ByuLl8Q{e7GHP1?-BdV-iDe zs-#3G4HExDn|F7vFNwX=f}h-s$qfGRys^dc=6_$xa+;Dvf~I54;7W-(Wtt_O(CaPDz=F zXmxcM?{EK&vp(81DClcr>QXELzW6uYVT>a!DceGUk3UjW4%h{112(iC|7VhR44b z@H$=p0V#rOmpMcQAUh4c3pdJt1`j=6e`MZ0_LZodUQ&>K6yI_nmmbqiFI;uT=8oEL zp;%=Z&;KT9#+5kq45M}$AA1SIgWv?#sSXY~W(k9k;s0L9vs3pArO(Xwtrfi4b+F-~ z-`3@$fquc8Bt+ynj6?mWjs^Afs$kaI|7+5{;#O4_E{HN~cbV#d#81;3S(O7^6m z&@qHoZ>RZW4UCES0(`LP%c&ur{_Cwf~)?YPGWvwTw-UpQ1gqS)WTxp8YY-r~y1M!6v>S4#`LE=z?(= z7y*H~ecOC!+4fK2p-m1_dUDk^h`I=vLdNB(-Q~e5XqEh_%5ppnPDJV}ciyV{7sv?! ztBgYUUKa2VMtbB-%*%mNa=#L7+R~~c0!VnqL?~`0Hu@?wZjN>qZJ9<*7Z>u2Vru`y zpAAV)6_i?VcY2vEjVRrgoy2lo&e+-FcTaH~!KB3ooj#!Cc{Wk10*mqw1H!Y06T->P zi?)VgxCWmKX!%X@e1VeE!0JV7#1am%2gNJ&|0k3vO+Y**62y*#w3!%RJq& z5g_XiFe&xLv^v~C>S-;cCXWHkt|G03+)D6pGJ9;pCGB$hP)BXLMvjW*lf}_DY>WsD z5-~?PqS}UT%VR>m!#L0;aW;KHEYMkTux$}Noe*M)!GER)u6Y%fyN6B4kJgPJ97&!4 zFc~Nl<07w&ivP4a@_ZTk&xh7sAVfM4SfXd`4a1hVS1BS6M7txU%mhvEbE0!bGCAxK zJ~ZDtuhVE*-0{~oVJE3mu$d@(dd+?Yu3;vsKG~di0?4^Zh3bVf#Xxx-2IoBKvx$1r z*BdN4U3I9n_lhA~C7@`YvQ%gHihhGLwJxilS94mh(S<|T?4eZ0i zI;rQOtOE%f9iX@o5@(m|OrQ`K$ayZ5UevA3CpJocRSa#9n3yH0?2)BR22VLK|;UTcIn8#gae2VsHZunM;uS1lxK>ws`AgGSE5`CqF<-33DEJz>a|}t6s3BPaA36{WI^0i zVw_2?o_>CVdL%h1ey1b_35>w5bn;bijTw?F_{Giw6fTxLN#`&x`WMOF9&k zyk8V=S`>^u>Td20Ugs6w-lB?P+;T|rbd$Sbc>cuc)8Mj)VJd>uR{18F#m^UHww@LU zBxwmI%7yrz#|EAD?T-_E+=?Fq04Ddm4(3KY5DrH%VllXaLJIwbVQX>%~Ki z)jqLhn`0Igy}e1T!;pDGwn2{lnI5iwaJ?1J5+1j!8XHfoDGps!2TkWgQQ_W;$Tnjp zFno4)SO$~wC6*a;#&LxQoKY!N?Xr-D$g~9~g)J;kCoNS8PDG8ru+ep8nCreMc2P!# ze>mcMKx_Otrb#ef4kb1KhS@b-=SCLHUD#Xm3_2$!Y|_rki$Z5pwH?nc;)@2J8kg8T z0mTV zg-khye3(=4$f3l8>EDbw|1r6@17d+*zgq;kw?;e}lWXLrq+P#G9_LS@LtrYD`724Y z{~j5^DFxmykVzzFpDn`^XRN1^$1IpPx7do-309;KgYH4` zZE^J0<~g9jt}fA-5f8eu6s+a$I$)u}>&|4k;5JAfKxRMCPnI|2E)qYF-APW{KNt@< zDfVabZWc|Zjc}HZKJj#RAPg88yxWhiGp7kI5gxa$YE*S*na8mK;qfX%dB)x?-j7x5 z)jxGtQy(okfr=I3I+tswr;(Y7O8>iWLC>8^4gLLPo)X_plt`Y!duC{bJlT>OyyD-O zZUt#PC%C5i%^2kTX`jYnP$SrDU?*PpYM_z>y z5o?)R8+4p(-}=K(kjFA}?rLM>$3;J)6sp;g@WWY#!$5^Cv0Yx7N{U&f^XxmNAeE`= zu@_5IRy^PYzogvLo@ip#*g95hap!np9i(@BBc1?IFpn_uTCxclW(O{I0*YvUIu)dJk51i~() z=`T>PhJxcTCj01Th?|JXzHVHEzm3U9%kq)*R1zu-dAc77ql<74!g&4m*B4&itT3!; zrPs7lXwa7V&{VDoMzu>FBs`sXG)FNtoIZAVgv+F+P)^rPK^BzaNMI`D#h0pk!s*5nk_`Yer-6eKIqE?8d` zEAbnG%NrCLNZR#*PjJWM5`lyNpXFVgum0EPsYfdt%u)OHy$#d6uN#JauoOMu_`g6F_`du;epk})$GIV-tz;zX~AVg&q6f8{B|>MHY*3NgB>)=MX?L-~Yg z4?q^0aUdS~+V&}3Xi}ZzCo{~!URj`2JC@$`IJ5n{@8uN$4yKK}P1z%T7p)hjm!e8? zn2uGp{ac9eFqWE$$BLr&`4Yh`hscVq(pkjAbIL*n`qs$b=YeS{6-v3aA5cWiXE*)b z4)Gkv4#(Y&nzQcZ$0$(Qfjy3_0$t;4fV!|Tw;HTb0 zP(o4Wa;!p~Ffh#)lHHyDlLwu#h0}$GOGVm;Ea^9E*C|}4Z?6HHw zen$H-BX^`%7I;g_}-)RUN zG|0a@azei&pphm;6e<7}Juv$1g-kN{UfT22hg4;kC58;O+`wBeHEgLeNU$eqk4*XU zRl4Dh(E3G7G?{OiYF$ODsEx}r;rGFfb?hMrT{$%>Ch6zO^PbgkW*wcRc)8)l!DA2J zHynJ+X$-@1Fy>ImcT$Qc9p*i1ACF)0gsrD6Sw*|3Mz|!@@*(H!f->iK91~FRiBhB}9zNq)!4I+4z zyo+XDHim$h-20`ys@mMBt-c>$B}{7+yu;5l&ne#goaE7kem+IJthHDp`FWP0oc|*T zB$h4w6&}$M4EL>Nja3}ZunZ&jj0d*A3k6M6TRS!u4ioVn?t-3~w0f%GCqXPWc`d9R z&aiB|k&q0MXC&VvB4dqY9w?74C(0`XT>cQ&+9>Z5kb9R&!L`(Tgh^YQl_ zgX%K>F-vhQjq!UvWXdX?E;+-sWFsxyYRsJdshb;e%m2CxQy70e!`e zv@IAh@VPUx1o$#tQ6{ZA3DmK>2JF#;4gNx*i1>3{B$>dKJ2K7fQm@n|vF1|Cj~*-n z_&L)C0Zgn>T2SGvM9$%f#eC_3L)p{#;JBp4ViB9^S^3Eh{r6(hkjWE1D9KdF`-O1a zuIK#(Ez7>#M`d??1z-AhnvwOrjZ~myd>RV(w|PFao!`L04c24+QQ}GpZNG{Pe=_6M z;ONeND>eXC{|Hb8UH9goK2OL>@-MdDFt-+QUHxfklX&If4V4BJ(8eqG>E~kBqdu=UQhCq%};57sXVrV17vTz}6OCK7hq z0$@_(?oM6e*6A}f{R&(9vWRaIxv;lu=VoYyh?#0GY072WNl!W7KL*y=B9Un+CC|jy zJ-@#d=sV%aC{wPC`O)0%vcwQyH?0QFTz`w})bHVdKae*mxqnWCP3?rqX@ZI_N*A(J(>6gY``t>tCE+GZ6yEeL_x&0W z=CGZr(74f?aPalYwmEK&G7W5KaMQ?NiO&YwfXV%1vk-_)fWwKPK8X(sW(k`B z$*Ln*qUH60rh6?WvO0znG>i-Nm)z)DV(5mOL-$Tt2>+Pa+@+9l-aYPEAV6#=Cc&|X zUl+2lJ+*Br5OGH{%wcGe`Drbsg%hYx+N5bzSuapHGj4d-9mP79Qz-AaG$k8}8u%IT zz;)M4PYjnCwt@B;zVlitj3^iEm;~Enl(7$YFI4HB*~h;}eXgWa13R4u{;Qtz0eHe<>#C%)3N$(1 zCymO2sUUUH`|ZZP0rPa=Hm?d@#Am4omP8Qu@xl#lEZ zzB4o}g}53M4JxUa?lv>};6>M@X7BERebX5Mx*JmxwiW(Sv%zrZhL@w&g80_DuMh#h z4Y(X%9z6zmpTLR}C03zECoj^T2$2$Sg?`|yLa1Rt8QDI0l!c`9*VaDhFirpN`Dt?O zo&|uN3|YFYkkPq$9$2L8Umj{u9Vb-2kEhQ$B#taAquz~+eO()k8T&V@jRz4d^K>}5 zLT$@m@q|zLK~J~ck+LKeCkj+#YGhiAbrK8;m4KDbJ(D-``7+M6s|M$b+qzB^GQ`waIF5jx1dG4HQD&D`R?!1@t+%PcahpM=Dnk zd`^Oi86zf$he}rA79c$-sCGrb82G>u%Q414mwg_&gP_j;%g`gsy_npH_LX$pK>SKf z64wk#CR}$IAB5~t=1Q;qw8N%8ISr08e?v1L9<}FFU@L?BIn@-NVcG)cM&S1D&C#r! zg~-2@kShJXWFAe$55}xmg&uMzuaAV1ISJ5Aq1wxjdcwJ+00|Q2Z77e=AR8+gy@S5l zXaTuaBZ{O+N|bsY&V2x4MCY8jW4HCSOr=PxxaZwo_0n_3p4#vFjC6li(d@j32x}WS zM#A%W;m(&tY0G9}9^)ltUK3<}X(rw=S$a^D8Uj@-6wd}cjfWAW(TI#M~;(XIfMALgFWW$C**U(DIzxj8uf@`Xan9 zP=cXy_1~$zz;d%#VYqRdUkBZSD_J`8;4T9rl{F_Yb~0K}#385Qf1f~>_kuodd!D*C z>Q-aMv|aW83KfLh8e+(7S@{kK@V0tnZMcPObrr(79jcVu$)&LqAhB)JEd$AhLLA0w z-h}vU$A~Y}KT5OEHNbm8{ zXQ(%uz{!T>0n*LZCYO@`Lce-PAdN=p5$uA>F`!?d9JUT!&vP!8ss*FENmk?)K)GQn ztu;6yY+sHmZDU9GNGlxi4rr%~!CrgKsO-#s74J>RbA29IQTA$76E54wIfo143`Tqs z+3n)7`l#kLZ^Rv%x_b_3fNy4L8=#PgWIYa3)&M@jnXyd0HvoFNw=7O4=Q<=;XSPtR zpK>JgBVl<#kMzrOvsQXG>jRQ`w_M>jzTGoG+}|Hk8-IO3;131w~F1oQ!|Zj5$5# zq_6n3L4Q%^rp&>6twNKFs=-=`7R|7!YBx-d@>A2?tqQJ?Z@oH4|Be)jF$p9{b|EJj z%FJHt#jYaK`zIw-Sdaijcg%&TV{+=CH6`2!)i}dXse!HMXq`8nAc&4##-BN&eoQmvi$xe3ZrJM<);5F z$JuId9stvQ@`x z>QN>U=S*T(W)(@ximbCR{a{M~;lCInjLcoaP5w-#fZDmxm2UC|1vl@*LH(4ft0wQf ziJj7BBV+31OONN!YacTqE?@J82F}@#1@p%b%RAKy>e<60z%wbjgtIBcsn3$QoiuKSzF*G*5^zsY>xPSnB&Z+%pf=h{2-}uq<`; zcDzMl&3E1sejz105v4g81ZH?aV%G`t4$D}|l}RGdqMghFZM!=CxJ$J~hss*c+5z!; z6=$NR5%RqK#0iF+#6a`i+GR>$=~AEMm(?nMlaS}=oADQJG6*GZgxtWp3wi)JKh_o= zu|Hq~&;GpAP6`!?1-T5^Y+SZt^j#cNDX6UyG-#|DXPNDO$iyiBQQ zT7~&7(i0V7-VERyNScPUx*w0(xW%OEFHiynL7V~!d@mDL8+Stb)a5l2+VNMi?60my zYFHtDVXi)9)ByAEWdSNy1FaK!_9t-1aEJPTl`kB@Mv%nvi5Ljg*VYESz2Z^6f?&bl z6P1{8!S*@}adm{Dlp##&Nx%d8_rggxrb zr#|g~Yp{(vh7l~;83FgmX)ez-TIsvx_!9)5c53Bh9l$niJC>MgMKUYdx!RnL z&v4F14P=-BY+g0v8SNuc0<0Pke+CAvlkbym@zI6PMo5YNi4KvD_sa|&<9POA)f}s< zyfY}thsfnIbB*?L4koQQW5Wg8H9iFlfCy`_p?2%yfysh?jd)eAftHH*NH{+10|A?( zfm8Ri8zzeG>m0C7LM)H2)b;lf6Y&9zuXeCH6?ee`UV}`@E;xLy_y@qyUXlTHJzRRQ zZL@9TUn-nlzD7{#c6!yh)$$;^j^{G0R8ph4agWLo?^vdo|2{WfFlV+tf&iiA|IhA> z+yKb8Mx~Tlfi0Zm*6LPbyZjV*Ya$SCO8ileemEfB%7asY`Re;rbTKb>pJ;$MWho50 zT2Znba{6I)qR%p3lsHKgT&9tNT6KPzp4JC${6^?-1${(x9%K_};^Oija?TJJzdh&_ z_!$UA>e6~??F*;yCpJH82$`5RklW8j+x$TP>BN+NUKM9j8^5yvm&I$CxF|7<3|X&? z$?LltFkJ!r(W%idx+qWP7;sxQz;FR}TC*B`E9G-^K1Z zJIt^{TvyCC%Xla8YOW>31}%lKaGM(@_-Q9-z z^R>l}kop#ul`XLvpdDr{h>EU)LxNzR#9luWUF(wHT*1lqUP8>ynC^s4W`brdwZyn3 zZ`fWao`}BQNXN~9>!2$l?7@_mEl6EHQZMx1!)t`(4{+6dN_0^Z{}Zvr?}c8l##^#5 zCU?+GWhpRi3Z1yvGEepKv?u&07V@t<-qZwh-`H7}tBwvK{~OO6w_v?L*Na1kPEw(?s8_4xbr`AjBg=yrc#SNwg~^4)H>R^C zJjPh9l!!>Ik5Uaz>Em0vX-0RxoWyPnr$9KP2$c~r;P)Abo&vIpaF(4Q?I${v&gaC} z5TQw%q8GC-Hy?dsMzepWSL`|8d>&R3`4^9TZ}R3m`oZllc;{`w1jOe$2^zuT{;`nW zJ%xRGHQXa<&hly#Xf{QLjzpWP3NIY0{!%ox7FF3sS<#gA=;LV>J5d%fwddnezJ2}c z-7#nae?a^t3(;TXtUIkcPp1iJaJn+HjLJW`*0EsWK<&LKi{Fkmh5f>`kcJkfQZGZF%8nq0P#z%m(#2A zduqT4Ymg#Z_lw*TN`&R350WiE@?tb0k$6D4V7+mxY#`oj7h?+DYrIrV?hLZYR4>3P zpQ_l>Jh1I6&Og(_; z2OQ6&cGdyiO*3|1D_=Z6Wo2}I{;~c*@LtqCDE{rY^P5@zkr9(OfUP<3UrG9wPFtCF zzm!noqq4R@CUif@!9imQi^B?5`h>{7(ghUrxocNz30^C(VuvF9Kp0^!=DWSJLK;Z} zbN7IaVwS!$kNwzwi3*KLNXlteP4AtY=^8*x_gc6_Wn1ewd59A7=MvKkLo?%)hb5`KGsi|)( zqblv$WEFsA;Zzftk0jqAg;}DAHS8mPSS*>K*Maiw%Lf#eI8_Rh1|hy%zUvJ#34ei+ zB(q@x^!s(UQYA5sH!3@ZN%`hR`z*Eltwljwb1L z<6_~QWM4?z@o|c91T0(N4YJ4m+X12nN$#55OlDO_Z2XPP<&hS?NBhfz zEB(U-Os6wgX|Ud~Lvo6f?hlVbKX)aD2OsS{OsU&ro4rwIHAJo|g@7C{I}u6j;`<=P zb5!%N?ZZ{V3#-gy)~QCW&s_mN9E5!sADM|&m>NBcw;oT^EDlWgU&i_q7hvq1!pZvS z-cqG{vi*CJQ=bxK?oCr~iQpdV+wvo&b|(>8(g`!c;cWIytydjyhpD4>wTZ_v#>m$V zY4Rb!&uy)Q>oV$9&t{bcax1rRVJPyY&k$Ci`x?JYi51Q=b8G5lv7 z3KAJA1zD}GEV?Rh~mppC>DEth%HPBP3cFRpS|nQBaS!gx&nkOR9XRl8K~5NB({?T#0y!~VKD=E zZ!Wb}IXL*tJ!P-hs+njoOB&UQG)sB>@Uk=%JwMHU6~!8)KE}*s&PamGy4vedXYU z9zkGe8Iw$-uG56ur81{;a2dPR`M}rDYgYc!xcY+Y^EO|1MOcgf{mcxqj1a+egI~5; z7MgerGa{t4xZHE8e&s<|bS{sGAaKe6T=AU!MbG2hd~)~)Rq-BlitJ2l87~~gM;NAl z$wQ9Na4U+j6!4DoSBu8pW2 z4%^|CS>ot-rD_J&Zn3e%zxXjL;n)&N-R3rT7rZHcSLii~s4H?)BW);O0Vy{f$~EAl zIij}5hMzjH)4xzsZf;Wz{V<8yc``T*`m4K4j5#Aaq{%p&7OTH97ug6yh}{D6kD`;c z*1F1g0+-y@Q`KaACl-H3bGY5wp2LM^&>4UH5YOM`}zIdaQ98Im+X< znDoF12mm?dfA86@e!4KI<)xxm@%&1cCy~HD(S4bR3#Sm*cu9<}?waW+i73}3Zat@Z z?raq+=fVe2OdX0q?ZsEmUj%jqwmF`0pTCQS!T~%qeJwr^eoH0FETXam(7CrKEF4*y7{d)_56VNxtpcIS zds23?8nlbk-ctWSUrwMT#!8XW{Lj}BHrBt>A1k!zw>k!e`u#xOY+HVd7fHkscoWQW zDKQDQOf_M&GhPyT^={>)i1#iK%7hE=U4Li2mbsbUmwTvh=~ETHPQm`uUCnhue&$10 zF(ZStu_ZC_fpv~aP2I7t#M#;vKYfl?gt&9AqZ_8<*bN()3R2^w3#36By|YX;9Gt74 z-#V(R8r2xYQ_-gZ2O+ug-0yrE-C=Bm$GiS)_>9741! zrdoSq+Z{-BYAy9^EcPW<9iT?Cb4>lkA3cFF7h?QvKfY9m<$2#CgXAuY`m#6_<)F<< zEl7BCz6ThrKxUOS#U2aVgl6Tz)FC9e;FmwM!~niQdlw_U(BX1>6fU%+Q%n$d_g|mW z_zhG0(_~KOHr-DLR%g1Vr*VAB9^;Q?8@Sr7FJr{j&v=EPVG<{31ojZ^L5LLJsqrf{lrfgZIkPt-`Z(T_j5S_aOyG5+-8neGTwr36IW+Kc+c8{;ma+BB8h z4xA|WrM7`Y2-35UogGF(e{ei05;7e>`J+C!Ygqajt<;!}vaRuE+pZ)wE*gi%()cvlBFq1<~Z5D*6T3XK7=Ome;?yeVdd> zm=}aP(&g6(Q>C5a^Bp@ci62MqJ)RR>$%)`s*G*Y5h80!`AL`+q^-?;*WXT5|A)DM=?hnrH4p>zI z_h^9^-wxKzgIbX1tAqg;p|vkyP%302u+4^;XaM`+rjXER)qf#b0>>g5TjW78#MvB! zlWzEx42Lz!-zeycR(b`(-fh7=ktKwwAdxWADGc`}J*ovt>w28jh> z?QT2PzyvQWagRtn#?^1|TtSXl*{nY{mwqLaD`NMXAI{2pX2k!|sm~q;3aX*>93z@h zz_NALDC1ITPyUp@o{CB-qGz{@^7Zoy{!J@Ug$-)4nW&4E7^g^ex(q|Yl@;b|p%5Dl zvrM+vR*&62Qos)gh%C9zR%SZau&jQ*UCDY0?lc8VW1aqip^+t(dd4g zzM9drcXk&RoRbdySaOP%)$jDgs3Xe#(q*{rftC1<%n0rkS`=200ScjycAMc2i0`=d z?+%I_%e%_J@cB5%xXtMvF2EE@in!Q^1?8CbFP3=n_JG<%zq2%*QD!c)TKP0MC;*^% zVwZ|XezZsHbhR<21B@x4P$MM-U@0ILSq#&a3VIUUh*cWi-(63hP_yNA~zi< z5In%PL;v1EFO_<;0=J1f=9;BM4pI3(6x>%bXY{&K*99WL8Isnw#Az_XMyvuA{lk)D zE=C9<8=|pSU}IYw3`Y4MUKdWIbE$9*#^xqaOGTEE0gVqO~JO}qyyfy|H~ z3nVwuDKa4&S_#Di1Qp;l4%IZu9dEX~JALhi@HJPiE{0~vzCQ4_`SJk;Si*D;nPVXT zi$KUgpFK|8`YLbhGN98}1B%J<4KA`6<2cn5`yK2saN_v%kZ)NC#_xYH6!bKBK znUeP5QSM=r;TF{g2=9uS`|n(c6BmjPFX`1I(trZe=nx=hNSLgCBVhdkZ|8p6nytT4 z%t$sLJ!g&Q3q&UPCcmz5vGt~^5wEp~ow5#-K(bCmR|YBBN_I+?&|iM|zvEq?OoWhz z3&^HH5sj4EN~8RPF&%IT9^JfFCxBekkhvY>l!WDGg{fBPx%1-?tKQj%PqLitJvYm4 z7Ct>?KL^JY{UyY%lA8ow5D_k<2}yosf1wH1rJJLG!^;lABzGQhY;e#bxyC%z=!AW> z3W0mW>Zi(Zr+CR=;wnUZNR*WoY6p;H>Qc^^A8SoQ zKFf?=7z*=ktiMNhQGo1Lt&{$dL(g23@IW1b0}m!^hQ6A6pSedMd4w(Gj>rpOu_JM# ze3C_2-POH|2oV!MkS-^}qGiwC+~98?)+TN>p1=)ARGpu#?pnS^6hNWMk^-~3Rdc95tkoWqm1U$GIWhy6RCu+u2<5=ovUu--oHS`#{Z z5Hi^`AXb^-m>k!~4ROcL*s|a;vJ*E}=K_qDtcB8qVzv!K?ulR}F;;Jb_Sl=wu127R z`%C;xNV&3^6)Zj;?yoKqJ&-s&er#26$KVW5AthgUB!yQ>*;x-ciR`dI+ZC?Z4ksG!^?{m;E?vTF^gX^Ue? ziM-QY=`Ct2lJTVBcKs}e)v-MHna-m!+nN+Bb!sDtK+v1<^a~C>F%oPbJF>3+1M>~% zbKvjMo9m$42?bM5{4&*lOnP`d>FxiL*AP%7pNet;!lYNp$Au^Mr;4ACF4Z->+g!&otFT&W*h;&kx0fgq%;zp;cXMF}P z`VpUBK7T6NwvIc?);bmbn!Nz{-PdgzO&Nai%D_Cq_U^-9GLFUe6|%z}qX1M1ap%*c zuLpdN7A>yFl%W@dKf^$kF`HOIDEQWcqFE0~7|Wlo+Jql-qM$oy!(iFAJ!ueO6uVI_}8O7+YIMoYhgy2OkXxVQ+g4q(>vVsS<{lQkv3dJAP3?;dUSDzS%R$5ap`lPl=nHs4}mZ)nAh`M z&?#{odkf-Nhw@>bRv^r+|1C^ZSuZ+Wuv1?DpTYGOzGI|JPVWyhvSZ95nWGCOB6NifZw5zKoYrUoBsfqb;uwlBLo9nKFaRga7#R$OO9k87!^D%yIeFgZa3J0`Fbhx z44Wt>whvyuGQCX4oplqS7q`51bg^>SP|0_MLp|2v|9N=E&Tx!Z*c4y@n~Q6^c&M4J z$p$$45sm?-KR$CRer+4!Uz&7XGTJ6>v~UPuJ@TW(f6u^n3a`iiKa-i2jiQSv4?yVJXa1S zmiS=|-8%aYu3j>X%3gE;?QlQ;?3NahJRQ`UF=f20bMMEo@F1W8du{}Ioeg=3uXYLU zY%LFEP0AhzLz-Qaqy7s!D9O_NX7L4PX|-Nv4vo`Hr3YPp=g&~tLkb1%khN(p)7tCZ zhUhVdI-9ud(ndESdfrv&jS*iAu(xalvgC!EEYSO|-Ytnx(T$q(1BH2uA%;e{HyU3z zx7ckdHjasox3SbLN0YseFjKBY>)LO_0xnw3MumfI-rA9uzxn!~6aZqT3o zDT_$76~7`M8dQ=)ALwI&t8j`6l8$BN2T8KgKbwQ>ww(9G@`OK1wBudX7m&ur7ew>2 ztdJuk5NLr2GWR=kY#*lR@=|s!oVKcTr@Y0L?c)bi`w;PgNy2knpvhR2qa5R^8;dPn z#k;Z{&Q{9y^tX%EK@@g}kASvNcI`>S^tu*akgTj>_CQfV?XPem%kYGUJGv}DimZUb zI~tNV2}W^0)i4({cx>1ne@NmbwYa|ZjyS(hxBZF4yMnWzkq#=UIL|yoB0su!dZ`7U zqSj)A-u#*vVd^kye@_wbSp`))Y1{}*BDF&yCXo!afwT#`D^JL%tO?g{!Ke&{vYibf zrq)!;33~R8ZKN3qP~i6Nkyj`a4}lZ*kc$G<_($H(nz#no&ZsXM2Y3{JX*6LjBEQ@G zt6lvT+_+O462C5yM0~=QBy={Etgt5hA8Z$+jx4|46RafSwlb)4^EJXuQZJTgHGMXi ze*3?OfgjeMH=!```beX@b2QgZkl}S7Z2WmjJ3?la7?VWrR6WQG@}cYzkzGP|VFRi&mD6ltK&gdB+PLwO8_k6nrbIEo)JL1!Rg{J<`Z=YciX zT7fQ2NtZxiSpc5Qw7M)|^X!UM|DMA(o_g=THSPwwHq5|IG7QYpJryy|`XA{t^S<+B zv#>JgD0Bac?;C^#Ed;Hb9^xTtHQ(d#LVjZ1O3Mo;qY>vK(^!F;umo00)0+{1U9ZjVB1~3|Jjr)-B3*zCl6F(mL~!=v>d0c+xp>HVq?fmBGXk&_2By zsV3BwVx4#YD0{7=KgViM3EebqOd> zQl_jmzUtdf{V5WNwkbAe-bNJSMIkLba2~4nSI20`n17q;pmr8yi*5EoPL_BFk=%qR zU|WdE!q1S_podYKJ2Tp}{_cl76_}NHUyzpY73bW7x5*FuEfSlHP{yCwWlO6SkPo}n z*0v zTusiLyRLdIwR(_%ztFs4Avf3RwY^9E|#TO&V2J6R8{{BiFt&q5f zw;F)n4w9P9+~|HucAQ~ciw-vz$HodPUEyfYPqs`Tn389_ViCgL3lR`Irti#iX~i1e z;FtR2`HKt=Jw9psUbOtw(&duQ*71-KPka=#0~A` zdk`z=F&R9b%S>zk$yX>n#$L3clExSzxyrkRauh`D3h$#S9_N}E{4Ow)Oz;Nj%MRhH z&J=kN(D)gSwlqJYx1ABv@4|K1>Bz~g{BDdH0~2wfP4*jEWjHWIJ@~uuJXuF_E4N!n zt~$olvf)!xlq_$3-Upo(f(fz3PV=suI27+?+f%!aN<-e6-G0l$Enh(LgYBblfujgQ z!MU44b0=;du#nXlw%oFS;ms_51gWI11htv6(WC>UpB|npK~i-E9mV$ z9ByhT7Z~7R4@WNfB{m9)F-BHgfLrSRR{-`ta4;}DuY7c$I5{`nRO{O1;8pR-$-|^1 z{$e>fwRZ7Keks2oui`xzH#>}4`L)*@N$%D2R0sR1++YvFNWW zoA=&wW6E-g4M@B6+CO?0R=3nGKlBVSge~K&9;yH*--gi!t z>|mqA-GbHxvCrA-ys*e)gFzc5C#N5N)&X8uWS6~} z5*TW_Zq4|e&O;wKUhh{lPq)8YapL69htrp+9uoF-=~1%2+nmd{GfEb{*xw{>*2+<> zH6@0E+vbZ$K8YBkH9BI;ns2J#rTZ*TmaEtBg5khqkHkX<>&9!jdnXh>Td_~IPs8U%*^>&aM(%QaVXQSL& zq_mmTEVx{`+-u9g5kInb%dTv2uTk(<$-+g>4W7BbnGhVNa>zcV-o#dgDJBE*7aVIg z>Bj^~zunwtTa}&5=Y%+BlzML8WHi{nVS|&W9`-pJdf|*q*Lq6?K#`jalEisA zDfeAY-*q#3U}paEn%~gVkLM2Yy|pa0eqP~r%dZ6iS7thD+8UhS9valKm-1Bqb|*?N zYCN?!c3!*Xc!T0m6?a!iFX+;8_zw9qFV{7ldG20owE~a6M*^gWk1`oO@SV)eRZlOb zw(2`qq;B{_+0pM(>u>w!w7NC#Vy8JzcU5?r&w0_MV(RUlGj7g~y!Czjg7@OtLG?9K z!}lCg(jK>I`{%N6BEKff?mr0Ej1Wj!51$$`OG{t>YOH)WuRH7eE)n-S+Iqgp#*+5y z28K6`HwyS{HXvf*_MNgr>+L?@YVf#Y70V9Yb17b$RPVgQuECmD!i-vt%~NjVd2-P> z!(N-zEv$yk`7QaP(*rlR_EByPHIqZuXn!+H2X$78pczzMEvQLTTsvX z_E*YocQ(6i=HGJSL&b`A@(-@&TOD~S zX;Ne&9^G+Uu<2l%5amZkSHBw!z3Jh1NUfoHy_6qsCChy5`UbY$d^NGW^ZdSZMt55} zdT9P8=k!swi#zrRx9wuPr?F8>x5ZH>iiV!(zWVyAujfOAmz@n(I4(6h|9I)PUay?X zCJv~4jrm)!#zo}?N~VpU>h{%f>g9BOYHG-p^dE^9>(s6|On=k)wxRyI!ZMWu`!e^p z8esJ5^wU-Xo_~pshpRMl01X;2x(sO1C`QMG?yu4-`;%x1_LgDH-VRU7553VWO}5kTz4l%hXSSnN&uxsGr7An=mDC#F**%s31CK3#+MqyP`H7`;kBNj51>C_ z0AMJf0q83LY5|In?#$vYg>nSatQ@SLKq#)NmlvQvpwwihCkFHZOa?3g%$UOT5FOpY zKf!FE1s+Tu3UngS5(tGd)MZP{3?JfiIJr0(t=^0!jcC{Ft5{U;tnSU>Tr+ zKhtvui~%eJ6fR+MOF)0XG{90ot))!Q1uz0I2T*DmlZyd;0Fwbr07c80o+Dr=U^bv& z1(TZsdI2T^N&ppBGCe!M0Kg2uGC+e>OwS!K2CxuN7{KI~fc}7KfTe(1flSW@Faj_K zP--=kivfKAlL1QrML|r@5ik@m8&I%@$xQ*h022WvfC_7wo*iHSU9Q0fifx+!D|qFb%L2P-_#@bJ1t(XXqG43v7;7 zt(Q5i7;RuVzltvD&1i9RrZ4Ej=(J6+uK+q`Bcmm*OfEHnp?fr}`+)Ai4+YEyej;G0 z9J3S1GZX@f087A5IFZRs0mUO2?E>fz7+}TtF@R}+Ie;aAE|8Z9z#KrS2#8}RLwCRo zKo=-K08ruv`jZ%n0WrT`ghqY|*dr|jKjM+#2jcJnOa?@KL>GCs?=g@CY|T&r{A8p- zo;{kiyAb$d1*Y%5m9<+8=;Z*qv|(})pcpU%{FK@=yBxt`!N2|)I4~OHOV^uM#TQon zUm!sJQqW&Mg2~$uc}9Ka5A|~hEg^I%p#=@9+Y1RTBD9#$c7%2TI%fo{pXuT1{=JC4 zKcPbj9Yg43LT3;`@10qxqG(K0|E-NtBTpjXXjbX%YW%NVT)^x)CVzX{Mv4Vb(s(0eB{S{`VX zEJmvWeeN-%)q#$;V*a`S{kk5bI|5y-$LLN#7ZUvknoO<-@>3%iZ4C6>TvnbM(Ci3MqTi%}e*9HA>7e;pjx`^aEf|TF*3oB0(^szmYNqc4xI)~5_pl45G z<@W%8?@9d~MAhR>3uW{G&@Tyw{`C*hSbs_5>f@!9(1PEp%Y}p%0Zr?J{tbw}n9z0{ z_SD~ho5uKENW5Nz_UDKn?L$F6W+ZEW93K<&s*jKIv5c03{!r-7XnCMRnlO7Upr6?? zx+~C?KjdHa3CH)=U5r)%d8q=^*8zI!awf<5rEDXk+kw2#Nk)s%9@jfke+i*Wfxc_Y z>}A3JK~qLc11)35Xq*o*Ut+21{mqWhE`;_1`YkE%n>q8}8p^Zn%xGMXx1}(;J*i(Q z@h@mnJsu&UMT9mWv>0jU>g$PuG%FwT(bkU9n6GE87~KrwD|$G$>Qe)tTZx#w1<*Ih ze1rM)$MT{5LJ1uM^!kO&AFe;kH!&LfgUMG$)A`e-Y4!Yg5!#>7p@fbhbTZJ}8?y3n zeZ%_X5Pb>KF4glZ9ABL-Xv_RHhkO;1`i)q@C3?uE+Y7vuTzNo$qkxM!< z{gzPv3K>RY`-Tx3>noCG`K@ov^zkAV<#r%P+68DjzCuWULH$r-9|LqBOI99^pAQ!p zjr$3-7dETj{vtvf5L!%VJ3_kvJ(QHc<{K*?`(ODfMvEYy=d{@ThWnA-u}qHpEA>5$ z{y87Qc*r2-=MY*#=u$!pnzQ;JCH-UW6jq)*#MgT{i%$%6A?a^zE;4&;lW=ujWeDJ~%(PllftaV)gZPBx%nw7iKR9?LVm-qj5az1~VGZ z3s*>gY8KA?P*_k{SIr!yM&w`pQV8-U#P z2J?^md$&nUZVK{la~a(WXme7(Eks|l0n^9x2lkg_$Uo8Fd)8NV)Rg0FuW#I zUw`d9=T}+c{!0w^Zc^Ycbmgw9PgC%I4(Lpvg{zo6+xBRco*l?DG>%l!F)>VDrpxGn z8}U{A9MBJicuHm1ct%>(x;kw@XfdJf2<<{>FQCQh3#!WB1sgWmy)3`D{)kBbNF?LA zy#dq5d@UKuXxtw*FlYHTtSUtyXcfokAwV~u%xF`f2NK#XlF2PVj{PMD;zv3eX!nV% ze4M|u9jeDe&u3^a0ei1#rjPScsUzzj*~b_nokQqCq;b8FW$lIjy$J13=un{f<~uq+ z<{xG8((^$M@h>5CDbOzlGke@W9U8{+-4*h^J($t`NdEoXRIgtsp<@W0Oy~?k=MY*# z=u)8jEn)GPK|J3{dtH&R`rv)ddy*gbe#{=%hwT1LANS8E8!_6bM^Nq$a->5E9Ru_x1J*vco=n}s z{NZ>Ve1Oq7f1$rp;!mJZz5facEdu&POXd&PEA=6)e7uje+QDd?&z6s4vaFB0?JwT1;p=Lc0*!i_rc+ zr}by~!tttN$Y^Z;;0o40c-}go%j9^zvRlpMxF6m#gVFMk|2w*jZV7ZtBSzzTwhQia zbwGZW*f&>U`Z)eK+AtdD(@8#zRsj3;4;hW~liqbk<9SN`Gov*?--^)AF06jEe@RIG zN(n7cBJD|N5zzWwS@~H1_@0c${r^K!zmJ5L8p8Ck{@DM$NO}H*4kdI9&_0uxKRL)p zM-4{feUgb6qvb(`D?6I zB@Tq=ZP?%XllsJLW%a@NY$@qq4#a*au@?)OJs~RU|6%9FF${`oG-t^E;Yx`Xa7&jOL*F!FFrndiNb#-KRB)s zaeVQ`7uu@k^0j#6eEpwKUU+&>RmfcPPZ>}7**xPvqV->^pF7X^HQ@2jC;zMM&u7mk z=j$I4Lu<|--~7ba|M|-2oIfwHeS$4?ctq^~rY1+KKH|EAh;lnaCT{=?M3m$BiQ$>w z|8aR6);<_FBF1mZBbVyHW3N`Tyio3+mE-=3YySAFa-VW|bv0V^RKA7ixP;jc|`e|Kea=hO`ME|kJnY=MD5K(T& zQNG0fFjH}0C<4Ux4DI#DHlJPt>mF`ti;GeD=TOHRtz#JwMp~xNalj`u$hq59L|k zy(ZUuA5z+)X1Tzm=KS-?x$b+h{(R;CRk_rgn(tGSU;nYZN(Y{}ECSMK=M3mo2U~&_9(1eKc0TrzOu&2xd0V2v>;5>`{3K8Wv{<-F#7&s^5 zb1p=**V@d+51xY&QLe_5pTcu2eg!ZaqIuguoF|Zg-Bg_W)oZqC6SC7mfGUh$t6k)I6Ui-(qrn-w+Y) zv*CUQ?_Cg4Zn>YurwR;2lusA1=kvIZe44YbT8Ikq%pRGDZl=r*-+MuSr@qXs`iSoX zBY(Uq)5rHxkdN)h)jw-1_wQcwe9tHUtL6XQ_Ac#N{V;EcwapJ-e0{8FCh z&vku1HIKaCig`oqeU0@?IxbKiUdZHX$RLRMuj}(A`h1~~Jm*3GiPLND-(357KL6Q| z*!+Uy9}%l5^_|J(fq{tf0Jxu)1_mO^{jak5qc<=RQ66!W$?+V3i1NpotbF|b1tQ8Z zKR(`noF56yUwH3~i1wlptbE)jAfmkNHY*?R^$}5SaHnRuJC8huM_$My7v8P8{8FCv zPxzSGW4j|_{X|7fj(I~wxg}5e{yg$D9(fGx2XUW>WFX54w^2BGylb?)_ ztbgJAo`@K~*1ekB&!5MCGLJliCw~$ixxtf~`-cyYJcCEBmCyX+z7rAipWox=VjcdAfo+MnVQf0TKcU1c+N*edn`W&p1&a<@z2U>`%`-^Ip6aKKKWlA zpIqa|650>rMx^=Sd!L%`zK8F9NiMlD^iS+ph!~%QXFU*HtGWM*c;sRpxeJfnpGO|U zBhTQGOL*kiKe^gp%C7qN8EE?_pRGB6c0A+Xkw>0=iTTHIkBIFn%3*T6pF%{rgvUOE zCw>>6_;PscB|LI>9{*lEavvVKKaX6@lfP1)_yc(SyYTog<7prN-E4i7h6Y8%_H`M_ z*zPeDlfgD|IfLTU8Q{V?KK!`8}1( zF6@3!4&tTuSpPDP?}ypJzS$A544(ghyMF__Sk^!OO#qBU9=RZ{W_w2-c`}b&YDdlf zU3lbaJn|#zEZ=xeQyai&{CxrJSGe!afpZ3~BO=HXm1BRW@)EGeah3u5V+o)D<^vHR zxEEk~$y?cakpqZ))I)h8$T5z3pqNJNF%B#M%xpXa`tTU9i@kEii8 zChG&0BmI&5P9yRu_HM}9kDmLfo&))vLMrE?as9z@mZ;87=*dm@RGHv==l`$SOTt(^ z_~PfP7xE*Z{ST4fVMIB_dnT;C@ScjwkxqEU`V;O$kWX%gJM^SY9&dcbBR@FQS~Hkeu(R9O+KvcX5zUu`e*hFmTe~e3t>34cHI#M6jUy z0N)=l0Fe6UqeJ05N7q%mZERh&1at)4Pkt|o&p(yBK4bF)-mg$OrGIPA+6C9s@iz8KIF&<^ks(RT#C6rd1L0WkUD z;i?qidqs#eFG!od{B!yx5y@4iZD9gHOdiahBe?<}5zo)Zcd_=U{$ML*Q>O6}B<3dEc6b?I-bD{4x7N;A;gXk<` zajF3y5$oAhh1uDIW5gIk#>cTDCfd=Gnn5rP(YLfG5%`c zBch)V3QXP)7>LcB8Gi`y5wYF)5rnV9jr10NBeHz<^``r+?qB2xcI zWBsITnct-#Kuj6O_``sY*c51Yc%KO0^G6hM%-8k7F8>pYvn|kw`5f(s{Y>19#e@A1 z(d!NKhvzUv?B5PL%+3wULkw_ad~4t%Vw^kvWcy)0kJWKK%BZ7V^q=gX7$?{JGucpY z%sV2aNx)_IvW|8Vj&{fL?m+v>00XgCYu0|sz(+(oQ|N~{pCY216XAY}%I!G%HR`?m zllv^RJI~SXWjuM|Y6o|oI2)c|;|2RUBF4jomM@rH3s6Ah(*Mcl$frL~oLu$uy2;|e z_C&<;3^JJ<`z<2MIguky;q{vRUFK*%&T>E?tYbUm*0H>H9OY>NALj+cpYe0##i)*U z5p`_$WFEV0kYj&9{8hb{YA`^7xi{*-Wm$=AjV8){1L!M#C?Oqe>lzgB%NMS{h#0oxHzvpZ5TYYbUZVfQ>$}k-76;B>h#05cYbF;00}_P& zABYApzHt3T{OOM)PBBkjLf^7>!h0@6%TmV2xDolvbL1(HYy5ff*iHHmuhRiM+OJ-ET4GqhxpSCNBhO_^s_XM{_@i=*9VUBl41V9`5W=48xFfno;YJ5 z-`H;vfBNP6z)@ZrPy2E8vz$8GW%A5}_2K?r8tQ?_RW0Nv!@7g_f`|iPUd8(siavE5 z56AxGy#~g~mCq8McIUE-;295(Ip*seo_63W?@k@twiPY}7(fATrTpCFsZABSDDTxN&&2Z(&-z2xaHTW$}bL@aN09mf$@c?xyR zi$NXpqQFx>t~ed)Se^k-{R%ne7xg;E=~Krz{W<1OZ1-r6b~mVFoR&O!;cACobu2HM zCoe7#53aL_Sbt9B7`Hw=^|OR};Jkv!Sq=&~$_wQwk1L-pJp1J59P0{(!-b`FwBw31 zv5xi2;AwZR@-pgJo)H;^uQ%Aeyb+ilRu@l367v4W0a`nrfe2#Hc zTE~1!U8vjoeu8J-h^7ZOizkMA0PxQ-$rgbdu z6UV-ss~qGHsAG9t<6VzuJaE}1^R)YVST|cj;E35gc3kC2>S!0rv;S-ezjuW1^&n!t zxv>5*o^j1#XjjMfyH&?~hKxG)Yp!-Et7AJjL%nhSL;RU0j`>A+k>wfZDMUUy_d1rB zQpbCCEuJ`~>eyen+Cd2K3*mh*B41v_JaKZB=U7KOJD&Mvb{)q9SDgMl?cT6}^(VaV zNBo&L@&Wr>i#oQSR(JNk!!+=VnDUXuf%^+Yynj=?&E)u;2a$yLZ)A)KD{m@D5C_2f zh*%CHuB&V6*bWhOw3Dr4J{9X|x1)}63Rkms2(V(`W5DOPrb`$f8$cuwRekIW477^@ zyH>!bb_N22D#>_amj-tD9w4<73;I=AtRQw6rwI50jyO>+;>hO-o^hnfVTZ+XVQwAQ zqegb~s$Amt{aegpG=9IWg$1MWd1-6%eQ;eZCT|IWjhn(~d7vMX-z7PJt@t_|A@FT)N0BJm2`#$ue$Kwa%!Tv>x6QG}t;0N;~ z0!5^0exxApE`aE_HSvSvg8IS!g?=1~pAN*22ns+ySTAgM^h4umLj2Hp&=0O}=!eE5 z3w|&T>PHLW=c`v!9zV5>CtAS%VLpHqVE^%lc#uXpBDVV$V2Drvh<4})$1PF&*?)S0 z0OJu68vUSO%(Dw=cYR_<^NfB#O@MxAd*S!LFpj$Vk;z~s;e3vMa9>N?T>$l=@!xy=;FEs%Nh;{Wx z?NBsw?XK z#dsG?WFy}**IO}vcpe&cu}uTPMWtjR{9bJHVN8ze z+MJih%@yMMPgel>e)2mWWBO?b(nsxFo?&|wBKTw2_=x2l*P+dXE+M}+@aALndF?D| zx7Z>Ury3O3CzH`4pg*`VS`KLG8H|<(+Sbyi>XRYRX1$mk=hZ6@tH%p!|8X!TzjxJ> z&`#v{)mr>uapAqs)z6H^{ZL;5Sx3P4Mes%*IP+pcVQu8t0!rmzcgP$ZdKtIi4qS2UZ_%&u=h& z9KX#9s?)hUnZ7O7EAnvFCriLkz(PP#6qCCHCIglMildo405AtoVGHBC044&K0-A1R za(}>VK;bsVcLa<9ECGD+X>L`#xGy^@&+3QgxT!)$f8jQwyeo1{s<2YCO&ivsx ze@Fal68UOkKaZ4`4*N*lS0<5hyNA&G34M^zsf11=^l?I;BJ^oOXA(M#&=(0kp3IZ? z$h;>{e!r(3p=ta%PguTjpPWx<3o_5j|6uyqUhX8GViM15LSr{abRp$k{ZhUC_YwbE zTrj9J8|o^a6|k%m6F_6uK~dQ$QEM0KjCxLO{WI zrmqEP2j~MB1DFk13aH@9?8JcXfT4hCfY=_0mc?_cKH~T&CjBwEjLC7nYDw z`uk`mBwxJ=okivwQFm4z?${IIsaukQ{PkYt_R~|8HPMC>s}lI@-t54!>`TiChjE zdVavUxk}|?WKS;D{|cX@eS*lk`;yFqVPv0NO5{DrKG=-V0|=c$?5&7=8CjN1;d*Z(Xsm}&NTZ!1bhv&Lq?Zxte z&pZCt+ly~(a}3L$X1||nelmaefp3}NTdw$)pP%>Kzbo_iAMt+T_q^YK#{K*6dB6XR z=iT4)e*YQU`S-lvf96}p_?E+3E^ogtvg)&BGh06tBL5nSz`m}i1@?7C1F)|vnu7g5 zg<>fGpF&G0|DVEt>zKg6{`pT~35<`@zlddEUsn`B`}|WV1?B%!D1`F=Ddg&(lpjIv z8&t{p-I$!eJCpOWGr3PtAm{hZs@3;Vx5)j^IPzRFf#^>n_bc1UeM(32_ZaB;eISYN zB)Q*6BK4>D74-gr-cO{Gc;}FK#Ux+HNO_jzKH~X!mM^?-xJ2}4kbDgz{^@;(A;}ND z&zeZ=uao=;$ofHdVgX=`qNX=AM{9hqe*^3NO|kxSibQ0!bTDQw7;j4 z`>0@YpY!=WyU)S>)oXHJ_=D2qTydZ^iwE~VJIH;V8mZ4oqF_KCOs-BQoCi5c`cJKWj*P$q|3eh(9GF7ZG|5xi1bS^jT6r4Pt+sw5JY{?D;l5 z#`Pg!Bct&?{Mt)4f8qI2c>$B-^9T8njBW$|hm-R4i2U#}rjO4natIwWh&}Jed)%!j zn7#=7Un2Q)H)e9Y|35|a=aYC&#V~!G-)|H8EXnT+B)&Vj%pTu|C?M?{3(xoQy!{dG^YQ$2&Y(LTOOWJ!LDX)y=yUli1KDLJ~$)`J^pOgMFa1FD^=L922`6{Hn-jez> zG-viW9<|8$kSFpbBpz*&zlO`1KkVNoqGNcjj zOW3@F_h!gnMbOCKTtoUE92w3hkWH;jF0m<=BYCWzq~)w$Mp>L%Lg+)j%&*bcH|{+NHzjq&B6$D{s->5MN=_^;kC-F!hHg^uQUf=mV>X%!Pn&A>vQl;Irx1!_=7n3_8fd?!iQn;Z?J^y zbLRT9JmG#tOPA5O{zedeO|qX0A@=pj{%S){<`37IHDupsO8lKV!}LWExdQPQPyDHo z{q$6_AKXvk??m(yN&N3Su<~);I!n$^^~gS2pX`&TB`|wjPqvZzE+G4^mc*Yjq0f`} zJ;-@r38}9xu{S04y+`u9n#6mWv27u6NUk|CDeh z$9-^TQeJmb-$BYuANMcjL_aZ_$#FlVK=$7j#Ge^y-!4RdBq^_$oF7viSb6x4+8ok; zG#?j;{yCD*Bc%UNB;}7K^-Un{yOH!4TT;K>MBa_e2i~N-YovXKll=LU_6#R)NWJ4k&dkorfE@h&0pk0bd%O!Nnk`Z*E$78$R1$$XJX+CQr~iyzM^Uc_H2$&Wc{ z|CL04m4xLJ&u8Uiewj=9<9ibCMsl9oMf~+PVDWZ>{1+6m@^JrpmyDN)-b{|?uO(!> z%^>-HK=RX!oZqv_cnc==c~1I&Iq~sWqpKK+f{Q)Q6xuR_kvof{f5d$q zmtL=?EMB~aK|Ku;pE`Li$fdWTgxwF~IT!Whi9ZE$-^rzyQA@qEwbVObOT7!V)KjXZ z-enFwV-1#n+)rU1D0b9idbsZ#qQYog$5G#e=pmotXbyX-_lUd)Oyx*Nu4nP!xIsR} zYaDr?dOP91n)V~A=U&TtbRg?8^@Ft15LOSoS3*8TKYgZ$_heL#w5?I?^d5Vfen< zr&^xRu>OA)@!ku|M}N5Po7D1rf_8ruF&-=*{UQCo5)ZydU_4D$@2s8t<>t|DkxWeJ~!pFTMN^#e?mI@gUvj zzdZloJc#oRw!aj7@cb|LXN(8OH^zhSqs;j)$Afu6#CY&tT!|KvXD6=|>9+GGD!`itdXgXizK4$<;4FI?ll2%cZz`*74=jwk<{q5t5z{AcY? z1+n(S=lIlKo~Qhn`OF^YIcm>0fAuB(W$T}8{}<%_p4#?5Y=2!#7C+8k(zSd)1N-v; z^8D=2+E0^VCBJh>?Qve{e4 zVddk#y+7GcaODr}4|S{_Kegw|AKLHiRlWR2v zwO@ZSUZ_1^{?3v88nx$Zzcb|hO={28e=z@@$ortw9`(2|hKzq|&sYB@{7#)`qgn(+^ELd-|T_P?NRN9x*F6zEjd3rY;O~pRxDes6mac zot9oNQ{vgdZJp-Hs4rJ9zjSi)?$K7~g zQV-&n4{v2E^p5P5*-2roSLCZoI_$PawIe_gk35BeSmEJ$d0SL*bq#?3U8 z)OR11p4zlYM9RIyTv5C9BS{2w096o&bP}$)_hySo%aWU=Ofnx9XN|Qr80~FqIdi+quFquY^A zQv-v8@>e}oQHn8KaAxURn@(ZH@yEVAnq(2B6s0)C(W>d(A&<@!HX5hox711bV4rbU ztftzmJ+RU8M}^g9?^%j3oK88qg_Y(WEB4ys{xDNob8S?f!shmUOb&z<7rW1TSvbGN zI*UM!TSn=x3cGB(TObpte0*yMZ{wTBD?-*jwzM3%Xq=RfbK3m5XPaEllDjs2bNer@ zmg$z8zq;G+*|{%i=T7gwkC!i3FUoTm)AQM#pf)>Grh8kbsOHLg?DGs>zXd33~=^baXU2P`EFslh)J#9cR<+ zk3E;EtkjFPduP0G$b>Q0-nSM`$P2fe74*K(fs&sET(JY7G?@+Fv5P8RTS;mma<;Rw4rXE`89&MdiFEYQA;)lGmTZ{tT7Jmqs`tZ7s zyv@E??JfZoLytdeRg{_cR=)ADH#YI*Cgt^+pmS=JO8HpbVGhGDQ!sL06Z?m4s2MNV@I z%om)~a!F9=XE3<`8ns)Wa%K7(OkJ0)I%V<0W)F`HT9U2$+NLa17(GgKwcnVnrVY~V zXLb5MwBgKQzC;A6yEc6KM8t_)vy|U0#2dty(#SL$Ex?AkSW(oscrQW)z?P!x0`!(ox zeE(AYflXJ~djw2%HFpx2tSp43xpXA|_*RdG#je?6U>t7V4|?~?jtf4r1q+@#6pGKMV( zJe-jFzMcQF{m0gJmznIAms_&ler#0Hwp{^X*|U_^8HOzz*vD|SLYS`ku>DW;&b#Nt zT#$3Bpa0fhF8;z=SM^WxzPcN1Q@Oh1!W^T4CWf&WpDa)}oT1<8uxF!vpVD6snxcLx zd`s%MHT^t|r-k*`du~0v$>NUNM~)w*HCX+aySH4Y=iZU|*JApf92&j)+rj!N3Bx|; z$aF}(?laxH{kE7@c^*CA_4NAq=;qCXnKyn6H%dw$6!mrPf{M$!13oz)aWg-r7-i$N zu7S3>jPdpEPSKNdmI`!WVJ$I(4j*ntA|S2#%MnaZjrONU`W5+?*i?;7mg6G zQ6D?%Wt_$kjp^5R#TrJ29L+p+FfHWs^|Q~6l9YU%u5G;AeUpZf-&N^>CL7nc%+Wli zeCyWj#_smVJr499c>DgaE{n~lwAb7ulNXzkcr$lLu+@ua4-SoUYh*ED%GT`jXHL|c z*s*8-fWDc>!>^>gdA0e+9UWJ7-~AIOE62_;d$aw5XUUCsF`r}t`$W#n*V%E}DkUlP zQ;y3D(?<781H-hMt+o$%-p(+*$N9aj5?uOqp7y+~ud7C<%{_cOCLG+@cwEBi$(|mw zzB$}-ewuLQmG7;WAM%QOq?O5d znQ?Bh(Ux1?vIp3&$-M17PUhUa8_tpWZavYqC=-}$+c@*e&3H*?LOI=c7t$P=A9 zk+jjIeRRL5m6iU6%e+#J%)FZE6d7$1HP%pO+~@1@Dp}psoC=kLDxR6V72Z+(ZO;B| zk&5L2k9Q+XW*T?;>Jg}#|5jH+yzGVhO!JvT5*N>y-C63hg{Vf+?Ht_ zeEPKX!SA9L8!L2&f7-s}`SDX7G~ zi^e&%>R)=i-t!q|njeR}vS=ca2v*Dgrj_<8LaSV_t!dM9@h$DO${#nC6jXW{KFZhN zw;4Ov9NjzQ9v876gI(yr5`XOrW~%7qmRvRt$*4k>6&?R7W{&Xkh{3Xr{++O%~e4jjF=I72HtrJ{R zQ+9VrIaK-}yw8-bE%Rc0HF^&i-ThbvLDS&B3L|ndXQz5wB<(sWp=yW-+3>X9AF=KyUUU5 zTL;~>ww`FGw5r>t57&1bwtBUFm8w%p&V#st(tDpcCB^O<6o2^54_TYwPU8mk))%ik zw$0>oo_fA! zJ$pV}s@Sl;?1yjq_eVD!CZABAW3i|Gilx$re%O0X(b3n}(>|J`u&!(WOjvIu)dyNQdm;f z{6UxIt`5;p(oWK@`lnacUpM}K`I(MS{UTq#e}&S>Dydoa(+JyPn)^(1ZfOggH2?MH+@Lo@nQV^F$a7bHr?88&FM~WHa&O9 z8+Yc1t=i{rKUT=h2v2=-?b^$%SeNT~Une@!!8vKR{Koa`*QDJhquo}Nhf(JeLeO=X35 zzjc_bezd@}Y}Mu;^&OJC>mK(SF@F4mM)Di;^JV3NZRhAbDR(sUUwU^`Wz2InU&{6O z*D&1hzW7R%S;^nqsvh{jgl`23_FT=zQ=8WpCl~lTZ7BOu{%E-VgODv| zx7%j4yKbqn!@S*Zc?Z^Mw93lX(bLmg|M8;Ao01*vVx#ldUreh|Zm>*uv_)=t(TZo5 zZh04C4^`%`v-4gzon6P?%4VhBUOM5}+*N*kt+#iUQMzfDE-4(_HOp`I%U)Rx=B`ig z(r%Q3(#UkLxAO51gKl;?zE?wLS__NFbi3=Vd+3C8+3~!%TfyQX9e2MN{r%0ooH(5? zYWuF9ZzTP+ebfrsTl!j?c3AAI+@EJ2P_Q-II3Z=b?~)HjJ$k4vj%)r=I=p;Hs_z5W zXR0zx+OUHrO8pFz25A(-c3DylD0LrULO2oQ0L~;<@=Y4&selB)SUg$TVs<+%Rtq_ zEv46Gj|FF~A7R+=vwFXV^^LxmHa~T-%h;~#Og?V%@X~Dl`g2}l)0%X_c3nx@|CeK>ur1aZpq_^FO5dN62IH= za?jf69c#Z1j?T1Sad^FEYWDcZ=zYVxE6((q-!!Z81o6$o`?pThcb*=VlH?aCXSh9J z?7fRkBl=8Se&Di&^0)N{okn==QV5(A7@A`zBiCW*y^cmFb~iNGy*5o$c^udgJf}(f z=G(^)J3aE8<$88#3sAxEUg@V;( z9eG8~HX8!N3b!ce8pWnKtWlrz=7Fgx zD^|XZ%CvM?+eXp*`uh{hr?u-~?mEwPZ%%2%Fmcq_DNmI@wD8I z%L4X)i~c-u!Si{SJgmYxr%xZ6KA_F^2Ls*2@xxQfrrnCZrr^+%WV z&9PY1B+s=`f~%F3avwt(GwToAuXHq8v}gHshv2aBhT)Eze1cZyc!{+`4OC-at>_#6 zzUkVsbqCGYs2}cl@w&+fcheoR+s|6eUY=>`x=?L~sC!qD`LL{yfx_M=0zcXG>o9ic zz2lj-QMX>6HF6u+XM3ytS~dgJX8bthY|(OCoQ<;dd-u09Qlw5jZCdOXJ#LYQ($E*P z#s*|g`mAj;cK4R?c2bYsCZE&19;+grJVkiBTd0{~Pu&syg5p*LA3k6-K+}7Q_Q`(2 zPV-X+Xd0$CNTm#pxv%K7SX>(MuY=>1^bNZX%@)7&adr zjX!pEpRhS3=j;c&o<~-hq~^8E8}QA^)iT1p`FKnJIFBY<6qMsn|L7-~xvgvAP_x17 zy5-6B7;oVoH27iuhy^P|jvDt>41rQ6Xxv9Y0~?q+pbrRgI`%q-RLaIpEjiR8Y}NP^S22VW*LpFjHW36 zfNGeb5oR~RnX__9S#Pr4K#_II;l}sfd12*4h`Q%4jUMfow>7* zs=>_OHtNG-P17oSg}SVvZ2yCYKDAb}oF?1jtNVN9?T^On6kj#&?`?m^BI?+)1e?2E zSD2(8YH91OG^Fc7cYEE}5AJk{bhiy$kpEf!W8BD0yNQ!0zv`GTN*!vc{x&`GjNk3+ zW$B;7bo;%!bJq8krNfJ;0VW6BJ2f|y?NE>$E?2qrjyDbKe`VSp7mM)4{hMig&{-hr zc+satYLiuY&T=pAPB)Sr=Y4q8_Gz)3zI-TET`*t8W@C=9L%{ha4~@PLz0jurgZ=SI z9m<>Lt7#^uIqS|znR0*Sz#q{%u3DY1UcI$#_7_{%B`P=fPikVbeS&k6!s`92Og~PE z%pbixcz>JglDXcB#bxe6+Xq;5kIY)#s%$}vmBp*`N_Xr@-5zc7v6FA)i4~3CuL$1X zE^gvCN5lFHTQ6H}z9rT^;FFZi?8kQRl~ug%Xqh?X+a6Y1`A}ovr(GMb8G9^eK9=ckXfjgz*wR}i zs~0OQDjKzFVo5=!isI#jgeBwm#TNMcjGHML>U$z_Td#r5&RP#Lx$;;pKXJ*2k-2%7 z8t0DN^q}3?*P%;1+vmCV>9n=ukh8f{4C{Z^)C?G378I^KR9Lc2 zeP*VIPyY*T&c^3GoNv78`a_=u-Gk&NUza@by_J7vm50pRnVW7u?zL)X)ZHb@m%?pF z4~e^HW#6^kJ(If|W9OvKjFW)C@(*x9v-B zo3;F&*i-IfUQEDv9}An-UPa=s$EQ?={Ce^$@mD|f>&qJInY%3RrD5W{d&KpJ5sKc5 zV}nLoxBZrB@ZI7{n}i29((;=1+1hz!tKL)gDea!!;pDr|>6c8mMk^ms|6*id`}%fx z?Cg_sd%e{$8=c=WF5rQwM$bz@`Wq^@?~x}~sszVhh$?yD=#;(d;g&Vq7k6sDpowgb zb*Jx!S4O6dv%g!mXYan3s~#E7o6^_ZCp@~#j-^3)QoT!b?t5iTOG0`ii(wQ6&=iLu_04iD#F?Yi%3oNtel z%NCuCI^5~`rUsywCV?&uTLI3dTS zx6ReKO}>$L`i}nebw=LV@7hL*CFMTXb~J z0ev55)q(;Czp2hiHtQcP%e)o&JnKg40C^*o-&Xa1kya4+sH3uyOW!eX=I?q+9B-DfuPdTXs& zyEeG4wQ2so!>r@of7+k@dxQ=U)irgD7j$nlXA=473h z6encQ>gJN}v!rNkbLrRztw+ctwXBfuqW1o2x6V_)=s)sScQ*2V*eI)Q_!wWg%Pswe zHXdT9Zd}lLjh?AVuA}v=3HE2boi6OuHaYUzv_YzLvZ&YF!os`X;}nzJd|xh&ozQyr z3AI`B`CEJr_uLg;c;{Gb;JK_x-%L{%sY<*L9G%m;LRx8C%g5X2EGpuv`Uk0fB()H#iZlKh2hi3 z-kH6~+E}B${PX3FzYWbeaJcZmi@|+++}Y4>+w@Hb9O`AoD9U?IH9dSQL13FW#=_NR z%DIY*9+Qs>H{UIk>1lG#A~$^YhVq;J)3isd%iorGXs7?(q?x`Gf?n)AWznTuSef0>^>GVef#Vl zH!ZfrCAXdR!gbc@NTm+b8;`yvHz-?GTJFdIr=3d2<~%I3dMBJ7H*25qp`;-_&Ubwg zsib_S%es!9ht&4U_>HhnncsKIqmb#lJd;99I)!=J%<1&teEy@Q=iW7`*;bFT+?nm*NgLgRgbDMfRdUkS_K?3${r z=4U%|Q&mwDttb324%=9DZqv6(9c{j=QP=;Eg|Ci_>U;i1L@?--?k>TV?pkW;20@wy zmlUK0iCtQ9=}u`_x^-#k6aisr5Tro_KF{_0d;Z$HuXFD?XXc!lGiT;KvpxSR!q)4c zCTg)}kI@UHB4D_syXC?H^Qj7UW$W|}R@xqBhXO8k1_EbnS4ONq)a7i zpH;6UyWjTT)T&EdFK<=gqx;%k$rF#Kxg^cO7cOOpxN>++WDKMlwT{kNaJs4U62f#DrFCdTq!?e^Y&AKqMkKu5^DC#Gjg=&$zURpKLnv0Iv=nw#I+ zRdWoIUgCko1S`TT;JVMU*ijMz9vioHVcdetCY%&o#c4MY^-g!M{(VvWXKMFV486C8 z)pJS_rBtu9`B%*#5SU8vAGOqR4$VoA$;vHOxc2Q{tKPA1Tgxy#+l{ zri-b6gib{yoo_a>@|k92@j@Zm?l`afp)DF2ZK6M(T+If+_~=B7S}LIBON95B z_p@Sk3PSue#g#dKVDnM8ya^UFLej0K{R_+e3ndPWroIOn+TLi{+I7>>3#gXFSv@z^ z0a~K7PZThDb#*o3lu!X+g>R;}+ao*;;>W6!H-ljEzBa&T8C=GLz}6`7t)cz0?LFV{ z@7Zp0<#}@UBZq&zy03YhV);TzBYq>y1q6~}IsoDFJo)%%L5b4hMYrnZiLhUQCh#J+ z`HTNDhp^o|q5`Q~_cy9a2hz!ZnU1sklkRjc8mfWfV|y>Ywm1LA6#w9pCCQpAv_P+N zr$+0jE^P1YobxZjSlXr#|Nn!Pq2h7RY>(dQ3LN|kU0P|cwj@OtWv!xo``&^ZUg9!W zxx+gDO+`0H5w^8P+>_xNvQ~w{>N9mkt$#xif6W-X&{IN+k^R#u6`%9?cdGU2yaM0U z>jJ}kJ}}Sxx4pU5ULMdsE1LeFu>Z8sk(Je3K$-0KmUxdPmbU-vy`rPMRj#`@633-) zS#?DrV}4ew1t4gaPt_DYEUf%brl$V@TRrn2v!=etYkMgC(U>=+X3rhk@SjEd8z0+I zY^sfqk${6~Y+(`5SE~9N#We*o8Fc0}QGEY|4k_^Vt#h=htHA3QW%a`ulL9%iz-Hdj zbRzZsCUC#>OQnKt{)tra zz84gqV`Z&5Db$l= zT!RX2wr@uFL`|t-6H5>|KjHm$S|fR2yQIFk^d=24LnIKVyba#Z8BE)5zfnEIlu|B$ zd`NBhz4>EoA7Ul49|ijE0rdTedq!iPM5=u+5GNvOlk@YrOFh->D}JB12n{N}9O-}) zx+l$b;-sc^b^Wfeco4q2Dr6BkFRGNByjTL6N<+}YG7ffsmYfw`EG*VX#6eucUbnxo z_IejTlQQOgk!Z)C6iWURGF4g<2U*{pPN#P zTk??F++=|~rWKPjv&eIye!AEC8&{K;7vdQZC3gKzUPU5k?)qC<1PwD4Eos;6)>;~+ zuqql>Fp~Ee#5hF-@g(;V2m4>Y03stplPOB)h);Pr8sy5lZDfYr0(yx>3AGp}Ko z*YYv&{FDAhHk@U^x@WsrDv-`|fKgs0X?dfB^DMbXO^i>S^FN{3$D}bMduqDUBD>`| zkp;qhbDQ}7P^Yiiw?Pm8)bao@2A2}ei7oqccM8Zj`3ledXB@OYL2bX6(=;(n^k!&q zEq*Hhj!JHgeJiP$tl`QJbswWDrPbjiODj^W=X)yk*_s-ku1%gy^UBdzlJbg&EtMxg z8zU_Dn?N4hqv>S+*U+0q)v(gVs$jX5{Na%F*ha4v8A6LDq)<6TtP+cU>l|>*IQ(_@ zN&F>aUj)^$QcgbGo}|n&wDCbuT4{n&iKSSi0o1J9Du~9XJW%G{uYTNYaoOOon=p{L zAco~BLxd9rB$Sg{@in@{E`x}gn+^9uMO<}#wv-J;o8#FMtkK?dLW(`q zg(X&&^}alMlTh^)AkoOw+U$qX3^_oX+n1foMpo43x$D5B(NPK#PbLs5hM%eA zQ1MdHA}5Lbs@BE%>>u3~ne@>Y z?b$QbY>2oibH z{thM_eE&wR&I&tP?v#+*vD92!1LM!hP|!dA&LSRt(mf3cqa@%9h!LH}NM&Z3YQ*q^ zK5+jgK%pH{uU(ek(~sAcU96wU5_~ zoqgt+{f_$c;}a#JQH&L6$&+$1YFRR68@72g=i{}*YaGAA0ZNjuK#jl0 zk+LfgF5&{!g||miUdW1<^}X1XMnw`|k-RPG|J(1H>MP8^L)NS4T$!%p zPqr=E(%CVj3pLpsQwbg0B5$$M{Qj!k%7Fc^azbZd^XiUIEVs;qLeLQ0Y5d=P7iXIrviQJJ)Xvn4`b(?Ib{#vM7Qc3Fe z&efeW?Q`GEPS2d{0FBeGP9At!G?;LzJHvceZT!WkBktc0B#W?+l%&fC0$8H*;oIza zjV!oRw5E-#r40W`p?ZplIQ)C5Cb8h>*4B{bAth6WyYpkS9b8RY+=re^FHJRwT4MOJ z=hS2Ti^8gcw=@AriV>b^s*;fbQ-cYwuo1qyuIxI@3OmjQSeg2eiv%S|~ zv%G;GzjQ4q$l0Itb;sIPE2e*;TV-&g-%vGnxTN|I>r(xesaCQ}vzp?UU?IZenj)J& zj{e*!LV6bFUjdQToam)q4SLlV{05l1*MIc>vs?f7tg+{vMo`=n$d)sTcWNmwBAvN^ z+zDm66MXn;=L}r+Mn<~-o^ZcxQlq*7&LC}dghlO%5WMsf>0v0ykPwmNN&n)#i_?l4 z$pxFLN}5I~*#&+@Mnd(u786uSHjWE;6U_IvJbOAH5>;bJmzNVaP&cx5xf~Z~PT7h> zLdL5EfxXgENhSgG56LkIDs@Pa^CbWV+ z#P8Dg#b4Yvga{x)8*ZjvjTI%+R>_et|6|rg{{usz=|JApeC;|V3hClS=Pxo>a@@(? z0EMpOW-^8A1#>?c?3@;ioeQfZt32tNbt^>14YwGApee;=APH_t zTIh5+wd#okH~YEgYZ~GAWYv+Bk~ySlQa>wlRyJe|rwfB|0R#Db(uS44=Cj&|@*onpAr z2}mEq=oOye@(3t`8*L>y3TVXZC`xkuW9J>qdUN*R!lr3bg}*!u_JXyg+@-{{NEPS_ zO}%+PF2AaxCiDF^Wsl*rXl~yX{@_aUTVCIkE@R0H*HZA~&QfC!2LAm~G#QV7nnBFE zN#@3LgzPxqP+1>UnYD+KU>jrtAn`pFM=7$JwoW1II5 zB+^Mq-WsBl#2tXYiUHpGYZ? zPlc7#5@)y|*kx>XY5XTiSt2PQ1ynI3LN<>myF8IZteJJ?bgY@zwloc=+DIjn^~~0Q z@Lt9XmhrWOpe3jGN;!EpHG(rjqy6Oji_La?wtRM)k1_8vN>JrFe@*w*cOF&fEjZZ! zJ6^bbDrZkdk{(Md5WmiNV8&MfmMS0><>%HWJ1xt2RO1xfXcy)+a&!NU34-YW$Y5Jt z$SZ@tq%XdnOY#)&42Vkhc^b-SPr22xm1nMZw91eK!aV9uHf1Yai)Z(Xotj8rtR^MH zCNz{CX zi^3ZhfP2}RM770m*b;!@St2L6wAByq{cP>&@kakch)8Yz*nb6Z80ax9&MPpHXmX9q za+h_M0+dz9_wH3|94h)tt9{X#RFXxEp$w9?)f#hll*)%+xmKBOOgy`4k}e5MpZP0%(%4g0aa z;COQ8umZBl&5m#nWP!)vncIx0nd zMh{)lxbc{&a~-HDfIGp8;D^ImW22OKf2noCdn>=@WL$)FtY6EHWhKNNT&}Ogj!i~q z-@kNLt78n!rihdjC~^26ajbME@SlCGN5h%+W1GQaJu^K&f3rY^HFL#ho02zX15ZN_ zB7I_3c%~LeOW1Lmq%33&g1tZH;=s&irBsW%o9Y9hbv+Ksj{}8))2ql=q5p7wssF@v9C6}*UR8dAQEoQ@ux#U6v?G|mf{Et z1tJpOGBD}QfkT<2#DQbz+}9W>1IMp!*3@-4~2a!CVJJGp#SXqulSsJ5wl|Zncy5 zn>zUytxQO;d*~8#D0r**>ZCpT`=A&*eyG%VCg)uD;obyrbS-IX5Kd0; zKP`FUIDx?SzsBMpF{c)p`RcM~AB*d4cb|$|{|4g?q z42!7#e>~D}3ykwju8`cBJ1=pa5W{HNnA7Dka`|P6!Yqbhr7)*G^`6CGKXCN)e_|=~ z(;I{j_(9_o9ftd@1#NMNttmzG$ID`cs=tg*`U*b;tMx?kE5!0OFQ zd>*Y@&4Lq%ujdgwo8dx&;n^>y$dl}iK=4Iw92t7c@I=F4nppt}O|m$d?Dpgb{?7~4 zKuV}*uU&YK2>()Z0Yr*LSqhXQU#@)cKKkA3^~iBLU*LCl4c)nj{=3Rnd45vrYcU4M zpL~fCX#L&wf9})K5rO#6yjtyh4NEL&e<2H4gpVDSr|kjo(f;2YfBI;>*&zed|3=jl zhkEHxX#)J_pGSF?9Z~Eqe_PBqORIf+XsW6=R&-=?Ky$*Q98a zY{Ig230R6k7}}m;%K8H9cBN?eG;2)3)xbTg3L(5lDWeqQ4Kh*tjelo%H(L2eh}T3z z5iEtL_~l%);BKYeOse8s@29pPEmV@XDR8MX2G^~GIae>L=Y4Dm^9bU?sj!cp{e0i# zQbsr$V?s%yUEy2H$~JQRFx*tb{OwHn9A+zCW(mWcYK(x@j#ja6hYLK`r419jnjXz^B6}$^Ie^Z2)yfwxq|8^0H#1n+ zib$79v)oT_h5PVd2m#b)-Q=K}q8L2^9D|=+ZKru}70c%vcZU#${q%#Pu|FtkP>^bL0O=bqx@O1s3qtjul^1<} zCQf)?p1`nAHC37Os0ay%dNI(pg;Nerj_PXFfCq=O%56^sj9%n9P!~{c%@l1MxUHYd zQJ1PjxjHsxr*HEX1(}UlwsKb#T(i;` zHnoaa_%|NDCnOn?P}^ag{h?(g#ld52`e&niMaZSyuc!*@p`((!XLp;G7s*XilL1qd z3M$V>+iNnPyo!zgbZ3<(@rz?(Vk&ZU}DJfSjYBDsMh~ z@#pvLcWH-a`S{fZG4-75ieKP^DZR={Mw7#@Hx-xPUntusa#-o}_-dfgz6_e)J|SUz))Wn?>eaKN5QG*SuHr@HL=m9+@e6B#oPZQvNh(o< zrN6gSwZU*|s63gZqyqYEx5OB1PD?6C%xO6F6$#b(Ir&A!FD_c-GhD=DM^|h@8xuIy zzgH6V@8t({X+|e2)AWJ81tl%gN*XD;w5fbo<|R=g{JC0W@85?btT2Gd@};NmNyM(p zhxNy&oT5|PJW@*}7$2HhS}4D)>)%^!d7&`hI%$>>#K9~U!Ty2M7{hGg!L-@AX&IV6 zOdZ5vYC{339^pTcEJG*!U@gRVLttGi_Rg*dDKeGZN59aFs9AB@*h@EUI zpZ#4)(0Nq6Er~<04B1HM5_?@9^pb$SQb|C@nK6b|2`eTDeazFw#`npCEnaNAPx3Gb zEpcK@gMxa>7sPP=JT%=|8@rUj7@aJzN!PZ(opxIdH!&BN^=KlckjPsJd`guhxgf$x zZx*VcL)$2qt)}9nyon{_=}C|3p?=3hG6aN$=__RUm#ieaXbjfL z!A!Z(JUPX|hb&YRs04N&eBvvMzh*QNJ_rk`1)0!RFpkA=K5NqEnl@pSxst&BtW27( z1y1oULFe;{uSVXF&XSja)?uENBgGqB%}`Qp zaq?S*O-u#An=;iVbaXs10exN}Ij_V3>2E^2YOjV>Wr2C`SoT#FIrToac}Y_@R;mL@ z4&o2WauOFG7D-A9Hfo3Zi6jR+d0=-|6%TH*ju!v&e7v>>qaX0~5=knU|F-m$xsT?! zdtUN+MbC{1aiLYwq8oCd#U1=Xhhn&I4Te)+!;1N2745A>0qxym9RxqNiFkO+jcqbT zvgCi2bk>&D?6b{DdNF|V*nU8Q);}bnkqBnS_Wiulav`ZPzLOkg0wKNAAVG%_9w!%K z5w-V*MQLHXk;>mzNMp(kAKY)+tV$rhvbiH4W5n@%;at65oan&X$C!*uMA7jh-_rl< z2Uwg~$E7@(!i*&0PD7j%$FfNW-4NLpNt-{z_5G($K3-QzW6t-nWL#tmh>2JcGI%!< zByvBa3Pcf1mTn1RtXf#L9j(Swlb*6PAm(DC-z^BH)wkL$4^Q!8BiNFElE`CnE+3ao zPyg1k|M1nYoq`3Ckez89g&jD1)NyijLM6^$p5uY?yrq?|+DC}ldSg{e{EvIx>7hU7 zUKQeZpyns`YqK?OQMP>2zE8TYp@TRWL9YBz2tA1w{p{k;-n^+%N%sJFLgalJ@1RxN zW+28s9JAg*-8~IgT@C0uPlH6L^ zWkC}}b)sUnw3j#eI|OR)swmC*aZ5_7F6`xg#G4QF(Oh3)??kv=Nnh5zH*Mnj+8xV8 z5RV&;#$R4sRZ&b?|6S<3uWW;R5_Z{bmRT4pu}bxTZ?p*ftrs?`FkL=sqOJdp$<<6G zG!4g})0T5$?Fzcum6|YiPRucXWZxRSB&!8?~oTy<>J>izKJT zkJDlIVehY>>fpPzz^YblH=9hta9!dZ5@A9B@t&?6*LuMhhn67_9&=6f`zbqd2o8Z;-d zGX+VlKw)3MlB0Mic4oHWmr+0ZDV>^$W5p`@GB+Abw+EFzd`U@Au&nR*OmY1DJiO0&skXUzI->C`b+u#D6hPmC{FDP-Lwk7Lfimdxqt zdk2Dlst9^J{n#x@TTrycrD_q=l7UI(nk>ENLt0b2&UZvznQeXC>rnJOu{K4l(a}>CR@Lns3&F_S+*ljF8iKm)Cfa+*^Tg~;A_k^o#dj12F zPPgKbOsVp+7@I25iKPo7GX6IqcW*#-cl9%5cET&gFT2Zp4r_NMGUDPEWjh=XVc@%$ zi-HuurnU!HlqVF+A6CMl$HHdW3eQ~-ZohIA0__Pr_Ex#8R0V$d#?cx{OQ_DiEmhlm z1U<3&-u;}E$?VFeM%y*0MqNJPDXFn*?_@~eAQBsW+hwvHl3@|ii3OWAI+ObI+GR;B zh*K!wA;d=Y6J@PCCKrb9!jfs#n$BTN!ubdh5wP`b*igwK#H4|$dVJwsA{o>6VZXa5 z)dLw7eFnr-&z6O|OXEilkM{=-G!mB20eqAB;E2oy;qx0)P*mC&DCc6VW_}Fx?$%jV zz^5sG%fRgBz21y}OV&g4kkAtHrP{E;HdW8H-tp6GByh3bm%Fi$ z`pw!e^LXE?22d+{t&k81`lvV^lL}!k2#ghgHH+g-xL*ATF2>tTi@OJ#*@&IoCXJ2b zdssP4v7@5C=`D38rxEH#+Xp0)^fq*%^%(h`sfL+L$fLSxMD%!-$~48E9R|HEjz1Hf zN?BL+wXKNFUMCh4q{70`?kVe$H|m1ieT)i^@8GK|qg@M!~N` z<9P$k5@)VPWS(7$=CF($s{p=o6<0@gUSED`&x;)GFyy3XPgck5%8JRaoB1>9ji7T< zGYZ{2Ruy8rwAd1Gd}{~bo~$r9YH(=Rwbw_xV}59O0`e;F(3|u1JXdYHWBT$bBv*iA zBavO^yR@dRid5QnNQ}hNps)&C`*TGXs)DBJ;=M95x`-=4xvPN_^veVo`l81Kv2Z+^*9!-r(@<1?as|Wb0UccJs(~-1EJt)E3OfQ z`OD2^4x*||bY=-Njl_NRj?LI~y)T$3oI1Zxy^tRq%QRn#TE9zayR~)*5#ir|^5Gf5 zxTlPoUG`|j^*c2}X|bv+n?KXe7~Cfn0mmOH^C2sWzjn_(7}K_s$(mmU9QMhU2n_mP)wzKYZ zG<>ign!)M7m;@-lQFHhuZ8xol=A6O@rP|C$R?*Q{GnxK>zI(mIe zSwJNoc6MKd4cxtB&K8GXniRCS=M-u6jPaB(^B~Nrkdkw`f+NT6`a9JzmHqg)dKI2; zK4dqoR-7mHZ-EfHhNw3hoTIj;2T&VR@e{ZRBY}Ti@&lSjs@KJqP)Fd@`ZjqY8*>%? z6s4q0ed24>TaQC^!H#4Y1&7}#S0jY07&3F3P88lZoU}HM-S^wlM+WCMIpRwLLJrkv z+o-dYM1@%LRdHzfaLk4JRuS39e%Ix^9YGj3wnLW{vN!@9M#TOT@sBFW0?f2f+Yg)( zNvqRV_}=`p2UIOl!iA!v^*Xgy76K!PZaznOzZFbZ16)(};uDeHm{v?fjWMNL8qEi= zkpRTsN$+<-zsL244I_l!+`e78nz*`x2+GGuy^s6^2;-8DA6tlq)9JyI-}vMQcc%Z` z6m!Uee^5;le~sejpDV=wKx5YX)KT7XviP2TsWYSbY(3}9AE*IS3Kx-m7ir!NywspH(e*41P5BAtanvm z3t@}$=Q52P*H&GCppsxHNYFCwVhZ#5+*aH(`U_mKqyL@rpH??$-pemX^I}WOONMFi&V-G!Toz~DU`F=0aB{vnmGv%HqjhhEn(JGsm1~t{Jrs46tgUAN`wAO zRnlO9VTxZ+-ekku&QF_!{|vXgsT|L71kQl7uAQGFmDHWcHolafwhU{BK zBC%#YiPa0iBW)OZss7xH#Z#w}PdoDzPg{F$R{vi{kFMVmRov;_DM@~%HW1CB-Uo9%G>No#Jlvt&pP1ITV-})I7$~N_O0<6D z$^TkGWBe!kwAM+(ytuXP33J;wRQafEOKEPgbX+sBP;rR4-GGUXs4{{6-+_#j{N zP&#Q$jQx2m`+E^o4Dpc$Nk-QG#ZT&^Uo#L}R^y$Q17{YM+coKe-;dCt)+-=iFN^kG z#o6w(%g|hiUqNsrh0r5bAkP_aWn1lSiJzZJL9_m@xuIuD|7zr55(1AI1}0kQQBm*4N^eD!n(vA8Z0M zbVwIYZfF(2H|9_#<8!FzRGhZvr@vlyS>5)Y8DOps{ZKTI`S})FOFRFtjLlY#5nYU` zlgu2a{;D#G+MqaG^Yzh_tQ4fi__$+LaY?%L;CI*OkVyblxClu0NN3y~45B0 z&^Dw9DbbCBN8X|m;}P1LimpJDw;EHXW|+Bxq9zbXPz_5MEA4w28%4unB2a2wg|Fe|lrNe?6^5bNhrqS5unF`IuH5Ra3-WN)kXe zWop6h{MahFk(sZQME{g0M?e{-Zgpz0I;)-SssfAt%jR4T37z9CwSFfzn=b=5NnAb$|DqkQR1WF?-lYUavd$n=uF#-ckWh1j(QLjH+!8a(M7cSoai|$s zfy8yxc%U>84Na$`e1)C`$fR)kRy1}4>OB#l_ftkyygr5|MYFvmd=@GrMDUlKySFQ< z2uJ$%1;Kby`U_W1T4e$c%TzBL9ZgmRTgTzrPvYXXnYf-cLzS8*heL02s#a1XMJQPP zqX+?CrlM3q71hkKj?G(k+d#N~-ELzTuTNapP zL$O-|p3M*BUlIv>Ko4UUBH+YRB1rq=tEwpp>6pwQPkF)}_n!`MO;gesm|Wp>b~m@F zdK<;l!anY9W&;1G^+Vyf4hU0V%L$g!aj z7@2#ztTuK)I5Xp(oVomXSvy&9dX3OOX6MyG>e%cz2LJMe0=3QBGQ0vR-$%SAklNUL z9PGx;^fyCtcz5_TFCRC}eb@U^$6~RrsDSfS@+-Lz5X6_N(IeqW z=+xKG_mR~srRyHAyych-N5P;Tq1@oiz;q5yAhc;sV`4;@vKlyO);{zjEI zEh3wUxSjd*F9-a_gV%;ecz}r7gYwAS4;uc#^BG}Ov(v2hvm!e1VzA~{JoSSq)GwNlWDFqLf+eq*KB9AS zg2c)x=^zp5D)j&9W;#VNd3XMxF6`sCp>dtYMk#$-;<{C&;r%Q_|8fDikROBD24r($|PXI$Lbx!g*TLWtn~S8*Iw*{&;3 z5y*Zj$bs1G{gbX67YS@A#crS=uP>xOYvSvNFL}wp1_1Mo+sX7OhcSjHHc(Ok3wESEYdLKixd42USsUC*s0r z5wp)iD8u&e*)MI)1db*HW=6V``2LE%QU$6{MPt=7GZcnyduqBWJMr^U7x}mnLHKlKtHB@!U=S?CIpMB-GI%Sk5UI{Tm44iwF7ggx|G#24`p z?^9jP~*w?#?tKuI~9ds@{47lRA1at zfo_Nr;!o1s^8q{)aKbc%=w}&R%$^p;at@OINz!5X|xn#*AoER4>txkh`s%n_Hz?7Tm&fZ@H~;dj?>O zH55;)Hu|n{!A>k80vGl|)IBjRQ6cdHO-z3jq$((<3cC|U3V?`e*C&yEg`wAdR8X>I z#pl)r;b=A~N}?z%8J(|-83@v{aKICJR&ZdDt^(BGiQk=?7h74o86QKD;IB(jEo^n@ zeH9ciW0id?p#1SvO4AJJ$4iu-tx&nBcC*^h0xS#rr4@dhjQ#D}9F|7VM+r!k ziGhwB9&Mm1D9&d`(&1))zjbb8lW!m>Q!s57+3RbshD~QPexRrkv%k|oTc(J{@&~e~ z(8lKCP2tSNPrF}!W{(_?y$)~AZQd~SOXV18cRzXBtxCJhIzZC1@TKYvdlyT{T+ZD2 zObjAH%tcwIYloQx<4+TxyOu;eP`eg`>Swbt4y1ySFy-pDM5&=4p3r@7xvI=^ir!PI z)nn_yY4`W$KNKLD><&F33!*~oDJ77W8soeRB)Qa9-@>& z78!nOX5DO@6UY57V?e5vlAXE*GKt^INZZiW>m7LW5rSmF!`|J&i_kRZk1sj_}gWyZ9Z2__DqUCy!=c8<>2;?IrKLw^lxq ze>{hjMebJ7oE2=EZ1w{jzmHIx#lI~nO0Xnh60wa)SGsLu1>=;*eL4I@mU6CmrP>XX zr>~U!xkGM-LW>1z;FvI9@t+lJO_M&5BKyfZ%0@KRGAV(anEq%I7C$*>Y`d$)M<|ph zLX6K!@{xuktvSkLu?E+qPaU3VHCPEnc%X@9d5r2fy5bK{UcW6gHY57|PE*yCXfd3n zjqxV)rM}jd&y@fH(bP@!%;ZExR|BO!4kBP<4pcV@x0jh!ffl~v++)x;(`&Y=?d*0S z9aVSo5{5YYNvFmuwtOr-h-oXaMbfIh*p;ZpVo(&dZFFiVF5VXQ>y%7E>5o#vZz^?^ zuzr#O#X5SK(juIQsjZi6YSrl(Ta0H|v0LR+qPuuxT=ST)P1wH}QxOA2Z@901)6)ZW z?J%+9wfR}Nzmbu0pPDHLzjvie8(D+`H62+(@S0vU)v`>1%`K-MOKilz{kvPS10=ni z8WJsQ05+9I>}|z>wx;A(6qA3ZiIl}XvW*g?Fz}>*??t~eQ`(&hKnRf@OJ>NWgI~#c z{obc+yWUDtnDj5fOGgavF#xx_;A6gbo0}LAG+LTuyFN$`V)@MEs}rc3|>_)~b?HNAbh)`GJjMOBTvP zio}-AK-1OFby}A2cbu@pZIlBdixUxuysDbDpKw5f~!pthj?_&?N8ms4pErw&I& z%J^;XGjt8qG{(~arM@yc9e&n||Fk<{o_xPKo3?W{X0Iez0^(dWH4n~8cG5Sm30BEk zGMo&6x>$wIfn&}4qU}J!2TljOzM+y9PojorPu>4(=$<`QlqCE6(%)Xkf{NfBp=$E( zvhu_F)bREh?%&G=@Mgrr479pM_cMY9M>GH#IxJHbPv8XBdT{O)uxVCv70q$VHw10S zq|29k6~^6ZcTA~Ooxi>5{hpo04F9Ci_VjW@{)b>K)wV(8^TII~7wD;nBZcyv)Zn;S zd1_kgz%49CMntcp3O*1EN=rNRR1Vf?A0kpqv^7OG;({I7AWy}Cdb7?nFQ1n}4&lxT z`rm)!@*M1E_o_HYF^D%(wLWEXBR^2ppSXNo;rJyj<@)>XGF~H#xBNwZ7T&{aMHNw7 zFQ?tf%e7JK*~k~D$NbFSR%0_{_+nl}YT&L6>iq4}`46iAft70yBpxX|BlV=01*&Kr zGEU_dJ(9^(ywf;$?GCx2MpbNGOqOmR6hP?rIcSzL5LX^gA*kALuEJFX^S?{rz&Y{w zKNI%dW@eHC((bQZ=w|jisO5Dd->;m{Rh<8}$Jt}1Y=VA2!u@uo?{mof4{9CJ8I4<} z$`}c8szxEMEi*lT`Ihp-n3jfJfg&4(#*?G94TUA9mb>BOQclX9;T&$C3x)#$>%&RI zRTvlHYI<#!8JNbgGd2CJ;-^|IkTU6V7KJqh7LR_tAkyb&u4qR-2}UdaNy-jjS9#A7 zwA#PRK5nJ`&?vX_!%T0LRN!H4r-|l3kC|7}=7#pK)xZZiK@XSbMEX2N5m+Z0J~Lm2 zd0Rs)o!c0vHL8h$`kLE~=YVeWc>e>3h9!jRIeCEL@`{K&PMwb`)=PzS6D9zXY+R|0 zb1YSfDAe=!eZqe^tx=w(_W=MpTGTf9SQ7C&Z}@L2+cSzIJ56Wv^80ZhER+<<^;!)F z>i^{>y?)m`1zea0BAZc(2Qbc;s~j8~^Y7|=*6rAqcI5+7_(6LoGm7Mg@7!uCi#?7Y z=}ix)sszuF0CF)w@Qt3F=0HJF37j`j4YJfCG+VnL{dlb(DBlPdC>slKLI@X@v9e)b zHv<+~^$2xeEOk|xa=8moeE0uxbd_OkG+P*_h2rk+1xj&ucXuf6?(P!YwYU`5;MU^B ziWMmCZo!?q-_5V=lgZBP9-BGx9>cSuNhC;GOl_^%5SOAO;ug1f|9QiF7UA{xg1EfsPofm(nf|^@0)&IM^>_O`rqT4#PIssDoxlRA1seq+A+<)?C9# zU|Z>@-|X)IcNuOJ%H9l8qcRJoDgX-9B3JCSg^4ma*F(2wa?P==ri?ADmYJi{$Jg4X zL@2L+oY;Tf&PHuxD>B+|S0y#lb7NmcSW6P_l3kGBPMG!J$By+Ci?pxnW4&PY-E?_x zZflrLHno$590%gXhua;%lqDXXC+Aw($W;QC8z(2|vN?PKdl;QnIWchKW=A(g+gCpHY1 zrBhe-$cytp9=@z7rlU&B^HYbFrOa?HCVvIIejCY<21Qw(oj5H%;Z#E5cfU|3BrPl%%v0z!xB03hQ^Ri()MUPxj6yR4)BW9^ z9{f;xq$fp`XU0bTDRKt0vp`!;xQwE07NG`9cin^Mc-%&9{GtfD1xlBHhCuAw=ia8? zxciwx!4G=Uc0`c~Dc>l}9r%jZn+Mt%d)8wU)$41t*0Fb8CTMp)^t*#wO?ngcr}I;Z zTcpmAZoOC~;TqW40f%Ua+Cfs$?|0tZU0 z-~)^f#T&k4B&*x$1=SO(NL+O0J$$|J41veuF;>?Hf@j8C@f*yK1tp`jcKEsUSQz62 z)0F18=&>WAS8<^Q`(^V}FIkacumk_TX}XII+0NUu3PpS0q5H`;|QD~ ze<^mJQ0-XujO~5o6M>clClY|Pw`d@u&ed&D?=#auAz>bohvI4LLpEEO5YCz+5WSK8 zUEnr&ZcBo5rZW?v$y2Rwu;)+)z$V1?pk7{*2!PiH^)RZki8@yJNO1OQ0s6PX8tdQ=_UQUvKzdE-Y9Z7I_iuvE86ti zDJ`jU9sz)k+|o~42UMNn-j3KzeB%ZJ!M@+etK3%s2uf{%vMZ!U#S&$W9R`|-+`O4T z)EVbFR0pdc9P(LOZKi6)NWeT&t28Jjw%ZIe3iWR3X9CN0(3O3j1U>d;nVrT8k?9;S zRiOIO>skm48^JH|?#x#LejDhrPk_UhiLA?y&s*2Vl||;Le>^5_j0EKRBFO+OnHG{7 z&V<8qz&GX97V_zz`~rl|aT&&oy>sS5Mf|L0fa8IP?fV0DK2;Uy$`uOtq*F0Xg z{fVMqyfPB|v(qet{X*^%co@t;&XpYcMM+UmSpr|qy4cdmOYXmtJ5XirsVV&}XQR1P$+=LaiMIm|UaH;}5umOD6;v`I zSvRE{u_Y`;adJp-LK;>_*@w*i2{Q-sOEQ@LIub_LmofAma}Y3L+H@2!$cFtoYW7g(ONs zaX-?ZGj5VM6vE7`0gyWF^yy8`I-8@k2QObxi)~vo(Mv^5Wr~ri;^}ckxv0V3T+|i*~{0`WMNzoSXX1Y9($-%aSf}4TW;$t#VA)YD9@-xqn zA-sLEySn#cRkxYk16?ND!z2Fq3F`$p~92H?io}(RZFasJfA+-x?3{Di9y=9c#(=FIVw9PFR!$T4WM}>QBl2Q4_KxcqzcrGJ$pW9n zrEPV-o;I)+p;T0WU?cGd1B4$FE2r~IFNo_pF9DK;>#T8%mX~YOtfnwxC70D&v0w?f zkPEUB(9#+zhT}nv64KG$)NHt{Oweq3-i9CNn5sMkh%ek`FFTQmG3Ov5P3juz;{!1g zWXbBm{FoF1Mc557MqXPri_^uZrwYf%5kTmpKC^YTYL^CVUK16?B?#^az*KxXkoOx6 z(;+G<^IRk?IjUPiHmye!SY;IN%PLTwgV2%0ld}wWBTx)z+YRO!5u{Ze#cx?1 z0P`dm_3qrE*l=gfH`<4GnPtpKytWyX8HOJPJfvg(Y(me7ILs8UL<9*Dl=je`%dbVg zHdPFhwv3_-{e*>}OkrPx^+a-kqleST+;9b&Io?JsX4kf16NCoxr=o0XZPAVR2y?iQGNTh{suwS2hb7APLl z`3l0a8q3S?O|bQq;M5}jB6+Ggvp7Qw=z-}$M&a?pJ=*2Zg+n$sax>>g?t5+0$n97^ zpXL!&t3Z8SgS1hQ_^)nV?2bJ?68p5-M|T@xl?qn7Ybp7UDH-+|2YidOa$MuAE#}Rq zN8d%z*ueT4W>H#jwK2G?MKlM)d#1#JB^i8c_xTU|rE4^8EDCG{)w3s0OBB?NTt`C5 zidQ}EuIs70aa3=`<%)1CW%Zu8J*yg&_dQbMJ3>3V8_jzg^>TED?seIwU!VA9k9&;x z#!EM?F}2g^4zTtnRo++YqiqSsJ)^ZR$7EkD#Uiy0#aM5>cA>thlj(}F@?CxK@fu^y zS=J?kXcAu8!FT{pwe97pBscs0UnWe}v9jJ@TXi+mM@-Iqtj0aGEg4WqG5UvSie*X^1>p#ufyR; zRGP@ivoisdV0fj=qSNS(r$^~%0x#OTR(#A1{5DBUjFFNw*?m9>zf3UZPlfbsJWZb;qg)6wIwl))t1;r5Wh%$&!o>QXE3}JR zrmdk~-R~yHio!;MVP;dz`LY0TKeF&w0{1S%_xoQErGs5AXE zldA`-_Po$BbIpc&uWLss6&Nq40<7|)vjCFF1cd2_mH(zW(Ck9?kET%1RNKzgkU6oV zGS#!*5uAT8>2?km8v*x^lEa<*%oG?uJ>hI~U%#^bk)`INqzqoeUoyz3NVGK{y{*@J`d#=(;FX`#+>1Zc zjj-lN=Cr=Wp#1Y(f?Y1)K$1tpboe?vbTb#(8P$@Y%JkYm;7W1`*Y?jfuP*?zXMUz5 z1)-?EXz13JVyn!vm$+=|X&O{T4W?bbncXEwFdIve_P2lhmpZY&E4?64Oel=2d8Lp* zZJGp{X~ZPK@H&4|923-6JWc9dpJG`*NMex(pd26@EV<0~3VF=%JP^_H#s8t0N{fjhwj!0w z`edPrOIAEdbXfLQSO5e?_5;AT9HBro3CJ|I>GInZ*HGstVg(ryO88}dO8#2J4Jmq@ z$|M7W4o}6a(J08sid99ZhkXhot zl(LoVRi_a!QH@WOti0iKbRG%_!*1j6yaVLnUOh_hSfb&~X5+I(@lK{`ZnLt2yaFYu z9oh``-}$S{=)*GR`!Rc4EH&|0A3+WskzBn-{&`kU_d$t~$a!{*jo^e)1HyS)6H()* z+x_u$rf2vc(Y7yaQ~+4RBu|d8JJ(W2PIZNNXM(n@*E6&aR|=QiQQ3LPmOXTZCI>nz z-PiuQ0Yj#T=xQD5Ts=cHhl4M>WJhHQWnY7NTT@84Z*Vv&5UsDFrG;upfB}w)#NevZ zunJJ?YH-kZ+8zKc`EN3faH%2*iR!X_DaZn2eH)x13qC8B_HF;PJ#J_HLG%pMzw{Qj zlk0%-h-$&ut$4U%TjHv-8@2}_-*YrClZ~}S z)}pi^K}cU5LQD3cOy!~L>sTN!6Tn_O-*EC6SvTJ%Fq&mwQI@ArlA8-C%GF1N`TVC|T75~+SZw#A_81MS2bmAcqI8z` zYpid&ZRV#$t;pIw5o0kEd0Gh9##9U&brKbu_*Q1l4*cVcYm}XGg6DY5$%^AvKOeF+ zrRuV|3}iz^8wyBZdu-@b1e_7A)^a)R5w44}j#53D`4B-}Vh{^K#+(#dvNcvJL|1<~ z92{C_@fhX3_!D;k>&l?Qh%uUsIaef=87#qhXTc%50osBVHJxihK~=1`f?FD0Jly*W zlw``JDz8hZkH6Ps&`d1_6vQ!X`dhhNS5Gxkl6l2w*&C%$!4~ygL5V78V0l?#&tz;} zx!7p86D1oR)0pzT%_dW+Ya2_}R}4EW(U$LglLm_IP=PH?WdLmMjC`W|&6rbR&wxi- zo+G!Q1UR0yhXdYar78Lazni8CA|sWaak6C5^26ZYhG`7Fl#-`boDl{!=`2h!zOv_& zwW_qh2=7X>GV)lwfjYMONIieaA-!^7i`#r=9nhyE+O)fl=e(nUk7Q|I0b`JJ%A{Os z%9M&V(}?wjJm0=|_ZNk#f&l4-X@wRXD8P1!x6?(w+X?D2X<1PodnXf8m-GQsQMJ1i z!8+E|0h<&+iz3fg87Rj0+a{{R78R(Alw|Wb1xee0$dmh05!#|nDNhGxRcc@EO5+!} zJ~1SLmwCa_R)2%#&uiRW+xVNDr*Lqv`aoV7%wZoFTw-5tj>1swQ?_3rEMTA}(|Cyc zn+tvXu`x~Mn`_K5ybwo(Ehu#WjBW@@C8@IO{qQ#^&I@DFpQY*@{i2_fF5?Cnf|5lh zmwJmVTcs?gy0$GYUXj7WtbpvMy$yz$!WK11nU5VWYnX%U8N)D=n?~F*l<;mSOsplS zAM8T+q(>!@=6=K82$ta+3X)T+`9XhvvvsV(%*LpI?8z&|i;b9&bRB=R%$8+M9OJbW z^GEz@0|5$;IB}nQhX`FE^Xde`g)s=e$>)>_)kl!M)EOj}R((&b@L^wc)2F(Wgwu!#58%n*)C7?JM{%)jT3a*c`1#LI1R-BKC3ha!~?w*?t9n&>U1($kTuBVF038-EUM7c^Xu zR`iy>Nxq=#Y@mYp_?}Wh>afNh`9Ub{tXs26Bu+ym9PO&u@<5DV7NS1J<@D<{y{7)MTy*CmDAWeM;)bnDTvGG=K-Ud}uz0dTakpW8)gn%&{je6=Mola#2&0t2GDkFUV|QkPSpBj+%fDhi}YUR zY=$>FiI3Z9^0^BKe_O7mANCWr5hR*J1pmeLX`{xPt`;l>w}k0I-l${IXgha*U6^k3 z(gdeF?y)2;0&h^+kTjF7%0=fRRrAO9gs4m1CY<-X2=C7qltS@QwvcSVJ(iy}RB8CY z5onK!CXZT>Mw~-*sk?d>rlvT_rAH}aPqcYai21W`H3x(dWwQhLC${;k<|5zYw0Hb$ z@x^m4r3At+s!Wc#W66zP#9j>7CA+cE{%&{K>cD}Jl}7XbMtCI*tl!T!d@$WMQH^u5 z|0#^%a*vYPMMkSe_@qn|ytwAOw%|u)r1Y}1cmA!Lu&vU>oMUUq`-8Bo>*8xfyWJtB z5eQf+R#cZ;9;r9+>nE?R^c`of++D{T;D((j4{ibh(Uoo;T`s|0%4twovh4o&o&Ez@y;vj&*O6S?N`uf!2k&d)#h$@BuH4W>F7wa8yREuCr3q_P91mQIPhvGjL{V0T`PIZ(`$2PHl z)(C+ZtRw2SAz)6fvN@sH_<7|9=YCm!8kTLFj_;_LXNHvwEXRRJj1Dn=)awz(l>m1; z#@?eC#qtoy+<;8Y9s323>}!&CiW3&Mi_910u0#duBW-r_y-D-6k-yJLA@beNGQ~jn z_r5@sIX~Z34W3UW(bKltz+c_oPo4Y$Yx(l1!$Dr%7pw}r^?ow&yJ!ngyC8yclBi0} zrhMqm1`S8Fe$RXMHzYYXrduPVG!?X3ju3}pJ zf-Q|VPR##x9zo*=CoAojhfEkT^V{uE>j70m>rfo3d|Kbpr0`wwYQhgEsJ_BjPZdS| zFp~%##$V>Jp4}Al&6t+>O!s0rbM+NJ+WUv;s?WKt{FH!1Z4oYu;9WTnOhN{AgI8*UG zP}GLWDUrBZFw}DF>rdNfs;$i0!VbyaUZvlAoq7n^kz{kxVJ^$O-u*pFDDY#KFRECA z4FX&HEzZs5-v&Pw(8EvGs2<0K<5m-_(@(hnn`Hij;1vrb0cA>1pL_6Gf=x&(meEcE zW&NCIAII!Ek7#bX8s7Tr`&R(XO0qbS6h`r(W`{oId!(se zQ7z70X|yY9nNRct?Q(IX_m5`4yj#{*G(}cRpg;_yCDuFAsV95f>~K+DDOD9#Ln&3m ze(;UwHK!M6d8;tBhvP2(#+Nu~Q|Y7>DwXxGO~a|6r$dql9lLIW)i^TdvgE&O@y%VR zys00>xLt@e>#~ZgMv-|ss#Bpdp4hnM(GL^p1>=P;C9~Q#sA4v*QEV&LimVUvKf~8y zat?+aDc+=M{bU~e$8u_Yf3s*I4q&{7PHBSoFj(QZIaej6qWm#G2{&|^j?vx0VAGiEoF zXFLx)39{Y(BZuK4-7oE5>t0^*>o~#osGlubIsE{H10p_tP+%zgH3ODtOd!$YW~+>T z=uB*vWwwBS!>Fh2tf?_yXv#1W zV=c@)*s4GKdp;D{DzIm$Ab=|E|3e`0{O*`a^VS0!-DzYTbZd*>3M2xcK*kfmmdi{h z*~&zAm_nu13 z#VW-IZGpa}w7n>1EUfy92!MmR(em2To%itTD>-)P>ZEczvgh z5HD{v)&&JfSK^0RD%+Zk=xOuCo#fECJR^6Pm~JQ*jk-&A#uqYaaiKZ{jt8jv?I6cIWacj=?F8d{CB_!QNS+H-)#FD_)@C{g)Jt z?!;I-s6dvy^x4)q=syy@qTaSq|1bi+$R2a^&7&=BTQ#O;RQw7+z5O%x;f8Q^QI#bI z^0}(Qa5w2yL|OtHOIWhH;#X`Qg=$=_9tL;Q!o`;c>A+G9@q9Wxx9F`Xn`l#0ywGBV zXZ|Z|bi{NuZR3K!FfWYPOp+-1nXY~MOr7ET)<(h+To{RzR0{I;nw5DUXP7!Uw&?&6 z4&s`i{?@V5kCcC$y&HJMKKyI#JGu;kKF**Y&edZv-aV3y+W*C?eMe*;LqGiIYZCzI zORTSI)7~Vk3ouJYa-Ii(r36Ccua;z+sf`$N#1XzAmKVn^(XYnr(mXx?P96ivT444Z zFO$u5SFs)P7K=O#kVCVY&G7d0=q2y^99X9LTmSc^$^o2e9342*;!XT_f9hrF!Z_2d z`U8PrjZ4hQ(m&piNPyzZ)wHCi|J|_kPWyhcwhLR?rsvZU)ot=i9O;xB`ew)!o^`b8 zHbJeN)s-)EdbJIR88u{05HyF&`2Kt4W+FHCW z&FuqO37UtN1$lR#Xr;hl?OFExrz2G9rFGr2&8K)RN%>Q)#%6X_(CH#eQy#3EkJJgx zGD(%v`tRx^24WFUC(M6NsiUO$B6o4IryU%`3ZG5IdAhv!Pg zeiWed-l;}e_dlJ7=R_j+0LCPkc4kZFxHIK2FjJz<3~J4drISR~J@t~PHd7}@f-XU# zjTv-)FYCU7nDrXJz&PWeT+B3lt;gEP^ZT=*C0fT>11IQAvQ6>gs78s>Z(Y(;8S|gS zi_!^=sjT@E#^`z4%$K9(Cm+m(71i!iVo&R!&4Zki z*U}}lLh)LROieKVsc75Ea$Ovrx+e9UQm*g?pGxBWTYxr41RGK2*w2_qlXnS%PI2)5 z{Xs|~aZY~y44N1$02`T#rc7c;H*_%k-ZwTd*GEWt{Vmx_1FC^zwdomrp>9e|C_HVY zwm>vA7bX$;Z{i=a=Cno&z974lG@33=HA`VxwY#d=(*$U9)~?ZW;C03<$WO>q68XSc z2m?Ls~XWZ z{zFI?E}1{syxYO*V4nyl>qiKc;e3?{w{THYTZ{TDKMz>k1z9nE;jSS zds%0ru~x!=O`yf&pJ57p@Q6~z-VxORPX4FPcRhg#d6dz8%;UeBZB>lA{orUEr(=oQ zAbm2w!_9wAo_CFx*n^{XfAD~b6VjFZ?Um<|@F&J{B4QB*COI{C?&rEoQ2i2(j zcu!1=dhlAGbELC-3cG zA(~vsPYC>h998AkyI-0>d>)ur84mJnQ5kSS#TT^5CUzJYt7RJE?nFBCx|UREE-nMp5B zHL|z0u7@pnjBFkwkoEW4e#-MRb%!0|=qr#jEg6lUNA2ar*YW;$@dZ~8G>(vbVw+!G zBx}0?{L#yQtCz9z6(oOFEo)m(Qs^lu1-0SssY<*hl%;g0T2jx%rp*lsDon3<6X<{C z*E9UNgM7~{dyZz{x*?ac()L;Myp0_u3nN9FO+RIohbeFQopDupMlLI?LNHTWV!cKHXZfy> zq}1cF{I36$)Xhm1?1xFQ{fPaWn=FWhM=it&w^m|t=0=O`%=$IoT2YMDc+iff=iT+l zFt_yn9`C8*F_7!O@+2F{WQ(6^7aH{8X6E*vboxSxct=N` zM()y5Imu%hWo1}Ta?f(r?Ui{tEx15=eQAyh$}0$~H60I)hlUz-q29G?bTJS!Rhj~l z=7$l}RC@xFz7)ml?Qdu&BsBoq3ythP@6w==1PR(n(DDLpKvkGv&5_akyO~op{jj43 z4IV*@a8FZEJjK9Gw!77vvc3#9R$uYX)aqZ{}NfxzXzA9Lf}(iCr9^HO=yg)O>&p?d}afFRvKiw&A>3PpOKDc??X1m zGbYUobW3Xl>1Zh#=)}B}`31p}X}Y|k{k&gi_wUgCGTmtt%Szn@Eq3eprLrs5(%~G? zsTc$GeTw6e&duhT4HW-Sx^k05nquo!B3gTki=YTTOlEWe@YEr(d+vn^yk1vL(d} zE(n>b>wqFWED%I?6_}5jF{{WzMB#Y1X&0>s&gH`mmil|C!CSub9Oy(H^&3Is8&ic9 z|3VYO^p8g$JgN!qYVWC;vi(McP8&@sx0wwoO%tYl7E!3H0B7|HWX9T}48Hcqyk>XH zI5LYpeh${#&pi3|5C{5E_n||=fFBLuNX}_t-{S;^Z>KQzA^iql1ru)z)vH8u@HAAz zItnLX+HF)xDvB+II2NFMOAZv}tx7)CGPK9^R6&5*OCb z<9B_QvQsY{&HRdYcr~NBH*Jt5ZRhLOl_1-L+*$;4W9(5_iKpI&M`$g60ka_TXU}PE zBb0HS%Gd{%@vvL1B2~mM;^b)S6KfN*lQ(|uFT5gCA&w-vjK2E&m3*`NTl1&72Z8VV zy-5o7aY#)FodKFu8vDg$#WB0S5~2ZZS5doE&cTF_eg23E(#XN(5XFv!55$EtY&_^Y ztfP>Pr${5kPpH$%>=-;hQ;l)r9QYSR>hC17hYR+hR~3Q=HG{nb~zGg8ez zpI=%wh0r$38>BFYk$?pg2rxUt>5gY4Fxf#HwJy-+GE~_ zDxO{{(gpdM#T-*6E7G^p<0s%dWl-IOf;zwU8x)T3nea4xv}G5HAbKt;mJcd-u->Cl zvC+VPS{ZI`Z^C1>WFaIpjDWI(>e*07!pY5w<%+u#FKR+cTCg_AF+@e|gDAM79#S1W z_pD^cu1A!;zqPnZye>KpTff-3qA)nv&WT{>qoyFCLfDHmNPjm;xYS-RKT-AvbBCqCCMW=~7&VHzt9}1z5V35J1Zi!n= zT~8g6VS)A^G%4+w2P7drqAe&I%8p6)09eEQ5|*hsZ5{E88+?rgksv(+(UgwEmKiLH zzKkx<=DQh5T~W-e*tgFs4zg%4OIzVF@*Ul>!_BO?*oRI{Btq>pw9&;X)Mt%NhZkRk zF{_SeoY3y~`)clZ&1}))*lrKfjri!bL@ZdcNr%XhXVrU*_KQbU|AgLL8?6!h5f5iA zFR=G#`Dy?Je6_V;$YjV4WV~j(txktGJC>byBaD}6m`r3H`zrR0g)rrei#upnNfOVl zP?4!8f);~}rhZhjCd5%sH>QFBqtp}^dzAVjJd{Bt1CT4p4kV=FVa;oGf9Ff0)$yXj z7ln!}6vT@91hnNY?FG?PiM$iPe4R8&nQttez4XS0ubaXqXZo~uWMfum#%!aZ;L62u zgByfn-6Y3dtzreItePHc>V@8MUB8y0<-U`ep3bC}3*w<=L9Mur1j;T4tks&3^A+lT3y^rM7Aw1avrdrsLIkf#fnFensv#R`?6bT;> zY@z4JhTkvNx8LtS-l>z?hcUFBvsx{x``{MRYsYUn+*9E7T|v5&a@tkhF;-|#=$FBb zO)}eF?_WbC9Bno{htF5yGftWg;jpR_Tft+5BJbdDb&OZy6#DQL)yc@J*n7@N#IUtF zsF@>ZbIy9<=$p)|21DhWfpLEp2QK1!*^CzY>QP?Fzjg$Su0jBEJ{LfP%UKs zEfjxQ2qh}2y8*!-DYi%R%pO5f#_rRt|v zF**H?B=$)I?v17PU{e7~E~K&;X=2E5x>R1$mJmh}nF>j7@P~rXl+5|>h%(KQ!qCpg zG~TiALTgfAX86|t(XxxFqHRX-ZDqpK@Qkk&yNJT;>h4BV_J=|09f(3Pw9`l9wks4j z>=BS!)!H#fDQxR{DC}L(s!x=Y!MfEc?mH1{URW^We8F&fxGJtf)`9I=*6jCV8Z~h5 zsD)t!lwkhG7j8TeI|q|?U09N%l|sUTLpGZVPLh@;xbFpDUyhx-J;(AIC1K%T*wIxZU2oTZOVzI?sj1z z|9PXOMWwP{qUq$i__9k<7Y<+wrjf%$^{35YjrK-ZB-_pPASojH5=5-UU!rvL7d)`n z-@!nM*h^p}!waDV&Vi_C>YG1JZB2>l8^1^s8T5^Kgg^c<8btVo^dr0)LEq{@H#EHt z%RBnF{H{8I~fkwO+rvF8?Hsoj3+P`o&HuO^3PCLqoLb6&_y)^l?BFZ z;_(USv(q8cM^^G@aYY^D^?=K*x0l3m^k_9aK%3F^`|S|BS={YVykVJ2V|vG-VlJ5+ zuPq8w<@b@(>dS8|BHLX%tf^#^}^MXM(Xpq1(zbJ z^cCq}94`YVJ!NvXR=b?iA52I}ri(W4-IT@Kh*W)u@Gzy0ufj66;P9_;O%yc8v~vpU z%{7UpRQTh+$b#cFHcjVE%T9Jphobtgc!mPQXa}Z&QF{Uv?J$lLbDU>>l>*GKuWUFv z@}ED*`E^)JixR1OWPCIWHsmk2CEa*iyqu@5cnV%ZY|{`u6E931hz<>ncMk3)4MVbx z&8iEATl_(HbqyOVy!3&w5cyzvQ^YGWSf)19{1P>}Iv zIHkH}m~iRFO}B5DPxD;9!OTWn%LiO*L!mKYu2ZDI$}L&k zgaenEd0^HAQMSHA*k_rbQ(%j-W>ak?y8LGnCi@&rK;@=v8=ma*yz~Wmwjia% z0croIcn^lD30dt`=^S;nbDsMZ)V#K(S|^5ZD1y&d>_F}v|8~Jur~4ybXFt(d zE;?+PbXb*37-F6R{?G^CnjmQ67b7jZi1HxT`o)tF#B=_sU_>MfxmTVGIqL`7zU8!y znAPxXYlPd(oR;a#6JT?4abNJm42EpA?fcMKC-PSL`q^8ZZpu!Hn_WPQ%2w}V*pI2g zb@>mPJls*?258(Z66Zf-)2)v36TKKnAX`Fu25Ot_f)DqSy0l0Wl8M*{XdPZD@4u2( zzAWIoYSUdsu68y8tR0mK*cGPXg=X@Atof)_9J6=|FLJj2q-RH$Ecl}moc*M(Zto;` zQL zm%sU;ofh2NlwaIw2O`4eFWMBKpODOrDG(tb&Qf-&0KA^&EW|-Lx!|DG; zdvR#zw6zqGaaYI&EYye z$%lkk2Tqb!V9QXp$AkJ-<(=bm>wW~?U=*O^i`&aBON5e#b+jZ%u1K$}A;3DOZ($XRt-gj4-F`|D6`P~)9 zySahnxk5WE(wAnp*e9C5Spuq_}@;w7#Vk)f!?h_4b3(Tt!kH81lyJPG&9+*k{-j%=y3$^L2)(|0GD@|t?O>ei4V#(nd-P&?Ra=HSfLh*xM zbvBOLk`k0{&$mpG$r?G_8aueqd{p??Xf1J=Ot(m3u*!3^>dx?&BY*hCCKg;n0no_> zp3t1^Q7%d1gKYScyNcqc+3=8|X=l7HeYjihrXvXx4lxt2*g|&3IJ`~`@UM_(_x`so z)jk@P9KN4_KC5qd3JoYs+pN5R{^}Qe@XTfT*~#QnCq&4*?2)1##ro{7ifiy~?x-te z&9efUakw*$@*mQ?>M89x!qh^wd3MdYz)g2l<>5^v{yR``s|o0bP6<#^8<;Ne&esg;KoxD||_YbqklndHG|FCTxNJym1b&1LFb z-t@L>D;xfKwy0(K{=WMvW_1xBCP*8)esZygYKOz&NSCX`8moEz$Y+=x#^mM{GW9(| ziicddkW4$dmuYryn;aWh1JBuBA~vB+_go*v;_Ce)3M3I!Xg8SWd@UWf@?AwF5kmL2 zKcIN95NyfSA5yFG&pn%T(%u{xbOBlvx9cUiI-6c{_vH>?@>3|ih+QBlxNYEA+3?O+@+N7DbT$ECSX^G!O-~`820d@t+A(!x0DdQ8{e< zvVj}nD!o-=jJtZL#K^b4!zi)OkvXn+6*BkPN5WXIDk5g4mY^RK-yM9XD)9ds8SU=T zr@DCZ!W$}Ge#~klG}AY33M)u)CJ9wdet+P+>L#X+D;eT*INs?oHz87w%;{`K3ZsJY zjdXgFfEDIbO6nWsr>k*U&ix`H_KbT=Hy8C*LST5c=ZesGl#Y+8GH=il6o1h~LV%;p zUc{GP24vPRXzBkPasefq9}>tq?_4e1@af9C=gfhi9%Ao}onj^uG^%P*cz~jjG9m6| zc}(3mbth&am(O!bXu{Tw62tU59@ZM51M-M8%y+yvwAlw^< zdX(a}7RmrX1Jsv~w(Bb2zkM=8GyI&RUYEOk5AFEVW1w^sb+)LTn`3V`*&D|Zwk_H-3}jVP)UT~N?6>r|@( zUkX6e#-@tm=~{tcWcDJt%-E<#9LCc4?JpaChrqEqjdwFF%zj17AB%BF{t6{yzp325 z1elBl(7=0Pz|F})j6#uKmw#qG0?qg%!K{R6_C5oo-*Sk;~gF|5-KI8iJPq**}iLyd6 zbg3L4j_bqZdT7*^RN&P=RqDyathJ(1!&7Lg_W7!3u*|`@;)iIC$T8|>)er4Msxh$@=oZl%@G*}tOzu_dq#s=V zxfWPiJu+aAk1K}_lKcg4Gp>AA;(f50LSkA}MCp1&U(4nl!_C5!0>frKK9D;XRsKWW zXY`LiJ6QISmk?2I*_v63+>{OuDOBQCR@M3)0uFG^*9p@k$(=@oQ^+M0>VCcMPaiKxmq zevKsJl6AF-NjmxR)X;e+PDAz?GlYM|C`h}O^zGvBrllOt8);wtXxG_NXZ_<#We)=N z^np)TO>1i_?)>4Nb%7qMp`Anwhc>6h4DOOxrxJLD%LE~(P^?_nrK(aGke%9`=W;k^jCQ(4&6Yb~oo((x^O+sv+lr)&odi(Ev(PUMO7W2~MM%jK zEqRruYwVIF+&c*F#iUmKy(RGG@x)h&DLe5E`G~m=QkE-mg+dVwrK#JNK_*bmAfNaX zcUEb}aV6aC(vSW{*4C%IgO>MWl>k|l38`-(%eClif(U$VTyFI(=XtrkBtT4M5I{_{ zlvR7dP$(Fofbi-U3XR|8ne^8j7RVp$DFlI15^_VTKwIV-OC7O?D2(ertyji>uSw{m z5VD17{mS3A14+2{2A{sw4Q@zwG5?+_I+*)AOgbYr-Lq}PbBXA-X5^Ou{}uxMmg|3M z7_phFc=^x0*d&&3Gg6_1wwP>|VV-~RZ!6odt=;F#@!ywi0u%ewZ*TDSTx$&Q|Lq=@ z_pf=9q^Q|MpHdS3h!UZC#u6q zqWB*Bwf!{N4R`5Nn|xr;_T+&cj<5n?7hX3V^|4lGClaTT+g`p=QIAMFbCZAM-eA3H z8Gt@M<18?(t#ugFqG`QXdqlzw@;MxVVl~oAKR9chiG~wGF@KYEuEtC)L z>H~?!s8U4||BY3L<|u3yat8(@u?mG^Q5{9|-hQ^C?gYG+Vw-&A4@)S{8bWZ<;y8X! z6k!3W?(Z>C?fbNx3v^=o+Y#8p=tLY7j&8V{VaH&I<3>q0_9)!T&hA=D19oF1#DIwzk@AY~F0!wr$()&3v-kYBh`GI%m!~*EKWWgiV`n;?8u{V4h6XfAN#mV<=59s7Q6es1|ELCAf2#N6k-K zjyee#xZY$;LJZH%hqrRXR_JANI^vkrOgtWa8f=`faS?U0ZboVSGDu8bL%_jSl!7TV)s}9$vUHL7C;HQ1XJ(XgiI;^TkdeE zwf|3wYV(iD;32~c_^X&ix+-F0=P+XI7WHzwli-h$Z#TG}&M~{JYJyKK5(ieyc&iZ& zj%&Owwq2=c!(uZ^ui2Y1#9Z8R0b> z(egrf(@w||^*^!=9*q17^BX&osHx8B-wjG)VbMHW&v~*pDl|o&4?gnMl_w^{V!} zBYs~cGI`SUf_#;^>6{QA|Ffy=F5dLY5f=9K> zI;WgU=(X{ZRZN2oDCD3I$qe|;7l5lYZ`k5_IM0v}ryq#x93OlthH@oilfaW>K(Xq9 zZP!xV2MRM6Dw5eDMX4YH?7ifDWiMC}%&DNzZXsW@Iv?hzX`(D|6Qt4a0{ki{8-EfN zemE!gOP>iBcgt8EiF6 zoj8b{aPIDy&0*tOgSM=axVS~S#OFFUQ(mefcKh+)Vs7u$WS%kw4pMO&Wh1U6MxpBq zgTZr3Yd^zno!NVJtAtveqAxx9|4Y$8Hr{$ms_3 z?do+LnyUmZ=_+9Y>G&?t<`zIyrz$Yp=sKS%4bAA%ySfsg1;w9kagW!=$r7ItI#G`A zP>|p`H^y|pWh|a?&_6jqt))i1@ZjbWMobGUgw>YOuuns7>Rb>ANX(eL)KAC;g45ME zpDq4o5X#+AZyR@p*<^rSi6 zGRcGHcNXg%%v>)QpDqBJ+pS>6a*;#KRD;h9N&o^r*;*c(gM8zn8PG>-Zz#g0#sA`P zkT8=tLv!)GW21c#oE25kQ>V0DPiuB?nIB{2M;fgloo6^zX<)r--qqfmpfM>AaA_pq z?Lu}7S03lP)Fu5e3N^{M>EJJyEtG#7189Q!cy<wf#DAbm;u1g2&7=n6x*U?X)U(lp^oO@UPUO{8e;B2J+Q&AYgPL zAw+Enej3ZGCn`)lEVzmLF_IeTS4txR_S%QIWf$u4`_&(q8wO6r@=|LSc{*0p`4dR= zAe%4ipEzGJ#e`W@>{>@udWe93%tfaXQhs-K;|AdJ15};q!0~RnIU{qPxlzzZ!R%?$ zToEY3G!hgljF@C}hJsvqk#_Rx!iIFq6i=EAp`V`8qr8q~0M<;?a2MyIeaZer1va0N zVEEBrU%jC-uF*pPsmgxSB~h{phrV50ha4BJI3aDXi_x-0c&3K;K5xfvIN(EpgO)$E z9^IyAz;xG63uLD&b?mm0nFuq+g z?$ND6dK6uyFoYcjlyBd*fw7$3ZTuslCc3rA6;d6MEIX%* zV2p68hSDol$-Ghte-p>eigEC^LG|2cx!9gOpFEFu$~+HZ<)OgblHe(fs2sE6%l6t} z+v2VfZQXw>PSKVkdx4jNT?VJ)cm{$`pg0Pgjh*~US!EW2F^wI~meqVi{U3X-#bkTD zW(>QdJkC6A^pj{{-yFGn_&|M%Lyo?!A+9z52c0&;>Cf~dyU1P1sBc3)yBaFSOh{^Y9kb6AI5q^~A67+x88EroN zPyImIkGJHd%4c+AFNv_0^4&1TX-g_9a)krE?Z?0P?{f%G*Fd98c>ubQ#wUQvGp@V* zx-JAP>Pcx^`(<;&lM>;eppksXRB+mK8#5dXgI5&gxheHus|BU)5!BYRtR^`C%cf$) zd@B=AMY7*Qix29ii48s(;6YiJ@&;z_hKJzw5t7oz_qpDDNMJ*@LR?X2hj&(6$EL^f zVj5_mA{0V)+pmUvQZ+}EYj2|YH^c|WRT%2}6T(M06$ShZ`Kr86CRe6G6?2-yi@dEU zggD;M1Q>LX8$d}J}$llcr3Qsvg#CYV$(j9a92EM7f8%eap z0J@SaE++l8ljzBL?NU1{Ax!lB@~0u)G(C7$BaQ(1b^pboQufBp3sB%je1bHWV8J>e z{ik;t-~XVGzRpbP#1&6ZfrY(bewl3(T-6it{`ndUOimNXbgR=zMFH9_#(P-@p>3KT6*#d&o1n36Z_(%VjA3!Zl%3TS z87(a;J7}xh+wm5der;(EdfGkaS%k$gJ^sbiO=p|ZO}nWUoKM6Bc&wdcVXveFq@Gb`5lRuylw7Zj{<=+}}wZ7ycc1 zaGsvMomOjB=UCtkoWHzqdEpA@AY|wKO`rxOyKfvFG;d0}nE&_J$Czp3@kV`tnfSQ@ zmTuQ!7j3V0x?f6=o#_Ndbkm6i0Udvz1p_N$a#)2nUzoL%u$i~r zd>;&rNn2t&h-%Y}PGX}tii4a`E3I?bGSQ93*FD<77twlBu08ulA5!Z@638Wo<@38auTD0MT#z&r1$ZIASLiPkhS>yw5`zZ-s1+XI5#*6Y~d z*EF&s=+-!8B3nJ@&iNK9PGrx&6**6jWwrqG1SO(g-36#_!rJ&dR4aE)R=pAHxvCA^ z=c|(X?s)x0{LE+K_w0-}9;8iC;@5cQ1G6a3n!PmT=fq+fIp6~&1#l^1i`wIlFx<|SeWvXT%$*yzswoZEz=K#Gt91N(nC3TqORttVd%-7#t?C-pM zc($yBwhnsa;D%pF?pi(%!ZAp_B(j>jQ2Y7*=vP}9QTg5YqKeMdk`IMKOjsj?>(XI|1mX1b$Ge;7-;Y1c>&Fub5qX-u7tBzyTcepr$N z7D17oG!igg9@BTsK8Dv>KC}O@aFZ|M->rbo0L!a;x;n*XUCA6g3Hmzk&1duAKkSye z1J$@H#Kmk}aQF?% zoiG=y8wj@P56S15%e++6_Fqil@v{$Iu=6gc9`PvbH(VB|i>Y3cy_jz`TX8$j=->V{ zvFG!mcf2`gn(=m=0|<3B-csK}o|mYj->(;1&xmKGJFcS_sE>*igF<0nM|(FL)Gc)U z5dXcko;4gUvYUUod3z)?|1Y3-?AK@a!*3i}dIYB9c^kB+InAKA^r66;27=c%SN6j< zmta5jmKRR3K|jZWdM0v8TWcX&CFgI%c2#6%l8`mKfryWd0$ zoc06Jau+==^qR}*E>bQ{)@^rq04~FkVv5_}hDDr%lf6|am%efy-`jmke)vGY7OS1^ zgM}w{vmAAf;!GEr^eDZlzQe_ocn3uSG3_fxFV&&LA$=mTDaYvZS_ZG5NCg{OSO{oV z(}c%D{QxsB#*IAn%zBhb&47+eN8|WQ#oP+zFW!aSQM@g!#bu#Z?|Fa_*2xe#6?R`$ zzJr){AT|$(U4W`Qp*wl&9)I-s1NuRqF9u=u$fe;#1BTnhRrc0?Y@iuNp}N|>XIt(5 z1FE)NZ8QVtM#{PXj41zVT$d=n6cQum+K*?=I6b}e1Bt$b9i`0XYA(B59Yz7GTnfN9 zxiO&M_`{}y&@JNY2Q`v?kXerg@SoT*0IWoSVosqqij8A4D6+!U^r}aS8FtSb;2L2- zA!tbAju-lCN-mE0NzJAEti1>+|3(1#I@0k=Cw7&_f^Fue>nar&7D#zrDbRu^ULe*1 z*gQ+0BS$P%nlwmU&*e1${Dw@IXK=5%InIb|HSr>}uO+IwU`-*oFjgqp%AuBB>QuXH zAVRpG`|%0r6%vi-_e_18Q7{Pu=9;2OWLIxZWyU|%>*?Vhyy@7R6~opd7ft(h4#GJS zjOx?1(%FBW=MnzG*DsJkzo?6S{KLJRGyiQ$V~DXI7&g)o7W8q6Z9GFTa`iK|fqM`2 zJ+V4%EVH|Du(BosZ^Yc!4Y+e!4pZVuOz~;e_21BM7_G3Y6^3Utu_*zCP@4n50$wh?Ctue+wCA7GB(C975eCBR=AW` znm+lnSTiT4e;4nK=+L=Szc}$B`Hett8D_yG-$*NG*e?_<>8N)waebR-(8?Jby4cWAfAMnxbjux}8ZNl} zrkq})T?d>yV$WwUl@D8ILf5=pfB5;2^|0aqn6TSn?<-c$?#Z78WeOEJiG)?cb zNwfeN$al(2RIu%_lS3@+z?52_A=01p#4deIU9Z<3FUeRet%MbR*XlVycCi((+`@WABsEv0D z$|>|dv6+dz2)}g{uI$_4gA(-db*BPzxxG4y16;?A4siDK`J=117u@9qzZd4^KY;tg z^&T6lz3*H%G7>WnT31(RovrCo3^6g2v}xPk(+b)jFJv_#0No!O2?u4AD0;6wG~G#| zZl#c80~b{H?tr#7b>ectAl~bE_*Nx18I&V^55&o(A6+i?T;54@&d+|GpJA*`?H%$x z$VUa{#MG@I{`dnbux^jZc&MR+1JuN;UBysL`h&h1otA#T_c+8Xg`aR0F7KT@!A8rH z+CZQD16hA4m6rMq9Xxo;PFS^?8YdVM%nq|D#<^hBdRr#s1mH*@=pRLg?z(0j`?_rW z?ApX%iZ-arhZZ`nUoW)5uQyl#oPy)PxoQCba`>@Ri{N#GQA!K$=OxRW663%v6Tw&c*2QR59e=T-|>9O*^4~4U%2b0jNFfLu|^K zW3L5{nU!JCNBScLm7`f~A4+|3Z+_1gYHM3h$W`dWJIcSc=}FXCWpBQ`M9 zr#3GeKoU1(YmKKk(@(w}vr$g+esaJd2Pt_S|R@U*Vc*ZAm5YK&K^ zePl1`Z0kAk7mqVRbaG0@Nh9tpVO+a#jb{NEBuF}+nkmXgPubO1ozYDzG1FH#$|jlyPowgaG9PcpqaM5 zNpnCV?|E&jKuGX5_-!)VV^zliKS1Bg0Fk_#xEb2l*JmzlO z+Jq4MiXMnn+4S(Z^Q29XkIQ&z)vhGi!U|-Y5OiWhM(gmuO4c?=Jt1d?e|loXL{La0 zba8OSUrnI-SPw9dK|3h~OndiHFD8_SaSDApE?ESgEkBLhY7fsFQ{Vo`k7*3OdpV;_ z;y1jfP*gzJ{WNItt(lTB7JO1HCdDL)(>~O5QaO9++KCUtxc_O-fXNg`S4hnS1X%bR zt=`7TT=XWy=~H8>A0gV9nEL}=B#@3+CV7Anl|PQEg6yOFeYH z5dgaG^*#30*}QDi6#lu3(s4_0*bzQr(fziFmF|<0Jc&E#>yS47^En}V=y!xmg(3qq zwDL;srX5GEL`Ee5i3F_{Tf-FQe(`>+?nkDKBMk6HG3%x6j;7cm&=UEFT5i#Fp9#he zi+C(slSk>bYpvK*@*p;+{dO%-;^HCt*5?9#J9;xw2 zM}jFWK#qKgTvYci#$+;;nuu~8y>mSYUnfbJ{eU`&WZ%%>y4BPXi3KcckcFxBC)~pI zLn6PP62vpla)&HlLcBC_ii&?Z2QP;v_=M15_wceuB ziyQxCu8{=d;5=SfqAu|gAFf;o4y>k63*3BB1D+47s6i$J&l{z4w`)%IkX_0VH=I6E z0V`cRA16$%xZG+a61~4Y3`+m)Brf$KZWj-hiDCoN#q~WbslcH-`zq`W$i+1#Cb*LC zPuvY?_Csr*DxCsw}`a%WRDU_O)#h|MTnPGn!TRZ;q&* zcWF9U3Sc}L++6+`4p@csv5w~Xt-tGKgSt?EA_Bnd5H{VgTn&M`6yT8A+}c-S6E0`^ zcDX`$9MCCMHg7jqY9|yNaLwu3@xaNQN89VEuxWrR`V_Tk{w&%?rtFJ?#v)*BA9<7X zz~ik7wMHM37wAX9;|K?FYKrV4P-$2b*~qKg_8pF$szkt$KI%r>k$Ht4%-uQrcZ~QD z2cYRXQKt3YMctgNAHyR9IWN;gE%_neXcXh%qzETYWkfXO^_~Rx(2Ndtbm8%0veQG)lg5`VdGLvu{)}9C<>;>Xx|PqJ?X| zWH#LrIZC|yfyZ_sQUv^mS@ZKZOsaoAw-wlb241*C2cCPE5g@iz+2io^F9-+SfIe@h zBI}D5yuePEEBVzc1R>$9Q09l;Lz-gLf{fA9zG)LiKyp^GB zQTr_ZV83|LLf4~y?h0KE_>|JqL;dL6hV~iCA|loQAGI80<8sue1ts~lI(6LhpA#b! z%K2+4zdl39{<4>2Gc}EBXoc{WEOb8mO`2L(Y;~6aOBGvpBBI5D5c%Q^TxA@G1$x5v zh*z8xMhr^Lm-eKH{3n@P=SQvtj%rmXqCbHXo7i_zMKmZuG!ey6<AnNLMoyc2>J;TW`eiMp<8sPmFsXG<8T9BaB)|_|0e)A zvqe_d8*J>5&;>`}-H;ZKzBVc4UY;HC8@ZrmuqUg~;$Vm79ud`?8di)>9 znD73pvi115cjT$9+_hTygxPTuTl<9XZ~K&k6@+Aj#O|}oo5x|bi_1qJW>4G(v&kD1 ze$e~4=xc^J=qht)+1BpJnu|DdVov*7`97_z8Pv2ATBL-p<}og@#ON0sk>`?I9q$f+1``B9Pmsn z-ONXZYO1r3Q|HW2-(`(rlgiyBb00j89!#`PtDk2cUnfsxvd^oZyU5YHb7h%Sq#Zdv z`S5LcB2YZar5|w@we~FTTi-p(*;>Sj1g-Eh?;enh&_xXLa+oa-nA|^(&uKBcLN56d zlt@Z7q<4gz{{AYWswx*dCU#bnZ&q_@|1xWr=ejV_r?|Cwh~^*Dk}WC~ud+`< zVYB!2_#=FcmCOA2Z|v+5xr5y=2~?BT&e>-!a<jCG~4N>E|x{#~a3hJX5E(=H5JfvF4$(n&;e8J2dx?z63d8Hms9uvGn3D z*NI~B)M86j>)OWTe*Q^oIFJZWIZ2m8yQXK#Urz6)!qEL3{V-H=F~yd6-B%rll!qQ? z4Nyp5j$ddx1o(s3e#^rhm06F^5$=`1d4uLA9zQO$4Vw|9v4uZnvjuOn{k5$p)+Ika z@*cmT4LO?VW&_*P%V7FB`>|=}R)rj8PTX)CG>^Qhy-swqf-h)f=vUl79<{^GB4r%$ z(*!qyZlIsgt4G}7xt0e8I26TMezk!`CDrA zn{O#Yr)T%)_r%_t`qZf@a`>Cs-kTt^r-EAVQHoS6??J_l$1>0jv&L44 zTj)W#?&2%9=Qug$ku@NjH#Yg!A@Ln5p2^UwJzLU6jtHw?1V|&S2)4jjVeUKNo;q+* zV^evUwE2+K47S*YiJc#6JJ&Lgze`q`ivkpW2!0pMlPLF{-&|QBejaB_tTto54Iq9t zNvviy+wK#+13o}+zrAK-#;a;#pQZ&2V~aVFl7>|pujz6Bs^Rs0%YSJvsEAlc_LxiZ z8J5K<>18<>ODjD4EIQW31hq>Cl7P!##(Zg@w~fPmN$(kvInmF4g>s)3VZTR4z=FCl zB8~QDLi)x`UpFrEqONCDmEK|*y|z!zXt9h6=#u8bR?iX734)v{&Vijw)(g_7@(l`Z z(~{G%=NcWl)Umx0gzVp*6!9vI_D0Um4T|dr*N%p?(nR#iUZVIUO;pT-$fOCb}iK)Cn#bzfNTj ztiYtYgd^|jqE;>Q({{w8vb~%MjCy=%6H7`hT+xPtOolD#BCbs=-IgFF&9j6oPer{G zu@~R(xB!2t0RT5Rp7A}jQtJ+t?IcP|I2Ykz+CsEr#K~1NbM@6^lPMnJdzKxV4VV9% zOf7lx8V9KpxAu~^6sT0NwdPUe-TD)o*37x4oaEm1Rk1$qh*-5xxu~gfSG=pYpsSf; zPwV5kwTfyKmM~{ai1w1uFB!$F?A5E3Uq7_!M%=}x#tmshXQ*CzDMu(so9tfINm%Vh z8po@c0wp_^=~o`ov?TXVq|Lj#i?;+X1}2x??V9i3|6=tWH2)m^%l$>wQJk`=(n+$> zb(hQ2ju?#_*dg&u0<@YfC^MxwYp&u(7kd}2<4wANf+TKSm7HgCIvy{`m5(1k8dH6z z(#V`70n(XBs4f~hnHMp!^e)`v*vl`IFxpk4W&B1P;fEN^2usB+lr=){L|TZFmtt|s zv6gTOYVtwcAA*s*8`Po_F7ps?+>63%%euU?kiK}AQUw)0U#SQkT)m@rnUyTKsMsT?=UTKIx{1FCp#WaCu4G|x$ag?Jap`kfknNUMo^GmX&mM zdHa@dFePfFtRse$@+@c)9DWZ%n~{bJmrW-qBrJ}|{JFCrO<__(;jvaRZ)64&fJA>) zIevcR7o#AiZX=dN%zoEBmudtI4568N2}(Rk4#3pF+xxrx(Enj<7#kt$+1ViO2V0mE zH!@+{Ykt@s#syh}VezG|gNZW)*{0*hTIw?LlzPd>XVIihcNUcuLk@XOgCW}{9j2a? zcyhbwwh`_w{l*{0irjnokEipFu^BA!hkgypJs@|AP?VWD zCUa{Y4o2k2kgO`l9)hDSjuqoe;P8cpKLqeaTHAGY4JI7R6YxVqWii!mAFtLi8{V8m zNU!X8$!Dj9yASlvXjqH$;Ef3X>sOGLRwteVXXapl_OuRVL~hrqC4UDS0mV^30Tpox zeO-g}G3x!(>Fn7!1T?q2CA4GVv>mPW!xD&$Z&Rl_~ zm$dOBQYX0g;5fB+dKXdRP0V?U;Zs&oV(DX@o^~e{sL&-H8cnRFJ`&Z? z9%h7RbhJkSWir4v`)aE5{|tka1wusKSe3!b|`vYK&2!nbYEUSl*${Q(+;PZE>7*Mu}gr;3*dEd#Xvs*DaHX zZD6HK+V5)WH{R+kWJ;tiAtN5~P|qjJPye}}%QkKKwTULmB0|ENC0**D9Lr~#+gw-j z?W}kaDjdn<%^aA4Ymzbr>J8z;Z)8d{AD>7O_iA!5u>^L-cPh1@!8?i=)ME7o2>U1D zVV=zmCgzmr2u%mG(=*ueV#>(0IPl_LjUK%UKP#y*bZ5}FWRINrYwF1ew3i8NB`qT) znAX<^JYP7M)OOb5Q&f2JM7dH#dbbJ`beHGXtBZ(v%X*hR{4v2`IlI!3MpDC;qFaz zC#O<-x2*J8B-Y?M^t~^Q5jKKa95_~>fy6S4sF}#JeOZ7G6E76M^ED*dCBqm>?D=Uf zZrt4Ca}>vN{Nx@mwl)us!7y^IiY?5@Ad37ly((TXzU5TvPW)dZG$}HnI+JjBrBYpO z6saZ$gsG1f40q2e%aQ4I5wGY8Vr6=$ zo8K>FLu&WoJ0P>>WL-mvEy}N>^L3LRNELqw<_CK)n*68U%7U_mn)w$w@(RLe@@KJj zZ;B~ZbI1b}(TN;W_KI#%2np>VDHCUcL_cbWdWp;6$_mL>yEgI_5@b6x1-fq1Bndir z$6E$gdD(sc8U}TY57k1OE+t}IB?$=4!xQ*Up#m7lzX&3l`uk?Ea-gOTW%{)NWg{qg z>vmkOs)=J8YoS|5nbVhCWH{#FN{3**z;eODw4CtKb1b0M0?=}iVHNZGdNuaS(8oO; zoP`u}Z(~|c+@+D8aYAU7W3XsH+U=uByiAGbjsT^g+*WZlCch8Q_n}dk+vd_R3(-|1=KYM}i`j_0=W!v{C#DOUz!#!MLOGF?S{8r)VwfRPQwQ6 zP=Bb-Hiv!xBdvgJ%#U(37r{lcgg_kO9d8o`nRFTgF{&ffiG1xNy0ny~i2~(TK(OBq zi8G4)AB$lw?q{CUpix4S4H)*q`p>0tU5x+H*@)t+X!%Awem~rI=4zP#=S6-EYyNnD zN{8H7XR*yydc{P@^Mge1T?`p)dDDFUgEHO|L1h}$hl@*NiALR^tQkQ$g#<@aboh?Op&MZwcinIluG)n{CXAj znIhAr6yG&&^mBa)I2v44YEHu5snp>oPXgXX9%9)){8a_`L-W zP*i#c7XgR@Jw7czI1&3mgqI}Vif);(=~_6*e}25RCH{oGcl4s{#FeZ}mMdBRp`fU7 z@s&l`SRbOQQcM6Q@l_!%819kFB2MlNOL2T&G#Z0lOI{pZ?ai6A4g-AD=ml&2BU#xD z*4h*YHwbAI?{pqFLiND$UV0JtSCUSjjp)5Tgb(&!X%>;vcy@nn3AP&Iej|AbIr(9 zyBpf_?i1&8knMKJM^M1xZ?jF*(v~HITqK-bztY41M*TnA~D(5HrkE` zX20&=-|U#AsonZI3-7B(*3mr zjc}#q7A1kO?q(53Auzx^y^EBwWJ_!k$%ey4P645vSFbH{yaY1gW>NcE2C_TINLGKc ze6p+nW6-;b7vf|+@!n=>s&G~lWO?a&J|Tng&qKb(?Fm&z6X~>hXR9a&>YT$FLeO{BK&1OJZMtRtHxFh z9(l?r;}Y&PYp!}!Gsm!}i<5gzJM`tzlc!9$+ueK3Aj}&XLwnPn+AT})*Py}_QCz7K zk6vfC>?i8>GH$=r-6!;N{Suk4LSW^Z;8p9BqxuX8d;zrM2vzIR)ZJTSB0z6a@U)649?5r*==y#J}b z!(2pYyEyY#Ehr;<2W1(e0!A;W>9=^wZ*lF^A~7|FwRjDV>{1(0bC^-pq(^>JeF+nW zq-v<~$fyI&60#(@aMe&OQ(3gA(#&Lh#e(hy$;Fcv7J)y>U5j_i)0Z=e{>td!uFbW3 zmBIq%Y*>7Ak<85LoF+(n4_^-0_k#yRP3ZYOv$^+%&O3TJx0Ri$_lo23uHR6p>Ksb% zv`4a{F%8Z+GGu@Wd>%hWwiB^atFqC|E0?8PXCcjlhutb?99xrcap+4vJe;0l+*r?> zAp??0>I%|XLOIiM>mVY8?BC6EJ*NP;JPlqZ;~?TOu2jM>7Dys63g6@pQpi76E|NTs ztCTqfhO$tx`t7Fe8n^V)MO+nPp3*r3?(VC9esEFL*5nL?3j|n zgSldGrHz%ImxQN#V~4)J5{jTYz8^TYUA;GI^D*-<=Tuu%vMv$GVh>f`Ne&^ka9XiT z?&?nYUM6he?mt`8UTQF*M;0YyxUR?83t};loKg&u`u3Nod|T)HeCkb&XS}dJQ&4GF zWd$FBdm~NKF7A;VNq9La2AIE!s2qhk{FpkPpiA;T8F*d&DzH?_Nl=BX6?j4&UfvIv zPsJ(sU3CN&xaSG{sR8dy5S7>L!zd%#V0}Rxx&RR5gY(DwErv8Rp?RE-n2wlYpyyc+*K|taCKu z_xt5jxAL{W%($?1ewm=u#B>FdHA&UnICmAvT>86ZPs-JQRDd~>HkWsiCR^XzNRB`0 zDcCR+akwz9&@V9w0rl98NjWJbeQ{MUw#tn3Z)BJ$gHZ?jkj%>z-Q>RdDUdj}*Z;*C zqrm0IicmitsuaXU{FBH-BQNq~82W8xN)X~ppqnG?CRjBzNE9(727z74Nrf^@Iubs# z)z|Xhd`dW4|BHso8#g0AdF{+#-D&MMFJDw%4)V1z+aK=hhGVRsZ9_CXLVxADbfV*Q z|4<0Ch(X{+>WY5^4SQp-K_tvb_& zVe_FbIv=}|WAqcg0=AceT}-U9B07zEE_pbA$yVLNEydo8CVrQ0PIe5-5HJJ zaVn(uE*doWli3rN3N5>D$7y?743$Hd(tVz0Ti{ys`s>@5!@?R|Y%dq^B0O=V(~o;E z-Lta{M$n0)(vS#+FK_oqZyR8{8~W(EfFBA961(jB2`|e*7hZ8Hf{~)ZpYxf4ZapMT zB$~vbRy%Pa2sOdrq<1#z3plTISkN+=O&<1W68?*V>^5ZYOAMKBN@@YW$sxp|D>l` z#4`&yG4>6V|WU#Eu>zy6A6u4Q`P#v0`w?MFH$Z(5PjJ5=byd71fnlOs#IM(y(HgD!i3A> z%(NPeymj=qaB}7c57=8&tJ1>=T}ZU8r3a01E_m<@$aJMsk9Bw}xDzCB7%%gYOW3$D z5!|!{NlEy}3sbpS7v}3kY9{7&iyTX2f@f2sDINm*vut9IZJa0o#|87?JWZsqfwz#t z`-&n_`5J5AQZ|??Rg{yCd70!V(y+QZxlk71O%UyYZOmL-zqdqeSy;1t1ZtSS zEk*%emWNnm2M=pHToa8uFbo>FQ^XMVbNb8|nW1FEY&<^BnSFRu{F)epD(X z>lg1eu18sxx?3`>^7p7wpSJ>O+Mc3GnDy!VHV0&@Zl{nv+It})lGkt z&(+C%AAI*9^`W3zS&+fEx8pjPQ>W3#)~)Gk%*?IE3qZb;(jh60Cm4^OoQ^#5_5-I` zj6UeuQX;o8jSh1zLjgb?$Lqf@%KXe!)flNXAx*N_vT=4U>HP3ZQ6)*Yzh2}0+E5_O zn=DOX@0HVCK;AaeE%7!0;$2%lYf~T9Zs10}To550d3K92EdR&Mw$!xQxhX4OGB zsINoB2*ksk`9olfG5t}~JDSFiyM)CO>t2wRp2F_;k*9)#s$p4uT|)zQpe-tk1jy?& zT7lG7kBd8#rq-xUvwkJPhG#9?GMLLAj=a{$OY)yI#bF$bbKFG~*Df@tKnb+^f>loy z>t=CS72JVW5$ZP`XNQs_1bzC@s?hh8y9@;T$$*SD;GLpb)eVrM!NToN7=HrHb88({w#^4}@pr>U2LrOtuIr7K1zBN{RFi!5W`;?|)NTxtj!P6{z+;WvSet87tUr#A=Nr^BfPjx2%F$+rcg&&nDh z>~B+1rupNT{Ryk7bIe_w#dZDiBJoYg(q!kb#*&`8IJ2MOFqpwYlNA@~i3ljUnv8p- zeeGo~e+ljqhk`r_D=Scbsc%74uQqsx>y4@Cvm{1XjZP%E;!`Ek8jNeyYJ!G40xRHD zpivbo0|K#d<==G!Th)#E&?tcv63b(eM;MIbgUXeu=s~~ypiGWAKjA35em*OXQ25J% zqoq0&Daeo7H%){Try+PGCL@H2E8ad^q>x)@^pt)W24}e}uJB_PaRdq7+E=c$hJM|j zlV@7s`3W~Ka2N>$3X-`maTg32j6A}gkv~#mi}6dK3xEKj&pPK5I{%pEWf`__>}Z&Z z`UJt$bSvf8S&`vwX6`LzFz~X!E6agf507{nrUg&T-$^YyC*1NQOGy0|NwH1k;>nu1 z$U)e2;3j4>OzJ}VHka^D{4Ylv<;Rw^8jOd;Gf2m6=y3bq4^>T6bYTz_Xdbyqj{-_a zos%mL0wFT&clHK5hfaE}JOSvlxdy|_rs+y*GMEv(3W96E-Vy?9u1cM9!x^d#4KA>i zY1x>kzlB-cFhWMP@@2=I@40PFop9t5e`>m6@Iih)rx1uguoX3EB7;3h=@ z5}J`Mdlfa0&47>ki|qsp@Qy7#uDtcY0gyp8=I3-Tw;&tUJr|@**kn*ao~mml)=l8| z(80kG7k4vE>f$jC^uwYq=xL%^vn$~NtsKhMvh+FJ6uuhbI=p zb7ZSTR8Jv&qi=9#tO5|sLpe3b<7;pNiZV@hd8aWpPa6c59>6MZPM;UZQ}~Gs(^feJ zh-O%2D5zlZMvIM^zZ*Web^=K5{E>Vu{UjZ2mF4)W)?U+euBD%px1!v}i1kBy5%X=z z(Ka8S)A=r_qXpP3$q2UsPyo;BC)aDb<5PnHdRn@Hq}0WP%={|fL$^K+Y{wn+(yGGd zQ=&<~UqS@7u2MTxheZ1&c}LRf4g81*rWcs}pkOD+ZL&XvaOz2`+sCM2C+8eFn9 zrFXk`HucC@zqpH?9gMu$mL$|^JhskbZ0Zf9nQ+k;Yx{_KiR5-+oNXFYH;Aa(kqwAT z+b6%t+OfgaMYt3Lt5@MK8C4!~4G2|+n+1e%(H{O9#`_Ve35GyYWx_t0bH#ij2&Izc z7^k>rYrz&+TwX77rIrqF=D~(5HT;aGFo60m;HlGwxHCRRVBklo(wU)!L&3xl%#aR2 zqHjEu)?W+JJ>~Q9(SH3OU-!f+MLyLChOlgrSi~J1d2C9SItcXi&F1x(lS(B5+nvy^ z{Ewom4vVr0;xq_S(jeX4A$@drcZYOIBO%@0a5RYY(JkF^Al(hpAg$l~{rNuk-0aNm z?C#Y5#w>?*O6Yy)#IaT9IhNfW4!A(3@^$+gs{9Ks@&4N^1&)&p%#GUa^WBsWhc&JFx*=|y7EIHb)$ za4adY(DS$g8xEpd50rnqitUqMl?b4oddWA4^5e%17{!d63LT!2 zkjpk_Nb0r!_{W_vvQMy#xTJ}^x&Esf1Q;}!RB$e34@w(*1*0_^s}%yX34-x7-OBYF zv6rI^X3%0Fdz)Bl0QwgT)1jhcR31kn5gS{Vjze}u?4AvY9Rg9h6taiA)7lYuQG(|K zg3=>_*joGzHO!b~bp$vhCK4N_xfcd;zR|oAOu%5{nYjNk*zo(4ma|EttwvJ-H0-8; zF}5DTx&01gKRg=_7JBY7(&Fx%A~Ktr5p0BGtA{x!@Xgeh$|UEr+e|Kbdg|e4g#aKC zFR34?9>~H+MF`~Xu1^>OR$LA{BQ=@nzxRkf2$DIsAvOmDC zOsd6227?UPH3-BmGmDq8c;r-L7sS3{7D;?L!njBifhN-`n89|0{%#3$O%;CsWWw;; zme2Jr$Zq*)kE*8dn=k?%fcSxI=arB9E3*I4R;Y0iV1DL*YyxLukvP>NaSeCbS)Siv zsHe>)lgqb8vMp(SaGvPUL_O@EZOEuL;vspV<7DaLhA&-e^>_=X*07^Ia^?)eM~yx9 zYW3-ec2Tct%OxL-S9QnXz~=LH&)$33&RvX2D&==r0CImrHVVbNbXEk?3x{tpNR>(C zWz}40SljgM`Y`h}#HAoR7L*QbZ5DBtKN%AJ-e6D;hcFI?!Qw>uys7SpK8z=6^-rA^ zEUs?oQTRB(mUa=5^C1j+&7a1qG=~3G+?n7+lb9#F_2_|ApAL{Lk$YNr9S(7Z!u8YA z&nxl7&5`n5q#EHl_qPl9R-H2car1lUm~v{~tW`UW`E zbpUVq(^sbQYW442<^RO=I?nWMTAeHif@>9ZZ@*(in@?J!Q9d1K21?E@BZ4c2m=N?} z?h@L_F#f1w-@Ts3yEegCt&V*;rRwdhBSu9F{-gHz`E4On^deC0Ddf8?SYmT#%D_mu z_KoYcdPU;dxA39zm*`GSAeyJ;7SwObMGaBw59=&zU}ups9kqNlUDZ;j+k9Yx!sd{%s8-UvcimY97OW#_>M zKUBqh66dcY8?WPrIk8DbTBgtv9>Sl;1GYH}%yZJuD0dd;adXZkrfY1H(!WtwOT4P* z{Ru1t2rbg3M1WtS`XtOy0hstHOajaJ*torTX^aQVM8+S=qVLK;m0)WxSMc_j>`rrn zqf=MM5|ArM9f1#r^&DEJfMbaKIXp){7XKa`JE8;XZ^afr_$p~`C^d^bW-Rz<8p8w* zzDU_LGn9I^ZA4&d5g&S@+w{L7?$7}s>OuzT#ZS)FIO~XDN4ddfbUf>QPLz1uGvP6k zM<>4!OREaa*h=lwh<1@dQ+r2KU&j_-aORwa2Ju66SOJPyU)8rvLWpL(Wv}rK_-V&+W z8pXr#Tl&K|W&?u5ii8>jJEztJGxyXBN2^6Tt$be44QmQ`$c7uff}f1xohdP3W%mP} zOP<%SS|jQC30H?7CcZfY4!Uh)C?$7$d`fTelzm2|JMC2Q#s#-;NW3q}UBroeJO&9G^^28D^k8T7b-)V# zEd@h-XhBAB216&=AA}&DXnQILKsgbUlxmT}QJjK;buvSTk&ZxNd7)g$nt=bZL${*6 zPIn~{7QmhMDJv!@NZ=RQx3CP^Q8I*k7I7G!4mj8}$*|uv(=4B()zlGrM(+-$P{eOR z*UFC;(8jZv?m4U4Rv`2qZS5t*MOfNL%U zmGl3`QAQ%~fRL{TB8|`T*ZkCGN=$>eBGJJu67Pg<->Zk%dWUO@Hd|TX+flxn!gmy= zJH*sRd5(>|(}yI06#`E)vW*m96-)w|pTM8L_j7W&Ui}h#XDSIkv2oHhY<@GYJGZ~4 zwsWKmWH+8_iMneb>>*L$Hk8XO>wYq#whk2Cnl7FY*y1}-<$7@YR6*b#0AI!;MM8zN zx)r&OsjY#a4wP5(77|8W;3qp%be^lhKft|j4EHSUO#t}I2ad^7*+JOaP*O+Afch8l)ZEsz-k2~0D(2zw(sm~5rv)8DKi5V& z4C%EXsr)wYxkW;}VPvp$0+T=Zdyy)zE8=CrEy4qDmqTuM`W)@QPuGR{YCD?!9}IH& z6;J!TfeiVKLi18&LH1D(1CK00vT3UI99W;D*p@NclpFFn?f+*mNE z<#NWs;4=6iIZGAoVlb>HiNUXS&=qss^QP=0myr|&4^qIX?F>X7Zphj*uwB3a)<0^t zSoPl@0x0P7afx@IW*=}%PYNYEE%6zkDB-4s)a}Sh^tpRc7v&lUzCDN1KB!E>v%;A_ zPp-u!shg#h=vQ+Z8dym4l7ROdl3Ni-RWUD|hBRa2y=Z|~;|RY`=|;s^e}_Kb zOjSc1ifZ2}cR~rhoD=5E7?L#Wel0qc)Elj9PgebAv5a=4UHp!CQy-cCFA5$8c`vDA z7>`4iR4**Ou`2>osaPz;9fhfMWr6owCOB))-A@Egy_PrTmnSp!UE!yycXeY!f@O(q?IT4W&=$pUtc zNC2!%%NEtxNAD!()HXUjdW|E%@lak6LeLMBeC}uP5dz2fRHaq2=i}f*B3CDP~1+?xPX3Qah^$U*j} zR{MX+D|RAF2xu;NaQ|R1R7MWNfzP|+hohcJKW_)~*azRrgz@-au~@Dkw*$b^qmXB1 zyCfTE7RW9MN&53%{;jEGl6IT2q6LsP88S8NhPd&N!&#_3D1f9Q{<@J(P|u zXMu|r+KGS!h?^#h?%r&$<#WP3DO7&sKUo0vP?qnV_L)BJ^7UX7XWaVm_P{gdt1wT- z-k#p-BJxM!uEo=Qe8l+(*4zpvA$2X;Lbm>}k31%V4O=N{2iCvr?`KO9zs02J<3~fq zFXxW}tNTB#UxK@Tk|f#RW5J<_hj{h}U+m3NBt{|upw?XX+U#`r<%?c}KQ(x3$W|M& zVj}GCk!JHKEt$${qc=KNscpb&9+Bk{O^m}{CM?}K z_2egwi-sdHTA4`r{0g3%yP+e;P133pLh!aFe&Xl>(YT<0l#>iY!aJX(xDP^@Vi6)I z-mgrYfNahIV4}FABw&yU4D!B4Pv0f;qIZhVhcd-7zrd{8PhuHEDJ8z#4+ZiRUa*}Y zgmdhlO2r%5G7Q6)`EsX>zmbyvpqMX644B@;G3tlFJp~c0Uv0C{fdpg8X5NF$`J?XA z>d%pVu!xt)SYJ;SE{RX}Ve{VM-8iUKxe!|`fTaCxCH4-pB9@AFyec)AYY2;X&+MhC z@ggaw1l}V;UO&9S{Zt>u%E}~xQzgkw1%mjgk4(U8Tpquxk9Ie(vu)iG6mJ57eH?)- z@*Rn$hbYe>ZMs{()9L01K?W;wN8e7am8j$2g$?(jD)6Ov(;r7GQ5PpEh=u0nD?OA) zE~8T&WA5Jmwt9B!NCT8c(E>f~69waY#G4>HpZN-JaFt}8{d)}e1M{nsiGV`=2h)eH?9pm)c7r)Cfv7cK&Nd5y?DR$s1(E;xj~_DI>(sA z20kk7w=tf&?chzLj`6Rmz#tB6k1-{!$=k7;rCHP|e`IqtVYtHY(Nj_#!=5X`mU4^5N+WZg%0tK|Tw&ih zowQv$34se{lY>W&K*LV1FfjMAB20&{uz^zZa*8m5DqpfGvhpi&JVux!r$VN?$j>_Y zxLpamq>f|zO_bhyugsMz(Sl*l-d^yI>UM-DQ^hZ;w|CPFCjDgnm3_99CaIC$Z|07> z28ZW=A7oZV+CZgWqx_S<4Xb3Rl-(P7&0^1CraOJ05L49Yzyp}knr_{5A;$qkXYI<-G{*4Lo-ugvo z%?7QSItIVodMu3)OX%=YJ%Vvwv?WgOH4tc6FfZ&muj-Fvpqatm6jPTw`WOvmkGn~C^=QsdluN${FQu%J^AXvPkykKEU-C?DB+~oCypk&uh?i>Cy08X zha~8E`ZFKEh#x!Rs3Dia-8BBHrN%_;JQ=}Cz1T=QF!v7tYWmcM+sI#%gOd%CZ8M;0 z1jzc`DZ9_Y%eI1|XYDrgLlY%GXh`U{WU>S;ig*s+k5tXm$e*O5?(h)#-;&snN&?tX zOiAl^YQB>khCV?#z-9ZXec|1qN%Fg8ZcmN?>37^`RibRzh4X0?@lKJ?}lM%=Z z_Z&yUAsfQ_iJga|B4>#Ab7-yiTS(!o_&n=np?Hy&i-(Ns1V_wos*ryMV9!yXIdKfx z??7SeW{wN}$jX9m9IfAZ@JkL%T0(ocurc_^AfGeC&Cn8q3&t!K3{w)<(z7-A$UOC~ zn()BP?Py~mSUm3~he%mujPYLul{nwE33|LY!L8&Dl*na|w)U4XV?JgDVO|`=@cOQx zx<3{*x`DrCda3=u#Rwp9p0s8bPkmhm-b#~`$mY|^^!|tps{#Mj_yudh>xkHce){k; z_OhN(B)MwhUO_rt$?(^jc@M85khEHt)Ch-WZf zx=nZ#vRJs>?>e{(!7juIZ!}FIbz4l!sI!U^S-U2cD1GSZg)4r`0~U9waf`~g9ECM7 zy!?&VS{?BD*|>n;k$Q40vC=6L5MR-q90r>CN$a1O2M zkuIIfNteYB2{u4#woJqkkvDUfmm%w{L`P9z{MS(9B< z-ZHaHN*kHuVq9=f@aK(<83!&G>N-1|aZg05P%-d<{o1QU?qACH z?Y^cfN?5=Q4oYHvP0)fzo)36eZ6=!7QN;X0;*q}8r{3{_U(yvhV_q8bMt z2FtGQ-`lnN7uKznLuO0;*H5qy9&k1kuy~i^LpqguaCl4o=;R)=k*|#bK?8r&fr5#@ zG@)M}9)9*aEx-=~+C1x<4*z4r_58ywHz z43#-1hhvqRzRm}OZbd6^Sk;PxpU<}Y9D&KKQtz$N-!dx*fy#Wt$65p zXXDH#?$ngiH}=baflFU&9yV#S3*PR3cNf0>KJteaU0XX_2~jJB8`)ln9ewhsaPu#h zH;Gu{-D>i4>9O_7A=KbYM{$ZF@mjK8DAx<&Eh%20)nCncB&5kPDsjeXMlCl|-sUyn z2}-*6?Pl3J@Cz!k^QV?v|qc^!#*@ZS2cF#rNqceX3-sBNMA6; z^=Ih}*W1dzfa4PopTlg z=L|2K^4QQ5U*2Ux-;<4@u*)xNb#Ctw(`7P34h7Z04_)-s%y^k|2aUosG{(a|wIq}v zE$Dh?L|YKZmVf;u$|u6x`#kUjg-$fRp4@jFA$e8Jm@@tK81^gt1dv>{Ah!XJlMog) z=*BC0B8W{E7YNkK93k)~km#0-)FoSTBx3l#9^4B)hw;!}>!@p!ef8~Dar7dZykxZ0 ze_ti6!U9dBJ`fU_a|`p+*(v;J<|V#>U$L;|cH~2^+z$FT3)-y2xFKYlQ+ zK}5brqr6%5g;7H?ceq?rswlG5cL=>~Nb-p5XAqtKKxvmDJzJHBeO8xdMaZgTF5!-Z zj1~eY_>Xp8lbyNX6b%8_Son$Z#4o>aI;V@w2UMd^rkhnIObV&#=cmnSSilr=jx}Ms z+%(va7+-U8@G`m%W07W7;n+9`&l|5LMW$r3g)`*N?arV@++p$-Gmhy5dnT zwiHT!=WH3p$8PowJHjrFQ@k|&O1nND19PslA^jIRF8N3_HBW;leY~xG?A95wFRU^Z z012>j(Md0g6iye8${;_#tFX#*@oCf(NYR{ zpNKgw;N~RpXE)BB-<_wUfA5d~qQBUUoyFgYxGOJ$yBsDYJ7Jc+#xxj}4TCGWWsT0Y{?`(HOJg|qatL+aP|9kMB$a&8QE zid z&pssLUrv~4bk4<^-s}#?SJHw34S)AMAE^a#nZ?Y$$)uPUyTB($UyC}I zUSo?%S!}^yH&F7nzpt||8+y@RI9!A)U6|;i*R?z*oV z_yAhHCx962y2J5D%}7Keb()LrMAzQk_^h42ur@kl0u7wT^qIco)_IQ)cg_axLbSO2h=AsicpFaz38MM1 z*Q~5V)P~(O1^vz1)Yzyue|@)l*D$m(*lQ0Tkb)5jR%-Imsiu0)jVfs!6EIOuAG02u zDmKc%TB@if0>i2^XJY3L!Te>#(JD6m9&d<0F7P+!rpU#FE^|kwTOkAMvced(A#V9c zg^9U{AD*;YDc{h03hbmDD?V`nZ!rU=h| zRyVh=unNqg>oX>q?yRaIo>&n-$ImDun{CCD&;Oc>hDUZS^FO;2)ympmpT(_@RNHIj z2}wjg%!B;+rKdQQr!5I`jSJNs<(oN+C6*d(+5iw$t^iZvDJy=`0>xO}d5v19=E&xr zYq^?24@2ZApzBaxVB*LK%)&m`I^ZIT>r^41I1*p1c^FD~5*AaFV-Hqn-Y&AXy}v|Z z-#;zaN;QgjkWM@N*p9+qIw87$+pAlX8?rQH==mri*Rp%@)1du5J37ytg&&zy4DUeX z)c#DEQ`}W}0OoA`=i}a}ibW6e-S6Hfqt3)_oV*H=Gk!>dZY4oU*gX`P=6c^YD*1B< zAdEUavYO5x2ARXW+=+TZIhFs^lj!$JFZ@T^E-~|B!Zi?As&}goDS4nS!71tZG@6a zb4ewta&`Ah4#Al8U}3Y9r`7~}m3^Mf;3{DeX>nBst+*R(0&#LhQEyI0mo`DgUMY4v zO7CLvjSi{l#BUio26!p&+%9cdb3FL2NV?W>X&>$CvMRrS?&a|gz~Wu@1kt04Czy=|8Odi)MTRyDsCPH zMB~;}RxFT#XJyKvkxH%mXx?KRFBLthl9NYIVBVXv&?)HlMT^mMLlB#cj0)#0)Vh4M4{+S#^-WDk?9e!Wf-p{cFP6lkmJEK>iZhc>YMB=_ z_@SHe*>JKSg6)a4*ovi0Okz(WaDvr=`R~gvrLK!TV{;Ox)SCDSCC!GYhm#_PdHRdf zrzzep@eg&l&rO>Rep+tLEnV{Td{!SILyl$$M6L3)%5K9iwH+tpbgS>9#&T*Mq$OU$ zM>?E-akfJqy+pr%baLAJq*A2pHV0beN&C1X|D8)bt*12V)`oP0iOiN#S?3Ff#Gdw( zH))u4+~|}b<%F^QAMXO4&-BXm(tnLdekrM$MEsjaN|S6&K|GJF>zTl_<3Agmo>VDk zsP)O@dpS{K85mbz&D)ji*(-Zo{$tljLe31BlLXTD^+&uNk$gj_TbXxM*d8uh!=@u6 z2EgyC_T!n^$V9$bxi-)h&xpn~;&jNq`))D#H{CP_^ijmgjj_dCid9a?$;*tNX(kRu zc@?)h@?_R086*A+t&?XJfyu@{r&9Hq_(680!ip(oe$GZnK56Du(ZB?uTlhACooUUL zDi1oes6KLWF~ifN%PJ=+`f0qBv^PFc8I-#5*sf#HRrn92eh=$3U2Ww-o!L&+>=!!Y zpVXiY^{SDB{M%eRaqcP&C}GpBRfmm1YrvuQw4-Q-;>S)JzC;=k22VLgSlaT4JnEFh)4{BwKl!?&z1mtc0w8utq9b zyKJP-D9SOT9G%PSDv=hsx?^6=$zSIfdx|V`-O;ngP@GICJENB%um(~;66hMfz$+uP zG!$T5BOWZqh+$42;lrCspTh~pTNVd7Ww&w}0c`%xkJ>Q&tRqv;CkGj}fj+fD?dOZsRTbIjFQy=4&byyjmDI1< z@?XrQ>V{YOaHSer(6cvmv8%v|I;&f|mdBN2&H)>EvkWQ`gyv0oadp-fjge8h(9&yT zz9z*lICT!@yIBltR+zQk$S>^YyfRjaAvM{2EAhQ{&5g*0TwWJ0yVf;`TjP_q!E(RG z$Sf4gCBEQ%ohzo4d1O&8`8LJFE*xoSulXY|bE;7mvIEUlUs3L=UYxfGq-Dj!>MqRC zOW-YuGcyaT%UyYJ4sfK(`8`bH2V8=U$h}Hp44n;%PdFe*<+|2ah1M~$4!#Z|$8y@v z=nbZ0&Rseq>`aNc*Qu`F>LOf>2}zsxwNdGO{}NV_7sO{6$CIKzLB({ai-swGUZo=1Y=joj;ei z5H;XET6>6&esOPI8mm9u59vCw5&D#LZe{+q0%4ebrI=uU6Iq*sH<6vtlJ!d4}c0cF&7-9=U6I&$|*YdrOS_ z9SI(XN3Vi*_|&11L~P7vRosuCRP;w1XAZ9J$Kt7%%=_3_U*`rTE zft<=MQ0&-x;25?%;hP3ax_v@jSjIeNg+!5;wQ`HEAN@UBx%(2JSXV6lYU?Ki|B6dW zOyG~(w|wyLsP6P?rc9YyKDQVtTm6eVkNH!jz{b!jDPnYk@Be3tRpzNyxcbHbrC_1v z&c^PC9}{u&#g(JGG(-0tKik7rF;)lTv!~hx@Cit^=87TFGd3TXLJwR60yO=j|4;=8 zLL*usNPnO^nJ2UAgnkSza2WBq^@4|cqanM4grmS3XQ~^#3bG&ZpH$+wo7!kG;uS2K zSbWPpW~mfz{`=WPHgZ^&Xq$I^AUNyvPt(QmpdLT)ClOa;)l187KHT}hO_&~n_`qM| zh&-UD9%oktAc-(c zJ9Wbczig=P7BwjBPab^+r#SMEs-<+2q0w25EiUgkiqwI-@II;^#G3#5J<_q7BOYMy zh(?3>*G3(9qI-@4*8*M^2A9nMDd?OOq-(8??0xVk0s;wS zQ+{nuOTcjS?rhGy1(c3ayOTd+*R+;~&f!^4{W6`F+yZ}%OtpSPS6}Fojhs5Q-SGci zY&UtYQzE*&Cn~^%r_l*S8(>){QQ{>b2Ve4+lkMF}dxJ`vD>1#TzHmu!-Y1Rob7dyX zn^%>y$GJT7_MXgimz#=pRnas^CPKA_dew(JTn>rOCf$O3AVf)PUIC0acZbW;*Vo?0 zcKd6B_z1>e^t@|g_`&bOM@?n5sVh2y?wtwR);&|!rq&jYrVGPewWNm@86F&KwYLL* ztsQhG&3?2O25Rn;sn+K9;u!NVoBBg-bM?wu;awc0@E zg~M?d+qa#TGarK$iKv-Gk0^k!OKqNNWbv!W*8b`9>&6*6MeAA2+-=}AohQeHHy?@1 z@xtUF;i_FDOz(mbCitM*egbay5thFsDlfp~&nn=;phoS9kb^&bBFYZPEQcFRSA<@> z<-8w-qrw)(^dmf>ur>Owm*ESsGfE-2WcnOoPco{dmd&F*uS<0cfax{sM{^SL>IZxC zNdKfL=E0cniiKVMVP8tSH`txM*cj}i!+gYoWc6;Y4XQaufTiP^a8nWzRsCo%V&`?g zWg|CyU6VI}32h91vS&ggRY5j3)`jOZ{h!xGX;j{Oj zV6it}5S_Nw@@JwE%WN*wGhtQy?NC&G350>h;5M-GC!n!M8a7o6)b{gIemY@pCmq@q z?~J0Hl>JA6fE)5s-3d4gAcyukmEE<{TPw}3hErL}UHnS3?rT~YCO75Z!9sag&$6Aq zci6S%(dl*+U|FkefNxeWk%9G5El2}#(7)lLudEZ~tS z<9&W-8|>wJBm)g zoq7y+gBdQ$jQ$r+YFuWwo2bjbvbl!!+fLYCxtC2JEM4szVN8MjEcq%xUNQCw;#1&{ zy51$oK3O&fL~B&Q1A$NP4!<4G%ybMFepPBok)M(=d{qsgW#sUgZcD~nunl~}?6XB}k67pbOqASecQfJS;(?fw_!tUl%q<4vutEBitmndk zu9CND^Y9?yT@FiMyleP3otP83#CaXTCjN*jkcm}y9(2ca1{IDTjk z+&{x04mvuwp^0B_l$4y+*qV;G#6J?y`K|h}lg@?jGbAKvC7zMxZlp8@;xSEiJ2l@R708KNh3vLxDGVK%9j63=+g49^rJ25MMx#dr+VG(XMJFK2Y%3o;Vlg{kHw?s&;yCS$v;6$I*%9eEj zMM5=<+jE``!XaEI=dzl{YvIa0w6Ky$lE?_V2{_?*{6eF;$5;;h&@bxB;RWx}d(J=K z4;!YTUXj)%ry#Mfoz(peIUHQxbpSLo3AkyvLw_=$zyGcC$XfcW-MM6d^ag18(9#lD{(%NHYNIi|9B`cr zYn@UM2l)@63c((4=l_(6h6afu0R_`Kq{S=s{~ojXrCz7KJwN7-fmK&*Ex2EuR;<`1 z4P%H=kC(|{J#1k!g)p~(t`}SaPJ=D#)N7so*P}f04qy_;XMx){nsH#f*)6tkyrmE$ z-Y`A;Q*kX-Bu4m?C}2G?|EsmMCW6nSYCU1V=$uaK{j)F~E!^ypt05HGBxtwG%ldm) zM+LT9nf_uLQYD4P6rpPrT>-(CVPL`-a}p$*LfD`TIzgX1#JEmKxR|=(+RX}aEPUut zICmOXIk=a1D>E3?J|;h?HR3r4k&}S(D5oNO=2h0hwm`N1RcqDJ>wOqpz@H&F3sy0@ zC4^6$66}?k1L0Jm!ZoMIT{-7;h2!h!RPLWTm)qqscg;i#?k>CGW$IwjA2Qi={UODZ zlD@b_z4UOv;pEo!M^p|9$7idin8Zxvs|$Txeq3#x{fUS-I3i~BGN*)i{q4_=GugNn z)=WT~xb%{kd@l1!T%B!BR3^_QM~rkEHTP*YTw}yVJmdhD)K+YYMmZ>g&P~;ZJ6@OY z>cPU)!I^ziSN~aUzR!l{bXg6Q%5A4?J0L9M6Zs%ET49e}Ssd=b9F-E`8#K19BEwOi z%HV7kTrs#r3<@S9YM~c=}S7g1Pb@ zIxY32+ii^hzW`&C)qTbQAk1Al&$2rC%AE(6xxU4bl z!pJ85Su3r>^0$L(9D321CdbBvif7Jyai92PApJ2Jq-yEL$%<#;@clgl9s6COqy2BW zxclO<366G%Ph|m}YARY3&cuPW6eJY39R^y=gU88H4^d*HP_awSWF*j3%=U#RaE+yD zsCX=(K0tU6ctKt7#gs^VQdD&FrLjI>&0ueZ2v{1R#U^b>LZ|B}h zuKtrEVUTlUK`cB+}(+g-OP97K?rCBed(=S1;ik4SgJf5ktH=PJ(AX*>$V zbZVC$nN#JKH&hae@(IoIi^3Rk5EPUR1Yp6rIg#?=X1rt8C3F9QVsEEK!s%T0o`f@D zor|Y(Sn5$7k)n7(AGLWY!Kc|+yx6##k~kANQHfF~qh|<1BUdgla)D8{%cXltn0B7= z#0>ty)qr)2rN^Z}Jrq1sqjISd2dWh(|MU9kVfK)k40!xVVt37F0sfgQfk;WLqCOGr z87}L`r#-jp#MafyDINs`GjAzs`fU?XPB3v-8isg&5b~<+hxp0K&M-*d7a2__lU@%J zR-*o@I|c4%z+q!$FAZr$8-VQ7;k(UNjPRgJ5azM%0<*@$S~NW>t$ zcDqU;`a8|L4TvXYbS3%pUeW$r8xEmR&VdXGzKPJ*gTJ=2!(6oSaUvyz9)S=OcLr|V zcO1xsO+P*kL~efy^l1t0$6g#DcGz=UKGJV8ZRT@(kj1YaV@7_8i z$XhEH2U|WS@ha|7$k&#_7hm-jrBA%lfxdWBOlNOt?q zeHSg8OW$rguaZf1R3fHnj^ig~jHYpNxpq&*UZ%6$xru&MCzta#P^MsM@u^5U5tW47 z4JDt2HAxI|ni3HODw$XBM3~?q;>oDQuBDi{IN8EnS5BuDr3w>48JQR16@v3XeAIFA zHLD<`NI<#tJG1?@C=!aWa&Bvt;h2pWX#xEf)GaKCo0{i~Jp5&87@=M9oDy{Dk*8KZ zjy0Pu6NjA9deoMGt!az12I6!4aW&wlf9tmWIjalTP|$@5u>MZS<*&zXqS||oVfWynu@%hXR6?rudw#W z{7`rtdnYs>-9VC*tl8_Wf@HHb(GJ6CC;e6Pn3AkDzAQCIYEvR>%S8lXcub3|_ z+S{O!`gSJhSeIndm@q%nJNBOoI;#hrzog&Bhsbj8&D(6%YQ8^tY(EtA&mnLlQErbC zXb(^5GN#Ya>WqCbE1#P2bgGsvZIc{vfh5=P^iFMYf*a|2Cv?|KlL^;PEbaG(2bZ-L zjl|TD;P5makoe~h>B{Y1vs;8KEmdv8RvX9}8hqh^0#d1J)3fRF1R zI&9znx4@Ow34BV)P=t8ZP#z6tn=C_#Lt8RA%d&1e8*KH>exL z)|WW{&HzFiZTv4z-6*(_QRX^984_PsvXc5!o5-oamCksHY)SfZt^;{=dN)dUK!Qm4q#Kx zq2yPZ-?BgFj^@o`pS#*b0C(Lm3M6!P8=GktvZPS-dtJl0@34(JEv5;|; zu~V8TYe_2&Ig6RV{Ms<0+I~LpH%L%stvi@1E{f9qC;m^!(*xX6~DGXfdl8D-DYjayxd$7isd2$bo{03!*UmVzD-hqjen1Bmi?g#H9$xGq_g_)o3%NMfNIHVbWpHU6j!Oj)PKCx| zQq@kh$u?=Txe{S_nhd)c59?}n9$lZ(twILp3Xmw5+DVupvcu6!(1vxQE)(w)sGT1? z<*qxdo7$&IDLbVS>AfcwqLpkB@tL#QtAu_8R^lW#!7e!^57nGMi-XH?fZo@2EK&G< z!5ICnbnHgN}#p&T-f81dJ6WYWLSwsLShnr$ivDw z`kroGtxZ-e4IhT5Kk+M{Y}@5j0Jw>IyRv-5A>;gByOC9VLsx`8%Kj82G*{&+ueP7z z;Q`(vgXDUu_7*+!jl=`=*)v^Ed9GeOSOufA!lc2D~kT+fg)muo9Zp&myx{{trLh@CMvmg z6Vd`gO0qpwxXp`P!P;JA6?f$-qpO~S$?a7X2eE`Fxh>kc1oAGQVVfnYMvZgE*GO9zy`wFb14MSKApf|zD$>5 zZU%y#drvi!IH%`lM9OxQuL_rG1bb+HS`hRJX{5htwK~N4Vr9A$vDfI>y6O@xr#=FU zQqbs@3ScUVEP)~rk1EUj#Fp!DFbPb z8*JTS6IXC`dTvjvXaz>w`b5XS{y(G|YY)bPT;h<$r!bue`~Nt)>bR!bHvB3AN=k4&%g z&SN>277sLPDTT-x6R}+kL;YIL*}-6|pU~81nQBP8?PplDCd!Mf5&ObJjE4J2r+V_0 z>x_&N2E@E^1L&0R4%?x9s#B%E?rIrqMbklNb9}Y5wwlH~#r=+>TzyX1Yj)Z0Z^I52 zx94w|Se0(PtbFBnIn^x5%zIH6V)}pr4w*7=d$E;cGThUk7xkz0gX~DM+b$xR<#KE_ z+Vdyl469L_O(<={e#d!gFfTRb(MX}8bpL2Rt%~>!ZkY@Jw^>W@SLs5q)g#qHBH}0} zR9zshW&TfCr^$jNW{8cmc$VGW7+w&<#fBgLsjr1)lMMvg&J4phpVVI}NOngWJJgYm z`m;m(Cf&9;*UgjD^*OU|glOM8B(4v`Ce z9c)-WpiaY|l13xu37q!Ym)ESvJRj%d6Rtu99M@6(tD_;Oi*x2bX{l)gB;bt!BF;=17tI;VIw8hf5FBD$Aepzu8U+(erwOZeL{?p3Bq3s_|M7~fS z3@e-u<)c^j8ce;tnw|lM$)xzx?343UHe#jL;ZALj<(FQ!{Pyl3ZDQv8C3eH1=T$y+ zEZ#D+?J)AacS&wLEZP$d!+-2265RH#?9=OmREtDjBxr6J2LxcdT&Koqq>dMIf&%C1 zPsB3*MNL^8ne^JgusqS2u{ScGo2MCEb2cD9WCM~}49o|f1Ce#W?l_mC<~l2#W262o zGJh`GAlJwUQukDXJ$PB-SfZbt&i@E1v(FzeX9PaywI3O(Wu&${5!WDGx}1`E6)YGi!q-ROdklr?5)Iob)Qu6vv;S- zpKM0z!lUSa${8%J(-fkOf_gzk0rzpfxr?eviu`eYoRG;Pv<){ExTe2_PK%#D)_E~ARNTi4DLk^Mbj5tg z-{s2r_&o4a@>PA@FHLd_#kqoK6DcGjlE0tR^CI)dNxTpg-4zXToE22(ie-Ioc-Du! zpKL@*osM0z;PK10xb4b_JMdyAaHeJ zHJYu5^q%%eUsHxI#K_Q4F6KvakZa5wm+;@=;RtKbk+txOdNQ(Sny(Ax__y^-i~QM+ zJb5?W&Av_DslP0`KQ+Ss94nyJ)M|ifrWSKhyfCFvjG6qwk=@<{oteK!_*(kb{K(nBqtf)x5%OSXAm;z(73cGu%tqUjO5`i~EAuDEJU~#B zIcLHM`uL9RJJoPhJ6B*ein$Zu!#+srxwf6K?wEOoDwr}7-=N+x(Kj~j;{T< zCC?*RH93?;%4nADH0v=^K7QSkEoN~*v5vy7#bkctzdrO{m5TY&RV0bqyK$ttp}!9D zDF3d|YJMg#Q=Szsr(lt}Yg(So?i0v;^E)X?<2&ckm|thr+GICZlm-TMlR7 zr^pn+%|S(cZsV=AV9mbns6azM!99neNt`?S^O!rh`XZBK%GVqntSIvW*kaa_@9un` z$72>&vmUW=h-T4MOk5>2f!rliD(%~Sn(zo^RxtVV*pP9)0(!MUk@f_Kd`?veel3RH z$U1Qo4)$jxxi99-24zs6)6a))+>uk>AoGeFH`Bu8UQkch+K!H_jkMoegyEWFj=7r4 zh0f>@#FU;*^?1k&0PD4vM3RtMoam0m`I)ncB)B2?7CCc-mQRh5E9X3fznaKK-o>UU z6{5bRQ4I!j*}mqa99p+V#_433e9`X-F#L4Cv+L}nhIJaGIOU|GZq$pq*U?++jo^2f zNF0J-P93-)7if7!#ZF~8%nx!A-fsQ?tkAAQ&4WV2rRa&xqps8%Y_rOc$?HVDnim~~ z>9FuzAPg9;F6W~`$H4ZqL&!V+lF zr$dd#p;7$or${f8Bc{he`)1vrP=wFr<^uT9sXm)f#Tx&Dx@yVS<6yz_!0Z_Bp;7nG zY8u(!hRhb^+93Y=VCZhKT5Q|((DGG-bA+!1hK9*a1^r}5lu~4IL{2D}#C5d2bUyQu zQ02+Ru7g@9}o%V`u^L*rv$uq;~U-it61_S-9 zTRd;}w6hfUs%u2#b}o~R66FpaqV;=g1Y)`0+tgw0*89OqY^qALL2`U?lAC@*k`J_ZuxYD%-4zJ-Px+1sH`y; z{R0oVXKCm_r4*2^ExdPCP369lF$D6krvk_P`jPcf!-JPDP@(K}i1hDmrm7t#9&-)$ z@s3*R$l;KnUysv=^T=2GgMwpH{X%|P+1(;i@2;{n2FQM&-@5(QeJqt7@(gSel!y5S zcac^2u9w_hKi9482-IDks?yBv6=~0wq8btQmPio4iuHGC->z#4gbR&sEtCy8dB)Ff zViVO}2UiSBbqpJe=qb8!I0Y}@Jewxq%_#I|+Zrnz7Tr1(Sa8O(a1ny8HGghW zAMw1b%_gO3ACqpoJz>jQ)BBMdOOqc4szDX=5kxhGf_>s z>b8{RGy}6UDhKU!gPckBlXP*~3f4$$x|cOz+-BS6f|)boGo_gq9Aw{oGOyP*bw!p+ zUk=LFaaGpBYyBX4KN5@`awsjO!3$Y|%mrVWKe_FE-*KG{9cl`5l4bpvRS53Vk=DUd6~I zGe51l5h*vg6B351-v_!PT09;S|y$|HPnDTyYf$vYTr-NqG2-oQ$w*@ zIWG}nt!75C_B{W_^w`?@#&l!9C)5jcUbeIL zH{(tIp;n8ns;_|t3FrNDH%9-sD{0P~(>1Vi#%Tqis5AG!fvq%fsVUu>Esv}B@AgsGFuJruewEqU->ffJap}x(rs-b_37V0molol3 zWAeX+1up%hJJqQ;uG1_UFQlfQ5ps{}P&;61imQK2lDXWNzHilU$RSYlm{JrM(%(=- zpM4Zol8e|!yk@@12S7PN#y{?S|2thp7b1z*w@S5hp?dYE{=t?jSGvmKj)7q zADaF>D+EkIlI%xXf3@oG=Ng0N8@=)Cl=p&vwrLKA;#x`F?&6K?nb(c(9zv(!l9fG` zk4l^u8+9MdTkDfi?b3mvPRyH*t=s4G>e0sB#1UKtPQOc0H7}gXhDuRHzObMfMBhiv z2TvUG5z9Am;tpAfdpD8Ge`yvV{99w2#NUU4zWT1$1&IA|TqKbGs=uL0w)to^wZJ>Q zw`N1_4Fnj@Yp>n5CJT8Zg=naoAN688MVb;8|^jtsoP6}`R+4ydmt;WVYf4wu_? zuI=4NtV{~+R-4!UaT%qog_f1%P47%QliJiZPDc7wx%yZi3yJin2hzOYd|Z!(YlDuN zy+pg+4z6$HFy##XthcOC9|wFJpfmFFPzt;ma8*XVjAVH|fqxCA9184fcM{NDrb2U*rigK2RRc=9r?{!`l2hhc5IDy4!4LBeK0B?Q4T9~wTLj@< zyZq5OXWO^a8mL0kp zdmcv;@cxc?{_rAuS^Q#Y?{G?PQBHiX=~mN?1%2gbe;3cvKDARm3G>dotlax{?#s65 zFAC9>{GGN7&KC+jy_qOodYX#rqg-%siJdLGbK3epLK~m+7n^cv8?*IEKf~tfAIr7!+8-{{*vst30?8`KJ(Y_qHBzp%lw&iaxhK-i%{PgU) zBuWcsGE?@A`Pk=IW=W3J)J^=r8jlEcQz*2f52;ExUg5V@)?mVzPScjhqmgiY1gu?krWVnmtS2YXSM zvtA$pFQ$K&CW|CT+s3Ao8Dm&_h$QM+1aOnmYJiElttxXQT<-@7H2CtYG5PJ^1}?W= zl3L8K4h)F@s7IJ)bY3dClirb95ZJRT(?qaF#)PcK$$hO$ zP%3wBql1UHhjL#6_L?flHTB@SUpKLIP1V->j5(k=Zc52=Mo{VL-SZz?Pb;Pv)HW_P`|uWt{XqN1GIYv4BNMLZPnKg?BN{*orJw@ z{;aCYIWPEaP%?SsllI?GgJlx)ypQJ{Kk_P-FMQ8@&+JNvtSyy&;ringj}6$fjoc52 zdp6Uyf4!>M-P?^X*AdJ&4W3s|FvaImMoee&-4_20^>!-*HU-6aMLV#>U!0~aNlYi} zOoEm4;lOQ@J}az}PfpFLeI7)L)g26&@i%ELdCQ|F}fV+l;D zI({H=KR*d7g?_&-I3RBx3g@QWi!P2xZ*43!A8xQ#jyFPBEiq^T8#8X`)&3QgDYvfR zl$L{n<&C7|u6im)94Dvx41bq?sr|&9T2k0cmoGY0Px)+cAeP`+x5P}nZxjpQg>ZQz zs<5|q_)Ce)B!|;IP`rPIf0JWA(b7fnBRBi;kMbFJ?D;gXc#;d_D|uXx&eY{^)uhYa zok5wz6{d+>CkthxU{{YNkSqo9eCfsU~Ee?q54hF=(=m|b@)CBx|scy#t*8DEvtl)rBRUTIT*%G1dG3GC*hnoM7Oi9ZgxB-!>mT$0p@f z4Mn$_Dg=9>c`c)T(=uxK-7k>IAFST8(wV(WcuBAj^LKDsexnn;wuiMbh*%e`|Jkco z2|1%0yj}h(IYQSw48aBjh)m23#Cxuhtr$fx0C9P$VXtBq#lrcgG>7Ks)vjBV;{Da* z`=4>Flq`Nj!9_7?JoL^Gg73R5Im9m+mivyM(XhHcS%2PeOn||~DF1m--u2YlHd zW-8yk6RZXdF|xaNPQOB}cgbln_MYpYM2!q;U@UPS*s;Z1Q?s*HK4_fCPmT)`5qdTO zbd&zHRzB=pC073xPrt-P%$L_fHpPO3a&X|woW!8zLE*l4)yP~yoQHLOt`S7lK*0nH2G|RAU$rO!9E+u79JP}m` z%F&USk#x8KLfe@s*rzloC%@j!Ii*rk{hdC};r_rC$%SVk$Gp`(pYA9=(Y%vS{|s3|*z zWbE&3>z;hM6gJjB^X2f_hQf!uO z?~IB9{>(I7?=R6Z@TO?q%kevn7u%Ds@RA=WpRxQ*l&qd)-!)E2iI1vD)T-i^*pQ;$ zsFX`kB~O9CSuzRV-B=DR%S%v{?x@)(rS^(R=uR-|!!yeu+JN+9M_HFzd3wj~?H=qI zq^LE1I;yJp=<9r8rH+)C$yYFx*}H-kEUqO%nU<)>?aj?5nV>m2@~wdQO=*^%m?!&6XE^*IhQfT-d?k9T?r8Am_0fJ5e`jv z+*r<5K$xa!lPZ+Y&gI2##DVb{`MW7~a964uCBF6YZ6Z%(`dE?(_x<-|>|)RX-dt`H z9UWltLf$+qM~8yN^WU2d^2hL9u0TIOucOL`j-ULnky!f zwxLRPz*fQk8MU z@ikZhE@|njM8oTcJL=2zl{}PeiOEaF_ zELyD%);Nxol!|)lg_acovc~80pt;>sqY(+4w>C>(geqA~zzo_YW-ddE z+|rb<(`K%^pP%8ANEo7gzu8?Q*fYwjI5HrQN1y5~74*F<6~6Sr?^V00zqkxMv>PbJ zCuTBJYG&6wPCvQNPOpC>dsc6U(wE1T=}q4uJ@KT#|!bkxxdTXtHSW#Hx9k z+ZF2ij!K4{echUj4>^yW?fV)QStIYe%&PefQq>T4NlF}}O_0or zr@do!vJt$>UZ8$P;;UVqSx$6cU7Vvg@(3#rglkm+I#jKLS&D;U&yqkq-Jtej?Cm<+ zVQ=sWvG1f#rD)GmZMy+q6?{}TG<%(WMtx*=LH$BeYw%YRk$VGjKwG7|h(XIh0-{A@W+-S_(J zZhE>c2XC@)JF4oRKn{Cok7HWqEv71}DE6BFXUPcVH*k*|0y4@LgsfVQv(^eWS*-fr z(oxwhIn8g0R>kCMYUAaedU1IvCdvuNhumZ_kv_~;TqSO>!+Dv_(Rb3k`}D+BZ!E_R zT04f$>&9xHYaN2!{NXi|u<&-j9>Lkh%%RCvt@ux(rkcLNCjZ@5WAEvz`Y__t^xNFw z-5PG37fH438v_EVbVQnZ?FVWnioYD_YSDSm;{AiY>sFkx;hww|VB{J6Q=hGRqPQXm z3O(X?PDf0SPU4tKS_^>@%#(RGyw|Hp3tV_>7ozzz6KIlfi4n_akRMd5)J7ydh7E=J6%TiHqVpZ$1m z82Pk`HV_8bg|+h!6YBy#UFT%~CQ{FwR5ePnFY`oVd$*+mRgqd;wVoJfCYV&*#F~?| zeQ>0Lm{vOp&D~r1^H0rRV|U7K4Y2!RTn{`Q1nm_pO+OdmQYB&^$INs-Cp(dk@+YUV z3IDQIf-1AsyE2g&pcT2uMxnx|xKya|&jO^AnygDPK4L-4 z@>?1;EQ#G-IK*!GVY)6}erdTZlGIFTCpPIA>yQGmMHzWP+qvV~D*yHv9ECw0l{}d4 zoiDXdT9uGmb?)d2SLn{WpPIJpJyy7^PDmXO6_l%OjJ&APk1kn_UeJ~9)wW#VNt=MD zi>WC^-01Rk4ej(}pp9pH5EQy3;mV)k3vAH4Qx?YdW61wmr$?J~O~r-iP3AEHIoGuf z_JsO9@}-4)MhSE72`z@zB!J)OmTdgHrt+TNQ_ajfV$Sa{@vHVZjhA%K;UHyT+xtRC(Ze& zTmI=o2H6u9O1~`OKnlSqmS)tvV7`|%JL*kgtn!*eQ!4q}u}#H=>J*J1k(xeZbOBcI z#pzV_j_-CjMFQ8##4SxFuXGD>Pw7Kq3Dgr5t`Y;Z50d;isgo2CE&=HTLPHwJ%bjm3 zy5TxsK{SP&m8R^{%G(zHoD()DNiWOIJa_;vSRT-!;}=z zC~-~>X=t9BAUMi%rC`{5`Sgu|>$}lg7gF6EVgKj`{#^O&6Hb2C5wW*0?YrOK#XSTm zPhQW=ZH1bBf=?i4ZFo^c<80B8P>qHGONsnhKKitmfm*M~zoCd3h>PIw!;K+=yzTVS zki9ddoqi^ScZQ?U?C-V-5#`ili-i;WC~C1d3IKiP8(|{*Eldc!&c*5t)+*xH`#x!y{{_=W6$5TR4^|7I zvkCa{OYmWlWVfoQ>ty3wi!j!Fgbm4VL-m{VyTXq2*o2&_WdRC>f(8&iRLLgUPi$H- zQt>V6YP^v^i-abU!q>l^kG}G|eVAw$7X_1);qZS)NdQ*>sW&FI)_^`jB}9kf!TafgnhOboC=?isoWYajMd&ZFqgm7yA<|v0Rmicqp8<=^=|nP9IgT#Ts`$f+WE z-nJ|X!qEk0n_j6Au;ImZp7tF}R=BG4N{T_gX$F%L1@@r9wsCwoo-eUxSs2Qrg{lY- zusmb}Nh72DvR3TWl-k?intQV0cOc92IZzp{Pp;mG00f}pc;~*HkhD4 z0sNXG9n!gwK)06yMt{u3N%^uaW-MI=){9~*^Ja(@-A(w2PIkh^*%*^!2br z+&3ky6)y8NvAz2YF7#ok9XD>aZ+>Hg%5kMURZyshFn#Url_Jm6oOSO(_W{l zqK3TCUGye|LR4!KK@25m5)}$NALv{tk1V5a5&JJ)n#_ts(1Y{&Ac0Z&9&K@C`Z_$a zF#Y~LuM1wf`?z0CoI1+*%!1q1Fe?ZmWXJOlV}8EqpZFH@1wpp5 z5^g4ZSlfQmCqL4L3}vvnu}_R6aEE~Xvb(2v`B)y&6j8YUsm-)v7V7kAP;katTBCf` z3|E>p4}6%Wikd5-1vjbpN#!eWF}0V@38Sck(?=SP3Z8dF>!?XyUDN&&Nis0p+}d~E zKcIM}kfe&@Yy;RCxDpiv{>Drst3pp$I1S}dR$+0PVjirTnyS&2Y#3SxdJt2A9371X zmWL0N)F}{vno@~$ypzP+Yh5c#Pqk{@v@A+fhh~t8$zXPcA0rItp7K(i)9l##5kB7kRc`M!l5lc-C6{vlyAYfr6`)iV5}p(Oo}UYM{@LQ{4g^cHT&1 zw&F9fY>|(F>sqbZC4Y-Oveg&uad>23jaK3e7R=?%>J55}x$+D;c)A_#;ViVK4@ap( zDY|#vzk)P3T>F}*C9QbuJy;*UrIF$f(C-gS0S#5@slry$l-7#9s2TPXRZ)=Fg#*c| zJck2QO}D3Ty}iVf|Na1UV7!Po$#j`TC$C*CAVNiI`Q4^;7(eS{+3hv6_|;%e_F7p0 zcqaGSxS`$-haAk+gW0S)eY-w>rPmxsumGH(J&Vj%gw_4H6Y$vNDDvb5IM!F?X8ll@B8jxK7y6~Va#)pYP;NlDU`&UV|!Oh};`iBt%O0$gq zK=bF84M=5(m@8v}-l~7C5}r!#IjmJGX+c#1$Zs)$nI`{h2NRj-muT{A&#Pit{BZAO zWGgq)9Qa;;M;reM+0GsXDGnkmkKjYrEkO#JkCvA5p*lW9xhf5;v!@?rZ{piiY$BSW z;2m6?F~6DMlhd%@EEi7Yi2Dq_8UCKZ!M$xB1mmq8&j6knjynT8yPGwc-PqL!@zY1+5SOPd zA$EltlHCns?9PlpK;rrN83u+m0V=uvbDRnVOAAzq57wl>ndFQrDYa>yH7%qx3_l$L zm_0rh?iYsjI=be$bAZh_ZhtaQ_CoeSA!W-rZ4pAk6NTG~w#j&5Jk%larp`Wg;d^{8 z4_n0c7fAmzM{JiZJRsHulSlX1AhleS4yS=BpLN=ZKIn)E>8Ab}Fz#C&yf?yKh=tY;)zSfHlZi|bEA8^&F-17HojKLGH_}=Zi zIl%~jweBqzk_%vMZ*7FXoc-+coakKO^BGT3}ulQ?e9QX<0p+LQ?^fLHN?+QoDqoiGR0k(rGCYJAHGzyIg+Gg zr5j=Lh8TB@G&e|}lt6k0W4j;y%C^wxHJBrMAkpNa4xO#RW%@Za)9aQ+t)ft7nz?0u zjBpUqGJk3sO|k=$sXU8-QjRZ7e45?&G`U_;tvgFokyz4kcy^ZY-Gx9BANWoydPoND zRFoD@O-$3%{F{Y=PX=vk8lY5p1AE)INX9IIyAsBI4j@AZoZKA&J;p5LYh!&3fu%<@ z{U|6^n1H6qjvZ`9uaDgKP-H2=A8;C%z(b6@kZC1#dcB7A-HI2ZF%wjIIs3lv-RN9r zW-IAqaS8zaoLqOK$m7+2{kcT}8|*XSgz`)YzkmtE4sG^ZeTer{HjBL#9dywP%ya;J#!djhpsr_3RKb4>XWl6jISKc(pgw?DDiOYQ9==anH4IXQ&&ERn zN9VBY`Jz5&29jTlSxOEY`_sVO?2AO)(&JhaEzt|(Sysohg{n$owbxU^H8-j)ca2}} zq>pZcSLXR=8bB?mLOmluWxGmV{@77e3Ox@HjTPWT9_?V66g7+qEH^^PmHXtYF1zAa z9*kQ5ZfYkfBk`Y4(ucHO$S5ZN{8D77t88rM^mlA`dNFXdF?njQeSsh2Gbmr=TME_^ zx{K1`p1FtlrN8--HOU2?=Fa%6xXGbfF#gzg3;v#u@k+O?mKc8hL#pr=rpzsqy*_`# z$b$G|ZM0TS=9p8l)#sW;gHtGcQ{#t@gCU{3z+ckOoy-Z2j1nQQe+9}IzGFT-eY|GBYj@K}NvwcMPBhxKByL9#Sq445eP;8>=zNkoQznzNkDLF4P!H>${QsY?~)*P11vWU_BZC=W8a};%HRz z_j$|@hTV>6L&Z#$c|K9q;4#`N{xr9&RGUZ(8(9LZsm&P_!+-aPPM&tp{A2KQ|z=l=oqxhKbL*cJMRdd4|5K zn|>kG8zryG`$vzzNAlR~l*94wHYdJ8v31{UB=G;dlVh80pbuHE`%PH?xOKAWxBSE~ zN`kJ!w&)UHpQS_Z;`PgBI?yPL#TJ#hK|MIy<$a@ByWM>a827Nl3t66^OoM$*jYqfoio83R&Qrq5K~2NT;{4Wwk<(1d%K`6e^2>kGjT^1D&DO#b z!o1E=dym>d`w0T`gQQ6y$uA&4e35*_>TVyz_V7Elh`oP&bHM-mS^6DZ5lfThu8G4^{jJgDS*HKDa8cC9(zkmpr~%Qfg`z6**x@ig^i$ou3^5qY zwmJ>w!8W1!9n?4UbQ(PId4y&NGx+YWE1Zms>iqUNS)y;VU>z0O@}Z@zrND9In#Lse zw^hpMxQg!A+{7ZDz^2zn=7>H!>6DvoJ>Z+HUfL%?>zQ0+eOQw5V{22X)^PF695E3@>qyo!u4_L0;FF3`qUs0P9#On+a~HeED~A)VOhf@V=Di-fQ3(1RO7T{udhHRWvKPX~X1o#MCuj;ne<;Mg zVtr9(71+D$p!HYpYOvteKDxwW#7qW8W5b^|?pl_>Jki-arLOp$c4m#qpB{Dji;va* zuQp3j?Ahnqp_AN~4$>8N0A(dVYIDGdBZV;Yq81PP!9S(_()rW~4H3 z)nc_K0L?w`BmeqT+Q77rB<2IVOGui~0T06oOO(ex8&$&7N<7Boj&Rm^zT=H9HrC_a zH(!yzVNsTMrC$ypouB9qVc4f6jea_v+MF>xL3s7{P2A~0V-anI` zF>WAq!Qbq_t2sjCRG|R!UHz~Lu6ac7nU7H|s(txmY{^bw06XsDS6A&7rE`oRHq&3v z70+gtJy{)>50pv_&T;s)Oqs}+8UXFIxR}XXnB_uCEsNt9sE!(4&bEwW^03M&VB$@J_~Nrw zVO_s=HHA(|7Kmq7=F29`u=d8378dtm-s{!-5ZG_-aQKd$LJS8=8VYY+TpQbBAT4y;xX$Yn(l@LM)|{ zl#6I5=fe*fpbC}bmY z`r)22=Sw@eyIQhPY)Fnu|9P!F?KzH1)Zl7)%yG*;T+TS_@--;_TjfCsg??UTYtCs_S_P(jdqC}|`hG)|y>uTi)Cx&W-!l)+LaTN2yP2qZPW0K0Fts76{mF@lqsr3^b45dBPAYF{-%G@sL)6(vL*k)T;QPKu!D zj1q$XOnq`F>z3grWqLWDQ${UW{ z(dVx!zbR1FxDdHmIY7>-D`b-~kR*tza`~WSk@_&mXr#SOxME;VwP*7@zfc7T{WTXG zXWSG|*BEOEEkI~=CXEGT-^#x$YsYy6excTaX# zUtNl731|G!W5oNtOY!PW($kJazz5y*BUTaGKzy(dZ+xF_e1!ovl-W1_Bd>&InOl}Z za<%`S0&pD1yhIad>eRM(P5yLM58Ot~{2H#cZW2NFrDUjn+F?YJywN!6r+V+2FG8_0 z7^4!_ryHL;a85pQM6fdHs4LyD=cjUBt!AcI8yM5W!S)kb1>ZiixSQ81K zt~91^zo6P~M?brr1&(rQ$zny}RHQ{F8z&Fjcs+QQ8iai1-`s$p_4F;Io!>d#52t?QPD6qTgM09%IL$)uq4`i5{twnzu> zV_gtN`(0)%rId&DhO}1com|reM2t*0#!=5)Nn&@fsaHP1F@!~~Jqt#(_4m_;<3y_f z2fE=oY$__;M=h0zo0U_&I{LhJI+*zRxXu}pV8KNBUlLVV_VvTHc%1vC8kQPhpp9}- z4%z=>4fl*UwoeM|Eon5YNx6p`QWfn4yjm;|bU~Kil4)y)+V90txnE09w)xfBGU?OE zbgaeut?zs0ycDRq*oOFxrHqBULI(OYYVSk7LvoTv6+FB(LL;?;vGDCl_?eKVs!Kdc z&Q1HK?eH3QDfMp7AWiL?fR_ow_3RShFTW>o*2ka~IrF&MCi}tz1Cd(nga;9lR*m13 z!-#+^pETM-l5(w=(kchG@=pU1Xh2c@Ah|Ob9tG0YBHWt*)_XvR)nY~^Ov824gVjAi zRQSYfM93AEo%#tPp#gj4P}BD5$+B7`GRi_se@L0Qh+QdD0xtbE)aLE4_(5gFq!Ah? z>+!+w&mM&Bl`h&-536bsS@J>pr3H{c{jX;1%&RR%*V2u0ELA~ zVv+s9g}rh2utZ*sQdsI)#TB!l z$Gc1Jd**kyx=E!;6$RS}=t(JWN*tM45I5li)ryS)T}I$HQt z=5&xnWs-SZP2tG2H;uHVX9SYe_fe@o*_Q!;sfG`yCgqH5`CI!f>&e*%9U$>A+f&Nr zi@maPD-3HQmDZIQ4d<Tf&Vxy&Cof0z6qJgohHBJ{?-$+ zAb;h*5cKTaLXrHP9%<4oR7Y@AcWn`%h5t%m8A8PA(<#yFe|lPb{d~8}kRf)Ut>pU7 zF^d|chuIXJnvTR`#vF0+QYJ;AueO!cLNWWX61qoF4=0unEE5_1ha?3BkXEY z`*kKau@;E8+Le-eYqrMjo>2>=K#kJGXFtVSeRE9o8;zKT^QNT^!SQ*!qN`f*`UGD} z+8|JxnF3}73cN1iq+8=ilXI%r9#H{@@6ZBokzyZ`&$SRH?^;L_4J~P!I|bTX-IwsN z;VhYGfGHvx!**%{8D0ClD2~*9FaYUT8M5^3ywnjI2Euv94Ug5KF#k)ec{oyZf7e^J zW1rXv2opI2|-w1nxQAgaUcB9shsj8zcc;l|S8yPC? z^-w`D&ashs&-C(~h)@&=N&_TqynO;yv%EkzNUKQgY;{~noMTsnK5S$hx?lOJ&s<>s9_s4OvQ-MPx_qPCGEe(gk=t>bm?{5me1<&k+*gn?DdHGvUjz2<}6>`ul@bQ_=*u?UdYA>ZRtHH{Wfe$h-knl zg_b+AUPkd0y?q&oF|??BM_yMeiY*Dod3hijdDt|Mdza0@sZMDBmDWrJoyi>r6hdHZ zNsR3r_2Y%(Y+)^!L+QzkAz?;1w&#djkG6XSTTRjIZ^iV{w&tDxp>ahlBsq2+O~@#> z#y&9u8q^};qF>HlriHo<>b+Rp;|g!62()fYBri*%eXWe{P$j3buQscUl%l9uZ;}U* z7xuI`oGO1wz=BIdth%y>o-=roXZ$*K;O{it{~pXxiR75^{b^S0^H;zIKUAcJ=TEYF zIH-zsNj}<7pWBX~?hv*8@nAemW775uDT<~TWQ4esM|)sMDL}u~F*;4gx~%0^0Eti+ zKcjPWm?+#Mbt%47Neg_|t2df%l*P;>1h92!AsnxpJrhf~BApQeUV>n9EB3wNv%8jB*f(+4tgS zsGCga+o9WP?~-RB!Ul@QD!KJRwB0EJc0UYpTf_tG!FAD*d)OE!xv!Udp0nFLSvEFi zhQ{(q$kDC5x4g?(G8m%|Gsle+Cql>Nm&h2=#QUqe+Zr0|GA4~4&%hDZGOPC%Nmjk8 zWwI>4mSU3iI}E#KEXC-s{ zVoRB|*Boesh}2)WhY7cz0~6at3_!|v1ecA6EkIUt$P1^;x!*1JB_jXvde5118LK^h zBhC1G{YNCS(7k78HiYjNBeLo4?zCF`Rt_*brY8Xcy%wi>RpcZ(Zn|Fd2q;q`0_5%p zI1SaJw;|)3F_eH#8ePQG$pRiJm!1t)ypDHbvsWgRL$6Dz^%n)xw`GD>+gFxX6qD#M zq*T>PnZ($5+EUVW6p|YK_|fDQl6}N6+ZZq0OuGIfn|u)XERbR{;^{ES(iHv#nJ7f5 zO@1tFxx^G}b^A>jxhboU|6V@G^zuo^F$*y(le+v4I#=N^=n&2%g_NxJDQ@6X%45{m zNPSsUr^6@P?;!1v7(PeC$E8K z$<})IPmaj_e*StXTzIv>;uI{Qe$2Zrz~8E^{Q*i#9-22{SLC#7uF%( z33JauDqVo3hCz3>6xjCL1vIwRbL(RYI=LMh@pQCQvz}b;U&*y_dEG}OtH(oa|S4~scXSO^ThuH zL5P=V+t1A#;-x;^^95?6&x9zp5q-Wq7l6 zUT`^CV%vZ0ZREbyUhH#vN$K8|VzJv|w6!c-f~BIkXkF2J3K{@(^$>OTv^{c+_xpJ> zDcc%nxgcA`E-a^7X*(F!zt)3 zeN4(EgrDc+ixWsbh62_%9}e$yv2}WEKUt@AMUCJGnaTkv!;o@^bbtgXO(BH8Q)1RB zhKzxuH;!0nO`oSF8z8Zk#Fhl-_FtMRRH(K!|90efbJ#=&u@D?(~gP)HWr6L*diis_flBmIsWO0`+ zHGasTIwTbjLbQ<0=4t<8NvD6>9E$W2Dbtgo(6>+RWB=p4jGfa#XT;YcOR#jj4`P68 z*ub?hjE-$l(AGlwZAbJO%2JpPhPt-dB9}NwLb3R0iT1uWqjiV9Ggl*A)Go>=wmY$5 zvW;&th>Bs3bkm~hATTB4n+dkrmRp!q?JCk~=fuoY(&2Mu&Q3>i#E0iSUGeSEmt>34 zhA?EBL)`t72emII#m_<)dl!&iDC$>+2qwLQ$KN01chdDe^%c{ZB=-%Zg9>{uOUEtn zT|URalBwaU7-IzJ9wW3^mcetSu*!r!lQ{{jQ@E;z9|K`=RHHAwb08oRm0O~#G{O?! z!y>pVu@wpXpMsEdR{RL!zO9UZJ*mu7rhvCOmJAmHFOlBN^sqeR{q0#CYABhpz{fet1t;?cy;Epj+PCq+ zzcAUSc~xCNJbeUpqqSL|9LVRltWfxuqMi~SW9WRwp8FvKWpIF3xYQ+x1ua{PhjKIq z&t_!!n*GzV$&xESW&2EoVP~TYmNPhYYZ*2!a(CFA(d>1htY2Liwt=zp6Yf9;GPs9= zqGrU#s581dtIeoX&#N26J+{B+sux_ca8z5{CpW&or|2!rR-4LzhfP$@l$KOBMo`!m z9H~XEp(d5oHaj$01KnxG$b>TOD-+19+D?`CN81W~WK13>fP25#P0VFiLhIhfA~%Rp zs*2*an>C0f9Ou-fVH_+^VX$FOO5&`LNX4r<<|HZn`aX1BqoEb2NVc8cQBUi9%1tH#;9|5P(w#v(&5*0Iq#!Y& zD<+4aqdAv~u&^3g$c({=2+;~d}WJRVNLt@za#1W~1Vt8}c#k-~G z{=W+_0-b&gQoyc93pYh_Fv)_jWuoR-p*MPuxJGj4{c%U!Py@qUao_Xq<=o}rdfCIa zI1hLy5qG@=p=sXe>1T%$@^w08S(FwL0kpS_fKBh?2$KyGCBAKs5O*$29(YqkYk0g~ z(`i#s7o09Ej){EAaP>?1Ge%b>w)~FJalSgtCKq-X=brW6%dq*NJ!aZ4zyRfYS=I&HmIN$fMxuv9l~vJs#EqDN+EVP^v4 zZ*|Ok{{Zllm2QVYU{`ZTvrT`d$j*+>AP$R7a(|O?sdH^Pcf*_zJO!aY1Hus z?QQERzUvFfJ}mcqvx|=r3HqOPdcQ^379(9tSL$QzxZsyg26*BJX5JCc=D-BiPHT1p zi^q!lGzy7hx}OUc4TjSh0T^A8u$=-o$gRu$NKXnz2g!rL?6)+5iUom6zdS;G@qAGKJ(Ral+Xd~7_lRnZ{m2YmI2A`RNbWC3z*IR>Kr7dF-Wo+!$OY%~ z^_E{+3`rYRp4=%2T{vl~!T_m(Vp~z4Tg#PurZ2EKM19N2M;F0FQLB^X7IptNcwBqV zsxA_+Zy=(V!H5N@(BXkIKRTfOV)>x_^{NPe4i6NYyyxe)W_s0JUM7$#1cmJiuHQWJi2#f``ARJPzibr79R*c@%NDCW^y$p_|1UcPnRj z*fi+>yk@#P?tVVib=$F!P#ez=sBcZ9spc?C_-(8&zDd@=Rz%ucN52lLQ>Hcs>HZGY zlBmX}B`U&Z%+j**@$?uD+&!^G1Rc!K|0(OvdLdp}lf*kXWgH?8?hK4`sy7drx z7Yz)HqB_iRh`i9K7v})AxtFR1-DNKJXn)b#$_6z?*;$J#qa=xT4amx5lz(eW`O-}1 zkNWUxJpQ+lg3cu=6sk!`hc!Q=jL*Jom)>BaW@$;+0_f*<rt_GBG7<#h-r!wRs&Y>>AbaH@C2o!!O+PJU)r;0}PKp*SM z7$nx3OQ*vARW8Q@>@++MuxtzE`{~l2!mD3HcAp}_SM$k95E1M zAn0BBFhTU4Q|6|A1QkmWFv6-W{T1{?kfA~07wtEA;g#+yw%krU11XjC&x30LrJmpb+#S zmP6HzZx^$QS1G8MWSg6RK_=HFkn7lDSv0~kcH%Ea60*y z=VMCW%*vW!p4HDERMtBF9>0lUJ7<|sF&_&mN_DuO$tNH;B4N1nWW!T6Z~+ZFGf-ux z97Vsnz(|3`T>(u59B`00^g7fK4d25di9fWL#j8JR8LEp5xH}cs7%#3XW$6+YgGui3 zs>ULBD6p;+mQ?OG5v$e-BUL}}hT1&cH8G+xC%-6fS<)#h1wXus%Uqygtm)4)2bH1R zWV96&hF8CwwFmhkxCHbo7Hm?cZ@!$nys?vn~r+ezoJ zNC(`99@SIS=v|llTkb9s*r;zkne&-$;bi*7-C4TPNA+Ss*OH$84y4gX9ij?z`@;#G zyZB>1Dq3oSl^!MhtLjTAl(KAGqlNaZQ4V}REFy+s)5y#uf4yEjJ6Zeu-XrmbWmo4= zp+!(?SNpJ{F#GFu?V$Fdugv4(FS+*`iaQ?=C79}4IL@B_Dg_~inUNC$Qc?XW%y-3i zmj&UKdHw~*)-I6K6gdV0Rz$vvNbK$*^{Qskpm+6Ft{A0~edj+16F|Qr-a_0O###M8 z|8zK+XX*Y^s?`h;j(7#6Sd6rlo$0Rg^X38=+r9OrK16?H`-JMsa0rJq3d;Nc5_+pN z&-_S=^wqGm2SDedS)9RHsvT@NKcKRlTZ^4+MvPIX(kXUp$w`qR73sda|70=e;9+)a zxCt|Y7|V?wKeW?zz zYbaa$BiO6#Q!bI~P5QM0G2s>yuMi@oKH zWuHie4?(UHYE(b(ea|D*PX}~^)Yl33lSrVV&b2S)&z>Y9z7VN%$qJ2V~f|M^U-HrV9X&L5RbhEHt?uh7#3TEj4C zhvx5+=4Ht&?y1B+KKJQ_2lI~6CZ{dOZV6xpE4`zl4&iXv$8BZ3;Fhl`-$x`3+x1en zzU%8nj#t9ziDez8tPCI2%q5W3x_drTx2G>#MV74mbozkYLzTdb^op6ZM)ieOs6Y+y2C42p+C8DY{# z-srTtY?%19bh-=@h9%Vlj9w>qi^83jG!1;~cbp}1Gvk&tl!`i?ExB`~Ym`(|NM$g3 zL+;Q0BH!_D;pdgJZ96M8*f!;ld|w1a!?DL&JcmWt zj^zHnTmNG-7VKP){C1Q4)J3~<6A2_3&-I?<*;P3I6;0H1l zh%?h3p&mm66K2#$7adLS6@L3SqcL6ifBFVgKl-(=z5Wi%^YR*LnWr2FtC>j=D6fqd7C`mAS6ta?--kV zx{x8NtOZ3c@;n3X{J`b>b9J_qT@*|j|4?gGa#P&LtvG|6w~N5?N=QV>q9NC;alp)BLWq(j-S^Al zT(&MJkwKYKZXul|;~U3EIa=i*Xy_=lqv8_2T*SJYGaDVOZ$ImQQxXXNT9wyNZ)c+z zLc*$1Mi%62v%OqS?})d34H~6>Ek>J3YlH`kHS#vJ;J>0N6)b58PVc?tKVchQ!itgK z2s15ALkbn1oAs9lUUDXG37~}f?I2U@QJDF@ic7X!YPN8r1s?9+8dE@JOGknj|2roA zqa@lvMw!aCq$(Q)#26OgkZB*;$kz10mg;ABkGzY?*}^4Z{doonKUv&y0&@^iGRnr% zfGDtoMx(5CJAQ>%PZGDUZ{hnmvi9tMMYb&Gxlt5`1ER znts+Z-*fDu7d$Zp@sHBUZcfw5qHwO$$v!gzWKpg$(@4(8=4Vq;j2ADi&v)bF;HeEF zgzo4QgOAV=YGTW%*~E;UXZ2G|XHAJzKxTLSpw{1;GrNjY5dS9Q~ESzQgst zpQ|Pv_NSU*{L#duea{uKRsQg#OptSu-TWh-dH^F~GRid~P&w<6b07m`iGKZ8lL9`} zgyvcQ^FvG#mpmQ4qG6-BRiLa)3ZK#}VsY~kwZ8-;(4ir)zUgM?$XE7nDHgFxE^#>T1s9hR>sPUa;;P&LGV_(rqAX~;TBLU z>Y%*TUJTK_Pq^vj$6=C7CXA(i9iubbZ!^rAz|~;W7Nz%i(0%OeAFRKLSF}QQF?AN! z-YAmuZ~kY;OoMIzLDc-!W=3wpB!(E>+*)zAZ4-@(Q%rtI0kL;sVApBn7bxZV++>aj z);H!}OvJ$zpqZ4za?c(e{(-gH-`5t9s;#{HZa_zt^(F_954PKAFQEN#U2xL&R-m4lA5 zYvcdB0JS|U3xf5eCvaiXeO6u?iSY|Ux z_Vd04XvP715RjpZ!k#Mo%6}vT`5l0gBOmzu{X3BYa%+o#F;`#x$;>`+-O5%f6L?0~v(nb0cf3FN zt2y@o&LRCv0X0^&q=2euztVY?IZG37mj>k{No!`TUNa2xkfB=Q_moAH^f_S^HKKXq zAi22eBKT@JG@|jLw+uT-=!LG7BW<|8qZcjnefVo$i9QX1W6gP;I;Tr8FkIojzgHiq z7aB)hii4+F5h^77nu`fxE;4vvPOI8XcGQrrly6rwl_7H|Y>ACSk`X8@Vx|#L@zF$R z;DTEj=F3FItkBngIx4uwZ8_4^CwTAx0AjBEYltf*@mk;lPHrdPh^=S+`M+kXKiHCF zyfoApFYg$7Qq;0;f*0XrIysvQ0-z?u!Q*tfrZd7uoOf-OYEQSHw2p0Q20#pYOfgne z09-G6h0Y?E@3a;5u5i)S0Ea`xT%QT**s`(#at54fZM{l9Y3TL(qpRnG%sW!D+aHGk z8{^C~rQr0BI^;CR=DfKJF&*w-thKIM`Ay~;Idep2e^XT{*ea5pfhm5K6nrl4@mKNR z?|Sn7drLf(Wx!q3^VKc3vA;PId~QFm8= ze_vnUPoOeU(B;n4)03NI!Av$hiSa$gWJR40(FvRoesy)>En@y{5_>X>&k4>tqf;Ij zCh2zA{^r^6%=mmy(B`FLvtvx$@#Yz3zyfMJ$W93ue1hlUw9(~FbAS2k)|O2TndthR_U-;}C=XVr(Y)PfZl# zNpIf2l0Q9gsS;oZGnd#R?)`BEo~ zxWG{XSZtV|g}vP-GiCzLUUP(K*${(f%?pWnU-Avx`i|e+t8KhH{TQ7M7iDmpd+;-& z(!i@TKe_P*Zp2{I;I`iORrM8Q+mwUEUX1Mw7bT?0ykRRF{ud{FHQo+)3g;Of<8~PK z(y!Oh?iSLYFGh~lHjRc7(r=38W;?L0%Ss;iIJmuB4bSs#8l4TB4V&1U2DEl`R|q4- zB6cKL#f*~k3U)lv{J=o<*ef+^YO+{T9g;8^ru~wu%iqN>d^*v-&HbgRRrY|+%L!!6gRqbpTk{6z zvxse7esY|M!G2SIG!eXPLagC|#_-2&-Fiz$4q~h+G!%w~6pWhf-ZeH&FZlP>k@1qQ zUzxn?SRk*{csmo}QRI#7GxmLi#*{il zY1=%qT#9UpEOtF}V`oRT=+?mBHLCYWFAZNXi?x`WC&RLf*0Sp-j$eBL9ofmKu`Zqk z`(H%*_u*at>U@UTe|6(L)60JrANBzi9sv)MyC((5yo62ba_}xuxi`KzMs4kw&b)j_ z{^AxQ5y*dJLe5eOgf|W7sO6eRh|?yYuo`wNIry$#aLz`rlky`^xc}p$ z6C>3lYOPVmnYeX_)8Jl@j^e9nF-X*+F|3L%%a~55#-g&Rb1AC6=B|uyD(_H`M;(raeU=`pq z`V{9j>h*Bom`x~!tU|8fj!wN$IZqhy3c<+=>G6z4I~9NMn-D;e+D_?<70_lh z>>YWC?r#E1!WT1AL(w!|PB%;kH3imNE-B4lVc`Ni&5`lEumk|$6>eB+BA&(X`YfC& z9J`qLdm>sf+bF`XWyUl#9X~~SE=7_~B`QX7XK)tbl5fqJLgp}JCD5RgMN%58#!f@~+62Kz zR9l)Jo~0?Qn)R;E{zEVv{;zqq{l`_r5uu=qnJ5rcQ3*Ouvob_Egzou&WBOwDTrxF& z_&_U=ENZ^2MAabiy7Zw?Ld-u~DrUs%H&jeeka4e;UYdK-O$92;&f7{uVJWMT!?YP7 zH^?vezChp}50uuJg`$H5an8v@VJ~%}QFUwf-JI?QfYyMjKcA1upvxT1=NEy`;V!z_ zf-uNaB%MidL$)2n+53CX?&B}LKQxC7&3K%P^2zu3QpSa}DsazT!^E^2O3Le^Stu`N znOLxdGX?}ulpk=`M2Wn`zhN$`%FVc7`-5#HKqpHp$- zIAl>dM1MSoeExF_u((QzqsK7XEOl*T@ysQV)bd*C@cG@>1Xt^0n>kg&b~!KfVkKmrP(vWEY(qmVvE!JI9Zz&6GttV%8=JD`8k`{CQzkv( zsPR#6h2*BtPbh81f`qKAR)~ajVzw*yo~OAf*Ug(C5Dp}I8-_Q?X3q2NPJ99$*qAkA z!~NV`d~!IJXn!Wpl=l8c97_WH-dez{Vo})qC`3AsYck}9=HMF&sKbFlC+G!>CT5B~ zCIU$9%VahQ^ygKJDkwsv?!T}q+E>4PPB1H1(6`^Ql=h}q#gd6~D{7w6u36w$*Kcn# z%Qhf_OrKX|Qx=2$k+EM21^#gN&)L-LHHNq)dN4VNLXq;y;+t%gq!L$4e1;B4z$e2n zIV>*-epVM~D~feMH`&7_z^`d}YjdjtGzju0#HJ2S{4_>cD&|FiE$JH#5aW$NX%a?% z;FUc^!_V($#r{}{ZOeikUeb&?S1cy)F6Uwq8B)FEVuKdaqCB&M0>RZ_$vZ-Yz&Sw8 zgq8i4W4t@PSE5v)EER3SNhpET%-6SI_+0S8FJNMh%5z+SA1CxXpcV`r$V<%*{{?aG z*ph*vXL^qEh-`>8M}I;d`pNX{oudMOjmp*M0sO!kQ-8g7<*CitTwk)ET-s9X7-(1?>b-hIGvRBpNbpZ ztYyF=-cv5tG~8~8Gb1ODqh)kVwTHG6F)} zNHpvKMa`X8aIEAYCB94J<)*v1%|q(M(4U;<^2z04q`%nBHZh84sg&URXtemEo(Oc6 zy40lCA{NMJxt>&j%374_UQrB3>OhQQHgR~&oZGY~=}@~CKItoS@s~Y?deO~a9sP$8 zHvw!2N>4B^dqJ!{9dr;{`UwYpvJjbP6gBdKcc)xCSKLN*w0smi^W&d1KKc!0WO+^n zIv)7_43Bgp^`cO0pEd4-LnRR@PUO#!h#1}%1sg9VN#*DWlUV7na3f2XsEA~!L{6ZfuWY%$yf$!zmjwJx6_0G2lObL2wp7CJZ~QFnlz3 zwM^i&z{nqyVk^gqj{s!Z5Lj-O*34$qV>5iyZ_foLo_?HBCY0kPTo)o?Xr95i=Va3c znFowCoWJm^7RAryP>sO-)z`FUBN8n=_Bu)v<6TGebOQ?58wjs z!S79ok4%+Y)9rL4=2xPdE(N|6EK3KV`uk;yV)aUslhOV#CMSEN2a=wZ;Zpg=5^KLV zDw^~wjw~iyh|*Qh3V~&gZMms@66len3hyre&P`s_a6g248IESEk<9t@pr@a$8Y3uc z3&F>ljoALAhVOcg6(EgxxU@5aCx-IqjCSf+5U*-S6YCfz35?PCfZZiqFebMbo+V^8T35Nv>t)&1^EJ z0HHu{_JI7eA^8rIyCI7Qdi~E4imMwLsyyFu#qs;JC)efN$Fc9^;MyQ!vvO2f^xoFv ztHbNBkC+gc#g&D}_#*J`>OIya^_Y}!o*Tv5jr~dh?`S2~Q^tRYBTMiD)Tb+yQMy`{ zFgF2{>YyUq*ZE`CyOjx8so18ZVPe()H`-)(*zSaQr%8Z4pcKdK3u(v)oa7^}+hOe8 z5OpNyw1X$NwA!Tk|C;|xw6kDUI@RQz*&`<<(bH2*r#rW47&XWiE?F_27fzWAQ9rS+ zf@p|+=VeBKIs^T?l105il4w}7a^!6Hr!U5lnZ!Gf4YoUqz;B!1y~QN6o&*96OB`s7 zDQ^kd>^dZV9A;2a5hy)Q4D;-SC9VK zi3X$(bS#;SfvERt29Vr%mE2F#qUaFJ=|fz@483g&WNo+<5Kqa(x8i(%k;y2){ISH68gzY1yN zKXe*inaJ5s{!{uBM9uv2gL;-ppr35S#gnLzNG|w|LV?Pqs(EZEegVyaGwdgu80%QE z<>`CFw7Q~SO6}6a&U7S)r=W`7F(jThQGg9JealT*KDWBWCHUW!;vNI_1wHTj&c@5M zD*@cxGH>5}&j}rG(7`QzreNWU7toCS;P?8Ui@kc!`X7OAB1@>p*Jlfn7bQpCWV23E ze2uF#LkggAM>=|V7pf<8FSgMk1Q(V*nZ&PD%d#R|3^zY#qi{da0P)Ml*x3*sz9<+R zM80;5IguPv!uxveMEb6sa|uworN^U!_+=2uHeDbJcQ!Si^aWJm1iVr)eC?{~6S^P4 zP4jG>phYQaw&8z8`xzYmC)143mI}-}*Y`9OpL6F(tRHkUat)#&j!xDc5s>%-Jw>Bd zlU+-2(>p?5uq-%ri^XX%QKum0!ZoKE4pVJ9i~aSNf!H-_po)U{Bzd*k({1KEun;Tf zt2u_1^xoiF$nV2n_l>GIM)Ypphp)?TKU|m@_p|!V)WXLi(}Vj3^}7yDOI=b21M?uQ z#2E*P2yUjDZMgo!ak36};+&l>5q@VId24fny-0HyMw%ItSngLCf^A&L zB~4B&9tb2f)6bScd@+V^*PIOBu;Eu0n}{CdEZYVT61nxL7B%v(jH{5sQ^lS1guEfD z)k|s18{ulFy@WlvkjboqsxWT5>|6vFGNbO0S4FkQ*ckU~>&zTHAD!Ykd17AHCT{&I9ewG?3LFbVU zSy}P4d5uGvJ;!owKO5LGLWUlab(82RU><7QDMXC&zBQO-4;NcVn(f-TP{f8W<9?7U zA!rhk4XNvt8`uQy?7+<^hUIzw0#w+Sug+gJ2EAmW(}UBtEBp+f7M0pRgw=N~ zk3+$fvWg77hCD!H*`)IutS?iA_-;ljh0Nku3$WsN-VSwsM@Cl%-7G*H<|D+Gu?yYd zaF_!a_jR@l=loYZd@>wG!FDboT(TiRP-t8mUpIVVNG1y7YV7ihks3&s(}-ag?ACzm zqL_Z_(oai0;_=FUk!0LhdtaieOe0G71LTE`-5rK~QR|UfoKO&`t{xeXS;e0=QpPlj z=M#bARMy?)7?61j`K;6>rIGhc>2t2RS)kyLOgNu4lVY1b?n4UtnLV_jD|KdEuG;CyTpOtML*vEn=nVkK8b))PqBv^ zZ#MOsb=gIi4=_z_I5*54iQnDFkdhyB z!N%aEfKEn*YLCoV8DZHRhnG?q9)lQvw?G=&aIBzz6 zSoB(YuLg(`pg0_#Tx$k`B6Dof>JGID^0W}4nC%qJF5Mkre6xmOH+bQ;Q8zP&`p}_I z1;ZZ)mD&X#4;BlK4M~MF!v8o1AG)zbkuBg|Ye2SQas9IZ*EN3YlB7^ucI=a@yMpdG z6g5Ix!ILfQNmtn#l={Y06nwu#6qh)}i_VM(U5aho9BITyLBmq`b4X+TYuN;Y-N%3` z`0Wt&m`+f=IVuC66e=`^w=r6?$7ydyI0(8@WeA;oO!1O~93W&?r4JHUG#E=@Qt3q0 zi|Hu&8DdYC{BrQ(){*n`gI&KeEXmsI(D5f!?aQT`!AjF(lQOchk zl0T?9C+dq!6iN3(2#|Z#!>=CyNx%OmiN0O=Pw`)6XmAzgCu(CIkExPhWG;}NI4`3N z`y-(nhbj5mk)<2D=6xAlk3%~MUfm~{(q!3f3+VVmimt(VK=rQ?uS?lF$=eRzoL7wm+t^_Rm$Nl48`{zzTOm^t!WU?( zgpL+MK*yqAVIWe-%+JC*FZ~g%50dnbwe>^e%!OD>6}e-_^ZQz!q#E0q>XcyjfOE&!p+h3*%s8dl`#wfuv zlhz_X@g`NQ7LA2n(?c9r=<{uheFjp>1jmH(Rrir$h;ufHV!>Ai|MZq7`r_#2Y|nm~(b+a* zdfk3DF<5<_`JM)F(f?#~eVuNQVkh6*iPT;`|A`qMp?AD!C+@gVn$~KYr%fJO``9a2 z-YTyq$kmNwZ0IKdh{BE#dV#xEHs#=7>RqG4YK2-MeaWmWKVi~}RxdpoD;;%k92Xrq zXcga`stx*M`nGqVB=h_l3_kAFDN(Xbb9nul5&W3k9G^K~zjU169B^`cp~QfqPT`mh zSQvHv%=m6iV)XI{vi_*Kj$5ZTbFe2Fid`Jj9@3y`jj6a$L2mFu%4aw%9?==o5S~C- z?DY-cl>ZBLeONyR(hx=Ll#H1&`BoUeJTLnUu>Oj{FT4>D%A?}+k;33wQ*^57vDILX zjB83A;qiR|0HV>Ggl>zuS8hxQ~9ySCw>&CYN> zF;ag#bk`qQfbS=A~)c0Z6$6daQ7$p~yW?-q~I?FbPi zzgIyVD#S)eCw;?nD4@{>0|mDc^0#&E$OCUu*95|$-~N-eD-p`k0bD8eeWd(bCqNdc zq_3to4?LRuW2W&15%^vE7Da!>Jp#fzT|dME2XS;X;V&vEdd%WU zh}Zy9mW>*&3duA^=D)$v>ze$p_=inV>@(0(7Mh*;?`=2;@>g7$BPJiq4*W5FzM*`@ zdWiy1Ioo>Lc88fAB`@qq~qx>1OaQ8pp z>kpJT2U$7y7T!RrmQ4Q(WLsRq+C+pKrWI)Bv*i|}H|uXNF^7u+uyBzuYix5u%+3|f zvRd{L$(4fj5-}(FuOS;mURh4^7qp?mscY^3@Tv;FI=X56`uNvt3KRE#c0TvVG{lTP6|7;RSwA{kM{HlzWeKpa8b}PLk?X16L8Wo+~6OazUXn za$&PhBHlp7AGUcP`9&j{80=kCD`Xlu2UB}|&npd4AOnRw@1^8{x0v*yeRR!HbQ>PlR-d<+|C3-3vo$P3+lHFntk86q}^eidxPw3h)FMW`$zI_T47lES63I zA0be4kEc}u{@q@N^434up_Lpmd4Y_voe6n{T$7b2z4>hG=*nh38I6i}8!g(hJ*e-JIVwVch zf=;zm_t}(RmKM$mu>YD_%@`S7Z7z#Wlh#S#Bg9w6eMJk%U6nAb8oF*W{TW zDJ@a}ykb;`koh--m?zHWqnKHX+#xPWC`2QWQFa#zC)!mwy{hz=Z)l&tZFY}Hs384V zLs@#)a8xj-JJ2B@g!dA*gHvjiYaYv2jur&WT%*T(OX&>rQUULjuBAY4PgK@EeV})s zH2!=~HJ`(6>Df$AIG@@>Smc7x3m9|hK8qJMLhC9YI-axUVjFXDsLdqKBSP@adHsHt zKY2L==t=JEjVvCw;hz2c&%0=^&wAdf=68W(2qe~151*P@_&X86*_RW(#B;}tU}bL+ z7X0s$V!Zvb<8PEVq%^YHaN9uzLkzNDkGW#rFI3pcm$DtiS}s$1;H1pJyiVCY2!Hqr zi86kQOXj@ab7Z{twh}?gJ4l$-brF225FAP$)2S%J0F6R6&b$uB5>yQZvAmp(A-sQb zNWRmOz2FUV=o(#-S7skz6}bv#6^kSliFDlK9j-YK&?M!OsXU1V6sJ=h9gY7fLv2jT zLwr*I-EP%f{2^#;Yxi*|Ph0P~6n~^8k3G>^?qrJ#B1ivNXK$1@ZXo zx%q;U15o!n);afl^xycuf+ufG09BSo|DLy<5SJa}w2MhW*Yq{`U@ZSM$$Zy;&|Szs zLr7E1sekSD?>gL~Fz4h{nX&V^=|B|+wz{5`xhk}rbbfK^B_?{Td~c~C^?Q^> zSLElxOL~D<@TB|w*T2P!f80H5{PXm=2K{rAmP{)5{3ZSu46~j{Ds+*mWY3^XUrm9# zgFD42MeR7inLJmrJOn&*xh45$Y-j@JX8*os3%0SRoL}U1`G)wfAL5n*oLZOvzPhVU z?@=F5JiiA|8{LZPvPEko>{m&yR_r@Uz=%01J54)Qi#kj{R7`tVq7b9 ztsHn)sWQ9jE{E9~N7hOR7Xb#a(`{Jx^bn>v-xf#pqsN zXkpIr#)i8Iyc(KEQrRBIlZ!O~ZmGK`Ll|A42?(;R+y|%{_7Ua4EV}fkmTl2rFzU@tooe9sZ5f6KaRA z#*H0Vb)|of2JyJR$HLP@$4M|FbEaQPP*4aJRZuX3vGnVGivAJR(Zx7QCv2=BV=Au4 zR7YQ+xs!c$m2>O+c0v$NhOhkF(?!AmqO0lV_{5e|v~j2^^V&=im`jU0O9;c55Rctk zBM+I#)DhS1!b6N8mWtN4)LBQWWxjiL|LZ>sIqe<+VRPz~W7T_0^&f$PbH{(zE8rQ< z8YWW0h4{IzarV4CGmLXFEE4}~W`mD2*i#T*PUX^9EF|~O%bXB&JI<$REJR5f}eO`3;95t5z_`jMA<9OU#9!3n@_&Ug$z@mPN z73rRbzNYCrA8P%|+(SArNm9nT`-+PUFVV&BN7N2=oE!JzXj%R+(Lv<=o@zQ_V{L9O z6zSLT|5AA}wtJ@3S%wuj+D1c8U9D0zI{z6bje1xJDH^&O0@m9_*Ym!1Z2P6n*ZoS~ zp*D0zRU397Kbk7t^JBu2F9Zm!<^4dc(wkdPVkWLt@W35WgSS)>-00i)E-_()XB{Us zhxXU@yhS5L$-#ad&TqZ@Ce2NGTk4!6<$K(;4wG9pwLSMX-QvDDhCLz;3~W~py&c_q zUxWu!ll#w!1(;%hJ;u2lcyDlZ|C~(KuyEjIk%><|Rw#KYSw26W8c~~Eo0;WKcO7&0 ztW~vyk86pm>8=E!wKYY^qoaJd!YVb70WrYy=RVrK9g>$kaKn@ zMZn5#E93%nS|yv7Y91n>?c^(mZEvOVyV1cZpW+@4fkQEpwm$sWQOoC9p4Cr^{`Bc* zhqJF63mvQRWa0{wawX~Zc5(rRLOdHj#-|5Y`P~;$E@&HNl)zWj&&N%_$9|k0ysu|7 z-QzW+%4N`x-Iwrv{7IpfG}A^9U7$eN)|ut!PS40fl%b{Pb)`lBS$}>=>CY5qO=%pc zaRQ&Le&@DvJVh-!he11j=L5HOZFMhm z_9|W^@+4zwRaCgseAT)&2VFld(i*F`IGx53GipE(S}N*d>yMRnOV*J;28d?o6x=l#~rt>3lS7W7us-MnV;%tlA`+I3`DMk!;g3e#2=Nyh)PSO)r;4>7# zTcgy?w5s}+gG@d3eJ{P=ym^F6r}wL+^N};S6+jPReHjC{H^FU}j{)_Qof;fAEBdA; zWX;m^IfwhVOaTm1O3xD&$F;*)NSYMx`#lqP<-bzQ$4$iPft_~|T~D?40P8YBse(1Q zoTewp-!=b6fkJUd8|->BrIl?H#}aP3v;VPmT3b7aJQV1-ZB2i5HviYO9~3dPfjk2q zb-OwEa6$x!E&jOsJL;{(P7^(a9X! zzxu)^ik7*s3VE#}NT62?oF6H?_rJccH`eiXWtnjlEZ?+{N*e`iXu@wD{j{X-wdyq{ zI{X;y&EuFH{(o}>_P~~KyL}1l(qwKukS`8?;mIB-drRJGz1O_;2rCZ~%KsK5R10jo zrVFXkrU$?Bs!k8KKO;CJQ-JMVVYm>&Jxn9JU??oM(`eyJ1nMj502)c?nf$o$WoQ2| zC4FR&W0axHQ%>O=#|w_$Qr8WuI=@TUA-Nv-Z1iuUQ5hrCQ<*|n%`L$xW7_%5VnP)1 zZxr)LQtChw#O%BBycfcx%lQXpYr+%95M7c!89Y!7bVC7I7W0*$glq-@cC8vM;r0|F z_3B9_xPty)+AloA@7vY-ea6izT#eSwjkL?UBulODx^|`m#&*1IsjshmiCMDEeoq!x zR5LEqtFON-l8|i~#UsjSO;8mauYwHf5EiM1PhJCq_oNwaVy;-Q$=Y@OdT5LFty7Tf zvb3(|%ypE!LCDUlJq|_L+^Jjzmr!TTha__kLsh`kM1_QUB^{&+`prm2i46aA_=L$4 zCCVYcZ9O;|>S*nw$rt+hzaZ@WpLYJagqY#$-r>)+?3KMW=oouTJuC_3^Ff-N@UT#! zqP1b>)lp^|2p42a_?&5Y>}Q8gZc+mFppHKE3;Co=VfcqqnQh3qNIkumekyNwwV!+m}$9D9LXu==@Ez zK@_gy5YLRq-Zv&92xwZFKd>`VhVB1rouo^wiz=VFk?jLYh3bFv`RcBP{-e&8a~04# zWnIa5ocMv6aj@+Z>c(5EL0(FY)jk5QGWJHD*#X!uN&Pdtcb8>8@TM~nU?!D%IqkYl zHGPeyISxbS|HYPxFiQ+|$nRI5EDx8|sD&-Cg)gL*GB?b@EXR^qdViFw?r z)2e2QUhcE^yL_QCcW&dS_khT=MxX0@SKy%X^5pkko!PE$leFeY34c%kZ*90WKO;t? zYb2AMcD(9A(d+ zD$$V-geo9U|Dpkat(pX!u>|V32qD~ChgZ>8XLHzO=QXfkBTGE?u?*NL^$97Fz#sjI z)ii@JyCgv@iroZ1Ir?DElwxXjeOUV(7=$;v>Da@=@{Z!nLo5j8k?cnb+&<)Fv(XKp zbzo!%RWC=To;hR;jiFf2HA4*9x;&Lk0*!i7&&+O0%vnHdj7o3!$gbJo|BqeEvHL(M zt4Ub%N_W+rpjAZ%2nBd!gUR^%H0TK{C;txda-PujiV5fLGY%Mwy5}9!VT6b{7m3DgZ5- zEADZClpDOLOcoQ9E>To*VL;1ATnQ|s-Oz|5(VU@!sh1cf>Om!v8OpcwsuX9^h$0@G zWjZ~X^t|}Joo@LEq5d$Rp~Zu#qJS^>Q{LB1Jm)Ym)cVAlLZd-gXW8(AR^*y(hsH*6 ze7APtU%-WMDs`9A7Lwu zL~9q6X%>lBNlN?VL1Fwyc|FvcaqEsI!`C!z`R|9`V8xBm@E1FL&+a8%>aWz#CA)o5 z?|C_nvf)iDjwfj!i@iXt?->0^ujC1t;aTyNW$Q9csN-YRBRH5w^w2n(4K0NT*8>q! zLLghP7A#=3G%%b0ug~nVVfA|F!5g36jqcB3K;gsja5b9r+QH#86)@w&wgv?kSh^eA8Qo{ns)6`?olw)U&1`JwPlq=m=tmYyMn@~L@5 zkw|m!4g1zQNhNzy#&wiP1ll!KmPA;>r`<-E!XCE9UAKwV#)Yc zZi}WIPeIWvgDSVf>=Zh7s_3!5z}`>H8}e8BFR49r9aul#6;1X@5ZkR;ueZuxS}t1p z9%=hC$z7dU2$iR)uwtyVQlRogKiE(uMB-#DzhjPXF_!32rMEEP*&p*5Im~2NcA{XT zld*}g$+<(V8_Xy;H$jSZZBrC~HS4+gwJzQ^M-<#cKMhnrCU&VB8vGobqn6qKTek9$ zLXCrSVn{!rH<~&BX|B%uMd^s_;or{!?)c6pdmatvMqZl#)ey;vH#0 zZ1_t%&(fUiGQf7o9q-k?0*`+jjg{$nWyV^bCzhRJPgO+*M1r>_9VS7v$m&7VJ_u`0 zNXzutiSMl5GDx5taATm@P^Wj_?WtBYPzdB}KruxL0@9=(xEG<9$rZ#*-SovZGU3Io zW>z#pP;h9bj(tTf%SYb`U{YQV&hj>6&Z{1TJ%6b;f4`S=(m*u+G2nHq`37&W1T329 zN}1ir@tV^07x5N{*XM-H{7-Xmq;h4SCBi}Q(s5}Jd*x$ID{njx9{*#pT^k>eY3S*+ zcC&KD4>ym-q=*ZQX@}LLW=!S+D@_CKu30KfQ( z{Jnxv8-$A>KTG%_tu+DEC`@=AbHmyCH}Z?qXR`l78RWE)d5}wPb+)3o#-wZ&Ku~;K z!ueOg&h4G$E{+GQm7467ixCjG-6%!aOU8P(7$`aGt@8pZfjLfu%CP9^JQswz!B9MB zulm?30EOhrvThF9X7Qf5* zxAi~G7A_q;eDxQ;??6~9uPac4g zw!`!N^X|)v<@5Zf@#Tt^C0J{Pf|$e`0PF08!lscm8Id6XgciO;1maHh(z9D-|DlN! zV<`O9P(ww~mNcWdZ}1}wBzO2Efshqiy|I8ayo%J4j#h`Fp)BaBMrb;|RA+<9phwIi zn)NS#f{{Be5}pZL4wf%{HYW0)hUg_O$x{CQCaL2}9CQ^>l|efGF?t$T^NV$;Mk9}8 zVYPMWhZu}zBz;o`2I#>w){C4V5ER+#aIBYMBA3`NAbiB`We+hD4KGgRkV*d*Oc)mx zxvXH@H(A`ARD4yT6v(a57_>Tf4h%@)hx|jrTwU05bBXEyb8i}dC+;FFInHa*0B&;sH?WivLOV)sVKqra6BLYdsYJnWbQ~yjq}nUE9TJ4s+lFWt0)35Fp`z5`xm8SxE52V;F}KtUf>4%ADBu! ze`_%8LhpMnsz4(&^bxSzUdL?N`=>5YG;^UuhUztyi!qd*(Ue+HG-ZaW@|$(Hmt)EZ z@aaKzkvKg?IXqhPZ)< zrt;_Qz#|2b*%#is0=q1(4G${OeZNiwn7Tz>y8^=-jaTy(UvEUeyhwQ+I12tQewp*^MCzXBH+yL3?nSU< z%rASw0F!4|;h1B?#aa)CS`WGtYf~;LHWLAUHZo``FLTgIQ4NLV%P)$sI(HcvUO;8< zP>Rem@S5E{2VyYQ`KKje;!Arje|`T`z%VwXE4k&>m#@Vfw$xmrjtuJse_Uw6_QK%Y z-7m~JG^`pk^_!Kq1sP~qI6+0KnV@=t;~<;PlCJFQl0Z_s6Mo1mv1$ojnqqNe$ag40^Zlg-fj>r7F#ygX5BA*4krkb3mBZIn|l-O4kRG)uv zIck;2(L*7^l$J88vtPk~g!9aU=P$T67f)k14U!nTdk%I38Y-mdJ96SD3PFMJu`-$u zeXOiL&hhxfEQh1Bs?Hu;tsiM1d6tj^!^@tQ*Y7=ICnQ&VW7mLgdqpd+U=w2qC8AZ< zRw+xU%NHg+?fDoPXe{CSsqAY|y=)XJzmK$Iy~ffPNp=JaJz~w-1cwi_!xL`wdlH9j z>wcv+vbh;{w2eKcYYN;hmNBwE{&}MEWZv|N|F5TzCsBM%lpb}R<^I+$T?q&z_=zPR z);_kCN3@6U=XR~@B^c)z=djj~cl3u}6(7euZzHyJdx~1&9u@rYA`L+5I{WkMk&We` z5ntqD@3*$_OxE^#65VCLgBM$R9+fJ=4A;NC4mLde(E+#0#Ki3!dtY0HKNR5TWWL|k zp|u8)z|78k(PRPR!!BQqRf6w?Xr2re%?Or+cB)=W7|^@MerEA&-F@H_ z(H|RsI{u~|FC5BY8YLS+^wt!vx~muY`ve3i`}y3SdZtM8a=5uVxS21H*H}|e6+Uc) zuI_VUJD3Hl-HMX_WMh)9opQovFi#JZth}NmWhH)d&R}e^dB1a;-imeUt!B3Sd^r6P zo#9uH&BJ}B>13uiD3O-IxH5Wnql|~i0omc>KAf=<*YSD3TH||Xm*jpo6#OE{{0@+;I z>)4mTozx?l>$FCc-2&i zZ{O4K6Xe(~Cp>nDnwjFxv6ux?2Cbo;n=x(GHCIotb_K?7 z(0JrEL((Vfx&I(0I|j)(ieF)MYQL?NRB4$w&hEpSz=HSuaX2yLAD052WQ<-e*Ph}z zwUy9Nb-&xs7gDIGDvsw`F!@z1)O{utjYgc+?`hD-U@7-eEF#-Pd_=hump%|eMhky` z9!~$KfIey-5M7|m9H&{E}(E-EZDx{q(f4A|5OjGLXM7p|SFz;#+K9uWYTa zhxTpIWyxs?cd7OL4-Bojsp5#1Iwv5c@VNEV$}($Lk@44p*N1jm`6$~r8Fwt@sS?rBc``i(zi zV`*ccO<-EkB@d7IkE4Tjt}^*|ol>eCc-p+U( z3BW1B-#y*erd7KIPQo;vZ>LXt`R=LL)How=KEt__H5gw*+mPwC|{e>*3&d^u_< zY`YIp7#yjm$aWIxIy(CCt%^uK6GrkaE_B-Z7`h^Z?w(_;9~ZotVqVGh?2!d zV1r8E(6(tSnABqXVD#gg2-q?1$g!}diyl6vby{lthkL>1lQJU8C)_9u#FpB zP0jf;hqpYMO#sGkU)I=NjrZP6WjuJMq-6KV1Utz7)Ftade7;w)j_*%pw>5clht7p~ z#d*lpE7b2}AVaA5q1vkWvaZVRRE-noUjG0_3e0ifttM+4ZI=r#;4+gLXsdRX;@<3C zHzkktuv6COwnDz(kz*ptIJF)XBxg=;7<0GoABXq^)O*P4iid6@f8 zap>&$`I21bI63^3Ox;(ORLVTvsrY=oeQN{$`_9NGl-Xo(rM~xWfA3I*F?;Y4ZgV^F zygku(_uh=FYG+u@?AuuO&;5+!TOC6`&^q>&xXsUFgFw&IRV-6@O;n$Ar}jc;Lu zclV!zx_dlB7ypIRBp)SO%ujd2gk|hLNM!W9{sWe}RA2!vWpJht{R5^e*I>)-4SF57 zKh^Y?q}~XvUj}{zU;hQRD-?0g|9SrAcMq*EfA+FJ!LKBX(IgCdW60YHu|UqOAWgvr}*^;lVl*V%K?nc)$v zXJ&7SzR}MjeXk4wMT!)`*CKsn;c|Dn(cfV=!gjeX!+k%%Y4tCi7D0G(iqX*hVjMde zt{F7&$HP>2Yc26}9`0{T1~DLn-(p|R9mzd!hd{2&#HLv&PJgTKox$?J3xLQ`$H|zn zV`n4U@xnVAW4DjWm(K|)HKR2{plYcMAKVw ze`~C(xML7p=~TsDRpIC32$YKWi(t9ZizP;*6m7P(NmlTzLsdhFgdu|og0E*|^d@o1 zAUr-%1yDP=_L1s;Oh^G}0hBUc&PL+*hSo-|ZGsqtFz0Q%tUdDJ6%66 zmN50$kZjHmeE4e?1)+zvo{B(c3um=NQ=F^_IGp-ir}`Cw(FnM!V2XEvyt`)Hdr!&U zMo(nGIV4@tr=D~5L}kwsLK@l(s1Y6gsO9ne+(pS+?Y5p@D_ike<)f) ziLqf$6jL%{0E(ae@d4(_ZUPcvQn$91!hLPg1;TkGwqA$Uz}u*3+GwjNcl;_Fh4Q!%VvA_Qsm2- zePVo2+=hq~1V)3zlGX7-G<~f4Sr38;nz%!r%s0H;f3lu7p^`|VHYqiu%-NB}(9(Vd z|B8Hhz2Gwy0sVBF3P9JZZx{%s^p32gGGVzaw-CvWN(w$jFJN|o#mT#y;Fq_jr57F+ zhzNQ6_Cozn-VS-)vk}Gd|egFAEiE4fk-lNV}r2d(U0eMlla}B0YzGFxX z2#tZk|Du3qgdxjV#j7Qwg)&DFd@#u(=JSI>)>y0MGOqYMrT*QwAh8a%Ra% z10x26K9c)wiVfBWfJDCU3O_Vv#Mwd%N-UEWZDNi!p2~o&L33YhChzzPg?g1 zxwcdJOyJAo&AOElke!4=>v}L08b78gsYd3}hOE&T$tyaYIk4ZZENG7@nwo6+?Zk|u z+Ihp&M7j0kKXYJWJy!NO?4w<(DSf|TZ$k@H>bJUb zuW)@+oE@^nt$_N)NwR9}Ipl#mZ>^6;CUG13T2i#8bi~4qapddYH+k}Rh$}kPHw}t* zrDB#$O3}ea{q1sZiQxl_4w@m6Ah$fQJ~^e_g1tpW3#Z|t+aBpr5e=_%0pN}^?8hJl zc-wn``8HkbFOa}{37m{Hj>B$u&_1`E| zM6y$Rrf)r5Z7H0Z;ff8Mho>GlGeIZ}A%CWFY?!w;FwUg98+H1D{(c;nR%J zYgz9!S<*$FLJKgiH4PcS2BE(n{G>Ue-n zd}3f|@+vThj)fO>QVY#x=sgStbs4;-ktrGGZEEAZ6WQ+8SlsD{!@M%izEryW8Nf%y zko=XVa1;~ND%@%ul=5TM7r+1$u!9Mv?8fL;biS(Krfw7vFlGF({VU60ua(QF+n)_U zLe;ur?wvDY*O(GaLV-UU`S}Bj6e=1bq*mzmAsL{X@_K0Z+F;0KOri-MnOVNhhUo~} z&74}a-Gr@xi{rJg{Z6ODe_6KYdsF$h_9w=O=4k#9>1bhutr3aShStIz!sO!3i0~(i zd#@PT>knLGgE_4My~f%yLbifWmlqt4FRT22d1RRUl!+S4$%oY#f8(>-=YuZ)k;JrM zQxeB=ZUNDRHW7)P)=Gr>&AuGk6HDA zx8(Lqt1P1l}~KPOW`05x$@PbH${QB}B@ zlvVau%waqWCiD6^I5vS@ZEAc>K#|?-6Q}<`|&h(_cVZz97*@*c=~_L z^Xa1~)>}{a{%6>ND zHFxhfdi5XC)4I1;al#ms(=dY3m8z&ZVoL$9x9ZEPWpUnvlaOMsqH= zpH-TiMz8ecBqMrWbpb>wt=w+XnwSd}+dqc+19ZcQlI^Ip2n}Dw$$qbE6Tu%eLNwoP z1htYXigSx;XHeb4_HC*0fA)P03P(V#pD7z11=&11UY$=EY$nIfo_aoaehCX$U%3kW z7(5W3v9~l7_{6<$_YmjfHW1R^IaI_d6rOy3v~Jd1VhZNXCLK``3#HkRF}+5Ycv$53 zdDJ8PHgX;@B_Xfxcqq}pb1(T$_x1YD!FC8`bQtR6>u-;+yx*M^|0#TsgFLjZ1&Ow| z!)eTXZXt4IV*cvg5;x-)l5RvqpXxa01*!`!lap=>*N zYf##wTC9hoBo2y;g$z{(zgqrDpl{QqXQE6M3De3 zilEQ6`1Jyta#)^9g|*MCm`fL0i(9LuZ=y5?)_e=9B_oj`GSCdGY<^ztJKdg-}rc64op3K@`B&>TZ;%&gju(=-Uxq)sy?0e z>dm{6Ol@eN;A>!;=StY!dj(uWJ+Q!QX#9wVE(ELkq*KO`xx4L=v2(CHcR)8sADL-4Zw_b7#6=!c(EiuDaEQ1AgFIFuY@KDGl&(x> z4={WXxk00dByl|Ioi0bG7(B-*)M~$M)-`hU|@U2A73bqrj97^riLJZ2WTbIKJRLvF9ehz<0;bPI{X2IV7{<%noNihJL|vKK0ZYR?NzV7igPcU zQe=nUQuC!7B|?^bn*qNGbb`K?b-|xxn7du%hQh)8xt*8I3cMo%< z1SZ;hSk0S@5~#1T_Skh@!T(TX`8@5^d}Em&ZP4=U`_E1vgtLqrQ1P()eM(UUXQH|4 zx)9FAm+s&2J*Q}A#%SW_(=id5@v*DjsrnRWmOfcmOt zOAVn4AvU2E@(djQZ{}pR0O*A3CGA&}rOj89mAVI}%Uqme2l!1^-i=u=CxQ}Gc2xg@ z9#qeZZn?|RmlS8G(+5Dd|E=lvCaqMBJjAIr)~+0Oti)0Osq4RPC%uf&JuqJWy_~Cb z?t2NBVz2!D3#EHVcIrCfo2aafph{WN1O+qPOaMAXBf{ziz(rp+2&3P9-j-cyuok3<1IAl-u@=;v*= zu*SmTo5I?-^1@JFm83vR;zVJEsrXOR$8 z?6I)bY9GPRRJ0)={~&@NMA2Rfqi<=Aa>b7p#}9Jon@-J8tRAS^QS`Mo6%`S2x%71R z?#(N_t6(is!+pu^WQkMvxt!jV9~8;;&qORQ&#t@jbHh5k%tJ!{l)?ogn9|o&ESdKG zfR67)RG0=Za;vAES$H6^Lq35D3w9s$4DV(y-L-{_oq`p%cTw1PYk)h>q~ zNkmin&TNjJVyz{M#k*7~ihgIf#=e_TTI#%rpbE;)`byAut%A+S@|~f3x|g3F|1usB z+lj1Z4(uP^&-mFfGU8>oJk%aJkghn| zs=me*y>dciH@&>_WQ7SOI&`jM%gGoTUpzV%=k2km+#IZKgVynC1iX33zKJH9OzKCw z&6K=sJjf@ST>NI&*Xxy20U5>n_zA-oep)9w8CP!LP)Z=!{I%FeDV)FV#Ys%qRW0ae zoz)7yj5LN+1oj&acOCz~CQ{MDMn_#)d2+T_@Gfa@dPBC8cnta>DHxG&-r*{KfD(NJ zz@Hs@W;E5BmRG$><78X*s>aF#I!q7!1rYD5UP=OLaK-e+c#P=wQD@K@VL-oRbh0om zR(+CcOyx5Oyc^Q3!N-$T<^Oiy#Z0^6L^}gs=(uRA)Twhe#`Ir+I`e%U_i|87TVqmi z(N0QP`p4x{1=6m7vLrWJ==6kvH!w%=) z+DebLD%IY*nlqqDw{cMbAEVk~V%>P5b*K+$CMuW*2@ciR42?1Iw!mLp{0(`^U)TD| zr*W%viKzJJ{Au$i>SDaqt#<5zheDYx1#?9-E-!j;j%@VJuYRJVPnRi+^#R$&)1raqe|2m@6Ab6XTvG~}r2N1_TSM2-EmoSv z@?EgZ@1(Ve=`H z4yisEVUM>PY?L44=dVrS!WG|ShHM;19q{^-f~yJ!yi~E&kVkXYT&Z@o5J)N=M2ktCus}vxl@*- z#RCP~tnRBTQpwCJmpU01J2iCQ)D5H^JJ2@YvHNTpuZqe|&q9#OI+6|~r-`4C}ahws`S$e0(^ zGmV~nM&B-olRhd0GReZ~j-;5(aBW&AXZ+fupzFS6@QF9M!;=_z`P7y5x9$c!E)fnq z3Uqq-edu#xXY8W6C9$n|%wVIiIYTI%w6KS>@*RUcCwVVvZ1{Y8>u)kQWjsir>6uQ3 z$&WpU@aAFWmcMlf``U1{>f+(=f*2u{E<_NM87)RNnqYln>8x3%V*Kg_ZktgUHEPMR z0a}VI0(;Z2S68!z8iT&)aAk1yS|ZX27}w$!^zix!z$<$G&mFl4;63ETllj3{LWpmC zXR=13HaWaRwWQdSmY8Vd4wGFHN&E*W12hx4sC62^?bi7jV`Y$pcoJZ}E~k2Z_=>~P9I+I*kUOPl+NH?bGncEXuXG*BZl9qd z9Tn`9PK98UpDE_C+!v%>pWei(7apUlRGT#2Ntb;lbe#|UjzG~w2vkIm@>6wk5z1`f zCtnC&;FTpkxtqftav*{PngC)TR<^7k7Bnd2Yh$r~Ih^{Sw)M^tdBSlkfWQZDiTD6R z$0qzBo5OIY*k^&n7{**V94Ez+XgdlqYvZy#OCtXEPcaryF})AbanIoIPbW zB5BgYY}#+ngAUEEl@5hDKy{InNgtu>r-9i90PS?jT}Ty=k$rS_98fdNlbu7l13(tT zI)m_BW(fLLOJD(TP{|bH%o49J_0(mXrNdi;-)KFi1S*LA3ZNZwVTr%3B!C2BLHJ<~ z$V+(+LP#JcUPeEhegzr`9(<-nWo$xSy!LZk7>}_7_R5pQ8TsYuqX|RWdsYQ$VcAb0 zVxBQwWo0C+K$_JaLIKV%0;CW;K8kV0Hu;?M8PTY<#k|7W?Vpw8MR&-;rOjY3ludhj zbERyz^MKgjrNo1~T||;dSB?9-N8FwgPtd&6dgh#O7Vox2eo}(}5%f)QV*)Yfm5~8ZWXHuLbMAAwmJ_XhaVJT3e#S11yo7t0N)AgbgJsIfwjAs~;tJ$brcPb`}-HCxR@Q zgMQcOsL-y=ZFrBle}Nu9jWPMfrg~V=6F-?RsjNaPCMLZ9vSTuN5@(Q;)c3C{HE_agV{6rfur$CvUHVre;Px+AjIRE7NnvuK+MAk^r5Q5uqp4|Bh@b)Bf1< zMr<2r*GFmzrs}}(3eSRo!-_!8Q4{1Jb5qg7+tEb_Ug=jBipI$BV66HJfid+Jbi2^R zEvAVkcEUeZ$#oInZCC-v5H1%vdrx98yL55Q_Pbpv{hMdi|G20oKeQd($+7I8#!R2QxLK|? zRDmj49tS_wk&&UV$us&`a>uW_Ymu>E1n3r&412m=a(L{SL5~JLk2>%cKDDUAvw`%^ z6a?43tH@vF}AkDq{vnEi^lm7`|LiZ17vG@A+37D2Nuzc-c!M z4Zyu^2z!oRAY1e(*6a>b{N%SD&;qZ$hm*mfy7P7LlzgIbo~%9YK`bI&LdODzNvm)oA-BcCqHNC)4iVj= z$!ebLO74@z!kTg>N%2wPS4j&jgYGUJ8CMGR1`2_42L(M&_Gj;?)S_|5i{tqTnp3`? z`M>KHva_NpMoo$INFfViqD%d1d9f3h56)rXGTIbhqVbJbr)-Uoji<4gfFu!xss%wR zpt2x^>T?V;^gY`+dKG0OI3!zZ0A-w}Hu9qT*bxUhF)cDQ;$J|3CW~VwcZM+abl9Z7 z>72gvR*VR35*d2qgbspjVwtaUw~6jg7_pTf7+5E4U$qsoz`}jeqII2 zMfYQG7D{S9^9S^aElI^vtJy98Fz;yL>?DU1tgmRvHz@r6@n4t&nW&)({a0^GYFoPI z3=k#Ko!0G}y2ym=9z44CXi`lP+;yf7(uT#)z{1lKt<^x}A|-PxS~a6TlNmBi4J|n= z8V%&yctGH&FlAi0toydJk0)Oq`W%f~mn>WsDb-fT%L3%Q%GK)zaV1|3eszT4pPY9! z89<%Xs&6S3qNuPm}J(qNIilwp#5Rr1V2h=pc6 z*IAt`gFjK#DTf5XHB(-1k?FZ*vt938IIq8^q(f7yjw|JoH(T-ez>@Z$sKyW*^Ph{9 zT5)OsKf3x(5BJ-Ez{Y9a3u(A=j-x&pg>BR7$(+#AD#ekfCN@eRBPIv-cx6JvNQdE8~MbOn3f z?AUy_#DGFTM;(T*>d(;y<=MJ@d&{!vO4jjXMRm^{t`GjG zl^|m=D!gX5E8>TBuc^YN{TC9jWjCjb|Eca{Uu!OFpCim%nK4I;Wyw6@wVz7`w!S0v z-G?F8*g&kLmz-L^1YLGh$7x(g8;L{<59f8W=zLR~gNGO^ilS5TBaxbA-ro0}=W3jLi{Z?x$o0Rn2)dO_tVnrJSZ%!8&OCsZKuJ9f+S)KYR zYstd?&NJ{%q2mM=judO2&kl5XupVKRoNB7$S8k-Rr1owrJ?s;T?Sa3YB_wXp{{_sC zC3u<mq*Sl6Zh2~uw@}5)D>kaeRietNf%t_H$AY}?m9m?l-fGf+Tsfz z$|dB!1ab2SE=)>M0*a_0A4r@IylPely>=~{-5S&hOuVh2vHW1RO4e6M2aE3e{1`zh z(>%M<_58qkrf&UHvoAe$Q3btcnr?QHehT!iqvi_A)+bgr@Vg-8;G%wfaXp%;BLbVN z8ZGJEe*DHQ?QITA*GpHYHiD>r6wNfSpo$(t%_GEGWs>mJnIQ0~)U%M+W5J2byy*p% zs=pZrkDKs`4N-A-N(*;eLium<$Zlj(4A$u7$kWGl?9LFkMow)+veuBw-O|9UKUu!s znDxy-tdRVCv!qican`w*V%>5Y~4Z7ST^r6La-NYdyyh+Pt{w@QY^3FWMlYb&AaQ3ti}94|ky3v*WIVuJ|oS$)Vqe z(2K>XLaLk*e+S6ToBp7q^xBp~xtce>vosd>4-gwWb*pI)HniWD2WQF2s%g=@#oqD(yHJC2T z@0C?xPyNR`+@sPz_;&|U(m2^S>i_`-1qNZrX)(pSv(`rh0q9ZwTJ$CTNTfm8j~gDh z`d*Q5P!G|9{@J0geSZnk(%lygo-LFUzQr||QXjJws^14c!@VWMv3ltbWLQY}R1G+Q zW{vH&M#uX|hQ$Hh&Jqr8$$P+I^cJgQh=KhNsQ|a!nO9YDO>xjkhCh$K)89wG%{HQ6 znzM9u1C zP{`Rb^vd!UjQU6$5p5V~>+D0)(Zgky)EP5XK;-u#; z*}3Z|`D0)bDzT%3eGr~TA6ypZZrTy+XNa+u5lF6jlRln`dT9eq9jB`LH7nGo*7hyT zJxDCdgxpN;Ym->W6AmWD1HntyxIprM^|f?7tvxIGtd5sEBwx^WvKo;_RW%T>X>lC1 zsPtgx0)s;-uI&j!bW#09Tp&}Ky=^I-$aG($bvj)cp&Z?8d5Ol!)x9(Oy3B~Fqh);G z5Cx3X0J1Jc&UvY5l4ejcgxEyNIyd4_q6vdMr*~W})Yy6$Tmr#=6EXg-XD!^kHZ zZPnRdZm?rt`@jqHVp)pvBe?86H-jH77!~IG`u*z;n5WWZ=OuApK;)LYTFgTc*DjY) zp!C=O_SJd)nZaV)M*hdoi~?oletzftr|fUi!a42eJ97$Qn22P+pQ zSx(XCHpBEJ+22#e6Kb8S5kFn(7sS$36Mdgm3}KHA4M}asF<8IXK{9m|5176gEgB9; z|JIQe@d~%qBX((U(ZB4S2p^LiOn;i#K~uz&61>|u(bxJKSc@DPt|v3oFzVA?ll&h? zR~^^n`?bG{V$t0l(gFhp5+dDQqog-VMmH)FV}#O;bVR0%-Cok1}xMu9tV9OTq$prDUwiSnpZ$(&IfMiMb1Cf|MTHzMU! zfS!P4NGJCouSv~*K6+w91(R(1rn6{T_DAghO9Y>JH%1apeW~*Lsx`ps`N`Oyy}cX_ zJ1*~=D98~#uLX!G`53fqk4X#kS|b##MpkaBO>Z7^a{~)jq#O(S=SOxFA}Rv5N9az8 zk0IXD3}j{8@|67kX!GA@xBQNi)gtC$5_pM6TK$nDK;3@bBXsLy)vc5<)$`af`m%j8 zy5&TtJ^B=x%pn}|E=EjXDWr=!yT_;zgiD}8mvJ)TcF;cmCK_LNoGLK3_u1_ak4F$+ zK8L{<<<7~;(u25=&x`5_%{f$VMGtZcO;Vo+FxK_bCi4B0#p)kQXyBsUzW7mSTvL9A zk+de@?o54){b~v&O?p5hnE~kZ_*r?1N%(x$Swwx|ah17{w2ztNFYi!2*O%7JP>GDx zpKH_8V7$XedEo^h%CbP>DI7XASsd__;PAcT&Nh$Vuto>@P_Rd8QT=Yk=~EGv&BgIw zigZmqUT>z@j5cr)X)&Otn4;~75Sc%UnN;yN0(Ybyh?Y|?^aW7LJeu2S0&e+QB#M*& z31RU{DG@12` zYK}Fp#M^!iGxtWEfaeTgT%nH_2njjTt7T<7ye(;lrK z)gRoTr~e}zXE|~4p>1Az#n%p9yLHOS(7U)g94@Yazg1QJC+B5y`Yh!`v5M!CAf$h0 zKyR8(OcX;anPpm2>T9-WT4IlkvgBf*0kk}%_jAMCX|3VE;GE-u+KI$*<;3aMNYy~8 z6h$8qzRD^6i1$k&W@S4p)aHMnnDXdIK5p!^TVg#pU821Utg$kO3Gev&V?+r_==SmR z?fUT@2D;3jdo~2kBu=0S2~D2Q+xHE;WaqGrBnp)+eJ@M{9WSy>Tt~WIRErr6wc4DW zJQiX39mL+CyVBg}+ncAL&Sa?(BvDMcsot&i9XqPV8#o|aG=fZ9H@n{4*qnlDD^i-x~|@eD@b}?)MX8cIRCEMN40m-06^w=7zMD!n?hOc&vf6$ zOcey<@x49B*Z4yrhoa7pyFBL*z^4)XLpI`^C!@IG%by!YDOOlxis!;)vAkJ0P%BT8 zGho#6ge?OOK`D@9n@KR@jClc^d&W#A{URsfx@-&%$5)scX{T$_L6`u@r*%9R@5Qgv-^- zze8hcI`kw4=znHesfvNR_>tV0s?n+ro(DP#fh?AsMZ`uDejVOS0tPrhTY_^=qhM%D zy77Z63Bed&rDu`c*0ra{`cVW6Zfgbz>F91)2r^TULW@#VZTvdO1dad>$+yK zS!SyG>(V06_&(JrLYcj%$fk}zom7`}0m8Q*bE!Ta1jDJYc_hSBd3n$8lP(^@eKE$r zdY1r7@sYZ~FC0rfR+o)5xw4_jB`gG+!1>+^eL6@1$<$QSCl=dUf(iyu<6oPT*PjV6 zy+u`XaSM3PVWX+$gqaCgv-RJ`vj0608l12~2ivujboHIWAQ1eb!@f6(Ddviy!JPMk z>`Z0H=YbIQZhLeZz=HhPrW@t8$%q(=Ij2RTL6RjPBzNYDqO&vU6hM~QSi;htq%}pj zqVDWy^H#k(4|tI5clTmh>>tIXk+mKutaXFD^xe1Wt3npNK(kYQ`^GoC`2k+uOh$YU zFY)Ushn34BU794WOP@FPlj?+c%} z_a*PIG*Q8L&uq4N6pppPe?2Jf&Vm#VRb84OV_nMmq9YGh%^rsIJ`e+EP-km0YR$!Z z{d$n{A(((tMKJwyGMi#s^b~r1X@c>w9L6x|^3)jA#lc^!)mlI@Rz6}yBec_NMy~}# zXxO5wXpPBo8D`9;jsS&iA5Vc+fc6FH*o%4+SP(Z#xibD3X$QwG&i0&9rf#WojD9D|sF73&4hq93lUTdrJWBtSDQ{#^J(vp@IwN${K zUJFNDKnE_Y(Wm&^`#KdNp8VY0!;ery-+4#M_2U+3w@;f-16S*tf_`{prz37IZow~A zK7487e1%;&4V80&e%_`N>_07H8!y4Vg&?*lGqO9F1;o7+TNd!}dsjo|O8O#V{O^>~ z?;p6L6KnOn_;e(1Oz7Hl5SL?dbqbsE+)Pd9Qfz)2EeWEzB1lsMXU6h7rb`*e3J`^r zO(Hlj61SpJ8PlXOqgxQ7@<=}Za-rxYzPB)cnOohLk47Oi1MI_I)|`CSzNxr1Tnae9 z^@iz2@J2q_yPQ^4z?%U+^N{QRx>|RMdN+B_#4B?{QSIwQML*>my zjssd@W_Y^64NpM&(*y&8onm}Ui4A3&-Lm>S)rlWt~Qg5J@$c3*L%K}Ur`z$*6Ha-rakuhN)h#nL|usxO2y z?1m-gI#v!>O*Zni82-PKZK0y!fN;upMenJ)(|#%Mx*g>_nG0y3KlDvPh21^un8qke8y=Pq&Ur44|J%3_802X4njk20Lc4Eh5YEf;dy z)s{=47ll@0A903;AjC`+No8vCBOH2o?AnkzFK_-i$*vWu^L^S1H6_AUul4c_uJPD@GXvIHSv`Fu(%T`CGHZ5V#l|%dg ze3R{1HqaNH5h#hH7xor28YCz(`8%WJI|Hql`F+1T|FST3VlQ^#XJyy5x*4{R+Um+|;8NVUQ z4joUAdZmrz$}KdepAqaxQ&wWefS%RGfmhYkkyCl?v6O2YS1HZF}lxmw{Ug>@M2 zTeOUa4$XYka&(2C!1)4tH8E0OCsQtCwcw)&k09&k3}C-0tQv_sl~`$#wOd26SY;kH zqZ4R^@JQtF0Mwu0s*E)GAO(D^)FWu5U8B!5k3d+?m;wwzgVDk)jh+_fxI*?)J=?#X ziA<4+pzodzybV}>tJM*bo023A$&B5nDTQ9wgAD3Y$Wbo>R=7`o8a8z%-nu7krWmdE z2n?=Pz_k^4yNf}<6>K=-F?m7};bwR>M|UU9OFyh3$) za)EY0DQm0u6av>;inkWetb!7c#Yj07BcA{%&;y7tKA=LB1Uk0ki{0sMopvCab0Qus z{Fslkt2&`Yda>E&tNe_pgZ6Z?_hP0oHLB5wmsPqlJhJ7~LNd>pSPyGB%9BjIG-H1q z341_uHpO9BRUkX;%;CM|gs|jdrV0Fn>wwTI^|k+=J{xm3Rm7gWZqFB6`2xsWjWs1% zQ)9UR<&g(8nUCv|{vy$3EuZ*6)m=QU24ABGfBysL_Q6hnP*h^HU>HUlpY@x4BH~z9 zikWTjTbD7J3b;EL=II|pDG)eALl{snVVs+g4&CWDKTkq6eLoX&+FqLVWmcHp*!VJ3 z-1gbj&dt$p%JZbnd3_JxOg>|FuQm6K*YADlW-N*i)g~c|M;ZQ(bb3>4=-nubF|NNyA6~?1aAMT zIy9BsjlXh>AsNi6@xmaNN|2~fR=;i%%1od!dFE3`B%}W@56@K8K$vwO(a=LA&6*Qu*oESVOOFxG$FL5 zL0 z!H>f#vs06!QPV6J^XaSO6Ym!|eEDeV<>dd4#DYTw(^-`lI{SvFp=c1#v44LINB-M)3KXqQji}JU2GU36ex$Oe(Wr(*aOGHo z6%)7pT929j_ugVfpGbeqshtXqd|`lgPhtW1`I4x?)HilRQpVUQ|7G1|c_Z2tT}-3& zDu?~rlctiAK8G1*c$n%RIv3LO`M67x^sZjh{JOmCMk;1Z|A*9%0UmXE3>PI!FlBRJ z;h;c6T>>HFu1YFWA&hqHGfju+_v5{AQ|$yY;p3$mQJuJ)5;?p{;DaUb*PPh~7ekEv z1ldLrP$V@_j@JT>^2aCHT6FUGwm-k8&N0BkUuWO!MCsy z2yb`QG&m?Pd)|DOJ9&MFb*3w>+bU+^r!aG0Di&)Keq=q0Z~Vaso;l7pE3KL>Jxt(uqeG0)p{zd zj3vd)>>I zra)T>GBSMOFqMWfD^X&xcTWXk{9$g-wANGGCDL$i zEv=V0-7)eKExG|66It<Z>{8)Dah}2%r9_*XYESI7!zEARTpF=Bvew6 zI<(F-8Zvr}i!Yc{XiEhbWCR$OF9iQF17G8d0pYup2$?e`%wr%-7DF1K#Ui3S(SJ|a_*lq}Uwi93 zA$B)l{jqoI$2IxHGXFqIQdAS*wc1$Wc8Cq~D*@clbP{Q-a69)!xG$J}uZi=fQrvqr zarW_O;`J=9PrQ_NO^-^``)=0Jhi7e3PY-r_@Gw5KTWl@rg#QZ;F;PRLf1qL93)+kK zsc#O(_L(tptX1ME=k9xw(Ac0K&aYSK`~>P`ERqYfhI_J1s*J;mi7C&~RYMz-l0GbL zL2oiA6rQ4c0wrIQk)MNqHfD+j3+7zjX=jx51#Q7IX~|Eqf3<xAu`S=s%2qR@tI>m0f@`POQeUf0jq=`I^`c7p z>ilZ~Go5YV$(RcQFMO3>U7)(g&(wm9aRe$}F(sTU*0;B(VuGRBjupK#E_Bo$sP^+l z_cFPSKG9i(|8k)cFq|f02x5+=SgrYk6VjAzSUPkyGo^L30s-!DV~dpYDF4=%jCVn) zYQ766Td2MKJ3)S8;p47w;NF{-n*~J8DxWz;sfF$wHbQjnJ~FW*PQofodNq?78YzQX z55KL~l8zrYXJ@|p_c>K<`70vIU($SLa0n(ob?B;6b(GTA6Syq3NnRe==b@t$hvZ?g zCa-xfCz3Knc77Slz{#K;Z%t#-@2emM4>B+tX0IIe<@|9SXr@2Qy^mG*zn8jN+ESfQ7=y0IT4T$IG9G&QAlDf|T;Nl2$d5Br-$GTW%96W$6luzFc}E)u&xB zwRR18Z0sa}UTL{0gOg)<Fis?j?HtFily#$f{Z@?kMN|BJ9Hb>yitq>Cf_PnCx@{05cb=ZH)kiW`balyz>5 z$8DHoiG?Nqtt>Jt!QGda%FbAf;!LEeiMqsI)tOlE?j!Cc*i@Fk#!cF*^LESaVQ|wL z_l^(n)e22~)zeMJn^hL$F}J-GeRyx@(LOhp9@{-WMJ_uq?F}j<5T_?^DoXm|ihB|G zI*Vp+GiF(8@WzT?#G&`$3+qcYE2fgVN?TlfM(H@hNNcP6bzn^eQIm@D|Ecn-z8r(e zftr|i)e9P?ymXz--FAs=KwmGO)0$pyrETTOML0dN|s(HVPMdPet89)-*E98$TE0rP+k5v1a>>5n9X5euo2iC)=3NRAV4BYdL^k6X<6#z-nIzwh%BMG%L$4NB&5Fk_5~$%U&8kVwN;Ns69sRk{P6GkHOFwr$dm z?~zDDvu4?Jd4xSM;~OZTRY*>;H&I`pJ(c)%p6Z5YJ=WyG<&Wig80gKp42gZZ>{9y_ zmkQphNW8iFILixxBT%m$I};;W30A0=Wc5(iwX=i5zIZwm5(jtCfD}6eMw z7YH`l*};9W5?at%=iw)0c=R*6(Su1F2lT~>)wN%#PJA?~&QH@h^Ee9HBL$>XQ;fr$ z>Hxnv*#LgS`c;GvW#uRgu6|V;^0K%d6SqKNbk0Lz_ccBf|2!7IK-pKQGk#tk$=#US z=uD`Z6^k=a50`+WFR$kR=Nbhh;F=A=h)c_fDD*u-ZR1_ezd$P?!`Oo*r)NlxAdo1x4o=pFg^^OavD0T^`h9Btjy-c-%0pQ+EAntdn@Apf(d2;$TTThlB ziM!QF0G=5#%m0%AnQuj5boZ`s<9OT~ewl;SRK$-3eA(Ik!u*TQKEqB`YT&^-@;up} zx?e3#1OBk@W1g{}u}U4eBIync{$u_Fld>4X&%2@nge11<_Q?w*Uq0Z09?T^ur03-se#9Y~-Ph`UX=j^qiEfNJzn_3B{8Jov;qMMMcn&Epyx3J*v_uE zl{m2_sZ3n1qgn;Q*zf1E(^W~+0?JWso%7&d;lF_8xHAtEVALppAs zboZcn$!q?+d(w(G<&tmOe8POYOqf^r*e78Vs*eCL80*8s>q}{Cj2J6mm?W!NS#ggQ z+DLRj1j9~D8L_UGLBl>1!XKsI5v-?=BFW)Xqu~12W~PtANSwEU?j-@U1PHXgT^U4! zRjj2eZ2*gA)_W14`>IwWl(l2Iu>zj{YaTT7Kz#Ik@_VuhU-fJ3%fY9$+vaaEu6rCm zl6$|I zrj`yvGx-R$;OuhJipw7~#O09=9t8P;CVcQgC)Ohp!q-F6sd_7IDVHkzd=SJ@36_wI zP>VoGfd_jdWF%?EL%=HinuXfV(!`7|9I0e@!aEVwFc_7A(2`g_Cr_r@nyo2;_5?w0 zr7{pBc0e3=#HbSyP$nv5vI#P#B!Zu> z4299lC!JrLb2q&!oqz~3hP(wj%_F~#bm84YXSxBxq~K~ z)9}HEY14-UKVD=5qVbb!i%qxp)qgpUb@WYcz$*r0dl4KT*3@Y@RWcM`D?3#G^z4xH zLaFJ|m&D?VP#0;xK61(dUQcn=I5#5E|a&M52 ze9yuCK*ixB`k<7f`-`+O<>sN|P;RfU-vtUN*Mb6Z@t*rcVu5D?dxLlOruQBOtiCbXkyF z?{~~ye0z06n)HU2P}f~sF(p|}dx?8&l-l>B7izfo$9-t_+4INja;+Gx$;}>w{M+p{ zttcVWHrLyl`Irjms*H+WPe(yw$xI2|Hi`45f=uhP0lL7=EZL)OS(F=o*Y{U75gWh4 zdc}9^|27mEbI-a_rc1J56B5q#LyB#yb<%AKu(tR8wpq*vD8#b~Zt{JLSIC#t?_8wK zmpgucpB_IsSHbEge~XrD zb1eootSQ@1D18`C+7=o`zjQWkYVl%2TKEU)GS`Ur*a^Gr`?@INg1XSrY&w&nJrwhw zEne)sA|aS;APtbGUjOr};n(v9@)Vha--&pJml;6oR4l7~>sablUkmc<^+dWe(lO73 zu@*oYj2t6%_e*%N%I9(Ijka#34kH20W2`fU{~nfF?EX%|<3Di#e(h{&1+)C_CZni) zzMaST#c^x*K24w1Jz==BXGO;=VwKfk>;9uYNZiBJ(S=7WGq2?Qt5QWmL*Xp)-+daS zUEeX%SbAV>AXXm-|tWt;5i-(dgfbG!Fdwr-NbsvW;fzs)|om9C4uW3Fqz zwbXW!_x>W@xRij)ua8x@7wf$~DmmX-(HvNNHYVZccXV8&;*7Z;Hgyr!1JHFUxP-CT zmWbHU&EmEhg)y+>({9m@RWrfB&nl@*XcEUI?A@@BrNy z8zK|kz&umXrYDyOSXdl=3jU4gfe!?(dKU%z7x+8F0oQ3T<$EHLFMb~{{=D$1*l7uV zQ+C?-k5SwyMyV_U=U%hy9^XOgLT^*T@au1*sFByr;w zWll*G5HZ=yDB%u;r3ct6B}x3v+wjL zJrMPsvI`7i0@ZAx4fRe+MlayDLvbTp=I!1K42<+5CxyezuEz5$)XR`Oj=!T}E9e!2 z_{2S5uTDbwF_9%ZGOD~!k8X4SvKGF{n9(d(c5Yx6)7oA;2}`z(3{az6y#1FY`t~xb z?TeGF-)lUj`aYL3A4ZqCQ8j4o;M9et=R0sC`}={vVAqfA)Xoc)^i34c*6Ur>gnXgV zaxX8M4-gxa1?+%rS*%MN^N;zKErl-aTh^Dxawv@BnOzxIW5Xy2s@cNvl^T?BFQT0o zE3v2=0wD?s-so5rd~ERpHK9wQ8sds;xN7x1(ZO+F_)*7hJ(P6smGr3y{^@g+81!`e zVL6K1D2Ue)>zNhj>MmO~LSpoXE!5KNd<}ankPHiT|As5OyzE(xjQVczmG-57<(~RJ> zNEsY1=JOu;U!GhN6c#phwRo*l(q9H~{;>L_V)x<2+V}kFvv%|wOLWs0b~qDXxG${Jn8NAvhYsN-<`e3-iSYIlq5)$%k^&JA1WZ_emf{+~pBY5jRy zw>-ve*WHldlfHW19s{jwy6+?JPivazURqqei{|w83^=*(=w-8$sFW_#D>S99eRh)mLgaFy+X$@Ek zqg(7wd>+^#Q?AEm@XO*17qyvmy~;L`mM6Xk0sMO28?%$6mfI~F)7tt|&Qi@ez?<&VzpwwzhCZLe=zgD8 zRcn6A)9D_P@M$w3}Ac?&mHem{MYr?}Pc=2suD(a(x z!28p`_7y0!`sC(FPeXzb>w6i#pMgWZ)`#5U8mwhm0#)0%G@cG+8HEvUI_$+xzO0l* zosUenKrvvo8)bHb<^toIDs~b5s{Lsve;6X|8_xzp%-t&8Jw1E|@&`S&pb*-`vg~MD zqmD0q;wNkBYq<21*{q1Y5I5sig}1WkV_h2`I;_cV>pA3m)Xij3?vodM_YNO_h=3J= zM&@#|f9_!65@`(h<}XvP8revpQ`$+2W2Fc-p&rxFOjDDq=X4#2fVn46uQ6E06E9?6 zs#wDiH&s^8OE*P8X}aPc@kA%yk(%=tKakoE zlXKLm#D<^Q@|#ml+Ck#`%W-o?y;SkB4i!>ik12Y^TWJNNM~NtTql6Vgofb;&PiR@H zT0c`(S$|F~{#PzO9#54uZPFhSa{OvyY`QIWh7)@HXp3+~KC~A4?NmWMGB=-Qsn0jP z(HBjbKm!yz8q#tyU=<2+=e9Eta6#Vhz3Ve*G{gHxl$+Zs`2TX*?ErQvnfl3*^SaYn)4zrCLvh5S--duCDcy%Se%vn z(d$pxP!tkd+%Bgpm$02c6IjmkGAK08PkJ$1TjSyxUnD@N_9(eH^+=u2pU zxn#;{K<)1~e4RYBL;LRXSEIh2jcDaast(;-UqRYLn(q?{*_K_j?IqLiyreDEU9l}7 z9c=hRliOEwydr3>bR0xkBseq%Wug|UC}k?1@E2eHXKqZ-9BEqhw2cD4M#_}r-?q17 zFDyx=OqQP)>S{^GvY{ z(3LZ*lB^#pVDPaGm4QCIaxCQ(b(otY3d2}(Oft{k7O2U{i* zmomE!N5HDNdm=v{i&^SBy5(C}8?vVu6he<35$mbTl5raCGeRWYmbF&T)?L{@n&)#I zT1l}AwkG0}M0_Ss`As{KBb^#Ep5G72EQoD>t6h6^QJTweU4Z+$Fp=XTiHIOZ4c}Xh zfk{yEi%Sug2wG7}?yL`il>$rbj_8=0Ilf{qU8YKKG*s6#3d1as4fZ17H7tkY@n3O| zl63{LGJdg$q*gk9q579xkxb*S%Z_bu_LBXM9*YNoQ#c$r;au_09oy(q@=3JtQDh*1 z({cZ4K$a*@0y3taUUYf)wJyYZ@UL%`j0HGeGpWE?t96QTyB6qrrh}Jow?;dar{$+J zz}S%(?EH4JjhhkKkcxiyUPRgs&*9vVv@QAh%jav+ftf|8+89YdaW{)iYpvh{bXa!Gu11XlApG%H}B^|JM2T zB-5IAvEZsSSN5g=*XM~U`)A5N_QG)R{qCz`O8f6%J}=f)Y3i4JCJD-HP&YBrX<|3W zG?we`=nop6R8|LOg=KN?el8}|H%HPA%2aW8K3#vGuE<(;SkW@M$+Ebc^TgarPq^z5 z;jVqw^$(t`cb~yR6?7Xvx*z;ei={dobI5;@`*H}T9PRraPGzT3+L^4Qf*|g@c!XFL zF`Cd;NsLl^&|?3EP92`-$`FjxTqKuE7Edc(M|Q+kNM(eRy{fM6BYbXZZ1BPeEyeOMNr{yCr?$MuAV(=+vsv~*w`&-o}RxQ z_i*=XztGT9Z2F>sDm}Vra@Vf)`{Mq`)35R2_i=C0o~Y+u8KKO9m>Z4W$FlhBn5 zI#$7trPqU4lK@k1RdJ`hwS)$BgbcrHGL5y<&vkuFsth)G6T9k%8&r4+0lTTm@ zmGsQaceYxDyDZ|eDH$oOI15Uu1v?`WLs#p#XfegtI=pZD!xF%P1+Moe4iYAx^JU+j}S!F*eNNLSi- z=lIPi8T?L3bsy2vz`mu?%_GVoyb>I2_!=DKan7t2U^w zq_?N_&=guOH?29bEfT;(o6=KBf2LaXy^2Rff0|RoSfn0RfR}F_eSBC(@7+gv2dCo! zK$Z+yhMJ+51sy=5AYQb1YVF_iP@8Bu0HyBdmY0l+eRnTu#wnP5in69q;eO)8w=dfk z63cdYB0_v|nYjl_`*|8P19HplP}z#=l)0(o9R15FUJ(ev#~&>kAPec7Do$c$>{H9e z>GTg#&r;H{(*j*G__X+*Tn3>W*0uryF3pt3}@J389QB~x1BEexrVxaWf zSE{7HV9^LG0N#YF;iWwG&F@ipQ4;5|oh6;xonSh*GAA|+DW)l_iOd-l8=7y?{(Vt&xq-mP1P^Va~ z?>*C56rxY@G~}UWp(sW&ceo(+kU1{x#9M2eG_WXS4-Y@8X3>fESVj% z3sH&DEStevxu`?G+!2`wbK7 z47yy}BI%;`pLRO=<($fKB>lDi5-|ru#x%}6*64?{LdGWu21=T)=bz7Pa77*tQUvO)J zS^yiQRK$vD1Q)xpmHB+WalCu-Zi}KBRrAtZvO8r{S5D-n0H5$mRc&@!^(iAOhYJ|S zG~7*{%17~c*q0gPg7&)th?7Ssd+?MNj~y%1U)NgjI*-#WPAW>~s38^1N(_Y7+5cUx z;tqN8&^yy66QHV-gx8Cxt^U(HD&~Xd{rKgyMya!CO?+zF`ZHTJPk^7|p$?3d!gSo) znmC!&rBTFkB+EoAG~C#Cd}lma6cZi@;l(_#WG9WjZFnFx8u$1NMNCMD!YiIN7pm~4 zaLEo`0hx=c(p4m13Kr^Oz%NIhQkLqI3O18)Rt{Vk3i1K6SH>80tPZR@7nZKB(`mTn z4u_A__rY4(@nGJ95T$ZgzK`6odWxL?5pUlxTWov9WoMGT6hg*>iO{fr^^9Gc4=2e=w1;s z1@@c3zJY&`be8p_l&z^hi?Uq5pHnug3;~4^oKZf#KMgu|wm*5AUa{h>1s*wsNGfCykISk-axKW%!&Lf;!WU0fXr-rs zLmCN57mj~4F$}ol35T6*Z-KnGzmvI$zMA~07osCiZ)U_xhc1|m7oo~282ahlEcre1 z>azREMAKzZy66Zdwth3N+sj$^rRtWiZwuSpOHeHj1!_Er3U0~75qw+7Ijo2vCglG1 z!F+d6A9MIiC|X$@-m)|t`3T`e2|5yL_{dLd$E{iFHGODv$SR0QzAJBw>o|Q4Vple+ zW%{1tyHR?h=UBoc{R|_U^JyoA#(EDL5urx3%3o%<|Gu!qpHatK%xo)|1TI7i`xgeFV65I&SmaYNAV~5geB9cyPo5bZ6hzpSbPUHdH5hER>Co z{rrocjrukiU!~n?RVVq+?Kl@Qtd>FT%g?Qj6lh0{ z{;;?XKQS@fR9r1B&80q88OP!J6)K8T-(>)r*AP2KlEvxMT2pcch=r=0bNTMlRAFmfjfdMq=;h5Gykrw z!X>*_&Le@R0a}&Rb8;z{ran|!m+^n%5$L1^`)BKA@Fd=y0Z`n#PsC~c|1n7UXM^;W z$wx;Y+YuZlGXQUG97hWHT2wi2V1IqaR|mahi)O_kf{Vr-)|FvkR^GHRU52b7qKL1_P|b)LZ&8R zLt{Eb1j)GYP5qG&rcYCa2GnX)VWkM0>Q!p8PYbP!lCv0s7?+CszIGrkb|fe!KHA|; zpRV8orInzc0jU$>`U!i2Cy#pKUYyD<3Oy;_RkLGhA29*h62wjj2@$VuO@@7=dtcc; zP)GEBdlH4MtBU__HL=J#4W5S_ANxs%`c%yEUo>wS! zv@LK&>-eNPjlXhI#i1~~cRK+AR#8=B;J5`6=F59dDTv0=7v}!`MqH!-3{%`E3TJmDP*vsrd1{eiMUzvg!*59(+ufS*ovv$K_Mg zreslq@?HWd@OP8#HQ80ww8-D5eCVdDq2tQ;>=Q;Bufj76-8^%9prnN=J!L?D^olh( z(iPVY(dnP}%VU006v{27znJ_9SCtp?{d8FaV~Q>v_g7789?SekMT8WDq7{wVrZkscYLK;QrJ-GkC-C{A1V@QD!|9hXuoyNE8m zYE(z>L9IVOquJM%`Wn6?MaGJ{yRB97K|9@_4z`Vy`t z+Aox*yj*g{EIbYxB=3$1;cI@`ZW2Vd|K6|;ZW13kw~oP=n6^@~>z`?f1LS2udtE?=FEUpWF8gDz7)YbU2-R(&Te zWmkgyTpS~ff`FOhQcY(Gt;o`rElNUA6Xy_PXf&OH`$>rSA|FA_Lg`>jb$6O+l}C6D z?4gLJ;s-ynvEZX&OGI}b3TIBZK&(lnPp`x+eOtU8@n6hT!|90b!apShr4h;CA|KtU zk169w^Kb~BjVADM&jf$sKafa|9^X9N{hLYr94FJ$)e#yfofa8zSIF)}@>HoO&gV(l z-k`iSJDnmp2G^X@Hr`b{%@M zbjfRK$6|3V&VUY-{V(LIb(*Lq(7hFY!qtnNcRav5X0Auu^ zDbS9-AOaUmhd<2Yy<%h-pZ{brtbO9T`TTLPv|cx&IfC@AAe|;dtdJ%uXC}*X_ke)P z5@P)$nUaE-paoV2BE{3kHcrj7bwr6a9D}n*pI%R*Uq*=5mJ+*o{CZrPyBPQbr|fy2 z`G3vA8T`1(#GMR^kstj)Pq%i3GC1bO7584Czh<4IUe7Be6i@cfQ$`++4uHO0R3k;_ z3KF-*w&9+>D0c-aBarw`0@J!$%@WU7yiKOlm21{SRuRla?r;=NE;Kb*RMWQ1!TZZ%@-vra(!b&(8ap7m;3ym zPunjgc(`ggH8QS`5`{GO$Y{?}=l(UT0UMvIO-kj&}T$I?aJO{O35*7e89c$pl4lVg?t(VlE#hIog0sltM2nI}-SFibnoZ72Vii z3@9Hzuf9|A-RT1^K0|7#tL{8U)<=BTfsb4aHA70iCw&$H2DBO2{y6f#EC2fJmoIGI zzc4t$5{ur=J5?QLwU0FJ6`KbCY%uw#>8ri6G+wTKWz!z#wh-5L;TW>mKu!72b3@=t zbR&~7z`W!xr#-Ivq!`(;vlN{Wa(!OhK4SdOrtn4G`}3gBHonugLg#7W!{o8_yJ5FJwc+X(LPUtwdzR%dsU?Lyqlu?6?D2%Xdn6&#@IPyXKmeOKQ z)OtpXqO)buKJ#R%N@hZI$pvlJ~v_84i`ggI{|Bh9%_-?bGe?n{nkrNzL*iKD|e{rzt)FFHS^y2n^ z?QGc3fG@?7Us$YGyzh;X`P)2x(Xq!^lhml%68rU$gRc%bCCTb}Lv$d@OKTp~* z;0OP-I)Y7BqeWy4o3(E;EGS1WkD6Zzb^ISkR~;5r_jOeSlwhgrq{7HXj^W~m>!Zc~z|58d0!8%x({np| z(U|?s?qFTH@kXt%h$J1+j{2k7MS~EFnD78FuNm470LXsz8EhdiOjYv2KiDLnAPJ&5 zU6Uol`nfiVKQDED_NY@yXI0KO*m7=8R1lw^_&|( zJNz)jqwDfoaKFsuo~iwJ4*JXkvABNF{PqMF+Dt`>_~zVd9ilU$weSx(*Q2%n?0L6| zh1v5G*o;}}pFiDjxKFUq>%=^e8vBa>28U+&=iNx~n0b~FBoizYWATodi)y=&N%P zb^zxRof8DbxGntmkE;6jY>n#d{p|jtH~eKVNv%FBcK^ku!5k%Qm%`1{J$Xzs>g?$w zpiqzXLPyc89$OWKH?%gRWTcukae=KBCXzJSk~2{DhkQ# zgcc>>`rpi#|KCE`WO1kiFvz!uLGqV_k_{UXiQgK2u#IhZE z)hJ`9>Dktd6`XQRY#;*oMyz}DPAcRCI2vb4D66C;N#_-a6m17t>N_($lOz z*PP(JM&~l6Tv=?A=~mM+=yB1T`oPQ183c zyEW0Bgo?UIt??CRFUWhhXW-}9gN)CUu6Y5~_We|e!T`Fg3Re40?Wr#T$T%~jNzX2? zF*2=3m36PS(9Re{XA6`k9L`i9Ad-KrJv+59K0^^LrX! z;oZvP?{c?Xdam28zax)c1(_L_h>@<(8Tj7=2Ku$BO=}pzJb3VlP_TD=;%EdXs5~({ zEu+cllCB$wUz8?~=k1q`_zGEm7ONz>u-*0-6lGqrBrNDvwH< z=}kCc4~yTJcX2J75(UpoH9{A@j}AQVu~QrezEF}VPE1PR=q<|Y!1muZ-#M*4`pu(= zF+mmEr@wT)P&z#rdF=eP5=_M1(_aY`V$Rd$@Y&4{Z)@R6A^c==ji_VLC-Lq?28THV z8D)NgxS)34`HCCe^l?TVqjIYGTZiIAdn{1$j;}_LsDR#p7S8Bq;qahU?6{9QgHz1U z3%oVZTsq+R0P%9<`TRS40*6 zJp>L4e4&wCKI_Wf&oy2Id(X-mR$7Z#Ut|k6Px%7F+1j zFdRIQ``Y}Ha0+c$C%F+;;fG0IbHoJ#Lbo;2OfR!v+(zfd3X!-%ELH@%Pl(KC;4$)G zo2WpTp%`aai1=sqNeCYw2zn|WN}9rRQmBR9c9!lX{)?M4(D1-Y;aP)q{II|L>$}Xu z$b8Oy#9==JO3D-!GAiVAQXuQNW4~XwnTlaFq^%hy(*5#>g?u}zSTCJ7RLjenb)2~$ z;M>%FL0`|#@(TIk!u*kXOQ2q-;k&0-_$RIwon$S9HG5;Z#@+hro4(jDv0&GX69J?P zteuH{U-;Ykmurekealb&Dk7PW)a~&K96!(DYU(w1@{@6-46Gzv$GB=DkoMSzo`wO1 zNk}20lOGo!)8pFI73PKH023qxv`F1aiSqreO8+2onfy)jbWt|zJw<)5*%q1RRRvPBZ272%Yx#luVx&)N2V=pGeyM)P!{bV#H_94Jy!n}3kzvJ7NCM?jSj*3IO zPOAqtri8iR_hJ+|V+D`~%Et4;k+zC&CD?AAjTUrw zau_304i?HS`r(5vFL%OL-xeLz0R{;(VS;B4Ry~6Gd93-&VLrIW-_RnlrJiM5rqhun;uE-`zP9n{y{1E~I-}s<=FLcT z(f#edbm(~S@aW%=g}mw#*54{3$<*d1&59K^iaL|?*%dOxkAk5X*qVkcD<&Cel`{Lr zG)f!WE-E6=!whaT%IiIW_G}i;nTIK61sMTF1~m6V#XqJ3QQO)K@t=WZ2eHxm)L_C`Rw^K`)qO_9tqa+{ zXbW0guP%AMFQ>9h(*cKVz_&qm?JPGnWaG z_l?0nD5rAooh)S)`Fw<+Gxi&b3{p5uE9d)8E>;dUAA+krBe>W|s$n0y#3r zAP&}X#0XU7N+f8@Osy(wBJ06l>wsYU zPrviEzS#E}_!Lm$#M~@VlfZJ#>u3gYy^~x`pZ!v!RZwYrHOkU$c4rikT(K)Kx3#O2PGJr{=Q z+*lo76lLgD9C-#9F-#Nd#O&w zuom=_P3n{Nki(-gy)evpTFj3+ahDp2EE7li6iDW=@gr5nCaXe(b?iSe!_7c_o#b`3 zT!v&*(ik|EKMXXVDeMl^tG$qCX;p|gQ8(9SI({p3wZy&zSNQjfwAC0ciw+p88<*+zm#ihnuu+4Ck_qXLW0K-gH;-BiCDViM z$noa0;jrJ+*}jX26x;4do#c93zR5>~z12I@z&GYUEE!&DuPuc~k6N-S6sa7YIMGou z|2c8;5^CFAJ^D))aq|yp(JFOHEOmJxt2Wux&#*Vq#m(uO>XmPpR-)EtlMtW7v#OZ& z;jZnWg`%}yRk|If>G00nV50F-I}29KzK>wFE&J_)9BH6)*sOZuF929lx?g|LKKkO8!L!WyVDK>oMY>DH1E+pfW=w zrtTZG<8fGAb23ignSs(+->M7-pf-9B<|}4*vc0zxxIXAPn+7JLQ;|YJi;<3O<027$ zNUEQM(wLA0g63a+M+;-HKwoMFIg>_K2B$62kStL*vt27EfMqY2z@6^3aj>t~WeWi^ zVc_HT|H}BNXNE!(IJH#!CS3k)jVgeDJxD*Q+h~&wF|8$jeNO`KBBcZpvnNPmo#dWZ zDyZbbI_KsuW5*|`&^!;3jpFnBf{j~ZBtUvg(iEN_z_YV6u)wzS{d^I$?F2ZABPaoZ z|Dzn+R5Hx3$%?5+ybfhIhrM~{X&oO(uJlwb#^Md_xGvAI9X$fP5=re9^?fp`f(!^k ze^Z8)nT9sqj@?|{^XNBIPUIn}u}<=1FJHJZk=`Mq&mxD@9JoZ2Y+WWVu-i;kZfv)! zL0?DHO!S*}+TT3PkCW)1^Nsp8m0AN|n2u_N%oAsdK22BdM9?FKto=%A3ha^NF(Dt0 zp_QTJtjvOmaSJ5-YdlMCdl{Mtp^s(j_}3I1p_v{*urysyH_7^}An(N+bLS(U8(^oQwKQpF(pH`b9r?)ojH`Jn)HChVMd)_M zt_zvv&J(}9c$_&gg}HbbnU5tTEA~IUcWI>f-z_qEl})L^c=tZ`Ht;Dn)q+Z1<-!NqqABy0 z$%({^*W7zNmkCVWUz<}~BvOzDn%YM1goQQe74jaoOr5SM+W1$osATh)T_4MOzF-KV zd@*D%SPicrFL4i7%6n*ABk}!aPds~S{v%bTj+P=rYZ8Kt0*Zz`i~GC_{}HR|pZ}_` zOrgzZhinYcv4mj}x!32lpWsOeQc?fUb3BCkx6o|94>S7^a)<1sx!i*xXRpStfy}Wv z9+f1~62ZMqFFgeLP=>)bEw?A;IKq=q~XP&i)#< zcmJ!Dbxq!-`^(e_cx(ODwcMX;z$Y+Z;PFwSxY!Zg>@)YhbpQ`ukG@nDX(;0P^2LOS z%-YKL!o_3Q_7;5@2o;Xg!${bv zTuU@iSx`goryoEydjKfjyXXXel@mD$#y90o0R=X^S{`mb_x<-RBw(^1l!{4+Y~3~8 zzCAWnU9$ac9dhVWI;9x$YdIytM_YTqu4k9zxlU(-Sr5^77}>={TmH@$k=I{-2XU5U z@x7bN(&KW8xr=l8z08p=ii8x=hvirG-?^@Hb8&|Ov<2;FyQ9X6IMm%yzSz#!$xFMD zFNym-+1TL8cb>&L4M6R2)D5(J;$Ra-HsD%1!A60#a|l}m^TdjP*Rt_Ov`LtRk3QSs z7?da-Lp#ujUR#RLf7P&#(k0vd&Ew_(^NSF~RhrRRXr*F~A5H1_ zV)VaBX9yMBA-m8wQDpkdlo)jE9-4-{4^r~7MN8H>7OIQ3FMXx5Ymr8Cgv_saFZasK zjE+6yGl`^Trh>UzeG%0rV^_d#}{$j28>}F8JKF+XNzgbanr6{Yl&i! zY|@R)y)qE=H%r*zeMF|P&uTW8^ZiMffz*^8zE=kSE0R&3F?Be&s+BnA$XV+W%k*xq? zvA%jSeGqiLCG#$oRXo(tpA2xhDe3?{c1OT)lLK@;#{U{G`=)S9E}=KEBx!3*Y7-8$ z%;7Qn`8(+roxO$AuQsfyV#-wy7D&QyX7&|Y@9`*se*Q)EHTAiDG%dSep*cB2HmH6A zXD;H&lTxD;WUOEticMQGGy(c#jw>;yM6>{xLkT^(El+B&(he{st)q2bW+o0;G&D&= zwILX#TZ4tiJGM8_Nm4`khYilFh_i(CX9K1OQj=N|KQWjaP%9gn*?8tm;CoLTC6>}~M?T2S-uHlu z<Fe+5mPig`Z7h5~$PcsZ)~FE=O;N-ZCv<^1H4=9zVDYOjA!}j^?_y zgnOfyz?Hxc_M*^0L$=-yT5}?1*I~0CUiZ-u9f5MOp5kwOI9%Vo`i07I+pD1P)!#`= zE*x{N@B!NmU`27It{?1&)9^jLGERsvpcr|-mK;5$je7P?O|6>_LsF$c8UIYI-md}u z1;nx4gbg}y%sb}fjjby`BYXRqKfSRz%&8$nC&KU#usznn(2$L6{j=$xU8@I2y35Fz zr`*AV3iqWv0>meEGHW_AW_-0KWB8HxpY?XsEcJ{r^7Kx_lLh}pnzJ>pXF`Oz24vZw zjUmaPonaeYorv(`$X0tcl)DhyyHW5$CauM!vfb zB~5qbucmki2HfWCKc4O7%P+P(W-iKeZD!`GU>UhGJgF#V?E6@1@m(P`u^C77n^Hf~ z0{lSe|AsM^!zniy~7^_pJoIfYZp%x)lX7N2@f@mIA`_*bjog z@^{98*yUcg-eb6-G0njNQ`P;JhJobn*1?f1`!n&y_{bzBIM`CIGCay>lsQAYWY9q;m2>{rY3lIl(pPn zg{22yBLa0IIzGMR2L(nQ9t(&bP@`Z`1-_sZF@Nf`D$Z@t!{Z(*i3nW?SRy4(=yWJ1 zP3PNE46dFOdOVfxl(q}`bu#n{^TQjm$W@Z+!QddQpbRdw;X0`${)8f!+YQOIX;8Wm zqUQ9Ut;0HojgMI7el0*J8RzGd=_#r|t?0P|DIU>$1$VK{*s+_w1+mtj=uzcis-i-Y z1)-~)2(SsRqDX6#fIoREG(H*~ZDC|YTm$>6EY;fmMud!zFu^F@Efqt&di(lS;AcA2zy=OKlCNAJQ-pD`I+1%^NpI3^$*C(GxFY z9vvP#z0i9q6(-bTb2rt^jzh`CPYMmEvEZH=F##%#kN*N_F#7%tiK{1Ff@w5QTl%Yb zoogFt*C+s^6ng?T2|vfE2yx0dh{u;cin9~UpufEnmP;{P>m9@V{P}fag@rJtrh+Tm znr|3&at=&xe$%BB2`i&PYo{M4CAbNQ5NB zZw7>QQj*?WtD+WOF@vXs^LdNQi*I*%-unuRt#bf#5Ttmv483|B){*HgSMRH@Ydo~@ z5wUyDe<2ZC74FXl_Vf8vP z;@{^~^5Ot6>G-Q)4lML5T=%^|vksTPA7B6w=lsFiz(!n-iegqi@rk;+8Xh3q_=x}I zYv+`)?_JEOt5p!N-$LhMkbqzZqY47YK*)y23>H9LJe5GRr@GWS|DG!WP@=G}!PSFm z&xr(TW)1pm*RhWy0AR7tqm;kou9eKMpP3>Q{_^HFy&B-Llu!A?U*-A63eKlyqJ?Z& zE}`o0sQsgJi%vHu63ZgHmXrIVg6dv&sO7nsSgyCz-)Fj$vS3wkcj+E(eG|vOdqD*r z+6f01=uyxMo*oc!rHSB)E_nS--fbc3lby{$#CWE2JqkC_SLR_NdOo!x!T5> za&PM}Oz60YJDtu!=I`flIO%mELvM^1|6w-YgcQ}eW?&$@`bG+|rbRFJBA)5`f7_RT z?8Hy*UJ3hddi1Cxy6~TON6Cg96(ZjUBA}UTAtetg(zE(m1+W?qC-pX}I@D0lW-GwJ z)F}3;JPB7Yvk-UAZX*?F=HR)ZEt8+?dYV2 z+9X1mWe%yg==>^P?w*)(9m5M(@f)R%sOnJI&cmM4%P&>J{B;(8f}-IHgwpi=GP%v{ z5Z~vw9#a3*1i!v{o{|j|o10-U*L?4TUbcSO+*lyYxIJuu#>67OKT!8?TY4dW1wE^ZPvsYG!8A$i4gj$A)QhGlvt0op`Mqz2}b7;Rrv$(n$?`p z=~UW3!!}*9sU~b47wjZV?O}==>)*c`RMVYZbWE`&b=GsU5F^Z=lPc#w=~G;)TN<%_ zp5NxG1tBN;=_;vZBYWno*m!f8yx%I8e-xgjg%6n%fb3u~3Bka^>K)9kTYzE)!R#*3 z(wo^YTP-Gj($JgNUMvsZ2y!&9)Vv_Zb)-WWJQs4gtrB+}dp`TG2kbt(%wkN z9GqRZsp)RUl-U11-KUziIhw17f{cao(!(uJTMDrc*wTIku#v08Asf4#t68d4%kEqn z6xckoNNg$TQF^lvwiW|HwNS8zPZu;*7 zgUebTH-HqX(snI}eP90SADQ`Q4;dF7RnK(o{l=x;iJ>iD%pkOT9&-y#y2uejnUkT{ z=t{c5>Lq##M==0Mx?dR38Sg0j+v9VlXV9VoWPYk zoPEYJ09Po;PD{l=wn!(wbTVC?WNV6RBsB##RV5LpGX%3Fy0Mxoa%;5UEroat6XBL; z7HTHndtT(PEqhQLyVuo)KWFYv11qq}I5vMevXkuT6dvVjuqV~U+QFTgb0t0=v(DP> zAkqF-CVM7vWEv^xUn+xwoI7~x@-bF8ic~EeFn$6$*s103n0D|QA4G+t4T#O_CbpA> zLUA^`sCG(fR4MNRB~Xd9lw3D@R?;w@7S zb25f;Y`3>@_S+F}$~hg5GCg+-a}ozY^l)L(c+?~nV!{iq55Slg2_AkT4ew&5Ya#%;{7$MqxUn9O#BLb$q+%Gah6U!1NeE4Aj7o5!C*YYAGs2mDX~TGM@ADr-*j(4r zGb(021Z=cp^m>#H^+4;QUt$tc`HUCHy#t!SZ9;HyG)N=fGcA9|)hN9}mA zeyk3<{jZgd=qexRC<*U3Yj$0r|L*Qk+C=tF$H)`A9045}k#d^%6vo7?g`-*Guz>f}g+YN7TKXW& zY(&Yo+exd(LfR#5*pM)~doGvTSB(=D4?+u}+A!!xXF?iNlZ8=}Z}UHDqklS;PZMF& z2obKf_J>;U`NbUm8)^Dq+$*6xtku29qNa)}$*Q87Xw-C337M`X-)~vp$u$fP*gNC_ zeyV9&2H9ocZIG5)zs*<0?kLbajKXGLI$O|D^$q(NW65Ya+Bq%tZE{ZddnSPZXF3fz zHmD2Ux|Z|jK)Nq{Z}GEk_4o8SRkH3lNFB2D@C;G;2!<0RtTU^L1D~tb8KSa+fG)*X zCra1K&^x7B@m!q<-!joVtSP7~Alr~T7lg6#Xxg2xXzHP`Z_w1#v<^&732$doViQ4RdIPRuw z7Nw3)pss2?V^%u?n$^QuO=kdn)m8#cx%<6!Eth_hj$y{v0Q7Q2LDPefSUb(V`p|mJ z|6x_Sw#r*;`xK12yv85WjFEkOHL+tMne!DEUD1N1!9mlNB%!Bo!CA?EdYy&+@*~Wc z18jri?5H!>wzi;7Yc35*b)5B@hS$q zH@&R~=Ul%}*5sGXJGXWvG(XeIYQ*p2iMU}~qn&f8Emf_3CI42vBI!)?HPxRE9~*VF zO%h(NiiPpj5L$G2!XRz>O)YI{BCwW+g}EsKzApPan~_pY+#g$N+zh-M+qwYMgsL~2 zIbZ07f2u%0AA^T!+@*Lc-+Z_H_D70obpaRaL>OKJxsT^_XC?Fvk8jZ{Z<>x0y>P_}QMeG~ zpa7~pE;Y0@L(IIrrt*11cXk;}DEHu_E5XmGU>-s_hvb&`3??byFQJ$=Yr+-Y>=3o zRI*F=kzTf(_+^KslYf-h9&DkXa#mrR77^isQNR`LhC9qWgL)AwM9CWF@G7&(m9qsDK-1C|43soK`p*_i=B((y7A9}0iX z-AOY6ngvlPB{4ynOkT23`7A&s-|gS}^xWzX1QnJuUjhb}K0O;zEf{zxhp#y(TL#HJ zr2p>+>W_%qdudgIzv$(=3NBkWjdI29p2S$UYHx2mlsrE$#Asau(0!D&xMO=9Z=|6I z(x{kn&)v8s+h?{rms3xUr?n+k^Ap;u3CYg>7I~n#hWLY1%KAkP+)TM>)7s^a&n79W zClE(l#>RMnT5koXA(q-Y!v&T+15+5X{<#1f} zyMLvVohbl&(%H=R;p!yoW~+$d(?#v`e(ui&#<2EeL9M*%v)aPec?Ge$-&kuQc3f+V zD?{F|C(G|w1(~K%VoASd{jYD_DhgebQ0nX}8e_~lk&hEG_A88LzDjX2i$%eOAFehU zTr=dLu7tZwqjnRUPSuoZYT1&H>%k{I0V6p+AO6lcg%FH510CGy*=mt4YC(>Hipv%3*h+@R&S50h+*&npa6=Rmu9T&G?ZAK-GU@t+*nNcvCwmWHQ zi^&rr#wDhX&D zNN+$u`Q;;~``2lIy!2UR3hOO(WKc9KVT9Rle0b*-)|+_(Bb%AeMQHWrVggQJey!}< z?}h*NS^!;Jti~^N-HJ~e6rI)#x6+&8-*D##nRz!3xH*mG=;B<>av-qbCI0`iRIsuh zsN00GyIH}5kthnG&RBy#_v3 z3IBv22dFlxKk2DnkwKb;y$O$KZ+>lo79L`sUoEwRJ{Pmzpt-AIoj*`_r@cQr)pcL& zT&CS4%H-$377nB2>qXM)wfoMlAEx&US0ET-3>ha2bn?6M1*d*|5Z`v3-xmR9iPxrH zO3rD92s~)`mmc(YP6{fwpfLU19U1%B9sj>B3(&q-Qb6fIPE!6fw6_X>)>-2%g;!S$ zrZ)tD3wwcyeTpqjxILSJF|XpmlrTpl?vx(#$}TZ=K>g8RZ1*k*KK)PpXF%AlBfNH5 zfBv9)lJX@jWBY<0f8vw98PL7>$0wv+eRP0;+-#B5F-mFf6Io$VL1uL)Pa$C2Pp5&8 z6M7-}UzD+!;d_%lJ6?j=KNh2!DK+e0oHLhpmT{j=uSq!!uEm|K zTMmE4J@Ls>eU8J=iN8W>_!5llwQ%OdUtjud9Qw~WQrBm$PWpTn-skRE#?{vTwa393 zNcMLc1mz5!7G5m6*YAqD7&rT1b7vB#xb3h=Fwzv1$aI;~uW3^trSeqfL5_`l6`sh{ z^ucX-T?8Z&X}=io&;a`8#WW>6y=a>w9>ulpba6rSaEPC9Xbnk-^0b-JSr$XgHk3^< zm={XtMI<=QDbEAk?0qF5FB<+z%EOV;T+?yy3~{{%oEj!zIJr)d{0n=bn3Fd|F1Ehc zD3GYbOT_fvwEHC$gxoa4QJ+1FRyNNM19-d+x+(4M5J>Mo+mH2=+>&q*v0x?MYGC$i zoGUl!oIUApaP-Uv@!D@~-*L4Un0fQ1YJl3FYygj;gco)a{_PR@+udigPx}P)?o00J zcr;(4iHkOheU+gBJVGfI2+zLuWW%P!Ph?)!kW0mI0gX6(N`{~N^KcoTb|QPtz?Uey z#uzi76LfEjMT&YBtupL=oQml=-fd*J1UPHI+5$C(RSihS?WSr2i%G9yLD=mZw&OBA z&5fh;vV7pnS8TXDc_^731^G!>^y>2t&MBKe2~eg%Z;j)D6L#cPGPp=?N)fxeu0Kw} zAV1aVQu9u#Y=vo*)V82c9d8_#RyU%Pi)pU@#~9zbd3-3b0PsFV36?1y^1_sSrC45f z&x*MoNtHNHSyh>!)|6T;;lL)U zxA;1f;6b$e?$`Jm5l}4apfPC4O{^p&PMl_4+O8h3 z`afGdGXYB@ErM?9KsE8DcoO_A#fFxwaHA9#Z!d?+TYOTSaz@48c%dUzXh0n|C$HI_ zmaI!@LK#PCb2eExuW29|wlbg$$W1a1h?Cs;WzY)lIQmBAnxIR>Mu6MEMD}R~|`)!59Z7KYVAiHo?-3lU3;_6`G|NVd75Mj27 z0$A7A9gB-wXp(J^2}2BL+1lusiiC9>eq*vu5d9BMdwEQJQfwmtl*FNv=c}WF)aFtk zUPX z%ckKTg(fkA5q+6R>H23QIx@Wp9|kW!5q7s0xFAji2$TlE-MP zBb0*NOJ^IES=9iKoX({WLl&BSGAhVZGQ>Z454+e|jW|YfKa(`ps13D*8kDU2gHN0Y zOw#Wla$GF60^(Kn;*BFG-WC(+ZCLZ#8oI{(yj+Tu;Z;n2i3@fwp6fwm0lq>uVN_BH zyN=pa1qO5&IM`v*`>hf4yopJ>{xYxmFgD()L>k$#R`%V4jt}CC?u1Fln|t9@uMAy; z6}%BCxJ%-Dgq)G4S0f)iOtt>v*%N_ju6TasFti_g?Bu;Xk#6_;gjT!47KZG5zHT-d z`I%NClentt(*`XHU|MId6)>w{2Ky1%+5kn~OWA(_Z*%w6#N0(#BipAxIMH@trs3CL zxRDF4ZFS!+T3>m5V{f0^nVL(lCZb0~SgV6ehsHjlJ0}YUjm+iE0{rf*ju@+m>%Swa0f9FG|KM7{ezRcq_xyOmuX3ub?wiD zf%?p)eLj&AWj*DLJ@pjX`M!uND5!z5ing@k{oyhO|Jxum(v7&R0E#BWU}=?It4$&+8d?wsQu7gsy1C zYhsG_1!RQqX&!onbzh>@EF4j?46wKQi-Fnfl>!oS7qOjpagPr*n3U6H&nIL|PrOJ+ zZ6xmUV+-sP9HVCzPl|WNzYn;&+N<{=pKF?kUTrCqAi;pcF{-bXH*6pDjdxf&SrB3# zR_I8S7-U;#sv`xG7Z_tU1~^tKc`g7W%>R~T%%9Ywmi~7pP+Vwa^zB^CVs(wdeLQc} z5fnRgT1#ZH4-?|8c-u$vt84Vd03%=Woo=`phyCfb8OYEDA@E#o1b}0mVhDUY$6(xj zt#x$x?cY%erv!#tr$u7SN*t-D4?w9(^XI>!P=4yB&s=$#A_%EJs_neP(ZGA6z4lu} z3|lBd&p;@v_}UH&3lHy_S-L|;7SbA`vb+z3FnE>8J$2Ua2;9HC%c_`ejthb-t!S+4 zeYOEO+_?y|%f04jE9;;ly^g1WKmWt6$84bI`vx6i!o^i9uraGH`_x%tSYL;}WbCC9 z4ggkwBA<=5u_Y!iD}Aj1QY5^`2oclI<5<&ObWPV`@w3IQEynwa_sp!(>0#!gzkgwy zf#lL}TX3eNz-Cv>Qt_#i?VOeN0Pmlkdn^5qlY>iO5c@%o?fr>U7^2C`6kKHbCJXwt zel2{yM}L6TyG#MW6svJ+j<+|nxa)BHw&epZ6Pm_uz2+;bxK})J8&B5rPb#IxZi0Rf z;-=g!;C@m$;~;^QQZO||v2kByGhObrhN%JgqK1Uho;*hSNF3-=-dg_UJwq5{bS(}? zj>vZn(NChR6TtVw}W46^r$r zgc}=k8UP44e9HOBk4W)ex{>QWn8gbg1+CD9h4cyoh*pQi0QUS&u~r~YM^P4$00^S+ z_ooi7v;zhrq*T(jSlmPT52Zk+d-UrTx5r|vw-RZqyZkquPCLXb8W^wayi$d#gkYB^ zLYhP7s}?<(M1%lxd`hB5j5JYofex+4zc#756Pwr@IA_GB4nuD}oCf<(Iq!6Y@X<}( zli>B{lEf&c`S4dCh^>dIBJ@?B}oEew-?PVNeQ!dc@Yb5lGA%y za`AMYH3VLIY*|{jfz{tVr3!a%6|jn-Y{}njwmUb=wc~JppxyXK%x0M7R>fQzZ*-)y z2;gfq^mPHLLoIOe^dL#wisEOI?*%+Mo-kEi^JNV=>Rw(&;b^p=Ojh%IB(mv`s+Bph zo3DW)B88u{5?ItiuW%CHBXJY-V#8n^LEBU>?iuSnq_=?gN==N2nYUE4?$f5R;1mky1 zg228lT*lz{QD?a`5gM&VYGUzc2-wO?fTkB36S6TZB?Ff`otLW13DM~!#JKHRib8P; zbw)&X!&f7ZmS;lI8h3Zvzu1<>9aNtJTG!J6aHdHwnR55RS$8mJ; zBwNN?mK5~poa}0_MIcQrmx7x?+aktKfOy4dd`R2jLqdon$A2NhV}rl9d1U$=*n2vm zT=+)JV!QA47GNgGj0gwuorL)vlgmAbEMP0h*<@UnfajOqrEl z?~@CDHKWBh8|k#z7L5vIN)NO5_Ei0WGG~82v0?Wu8?x=Cnsc1@t}@DVCj0Ta3xtM> z>RLj%SA)Lq-gNhs2px97`=04+_y0y7SK`x1^@2{k!G!Snb9iK}{-v%UWC;bR$Ghk~ zmzyB*>&iKAoe|3@kX)SvrJXN!NR9ePd_NV=Z$CKJ)W7Iak?S!48=3@4rs1>7hGJf< zG78rO2^NV?0>IwNyMn)DPQpqK(3fZrEYGq`)OXe2%4&N9nlF~zS6kbV&YPO{ZIKnnr!s1w(bDEaohoW-qtUpqR1EKeZp zvnx-_TSi^VJNmA~_D&Ew5)6Nd>xh~DBlVXV>X!!!H=9#Tj7;AGij;({Kr6y)OWAeR zJsaNy%^ES?6OSByk?&b&8d-w8+wXDo>A0{J&~EA}&gS`MiQtSs!70b!MU8^b`DnG7 zS|n1Mv#38+IWPMUE`)6$*@AANy@re3skt-S4sa96(R=+lYAn4_%VS=`VnXE;j%i#p#Mk?z zq@=Z4pq0?5Q}v}$t_=a@HG^9|UIRJ(Kh$f=Huk=}p%&MHJn#yJ`F2=Gd5QgnuZcU6nKQF5QOjKU}ooR(PgS!nrt# zI=e^igaMe&01FhX&e9ezasC;0yKn#p1w`dn?^g78`s)g-_#aIIvJEQVN@e7nAsySS zTXClk`>Kx4-Z#ad9mMl>biEycQdIS9o$gK*MUA&a?L+!zb*(DTkAc zm&FP`<2_k8Pct5V!<}vf@I~N%ve~kHst>!*<2ch$_F~S( zXedc|nOLLeDyK}4(08tAXuwLCdpne^swkYtG*4V1^K>ePJfhR4DVul^bT|)B`exnn zQRM{4jP9qKgbckJ)8BCfy#<#>6!PFh;}W0XrK7P2qp@k zWMPB!kbrntZwj+9F+sw$%<74KA-U{f;@?O!Ow4{6in$8bYu(m3_jq>J)V_i<+Am@_ zcd+F|CG|lr_eRV5QIK<1Pw>^4p~bCdE~mkbwTgK%oc!Wi0^5|$JGXZ z1eKGdBNkWE#@2$sOnvPoURJQuCqr`3( z5EZ;@L!@bwBaeWNtCk=P?;CE*p6oks$*+plj5Ip05q=tcZ)a~@#k`x`9NiTl2cqR9 zq=|r z?#f9#UN0RB!Qf@L)8S=nfn_$Rjgf!tLI+;CW5h?pn4*^(YwN!~_-{ufTk#&z@3F8g z6!QG%cgVNG{_P`Az{;G@M9Ku*4>mQre}bYl)Jq-Uuk^+Hg;>%rWE%#ZJyMRV(o_Pv z9HaPW=hA2lEs8V0djk}l(daUpt^ecbtizi89yb0}x}>`V21wT^0g+U?yQCRCK%`MZ z7%AP|U85TYNJ@xw4N0jH5)$w8d;i+5UC*`coafYY&V7IGWyuP5_0`j8Vl>N&A@U+C zz?KvpsvX^no+$sxk8ip66)s4Hw}O$T0_fjk``Q`0ZyB#rKRbRO963ldMs{i`WrRiO z`5RQV#NP&4x0Vk-R?>97W8z?sn(KfR7kDbBrKX2Nq?$f0X?(i`muQPdjw;b0^llxw zUo<9M!1e-D5MP0F(cI4m^$9|ybHDLR_HSVsL7@UCO&@688&o3dSoczWI7Q!RgzCW# zz>A7m4mfilZx}Ha2FxMGFxyV_SXQ>SQ%}r%2EEN@`;4fL`~$Jk1qV7Q+r0h8 zG!Y#WBIm~JF|P+-0?2LXY8;mT?eQIjNy7rNzy2iokqTVe5M*iU2uo8=^zXBPJ*J|^ zt|hZl&_h(K5%;O+F7z0=?OoIDdNe2c`PSf@*H583m5~9a3iXQ&*x3}eTvZN@<^`{( zvLQ1LTh;O_q*_-cF^Ob=gi;FqCGA|z1( zv&-1b$y>0Sc{jwF?Gt*Sjb947Rj77U29={#Vi|BfSpX^-%sk8Ad~2ptX1=f0{GxV7 z!O6efE(()zcOj)v{LXK9K^pBApFaLi83@}Jw*W@4<=2YEu>f`sduDDT5+Sa#j14Ye z=YbymL}05y2JiX(c9pUhIYt$&UQWJeLV9A3&rq@}vX;c&m>DAR^Sg3d;9D_ zEF~THUVWTS5sMo&`T1kM$1v{E%eep8R~^&;Pf|DLpV}%$<^m0*j{9YR&g~qdQJ}~LM=Z3*=m78NvsdQy%L?M!yktuC6ncP z4g(%2(wk>gF=S?2XaD`&&elGS7SznbkQkbszepwlf(`O?;CJy7i0N741OkYa>>F9y z-=-foQYzX^s&t9ap^~XiwVD0AC*!=BC%fiXF(*U3Q_4zcZ@v?xjgV83N%xFlF1>!*bP+;n85e7Da_*tQ9eK2c?UcYbQxBulbWNR3w$7L0M53!;*3*p*8hUKa-B z*CL<75!be1(UP5~#cTjv)YxAf)~0Xk_txkun?=DSnxq(TKZ-GptK@z5 zP1!G*tToQ->*FOjqCr=qGD&H}Ke|KsVM@n^eAI7_|4Xu?6CoQ_pV<<)!6=@@z@};_ zo+E{1L2Oxy1>AZr1(0hcy1YX8?=`fH4!=N~^hs(0tyYN8a48VK*uoYAz zrS3dsl>UuOx^_}{E=3IWZFia#0EOx^oi9#Va;<>m;o+=tJ^xRAmq4My*jj-0Q(u%B z8*%22>;sPcbnERRZ|d3*XO1Fqjl~F9^d*RtWKd{nlW?FNS$%JwY!v`f7Wlg0Uj+ez z4}O)GfLYbM77b!Kw0?YiCkuGWY-tH#q^Dl+_t;LYpFnX!5>>47T|xzkE(`}#N7Z(? zy(dFPnV}0F(Cm_C73}Ns<3BhX+Q^qGM%wtz2CXvyc3(SK7wJ>V$198&dQ^sy{U@C#oJt0q`+mqhru#Ak8KXfnx&-V^`)hYRP7wGyRUvVkPi-fuj1G*on;7 z{~ey%>{)h#)U0Hh!rU_%QmAT2hYPGCrs>nf9>dBJ?p7kII>?(eh7=miGpa=s&@=u9peGk?Dzb*Td@&mIIetlD{B42S z$QyXkvUOtru>o)c;4E>hw|X~Il-qg;l(7WLb_(FXaSqBrkB(w~-lW%!Zb#7`L`G*( zjIhSdT^6??{w?MIBns9M(RwG_)&v5gGCo?Gj#9Ndx>@*_0}!s{tg!XuOdg8$0}T~A zE><0dq%XxJrfSU)hKh5k`&1DEMNn9<9S;iFu9;qWcbY&&@R-CV;K#+1txih0H;ZUm zo@HC+G%SgI7BHQrAI<$)=OL6saZyI+UaYJ))3A#DKsmcj=MyOGPa^IS|M|}Dgl%9IF3W8vz!*ws z289_IR^%QgLCt|#0A=pY(4c>sp_&zW>0_%wReLV<^g)URQE-tuw;Qn2ec0$+dIKGL z`=zDsLs8kwR3emSi^9~;dO_MUCTR9)e1*y0@|O=X{l0EfiDDu*IXR#(rwYL^%_mld zgNLZUjP7suo^$Ub3UcIYlXzXYHEBLYW1^YCE7$??E{`xm$qN`9{drC--j~&hx@p-` z7$K2O&P}cKIr&|wRiLo#77b-O3$HMUa^$)OGCJ-M&q#x=s(E`nJKVrCXTyYH@yKbQ z!I;cqcUD_2fH@9&hkoY*x{Ab8CIhyV-Q%uR#?z2?ccRZ8S3v zgKQ$fl@)OsA(_W60#@~n7%vNJfP_7+C^Wi}BKNO&8;Eg)^i4#YfSXdJI}eOyHVg=- z_}`c^4vN#bqPo`N?~b+Fim4vb2YT#*+B$V>to@jVnC1P?giH8(ZHI^7`oM#+e}ja% z+omxIdu7%>N&KPKse7AQyfWR! zzx`bU(jQ{W5vcE<6|#&n1HyJ8+(nboi=4vvn{rZea!4^&C#W~M3#KDPNK?kdk?g$w z-Eqp2JChg_e~!q;_0-RW=(>gSg;R2mA6|kwL;7qliYEcFTG?QN*c+<)V#R(>p_IbO z(U^J)$BbaH4@v}3Wz;-z%=>Jg;19XV9De)tn}5#-ujITgmFU>xv^g8}8>sql0{gd` zQN_|66pyQvsbURFrynBNnu8dQnm}<)_YH-?t%f)CKhEV>b)>M03GW^^h8k8b|N40u z%Dbh%a;v12hC27MLc5p%W@XjCP!jg_Wc*=U2ck8Il_~zax`DRx8#J+&UL7RD09k*v zTXYQ^Lb2=hFN{fv?1(?{9s|S0$c+$uiJijylxNd+74(w@Ry2 z%~#eM*BGpEDi6R;g|(-JF|zGf9sRtU50vnWMnUK*tS=?G?*(HZO)e22lSEhUk#J(C?AQq zXG>f!+<)Y15@e{(d|;E2`*QS$RtH|d8mx3F_4zoH1WfhTB7L~3+EK^7>#v0s9?nk9 zi|)|aXEqYuoiDtwZm*_uI>_$0Z*n?b;~UE7FJ|O|JKc5b%T2Bxx`WF3-ZY?^cR3Od zap^0SXV$F^Xy7TIy(Euwd^Dqmr?ThOvI1jX?L<~I<|;T`D0`ttEFj-^r}-W-WjUqz zl-!@O&3ynVWMR=I=1+3I{%(?;T{wvb`brph4EA}c$q^J&Q_LmcH3BHVlilp(tq@#2 zuL#tw<(-kM0ftsSYiVS(wCAa+Lk2>EG5jNui-^YVyl)idmZ17F*o~?M)(RsA~Pwi0)Zuzc?eQ;UR$}79`W`!Ge|JT@h^w3du z81ep;v~&NxwFj{pL-DKGvD*x#@1-jap0($eC;8)})O0E9S+t7qI2VltLOmoYt;v-( z`764&YIY`fzNkM|q!n!l_lUalC&+&ljx-%7SAlcytM-cEHflU3OQox1|FgNLe=Fz@ z+-pkFoBe#w+#v)=j0^y%eEu1_Vg&Pgma_rZz-3@vzMd?TL zy1Xr^;XVxdB_$!*wU;ca8S)+jLh7#wnO5u9f8TIw?#_Y^jvHQJ?R^!m0rS>vRDfWC%Gu>7l>(9 zvoV=hi=32pj}KoZ^t^*heK~?EnaG?6QaDcS4BGvAKr&~gv+qG;wyVqA;p>Id#U!F` zycm+Lkmf2k!&rM9epkSIix^f0G<{7H_V3Z4rqJ`0(y3u>s3dp%xJn_QZsvB@;{H1- zvUdACG{)Vc1OLNM0ByL?D1)>0s{tS}Mfuo$VP!%hk1>bX%*_@B>ED%H`LCzHjia`;WoJU-*ahpf^AYdBcb zo4FPg@VAn#mcMf@03G8#>y=&L*14Rn+s!!hdKJY7L?KX@wg$ z^zzMUc!R9UNeHQ4%u}>uy%Xy&_KHJeDnJpYduCJd@7;r@^&6ZmNHE7^@{_rzgz(n& zmP=MvJxTDC9%+_d^mHLOva@k(tJGYF(i%ux3b%)YSh6Rvxg79U<`tJEQh`!LHiA(8 zPLv(^$t4aKYfr(C+s_*55!h7@%CrqYegad#(GNhneB8o(P$$gkD9{&~tH4^rD8?ZUzk2Tym0EcTe)BlaFFafsO?SqT1TqS8Ycw7&#$ zs^VuY`-=OAllMqf0_H4un7C8CPXM~GnC7HD&K4#&xilsgH;yF?;eJCZi1o+g0wmv6 zE>5)<$@sKSs2nM#B)G^i3=ndR!zrNNya2+bQ{lj>Zq?4*RoCNm<8ENc`7H(1xJ5yB zkyC-#M*+(A=IXg2=Dg~w*AKs?uKzLDi;~`JERzi6uY&-#TsPS&Q+9sqcHQmP&idaU zcTA}lO4uVYoIJjU;*M|?y3oL=xQ&}4686-qhb&G>MoQ_1CCZChp@rX!Zu! z1k}pHP!^%z+gLqoqkQn+-2e&hCSETKlx~3%SQv&|Smu6Ej+hNW<~!Qq&CH9=1?Ec3 zZ93EJO<2aU?ah8>7#eU)7Bh67RBdKjkxdo@Q!#N`->Bgc8@`hh*TVQUy9oO%N7_y? z#T-|us3$SAq?**U^xbv2>eMpC>;o1BoDP3!qH=9%EC|x)6gX5P8Mdu><-Bo*7xfWUgmtFTVs3>$b>8>0n|apJwg#6Ic98zSff8JqNE5rBOOlGMTdaP9PW zL`*^UrgNQ_z^6b|OtQR6@oIY5ZI5XMrtoXV88MK5;*&Tq?zTXPiqVketnym`v~oIi z&st{n-;L4G3~A=Dp8g~ZJWL`=MF)|s$ab@AFfhL2;aG_! zMxws>9x*@0c&A=mgB_)$vD{7#9K>SBuI6pjADrBI&5#9O9BJApMz5wbE9b8*e@iUs zb*0w$w+5A4yuq;y%m=1|5aPnuuVaT}&|j42DidA{%C3U>&PKr;uYbF z_qO3V0=!D07u_pZk3?+Vku!a#17j{fHnF^nG|(cZ244tZByF*B7zDLpnH*()f1B#9 zwR_QR0l1s~}_cK<4YArJ#l54(4*wU#V0}mJ)8CxJb9FZB@mjY@2EDNJ#w6}cf z);S@Cqa@J-eia5604{n1+yVb>SqK{Zk3!Tsc`V(}LZc}xGE1>}?i)42I+{0$sFwa% zS8pa66Nwt)!9a{qfc-3iDbogWFkOPYLbu zCuuS#FdZsm*TtKUem~u>PpRRcF;&j8s83Op0$Ny);i~q1>W%lMGK!Rv@6Pa$UqmR| z8WdKCCXkuU5mdd813Xs8j;R(kRNcTx{eXYp5;r!ToD;eCZkIBmU+qQ;1YEz$=O9O6&$ z#+5W}{+2+GwNRmJ@sR7r((Sa;YMwQ9r9M96Z4q=A^NOfZc6%eFAUE|h@)Jc%B%_66 z3P$|Kwnu7Mq>yrUZ=;GOlfMjUi|iw$=!gi zzwo}WnvWZqhGGS#_{Fvcust~W+-4UNc|4ed-F_AJdqSF2rhdAw$*Oqwz3WlN*=nDm zJ{gb#SQME$h6?_{$kb=iB2daiJs0E%7v3DnfG?{Oij@}zA1 z!TyIUS8+fNU(jk7zq*dBm~EjPt>{M+7jJ`24l$IL};f?>alR)%f=-uPGqWQJ&!*uoyD6GUm!f?-S(;Dp;w*KM|32n70#dL2S+$wZzYu&5$a=dY{`V2Q6t(Y^ zesE)!@|8_4vDXWqUFgzll=QcQ1DTcL$vN)!@d^gAQL11Yc4QGUNe4g?plRd`zolhKU#@NG*fIa55j-(BSFm7} zZ`U4G><*bKoa8NaHwq$0CD-LhROF*&wX})ZC$KVgiF7D!4bA=i@7RH~>YPQU!z7|E zYcH0I$4E!Tgd3Sv>l+29Za6bC@bgjV5n$t>XlUvD5On7dQ{?RDV3lJC#O9`kxgVq> zg^RSfyMCIr*=0+Y!fdU!hEC3&lDxQ>kg0DwL$ehmmf?SrZn4g%#;PuA`qCKEaoklp+xDw^P$=5BYhN)Ro1X%qtSL4~xnj{$~g1M{z z@<&*lH$Qz|+rYJ{FJPbWK(=eOZWZS86G%!_Mzpn+rLpBwH^==`!WZS_UnGJ)rK^&w zA$auRC1e7|2C*jv9u*oKvgOhn_-+M+h*H1gH5TOGo0V601RVP|)XFBqb# zC@9jZI|y^>zfb>u2KEu9^(8(@h@p#ei{s_4GeP_FTN61oB*XAF&4pwj5lW5Zdw?KS z4+>OP#&cas_x>6pNQ?X&h_1OiV%VS;4iO?(I&dB@h>3E;&oa|l7KH@6xldPeVSkmd z*46EW&sDtDFVNc<|`c4WfE=*O8nbChM0UyJsxHL_76NmF69ms z7SRga)uQB8X@hm`*_dx@cz7ES5I@G{*5se* z!7A#@z;fRd@->F&qh)3_bH@PHO59s*84O>s(7EYC{*>HT9d1M$sW$GK-*zN3c8SOS zfIf3jL;CXKUr-WR%ce6Ttl4Kx@6=1xk;AOFf zwW<^%_VHOH<8D4?rcZAVsW|_M?NG9Nkubu})Fspda7LYc7kg*+%$iNI!E79!k?}xF zJa$Q8kA)iY5gMO`1qTy+?>ft&~52S@Tvw%Qex=4kJ>};D4Wm(~+dJnk2%~ z413B4sPRp)B2PjxS%BJIgay8&p4J2bP{oBOz9a*l3>czbSilZ6xKwF(^WODiAL)-+ z=spQohd*j5or)bwK`xjzVfi1WS48(xFjQ4>muT-3R;O=Q*x5k3_pH^4gCRz{1KWFUnUlbY!T^|Nxq32p`v4YgN12g=i>_Ol6? zs}I)4_v21`h$2Pr3JqNe1J}7J9#YH%4N+&>C__=d-Dzi_17H8I#09X~)A}=O$je8` zRZVO@pE;Q{N)4>YKB ze%>ON*6Fi(;6@jiA!=dquVprs2>N#s;4t4ejc;>X9WQ!g{)F4DzX{NR<;Sqp-|ZCf{bB1o`W+b zG*;R_tQ_ec_G1@~NlC^SGA1PecLfa@xEwnoC^cksIR5j z*luIqK|fmK+H6cQMeRblv$~J}2K25o5r}#FJhm+5{h(d|9z6`=UjXQ29LwW2?-cQZ zXJs#h`bD@dk;g(n%9QHJ_uC%Je=%S(!(r<ew;9_taT2;q zYTLl@(e|*vb@3r7@t9c<>zdAN6Ja9hxN25BJh{C*lg2v?=F8ysEVppny6*yf#uNSY zcu10g(&L{oZpK8vopFe>T2#iwB!6vLCZBEvNN;3@)w{YHmm({RLcDHkC;A04S(qf@ zX4<<%3x4w-=Dd|UvbhLukc8pSstP9it&!9Etw+Z{5BwHF{=erwc9?al4qePoY1l03 zl*8?hXIPk=vz;tuIvmQ38y_YL5^h0ZCc$sAna)zIIyc6NsF?L9=%5qZ}a zGQZ~(RB})4g(501m4G}9Q<$7ce=HnlDE^wFKZXNEhHFmgDf9l`Z#vuUGm;B5wn_8J7`6r{&A05JlW^qdx8RRKZIsKm#kb$ zFf(;Mc$Q^hZpAaFluim>VnEJ(Kv@7Mm4}7OgYPL|m#7A4eM=>|HahPHb>x+))%USy zQ#Jp~bL~x}(phwKeLa>)baIC2yYl_zDV4=HuNJ!7&+n{owyI|tx_&Vhn~m#g;diAH zBfSm^l)5$;?Zd?63THptKYj3JS@N!H3l2z{U~-kLtT&L{Cq6v0>(ExrUYZ%_P3hZo z?J!kIGnm=2%%weBS$Q}A&2unU?N5kM1m;l^Q7#`3kI^6~q4lup_lE!v`EMd-I9tE9 zBSeUmXFt#e(NapkIRX-R%Ul_YzMQ|>)#F+fBHtU|)*iDBHnKOZ_{}DUZjEGb@q+t2 z+;|TtJ7}S{Pb)K}-585T>5O&7)L+2{zfPw8VVj~m%42k0#-8ne0UE7jRrxA9HRT~o|7hznOQek_ zp(M;FxQf68t_taE9x~P?z?ebBGnlnZJtfe9!g?{V3dF&;G2jo@4bK(oT{@tN2BRa= z`mlxAUaTUal4rC*)p%w8B^&=5W=RH``ephOFsnJVEmt1%w#kF8*l~L)=n(s_)OL%X zvELj1G4LUmd}AtuorVRpsUNzY3?@O;bk6xIw5>aHLta5WQ5kY{`@kK`F$DYqOR7!( zjWhNE>1tj>*Dr@(Geq@4ykG)Kmtkcy7z<3&d!!Y&(`f z1ARn9%K9j4h}ynpID6My2l}Sz!XA@mECG(tU;Hk$B`RS_4h9=3bu7laGavq&TR~;j zM@f0ZEZCr$J~U=lX&=FVnZWOSS=zFB32wHDS;kR$q*#z5p~(!djC3vnG3%^Wjf&Pa z2vDDUjHp1!!y_y%O#_`=Eq59DHu?(}SL;WEbG<3L!h8+cwhs}OKa%QR@Ksw3*)e6q zL*)#%s!KP2kmWz@3Kqt7*^?c28NGIikXhy~`edA5ZQx7jFA=TInx&Z835l>O#b}28 zC^74$oMBAGlx$IpwXdQE8d1e~g%;wv4(lXvr`va4R0K#P6hXDC0?rB=wj)B1yVYH8ED8-FkuKj}}4w z;densnHqk{CHi!m2+mN5P{^8#gsG#(HJUCQh`266Yk}G~pcSR;!p83yl@9Kd%NM$u z)%H_uT(lIVt%p)cJE{cNwxL!e!233yC-mCyB@N1_FE{H`47LazX>{K^QNEy44>_&M z6qjepOK&5`2z;9ZCi=ngt^i<03qVWG*(B^-E$K@))aO4{v|%kDm9P8upr*X`ea!gKDSif zh_!+cY9EihfO{hyqS+QUFP*b7*XNQD?CrK*4YE!H?Bda4N}VpiUA5t|C>ZUA<-De< zhw#gWiV6QiH=7zM>yS%Z12{+$BqMfvGpqJAEr%*q>VvX)Wp*_p&hsmbTX~Y<)eN^H zdTAd%7}L67rfQUq;^m9Wd#{_{d}Lq$VPsgq!>azn*qJqV?$-<}?=SOwfKiEw`bX}= zW>385Bz1(u7ZJHe#%3#+mRtc*yJv>H>ZTRVt(JPf99h<l2F-hQa=&gc6)kX&TX;D9nbc4RW-D7v-G47A1rEC!Dky9!w;=*6_?s)a+dyzuRexxK$7RE1{WyD ze1Ns+Zr!dJCN!N@w5ac-?jz0jHWArFpQFo~$4(;>H27Z0sCLx~KB^`Vb%d@{h=?er z5wr4rGO{AEme_CP7Y&4nc)043n&B7g1^A(Ik5^oFr^hZ~u$@PMk_L+iphkAw+m^>o zx!7@O&DO3Gv|1Pq>EBrIJ8hYPGs?zevz2W2X2NrS2T#lQWHzihSZ%81=S*AVtC%iZ zO!7){W_p9Xu3g|D4BXJ|XMrr*i>|b)W3Bj}{Zg*elM>l9p z5o>y~&O|JD?UUr$m^dIO9@PV0Z4k5Xt1Kx5`Uq#S1tk zUI_VAOy4~(ezP*O64G=@1yy!kQk7MS>pJanym`>h&TWcJyZagUH+y$_h@u;3#NGr@ znNI>Lb5fKB2qKuM%}c1}4_Z{NJ}^j zWp*9gdqXJiP*2@zAH&e_?1C z&+wcc?4v+n(ja$E)K%NOowzD^UsQ*|b$?7n$r5L-7z$`Pi0Yiwz>9sn$U;+L7s)DC zsFo`=s)ORHa$~ChpdE~AX-OouvYi_6H%?|#|4~v=x6ney{L7d;EcZpZ+0#|(g2@@rg$C^adM{L;=rR02R@h+4~=zZ25#nC->wWW8ZU;coU>5h{iQN5 zb*qBQ>bR>~2z8#-^hQt}{Y#HU=m#hAo|cRbLP!8q@iJn(-L9kyjI!cY!~bgpj@*OW zSYDW_W1aprL1cIY_mj*g_x1X1!=cZUU}g&*#=7E0RTKZIdHG7R^xCqxxVlRg?2WJ6 z0n4C!SXNas@zZC(r>Av{A-IBQ?H+d^9jPyR>&JT0Gvl^}e^3w`&hl?0cQCa3JrnyW zbJCf9U1Ak5kyj(#sBWkM0dP`Vk!X#)Ps#*k@Xi<~a%!C)Dq%4DlHo|rpT%`~x2^5n z5FdPI==OmE6|%~Q1yP3`_nWlpN2KpHw0W0v&x2Jy3A-m zT+f!Puhbwq&32-5d+sitwA0oh{XWe{HPc z103mCn$(@Y4?#$OK&U$qRU{>`o_8ixeO1~VIN1xp`uJz9h$iG?g^)kT?%9*2SJa&iEpd6sPC+M6#{r#XAq5# zzKfhnwpnA9vzl!2KeQ1efe@>Ts0F>S*R7wV2#|VgsE>KCE$Y5^zekIAqDC49Ym@lY zOGirYZ6AIRG5pAHCIFo;F9$_N`~%3#by$QuxJ8N+IB`d7QTwn2yva_Am*f-l)!yW3L6~ z3nJivrAQ_Mv%#IgrSP}N*nSJ>U+0^wbSsvEcRJHa)7H))3S%%Vu@oZzNth_K zCvJbA^^&SFm1LcL+hIt2+q|zZ0e5eT^*J@z$P0!Q5ZcDUn0x$8OxOeS1U2NadA;&7 zWL{h-;`N^-dT2x)+-C9wjz)F$e1;Uz;=*zrGaaFMOuQ(2DHaJ54VyXqC>7HZw_*-^ zM?{|IWXze^5^>rN4^0?FiCW;oj|9DIy2}#ZoA)$RtOpr#lXo`nx_)!<_=@%GA6gzY zrVu0dvLNSmV0W9kyNuNf2V}V;kX+iBGEFA{gEBTm|EM3w6G)_o4K8f|S7oZYx>E(Z z8|=-%L?8h1K2ByrP3bc!HVI_4sjw$FGSvUzSCmS2eidX)e=eCG27pK4=;Pg@N;Xxt z?*ej;$a4X!{0$m}D|C1Q35rNSnR2oruf0m2k|HzLo}qeZ1q z-p=bSQ>!OEuRlW|Z%+s3IkYsN_baa?tdwf~idlB7tge3t&&5k0D$z{WamDrAVHL%v zSUa*pZSb@T>_7|563hz~lBDdGLBcLpYH#R=ntGJoK9dV5+K}w>CD9WfB`Dz3RJxmXM z!vs7H_YqAlE{!Y=o)Ro#mwtWyMbd&xR$R!Fp53zoIgCpQKFh5FOhMTNdSh`ue3aL4x&_BkV)MZb&q;35 zv^K>m;0BC%%y-V*@9-i=@^`<-A$mRLV@{MqMS{{Oq(vMSM&oY43rg?A=qEofA)9wd=#HN>&caUGXk6RIg3iqu7GmQlT0mP$g$={qrRU;ZhfkoE8#*h~&gX&ig^esI=+wFCw8pGRqnAMmsX)$O|8QFJ)FOk1z} z-kv`SMc7TUOCaTH;Kk9?iT;573L5z4JGNUQeai46kVJ| z;{A_%Qg>aRct`4|{^#BI)4%88DW~3HPkLl8*@b`5aULa6-^6PxZ8AuW8fSdzwc%0P zd?TgE-$6^ESGB*7RDT`&b>e01n25@A!b7cPM0)x}pMp`<^k1(XvIdDPh&f{Js|)E@ zhBKNV-{P%*fq;yGWKlXMeGr=x2D3mcD)9er9Y_O)e8)#xEVZR0UZiZkG+%ffNzh)` zRZHhCLBLG=bzNSrq+;Bc{sYm$SaTQu+wF6ruzbL0_70)iY$ePIabdtVn)1#!d9ytwzIVXt`-v1F1N4>=J*b?yO>|TBex6I5Pw0{=ot9$uD#BZr&8OYY~t0ry$5>078 zaen;}c3PpBi5r_;VM=7iTSnbCAm+u6vDTjMcS~_u1_U!v;>~TiC4HFF+HY`p3ZXUB z$Is00ns&FY`=_ijRyy;WH|A_tR_EQU?qMpK+SjG;|DBIhZPAF3JThcTrpK;^W1@+Y zw)3A;m_(m%6;DhQR0byYY1bqZ=PDbxh%}Mk?Ap*|U#a+NhxR5CD-nr1eag%>|E~(5 zcX+*?e9GizL%m4yVwI^rG-G31xAl@2NkLaXttplH9pcDRSv$_HOa4UjXZnLl6sFFVkVCna!@YsTzC3U^$ewdM0l+~aA)40~LjQ9-qSyXZfpAKirIj-K6%qw? z@~NH3Zs&DY9OYrM&wXPTM&6pPW}V={U!+gGseZkNm5Wn}2_z$bfU(PvHk~PGwNg)+6>3nMfoZRTrp}02T8-FS&cA^s>2svC z@hzA}=K7|K?9FWkAxGFg{?sM;^m}&pvw}kKH)ZYxESM`^W@vV}D;_Jos=&bQoTP#2 zV`i+p64}ERI>A&)KN<;f(!spISwX(q_YVJ;PeLqCU` z(WADd@>o)Qc0KRF@qSy6hm012;Q-4w{TNyS{vCiH_Bk4NevIn7FhX0m{U zAMnhbn^}hu%~_T#Qw2gfP*Z$}3~z#(P4{R7`(vi^%vOK;-?A(CNY0<-i1uBfAz>V3 zfvM)bM7x@7jBacpKspXKBWeb3Gm3KN<^ z&xvGTE`BY8MgB9N?d|hXd`zzLeojvP&?r4Etv@A&dR10>Kg-rDTO9vjoEo3j6w1zD zCk5KEP5(W(@Xx(|2w0a!Oo;zG>i)azRM-8tLz$?qy|d&Q8V0#WP5n!mu9KE&vlj8z z9~F$xCs}2_+zIL$o(dt2Sj~54NcM}+jvmEAZ%aSSyOOPhA-*clNT$RB=I`Is0&*Zrc zi|`DHZIlMRiZ4|=?I0U8C^pRJAwaAIdeTLApf{+`mmMTxN+uDKt(Au;r?}2Z{iXGK zWx+2S5^?}O~pKJ^%We3a8 zrvO9hF#A@ttsX(_YZt76<9+YLPD}^Ell39$j|Zbya-kidNY9eU_@H5}_j13+xsf<& ztTOkdnp{nhBW5xp0=ycI2;o3X7Z}M8Az(XFO=VYib~hG&OAh4cz!^$$KO;%$xL-?o z395fOW2|KMc8g^D_Qjv;W2RuVxhjWib*Wv3!cRCz49k#F*f_Q(OKH%w{h&{m+K-y#rKMZj4crr1*sdxec5HBk zwisUi6dow%pcO{muTz2|`G}KZXn=0|)du9!=My)}5sjp+_wjNdJsA}U7 zvTYAAw1HjLECewUy|+C9w~}qhW2n+bdRgj*?N{&M9&Y8R0e7vNWZAG}Q9WMI ztFR0mmdGHLZKzV!Xd3*KB1_R>yH)%!Nf=6#aq zH|DkM#ojXey91@_E~2hV>Tm17Y|w-4oNXa}Sp&4A@7p(bK}mHfFEQc86U;pmSc@Q; z>^j!67EOD@ookq<`1bT&h0v6|qa)t-e$acnt>`W$8PiH5p>(V4>k5-2MRTR~~0CSSCkNjM$9E(*eyO+y!W%TCj8O{`K|Fr^0; zH={YbU{!d>h=auX@t<0cTFyG#Fnh5N_O`;ONiloDaXp=qXN(nmwXXud#KBiQ&Wt|U zJxseh8qA#1W_$mBR0aTFDvzkdXr$GdyS5Ic5Lq)}Yo`kNUbIT`jqiFs zP{(*f@a_jB6X1l?k2w2I^|*hxWU;8YB$d2Ds84Ojz9ZOpd}PjPwD$~+8J*7rm&bthlBT{_iJ^hrK0^D1or~}_zVfFt2T#8 z$W0FV8nwNU^GPk^^L|ztQ|+xj{w$-Nh}~o4z+;w{!#2)Ec@dFS%*Oy%5w%Yesm_Du zYr$5mgV_=}YzbN0apGpRW&rV}NM+c{qPNbIQ{px@@r-u$-)o*>z(MY~nb;uq{gf8L zRSS}U(c((^ERkE%iIQca8o5Gfapw=MR^#@5Uaa6wdOdrf1J{kRz*_`e&qdtGE&6=e~%I$c_=IV zcoe0{-qK-(zkM$&jH=(#rPy;!l4Txu zbH2@IJfq4-HpFI=F>}!o7oKPNsWwzBR{QIHN)aCCmRR)(P(MNgyWlk`7rb9P1W59l zEGVDrsKGXdi?Cm;5*?O?GxK(vz!Q=AtbWmo(#J>zCaW?kTBunMLGXz^eIyL$4>x{y=DbG*H7(^}R$dqNW{)VmeP{`QlXY8h$)a|U>d#m^QTWhxNl zxBtz!e0Qd^Vsd+{(wOiXIB10cAGZX&wcCcKu`&eIVL-;53#Fwa*mxwXF@{39n)4@y zQv#bgzg(HPs@RblTvKNcvs@c=2xm@`iibi`n`WO{FZ|vF6#*AJ%}=_DG_=&|b66yT z$vxo?Q4v1B=so}It#OO<;s5+{hUn!lipre5v|XnX5+~ee8EX3!P)%)`v)J*(B_Afn z0U^h9uI889f>}4dz!dKuJr_H{#&A%@_JRNwAx2AGHnTN}WO{);=8Vkk5t(?Org{9j zEXX0jRFIa^F=*qZh?CN4I^ibq$k^rE9tsVJ%xVfDziJ!HPv37o?!6SrO9<;*W2@qD zS~yh_;^G#_WQfETagaf6_R9k0FO=o^t)u=H6vN`<|8aDcVNtbR*8-JLI;3;xmK;E(hwcVx20<8dXnBwrO1itd zkp_VQq`OOoZiY_%&inmh;>>m3=Wxf`Yp=Z*tYTDsriC^Jb^ctdJq~m>^Tt=exJNd@ zuHO;yQm8r5_7x9D9YXPZ2Cf)TTdwAFk-;uYp-YUD+Ef$G_1eO1=pf|uFm_=+mo;^D zA40H0^bD?>U=j!#m_W(|J?Q~|0?!|Y4cM1+PK#PoMy#3jb!zkf{fJF~3p{IZbX6f2 zHR|std25R}_HDBMV{OSS=id3yTRL+`Meuwf?$~;a&-=oM10rN#9Bzv8@cYw(R8-3( z(aucROYWBcM!!39e|x(8h_en}8P_!36b5O-xVG| z+~uen@x9S?lpLO%wpJ#pp z>}f}56%fcS#ET7Z@=thZo!4p->?WWhf-qC3@77jdT|#XWJ%!F68WVnMH8K&qMf~n- zjn4T!YKm+JS`YK5lLl`aq~$25F>|wyI2;b5mJ2tYjsOr~kjIcR@)LK(GY9kQP{+$4 z{GOf>J8w53gNl8nD?RgUQyf80hHpbLRE7@e6kYY347{ld!J$xnt)BEelsyHoo`|Y7 zDF)F*>{=TY5(>HM5*8)(FS$Lsiae=`eC1ppLHAXkvfD69Y)SVPPs~ab=4)CP(e*Oa zi6%wGXtwoZ-ybRI;vv`a z<@)39yPP1{0NkkbwupE59rc(3PMs_mt~WFQ2baT7HPD~OvLpK2_95tBG>pthOR&1` z2oDK4iY`;5+ySgEG}E}Q;^NU(rp{Ae#;z70=Zn`5O$O&gG_-tgnN6xJ*eL{mO3rwK_}_GmR_mm$Lg=9^mAA>me|SA zG2%Ama;vR=A5#$GrO!k8DVgu+G1UqClDi{LPr>hIdf*!GoZPe2l_t&jxHiz4?|9t= zl-;Q!S7IS62jxFGHxQ~TZ2gNg_mg~?H)SL)EI*~K(&efChQdQl*}9a~5AO!eF{Cx#A`U)_S(_WqvSx3mqb&3dO3iMvgH<4%f? zwTtX8D1{5k)=zF4;t);_3TsYlN8W?Ho?B7hDgKbrWX9_>jOM|eH-WJ8J8bciFZ z*rjy-W(f67=~pY8+R4j8IOT`}`1kD}3G(RIa94$If)optt5l2|HR>E33WV4Zv9!$> zVWW-~57I?kK~in}cI&TT-E=aGL0kKSrL$QmSc|p)n%q1fP@5 zQl)>z&b{ZbEmUw!F0>5Ih@IA#iQ_zLksVf5#LVO98|sP%-f-|S_S|VCXljb5eUT5I z*A~eTVQcy%@}cgl@+00f*TA38omKo@&Gx!98Pm+<=B{rX8m3F87@75ep@@tK?BOb6 z-s?@LaN!SauV+%bJIoO;rj>}%eCOEbFw9)4;_yH9PFfRUp)Q||#Ze5tVfkk;!^-kK zUG4iQk(-JZ>_1Uftuw)EeQwxojv3ndw;YX!bvD*1IKZc z+$HOasnUsbWXE@}`^O=s5yzOWZCR#VlKNN18>novR-xDB0n+H+o zgW0DhlLeCKe@t7I>kX8THXERQ{}N;p_}oQ0hdhtNy5@!sbs?Dg5KxE}@s*K;VmEbc z13F3N!lhIs`f9az9lO$W_U-x{6MxLbJxXoy8>DX!cWRT3nhk`1-)qSXdjJaQ_xa+4 zZ}~)Cdt;`=rXY<1VO~{51KLb<$i`G)7woX zrXa=T-j|J7P6DyVMtRXlpOo!nc(bemRrT%N9o;J)t7PdQ5f_K=O6FUS&gOaDrw=p)&4+K zx)xvQ7GCNNENF*nSpm25J#>;*C@e&8){vbaO=Zv3Giy(po^ihU z#)RJuyb=6((3t>MwkXkPi)^fXsr{94 zUnb7|OYV)eF%bB)nnw&NwQZ>kDj*A)8V&){&gWziSPY8TBakCz7V)#ph{&e-Qql z>L7BM<7(O^t5;gALjt1z9SZr8_hK_-nTBRT85>rB1+Y#Dd5TL=2fMYna7-T z-v7cdEi8v$tU-rwI1S)x<<3*d!QXeW_1(ZP6h8?hG!rOB#NzQ^32ni?x|7yDm4KwV zKwXYa3aC0=n`WvqbOc+&DwK|U;d`qco=xk%|7y%u+P8xJVE{4lnz;icz}|am5mL?C zbz@@GB}^#rgVWkLy^zhFb)~eqXAgYUahFqRq!HBF`q#?@5WfkB;E^Spv~33{^rhIU67ieGGX}M+B}(2`0E9Ikc2~aE`gemAnL|>` zIIZ=YMUqrLYzxf%XN_0n8Zyg!KY=Wak;a939;-IeOD|%|`jeHF`U071=5W(6{j;(H ztfE3Ik{Y?_Bb;-ilI{|RX_0k+>qZIO;go&~og&{k0*A80@eCKqJ3TR1X>FjAqcPrnA^9fNwG)rZ+CnX`L2IAmnzud1>E?i{u=vmv&Pg~UV2L#yY?c7_l zUM6j_QzDNVq4yd3m0@Z{T`J78>pDwYhXWzPmWmGhb$U3ZCGJiAv-{UzLW8Q~(j z0fq}IXZG?;EdR_!9@?jp3AQ&#nn=D#09O0mD}XhnR^DQDdgjp5Z+@neiZp`~hZurk z#;QQg{dz1Lj#ow?nw4|!u(w{Ir=O97T6;F`(8sg}-4jZBHCOKF+ct80=g4aIKbMJ056^QzS-4bAel znAQ*4xqF5~*x1Aw+{-Ls7@x>ye}yDi@(^yGH+wBV7ojBEe2$7*YLyU1ZL2rmfw>iex+qYTZ?1|CiL

    4. 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%0DTJGstA3?#WGS?=nL%S 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

      Se~zg?-FLpJKkXUwqxGl9K4=24 ze~bRq@$W6xpX%OJN&l1dr|*ZE8qn(Vl)NzXr+IF>{`9~NG4-c+t=vH)x1m3|-nQ#c zuGqP!ShvHYi7qCaiPGg0(XPlX~wf9j{yJTS`} zuMdk<*S|x5I{ND<{pou@q}NMNnVc||{xnY{2t^pwDUmebki2W8KgCTqh0_Eow%})w zsy6-U-RmOsr*&Ae`RVni$*W^`sW9)KNq_o!NLYVba*pb3r?BAEL2FI@Y3#^wXM^wl z#QM{%D}TxQ)AXw%^r!pqXzEXs9|8q-f0CW{L-nWRFPZBH=}&unCW&s~ybqZ{#}WF| zDftolQ@fq2j;8gex@(xhrav9Rn#vE?pY~4^{b|h|P?r8sh)RPA+tsU=`Kk=BVhU)P zHt5r;3Fc3&KMlPxhW@mQP(gos?DwehSo%}2_!p!MFr9aL4 z4Eocb@e{Lq^w5gfJ@fyfKV972)Sv!(ebf5WI`%j+0;~o4Q;X!E+me6XBjw*a zCQH2W>M%?E_sG8?(eiI9<=-rml4Ht0!?U0T^6x>DxlG86DgVIsZ1#h7SONMOFFjKJtuQ-#?1*q@{|xeP=`ULTc_QT>9xeG-O8NH~JM9O{KSMTwGFxgt z*i&MX=!UE&`lw{b2tCO8(tU`F95@h5S>mUgoPZ zyo$+S4f$8u4AuW=`@zusSn`ihQT{!ODvv4u?)@dnKc1<5O!;>(QvQuNru_Su@(({T zyGIYb8@p$kkbkB9-gJYW#wR%zB)p2dP^+wp83_U0sg+7)|G6t{|G{KL%xf@`*(`d& zVaI8ehcAPFOg}ByF+~dw=W}be-YJ^}a%xL%@dR9n?wlGpSGgTSYYh8yPOW2VTbc)9 z2ZXgO4qgYywn4uIEu@AeVnCy@$0Zg!x|BuiM z41Sww|ItSVS&o1KyRqiK8k5qi5kKTvFPc53e7r*ooTM+n+K?Q-2R}4_TROa;7F(ry zZ}?rqE>(1i0TT8GHmnRC$Gw0&+h^L!5*(R>4HG%*#&yuRrK001HfS640mjNWfFTOd z4jqB5s5^kwZySggvT}IWWbmVt#-LBvA(6fYKe0Qu!#fHgiP7s<*Tysq8B18I|LB++ zxyDAPp|OeOw6!<9A8L&sZQ6kn0N!^W*CxKsT3<)3(&TFI+IHw#H@fx^`iMJ#f(hpU zeh$z50fpyGEpP$$IwWSnxkg;;Dno6xhAKL5skZKGT9m)jDnD-v54{WO&Nr-k=w&SI2z@Mh+m6;c?!O7I z{+atz-VWo>r2p|;b%`7Vfs@#9p?Q#cayiQfy_X<_kp{wFM@K)$&~5oB2ZS#0lrj{7v?8Y~9JXV@=}gl*w= zx-jq6_*(aq)5pXn=);5Nw2(fs?DSDKk;7Ez!#yK5eUxh!eY~*Y81!+bfG6vR6-B2T z0D=GESZpn4pJV!bp$PDT5w!=i4um>I(u3Bp0vizx`dVMKmskgd!z4c`(G$F~!IM)p z;cl{~z=*>Kvl@hfaOWacC%*&1-EVE2{JgI@=XtYJgc`haiAg4RxueKL@6n#r3QD$- z%&)PqtLO1&Fn_MVPt!!BKeVtJnyIU^Q;edI4}gv^|ApH^)_N?&hEB$y0hjD_5YC8> z>~Gp^)O?i($+vRy5+680;m3C<@%~M~K_^cD8zvWw=+v;he`Wo8Z&Jr~H~<2^ML1cd z!FB&>6t13}rT3>o7(I}RyK&ceg1JEDiu>LRU5S?u9&fnjIImx3jhcXuELyEW3LqH**WXL zyPz=0=g_%Ypv^v<%Zg|wm7X3Ij>jq-3o5)ls=-Anz(p!NNfnxJZ#+D*NL4xSmtcAG zAeev;>$>G@us;rELx$i0B?vb}-}yxIh2kYH)3PP3LhGTTG;P(AHnAXi8OqA4K$L?E z5!;|%^L-WPay+)eLJ-^fexAJzEc+z+p3*`UlvfSquEqa<(|8o+&QJ z`H6M+v+iKRiD(+7(N-U`(LDiyaOgG(zUl;zAZ8t&eOk_@@lI(rVZi#dJ`dEzdJ2qO zU2E+2XmrZGnVw6+^cH5lN${+uVk(hi*fa4J?ZTC3g|2 zVR`>W^(%#gU4%!9a`2^0tRvSRlzQ}ja2VLGy>%HC9d2-$#w^dfM zxrm*Ih49|SDu7fuO?Vhr1$ZL3bc$4|Y9laUEXY^x$yqseMF`5Cq%nYjZz+OcPOEsp zEj36pD)rZ~J�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%0A}J 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

      @OyG$^Hf=d z#6mDBlCrP)@6?yr#nf;2?JTBWfAQw}ydf>AhSz?t&9=_s^e0)-z&OoN!b0LFvyQOi zG}BjNI-S(zY=~S#FDTGO+GJN&s-0X!Q_yx0#u(%6fR>N!UGNT zkg}giA9<(<{sOa#=I4xBnLBAk`%hMST>4UhiBQoKw(p*Og@88$37CDCV!$fGf*+7- zS72&tm#y*ncmJZfkfjBoRnb zlK<8hs@#-s{N?TUl>68aYGqWeVZKH}ezPWttWW(X_V(@ko3qOp!#wibpHmO8T)>bF@<+!zy)if&vf{C+S5V~K$pt{6G1Umtq*sZEwK zhbNU!O8~3b-xMH4M$lY8e*WI#<|Fk%+WwQsa4LX&R zMdNf_k-N{4Kmr?}P&ZohXW|i{=qKSq+SJc0!&|BU{3f=J2B^_E(MN>T)F*%(HJs%U zLdt58+yzVQtD()fBgNi=2mSs4!(fEb)a1dz@q?Yk^T}A?4m0b&Ka#T-%{wOtsUZT-pMr!8R2Jm4CxNkyPYN2d@ngj(BG<++W%VB@Q<3& zi};4+F4%7M%PbN6r5`d%iMEehS9A`iTeY*UA=vnzQdRimTN~6`ci8ar(o`1apKSsX zjE-EBbd97hbh$x~T7E-l^Hz8AgZv=mV=sQ1U!@`_>ff}AwHx$@DEpYf{?D+8`t&5> z&Wn9Y`4NO0FV#z0HImOpXR;=K%_~53x2jeZZ5kmC|L}s3QI3VSS1CVrSZN$yv>PVB z6NcS`8m;QD+r;_pClP6UP1_0)iVE~tY=sC;AeU4EJEERb)~lFQB3ad3crMz6yde9` zsFOn(*O2ZFdoCExr;xOp;oib5{>FtjlteD)c{O^2P!8VnH))WxxcATe??+>hU{!0M zCT{&7GL&;%PKh&GbOFBci7~LJR{dGrns4T`s>;Lp;AQ85Kw&sv%IuT`RSx+VVNp1N ze8KK?34(KlFSf45f?lirbO+B{G4}8gTre6_OiXqQ`BnbFC9G>xG z+YTbYrb)Bxs?}@iqiGp2x44X=^xv!o?&RIqnG@S4BXSa+?u}dOD)G7tB|&J(^ziL? z{__J_*nJYox0X8RA*C6-jL2(rs{U<@89BcL zKjSaa?cnDI_6%sV_T|Z#bNz=tpGKV1I3j%-@1=|!0+%;{59Gy>?o{-Dz_?|&&vzM_ zgH9OQ6>!4y)_5Nr;;tpSu=X+>I1)&X@#zGdBH_t_Q9oTcBD8ugeI55AW0MsTx1Tei zRMo>YCOfAcJ`9xD14xF8=T9026*r&*fAWf}e*UX6smlOnf*EbV*k;zMH3Yr?xVfR@ zoL&0)_-}Rlt=93>J^fd$n0=pf&>ddeQlBdS5HZFk-Y|e3qIT7>^6iSyj!&JTXKwz0 z%Xnr-L@AMw7ItKeH}qse$wqe9&9%pdzY_oD=%v%>-lqC*WRA_EHTR~h20EM{sMJq) zce#Lyeen8kmX!eNRC1}ICOMZ-pQOE5V78ac#HXGEg3kx!0^A19o#NWD;Sv}N(0-so zfGkQUQknYKEEKvS3$Boec zMllHwsPB2i5;Iv!TeR!vAHw;{ostd?NwJn-9rF`vKJ9n!xeI2h7r^a{>+gsrk#nn$ z$mc@t{n>y(eVjHz`Iu_q=IcQy{1oyM15YyOm91cZsNil-KYyLsei2)a!QD9^jM{Ox+ZvPYgt#xjg58 zGjk`0=^cQmS}m(zE&Iu`c)vh3yxy12K`<^HhY6VwH31f#`=!7%(IfsJQZIEOgiv;) z5VB$TA*8uQjL*{yJ9G^9m@@a%a*#=eXXtNS=jnM47@6O2gAUDD11lBqz=eubmG*FB z(p$=v#7)r`6LeKLA&G`K6y5>n2k4l25(Vh+4!2TA^0=C2{s zF{hu~x7B>%g}mp$8ilGOyf*C<8f{nu6kOzUSrWhA^Mo3JJEEBSa!12j zzli1L0{zY5gj59m3{lryAe#tEW)k;?^Jzite#O#rSJO-@EZ^_ssOCpDSPI%W?Iwsq zPO< zEWa6Hhwjl_?%6C3l4Hz{GK!LEakYG12vmp5Dzex$8a#J!fsS-B6Z<+UN*%Slz>x9a zYUZ0L@ts*2M5PS|&l6eBerp&GLR8Q}73c7>PHD;wPUt1)&Lv6e?kq)r>QE(?aZJ!k z&Kn4RIz5norC6?hat<2|B(v$+^hoHHk|wFrCbWp76_FvR4U|gwXMHVXJn~Eu z@&XAqVyZ&K##7aJWBkTh%AeAuQmv{rgcv4qheBlaR>IAxaA7*IYxN}@d2EuX&WpP@ zjsTpEUSYoP(Gw^RM_sE_X)en3$u0$8>;P`vTca(7$RFE0n^3s=(N;xdg+fS3Yk_A9 z)-n$OO3>vB8CJt#+_}9U?s6Rjv#~>#07c(VvUi0zZlP9?&{1|#HJJ&ZY+zETYBM=G zYX*O(=$f`;5E=w4`t}BPQdBAwnqK4g@j!J3YX*lz)7c2^wo;e41A33ecE=MX_O-?;VHP)=mF}%4sfBDx9jm z4E>QD`V%~C=9YZPvT<4CsyxxGO4cAYbQLI-mUSqKii+$*ISc=agN}kQAZX>W{Z1>7-;eXwzZTzGn*&KA1sA<_*2OuV+<;rFFC7`X)X?u-R(I zP$*2|n@jzr3W^QiUI z_02uTlfU0@@oXDST!ku|IY8>I<+k486`X=W0I7gm6p5&(xpM~x(M@}FW|KX%pJ0V5 z8^QCfn|AL}S00HWAx|VUqaX)@Bx^TvC8ZaI7 zSPn45YGeu^Kn>xMUvy6$G(o(9e*W|KuhV*4_AqwQGj*o5ufDQsvaz2`dI=&Zjfyn%R0jwn++?EoHBauKbpuYa zy^%c$d@^{XnWnbKl)JQ@Qadm7k1px5Fcy0dW%$?BDuWTri}nK#z(4ekG^g+YCN5 zGb&18n?=;hmq0nAa!s14rF+G=#!}QY6kRCe5e75%+kmXEMF5JxBMOF*& zjo=Y0v^ZZ2j`dBj#~<9Y+rPKSbYw=Ng* zc?h;F(2#|RuBQSASH6%CmFkHOf>+lOo6W??8d_7*tHt?5tXZEs;dn3zYs5#k&Zh4s zN2}^7{j`$M`Rj8I>&f5*TQtJ;XeNfAY%056?aC+O%PEFx>}zw;o2pC<+yPH@q`4&o zYZ;PgU*D~8#GAapK0(csJZdcWsk^{g9MrJ{cM3h^43_(5#fg;5tdT|eY%8P*#3F=@ zwyD_0TT#t_3(2)Livq^ot5~KU$qri6B zK0x#!UnaA<(eogV9caGyAd$DI;x3M*$XyH7an=iDs>@g5lMeI7b9P()K3{xCr=UsZ zcBMv?RG{Whr{Bw=dg!xUTH6lYNc{$te=zKYo1l=fTV@*Nx?Mxnrps5GfPNZ$L-A<` zAm_C~O{!_0An82MOrakS)P0jFMMiKbgm-emM!o03J;`*!-f4vJCJ9&BpT}AwV7y-p5@V zm7o_0NVGl3L%g7Ih}8^iR+2NakqxwFx?y{{rx85JSzG#Tg0X$%3WsZ{ zUBnw#lJZ-hTOIq!${F{M%ZM@)e(91F%^LQed)h%qPP91lvy{aATA&-4Xy>2P=b8v5 zPVd3jmxdU2v8jYuD^rmhO;?Ou!(NCWm}zW7*iYg_HCj|P8}089q%?B|M>rBbGCEn@$R_$w&C3x$>}c1u95ZbxMM}c z41{++$gUwQ3A_1+xc=0ontneFI)%DuFirYd<7w-* zn4vYiE7N-f!D8-DzPn)`??*Z3<; zs*SYBkviBF=SGL%=70L>+rB?j2Qg(2eKI2eBQ!7@rp-pe6RP=-9rQwidNOgaA7t54 z3=mdHD}B}?bMAY=-;CHpmtu8(V5~RujV`8bR7WyaJG9X!S48AuzZbyFGWrtt_u%M*w;Lz2K?^nJnH-On_1T$B zcTOZ@%|F4Z?3$bjo--K#PnSO>SxpUpe=-g!A6b zUV1OXSv89A^`$Et5gN_)qtFI*9sEOT^@N+fu+707Y@y+TpS{Q_bKql_(4->0BW6)T zK|Wauqtvsl6*eTD58K$lfF76l5dHA+qo8XxGoTqsD6autTjm&FZCDTEj(l+}QbED1 zl+BOexSyIYyah+J>gCzj8-6O6vP7~rN9_zBHSqeHEQ`qpu`#ivLih1a$R6*RR4Dyf zr}*_6T-rvnvzt}lanP)lU(CcGc5H7|{UPw;8v8&OyOZvAXeM}veD)S_-`3OIH!nQ{ zoHkuP7vHgV+cUOpNT0GK1~qcr%9*s`ca89~&6CwcsiVexHQ9d>#z3cCcDq=N5ytrS z#q;I{XMD0p2rU?qkD=g6R_-3JK8`h^>r?Ll{JpFkf8eQ{^STG)4mst{Sx!46duNyPnvd}DuDkm_k5e@_h=_gDsu^r8NNDXo!?T3E_GdP^ zJ(*xG+PQG3Jx8C&FV-9u#@)a;WE^Y!-$NEy@Ryjuq}|agJsmz`%^Jbt-2S#fEKx9H;QLqr71l8u^U@1lQ0@{_kS&-3?pm!-IN$O-dVrAvv$4P zhw@?cFAf3R`@Jrs|5<$O6mYiN9%udw>w<_|Oe(=o@EwA{OIJ|!_-pR=J=LDahlDQT z8G1?3<;CYeKpJ+4wpy-5`K$h1l&&h-z=I%9J2!jIu1~rF?eg&Ge^A>?n)HT)3n)rM zC+?{NyjxH{{rV-c{+cjGy_|y9hv~k5CJas6BB>RyeA={#G`9P89y}qEhY*Z5$(Ziq zx;MNp?X?yv-e)PFkS8j;K;A9B-=usui}&Cusao zIv0!USfPAW9E@jMiwmjT<}9WUen1C1SdmNg6@XK`E{O#6<>EXzVofFrz}eDQL^XJU z+b(iEqp@S=-+mOx|MbJel{S#;g}@#o)KDU1WRAO)V}kyR+V5YcEY`$f?bSrLkoH3kXF`@?Ai?QH%v~W>dwA;(-K~Z z$vW$;%c-27jE18(uuRtSSlwp= z*z%oQeQCONE81_hm`U{our*&Q*P&Z8CI+_j8IJx(PJHmK;y1vFk7cY=!LXBuKODBw zW{rMM%N-rHDz=x0Cn2<}wmL9!u^$beyXk>|M-JRcySod|?(T9gWPq~`9=NuLu{FTi z8*Lc81A%7Hn=eM8R~g{NG9Th5KE|3^A7T^%g$iz3>)LgJWyZ#bjQAsQwD*mQQC|({ zMIaTx{ob^_+J0=z32i_0y}Q?lD61U=@$K}NY~qx9TNOb`Icq5PMSvT*%b!QDBIkc{ zU7o^3AYk#?cQBT!bv<9f(q{{Q@FG+sH?8@nl5tqN31ICm@R9&PI5cY?2qP-ftDK+l zk~Rs8?9~R8z)K7-&Z?Z>#Q_T|Gm^V5Aqltzorc6N*ej{nG4>_1^}jK4&=hlp6Pk`$>qHBL(lXxN6K2l?iw@y>40Gr zFZ~Es!SZ!f&JYpOsgIxqHAUU^>y5IWYGIyla}38?8BqwQ>;4iSL4WJ81Q>Jo+ayn{ zp@_UTU(ZIv6RITgBM>$K&2<#E5u@}Ul4KQ`4Ji5m0(2OD%iP|sS^a&Bb58&z4>!b%$@`NFb^4jtRByg=UhPsQm+5!W-;`o~H-C`$rSK z8;bmoKYZeAP--lH%~`wfBmWm6mcVi`I;8%(oyej9sqk^yWJXSkssQ1otPN*bn*fES z#jH+0j|40*R>ElcL1n_-7c7O$8lcoJVzY#+j?<{m!gHOqouom2PE)`1dzevwrwL%4 zetB!2OB!^Zf8x&CJDnsw?w$yzw8%71Z`!+4*qv2lFh?)o@Jz#7XI*0CuMt&kzqsrj zs?>;9Q?5y;u;wTQkG4NC)&cY;28k z$%a%&Kcx2SUv(?(e#NCe5Pl*X$jikv@-Mq(B7Cd%$Z72`b!_{-U?%^H86^L?Q$Z~Yt0AsG$!00Y2V#0n|0;}gPo2Eae%Gtd&Nv7#F zu%CCmHsNc};1Bs|aCi}DFg$A3@OyM&Fq#`8c5pfn*-Yy4xFSnnEnx)7>E3aJU3Mz#21&fiU2x4z@~&- zLrt{=L63O^%jnHxF+r_ECZTm}7S^P-$2kEc!` zfsY#R>Qp#jtF(dP)pyH!7#1Q6h)iK!5d`1~<~vP<>HN39x-PZ(X&bn@Q5JyQx7jIe zfXDI1<#n~>om*OeQ#(6N0cj4I{SIXGU}wIPwiv1+#E|EYk@#biJIPt!vNJHpzh(RT z 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¬J3vY_{ZE4VT#{4hVJg3#L>=ekC5?A6<3 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 z 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¥uT9Zef^5|G*D~mia6Sd6 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�?~8t?t0YuW;Fa})Zi%Df0}Yh*mJoW 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

    )B}t2?IeP%{~F* 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%0AgGiRkpP`QIoh;#vSQax5CvTRcH%S~AgQr;xvG7? zvLy1rj&FX|U#4+Ut9~Cbi45mB4y=P(>1Duqw^Vi3oKORa@5MBA#vE>{y#q5 z?yYk(XnQUn96p~ulDfe;$@;e@C=Tqw{^|p+w24j6O09%&>Mi&ZKp5Hd5xuP^EpoN1 zNxf1}8%F6=zZkRq={OaUp>wzgfvx-&Ar~j!UYsJ>l!7g?-_?}Cwd^NP#q+2?_`tA( zowDY5+PuEpPqqLQ@I}3?~Kdj2~=H(Oa{{XCK}f`VL%$)W;!iCxmeDZ92j|s~H;) z=dD!!C~_MZ=PuC>02UeRQHmdN_)}}LfI~^!4eJvfb)NU==By5l@xr)l({?#kOI za2fn|lKz4clr+qhuw#rPFyZK!#^-}wb%l>p>D7F@zO%$KFs5Rlf(Io*Z1k5yGqx?t z;X)NEi2<{}RZfi`|Dd?hd<~DpDXCde(fnOOZJV{CV)14---nfWAUe#ZbjijU8SETX zdgtz5%4I-ud0_BcRr7ZhwXN9fsJsyMiu3BXao-4qn!dfAKa~<;8|qOWg4|smPqU#6ue?MIt%IXG;hFM|ecm8r<{$6_kFjbjO%w4S<_lQz%)uCa^W?BPQfvrVyCS z%{6>k1rgP$;F^)wp5K?Y{-Ozv+vgkBI|Yk7F=8tx4_*6%JoB$K@&w%? zahiZ5;>1g=mCp*d(wvGFI4!qa?A2#1E0W!`Kf1(fLUmIWh%Fzbc3pcEvA=qnCFjj^ z<$O^;LJpjPQK4T3%=#EL$#vD@DBs#^MG<>Nd3wS$yfvY6m+vw$Blip&LLLSEBy%$KCj#A>s2ti`gXu|M)Z@o@|(;?`{!YlzZq7!89tVO zedrkq?Jc)`{5wA*`-|C^<#CiO`I^M1G0<*_bYYb(OqNo6Y-idFBO)EIcNx})FxoBX zR5T7LINYdTqfkGCLyR5o)Z%~4DAg_Xp_~$NdYq?M=#I!wQgV$e^P?0}Q-0YS|maLlmVRnI28kI4Yj*X zr8y&{y9r9hno=5+16h<;yeDne?Q0cGO^xXTxE4-hm4=!sEvD#xVdy~z~zyljBxVkwx!y|&y_hPBoCfvA|>zK z8tWeC3GcoY@3plW8vRvz^7`P?*6;#)`f~SI?6dS=&UJ$w<7ynkN`}1BNz0%Q8#{Z> zXs|Gn$1cOlX<}`TY2vpN!BB4E>9I6s)7VKv+hA@_UwX8N5a$Kr_3RLr+`W>@s}Eb9 z%j5in`#FY3pLA^EwNFN>A&ZO^ANf$Wq*o{T3Af;<;{8w9aH?6UxTQ|>+denL(i%P zpyoK5Dhm+B-_lLb&e9a?@H;{4%-Un8H02q0gGFvd7`Fj$DRL7($(*p;f@e)SEQ3QC zbK$$&oG{~l^~s@L9uO|MJmr4l-cpy-SZNpV_#5_j>U+!GcASTqHt^n~&flnaLwgIJ z&^Wz4M}N+~3CGK5A~kE7n}sDG0poL83Rz)^fkBGYep>Ev>oa_z3ZB)<)8A*)4rOnt z1bsKGdbC;=b3~j@1gchHRm0N7jND4?qR?}ktdxo~_tGxGc2Ce@_gRYD3TK6f z!On$LZU^o$%KAt3IAM7h@d~fGS`O(tsqkq=+-^o@b7hs81IJRv+)c{qp~5fDlEaF# z6w)dl_c{#EQm*<2;T%->v0Bg1Ww>2^e<7z7t?qxH1?&vz{x_)h%zSa|PN7l;Pod7S z4jbMz!*Jd398xDgrLMVqba!(U2g!4Dk%3PP>?u<4 zCH4_V7F5^G5Y+9P0&8`*3wH^?JJ7h7{LGX#^rWAaqBQ{r;*X$CCWTRnG>voG)^0 zz;7jib6Pm8j$QqpfnhB6uU09&(od0-SG)lQPSu+pPu{m*H+WJO00lE$87(s}zFQUVo?bziRtb^_i7ogt`1XZhoIsKXRHr^4Z<> zv&*>x=CVJOCb|I03vT}9*!Jrm3@H4&cmY3n&adS1$V(}M+wu94_Ro{@gCEPYf9l|o z;=Po`+ z%-a+AJUG;$VtJ=_KuCl$=X$>9KCc()F^?I++)@jrN6EcW(Ra)PF7@j#Ed?DPC6- zU1ligabRglQr#vzAdH4k$|y@sLt*9wm80KM+B!#`QhHyEeA8CTahWkPB?l5bkizjhS+ZSp8{A@B6GQi}G?F_!Uz z=2CZqKxWJ=#lj+IFH@Ee!VX4#Mr-TQGc0X8L=`+u#Zp-uj6-4#IL`WA>?S`$Q9ES! zFlQ|6qDt+889s0{Rh2P=_p{76*>#UWPM>VPc06WID;eRwsL)^FgAD{`sqa%z|69!+ zt_3s7M`{1pG}kl!D%64l&?k!AKQa$9Pj%VeUMYDn#yylPtV^O3{jsr90>NC1CYHW< z{ze#b3u(pm1&?SEw_Kvekefci{W54#lrg`(@rbts5?2tO?ASIY$cp!k;3YC)0m+KT`$$VA0Lbn z>)Vr%1Ak;nXJ$`XPHB-Ikg#jv2_!7#5)B$9BLrRX-7itqyQWRIE#mUs_u%foI`;0Y z!PyZsq$2c+d%X(yT5@<;Eq{C*&oA_}IABwXqD}XCV7$C5{e|1AAZ=sjQ=(IP*setbFuGdGdq_}|v!Hb7mV06^ zwds<};#u{dM0Jp{1gm5gS2a!|*}Iea(pmh9kE|e@5pOGNioVh&)NVY$N2U`gIWKcV zIxia>#HiL4bBRM6kI^qFcXP3QcD01yDFT9E;G+!tFUbA50kgy_7?MI^0=J1;491Jn z);L*eh2k&|xK%J3jS-)vaw)m@{Zv3ri__tznTx{?5S%IFF&jC%P&ow7OOp{$zDLma$-P>;gU-H7uV|EI1=kDo;?5T_g&MAB8xj50 z?OhH-uAE@uMpc%L`WnL>Z0oaUz=PyLN20@kQ=JT`Y$JyZ2H=?2Y*LNpr`>HwgtV4Sw` zh4#<5NWkA6>_@i1)S4Uo`Qd{Lb^$2wZE-a4m}WDE^;k7??GyZlq=ZIeiGYH~I^(uZ z|Cs~~lO}^iq~T5~@PpqC-KA`E>N{j2=M>Qx+o7oQqYieLQneO$aP6nL4*gSVEf_dC za@wNmKo;;e6A@qbj|iS|cU*AeW&sM-V#CcK#t0BPzbvxy*_cx~3C3U}2fu21Y&v_5 zo4E!Vs&FzO&3xsc21)D6yXi~X@oFbaX^>4)tDy$C40Sf&R07{c&|xah8~+EPJ%CeR z?Sx6=B|HfwHFg9QS{0IlW@fVG%Rcd6UeQ1RWchPJ)3Yw|@XS^)iegdnG(}pO{SK** zb3C1Mt+%zmrc!T$E+XE<)8IvuyY)mFB`uBylj1)m z=o+nj^t3<2|Bf1X(*g{BqX+A+N`nXO=Ng6aCz;Wfh`35rFqp2>SaNaVGV2g$?g_^qMczl;aS3&h5xcc%QX z^FT|QCsb_vQeaR$u3h7D*szlzw=w7X(V%cVBb7?}hFAcXJTOFwTWVZ{e#QuxybVE2 zN>CMG0CN(+B~}8zMAG|J| z+?A}fl%RDV7!Os_b%exalDx(A_v8q9F|}q*^Z`A1szdYtzHB{0TQUkl`f$J2UO~cN zg?{C@0JlMrV?d}pqGsq4Fbh$kLq1h^$W~8W4Ecf3;kCEsLPk~MDVb2=@;k;~34ZEu zj-qSDWT+)Hydc4Y|NCK3?y9m+e9*!H^gv(U8DSQUZ3Q# zN~634SsUxM>aJ7!@|~(ga=*~GtP%GID(mO(mSBWTCQZZIxGxN+%;47?KrqYpFyR|z zU5P}!!KQMA^4v=4E`>`@w^0rsGfV09DBgB8FZ~hL3_F?o+uTE~TJcfEjYU?@TgHbT zDI3ce$|#$jkr;fKIeqidYtrimb$wUQM9jj1IlUw7%>!t^-?I%!OMGSS7qHnDvn8S!E`b1mz*9 zd{qT1)qe480YGsjUT`+FZ~vPYO*=sC5&Q%jVt$B7xwFo>ExZv z$9}mer#3y=#E*A3e&w%@;_w;ewWIlee!SbcpGiQtKMiqtPL8A9kkIrXp^%SqLRbE{ z>ghdLU)ANFuUE14P~Ez>8ys{?ww7eZC5wk>}_RV#|w3ecwaq~nJ0 zIh4fux*|HD4ZobTsx|(Z@IIdTo#JfCHU5txI$%cXz&I)^6ShG_!s=r79M}tN&amDDYz$wI z=n(!!ZN6gt_n={dxif8+HAFc?qwHs7(w*pmIP_FpT;8-lbN5gHYwP4zV!dC2>78xSoil%x84C(svLtHReIxy}mAy(;U@n zVKbXOjMePN{htzh;jAduBW?CCv^aUw>)QX_Me`J6Et(?NPRHWTy;Wn*7VzPlrpNJN z22lFrFF&IP^YF*Fy4J~p_}HVGsU>d}-d&gFZ_UQij z!1X41&iJEKkI|9z{%enWb%cLQgKzfzX1|p7SWx19LoqrH+(njya3nrV0q%w9*xCyH zRn~sRWc=X_vrGUFJm;r;3@vg4M4+8;bTXst51oe^@^ zn>3r0iJQKU-^F5dqp9iM%bH1tE8JKp#4PXZKz6i=#nN7;auYEY4SBz~+t*z?)=udE zIa8~UXeGBkqvB*eROKeHNx2s=S0Eg;-7xIzhT4U_HL!Il^jgF&d$gu5;~|*9rs~4wIL+=w)rEd-?M+M#W~R zg5m6NW6@Wn=x|TQH^N0kR)&}hu4)Hh{vK^)dHfH7y+WE8StK1?qJv+`Ud|+gU~lnf zZA3^!8K;dwJYFuOJbFy68ciM%Hoq9_ZY>v*PF6xKABE>I_a!ciUOp>y_=pq@Y?hhDeJ&F$quqVE-{0?;V>bWn}f#_BN|-`vs3q2{iK5qe(rY&}E(JPlxM*$sGE7}`5I#bTsn}5QKI302AH0ig(fzk+ zl)R!M^=_hFDZ9A{(Wn7Yk`(EYgQkqSW;GznMCi7xwIUq=6!zRxuQTy>(`Z_+!{`MOhGt_Z3VJ)xG|v=ea3WvnD-I|`SIzSvntjubb#nkadce*TJZuEs_j>KD)_uq ziLw)zQW}NWw76(B-y1DsKTKDBLPN%>*P(iQi;@^2g8y`&;{EtABfK+K?U8sK-b-Gk zf%W6ZB@wJdSvq$VDgp~$MqF25euDOC{OsM={A)s}Y5jr@1-x~o+&2muy|9p=jF(0n zp~{O78Wc~IrNWJpG_6lZxZJR-Y=F<78fEcYh9c40!9iG1XPwwCwrOZeiE51}e#AyB z&9?xl0I5%w4Of4rou`$L&^GqHo>}6|a-#7`z=eagDjfhAN|C5yUO(+4@`3D8JCViH z`lz61U9B%&Fri>%8(OHtgby-E(7}ynM){jDXc1eV{(xfN{q0s5fEorLX{~zD_08ZT zT7_$%6HdWM;*+4~^adj8Pz_-W_3s&Y4_ONM{|$do=%_r%ik2c#5?+wJTrl!!lueq` zj0(xDre2Z?5ItxLl9)&D{A(4_dA{`XPod;U7E*y!P2YkF6E4~mX1MqUn8Ya`|MSXH zL62shY2W42DC-#>D9p6a_@ZA0&Og2kd9na%8bYF^X|@I9C(xj2O-&7GXpL@T z^?|_Q{cC@~MPYzBjat#cDU#WMGwPpLlB%0eiy#TFr1~G9W13gfpI8Z_;mcS+>RU<_ zEP9yRQ@EX`y(a7km($Mr(LxJpZrd8oRnXF|+QWrnciMw@x&)dyBgFM~LHrhGS|BTxu!1Xk_u{}MVSinw@OjC6LXz3<3?5wgwE?Z=a3sox;&)lS$C6mr z8^5MKyoaT*`?}G!-p>p6gvdR(TBrvd-+R_eeHbk*7%9AuIr}6SNcXqzUVsJ7sR`22 z@GTb{Aue=t|5T!wD-BQ*~G_-Iyk?@ezD1Hv-PKEh!H0F-Zmw2bN0I1!bKjO~7 z2*LN+lrxEssP=R$ z#tbJfq6wa%nC)(cbqR_DR)a3$&QdDOwY|!cZH(%*zEd5O_%2lH1;rE0Q};OaVr>2( zdd>PVk;P2;rn%jaz)>|dzz(&2DV4Lh)ITgwRY*CX04oEYxN?xM zm3p^E6WX@vY-<93$5esM^9!Z^sof=aE=)jIDfyysC0^Uvso>9dygfndQM0HL2S_9V zBnKX@kwc9JsS2J*uWk8sN1t!FU2BqS2PZQ5FxBt=YPVyzO6S2m&L7)vYIln1B{%4q zVT3c^v6skf`SNo+2Y%R*Tvy`3+21VhCNYN0P)%te$DoH>6Y)KHQ0U7fCvbaz(N<3O z)?bbN;C9P(*~)`k9DJ`6W*76@EbipIxs4hgz{IN@E4*fr^ zRT&Y{UVq`kJIJ`2tN;p$<82299X?X4n&uPo-C3&^Qqh-fgXrrbyP{N`MEqQcA-sL)(ZvM1PLS&V#ci@b^1Ax9`ZpW+Y zKfv5cy6_!Jtiq*jgGuVm35@k+z9(D2duq&ihiCaAZ=BgA+uLAO>-4)^-hofJ0^P9- z__TB~Z&nTKV^x&CI&NM$MO?d_kI6tNo$qR`k~6=e7VO!bDvht|g-M*n><3R)M$sTQ zS4IKwnO|>^?-Hr2C6k5|Vr_1H3Flrc{~I)bfq zSIP#H-4krP-qe+ODhK{SD$v4ACYakzMLE504aV=VhKU=|ff2^0YWUZnA|RZ@;2&qE$75l}(v7iRL&cy4;=Sq*9 zV7G%TT4%WTwFSznywnNt08?eYca(uYGrCqdK|2b_8pEY9_W=^+uic&XlSq_e&uN6F zpX;tTO!YPcxT1P~g)c2=Qdx4{=Q z?~kjyRND{b?^73ttgj_?xhS}zXqV-)me#f9&9mT5b}<}EtK2wEHaOGv_Q}1N<;j}R z07OLqboyh8CNu}p!CFf0h?kbI>1zxv+ z%AxQ61CgQnt1a^$`Gc$BAfE$jCyc=J`_coR*UVp08})2RJWUMocG7qiQE%^_BrvDC ze-aU1utH_Z+6?@nCrDzNag}&F_2aVxe;6ULEME8)G6p+K*~cKl1IA**kgr2gxgyAH z$CZsUM5VE{&*0^!`UTaq87j6IxEqqKY{suhJWS^%1fsaXA|>Nnh3Sg9@{pPfqRh&7 z8gk(1Jyu2X${!tk%+nmY<7NNWsoIcL8l3Y&`d|RW6@1G3a+fM;<5K_D^N)6BWt`J8 zZ0Xr0x6g8_kh*N9w}lsP4ni@_=mg8+{rh}kdh~*2)4&6^dw5YpSd{T$l zRP2p$lR#S;AvXP3A6m(_M z#m*I!uMG3uvrl0N1{1@jNdBk=@G4G~h9#Z=OhMgQ_?Vq30U0*i!TRY~c_owFTt4rZ zchBUB9}2p&8f~^#mua?X4O7;aWztjCBac5+uH^zhvYJJ{;}3i2??p%I_W2}%k-tk_ zd(rGm&>5m{OM+=EtJHr=%}Hd{_&#u%ymT}@bG#+RUH;GVD_fBA_4~kFtU>q1ICUR_ z-BFBR@$bY9r6X+ia1faxhmzJDLo7V7M43?c?yeq0r5T8LO1U#>|Vw$)LWi z$^-nuh3a1fjr~tiLFL`aW0iHqOh11q>TF>+jOqqo7vnN?=IG+t zziuu1&ng~GcBM}Gj^!9llf6D@)Qk|ly*@ysDC(20LKK>EZYy6;#EX7daK>~UY`2N4 zEu9Dc{C4R5Zba*JE3_l`I3dCKn6+Z$2;UMAH!6BcWrxG9q#-lA z_{xu$%~R8jN=gID8g-skhNlO08f&VWf8qw(sV)CBCzrN{;B58(z`ymjs6nk4_vxeaIu=dz|Rzk?1&0CS5X?EebSU62&29*ps^XX zf!@B{X4ii9{ydi%+>;6!v3ckuzToN9VNP0_}vh0PhA!;q$1L!1faFo4V3h!}A)~77x^Iw-O1i z^S_K-|J3=T9+J}OgGDh6S!h4;Mhaxw-uLw$=k~MbF1Jb|tjZm;8+)ZG#3#$ zJ^cc+QxuV3ieyr2vm}<;A%o&!5ik4l5!QjBWu~@ZnpqeASh1DYfA-UV7gPb(0Pn8f z+;Lcye_9NxP`cvYnWueIj^4RPN@J98Kn$V8_%F?6!$a=Kg|NVFIMYY$pBV9j|9QaK zzh|eCfvXT`Q&$S$!S7JsAB=Tg4BTPo&gaP+cnL_U)rtPZR^^D%0kr1{=Fl{&~nNmPxFXqLfo- zwbpP&cRVp1vN4x!)h+*e|Eiw}e?_>S7wDP48P|vv@p@?v;9!vqW`hHjg*MX>CqGU@7x`EzcU8fEVn&ZDe1mZRRjcr;qOx zg*keq#rjpB>4!*+epWqZn=`4a!;pfhIv!#|+AN_)86KkYLE7x@Wb_t>P(s%l=5ZhF z@M0qpFkr6*OH8);Q?Ws?%cP&IZYAr#90{-(=gV@^hJ6|~8$cQJW0h{l#7VZg^w%vU zIZVXRhJ7s+Q3Tb^ahyrjHcK0%P+4D=alz|(tvW-LkVoj-Te{HcVd_4<`;vmu^5L~b+2ur12F(BT-f1_~ul{oPifDWrKxZwQ3}9s+>| z+{|Xoc0K^b+{PDMQ|tVY(%`3A5IJV3i)i7-CjPVamkAW+?Nx?uRiSh2;>&iSSu)lt zy3N^dSrk0tSv@x`bf=FCvjE!&7r*X=Sd0ra4|f#zY{l8O_;-OZG}?RLudaPuU!FS1 zc*#_({yT3qdEUB!Nt^1yEn%&n4PGMUADP`H&cKE0Q^N%;0bC=AjW4DP1bQ+sZoDYv z>^)++PW4(F>db-{gBY7$Rgo#i!zcDgLYyB@o?Mar6(S{3;gJaZ;V~n{q4E%*gsJdTZRqf+3xyiSm=^VR2kDogCD2UJ9K{dbr zwfdX6MI$B>Bprj2?s1d$EA(79q~!nYzaTqA<6zJH<&WVcv&_D9o0sz2ScYw6{2Pn6 zIos(ofV8G#5pYg6UVlt*FwGV<%QjGvuDx`#!I%S-%IAM?WFZbK0!G>3?ZIp~`nmSm zCXp~k=%I%mYK3iDN_{pSY7|fvL2;}j&iGQ7io&!KfVoct5Fz|6vG{`CT_LDCY})-ViM4Z#z=qp;H zeS;WS>kpnh*BoBbHz88`C}V&f~a%s^B?Pp$gGRnSr%IW=Qf+&dw_pVG?MA|H0k^Utqk4VcF6T#y|d zzaSTtY`3fNtd|GoD+yPgE41eOmbJ(b98h$uEZ>G{%)4_U0ORhbL{Q!BcQ1y{$<1y@ zNzT_=WPtguF9P4>(1_DpS5JK`({Q1o5`HXY+qL>x;D^LiXgJRodZe*rHDVoY`ZB;< zv!vWMgqT0YTC1Svv3ZVateu~f#4bQLv{oP#f6olI9Wzd-LseE-uO*kQNm;i2N$N^i zHx`#JNLS8Of`mC5hBc$LJS_|KH|mIa7Z~R9nuCQ|+>a!e;>kJXovXH|N`ZE)xBEw5C`LdcT*9z5if3x9$Qr!90 z<9+6J{ATH>rZ*26S!kJ-6lIbk9aDa$pSQ`eow)>1j{pxgsF6xZ6R4(+lYjCF(*qIj zV!29sGg{>P$r2H)x@pP)*n3Cw%*=905Nb?~g^>y!9Gb^U>rWP#(4nzND)udIQ#nvJ z+CCD{)HEqwjk2tNnE@$xE-C5P>aGSw7l_8Gz^#Ug{of(FwOednOeTE@Qc^?e=+ZP6>*3wI5e7jVT58)GK z8jotvP-uwb}_I-XbOMRRPHF>j*vWB_A*Fc$7Qhaxme*nD={gDBESQ0ua2$Oe-mW3 zQ9Q|Aos?{CdB(t~JdU%wV-9T8u>bLpmoS%Y zpZEf|W2g|H3wn^(Dmw8Cdl*D%)IQ2c?NJr>WvM{5;h`{c0CQ$-53@e#4|a@$hM_>* zf7t{}T3$DC%r$M|^Gi*`=$PB|OtA)s>yTxwn(@{#GqaV*I!{XN0~R^CDYqQTd|4#< z_KTFz)Wy<5Et)(3S-}~U&qiXfw1hj~VN`k*Bh~H@{MqFGU1Z?%_X!PJDs?n{frm&c zX-RMkOu()H7uU_@-C_^h-<=>o=2+O;JO zmZrXpj^sG`UKkYk3n&R^p3%L>$o7yRJI=GKU26!& zmrMK9b<0K^DQ`;@l|9Wz`AIjsM#}=UX`21k#}`~?j^!dMXcL74@2-hg-YBC4CBe+ z{3%!)|3?@isMm)ytqkmsz8IU@D}nLz(nRg)@+gL|LNI z?ZlU%rL0Sk-}BC!^JE>OKCB%!d2hD1oGU6BSA~D1#CmVdW5W{g2(9!3{3s>CsfR z-MLH1-AL|T%%dJemWZJxzyY3!M|Jwn$Y|}K+98SMSqeeb&9Hv16vQ0gQOj?LYyKU@ zt=Wy37MjM4!~l1CoD;C;c9S7CYrTAM2JQ_{(QjEp2Cp(Ab|>-L(UoSffQ0eiVO38p z@jT{mz1yGq;fjh7bgTjrr!g~}aySTG-seL{tMqzTCYQ|>awZpmYY$_422RZ_pjMs0 z8QD%nN{^wh(xE@qTcJvi!PG4TkJAE{4fIEo_b^Ny)%aP5l4!KV_~pD3I$U@g9A=W6 z^x-2g|uj1ZQi>v(_h?9d<*v06;dBv~Hn#C54JKyy2gUhA(YxF>Q-)?-RLyOkO$ zgm1*G8Vv_Y48F1{I+L6iOSt?M(M6Us9Qa1!OoYtxMzudiq=TP|KrS~%gfhhxIDOi{^`Tlj3l$+Uc|O1 z{VNTwk)2=0G|Y&b6JeJzsnCEnk~H~X{VbulhqhF>7c7S?qTcCNQy}%Mpds ziVtCS&lQ=SQ0rXfOWz15*lw~Y}eJMPc2TaS}N{Z+}w;6@$(D|V-_??paT+!&F zP0qK-a6(0v{HSh`aKij|ShM}%X{v^_O8tLOkXKZ4p~y&11F>|s}JidZESHV%dI0xH<`7PPWT+0VS8NCq7DNX|<^bl~*x-(M~cW^$C%0GH48MVek+Z z69$3kgXH1Gal}VW!jYR%qV!*a${L*T)A$~BI;hNYv@FH7e?KF*J}-f`R@`w88k=kd zCV$VQJ+bUX?_(-GH`C`jm0{^TZC5{FV<|nCVZjiNve&!OCH^`zU($ch8ksYU5=&xj z;w&i1x^qob_Q@(69i2QiJ>&$1hsB3%ZnG!&ZsMqqQf69&zI7lDr;Lk^(Q7VDASO_~i80r!CmFd0 z@MnwOBUON1)s0!LZwj<~+o=6nY-hwGmYLip352KzL!KLejG;5Zyw9^eS_ovMW-x zT>@HrcPo7jeEC*6UYCL{mbk%_n0_fP_U;QsryVm*Z<+VNLdTIgLI zB*-WBX9?(Jtav3PhrULV5objuus&T&H8&O7a*O;udee%rq;~~eh0_0nnosx^%GT0ex(Oe_-Lq6&9g@z$)|1a$LjmDZyQbEh@1$pU-(0>jui^toLc>5bQAsJVAk1cC@IEU{9X-hD@LDO8>^~$hRd70j=`)$;+QTJlW<9!-#eZ@llyE?BqE-siR*vkF3JTZZ)JFUjN z5e#>nFlN##9YcTA9jWqXw2CY)u!wc$Q}3CdOlZy}eYvw`cI9xK(3CT_Nq@KD%BHw6 zXKRfkBdnPGASsLp-^0|E_zYtz%$N)BK*7ZBi?E^JWl^_H7<4tOjMf`24h0jl+!z-K z+7{g@G=6^{-u~Tu&dlbGpgF&PHM_JmHLF1gq+s4ou_s6DJU0H_ozI$_9A)Q53ZaI} zK9<&fC=y;5kRw-2HIb9@(N*fZzd`2LbP%;TAoP2p|IJ@<;N#-&4@BKE8i4PaMPbm|nWsl?t{;s}yjIF>kcgqa=Na>pS zDi=r0c$DN~Z0&!vm7W$SS?`|T`-vZ(`^l@UUjScBLVLo>+pKtXpfrEJ~M*F5}f_Q=rj3Z084EKO=bgzdSS$$ zM;wAI7HmOcBUgeAJha7N|60&7u~J%cA_^?k0$P3Wfa3JpB)@hAu~WK%Ki?c(fQYe~ zEs#XTPrjQFfFk28#_6INsCmbx(_8PNefQ7|{p0!O*1cZ}`ESMj4xP%5K-udVp|4v( zl*qBnmEO1)e>%iRit9rYJVs$D565eO=Y7ygjmRh6hHTj~w756gHr02`2;9aY zOf_lS8usPj65|kDD>JhaCMjSJuGLPG+;_C^v`EPP7=^4DcW^F0Ie)s!$QHQj>~TVk zdE{4QbN<;`E$icQII-b>zAkK?T|Ew@gKF?XsId>F(dy|>)>neBqyv99o8s{2ihDQL z_jC9tBQ<<|X|L8J(Xo6Z%$>%>OUq$vr5|1 z%xu`Nc1d=q*o+1{Gvex974eAx5C9 zYj^KY4&mnXh7(%A;JPEs23)_!CN<--jW6<-9riW2t*TB5B@Z=^-9V>&MGSkZY#VbS z3!1EV>{75>Z11VNv`$f(sk3NyD}#m+Ww$_ThP&zNuHOQ3$e4wNYif@F$I@8<#nC)} zKR_VCgS!NGcMTroaMxhra1M7u2yVfG26uOt5FCQL!{N^1&VQfZ`_|P~&28OI&CcEJ z^mO<4)3Ju^7Bw4YI|}@SQ4Cq4-Cx`|@HI122ks-@8pVEjbxdadqPx=gdh)`&fs3ZS z=i>@)UGI{be$FIIdkN4IBSe$^p7W(zh%hSp@^3-(`Zd@& z(|r32$98RgcHt3qrqg9=JZF(ipMZzx(K2`0UiqQ^GG`|{+3g?kMvIB0v^pEo0~%iC zhr97kneS1N<99DEQ+@|YC$b1}ZQ6zLWG;Lb+QI$(6%&rvnd#aHd2E{F#2RRJz${t?&8 zzI);iv?sRgz#fMupL>nlxzMr02a#E)V79F3^~p&62{=4oZp0$9x)kS{th9xJZf8cS zGfxeg8p{kCwgL#a{4_mP$qqQRIt>p>+2$c}R{{z{>1C~R?%R=rT0>7Bi>3JqT}sTC zTyw=f+qExB>kl#Yb&X{{QjQWetuv0Wi7PF6D?ghP{UR$VkA5FFc7r5W?SjWv9ibx) z>m~}z(v;UNO5H>6F-5iYvZ>S?B_G+%{KG;GW_INYo$=$BrbuJRscE0ltFmSCm8+!? zUupbMWu|Y*_o5Q#byO{{Oe!4T08N|(BT<<{q=Z&sF183GTVa&vxC1lS*(!Ifu}2n* zYmck^41mYyhxk-*rfE~_@hSjQ-BVBS+f&!jt~8(klD6fpUF+#Z|5bA}{xgq#HuQRVMjgu9hoSsP8A%6rf4hz?Ji?V~itV)@3{((8t*mHSPHe zQnGc@&4eV~!rXjvg)$;9ARFwxDVbK^Q8b{$3u3hXGR!52eAE+3M2WO49bI_THL+4> zfBTpau@-3>=*Y2=`Pi$MR;c-ahtu|v^@iLfPLjl1h6WqbvB!oHB8e(uDisXxBqi+G z)lvU*@4H9Ml3b*jRxduH)W;m#*3P1TCktfeU8YLpRwkFd9ao1pkowpQ#U;R1-H!x& z8NW8p^O`U^nv1RLBej+Y=%Ro0O}NjyTJRIX?ZGR_tUMj78DZihw<2)ci~{lVvj-TQ zJ6NKCnMHQ<+eB16H3pWnr^=R9jB5BAF3e)@Ba}3xz1`ZTGKNh=|IE51-YWppQs_}( z(51b~dN-X#p7x*n+XinKN0s$vwIoWBs$s4L7udwtJA3>{Y@Pf_@BwGq=r?c?pFA^8 zbX7yl7%B)wsq#yPS-%((_`k~9w;m6)G;}(N13MOmCG+y(fO5c@3r57QpOzm8?1i1V zAi>5`1`2>GfKkDSa_Pv6vKz=WafUbL{Vbo6-W8SdDPxI}maRAmhl8JqR^Mjl?Z0q^ zaM}iE`0r|rusD4|xUZTDPX??NCjITU;Wk3JSqpM|N3+iGux9tRL{AQ#vlpfN7@TX)BJg_ufpGv}*VT@)k`GTWxi!TiHI5qQO`Ek!RdD_*0>?e*L(< zQma;pWsgyehhkFL<2G#sF0C1#eLw0HtYyOp?9~wJyC)x!zcJ03_R&ZgDN=y8_1w(am9XMzS0iQ|pY>slrx9!PLR;gkUHx5fQ~l#_m8_|NM4h2$-^+-ejeF!Wqg@g(oz z<0d}^@L7G#++=<)4lr;GASK7G(O3ccRrJ95Pb@}mFRM4dL9;J9YlsL1rw`Gde9i_u zAM-7Emd6W_HbO91Ge4t}n3zZ_g-t=XB6RGCJs8sq{=TLW>P%YNUsLIUBExa4VYEw8 z?D?QA{3T!2gZs7sb{#w$@bn+S)9BbP?PI|Sp(R?-FEeME78zSwaoKcn%MJXQ*$<0y z-|LCckgQ!WK+q>|_L#Hq`a8#{amhtxyK)&leshH&=0AI4N}BUItWgQA;i$`CQ**rG zTwb(EsFXv=2^wehH`|{Tw93VggxIEk#=3sof~>N-S)vf z@0zg6dg>{O33Dx_$24#;II~qff8xiL(Z-ZYF-2jz;@B=<6bvAV)L2zo1uXSQSKCjq z#-ERR7G{1-89VmzR2G0BPbBr>(OUI0K~!{h<{H#n%`^cg3%VVyxRu(OUkUnP?>y;Q zIkl#*trUzluh!SHoDPw(6+$#Z0bU6?)!Sz5edQL{dP{UbGYPE#6b869Zc;*TrNXl> z41b5!187}cTN-TU2bF);<1(qFJHIP9`YjE0Al z;@GGx>=K}fWL|Ul#m$xjKhiS*^JQzV5*E+Bwl1YWaWT!jtusb1{p6g}Q+L7WpZed& zXlm(njmRRkbadVsnAiOEpi#fW!1JR>G}aWuXG&!Jj?IiDPM!jrdUZSRBP0kQ_?$0W z_^IHhoZ6WRO=JJ#MaeGC=TwJ-Ld-I>Hk7)@|E;c#MY$?r7Ob`MM*-a+ECSo#^uC1mbj@1 z*W>*e@*jy6z1{|Me|%0)&K`VPg3{-*Z;^tX#c{U?&4d(Lq!Eh)=Jh@O8>&i7s#>mk23+J|{F3uPR6vly zfUO=N88`9$_3@SMeXwMtWR48*+JJuEm!x&}g=zdx!IecHdmz#4e_NKiHoZ4S@d)27 z`Ze}1K2iZOCeb{- z+x6K>J7^IgA3AmN&HH;A^KXI7cfOh8%vs`)svbx%hq1}VoRz#RT+)a;90|`w8~yG3 zqO8*DcO1UGv$q%JF@OEST)uw@_^D%72irv8yiYvJmB`_GVj67Q=B!%#Cz;s4>51|c zw8P)~w>E{JRg|kFz;Zk+g}m4B=2{!%4o%3pyBa)7pu}7;tJ!J7Tg*R7bji%;uRiCG zsh`PO@MpZV{oVgO_uK!WWUGADSlC#6ASA)+c$TcgJXv?X(?289>g>1Wu~^jY_7gdI z%X%cXKi8_5dz+m9CsroNVS7#7t4VJ+EKIC2BsV#LfglFd3qct_I90F`TJsAbU;3tF zHC9@A^KT(~$F`mMIZ|;aD{CMl?mqtPVdFPDZ{?7Cr}T^9AHU~Tb&4ZXs@WvXD%8r2 zT(su-rrZ2g{y;COSYF)12l}SH7fPu9=xAsFp5f4SdfbM$Dn7n(jsrtFm zqJ*d_uGokuY9aCwyK$Dt(tHM~`_gx4W^dEe`5^XRwARSM=xO)_~O)c!lXY_IZsZLdmz_RM$S zpaR~beBGDB`!^A*zdqeiDJ8nFJ30|dJb?CG%n6)i;*t_)at!gW2M*U7BA^%G==6Je z=iBik!VEaR8-KsmD^FJ46id}{*jH<xV6Pj-oxE}>2`XNddc<$ z`-NUu@O99yk^^SufMbir8;=DH`PaXQuFf* z0(wj3tF=wVr_lSwLy69gHpkfzha~RhfH>ij!HIy}rAgo$sVLm&-Uh!`RL!lH18+}y z0BgPoPpy5G@xRO2E+7{i{;!voFJU@)P$x5n8TzF@A zrWKfYG8q(7D}4BGZvX8B+}{GjN=3ZIvWh05IsW&A@d5ZIqXFEF;LuG~%NCD&*jC3@ ztANfl4=AsMyq^^5iGQs(U_fphmS%`nmir|Cg@_D6!#Fo3QYC6)`@a5tM=%|Lpso$& zu20G4PBxo^6KemCUk1w+OHdyC!@4L3mfjD;ltMH2A{;Obj$wk{;S2p;3XOH_gXwTe z$dSgz#(tP(XU+XD?VLj&`l9C$Ho)Wk zou``HKtACyZ2eHJuqL2doyCQM&ApR|q9B%zU`u_qNra0r?Pe0%H(NA;KX7Kd9jlyU zErKK((aq7@Lx^@coB(EO@-nJKFo?|AAVt%j)TDcupMb*YqfLs%rYwLWb0~py&_O-1 zL7lw8kR0(SyA*=4LV5F6gL&P9K5gfZL~yrp$L$=oCERhS=1xbcR$R{?yC~AvV`AN< z5+WgGrv^`V&ndC-#8uCl*NpXjkVj%`LvIuiC&B|q?dE6dE6c%<76=~*V+uN24=%UB z0eVVLdHJbQE&8~XcLH|i>@3nrJfplqBBnr@wD{Jov7i*GH~Se+Aru%t|BbY&e$X06 z7X%LU5<(Y^$Rlo-?Mm<6V~c#x0WwyM{DgqeyF`byAWcF6Hhm|xZ{5=iersf!TboR0 z&NCi)epWBTDL8108o80M)3b**V7l?4J{a7_t5S41WUQ*Q4cYMwgZgvR0!v8YU3 zI+;m4S((Ja!Z16+4#v|zU)BQj^T1>$CBS5V1BAgeTR)U4g_7vbb`Q`vdlBnX3f$H{ zTVS1amkXug?lA_~7nkMEZjW-;~OKj3`{F@GSAYUntfG^&3dDDb*DwA*Vgzp9n^G?KQ1@Gw+|R*;C%6 z%Ix9szLaV%DtE*E@5Yi9bn-rIKOaJBrBu@{dblaJnsbTZfJ z^^D5?MZtr76;{MSNiX@!TU|n@Kk=H^!2k$=R2;X*nfL`Fp8|ohW}o{BYfKEO)Y$~N-@KFH=C@8v{_R+3$k`9gtAXj zjjhODdPb!2hs!x{zJ>X*G6MX86>K4Aq#N7iZEVA|Wj3on3Q!1ZDp)w&es*t~kK-I| zf;Bm8x>{VA%4$Ph6o{3vZ$Vh)A>D!Rw|tKkfsaghQ1AaDRihOzp@;om86ljC#~s07 z$+zE#fBfP)LJQ?-FBtaKSAlk}jNDuF=q>{U^ub&;3 z%GSdx`zwYjdx+>RiQgYtNOxUYX;C(T1YD~pXs43{Bg|&}O2sd^uSTUKgYda^R~&cX zOmRZmF$t0wQR#`V<1GmAS5_*v{$iyGlmy>3U$~~8{rfF<{7=XioU&hDAd`4pX#T|; z-5x2dk1UEiCeJ|nxA3(UFDuze9Nk_ElIq7L9{dUXx;3!oVUZP=6Wm_Q*qZfpK7I_*}gD)OuQmu?wz=pcC(DJm%jP=;+Ux{!I*b6}%I-m9~cIjb_Ae0L$- z!(cPK6BHWm9Ue)m5rV#lU6sGupql@!hyYWw)ZC}kPphI|w=111w?T@q?uDB*@(+FdWUQsoxw zVX{%MVuT@~LnkGsN0;%YAYmBJqP{y!I;}lrHyjZEr)lT387(AKNv=>br65DZR8XjN z6cdp3|COST|0v(&|M+#vB8G17VJvVZdzkKW5f`!yqV@kP=c- zI;|)ieQ*DFVMqWXPhr1N8pgHHeUEGZmCD#64FFsH^9`b-FwZ~|`gIopu6waR0Q2(* zVpfI!U9-S(4?g2&-l9`cB8s{pqR*jMGAgbk`!H=*uG>TPd5V7rmIF?DH{N zAIX!EOv#tr+H#F0S>vtK-bR?dgPmaPT}yG~r2p|@tO<+q+5ntBZrv^GHa@X6zdK^B z*4xl>PNvnAHJC*`lxsVa|3Zl28{jSyx~T5qXQuJV7O+he^} z*ZSMEjL^2t5KyN~@U!Zq+n6e9Xx%sbDuGbALa>J6RU_Dm*_MEntfFkl%aa_)AgfM- z{y=bb&_h0^V_TF-=qFCYEjruMN80x_r{%1Uq>COP+=Cawb-Af9BdE$@6_-3F_xug% z{G6_aOv*p)@>dMgM5p^I+k^Yl9*JF^Jmjw!g{;Lole=1m>!08Y5Mp17zd(xPZnucS z9?6PA0#$P?q%vD7&b?cgJf(`6!y!tvxf{Vzd+@mb!!#S4?(CjoR{HOPyxxgzk@g^f zqQ<5vmaQb@APs#6q;@KY>?P(gQ*DV!ceiWasTYQ}AZmYAZEB5$x=FVR-q<_T!+0(k zL+*{XxwKI6JmC^Eu_T%uk(EW0zDuxXajGe^+&7HqH}(-N!76n>y@vT4`uP5>?X_Sov9^d%pKiCSRDMe!+VC*E(j=e{4CO&0siMms2{IyUd z7w%Kr;7oqwh!RO0yC{5#^Yrnc@}6i(L?vT?mmcNb#{zJR84e2*?%}y|6a?yK<&Lrm z@fa8Mp^aW{J3|ZO*L>eJc-=*nCnO)<4HYsqh;7JR4J*1qnGuql$stwcdGggEd=I~z zIw{Vk(EU;iD^LO)HBxRIfs4I>>1)rP9olK;)uCmd4QEH!ywF7Qqz4INVvg*~ugD}2 zOcZ`@AFY3Sk1o<_eUuZ`CBymR#?)-_=2_)jNC=wpjI8xC1o8`2#%+4CTD_3IK`z{p z18<~)3$G2n=ZcUo3%D67-bYaJEGK&exjhOC36KY@Mv9Wq+?|cj89vL zNIoVLMa(P*@9eyQs<_7xLaR`PJLa^OpWB`|9goLi53*)c#?RtL!khTDfV=Y*){&32 z_JH~8i-8j88B@FSAzTP24(HS=Z�kumu_bi@QHHyKjAhYB-)JJX(>XCWKGjPoNYd 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

VwIJGB6qLW<8H)~_` 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∋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%0AHwT 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 IUYuu*QA}qwO-I*Tu|H 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